From 69d02b7e7209e3b346e556c4d69112ba9dc69231 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 9 Mar 2015 06:40:13 -0400 Subject: [PATCH 001/846] perl $npc->GetCombatState --- zone/npc.cpp | 4 +--- zone/perl_npc.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index a9a383d55..22fb5f188 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1839,7 +1839,7 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns) if(swarmOwner->IsClient()) { SetPetOwnerClient(true); //Simple flag to determine if pet belongs to a client - SetAllowBeneficial(1);//Allow temp pets to receive buffs and heals if owner is client. + SetAllowBeneficial(true);//Allow temp pets to receive buffs and heals if owner is client. //This will allow CLIENT swarm pets NOT to be targeted with F8. ns->spawn.targetable_with_hotkey = 0; no_target_hotkey = 1; @@ -2258,8 +2258,6 @@ bool NPC::CanTalk() 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; diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index febee6941..0c9cec797 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -2530,6 +2530,32 @@ XS(XS_NPC_ClearLastName) XSRETURN_EMPTY; } +XS(XS_NPC_GetCombatState); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetCombatState) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetCombatState(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->GetCombatEvent(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -2643,6 +2669,7 @@ XS(boot_NPC) newXSproto(strcpy(buf, "RemoveDefensiveProc"), XS_NPC_RemoveDefensiveProc, file, "$$"); newXSproto(strcpy(buf, "ChangeLastName"), XS_NPC_ChangeLastName, file, "$:$"); newXSproto(strcpy(buf, "ClearLastName"), XS_NPC_ClearLastName, file, "$"); + newXSproto(strcpy(buf, "GetCombatState"), XS_NPC_GetCombatState, file, "$"); XSRETURN_YES; } From 2cf2ef4fac63652ee606cd31f1243a35c43cc155 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 10 Mar 2015 00:33:11 -0400 Subject: [PATCH 002/846] Fix to check if weapon actually has a valid proc before trying to proc it. --- zone/attack.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 2946c0ef7..950663a38 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3650,6 +3650,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons (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)) { @@ -3994,7 +3995,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) { + if (weapon->Proc.Type == ET_CombatProc && 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. @@ -4032,7 +4033,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on if (!aug) continue; - if (aug->Proc.Type == ET_CombatProc) { + if (aug->Proc.Type == ET_CombatProc && 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)) { From be9066235b1b06e26c63b15030df74104d177bcb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2015 22:37:17 -0500 Subject: [PATCH 003/846] [eqemu_update.pl] Add Option 6) Download Latest map and water files --- changelog.txt | 3 +++ utils/scripts/eqemu_update.pl | 26 ++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 09cd52d88..f3a7c7f9e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/10/2015 == +Akkadius: [eqemu_update.pl] Add Option 6) Download Latest map and water files + == 03/04/2015 == Akkadius: Fix Spell Book Deletion diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 04c5367b3..921fdf3e4 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -14,7 +14,7 @@ if($Config{osname}=~/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 = 2; +$current_version = 3; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -160,6 +160,7 @@ sub ShowMenuPrompt { 3 => \&Run_Database_Check, 4 => \&AA_Fetch, 5 => \&OpCodes_Fetch, + 6 => \&MapFiles_Fetch, 0 => \&Exit, ); @@ -215,6 +216,7 @@ Database Management Menu (Please Select): 3) $option[3] 4) AAs - Get Latest AA's from PEQ (This deletes AA's already in the database) 5) OPCodes - Download latest opcodes from repository + 6) Maps - Download latest map and water files 0) Exit EO_MENU @@ -325,7 +327,7 @@ sub OpCodes_Fetch{ 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"], + 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Underfoot.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"], ); @@ -346,6 +348,26 @@ sub OpCodes_Fetch{ print "\nDone...\n\n"; } +sub MapFiles_Fetch{ + print "\n --- Fetching Latest Maps --- \n"; + GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "db_update/eqemu_maps_manifest.txt"); + #::: Get Data from manifest + open (FILE, "db_update/eqemu_maps_manifest.txt"); + $i = 0; + while () { + chomp; + $o = $_; + $maps_manifest[$i] = $o; + $i++; + } + #::: Download + for($m = 0; $m <= $i; $m++){ + GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m], "maps/" . $maps_manifest[$m]); + } + + print "\n --- Done Fetching Latest Maps --- \n"; +} + #::: Responsible for Database Upgrade Routines sub Run_Database_Check{ #::: Run 2 - Running pending updates... From c313bd8d077705d91f110c8b9e5f5cebb97b5def Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2015 22:40:20 -0500 Subject: [PATCH 004/846] Re-rename UF.conf again [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 921fdf3e4..20a5313a6 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -327,7 +327,7 @@ sub OpCodes_Fetch{ 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_Underfoot.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"], ); From b36d9fe1155f2d550dbd25c5cd56fbdee5a25d49 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2015 22:44:30 -0500 Subject: [PATCH 005/846] Update world binary with eqemu_update.pl script version [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 f6c43687f..443763961 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -494,7 +494,7 @@ bool Database::CheckDatabaseConversions() { /* 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 2"); + system("perl eqemu_update.pl V 3"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); From 6a241d44ccf13854ed48c87d9081b83d8a8e8dd4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 10 Mar 2015 22:59:07 -0500 Subject: [PATCH 006/846] Fix small issue where eqemu_update.pl script would bomb at the very end of the maps download because of blank string [skip ci] --- utils/scripts/eqemu_update.pl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 20a5313a6..2c41306fb 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -14,7 +14,7 @@ if($Config{osname}=~/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 = 3; +$current_version = 2; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -362,7 +362,10 @@ sub MapFiles_Fetch{ } #::: Download for($m = 0; $m <= $i; $m++){ - GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m], "maps/" . $maps_manifest[$m]); + print "'" . $maps_manifest[$m] . "'\n"; + if($maps_manifest[$m] ne ""){ + GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m], "maps/" . $maps_manifest[$m]); + } } print "\n --- Done Fetching Latest Maps --- \n"; From 13743caf19591c846e2f443a633e896992d87ef5 Mon Sep 17 00:00:00 2001 From: Shane Lynch Date: Tue, 10 Mar 2015 21:33:44 -0700 Subject: [PATCH 007/846] Enable multiple NPC equipment materials This change allows #npcedit armtexture/bracertexture/handtexture/legtexture/feettexture to work properly and sets individual armor slot materials for NPCs. --- zone/beacon.cpp | 2 +- zone/client.cpp | 8 ++++++-- zone/corpse.cpp | 14 ++++++++++++-- zone/mob.cpp | 16 ++++++++++++++-- zone/npc.cpp | 17 ++++++++++++++++- zone/zonedb.cpp | 13 ++++++++++++- zone/zonedump.h | 5 +++++ 7 files changed, 66 insertions(+), 9 deletions(-) diff --git a/zone/beacon.cpp b/zone/beacon.cpp index 5a952dc9d..0df02b201 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -54,7 +54,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), remove_timer(lifetime), spell_timer(0) diff --git a/zone/client.cpp b/zone/client.cpp index 8246e12a8..c5ca6e233 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -107,8 +107,12 @@ Client::Client(EQStreamInterface* ieqs) 0, 0, // qglobal 0, // maxlevel - 0 // scalerate - + 0, // scalerate + 0, + 0, + 0, + 0, + 0 ), //these must be listed in the order they appear in client.h position_timer(250), diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 551f49a1b..fad65aa3a 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -152,7 +152,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,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)), @@ -253,7 +253,12 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( 0, // int32 in_mana_regen, 0, // uint8 in_qglobal, 0, // uint8 in_maxlevel, - 0 // uint32 in_scalerate + 0, // uint32 in_scalerate + 0, // uint8 in_armtexture, + 0, // uint8 in_bracertexture, + 0, // uint8 in_handtexture, + 0, // uint8 in_legtexture, + 0 // uint8 in_feettexture, ), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), @@ -478,6 +483,11 @@ in_helmtexture, 0, 0, 0, +0, +0, +0, +0, +0, 0), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), diff --git a/zone/mob.cpp b/zone/mob.cpp index b4d28c6c0..ca2493b9b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -83,7 +83,12 @@ Mob::Mob(const char* in_name, int32 in_mana_regen, uint8 in_qglobal, uint8 in_maxlevel, - uint32 in_scalerate + uint32 in_scalerate, + uint8 in_armtexture, + uint8 in_bracertexture, + uint8 in_handtexture, + uint8 in_legtexture, + uint8 in_feettexture ) : attack_timer(2000), attack_dw_timer(2000), @@ -158,6 +163,13 @@ Mob::Mob(const char* in_name, texture = in_texture; helmtexture = in_helmtexture; + armtexture = in_armtexture; + bracertexture = in_bracertexture; + handtexture = in_handtexture; + legtexture = in_legtexture; + feettexture = in_feettexture; + multitexture = (armtexture || bracertexture || handtexture || legtexture || feettexture); + haircolor = in_haircolor; beardcolor = in_beardcolor; eyecolor1 = in_eyecolor1; @@ -930,7 +942,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.drakkin_heritage = drakkin_heritage; ns->spawn.drakkin_tattoo = drakkin_tattoo; ns->spawn.drakkin_details = drakkin_details; - ns->spawn.equip_chest2 = GetHerosForgeModel(1) != 0 ? 0xff : texture; + ns->spawn.equip_chest2 = GetHerosForgeModel(1) != 0 || multitexture? 0xff : texture; // ns->spawn.invis2 = 0xff;//this used to be labeled beard.. if its not FF it will turn mob invis diff --git a/zone/npc.cpp b/zone/npc.cpp index 22fb5f188..4e69657cd 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -103,7 +103,12 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if d->mana_regen, d->qglobal, d->maxlevel, - d->scalerate ), + d->scalerate, + d->armtexture, + d->bracertexture, + d->handtexture, + d->legtexture, + d->feettexture), attacked_timer(CombatEventTimer_expire), swarm_timer(100), classattack_timer(1000), @@ -1308,6 +1313,16 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const return helmtexture; case MaterialChest: return texture; + case MaterialArms: + return armtexture; + case MaterialWrist: + return bracertexture; + case MaterialHands: + return handtexture; + case MaterialLegs: + return legtexture; + case MaterialFeet: + return feettexture; case MaterialPrimary: return d_melee_texture1; case MaterialSecondary: diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 685fbd3ca..1fab4aff2 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1904,7 +1904,12 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load "npc_types.no_target_hotkey, " "npc_types.raid_target, " "npc_types.attack_delay, " - "npc_types.light " + "npc_types.light, " + "npc_types.armtexture, " + "npc_types.bracertexture, " + "npc_types.handtexture, " + "npc_types.legtexture, " + "npc_types.feettexture " "FROM npc_types %s", where_condition.c_str() ); @@ -2074,6 +2079,12 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load temp_npctype_data->attack_delay = atoi(row[90]); temp_npctype_data->light = (atoi(row[91]) & 0x0F); + temp_npctype_data->armtexture = atoi(row[92]); + temp_npctype_data->bracertexture = atoi(row[93]); + temp_npctype_data->handtexture = atoi(row[94]); + temp_npctype_data->legtexture = atoi(row[95]); + temp_npctype_data->feettexture = atoi(row[96]); + // If NPC with duplicate NPC id already in table, // free item we attempted to add. if (zone->npctable.find(temp_npctype_data->npc_id) != zone->npctable.end()) { diff --git a/zone/zonedump.h b/zone/zonedump.h index dc13300e3..e69692339 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -127,6 +127,11 @@ struct NPCType bool no_target_hotkey; bool raid_target; uint8 probability; + uint8 armtexture; + uint8 bracertexture; + uint8 handtexture; + uint8 legtexture; + uint8 feettexture; }; namespace player_lootitem { From 2003efb5ab37d71b8a6c678e2937ed8aeb0632b2 Mon Sep 17 00:00:00 2001 From: Shane Lynch Date: Tue, 10 Mar 2015 21:59:31 -0700 Subject: [PATCH 008/846] Enable multiple NPC equipment materials (part2) Adding missing header from previous commit. --- zone/mob.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/zone/mob.h b/zone/mob.h index 6d7b386cf..270ed7461 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -112,7 +112,12 @@ public: int32 in_mana_regen, uint8 in_qglobal, uint8 in_maxlevel, - uint32 in_scalerate + uint32 in_scalerate, + uint8 in_armtexture, + uint8 in_bracertexture, + uint8 in_handtexture, + uint8 in_legtexture, + uint8 in_feettexture ); virtual ~Mob(); @@ -971,6 +976,12 @@ protected: uint16 entity_id_being_looted; //the id of the entity being looted, 0 if not looting. uint8 texture; uint8 helmtexture; + uint8 armtexture; + uint8 bracertexture; + uint8 handtexture; + uint8 legtexture; + uint8 feettexture; + bool multitexture; int AC; int32 ATK; From bcf8b1af8e8a49fd88a4152ac1a352c8e6fc362a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 11 Mar 2015 21:01:43 -0500 Subject: [PATCH 009/846] [eqemu_update.pl] Add Option 7) Plugins - Download latest Perl plugins [eqemu_update.pl] Add Option 8) Quests - Download latest PEQ quests and stage updates [eqemu_update.pl] Set version 5 of script [skip ci] --- changelog.txt | 5 + common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 302 +++++++++++++++++++++++++++----- 3 files changed, 268 insertions(+), 41 deletions(-) diff --git a/changelog.txt b/changelog.txt index f3a7c7f9e..ad6b6f5d5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/11/2015 == +Akkadius: [eqemu_update.pl] Add Option 7) Plugins - Download latest Perl plugins +Akkadius: [eqemu_update.pl] Add Option 8) Quests - Download latest PEQ quests and stage updates +Akkadius: [eqemu_update.pl] Set version 5 of script + == 03/10/2015 == Akkadius: [eqemu_update.pl] Add Option 6) Download Latest map and water files diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 443763961..bda4e7f9b 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -494,7 +494,7 @@ bool Database::CheckDatabaseConversions() { /* 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 3"); + system("perl eqemu_update.pl V 5"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 2c41306fb..73e1423eb 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -9,12 +9,22 @@ $menu_displayed = 0; use Config; +use File::Copy qw(copy); +use POSIX qw(strftime); +use File::Path; +use File::Find; +use URI::Escape; + +use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); + +$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}=~/Win|MS/i){ $OS = "Windows"; } #::: If current version is less than what world is reporting, then download a new one... -$current_version = 2; +$current_version = 5; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -36,6 +46,8 @@ 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") or die "Unable to open config: $confile\n"; my $indb = 0; @@ -161,6 +173,8 @@ sub ShowMenuPrompt { 4 => \&AA_Fetch, 5 => \&OpCodes_Fetch, 6 => \&MapFiles_Fetch, + 7 => \&Plugins_Fetch, + 8 => \&QuestFiles_Fetch, 0 => \&Exit, ); @@ -203,20 +217,19 @@ sub MenuOptions { $option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; } else{ - $option[3] = "Check for pending REQUIRED Database updates - Stages updates for automatic upgrade..."; + $option[3] = "Check and stage pending REQUIRED Database updates"; } return <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); - print " URL: " . $URL . "\n"; - print " Saved: " . $Dest_File . " \n"; + #::: For non-text type requests... + if($content_type == 1){ + use LWP::Simple qw(getstore); + if(!getstore($URL, $Dest_File)){ + print "Error, no connection or failed request...\n\n"; + } + else{ + print " o URL: (" . $URL . ")\n"; + print " o Saved: (" . $Dest_File . ") \n"; + } } - else { - print "Error, no connection to the internet...\n\n"; - die $response->status_line; + else{ + 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); + print " o URL: (" . $URL . ")\n"; + print " o Saved: (" . $Dest_File . ") \n"; + } + else { + print "Error, no connection or failed request...\n\n"; + } } } 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 " URL: " . $URL . "\n"; - print " Saved: " . $Dest_File . " \n"; + print " o URL: (" . $URL . ")\n"; + print " o Saved: (" . $Dest_File . ") \n"; if($wget=~/unable to resolve/i){ - print "Error, no connection to the internet...\n\n"; - die; + print "Error, no connection or failed request...\n\n"; + #die; } } } @@ -343,32 +389,208 @@ sub OpCodes_Fetch{ print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; GetRemoteFile($opcodes{$loop}[1], $file_name); - $loop++; + $loop++; } print "\nDone...\n\n"; } +sub CopyFile{ + $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 MapFiles_Fetch{ print "\n --- Fetching Latest Maps --- \n"; - GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "db_update/eqemu_maps_manifest.txt"); + + GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); + #::: Get Data from manifest - open (FILE, "db_update/eqemu_maps_manifest.txt"); + open (FILE, "updates_staged/eqemu_maps_manifest.txt"); $i = 0; - while () { + while (){ chomp; $o = $_; - $maps_manifest[$i] = $o; - $i++; - } - #::: Download - for($m = 0; $m <= $i; $m++){ - print "'" . $maps_manifest[$m] . "'\n"; - if($maps_manifest[$m] ne ""){ - GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m], "maps/" . $maps_manifest[$m]); + @manifest_map_data = split(',', $o); + if($manifest_map_data[0] ne ""){ + $maps_manifest[$i] = [$manifest_map_data[0], $manifest_map_data[1]]; + $i++; } } - print "\n --- Done Fetching Latest Maps --- \n"; + #::: 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"; + GetRemoteFile("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 QuestFiles_Fetch{ + print "\n --- Fetching Latest Quests --- \n"; + + GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + + print "\nFetched latest quests...\n"; + my $zip = Archive::Zip->new(); + unless ( $zip->read( 'updates_staged\Quests-Plugins-master.zip' ) == AZ_OK ) { + die 'read error'; + } + print "Extracting...\n"; + $zip->extractTree('', 'updates_staged/'); + + $fc = 0; + use File::Find; + use File::Compare; + use Text::Diff; + 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) { + CopyFile($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; + } + else{ + $diff = diff($dest_file, $staged_file, { STYLE => "Unified" }); + 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)] - A backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if($input=~/N/i){} + else{ + #::: Make a backup + CopyFile($dest_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; + } + $fc++; + } + } + } + } + + #::: Cleanup staged folder... + rmtree("updates_staged/"); + + if($fc == 0){ + print "\nNo Quest Updates found... \n\n"; + } +} + +sub Plugins_Fetch{ + print "\n --- Fetching Latest Plugins --- \n"; + + GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + + print "\nFetched latest plugins...\n"; + my $zip = Archive::Zip->new(); + unless ( $zip->read( 'updates_staged\Quests-Plugins-master.zip' ) == AZ_OK ) { + die 'read error'; + } + print "Extracting...\n"; + $zip->extractTree('', 'updates_staged/'); + + $fc = 0; + use File::Find; + use File::Compare; + use Text::Diff; + 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) { + CopyFile($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; + } + else{ + $diff = diff($dest_file, $staged_file, { STYLE => "Unified" }); + 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)] - A backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if($input=~/N/i){} + else{ + #::: Make a backup + CopyFile($dest_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; + } + $fc++; + } + } + } + } + + #::: Cleanup staged folder... + rmtree("updates_staged/"); + + if($fc == 0){ + print "\nNo Plugin Updates found... \n\n"; + } +} + +sub AreFileSizesDifferent{ + $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; } #::: Responsible for Database Upgrade Routines From 9344cfb4e321adeca8d3461b9707ba23b9071989 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 11 Mar 2015 21:06:58 -0500 Subject: [PATCH 010/846] [eqemu_update.pl] Add Option 20) to self update script [skip ci] --- utils/scripts/eqemu_update.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 73e1423eb..e09a5598c 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -164,6 +164,10 @@ else{ ShowMenuPrompt(); } +sub UpdateSelf{ + GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + die "Rerun eqemu_update.pl"; +} sub ShowMenuPrompt { my %dispatch = ( @@ -175,6 +179,7 @@ sub ShowMenuPrompt { 6 => \&MapFiles_Fetch, 7 => \&Plugins_Fetch, 8 => \&QuestFiles_Fetch, + 20 => \&UpdateSelf, 0 => \&Exit, ); @@ -230,6 +235,7 @@ Database Management Menu (Please Select): 6) Maps - Download latest map and water files 7) Plugins - Download latest Perl plugins 8) Quests - Download latest PEQ quests and stage updates + 20) Force update this script (Redownload) 0) Exit EO_MENU From b3a0370e71443500f55e87a073b2a60b37d70cb8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 12 Mar 2015 00:08:10 -0500 Subject: [PATCH 011/846] [eqemu_update.pl] Linux compatibility adjustments [skip ci] --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 61 ++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index bda4e7f9b..7213e3a50 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -494,7 +494,7 @@ bool Database::CheckDatabaseConversions() { /* 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 5"); + system("perl eqemu_update.pl V 6"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index e09a5598c..d5dddd407 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -15,8 +15,6 @@ use File::Path; use File::Find; use URI::Escape; -use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); - $time_stamp = strftime('%m-%d-%Y', gmtime()); $console_output .= " Operating System is: $Config{osname}\n"; @@ -24,7 +22,7 @@ if($Config{osname}=~/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 = 5; +$current_version = 6; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -465,17 +463,13 @@ sub QuestFiles_Fetch{ GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); print "\nFetched latest quests...\n"; - my $zip = Archive::Zip->new(); - unless ( $zip->read( 'updates_staged\Quests-Plugins-master.zip' ) == AZ_OK ) { - die 'read error'; - } - print "Extracting...\n"; - $zip->extractTree('', 'updates_staged/'); + mkdir('updates_staged'); + UnZip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); $fc = 0; use File::Find; use File::Compare; - use Text::Diff; + my @files; my $start_dir = "updates_staged/Quests-Plugins-master/quests/"; find( @@ -493,7 +487,7 @@ sub QuestFiles_Fetch{ print "Installing :: '" . $dest_file . "'\n"; } else{ - $diff = diff($dest_file, $staged_file, { STYLE => "Unified" }); + $diff = Diff($dest_file, $staged_file); if($diff ne ""){ $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; @@ -529,17 +523,13 @@ sub Plugins_Fetch{ GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); print "\nFetched latest plugins...\n"; - my $zip = Archive::Zip->new(); - unless ( $zip->read( 'updates_staged\Quests-Plugins-master.zip' ) == AZ_OK ) { - die 'read error'; - } - print "Extracting...\n"; - $zip->extractTree('', 'updates_staged/'); + + UnZip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); $fc = 0; use File::Find; use File::Compare; - use Text::Diff; + my @files; my $start_dir = "updates_staged/Quests-Plugins-master/plugins/"; find( @@ -557,10 +547,9 @@ sub Plugins_Fetch{ print "Installing :: '" . $dest_file . "'\n"; } else{ - $diff = diff($dest_file, $staged_file, { STYLE => "Unified" }); + $diff = 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)] - A backup will be found in '" . $backup_dest . "'\n"; @@ -587,6 +576,38 @@ sub Plugins_Fetch{ } } +sub 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 AreFileSizesDifferent{ $file_1 = $_[0]; $file_2 = $_[1]; From 2bcb96432660332bb48d8277344eefa935a2013c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 12 Mar 2015 00:33:52 -0500 Subject: [PATCH 012/846] [eqemu_update.pl V7] Add Option 9) LUA Modules - Download latest LUA Modules (Required for Lua) [skip ci] --- changelog.txt | 3 ++ common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 66 ++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index ad6b6f5d5..30cdf9ba7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/12/2015 == +Akkadius: [eqemu_update.pl V7] Add Option 9) LUA Modules - Download latest LUA Modules (Required for Lua) + == 03/11/2015 == Akkadius: [eqemu_update.pl] Add Option 7) Plugins - Download latest Perl plugins Akkadius: [eqemu_update.pl] Add Option 8) Quests - Download latest PEQ quests and stage updates diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 7213e3a50..a96f51967 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -494,7 +494,7 @@ bool Database::CheckDatabaseConversions() { /* 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 6"); + system("perl eqemu_update.pl V 7"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index d5dddd407..f1ec5b688 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -22,7 +22,7 @@ if($Config{osname}=~/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 = 6; +$current_version = 7; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -177,6 +177,7 @@ sub ShowMenuPrompt { 6 => \&MapFiles_Fetch, 7 => \&Plugins_Fetch, 8 => \&QuestFiles_Fetch, + 9 => \&LUA_Modules_Fetch, 20 => \&UpdateSelf, 0 => \&Exit, ); @@ -233,6 +234,7 @@ Database Management Menu (Please Select): 6) Maps - Download latest map and water files 7) Plugins - Download latest Perl plugins 8) Quests - Download latest PEQ quests and stage updates + 9) LUA Modules - Download latest LUA Modules (Required for Lua) 20) Force update this script (Redownload) 0) Exit @@ -485,6 +487,7 @@ sub QuestFiles_Fetch{ if (!-e $dest_file) { CopyFile($staged_file, $dest_file); print "Installing :: '" . $dest_file . "'\n"; + $fc++; } else{ $diff = Diff($dest_file, $staged_file); @@ -517,6 +520,66 @@ sub QuestFiles_Fetch{ } } +sub LUA_Modules_Fetch{ + print "\n --- Fetching Latest LUA Modules --- \n"; + + GetRemoteFile("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) { + CopyFile($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; + $fc++; + } + else{ + $diff = 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)] - A backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if($input=~/N/i){} + else{ + #::: Make a backup + CopyFile($dest_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; + } + $fc++; + } + } + } + } + + #::: Cleanup staged folder... + rmtree("updates_staged/"); + + if($fc == 0){ + print "\nNo LUA Modules Updates found... \n\n"; + } +} + sub Plugins_Fetch{ print "\n --- Fetching Latest Plugins --- \n"; @@ -545,6 +608,7 @@ sub Plugins_Fetch{ if (!-e $dest_file) { CopyFile($staged_file, $dest_file); print "Installing :: '" . $dest_file . "'\n"; + $fc++; } else{ $diff = Diff($dest_file, $staged_file); From c5fb9ba6ddf0063160aa7660c631bd32e5da1900 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 12 Mar 2015 01:05:25 -0500 Subject: [PATCH 013/846] [eqemu_update.pl] Make it so script is still useable when eqemu_config.xml is not present with no DB configurations [skip ci] --- utils/scripts/eqemu_update.pl | 104 ++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index f1ec5b688..c60a1bc3b 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -22,7 +22,7 @@ if($Config{osname}=~/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 = 7; +$current_version = 6; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -46,8 +46,11 @@ no warnings; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); +#::: Cleanup staged folder... +rmtree("updates_staged/"); + my $confile = "eqemu_config.xml"; #default -open(F, "<$confile") or die "Unable to open config: $confile\n"; +open(F, "<$confile"); my $indb = 0; while() { s/\r//g; @@ -107,12 +110,12 @@ if($path eq ""){ mkdir('db_update'); #::: Check if db_version table exists... -if(trim(GetMySQLResult("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne ""){ +if(trim(GetMySQLResult("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ print GetMySQLResult("DROP TABLE db_version"); print "Old db_version table present, dropping...\n\n"; } -if(GetMySQLResult("SHOW TABLES LIKE 'db_version'") eq ""){ +if(GetMySQLResult("SHOW TABLES LIKE 'db_version'") eq "" && $db){ print GetMySQLResult(" CREATE TABLE db_version ( version int(11) DEFAULT '0' @@ -133,24 +136,24 @@ if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){ exit; } else{ - print $console_output; + print $console_output if $db; } +if($db){ + print " Binary Database Version: (" . $bin_db_ver . ")\n"; + print " Local Database Version: (" . $local_db_ver . ")\n\n"; -print " Binary Database Version: (" . $bin_db_ver . ")\n"; -print " Local Database Version: (" . $local_db_ver . ")\n\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 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; + print "Retrieving latest database manifest...\n"; + GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } -print "Retrieving latest database manifest...\n"; -GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); -# GetRemoteFile("https://dl.dropboxusercontent.com/u/50023467/dl/db_update_manifest.txt", "db_update/db_update_manifest.txt"); - 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 @@ -217,6 +220,7 @@ sub ShowMenuPrompt { } sub MenuOptions { + if(@total_updates){ $option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; } @@ -225,7 +229,7 @@ sub MenuOptions { } return < Date: Thu, 12 Mar 2015 11:19:41 -0500 Subject: [PATCH 014/846] [eqemu_update.pl] Set version back to 7... [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 c60a1bc3b..302b4113b 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -22,7 +22,7 @@ if($Config{osname}=~/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 = 6; +$current_version = 7; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ From cd82aae183a1626e86659cb969575e6ea97d2119 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 12 Mar 2015 11:40:46 -0500 Subject: [PATCH 015/846] [eqemu_update.pl] Small line adjustment [skip ci] --- utils/scripts/eqemu_update.pl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 302b4113b..3b1a0272c 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -509,7 +509,7 @@ sub QuestFiles_Fetch{ print $diff . "\n"; print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Quest? '" . $dest_file . "' [Yes (Enter) - No (N)] - A backup will be found in '" . $backup_dest . "'\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{ @@ -565,7 +565,7 @@ sub LUA_Modules_Fetch{ $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)] - A backup will be found in '" . $backup_dest . "'\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{ @@ -621,7 +621,7 @@ sub Plugins_Fetch{ $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)] - A backup will be found in '" . $backup_dest . "'\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{ From 3b9f62f0a1521fbdadd3698375a8565516a8db04 Mon Sep 17 00:00:00 2001 From: JJ Date: Wed, 18 Mar 2015 02:49:00 -0400 Subject: [PATCH 016/846] Exported ReloadZoneStaticData to perl and lua. Usage: (perl) quest::reloadzonestaticdata(); (lua) eq.reloadzonestaticdata(); --- zone/embparser_api.cpp | 11 +++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 7 +++++++ zone/questmgr.h | 1 + 4 files changed, 24 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 8b49f01b2..1729978b0 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3429,6 +3429,16 @@ XS(XS__clear_npctype_cache) XSRETURN_EMPTY; } +XS(XS__reloadzonestaticdata); +XS(XS__reloadzonestaticdata) +{ + dXSARGS; + + quest_manager.ReloadZoneStaticData(); + + XSRETURN_EMPTY; +} + XS(XS__qs_send_query); XS(XS__qs_send_query) { @@ -3686,6 +3696,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "qs_send_query"), XS__qs_send_query, file); newXS(strcpy(buf, "rain"), XS__rain, file); newXS(strcpy(buf, "rebind"), XS__rebind, file); + newXS(strcpy(buf, "reloadzonestaticdata"), XS__reloadzonestaticdata, file); newXS(strcpy(buf, "removetitle"), XS__removetitle, file); newXS(strcpy(buf, "repopzone"), XS__repopzone, file); newXS(strcpy(buf, "resettaskactivity"), XS__resettaskactivity, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 50afdb6e9..59a5d3740 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1242,6 +1242,10 @@ void lua_clear_npctype_cache(int npctype_id) { quest_manager.ClearNPCTypeCache(npctype_id); } +void lua_reloadzonestaticdata() { + quest_manager.ReloadZoneStaticData(); +} + double lua_clock() { timeval read_time; gettimeofday(&read_time, nullptr); @@ -1592,6 +1596,7 @@ luabind::scope lua_register_general() { luabind::def("enable_recipe", &lua_enable_recipe), luabind::def("disable_recipe", &lua_disable_recipe), luabind::def("clear_npctype_cache", &lua_clear_npctype_cache), + luabind::def("reloadzonestaticdata", &lua_reloadzonestaticdata), luabind::def("clock", &lua_clock), luabind::def("create_npc", &lua_create_npc), luabind::def("debug", (void(*)(std::string))&lua_debug), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 97992e0bc..47d92b68e 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2927,6 +2927,13 @@ void QuestManager::ClearNPCTypeCache(int npctype_id) { } } +void QuestManager::ReloadZoneStaticData() +{ + if (zone) { + zone->ReloadStaticData(); + } +} + Client *QuestManager::GetInitiator() const { if(!quests_running_.empty()) { running_quest e = quests_running_.top(); diff --git a/zone/questmgr.h b/zone/questmgr.h index 7051bbb2b..d2f018b8c 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -249,6 +249,7 @@ public: bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); void ClearNPCTypeCache(int npctype_id); + void ReloadZoneStaticData(); Client *GetInitiator() const; NPC *GetNPC() const; From 1c454d9569823876f2a886ba2c39b2ed6360f5a2 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 19 Mar 2015 16:22:17 -0400 Subject: [PATCH 017/846] Fix for pets not receiving group buffs cast on them correctly. --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index b0ed519d9..08030b8b5 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2151,7 +2151,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 // it can affect up to 7 people if the targeted group is not our own // Allow pets who cast group spells to affect the group. - if (spell_target->IsPetOwnerClient()){ + if (spell_target->IsPetOwnerClient() && IsPetOwnerClient()){ Mob* owner = spell_target->GetOwner(); if (owner) From 6c26bc9c8f05700e851f11d69dc5f018cecc2760 Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 20 Mar 2015 13:10:36 -0700 Subject: [PATCH 018/846] Fix for alt currency reclaim exploit and fix for exploit in trader code where price != set price --- zone/client_packet.cpp | 2 +- zone/trading.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1bf44e3ee..a04d4359c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2604,7 +2604,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) ++iter; } - if (item_id == 0) { + if (item_id == 0 || reclaim->count == 0) { return; } diff --git a/zone/trading.cpp b/zone/trading.cpp index 0e44a91bc..a521e63cc 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1583,6 +1583,8 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic return; } + tbs->Price = BuyItem->GetPrice(); + Log.Out(Logs::Detail, Logs::Trading, "Buyitem: Name: %s, IsStackable: %i, Requested Quantity: %i, Charges on Item %i", BuyItem->GetItem()->Name, BuyItem->IsStackable(), tbs->Quantity, BuyItem->GetCharges()); // If the item is not stackable, then we can only be buying one of them. From f021ee54911f6dde063580ea23c853d61b1842a3 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 22 Mar 2015 14:47:45 -0700 Subject: [PATCH 019/846] Fix for traders not correctly setting price --- zone/client_packet.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a04d4359c..21ab1c7cf 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13385,6 +13385,10 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) if (database.GetItem(gis->Items[i])) { database.SaveTraderItem(this->CharacterID(), gis->Items[i], gis->SerialNumber[i], gis->Charges[i], ints->ItemCost[i], i); + + auto inst = FindTraderItemBySerialNumber(gis->SerialNumber[i]); + if(inst) + inst->SetPrice(ints->ItemCost[i]); } else { //return; //sony doesnt memset so assume done on first bad item From 0cf5cca4159c4a73265c7260afac7051bd843a4a Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 22 Mar 2015 23:18:08 -0700 Subject: [PATCH 020/846] Other half of bazaar exploit --- zone/trading.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index a521e63cc..b6c869b61 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1652,7 +1652,12 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic outtbs->Price = TotalCost; } - this->TakeMoneyFromPP(TotalCost); + if(!TakeMoneyFromPP(TotalCost)) { + database.SetHackerFlag(account_name, name, "Attempted to buy something in bazaar but did not have enough money."); + TradeRequestFailed(app); + safe_delete(outapp); + return; + } Log.Out(Logs::Detail, Logs::Trading, "Customer Paid: %d in Copper", TotalCost); From 340ed6c59d5e2bf4558cc3f4f39b3219dd6917cc Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 24 Mar 2015 01:42:34 -0400 Subject: [PATCH 021/846] Fix for sympathetic proc code to allow for it to be properly checked from spell buffs. --- common/spdat.h | 1 + zone/spell_effects.cpp | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index b70d708f0..487b5d00a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -38,6 +38,7 @@ #define MAX_RESISTABLE_EFFECTS 12 // Number of effects that are typcially checked agianst resists. #define MaxLimitInclude 16 //Number(x 0.5) of focus Limiters that have inclusive checks used when calcing focus effects #define MAX_SKILL_PROCS 4 //Number of spells to check skill procs from. (This is arbitrary) [Single spell can have multiple proc checks] +#define MAX_SYMPATHETIC_PROCS 10 // Number of sympathetic procs a client can have (This is arbitrary) const int Z_AGGRO=10; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 24eac51ee..e03d5672a 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5183,7 +5183,6 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { return 0; uint16 proc_spellid = 0; - uint8 MAX_SYMPATHETIC = 10; float ProcChance = 0.0f; std::vector SympatheticProcList; @@ -5195,7 +5194,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) { - if (SympatheticProcList.size() > MAX_SYMPATHETIC) + if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; TempItem = nullptr; @@ -5215,7 +5214,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { for (int y = AUG_BEGIN; y < EmuConstants::ITEM_COMMON_SIZE; ++y) { - if (SympatheticProcList.size() > MAX_SYMPATHETIC) + if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; ItemInst *aug = nullptr; @@ -5243,11 +5242,11 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { int buff_max = GetMaxTotalSlots(); for (buff_slot = 0; buff_slot < buff_max; buff_slot++) { - if (SympatheticProcList.size() > MAX_SYMPATHETIC) + if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; focusspellid = buffs[buff_slot].spellid; - if (IsValidSpell(focusspellid)) + if (!IsValidSpell(focusspellid)) continue; proc_spellid = CalcFocusEffect(type, focusspellid, spell_id); @@ -5275,7 +5274,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (aa_AA < 1 || aa_value < 1) continue; - if (SympatheticProcList.size() > MAX_SYMPATHETIC) + if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; proc_spellid = CalcAAFocus(type, aa_AA, spell_id); From 202c59eb4821e0baf284a80840995e3aa430d4c4 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 24 Mar 2015 07:13:22 -0400 Subject: [PATCH 022/846] More sympathetic proc fixes --- zone/client.h | 2 +- zone/mob.cpp | 53 +++++++++++++++++++++++------------------- zone/mob.h | 2 ++ zone/spell_effects.cpp | 24 +++++++++++++++++-- 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/zone/client.h b/zone/client.h index 3a90e87eb..533db7b04 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1268,7 +1268,7 @@ protected: bool client_data_loaded; int16 GetFocusEffect(focusType type, uint16 spell_id); - int16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); + uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); Mob* bind_sight_target; diff --git a/zone/mob.cpp b/zone/mob.cpp index b4d28c6c0..2053594be 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3615,36 +3615,41 @@ bool Mob::TryFadeEffect(int slot) void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) { - if(target == nullptr || !IsValidSpell(spell_id)) + if(target == nullptr || !IsValidSpell(spell_id) || !IsClient()) return; - int focus_spell = CastToClient()->GetSympatheticFocusEffect(focusSympatheticProc,spell_id); + uint16 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); + if(!IsValidSpell(focus_spell)) + return; - 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); + uint16 focus_trigger = GetSympatheticSpellProcID(focus_spell); - else - SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff); - } + if(!IsValidSpell(focus_trigger)) + return; - CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell); - } + // 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, -1, focus_spell); } int32 Mob::GetItemStat(uint32 itemid, const char *identifier) diff --git a/zone/mob.h b/zone/mob.h index 6d7b386cf..979d9728a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1063,6 +1063,8 @@ protected: void PrintRoute(); virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0); + int16 GetSympatheticSpellProcRate(uint16 spell_id); + uint16 GetSympatheticSpellProcID(uint16 spell_id); enum {MAX_PROCS = 4}; tProc PermaProcs[MAX_PROCS]; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e03d5672a..21ba36e0a 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5177,7 +5177,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo return(value*lvlModifier/100); } -int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { +uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (IsBardSong(spell_id)) return 0; @@ -5253,7 +5253,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (IsValidSpell(proc_spellid)){ - ProcChance = GetSympatheticProcChances(spell_id, spells[focusspellid].base[0]); + ProcChance = GetSympatheticProcChances(spell_id, GetSympatheticSpellProcRate(spell_id)); if(zone->random.Roll(ProcChance)) SympatheticProcList.push_back(proc_spellid); } @@ -5929,6 +5929,26 @@ float Mob::GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 I return ProcChance; } +int16 Mob::GetSympatheticSpellProcRate(uint16 spell_id) +{ + for (int i = 0; i < EFFECT_COUNT; i++){ + if (spells[spell_id].effectid[i] == SE_SympatheticProc) + return spells[spell_id].base[i]; + } + + return 0; +} + +uint16 Mob::GetSympatheticSpellProcID(uint16 spell_id) +{ + for (int i = 0; i < EFFECT_COUNT; i++){ + if (spells[spell_id].effectid[i] == SE_SympatheticProc) + return spells[spell_id].base2[i]; + } + + return 0; +} + bool Mob::DoHPToManaCovert(uint16 mana_cost) { if (spellbonuses.HPToManaConvert){ From 9ef4825a7274cd391406babf3c359f078f1e4c36 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 24 Mar 2015 16:37:12 -0700 Subject: [PATCH 023/846] Fix for gaps in path files during add --- zone/pathing.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zone/pathing.cpp b/zone/pathing.cpp index e01cb6916..8224f3692 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -1478,6 +1478,11 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques { for(uint32 i = 0; i < Head.PathNodeCount; ++i) { + if(PathNodes[i].id - new_id > 1) { + new_id = PathNodes[i].id - 1; + break; + } + if(PathNodes[i].id > new_id) new_id = PathNodes[i].id; } From e6835804affef7cb619cde408e52e8c35d0ed85f Mon Sep 17 00:00:00 2001 From: N0ctrnl Date: Wed, 25 Mar 2015 12:00:14 -0500 Subject: [PATCH 024/846] Update ruletypes.h --- common/ruletypes.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/ruletypes.h b/common/ruletypes.h index 7894c5ebd..c8f9557f5 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -103,6 +103,16 @@ RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's RULE_INT ( Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type RULE_REAL(Character, EnvironmentDamageMulipliter, 1) RULE_BOOL(Character, UnmemSpellsOnDeath, true) +RULE_INT ( Character, TradeskillUpAlchemy, 2 ) // Alchemy skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpBaking, 2 ) // Baking skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpBlacksmithing, 2 ) // Blacksmithing skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpBrewing, 3 ) // Brewing skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpFletching, 2 ) // Fletching skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpJewelcrafting, 2 ) // Jewelcrafting skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpMakePoison, 2 ) // Make Poison skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpPottery, 4 ) // Pottery skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpResearch, 1 ) // Research skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpTinkering, 2 ) // Tinkering skillup rate adjust. Lower is faster. RULE_CATEGORY_END() RULE_CATEGORY( Mercs ) From c4a7acb6d1768d5c25af3504b5a8d6acfaf5e500 Mon Sep 17 00:00:00 2001 From: N0ctrnl Date: Wed, 25 Mar 2015 12:04:03 -0500 Subject: [PATCH 025/846] Update tradeskills.cpp --- zone/tradeskills.cpp | 53 +++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 07ae6d2a5..15cf45e20 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -848,24 +848,41 @@ 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: - case SkillAlchemy: - case SkillJewelryMaking: - case SkillPottery: - skillup_modifier = 4; - break; - case SkillBaking: - case SkillBrewing: - skillup_modifier = 3; - break; - case SkillResearch: - skillup_modifier = 1; - break; - default: - skillup_modifier = 2; - break; - } + 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; + } // 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 From 4dcb679c539b4fce53e48dbd061ffdf860ef8d87 Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 27 Mar 2015 16:40:02 -0400 Subject: [PATCH 026/846] Manual merge of #387. --- zone/spells.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 08030b8b5..a4bef767c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2672,7 +2672,7 @@ int CalcBuffDuration_formula(int level, int formula, int duration) return i < duration ? (i < 1 ? 1 : i) : duration; case 11: - return duration; + return std::min((level + 3) * 30, duration); case 12: return duration; @@ -5254,7 +5254,7 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) sbf->slot = 2; sbf->spellid = buff.spellid; sbf->slotid = 0; - sbf->effect = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); + sbf->effect = 255; sbf->level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); sbf->bufffade = 0; sbf->duration = buff.ticsremaining; From 94d118fdf803c8233dc33f05129aa07ac5307c68 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Fri, 27 Mar 2015 17:12:39 -0400 Subject: [PATCH 027/846] Some vendors would decide not to see based on deity, but messages were picking the next best reason. Added a message choice that seemed to make sense for deity. --- zone/client.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 8246e12a8..3d0a8d75a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7763,7 +7763,8 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) if (primaryfaction > 0) { if (database.GetFactionData(&fmod, GetClass(), GetRace(), GetDeity(), primaryfaction)) { tmpFactionValue = GetCharacterFactionLevel(primaryfaction); - lowestvalue = std::min(tmpFactionValue, std::min(fmod.class_mod, fmod.race_mod)); + lowestvalue = std::min(std::min(tmpFactionValue, fmod.deity_mod), + std::min(fmod.class_mod, fmod.race_mod)); } } // If no primary faction or biggest influence is your faction hit @@ -7811,6 +7812,11 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) } } else if (lowestvalue == fmod.class_mod) { merchant->Say_StringID(zone->random.Int(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass())); + } else { + // Must be deity - these two sound the best for that. + // Can't use a message with a field, GUI wants class/race names. + // for those message IDs. These are straight text. + merchant->Say_StringID(zone->random.Int(WONT_SELL_DEEDS1, WONT_SELL_DEEDS2)); } return; } From b6cc0706338419f0319c5e9f8aaff7cd5696c1d3 Mon Sep 17 00:00:00 2001 From: SecretsOTheP Date: Sun, 29 Mar 2015 01:35:24 -0400 Subject: [PATCH 028/846] Identified the Target Ring fields for RoF/RoF2 and added a perl accessor for the last target ring position received from the client. Usage: $client->GetTargetRingX(), $client->GetTargetRingY(), $client->GetTargetRingZ() --- changelog.txt | 4 ++ common/patches/rof.cpp | 4 ++ common/patches/rof2.cpp | 3 ++ common/patches/rof2_structs.h | 5 ++- common/patches/rof_structs.h | 5 ++- zone/perl_client.cpp | 81 +++++++++++++++++++++++++++++++++++ 6 files changed, 100 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 30cdf9ba7..2dca36203 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/29/2015 == +Secrets: Identified the Target Ring fields for RoF/RoF2. +Secrets: Added a perl accessor for the last target ring position received from the client. Usage: $client->GetTargetRingX(), $client->GetTargetRingY(), $client->GetTargetRingZ() + == 03/12/2015 == Akkadius: [eqemu_update.pl V7] Add Option 9) LUA Modules - Download latest LUA Modules (Required for Lua) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 0495935b1..81865d12b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -4236,6 +4236,10 @@ namespace RoF //IN(inventoryslot); IN(target_id); + IN(y_pos); + IN(x_pos); + IN(z_pos); + FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 9e0bd9c8a..f51ee685c 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4380,6 +4380,9 @@ namespace RoF2 emu->inventoryslot = RoF2ToServerSlot(eq->inventoryslot); //IN(inventoryslot); IN(target_id); + IN(y_pos); + IN(x_pos); + IN(z_pos); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 79da918b9..033e0ed9a 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -658,7 +658,10 @@ struct CastSpell_Struct /*04*/ uint32 spell_id; /*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast /*20*/ uint32 target_id; -/*24*/ uint32 cs_unknown[5]; +/*24*/ uint32 cs_unknown[2]; +/*32*/ float y_pos; +/*36*/ float x_pos; +/*40*/ float z_pos; /*44*/ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index a623c7cf4..456c7b1a9 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -647,7 +647,10 @@ struct CastSpell_Struct /*04*/ uint32 spell_id; /*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast /*20*/ uint32 target_id; -/*24*/ uint32 cs_unknown[5]; +/*24*/ uint32 cs_unknown[2]; +/*32*/ float y_pos; +/*36*/ float x_pos; +/*40*/ float z_pos; /*44*/ }; diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d399d7665..a885922e9 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6110,6 +6110,84 @@ XS(XS_Client_SendSpellAnim) XSRETURN_EMPTY; } +XS(XS_Client_GetTargetRingX); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetTargetRingX) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::GetTargetRingX(THIS)"); + { + Client * THIS; + float 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->GetTargetRingX(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Client_GetTargetRingY); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetTargetRingY) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::GetTargetRingY(THIS)"); + { + Client * THIS; + float 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->GetTargetRingY(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Client_GetTargetRingZ); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetTargetRingZ) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::GetTargetRingZ(THIS)"); + { + Client * THIS; + float 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->GetTargetRingZ(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -6351,6 +6429,9 @@ XS(boot_Client) newXSproto(strcpy(buf, "SendMarqueeMessage"), XS_Client_SendMarqueeMessage, file, "$$$$$$$"); newXSproto(strcpy(buf, "SendColoredText"), XS_Client_SendColoredText, file, "$$$"); newXSproto(strcpy(buf, "SendSpellAnim"), XS_Client_SendSpellAnim, file, "$$$"); + newXSproto(strcpy(buf, "GetTargetRingX"), XS_Client_GetTargetRingX, file, "$$"); + newXSproto(strcpy(buf, "GetTargetRingY"), XS_Client_GetTargetRingY, file, "$$"); + newXSproto(strcpy(buf, "GetTargetRingZ"), XS_Client_GetTargetRingZ, file, "$$"); XSRETURN_YES; } From a75f4e70a1791c436e5a0fa648dc924a7d8aa158 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 29 Mar 2015 02:11:02 -0400 Subject: [PATCH 029/846] sympathetic proc fix --- 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 21ba36e0a..b159fbabc 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5253,7 +5253,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (IsValidSpell(proc_spellid)){ - ProcChance = GetSympatheticProcChances(spell_id, GetSympatheticSpellProcRate(spell_id)); + ProcChance = GetSympatheticProcChances(spell_id, GetSympatheticSpellProcRate(proc_spellid)); if(zone->random.Roll(ProcChance)) SympatheticProcList.push_back(proc_spellid); } From b6a01871d84f09f6a7a14e68eafe565fc1a31f9a Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 28 Mar 2015 23:38:41 -0700 Subject: [PATCH 030/846] Fix for another bazaar problem --- zone/trading.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index b6c869b61..df8d159b1 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1626,23 +1626,10 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic return; } - ReturnTraderReq(app, outtbs->Quantity, ItemID); - - outtbs->TraderID = this->GetID(); - outtbs->Action = BazaarBuyItem; - strn0cpy(outtbs->ItemName, BuyItem->GetItem()->Name, 64); - - int TraderSlot = 0; - - if(BuyItem->IsStackable()) - SendTraderItem(BuyItem->GetItem()->ID, outtbs->Quantity); - else - SendTraderItem(BuyItem->GetItem()->ID, BuyItem->GetCharges()); - // 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->GetClientVersion() >= ClientVersion::RoF) { // RoF+ uses individual item price where older clients use total price outtbs->Price = tbs->Price; @@ -1673,6 +1660,19 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic Log.Out(Logs::Detail, Logs::Trading, "Trader Received: %d Platinum, %d Gold, %d Silver, %d Copper", platinum, gold, silver, copper); + ReturnTraderReq(app, outtbs->Quantity, ItemID); + + outtbs->TraderID = this->GetID(); + outtbs->Action = BazaarBuyItem; + strn0cpy(outtbs->ItemName, BuyItem->GetItem()->Name, 64); + + int TraderSlot = 0; + + if(BuyItem->IsStackable()) + SendTraderItem(BuyItem->GetItem()->ID, outtbs->Quantity); + else + SendTraderItem(BuyItem->GetItem()->ID, BuyItem->GetCharges()); + TraderSlot = Trader->FindTraderItem(tbs->ItemID, outtbs->Quantity); if(RuleB(Bazaar, AuditTrail)) From e304e67cf1a7f24bbaf0f62ad52a0dd8e1b19f51 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sun, 29 Mar 2015 01:00:06 -0700 Subject: [PATCH 031/846] Fix how Alternate Currency Reclaim and Create works if the player has 0 currency available --- zone/client_packet.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 21ab1c7cf..52afd6460 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2604,7 +2604,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) ++iter; } - if (item_id == 0 || reclaim->count == 0) { + if (item_id == 0) { return; } @@ -2624,6 +2624,9 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) /* Cursor to Item storage */ else { uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id); + + if(max_currency == 0) + return; /* If you input more than you have currency wise, just give the max of the currency you currently have */ if (reclaim->count > max_currency) { From 8bd22e8c385baeebe18a61adab5b37aa8002643e Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sun, 29 Mar 2015 02:16:16 -0700 Subject: [PATCH 032/846] 2nd part to Alternate currency fix forgot to paste this back in --- 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 52afd6460..07e9876ca 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2625,7 +2625,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) else { uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id); - if(max_currency == 0) + if(max_currency == 0 || reclaim->count == 0) return; /* If you input more than you have currency wise, just give the max of the currency you currently have */ From a5872b165fbe8582d8f779774291eaee16893aa4 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 1 Apr 2015 13:00:38 -0400 Subject: [PATCH 033/846] Zoning into a new zone did not properly display PCs with tree/object illusions and NPCs wearing gear in non-weapon slots. The illusion thing: Not sure why, but te opcode for BulkZoneSpawn doesn't display the tree/object illusions. I did notice that even OP_Illusion gets rejected by the client if sent before Client_Ready. Maybe that is why. The BULKSpawns cannot be sent that late, I tried moving it in the sequence but it never did the illusions correctly, at any point. So, we new new the single spawn OP code for PCs with those illusions. This works. The NPC gear thing. Same story with BulkZoneSpawn, Not sure why. The data is sent correctly. So now we update the client zoning in (only them) with what the NPCs are wearing. Every othe client already is up to date. --- common/races.h | 2 ++ zone/entity.cpp | 37 ++++++++++++++++++++++++++++++++++--- zone/mob.cpp | 12 ++++++++++-- zone/mob.h | 2 +- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/common/races.h b/common/races.h index 2c360e908..68add5cca 100644 --- a/common/races.h +++ b/common/races.h @@ -47,6 +47,8 @@ #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 diff --git a/zone/entity.cpp b/zone/entity.cpp index a28a4b846..a2fb2657d 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1149,19 +1149,50 @@ void EntityList::SendZoneSpawnsBulk(Client *client) NewSpawn_Struct ns; Mob *spawn; uint32 maxspawns = 100; + EQApplicationPacket *app; if (maxspawns > mob_list.size()) maxspawns = mob_list.size(); BulkZoneSpawnPacket *bzsp = new BulkZoneSpawnPacket(client, maxspawns); + + int32 race=-1; for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { spawn = it->second; if (spawn && spawn->InZone()) { if (spawn->IsClient() && (spawn->CastToClient()->GMHideMe(client) || spawn->CastToClient()->IsHoveringForRespawn())) continue; - memset(&ns, 0, sizeof(NewSpawn_Struct)); - spawn->FillSpawnStruct(&ns, client); - bzsp->AddSpawn(&ns); + + 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)) { + 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); + } + + // On NPCs wearing gear from loottable or previously traded + // to them, mass spawn does not properly update the visual look. + // (Bulk packet sends the same info - client just doesn't use it. + // except on primary/secondary - tested on multiple client types) + // Do that using a Wear Change now. + if (!spawn->IsClient()) { + const Item_Struct *item; + for (int i=0; i< 7 ; ++i) { + item=database.GetItem(spawn->GetEquipment(i)); + if (item != 0) { + spawn->SendWearChange(i,client); + } + } + } } } safe_delete(bzsp); diff --git a/zone/mob.cpp b/zone/mob.cpp index 2053594be..f21ed3d6e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2540,7 +2540,7 @@ uint32 NPC::GetEquipment(uint8 material_slot) const return equipment[invslot]; } -void Mob::SendWearChange(uint8 material_slot) +void Mob::SendWearChange(uint8 material_slot, Client *one_client) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; @@ -2552,7 +2552,15 @@ void Mob::SendWearChange(uint8 material_slot) wc->color.Color = GetEquipmentColor(material_slot); wc->wear_slot_id = material_slot; - entity_list.QueueClients(this, outapp); + if (!one_client) + { + entity_list.QueueClients(this, outapp); + } + else + { + one_client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + } + safe_delete(outapp); } diff --git a/zone/mob.h b/zone/mob.h index 979d9728a..f35857823 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -166,7 +166,7 @@ public: 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 SendWearChange(uint8 material_slot, Client *one_client = nullptr); 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); From bf93d72a431a3037e7105a2a1c8fb42f1751f9fa Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Thu, 2 Apr 2015 13:25:12 -0400 Subject: [PATCH 034/846] Added more changes so mobs armor will appear correctly (pc races only) when the spawn vie gm command or normally with loot tables that equip. Refined previous changes that fixed the issue with zoning in and not seeing previosuly spawned armor by sharing the same module. --- zone/entity.cpp | 26 +++++++++++--------------- zone/mob.cpp | 28 ++++++++++++++++++++++++++++ zone/mob.h | 1 + 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index a2fb2657d..c6de7b33e 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -618,6 +618,7 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) EQApplicationPacket *app = new EQApplicationPacket; npc->CreateSpawnPacket(app, npc); QueueClients(npc, app); + npc->SendArmorAppearance(); safe_delete(app); } else { NewSpawn_Struct *ns = new NewSpawn_Struct; @@ -726,10 +727,16 @@ void EntityList::CheckSpawnQueue() EQApplicationPacket *outapp = 0; iterator.Reset(); + NewSpawn_Struct *ns; + while(iterator.MoreElements()) { outapp = new EQApplicationPacket; - Mob::CreateSpawnPacket(outapp, iterator.GetData()); + ns = iterator.GetData(); + Mob::CreateSpawnPacket(outapp, ns); QueueClients(0, outapp); + auto it = npc_list.find(ns->spawn.spawnId); + NPC *pnpc = it->second; + pnpc->SendArmorAppearance(); safe_delete(outapp); iterator.RemoveCurrent(); } @@ -1179,20 +1186,9 @@ void EntityList::SendZoneSpawnsBulk(Client *client) bzsp->AddSpawn(&ns); } - // On NPCs wearing gear from loottable or previously traded - // to them, mass spawn does not properly update the visual look. - // (Bulk packet sends the same info - client just doesn't use it. - // except on primary/secondary - tested on multiple client types) - // Do that using a Wear Change now. - if (!spawn->IsClient()) { - const Item_Struct *item; - for (int i=0; i< 7 ; ++i) { - item=database.GetItem(spawn->GetEquipment(i)); - if (item != 0) { - spawn->SendWearChange(i,client); - } - } - } + // Despite being sent in the OP_ZoneSpawns packet, the client + // does not display worn armor correctly so display it. + spawn->SendArmorAppearance(client); } } safe_delete(bzsp); diff --git a/zone/mob.cpp b/zone/mob.cpp index 9e9bcbd5d..9b4c2f88e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2552,6 +2552,34 @@ uint32 NPC::GetEquipment(uint8 material_slot) const return equipment[invslot]; } +void Mob::SendArmorAppearance(Client *one_client) +{ + // one_client of 0 means sent to all clients + // + // Despite the fact that OP_NewSpawn and OP_ZoneSpawns include the + // armor being worn and its mats, the client doesn't update the display + // on arrival of these packets reliably. + // + // Send Wear changes if mob is a PC race and item is an armor slot. + // The other packets work for primary/secondary. + + if (IsPlayerRace(race)) + { + if (!IsClient()) + { + const Item_Struct *item; + for (int i=0; i< 7 ; ++i) + { + item=database.GetItem(GetEquipment(i)); + if (item != 0) + { + SendWearChange(i,one_client); + } + } + } + } +} + void Mob::SendWearChange(uint8 material_slot, Client *one_client) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); diff --git a/zone/mob.h b/zone/mob.h index 22f9cb5f1..ada2c56dd 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -171,6 +171,7 @@ public: 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 SendArmorAppearance(Client *one_client = nullptr); virtual void SendWearChange(uint8 material_slot, Client *one_client = nullptr); virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0); From b3efd8a8173c6d22323b2331663108f0266f94bd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 2 Apr 2015 13:42:47 -0400 Subject: [PATCH 035/846] Quick fix for RoF2 discs showing in song window This is just a hack until someone does a proper solution --- common/patches/rof2.cpp | 43 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index f51ee685c..90affbf9a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -158,7 +158,7 @@ namespace RoF2 eq->exit_url_length = emu->exit_url_length; eq->exit_url_length2 = emu->exit_url_length2; - + FINISH_ENCODE(); } @@ -183,7 +183,7 @@ namespace RoF2 { eq->entries[i] = 1; } - + FINISH_ENCODE(); } @@ -513,6 +513,11 @@ namespace RoF2 { 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->entries[i].spell_id); @@ -545,7 +550,7 @@ namespace RoF2 eq->slot = 13; else OUT(slot); - + OUT(spell_id); eq->inventoryslot = ServerToRoF2Slot(emu->inventoryslot); //OUT(inventoryslot); @@ -569,7 +574,7 @@ namespace RoF2 //in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39; - + in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -768,7 +773,7 @@ namespace RoF2 { SETUP_VAR_ENCODE(ExpeditionCompass_Struct); ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); - + OUT(count); for (uint32 i = 0; i < emu->count; ++i) @@ -1315,7 +1320,7 @@ namespace RoF2 switch (emu_e->rank) { case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0 case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1 - case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 + case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE } @@ -2388,9 +2393,9 @@ namespace RoF2 outapp->WriteSInt32(-1); } } - + 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) { outapp->WriteString(emu->potionbelt.Items[r].Name); @@ -2486,7 +2491,7 @@ namespace RoF2 outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(emu->gm); outapp->WriteUInt32(emu->guild_id); - + outapp->WriteUInt8(emu->guildrank); // guildrank outapp->WriteUInt32(0); // Unknown outapp->WriteUInt8(0); // Unknown @@ -2541,12 +2546,12 @@ namespace RoF2 outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown - + for (uint32 r = 0; r < 125; r++) { outapp->WriteUInt8(0); // Unknown } - + outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(emu->currentRadCrystals); @@ -3112,7 +3117,7 @@ namespace RoF2 switch (emu->Rank) { case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0 case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1 - case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 + case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 default: { eq->Rank = emu->Rank; break; } } @@ -3918,7 +3923,7 @@ namespace RoF2 } ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } - + ENCODE(OP_ZonePlayerToBind) { SETUP_VAR_ENCODE(ZonePlayerToBind_Struct); @@ -4109,8 +4114,8 @@ namespace RoF2 switch (emu->guildrank) { case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0 case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1 - case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 - default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // + case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 + default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // } } @@ -4193,7 +4198,7 @@ namespace RoF2 Position->z = emu->z; Position->animation = emu->animation; Position->deltaY = emu->deltaY; - + Buffer += sizeof(structs::Spawn_Struct_Position); if (strlen(emu->title)) @@ -4375,7 +4380,7 @@ namespace RoF2 emu->slot = 10; else IN(slot); - + IN(spell_id); emu->inventoryslot = RoF2ToServerSlot(eq->inventoryslot); //IN(inventoryslot); @@ -5101,7 +5106,7 @@ namespace RoF2 IN(Quantity); Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct (Unknowns) Unknown004 %d, Unknown008 %d, Unknown012 %d, Unknown076 %d, Unknown276 %d", eq->Unknown004, eq->Unknown008, eq->Unknown012, eq->Unknown076, eq->Unknown276); - Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s", + Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s", eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, eq->ItemName); FINISH_DIRECT_DECODE(); @@ -5790,7 +5795,7 @@ namespace RoF2 RoF2Slot.SlotType = maps::MapPossessions; RoF2Slot.MainSlot = serverSlot; } - + if (serverSlot == MainPowerSource) RoF2Slot.MainSlot = slots::MainPowerSource; From 51a314fa314faa960b0b2f2ae8b665dd49a81bfd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 2 Apr 2015 14:54:11 -0400 Subject: [PATCH 036/846] for whatever reason spell based procs generate casting messages --- zone/attack.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 950663a38..e573b12cc 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -384,7 +384,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) int counter_dodge = 0; if (attacker->GetSpecialAbility(COUNTER_AVOID_DAMAGE)){ - + counter_all = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 0); counter_riposte = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE,1); counter_block = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 2); @@ -406,7 +406,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) float riposte_chance = 0.0f; if (CanRiposte && damage > 0 && CanThisClassRiposte() && InFront) { - riposte_chance = (100.0f + static_cast(aabonuses.RiposteChance + spellbonuses.RiposteChance + + riposte_chance = (100.0f + static_cast(aabonuses.RiposteChance + spellbonuses.RiposteChance + itembonuses.RiposteChance - counter_riposte - counter_all)) / 100.0f; skill = GetSkill(SkillRiposte); if (IsClient()) { @@ -437,7 +437,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) float block_chance = 0.0f; if (damage > 0 && CanThisClassBlock() && (InFront || bBlockFromRear)) { - block_chance = (100.0f + static_cast(aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance + + block_chance = (100.0f + static_cast(aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance + itembonuses.IncreaseBlockChance - counter_block - counter_all)) / 100.0f; skill = CastToClient()->GetSkill(SkillBlock); if (IsClient()) { @@ -455,18 +455,18 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) } //Try Shield Block OR TwoHandBluntBlockCheck - if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (InFront || bBlockFromRear)) + if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (InFront || bBlockFromRear)) RollTable[1] += static_cast(aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock - counter_block - counter_all); - else if(damage > 0 && HasTwoHandBluntEquiped() && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) && (InFront || bBlockFromRear)) + else if(damage > 0 && HasTwoHandBluntEquiped() && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) && (InFront || bBlockFromRear)) RollTable[1] += static_cast(aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock - counter_block - counter_all); - + ////////////////////////////////////////////////////// // parry ////////////////////////////////////////////////////// float parry_chance = 0.0f; if (damage > 0 && CanThisClassParry() && InFront){ - parry_chance = (100.0f + static_cast(aabonuses.ParryChance + itembonuses.ParryChance + + parry_chance = (100.0f + static_cast(aabonuses.ParryChance + itembonuses.ParryChance + itembonuses.ParryChance - counter_parry - counter_all)) / 100.0f; skill = CastToClient()->GetSkill(SkillParry); if (IsClient()) { @@ -490,7 +490,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) float dodge_chance = 0.0f; if (damage > 0 && CanThisClassDodge() && InFront){ - dodge_chance = (100.0f + static_cast(aabonuses.DodgeChance + spellbonuses.DodgeChance + + dodge_chance = (100.0f + static_cast(aabonuses.DodgeChance + spellbonuses.DodgeChance + itembonuses.DodgeChance - counter_dodge - counter_all)) / 100.0f; skill = CastToClient()->GetSkill(SkillDodge); @@ -946,10 +946,10 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate bool MagicWeapon = false; if(weapon_item->GetItem() && weapon_item->GetItem()->Magic) MagicWeapon = true; - else + else if(spellbonuses.MagicWeapon || itembonuses.MagicWeapon) MagicWeapon = true; - else + else // An augment on the weapon that is marked magic makes // the item magical. for(x = 0; MagicWeapon == false && x < EmuConstants::ITEM_COMMON_SIZE; x++) @@ -2427,7 +2427,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b bool wasengaged = IsEngaged(); Mob* owner = other->GetOwner(); - Mob* mypet = this->GetPet(); + Mob* mypet = this->GetPet(); Mob* myowner = this->GetOwner(); Mob* targetmob = this->GetTarget(); @@ -3932,7 +3932,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) { 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, + CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0, DefensiveProcs[i].base_spellID); } } @@ -4108,6 +4108,14 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, Log.Out(Logs::Detail, Logs::Combat, "Spell proc %d procing spell %d (%.2f percent chance)", i, SpellProcs[i].spellID, chance); + auto outapp = new EQApplicationPacket(OP_BeginCast,sizeof(BeginCast_Struct)); + BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer; + begincast->caster_id = GetID(); + begincast->spell_id = SpellProcs[i].spellID; + begincast->cast_time = 0; + outapp->priority = 3; + entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); + safe_delete(outapp); ExecWeaponProc(nullptr, SpellProcs[i].spellID, on); CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, SpellProcs[i].base_spellID); From 7e1c296ecfaa1e70794cacc72d74a34c9220a0ef Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 4 Apr 2015 05:04:12 -0700 Subject: [PATCH 037/846] Fix for RoF2 Bow shoot animation struct was off --- common/patches/rof2_structs.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 033e0ed9a..b33d568d0 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4189,9 +4189,11 @@ struct Arrow_Struct { /*068*/ uint8 unknown068; /*069*/ uint8 unknown069; /*070*/ uint8 unknown070; -/*071*/ uint8 item_type; -/*072*/ uint8 skill; -/*073*/ uint8 unknown073[16]; +/*071*/ uint8 unknown071; +/*072*/ uint8 unknown072; +/*073*/ uint8 skill; +/*074*/ uint8 item_type; +/*075*/ uint8 unknown075[14]; /*089*/ char model_name[27]; /*116*/ }; From fc1d6c0676b6a6962d9f0fcbc108e97347ce1a5f Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 4 Apr 2015 17:03:28 -0700 Subject: [PATCH 038/846] Fix for mindrop on drop tables sometimes not being fully respected --- zone/loottables.cpp | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 0d392ec68..5d4b6f92b 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -137,6 +137,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } float roll_t = 0.0f; + 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); @@ -146,15 +147,45 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } } + roll_t_min = roll_t; roll_t = EQEmu::ClampLower(roll_t, 100.0f); if(!active_item_list) { return; } - mindrop = EQEmu::ClampLower(mindrop, (uint8)1); + 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); + if(db_item) { + if(roll < lds->Entries[j].chance) { + npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, + lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false); + + int charges = (int)lds->Entries[i].multiplier; + charges = EQEmu::ClampLower(charges, 1); + + for(int k = 1; k < charges; ++k) { + float c_roll = (float)zone->random.Real(0.0, 100.0); + if(c_roll <= lds->Entries[i].chance) { + npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, + lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false); + } + } + + j = lds->NumEntries; + break; + } + else { + roll -= lds->Entries[j].chance; + } + } + } + } + int item_count = zone->random.Int(mindrop, droplimit); - for(int i = 0; i < item_count; ++i) { + for(int i = mindrop; i < item_count; ++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); From 7662eaf9837fb907158ce7836892b40b50d45a08 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 6 Apr 2015 03:01:48 -0700 Subject: [PATCH 039/846] All animation structs were backwards and poorly named.. RoF+ animations work properly --- common/eq_packet_structs.h | 4 ++-- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/rof2_structs.h | 4 ++-- common/patches/rof_structs.h | 4 ++-- common/patches/sod_structs.h | 4 ++-- common/patches/sof_structs.h | 4 ++-- common/patches/titanium_structs.h | 4 ++-- common/patches/uf_structs.h | 4 ++-- zone/client_packet.cpp | 9 ++++++--- zone/mob.cpp | 6 +++--- 11 files changed, 25 insertions(+), 22 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 57dfe5482..1481fce8c 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1279,8 +1279,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 81865d12b..1c9cf3fd6 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -227,8 +227,8 @@ namespace RoF SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct); OUT(spawnid); - OUT(value); OUT(action); + OUT(speed); FINISH_ENCODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 90affbf9a..681bef783 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -293,8 +293,8 @@ namespace RoF2 SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct); OUT(spawnid); - OUT(value); OUT(action); + OUT(speed); FINISH_ENCODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index b33d568d0..21681df5e 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1418,8 +1418,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 value; -/*03*/ uint8 action; +/*02*/ uint8 action; +/*03*/ uint8 speed; /*04*/ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 456c7b1a9..622305833 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1448,8 +1448,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 value; -/*03*/ uint8 action; +/*02*/ uint8 action; +/*03*/ uint8 speed; /*04*/ }; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index ef4dd32cb..55730423b 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1205,8 +1205,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 51dbef1f5..fff207893 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1182,8 +1182,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 1c3afd90b..5ad997d5b 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -1062,8 +1062,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index d7b14b385..a82bfc4e3 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1260,8 +1260,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 07e9876ca..e7a4684d8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2831,9 +2831,12 @@ void Client::Handle_OP_Animation(const EQApplicationPacket *app) Animation_Struct *s = (Animation_Struct *)app->pBuffer; //might verify spawn ID, but it wouldent affect anything - - DoAnim(s->action, s->value); - + if (GetClientVersion() >= ClientVersion::RoF) { + DoAnim(s->speed, s->action); //This was backwards so we gotta make up for it here + } else { + DoAnim(s->action, s->speed); + } + return; } diff --git a/zone/mob.cpp b/zone/mob.cpp index d196e3ce8..d47be1957 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1314,12 +1314,12 @@ void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; anim->spawnid = GetID(); if(type == 0){ - anim->action = 10; - anim->value=animnum; + anim->action = animnum; + anim->speed = 10; } else{ anim->action = animnum; - anim->value=type; + anim->speed = type; } entity_list.QueueCloseClients(this, outapp, false, 200, 0, ackreq, filter); safe_delete(outapp); From 7bd185b7b7302d99ddadbe9005814f97b6b6a662 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 6 Apr 2015 16:13:58 -0400 Subject: [PATCH 040/846] Fix RoF+ OP_Animation handling That's handled in the patch file --- zone/client_packet.cpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e7a4684d8..201b0d13e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -336,7 +336,7 @@ void MapOpcodes() // Use or Ignore sense heading based on rule. bool train=RuleB(Skills, TrainSenseHeading); - ConnectedOpcodes[OP_SenseHeading] = + ConnectedOpcodes[OP_SenseHeading] = (train) ? &Client::Handle_OP_SenseHeading : &Client::Handle_OP_Ignore; ConnectedOpcodes[OP_SenseTraps] = &Client::Handle_OP_SenseTraps; @@ -412,10 +412,10 @@ int Client::HandlePacket(const EQApplicationPacket *app) if (Log.log_settings[Logs::Client_Server_Packet].is_category_enabled == 1) Log.Out(Logs::General, Logs::Client_Server_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size()); - + if (Log.log_settings[Logs::Client_Server_Packet_With_Dump].is_category_enabled == 1) Log.Out(Logs::General, Logs::Client_Server_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size(), DumpPacketToString(app).c_str()); - + EmuOpcode opcode = app->GetOpcode(); if (opcode == OP_AckPacket) { return true; @@ -457,7 +457,7 @@ int Client::HandlePacket(const EQApplicationPacket *app) case CLIENT_CONNECTED: { ClientPacketProc p; p = ConnectedOpcodes[opcode]; - if(p == nullptr) { + if(p == nullptr) { std::vector args; args.push_back(const_cast(app)); parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args); @@ -2624,7 +2624,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) /* Cursor to Item storage */ else { uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id); - + if(max_currency == 0 || reclaim->count == 0) return; @@ -2831,12 +2831,8 @@ void Client::Handle_OP_Animation(const EQApplicationPacket *app) Animation_Struct *s = (Animation_Struct *)app->pBuffer; //might verify spawn ID, but it wouldent affect anything - if (GetClientVersion() >= ClientVersion::RoF) { - DoAnim(s->speed, s->action); //This was backwards so we gotta make up for it here - } else { - DoAnim(s->action, s->speed); - } - + DoAnim(s->action, s->speed); + return; } @@ -3018,7 +3014,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { DeleteItemInInventory(slot_id, 0, true); DeleteItemInInventory(MainCursor, 0, true); - + if (PutItemInInventory(slot_id, *itemOneToPush, true)) { CalcBonuses(); @@ -5424,12 +5420,12 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app) /* EVENT_ENVIRONMENTAL_DAMAGE */ int final_damage = (damage * RuleR(Character, EnvironmentDamageMulipliter)); char buf[24]; - snprintf(buf, 23, "%u %u %i", ed->damage, ed->dmgtype, final_damage); + snprintf(buf, 23, "%u %u %i", ed->damage, ed->dmgtype, final_damage); parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, buf, 0); } if (GetHP() <= 0) { - mod_client_death_env(); + mod_client_death_env(); Death(0, 32000, SPELL_UNKNOWN, SkillHandtoHand); } SendHPUpdate(); @@ -9846,7 +9842,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) Message_StringID(10, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName()); break; } - + if (!mypet->IsAttackAllowed(GetTarget())) { mypet->Say_StringID(NOT_LEGAL_TARGET); break; @@ -9942,7 +9938,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } } break; - } + } case PET_TAUNT_ON: { if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { Message_StringID(MT_PetResponse, PET_DO_TAUNT); @@ -11676,7 +11672,7 @@ void Client::Handle_OP_SenseHeading(const EQApplicationPacket *app) // eventually sends a message. if (GetLevel() <= 8) chancemod += (9-level) * 10; - + CheckIncreaseSkill(SkillSenseHeading, nullptr, chancemod); return; @@ -12317,7 +12313,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(); - + while (true) { if (inst2 == nullptr) break; @@ -13405,7 +13401,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) safe_delete(gis); this->Trader_StartTrader(); - + // This refreshes the Trader window to display the End Trader button if (GetClientVersion() >= ClientVersion::RoF) { @@ -13550,7 +13546,7 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app) if (app->size == sizeof(TraderClick_Struct)) { - + TraderClick_Struct* tcs = (TraderClick_Struct*)app->pBuffer; Log.Out(Logs::Detail, Logs::Trading, "Handle_OP_TraderShop: TraderClick_Struct TraderID %d, Code %d, Unknown008 %d, Approval %d", From 979590db9ff2185c080d7e4e7d0a9d70249b7f71 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 6 Apr 2015 17:42:15 -0700 Subject: [PATCH 041/846] Fix for lower than intended drop rates for drop limit loot tables after the min drop changes --- zone/loottables.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 5d4b6f92b..3170729d0 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -184,8 +184,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } } - int item_count = zone->random.Int(mindrop, droplimit); - for(int i = mindrop; i < item_count; ++i) { + 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); From 739a7b6f7542bc330ea5b1054684df03644e43b7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 6 Apr 2015 21:46:37 -0400 Subject: [PATCH 042/846] Add decoder for OP_Animation for RoF/RoF2 --- common/patches/rof.cpp | 34 +++++++++++++++++++++++----------- common/patches/rof2.cpp | 12 ++++++++++++ common/patches/rof2_ops.h | 1 + common/patches/rof_ops.h | 1 + 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 1c9cf3fd6..7bb64735b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -479,7 +479,7 @@ namespace RoF eq->slot = 13; else OUT(slot); - + OUT(spell_id); eq->inventoryslot = ServerToRoFSlot(emu->inventoryslot); //OUT(inventoryslot); @@ -702,7 +702,7 @@ namespace RoF { SETUP_VAR_ENCODE(ExpeditionCompass_Struct); ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); - + OUT(count); for (uint32 i = 0; i < emu->count; ++i) @@ -1249,7 +1249,7 @@ namespace RoF switch (emu_e->rank) { case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0 case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1 - case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 + case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE } @@ -2989,7 +2989,7 @@ namespace RoF eq_cse->Enabled = emu_cse->Enabled; eq_cse->LastLogin = emu_cse->LastLogin; eq_cse->Unknown2 = emu_cse->Unknown2; - + emu_ptr += sizeof(CharacterSelectEntry_Struct); eq_ptr += sizeof(structs::CharacterSelectEntry_Struct); } @@ -3046,7 +3046,7 @@ namespace RoF switch (emu->Rank) { case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0 case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1 - case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 + case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 default: { eq->Rank = emu->Rank; break; } } @@ -3313,7 +3313,7 @@ namespace RoF delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); - + #if 0 // original code EQApplicationPacket *in = *p; *p = nullptr; @@ -3777,7 +3777,7 @@ namespace RoF } ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } - + ENCODE(OP_ZonePlayerToBind) { SETUP_VAR_ENCODE(ZonePlayerToBind_Struct); @@ -3968,8 +3968,8 @@ namespace RoF switch (emu->guildrank) { case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0 case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1 - case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 - default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // + case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 + default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // } } @@ -4118,6 +4118,18 @@ namespace RoF FINISH_DIRECT_DECODE(); } + DECODE(OP_Animation) + { + DECODE_LENGTH_EXACT(structs::Animation_Struct); + SETUP_DIRECT_DECODE(Animation_Struct, structs::Animation_Struct); + + IN(spawnid); + IN(action); + IN(speed); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_ApplyPoison) { DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); @@ -4230,7 +4242,7 @@ namespace RoF emu->slot = 10; else IN(slot); - + IN(spell_id); emu->inventoryslot = RoFToServerSlot(eq->inventoryslot); //IN(inventoryslot); @@ -5105,7 +5117,7 @@ namespace RoF hdrf.ItemClass = item->ItemClass; ss.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish)); - + if (strlen(item->Name) > 0) { ss.write(item->Name, strlen(item->Name)); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 681bef783..06c524053 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4269,6 +4269,18 @@ namespace RoF2 FINISH_DIRECT_DECODE(); } + DECODE(OP_Animation) + { + DECODE_LENGTH_EXACT(structs::Animation_Struct); + SETUP_DIRECT_DECODE(Animation_Struct, structs::Animation_Struct); + + IN(spawnid); + IN(action); + IN(speed); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_ApplyPoison) { DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 4e4400cdf..3bb69af5e 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -124,6 +124,7 @@ E(OP_ZoneSpawns) D(OP_AdventureMerchantSell) D(OP_AltCurrencySell) D(OP_AltCurrencySellSelection) +D(OP_Animation) D(OP_ApplyPoison) D(OP_AugmentInfo) D(OP_AugmentItem) diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 08e8647f3..8e9adfdc9 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -109,6 +109,7 @@ E(OP_ZoneSpawns) D(OP_AdventureMerchantSell) D(OP_AltCurrencySell) D(OP_AltCurrencySellSelection) +D(OP_Animation) D(OP_ApplyPoison) D(OP_AugmentInfo) D(OP_AugmentItem) From 0321bf72a511c87ac7d343ad6490f4451768c616 Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 7 Apr 2015 10:22:47 -0400 Subject: [PATCH 043/846] Attempt to catch rare crash in zoneserver process. See http://www.eqemulator.org/forums/showthread.php?t=39549 --- world/zoneserver.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index e24dc421c..ffc22352a 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1318,8 +1318,10 @@ bool ZoneServer::Process() { break; } } - - delete pack; + if (pack) + delete pack; + else + Log.Out(Logs::Detail, Logs::World_Server, "Zoneserver process tried to delete pack when pack does not exist."); } return true; } From 0d4775a9dfbcfbaaacbb36cf916e503ce2f999d8 Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 7 Apr 2015 19:57:36 -0400 Subject: [PATCH 044/846] Adjust to safe_delete packets. --- world/zoneserver.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index ffc22352a..b40f3dc04 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -190,7 +190,7 @@ bool ZoneServer::Process() { Log.Out(Logs::Detail, Logs::World_Server,"Zone authorization failed."); auto pack = new ServerPacket(ServerOP_ZAAuthFailed); SendPacket(pack); - delete pack; + safe_delete(pack); Disconnect(); return false; } @@ -201,7 +201,7 @@ bool ZoneServer::Process() { Log.Out(Logs::Detail, Logs::World_Server,"Zone authorization failed."); auto pack = new ServerPacket(ServerOP_ZAAuthFailed); SendPacket(pack); - delete pack; + safe_delete(pack); Disconnect(); return false; } @@ -779,7 +779,7 @@ bool ZoneServer::Process() { whom->wrace = whoall->wrace; strcpy(whom->whom,whoall->whom); client_list.SendWhoAll(whoall->fromid,whoall->from, whoall->admin, whom, this); - delete whom; + safe_delete(whom); break; } case ServerOP_RequestOnlineGuildMembers: { @@ -958,7 +958,7 @@ bool ZoneServer::Process() { tod->start_eqtime=zoneserver_list.worldclock.getStartEQTime(); tod->start_realtime=zoneserver_list.worldclock.getStartRealTime(); SendPacket(pack); - delete pack; + safe_delete(pack); break; } case ServerOP_SetWorldTime: { @@ -1059,8 +1059,7 @@ bool ZoneServer::Process() { } else { - delete pack; - pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); + auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer; strcpy(scs->grantname, s->grantname); strcpy(scs->ownername, s->ownername); @@ -1076,6 +1075,7 @@ bool ZoneServer::Process() { else { Log.Out(Logs::Detail, Logs::World_Server, "Unable to locate zone record for instance id %u in zoneserver list for ServerOP_Consent_Response operation.", s->instance_id); } + safe_delete(pack); } } else @@ -1091,8 +1091,7 @@ bool ZoneServer::Process() { } else { // send target not found back to requester - delete pack; - pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); + auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer; strcpy(scs->grantname, s->grantname); strcpy(scs->ownername, s->ownername); @@ -1107,13 +1106,13 @@ bool ZoneServer::Process() { else { Log.Out(Logs::Detail, Logs::World_Server, "Unable to locate zone record for zone id %u in zoneserver list for ServerOP_Consent_Response operation.", s->zone_id); } + safe_delete(pack); } } } else { // send target not found back to requester - delete pack; - pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); + auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer; strcpy(scs->grantname, s->grantname); strcpy(scs->ownername, s->ownername); @@ -1128,6 +1127,7 @@ bool ZoneServer::Process() { else { Log.Out(Logs::Detail, Logs::World_Server, "Unable to locate zone record for zone id %u in zoneserver list for ServerOP_Consent_Response operation.", s->zone_id); } + safe_delete(pack); } break; } @@ -1313,15 +1313,17 @@ bool ZoneServer::Process() { } default: { - Log.Out(Logs::Detail, Logs::World_Server,"Unknown ServerOPcode from zone 0x%04x, size %d",pack->opcode,pack->size); + Log.Out(Logs::Detail, Logs::World_Server, "Unknown ServerOPcode from zone 0x%04x, size %d", pack->opcode, pack->size); DumpPacket(pack->pBuffer, pack->size); break; } } - if (pack) - delete pack; - else - Log.Out(Logs::Detail, Logs::World_Server, "Zoneserver process tried to delete pack when pack does not exist."); + if (pack) { + safe_delete(pack); + } + else { + Log.Out(Logs::Detail, Logs::World_Server, "Zoneserver process attempted to delete pack when pack does not exist."); + } } return true; } From ea240f781406118858b61d67c85ca99b45705b48 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 10 Apr 2015 03:06:05 -0400 Subject: [PATCH 045/846] Fix sign issue with hate redux spells --- zone/spells.cpp | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index a4bef767c..ab8b44408 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -82,6 +82,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include #include +#include #ifndef WIN32 #include @@ -2149,7 +2150,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 // caster if they're not using TGB // NOTE: this will always hit the caster, plus the target's group so // it can affect up to 7 people if the targeted group is not our own - + // Allow pets who cast group spells to affect the group. if (spell_target->IsPetOwnerClient() && IsPetOwnerClient()){ Mob* owner = spell_target->GetOwner(); @@ -2157,7 +2158,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 if (owner) spell_target = owner; } - + if(spell_target->IsGrouped()) { Group *target_group = entity_list.GetGroupByMob(spell_target); @@ -3669,22 +3670,16 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r spelltar->Message_StringID(MT_SpellFailure, YOU_RESIST, spells[spell_id].name); } - if(spelltar->IsAIControlled()){ + if (spelltar->IsAIControlled()) { int32 aggro = CheckAggroAmount(spell_id); - if(aggro > 0) { - if(!IsHarmonySpell(spell_id)) - spelltar->AddToHateList(this, aggro); - else - if(!spelltar->PassCharismaCheck(this, spell_id)) - spelltar->AddToHateList(this, aggro); - } - else{ - uint32 newhate = spelltar->GetHateAmount(this) + aggro; - if (newhate < 1) { - spelltar->SetHateAmountOnEnt(this,1); - } else { - spelltar->SetHateAmountOnEnt(this,newhate); - } + if (aggro > 0) { + if (!IsHarmonySpell(spell_id)) + spelltar->AddToHateList(this, aggro); + else if (!spelltar->PassCharismaCheck(this, spell_id)) + spelltar->AddToHateList(this, aggro); + } else { + int newhate = spelltar->GetHateAmount(this) + aggro; + spelltar->SetHateAmountOnEnt(this, std::max(1, newhate)); } } @@ -4404,7 +4399,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use level_mod += (2 * level_diff); } } - + if (CharismaCheck) { /* @@ -5053,7 +5048,7 @@ bool Mob::FindType(uint16 type, bool bOffensive, uint16 threshold) { spells[buffs[i].spellid].base[j], spells[buffs[i].spellid].max[j], buffs[i].casterlevel, buffs[i].spellid); - Log.Out(Logs::General, Logs::Normal, + Log.Out(Logs::General, Logs::Normal, "FindType: type = %d; value = %d; threshold = %d", type, value, threshold); if (value < threshold) From a4ac2b3831d610324c7443b840e330a918a7bcbb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 10 Apr 2015 21:23:29 -0400 Subject: [PATCH 046/846] Added some comments about powersource [skip ci] --- common/item_struct.h | 2 +- zone/attack.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/item_struct.h b/common/item_struct.h index 3ef26db94..1fcb49f51 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -185,7 +185,7 @@ struct Item_Struct { 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 + uint8 AugSlotUnk2[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related uint32 LDoNTheme; uint32 LDoNPrice; uint32 LDoNSold; diff --git a/zone/attack.cpp b/zone/attack.cpp index e573b12cc..2ba068010 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3968,7 +3968,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { } // Innate + aug procs from weapons - // TODO: powersource procs + // TODO: powersource procs -- powersource procs are on invis augs, so shouldn't need anything extra 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); @@ -4054,7 +4054,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on } } } - // TODO: Powersource procs + // TODO: Powersource procs -- powersource procs are from augs so shouldn't need anything extra return; } From 0eda3efe6a1aebbc1c1b9cb09b3b6d9264468bb4 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 11 Apr 2015 22:48:49 -0700 Subject: [PATCH 047/846] Ignore procs when setting recast timers --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index ab8b44408..643b70ca8 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2253,7 +2253,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } //set our reuse timer on long ass reuse_time spells... - if(IsClient()) + if(IsClient() && !isproc) { if(spell_id == casting_spell_id && casting_spell_timer != 0xFFFFFFFF) { From 23dd560a720a737de0affc6347352fd5ea1b16a7 Mon Sep 17 00:00:00 2001 From: JJ Date: Mon, 20 Apr 2015 19:48:52 -0400 Subject: [PATCH 048/846] Don't delete packet when it is still referenced. Create a new packet instead for deconfliction. --- zone/worldserver.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index ec2893e05..aa3e32d43 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1406,17 +1406,16 @@ void WorldServer::Process() { // CONSENT_INVALID_NAME = 397 // TARGET_NOT_FOUND = 101 - safe_delete(pack); - pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); - ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer; + ServerPacket *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); scs->permission = s->permission; scs->zone_id = s->zone_id; scs->instance_id = s->instance_id; scs->message_string_id = TARGET_NOT_FOUND; - worldserver.SendPacket(pack); - safe_delete(pack); + worldserver.SendPacket(scs_pack); + safe_delete(scs_pack); } break; } From c974b30192d89e7eacf67c13916e4f2f0442c911 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 22 Apr 2015 12:29:35 -0400 Subject: [PATCH 049/846] Probable fix for 'Debug Assertion Failure' in Client::GarbleMessage() --- changelog.txt | 4 ++++ zone/client.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 2dca36203..29caca258 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/22/2015 == +Uleat: Probable fix for 'Debug Assertion Failure' in Client::GarbleMessage() when calling the 'isalpha' macro. +ref: https://connect.microsoft.com/VisualStudio/feedback/details/932876/calling-isdigit-with-a-signed-char-1-results-in-a-assert-failure-in-debug-compiles + == 03/29/2015 == Secrets: Identified the Target Ring fields for RoF/RoF2. Secrets: Added a perl accessor for the last target ring position received from the client. Usage: $client->GetTargetRingX(), $client->GetTargetRingY(), $client->GetTargetRingZ() diff --git a/zone/client.cpp b/zone/client.cpp index 677884171..ad1863a05 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7500,7 +7500,7 @@ void Client::GarbleMessage(char *message, uint8 variance) } uint8 chance = (uint8)zone->random.Int(0, 115); // variation just over worst possible scrambling - if (isalpha(message[i]) && (chance <= variance)) { + if (isalpha((unsigned char)message[i]) && (chance <= variance)) { uint8 rand_char = (uint8)zone->random.Int(0,51); // choose a random character from the alpha list message[i] = alpha_list[rand_char]; } From de57c94d3e0bae5b6e481c21073b9c494b559199 Mon Sep 17 00:00:00 2001 From: JJ Date: Thu, 23 Apr 2015 18:42:17 -0400 Subject: [PATCH 050/846] Blocked spell negation fix. --- zone/zone.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/zone.cpp b/zone/zone.cpp index 6cd81929f..eb22b0a6e 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1900,7 +1900,7 @@ bool Zone::IsSpellBlocked(uint32 spell_id, const glm::vec3& location) } case 2: { - if (!IsWithinAxisAlignedBox(location, blocked_spells[x].m_Location - blocked_spells[x].m_Difference, blocked_spells[x].m_Location + blocked_spells[x].m_Difference)) + if (IsWithinAxisAlignedBox(location, blocked_spells[x].m_Location - blocked_spells[x].m_Difference, blocked_spells[x].m_Location + blocked_spells[x].m_Difference)) return true; break; } @@ -1934,7 +1934,7 @@ const char* Zone::GetSpellBlockedMessage(uint32 spell_id, const glm::vec3& locat } case 2: { - if(!IsWithinAxisAlignedBox(location, blocked_spells[x].m_Location - blocked_spells[x].m_Difference, blocked_spells[x].m_Location + blocked_spells[x].m_Difference)) + if(IsWithinAxisAlignedBox(location, blocked_spells[x].m_Location - blocked_spells[x].m_Difference, blocked_spells[x].m_Location + blocked_spells[x].m_Difference)) return blocked_spells[x].message; break; } From 47c9690a32ad60bad667b9a5320f48c3b626d2a3 Mon Sep 17 00:00:00 2001 From: JJ Date: Sat, 25 Apr 2015 11:46:43 -0400 Subject: [PATCH 051/846] Don't garble # commands. --- zone/client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/client.cpp b/zone/client.cpp index ad1863a05..fdab00a3c 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7491,6 +7491,10 @@ void Client::GarbleMessage(char *message, uint8 variance) const char delimiter = 0x12; int delimiter_count = 0; + // Don't garble # commands + if (message[0] == '#') + return; + for (size_t i = 0; i < strlen(message); i++) { // Client expects hex values inside of a text link body if (message[i] == delimiter) { From c84f56f1f53df3f890ae8abce430146fa359f326 Mon Sep 17 00:00:00 2001 From: GPanula Date: Sun, 26 Apr 2015 09:43:05 -0500 Subject: [PATCH 052/846] Avoid returning nulls when looking up if the server is trusted. Nulls will in the query results will cause the loginserver to crash --- loginserver/database_mysql.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index 9cf08563b..d1bcff9b3 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -113,8 +113,8 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); escaped_short_name[length+1] = 0; stringstream query(stringstream::in | stringstream::out); - query << "SELECT WSR.ServerID, WSR.ServerTagDescription, WSR.ServerTrusted, SLT.ServerListTypeID, "; - query << "SLT.ServerListTypeDescription, WSR.ServerAdminID FROM " << server.options.GetWorldRegistrationTable(); + query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,999999) AS ServerListTypeID, "; + query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable(); query << " AS WSR JOIN " << server.options.GetWorldServerTypeTable() << " AS SLT ON WSR.ServerListTypeID = SLT.ServerListTypeID"; query << " WHERE WSR.ServerShortName = '"; query << escaped_short_name; From d7e3a33179c747ff1bd3917e14b58c811563ef57 Mon Sep 17 00:00:00 2001 From: GPanula Date: Sun, 26 Apr 2015 09:56:46 -0500 Subject: [PATCH 053/846] opps, lets use a valid ServeLisTypeID --- loginserver/database_mysql.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index d1bcff9b3..aefe4b094 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -113,7 +113,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); escaped_short_name[length+1] = 0; stringstream query(stringstream::in | stringstream::out); - query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,999999) AS ServerListTypeID, "; + query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, "; query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable(); query << " AS WSR JOIN " << server.options.GetWorldServerTypeTable() << " AS SLT ON WSR.ServerListTypeID = SLT.ServerListTypeID"; query << " WHERE WSR.ServerShortName = '"; From 0d84ede3d62e8a978f608f157145487fe7ab7ef7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 26 Apr 2015 13:35:36 -0400 Subject: [PATCH 054/846] Allow /pet attack by mob name to work ex. /pet attack a_snake --- common/eq_packet_structs.h | 2 +- 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/sof_structs.h | 2 +- common/patches/titanium.cpp | 16 ++++++++-------- common/patches/titanium_structs.h | 2 +- common/patches/uf.cpp | 6 +++--- common/patches/uf_structs.h | 2 +- zone/client_packet.cpp | 17 +++++++++-------- 14 files changed, 31 insertions(+), 30 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 1481fce8c..8aafc0a62 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1160,7 +1160,7 @@ struct TargetReject_Struct { struct PetCommand_Struct { /*000*/ uint32 command; -/*004*/ uint32 unknown; +/*004*/ uint32 target; }; /* diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 7bb64735b..ac6301c75 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -4717,7 +4717,7 @@ namespace RoF SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); IN(command); - emu->unknown = eq->unknown04; + IN(target); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 06c524053..16115d881 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4864,7 +4864,7 @@ namespace RoF2 SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); IN(command); - emu->unknown = eq->unknown04; + IN(target); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 21681df5e..4034e359a 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1293,7 +1293,7 @@ struct TargetReject_Struct { struct PetCommand_Struct { /*00*/ uint32 command; -/*04*/ uint32 unknown04; +/*04*/ uint32 target; /*08*/ uint32 unknown08; }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 622305833..344d0e386 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1323,7 +1323,7 @@ struct TargetReject_Struct { struct PetCommand_Struct { /*00*/ uint32 command; -/*04*/ uint32 unknown04; +/*04*/ uint32 target; /*08*/ uint32 unknown08; }; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index adf4ec06f..88e52a70a 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3349,7 +3349,7 @@ namespace SoD default: emu->command = eq->command; } - OUT(unknown); + IN(target); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 55730423b..8ccb58937 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1091,7 +1091,7 @@ struct TargetReject_Struct { struct PetCommand_Struct { /*000*/ uint32 command; -/*004*/ uint32 unknown; +/*004*/ uint32 target; }; /* diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index a7553e7f9..42ebeb392 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2687,7 +2687,7 @@ namespace SoF default: emu->command = eq->command; } - OUT(unknown); + IN(target); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index fff207893..c969c4b56 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1068,7 +1068,7 @@ struct TargetReject_Struct { struct PetCommand_Struct { /*000*/ uint32 command; -/*004*/ uint32 unknown; +/*004*/ uint32 target; }; /* diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index c8eeea36a..beb338431 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -122,7 +122,7 @@ namespace Titanium EAT_ENCODE(OP_GuildMemberLevelUpdate); // added ; EAT_ENCODE(OP_ZoneServerReady); // added ; - + ENCODE(OP_Action) { ENCODE_LENGTH_EXACT(Action_Struct); @@ -326,7 +326,7 @@ namespace Titanium { SETUP_VAR_ENCODE(ExpeditionCompass_Struct); ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); - + OUT(count); for (uint32 i = 0; i < emu->count; ++i) @@ -1308,7 +1308,7 @@ namespace Titanium VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]); VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); } @@ -1351,7 +1351,7 @@ namespace Titanium InBuffer += strlen(InBuffer) + 1; memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct)); - + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); } @@ -1621,7 +1621,7 @@ namespace Titanium FINISH_DIRECT_DECODE(); } - + DECODE(OP_ApplyPoison) { DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); @@ -1942,7 +1942,7 @@ namespace Titanium default: emu->command = eq->command; } - OUT(unknown); + IN(target); FINISH_DIRECT_DECODE(); } @@ -2151,7 +2151,7 @@ namespace Titanium return serverSlot; // deprecated } - + static inline int16 ServerToTitaniumCorpseSlot(uint32 serverCorpseSlot) { //int16 TitaniumCorpse; @@ -2166,7 +2166,7 @@ namespace Titanium return titaniumSlot; // deprecated } - + static inline uint32 TitaniumToServerCorpseSlot(int16 titaniumCorpseSlot) { //uint32 ServerCorpse; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 5ad997d5b..12042ed31 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -950,7 +950,7 @@ struct TargetReject_Struct { struct PetCommand_Struct { /*000*/ uint32 command; -/*004*/ uint32 unknown; +/*004*/ uint32 target; }; /* diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index aafef5896..038dcf548 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2213,7 +2213,7 @@ namespace UF FINISH_ENCODE(); return; } - + unsigned char *emu_ptr = __emu_buffer; emu_ptr += sizeof(CharacterSelect_Struct); CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr; @@ -3599,7 +3599,7 @@ namespace UF SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); IN(command); - IN(unknown); + IN(target); FINISH_DIRECT_DECODE(); } @@ -3861,7 +3861,7 @@ namespace UF UF::structs::ItemSerializationHeaderFinish hdrf; hdrf.ornamentIcon = ornaIcon; - hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit.. + 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; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index a82bfc4e3..b39bc5b19 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1146,7 +1146,7 @@ struct TargetReject_Struct { struct PetCommand_Struct { /*000*/ uint32 command; -/*004*/ uint32 unknown; +/*004*/ uint32 target; }; /* diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 201b0d13e..12b16610e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9752,6 +9752,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) char val1[20] = { 0 }; PetCommand_Struct* pet = (PetCommand_Struct*)app->pBuffer; Mob* mypet = this->GetPet(); + Mob *target = entity_list.GetMob(pet->target); if (!mypet || pet->command == PET_LEADER) { @@ -9799,22 +9800,22 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) switch (PetCommand) { case PET_ATTACK: { - if (!GetTarget()) + if (!target) break; - if (GetTarget()->IsMezzed()) { - Message_StringID(10, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName()); + if (target->IsMezzed()) { + Message_StringID(10, CANNOT_WAKE, mypet->GetCleanName(), target->GetCleanName()); break; } if (mypet->IsFeared()) break; //prevent pet from attacking stuff while feared - if (!mypet->IsAttackAllowed(GetTarget())) { + if (!mypet->IsAttackAllowed(target)) { mypet->Say_StringID(NOT_LEGAL_TARGET); break; } if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { - if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { + if (target != this && DistanceSquaredNoZ(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { if (mypet->IsHeld()) { if (!mypet->IsFocused()) { mypet->SetHeld(false); //break the hold and guard if we explicitly tell the pet to attack. @@ -9822,12 +9823,12 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetPetOrder(SPO_Follow); } else { - mypet->SetTarget(GetTarget()); + mypet->SetTarget(target); } } zone->AddAggroMob(); - mypet->AddToHateList(GetTarget(), 1); - Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName()); + mypet->AddToHateList(target, 1); + Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), target->GetCleanName()); } } break; From 46d70199099a93d73dd28017d736a84539784eca Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 29 Apr 2015 08:26:59 -0400 Subject: [PATCH 055/846] Spells like flame_lick were not requiring flame lick. Noexpend for flame lick was not working. Also fixed a log message with arguments reversed. --- zone/spells.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index a4bef767c..020064637 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1164,12 +1164,14 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, } else if (!bard_song_mode) { + int noexpend; for(int t_count = 0; t_count < 4; t_count++) { component = spells[spell_id].components[t_count]; - if (component == -1) + noexpend = spells[spell_id].NoexpendReagent[t_count]; + if (component == -1 || noexpend == component) continue; component_count = spells[spell_id].component_counts[t_count]; - Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Consuming %d of spell component item id %d", spell_id, component, component_count); + Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Consuming %d of spell component item id %d", spell_id, component_count, component); // Components found, Deleting // now we go looking for and deleting the items one by one for(int s = 0; s < component_count; s++) From 2c4ca77ffc38bdbd0bbcafbfbea66f95ecbbab46 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 29 Apr 2015 19:18:17 -0400 Subject: [PATCH 056/846] Monk wearing magical gloves can hit creatures that need a magical weapon when fighting hand to hand. --- zone/attack.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 950663a38..da0504902 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -982,14 +982,22 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate return 0; } else{ - if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){ - dmg = GetMonkHandToHandDamage(); - if (hate) *hate += dmg; + bool MagicGloves=false; + ItemInst *gloves=CastToClient()->GetInv().GetItem(MainHands); + if (gloves != nullptr) { + MagicGloves = gloves->GetItem()->Magic; + } + + if((GetClass() == MONK || GetClass() == BEASTLORD)) { + if(MagicGloves || 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)){ + else if(MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)){ dmg = 1; } else From a1960d4a4ab37ad9864cd77023c5b6beea76e76a Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Thu, 30 Apr 2015 08:00:36 -0400 Subject: [PATCH 057/846] Npcs won't respond to hails if they can't see you. --- zone/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 677884171..01d3de558 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1051,12 +1051,12 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s if(quest_manager.ProximitySayInUse()) entity_list.ProcessProximitySay(message, this, language); - if (GetTarget() != 0 && GetTarget()->IsNPC()) { + if (GetTarget() != 0 && GetTarget()->IsNPC() && + !IsInvisible(GetTarget())) { if(!GetTarget()->CastToNPC()->IsEngaged()) { CheckLDoNHail(GetTarget()); CheckEmoteHail(GetTarget(), message); - if(DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= 200) { NPC *tar = GetTarget()->CastToNPC(); parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language); From eea667e22dc574f0115572f653c19409e1862b02 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Thu, 30 Apr 2015 09:33:11 -0400 Subject: [PATCH 058/846] Check to make sure we're a client before a CastToClient(). Missed this on first patch. --- zone/attack.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index da0504902..8689f9b85 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -983,9 +983,11 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate } else{ bool MagicGloves=false; - ItemInst *gloves=CastToClient()->GetInv().GetItem(MainHands); - if (gloves != nullptr) { - MagicGloves = gloves->GetItem()->Magic; + if (IsClient()) { + ItemInst *gloves=CastToClient()->GetInv().GetItem(MainHands); + if (gloves != nullptr) { + MagicGloves = gloves->GetItem()->Magic; + } } if((GetClass() == MONK || GetClass() == BEASTLORD)) { From 06f4fd49efc1dde83c4f18b0f20a93b709798436 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Apr 2015 19:36:21 -0400 Subject: [PATCH 059/846] Implement mob and client melee push New rules: Combat:MeleePush turns melee push on/off Combat:MeleePushChance is the chance that an NPC will be pushed Clients are pushed every successful hit, need to verify or disprove this --- changelog.txt | 5 + common/eq_packet_structs.h | 6 +- common/patches/rof.cpp | 6 +- common/patches/rof2.cpp | 6 +- common/patches/rof2_structs.h | 7 +- common/patches/rof_structs.h | 7 +- common/patches/sod.cpp | 4 +- common/patches/sod_structs.h | 7 +- common/patches/sof.cpp | 4 +- common/patches/sof_structs.h | 7 +- common/patches/titanium_structs.h | 6 +- common/patches/uf.cpp | 6 +- common/patches/uf_structs.h | 7 +- common/ruletypes.h | 8 +- common/skills.cpp | 37 +++ common/skills.h | 1 + .../sql/git/optional/2015_4_30_MeleePush.sql | 2 + zone/attack.cpp | 17 ++ zone/spell_effects.cpp | 286 +++++++++--------- zone/spells.cpp | 4 +- zone/trap.cpp | 2 +- 21 files changed, 257 insertions(+), 178 deletions(-) create mode 100644 utils/sql/git/optional/2015_4_30_MeleePush.sql diff --git a/changelog.txt b/changelog.txt index 29caca258..a90c903bd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/30/2015 == +demonstar55: 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. + == 04/22/2015 == Uleat: Probable fix for 'Debug Assertion Failure' in Client::GarbleMessage() when calling the 'isalpha' macro. ref: https://connect.microsoft.com/VisualStudio/feedback/details/932876/calling-isdigit-with-a-signed-char-1-results-in-a-assert-failure-in-debug-compiles diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 8aafc0a62..c203dad53 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1318,9 +1318,9 @@ struct CombatDamage_Struct /* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells /* 05 */ uint16 spellid; /* 07 */ uint32 damage; -/* 11 */ uint32 unknown11; -/* 15 */ uint32 sequence; // see above notes in Action_Struct -/* 19 */ uint32 unknown19; +/* 11 */ float force; +/* 15 */ float meleepush_xy; // see above notes in Action_Struct +/* 19 */ float meleepush_z; /* 23 */ }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index ac6301c75..b4a6e73d3 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -658,7 +658,9 @@ namespace RoF OUT(type); OUT(spellid); OUT(damage); - eq->sequence = emu->sequence; + OUT(force) + OUT(meleepush_xy); + OUT(meleepush_z) FINISH_ENCODE(); } @@ -4389,7 +4391,7 @@ namespace RoF IN(type); IN(spellid); IN(damage); - emu->sequence = eq->sequence; + IN(meleepush_xy); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 16115d881..e8b98e7af 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -729,7 +729,9 @@ namespace RoF2 OUT(type); OUT(spellid); OUT(damage); - eq->sequence = emu->sequence; + OUT(force) + OUT(meleepush_xy); + OUT(meleepush_z) FINISH_ENCODE(); } @@ -4538,7 +4540,7 @@ namespace RoF2 IN(type); IN(spellid); IN(damage); - emu->sequence = eq->sequence; + IN(meleepush_xy); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 4034e359a..92ff47fda 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1484,9 +1484,10 @@ struct CombatDamage_Struct /* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells /* 05 */ uint32 spellid; /* 09 */ int32 damage; -/* 13 */ float unknown11; // cd cc cc 3d -/* 17 */ float sequence; // see above notes in Action_Struct -/* 21 */ uint8 unknown19[9]; // was [9] +/* 13 */ float force; // cd cc cc 3d +/* 17 */ float meleepush_xy; // see above notes in Action_Struct +/* 21 */ float meleepush_z; +/* 25 */ uint8 unknown25[5]; // was [9] /* 30 */ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 344d0e386..55c86a557 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1514,9 +1514,10 @@ struct CombatDamage_Struct /* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells /* 05 */ uint32 spellid; /* 09 */ int32 damage; -/* 13 */ float unknown11; // cd cc cc 3d -/* 17 */ float sequence; // see above notes in Action_Struct -/* 21 */ uint8 unknown19[9]; // was [9] +/* 13 */ float force; // cd cc cc 3d +/* 17 */ float meleepush_xy; // see above notes in Action_Struct +/* 21 */ float meleepush_z; +/* 25 */ uint8 unknown25[5]; // was [9] /* 30 */ }; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 88e52a70a..8e5656b4b 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -446,7 +446,9 @@ namespace SoD OUT(type); OUT(spellid); OUT(damage); - eq->sequence = emu->sequence; + OUT(force) + OUT(meleepush_xy); + OUT(meleepush_z) FINISH_ENCODE(); } diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 8ccb58937..024814bfd 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1272,9 +1272,10 @@ struct CombatDamage_Struct /* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells /* 05 */ uint16 spellid; /* 07 */ int32 damage; -/* 11 */ float unknown11; // cd cc cc 3d -/* 15 */ float sequence; // see above notes in Action_Struct -/* 19 */ uint8 unknown19[9]; // was [9] +/* 11 */ float force; // cd cc cc 3d +/* 15 */ float meleepush_xy; // see above notes in Action_Struct +/* 19 */ float meleepush_z; +/* 23 */ uint8 unknown23[5]; // was [9] /* 28 */ }; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 42ebeb392..1cd5ee7ed 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -426,7 +426,9 @@ namespace SoF OUT(type); OUT(spellid); OUT(damage); - eq->sequence = emu->sequence; + OUT(force) + OUT(meleepush_xy); + OUT(meleepush_z) FINISH_ENCODE(); } diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index c969c4b56..4dd0e7d80 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1249,9 +1249,10 @@ struct CombatDamage_Struct /* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells /* 05 */ uint16 spellid; /* 07 */ int32 damage; -/* 11 */ float unknown11; // cd cc cc 3d -/* 15 */ float sequence; // see above notes in Action_Struct -/* 19 */ uint8 unknown19[9]; // was [9] +/* 11 */ float force; // cd cc cc 3d +/* 15 */ float meleepush_xy; // see above notes in Action_Struct +/* 19 */ float meleepush_z; +/* 23 */ uint8 unknown23[5]; // was [9] /* 28 */ }; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 12042ed31..53bcb38da 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -1101,9 +1101,9 @@ struct CombatDamage_Struct /* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells /* 05 */ uint16 spellid; /* 07 */ uint32 damage; -/* 11 */ uint32 unknown11; -/* 15 */ uint32 sequence; // see above notes in Action_Struct -/* 19 */ uint32 unknown19; +/* 11 */ float force; +/* 15 */ float meleepush_xy; // see above notes in Action_Struct +/* 19 */ float meleepush_z; /* 23 */ }; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 038dcf548..c2b3dba4a 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -581,7 +581,9 @@ namespace UF OUT(type); OUT(spellid); OUT(damage); - eq->sequence = emu->sequence; + OUT(force) + OUT(meleepush_xy); + OUT(meleepush_z) FINISH_ENCODE(); } @@ -3356,7 +3358,7 @@ namespace UF IN(type); IN(spellid); IN(damage); - emu->sequence = eq->sequence; + IN(meleepush_xy); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index b39bc5b19..49fb9a155 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1330,9 +1330,10 @@ struct CombatDamage_Struct /* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells /* 05 */ uint16 spellid; /* 07 */ int32 damage; -/* 11 */ float unknown11; // cd cc cc 3d -/* 15 */ float sequence; // see above notes in Action_Struct -/* 19 */ uint8 unknown19[9]; // was [9] +/* 11 */ float force; // cd cc cc 3d +/* 15 */ float meleepush_xy; // see above notes in Action_Struct +/* 19 */ float meleepush_z; +/* 23 */ uint8 unknown23[5]; // was [9] /* 28 */ }; diff --git a/common/ruletypes.h b/common/ruletypes.h index c8f9557f5..5c4154cf9 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -377,7 +377,7 @@ RULE_REAL ( Combat, HitBonusPerLevel, 1.2) //You gain this % of hit for every le RULE_REAL ( Combat, WeaponSkillFalloff, 0.33) //For every weapon skill point that's not maxed you lose this % of hit RULE_REAL ( Combat, ArcheryHitPenalty, 0.25) //Archery has a hit penalty to try to help balance it with the plethora of long term +hit modifiers for it RULE_REAL ( Combat, AgiHitFactor, 0.01) -RULE_REAL ( Combat, MinChancetoHit, 5.0) //Minimum % chance to hit with regular melee/ranged +RULE_REAL ( Combat, MinChancetoHit, 5.0) //Minimum % chance to hit with regular melee/ranged RULE_REAL ( Combat, MaxChancetoHit, 95.0) //Maximum % chance to hit with regular melee/ranged RULE_INT ( Combat, MinRangedAttackDist, 25) //Minimum Distance to use Ranged Attacks RULE_BOOL ( Combat, ArcheryBonusRequiresStationary, true) //does the 2x archery bonus chance require a stationary npc @@ -438,6 +438,8 @@ RULE_INT ( Combat, BerserkerFrenzyStart, 35) RULE_INT ( Combat, BerserkerFrenzyEnd, 45) RULE_BOOL ( Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round RULE_BOOL ( Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly. +RULE_BOOL ( Combat, MeleePush, true) // enable melee push +RULE_INT ( Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad RULE_CATEGORY_END() RULE_CATEGORY( NPC ) @@ -577,7 +579,7 @@ RULE_INT ( Console, SessionTimeOut, 600000 ) // Amount of time in ms for the con RULE_CATEGORY_END() RULE_CATEGORY( QueryServ ) -RULE_BOOL( QueryServ, PlayerLogChat, false) // Logs Player Chat +RULE_BOOL( QueryServ, PlayerLogChat, false) // Logs Player Chat RULE_BOOL( QueryServ, PlayerLogTrades, false) // Logs Player Trades RULE_BOOL( QueryServ, PlayerLogHandins, false) // Logs Player Handins RULE_BOOL( QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills @@ -590,7 +592,7 @@ RULE_BOOL( QueryServ, PlayerLogZone, false) // Logs Player Zone Events RULE_BOOL( QueryServ, PlayerLogDeaths, false) // Logs Player Deaths RULE_BOOL( QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State RULE_BOOL( QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling -RULE_BOOL( QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates +RULE_BOOL( QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates RULE_BOOL( QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates RULE_BOOL( QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates RULE_BOOL( QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions diff --git a/common/skills.cpp b/common/skills.cpp index ceb726d8c..363c077d8 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -55,3 +55,40 @@ bool EQEmu::IsSpecializedSkill(SkillUseTypes skill) return false; } } + +float EQEmu::GetSkillMeleePushForce(SkillUseTypes 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 + switch (skill) { + case Skill1HBlunt: + case Skill1HSlashing: + case SkillHandtoHand: + case SkillThrowing: + return 0.1f; + case Skill2HBlunt: + case Skill2HSlashing: + case SkillEagleStrike: + case SkillKick: + case SkillTigerClaw: + //case Skill2HPiercing: + return 0.2f; + case SkillArchery: + return 0.15f; + case SkillBackstab: + case SkillBash: + return 0.3f; + case SkillDragonPunch: + case SkillRoundKick: + return 0.25f; + case SkillFlyingKick: + return 0.4f; + case Skill1HPiercing: + case SkillFrenzy: + return 0.05f; + case SkillIntimidation: + return 2.5f; + default: + return 0.0f; + } +} diff --git a/common/skills.h b/common/skills.h index f7f66b49c..aafb1abce 100644 --- a/common/skills.h +++ b/common/skills.h @@ -270,6 +270,7 @@ typedef enum { namespace EQEmu { bool IsTradeskill(SkillUseTypes skill); bool IsSpecializedSkill(SkillUseTypes skill); + float GetSkillMeleePushForce(SkillUseTypes skill); } #endif diff --git a/utils/sql/git/optional/2015_4_30_MeleePush.sql b/utils/sql/git/optional/2015_4_30_MeleePush.sql new file mode 100644 index 000000000..e640d4237 --- /dev/null +++ b/utils/sql/git/optional/2015_4_30_MeleePush.sql @@ -0,0 +1,2 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:MeleePush', 'true', 'Turns on Melee Push.'); +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:MeleePushChance', '50', 'Chance that an NPC can be pushed from melee.'); diff --git a/zone/attack.cpp b/zone/attack.cpp index a8cff65f5..d89c9932b 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3708,6 +3708,23 @@ 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->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); + // 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); + if (zone->zonemap->CheckLoS(glm::vec3(m_Position), new_pos)) { // If we have LoS on the new loc it should be reachable. + if (IsNPC()) { + // Is this adequate? + Teleport(new_pos); + SendPosUpdate(); + } + } else { + a->force = 0.0f; // we couldn't move there, so lets not + } + } //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) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b159fbabc..8644ac918 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -189,8 +189,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (!IsPowerDistModSpell(spell_id)) SetSpellPowerDistanceMod(0); - - bool SE_SpellTrigger_HasCast = false; + + bool SE_SpellTrigger_HasCast = false; // iterate through the effects in the spell for (i = 0; i < EFFECT_COUNT; i++) @@ -424,11 +424,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) } case SE_Succor: - { - + { + float x, y, z, heading; const char *target_zone; - + x = static_cast(spell.base[1]); y = static_cast(spell.base[0]); z = static_cast(spell.base[2]); @@ -872,7 +872,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(buffs[buffslot].ticsremaining > RuleI(Character, MaxFearDurationForPlayerCharacter)) buffs[buffslot].ticsremaining = RuleI(Character, MaxFearDurationForPlayerCharacter); } - + if(RuleB(Combat, EnableFearPathing)){ if(IsClient()) @@ -921,7 +921,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) cd->source = action->source; cd->type = action->type; cd->spellid = action->spell; - cd->sequence = action->sequence; + cd->meleepush_xy = action->sequence; CastToClient()->QueuePacket(action_packet); if(caster->IsClient() && caster != this) @@ -970,7 +970,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) cd->source = action->source; cd->type = action->type; cd->spellid = action->spell; - cd->sequence = action->sequence; + cd->meleepush_xy = action->sequence; CastToClient()->QueuePacket(action_packet); if(caster->IsClient() && caster != this) @@ -1006,7 +1006,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) cd->source = action->source; cd->type = action->type; cd->spellid = action->spell; - cd->sequence = action->sequence; + cd->meleepush_xy = action->sequence; CastToClient()->QueuePacket(action_packet); if(caster->IsClient() && caster != this) @@ -1291,7 +1291,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Spell Absorb Rune: %+i", effect_value); #endif - if(effect_value > 0) + if(effect_value > 0) buffs[buffslot].magic_rune = effect_value; break; @@ -1329,12 +1329,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_DistanceRemoval: { - buffs[buffslot].caston_x = int(GetX()); - buffs[buffslot].caston_y = int(GetY()); - buffs[buffslot].caston_z = int(GetZ()); + buffs[buffslot].caston_x = int(GetX()); + buffs[buffslot].caston_y = int(GetY()); + buffs[buffslot].caston_z = int(GetZ()); break; } - + case SE_Levitate: { #ifdef SPELL_EFFECT_SPAM @@ -1349,13 +1349,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_DeathSave: { int16 mod = 0; - + if(caster) { mod = caster->aabonuses.UnfailingDivinity + caster->itembonuses.UnfailingDivinity + caster->spellbonuses.UnfailingDivinity; } - + buffs[buffslot].ExtraDIChance = mod; break; } @@ -1440,7 +1440,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) for(int x = EmuConstants::MATERIAL_BEGIN; x <= EmuConstants::MATERIAL_TINT_END; x++) SendWearChange(x); - + if(caster && (caster->spellbonuses.IllusionPersistence || caster->aabonuses.IllusionPersistence || caster->itembonuses.IllusionPersistence)) buffs[buffslot].persistant_buff = 1; @@ -1555,8 +1555,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) { uint16 pet_spellid = CastToNPC()->GetPetSpellID(); uint16 pet_ActSpellCost = caster->GetActSpellCost(pet_spellid, spells[pet_spellid].mana); - int16 ImprovedReclaimMod = caster->spellbonuses.ImprovedReclaimEnergy + - caster->itembonuses.ImprovedReclaimEnergy + + int16 ImprovedReclaimMod = caster->spellbonuses.ImprovedReclaimEnergy + + caster->itembonuses.ImprovedReclaimEnergy + caster->aabonuses.ImprovedReclaimEnergy; if (!ImprovedReclaimMod) @@ -1666,9 +1666,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) // Only allow 2 size changes from Base Size float modifyAmount = (static_cast(effect_value) / 100.0f); float maxModAmount = GetBaseSize() * modifyAmount * modifyAmount; - if ((GetSize() <= GetBaseSize() && GetSize() > maxModAmount) || + if ((GetSize() <= GetBaseSize() && GetSize() > maxModAmount) || (GetSize() >= GetBaseSize() && GetSize() < maxModAmount) || - (GetSize() <= GetBaseSize() && maxModAmount > 1.0f) || + (GetSize() <= GetBaseSize() && maxModAmount > 1.0f) || (GetSize() >= GetBaseSize() && maxModAmount < 1.0f)) { ChangeSize(GetSize() * modifyAmount); @@ -1684,7 +1684,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) rooted = true; if (caster){ - buffs[buffslot].RootBreakChance = caster->aabonuses.RootBreakChance + + buffs[buffslot].RootBreakChance = caster->aabonuses.RootBreakChance + caster->itembonuses.RootBreakChance + caster->spellbonuses.RootBreakChance; } @@ -2249,7 +2249,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) float range = 0.0f; if (spells[spell_id].base2[i]) range = (float)spells[spell_id].base[i]; - + entity_list.AETaunt(caster->CastToClient(), range); } break; @@ -2540,7 +2540,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) int mana_damage = 0; int32 mana_to_use = GetMana() - spell.base[i]; if(mana_to_use > -1) { - SetMana(GetMana() - spell.base[i]); + SetMana(GetMana() - spell.base[i]); TryTriggerOnValueAmount(false, true); // we take full dmg(-10 to make the damage the right sign) mana_damage = spell.base[i] / -10 * spell.base2[i]; @@ -2661,7 +2661,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) { 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])); } @@ -2972,7 +2972,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_TriggerOnReqTarget: case SE_LimitRace: case SE_FcLimitUse: - case SE_FcMute: + case SE_FcMute: case SE_LimitUseType: case SE_FcStunTimeMod: case SE_StunBashChance: @@ -2981,9 +2981,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_LimitCastTimeMax: case SE_TriggerOnReqCaster: case SE_FrenziedDevastation: - case SE_AStacker: - case SE_BStacker: - case SE_CStacker: + case SE_AStacker: + case SE_BStacker: + case SE_CStacker: case SE_DStacker: case SE_DoubleRiposte: case SE_Berserk: @@ -3473,7 +3473,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster, ticsremaining); //Handle client cast DOTs here. if (caster && effect_value < 0){ - + if (IsDetrimentalSpell(spell_id)){ if (caster->IsClient()){ if (!caster->CastToClient()->GetFeigned()) @@ -3715,7 +3715,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste { if (spellbonuses.DistanceRemoval){ - int distance = ((int(GetX()) - buffs[slot].caston_x) * (int(GetX()) - buffs[slot].caston_x)) + + int distance = ((int(GetX()) - buffs[slot].caston_x) * (int(GetX()) - buffs[slot].caston_x)) + ((int(GetY()) - buffs[slot].caston_y) * (int(GetY()) - buffs[slot].caston_y)) + ((int(GetZ()) - buffs[slot].caston_z) * (int(GetZ()) - buffs[slot].caston_z)); @@ -3729,12 +3729,12 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste } case SE_AddHateOverTimePct: - { + { if (IsNPC()){ uint32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100; if (new_hate <= 0) new_hate = 1; - + CastToNPC()->SetHateAmountOnEnt(caster, new_hate); } break; @@ -4136,9 +4136,9 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) uint32 buff_max = GetMaxTotalSlots(); bool found_numhits = false; - + for(uint32 d = 0; d < buff_max; d++) { - + if(IsValidSpell(buffs[d].spellid) && (buffs[d].numhits > 0)) { Numhits(true); found_numhits = true; @@ -4148,7 +4148,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) if (!found_numhits) Numhits(false); } - + if (spells[buffs[slot].spellid].NimbusEffect > 0) RemoveNimbusEffect(spells[buffs[slot].spellid].NimbusEffect); @@ -4204,15 +4204,15 @@ int32 Client::GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect base1 = iter->second.base1; base2 = iter->second.base2; slot = iter->second.slot; - + if (slot && slot == slot_id) { if (GetEffect) return effect; - + if (GetBase1) return base1; - + if (GetBase2) return base2; } @@ -4236,7 +4236,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) uint32 slot = 0; bool LimitFailure = false; - bool LimitInclude[MaxLimitInclude] = { false }; + bool LimitInclude[MaxLimitInclude] = { false }; /* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice spells. 0/1 SE_LimitResist 2/3 SE_LimitSpell @@ -4247,7 +4247,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) 12/13 SE_LimitSpellClass: 14/15 SE_LimitSpellSubClass: Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes - */ + */ int FocusCount = 0; std::map >::const_iterator find_iter = aa_effects.find(aa_ID); @@ -4262,7 +4262,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) base1 = iter->second.base1; base2 = iter->second.base2; slot = iter->second.slot; - + /* AA Foci's can contain multiple focus effects within the same AA. To handle this we will not automatically return zero if a limit is found. @@ -4283,7 +4283,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) if (LimitFailure){ value = 0; LimitFailure = false; - + for(int e = 0; e < MaxLimitInclude; e++) { LimitInclude[e] = false; //Reset array } @@ -4322,7 +4322,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) LimitFailure = true; break; - + case SE_LimitMaxLevel: spell_level = spell.classes[(GetClass()%16) - 1]; lvldiff = spell_level - base1; @@ -4333,7 +4333,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) if(lvlModifier < 1) LimitFailure = true; } - else + else LimitFailure = true; } break; @@ -4357,7 +4357,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) if(base1 < 0) { //Exclude if (spell_id == -base1) LimitFailure = true; - } + } else { LimitInclude[2] = true; if (spell_id == base1) //Include @@ -4450,7 +4450,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) if(base1 < 0) { //Exclude if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) return(0); - } + } else { LimitInclude[12] = true; if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) //Include @@ -4462,7 +4462,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) if(base1 < 0) { //Exclude if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) return(0); - } + } else { LimitInclude[14] = true; if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) //Include @@ -4599,7 +4599,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) //Note if using these as AA, make sure this is first focus used. case SE_SympatheticProc: - if(type == focusSympatheticProc) + if(type == focusSympatheticProc) value = base2; break; @@ -4657,12 +4657,12 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) if(type == focusIncreaseNumHits) value = base1; break; - + case SE_FcLimitUse: if(type == focusFcLimitUse) value = base1; break; - + case SE_FcMute: if(type == focusFcMute) value = base1; @@ -4683,7 +4683,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) if (LimitFailure) return 0; - + return(value*lvlModifier/100); } @@ -4694,7 +4694,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo if(!IsValidSpell(focus_id) || !IsValidSpell(spell_id)) return 0; - + const SPDat_Spell_Struct &focus_spell = spells[focus_id]; const SPDat_Spell_Struct &spell = spells[spell_id]; @@ -4704,7 +4704,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo int lvldiff = 0; uint32 Caston_spell_id = 0; - bool LimitInclude[MaxLimitInclude] = { false }; + bool LimitInclude[MaxLimitInclude] = { false }; /* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice spells. 0/1 SE_LimitResist 2/3 SE_LimitSpell @@ -4715,15 +4715,15 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo 12/13 SE_LimitSpellClass: 14/15 SE_LimitSpellSubClass: Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes - */ - + */ + for (int i = 0; i < EFFECT_COUNT; i++) { switch (focus_spell.effectid[i]) { - + case SE_Blank: break; - + case SE_LimitResist: if(focus_spell.base[i] < 0){ if (spell.resisttype == -focus_spell.base[i]) //Exclude @@ -4735,7 +4735,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo LimitInclude[1] = true; } break; - + case SE_LimitInstant: if(focus_spell.base[i] == 1 && spell.buffduration) //Fail if not instant return 0; @@ -4760,7 +4760,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo return 0; } break; - + case SE_LimitMinLevel: if (IsNPC()) break; @@ -4777,12 +4777,12 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo if (spells[spell_id].cast_time > (uint16)focus_spell.base[i]) return(0); break; - + case SE_LimitSpell: if(focus_spell.base[i] < 0) { //Exclude if (spell_id == -focus_spell.base[i]) return(0); - } + } else { LimitInclude[2] = true; if (spell_id == focus_spell.base[i]) //Include @@ -4871,7 +4871,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo LimitInclude[11] = true; } break; - + case SE_LimitClass: //Do not use this limit more then once per spell. If multiple class, treat value like items would. if (!PassLimitClass(focus_spell.base[i], GetClass())) @@ -4989,7 +4989,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo if (type == focusSpellHaste && focus_spell.base[i] > value) value = focus_spell.base[i]; break; - + case SE_IncreaseSpellDuration: if (type == focusSpellDuration && focus_spell.base[i] > value) value = focus_spell.base[i]; @@ -5161,14 +5161,14 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]); #endif } - + } for(int e = 0; e < MaxLimitInclude; e+=2) { if (LimitInclude[e] && !LimitInclude[e+1]) return 0; } - + 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); @@ -5260,7 +5260,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { } } - /*Note: At present, ff designing custom AA to have a sympathetic proc effect, only use one focus + /*Note: At present, ff designing custom AA to have a sympathetic proc effect, only use one focus effect within the aa_effects data for each AA*[No live AA's use this effect to my knowledge]*/ if (aabonuses.FocusEffects[type]){ @@ -5557,10 +5557,10 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { //item focus for(int i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++){ const Item_Struct *cur = database.GetItem(equipment[i]); - + if(!cur) continue; - + TempItem = cur; if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { @@ -5590,7 +5590,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { } } } - + if(UsedItem && rand_effectiveness && focus_max_real != 0) realTotal = CalcFocusEffect(type, UsedFocusID, spell_id); } @@ -5909,21 +5909,21 @@ float Mob::GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 I int32 total_cast_time = 0; float cast_time_mod = 0.0f; ProcRateMod -= 100; - + if (spells[spell_id].recast_time >= spells[spell_id].recovery_time) total_cast_time = spells[spell_id].recast_time + spells[spell_id].cast_time; else total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time; - - if (total_cast_time > 0 && total_cast_time <= 2500) - cast_time_mod = 0.25f; - else if (total_cast_time > 2500 && total_cast_time < 7000) - cast_time_mod = 0.167f*((static_cast(total_cast_time) - 1000.0f)/1000.0f); - else - cast_time_mod = static_cast(total_cast_time) / 7000.0f; - ProcChance = (RuleR(Casting, AvgSpellProcsPerMinute)/100.0f) * (static_cast(100.0f + ProcRateMod) / 10.0f) + if (total_cast_time > 0 && total_cast_time <= 2500) + cast_time_mod = 0.25f; + else if (total_cast_time > 2500 && total_cast_time < 7000) + cast_time_mod = 0.167f*((static_cast(total_cast_time) - 1000.0f)/1000.0f); + else + cast_time_mod = static_cast(total_cast_time) / 7000.0f; + + ProcChance = (RuleR(Casting, AvgSpellProcsPerMinute)/100.0f) * (static_cast(100.0f + ProcRateMod) / 10.0f) * cast_time_mod * (static_cast(100.0f + ItemProcRate)/100.0f); return ProcChance; @@ -6063,7 +6063,7 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel CheckNumHitsRemaining(NumHit::MatchingSpells, tmp_buffslot); } - + return value; } @@ -6147,8 +6147,8 @@ uint16 Mob::GetSpellEffectResistChance(uint16 spell_id) bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){ - /*Live 5-20-14 Patch Note: Updated all spells which use Remove Detrimental and - Cancel Beneficial spell effects to use a new method. The chances for those spells to + /*Live 5-20-14 Patch Note: Updated all spells which use Remove Detrimental and + Cancel Beneficial spell effects to use a new method. The chances for those spells to affect their targets have not changed unless otherwise noted.*/ /*This should provide a somewhat accurate conversion between pre 5/14 base values and post. @@ -6160,7 +6160,7 @@ bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){ //Effect value of dispels are treated as a level modifier. //Values for scaling were obtain from live parses, best estimates. - caster_level += level_modifier - 1; + caster_level += level_modifier - 1; int dispel_chance = 32; //Baseline chance if no level difference and no modifier int level_diff = caster_level - buff_level; @@ -6201,7 +6201,7 @@ bool Mob::ImprovedTaunt(){ else { if(!TryFadeEffect(spellbonuses.ImprovedTaunt[2])) BuffFadeBySlot(spellbonuses.ImprovedTaunt[2], true); //If caster killed removed effect. - } + } } } @@ -6267,7 +6267,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama Range 845 - 847 : UNKNOWN Range 10000 - 11000 : Limit to Race [base2 - 10000 = Race] (*Not on live: Too useful a function to not implement) THIS IS A WORK IN PROGRESS - */ + */ if (value <= 0) return true; @@ -6276,174 +6276,174 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama switch(value) { - case 100: + case 100: if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Humanoid)) return true; break; - case 101: + case 101: if (GetBodyType() == BT_Dragon || GetBodyType() == BT_VeliousDragon || GetBodyType() == BT_Dragon3) return true; break; - case 102: + case 102: if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Insect)) return true; break; - case 104: + case 104: if (GetBodyType() == BT_Animal) return true; break; - case 105: + case 105: if (GetBodyType() == BT_Plant) return true; break; - case 106: + case 106: if (GetBodyType() == BT_Giant) return true; break; - case 108: + case 108: if ((GetBodyType() != BT_Animal) || (GetBodyType() != BT_Humanoid)) return true; break; - case 109: + case 109: if ((GetRace() == 520) ||(GetRace() == 79)) return true; break; - case 111: + case 111: if ((GetRace() == 527) ||(GetRace() == 11)) return true; break; - case 112: + case 112: if ((GetRace() == 456) ||(GetRace() == 28)) return true; break; - case 113: + case 113: if ((GetRace() == 456) ||(GetRace() == 48)) return true; break; - case 114: + case 114: if (GetRace() == 526) return true; break; - case 115: + case 115: if (GetRace() == 522) return true; break; - case 117: + case 117: if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Plant)) return true; break; - case 118: + case 118: if (GetBodyType() == BT_Summoned) return true; break; - case 119: + case 119: if (IsPet() && ((GetRace() == 212) || ((GetRace() == 75) && GetTexture() == 1))) return true; break; - case 120: + case 120: if (GetBodyType() == BT_Undead) return true; break; - case 121: + case 121: if (GetBodyType() != BT_Undead) return true; break; - case 122: + case 122: if ((GetRace() == 473) || (GetRace() == 425)) return true; break; - case 123: + case 123: if (GetBodyType() == BT_Humanoid) return true; break; - case 124: + case 124: if ((GetBodyType() == BT_Undead) && (GetHPRatio() < 10)) return true; break; - case 125: + case 125: if ((GetRace() == 457 || GetRace() == 88) && (GetHPRatio() < 10)) return true; break; - case 126: + case 126: if ((GetRace() == 581 || GetRace() == 69) && (GetHPRatio() < 10)) return true; break; - case 201: + case 201: if (GetHPRatio() > 75) return true; break; - case 204: + case 204: if (GetHPRatio() < 20) return true; break; - case 216: + case 216: if (!IsEngaged()) return true; break; - case 250: + case 250: if (GetHPRatio() < 35) return true; break; - case 304: - if (IsClient() && + case 304: + if (IsClient() && ((GetClass() == WARRIOR) || (GetClass() == BARD) || (GetClass() == SHADOWKNIGHT) || (GetClass() == PALADIN) || (GetClass() == CLERIC) || (GetClass() == RANGER) || (GetClass() == SHAMAN) || (GetClass() == ROGUE) || (GetClass() == BERSERKER))) return true; break; - case 701: + case 701: if (!IsPet()) return true; break; - case 818: + case 818: if (GetBodyType() == BT_Undead) return true; break; - case 819: + case 819: if (GetBodyType() != BT_Undead) return true; break; - case 842: + case 842: if (GetBodyType() == BT_Humanoid && GetLevel() <= 84) return true; break; - case 843: + case 843: if (GetBodyType() == BT_Humanoid && GetLevel() <= 86) return true; break; - case 844: + case 844: if (GetBodyType() == BT_Humanoid && GetLevel() <= 88) return true; break; @@ -6452,7 +6452,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama //Limit to amount of pets if (value >= 221 && value <= 249){ int count = hate_list.GetSummonedPetCountOnHateList(this); - + for (int base2_value = 221; base2_value <= 249; ++base2_value){ if (value == base2_value){ if (count >= (base2_value - 220)){ @@ -6476,12 +6476,12 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama } //End Damage if (!IsDamage || UseCastRestriction) { - + //Heal only if HP within specified range. [Doesn't follow a set forumla for all values...] if (value >= 400 && value <= 408){ for (int base2_value = 400; base2_value <= 408; ++base2_value){ if (value == base2_value){ - + if (value == 400 && GetHPRatio() <= 25) return true; @@ -6492,11 +6492,11 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama } } } - + else if (value >= 500 && value <= 549){ for (int base2_value = 500; base2_value <= 520; ++base2_value){ if (value == base2_value){ - if (GetHPRatio() < (base2_value - 500)*5) + if (GetHPRatio() < (base2_value - 500)*5) return true; } } @@ -6507,8 +6507,8 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama return true; } } // End Heal - - + + return false; } @@ -6521,18 +6521,18 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){ and you lose your mana. If there is LOS the bolt will lock onto your target and the damage is applied when it hits the target. -If your target moves the bolt moves with it in any direction or angle (consistent with other projectiles). -The way this is written once a bolt is cast a the distance from the initial cast to the target repeatedly - check and if target is moving recalculates at what predicted time the bolt should hit that target in client_process + check and if target is moving recalculates at what predicted time the bolt should hit that target in client_process When bolt hits its predicted point the damage is then done to target. Note: Projectile speed of 1 takes 3 seconds to go 100 distance units. Calculations are based on this constant. - Live Bolt speed: Projectile speed of X takes 5 seconds to go 300 distance units. + Live Bolt speed: Projectile speed of X takes 5 seconds to go 300 distance units. Pending Implementation: What this code can not do is prevent damage if the bolt hits a barrier after passing the initial LOS check because the target has moved while the bolt is in motion. (it is rare to actual get this to occur on live in normal game play) */ if (!spell_target) return false; - - uint8 anim = spells[spell_id].CastingAnim; + + uint8 anim = spells[spell_id].CastingAnim; int slot = -1; //Make sure there is an avialable bolt to be cast. @@ -6545,9 +6545,9 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){ if (slot < 0) return false; - + if (CheckLosFN(spell_target)) { - + float speed_mod = speed * 0.45f; //Constant for adjusting speeds to match calculated impact time. float distance = spell_target->CalculateDistance(GetX(), GetY(), GetZ()); float hit = 60.0f + (distance / speed_mod); @@ -6570,18 +6570,18 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){ ProjectileAnimation(spell_target,0, false, speed,0,0,0, spells[spell_id].player_1); } - //This allows limited support for server using older spell files that do not contain data for bolt graphics. + //This allows limited support for server using older spell files that do not contain data for bolt graphics. else { //Only use fire graphic for fire spells. if (spells[spell_id].resisttype == RESIST_FIRE) { - + if (IsClient()){ if (CastToClient()->GetClientVersionBit() <= 4) //Titanium needs alternate graphic. ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_Titanium)), false, speed); - else + else ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_SOF)), false, speed); } - + else ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_NPC)), false, speed); } @@ -6627,7 +6627,7 @@ void Mob::ResourceTap(int32 damage, uint16 spellid) } void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){ - + if (damage <= 0) return; @@ -6649,15 +6649,15 @@ void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){ uint16 spell_id = spells[buffs[slot].spellid].base[i]; if (damage > spells[buffs[slot].spellid].base2[i]){ - + BuffFadeBySlot(slot); if (IsValidSpell(spell_id)) { - if (IsBeneficialSpell(spell_id)) + if (IsBeneficialSpell(spell_id)) SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); - - else if(attacker) + + else if(attacker) SpellFinished(spell_id, attacker, 10, 0, -1, spells[spell_id].ResistDiff); } } @@ -6734,7 +6734,7 @@ void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster) 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; - + SetSpellPowerDistanceMod(static_cast(mod)); } } diff --git a/zone/spells.cpp b/zone/spells.cpp index 98535e638..db2d61f91 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2563,7 +2563,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) { cd->source = action->source; cd->type = DamageTypeSpell; cd->spellid = action->spell; - cd->sequence = action->sequence; + cd->meleepush_xy = action->sequence; cd->damage = 0; if(!IsEffectInSpell(spell_id, SE_BindAffinity)) { @@ -3827,7 +3827,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r cd->source = action->source; cd->type = action->type; cd->spellid = action->spell; - cd->sequence = action->sequence; + cd->meleepush_xy = action->sequence; cd->damage = 0; if(!IsEffectInSpell(spell_id, SE_BindAffinity)) { diff --git a/zone/trap.cpp b/zone/trap.cpp index 9462e658a..1cce48e19 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -192,7 +192,7 @@ void Trap::Trigger(Mob* trigger) int dmg = zone->random.Int(effectvalue, effectvalue2); trigger->SetHP(trigger->GetHP() - dmg); a->damage = dmg; - a->sequence = zone->random.Int(0, 1234567); + a->meleepush_xy = zone->random.Int(0, 1234567); a->source = GetHiddenTrigger()!=nullptr ? GetHiddenTrigger()->GetID() : trigger->GetID(); a->spellid = 0; a->target = trigger->GetID(); From 399942f6f4423728b5050c901efab6a1f4ebfd4a Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Fri, 1 May 2015 07:02:23 -0400 Subject: [PATCH 060/846] Allow Kerran race illusions to be either gender. --- zone/mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 9b4c2f88e..afabeaae4 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1787,7 +1787,7 @@ bool Mob::IsPlayerRace(uint16 in_race) { uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) { - if (Mob::IsPlayerRace(in_race) || in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118) { + if (Mob::IsPlayerRace(in_race) || in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118 || in_race == 23) { if (in_gender >= 2) { // Male default for PC Races return 0; From eda74e66e03dbaeb8d85f8264c0b5a930e053650 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Fri, 1 May 2015 19:22:06 -0400 Subject: [PATCH 061/846] Fix proc messages for undead proc against non-undead. --- zone/spells.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 020064637..891ad64f6 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1479,7 +1479,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce { //invalid target Log.Out(Logs::Detail, Logs::Spells, "Spell %d canceled: invalid target of body type %d (undead)", spell_id, mob_body); - Message_StringID(13,SPELL_NEED_TAR); + if(!spell_target) + Message_StringID(13,SPELL_NEED_TAR); + else + Message_StringID(13,CANNOT_AFFECT_NPC); return false; } CastAction = SingleTarget; From 6c8dfbdc4d7eca1a0d7d1bcc0e28a0009ce4f6ef Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Fri, 1 May 2015 20:40:46 -0400 Subject: [PATCH 062/846] Mobs that were blinded were being included in every use of IsFeared() which was bad. Blinded mobs can still cast spells when in melee range. The original fear code had no blind rolled into it, I added that. This was an overright. I changed the macro to use bonues and fleemode instead of looking at curfp. Testing looks good to me. --- zone/mob.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index ada2c56dd..1d41f4098 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -803,8 +803,7 @@ public: //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); } + bool IsFeared() { return (spellbonuses.IsFeared || flee_mode); } // This returns true if the mob is feared or fleeing due to low HP inline void StartFleeing() { flee_mode = true; CalculateNewFearpoint(); } void ProcessFlee(); void CheckFlee(); From 1ab3cf53e2106e56c58d8171d3f70b64fe0566c6 Mon Sep 17 00:00:00 2001 From: GPanula Date: Fri, 1 May 2015 22:53:36 -0500 Subject: [PATCH 063/846] if ServerID is null, it will crash the loginserver when it tries to add the new server to tblWorldServerRegistration table --- loginserver/database_mysql.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index aefe4b094..cffec5548 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -254,7 +254,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); escaped_short_name[length+1] = 0; stringstream query(stringstream::in | stringstream::out); - query << "SELECT max(ServerID) FROM " << server.options.GetWorldRegistrationTable(); + query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable(); if(mysql_query(db, query.str().c_str()) != 0) { From 59ab7071b7a1525ffc9e8057818683b5b9fcb8ff Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 2 May 2015 07:00:52 -0400 Subject: [PATCH 064/846] Beginnings of fix to SendBuffDuration. --- zone/spells.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 891ad64f6..72c659271 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5259,8 +5259,31 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) sbf->slot = 2; sbf->spellid = buff.spellid; sbf->slotid = 0; - sbf->effect = 255; sbf->level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); + + 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, any + // other value has the GUI doing that value at the same time server + // is doing theirs. This makes the two match. + int index = GetSpellEffectIndex(buff.spellid, SE_CurrentHP); + sbf->effect = abs(spells[buff.spellid].base[index]); + } + else + { + // Default to what old code did until we find a better fix for + // other spell lines. + sbf->effect=sbf->level; + } + sbf->bufffade = 0; sbf->duration = buff.ticsremaining; sbf->num_hits = buff.numhits; From 77dca484fee2ec690ec079679db1b5a12079e6a7 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 6 May 2015 15:39:36 -0400 Subject: [PATCH 065/846] The mob AT_Anim (as set in spawn2) was not correctly displaying in various situations. First, the set function for mob _appearance optimized sending a message if the new appearance was equal to the old. This cann't be done, as the 1st time the zone runs there is no client when the set function is called. If we're combining set/send, as we are, better to always do both. This fixes several of the cases. Repop also did not work, as no code was being called reliably to set appearance and update the client based on code path and various flags. This is also fixed. --- zone/entity.cpp | 2 ++ zone/mob.cpp | 10 ++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index c6de7b33e..5646f0870 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -619,6 +619,7 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) npc->CreateSpawnPacket(app, npc); QueueClients(npc, app); npc->SendArmorAppearance(); + npc->SetAppearance(npc->GetGuardPointAnim(),false); safe_delete(app); } else { NewSpawn_Struct *ns = new NewSpawn_Struct; @@ -737,6 +738,7 @@ void EntityList::CheckSpawnQueue() auto it = npc_list.find(ns->spawn.spawnId); NPC *pnpc = it->second; pnpc->SendArmorAppearance(); + pnpc->SetAppearance(pnpc->GetGuardPointAnim(),false); safe_delete(outapp); iterator.RemoveCurrent(); } diff --git a/zone/mob.cpp b/zone/mob.cpp index afabeaae4..66fbc7809 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2040,12 +2040,10 @@ const int32& Mob::SetMana(int32 amount) 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); - } + _appearance = app; + SendAppearancePacket(AT_Anim, GetAppearanceValue(app), true, iIgnoreSelf); + if (this->IsClient() && this->IsAIControlled()) + SendAppearancePacket(AT_Anim, ANIM_FREEZE, false, false); } bool Mob::UpdateActiveLight() From 4a4a0c5e8bdcbe5cb3e49b8422e396dc21bf65d7 Mon Sep 17 00:00:00 2001 From: SecretsOTheP Date: Wed, 6 May 2015 18:50:08 -0400 Subject: [PATCH 066/846] * -Exported additional entity IDs for dropped items to perl upon EVENT_CLICK_OBJECT (clicker_id) and EVENT_PLAYER_PICKUP ($picked_up_entity_id) -Identified Size / SolidType fields in newer clients and properly exported it to EQEmu for use in UF, RoF, RoF2 via perl accessors. (Should work in LUA, no testing was done though for LUA) -Added a sanity check for size to objects. Any size over 5000.f seems to crash the newer clients' graphical engines and PEQ has some containers filled in with bogus values. -Added the ability to return a value on perl function EVENT_PLAYER_PICKUP which sends a fake dropped item ID to the client to generate the appropriate client response so the item can stay on the ground and not be 'picked up'. Should also work in LUA, didn't test LUA. -Renamed unknown008 and unknown010 to size and solidtype respectively for objects. --- common/patches/rof.cpp | 4 ++-- common/patches/rof2.cpp | 4 ++-- common/patches/uf.cpp | 4 ++-- zone/client_packet.cpp | 2 +- zone/command.cpp | 46 ++++++++++++++++++++--------------------- zone/embparser.cpp | 2 ++ zone/object.cpp | 25 +++++++++++++++++----- zone/zone.cpp | 4 ++-- 8 files changed, 54 insertions(+), 37 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index b4a6e73d3..da9ed18f9 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -975,8 +975,8 @@ namespace RoF 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); // Normally 0, but seen (float)255.0 as well - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Unknown - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 1); // Need to add emu->size to struct + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown + 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); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index e8b98e7af..2041a3c3a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1046,8 +1046,8 @@ namespace RoF2 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); // Normally 0, but seen (float)255.0 as well - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Unknown - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 1); // Need to add emu->size to struct + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown + 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); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index c2b3dba4a..4fbc7b6b8 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -857,8 +857,8 @@ namespace UF // 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(uint32, OutBuffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observed 0 - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // This appears to be the size field. + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown, observed 0 + 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); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 12b16610e..e2c63c232 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4126,7 +4126,7 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app) char buf[10]; snprintf(buf, 9, "%u", click_object->drop_id); buf[9] = '\0'; - parse->EventPlayer(EVENT_CLICK_OBJECT, this, buf, 0, &args); + parse->EventPlayer(EVENT_CLICK_OBJECT, this, buf, GetID(), &args); } // Observed in RoF after OP_ClickObjectAction: diff --git a/zone/command.cpp b/zone/command.cpp index b383e09b3..3f3d4b6c1 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -8549,20 +8549,20 @@ void command_object(Client *c, const Seperator *sep) od.object_type = atoi(row[7]); icon = atoi(row[8]); - od.unknown008 = atoi(row[9]); - od.unknown010 = atoi(row[10]); + od.size = atoi(row[9]); + od.solidtype = atoi(row[10]); od.unknown020 = atoi(row[11]); switch (od.object_type) { case 0: // Static Object case staticType: // Static Object unlocked for changes - if (od.unknown008 == 0) // Unknown08 field is optional Size parameter for static objects - od.unknown008 = 100; // Static object default Size is 100% + if (od.size == 0) // Unknown08 field is optional Size parameter for static objects + od.size = 100; // Static object default Size is 100% c->Message(0, "- STATIC Object (%s): id %u, x %.1f, y %.1f, z %.1f, h %.1f, model %s, " "size %u, solidtype %u, incline %u", (od.object_type == 0) ? "locked" : "unlocked", id, od.x, od.y, od.z, - od.heading, od.object_name, od.unknown008, od.unknown010, od.unknown020); + od.heading, od.object_name, od.size, od.solidtype, od.unknown020); break; case OT_DROPPEDITEM: // Ground Spawn @@ -8620,10 +8620,10 @@ void command_object(Client *c, const Seperator *sep) switch (od.object_type) { case 0: // Static Object if ((sep->argnum - col) > 3) { - od.unknown008 = atoi(sep->arg[4 + col]); // Size specified + od.size = atoi(sep->arg[4 + col]); // Size specified if ((sep->argnum - col) > 4) { - od.unknown010 = atoi(sep->arg[5 + col]); // SolidType specified + od.solidtype = atoi(sep->arg[5 + col]); // SolidType specified if ((sep->argnum - col) > 5) od.unknown020 = atoi(sep->arg[6 + col]); // Incline specified @@ -8922,16 +8922,16 @@ void command_object(Client *c, const Seperator *sep) return; } - od.unknown008 = atoi(sep->arg[4]); + od.size = atoi(sep->arg[4]); o->SetObjectData(&od); - if (od.unknown008 == 0) // 0 == unspecified == 100% - od.unknown008 = 100; + if (od.size == 0) // 0 == unspecified == 100% + od.size = 100; c->Message(0, "Static Object %u set to %u%% size. Size will take effect when you commit to the " "database with '#object Save', after which the object will be unchangeable until " "you unlock it again with '#object Edit' and zone out and back in.", - id, od.unknown008); + id, od.size); } else if (strcmp(sep->arg[3], "solidtype") == 0) { if (od.object_type != staticType) { @@ -8946,13 +8946,13 @@ void command_object(Client *c, const Seperator *sep) return; } - od.unknown010 = atoi(sep->arg[4]); + od.solidtype = atoi(sep->arg[4]); o->SetObjectData(&od); c->Message(0, "Static Object %u set to SolidType %u. Change will take effect when you commit " "to the database with '#object Save'. Support for this property is on a " "per-model basis, mostly seen in smaller objects such as chests and tables.", - id, od.unknown010); + id, od.solidtype); } else if (strcmp(sep->arg[3], "icon") == 0) { if ((od.object_type < 2) || (od.object_type == staticType)) { @@ -9239,24 +9239,24 @@ void command_object(Client *c, const Seperator *sep) "unknown08 = %u, unknown10 = %u, unknown20 = %u " "WHERE ID = %u", zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, - od.heading, od.object_name, od.object_type, icon, od.unknown008, - od.unknown010, od.unknown020, id); + od.heading, od.object_name, od.object_type, icon, od.size, + od.solidtype, od.unknown020, id); else if (id == 0) query = StringFormat("INSERT INTO object " "(zoneid, version, xpos, ypos, zpos, heading, objectname, " "type, icon, unknown08, unknown10, unknown20) " "VALUES (%u, %u, %.1f, %.1f, %.1f, %.1f, '%s', %u, %u, %u, %u, %u)", zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, - od.heading, od.object_name, od.object_type, icon, od.unknown008, - od.unknown010, od.unknown020); + od.heading, od.object_name, od.object_type, icon, od.size, + od.solidtype, od.unknown020); else query = StringFormat("INSERT INTO object " "(id, zoneid, version, xpos, ypos, zpos, heading, objectname, " "type, icon, unknown08, unknown10, unknown20) " "VALUES (%u, %u, %u, %.1f, %.1f, %.1f, %.1f, '%s', %u, %u, %u, %u, %u)", id, zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, - od.heading, od.object_name, od.object_type, icon, od.unknown008, - od.unknown010, od.unknown020); + od.heading, od.object_name, od.object_type, icon, od.size, + od.solidtype, od.unknown020); results = database.QueryDatabase(query); if (!results.Success()) { @@ -9314,12 +9314,12 @@ void command_object(Client *c, const Seperator *sep) memcpy(door.dest_zone, "NONE", 5); - if ((door.size = od.unknown008) == 0) // unknown08 = optional size percentage + if ((door.size = od.size) == 0) // unknown08 = optional size percentage door.size = 100; switch ( door.opentype = - od.unknown010) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) + od.solidtype) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) { case 0: door.opentype = 31; @@ -9576,8 +9576,8 @@ void command_object(Client *c, const Seperator *sep) strn0cpy(od.object_name, row[4], sizeof(od.object_name)); od.object_type = atoi(row[5]); icon = atoi(row[6]); - od.unknown008 = atoi(row[7]); - od.unknown010 = atoi(row[8]); + od.size = atoi(row[7]); + od.solidtype = atoi(row[8]); od.unknown020 = atoi(row[9]); if (od.object_type == 0) diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 3bfb2e90a..db017750a 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1277,6 +1277,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_PLAYER_PICKUP:{ ExportVar(package_name.c_str(), "picked_up_id", data); + ExportVar(package_name.c_str(), "picked_up_entity_id", extradata); break; } @@ -1367,6 +1368,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_CLICK_OBJECT: { ExportVar(package_name.c_str(), "objectid", data); + ExportVar(package_name.c_str(), "clicker_id", extradata); break; } diff --git a/zone/object.cpp b/zone/object.cpp index 7dd97d355..7255cd9e9 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -485,7 +485,22 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) buf[9] = '\0'; std::vector args; args.push_back(m_inst); - parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, buf, 0, &args); + if(parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, buf, this->GetID(), &args)) + { + EQApplicationPacket* 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; + entity_list.QueueClients(nullptr, outapp, false); + safe_delete(outapp); + + // No longer using a tradeskill object + sender->SetTradeskillObject(nullptr); + user = nullptr; + + return true; + } + // Transfer item to client sender->PutItemInInventory(MainCursor, *m_inst, false); @@ -809,7 +824,7 @@ void Object::SetModelName(const char* modelname) void Object::SetSize(uint16 size) { - m_data.unknown008 = size; + m_data.size = size; EQApplicationPacket* app = new EQApplicationPacket(); EQApplicationPacket* app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); @@ -822,7 +837,7 @@ void Object::SetSize(uint16 size) void Object::SetSolidType(uint16 solidtype) { - m_data.unknown010 = solidtype; + m_data.solidtype = solidtype; EQApplicationPacket* app = new EQApplicationPacket(); EQApplicationPacket* app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); @@ -835,12 +850,12 @@ void Object::SetSolidType(uint16 solidtype) uint16 Object::GetSize() { - return m_data.unknown008; + return m_data.size; } uint16 Object::GetSolidType() { - return m_data.unknown010; + return m_data.solidtype; } const char* Object::GetModelName() diff --git a/zone/zone.cpp b/zone/zone.cpp index eb22b0a6e..56181695d 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -241,8 +241,8 @@ bool Zone::LoadZoneObjects() { data.object_type = type; data.linked_list_addr[0] = 0; data.linked_list_addr[1] = 0; - data.unknown008 = (uint32)atoi(row[11]); - data.unknown010 = (uint32)atoi(row[12]); + 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]); From cfedf53dc081864262263cb1f577b510fa4dd804 Mon Sep 17 00:00:00 2001 From: SecretsOTheP Date: Wed, 6 May 2015 18:53:41 -0400 Subject: [PATCH 067/846] *cone of shame* forgot a file --- common/eq_packet_structs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c203dad53..980fcc419 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2535,8 +2535,8 @@ struct BookRequest_Struct { */ struct Object_Struct { /*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list -/*08*/ uint16 unknown008; // -/*10*/ uint16 unknown010; // +/*08*/ uint16 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; // From 8224a9e7762c77396ba11bc750ec0713fd377f91 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 6 May 2015 23:40:01 -0400 Subject: [PATCH 068/846] Fix bards not playing their instruments This is a rather naive implementation, we should really save the PlayerState server side so we can have newly zoned in clients after the equip happened to see the animation. But until we find all the places the PlayerState is sent, this is fine. --- zone/client_packet.cpp | 24 ++++++++++++++++++++++++ zone/client_packet.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e2c63c232..4424d1f47 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -381,6 +381,8 @@ void MapOpcodes() ConnectedOpcodes[OP_VetClaimRequest] = &Client::Handle_OP_VetClaimRequest; ConnectedOpcodes[OP_VoiceMacroIn] = &Client::Handle_OP_VoiceMacroIn; ConnectedOpcodes[OP_WearChange] = &Client::Handle_OP_WearChange; + ConnectedOpcodes[OP_WeaponEquip2] = &Client::Handle_OP_WeaponEquip2; + ConnectedOpcodes[OP_WeaponUnequip2] = &Client::Handle_OP_WeaponUnequip2; ConnectedOpcodes[OP_WhoAllRequest] = &Client::Handle_OP_WhoAllRequest; ConnectedOpcodes[OP_WorldUnknown001] = &Client::Handle_OP_Ignore; ConnectedOpcodes[OP_XTargetAutoAddHaters] = &Client::Handle_OP_XTargetAutoAddHaters; @@ -13889,6 +13891,28 @@ void Client::Handle_OP_WearChange(const EQApplicationPacket *app) return; } +void Client::Handle_OP_WeaponEquip2(const EQApplicationPacket *app) +{ + if (app->size != 8) { + std::cout << "Wrong size: OP_WeaponEquip2, size=" << app->size << ", expected " << 8 << std::endl; + return; + } + + // We should probably save it server side, but for now this works + entity_list.QueueClients(this, app, false); +} + +void Client::Handle_OP_WeaponUnequip2(const EQApplicationPacket *app) +{ + if (app->size != 8) { + std::cout << "Wrong size: OP_WeaponUnequip2, size=" << app->size << ", expected " << 8 << std::endl; + return; + } + + // We should probably save it server side, but for now this works + entity_list.QueueClients(this, app, false); +} + void Client::Handle_OP_WhoAllRequest(const EQApplicationPacket *app) { if (app->size != sizeof(Who_All_Struct)) { diff --git a/zone/client_packet.h b/zone/client_packet.h index 51b6713b7..0f09cf574 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -288,6 +288,8 @@ void Handle_OP_VetClaimRequest(const EQApplicationPacket *app); void Handle_OP_VoiceMacroIn(const EQApplicationPacket *app); void Handle_OP_WearChange(const EQApplicationPacket *app); + void Handle_OP_WeaponEquip2(const EQApplicationPacket *app); + void Handle_OP_WeaponUnequip2(const EQApplicationPacket *app); void Handle_OP_WhoAllRequest(const EQApplicationPacket *app); void Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app); void Handle_OP_XTargetRequest(const EQApplicationPacket *app); From ebe2ea697ebb6301abf1c128e7c11ae53141b4ac Mon Sep 17 00:00:00 2001 From: hateborne Date: Thu, 7 May 2015 16:06:06 -0400 Subject: [PATCH 069/846] Exporting ConnectNodeToNode and AddNode (from Pathing) to Perl Exporting ConnectNodeToNode and AddNode from pathing to Perl so devs can more quickly build grids with Perl script(s). --- zone/embparser_api.cpp | 48 +++++++++++++++++++++++++++ zone/questmgr.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++ zone/questmgr.h | 2 ++ 3 files changed, 123 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 1729978b0..800ed9f83 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1917,6 +1917,52 @@ XS(XS__repopzone) XSRETURN_EMPTY; } +XS(XS__ConnectNodeToNode); +XS(XS__ConnectNodeToNode) +{ + dXSARGS; + if (items != 4) + Perl_croak(aTHX_ "Usage: ConnectNodeToNode(node1, node2, teleport, doorid)"); + + int node1 = (int)SvIV(ST(0)); + int node2 = (int)SvIV(ST(1)); + int teleport = (int)SvIV(ST(2)); + int doorid = (int)SvIV(ST(3)); + + quest_manager.ConnectNodeToNode(node1, node2, teleport, doorid); + + XSRETURN_EMPTY; +} + +XS(XS__AddNode); +XS(XS__AddNode) +{ + dXSARGS; + //void QuestManager::AddNode(float x, float y, float z, float best_z, int32 requested_id); + if (items < 3 || items > 5) + Perl_croak(aTHX_ "Usage: AddNode(x, y, z, [best_z], [requested_id])"); + + int x = (int)SvIV(ST(0)); + int y = (int)SvIV(ST(1)); + int z = (int)SvIV(ST(2)); + int best_z = 0; + int requested_id = 0; + + if (items == 4) + { + best_z = (int)SvIV(ST(3)); + } + else if (items == 5) + { + best_z = (int)SvIV(ST(3)); + requested_id = (int)SvIV(ST(4)); + } + + quest_manager.AddNode(x, y, z, best_z, requested_id); + + XSRETURN_EMPTY; +} + XS(XS__npcrace); XS(XS__npcrace) { @@ -3699,6 +3745,8 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "reloadzonestaticdata"), XS__reloadzonestaticdata, file); newXS(strcpy(buf, "removetitle"), XS__removetitle, file); newXS(strcpy(buf, "repopzone"), XS__repopzone, file); + newXS(strcpy(buf, "ConnectNodeToNode"), XS__ConnectNodeToNode, file); + newXS(strcpy(buf, "AddNode"), XS__AddNode, file); newXS(strcpy(buf, "resettaskactivity"), XS__resettaskactivity, file); newXS(strcpy(buf, "respawn"), XS__respawn, file); newXS(strcpy(buf, "resume"), XS__resume, file); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 47d92b68e..b9025956e 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -668,6 +668,79 @@ void QuestManager::repopzone() { } } +void QuestManager::ConnectNodeToNode(int node1, int node2, int teleport, int doorid) { + if (!node1 || !node2) + { + Log.Out(Logs::General, Logs::Quests, "QuestManager::ConnectNodeToNode called without node1 or node2. Probably syntax error in quest file."); + } + else + { + if (!teleport) + { + teleport = 0; + } + else if (teleport == 1 || teleport == -1) + { + teleport = -1; + } + + if (!doorid) + { + doorid = 0; + } + + if (!zone->pathing) + { + // if no pathing bits available, make them available. + zone->pathing = new PathManager(); + } + + if (zone->pathing) + { + zone->pathing->ConnectNodeToNode(node1, node2, teleport, doorid); + Log.Out(Logs::Moderate, Logs::Quests, "QuestManager::ConnectNodeToNode connecting node %i to node %i.", node1, node2); + } + } +} + +void QuestManager::AddNode(float x, float y, float z, float best_z, int32 requested_id) +{ + if (!x || !y || !z) + { + Log.Out(Logs::General, Logs::Quests, "QuestManager::AddNode called without x, y, z. Probably syntax error in quest file."); + } + + if (!best_z || best_z == 0) + { + if (zone->zonemap) + { + glm::vec3 loc(x, y, z); + best_z = zone->zonemap->FindBestZ(loc, nullptr); + } + else + { + best_z = z; + } + } + + if (!requested_id) + { + requested_id = 0; + } + + if (!zone->pathing) + { + // if no pathing bits available, make them available. + zone->pathing = new PathManager(); + } + + if (zone->pathing) + { + zone->pathing->AddNode(x, y, z, best_z, requested_id); + Log.Out(Logs::Moderate, Logs::Quests, "QuestManager::AddNode adding node at (%i, %i, %i).", x, y, z); + } +} + void QuestManager::settarget(const char *type, int target_id) { QuestManagerCurrentQuestVars(); if (!owner || !owner->IsNPC()) diff --git a/zone/questmgr.h b/zone/questmgr.h index d2f018b8c..b278e2c2a 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -87,6 +87,8 @@ public: void depopall(int npc_type = 0); void depopzone(bool StartSpawnTimer = true); void repopzone(); + void ConnectNodeToNode(int node1, int node2, int teleport, int doorid); + void AddNode(float x, float y, float z, float best_z, int32 requested_id); void settarget(const char *type, int target_id); void follow(int entity_id, int distance); void sfollow(); From 7bcfaf60ab89fee489bea279a513f45df531279e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 7 May 2015 18:34:19 -0400 Subject: [PATCH 070/846] Save PlayerState server side We now send the PlayerState in the spawn struct to allow clients to see other bard animations with instrument to be played if they zone in after the bard equipped the instrument OP_WeaponEquip2 and OP_WeaponUnequip2 renamed to OP_PlayerStateAdd and OP_PlayerStateRemove Still needs work: Get AI controlled mobs sending the correct PlayerStates. (stunned, attacking, etc) --- common/emu_oplist.h | 4 +-- common/eq_packet_structs.h | 8 ++++- 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 | 1 + common/patches/sof_structs.h | 3 +- common/patches/titanium.cpp | 2 +- common/patches/titanium_structs.h | 2 +- common/patches/uf.cpp | 2 +- common/patches/uf_structs.h | 2 +- utils/patches/patch_RoF.conf | 4 +-- utils/patches/patch_RoF2.conf | 4 +-- utils/patches/patch_SoD.conf | 4 +-- utils/patches/patch_SoF.conf | 4 +-- utils/patches/patch_Titanium.conf | 4 +-- utils/patches/patch_UF.conf | 4 +-- zone/client.cpp | 30 +++++++++--------- zone/client_packet.cpp | 52 +++++++++++++++++-------------- zone/client_packet.h | 4 +-- zone/lua_packet.cpp | 6 ++-- zone/mob.cpp | 26 +++++++++------- zone/mob.h | 5 +++ 26 files changed, 101 insertions(+), 82 deletions(-) diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 62978655a..c51e4b600 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -364,6 +364,8 @@ N(OP_PetitionUnCheckout), N(OP_PetitionUpdate), N(OP_PickPocket), N(OP_PlayerProfile), +N(OP_PlayerStateAdd), +N(OP_PlayerStateRemove), N(OP_PlayEverquestRequest), N(OP_PlayEverquestResponse), N(OP_PlayMP3), @@ -519,8 +521,6 @@ N(OP_VetRewardsAvaliable), N(OP_VoiceMacroIn), N(OP_VoiceMacroOut), N(OP_WeaponEquip1), -N(OP_WeaponEquip2), -N(OP_WeaponUnequip2), N(OP_WearChange), N(OP_Weather), N(OP_Weblink), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 980fcc419..ac6528860 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -273,7 +273,8 @@ struct Spawn_Struct { /*0146*/ uint8 beard; // Beard style (not totally, sure but maybe!) /*0147*/ uint8 unknown0147[4]; /*0151*/ uint8 level; // Spawn Level -/*0152*/ uint8 unknown0259[4]; // ***Placeholder +// None = 0, Open = 1, WeaponSheathed = 2, Aggressive = 4, ForcedAggressive = 8, InstrumentEquipped = 16, Stunned = 32, PrimaryWeaponEquipped = 64, SecondaryWeaponEquipped = 128 +/*0152*/ uint32 PlayerState; // Controls animation stuff /*0156*/ uint8 beardcolor; // Beard color /*0157*/ char suffix[32]; // Player's suffix (of Veeshan, etc.) /*0189*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner @@ -366,6 +367,11 @@ union }; +struct PlayerState_Struct { +/*00*/ uint32 spawn_id; +/*04*/ uint32 state; +}; + /* ** New Spawn ** Length: 176 Bytes diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index da9ed18f9..bfb47492a 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3990,7 +3990,7 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17 diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 2041a3c3a..da9fa311a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4140,7 +4140,7 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17 diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 92ff47fda..4aac9e7de 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -416,7 +416,7 @@ struct Spawn_Struct /*0000*/ uint8 unknown12; /*0000*/ uint32 petOwnerId; /*0000*/ uint8 unknown13; -/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed +/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed /*0000*/ uint32 unknown15; /*0000*/ uint32 unknown16; /*0000*/ uint32 unknown17; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 55c86a557..8fcfdb21d 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -410,7 +410,7 @@ struct Spawn_Struct /*0000*/ uint8 unknown12; /*0000*/ uint32 petOwnerId; /*0000*/ uint8 unknown13; -/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed +/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed /*0000*/ uint32 unknown15; /*0000*/ uint32 unknown16; /*0000*/ uint32 unknown17; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 8e5656b4b..a4765939d 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -2737,7 +2737,7 @@ namespace SoD VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown12 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17 diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 024814bfd..584318a71 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -286,7 +286,7 @@ struct Spawn_Struct /*0000*/ uint8 unknown12; /*0000*/ uint32 petOwnerId; /*0000*/ uint8 unknown13; -/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed +/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed /*0000*/ uint32 unknown15; /*0000*/ uint32 unknown16; /*0000*/ uint32 unknown17; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 1cd5ee7ed..186515b3b 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2088,6 +2088,7 @@ namespace SoF eq->runspeed = emu->runspeed; eq->light = emu->light; eq->level = emu->level; + eq->PlayerState = emu->PlayerState; eq->lfg = emu->lfg; eq->hairstyle = emu->hairstyle; eq->haircolor = emu->haircolor; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 4dd0e7d80..23404e051 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -241,7 +241,8 @@ struct Spawn_Struct { /*0506*/ uint8 light; // Spawn's lightsource /*0507*/ uint8 unknown0507[4]; /*0511*/ uint8 level; // Spawn Level -/*0512*/ uint8 unknown0512[16]; +/*0512*/ uint32 PlayerState; +/*0516*/ uint8 unknown0516[12]; /*0528*/ uint8 lfg; /*0529*/ uint8 unknown0529[4]; /*0533*/ uint8 hairstyle; // Sets the style of hair diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index beb338431..e23202c87 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1549,7 +1549,7 @@ namespace Titanium eq->beardcolor = emu->beardcolor; // eq->unknown0147[4] = emu->unknown0147[4]; eq->level = emu->level; - // eq->unknown0259[4] = emu->unknown0259[4]; + eq->PlayerState = emu->PlayerState; eq->beard = emu->beard; strcpy(eq->suffix, emu->suffix); eq->petOwnerId = emu->petOwnerId; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 53bcb38da..89a3634fd 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -212,7 +212,7 @@ struct Spawn_Struct { /*0146*/ uint8 beardcolor; // Beard color /*0147*/ uint8 unknown0147[4]; /*0151*/ uint8 level; // Spawn Level -/*0152*/ uint8 unknown0259[4]; // ***Placeholder +/*0152*/ uint32 PlayerState; // PlayerState controls some animation stuff /*0156*/ uint8 beard; // Beard style /*0157*/ char suffix[32]; // Player's suffix (of Veeshan, etc.) /*0189*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 4fbc7b6b8..58131bd35 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -3005,7 +3005,7 @@ namespace UF VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown12 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17 diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 49fb9a155..66cc58d1d 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -286,7 +286,7 @@ struct Spawn_Struct /*0000*/ uint8 unknown12; /*0000*/ uint32 petOwnerId; /*0000*/ uint8 unknown13; -/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed +/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed /*0000*/ uint32 unknown15; /*0000*/ uint32 unknown16; /*0000*/ uint32 unknown17; diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index d144b040e..02d7c9bb8 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -269,8 +269,8 @@ OP_RequestDuel=0x1ea9 OP_MobRename=0x5040 OP_AugmentItem=0x1627 # Was 0x37cb OP_WeaponEquip1=0x35c3 -OP_WeaponEquip2=0x012f # Was 0x6022 -OP_WeaponUnequip2=0x1076 # Was 0x0110 +OP_PlayerStateAdd=0x012f # Was 0x6022 +OP_PlayerStateRemove=0x1076 # Was 0x0110 OP_ApplyPoison=0x1499 OP_Save=0x2e6f OP_TestBuff=0x046e # Was 0x3772 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 0cc0c69d0..312f725fe 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -268,8 +268,8 @@ OP_RequestDuel=0x3af1 OP_MobRename=0x2c57 OP_AugmentItem=0x661b OP_WeaponEquip1=0x34a7 -OP_WeaponEquip2=0x559a -OP_WeaponUnequip2=0x2d25 +OP_PlayerStateAdd=0x559a +OP_PlayerStateRemove=0x2d25 OP_ApplyPoison=0x31e6 OP_Save=0x4a39 OP_TestBuff=0x7cb8 diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index a5dee668c..2f01ef89b 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -266,8 +266,8 @@ OP_RequestDuel=0x79e0 # C OP_MobRename=0x0a1d # C OP_AugmentItem=0x0370 # C OP_WeaponEquip1=0x719e # C -OP_WeaponEquip2=0x7b6e # C -OP_WeaponUnequip2=0x19a8 # C +OP_PlayerStateAdd=0x7b6e # C +OP_PlayerStateRemove=0x19a8 # C OP_ApplyPoison=0x405b # C OP_Save=0x5c85 # C OP_TestBuff=0x5fc7 # C diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 80aee8bdc..9c58b5684 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -262,8 +262,8 @@ OP_RequestDuel=0x3A2B #Xinu 02/22/09 OP_MobRename=0x6be5 #Trevius 01/16/09 OP_AugmentItem=0x172A #Trevius 03/14/09 OP_WeaponEquip1=0x7260 #Trevius 02/27/09 -OP_WeaponEquip2=0x5C2F #Trevius 02/27/09 -OP_WeaponUnequip2=0x6213 #Trevius 02/27/09 +OP_PlayerStateAdd=0x5C2F #Trevius 02/27/09 +OP_PlayerStateRemove=0x6213 #Trevius 02/27/09 OP_ApplyPoison=0x4543 #WildcardX 03/6/09 OP_Save=0x72F2 #Trevius 03/15/09 OP_TestBuff=0x07BF #/testbuff diff --git a/utils/patches/patch_Titanium.conf b/utils/patches/patch_Titanium.conf index 2660738de..99ef322a0 100644 --- a/utils/patches/patch_Titanium.conf +++ b/utils/patches/patch_Titanium.conf @@ -534,8 +534,8 @@ OP_PVPLeaderBoardDetailsRequest=0x06a2 OP_PVPLeaderBoardDetailsReply=0x246a OP_PickLockSuccess=0x40E7 OP_WeaponEquip1=0x6c5e -OP_WeaponEquip2=0x63da -OP_WeaponUnequip2=0x381d +OP_PlayerStateAdd=0x63da +OP_PlayerStateRemove=0x381d OP_VoiceMacroIn=0x2866 # Client to Server OP_VoiceMacroOut=0x2ec6 # Server to Client OP_CameraEffect=0x0937 # Correct diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index 09c6a8252..cbe57e399 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -272,8 +272,8 @@ OP_RequestDuel=0x6cfe # C OP_MobRename=0x0507 # C OP_AugmentItem=0x7c87 # C OP_WeaponEquip1=0x4572 # C -OP_WeaponEquip2=0x399b # C -OP_WeaponUnequip2=0x416b # C +OP_PlayerStateAdd=0x399b # C +OP_PlayerStateRemove=0x416b # C OP_ApplyPoison=0x5cd3 # C OP_Save=0x6618 # C OP_TestBuff=0x3415 # C diff --git a/zone/client.cpp b/zone/client.cpp index cd96ed29b..c31de64fa 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2540,12 +2540,12 @@ void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 bool Client::BindWound(Mob* bindmob, bool start, bool fail){ EQApplicationPacket* outapp = 0; - if(!fail) + if(!fail) { outapp = new EQApplicationPacket(OP_Bind_Wound, sizeof(BindWound_Struct)); BindWound_Struct* bind_out = (BindWound_Struct*) outapp->pBuffer; // Start bind - if(!bindwound_timer.Enabled()) + if(!bindwound_timer.Enabled()) { //make sure we actually have a bandage... and consume it. int16 bslot = m_inv.HasItemByUse(ItemTypeBandage, 1, invWhereWorn|invWherePersonal); @@ -2592,9 +2592,9 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ ; // Binding self } } - } + } else if (bindwound_timer.Check()) // Did the timer finish? - { + { // finish bind // disable complete timer bindwound_timer.Disable(); @@ -5709,8 +5709,8 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { else if (inst && inst->GetOrnamentationIcon()) { insr->itemicons[L] = inst->GetOrnamentationIcon(); - } - else + } + else { insr->itemicons[L] = item->Icon; } @@ -7612,7 +7612,7 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui // Find out starting faction for this faction // It needs to be used to adj max and min personal // The range is still the same, 1200-3000(4200), but adjusted for base - database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(), + database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(), faction_id[i]); // Adjust the amount you can go up or down so the resulting range @@ -7653,7 +7653,7 @@ void Client::SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class // Find out starting faction for this faction // It needs to be used to adj max and min personal // The range is still the same, 1200-3000(4200), but adjusted for base - database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(), + database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(), faction_id); // Adjust the amount you can go up or down so the resulting range @@ -7839,14 +7839,14 @@ void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_ char name[50]; int32 faction_value; - // If we're dropping from MAX or raising from MIN or repairing, + // If we're dropping from MAX or raising from MIN or repairing, // we should base the message on the new updated value so we don't show // a min MAX message // // If we're changing any other place, we use the value before the // hit. For example, if we go from 1199 to 1200 which is the MAX // we still want to say faction got better this time around. - + if ( (faction_before_hit >= this_faction_max) || (faction_before_hit <= this_faction_min)) faction_value = totalvalue; @@ -8382,10 +8382,10 @@ std::string Client::TextLink::GenerateLink() m_Link.clear(); m_LinkBody.clear(); m_LinkText.clear(); - + generate_body(); generate_text(); - + if ((m_LinkBody.length() == EmuConstants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { m_Link.push_back(0x12); m_Link.append(m_LinkBody); @@ -8424,7 +8424,7 @@ 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) @@ -8432,7 +8432,7 @@ void Client::TextLink::generate_body() */ memset(&m_LinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); - + const Item_Struct* item_data = nullptr; switch (m_LinkType) { @@ -8479,7 +8479,7 @@ void Client::TextLink::generate_body() default: break; } - + if (m_ProxyItemID != NOT_USED) { m_LinkBodyStruct.item_id = m_ProxyItemID; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 4424d1f47..690185744 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -305,6 +305,8 @@ void MapOpcodes() ConnectedOpcodes[OP_PetitionRefresh] = &Client::Handle_OP_PetitionRefresh; ConnectedOpcodes[OP_PetitionResolve] = &Client::Handle_OP_PetitionResolve; ConnectedOpcodes[OP_PetitionUnCheckout] = &Client::Handle_OP_PetitionUnCheckout; + ConnectedOpcodes[OP_PlayerStateAdd] = &Client::Handle_OP_PlayerStateAdd; + ConnectedOpcodes[OP_PlayerStateRemove] = &Client::Handle_OP_PlayerStateRemove; ConnectedOpcodes[OP_PickPocket] = &Client::Handle_OP_PickPocket; ConnectedOpcodes[OP_PopupResponse] = &Client::Handle_OP_PopupResponse; ConnectedOpcodes[OP_PotionBelt] = &Client::Handle_OP_PotionBelt; @@ -381,8 +383,6 @@ void MapOpcodes() ConnectedOpcodes[OP_VetClaimRequest] = &Client::Handle_OP_VetClaimRequest; ConnectedOpcodes[OP_VoiceMacroIn] = &Client::Handle_OP_VoiceMacroIn; ConnectedOpcodes[OP_WearChange] = &Client::Handle_OP_WearChange; - ConnectedOpcodes[OP_WeaponEquip2] = &Client::Handle_OP_WeaponEquip2; - ConnectedOpcodes[OP_WeaponUnequip2] = &Client::Handle_OP_WeaponUnequip2; ConnectedOpcodes[OP_WhoAllRequest] = &Client::Handle_OP_WhoAllRequest; ConnectedOpcodes[OP_WorldUnknown001] = &Client::Handle_OP_Ignore; ConnectedOpcodes[OP_XTargetAutoAddHaters] = &Client::Handle_OP_XTargetAutoAddHaters; @@ -10325,6 +10325,32 @@ void Client::Handle_OP_PetitionUnCheckout(const EQApplicationPacket *app) return; } +void Client::Handle_OP_PlayerStateAdd(const EQApplicationPacket *app) +{ + if (app->size != sizeof(PlayerState_Struct)) { + std::cout << "Wrong size: OP_PlayerStateAdd, size=" << app->size << ", expected " << sizeof(PlayerState_Struct) << std::endl; + return; + } + + PlayerState_Struct *ps = (PlayerState_Struct *)app->pBuffer; + AddPlayerState(ps->state); + + entity_list.QueueClients(this, app, false); +} + +void Client::Handle_OP_PlayerStateRemove(const EQApplicationPacket *app) +{ + if (app->size != sizeof(PlayerState_Struct)) { + std::cout << "Wrong size: OP_PlayerStateRemove, size=" << app->size << ", expected " << sizeof(PlayerState_Struct) << std::endl; + return; + } + PlayerState_Struct *ps = (PlayerState_Struct *)app->pBuffer; + RemovePlayerState(ps->state); + + // We should probably save it server side, but for now this works + entity_list.QueueClients(this, app, false); +} + void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) { if (app->size != sizeof(PickPocket_Struct)) @@ -13891,28 +13917,6 @@ void Client::Handle_OP_WearChange(const EQApplicationPacket *app) return; } -void Client::Handle_OP_WeaponEquip2(const EQApplicationPacket *app) -{ - if (app->size != 8) { - std::cout << "Wrong size: OP_WeaponEquip2, size=" << app->size << ", expected " << 8 << std::endl; - return; - } - - // We should probably save it server side, but for now this works - entity_list.QueueClients(this, app, false); -} - -void Client::Handle_OP_WeaponUnequip2(const EQApplicationPacket *app) -{ - if (app->size != 8) { - std::cout << "Wrong size: OP_WeaponUnequip2, size=" << app->size << ", expected " << 8 << std::endl; - return; - } - - // We should probably save it server side, but for now this works - entity_list.QueueClients(this, app, false); -} - void Client::Handle_OP_WhoAllRequest(const EQApplicationPacket *app) { if (app->size != sizeof(Who_All_Struct)) { diff --git a/zone/client_packet.h b/zone/client_packet.h index 0f09cf574..1a9591f4c 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -218,6 +218,8 @@ void Handle_OP_PetitionRefresh(const EQApplicationPacket *app); void Handle_OP_PetitionResolve(const EQApplicationPacket *app); void Handle_OP_PetitionUnCheckout(const EQApplicationPacket *app); + void Handle_OP_PlayerStateAdd(const EQApplicationPacket *app); + void Handle_OP_PlayerStateRemove(const EQApplicationPacket *app); void Handle_OP_PickPocket(const EQApplicationPacket *app); void Handle_OP_PopupResponse(const EQApplicationPacket *app); void Handle_OP_PotionBelt(const EQApplicationPacket *app); @@ -288,8 +290,6 @@ void Handle_OP_VetClaimRequest(const EQApplicationPacket *app); void Handle_OP_VoiceMacroIn(const EQApplicationPacket *app); void Handle_OP_WearChange(const EQApplicationPacket *app); - void Handle_OP_WeaponEquip2(const EQApplicationPacket *app); - void Handle_OP_WeaponUnequip2(const EQApplicationPacket *app); void Handle_OP_WhoAllRequest(const EQApplicationPacket *app); void Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app); void Handle_OP_XTargetRequest(const EQApplicationPacket *app); diff --git a/zone/lua_packet.cpp b/zone/lua_packet.cpp index e16a85c6d..1eef7220d 100644 --- a/zone/lua_packet.cpp +++ b/zone/lua_packet.cpp @@ -18,7 +18,7 @@ Lua_Packet::Lua_Packet(int opcode, int size, bool raw) { if(raw) { SetLuaPtrData(new EQApplicationPacket(OP_Unknown, size)); owned_ = true; - + EQApplicationPacket *self = reinterpret_cast(d_); self->SetOpcodeBypass(opcode); } else { @@ -692,8 +692,8 @@ luabind::scope lua_register_packet_opcodes() { luabind::value("VetClaimRequest", static_cast(OP_VetClaimRequest)), luabind::value("VetClaimReply", static_cast(OP_VetClaimReply)), luabind::value("WeaponEquip1", static_cast(OP_WeaponEquip1)), - luabind::value("WeaponEquip2", static_cast(OP_WeaponEquip2)), - luabind::value("WeaponUnequip2", static_cast(OP_WeaponUnequip2)), + luabind::value("PlayerStateAdd", static_cast(OP_PlayerStateAdd)), + luabind::value("PlayerStateRemove", static_cast(OP_PlayerStateRemove)), luabind::value("WorldLogout", static_cast(OP_WorldLogout)), luabind::value("SessionReady", static_cast(OP_SessionReady)), luabind::value("Login", static_cast(OP_Login)), diff --git a/zone/mob.cpp b/zone/mob.cpp index 0659110cd..1c4c2a01e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -148,6 +148,7 @@ Mob::Mob(const char* in_name, size = in_size; base_size = size; runspeed = in_runspeed; + PlayerState = 0; // sanity check @@ -160,7 +161,7 @@ Mob::Mob(const char* in_name, 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; - + texture = in_texture; helmtexture = in_helmtexture; armtexture = in_armtexture; @@ -739,7 +740,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(strlen(ns->spawn.lastName) == 0) { switch(ns->spawn.class_) { @@ -915,6 +916,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.class_ = class_; ns->spawn.gender = gender; ns->spawn.level = level; + ns->spawn.PlayerState = PlayerState; ns->spawn.deity = deity; ns->spawn.animation = 0; ns->spawn.findable = findable?1:0; @@ -2566,10 +2568,10 @@ void Mob::SendArmorAppearance(Client *one_client) if (!IsClient()) { const Item_Struct *item; - for (int i=0; i< 7 ; ++i) + for (int i=0; i< 7 ; ++i) { item=database.GetItem(GetEquipment(i)); - if (item != 0) + if (item != 0) { SendWearChange(i,one_client); } @@ -2597,7 +2599,7 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client) else { one_client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); - } + } safe_delete(outapp); } @@ -2724,7 +2726,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const const Item_Struct *item; item = database.GetItem(GetEquipment(material_slot)); int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); - + if (item != 0 && invslot != INVALID_INDEX) { if (IsClient()) @@ -2982,10 +2984,10 @@ uint32 Mob::GetLevelHP(uint8 tlevel) } int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime) { - + int32 cast_reducer = 0; cast_reducer += GetFocusEffect(focusSpellHaste, spell_id); - + if (level >= 60 && casttime > 1000) { casttime = casttime / 2; @@ -3599,7 +3601,7 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used) // 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]; - + skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1]; @@ -5317,7 +5319,7 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) if (slot < 4){ if (id == "components") { return spells[spell_id].components[slot];} - else if (id == "component_counts") { return spells[spell_id].component_counts[slot];} + else if (id == "component_counts") { return spells[spell_id].component_counts[slot];} else if (id == "NoexpendReagent") {return spells[spell_id].NoexpendReagent[slot];} } @@ -5395,7 +5397,7 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) else if (id == "max_dist") {return static_cast(spells[spell_id].max_dist); } else if (id == "min_range") {return static_cast(spells[spell_id].min_range); } else if (id == "DamageShieldType") {return spells[spell_id].DamageShieldType; } - + return stat; } @@ -5415,7 +5417,7 @@ bool Mob::CanClassEquipItem(uint32 item_id) int bitmask = 1; bitmask = bitmask << (GetClass() - 1); - + if(!(itm->Classes & bitmask)) return false; else diff --git a/zone/mob.h b/zone/mob.h index 1d41f4098..fc5e1d8e0 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1026,6 +1026,11 @@ protected: uint32 follow_dist; bool no_target_hotkey; + uint32 PlayerState; + uint32 GetPlayerState() { return PlayerState; } + void AddPlayerState(uint32 new_state) { PlayerState |= new_state; } + void RemovePlayerState(uint32 old_state) { PlayerState &= ~old_state; } + uint8 gender; uint16 race; uint8 base_gender; From 103d808925369785ef4567de6e5157e63e775c67 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 7 May 2015 22:15:43 -0400 Subject: [PATCH 071/846] Whoops, we do want to ignore the sender --- 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 690185744..317530110 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10335,7 +10335,7 @@ void Client::Handle_OP_PlayerStateAdd(const EQApplicationPacket *app) PlayerState_Struct *ps = (PlayerState_Struct *)app->pBuffer; AddPlayerState(ps->state); - entity_list.QueueClients(this, app, false); + entity_list.QueueClients(this, app, true); } void Client::Handle_OP_PlayerStateRemove(const EQApplicationPacket *app) @@ -10348,7 +10348,7 @@ void Client::Handle_OP_PlayerStateRemove(const EQApplicationPacket *app) RemovePlayerState(ps->state); // We should probably save it server side, but for now this works - entity_list.QueueClients(this, app, false); + entity_list.QueueClients(this, app, true); } void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) From bf4ff036413c3e3ff49e09109c0aace4ad187c02 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 8 May 2015 00:59:38 -0400 Subject: [PATCH 072/846] Use PlayerState to generate stun particles --- zone/bot.cpp | 11 ++++------- zone/client_packet.cpp | 1 - zone/client_process.cpp | 12 +++++------- zone/common.h | 14 +++++++++++++- zone/merc.cpp | 5 +---- zone/mob.cpp | 31 +++++++++++++++++++++++++++++-- zone/mob.h | 10 ++++++---- zone/npc.cpp | 15 +++++++-------- zone/spells.cpp | 5 +++-- 9 files changed, 68 insertions(+), 36 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index ea48727ec..ba7624158 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2858,10 +2858,7 @@ void Bot::SaveTimers() { bool Bot::Process() { if(IsStunned() && stunned_timer.Check()) - { - this->stunned = false; - this->stunned_timer.Disable(); - } + Mob::UnStun(); if(!GetBotOwner()) return false; @@ -11719,11 +11716,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { const char* equipped[EmuConstants::EQUIPMENT_SIZE] = {"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" }; - + const ItemInst* inst = nullptr; const Item_Struct* item = nullptr; bool is2Hweapon = false; - + std::string item_link; Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); @@ -11753,7 +11750,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { // I could not find a difference between the criteria positive code and the criteria negative code.. // ..so, I deleted the check (old criteria: i = { MainCharm, MainRange, MainPrimary, MainSecondary, MainAmmo }) - + linker.SetItemInst(inst); item_link = linker.GenerateLink(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 317530110..73d028e68 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10347,7 +10347,6 @@ void Client::Handle_OP_PlayerStateRemove(const EQApplicationPacket *app) PlayerState_Struct *ps = (PlayerState_Struct *)app->pBuffer; RemovePlayerState(ps->state); - // We should probably save it server side, but for now this works entity_list.QueueClients(this, app, true); } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 40e8e6d1b..42681340b 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -197,10 +197,8 @@ bool Client::Process() { instalog = true; } - if (IsStunned() && stunned_timer.Check()) { - this->stunned = false; - this->stunned_timer.Disable(); - } + if (IsStunned() && stunned_timer.Check()) + Mob::UnStun(); if(!m_CheatDetectMoved) { @@ -262,7 +260,7 @@ bool Client::Process() { } if(light_update_timer.Check()) { - + UpdateEquipmentLight(); if(UpdateActiveLight()) { SendAppearancePacket(AT_Light, GetActiveLightType()); @@ -562,7 +560,7 @@ bool Client::Process() { } ProjectileAttack(); - + if(spellbonuses.GravityEffect == 1) { if(gravity_timer.Check()) DoGravityEffect(); @@ -793,7 +791,7 @@ void Client::OnDisconnect(bool hard_disconnect) { Mob *Other = trade->With(); if(Other) { - Log.Out(Logs::Detail, Logs::Trading, "Client disconnected during a trade. Returning their items."); + Log.Out(Logs::Detail, Logs::Trading, "Client disconnected during a trade. Returning their items."); FinishTrade(this); if(Other->IsClient()) diff --git a/zone/common.h b/zone/common.h index 56ab6f819..a7d9e2d99 100644 --- a/zone/common.h +++ b/zone/common.h @@ -173,6 +173,18 @@ enum class NumHit { // Numhits type OffensiveSpellProcs = 11 // Offensive buff procs }; +enum class PlayerState : uint32 { + None = 0, + Open = 1, + WeaponSheathed = 2, + Aggressive = 4, + ForcedAggressive = 8, + InstrumentEquipped = 16, + Stunned = 32, + PrimaryWeaponEquipped = 64, + SecondaryWeaponEquipped = 128 +}; + //this is our internal representation of the BUFF struct, can put whatever we want in it struct Buffs_Struct { uint16 spellid; @@ -438,7 +450,7 @@ struct StatBonuses { int32 ShieldEquipHateMod; // Hate mod when shield equiped. int32 ShieldEquipDmgMod[2]; // Damage mod when shield equiped. 0 = damage modifier 1 = Unknown bool TriggerOnValueAmount; // Triggers off various different conditions, bool to check if client has effect. - int8 StunBashChance; // chance to stun with bash. + int8 StunBashChance; // chance to stun with bash. int8 IncreaseChanceMemwipe; // increases chance to memory wipe int8 CriticalMend; // chance critical monk mend int32 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy diff --git a/zone/merc.cpp b/zone/merc.cpp index 4609487cf..73f6b1fbf 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1236,10 +1236,7 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { bool Merc::Process() { if(IsStunned() && stunned_timer.Check()) - { - this->stunned = false; - this->stunned_timer.Disable(); - } + Mob::UnStun(); if (GetDepop()) { diff --git a/zone/mob.cpp b/zone/mob.cpp index 1c4c2a01e..b4c3370cb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -148,7 +148,7 @@ Mob::Mob(const char* in_name, size = in_size; base_size = size; runspeed = in_runspeed; - PlayerState = 0; + m_PlayerState = 0; // sanity check @@ -916,7 +916,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.class_ = class_; ns->spawn.gender = gender; ns->spawn.level = level; - ns->spawn.PlayerState = PlayerState; + ns->spawn.PlayerState = m_PlayerState; ns->spawn.deity = deity; ns->spawn.animation = 0; ns->spawn.findable = findable?1:0; @@ -5423,3 +5423,30 @@ bool Mob::CanClassEquipItem(uint32 item_id) else return true; } + +void Mob::SendAddPlayerState(PlayerState new_state) +{ + auto app = new EQApplicationPacket(OP_PlayerStateAdd, sizeof(PlayerState_Struct)); + auto ps = (PlayerState_Struct *)app->pBuffer; + + ps->spawn_id = GetID(); + ps->state = static_cast(new_state); + + AddPlayerState(ps->state); + entity_list.QueueClients(nullptr, app); + safe_delete(app); +} + +void Mob::SendRemovePlayerState(PlayerState old_state) +{ + auto app = new EQApplicationPacket(OP_PlayerStateRemove, sizeof(PlayerState_Struct)); + auto ps = (PlayerState_Struct *)app->pBuffer; + + ps->spawn_id = GetID(); + ps->state = static_cast(old_state); + + RemovePlayerState(ps->state); + entity_list.QueueClients(nullptr, app); + safe_delete(app); +} + diff --git a/zone/mob.h b/zone/mob.h index fc5e1d8e0..3b0702e60 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1026,10 +1026,12 @@ protected: uint32 follow_dist; bool no_target_hotkey; - uint32 PlayerState; - uint32 GetPlayerState() { return PlayerState; } - void AddPlayerState(uint32 new_state) { PlayerState |= new_state; } - void RemovePlayerState(uint32 old_state) { PlayerState &= ~old_state; } + uint32 m_PlayerState; + uint32 GetPlayerState() { return m_PlayerState; } + void AddPlayerState(uint32 new_state) { m_PlayerState |= new_state; } + void RemovePlayerState(uint32 old_state) { m_PlayerState &= ~old_state; } + void SendAddPlayerState(PlayerState new_state); + void SendRemovePlayerState(PlayerState old_state); uint8 gender; uint16 race; diff --git a/zone/npc.cpp b/zone/npc.cpp index 4e69657cd..0ece7ab6c 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -522,7 +522,7 @@ void NPC::QueryLoot(Client* to) linker.SetItemData(item); 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); } @@ -569,8 +569,7 @@ bool NPC::Process() { if (IsStunned() && stunned_timer.Check()) { - this->stunned = false; - this->stunned_timer.Disable(); + Mob::UnStun(); this->spun_timer.Disable(); } @@ -724,7 +723,7 @@ 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; } @@ -1933,7 +1932,7 @@ 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") { attack_delay = atoi(val.c_str()); 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; } @@ -2418,7 +2417,7 @@ void NPC::DoQuestPause(Mob *other) { } -void NPC::ChangeLastName(const char* in_lastname) +void NPC::ChangeLastName(const char* in_lastname) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); @@ -2468,9 +2467,9 @@ void NPC::DepopSwarmPets() } if (IsPet() && GetPetType() == petTargetLock && GetPetTargetLockID()){ - + Mob *targMob = entity_list.GetMob(GetPetTargetLockID()); - + if(!targMob || (targMob && targMob->IsCorpse())){ Kill(); return; diff --git a/zone/spells.cpp b/zone/spells.cpp index 472a0ac9f..d93050746 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4708,7 +4708,7 @@ void Mob::Stun(int duration) { stunned = true; stunned_timer.Start(duration); - SendStunAppearance(); + SendAddPlayerState(PlayerState::Stunned); } } @@ -4716,6 +4716,7 @@ void Mob::UnStun() { if(stunned && stunned_timer.Enabled()) { stunned = false; stunned_timer.Disable(); + SendRemovePlayerState(PlayerState::Stunned); } } @@ -5259,7 +5260,7 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) 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. + // If its set to 0 the effect is cancelled. // 128 seems to work (ie: change only duration). sbf->effect = 128; } From f68952c168d6610f5de8d5984ef38860d191d47b Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 8 May 2015 22:23:50 -0400 Subject: [PATCH 073/846] Update to some spell duration formulas (Shendare). Filename fixes. --- ...l => 2015_02_05_UseAdditiveFocusFromWornSlot.sql} | 0 ...Type.sql => 2015_02_06_AdditiveBonusWornType.sql} | 0 ...5_4_30_MeleePush.sql => 2015_04_30_MeleePush.sql} | 0 zone/spells.cpp | 12 +++++++----- 4 files changed, 7 insertions(+), 5 deletions(-) rename utils/sql/git/optional/{2015_2_5_UseAdditiveFocusFromWornSlot.sql => 2015_02_05_UseAdditiveFocusFromWornSlot.sql} (100%) rename utils/sql/git/optional/{2015_2_6_AdditiveBonusWornType.sql => 2015_02_06_AdditiveBonusWornType.sql} (100%) rename utils/sql/git/optional/{2015_4_30_MeleePush.sql => 2015_04_30_MeleePush.sql} (100%) diff --git a/utils/sql/git/optional/2015_2_5_UseAdditiveFocusFromWornSlot.sql b/utils/sql/git/optional/2015_02_05_UseAdditiveFocusFromWornSlot.sql similarity index 100% rename from utils/sql/git/optional/2015_2_5_UseAdditiveFocusFromWornSlot.sql rename to utils/sql/git/optional/2015_02_05_UseAdditiveFocusFromWornSlot.sql diff --git a/utils/sql/git/optional/2015_2_6_AdditiveBonusWornType.sql b/utils/sql/git/optional/2015_02_06_AdditiveBonusWornType.sql similarity index 100% rename from utils/sql/git/optional/2015_2_6_AdditiveBonusWornType.sql rename to utils/sql/git/optional/2015_02_06_AdditiveBonusWornType.sql diff --git a/utils/sql/git/optional/2015_4_30_MeleePush.sql b/utils/sql/git/optional/2015_04_30_MeleePush.sql similarity index 100% rename from utils/sql/git/optional/2015_4_30_MeleePush.sql rename to utils/sql/git/optional/2015_04_30_MeleePush.sql diff --git a/zone/spells.cpp b/zone/spells.cpp index d93050746..77a9f691d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2642,7 +2642,7 @@ int CalcBuffDuration_formula(int level, int formula, int duration) return i < duration ? (i < 1 ? 1 : i) : duration; case 2: - i = (int)ceil(duration / 5.0f * 3); + i = (int)ceil(level / 5.0f * 3); return i < duration ? (i < 1 ? 1 : i) : duration; case 3: @@ -2681,13 +2681,15 @@ int CalcBuffDuration_formula(int level, int formula, int duration) return std::min((level + 3) * 30, duration); case 12: - return duration; - + case 13: + case 14: case 15: // Don't know what the real formula for this should be. Used by Skinspikes potion. return duration; - case 50: // lucy says this is unlimited? - return 72000; // 5 days + case 50: // Permanent. Cancelled by casting/combat for perm invis, non-lev zones for lev, curing poison/curse counters, etc. + return 72000; // 5 days until better method to make permanent + + //case 51: // Permanent. Cancelled when out of range of aura. Placeholder until appropriate duration identified. case 3600: return duration ? duration : 3600; From c360aa9b0f99e34da33386ce474f3cd2f5fa483d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 8 May 2015 22:42:45 -0400 Subject: [PATCH 074/846] Make use of Aggressive/Weapon PlayerStates I HAVE NO IDEA WHAT THIS DOES, BUT LIVE DOES IT Something to do with the animation system, all I know --- zone/bot.cpp | 6 ++++++ zone/loottables.cpp | 8 ++++++-- zone/merc.cpp | 6 ++++++ zone/mob_ai.cpp | 4 ++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index ba7624158..48a4dfe55 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3459,6 +3459,9 @@ void Bot::AI_Process() { return; } + if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) + SendAddPlayerState(PlayerState::Aggressive); + bool atCombatRange = false; float meleeDistance = GetMaxMeleeRangeToTarget(GetTarget()); @@ -3717,6 +3720,9 @@ void Bot::AI_Process() { // Not engaged in combat SetTarget(0); + if (m_PlayerState & static_cast(PlayerState::Aggressive)) + SendRemovePlayerState(PlayerState::Aggressive); + if(!IsMoving() && AIthink_timer->Check() && !spellend_timer.Enabled()) { if(GetBotStance() != BotStancePassive) { if(!AI_IdleCastCheck() && !IsCasting()) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 3170729d0..e3014b12e 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -58,7 +58,7 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite if(max_cash > 0 && lts->avgcoin > 0 && EQEmu::ValueWithin(lts->avgcoin, min_cash, max_cash)) { float upper_chance = (float)(lts->avgcoin - min_cash) / (float)(max_cash - min_cash); float avg_cash_roll = (float)zone->random.Real(0.0, 1.0); - + if(avg_cash_roll < upper_chance) { cash = zone->random.Int(lts->avgcoin, max_cash); } else { @@ -120,7 +120,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml 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); - npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel, + 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); } } @@ -332,6 +332,8 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = MaterialPrimary; + if (item2->Damage > 0) + SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); } else if (foundslot == MainSecondary && (GetOwner() != nullptr || (GetLevel() >= 13 && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && @@ -342,6 +344,8 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = MaterialSecondary; + if (item2->Damage > 0) + SendAddPlayerState(PlayerState::SecondaryWeaponEquipped); } else if (foundslot == MainHead) { eslot = MaterialHead; diff --git a/zone/merc.cpp b/zone/merc.cpp index 73f6b1fbf..5f06331fa 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1468,6 +1468,9 @@ void Merc::AI_Process() { return; } + if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) + SendAddPlayerState(PlayerState::Aggressive); + bool atCombatRange = false; float meleeDistance = GetMaxMeleeRangeToTarget(GetTarget()); @@ -1681,6 +1684,9 @@ void Merc::AI_Process() { confidence_timer.Disable(); _check_confidence = false; + if (m_PlayerState & static_cast(PlayerState::Aggressive)) + SendRemovePlayerState(PlayerState::Aggressive); + if(!check_target_timer.Enabled()) check_target_timer.Start(2000, false); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 452ca71fd..020c833e8 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1084,6 +1084,8 @@ void Mob::AI_Process() { if (engaged) { + if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) + SendAddPlayerState(PlayerState::Aggressive); // we are prevented from getting here if we are blind and don't have a target in range // from above, so no extra blind checks needed if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind()) @@ -1435,6 +1437,8 @@ void Mob::AI_Process() { } else { + if (m_PlayerState & static_cast(PlayerState::Aggressive)) + SendRemovePlayerState(PlayerState::Aggressive); if(AIfeignremember_timer->Check()) { // 6/14/06 // Improved Feign Death Memory From d1fbd086d73299d088b8ef577fbc8a6b8c625f08 Mon Sep 17 00:00:00 2001 From: regneq Date: Mon, 11 May 2015 11:35:54 -0700 Subject: [PATCH 075/846] Fully implemented QuestReward. (credit to Cavedude on EQMacEmu) Syntax on NPC is: e.other:QuestReward(e.self,copper,silver,gold,platinum,item,experience,factionid,factionvalue); This will give you any or all of the rewards and their messages with one call, including the quest ding sound. Any item is sent to your inventory, like SummonItem does now. The coin message is generated by the client, and will give you a message for each coin type (You recieve 5 copper...). No way around that, but it's still useful if the reward only calls for a single type. --- common/eq_packet_structs.h | 36 +++++++++++++------------- zone/client.cpp | 33 ++++++++++++++++++++++++ zone/client.h | 1 + zone/lua_client.cpp | 50 ++++++++++++++++++++++++++++++++++- zone/lua_client.h | 8 ++++++ zone/lua_mob.cpp | 24 ----------------- zone/lua_mob.h | 4 --- zone/mob.cpp | 16 ------------ zone/mob.h | 1 - zone/perl_client.cpp | 53 +++++++++++++++++++++++++++++++++++++- zone/perl_mob.cpp | 42 ------------------------------ 11 files changed, 161 insertions(+), 107 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index ac6528860..f91107a14 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2154,24 +2154,24 @@ struct Illusion_Struct_Old { // OP_Sound - Size: 68 struct QuestReward_Struct { -/*000*/ uint32 from_mob; // ID of mob awarding the client -/*004*/ uint32 unknown004; -/*008*/ uint32 unknown008; -/*012*/ uint32 unknown012; -/*016*/ uint32 unknown016; -/*020*/ uint32 unknown020; -/*024*/ uint32 silver; // Gives silver to the client -/*028*/ uint32 gold; // Gives gold to the client -/*032*/ uint32 platinum; // Gives platinum to the client -/*036*/ uint32 unknown036; -/*040*/ uint32 unknown040; -/*044*/ uint32 unknown044; -/*048*/ uint32 unknown048; -/*052*/ uint32 unknown052; -/*056*/ uint32 unknown056; -/*060*/ uint32 unknown060; -/*064*/ uint32 unknown064; -/*068*/ + /*000*/ uint32 mob_id; // ID of mob awarding the client + /*004*/ uint32 target_id; + /*008*/ uint32 exp_reward; + /*012*/ uint32 faction; + /*016*/ int32 faction_mod; + /*020*/ uint32 copper; // Gives copper to the client + /*024*/ uint32 silver; // Gives silver to the client + /*028*/ uint32 gold; // Gives gold to the client + /*032*/ uint32 platinum; // Gives platinum to the client + /*036*/ uint32 item_id; + /*040*/ uint32 unknown040; + /*044*/ uint32 unknown044; + /*048*/ uint32 unknown048; + /*052*/ uint32 unknown052; + /*056*/ uint32 unknown056; + /*060*/ uint32 unknown060; + /*064*/ uint32 unknown064; + /*068*/ }; // Size: 8 diff --git a/zone/client.cpp b/zone/client.cpp index c31de64fa..f86b641c1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8584,3 +8584,36 @@ bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLin if (textLinkBody.length() != EmuConstants::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, uint32 factionid, int32 faction) { + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct)); + memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); + QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer; + + qr->mob_id = target->GetID(); // Entity ID for the from mob name + qr->target_id = GetID(); // The Client ID (this) + qr->copper = copper; + qr->silver = silver; + qr->gold = gold; + qr->platinum = platinum; + qr->item_id = itemid; + qr->exp_reward = exp; + qr->faction = factionid; + qr->faction_mod = faction; + + if (copper > 0 || silver > 0 || gold > 0 || platinum > 0) + AddMoneyToPP(copper, silver, gold, platinum, false); + + if (itemid > 0) + SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, MainPowerSource); + + if (exp > 0) + AddEXP(exp); + + if (factionid > 0) + SetFactionLevel2(CharacterID(), factionid, GetClass(), GetBaseRace(), GetDeity(), faction, 0); + + QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + safe_delete(outapp); +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index 533db7b04..b5a016fdc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1254,6 +1254,7 @@ public: virtual int32 Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false); + void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, uint32 factionid = 0, int32 faction = 0); protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index ac0ddcf99..0242041a6 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1255,6 +1255,46 @@ void Lua_Client::PlayMP3(std::string file) self->PlayMP3(file.c_str()); } +void Lua_Client::QuestReward(Lua_Mob target) { + Lua_Safe_Call_Void(); + self->QuestReward(target); +} + +void Lua_Client::QuestReward(Lua_Mob target, uint32 copper) { + Lua_Safe_Call_Void(); + self->QuestReward(target, copper); +} + +void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver) { + Lua_Safe_Call_Void(); + self->QuestReward(target, copper, silver); +} + +void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold) { + Lua_Safe_Call_Void(); + self->QuestReward(target, copper, silver, gold); +} + +void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum) { + Lua_Safe_Call_Void(); + self->QuestReward(target, copper, silver, gold, platinum); +} + +void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid) { + Lua_Safe_Call_Void(); + self->QuestReward(target, copper, silver, gold, platinum, itemid); +} + +void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp) { + Lua_Safe_Call_Void(); + self->QuestReward(target, copper, silver, gold, platinum, itemid, exp); +} + +void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, uint32 factionid, int32 faction) { + Lua_Safe_Call_Void(); + self->QuestReward(target, copper, silver, gold, platinum, itemid, exp, factionid, faction); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -1504,7 +1544,15 @@ luabind::scope lua_register_client() { .def("SetConsumption", (void(Lua_Client::*)(int, int))&Lua_Client::SetConsumption) .def("SendMarqueeMessage", (void(Lua_Client::*)(uint32, uint32, uint32, uint32, uint32, std::string))&Lua_Client::SendMarqueeMessage) .def("SendColoredText", (void(Lua_Client::*)(uint32, std::string))&Lua_Client::SendColoredText) - .def("PlayMP3", (void(Lua_Client::*)(std::string))&Lua_Client::PlayMP3); + .def("PlayMP3", (void(Lua_Client::*)(std::string))&Lua_Client::PlayMP3) + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob))&Lua_Client::QuestReward) + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32))&Lua_Client::QuestReward) + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32))&Lua_Client::QuestReward) + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32))&Lua_Client::QuestReward) + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32, uint32, int32))&Lua_Client::QuestReward); } luabind::scope lua_register_inventory_where() { diff --git a/zone/lua_client.h b/zone/lua_client.h index e2b0a6614..d28da9cdb 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -278,6 +278,14 @@ public: void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg); void SendColoredText(uint32 type, std::string msg); void PlayMP3(std::string file); + void QuestReward(Lua_Mob target); + void QuestReward(Lua_Mob target, uint32 copper); + void QuestReward(Lua_Mob target, uint32 copper, uint32 silver); + void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold); + void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum); + void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid); + void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp); + void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, uint32 factionid, int32 faction); }; #endif diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 04d11566a..036af2072 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1590,26 +1590,6 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) { beard, aa_title, drakkin_heritage, drakkin_tattoo, drakkin_details, size); } -void Lua_Mob::QuestReward(Lua_Client c) { - Lua_Safe_Call_Void(); - self->QuestReward(c); -} - -void Lua_Mob::QuestReward(Lua_Client c, uint32 silver) { - Lua_Safe_Call_Void(); - self->QuestReward(c, silver); -} - -void Lua_Mob::QuestReward(Lua_Client c, uint32 silver, uint32 gold) { - Lua_Safe_Call_Void(); - self->QuestReward(c, silver, gold); -} - -void Lua_Mob::QuestReward(Lua_Client c, uint32 silver, uint32 gold, uint32 platinum) { - Lua_Safe_Call_Void(); - self->QuestReward(c, silver, gold, platinum); -} - void Lua_Mob::CameraEffect(uint32 duration, uint32 intensity) { Lua_Safe_Call_Void(); self->CameraEffect(duration, intensity); @@ -2132,10 +2112,6 @@ luabind::scope lua_register_mob() { .def("SetRace", (void(Lua_Mob::*)(int))&Lua_Mob::SetRace) .def("SetGender", (void(Lua_Mob::*)(int))&Lua_Mob::SetGender) .def("SendIllusionPacket", (void(Lua_Mob::*)(luabind::adl::object))&Lua_Mob::SendIllusionPacket) - .def("QuestReward", (void(Lua_Mob::*)(Lua_Client))&Lua_Mob::QuestReward) - .def("QuestReward", (void(Lua_Mob::*)(Lua_Client,uint32))&Lua_Mob::QuestReward) - .def("QuestReward", (void(Lua_Mob::*)(Lua_Client,uint32,uint32))&Lua_Mob::QuestReward) - .def("QuestReward", (void(Lua_Mob::*)(Lua_Client,uint32,uint32,uint32))&Lua_Mob::QuestReward) .def("CameraEffect", (void(Lua_Mob::*)(uint32,uint32))&Lua_Mob::CameraEffect) .def("CameraEffect", (void(Lua_Mob::*)(uint32,uint32,Lua_Client))&Lua_Mob::CameraEffect) .def("CameraEffect", (void(Lua_Mob::*)(uint32,uint32,Lua_Client,bool))&Lua_Mob::CameraEffect) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index f272cd440..3caf62839 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -296,10 +296,6 @@ public: void SetRace(int in); void SetGender(int in); void SendIllusionPacket(luabind::adl::object illusion); - void QuestReward(Lua_Client c); - void QuestReward(Lua_Client c, uint32 silver); - void QuestReward(Lua_Client c, uint32 silver, uint32 gold); - void QuestReward(Lua_Client c, uint32 silver, uint32 gold, uint32 platinum); void CameraEffect(uint32 duration, uint32 intensity); void CameraEffect(uint32 duration, uint32 intensity, Lua_Client c); void CameraEffect(uint32 duration, uint32 intensity, Lua_Client c, bool global); diff --git a/zone/mob.cpp b/zone/mob.cpp index b4c3370cb..05ec2015d 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1910,22 +1910,6 @@ void Mob::SendTargetable(bool on, Client *specific_target) { safe_delete(outapp); } -void Mob::QuestReward(Client *c, uint32 silver, uint32 gold, uint32 platinum) { - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct)); - 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) { diff --git a/zone/mob.h b/zone/mob.h index 3b0702e60..0d412a666 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -493,7 +493,6 @@ public: inline bool CheckLastLosState() const { return last_los_check; } //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; } diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index a885922e9..785ad04f6 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6188,6 +6188,57 @@ XS(XS_Client_GetTargetRingZ) XSRETURN(1); } +XS(XS_Client_QuestReward); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_QuestReward) +{ + dXSARGS; + if (items < 1 || items > 9) + Perl_croak(aTHX_ "Usage: Client::QuestReward(THIS, mob, copper, silver, gold, platinum, itemid, exp, factionid, faction)"); + { + Client* THIS; + Mob * mob = nullptr; + int32 copper = 0; + int32 silver = 0; + int32 gold = 0; + int32 platinum = 0; + int32 itemid = 0; + int32 exp = 0; + int32 factionid = 0; + int32 faction = 0; + + if (sv_derived_from(ST(0), "THIS")) { + 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."); + + if (items > 1) { + if (sv_derived_from(ST(1), "mob")) { + IV tmp = SvIV((SV*)SvRV(ST(1))); + mob = INT2PTR(Mob *, tmp); + } + else + Perl_croak(aTHX_ "mob is not of type Mob"); + if (mob == nullptr) + Perl_croak(aTHX_ "mob is nullptr, avoiding crash."); + } + if (items > 2) { copper = (int32)SvIV(ST(2)); } + if (items > 3) { silver = (int32)SvIV(ST(3)); } + if (items > 4) { gold = (int32)SvIV(ST(4)); } + if (items > 5) { platinum = (int32)SvIV(ST(5)); } + if (items > 6) { itemid = (int32)SvIV(ST(6)); } + if (items > 7) { exp = (int32)SvIV(ST(7)); } + if (items > 8) { factionid = (int32)SvIV(ST(8)); } + if (items > 9) { faction = (int32)SvIV(ST(9)); } + + THIS->QuestReward(mob, copper, silver, gold, platinum, itemid, exp, factionid, faction); + } + XSRETURN_EMPTY; +} + #ifdef __cplusplus extern "C" #endif @@ -6432,7 +6483,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetTargetRingX"), XS_Client_GetTargetRingX, file, "$$"); newXSproto(strcpy(buf, "GetTargetRingY"), XS_Client_GetTargetRingY, file, "$$"); newXSproto(strcpy(buf, "GetTargetRingZ"), XS_Client_GetTargetRingZ, file, "$$"); - + newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$$"); XSRETURN_YES; } diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 5eeb7be1b..f5ab99cd6 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -7027,47 +7027,6 @@ XS(XS_Mob_SendAppearanceEffect) XSRETURN_EMPTY; } -XS(XS_Mob_QuestReward); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_QuestReward) -{ - dXSARGS; - if (items < 1 || items > 5) - Perl_croak(aTHX_ "Usage: Mob::QuestReward(THIS, client, silver, gold, platinum)"); - { - Mob * THIS; - Client* client = nullptr; - int32 silver = 0; - int32 gold = 0; - int32 platinum = 0; - - 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 (items > 1) { - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - client = INT2PTR(Client *,tmp); - } - else - Perl_croak(aTHX_ "client is not of type Client"); - if(client == nullptr) - Perl_croak(aTHX_ "client is nullptr, avoiding crash."); - } - if (items > 2) { silver = (int32)SvIV(ST(2)); } - if (items > 3) { gold = (int32)SvIV(ST(3)); } - if (items > 4) { platinum = (int32)SvIV(ST(4)); } - - THIS->QuestReward(client, silver, gold, platinum); - } - XSRETURN_EMPTY; -} - XS(XS_Mob_SetFlyMode); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_SetFlyMode) { @@ -8660,7 +8619,6 @@ XS(boot_Mob) newXSproto(strcpy(buf, "SendIllusion"), XS_Mob_SendIllusion, file, "$$;$$$$$$$$$$$$"); newXSproto(strcpy(buf, "MakeTempPet"), XS_Mob_MakeTempPet, file, "$$;$$$$"); newXSproto(strcpy(buf, "TypesTempPet"), XS_Mob_TypesTempPet, file, "$$;$$$$$"); - newXSproto(strcpy(buf, "QuestReward"), XS_Mob_QuestReward, file, "$$;$$$"); newXSproto(strcpy(buf, "CameraEffect"), XS_Mob_CameraEffect, file, "$$;$$$"); newXSproto(strcpy(buf, "SpellEffect"), XS_Mob_SpellEffect, file, "$$;$$$$$$"); newXSproto(strcpy(buf, "TempName"), XS_Mob_TempName, file, "$:$"); From 6fad93aeeef45b308710e0e1f2530702cafe3d81 Mon Sep 17 00:00:00 2001 From: regneq Date: Mon, 11 May 2015 12:42:13 -0700 Subject: [PATCH 076/846] QuestReward now accepts a single bool (true or false) for faction instead of 2 int32s. If true, it will pull the faction hits assigned to the NPC in the DB (reversed, of course) and give you that as part of the reward. Example usage: e.other:QuestReward(e.self,copper,silver,gold,platinum,itemid,exp,faction) (Credit to Cavedude) --- zone/client.cpp | 29 ++++++++++++++++++++++------- zone/client.h | 4 ++-- zone/lua_client.cpp | 6 +++--- zone/lua_client.h | 2 +- zone/perl_client.cpp | 12 +++++------- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index f86b641c1..0aa5510ff 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7588,7 +7588,7 @@ FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_ra } //Sets the characters faction standing with the specified NPC. -void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity) +void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity, bool quest) { int32 faction_id[MAX_NPC_FACTIONS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int32 npc_value[MAX_NPC_FACTIONS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -7615,6 +7615,15 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(), faction_id[i]); + if (quest) + { + //The ole switcheroo + if (npc_value[i] > 0) + npc_value[i] = -abs(npc_value[i]); + else if (npc_value[i] < 0) + npc_value[i] = abs(npc_value[i]); + } + // Adjust the amount you can go up or down so the resulting range // is PERSONAL_MAX - PERSONAL_MIN // @@ -8585,7 +8594,7 @@ bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLin return true; } -void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, uint32 factionid, int32 faction) { +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)); memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); @@ -8599,8 +8608,6 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, qr->platinum = platinum; qr->item_id = itemid; qr->exp_reward = exp; - qr->faction = factionid; - qr->faction_mod = faction; if (copper > 0 || silver > 0 || gold > 0 || platinum > 0) AddMoneyToPP(copper, silver, gold, platinum, false); @@ -8608,12 +8615,20 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, if (itemid > 0) SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, MainPowerSource); + if (faction) + { + if (target->IsNPC()) + { + int32 nfl_id = target->CastToNPC()->GetNPCFactionID(); + SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true); + qr->faction = target->CastToNPC()->GetPrimaryFaction(); + qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow. + } + } + if (exp > 0) AddEXP(exp); - if (factionid > 0) - SetFactionLevel2(CharacterID(), factionid, GetClass(), GetBaseRace(), GetDeity(), faction, 0); - QueuePacket(outapp, false, Client::CLIENT_CONNECTED); safe_delete(outapp); } \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index b5a016fdc..38c5911e0 100644 --- a/zone/client.h +++ b/zone/client.h @@ -611,7 +611,7 @@ public: void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp, int32 this_faction_min, int32 this_faction_max); void UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp, int32 this_faction_min, int32 this_faction_max); - void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity); + void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity, bool quest = false); void SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp); int32 GetRawItemAC(); uint16 GetCombinedAC_TEST(); @@ -1254,7 +1254,7 @@ public: virtual int32 Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false); - void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, uint32 factionid = 0, int32 faction = 0); + void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false); protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 0242041a6..47607b705 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1290,9 +1290,9 @@ void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint3 self->QuestReward(target, copper, silver, gold, platinum, itemid, exp); } -void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, uint32 factionid, int32 faction) { +void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction) { Lua_Safe_Call_Void(); - self->QuestReward(target, copper, silver, gold, platinum, itemid, exp, factionid, faction); + self->QuestReward(target, copper, silver, gold, platinum, itemid, exp, faction); } luabind::scope lua_register_client() { @@ -1552,7 +1552,7 @@ luabind::scope lua_register_client() { .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) - .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32, uint32, int32))&Lua_Client::QuestReward); + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Lua_Client::QuestReward); } luabind::scope lua_register_inventory_where() { diff --git a/zone/lua_client.h b/zone/lua_client.h index d28da9cdb..8f930fc26 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -285,7 +285,7 @@ public: void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum); void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid); void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp); - void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, uint32 factionid, int32 faction); + void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction); }; #endif diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 785ad04f6..b9ba00622 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6193,7 +6193,7 @@ XS(XS_Client_QuestReward) { dXSARGS; if (items < 1 || items > 9) - Perl_croak(aTHX_ "Usage: Client::QuestReward(THIS, mob, copper, silver, gold, platinum, itemid, exp, factionid, faction)"); + Perl_croak(aTHX_ "Usage: Client::QuestReward(THIS, mob, copper, silver, gold, platinum, itemid, exp, faction)"); { Client* THIS; Mob * mob = nullptr; @@ -6203,8 +6203,7 @@ XS(XS_Client_QuestReward) int32 platinum = 0; int32 itemid = 0; int32 exp = 0; - int32 factionid = 0; - int32 faction = 0; + bool faction = false; if (sv_derived_from(ST(0), "THIS")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -6231,10 +6230,9 @@ XS(XS_Client_QuestReward) if (items > 5) { platinum = (int32)SvIV(ST(5)); } if (items > 6) { itemid = (int32)SvIV(ST(6)); } if (items > 7) { exp = (int32)SvIV(ST(7)); } - if (items > 8) { factionid = (int32)SvIV(ST(8)); } - if (items > 9) { faction = (int32)SvIV(ST(9)); } + if (items > 8) { faction = (bool)SvIV(ST(8)); } - THIS->QuestReward(mob, copper, silver, gold, platinum, itemid, exp, factionid, faction); + THIS->QuestReward(mob, copper, silver, gold, platinum, itemid, exp, faction); } XSRETURN_EMPTY; } @@ -6483,7 +6481,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetTargetRingX"), XS_Client_GetTargetRingX, file, "$$"); newXSproto(strcpy(buf, "GetTargetRingY"), XS_Client_GetTargetRingY, file, "$$"); newXSproto(strcpy(buf, "GetTargetRingZ"), XS_Client_GetTargetRingZ, file, "$$"); - newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$$"); + newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$"); XSRETURN_YES; } From cc2a60feb226a1c29eb3b2d7bdebab95268e0c5b Mon Sep 17 00:00:00 2001 From: regneq Date: Mon, 11 May 2015 16:34:46 -0700 Subject: [PATCH 077/846] * change the kill faction hits display before the xp message not after. * removed the double level gain messages to display once either the level gained or the level. * implement the message "You will now lose experience when you die" and "Your items will no longer stay with you..." when reach a certain level already sets in the rule table. --- zone/attack.cpp | 8 ++++---- zone/exp.cpp | 28 +++++++++++++++++++--------- zone/string_ids.h | 2 ++ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 256eefe0f..49b5df187 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2144,6 +2144,10 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack if(give_exp && give_exp->IsClient()) give_exp_client = give_exp->CastToClient(); + //do faction hits even if we are a merchant, so long as a player killed us + if (give_exp_client && !RuleB(NPC, EnableMeritBasedFaction)) + hate_list.DoFactionHits(GetNPCFactionID()); + bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE); if (give_exp_client && !IsCorpse()) { @@ -2287,10 +2291,6 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack } } - //do faction hits even if we are a merchant, so long as a player killed us - if(give_exp_client && !RuleB(NPC, EnableMeritBasedFaction)) - 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()))) diff --git a/zone/exp.cpp b/zone/exp.cpp index 7e878206a..3a77f30dc 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -268,12 +268,17 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { //this ammount of exp (once these loops complete) uint16 check_level = GetLevel()+1; //see if we gained any levels + bool level_increase = true; + int8 level_count = 0; + while (set_exp >= GetEXPForLevel(check_level)) { check_level++; if (check_level > 127) { //hard level cap check_level = 127; break; } + level_count++; + if(GetMercID()) UpdateMercLevel(); } @@ -284,6 +289,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { check_level = 2; break; } + level_increase = false; if(GetMercID()) UpdateMercLevel(); } @@ -364,17 +370,21 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { if ((GetLevel() != check_level) && !(check_level >= maxlevel)) { char val1[20]={0}; - if (GetLevel() == check_level-1){ - Message_StringID(MT_Experience, GAIN_LEVEL,ConvertArray(check_level,val1)); - SendLevelAppearance(); - /* Message(15, "You have gained a level! Welcome to level %i!", check_level); */ - } - if (GetLevel() == check_level){ - Message_StringID(MT_Experience, LOSE_LEVEL,ConvertArray(check_level,val1)); - /* Message(15, "You lost a level! You are now level %i!", check_level); */ + if (level_increase) + { + if (level_count == 1) + Message_StringID(MT_Experience, GAIN_LEVEL, ConvertArray(check_level, val1)); + else + Message(15, "Welcome to level %i!", check_level); + + if (check_level == RuleI(Character, DeathItemLossLevel)) + Message_StringID(15, CORPSE_ITEM_LOST); + + if (check_level == RuleI(Character, DeathExpLossLevel)) + Message_StringID(15, CORPSE_EXP_LOST); } else - Message(15, "Welcome to level %i!", check_level); + Message_StringID(MT_Experience, LOSE_LEVEL, ConvertArray(check_level, val1)); #ifdef BOTS uint8 myoldlevel = GetLevel(); diff --git a/zone/string_ids.h b/zone/string_ids.h index ef758dba6..2db4e34e8 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -231,6 +231,8 @@ #define MISSED_NOTE_OTHER 1219 //A missed note brings %1's song to a close! #define SPELL_LEVEL_REQ 1226 //This spell only works on people who are level %1 and under. #define CORPSE_DECAY_NOW 1227 //This corpse is waiting to expire. +#define CORPSE_ITEM_LOST 1228 //Your items will no longer stay with you when you respawn on death. You will now need to return to your corpse for your items. +#define CORPSE_EXP_LOST 1229 //You will now lose experience when you die. #define SURNAME_REJECTED 1374 //Your new surname was rejected. Please try a different name. #define DUEL_DECLINE 1383 //%1 has declined your challenge to duel to the death. #define DUEL_ACCEPTED 1384 //%1 has already accepted a duel with someone else. From 052f343e4dc0549958e389f588fef9284dd0bd7f Mon Sep 17 00:00:00 2001 From: regneq Date: Mon, 11 May 2015 21:42:48 -0700 Subject: [PATCH 078/846] smoother NPC pathing. (credit to Haynar from EQMacEmu) --- zone/client.h | 1 + zone/map.cpp | 37 +++++++++++- zone/map.h | 1 + zone/mob.cpp | 1 + zone/mob_ai.cpp | 148 ++++++++++++++++++++++++--------------------- zone/npc.h | 1 + zone/waypoints.cpp | 17 +++++- 7 files changed, 133 insertions(+), 73 deletions(-) diff --git a/zone/client.h b/zone/client.h index 38c5911e0..79dcf87ff 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1129,6 +1129,7 @@ public: inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); } void DragCorpses(); inline void ClearDraggedCorpses() { DraggedCorpses.clear(); } + inline void ResetPositionTimer() { position_timer_counter = 0; } void SendAltCurrencies(); void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount); void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0); diff --git a/zone/map.cpp b/zone/map.cpp index d4bb5a268..37f394626 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -64,7 +64,7 @@ Map::~Map() { float Map::FindBestZ(glm::vec3 &start, glm::vec3 *result) const { if (!imp) - return false; + return BEST_Z_INVALID; glm::vec3 tmp; if(!result) @@ -93,6 +93,41 @@ float Map::FindBestZ(glm::vec3 &start, glm::vec3 *result) const { return BEST_Z_INVALID; } +float Map::FindClosestZ(glm::vec3 &start, glm::vec3 *result) const { + // Unlike FindBestZ, this method finds the closest Z value above or below the specified point. + // + if (!imp) + return false; + + float ClosestZ = BEST_Z_INVALID; + + glm::vec3 tmp; + if (!result) + result = &tmp; + + glm::vec3 from(start.x, start.y, start.z); + glm::vec3 to(start.x, start.y, BEST_Z_INVALID); + float hit_distance; + bool hit = false; + + // first check is below us + hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance); + if (hit) { + ClosestZ = result->z; + + } + + // Find nearest Z above us + 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)) + return result->z; + } + + return ClosestZ; +} + bool Map::LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const { if(!imp) return false; diff --git a/zone/map.h b/zone/map.h index 2bce1c6db..f3e81fe20 100644 --- a/zone/map.h +++ b/zone/map.h @@ -34,6 +34,7 @@ public: ~Map(); float FindBestZ(glm::vec3 &start, glm::vec3 *result) const; + float FindClosestZ(glm::vec3 &start, glm::vec3 *result) const; 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; diff --git a/zone/mob.cpp b/zone/mob.cpp index 05ec2015d..d95b3bea7 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1201,6 +1201,7 @@ void Mob::SendPosition() PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdateNoDelta(spu); move_tic_count = 0; + tar_ndx = 20; entity_list.QueueClients(this, app, true); safe_delete(app); } diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 020c833e8..18618e262 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1666,92 +1666,41 @@ void NPC::AI_DoMovement() { 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; - - Log.Out(Logs::Detail, Logs::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) { - Log.Out(Logs::Detail, Logs::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; - } - } + AI_SetupNextWaypoint(); } // endif (movetimercompleted==true) else if (!(AIwalking_timer->Enabled())) { // currently moving + bool doMove = true; 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()); - SetWaypointPause(); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - SetMoving(false); - if (m_CurrentWayPoint.w >= 0.0) { - SetHeading(m_CurrentWayPoint.w); + if (cur_wp_pause != 0) { + SetWaypointPause(); + if (GetAppearance() != eaStanding) + SetAppearance(eaStanding, false); + SetMoving(false); + 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); parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0); + // start moving directly to next waypoint if we're at a 0 pause waypoint and we didn't get quest halted. + if (!AIwalking_timer->Enabled()) + AI_SetupNextWaypoint(); + else + doMove = false; // wipe feign memory since we reached our first waypoint if(cur_wp == 1) ClearFeignMemory(); } - else - { // not at waypoint yet, so keep moving + if (doMove) + { // not at waypoint yet or at 0 pause WP, so keep moving if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0)) CalculateNewPosition2(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true); else @@ -1829,6 +1778,67 @@ void NPC::AI_DoMovement() { } } } +void NPC::AI_SetupNextWaypoint() { + 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 restart 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; + + Log.Out(Logs::Detail, Logs::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) { + Log.Out(Logs::Detail, Logs::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 (GetGrid() > 0) { + CastToNPC()->CalculateNewWaypoint(); + } + } + else { + DistractedFromGrid = false; + } + } +} // 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) { diff --git a/zone/npc.h b/zone/npc.h index 95a857460..f960c736e 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -119,6 +119,7 @@ public: virtual void AI_Start(uint32 iMoveDelay = 0); virtual void AI_Stop(); void AI_DoMovement(); + void AI_SetupNextWaypoint(); bool AI_AddNPCSpells(uint32 iDBSpellsID); bool AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID); virtual bool AI_EngagedCastCheck(); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index d3b85bf03..b81e100d7 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -394,6 +394,7 @@ void NPC::SetWaypointPause() if (cur_wp_pause == 0) { AIwalking_timer->Start(100); + AIwalking_timer->Trigger(); } else { @@ -514,7 +515,9 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b return true; } + bool send_update = false; int compare_steps = IsBoat() ? 1 : 20; + if(tar_ndx < compare_steps && m_TargetLocation.x==x && m_TargetLocation.y==y) { float new_x = m_Position.x + m_TargetV.x*tar_vector; @@ -637,13 +640,14 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b m_Position.y = y; m_Position.z = z; + tar_ndx = 20; Log.Out(Logs::Detail, Logs::AI, "Only a single step to get there... jumping."); } } else { - tar_vector/=20; + tar_vector/=20.0f; float new_x = m_Position.x + m_TargetV.x*tar_vector; float new_y = m_Position.y + m_TargetV.y*tar_vector; @@ -699,12 +703,19 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f); if (IsClient()) + { SendPosUpdate(1); + CastToClient()->ResetPositionTimer(); + } else + { + // force an update now + move_tic_count = RuleI(Zone, NPCPositonUpdateTicCount); SendPosUpdate(); - - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); + } pLastChange = Timer::GetCurrentTime(); + return true; } From cbcaead8df30ece74de4ec48ee737a3df55b0e27 Mon Sep 17 00:00:00 2001 From: hateborne Date: Wed, 13 May 2015 18:41:14 -0400 Subject: [PATCH 079/846] GM Output for Casting Blocked Spells Utilizing the logging system to display an alert when a GM casts a blocked spell, giving some notification instead of silent successes on cast. --- zone/spells.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 77a9f691d..fc5856284 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1939,6 +1939,12 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } } + if (IsClient() && CastToClient()->GetGM()){ + if (zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))){ + Log.Out(Logs::Detail, Logs::Spells, "GM Cast Blocked Spell: %s (ID %i)", GetSpellName(spell_id), spell_id); + } + } + if ( this->IsClient() && From 2308d3e88021d146aa20e66bfea63fda8438fc08 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 15 May 2015 22:49:59 -0400 Subject: [PATCH 080/846] Fix for EntityList::CheckSpawnQueue() debug assertion failure crash --- changelog.txt | 3 +++ zone/entity.cpp | 12 +++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index a90c903bd..17126ff43 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/15/2015 == +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 You can set Combat:MeleePush to false to turn off or change Combat:MeleePushChance to increase the chance an NPC can be pushed diff --git a/zone/entity.cpp b/zone/entity.cpp index 5646f0870..bf1f6b720 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -736,9 +736,15 @@ void EntityList::CheckSpawnQueue() Mob::CreateSpawnPacket(outapp, ns); QueueClients(0, outapp); auto it = npc_list.find(ns->spawn.spawnId); - NPC *pnpc = it->second; - pnpc->SendArmorAppearance(); - pnpc->SetAppearance(pnpc->GetGuardPointAnim(),false); + if (it == npc_list.end()) { + // We must of despawned, hope that's the reason! + Log.Out(Logs::General, Logs::Error, "Error in EntityList::CheckSpawnQueue: Unable to find NPC for spawnId '%u'", ns->spawn.spawnId); + } + else { + NPC *pnpc = it->second; + pnpc->SendArmorAppearance(); + pnpc->SetAppearance(pnpc->GetGuardPointAnim(), false); + } safe_delete(outapp); iterator.RemoveCurrent(); } From 79a87fac1d2bb9da7748041bc14719c4cf6c1a5c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 17 May 2015 23:51:24 -0400 Subject: [PATCH 081/846] Guard against eaStanding spam --- zone/waypoints.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index b81e100d7..d1a447a5e 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -712,7 +712,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b // force an update now move_tic_count = RuleI(Zone, NPCPositonUpdateTicCount); SendPosUpdate(); - SetAppearance(eaStanding, false); + if (GetAppearance() != eaStanding) + SetAppearance(eaStanding, false); } pLastChange = Timer::GetCurrentTime(); @@ -1050,7 +1051,7 @@ void ZoneDatabase::AssignGrid(Client *client, int grid, int spawn2id) { if (!results.Success()) return; - + if (results.RowsAffected() != 1) { return; } From 553b7c9f8c36009fc5a3ef5c036d0c8a0a0b67a8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 18 May 2015 00:04:55 -0400 Subject: [PATCH 082/846] Move the extra appearance packet guard to SetAppearance --- zone/mob.cpp | 2 ++ zone/mob_ai.cpp | 14 ++++---------- zone/waypoints.cpp | 3 +-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index d95b3bea7..a8bed6417 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2027,6 +2027,8 @@ const int32& Mob::SetMana(int32 amount) void Mob::SetAppearance(EmuAppearance app, bool iIgnoreSelf) { + if (_appearance == app) + return; _appearance = app; SendAppearancePacket(AT_Anim, GetAppearanceValue(app), true, iIgnoreSelf); if (this->IsClient() && this->IsAIControlled()) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 18618e262..dd20d605c 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1676,8 +1676,7 @@ void NPC::AI_DoMovement() { 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(); - if (GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); SetMoving(false); if (m_CurrentWayPoint.w >= 0.0) { SetHeading(m_CurrentWayPoint.w); @@ -1728,8 +1727,7 @@ void NPC::AI_DoMovement() { SetGrid( 0 - GetGrid()); // revert to AI control Log.Out(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid()); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); CalculateNewWaypoint(); } @@ -1817,8 +1815,7 @@ void NPC::AI_SetupNextWaypoint() { cur_wp = 0; } - if (GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); entity_list.OpenDoorsNear(CastToNPC()); @@ -1845,10 +1842,7 @@ void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) { if (!IsAIControlled()) return; - if(GetAppearance() != eaStanding) - { - SetAppearance(eaStanding); - } + SetAppearance(eaStanding); if (iYellForHelp) { if(IsPet()) { diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index d1a447a5e..f75743a7d 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -712,8 +712,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b // force an update now move_tic_count = RuleI(Zone, NPCPositonUpdateTicCount); SendPosUpdate(); - if (GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); } pLastChange = Timer::GetCurrentTime(); From 4266f45295c35d1c24fca919b3c9e37ddc89d95c Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 18 May 2015 20:40:57 -0400 Subject: [PATCH 083/846] Added merc pointer initialization to avoid an invalid pointer condition --- zone/zonedb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 1fab4aff2..ef790e9d8 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2183,7 +2183,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client return nullptr; } - const NPCType *npc; + const NPCType *npc = nullptr; // Process each row returned. for (auto row = results.begin(); row != results.end(); ++row) { From 2ef0fc93424f03e1eb675d135f34979115b80873 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 18 May 2015 21:45:51 -0700 Subject: [PATCH 084/846] Change to fishing water location algorithim --- changelog.txt | 3 ++ common/ruletypes.h | 3 +- .../optional/2015_05_18_FishingLineLength.sql | 1 + zone/forage.cpp | 41 +++++++++++-------- 4 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 utils/sql/git/optional/2015_05_18_FishingLineLength.sql diff --git a/changelog.txt b/changelog.txt index 17126ff43..4ad457d78 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/18/2015 == +KLS: Changed how fishing locates water to hopefully be a bit more accurate at the expense of a bit more cpu power per line cast. + == 05/15/2015 == Uleat: Added check to EntityList::CheckSpawnQueue() to bypass dereference if returned iterator is npc_list.end() - should fix the debug assertion failure crash diff --git a/common/ruletypes.h b/common/ruletypes.h index 5c4154cf9..a581e527d 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -272,7 +272,8 @@ RULE_BOOL ( Watermap, CheckForWaterWhenMoving, false) // Checks if a mob has mo RULE_BOOL ( Watermap, CheckForWaterOnSendTo, false) // Checks if a mob has moved into/out of water on SendTo RULE_BOOL ( Watermap, CheckForWaterWhenFishing, false) // Only lets a player fish near water (if a water map exists for the zone) RULE_REAL ( Watermap, FishingRodLength, 30) // How far in front of player water must be for fishing to work -RULE_REAL ( Watermap, FishingLineLength, 40) // If water is more than this far below the player, it is considered too far to fish +RULE_REAL ( Watermap, FishingLineLength, 100) // If water is more than this far below the player, it is considered too far to fish +RULE_REAL ( Watermap, FishingLineStepSize, 1) // Basic step size for fishing calc, too small and it will eat cpu, too large and it will miss potential water RULE_CATEGORY_END() RULE_CATEGORY( Spells ) diff --git a/utils/sql/git/optional/2015_05_18_FishingLineLength.sql b/utils/sql/git/optional/2015_05_18_FishingLineLength.sql new file mode 100644 index 000000000..f57c4d02e --- /dev/null +++ b/utils/sql/git/optional/2015_05_18_FishingLineLength.sql @@ -0,0 +1 @@ +UPDATE rule_values SET rule_value=100 WHERE rule_name='Watermap:FishingLineLength'; diff --git a/zone/forage.cpp b/zone/forage.cpp index 96b0efcdc..89d4e254f 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -185,26 +185,35 @@ bool Client::CanFish() { rodPosition.x = m_Position.x + RodLength * sin(HeadingDegrees * M_PI/180.0f); rodPosition.y = m_Position.y + RodLength * cos(HeadingDegrees * M_PI/180.0f); + rodPosition.z = m_Position.z; - // Do BestZ to find where the line hanging from the rod intersects the water (if it is water). - // and go 1 unit into the water. - glm::vec3 dest; - dest.x = rodPosition.x; - dest.y = rodPosition.y; - dest.z = m_Position.z+10; - - rodPosition.z = zone->zonemap->FindBestZ(dest, nullptr) + 4; - bool in_lava = zone->watermap->InLava(rodPosition); - bool in_water = zone->watermap->InWater(rodPosition) || zone->watermap->InVWater(rodPosition); - //Message(0, "Rod is at %4.3f, %4.3f, %4.3f, InWater says %d, InLava says %d", RodX, RodY, RodZ, in_water, in_lava); - if (in_lava) { - Message_StringID(MT_Skills, FISHING_LAVA); //Trying to catch a fire elemental or something? + float bestz = zone->zonemap->FindBestZ(rodPosition, nullptr); + float len = m_Position.z - bestz; + if(len > LineLength || len < 0.0f) { + Message_StringID(MT_Skills, FISHING_LAND); return false; } - if((!in_water) || (m_Position.z-rodPosition.z)>LineLength) { //Didn't hit the water OR the water is too far below us - Message_StringID(MT_Skills, FISHING_LAND); //Trying to catch land sharks perhaps? - return false; + + float step_size = RuleR(Watermap, FishingLineStepSize); + + for(float i = 0.0f; i < len; i += step_size) { + glm::vec3 dest(rodPosition.x, rodPosition.y, m_Position.z - i); + + bool in_lava = zone->watermap->InLava(dest); + bool in_water = zone->watermap->InWater(dest) || zone->watermap->InVWater(dest); + + if (in_lava) { + Message_StringID(MT_Skills, FISHING_LAVA); //Trying to catch a fire elemental or something? + return false; + } + + if(in_water) { + return true; + } } + + Message_StringID(MT_Skills, FISHING_LAND); + return false; } return true; } From ea5a1dd6f1bc910e5f092081186eb8d7a6095c65 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 20 May 2015 02:01:43 -0400 Subject: [PATCH 085/846] Bard instrument mods should be more consistent with live Changes: Mods are now saved for in the DB so they are loaded on zone This allows long duration buffs from bards that get mods to keep their mods Ex. Selo's, Symphony of Battle Instrument mods are applied to basically anything that is an instrument skill The only exception to this is discs (ex. Puretone is Singing but always 10) Singing spells from procs (Ex. Storm Blade) that are instrument skills should inherit their buffs instrument mod. Doom effects should also. This isn't implemented yet. --- changelog.txt | 4 + common/skills.cpp | 14 + common/skills.h | 1 + common/spdat.cpp | 14 +- common/version.h | 8 +- utils/sql/db_update_manifest.txt | 3 +- .../required/2015_05_20_BuffInstrumentMod.sql | 1 + zone/bonuses.cpp | 61 +- zone/bot.cpp | 4 +- zone/bot.h | 2 +- zone/client_mods.cpp | 158 +++-- zone/client_packet.cpp | 2 +- zone/common.h | 1 + zone/mob.h | 6 +- zone/mob_ai.cpp | 8 +- zone/spell_effects.cpp | 565 +++++++++--------- zone/spells.cpp | 1 + zone/zonedb.cpp | 150 ++--- 18 files changed, 493 insertions(+), 510 deletions(-) create mode 100644 utils/sql/git/required/2015_05_20_BuffInstrumentMod.sql diff --git a/changelog.txt b/changelog.txt index 4ad457d78..204d08d7b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/20/2015 == +demonstar55: 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 == KLS: Changed how fishing locates water to hopefully be a bit more accurate at the expense of a bit more cpu power per line cast. diff --git a/common/skills.cpp b/common/skills.cpp index 363c077d8..5edca778b 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -92,3 +92,17 @@ float EQEmu::GetSkillMeleePushForce(SkillUseTypes skill) return 0.0f; } } + +bool EQEmu::IsBardInstrumentSkill(SkillUseTypes skill) +{ + switch (skill) { + case SkillBrassInstruments: + case SkillSinging: + case SkillStringedInstruments: + case SkillWindInstruments: + case SkillPercussionInstruments: + return true; + default: + return false; + } +} diff --git a/common/skills.h b/common/skills.h index aafb1abce..1fad4de3e 100644 --- a/common/skills.h +++ b/common/skills.h @@ -271,6 +271,7 @@ namespace EQEmu { bool IsTradeskill(SkillUseTypes skill); bool IsSpecializedSkill(SkillUseTypes skill); float GetSkillMeleePushForce(SkillUseTypes skill); + bool IsBardInstrumentSkill(SkillUseTypes skill); } #endif diff --git a/common/spdat.cpp b/common/spdat.cpp index e52a06e2e..7dd21479c 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -72,7 +72,7 @@ -#include "../common/eqemu_logsys.h" +#include "../common/eqemu_logsys.h" #include "classes.h" #include "spdat.h" @@ -162,7 +162,7 @@ bool IsCureSpell(uint16 spell_id) bool CureEffect = false; for(int i = 0; i < EFFECT_COUNT; i++){ - if (sp.effectid[i] == SE_DiseaseCounter || sp.effectid[i] == SE_PoisonCounter + if (sp.effectid[i] == SE_DiseaseCounter || sp.effectid[i] == SE_PoisonCounter || sp.effectid[i] == SE_CurseCounter || sp.effectid[i] == SE_CorruptionCounter) CureEffect = true; } @@ -405,7 +405,7 @@ bool IsPartialCapableSpell(uint16 spell_id) { if (spells[spell_id].no_partial_resist) return false; - + if (IsPureNukeSpell(spell_id)) return true; @@ -447,7 +447,7 @@ bool IsTGBCompatibleSpell(uint16 spell_id) bool IsBardSong(uint16 spell_id) { - if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255) + if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 127 && !spells[spell_id].IsDisciplineBuff) return true; return false; @@ -693,9 +693,9 @@ bool IsCombatSkill(uint16 spell_id) { if (!IsValidSpell(spell_id)) return false; - + //Check if Discipline - if ((spells[spell_id].mana == 0 && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep))) + if ((spells[spell_id].mana == 0 && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep))) return true; return false; @@ -1040,7 +1040,7 @@ bool IsCastonFadeDurationSpell(uint16 spell_id) bool IsPowerDistModSpell(uint16 spell_id) { - if (IsValidSpell(spell_id) && + if (IsValidSpell(spell_id) && (spells[spell_id].max_dist_mod || spells[spell_id].min_dist_mod) && spells[spell_id].max_dist > spells[spell_id].min_dist) return true; diff --git a/common/version.h b/common/version.h index 7b8cfd78c..9ce7b285c 100644 --- a/common/version.h +++ b/common/version.h @@ -24,13 +24,13 @@ #define CURRENT_VERSION "1.1.3" -/* - Everytime a Database SQL is added to Github, +/* + Everytime a Database SQL is added to Github, increment CURRENT_BINARY_DATABASE_VERSION number and make sure you update the manifest - Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt + Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9077 +#define CURRENT_BINARY_DATABASE_VERSION 9078 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 2ad0b647c..8e01d0420 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -331,9 +331,10 @@ 9075|2015_02_02_logsys_packet_logs_with_dump.sql|SELECT * FROM `logsys_categories` WHERE `log_category_description` LIKE 'Packet: Server -> Client With Dump'|empty| 9076|2015_02_04_average_coin.sql|SHOW COLUMNS FROM `loottable` WHERE Field = 'avgcoin'|contains|smallint 9077|2015_02_12_zone_gravity.sql|SHOW COLUMNS FROM `zone` LIKE 'gravity'|empty| +9078|2015_05_20_BuffInstrumentMod.sql|SHOW COLUMNS FROM `character_buffs` LIKE `instrument_mod`|empty| # Upgrade conditions: -# This won't be needed after this system is implemented, but it is used database that are not +# This won't be needed after this system is implemented, but it is used database that are not # yet using the versioning system to figure out where the database is schema wise to determine # which updates are necessary to run # diff --git a/utils/sql/git/required/2015_05_20_BuffInstrumentMod.sql b/utils/sql/git/required/2015_05_20_BuffInstrumentMod.sql new file mode 100644 index 000000000..140fe5b66 --- /dev/null +++ b/utils/sql/git/required/2015_05_20_BuffInstrumentMod.sql @@ -0,0 +1 @@ +ALTER TABLE `character_buffs` ADD COLUMN `instrument_mod` int(10) DEFAULT 10 NOT NULL; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index c17980297..ab4afeab4 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -428,7 +428,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu 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, item->Worn.Type); + ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); } if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects @@ -559,7 +559,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool /* Powerful Non-live like option allows developers to add worn effects on items that can stack with other worn effects of the same spell effect type, instead of only taking the highest value. - Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus. + Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus. To enable use RuleI(Spells, AdditiveBonusWornType) Setting value = 2 Will force all live items to automatically be calculated additivily Setting value to anything else will indicate the item 'worntype' that if set to the same, will cause the bonuses to use this calculation @@ -579,7 +579,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if(GetLevel() < item->ReqLevel) return; - + if (item->Worn.Effect > 0 && item->Worn.Type == RuleI(Spells, AdditiveBonusWornType)) ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);// Non-live like - Addititive latent effects @@ -691,7 +691,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) continue; Log.Out(Logs::Detail, Logs::AA, "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) { @@ -1007,7 +1007,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_BlockBehind: newbon->BlockBehind += base1; break; - + case SE_StrikeThrough: case SE_StrikeThrough2: newbon->StrikeThrough += base1; @@ -1313,7 +1313,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_Vampirism: newbon->Vampirism += base1; - break; + break; case SE_FrenziedDevastation: newbon->FrenziedDevastation += base2; @@ -1416,7 +1416,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) } case SE_SkillProcSuccess:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid) @@ -1449,7 +1449,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) int 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, 0, buffs[i].ticsremaining,i); + ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, 0, buffs[i].ticsremaining, i, buffs[i].instrument_mod); if (buffs[i].numhits > 0) Numhits(true); @@ -1472,8 +1472,9 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } -void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, uint8 WornType, uint32 ticsremaining, int buffslot, - bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) +void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *new_bonus, uint16 casterId, + uint8 WornType, uint32 ticsremaining, int buffslot, int instrument_mod, + bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) { int i, effect_value, base2, max, effectid; bool AdditiveWornBonus = false; @@ -1509,9 +1510,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (WornType && (RuleI(Spells, AdditiveBonusWornType) == WornType)) AdditiveWornBonus = true; - + effectid = spells[spell_id].effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining); + effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, caster, ticsremaining); base2 = spells[spell_id].base2[i]; max = spells[spell_id].max[i]; } @@ -1620,10 +1621,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) { effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value > new_bonus->inhibitmelee) + if (effect_value > new_bonus->inhibitmelee) new_bonus->inhibitmelee = effect_value; } - + break; } @@ -1839,7 +1840,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne new_bonus->DamageShieldType = GetDamageShieldType(spell_id, max); else new_bonus->DamageShieldType = GetDamageShieldType(spell_id); - + break; } @@ -2020,7 +2021,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_Vampirism: new_bonus->Vampirism += effect_value; - break; + break; case SE_AllInstrumentMod: { @@ -2263,7 +2264,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CriticalSpellChance: { new_bonus->CriticalSpellChance += effect_value; - + if (base2 > new_bonus->SpellCritDmgIncNoStack) new_bonus->SpellCritDmgIncNoStack = base2; break; @@ -2473,7 +2474,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_NegateAttacks: { - if (!new_bonus->NegateAttacks[0] || + if (!new_bonus->NegateAttacks[0] || ((new_bonus->NegateAttacks[0] && new_bonus->NegateAttacks[2]) && (new_bonus->NegateAttacks[2] < max))){ new_bonus->NegateAttacks[0] = 1; new_bonus->NegateAttacks[1] = buffslot; @@ -2493,7 +2494,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } - + case SE_MeleeThresholdGuard: { if (new_bonus->MeleeThresholdGuard[0] < effect_value){ @@ -2860,17 +2861,17 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne new_bonus->NegateIfCombat = true; break; - case SE_Screech: + case SE_Screech: new_bonus->Screech = effect_value; break; case SE_AlterNPCLevel: if (IsNPC()){ - if (!new_bonus->AlterNPCLevel - || ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value)) + if (!new_bonus->AlterNPCLevel + || ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value)) || ((effect_value > 0) && (new_bonus->AlterNPCLevel < effect_value))) { - + int tmp_lv = GetOrigLevel() + effect_value; if (tmp_lv < 1) tmp_lv = 1; @@ -2908,7 +2909,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne new_bonus->BerserkSPA = true; break; - + case SE_Metabolism: new_bonus->Metabolism += effect_value; break; @@ -3009,7 +3010,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } case SE_SkillProc:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(new_bonus->SkillProc[e] && new_bonus->SkillProc[e] == spell_id) @@ -3024,7 +3025,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } case SE_SkillProcSuccess:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(new_bonus->SkillProcSuccess[e] && new_bonus->SkillProcSuccess[e] == spell_id) @@ -3040,9 +3041,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { - + //Non-Focused Effect to modify incoming spell damage by resist type. - case SE_FcSpellVulnerability: + case SE_FcSpellVulnerability: ModVulnerability(base2, effect_value); break; } @@ -4394,7 +4395,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.SlayUndead[0] = effect_value; aabonuses.SlayUndead[1] = effect_value; break; - + case SE_DoubleRangedAttack: spellbonuses.DoubleRangedAttack = effect_value; aabonuses.DoubleRangedAttack = effect_value; @@ -4414,7 +4415,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.ShieldEquipDmgMod[1] = effect_value; itembonuses.ShieldEquipDmgMod[0] = effect_value; itembonuses.ShieldEquipDmgMod[1] = effect_value; - break; + break; case SE_TriggerMeleeThreshold: spellbonuses.TriggerMeleeThreshold = false; diff --git a/zone/bot.cpp b/zone/bot.cpp index 48a4dfe55..e2c506575 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -9092,8 +9092,8 @@ bool Bot::SpellEffect(Mob* caster, uint16 spell_id, float partial) { return Result; } -void Bot::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster) { - Mob::DoBuffTic(spell_id, slot, ticsremaining, caster_level, caster); +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, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust) { diff --git a/zone/bot.h b/zone/bot.h index 42d0b7f65..871d96df4 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -310,7 +310,7 @@ public: virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration); virtual float GetAOERange(uint16 spell_id); virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100); - virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0); + 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, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr); virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 6aae0d0e9..f12c20064 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1974,101 +1974,87 @@ int32 Client::CalcATK() uint32 Mob::GetInstrumentMod(uint16 spell_id) const { - if (GetClass() != BARD) { + if (GetClass() != BARD || spells[spell_id].IsDisciplineBuff) // Puretone is Singing but doesn't get any mod return 10; - } + uint32 effectmod = 10; int effectmodcap = RuleI(Character, BaseInstrumentSoftCap); - //this should never use spell modifiers... - //if a spell grants better modifers, they are copied into the item mods - //because the spells are supposed to act just like having the intrument. - //item mods are in 10ths of percent increases + // this should never use spell modifiers... + // if a spell grants better modifers, they are copied into the item mods + // because the spells are supposed to act just like having the intrument. + // item mods are in 10ths of percent increases + // 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: - if (itembonuses.percussionMod == 0 && spellbonuses.percussionMod == 0) { - effectmod = 10; - } - else if (GetSkill(SkillPercussionInstruments) == 0) { - effectmod = 10; - } - else if (itembonuses.percussionMod > spellbonuses.percussionMod) { - effectmod = itembonuses.percussionMod; - } - else { - effectmod = spellbonuses.percussionMod; - } - effectmod += aabonuses.percussionMod; - break; - case SkillStringedInstruments: - if (itembonuses.stringedMod == 0 && spellbonuses.stringedMod == 0) { - effectmod = 10; - } - else if (GetSkill(SkillStringedInstruments) == 0) { - effectmod = 10; - } - else if (itembonuses.stringedMod > spellbonuses.stringedMod) { - effectmod = itembonuses.stringedMod; - } - else { - effectmod = spellbonuses.stringedMod; - } - effectmod += aabonuses.stringedMod; - break; - case SkillWindInstruments: - if (itembonuses.windMod == 0 && spellbonuses.windMod == 0) { - effectmod = 10; - } - else if (GetSkill(SkillWindInstruments) == 0) { - effectmod = 10; - } - else if (itembonuses.windMod > spellbonuses.windMod) { - effectmod = itembonuses.windMod; - } - else { - effectmod = spellbonuses.windMod; - } - effectmod += aabonuses.windMod; - break; - case SkillBrassInstruments: - if (itembonuses.brassMod == 0 && spellbonuses.brassMod == 0) { - effectmod = 10; - } - else if (GetSkill(SkillBrassInstruments) == 0) { - effectmod = 10; - } - else if (itembonuses.brassMod > spellbonuses.brassMod) { - effectmod = itembonuses.brassMod; - } - else { - effectmod = spellbonuses.brassMod; - } - effectmod += aabonuses.brassMod; - break; - case SkillSinging: - if (itembonuses.singingMod == 0 && spellbonuses.singingMod == 0) { - effectmod = 10; - } - else if (itembonuses.singingMod > spellbonuses.singingMod) { - effectmod = itembonuses.singingMod; - } - else { - effectmod = spellbonuses.singingMod; - } - effectmod += aabonuses.singingMod + spellbonuses.Amplification; - break; - default: + case SkillPercussionInstruments: + if (itembonuses.percussionMod == 0 && spellbonuses.percussionMod == 0) effectmod = 10; - break; + else if (GetSkill(SkillPercussionInstruments) == 0) + effectmod = 10; + else if (itembonuses.percussionMod > spellbonuses.percussionMod) + effectmod = itembonuses.percussionMod; + else + effectmod = spellbonuses.percussionMod; + if (IsBardSong(spell_id)) + effectmod += aabonuses.percussionMod; + break; + case SkillStringedInstruments: + if (itembonuses.stringedMod == 0 && spellbonuses.stringedMod == 0) + effectmod = 10; + else if (GetSkill(SkillStringedInstruments) == 0) + effectmod = 10; + else if (itembonuses.stringedMod > spellbonuses.stringedMod) + effectmod = itembonuses.stringedMod; + else + effectmod = spellbonuses.stringedMod; + if (IsBardSong(spell_id)) + effectmod += aabonuses.stringedMod; + break; + case SkillWindInstruments: + if (itembonuses.windMod == 0 && spellbonuses.windMod == 0) + effectmod = 10; + else if (GetSkill(SkillWindInstruments) == 0) + effectmod = 10; + else if (itembonuses.windMod > spellbonuses.windMod) + effectmod = itembonuses.windMod; + else + effectmod = spellbonuses.windMod; + if (IsBardSong(spell_id)) + effectmod += aabonuses.windMod; + break; + case SkillBrassInstruments: + if (itembonuses.brassMod == 0 && spellbonuses.brassMod == 0) + effectmod = 10; + else if (GetSkill(SkillBrassInstruments) == 0) + effectmod = 10; + else if (itembonuses.brassMod > spellbonuses.brassMod) + effectmod = itembonuses.brassMod; + else + effectmod = spellbonuses.brassMod; + if (IsBardSong(spell_id)) + effectmod += aabonuses.brassMod; + break; + case SkillSinging: + if (itembonuses.singingMod == 0 && spellbonuses.singingMod == 0) + effectmod = 10; + else if (itembonuses.singingMod > spellbonuses.singingMod) + effectmod = itembonuses.singingMod; + else + effectmod = spellbonuses.singingMod; + if (IsBardSong(spell_id)) + effectmod += aabonuses.singingMod + spellbonuses.Amplification; + break; + default: + effectmod = 10; + return effectmod; } effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; - if (effectmod < 10) { + if (effectmod < 10) effectmod = 10; - } - if (effectmod > effectmodcap) { + if (effectmod > effectmodcap) effectmod = effectmodcap; - } - Log.Out(Logs::Detail, Logs::Spells, "%s::GetInstrumentMod() spell=%d mod=%d modcap=%d\n", - GetName(), spell_id, effectmod, effectmodcap); + Log.Out(Logs::Detail, Logs::Spells, "%s::GetInstrumentMod() spell=%d mod=%d modcap=%d\n", GetName(), spell_id, + effectmod, effectmodcap); return effectmod; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 73d028e68..3a2c6e2c9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1494,7 +1494,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) for (int i = 0; i < max_slots; i++) { if (buffs[i].spellid != SPELL_UNKNOWN) { m_pp.buffs[i].spellid = buffs[i].spellid; - m_pp.buffs[i].bard_modifier = 10; + m_pp.buffs[i].bard_modifier = buffs[i].instrument_mod; m_pp.buffs[i].slotid = 2; m_pp.buffs[i].player_id = 0x2211; m_pp.buffs[i].level = buffs[i].casterlevel; diff --git a/zone/common.h b/zone/common.h index a7d9e2d99..b2e4d5ed5 100644 --- a/zone/common.h +++ b/zone/common.h @@ -202,6 +202,7 @@ struct Buffs_Struct { int32 caston_z; int32 ExtraDIChance; int16 RootBreakChance; //Not saved to dbase + uint32 instrument_mod; bool persistant_buff; bool client; //True if the caster is a client bool UpdateClient; diff --git a/zone/mob.h b/zone/mob.h index 0d412a666..579ec75a8 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -200,7 +200,7 @@ public: bool IsBeneficialAllowed(Mob *target); virtual int GetCasterLevel(uint16 spell_id); void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0, - uint8 WornType = 0, uint32 ticsremaining = 0, int buffslot = -1, + uint8 WornType = 0, uint32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10, 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); @@ -253,7 +253,7 @@ public: //Buff void BuffProcess(); - virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0); + virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr); void BuffFadeBySpellID(uint16 spell_id); void BuffFadeByEffect(int effectid, int skipslot = -1); void BuffFadeAll(); @@ -857,7 +857,7 @@ public: virtual uint32 GetAA(uint32 aa_id) const { return(0); } uint32 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(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/mob_ai.cpp b/zone/mob_ai.cpp index dd20d605c..355b6ba48 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2565,11 +2565,9 @@ void NPC::ApplyAISpellEffects(StatBonuses* newbon) if (!AI_HasSpellsEffects()) return; - for(int i=0; i < AIspellsEffects.size(); i++) - { - ApplySpellsBonuses(0, 0, newbon, 0, 0, 0,-1, - true, AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); - } + for (int i = 0; i < AIspellsEffects.size(); i++) + ApplySpellsBonuses(0, 0, newbon, 0, 0, 0, -1, 10, true, AIspellsEffects[i].spelleffectid, + AIspellsEffects[i].base, AIspellsEffects[i].limit, AIspellsEffects[i].max); return; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 8644ac918..19e83c4df 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -199,7 +199,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) continue; effect = spell.effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster ? caster : this); + effect_value = CalcSpellEffectValue(spell_id, i, caster_level, buffslot > -1 ? buffs[buffslot].instrument_mod : 10, caster ? caster : this); if(spell_id == SPELL_LAY_ON_HANDS && caster && caster->GetAA(aaImprovedLayOnHands)) effect_value = GetMaxHP(); @@ -3029,48 +3029,44 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) return true; } -int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, Mob *caster, int ticsremaining) +int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, uint32 instrument_mod, Mob *caster, + int ticsremaining) { int formula, base, max, effect_value; - if - ( - !IsValidSpell(spell_id) || - effect_id < 0 || - effect_id >= EFFECT_COUNT - ) + if (!IsValidSpell(spell_id) || effect_id < 0 || effect_id >= EFFECT_COUNT) return 0; formula = spells[spell_id].formula[effect_id]; base = spells[spell_id].base[effect_id]; max = spells[spell_id].max[effect_id]; - if(IsBlankSpellEffect(spell_id, effect_id)) + if (IsBlankSpellEffect(spell_id, effect_id)) return 0; effect_value = CalcSpellEffectValue_formula(formula, base, max, caster_level, spell_id, ticsremaining); - if(caster && IsBardSong(spell_id) && - (spells[spell_id].effectid[effect_id] != SE_AttackSpeed) && - (spells[spell_id].effectid[effect_id] != SE_AttackSpeed2) && - (spells[spell_id].effectid[effect_id] != SE_AttackSpeed3) && - (spells[spell_id].effectid[effect_id] != SE_Lull) && - (spells[spell_id].effectid[effect_id] != SE_ChangeFrenzyRad) && - (spells[spell_id].effectid[effect_id] != SE_Harmony) && - (spells[spell_id].effectid[effect_id] != SE_CurrentMana)&& - (spells[spell_id].effectid[effect_id] != SE_ManaRegen_v2)) - { + // this doesn't actually need to be a song to get mods, just the right skill + if (EQEmu::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 && + spells[spell_id].effectid[effect_id] != SE_Lull && + spells[spell_id].effectid[effect_id] != SE_ChangeFrenzyRad && + spells[spell_id].effectid[effect_id] != SE_Harmony && + spells[spell_id].effectid[effect_id] != SE_CurrentMana && + spells[spell_id].effectid[effect_id] != SE_ManaRegen_v2) { int oval = effect_value; - int mod = caster->GetInstrumentMod(spell_id); - mod = ApplySpellEffectiveness(caster, spell_id, mod, true); + 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); + 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); - return(effect_value); + return effect_value; } // generic formula calculations @@ -3365,7 +3361,7 @@ void Mob::BuffProcess() { if (buffs[buffs_i].spellid != SPELL_UNKNOWN) { - DoBuffTic(buffs[buffs_i].spellid, buffs_i, buffs[buffs_i].ticsremaining, buffs[buffs_i].casterlevel, entity_list.GetMob(buffs[buffs_i].casterid)); + DoBuffTic(buffs[buffs_i], buffs_i, entity_list.GetMob(buffs[buffs_i].casterid)); // If the Mob died during DoBuffTic, then the buff we are currently processing will have been removed if(buffs[buffs_i].spellid == SPELL_UNKNOWN) continue; @@ -3418,333 +3414,308 @@ void Mob::BuffProcess() } } -void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster) { +void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) +{ int effect, effect_value; - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(buff.spellid)) return; - const SPDat_Spell_Struct &spell = spells[spell_id]; + const SPDat_Spell_Struct &spell = spells[buff.spellid]; - if (spell_id == SPELL_UNKNOWN) - return; - - if(IsNPC()) - { + if (IsNPC()) { std::vector args; - args.push_back(&ticsremaining); - args.push_back(&caster_level); + args.push_back(&buff.ticsremaining); + args.push_back(&buff.casterlevel); args.push_back(&slot); - int i = parse->EventSpell(EVENT_SPELL_BUFF_TIC_NPC, CastToNPC(), nullptr, spell_id, caster ? caster->GetID() : 0, &args); - if(i != 0) { + int i = parse->EventSpell(EVENT_SPELL_BUFF_TIC_NPC, CastToNPC(), nullptr, buff.spellid, + caster ? caster->GetID() : 0, &args); + if (i != 0) { return; } - } - else - { + } else { std::vector args; - args.push_back(&ticsremaining); - args.push_back(&caster_level); + args.push_back(&buff.ticsremaining); + args.push_back(&buff.casterlevel); args.push_back(&slot); - int i = parse->EventSpell(EVENT_SPELL_BUFF_TIC_CLIENT, nullptr, CastToClient(), spell_id, caster ? caster->GetID() : 0, &args); - if(i != 0) { + int i = parse->EventSpell(EVENT_SPELL_BUFF_TIC_CLIENT, nullptr, CastToClient(), buff.spellid, + caster ? caster->GetID() : 0, &args); + if (i != 0) { return; } } // Check for non buff spell effects to fade // AE melee effects - if(IsClient()) + if (IsClient()) CastToClient()->CheckAAEffect(aaEffectRampage); - for (int i = 0; i < EFFECT_COUNT; i++) - { - if(IsBlankSpellEffect(spell_id, i)) + for (int i = 0; i < EFFECT_COUNT; i++) { + if (IsBlankSpellEffect(buff.spellid, i)) continue; effect = spell.effectid[i]; - //I copied the calculation into each case which needed it instead of - //doing it every time up here, since most buff effects dont need it + // I copied the calculation into each case which needed it instead of + // doing it every time up here, since most buff effects dont need it - switch(effect) - { - case SE_CurrentHP: - { - effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster, ticsremaining); - //Handle client cast DOTs here. - if (caster && effect_value < 0){ + switch (effect) { + case SE_CurrentHP: { + effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod, + caster, buff.ticsremaining); + // Handle client cast DOTs here. + if (caster && effect_value < 0) { - if (IsDetrimentalSpell(spell_id)){ - if (caster->IsClient()){ - if (!caster->CastToClient()->GetFeigned()) - AddToHateList(caster, -effect_value); - } - else if (!IsClient()) //Allow NPC's to generate hate if casted on other NPC's. + if (IsDetrimentalSpell(buff.spellid)) { + if (caster->IsClient()) { + if (!caster->CastToClient()->GetFeigned()) AddToHateList(caster, -effect_value); - } - - effect_value = caster->GetActDoTDamage(spell_id, effect_value, this); - - caster->ResourceTap(-effect_value, spell_id); - effect_value = -effect_value; - Damage(caster, effect_value, spell_id, spell.skill, false, i, true); - } else if(effect_value > 0) { - // Regen spell... - // handled with bonuses + } else if (!IsClient()) // Allow NPC's to generate hate if casted on other + // NPC's. + AddToHateList(caster, -effect_value); } - break; + + effect_value = caster->GetActDoTDamage(buff.spellid, effect_value, this); + + caster->ResourceTap(-effect_value, buff.spellid); + effect_value = -effect_value; + Damage(caster, effect_value, buff.spellid, spell.skill, false, i, true); + } else if (effect_value > 0) { + // Regen spell... + // handled with bonuses } - case SE_HealOverTime: - { - effect_value = CalcSpellEffectValue(spell_id, i, caster_level); - if(caster) - effect_value = caster->GetActSpellHealing(spell_id, effect_value); + break; + } + case SE_HealOverTime: { + effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod); + if (caster) + effect_value = caster->GetActSpellHealing(buff.spellid, effect_value); - HealDamage(effect_value, caster, spell_id); - //healing aggro would go here; removed for now + HealDamage(effect_value, caster, buff.spellid); + // healing aggro would go here; removed for now + break; + } + + case SE_CurrentEndurance: { + // Handled with bonuses + break; + } + + case SE_BardAEDot: { + effect_value = + CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod, caster); + + if ((!RuleB(Spells, PreNerfBardAEDoT) && IsMoving()) || invulnerable || + /*effect_value > 0 ||*/ DivineAura()) break; + + if (effect_value < 0) { + effect_value = -effect_value; + if (caster) { + if (caster->IsClient() && !caster->CastToClient()->GetFeigned()) { + AddToHateList(caster, effect_value); + } else if (!caster->IsClient()) + AddToHateList(caster, effect_value); + } + Damage(caster, effect_value, buff.spellid, spell.skill, false, i, true); + } else if (effect_value > 0) { + // healing spell... + HealDamage(effect_value, caster); + // healing aggro would go here; removed for now } + break; + } - case SE_CurrentEndurance: { - // Handled with bonuses - break; - } - - case SE_BardAEDot: - { - effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster); - - if ((!RuleB(Spells, PreNerfBardAEDoT) && IsMoving()) || invulnerable || /*effect_value > 0 ||*/ DivineAura()) - break; - - if(effect_value < 0) { - effect_value = -effect_value; - if(caster){ - if(caster->IsClient() && !caster->CastToClient()->GetFeigned()){ + case SE_Hate: { + effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod); + if (caster) { + if (effect_value > 0) { + if (caster) { + if (caster->IsClient() && !caster->CastToClient()->GetFeigned()) { AddToHateList(caster, effect_value); - } - else if(!caster->IsClient()) + } else if (!caster->IsClient()) AddToHateList(caster, effect_value); } - Damage(caster, effect_value, spell_id, spell.skill, false, i, true); - } else if(effect_value > 0) { - //healing spell... - HealDamage(effect_value, caster); - //healing aggro would go here; removed for now - } - break; - } - - case SE_Hate:{ - effect_value = CalcSpellEffectValue(spell_id, i, caster_level); - if(caster){ - if(effect_value > 0){ - if(caster){ - if(caster->IsClient() && !caster->CastToClient()->GetFeigned()){ - AddToHateList(caster, effect_value); - } - else if(!caster->IsClient()) - AddToHateList(caster, effect_value); - } - }else{ - int32 newhate = GetHateAmount(caster) + effect_value; - if (newhate < 1) { - SetHateAmountOnEnt(caster,1); - } else { - SetHateAmountOnEnt(caster,newhate); - } + } else { + int32 newhate = GetHateAmount(caster) + effect_value; + if (newhate < 1) { + SetHateAmountOnEnt(caster, 1); + } else { + SetHateAmountOnEnt(caster, newhate); } } + } + break; + } + + case SE_WipeHateList: { + if (IsMezSpell(buff.spellid)) break; + + int wipechance = spells[buff.spellid].base[i]; + int bonus = 0; + + if (caster) { + bonus = caster->spellbonuses.IncreaseChanceMemwipe + + caster->itembonuses.IncreaseChanceMemwipe + + caster->aabonuses.IncreaseChanceMemwipe; } - case SE_WipeHateList: - { - if (IsMezSpell(spell_id)) + wipechance += wipechance * bonus / 100; + + if (zone->random.Roll(wipechance)) { + if (IsAIControlled()) { + WipeHateList(); + } + Message(13, "Your mind fogs. Who are my friends? Who are my enemies?... it was all so " + "clear a moment ago..."); + } + break; + } + + case SE_Charm: { + if (!caster || !PassCharismaCheck(caster, buff.spellid)) { + BuffFadeByEffect(SE_Charm); + } + + break; + } + + case SE_Root: { + /* Root formula derived from extensive personal live parses - Kayen + ROOT has a 70% chance to do a resist check to break. + */ + + if (zone->random.Roll(RuleI(Spells, RootBreakCheckChance))) { + float resist_check = + ResistSpell(spells[buff.spellid].resisttype, buff.spellid, caster, 0, 0, 0, 0, true); + + if (resist_check == 100) break; - - int wipechance = spells[spell_id].base[i]; - int bonus = 0; - - if (caster){ - bonus = caster->spellbonuses.IncreaseChanceMemwipe + - caster->itembonuses.IncreaseChanceMemwipe + - caster->aabonuses.IncreaseChanceMemwipe; - } - - wipechance += wipechance*bonus/100; - - if(zone->random.Roll(wipechance)) - { - if(IsAIControlled()) - { - WipeHateList(); - } - Message(13, "Your mind fogs. Who are my friends? Who are my enemies?... it was all so clear a moment ago..."); - } - break; + else if (!TryFadeEffect(slot)) + BuffFadeBySlot(slot); } - case SE_Charm: { - if (!caster || !PassCharismaCheck(caster, spell_id)) { - BuffFadeByEffect(SE_Charm); - } + break; + } - break; - } + case SE_Fear: { + if (zone->random.Roll(RuleI(Spells, FearBreakCheckChance))) { + float resist_check = ResistSpell(spells[buff.spellid].resisttype, buff.spellid, caster); - case SE_Root: { - /* Root formula derived from extensive personal live parses - Kayen - ROOT has a 70% chance to do a resist check to break. - */ - - if (zone->random.Roll(RuleI(Spells, RootBreakCheckChance))) { - float resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, 0,0,0,0,true); - - if(resist_check == 100) - break; - else - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - - break; - } - - case SE_Fear: - { - if (zone->random.Roll(RuleI(Spells, FearBreakCheckChance))) { - float resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster); - - if(resist_check == 100) - break; - else - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - - break; - } - - case SE_Hunger: { - // this procedure gets called 7 times for every once that the stamina update occurs so we add 1/7 of the subtraction. - // It's far from perfect, but works without any unnecessary buff checks to bog down the server. - if(IsClient()) { - CastToClient()->m_pp.hunger_level += 5; - CastToClient()->m_pp.thirst_level += 5; - } - break; - } - case SE_Invisibility: - case SE_InvisVsAnimals: - case SE_InvisVsUndead: - { - if(ticsremaining > 3) - { - if(!IsBardSong(spell_id)) - { - double break_chance = 2.0; - if(caster) - { - break_chance -= (2 * (((double)caster->GetSkill(SkillDivination) + ((double)caster->GetLevel() * 3.0)) / 650.0)); - } - else - { - break_chance -= (2 * (((double)GetSkill(SkillDivination) + ((double)GetLevel() * 3.0)) / 650.0)); - } - - if(zone->random.Real(0.0, 100.0) < break_chance) - { - BuffModifyDurationBySpellID(spell_id, 3); - } - } - } - } - case SE_Invisibility2: - case SE_InvisVsUndead2: - { - if(ticsremaining <= 3 && ticsremaining > 1) - { - Message_StringID(MT_Spells, INVIS_BEGIN_BREAK); - } - break; - } - case SE_InterruptCasting: - { - if(IsCasting()) - { - if(zone->random.Roll(spells[spell_id].base[i])) - { - InterruptSpell(); - } - } - break; - } - // These effects always trigger when they fade. - case SE_CastOnFadeEffect: - case SE_CastOnFadeEffectNPC: - case SE_CastOnFadeEffectAlways: - { - if (ticsremaining == 1) - { - SpellOnTarget(spells[spell_id].base[i], this); - } - break; - } - case SE_LocateCorpse: - { - // This is handled by the client prior to SoD. - - if(IsClient() && (CastToClient()->GetClientVersionBit() & 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){ - - int distance = ((int(GetX()) - buffs[slot].caston_x) * (int(GetX()) - buffs[slot].caston_x)) + - ((int(GetY()) - buffs[slot].caston_y) * (int(GetY()) - buffs[slot].caston_y)) + - ((int(GetZ()) - buffs[slot].caston_z) * (int(GetZ()) - buffs[slot].caston_z)); - - if (distance > (spells[spell_id].base[i] * spells[spell_id].base[i])){ - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot , true); - } + if (resist_check == 100) break; - } + else if (!TryFadeEffect(slot)) + BuffFadeBySlot(slot); } - case SE_AddHateOverTimePct: - { - if (IsNPC()){ - uint32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100; - if (new_hate <= 0) - new_hate = 1; + break; + } - CastToNPC()->SetHateAmountOnEnt(caster, new_hate); + case SE_Hunger: { + // this procedure gets called 7 times for every once that the stamina update occurs so we add + // 1/7 of the subtraction. + // It's far from perfect, but works without any unnecessary buff checks to bog down the server. + if (IsClient()) { + CastToClient()->m_pp.hunger_level += 5; + CastToClient()->m_pp.thirst_level += 5; + } + break; + } + case SE_Invisibility: + case SE_InvisVsAnimals: + case SE_InvisVsUndead: { + if (buff.ticsremaining > 3) { + if (!IsBardSong(buff.spellid)) { + double break_chance = 2.0; + if (caster) { + break_chance -= (2 * (((double)caster->GetSkill(SkillDivination) + + ((double)caster->GetLevel() * 3.0)) / + 650.0)); + } else { + break_chance -= + (2 * + (((double)GetSkill(SkillDivination) + ((double)GetLevel() * 3.0)) / + 650.0)); + } + + if (zone->random.Real(0.0, 100.0) < break_chance) { + BuffModifyDurationBySpellID(buff.spellid, 3); + } + } + } + } + case SE_Invisibility2: + case SE_InvisVsUndead2: { + if (buff.ticsremaining <= 3 && buff.ticsremaining > 1) { + Message_StringID(MT_Spells, INVIS_BEGIN_BREAK); + } + break; + } + case SE_InterruptCasting: { + if (IsCasting()) { + if (zone->random.Roll(spells[buff.spellid].base[i])) { + InterruptSpell(); + } + } + break; + } + // These effects always trigger when they fade. + case SE_CastOnFadeEffect: + case SE_CastOnFadeEffectNPC: + case SE_CastOnFadeEffectAlways: { + if (buff.ticsremaining == 1) { + SpellOnTarget(spells[buff.spellid].base[i], this); + } + break; + } + case SE_LocateCorpse: { + // This is handled by the client prior to SoD. + + if (IsClient() && (CastToClient()->GetClientVersionBit() & 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) { + + int distance = + ((int(GetX()) - buff.caston_x) * (int(GetX()) - buff.caston_x)) + + ((int(GetY()) - buff.caston_y) * (int(GetY()) - buff.caston_y)) + + ((int(GetZ()) - buff.caston_z) * (int(GetZ()) - buff.caston_z)); + + if (distance > (spells[buff.spellid].base[i] * spells[buff.spellid].base[i])) { + + if (!TryFadeEffect(slot)) + BuffFadeBySlot(slot, true); } break; } + } + case SE_AddHateOverTimePct: { + if (IsNPC()) { + uint32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100; + if (new_hate <= 0) + new_hate = 1; - default: - { - // do we need to do anyting here? + CastToNPC()->SetHateAmountOnEnt(caster, new_hate); } + break; + } + + default: { + // do we need to do anyting here? + } } } } diff --git a/zone/spells.cpp b/zone/spells.cpp index fc5856284..525470303 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3189,6 +3189,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid buffs[emptyslot].dot_rune = 0; buffs[emptyslot].ExtraDIChance = 0; buffs[emptyslot].RootBreakChance = 0; + buffs[emptyslot].instrument_mod = caster ? caster->GetInstrumentMod(spell_id) : 10; if (level_override > 0) { buffs[emptyslot].UpdateClient = true; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ef790e9d8..8369652b7 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -196,7 +196,7 @@ bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct zone_data->time_type = atoi(row[30]); //not in the DB yet: - zone_data->gravity = atof(row[56]); + zone_data->gravity = atof(row[56]); Log.Out(Logs::General, Logs::Debug, "Zone Gravity is %f", zone_data->gravity); allow_mercs = true; @@ -248,7 +248,7 @@ void ZoneDatabase::UpdateRespawnTime(uint32 spawn2_id, uint16 instance_id, uint3 if(time_left == 0) { std::string query = StringFormat("DELETE FROM `respawn_times` WHERE `id` = %u AND `instance_id` = %u", spawn2_id, instance_id); - QueryDatabase(query); + QueryDatabase(query); return; } @@ -258,14 +258,14 @@ void ZoneDatabase::UpdateRespawnTime(uint32 spawn2_id, uint16 instance_id, uint3 "start, " "duration, " "instance_id) " - "VALUES " + "VALUES " "(%u, " "%u, " "%u, " "%u)", - spawn2_id, + spawn2_id, current_time, - time_left, + time_left, instance_id ); QueryDatabase(query); @@ -1054,8 +1054,8 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str for (i = 0; i < MAX_PP_LANGUAGE; ++i) pp->languages[i] = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]); + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); if (i < MAX_PP_LANGUAGE){ pp->languages[i] = atoi(row[1]); } @@ -1102,14 +1102,14 @@ bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct "FROM " "`character_skills` " "WHERE `id` = %u ORDER BY `skill_id`", character_id); - auto results = database.QueryDatabase(query); + auto results = database.QueryDatabase(query); int i = 0; /* Initialize Skill */ for (i = 0; i < MAX_PP_SKILL; ++i) pp->skills[i] = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]); + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); if (i < MAX_PP_SKILL) pp->skills[i] = atoi(row[1]); } @@ -1259,7 +1259,7 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %u LIMIT 2", character_id); - auto results = database.QueryDatabase(query); + auto results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { @@ -1705,8 +1705,8 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru pp->careerRadCrystals, pp->currentEbonCrystals, pp->careerEbonCrystals); - auto results = database.QueryDatabase(query); - Log.Out(Logs::General, Logs::None, "Saving Currency for character ID: %i, done", character_id); + auto results = database.QueryDatabase(query); + Log.Out(Logs::General, Logs::None, "Saving Currency for character ID: %i, done", character_id); return true; } @@ -1802,7 +1802,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load std::string where_condition = ""; if (bulk_load){ - Log.Out(Logs::General, Logs::Debug, "Performing bulk NPC Types load"); + Log.Out(Logs::General, Logs::Debug, "Performing bulk NPC Types load"); where_condition = StringFormat( "INNER JOIN spawnentry ON npc_types.id = spawnentry.npcID " "INNER JOIN spawn2 ON spawnentry.spawngroupID = spawn2.spawngroupID " @@ -1910,7 +1910,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load "npc_types.handtexture, " "npc_types.legtexture, " "npc_types.feettexture " - "FROM npc_types %s", + "FROM npc_types %s", where_condition.c_str() ); @@ -2369,7 +2369,7 @@ bool ZoneDatabase::LoadCurrentMerc(Client *client) { if(!results.Success()) return false; - + if(results.RowCount() == 0) return false; @@ -2980,45 +2980,48 @@ void ZoneDatabase::SaveBuffs(Client *client) { query = StringFormat("INSERT INTO `character_buffs` (character_id, slot_id, spell_id, " "caster_level, caster_name, ticsremaining, counters, numhits, melee_rune, " - "magic_rune, persistent, dot_rune, caston_x, caston_y, caston_z, ExtraDIChance) " + "magic_rune, persistent, dot_rune, caston_x, caston_y, caston_z, ExtraDIChance, " + "instrument_mod) " "VALUES('%u', '%u', '%u', '%u', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', " - "'%i', '%i', '%i', '%i')", client->CharacterID(), index, buffs[index].spellid, + "'%i', '%i', '%i', '%i', '%i')", client->CharacterID(), index, buffs[index].spellid, buffs[index].casterlevel, buffs[index].caster_name, buffs[index].ticsremaining, buffs[index].counters, buffs[index].numhits, buffs[index].melee_rune, buffs[index].magic_rune, buffs[index].persistant_buff, buffs[index].dot_rune, buffs[index].caston_x, buffs[index].caston_y, buffs[index].caston_z, - buffs[index].ExtraDIChance); + buffs[index].ExtraDIChance, buffs[index].instrument_mod); QueryDatabase(query); } } -void ZoneDatabase::LoadBuffs(Client *client) { +void ZoneDatabase::LoadBuffs(Client *client) +{ Buffs_Struct *buffs = client->GetBuffs(); uint32 max_slots = client->GetMaxBuffSlots(); - for(int index = 0; index < max_slots; ++index) + for (int index = 0; index < max_slots; ++index) buffs[index].spellid = SPELL_UNKNOWN; std::string query = StringFormat("SELECT spell_id, slot_id, caster_level, caster_name, ticsremaining, " - "counters, numhits, melee_rune, magic_rune, persistent, dot_rune, " - "caston_x, caston_y, caston_z, ExtraDIChance " - "FROM `character_buffs` WHERE `character_id` = '%u'", client->CharacterID()); - auto results = QueryDatabase(query); - if (!results.Success()) { + "counters, numhits, melee_rune, magic_rune, persistent, dot_rune, " + "caston_x, caston_y, caston_z, ExtraDIChance, instrument_mod " + "FROM `character_buffs` WHERE `character_id` = '%u'", + client->CharacterID()); + auto results = QueryDatabase(query); + if (!results.Success()) { return; - } + } - for (auto row = results.begin(); row != results.end(); ++row) { - uint32 slot_id = atoul(row[1]); - if(slot_id >= client->GetMaxBuffSlots()) + for (auto row = results.begin(); row != results.end(); ++row) { + uint32 slot_id = atoul(row[1]); + if (slot_id >= client->GetMaxBuffSlots()) continue; - uint32 spell_id = atoul(row[0]); - if(!IsValidSpell(spell_id)) - continue; + uint32 spell_id = atoul(row[0]); + if (!IsValidSpell(spell_id)) + continue; - Client *caster = entity_list.GetClientByName(row[3]); + Client *caster = entity_list.GetClientByName(row[3]); uint32 caster_level = atoi(row[2]); uint32 ticsremaining = atoul(row[4]); uint32 counters = atoul(row[5]); @@ -3031,53 +3034,54 @@ void ZoneDatabase::LoadBuffs(Client *client) { int32 caston_y = atoul(row[12]); int32 caston_z = atoul(row[13]); int32 ExtraDIChance = atoul(row[14]); + uint32 instrument_mod = atoul(row[15]); buffs[slot_id].spellid = spell_id; - buffs[slot_id].casterlevel = caster_level; + buffs[slot_id].casterlevel = caster_level; - if(caster) { - buffs[slot_id].casterid = caster->GetID(); - strcpy(buffs[slot_id].caster_name, caster->GetName()); - buffs[slot_id].client = true; - } else { - buffs[slot_id].casterid = 0; + if (caster) { + buffs[slot_id].casterid = caster->GetID(); + strcpy(buffs[slot_id].caster_name, caster->GetName()); + buffs[slot_id].client = true; + } else { + buffs[slot_id].casterid = 0; strcpy(buffs[slot_id].caster_name, ""); buffs[slot_id].client = false; - } + } - buffs[slot_id].ticsremaining = ticsremaining; + buffs[slot_id].ticsremaining = ticsremaining; buffs[slot_id].counters = counters; buffs[slot_id].numhits = numhits; buffs[slot_id].melee_rune = melee_rune; buffs[slot_id].magic_rune = magic_rune; - buffs[slot_id].persistant_buff = persistent? true: false; + buffs[slot_id].persistant_buff = persistent ? true : false; buffs[slot_id].dot_rune = dot_rune; buffs[slot_id].caston_x = caston_x; - buffs[slot_id].caston_y = caston_y; - buffs[slot_id].caston_z = caston_z; - buffs[slot_id].ExtraDIChance = ExtraDIChance; - buffs[slot_id].RootBreakChance = 0; - buffs[slot_id].UpdateClient = false; - - } + buffs[slot_id].caston_y = caston_y; + buffs[slot_id].caston_z = caston_z; + buffs[slot_id].ExtraDIChance = ExtraDIChance; + buffs[slot_id].RootBreakChance = 0; + buffs[slot_id].UpdateClient = false; + buffs[slot_id].instrument_mod = instrument_mod; + } max_slots = client->GetMaxBuffSlots(); - for(int index = 0; index < max_slots; ++index) { - if(!IsValidSpell(buffs[index].spellid)) + for (int index = 0; index < max_slots; ++index) { + if (!IsValidSpell(buffs[index].spellid)) continue; - for(int effectIndex = 0; effectIndex < 12; ++effectIndex) { + for (int effectIndex = 0; effectIndex < 12; ++effectIndex) { if (spells[buffs[index].spellid].effectid[effectIndex] == SE_Charm) { - buffs[index].spellid = SPELL_UNKNOWN; - break; - } + buffs[index].spellid = SPELL_UNKNOWN; + break; + } - if (spells[buffs[index].spellid].effectid[effectIndex] == SE_Illusion) { - if(buffs[index].persistant_buff) - break; + if (spells[buffs[index].spellid].effectid[effectIndex] == SE_Illusion) { + if (buffs[index].persistant_buff) + break; - buffs[index].spellid = SPELL_UNKNOWN; + buffs[index].spellid = SPELL_UNKNOWN; break; } } @@ -3389,7 +3393,7 @@ bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, in "ON DUPLICATE KEY UPDATE `current_value`=%i,`temp`=%i", char_id, faction_id, value, temp, value, temp); auto results = QueryDatabase(query); - + if (!results.Success()) return false; else @@ -3534,7 +3538,7 @@ uint32 ZoneDatabase::GetCharacterCorpseDecayTimer(uint32 corpse_db_id){ auto results = QueryDatabase(query); auto row = results.begin(); if (results.Success() && results.RowsAffected() != 0) - return atoul(row[0]); + return atoul(row[0]); return 0; } @@ -3621,8 +3625,8 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui "`wc_6` = %u, " "`wc_7` = %u, " "`wc_8` = %u, " - "`wc_9` = %u ", - EscapeString(charname).c_str(), + "`wc_9` = %u ", + EscapeString(charname).c_str(), zoneid, instanceid, charid, @@ -3675,21 +3679,21 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui corpse_items_query = StringFormat("REPLACE INTO `character_corpse_items` \n" " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", - last_insert_id, + last_insert_id, dbpc->items[i].equip_slot, - dbpc->items[i].item_id, - dbpc->items[i].charges, - dbpc->items[i].aug_1, - dbpc->items[i].aug_2, - dbpc->items[i].aug_3, - dbpc->items[i].aug_4, + dbpc->items[i].item_id, + dbpc->items[i].charges, + dbpc->items[i].aug_1, + dbpc->items[i].aug_2, + dbpc->items[i].aug_3, + dbpc->items[i].aug_4, dbpc->items[i].aug_5, dbpc->items[i].aug_6, dbpc->items[i].attuned ); first_entry = 1; } - else{ + else{ corpse_items_query = corpse_items_query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", last_insert_id, dbpc->items[i].equip_slot, From ea44b4b3b19090125837133df8837e28b47f3ebf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 21 May 2015 17:25:59 -0400 Subject: [PATCH 086/846] Fix manifest --- utils/sql/db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 8e01d0420..537f8009b 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -331,7 +331,7 @@ 9075|2015_02_02_logsys_packet_logs_with_dump.sql|SELECT * FROM `logsys_categories` WHERE `log_category_description` LIKE 'Packet: Server -> Client With Dump'|empty| 9076|2015_02_04_average_coin.sql|SHOW COLUMNS FROM `loottable` WHERE Field = 'avgcoin'|contains|smallint 9077|2015_02_12_zone_gravity.sql|SHOW COLUMNS FROM `zone` LIKE 'gravity'|empty| -9078|2015_05_20_BuffInstrumentMod.sql|SHOW COLUMNS FROM `character_buffs` LIKE `instrument_mod`|empty| +9078|2015_05_20_BuffInstrumentMod.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'instrument_mod'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 9cbda0f81b85a9fd0d7d202cb1461867029b77fe Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 21 May 2015 18:15:34 -0400 Subject: [PATCH 087/846] Unlink Tiger Claw from other monk skills for RoF2+ Tiger Claw has its own reuse now, which the client expects pTimerCombatAbility2 should be able to be used if they do something similar for other classes. --- common/ptimer.h | 3 +- zone/special_attacks.cpp | 111 ++++++++++++++++++++------------------- 2 files changed, 60 insertions(+), 54 deletions(-) diff --git a/common/ptimer.h b/common/ptimer.h index d12b6779d..8a559a148 100644 --- a/common/ptimer.h +++ b/common/ptimer.h @@ -39,7 +39,8 @@ enum { //values for pTimerType pTimerDisciplineReuseStart = 14, pTimerDisciplineReuseEnd = 24, pTimerCombatAbility = 25, - pTimerBeggingPickPocket = 26, + pTimerCombatAbility2 = 26, // RoF2+ Tiger Claw is unlinked from other monk skills, generic in case other classes ever need it + pTimerBeggingPickPocket = 27, pTimerLayHands = 87, //these IDs are used by client too pTimerHarmTouch = 89, //so dont change them diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index faae0e3b1..0f0a110cd 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -95,7 +95,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, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, bool HitChance, bool CanAvoid) { //this really should go through the same code as normal melee damage to //pick up all the special behavior there @@ -181,6 +181,11 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { 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 + if (GetClientVersion() >= ClientVersion::RoF2 && ca_atk->m_skill == SkillTigerClaw) + timer = pTimerCombatAbility2; /* Check to see if actually have skill */ if (!MaxSkill(static_cast(ca_atk->m_skill))) @@ -218,7 +223,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { if(!CombatRange(GetTarget())) return; - if(!p_timers.Expired(&database, pTimerCombatAbility, false)) { + if(!p_timers.Expired(&database, timer, false)) { Message(13,"Ability recovery time not yet met."); return; } @@ -268,7 +273,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { DoSpecialAttackDamage(GetTarget(), SkillBash, dmg, 1, ht, ReuseTime); if(ReuseTime > 0) { - p_timers.Start(pTimerCombatAbility, ReuseTime); + p_timers.Start(timer, ReuseTime); } } return; @@ -304,7 +309,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { } if(ReuseTime > 0) { - p_timers.Start(pTimerCombatAbility, ReuseTime); + p_timers.Start(timer, ReuseTime); } return; } @@ -390,7 +395,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { ReuseTime = (ReuseTime*HasteMod)/100; if(ReuseTime > 0){ - p_timers.Start(pTimerCombatAbility, ReuseTime); + p_timers.Start(timer, ReuseTime); } } @@ -558,7 +563,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { if (level > 54) { // Check for double attack with main hand assuming maxed DA Skill (MS) - if(IsClient() && CastToClient()->CheckDoubleAttack(false)) + if(IsClient() && CastToClient()->CheckDoubleAttack(false)) if(other->GetHP() > 0) RogueBackstab(other,true, ReuseTime); @@ -650,10 +655,10 @@ 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); - + if (Assassinate_Dmg) { ndamage = Assassinate_Dmg; entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); @@ -797,26 +802,26 @@ 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 (!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 { Log.Out(Logs::Detail, Logs::Combat, "Endless Quiver prevented ammo consumption."); } - CheckIncreaseSkill(SkillArchery, GetTarget(), -15); + CheckIncreaseSkill(SkillArchery, GetTarget(), -15); CommonBreakInvisible(); } -void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, +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) { - - if ((other == nullptr || - ((IsClient() && CastToClient()->dead) || - (other->IsClient() && other->CastToClient()->dead)) || - HasDied() || + + if ((other == nullptr || + ((IsClient() && CastToClient()->dead) || + (other->IsClient() && other->CastToClient()->dead)) || + HasDied() || (!IsAttackAllowed(other)) || - (other->GetInvul() || + (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) { return; @@ -841,12 +846,12 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite LaunchProjectile = true; else{ /* - Item sync check on projectile landing. + 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 (!RangeWeapon && !Ammo && range_id && ammo_id){ ProjectileImpact = true; @@ -858,8 +863,8 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite _RangeWeapon = CastToClient()->m_inv[MainRange]; if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id) - RangeWeapon = _RangeWeapon; - + RangeWeapon = _RangeWeapon; + _Ammo = CastToClient()->m_inv[AmmoSlot]; if (_Ammo && _Ammo->GetItem() && _Ammo->GetItem()->ID == ammo_id) Ammo = _Ammo; @@ -985,7 +990,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite other->AddToHateList(this, hate, 0, false); other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery); - + //Skill Proc Success if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()){ if (ReuseTime) @@ -1047,10 +1052,10 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes ProjectileAtk[slot].origin_x = GetX(); ProjectileAtk[slot].origin_y = GetY(); ProjectileAtk[slot].origin_z = GetZ(); - + if (RangeWeapon && RangeWeapon->GetItem()) ProjectileAtk[slot].ranged_id = RangeWeapon->GetItem()->ID; - + if (Ammo && Ammo->GetItem()) ProjectileAtk[slot].ammo_id = Ammo->GetItem()->ID; @@ -1085,7 +1090,7 @@ void Mob::ProjectileAttack() disable = false; 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()){ @@ -1109,7 +1114,7 @@ void Mob::ProjectileAttack() else CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg,0, static_cast(ProjectileAtk[i].skill)); } - + else { if (ProjectileAtk[i].skill == SkillArchery) @@ -1120,7 +1125,7 @@ void Mob::ProjectileAttack() SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true); } } - + ProjectileAtk[i].increment = 0; ProjectileAtk[i].target_id = 0; ProjectileAtk[i].wpn_dmg = 0; @@ -1180,7 +1185,7 @@ float Mob::GetRangeDistTargetSizeMod(Mob* other) mod = 42.0f + (5.8f * (tsize - 15.0f)); else mod = 75.0f; - + return (mod + 2.0f); //Add 2.0f as buffer to prevent any chance of failures, client enforce range check regardless. } @@ -1210,7 +1215,7 @@ void NPC::RangedAttack(Mob* other) float min_range = static_cast(RuleI(Combat, MinRangedAttackDist)); float max_range = 250; // needs to be longer than 200(most spells) - + if (sa_max_range) max_range = static_cast(sa_max_range); @@ -1242,12 +1247,12 @@ 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) { - - if ((other == nullptr || - (other->HasDied())) || - HasDied() || + + if ((other == nullptr || + (other->HasDied())) || + HasDied() || (!IsAttackAllowed(other)) || - (other->GetInvul() || + (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE))) { return; @@ -1268,7 +1273,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha ammo = GetAmmoIDfile(); ProjectileAnimation(other, 0,false,speed,0,0,0,ammo,skillInUse); - + if (RuleB(Combat, ProjectileDmgOnImpact)) { TryProjectileAttack(other, nullptr, skillInUse, damage_mod, nullptr, nullptr, 0, speed); @@ -1276,7 +1281,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha } } - if (!chance_mod) + if (!chance_mod) chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2); if (!other->CheckHitChance(this, skillInUse, MainRange, chance_mod)) @@ -1298,11 +1303,11 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha if (!damage_mod) damage_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3);//Damage modifier - TotalDmg += TotalDmg * damage_mod / 100; + TotalDmg += TotalDmg * damage_mod / 100; other->AvoidDamage(this, TotalDmg, false); other->MeleeMitigation(this, TotalDmg, MinDmg); - + if (TotalDmg > 0) CommonOutgoingHitSuccess(other, TotalDmg, skillInUse); else if (TotalDmg < -4) @@ -1432,18 +1437,18 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 //consume ammo DeleteItemInInventory(ammo_slot, 1, true); - CheckIncreaseSkill(SkillThrowing, GetTarget()); + CheckIncreaseSkill(SkillThrowing, GetTarget()); CommonBreakInvisible(); } 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) { - if ((other == nullptr || - ((IsClient() && CastToClient()->dead) || - (other->IsClient() && other->CastToClient()->dead)) || - HasDied() || + if ((other == nullptr || + ((IsClient() && CastToClient()->dead) || + (other->IsClient() && other->CastToClient()->dead)) || + HasDied() || (!IsAttackAllowed(other)) || - (other->GetInvul() || + (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) { return; @@ -1511,7 +1516,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite return; } } - else + else WDmg = weapon_damage; if (focus) //From FcBaseEffects @@ -1535,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, false); //CanRiposte=false - Can not riposte throw attacks. - + other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0) CommonOutgoingHitSuccess(other, TotalDmg, SkillThrowing); @@ -1620,7 +1625,7 @@ void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skil 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, SkillUseTypes skillInUse) { if (!to) return; @@ -2092,7 +2097,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) } ReuseTime = ReuseTime / HasteMod; - if(ReuseTime > 0 && !IsRiposte){ + if(ReuseTime > 0 && !IsRiposte){ p_timers.Start(pTimerCombatAbility, ReuseTime); } } @@ -2270,7 +2275,7 @@ float Mob::GetSpecialProcChances(uint16 hand) if (RuleB(Combat, AdjustSpecialProcPerMinute)) { ProcChance = (static_cast(weapon_speed) * - RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f); + RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f); ProcBonus += static_cast(mydex/35) + static_cast(itembonuses.HeroicDEX / 25); ProcChance += ProcChance * ProcBonus / 100.0f; } else { @@ -2363,7 +2368,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int Hand = MainPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; - if(weapon_damage > 0){ + if(weapon_damage > 0){ if (focus) //From FcBaseEffects weapon_damage += weapon_damage*focus/100; @@ -2376,7 +2381,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 Item_Struct*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2411,7 +2416,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes } else { other->AvoidDamage(this, damage, CanRiposte); other->MeleeMitigation(this, damage, min_hit); - if(damage > 0) + if(damage > 0) CommonOutgoingHitSuccess(other, damage, skillinuse); } @@ -2449,7 +2454,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if (CanSkillProc && HasSkillProcs()) TrySkillProc(other, skillinuse, ReuseTime); - + if (CanSkillProc && (damage > 0) && HasSkillProcSuccess()) TrySkillProc(other, skillinuse, ReuseTime, true); } From 351e63ae729accccf7d831e3f12dff3d69031002 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 22 May 2015 19:15:51 -0400 Subject: [PATCH 088/846] Possible fix for some 'random' character select crashes --- changelog.txt | 3 +++ common/patches/rof.cpp | 3 ++- common/patches/rof2.cpp | 3 ++- common/patches/sod.cpp | 3 ++- common/patches/sof.cpp | 3 ++- common/patches/uf.cpp | 3 ++- 6 files changed, 13 insertions(+), 5 deletions(-) diff --git a/changelog.txt b/changelog.txt index 204d08d7b..6c5d695ab 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/22/2015 == +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) Still need to have procs/doom effects to inherit the instrument mods from their source buff/whatever diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index bfb47492a..89ad7db7f 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2949,8 +2949,9 @@ namespace RoF eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; strcpy(eq_cse->Name, emu_cse->Name); - eq_ptr += strlen(eq_cse->Name); + eq_ptr += strlen(emu_cse->Name); eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse->Name[0] = '\0'; eq_cse->Class = emu_cse->Class; eq_cse->Race = emu_cse->Race; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index da9fa311a..75c4c7836 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3038,8 +3038,9 @@ namespace RoF2 eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; strcpy(eq_cse->Name, emu_cse->Name); - eq_ptr += strlen(eq_cse->Name); + eq_ptr += strlen(emu_cse->Name); eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse->Name[0] = '\0'; eq_cse->Class = emu_cse->Class; eq_cse->Race = emu_cse->Race; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index a4765939d..8e730cfb9 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1969,8 +1969,9 @@ namespace SoD eq_cse->Gender = emu_cse->Gender; strcpy(eq_cse->Name, emu_cse->Name); - eq_ptr += strlen(eq_cse->Name); + eq_ptr += strlen(emu_cse->Name); eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse->Name[0] = '\0'; eq_cse->Beard = emu_cse->Beard; eq_cse->HairColor = emu_cse->HairColor; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 186515b3b..a677cede3 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1628,8 +1628,9 @@ namespace SoF eq_cse->Gender = emu_cse->Gender; strcpy(eq_cse->Name, emu_cse->Name); - eq_ptr += strlen(eq_cse->Name); + eq_ptr += strlen(emu_cse->Name); eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse->Name[0] = '\0'; eq_cse->Beard = emu_cse->Beard; eq_cse->HairColor = emu_cse->HairColor; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 58131bd35..4177e4f81 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2260,8 +2260,9 @@ namespace UF eq_cse->Gender = emu_cse->Gender; strcpy(eq_cse->Name, emu_cse->Name); - eq_ptr += strlen(eq_cse->Name); + eq_ptr += strlen(emu_cse->Name); eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse->Name[0] = '\0'; eq_cse->Beard = emu_cse->Beard; eq_cse->HairColor = emu_cse->HairColor; From 8aadc3632002696a9feada53d582e2e61b517ed7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 May 2015 02:20:36 -0400 Subject: [PATCH 089/846] Rework buff duration formulas These are derived from the client SE_IllusionPresistence will also set the duration to 10k tics like live --- common/eq_packet_structs.h | 18 +-- common/patches/rof2_structs.h | 10 +- common/patches/rof_structs.h | 10 +- common/patches/sod_structs.h | 4 +- common/patches/sof_structs.h | 4 +- common/patches/titanium_structs.h | 4 +- common/patches/uf_structs.h | 8 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../git/required/2015_05_23_BuffDurations.sql | 2 + zone/bonuses.cpp | 2 +- zone/effects.cpp | 24 ++-- zone/mob.h | 2 +- zone/spell_effects.cpp | 4 +- zone/spells.cpp | 129 +++++++++--------- zone/zonedb.cpp | 12 +- 16 files changed, 116 insertions(+), 120 deletions(-) create mode 100644 utils/sql/git/required/2015_05_23_BuffDurations.sql diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index f91107a14..e5ab88e57 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -553,7 +553,7 @@ struct SpellBuff_Struct /*002*/ uint8 bard_modifier; /*003*/ uint8 effect; //not real /*004*/ uint32 spellid; -/*008*/ uint32 duration; +/*008*/ int32 duration; /*012*/ uint32 counters; /*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages /*020*/ @@ -566,7 +566,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 num_hits; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 slotid; @@ -584,14 +584,8 @@ struct BuffRemoveRequest_Struct struct PetBuff_Struct { /*000*/ uint32 petid; -/*004*/ uint32 spellid[BUFF_COUNT]; -/*104*/ uint32 unknown700; -/*108*/ uint32 unknown701; -/*112*/ uint32 unknown702; -/*116*/ uint32 unknown703; -/*120*/ uint32 unknown704; -/*124*/ uint32 ticsremaining[BUFF_COUNT]; -/*224*/ uchar unknown705[20]; +/*004*/ uint32 spellid[BUFF_COUNT+5]; +/*124*/ int32 ticsremaining[BUFF_COUNT+5]; /*244*/ uint32 buffcount; }; @@ -4036,7 +4030,7 @@ struct MarkNPC_Struct struct InspectBuffs_Struct { /*000*/ uint32 spell_id[BUFF_COUNT]; -/*100*/ uint32 tics_remaining[BUFF_COUNT]; +/*100*/ int32 tics_remaining[BUFF_COUNT]; }; struct RaidGeneral_Struct { @@ -4737,7 +4731,7 @@ struct BuffIconEntry_Struct { uint32 buff_slot; uint32 spell_id; - uint32 tics_remaining; + int32 tics_remaining; uint32 num_hits; }; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 4aac9e7de..a572a3834 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -687,7 +687,7 @@ struct SpellBuff_Struct /*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*009*/ uint32 unknown016; /*013*/ uint8 bard_modifier; -/*014*/ uint32 duration; +/*014*/ int32 duration; /*018*/ uint8 level; /*019*/ uint32 spellid; /*023*/ uint32 counters; @@ -703,7 +703,7 @@ struct SpellBuff_Struct_Old /*003*/ uint8 effect; // not real /*004*/ float unknown004; // Seen 1 for no buff /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*024*/ uint32 counters; @@ -720,7 +720,7 @@ struct SpellBuffFade_Struct_Live { /*007*/ uint8 unknown007; /*008*/ float unknown008; /*012*/ uint32 spellid; -/*016*/ uint32 duration; +/*016*/ int32 duration; /*020*/ uint32 playerId; // Global player ID? /*024*/ uint32 num_hits; /*028*/ uint8 unknown0028[64]; @@ -736,7 +736,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 num_hits; /*020*/ uint32 unknown020; // Global player ID? /*024*/ uint32 playerId; // Player id who cast the buff @@ -2473,7 +2473,7 @@ struct GroupFollow_Struct { // Live Follow Struct struct InspectBuffs_Struct { /*000*/ uint32 spell_id[BUFF_COUNT]; -/*168*/ uint32 tics_remaining[BUFF_COUNT]; +/*168*/ int32 tics_remaining[BUFF_COUNT]; }; struct LFG_Struct { diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 8fcfdb21d..7db21597c 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -676,7 +676,7 @@ struct SpellBuff_Struct /*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*009*/ uint32 unknown016; /*013*/ uint8 bard_modifier; -/*014*/ uint32 duration; +/*014*/ int32 duration; /*018*/ uint8 level; /*019*/ uint32 spellid; /*023*/ uint32 counters; @@ -692,7 +692,7 @@ struct SpellBuff_Struct_Old /*003*/ uint8 effect; // not real /*004*/ float unknown004; // Seen 1 for no buff /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*024*/ uint32 counters; @@ -709,7 +709,7 @@ struct SpellBuffFade_Struct_Live { /*007*/ uint8 unknown007; /*008*/ float unknown008; /*012*/ uint32 spellid; -/*016*/ uint32 duration; +/*016*/ int32 duration; /*020*/ uint32 playerId; // Global player ID? /*024*/ uint32 num_hits; /*028*/ uint8 unknown0028[64]; @@ -725,7 +725,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 num_hits; /*020*/ uint32 unknown020; // Global player ID? /*024*/ uint32 playerId; // Player id who cast the buff @@ -2501,7 +2501,7 @@ struct GroupFollow_Struct { // Live Follow Struct struct InspectBuffs_Struct { /*000*/ uint32 spell_id[BUFF_COUNT]; -/*168*/ uint32 tics_remaining[BUFF_COUNT]; +/*168*/ int32 tics_remaining[BUFF_COUNT]; }; struct LFG_Struct { diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 584318a71..2b7178daf 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -547,7 +547,7 @@ struct SpellBuff_Struct /*002*/ uint8 bard_modifier; /*003*/ uint8 effect; //not real /*004*/ uint32 spellid; -/*008*/ uint32 duration; +/*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 @@ -564,7 +564,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 playerId; // Player id who cast the buff diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 23404e051..f7ad59011 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -526,7 +526,7 @@ struct SpellBuff_Struct /*002*/ uint8 bard_modifier; /*003*/ uint8 effect; //not real /*004*/ uint32 spellid; -/*008*/ uint32 duration; +/*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 @@ -543,7 +543,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 playerId; // Player id who cast the buff diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 89a3634fd..bdca057d0 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -445,7 +445,7 @@ struct SpellBuff_Struct /*002*/ uint8 bard_modifier; /*003*/ uint8 effect; //not real /*004*/ uint32 spellid; -/*008*/ uint32 duration; +/*008*/ int32 duration; /*012*/ uint32 counters; /*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages }; @@ -457,7 +457,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 slotid; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 66cc58d1d..79363d68a 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -551,7 +551,7 @@ struct SpellBuff_Struct /*003*/ uint8 effect; // not real /*004*/ uint32 unknown004; // Seen 1 for no buff /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*024*/ uint32 counters; @@ -568,7 +568,7 @@ struct SpellBuffFade_Struct_Underfoot { /*007*/ uint8 unknown7; /*008*/ float unknown008; /*012*/ uint32 spellid; -/*016*/ uint32 duration; +/*016*/ int32 duration; /*020*/ uint32 num_hits; /*024*/ uint32 playerId; // Global player ID? /*028*/ uint32 unknown020; @@ -585,7 +585,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 unknown020; // Global player ID? /*024*/ uint32 playerId; // Player id who cast the buff @@ -2188,7 +2188,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*/ uint32 tics_remaining[BUFF_COUNT]; +/*120*/ int32 tics_remaining[BUFF_COUNT]; /*220*/ uint32 filler220[5]; // BUFF_COUNT is really 30... }; diff --git a/common/version.h b/common/version.h index 9ce7b285c..fd0f433f4 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 9078 +#define CURRENT_BINARY_DATABASE_VERSION 9079 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 537f8009b..00d7b9609 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -332,6 +332,7 @@ 9076|2015_02_04_average_coin.sql|SHOW COLUMNS FROM `loottable` WHERE Field = 'avgcoin'|contains|smallint 9077|2015_02_12_zone_gravity.sql|SHOW COLUMNS FROM `zone` LIKE 'gravity'|empty| 9078|2015_05_20_BuffInstrumentMod.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'instrument_mod'|empty| +9079|2015_05_23_BuffDurations.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'ticsremaining'|contains|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/2015_05_23_BuffDurations.sql b/utils/sql/git/required/2015_05_23_BuffDurations.sql new file mode 100644 index 000000000..5f03039a6 --- /dev/null +++ b/utils/sql/git/required/2015_05_23_BuffDurations.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_buffs` CHANGE COLUMN `ticsremaining` `ticsremaining` INT(11) SIGNED NOT NULL; +ALTER TABLE `merc_buffs` CHANGE COLUMN `TicsRemaining` `TicsRemaining` INT(11) SIGNED NOT NULL DEFAULT 0; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index ab4afeab4..5dd7440f6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1473,7 +1473,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) } void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *new_bonus, uint16 casterId, - uint8 WornType, uint32 ticsremaining, int buffslot, int instrument_mod, + uint8 WornType, int32 ticsremaining, int buffslot, int instrument_mod, bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) { int i, effect_value, base2, max, effectid; diff --git a/zone/effects.cpp b/zone/effects.cpp index 8a42b8e09..0f9dcfca1 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -89,7 +89,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { if (IsClient() && GetClass() == WIZARD) ratio += RuleI(Spells, WizCritRatio); //Default is zero - + if (Critical){ value = value_BaseEffect*ratio/100; @@ -172,7 +172,7 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100; value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100; value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100; - extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + + extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) + GetFocusEffect(focusFcDamageAmt, spell_id); @@ -219,11 +219,11 @@ int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_s total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time; if (total_cast_time > 0 && total_cast_time <= 2500) - extra_spell_amt = extra_spell_amt*25/100; - else if (total_cast_time > 2500 && total_cast_time < 7000) - extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000; - else - extra_spell_amt = extra_spell_amt * total_cast_time / 7000; + extra_spell_amt = extra_spell_amt*25/100; + else if (total_cast_time > 2500 && total_cast_time < 7000) + extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000; + else + extra_spell_amt = extra_spell_amt * total_cast_time / 7000; if(extra_spell_amt*2 < base_spell_dmg) return 0; @@ -281,7 +281,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (Critical) { entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetName(), itoa(value)); - + if (IsClient()) Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value)); } @@ -413,6 +413,10 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) { + if ((aabonuses.IllusionPersistence || spellbonuses.IllusionPersistence || itembonuses.IllusionPersistence) && + IsEffectInSpell(spell_id, SE_Illusion)) + return 10000; // ~16h + if (spells[spell_id].not_extendable) return duration; @@ -771,7 +775,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } else { - if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) + if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); if (!spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); @@ -859,7 +863,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff if (!center->CheckLosFN(curmob)) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... - // See notes in AESpell() above for more info. + // See notes in AESpell() above for more info. if (caster->IsAttackAllowed(curmob, true)) continue; if (caster->CheckAggro(curmob)) diff --git a/zone/mob.h b/zone/mob.h index 579ec75a8..bf7e2030a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -200,7 +200,7 @@ public: bool IsBeneficialAllowed(Mob *target); virtual int GetCasterLevel(uint16 spell_id); void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0, - uint8 WornType = 0, uint32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10, + uint8 WornType = 0, int32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10, 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); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 19e83c4df..59b154835 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -83,7 +83,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(c_override) { int durat = CalcBuffDuration(caster, this, spell_id, caster_level); - if(durat > 0) + if(durat) // negatives are perma buffs { buffslot = AddBuff(caster, spell_id, durat, caster_level); if(buffslot == -1) // stacking failure @@ -3366,7 +3366,7 @@ void Mob::BuffProcess() if(buffs[buffs_i].spellid == SPELL_UNKNOWN) continue; - if(spells[buffs[buffs_i].spellid].buffdurationformula != DF_Permanent) + if(buffs[buffs_i].ticsremaining > 0) // perma buffs will either be -1 or -4 { if(!zone->BuffTimersSuspended() || !IsSuspendableSpell(buffs[buffs_i].spellid)) { diff --git a/zone/spells.cpp b/zone/spells.cpp index 525470303..d0f60ea47 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2630,80 +2630,75 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Casting level %d, formula %d, base_duration %d: result %d", spell_id, castlevel, formula, duration, res); - return(res); + return res; } // the generic formula calculations int CalcBuffDuration_formula(int level, int formula, int duration) { - int i; // temp variable + int temp; - switch(formula) - { - case 0: // not a buff - return 0; - - case 1: - i = (int)ceil(level / 2.0f); - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 2: - i = (int)ceil(level / 5.0f * 3); - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 3: - i = level * 30; - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 4: // only used by 'LowerElement' - return ((duration != 0) ? duration : 50); - - case 5: - i = duration; - // 0 value results in a 3 tick spell, else its between 1-3 ticks. - return i < 3 ? (i < 1 ? 3 : i) : 3; - - case 6: - i = (int)ceil(level / 2.0f); - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 7: - i = level; - return (duration == 0) ? (i < 1 ? 1 : i) : duration; - - case 8: - i = level + 10; - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 9: - i = level * 2 + 10; - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 10: - i = level * 3 + 10; - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 11: - return std::min((level + 3) * 30, duration); - - case 12: - case 13: - case 14: - case 15: // Don't know what the real formula for this should be. Used by Skinspikes potion. - return duration; - - case 50: // Permanent. Cancelled by casting/combat for perm invis, non-lev zones for lev, curing poison/curse counters, etc. - return 72000; // 5 days until better method to make permanent - - //case 51: // Permanent. Cancelled when out of range of aura. Placeholder until appropriate duration identified. - - case 3600: - return duration ? duration : 3600; - - default: - Log.Out(Logs::General, Logs::None, "CalcBuffDuration_formula: unknown formula %d", formula); + switch (formula) { + case 1: + temp = level > 3 ? level / 2 : 1; + break; + case 2: + temp = level > 3 ? level / 2 + 5 : 6; + break; + case 3: + temp = 30 * level; + break; + case 4: // only used by 'LowerElement' + temp = 50; + break; + case 5: + temp = 2; + break; + case 6: + temp = level / 2 + 2; + break; + case 7: + temp = level; + break; + case 8: + temp = level + 10; + break; + case 9: + temp = 2 * level + 10; + break; + case 10: + temp = 3 * level + 10; + break; + case 11: + temp = 30 * (level + 3); + break; + case 12: + temp = level > 7 ? level / 4 : 1; + break; + case 13: + temp = 4 * level + 10; + break; + case 14: + temp = 5 * (level + 2); + break; + case 15: + temp = 10 * (level + 10); + break; + case 50: // Permanent. Cancelled by casting/combat for perm invis, non-lev zones for lev, curing poison/curse + // counters, etc. + return -1; + case 51: // Permanent. Cancelled when out of range of aura. + return -4; + default: + // the client function has another bool parameter that if true returns -2 -- unsure + if (formula < 200) return 0; + temp = formula; + break; } + if (duration && duration < temp) + temp = duration; + return temp; } // helper function for AddBuff to determine stacking @@ -3066,7 +3061,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if (duration == 0) { duration = CalcBuffDuration(caster, this, spell_id); - if (caster) + if (caster && duration > 0) // negatives are perma buffs duration = caster->GetActSpellDuration(spell_id, duration); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8369652b7..0313b8064 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2504,7 +2504,7 @@ void ZoneDatabase::SaveMercBuffs(Merc *merc) { "TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, " "CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, " "caston_x, Persistent, caston_y, caston_z, ExtraDIChance) " - "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %i, %u, %i, %i, %i);", + "VALUES (%u, %u, %u, %u, %u, %d, %u, %u, %u, %u, %u, %u, %u, %i, %u, %i, %i, %i);", merc->GetMercID(), buffs[buffCount].spellid, buffs[buffCount].casterlevel, spells[buffs[buffCount].spellid].buffdurationformula, buffs[buffCount].ticsremaining, CalculatePoisonCounters(buffs[buffCount].spellid) > 0 ? buffs[buffCount].counters : 0, @@ -2982,7 +2982,7 @@ void ZoneDatabase::SaveBuffs(Client *client) { "caster_level, caster_name, ticsremaining, counters, numhits, melee_rune, " "magic_rune, persistent, dot_rune, caston_x, caston_y, caston_z, ExtraDIChance, " "instrument_mod) " - "VALUES('%u', '%u', '%u', '%u', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', " + "VALUES('%u', '%u', '%u', '%u', '%s', '%d', '%u', '%u', '%u', '%u', '%u', '%u', " "'%i', '%i', '%i', '%i', '%i')", client->CharacterID(), index, buffs[index].spellid, buffs[index].casterlevel, buffs[index].caster_name, buffs[index].ticsremaining, buffs[index].counters, buffs[index].numhits, buffs[index].melee_rune, @@ -3023,7 +3023,7 @@ void ZoneDatabase::LoadBuffs(Client *client) Client *caster = entity_list.GetClientByName(row[3]); uint32 caster_level = atoi(row[2]); - uint32 ticsremaining = atoul(row[4]); + int32 ticsremaining = atoi(row[4]); uint32 counters = atoul(row[5]); uint32 numhits = atoul(row[6]); uint32 melee_rune = atoul(row[7]); @@ -3128,12 +3128,12 @@ void ZoneDatabase::SavePetInfo(Client *client) query = StringFormat("INSERT INTO `character_pet_buffs` " "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " "`ticsremaining`, `counters`) " - "VALUES (%u, %u, %u, %u, %u, %u, %d)", + "VALUES (%u, %u, %u, %u, %u, %d, %d)", client->CharacterID(), pet, index, petinfo->Buffs[index].spellid, petinfo->Buffs[index].level, petinfo->Buffs[index].duration, petinfo->Buffs[index].counters); else - query += StringFormat(", (%u, %u, %u, %u, %u, %u, %d)", + query += StringFormat(", (%u, %u, %u, %u, %u, %d, %d)", client->CharacterID(), pet, index, petinfo->Buffs[index].spellid, petinfo->Buffs[index].level, petinfo->Buffs[index].duration, petinfo->Buffs[index].counters); @@ -3238,7 +3238,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) { uint32 caster_level = atoi(row[3]); int caster_id = 0; // The castername field is currently unused - uint32 ticsremaining = atoul(row[5]); + int32 ticsremaining = atoi(row[5]); uint32 counters = atoul(row[6]); pi->Buffs[slot_id].spellid = spell_id; From 00721f4a9646d7b826299270b0267620f0b8b106 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 May 2015 17:14:08 -0400 Subject: [PATCH 090/846] Fix pet instrument mod issue --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2015_05_23_PetBuffInstrumentMod.sql | 1 + zone/pets.cpp | 3 +- zone/zonedb.cpp | 135 +++++++++--------- 5 files changed, 75 insertions(+), 67 deletions(-) create mode 100644 utils/sql/git/required/2015_05_23_PetBuffInstrumentMod.sql diff --git a/common/version.h b/common/version.h index fd0f433f4..062afdecd 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 9079 +#define CURRENT_BINARY_DATABASE_VERSION 9080 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 00d7b9609..954abe263 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -333,6 +333,7 @@ 9077|2015_02_12_zone_gravity.sql|SHOW COLUMNS FROM `zone` LIKE 'gravity'|empty| 9078|2015_05_20_BuffInstrumentMod.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'instrument_mod'|empty| 9079|2015_05_23_BuffDurations.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'ticsremaining'|contains|unsigned| +9080|2015_05_23_PetBuffInstrumentMod.sql|SHOW COLUMNS FROM `character_pet_buffs` LIKE 'instrument_mod'|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/2015_05_23_PetBuffInstrumentMod.sql b/utils/sql/git/required/2015_05_23_PetBuffInstrumentMod.sql new file mode 100644 index 000000000..40cc453dc --- /dev/null +++ b/utils/sql/git/required/2015_05_23_PetBuffInstrumentMod.sql @@ -0,0 +1 @@ +ALTER TABLE `character_pet_buffs` ADD COLUMN `instrument_mod` tinyint UNSIGNED DEFAULT 10 NOT NULL; diff --git a/zone/pets.cpp b/zone/pets.cpp index 5a6a0be9f..a504a05e9 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -426,7 +426,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, entity_list.AddNPC(npc, true, true); SetPetID(npc->GetID()); // We need to handle PetType 5 (petHatelist), add the current target to the hatelist of the pet - + if (record.petcontrol == petTargetLock) { @@ -588,6 +588,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { buffs[i].casterid = 0; buffs[i].counters = pet_buffs[i].counters; buffs[i].numhits = spells[pet_buffs[i].spellid].numhits; + buffs[i].instrument_mod = pet_buffs[i].bard_modifier; } else { buffs[i].spellid = SPELL_UNKNOWN; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 0313b8064..e81a66308 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3127,16 +3127,16 @@ void ZoneDatabase::SavePetInfo(Client *client) if (query.length() == 0) query = StringFormat("INSERT INTO `character_pet_buffs` " "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " - "`ticsremaining`, `counters`) " - "VALUES (%u, %u, %u, %u, %u, %d, %d)", + "`ticsremaining`, `counters`, `instrument_mod`) " + "VALUES (%u, %u, %u, %u, %u, %d, %d, %u)", client->CharacterID(), pet, index, petinfo->Buffs[index].spellid, petinfo->Buffs[index].level, petinfo->Buffs[index].duration, - petinfo->Buffs[index].counters); + petinfo->Buffs[index].counters, petinfo->Buffs[index].bard_modifier); else - query += StringFormat(", (%u, %u, %u, %u, %u, %d, %d)", + query += StringFormat(", (%u, %u, %u, %u, %u, %d, %d, %u)", client->CharacterID(), pet, index, petinfo->Buffs[index].spellid, petinfo->Buffs[index].level, petinfo->Buffs[index].duration, - petinfo->Buffs[index].counters); + petinfo->Buffs[index].counters, petinfo->Buffs[index].bard_modifier); } database.QueryDatabase(query); query.clear(); @@ -3174,7 +3174,8 @@ void ZoneDatabase::UpdateItemRecastTimestamps(uint32 char_id, uint32 recast_type QueryDatabase(query); } -void ZoneDatabase::LoadPetInfo(Client *client) { +void ZoneDatabase::LoadPetInfo(Client *client) +{ // Load current pet and suspended pet PetInfo *petinfo = client->GetPetInfo(0); @@ -3183,17 +3184,18 @@ void ZoneDatabase::LoadPetInfo(Client *client) { memset(petinfo, 0, sizeof(PetInfo)); memset(suspended, 0, sizeof(PetInfo)); - std::string query = StringFormat("SELECT `pet`, `petname`, `petpower`, `spell_id`, " - "`hp`, `mana`, `size` FROM `character_pet_info` " - "WHERE `char_id` = %u", client->CharacterID()); - auto results = database.QueryDatabase(query); - if(!results.Success()) { + std::string query = StringFormat("SELECT `pet`, `petname`, `petpower`, `spell_id`, " + "`hp`, `mana`, `size` FROM `character_pet_info` " + "WHERE `char_id` = %u", + client->CharacterID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) { return; } - PetInfo *pi; + PetInfo *pi; for (auto row = results.begin(); row != results.end(); ++row) { - uint16 pet = atoi(row[0]); + uint16 pet = atoi(row[0]); if (pet == 0) pi = petinfo; @@ -3202,7 +3204,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) { else continue; - strncpy(pi->Name,row[1],64); + strncpy(pi->Name, row[1], 64); pi->petpower = atoi(row[2]); pi->SpellID = atoi(row[3]); pi->HP = atoul(row[4]); @@ -3210,56 +3212,60 @@ void ZoneDatabase::LoadPetInfo(Client *client) { pi->size = atof(row[6]); } - query = StringFormat("SELECT `pet`, `slot`, `spell_id`, `caster_level`, `castername`, " - "`ticsremaining`, `counters` FROM `character_pet_buffs` " - "WHERE `char_id` = %u", client->CharacterID()); - results = QueryDatabase(query); - if (!results.Success()) { - return; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - uint16 pet = atoi(row[0]); - if (pet == 0) - pi = petinfo; - else if (pet == 1) - pi = suspended; - else - continue; - - uint32 slot_id = atoul(row[1]); - if(slot_id >= RuleI(Spells, MaxTotalSlotsPET)) - continue; - - uint32 spell_id = atoul(row[2]); - if(!IsValidSpell(spell_id)) - continue; - - uint32 caster_level = atoi(row[3]); - int caster_id = 0; - // The castername field is currently unused - int32 ticsremaining = atoi(row[5]); - uint32 counters = atoul(row[6]); - - 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].duration = ticsremaining; - pi->Buffs[slot_id].counters = counters; - } - - query = StringFormat("SELECT `pet`, `slot`, `item_id` " - "FROM `character_pet_inventory` " - "WHERE `char_id`=%u",client->CharacterID()); - results = database.QueryDatabase(query); - if (!results.Success()) { + query = StringFormat("SELECT `pet`, `slot`, `spell_id`, `caster_level`, `castername`, " + "`ticsremaining`, `counters`, `instrument_mod` FROM `character_pet_buffs` " + "WHERE `char_id` = %u", + client->CharacterID()); + results = QueryDatabase(query); + if (!results.Success()) { return; } - for(auto row = results.begin(); row != results.end(); ++row) { - uint16 pet = atoi(row[0]); + for (auto row = results.begin(); row != results.end(); ++row) { + uint16 pet = atoi(row[0]); + if (pet == 0) + pi = petinfo; + else if (pet == 1) + pi = suspended; + else + continue; + + uint32 slot_id = atoul(row[1]); + if (slot_id >= RuleI(Spells, MaxTotalSlotsPET)) + continue; + + uint32 spell_id = atoul(row[2]); + if (!IsValidSpell(spell_id)) + continue; + + uint32 caster_level = atoi(row[3]); + int caster_id = 0; + // The castername field is currently unused + int32 ticsremaining = atoi(row[5]); + uint32 counters = atoul(row[6]); + uint8 bard_mod = atoul(row[7]); + + 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].duration = ticsremaining; + pi->Buffs[slot_id].counters = counters; + pi->Buffs[slot_id].bard_modifier = bard_mod; + } + + query = StringFormat("SELECT `pet`, `slot`, `item_id` " + "FROM `character_pet_inventory` " + "WHERE `char_id`=%u", + client->CharacterID()); + results = database.QueryDatabase(query); + if (!results.Success()) { + return; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + uint16 pet = atoi(row[0]); if (pet == 0) pi = petinfo; else if (pet == 1) @@ -3269,11 +3275,10 @@ void ZoneDatabase::LoadPetInfo(Client *client) { int slot = atoi(row[1]); if (slot < EmuConstants::EQUIPMENT_BEGIN || slot > EmuConstants::EQUIPMENT_END) - continue; - - pi->Items[slot] = atoul(row[2]); - } + continue; + pi->Items[slot] = atoul(row[2]); + } } bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id) { From a46b1ac18b3243296b27105c454dd9eb3bfea77a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 May 2015 17:36:05 -0400 Subject: [PATCH 091/846] Need to actually copy the bard mod too! --- zone/pets.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/pets.cpp b/zone/pets.cpp index a504a05e9..908b756d4 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -555,6 +555,7 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) { pet_buffs[i].level = buffs[i].casterlevel; pet_buffs[i].effect = 10; pet_buffs[i].counters = buffs[i].counters; + pet_buffs[i].bard_modifier = buffs[i].instrument_mod; } else { pet_buffs[i].spellid = SPELL_UNKNOWN; From 70048eb6e111af1b13d4bf98e18a7a59b2521a46 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 May 2015 17:45:51 -0400 Subject: [PATCH 092/846] SE_IllusionPersistence affects self only --- zone/effects.cpp | 4 ---- zone/spell_effects.cpp | 5 +++-- zone/spells.cpp | 4 ++++ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 0f9dcfca1..493de9fa7 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -413,10 +413,6 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) { - if ((aabonuses.IllusionPersistence || spellbonuses.IllusionPersistence || itembonuses.IllusionPersistence) && - IsEffectInSpell(spell_id, SE_Illusion)) - return 10000; // ~16h - if (spells[spell_id].not_extendable) return duration; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 59b154835..5fcee64cb 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1441,8 +1441,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) for(int x = EmuConstants::MATERIAL_BEGIN; x <= EmuConstants::MATERIAL_TINT_END; x++) SendWearChange(x); - if(caster && (caster->spellbonuses.IllusionPersistence || caster->aabonuses.IllusionPersistence - || caster->itembonuses.IllusionPersistence)) + if (caster == this && + (spellbonuses.IllusionPersistence || aabonuses.IllusionPersistence || + itembonuses.IllusionPersistence)) buffs[buffslot].persistant_buff = 1; else buffs[buffslot].persistant_buff = 0; diff --git a/zone/spells.cpp b/zone/spells.cpp index d0f60ea47..d8699d068 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2624,6 +2624,10 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste castlevel = caster_level_override; int res = CalcBuffDuration_formula(castlevel, formula, duration); + if (caster == target && (target->aabonuses.IllusionPersistence || target->spellbonuses.IllusionPersistence || + target->itembonuses.IllusionPersistence) && + IsEffectInSpell(spell_id, SE_Illusion)) + res = 10000; // ~16h override res = mod_buff_duration(res, caster, target, spell_id); From 7041db7480b6acfe5056ea3dd679db28ed6c1171 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 23 May 2015 15:50:35 -0700 Subject: [PATCH 093/846] Adding dbstr_us.txt support to client files --- client_files/export/main.cpp | 36 ++++++++++++ client_files/import/main.cpp | 56 ++++++++++++++++++- .../sql/git/required/2015_05_23_dbstr_us.sql | 6 ++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2015_05_23_dbstr_us.sql diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 865fbd6d8..7ad7bf3e1 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -32,6 +32,7 @@ EQEmuLogSys Log; void ExportSpells(SharedDatabase *db); void ExportSkillCaps(SharedDatabase *db); void ExportBaseData(SharedDatabase *db); +void ExportDBStrings(SharedDatabase *db); int main(int argc, char **argv) { RegisterExecutablePlatform(ExePlatformClientExport); @@ -62,6 +63,7 @@ int main(int argc, char **argv) { ExportSpells(&database); ExportSkillCaps(&database); ExportBaseData(&database); + ExportDBStrings(&database); Log.CloseFileLogs(); @@ -200,3 +202,37 @@ void ExportBaseData(SharedDatabase *db) { fclose(f); } +void ExportDBStrings(SharedDatabase *db) { + Log.Out(Logs::General, Logs::Status, "Exporting DB Strings..."); + + FILE *f = fopen("export/dbstr_us.txt", "w"); + if(!f) { + Log.Out(Logs::General, Logs::Error, "Unable to open export/dbstr_us.txt to write, skipping."); + return; + } + + fprintf(f, "Major^Minor^String(New)\n"); + const std::string query = "SELECT * FROM db_str ORDER BY id, type"; + auto results = db->QueryDatabase(query); + if(results.Success()) { + for(auto row = results.begin(); row != results.end(); ++row) { + std::string line; + unsigned int fields = results.ColumnCount(); + for(unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) { + if(rowIndex != 0) + line.push_back('^'); + + if(row[rowIndex] != nullptr) { + line += row[rowIndex]; + } + } + + fprintf(f, "%s\n", line.c_str()); + } + } + else { + } + + fclose(f); +} + diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index 3a2f4154f..72ae6fd5d 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -30,6 +30,7 @@ EQEmuLogSys Log; void ImportSpells(SharedDatabase *db); void ImportSkillCaps(SharedDatabase *db); void ImportBaseData(SharedDatabase *db); +void ImportDBStrings(SharedDatabase *db); int main(int argc, char **argv) { RegisterExecutablePlatform(ExePlatformClientImport); @@ -59,6 +60,7 @@ int main(int argc, char **argv) { ImportSpells(&database); ImportSkillCaps(&database); ImportBaseData(&database); + ImportDBStrings(&database); Log.CloseFileLogs(); @@ -202,7 +204,6 @@ void ImportSkillCaps(SharedDatabase *db) { continue; } - int class_id, skill_id, level, cap; class_id = atoi(split[0].c_str()); skill_id = atoi(split[1].c_str()); @@ -262,3 +263,56 @@ void ImportBaseData(SharedDatabase *db) { fclose(f); } + +void ImportDBStrings(SharedDatabase *db) { + Log.Out(Logs::General, Logs::Status, "Importing DB Strings..."); + + FILE *f = fopen("import/dbstr_us.txt", "r"); + if(!f) { + Log.Out(Logs::General, Logs::Error, "Unable to open import/dbstr_us.txt to read, skipping."); + return; + } + + std::string delete_sql = "DELETE FROM db_str"; + db->QueryDatabase(delete_sql); + + char buffer[2048]; + bool first = true; + while(fgets(buffer, 2048, f)) { + if(first) { + first = false; + continue; + } + + for(int i = 0; i < 2048; ++i) { + if(buffer[i] == '\n') { + buffer[i] = 0; + break; + } + } + + auto split = SplitString(buffer, '^'); + + if(split.size() < 2) { + continue; + } + + std::string sql; + int id, type; + std::string value; + + id = atoi(split[0].c_str()); + type = atoi(split[1].c_str()); + + if(split.size() >= 3) { + value = ::EscapeString(split[2]); + } + + sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')", + id, type, value.c_str()); + + db->QueryDatabase(sql); + } + + fclose(f); +} diff --git a/utils/sql/git/required/2015_05_23_dbstr_us.sql b/utils/sql/git/required/2015_05_23_dbstr_us.sql new file mode 100644 index 000000000..d4e789b83 --- /dev/null +++ b/utils/sql/git/required/2015_05_23_dbstr_us.sql @@ -0,0 +1,6 @@ +CREATE TABLE `db_str` ( + `id` INT(10) NOT NULL, + `type` INT(10) NOT NULL, + `value` TEXT NOT NULL, + PRIMARY KEY (`id`, `type`) +);; From 7d61934ce640c4e0c68f71ef877be18affbfcc07 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 23 May 2015 15:52:42 -0700 Subject: [PATCH 094/846] Add db manifest for dbstr_us.txt stuff --- utils/sql/db_update_manifest.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 954abe263..34330f041 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -334,6 +334,7 @@ 9078|2015_05_20_BuffInstrumentMod.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'instrument_mod'|empty| 9079|2015_05_23_BuffDurations.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'ticsremaining'|contains|unsigned| 9080|2015_05_23_PetBuffInstrumentMod.sql|SHOW COLUMNS FROM `character_pet_buffs` LIKE 'instrument_mod'|empty| +9081|2015_05_23_dbstr_us.sql|SHOW TABLES LIKE 'db_str'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From a882397eb632fcffde75941df2e5ce2c5d7fed46 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 23 May 2015 15:53:56 -0700 Subject: [PATCH 095/846] errant semi-colon, doesn't matter but still --- utils/sql/git/required/2015_05_23_dbstr_us.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/required/2015_05_23_dbstr_us.sql b/utils/sql/git/required/2015_05_23_dbstr_us.sql index d4e789b83..1eba0afa6 100644 --- a/utils/sql/git/required/2015_05_23_dbstr_us.sql +++ b/utils/sql/git/required/2015_05_23_dbstr_us.sql @@ -3,4 +3,4 @@ CREATE TABLE `db_str` ( `type` INT(10) NOT NULL, `value` TEXT NOT NULL, PRIMARY KEY (`id`, `type`) -);; +); From ec8e7139ec8286e7b9616409b148962af3b11bd9 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 23 May 2015 15:54:33 -0700 Subject: [PATCH 096/846] errant else statements --- client_files/export/main.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 7ad7bf3e1..708d48456 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -196,7 +196,6 @@ void ExportBaseData(SharedDatabase *db) { fprintf(f, "%s\n", line.c_str()); } - } else { } fclose(f); @@ -230,8 +229,6 @@ void ExportDBStrings(SharedDatabase *db) { fprintf(f, "%s\n", line.c_str()); } } - else { - } fclose(f); } From 8922c72452b03c184654e8c88832f4e226ccd4bd Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 23 May 2015 18:59:03 -0400 Subject: [PATCH 097/846] Added a name block memset to the server character select code and a few comments to the OP_CharInfo encodes --- common/patches/rof.cpp | 6 +++--- common/patches/rof2.cpp | 6 +++--- common/patches/sod.cpp | 6 +++--- common/patches/sof.cpp | 6 +++--- common/patches/uf.cpp | 6 +++--- world/worlddb.cpp | 1 + 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 89ad7db7f..9f9f58ab2 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2946,12 +2946,12 @@ namespace RoF for (int counter = 0; counter < character_count; ++counter) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address strcpy(eq_cse->Name, emu_cse->Name); eq_ptr += strlen(emu_cse->Name); - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; - eq_cse->Name[0] = '\0'; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset) + eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)] eq_cse->Class = emu_cse->Class; eq_cse->Race = emu_cse->Race; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 75c4c7836..708c5a6a9 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3035,12 +3035,12 @@ namespace RoF2 for (int counter = 0; counter < character_count; ++counter) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address strcpy(eq_cse->Name, emu_cse->Name); eq_ptr += strlen(emu_cse->Name); - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; - eq_cse->Name[0] = '\0'; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset) + eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)] eq_cse->Class = emu_cse->Class; eq_cse->Race = emu_cse->Race; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 8e730cfb9..0a8073131 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1962,7 +1962,7 @@ namespace SoD for (int counter = 0; counter < character_count; ++counter) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address eq_cse->Level = emu_cse->Level; eq_cse->HairStyle = emu_cse->HairStyle; @@ -1970,8 +1970,8 @@ namespace SoD strcpy(eq_cse->Name, emu_cse->Name); eq_ptr += strlen(emu_cse->Name); - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; - eq_cse->Name[0] = '\0'; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset) + eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)] eq_cse->Beard = emu_cse->Beard; eq_cse->HairColor = emu_cse->HairColor; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index a677cede3..f0e8a2dbe 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1621,7 +1621,7 @@ namespace SoF for (int counter = 0; counter < character_count; ++counter) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address eq_cse->Level = emu_cse->Level; eq_cse->HairStyle = emu_cse->HairStyle; @@ -1629,8 +1629,8 @@ namespace SoF strcpy(eq_cse->Name, emu_cse->Name); eq_ptr += strlen(emu_cse->Name); - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; - eq_cse->Name[0] = '\0'; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset) + eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)] eq_cse->Beard = emu_cse->Beard; eq_cse->HairColor = emu_cse->HairColor; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 4177e4f81..e963312e2 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2253,7 +2253,7 @@ namespace UF for (int counter = 0; counter < character_count; ++counter) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address eq_cse->Level = emu_cse->Level; eq_cse->HairStyle = emu_cse->HairStyle; @@ -2261,8 +2261,8 @@ namespace UF strcpy(eq_cse->Name, emu_cse->Name); eq_ptr += strlen(emu_cse->Name); - eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; - eq_cse->Name[0] = '\0'; + eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset) + eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)] eq_cse->Beard = emu_cse->Beard; eq_cse->HairColor = emu_cse->HairColor; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 4b2a75ac6..b09758888 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -105,6 +105,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou memset(&pp, 0, sizeof(PlayerProfile_Struct)); /* Fill CharacterSelectEntry_Struct */ + memset(cse->Name, 0, sizeof(cse->Name)); strcpy(cse->Name, row[1]); cse->Class = (uint8)atoi(row[4]); cse->Race = (uint32)atoi(row[3]); From 85bdcf413bdf4020763a8105a1d806fae208e335 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 24 May 2015 18:50:33 -0400 Subject: [PATCH 098/846] Bard songs go negative for some reason? Hot fix for now, I don't think they really need to be extended, but I need to investigate more. --- common/spdat.h | 33 +++++++++++++++++---------------- zone/spell_effects.cpp | 6 ++++-- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index 487b5d00a..ff2976607 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -133,7 +133,7 @@ typedef enum { /* 42 */ ST_Directional = 0x2a, //ae around this target between two angles /* 43 */ ST_GroupClientAndPet = 0x2b, /* 44 */ ST_Beam = 0x2c, -/* 45 */ ST_Ring = 0x2d, +/* 45 */ ST_Ring = 0x2d, /* 46 */ ST_TargetsTarget = 0x2e, // uses the target of your target /* 47 */ ST_PetMaster = 0x2f, // uses the master as target /* 48 */ // UNKNOWN @@ -154,7 +154,7 @@ typedef enum { // full listing: https://forums.station.sony.com/eq/index.php?threads/enumerated-spa-list.206288/ // mirror: http://pastebin.com/MYeQqGwe #define SE_CurrentHP 0 // implemented - Heals and nukes, repeates every tic if in a buff -#define SE_ArmorClass 1 // implemented +#define SE_ArmorClass 1 // implemented #define SE_ATK 2 // implemented #define SE_MovementSpeed 3 // implemented - SoW, SoC, etc #define SE_STR 4 // implemented @@ -197,7 +197,7 @@ typedef enum { #define SE_Destroy 41 // implemented - Disintegrate, Banishment of Shadows #define SE_ShadowStep 42 // implemented #define SE_Berserk 43 // implemented (*not used in any known live spell) Makes client 'Berserk' giving crip blow chance. -#define SE_Lycanthropy 44 // implemented +#define SE_Lycanthropy 44 // implemented #define SE_Vampirism 45 // implemented (*not used in any known live spell) Stackable lifetap from melee. #define SE_ResistFire 46 // implemented #define SE_ResistCold 47 // implemented @@ -247,7 +247,7 @@ typedef enum { #define SE_SummonCorpse 91 // implemented #define SE_InstantHate 92 // implemented - add hate #define SE_StopRain 93 // implemented - Wake of Karana -#define SE_NegateIfCombat 94 // implemented +#define SE_NegateIfCombat 94 // implemented #define SE_Sacrifice 95 // implemented #define SE_Silence 96 // implemented #define SE_ManaPool 97 // implemented @@ -299,7 +299,7 @@ typedef enum { #define SE_LimitCastTimeMin 143 // implemented #define SE_LimitCastTimeMax 144 // implemented (*not used in any known live spell) #define SE_Teleport2 145 // implemented - Banishment of the Pantheon -//#define SE_ElectricityResist 146 // *not implemented (Lightning Rod: 23233) +//#define SE_ElectricityResist 146 // *not implemented (Lightning Rod: 23233) #define SE_PercentalHeal 147 // implemented #define SE_StackingCommand_Block 148 // implemented? #define SE_StackingCommand_Overwrite 149 // implemented? @@ -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 @@ -560,7 +560,7 @@ typedef enum { #define SE_LimitSpellSubclass 404 // *not implemented - Limits to specific types of spells (see CheckSpellCategory) [Categories NOT defined yet] #define SE_TwoHandBluntBlock 405 // implemented - chance to block attacks when using two hand blunt weapons (similiar to shield block) #define SE_CastonNumHitFade 406 // implemented - casts a spell when a buff fades due to its numhits being depleted -#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied) +#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied) #define SE_LimitHPPercent 408 // implemented - limited to a certain percent of your hp(ie heals up to 50%) #define SE_LimitManaPercent 409 // implemented - limited to a certain percent of your mana #define SE_LimitEndPercent 410 // implemented - limited to a certain percent of your end @@ -576,7 +576,7 @@ typedef enum { #define SE_FcLimitUse 420 // implemented - increases numhits count by percent (Note: not used in any known live spells) #define SE_FcIncreaseNumHits 421 // implemented[AA] - increases number of hits a buff has till fade. (focus) #define SE_LimitUseMin 422 // implemented - limit a focus to require a min amount of numhits value (used with above) -#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type +#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type #define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace //#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626) //#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window @@ -600,9 +600,9 @@ typedef enum { #define SE_ImprovedTaunt 444 // implemented - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y //#define SE_AddMercSlot 445 // *not implemented[AA] - [Hero's Barracks] Allows you to conscript additional mercs. #define SE_AStacker 446 // implementet - bufff stacking blocker (26219 | Qirik's Watch) -#define SE_BStacker 447 // implemented +#define SE_BStacker 447 // implemented #define SE_CStacker 448 // implemented -#define SE_DStacker 449 // implemented +#define SE_DStacker 449 // implemented #define SE_MitigateDotDamage 450 // implemented DOT spell mitigation rune with max value #define SE_MeleeThresholdGuard 451 // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage #define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage @@ -618,6 +618,7 @@ typedef enum { #define DF_Permanent 50 +#define DF_Aura 51 // note this struct is historical, we don't actually need it to be // aligned to anything, but for maintaining it it is kept in the order that @@ -733,31 +734,31 @@ struct SPDat_Spell_Struct /* 197 */ bool not_extendable; /* 198- 199 */ /* 200 */ bool suspendable; // buff is suspended in suspended buff zones -/* 201 */ int viral_range; +/* 201 */ int viral_range; /* 202 */ /* 203 */ //int songcap; // individual song cap (how live currently does it, not implemented) /* 204 */ /* 205 */ bool no_block; -/* 206 */ +/* 206 */ /* 207 */ int spellgroup; /* 208 */ int rank; //increments AA effects with same name /* 209 */ int powerful_flag; // Need more investigation to figure out what to call this, for now we know -1 makes charm spells not break before their duration is complete, it does alot more though -/* 210 */ // bool DurationFrozen; ??? +/* 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 - 217 */ -/* 218 */ int aemaxtargets; //Is used for various AE effects +/* 218 */ int aemaxtargets; //Is used for various AE effects /* 219 */ int maxtargets; //Is used for beam and ring spells for target # limits (not implemented) -/* 220 - 223 */ +/* 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 +/* 231 */ float min_range; //Min casting range /* 232 - 236 */ uint8 DamageShieldType; // This field does not exist in spells_us.txt }; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 5fcee64cb..a5b678e57 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3367,13 +3367,15 @@ void Mob::BuffProcess() if(buffs[buffs_i].spellid == SPELL_UNKNOWN) continue; - if(buffs[buffs_i].ticsremaining > 0) // perma buffs will either be -1 or -4 - { + // DF_Permanent uses -1 DF_Aura uses -4 but we need to check negatives for some spells for some reason? + if (spells[buffs[buffs_i].spellid].buffdurationformula != DF_Permanent && + spells[buffs[buffs_i].spellid].buffdurationformula != DF_Aura) { if(!zone->BuffTimersSuspended() || !IsSuspendableSpell(buffs[buffs_i].spellid)) { --buffs[buffs_i].ticsremaining; if (buffs[buffs_i].ticsremaining == 0) { + // Why do we need to let these go negative? Client uses negatives for perma buffs if (!IsShortDurationBuff(buffs[buffs_i].spellid) || IsFearSpell(buffs[buffs_i].spellid) || IsCharmSpell(buffs[buffs_i].spellid) || From 249d67a1c316c675268530fa607c8f02ff38ac06 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 25 May 2015 02:01:51 -0400 Subject: [PATCH 099/846] Bards get a bonus tic at some point Not sure what level but it's between 53 and 85 ... (although I remember reading something about around 60) I also didn't notice any of the odd effects the comments speak of ... I suspect they were fighting each other? --- zone/effects.cpp | 12 ++++-------- zone/spell_effects.cpp | 13 ------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 493de9fa7..c814ea554 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -421,14 +421,10 @@ int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) int tic_inc = 0; tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id); - // Only need this for clients, since the change was for bard songs, I assume we should keep non bard songs getting +1 - // However if its bard or not and is mez, charm or fear, we need to add 1 so that client is in sync - if (IsClient() && !(IsShortDurationBuff(spell_id) && IsBardSong(spell_id)) || - IsFearSpell(spell_id) || - IsCharmSpell(spell_id) || - IsMezSpell(spell_id) || - IsBlindSpell(spell_id)) - tic_inc += 1; + // unsure on the exact details, but bard songs that don't cost mana at some point get an extra tick, 60 for now + // a level 53 bard reported getting 2 tics + if (IsShortDurationBuff(spell_id) && IsBardSong(spell_id) && spells[spell_id].mana == 0 && GetClass() == BARD && GetLevel() > 60) + tic_inc++; return (((duration * increase) / 100) + tic_inc); } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a5b678e57..fc942f9fe 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3375,19 +3375,6 @@ void Mob::BuffProcess() --buffs[buffs_i].ticsremaining; if (buffs[buffs_i].ticsremaining == 0) { - // Why do we need to let these go negative? Client uses negatives for perma buffs - if (!IsShortDurationBuff(buffs[buffs_i].spellid) || - IsFearSpell(buffs[buffs_i].spellid) || - IsCharmSpell(buffs[buffs_i].spellid) || - IsMezSpell(buffs[buffs_i].spellid) || - IsBlindSpell(buffs[buffs_i].spellid)) - { - Log.Out(Logs::Detail, Logs::Spells, "Buff %d in slot %d has expired. Fading.", buffs[buffs_i].spellid, buffs_i); - BuffFadeBySlot(buffs_i); - } - } - else 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 1bcb5c72a53a20b7491fba644e2aad6376d123eb Mon Sep 17 00:00:00 2001 From: hateborne Date: Mon, 25 May 2015 10:44:15 -0400 Subject: [PATCH 100/846] Making $npc->RemoveFromHateList actually work $npc->RemoveFromHateList is a mob function, not an NPC function. Casting to Mob to let it work. --- zone/perl_npc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 0c9cec797..861759d12 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -823,7 +823,7 @@ XS(XS_NPC_RemoveFromHateList) if(ent == nullptr) Perl_croak(aTHX_ "ent is nullptr, avoiding crash."); - THIS->RemoveFromHateList(ent); + THIS->CastToMob()->RemoveFromHateList(ent); } XSRETURN_EMPTY; From 788959a5e287e07006419c3532668315c0a931d1 Mon Sep 17 00:00:00 2001 From: SecretsOTheP Date: Mon, 25 May 2015 12:35:53 -0400 Subject: [PATCH 101/846] Haynar's movement fixes. Changes Speed from float to int. EQ client deals with int step locs better than it does floats according to Haynar's testing. This also contains mob runspeed changes. I recommend you set runspeeds to start in the DB 1.25 for NPCs below 1.25 which will match player runspeeds almost equally. Existing DBs will need to be updated. General Cleanup of MobAI functions. Mobs now change their heading on AIMovement timers if their targets' heading has changed since that time. This prevents players from being able to land backstabs inbetween mob swings. Charmed/feared players now send the appropriate packet, there was a missing CastToClient() in spells that was missing. Mob runspeed can no longer be snared to 0%, instead, 1% of their base runspeed is the maximum. Roots apply as roots instead of a modifier under this code. There is going to be bugs with this code. It's better we push through it than revert it. Sanctuary has been running this for a good week and we've worked through the issues. Misc updates: Exported some variables to perl, including: EVENT_ITE_CLICK_CAST: EVENT_ITEM_CLICK: spell_id - returns the spell_id of the click effect. return value - cancels the cast. EVENT_DROP_ITEM: quantity - returns the # of items dropped in the packet. If the item has charges, charges are returned here instead. itemname - name of the item being dropped itemid - id of the item being droppped spell_id - spell_id associated with the item's click effect. slotid - the inventory slot id of the item being dropped. return value - cancels the item from being dropped. Added Perl function: CalcEXP. Calculates the experience you would gain for an NPC that cons a specific con value to you. Fixed a bug where you would receive the group experience bonus and group experience messages for simply being in a group, regardless of the player being in the same zone as you. --- zone/bonuses.cpp | 194 +++++++++++++++++---------- zone/bot.cpp | 28 ++-- zone/client.cpp | 6 +- zone/client.h | 2 +- zone/client_packet.cpp | 4 +- zone/command.cpp | 2 +- zone/effects.cpp | 51 ++++---- zone/embparser.cpp | 9 ++ zone/exp.cpp | 109 ++++++++++++++- zone/fearpath.cpp | 23 ---- zone/inventory.cpp | 2 +- zone/merc.cpp | 14 +- zone/mob.cpp | 282 +++++++++++++++++++++++++++++++-------- zone/mob.h | 30 ++++- zone/mob_ai.cpp | 291 +++++++++++++++++++---------------------- zone/npc.h | 1 - zone/perl_client.cpp | 30 +++++ zone/spell_effects.cpp | 14 +- zone/spells.cpp | 6 +- zone/tradeskills.cpp | 4 + zone/waypoints.cpp | 66 ++++------ zone/zone.cpp | 2 +- 22 files changed, 751 insertions(+), 419 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 5dd7440f6..0c9c6d904 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -335,8 +335,8 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu } //FatherNitwit: New style haste, shields, and regens - if(newbon->haste < (int32)item->Haste) { - newbon->haste = item->Haste; + if((int32)item->Haste > 0) { + newbon->haste += item->Haste; } if(item->Regen > 0) newbon->HPRegen += item->Regen; @@ -390,10 +390,10 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu newbon->HitChance += item->Accuracy; } if(item->CombatEffects > 0) { - if((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) - newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap); + if((newbon->MeleeDamage + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) + newbon->MeleeDamage = RuleI(Character, ItemCombatEffectsCap); else - newbon->ProcChance += item->CombatEffects; + newbon->MeleeDamage += item->CombatEffects; } if(item->DotShielding > 0) { if((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) @@ -428,7 +428,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu 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, item->Worn.Type); + ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); } if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects @@ -559,7 +559,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool /* Powerful Non-live like option allows developers to add worn effects on items that can stack with other worn effects of the same spell effect type, instead of only taking the highest value. - Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus. + Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus. To enable use RuleI(Spells, AdditiveBonusWornType) Setting value = 2 Will force all live items to automatically be calculated additivily Setting value to anything else will indicate the item 'worntype' that if set to the same, will cause the bonuses to use this calculation @@ -579,7 +579,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if(GetLevel() < item->ReqLevel) return; - + if (item->Worn.Effect > 0 && item->Worn.Type == RuleI(Spells, AdditiveBonusWornType)) ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);// Non-live like - Addititive latent effects @@ -691,7 +691,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) continue; Log.Out(Logs::Detail, Logs::AA, "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) { @@ -1007,7 +1007,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_BlockBehind: newbon->BlockBehind += base1; break; - + case SE_StrikeThrough: case SE_StrikeThrough2: newbon->StrikeThrough += base1; @@ -1313,7 +1313,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_Vampirism: newbon->Vampirism += base1; - break; + break; case SE_FrenziedDevastation: newbon->FrenziedDevastation += base2; @@ -1416,7 +1416,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) } case SE_SkillProcSuccess:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid) @@ -1449,7 +1449,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) int 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, 0, buffs[i].ticsremaining, i, buffs[i].instrument_mod); + ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, 0, buffs[i].ticsremaining,i); if (buffs[i].numhits > 0) Numhits(true); @@ -1472,9 +1472,8 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } -void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *new_bonus, uint16 casterId, - uint8 WornType, int32 ticsremaining, int buffslot, int instrument_mod, - bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) +void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, uint8 WornType, 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; bool AdditiveWornBonus = false; @@ -1510,9 +1509,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne if (WornType && (RuleI(Spells, AdditiveBonusWornType) == WornType)) 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, caster, ticsremaining); base2 = spells[spell_id].base2[i]; max = spells[spell_id].max[i]; } @@ -1561,49 +1560,100 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_AttackSpeed: { - if ((effect_value - 100) > 0) { // Haste - if (new_bonus->haste < 0) break; // Slowed - Don't apply haste - if ((effect_value - 100) > new_bonus->haste) { - new_bonus->haste = effect_value - 100; + + if (AdditiveWornBonus) { + if ((effect_value - 100) > 0) { // Haste + if (new_bonus->haste < 0) break; // Slowed - Don't apply haste + if ((effect_value - 100) > new_bonus->haste) { + new_bonus->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 < new_bonus->haste) + new_bonus->haste += real_slow_value; } } - 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 < new_bonus->haste) - new_bonus->haste = real_slow_value; + else + { + if ((effect_value - 100) > 0) { // Haste + if (new_bonus->haste < 0) break; // Slowed - Don't apply haste + if ((effect_value - 100) > new_bonus->haste) { + new_bonus->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 < new_bonus->haste) + new_bonus->haste = real_slow_value; + } } break; } case SE_AttackSpeed2: - { - if ((effect_value - 100) > 0) { // Haste V2 - Stacks with V1 but does not Overcap - if (new_bonus->hastetype2 < 0) break; //Slowed - Don't apply haste2 - if ((effect_value - 100) > new_bonus->hastetype2) { - new_bonus->hastetype2 = effect_value - 100; + { + if (AdditiveWornBonus) { + if ((effect_value - 100) > 0) { // Haste + if (new_bonus->hastetype2 < 0) break; // Slowed - Don't apply haste + if ((effect_value - 100) > new_bonus->hastetype2) { + new_bonus->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 < new_bonus->hastetype2) + new_bonus->hastetype2 += real_slow_value; } } - 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 < new_bonus->hastetype2) - new_bonus->hastetype2 = real_slow_value; + else + { + if ((effect_value - 100) > 0) { // Haste + if (new_bonus->hastetype2 < 0) break; // Slowed - Don't apply haste + if ((effect_value - 100) > new_bonus->hastetype2) { + new_bonus->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 < new_bonus->hastetype2) + new_bonus->hastetype2 = real_slow_value; + } } break; } case SE_AttackSpeed3: { - if (effect_value < 0){ //Slow - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value < new_bonus->hastetype3) - new_bonus->hastetype3 = effect_value; - } + if (AdditiveWornBonus) { + if (effect_value < 0){ //Slow + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value < new_bonus->hastetype3) + new_bonus->hastetype3 += effect_value; + } - else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps - if (effect_value > new_bonus->hastetype3) { - new_bonus->hastetype3 = effect_value; + else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps + if (effect_value > new_bonus->hastetype3) { + new_bonus->hastetype3 += effect_value; + } + } + } + else + { + if (effect_value < 0){ //Slow + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value < new_bonus->hastetype3) + new_bonus->hastetype3 = effect_value; + } + + else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps + if (effect_value > new_bonus->hastetype3) { + new_bonus->hastetype3 = effect_value; + } } } break; @@ -1618,13 +1668,21 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne 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 > new_bonus->inhibitmelee) { - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value > new_bonus->inhibitmelee) - new_bonus->inhibitmelee = effect_value; + if (AdditiveWornBonus) { + if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) { + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value > new_bonus->inhibitmelee) + new_bonus->inhibitmelee += effect_value; + } + } + else + { + if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) { + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value > new_bonus->inhibitmelee) + new_bonus->inhibitmelee = effect_value; + } } - break; } @@ -1840,7 +1898,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->DamageShieldType = GetDamageShieldType(spell_id, max); else new_bonus->DamageShieldType = GetDamageShieldType(spell_id); - + break; } @@ -2021,7 +2079,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_Vampirism: new_bonus->Vampirism += effect_value; - break; + break; case SE_AllInstrumentMod: { @@ -2264,7 +2322,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_CriticalSpellChance: { new_bonus->CriticalSpellChance += effect_value; - + if (base2 > new_bonus->SpellCritDmgIncNoStack) new_bonus->SpellCritDmgIncNoStack = base2; break; @@ -2474,7 +2532,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_NegateAttacks: { - if (!new_bonus->NegateAttacks[0] || + if (!new_bonus->NegateAttacks[0] || ((new_bonus->NegateAttacks[0] && new_bonus->NegateAttacks[2]) && (new_bonus->NegateAttacks[2] < max))){ new_bonus->NegateAttacks[0] = 1; new_bonus->NegateAttacks[1] = buffslot; @@ -2494,7 +2552,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - + case SE_MeleeThresholdGuard: { if (new_bonus->MeleeThresholdGuard[0] < effect_value){ @@ -2861,17 +2919,17 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->NegateIfCombat = true; break; - case SE_Screech: + case SE_Screech: new_bonus->Screech = effect_value; break; case SE_AlterNPCLevel: if (IsNPC()){ - if (!new_bonus->AlterNPCLevel - || ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value)) + if (!new_bonus->AlterNPCLevel + || ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value)) || ((effect_value > 0) && (new_bonus->AlterNPCLevel < effect_value))) { - + int tmp_lv = GetOrigLevel() + effect_value; if (tmp_lv < 1) tmp_lv = 1; @@ -2909,7 +2967,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->BerserkSPA = true; break; - + case SE_Metabolism: new_bonus->Metabolism += effect_value; break; @@ -3010,7 +3068,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } case SE_SkillProc:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(new_bonus->SkillProc[e] && new_bonus->SkillProc[e] == spell_id) @@ -3025,7 +3083,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } case SE_SkillProcSuccess:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(new_bonus->SkillProcSuccess[e] && new_bonus->SkillProcSuccess[e] == spell_id) @@ -3041,9 +3099,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { - + //Non-Focused Effect to modify incoming spell damage by resist type. - case SE_FcSpellVulnerability: + case SE_FcSpellVulnerability: ModVulnerability(base2, effect_value); break; } @@ -3109,7 +3167,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) newbon->HitChance += cur->Accuracy; } if(cur->CombatEffects > 0) { - newbon->ProcChance += cur->CombatEffects; + newbon->MeleeDamage += cur->CombatEffects; } if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon, 0, cur->Worn.Type); @@ -4395,7 +4453,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.SlayUndead[0] = effect_value; aabonuses.SlayUndead[1] = effect_value; break; - + case SE_DoubleRangedAttack: spellbonuses.DoubleRangedAttack = effect_value; aabonuses.DoubleRangedAttack = effect_value; @@ -4415,7 +4473,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.ShieldEquipDmgMod[1] = effect_value; itembonuses.ShieldEquipDmgMod[0] = effect_value; itembonuses.ShieldEquipDmgMod[1] = effect_value; - break; + break; case SE_TriggerMeleeThreshold: spellbonuses.TriggerMeleeThreshold = false; diff --git a/zone/bot.cpp b/zone/bot.cpp index e2c506575..5ddbb1377 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -292,9 +292,7 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) { void Bot::Sit() { if(IsMoving()) { moved = false; - // SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); tar_ndx = 0; } @@ -3448,11 +3446,10 @@ void Bot::AI_Process() { if(IsMoving()) { SetHeading(0); SetRunAnimSpeed(0); + SetCurrentSpeed(GetRunSpeed()); if(moved) { - moved = false; - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); } } @@ -3495,11 +3492,10 @@ void Bot::AI_Process() { if(IsMoving()) { SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); SetRunAnimSpeed(0); - + SetCurrentSpeed(0); if(moved) { moved = false; - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); } } @@ -3517,11 +3513,10 @@ void Bot::AI_Process() { if(IsMoving()) { SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); SetRunAnimSpeed(0); - + SetCurrentSpeed(0); if(moved) { moved = false; - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); } } @@ -3740,7 +3735,7 @@ void Bot::AI_Process() { if(follow) { float dist = DistanceSquared(m_Position, follow->GetPosition()); - float speed = follow->GetRunspeed(); + int speed = follow->GetRunspeed(); if(dist < GetFollowDistance() + 1000) speed = follow->GetWalkspeed(); @@ -3757,9 +3752,8 @@ void Bot::AI_Process() { { if(moved) { - moved=false; - SendPosition(); - SetMoving(false); + moved = false; + SetCurrentSpeed(0); } } } @@ -3987,6 +3981,7 @@ void Bot::PetAIProcess() { botPet->SetHeading(botPet->GetTarget()->GetHeading()); if(moved) { moved=false; + SetCurrentSpeed(0); botPet->SendPosition(); botPet->SetMoving(false); } @@ -4020,6 +4015,7 @@ void Bot::PetAIProcess() { botPet->SetHeading(botPet->GetTarget()->GetHeading()); if(moved) { moved=false; + SetCurrentSpeed(0); botPet->SendPosition(); botPet->SetMoving(false); } diff --git a/zone/client.cpp b/zone/client.cpp index 0aa5510ff..7471a6a62 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4991,7 +4991,7 @@ void Client::SetShadowStepExemption(bool v) if((cur_time - m_TimeSinceLastPositionCheck) > 1000) { float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); - float runs = GetRunspeed(); + int runs = GetRunspeed(); if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) { printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__, @@ -5048,7 +5048,7 @@ void Client::SetKnockBackExemption(bool v) if((cur_time - m_TimeSinceLastPositionCheck) > 1000) { float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); - float runs = GetRunspeed(); + int runs = GetRunspeed(); if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) { if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) @@ -5105,7 +5105,7 @@ void Client::SetPortExemption(bool v) if((cur_time - m_TimeSinceLastPositionCheck) > 1000) { float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); - float runs = GetRunspeed(); + int runs = GetRunspeed(); if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) { if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) diff --git a/zone/client.h b/zone/client.h index 79dcf87ff..ac505ecdb 100644 --- a/zone/client.h +++ b/zone/client.h @@ -557,6 +557,7 @@ public: void SendCrystalCounts(); void AddEXP(uint32 in_add_exp, uint8 conlevel = 0xFF, bool resexp = false); + uint32 CalcEXP(uint8 conlevel = 0xFF); void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp=false); void AddLevelBasedExp(uint8 exp_percentage, uint8 max_level=0); void SetLeadershipEXP(uint32 group_exp, uint32 raid_exp); @@ -1129,7 +1130,6 @@ public: inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); } void DragCorpses(); inline void ClearDraggedCorpses() { DraggedCorpses.clear(); } - inline void ResetPositionTimer() { position_timer_counter = 0; } void SendAltCurrencies(); void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount); void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 3a2c6e2c9..3f40f3c00 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4266,7 +4266,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) if((cur_time - m_TimeSinceLastPositionCheck) > 0) { float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); - float runs = GetRunspeed(); + int runs = GetRunspeed(); if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) { if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) @@ -4334,7 +4334,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) if((cur_time - m_TimeSinceLastPositionCheck) > 2500) { float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); - float runs = GetRunspeed(); + int runs = GetRunspeed(); if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) { if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) diff --git a/zone/command.cpp b/zone/command.cpp index 3f3d4b6c1..a62ee4ce8 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1484,7 +1484,7 @@ void command_npcstats(Client *c, const Seperator *sep) 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: %f Walkspeed: %f", c->GetTarget()->GetRunspeed(), c->GetTarget()->GetWalkspeed()); + c->Message(0, "Runspeed: %i Walkspeed: %i", c->GetTarget()->GetRunspeed(), 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); diff --git a/zone/effects.cpp b/zone/effects.cpp index c814ea554..c7066da68 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -89,7 +89,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { if (IsClient() && GetClass() == WIZARD) ratio += RuleI(Spells, WizCritRatio); //Default is zero - + if (Critical){ value = value_BaseEffect*ratio/100; @@ -138,7 +138,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(itembonuses.SpellDmg) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -172,7 +172,7 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100; value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100; value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100; - extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + + extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) + GetFocusEffect(focusFcDamageAmt, spell_id); @@ -200,6 +200,11 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { extra_dmg /= duration; } + //Sanctuary Custom: Spelldmg per tick + if(itembonuses.SpellDmg) + value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg / 6, value); //per tick + + value -= extra_dmg; } @@ -211,23 +216,6 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg) { - int total_cast_time = 0; - - if (spells[spell_id].recast_time >= spells[spell_id].recovery_time) - total_cast_time = spells[spell_id].recast_time + spells[spell_id].cast_time; - else - total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time; - - if (total_cast_time > 0 && total_cast_time <= 2500) - extra_spell_amt = extra_spell_amt*25/100; - else if (total_cast_time > 2500 && total_cast_time < 7000) - extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000; - else - extra_spell_amt = extra_spell_amt * total_cast_time / 7000; - - if(extra_spell_amt*2 < base_spell_dmg) - return 0; - return extra_spell_amt; } @@ -270,7 +258,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { value += GetFocusEffect(focusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(itembonuses.HealAmt) value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier; value += value*target->GetHealRate(spell_id, this)/100; @@ -281,7 +269,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (Critical) { entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetName(), itoa(value)); - + if (IsClient()) Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value)); } @@ -301,6 +289,9 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if(chance && zone->random.Roll(chance)) value *= 2; + + if(itembonuses.HealAmt) + value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt / 6, value) * modifier; } if (IsNPC() && CastToNPC()->GetHealScale()) @@ -421,10 +412,14 @@ int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) int tic_inc = 0; tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id); - // unsure on the exact details, but bard songs that don't cost mana at some point get an extra tick, 60 for now - // a level 53 bard reported getting 2 tics - if (IsShortDurationBuff(spell_id) && IsBardSong(spell_id) && spells[spell_id].mana == 0 && GetClass() == BARD && GetLevel() > 60) - tic_inc++; + // Only need this for clients, since the change was for bard songs, I assume we should keep non bard songs getting +1 + // However if its bard or not and is mez, charm or fear, we need to add 1 so that client is in sync + if (IsClient() && !(IsShortDurationBuff(spell_id) && IsBardSong(spell_id)) || + IsFearSpell(spell_id) || + IsCharmSpell(spell_id) || + IsMezSpell(spell_id) || + IsBlindSpell(spell_id)) + tic_inc += 1; return (((duration * increase) / 100) + tic_inc); } @@ -767,7 +762,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } else { - if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) + if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); if (!spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); @@ -855,7 +850,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff if (!center->CheckLosFN(curmob)) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... - // See notes in AESpell() above for more info. + // See notes in AESpell() above for more info. if (caster->IsAttackAllowed(curmob, true)) continue; if (caster->CheckAggro(curmob)) diff --git a/zone/embparser.cpp b/zone/embparser.cpp index db017750a..326585806 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1321,6 +1321,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID ExportVar(package_name.c_str(), "itemid", objid); ExportVar(package_name.c_str(), "itemname", iteminst->GetItem()->Name); ExportVar(package_name.c_str(), "slotid", extradata); + ExportVar(package_name.c_str(), "spell_id", iteminst->GetItem()->Click.Effect); break; } @@ -1399,6 +1400,14 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); 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(), "slotid", extradata); + break; + } default: { break; diff --git a/zone/exp.cpp b/zone/exp.cpp index 3a77f30dc..ab8506aca 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -59,6 +59,97 @@ static uint32 MaxBankedRaidLeadershipPoints(int Level) return 10; } +uint32 Client::CalcEXP(uint8 conlevel) { + + uint32 in_add_exp = EXP_FORMULA; + + + if((XPRate != 0)) + in_add_exp = static_cast(in_add_exp * (static_cast(XPRate) / 100.0f)); + + float totalmod = 1.0; + float zemmod = 1.0; + //get modifiers + if(RuleR(Character, ExpMultiplier) >= 0){ + totalmod *= RuleR(Character, ExpMultiplier); + } + + if(zone->newzone_data.zone_exp_multiplier >= 0){ + zemmod *= zone->newzone_data.zone_exp_multiplier; + } + + if(RuleB(Character,UseRaceClassExpBonuses)) + { + if(GetBaseRace() == HALFLING){ + totalmod *= 1.05; + } + + if(GetClass() == ROGUE || GetClass() == WARRIOR){ + totalmod *= 1.05; + } + } + + if(zone->IsHotzone()) + { + totalmod += RuleR(Zone, HotZoneBonus); + } + + in_add_exp = uint32(float(in_add_exp) * totalmod * zemmod); + + if(RuleB(Character,UseXPConScaling)) + { + if (conlevel != 0xFF) { + switch (conlevel) + { + case CON_GREEN: + in_add_exp = 0; + return 0; + case CON_LIGHTBLUE: + in_add_exp = in_add_exp * RuleI(Character, LightBlueModifier)/100; + break; + case CON_BLUE: + in_add_exp = in_add_exp * RuleI(Character, BlueModifier)/100; + break; + case CON_WHITE: + in_add_exp = in_add_exp * RuleI(Character, WhiteModifier)/100; + break; + case CON_YELLOW: + in_add_exp = in_add_exp * RuleI(Character, YellowModifier)/100; + break; + case CON_RED: + in_add_exp = in_add_exp * RuleI(Character, RedModifier)/100; + break; + } + } + } + + float aatotalmod = 1.0; + if(zone->newzone_data.zone_exp_multiplier >= 0){ + aatotalmod *= zone->newzone_data.zone_exp_multiplier; + } + + + + if(RuleB(Character,UseRaceClassExpBonuses)) + { + if(GetBaseRace() == HALFLING){ + aatotalmod *= 1.05; + } + + if(GetClass() == ROGUE || GetClass() == WARRIOR){ + aatotalmod *= 1.05; + } + } + + if(RuleB(Zone, LevelBasedEXPMods)){ + if(zone->level_exp_mod[GetLevel()].ExpMod){ + in_add_exp *= zone->level_exp_mod[GetLevel()].ExpMod; + } + } + + return in_add_exp; +} + void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { this->EVENT_ITEM_ScriptStopReturn(); @@ -78,7 +169,7 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { //figure out how much of this goes to AAs add_aaxp = add_exp * m_epp.perAA / 100; - //take that ammount away from regular exp + //take that amount away from regular exp add_exp -= add_aaxp; float totalmod = 1.0; @@ -247,12 +338,22 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { Message(13, "Error in Client::SetEXP. EXP not set."); return; // Must be invalid class/race } + uint32 i = 0; + uint32 membercount = 0; + if(GetGroup()) + { + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (GetGroup()->members[i] != nullptr) { + membercount++; + } + } + } if ((set_exp + set_aaxp) > (m_pp.exp+m_pp.expAA)) { if (isrezzexp) this->Message_StringID(MT_Experience, REZ_REGAIN); else{ - if(this->IsGrouped()) + if(membercount > 1) this->Message_StringID(MT_Experience, GAIN_GROUPXP); else if(IsRaidGrouped()) Message_StringID(MT_Experience, GAIN_RAIDEXP); @@ -604,8 +705,8 @@ void Group::SplitExp(uint32 exp, Mob* other) { groupmod = 2.16; else groupmod = 1.0; - - groupexp += (uint32)((float)exp * groupmod * (RuleR(Character, GroupExpMultiplier))); + if(membercount > 1 && membercount < 6) + groupexp += (uint32)((float)exp * groupmod * (RuleR(Character, GroupExpMultiplier))); int conlevel = Mob::GetLevelCon(maxlevel, other->GetLevel()); if(conlevel == CON_GREEN) diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index 0b33a662e..0fd5ffa98 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -123,29 +123,6 @@ void Mob::ProcessFlee() } } -float Mob::GetFearSpeed() -{ - if (flee_mode) { - //we know ratio < FLEE_HP_RATIO - float speed = GetBaseRunspeed(); - float ratio = GetHPRatio(); - float multiplier = RuleR(Combat, FleeMultiplier); - - if (GetSnaredAmount() > 40) - multiplier = multiplier / 6.0f; - - speed = speed * ratio * multiplier / 100; - - //NPC will eventually stop. Snares speeds this up. - if (speed < 0.09) - speed = 0.0001f; - - return speed; - } - // fear and blind use their normal run speed - return GetRunspeed(); -} - void Mob::CalculateNewFearpoint() { if(RuleB(Pathing, Fear) && zone->pathing) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index badc059e0..2ce30fe5e 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -606,7 +606,7 @@ void Client::DropItem(int16 slot_id) // Take control of item in client inventory ItemInst *inst = m_inv.PopItem(slot_id); if(inst) { - int i = parse->EventItem(EVENT_DROP_ITEM, this, inst, nullptr, "", 0); + int i = parse->EventItem(EVENT_DROP_ITEM, this, inst, nullptr, "", slot_id); if(i != 0) { safe_delete(inst); } diff --git a/zone/merc.cpp b/zone/merc.cpp index 5f06331fa..936dfcc68 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1460,8 +1460,7 @@ void Merc::AI_Process() { if(moved) { moved = false; - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); } } @@ -1497,9 +1496,7 @@ void Merc::AI_Process() { SetRunAnimSpeed(0); if(moved) { - moved = false; - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); } } @@ -1710,7 +1707,7 @@ void Merc::AI_Process() { if(follow) { float dist = DistanceSquared(m_Position, follow->GetPosition()); - float speed = GetRunspeed(); + int speed = GetRunspeed(); if(dist < GetFollowDistance() + 1000) speed = GetWalkspeed(); @@ -1727,9 +1724,8 @@ void Merc::AI_Process() { { if(moved) { - moved=false; - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); + moved = false; } } } diff --git a/zone/mob.cpp b/zone/mob.cpp index a8bed6417..ddad36ff1 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef BOTS #include "bot.h" @@ -148,6 +149,28 @@ Mob::Mob(const char* in_name, size = in_size; base_size = size; runspeed = in_runspeed; + // neotokyo: sanity check + if (runspeed < 0 || runspeed > 20) + runspeed = 1.25f; + base_runspeed = (int)((float)runspeed * 40.0f); + // clients + if (runspeed == 0.7f) { + base_runspeed = 28; + walkspeed = 0.3f; + base_walkspeed = 12; + fearspeed = 0.625f; + base_fearspeed = 25; + // npcs + } else { + base_walkspeed = base_runspeed * 100 / 265; + walkspeed = ((float)base_walkspeed) * 0.025f; + base_fearspeed = base_runspeed * 100 / 127; + fearspeed = ((float)base_fearspeed) * 0.025f; + } + + + current_speed = base_runspeed; + m_PlayerState = 0; @@ -531,48 +554,32 @@ bool Mob::IsInvisible(Mob* other) const 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; +int Mob::_GetWalkSpeed() const { + + if (IsRooted() || IsStunned() || IsMezzed()) + return 0; + else if (IsPseudoRooted()) - return 0.00001f; + return 0; - float speed_mod = runspeed; + int aa_mod = 0; + int speed_mod = base_walkspeed; + int base_run = base_runspeed; + bool has_horse = false; + int runspeedcap = RuleI(Character,BaseRunSpeedCap); + runspeedcap += itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; + aa_mod += aabonuses.BaseMovementSpeed; - // 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; + Mob *horse = entity_list.GetMob(CastToClient()->GetHorseId()); + if (horse) { + speed_mod = horse->GetBaseRunspeed(); 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 spell_mod = spellbonuses.movementspeed + itembonuses.movementspeed; 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; @@ -581,27 +588,189 @@ float Mob::_GetMovementSpeed(int mod) const else movemod = aa_mod; - // cap negative movemods from snares mostly - if (movemod < -85) + // hard cap + if (runspeedcap > 225) + runspeedcap = 225; + + if(movemod < -85) //cap it at moving very very slow movemod = -85; - if (movemod != 0) - speed_mod += speed_mod * static_cast(movemod) / 100.0f; + if (!has_horse && movemod != 0) + speed_mod += (base_run * movemod / 100); - // runspeed caps - frunspeedcap = static_cast(runspeedcap) / 100.0f; - if (IsClient() && speed_mod > frunspeedcap) - speed_mod = frunspeedcap; + if(speed_mod < 1) + return(1); - // 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; + //runspeed cap. + if(IsClient()) + { + if(speed_mod > runspeedcap) + speed_mod = runspeedcap; + } + return speed_mod; +} - if (speed_mod <= 0.0f) - speed_mod = IsClient() ? 0.0001f : 0.0f; +int Mob::_GetRunSpeed() const { + if (IsRooted() || IsStunned() || IsMezzed()) + return 0; + + int aa_mod = 0; + int speed_mod = base_runspeed; + int base_walk = base_walkspeed; + bool has_horse = false; + if (IsClient()) + { + if(CastToClient()->GetGMSpeed()) + { + speed_mod = 325; + } + else + { + Mob* horse = entity_list.GetMob(CastToClient()->GetHorseId()); + if(horse) + { + speed_mod = horse->GetBaseRunspeed(); + base_walk = horse->GetBaseWalkspeed(); + has_horse = true; + } + } + } + + int runspeedcap = RuleI(Character,BaseRunSpeedCap); + runspeedcap += itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; + + aa_mod = itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; + int spell_mod = spellbonuses.movementspeed + itembonuses.movementspeed; + int movemod = 0; + + if(spell_mod < 0) + { + movemod += spell_mod; + } + else if(spell_mod > aa_mod) + { + movemod = spell_mod; + } + else + { + movemod = aa_mod; + } + + if(movemod < -85) //cap it at moving very very slow + movemod = -85; + + if (!has_horse && movemod != 0) + { + if (IsClient()) + { + speed_mod += (speed_mod * movemod / 100); + } else { + if (movemod < 0) { + speed_mod += (50 * movemod / 100); + // basically stoped + if(speed_mod < 1) + { + return(1); + } + // moving slowly + if (speed_mod < 8) + return(8); + } else { + speed_mod += GetBaseWalkspeed(); + if (movemod > 50) + speed_mod += 4; + if (movemod > 40) + speed_mod += 3; + } + } + } + + if(speed_mod < 1) + { + return(1); + } + //runspeed cap. + if(IsClient()) + { + if(speed_mod > runspeedcap) + speed_mod = runspeedcap; + } + return speed_mod; +} + +int Mob::_GetFearSpeed() const { + + if (IsRooted() || IsStunned() || IsMezzed()) + return 0; + + //float speed_mod = fearspeed; + int speed_mod = GetBaseFearSpeed(); + + // use a max of 1.75f in calcs. + int base_run = std::min(GetBaseRunspeed(), 70); + + int spell_mod = spellbonuses.movementspeed + itembonuses.movementspeed; + int movemod = 0; + + if(spell_mod < 0) + { + movemod += spell_mod; + } + + if(movemod < -85) //cap it at moving very very slow + movemod = -85; + + if (IsClient()) { + if (CastToClient()->IsRunning()) + speed_mod = GetBaseRunspeed(); + else + speed_mod = GetBaseWalkspeed(); + if (movemod < 0) + return GetBaseWalkspeed(); + speed_mod += (base_run * movemod / 100); + return speed_mod; + } else { + int hp_ratio = GetIntHPRatio(); + // very large snares 50% or higher + if (movemod < -49) + { + if (hp_ratio < 25) + { + return (1); + } + if (hp_ratio < 50) + return (8); + else + return (12); + } + if (hp_ratio < 5) { + speed_mod = base_walkspeed / 3; + } else if (hp_ratio < 15) { + speed_mod = base_walkspeed / 2; + } else if (hp_ratio < 25) { + speed_mod = base_walkspeed + 1; // add the +1 so they do the run animation + } else if (hp_ratio < 50) { + speed_mod *= 82; + speed_mod /= 100; + } + if (movemod > 0) { + speed_mod += GetBaseWalkspeed(); + if (movemod > 50) + speed_mod += 4; + if (movemod > 40) + speed_mod += 3; + return speed_mod; + } + else if (movemod < 0) { + speed_mod += (base_run * movemod / 100); + } + } + if (speed_mod < 1) + return (1); + if (speed_mod < 9) + return (8); + if (speed_mod < 13) + return (12); return speed_mod; } @@ -1201,7 +1370,6 @@ void Mob::SendPosition() PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdateNoDelta(spu); move_tic_count = 0; - tar_ndx = 20; entity_list.QueueClients(this, app, true); safe_delete(app); } @@ -1303,7 +1471,7 @@ void Mob::ShowStats(Client* client) 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()); + client->Message(0, " Accuracy: %i MerchantID: %i EmoteID: %i Runspeed: %u Walkspeed: %u", n->GetAccuracyRating(), n->MerchantType, n->GetEmoteID(), n->GetRunspeed(), n->GetWalkspeed()); n->QueryLoot(client); } if (IsAIControlled()) { @@ -5437,3 +5605,15 @@ void Mob::SendRemovePlayerState(PlayerState old_state) safe_delete(app); } +void Mob::SetCurrentSpeed(int in){ + if (current_speed != in) + { + current_speed = in; + tar_ndx = 20; + if (in == 0) { + SetRunAnimSpeed(0); + SetMoving(false); + SendPosition(); + } + } +} \ No newline at end of file diff --git a/zone/mob.h b/zone/mob.h index bf7e2030a..896b9c71b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -364,6 +364,7 @@ public: 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); } + virtual inline float GetIntHPRatio() const { return max_hp == 0 ? 0 : (cur_hp/max_hp*100); } inline virtual int32 GetAC() const { return AC + itembonuses.AC + spellbonuses.AC; } inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } @@ -441,9 +442,12 @@ public: virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); } 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; } + int GetWalkspeed() const { return(_GetWalkSpeed()); } + int GetRunspeed() const { return(_GetRunSpeed()); } + void SetCurrentSpeed(int in); + int GetBaseRunspeed() const { return base_runspeed; } + int GetBaseWalkspeed() const { return base_walkspeed; } + int GetBaseFearSpeed() const { return base_fearspeed; } float GetMovespeed() const { return IsRunning() ? GetRunspeed() : GetWalkspeed(); } bool IsRunning() const { return m_is_running; } void SetRunning(bool val) { m_is_running = val; } @@ -801,7 +805,7 @@ public: //old fear function //void SetFeared(Mob *caster, uint32 duration, bool flee = false); - float GetFearSpeed(); + int GetFearSpeed() { return _GetFearSpeed(); } bool IsFeared() { return (spellbonuses.IsFeared || flee_mode); } // This returns true if the mob is feared or fleeing due to low HP inline void StartFleeing() { flee_mode = true; CalculateNewFearpoint(); } void ProcessFlee(); @@ -810,8 +814,8 @@ public: inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(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); + bool CalculateNewPosition(float x, float y, float z, int speed, bool checkZ = false, bool calcheading = true); + virtual bool CalculateNewPosition2(float x, float y, float z, int speed, bool checkZ = true, bool calcheading = 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); @@ -882,6 +886,8 @@ public: Timer *GetSpecialAbilityTimer(int ability); void ClearSpecialAbilities(); void ProcessSpecialAbilities(const std::string &str); + bool IsMoved() { return moved; } + void SetMoved(bool moveflag) { moved = moveflag; } Shielders_Struct shielder[MAX_SHIELDERS]; Trade* trade; @@ -951,7 +957,10 @@ 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); + int _GetWalkSpeed() const; + int _GetRunSpeed() const; + int _GetFearSpeed() const; + virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ); virtual bool AI_EngagedCastCheck() { return(false); } virtual bool AI_PursueCastCheck() { return(false); } @@ -1048,6 +1057,13 @@ protected: float base_size; float size; float runspeed; + float walkspeed; + float fearspeed; + int base_runspeed; + int base_walkspeed; + int base_fearspeed; + int current_speed; + uint32 pLastChange; bool held; bool nocast; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 355b6ba48..9909672de 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -339,9 +339,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain //stop moving if were casting a spell and were not a bard... if(!IsBardSong(AIspells[i].spellid)) { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); } 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)); @@ -698,9 +696,7 @@ void Client::AI_SpellCast() { if(!IsBardSong(spell_to_cast)) { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); } CastSpell(spell_to_cast, tar->GetID(), slot_to_use); return; @@ -714,9 +710,7 @@ void Client::AI_SpellCast() { if(!IsBardSong(spell_to_cast)) { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); } CastSpell(spell_to_cast, tar->GetID(), slot_to_use); return; @@ -772,16 +766,13 @@ void Client::AI_Process() { if(GetTarget()) SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; + SetCurrentSpeed(0); } //continue on to attack code, ensuring that we execute the engaged code engaged = true; } else { if(AImovement_timer->Check()) { - animation = GetRunspeed() * 21; + //animation = GetFearSpeed() * 21; // Check if we have reached the last fear point if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) && (std::abs(GetY() - m_FearWalkTarget.y) < 0.1)) { @@ -839,16 +830,13 @@ void Client::AI_Process() } if (AImovement_timer->Check()) { - SetRunAnimSpeed(0); + if(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) + { + SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); + SendPosition(); + } + SetCurrentSpeed(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(), MainPrimary); @@ -944,28 +932,27 @@ void Client::AI_Process() { if(!IsRooted()) { - animation = 21 * GetRunspeed(); - if(!RuleB(Pathing, Aggro) || !zone->pathing) - CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed()); - else + if(AImovement_timer->Check()) { - bool WaypointChanged, NodeReached; - glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), - GetRunspeed(), WaypointChanged, NodeReached); + if(!RuleB(Pathing, Aggro) || !zone->pathing) + CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed()); + else + { + bool WaypointChanged, NodeReached; + glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), + GetRunspeed(), WaypointChanged, NodeReached); - if(WaypointChanged) - tar_ndx = 20; + if(WaypointChanged) + tar_ndx = 20; - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); + } } } else if(IsMoving()) { SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; + SetCurrentSpeed(0); } } AI_SpellCast(); @@ -998,21 +985,23 @@ void Client::AI_Process() return; float dist = DistanceSquared(m_Position, owner->GetPosition()); - if (dist >= 100) + if (dist >= 400) { - float speed = dist >= 225 ? GetRunspeed() : GetWalkspeed(); - animation = 21 * speed; - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); + if(AImovement_timer->Check()) + { + int speed = GetWalkspeed(); + if (dist >= 5625) + speed = GetRunspeed(); + + CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); + } } else { - SetHeading(owner->GetHeading()); if(moved) { - moved=false; - SetMoving(false); - SendPosition(); - SetRunAnimSpeed(0); + SetCurrentSpeed(0); + moved = false; } } } @@ -1042,9 +1031,7 @@ void Mob::AI_Process() { { if(target) SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); moved=false; } //continue on to attack code, ensuring that we execute the engaged code @@ -1058,7 +1045,9 @@ void Mob::AI_Process() { CalculateNewFearpoint(); } if(!RuleB(Pathing, Fear) || !zone->pathing) + { CalculateNewPosition2(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, GetFearSpeed(), true); + } else { bool WaypointChanged, NodeReached; @@ -1156,15 +1145,21 @@ void Mob::AI_Process() { { if (AImovement_timer->Check()) { - SetRunAnimSpeed(0); + if(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) + { + SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); + SendPosition(); + } + SetCurrentSpeed(0); } if(IsMoving()) { - SetMoving(false); - moved=false; - SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SendPosition(); - tar_ndx =0; + if(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) + { + SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); + SendPosition(); + } + SetCurrentSpeed(0); } //casting checked above... @@ -1369,7 +1364,7 @@ void Mob::AI_Process() { CastToNPC()->DoClassAttacks(target); } AI_EngagedCastCheck(); - } //end is within combat range + } //end is within combat rangepet else { //we cannot reach our target... //underwater stuff only works with water maps in the zone! @@ -1425,10 +1420,7 @@ void Mob::AI_Process() { } else if(IsMoving()) { SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; + SetCurrentSpeed(0); } } @@ -1481,7 +1473,6 @@ void Mob::AI_Process() { } else if (AImovement_timer->Check() && !IsRooted()) { - SetRunAnimSpeed(0); if (IsPet()) { // we're a pet, do as we're told @@ -1500,18 +1491,18 @@ void Mob::AI_Process() { float dist = DistanceSquared(m_Position, owner->GetPosition()); if (dist >= 400) { - float speed = GetWalkspeed(); + int speed = GetWalkspeed(); if (dist >= 5625) speed = GetRunspeed(); + CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); } else { if(moved) { - moved=false; - SetMoving(false); - SendPosition(); + SetCurrentSpeed(0); + moved = false; } } @@ -1557,19 +1548,15 @@ void Mob::AI_Process() { if (dist2 >= followdist) // Default follow distance is 100 { - float speed = GetWalkspeed(); + int speed = GetWalkspeed(); if (dist2 >= followdist + 150) speed = GetRunspeed(); CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); } else { - if(moved) - { - SendPosition(); - moved=false; - SetMoving(false); - } + moved = false; + SetCurrentSpeed(0); } } } @@ -1666,40 +1653,92 @@ void NPC::AI_DoMovement() { if (gridno > 0 || cur_wp==-2) { if (movetimercompleted==true) { // time to pause at wp is over - AI_SetupNextWaypoint(); + + 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; + + Log.Out(Logs::Detail, Logs::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) { + Log.Out(Logs::Detail, Logs::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 - bool doMove = true; 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(); + SetWaypointPause(); + if(GetAppearance() != eaStanding) SetAppearance(eaStanding, false); - SetMoving(false); - if (m_CurrentWayPoint.w >= 0.0) { - SetHeading(m_CurrentWayPoint.w); - } - SendPosition(); + SetMoving(false); + if (m_CurrentWayPoint.w >= 0.0) { + SetHeading(m_CurrentWayPoint.w); } + SendPosition(); //kick off event_waypoint arrive char temp[16]; sprintf(temp, "%d", cur_wp); parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0); - // start moving directly to next waypoint if we're at a 0 pause waypoint and we didn't get quest halted. - if (!AIwalking_timer->Enabled()) - AI_SetupNextWaypoint(); - else - doMove = false; // wipe feign memory since we reached our first waypoint if(cur_wp == 1) ClearFeignMemory(); } - if (doMove) - { // not at waypoint yet or at 0 pause WP, so keep moving + else + { // not at waypoint yet, so keep moving if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0)) CalculateNewPosition2(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true); else @@ -1727,7 +1766,8 @@ void NPC::AI_DoMovement() { SetGrid( 0 - GetGrid()); // revert to AI control Log.Out(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid()); - SetAppearance(eaStanding, false); + if(GetAppearance() != eaStanding) + SetAppearance(eaStanding, false); CalculateNewWaypoint(); } @@ -1763,86 +1803,28 @@ void NPC::AI_DoMovement() { Log.Out(Logs::Detail, Logs::AI, "Reached guard point (%.3f,%.3f,%.3f)", m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z); ClearFeignMemory(); moved=false; - SetMoving(false); if (GetTarget() == nullptr || DistanceSquared(m_Position, GetTarget()->GetPosition()) >= 5*5 ) { SetHeading(m_GuardPoint.w); } else { FaceTarget(GetTarget()); } - SendPosition(); + SetCurrentSpeed(0); SetAppearance(GetGuardPointAnim()); } } } } -void NPC::AI_SetupNextWaypoint() { - 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 restart 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; - - Log.Out(Logs::Detail, Logs::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) { - Log.Out(Logs::Detail, Logs::Pathing, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode."); - roamer = false; - cur_wp = 0; - } - - 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 (GetGrid() > 0) { - CastToNPC()->CalculateNewWaypoint(); - } - } - else { - DistractedFromGrid = false; - } - } -} // 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; - SetAppearance(eaStanding); + if(GetAppearance() != eaStanding) + { + SetAppearance(eaStanding); + } if (iYellForHelp) { if(IsPet()) { @@ -1889,9 +1871,10 @@ void Mob::AI_Event_NoLongerEngaged() { pLastFightingDelayMoving += zone->random.Int(minLastFightingDelayMoving, maxLastFightingDelayMoving); // So mobs don't keep running as a ghost until AIwalking_timer fires // if they were moving prior to losing all hate - if(IsMoving()){ + // except if we're a pet, then we might run into some issues with pets backing off when they should immediately be moving + if(!IsPet()) + { SetRunAnimSpeed(0); - SetMoving(false); SendPosition(); } ClearRampage(); diff --git a/zone/npc.h b/zone/npc.h index f960c736e..95a857460 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -119,7 +119,6 @@ public: virtual void AI_Start(uint32 iMoveDelay = 0); virtual void AI_Stop(); void AI_DoMovement(); - void AI_SetupNextWaypoint(); bool AI_AddNPCSpells(uint32 iDBSpellsID); bool AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID); virtual bool AI_EngagedCastCheck(); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index b9ba00622..eed8305f4 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6188,6 +6188,35 @@ XS(XS_Client_GetTargetRingZ) XSRETURN(1); } +XS(XS_Client_CalcEXP); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_CalcEXP) +{ + dXSARGS; + if (items < 1 || items > 2) + Perl_croak(aTHX_ "Usage: CalcEXP(THIS, uint8 conlevel)"); + { + Client * THIS; + uint8 conlevel = 0xFF; + uint32 RETVAL; + if(items == 2) + conlevel = (uint16)SvUV(ST(1)); + 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 == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + RETVAL = THIS->CalcEXP(conlevel); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + XS(XS_Client_QuestReward); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_QuestReward) { @@ -6482,6 +6511,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetTargetRingY"), XS_Client_GetTargetRingY, file, "$$"); newXSproto(strcpy(buf, "GetTargetRingZ"), XS_Client_GetTargetRingZ, file, "$$"); newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$"); + newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$"); XSRETURN_YES; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index fc942f9fe..d0069683b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -787,8 +787,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (IsClient()) { - AI_Start(); - SendAppearancePacket(14, 100, true, true); + CastToClient()->AI_Start(); } else if(IsNPC()) { CastToNPC()->SetPetSpellID(0); //not a pet spell. } @@ -877,8 +876,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(RuleB(Combat, EnableFearPathing)){ if(IsClient()) { - AI_Start(); - animation = static_cast(GetRunspeed() * 21.0f); //set our animation to match our speed about + CastToClient()->AI_Start(); } CalculateNewFearpoint(); @@ -3911,9 +3909,9 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) if(IsNPC()) { CastToNPC()->RestoreGuardSpotCharm(); - SendAppearancePacket(AT_Pet, 0, true, true); } + SendAppearancePacket(AT_Pet, 0, true, true); Mob* tempmob = GetOwner(); SetOwnerID(0); if(tempmob) @@ -3943,12 +3941,12 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) { InterruptSpell(); if (this->CastToClient()->IsLD()) - AI_Start(CLIENT_LD_TIMEOUT); + CastToClient()->AI_Start(CLIENT_LD_TIMEOUT); else { bool feared = FindType(SE_Fear); if(!feared) - AI_Stop(); + CastToClient()->AI_Stop(); } } break; @@ -3973,7 +3971,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) { bool charmed = FindType(SE_Charm); if(!charmed) - AI_Stop(); + CastToClient()->AI_Stop(); } if(curfp) { diff --git a/zone/spells.cpp b/zone/spells.cpp index d8699d068..f90335e31 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4754,14 +4754,12 @@ void Client::UnStun() { void NPC::Stun(int duration) { Mob::Stun(duration); - SetRunAnimSpeed(0); - SendPosition(); + SetCurrentSpeed(0); } void NPC::UnStun() { Mob::UnStun(); - SetRunAnimSpeed(static_cast(GetRunspeed())); - SendPosition(); + SetCurrentSpeed(GetRunspeed()); } void Mob::Mesmerize() diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 15cf45e20..6ed516da0 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1561,6 +1561,8 @@ bool ZoneDatabase::EnableRecipe(uint32 recipe_id) if (!results.Success()) return results.RowsAffected() > 0; + + return false; } bool ZoneDatabase::DisableRecipe(uint32 recipe_id) @@ -1571,4 +1573,6 @@ bool ZoneDatabase::DisableRecipe(uint32 recipe_id) if (!results.Success()) return results.RowsAffected() > 0; + + return false; } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index f75743a7d..a59e49966 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -394,7 +394,6 @@ void NPC::SetWaypointPause() if (cur_wp_pause == 0) { AIwalking_timer->Start(100); - AIwalking_timer->Trigger(); } else { @@ -437,9 +436,8 @@ void NPC::NextGuardPosition() { { if(moved) { - moved=false; - SetMoving(false); - SendPosition(); + moved = false; + SetCurrentSpeed(0); } } } @@ -490,10 +488,16 @@ float Mob::CalculateHeadingToTarget(float in_x, float in_y) { return (256*(360-angle)/360.0f); } -bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool checkZ) { +bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ) { if(GetID()==0) return true; + if(speed == 0) + { + SetCurrentSpeed(0); + return true; + } + if ((m_Position.x-x == 0) && (m_Position.y-y == 0)) {//spawn is at target coords if(m_Position.z-z != 0) { m_Position.z = z; @@ -515,9 +519,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b return true; } - bool send_update = false; int compare_steps = IsBoat() ? 1 : 20; - if(tar_ndx < compare_steps && m_TargetLocation.x==x && m_TargetLocation.y==y) { float new_x = m_Position.x + m_TargetV.x*tar_vector; @@ -589,7 +591,12 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b m_TargetV.x = x - nx; m_TargetV.y = y - ny; m_TargetV.z = z - nz; - + SetCurrentSpeed((int8)speed); + pRunAnimSpeed = speed; + if(IsClient()) + { + animation = speed; + } //pRunAnimSpeed = (int8)(speed*NPC_RUNANIM_RATIO); //speed *= NPC_SPEED_MULTIPLIER; @@ -599,10 +606,10 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b // 2: get unit vector // -------------------------------------------------------------------------- float mag = sqrtf (m_TargetV.x*m_TargetV.x + m_TargetV.y*m_TargetV.y + m_TargetV.z*m_TargetV.z); - tar_vector = speed / mag; + tar_vector = (float)speed / mag; // mob move fix - int numsteps = (int) ( mag * 20 / speed) + 1; + int numsteps = (int) ( mag * 16.0f / (float)speed); // mob move fix @@ -612,9 +619,9 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b if (numsteps>1) { tar_vector=1.0f ; - m_TargetV.x = m_TargetV.x/numsteps; - m_TargetV.y = m_TargetV.y/numsteps; - m_TargetV.z = m_TargetV.z/numsteps; + m_TargetV.x = 1.25f * m_TargetV.x/(float)numsteps; + m_TargetV.y = 1.25f * m_TargetV.y/(float)numsteps; + m_TargetV.z = 1.25f *m_TargetV.z/(float)numsteps; float new_x = m_Position.x + m_TargetV.x; float new_y = m_Position.y + m_TargetV.y; @@ -640,14 +647,13 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b m_Position.y = y; m_Position.z = z; - tar_ndx = 20; Log.Out(Logs::Detail, Logs::AI, "Only a single step to get there... jumping."); } } else { - tar_vector/=20.0f; + tar_vector/=16.0f; float new_x = m_Position.x + m_TargetV.x*tar_vector; float new_y = m_Position.y + m_TargetV.y*tar_vector; @@ -703,32 +709,20 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f); if (IsClient()) - { SendPosUpdate(1); - CastToClient()->ResetPositionTimer(); - } else - { - // force an update now - move_tic_count = RuleI(Zone, NPCPositonUpdateTicCount); SendPosUpdate(); - SetAppearance(eaStanding, false); - } - pLastChange = Timer::GetCurrentTime(); + SetAppearance(eaStanding, false); + pLastChange = Timer::GetCurrentTime(); return true; } -bool Mob::CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ) { - if(IsNPC() || IsClient() || IsPet()) { - pRunAnimSpeed = (int8)(speed*NPC_RUNANIM_RATIO); - speed *= NPC_SPEED_MULTIPLIER; - } - +bool Mob::CalculateNewPosition2(float x, float y, float z, int speed, bool checkZ, bool calcHeading) { return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ); } -bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool checkZ) { +bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ, bool calcHeading) { if(GetID()==0) return true; @@ -737,14 +731,12 @@ bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool chec float nz = m_Position.z; // if NPC is rooted - if (speed == 0.0) { + if (speed == 0) { SetHeading(CalculateHeadingToTarget(x, y)); if(moved){ - SendPosition(); - SetMoving(false); + SetCurrentSpeed(0); moved=false; } - SetRunAnimSpeed(0); Log.Out(Logs::Detail, Logs::AI, "Rooted while calculating new position to (%.3f, %.3f, %.3f)", x, y, z); return true; } @@ -756,8 +748,8 @@ bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool chec if (m_TargetV.x == 0 && m_TargetV.y == 0) return false; - pRunAnimSpeed = (uint8)(speed*NPC_RUNANIM_RATIO); - speed *= NPC_SPEED_MULTIPLIER; + SetCurrentSpeed((int8)(speed)); //*NPC_RUNANIM_RATIO); + //speed *= NPC_SPEED_MULTIPLIER; Log.Out(Logs::Detail, Logs::AI, "Calculating new position to (%.3f, %.3f, %.3f) vector (%.3f, %.3f, %.3f) rate %.3f RAS %d", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z, speed, pRunAnimSpeed); diff --git a/zone/zone.cpp b/zone/zone.cpp index 56181695d..3bf2173c9 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -2209,9 +2209,9 @@ void Zone::ReloadWorld(uint32 Option){ entity_list.ClearAreas(); parse->ReloadQuests(); } else if(Option == 1) { - zone->Repop(0); entity_list.ClearAreas(); parse->ReloadQuests(); + zone->Repop(0); } } From 5c4389effb571a4cf2bfb0a73d0c849e2a52e3eb Mon Sep 17 00:00:00 2001 From: SecretsOTheP Date: Mon, 25 May 2015 12:39:36 -0400 Subject: [PATCH 102/846] Revert custom changes that came with my code load --- zone/bonuses.cpp | 192 +++++++++++++++++------------------------------ zone/effects.cpp | 51 +++++++------ 2 files changed, 95 insertions(+), 148 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 0c9c6d904..5dd7440f6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -335,8 +335,8 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu } //FatherNitwit: New style haste, shields, and regens - if((int32)item->Haste > 0) { - newbon->haste += item->Haste; + if(newbon->haste < (int32)item->Haste) { + newbon->haste = item->Haste; } if(item->Regen > 0) newbon->HPRegen += item->Regen; @@ -390,10 +390,10 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu newbon->HitChance += item->Accuracy; } if(item->CombatEffects > 0) { - if((newbon->MeleeDamage + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) - newbon->MeleeDamage = RuleI(Character, ItemCombatEffectsCap); + if((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) + newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap); else - newbon->MeleeDamage += item->CombatEffects; + newbon->ProcChance += item->CombatEffects; } if(item->DotShielding > 0) { if((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) @@ -428,7 +428,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu 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, item->Worn.Type); + ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); } if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects @@ -559,7 +559,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool /* Powerful Non-live like option allows developers to add worn effects on items that can stack with other worn effects of the same spell effect type, instead of only taking the highest value. - Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus. + Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus. To enable use RuleI(Spells, AdditiveBonusWornType) Setting value = 2 Will force all live items to automatically be calculated additivily Setting value to anything else will indicate the item 'worntype' that if set to the same, will cause the bonuses to use this calculation @@ -579,7 +579,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if(GetLevel() < item->ReqLevel) return; - + if (item->Worn.Effect > 0 && item->Worn.Type == RuleI(Spells, AdditiveBonusWornType)) ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);// Non-live like - Addititive latent effects @@ -691,7 +691,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) continue; Log.Out(Logs::Detail, Logs::AA, "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) { @@ -1007,7 +1007,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_BlockBehind: newbon->BlockBehind += base1; break; - + case SE_StrikeThrough: case SE_StrikeThrough2: newbon->StrikeThrough += base1; @@ -1313,7 +1313,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_Vampirism: newbon->Vampirism += base1; - break; + break; case SE_FrenziedDevastation: newbon->FrenziedDevastation += base2; @@ -1416,7 +1416,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) } case SE_SkillProcSuccess:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid) @@ -1449,7 +1449,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) int 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, 0, buffs[i].ticsremaining,i); + ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, 0, buffs[i].ticsremaining, i, buffs[i].instrument_mod); if (buffs[i].numhits > 0) Numhits(true); @@ -1472,8 +1472,9 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } -void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, uint8 WornType, uint32 ticsremaining, int buffslot, - bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) +void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *new_bonus, uint16 casterId, + uint8 WornType, int32 ticsremaining, int buffslot, int instrument_mod, + bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) { int i, effect_value, base2, max, effectid; bool AdditiveWornBonus = false; @@ -1509,9 +1510,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (WornType && (RuleI(Spells, AdditiveBonusWornType) == WornType)) AdditiveWornBonus = true; - + effectid = spells[spell_id].effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining); + effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, caster, ticsremaining); base2 = spells[spell_id].base2[i]; max = spells[spell_id].max[i]; } @@ -1560,100 +1561,49 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_AttackSpeed: { - - if (AdditiveWornBonus) { - if ((effect_value - 100) > 0) { // Haste - if (new_bonus->haste < 0) break; // Slowed - Don't apply haste - if ((effect_value - 100) > new_bonus->haste) { - new_bonus->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 < new_bonus->haste) - new_bonus->haste += real_slow_value; + if ((effect_value - 100) > 0) { // Haste + if (new_bonus->haste < 0) break; // Slowed - Don't apply haste + if ((effect_value - 100) > new_bonus->haste) { + new_bonus->haste = effect_value - 100; } } - else - { - if ((effect_value - 100) > 0) { // Haste - if (new_bonus->haste < 0) break; // Slowed - Don't apply haste - if ((effect_value - 100) > new_bonus->haste) { - new_bonus->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 < new_bonus->haste) - new_bonus->haste = real_slow_value; - } + 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 < new_bonus->haste) + new_bonus->haste = real_slow_value; } break; } case SE_AttackSpeed2: - { - if (AdditiveWornBonus) { - if ((effect_value - 100) > 0) { // Haste - if (new_bonus->hastetype2 < 0) break; // Slowed - Don't apply haste - if ((effect_value - 100) > new_bonus->hastetype2) { - new_bonus->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 < new_bonus->hastetype2) - new_bonus->hastetype2 += real_slow_value; + { + if ((effect_value - 100) > 0) { // Haste V2 - Stacks with V1 but does not Overcap + if (new_bonus->hastetype2 < 0) break; //Slowed - Don't apply haste2 + if ((effect_value - 100) > new_bonus->hastetype2) { + new_bonus->hastetype2 = effect_value - 100; } } - else - { - if ((effect_value - 100) > 0) { // Haste - if (new_bonus->hastetype2 < 0) break; // Slowed - Don't apply haste - if ((effect_value - 100) > new_bonus->hastetype2) { - new_bonus->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 < new_bonus->hastetype2) - new_bonus->hastetype2 = real_slow_value; - } + 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 < new_bonus->hastetype2) + new_bonus->hastetype2 = real_slow_value; } break; } case SE_AttackSpeed3: { - if (AdditiveWornBonus) { - if (effect_value < 0){ //Slow - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value < new_bonus->hastetype3) - new_bonus->hastetype3 += effect_value; - } - - else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps - if (effect_value > new_bonus->hastetype3) { - new_bonus->hastetype3 += effect_value; - } - } + if (effect_value < 0){ //Slow + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value < new_bonus->hastetype3) + new_bonus->hastetype3 = effect_value; } - else - { - if (effect_value < 0){ //Slow - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value < new_bonus->hastetype3) - new_bonus->hastetype3 = effect_value; - } - else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps - if (effect_value > new_bonus->hastetype3) { - new_bonus->hastetype3 = effect_value; - } + else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps + if (effect_value > new_bonus->hastetype3) { + new_bonus->hastetype3 = effect_value; } } break; @@ -1668,21 +1618,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (effect_value < 0) //A few spells use negative values(Descriptions all indicate it should be a slow) effect_value = effect_value * -1; - if (AdditiveWornBonus) { - if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) { - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value > new_bonus->inhibitmelee) - new_bonus->inhibitmelee += effect_value; - } - } - else - { - if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) { - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value > new_bonus->inhibitmelee) - new_bonus->inhibitmelee = effect_value; - } + + if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) { + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value > new_bonus->inhibitmelee) + new_bonus->inhibitmelee = effect_value; } + break; } @@ -1898,7 +1840,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne new_bonus->DamageShieldType = GetDamageShieldType(spell_id, max); else new_bonus->DamageShieldType = GetDamageShieldType(spell_id); - + break; } @@ -2079,7 +2021,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_Vampirism: new_bonus->Vampirism += effect_value; - break; + break; case SE_AllInstrumentMod: { @@ -2322,7 +2264,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CriticalSpellChance: { new_bonus->CriticalSpellChance += effect_value; - + if (base2 > new_bonus->SpellCritDmgIncNoStack) new_bonus->SpellCritDmgIncNoStack = base2; break; @@ -2532,7 +2474,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_NegateAttacks: { - if (!new_bonus->NegateAttacks[0] || + if (!new_bonus->NegateAttacks[0] || ((new_bonus->NegateAttacks[0] && new_bonus->NegateAttacks[2]) && (new_bonus->NegateAttacks[2] < max))){ new_bonus->NegateAttacks[0] = 1; new_bonus->NegateAttacks[1] = buffslot; @@ -2552,7 +2494,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } - + case SE_MeleeThresholdGuard: { if (new_bonus->MeleeThresholdGuard[0] < effect_value){ @@ -2919,17 +2861,17 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne new_bonus->NegateIfCombat = true; break; - case SE_Screech: + case SE_Screech: new_bonus->Screech = effect_value; break; case SE_AlterNPCLevel: if (IsNPC()){ - if (!new_bonus->AlterNPCLevel - || ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value)) + if (!new_bonus->AlterNPCLevel + || ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value)) || ((effect_value > 0) && (new_bonus->AlterNPCLevel < effect_value))) { - + int tmp_lv = GetOrigLevel() + effect_value; if (tmp_lv < 1) tmp_lv = 1; @@ -2967,7 +2909,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne new_bonus->BerserkSPA = true; break; - + case SE_Metabolism: new_bonus->Metabolism += effect_value; break; @@ -3068,7 +3010,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } case SE_SkillProc:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(new_bonus->SkillProc[e] && new_bonus->SkillProc[e] == spell_id) @@ -3083,7 +3025,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } case SE_SkillProcSuccess:{ - + for(int e = 0; e < MAX_SKILL_PROCS; e++) { if(new_bonus->SkillProcSuccess[e] && new_bonus->SkillProcSuccess[e] == spell_id) @@ -3099,9 +3041,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { - + //Non-Focused Effect to modify incoming spell damage by resist type. - case SE_FcSpellVulnerability: + case SE_FcSpellVulnerability: ModVulnerability(base2, effect_value); break; } @@ -3167,7 +3109,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) newbon->HitChance += cur->Accuracy; } if(cur->CombatEffects > 0) { - newbon->MeleeDamage += cur->CombatEffects; + newbon->ProcChance += cur->CombatEffects; } if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon, 0, cur->Worn.Type); @@ -4453,7 +4395,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.SlayUndead[0] = effect_value; aabonuses.SlayUndead[1] = effect_value; break; - + case SE_DoubleRangedAttack: spellbonuses.DoubleRangedAttack = effect_value; aabonuses.DoubleRangedAttack = effect_value; @@ -4473,7 +4415,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.ShieldEquipDmgMod[1] = effect_value; itembonuses.ShieldEquipDmgMod[0] = effect_value; itembonuses.ShieldEquipDmgMod[1] = effect_value; - break; + break; case SE_TriggerMeleeThreshold: spellbonuses.TriggerMeleeThreshold = false; diff --git a/zone/effects.cpp b/zone/effects.cpp index c7066da68..c814ea554 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -89,7 +89,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { if (IsClient() && GetClass() == WIZARD) ratio += RuleI(Spells, WizCritRatio); //Default is zero - + if (Critical){ value = value_BaseEffect*ratio/100; @@ -138,7 +138,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); - if(itembonuses.SpellDmg) + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -172,7 +172,7 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100; value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100; value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100; - extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + + extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) + GetFocusEffect(focusFcDamageAmt, spell_id); @@ -200,11 +200,6 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { extra_dmg /= duration; } - //Sanctuary Custom: Spelldmg per tick - if(itembonuses.SpellDmg) - value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg / 6, value); //per tick - - value -= extra_dmg; } @@ -216,6 +211,23 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg) { + int total_cast_time = 0; + + if (spells[spell_id].recast_time >= spells[spell_id].recovery_time) + total_cast_time = spells[spell_id].recast_time + spells[spell_id].cast_time; + else + total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time; + + if (total_cast_time > 0 && total_cast_time <= 2500) + extra_spell_amt = extra_spell_amt*25/100; + else if (total_cast_time > 2500 && total_cast_time < 7000) + extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000; + else + extra_spell_amt = extra_spell_amt * total_cast_time / 7000; + + if(extra_spell_amt*2 < base_spell_dmg) + return 0; + return extra_spell_amt; } @@ -258,7 +270,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { value += GetFocusEffect(focusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(itembonuses.HealAmt) + if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier; value += value*target->GetHealRate(spell_id, this)/100; @@ -269,7 +281,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (Critical) { entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetName(), itoa(value)); - + if (IsClient()) Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value)); } @@ -289,9 +301,6 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if(chance && zone->random.Roll(chance)) value *= 2; - - if(itembonuses.HealAmt) - value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt / 6, value) * modifier; } if (IsNPC() && CastToNPC()->GetHealScale()) @@ -412,14 +421,10 @@ int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) int tic_inc = 0; tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id); - // Only need this for clients, since the change was for bard songs, I assume we should keep non bard songs getting +1 - // However if its bard or not and is mez, charm or fear, we need to add 1 so that client is in sync - if (IsClient() && !(IsShortDurationBuff(spell_id) && IsBardSong(spell_id)) || - IsFearSpell(spell_id) || - IsCharmSpell(spell_id) || - IsMezSpell(spell_id) || - IsBlindSpell(spell_id)) - tic_inc += 1; + // unsure on the exact details, but bard songs that don't cost mana at some point get an extra tick, 60 for now + // a level 53 bard reported getting 2 tics + if (IsShortDurationBuff(spell_id) && IsBardSong(spell_id) && spells[spell_id].mana == 0 && GetClass() == BARD && GetLevel() > 60) + tic_inc++; return (((duration * increase) / 100) + tic_inc); } @@ -762,7 +767,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } else { - if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) + if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); if (!spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); @@ -850,7 +855,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff if (!center->CheckLosFN(curmob)) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... - // See notes in AESpell() above for more info. + // See notes in AESpell() above for more info. if (caster->IsAttackAllowed(curmob, true)) continue; if (caster->CheckAggro(curmob)) From 41ca23eb7cab1b2e2c099c936ae5077d93af9c79 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 25 May 2015 13:20:26 -0400 Subject: [PATCH 103/846] Revert "Making $npc->RemoveFromHateList actually work" --- zone/perl_npc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 861759d12..0c9cec797 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -823,7 +823,7 @@ XS(XS_NPC_RemoveFromHateList) if(ent == nullptr) Perl_croak(aTHX_ "ent is nullptr, avoiding crash."); - THIS->CastToMob()->RemoveFromHateList(ent); + THIS->RemoveFromHateList(ent); } XSRETURN_EMPTY; From ee136881c8a66e025dfdbc2e2e137c514d3b58a2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 25 May 2015 23:48:11 -0500 Subject: [PATCH 104/846] Implemented disjointed zone based time, this can be triggered via quest methods Added parameter to LUA and Perl method settime(hour, minute, [update_world = true]) - If update_world is false, the zone will then unsubscribe itself from regular worldserver time synchronizations Added DB ver 9082 with update to add npc_types texture columns if table does not currently have them --- changelog.txt | 7 +++++ common/eqtime.cpp | 6 ++-- common/eqtime.h | 6 ++-- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + world/zoneserver.cpp | 2 +- zone/client_packet.cpp | 2 +- zone/command.cpp | 6 ++-- zone/embparser.cpp | 2 +- zone/embparser_api.cpp | 23 +++++++++++---- zone/lua_general.cpp | 11 +++++-- zone/questmgr.cpp | 5 ++-- zone/questmgr.h | 2 +- zone/spawn2.cpp | 10 +++---- zone/worldserver.cpp | 48 +++++++++++++++++-------------- zone/zone.cpp | 49 +++++++++++++++++++++++++------- zone/zone.h | 11 +++++-- 17 files changed, 128 insertions(+), 65 deletions(-) diff --git a/changelog.txt b/changelog.txt index 6c5d695ab..7d965260c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- + +== 05/25/2015 == +Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods +Akkadius: Added parameter to LUA and Perl method settime(hour, minute, [update_world = true]) + - If update_world is false, the zone will then unsubscribe itself from regular worldserver time synchronizations +Akkadius: Added DB ver 9082 with update to add npc_types texture columns if table does not currently have them + == 05/22/2015 == Uleat: Added null-term declaration for character names in ENCODE(OP_CharInfo) - where appropriate diff --git a/common/eqtime.cpp b/common/eqtime.cpp index 79301a28f..cb3afb37d 100644 --- a/common/eqtime.cpp +++ b/common/eqtime.cpp @@ -55,7 +55,7 @@ EQTime::EQTime() //Set default time zone timezone=0; //Start EQTimer - setEQTimeOfDay(start, time(0)); + SetCurrentEQTimeOfDay(start, time(0)); } EQTime::~EQTime() @@ -67,7 +67,7 @@ EQTime::~EQTime() //Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to. //Output: 0=Error, 1=Sucess -int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeOfDay ) +int EQTime::GetCurrentEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeOfDay ) { /* check to see if we have a reference time to go by. */ if( eqTime.start_realtime == 0 ) @@ -124,7 +124,7 @@ int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeO } //setEQTimeOfDay -int EQTime::setEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real) +int EQTime::SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real) { if(start_real==0) return 0; diff --git a/common/eqtime.h b/common/eqtime.h index aa608f307..aeda9f0f6 100644 --- a/common/eqtime.h +++ b/common/eqtime.h @@ -21,8 +21,8 @@ public: ~EQTime(); //Get functions - int getEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(getEQTimeOfDay(time(nullptr), eqTimeOfDay)); } - int getEQTimeOfDay( time_t timeConvert, TimeOfDay_Struct *eqTimeOfDay ); + int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); } + int GetCurrentEQTimeOfDay( time_t timeConvert, TimeOfDay_Struct *eqTimeOfDay ); TimeOfDay_Struct getStartEQTime() { return eqTime.start_eqtime; } time_t getStartRealTime() { return eqTime.start_realtime; } uint32 getEQTimeZone() { return timezone; } @@ -30,7 +30,7 @@ public: uint32 getEQTimeZoneMin() { return timezone%60; } //Set functions - int setEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real); + int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real); void setEQTimeZone(int32 in_timezone) { timezone=in_timezone; } //Time math/logic functions diff --git a/common/version.h b/common/version.h index 062afdecd..78f7a67b3 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 9080 +#define CURRENT_BINARY_DATABASE_VERSION 9082 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 34330f041..5ca25a029 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -335,6 +335,7 @@ 9079|2015_05_23_BuffDurations.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'ticsremaining'|contains|unsigned| 9080|2015_05_23_PetBuffInstrumentMod.sql|SHOW COLUMNS FROM `character_pet_buffs` LIKE 'instrument_mod'|empty| 9081|2015_05_23_dbstr_us.sql|SHOW TABLES LIKE 'db_str'|empty| +9082|2015_05_25_npc_types_texture_fields.sql|SHOW COLUMNS FROM `npc_types` LIKE 'armtexture'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index b40f3dc04..17cac7f62 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -964,7 +964,7 @@ bool ZoneServer::Process() { case ServerOP_SetWorldTime: { Log.Out(Logs::Detail, Logs::World_Server,"Received SetWorldTime"); eqTimeOfDay* newtime = (eqTimeOfDay*) pack->pBuffer; - zoneserver_list.worldclock.setEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime); + zoneserver_list.worldclock.SetCurrentEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime); Log.Out(Logs::Detail, Logs::World_Server,"New time = %d-%d-%d %d:%d (%d)\n", newtime->start_eqtime.year, newtime->start_eqtime.month, (int)newtime->start_eqtime.day, (int)newtime->start_eqtime.hour, (int)newtime->start_eqtime.minute, (int)newtime->start_realtime); zoneserver_list.worldclock.saveFile(WorldConfig::get()->EQTimeFile.c_str()); zoneserver_list.SendTimeSync(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 3f40f3c00..9f527476c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1703,7 +1703,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* Time of Day packet */ outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); TimeOfDay_Struct* tod = (TimeOfDay_Struct*)outapp->pBuffer; - zone->zone_time.getEQTimeOfDay(time(0), tod); + zone->zone_time.GetCurrentEQTimeOfDay(time(0), tod); outapp->priority = 6; FastQueuePacket(&outapp); diff --git a/zone/command.cpp b/zone/command.cpp index a62ee4ce8..a286f92bd 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1369,7 +1369,7 @@ void command_date(Client *c, const Seperator *sep) else { int h=0, m=0; TimeOfDay_Struct eqTime; - zone->zone_time.getEQTimeOfDay( time(0), &eqTime); + zone->zone_time.GetCurrentEQTimeOfDay( time(0), &eqTime); if(!sep->IsNumber(4)) h=eqTime.hour; else @@ -1402,7 +1402,7 @@ void command_timezone(Client *c, const Seperator *sep) // Update all clients with new TZ. EQApplicationPacket* outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); TimeOfDay_Struct* tod = (TimeOfDay_Struct*)outapp->pBuffer; - zone->zone_time.getEQTimeOfDay(time(0), tod); + zone->zone_time.GetCurrentEQTimeOfDay(time(0), tod); entity_list.QueueClients(c, outapp); safe_delete(outapp); } @@ -4393,7 +4393,7 @@ void command_time(Client *c, const Seperator *sep) else { c->Message(13, "To set the Time: #time HH [MM]"); TimeOfDay_Struct eqTime; - zone->zone_time.getEQTimeOfDay( time(0), &eqTime); + zone->zone_time.GetCurrentEQTimeOfDay( time(0), &eqTime); sprintf(timeMessage,"%02d:%s%d %s (Timezone: %ih %im)", ((eqTime.hour - 1) % 12) == 0 ? 12 : ((eqTime.hour - 1) % 12), (eqTime.minute < 10) ? "0" : "", diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 326585806..d571dce24 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1072,7 +1072,7 @@ void PerlembParser::ExportZoneVariables(std::string &package_name) { ExportVar(package_name.c_str(), "instanceid", zone->GetInstanceID()); ExportVar(package_name.c_str(), "instanceversion", zone->GetInstanceVersion()); TimeOfDay_Struct eqTime; - zone->zone_time.getEQTimeOfDay( time(0), &eqTime); + zone->zone_time.GetCurrentEQTimeOfDay( time(0), &eqTime); ExportVar(package_name.c_str(), "zonehour", eqTime.hour - 1); ExportVar(package_name.c_str(), "zonemin", eqTime.minute); ExportVar(package_name.c_str(), "zonetime", (eqTime.hour - 1) * 100 + eqTime.minute); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 800ed9f83..6db7777ac 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1182,13 +1182,26 @@ XS(XS__settime); XS(XS__settime) { dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: settime(new_hour, new_min)"); + if (items < 2) + Perl_croak(aTHX_ "Usage: settime(new_hour, new_min, [update_world = true])"); - int new_hour = (int)SvIV(ST(0)); - int new_min = (int)SvIV(ST(1)); + if (items == 2){ + int new_hour = (int)SvIV(ST(0)); + int new_min = (int)SvIV(ST(1)); + quest_manager.settime(new_hour, new_min, true); + } + else if (items == 3){ + int new_hour = (int)SvIV(ST(0)); + int new_min = (int)SvIV(ST(1)); - quest_manager.settime(new_hour, new_min); + int update_world = (int)SvIV(ST(2)); + if (update_world == 1){ + quest_manager.settime(new_hour, new_min, true); + } + else{ + quest_manager.settime(new_hour, new_min, false); + } + } XSRETURN_EMPTY; } diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 59a5d3740..6b290dc03 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -386,7 +386,11 @@ void lua_create_guild(const char *name, const char *leader) { } void lua_set_time(int hour, int min) { - quest_manager.settime(hour, min); + quest_manager.settime(hour, min, true); +} + +void lua_set_time(int hour, int min, bool update_world) { + quest_manager.settime(hour, min, update_world); } void lua_signal(int npc_id, int signal_id) { @@ -979,7 +983,7 @@ int lua_get_zone_weather() { luabind::adl::object lua_get_zone_time(lua_State *L) { TimeOfDay_Struct eqTime; - zone->zone_time.getEQTimeOfDay(time(0), &eqTime); + zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime); luabind::adl::object ret = luabind::newtable(L); ret["zone_hour"] = eqTime.hour - 1; @@ -1467,7 +1471,8 @@ luabind::scope lua_register_general() { luabind::def("set_sky", &lua_set_sky), luabind::def("set_guild", &lua_set_guild), luabind::def("create_guild", &lua_create_guild), - luabind::def("set_time", &lua_set_time), + luabind::def("set_time", (void(*)(int, int))&lua_set_time), + luabind::def("set_time", (void(*)(int, int, bool))&lua_set_time), luabind::def("signal", (void(*)(int,int))&lua_signal), luabind::def("signal", (void(*)(int,int,int))&lua_signal), luabind::def("set_global", &lua_set_global), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index b9025956e..6b5c8978d 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1292,9 +1292,10 @@ void QuestManager::CreateGuild(const char *guild_name, const char *leader) { } } -void QuestManager::settime(uint8 new_hour, uint8 new_min) { +void QuestManager::settime(uint8 new_hour, uint8 new_min, bool update_world /*= true*/) +{ if (zone) - zone->SetTime(new_hour + 1, new_min); + zone->SetTime(new_hour + 1, new_min, update_world); } void QuestManager::itemlink(int item_id) { diff --git a/zone/questmgr.h b/zone/questmgr.h index b278e2c2a..879407dc6 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -126,7 +126,7 @@ public: void setsky(uint8 new_sky); void setguild(uint32 new_guild_id, uint8 new_rank); void CreateGuild(const char *guild_name, const char *leader); - void settime(uint8 new_hour, uint8 new_min); + void settime(uint8 new_hour, uint8 new_min, bool update_world = true); void itemlink(int item_id); void signal(int npc_id, int wait_ms = 0); void signalwith(int npc_id, int signal_id, int wait_ms = 0); diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index c0eafea80..c42356ea9 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -624,7 +624,7 @@ void SpawnConditionManager::Process() { //get our current time TimeOfDay_Struct tod; - zone->zone_time.getEQTimeOfDay(&tod); + zone->zone_time.GetCurrentEQTimeOfDay(&tod); //see if time is past our nearest event. if(EQTime::IsTimeBefore(&next_event, &tod)) @@ -673,7 +673,7 @@ void SpawnConditionManager::ExecEvent(SpawnEvent &event, bool send_update) { } TimeOfDay_Struct tod; - zone->zone_time.getEQTimeOfDay(&tod); + zone->zone_time.GetCurrentEQTimeOfDay(&tod); if(event.strict && (event.next.hour != tod.hour || event.next.day != tod.day || event.next.month != tod.month || event.next.year != tod.year)) { Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Unable to execute. Condition is strict, and event time has already passed.", event.id); @@ -871,7 +871,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in //better solution, and I just dont care thats much. //get our current time TimeOfDay_Struct tod; - zone->zone_time.getEQTimeOfDay(&tod); + zone->zone_time.GetCurrentEQTimeOfDay(&tod); for(auto cur = spawn_events.begin(); cur != spawn_events.end(); ++cur) { SpawnEvent &cevent = *cur; @@ -1096,7 +1096,7 @@ void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool stri if(reset_base) { Log.Out(Logs::Detail, Logs::Spawns, "Spawn event %d located in this zone. State set. Trigger time reset (period %d).", event_id, cevent.period); //start with the time now - zone->zone_time.getEQTimeOfDay(&cevent.next); + zone->zone_time.GetCurrentEQTimeOfDay(&cevent.next); //advance the next time by our period EQTime::AddMinutes(cevent.period, &cevent.next); } else { @@ -1141,7 +1141,7 @@ void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool stri if(reset_base) { Log.Out(Logs::Detail, Logs::Spawns, "Spawn event %d is in zone %s. State set. Trigger time reset (period %d). Notifying world.", event_id, zone_short_name.c_str(), e.period); //start with the time now - zone->zone_time.getEQTimeOfDay(&e.next); + zone->zone_time.GetCurrentEQTimeOfDay(&e.next); //advance the next time by our period EQTime::AddMinutes(e.period, &e.next); } else { diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index aa3e32d43..517106aca 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -742,32 +742,36 @@ void WorldServer::Process() { break; } case ServerOP_SyncWorldTime: { - if(zone!=0) { + if (zone != 0 && !zone->is_zone_time_localized) { Log.Out(Logs::Moderate, Logs::Zone_Server, "%s Received Message SyncWorldTime", __FUNCTION__); - eqTimeOfDay* newtime = (eqTimeOfDay*) pack->pBuffer; - zone->zone_time.setEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime); + + eqTimeOfDay* newtime = (eqTimeOfDay*)pack->pBuffer; + zone->zone_time.SetCurrentEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime); EQApplicationPacket* outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); - TimeOfDay_Struct* tod = (TimeOfDay_Struct*)outapp->pBuffer; - zone->zone_time.getEQTimeOfDay(time(0), tod); + TimeOfDay_Struct* time_of_day = (TimeOfDay_Struct*)outapp->pBuffer; + zone->zone_time.GetCurrentEQTimeOfDay(time(0), time_of_day); entity_list.QueueClients(0, outapp, false); safe_delete(outapp); - //TEST - char timeMessage[255]; - time_t timeCurrent = time(nullptr); - TimeOfDay_Struct eqTime; - zone->zone_time.getEQTimeOfDay( timeCurrent, &eqTime); - //if ( eqTime.hour >= 0 && eqTime.minute >= 0 ) - //{ - sprintf(timeMessage,"EQTime [%02d:%s%d %s]", - ((eqTime.hour - 1) % 12) == 0 ? 12 : ((eqTime.hour - 1) % 12), - (eqTime.minute < 10) ? "0" : "", - eqTime.minute, - (eqTime.hour >= 13) ? "pm" : "am" - ); - Log.Out(Logs::General, Logs::Zone_Server, "Time Broadcast Packet: %s", timeMessage); - zone->GotCurTime(true); - //} - //Test + + /* Buffer garbage to generate debug message */ + char time_message[255]; + time_t current_time = time(nullptr); + TimeOfDay_Struct eq_time; + zone->zone_time.GetCurrentEQTimeOfDay(current_time, &eq_time); + + sprintf(time_message, "EQTime [%02d:%s%d %s]", + ((eq_time.hour - 1) % 12) == 0 ? 12 : ((eq_time.hour - 1) % 12), + (eq_time.minute < 10) ? "0" : "", + eq_time.minute, + (eq_time.hour >= 13) ? "pm" : "am" + ); + + Log.Out(Logs::General, Logs::Zone_Server, "Time Broadcast Packet: %s", time_message); + zone->SetZoneHasCurrentTime(true); + + } + if (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; } diff --git a/zone/zone.cpp b/zone/zone.cpp index 3bf2173c9..e58bea24a 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -697,7 +697,7 @@ void Zone::Shutdown(bool quite) Log.Out(Logs::General, Logs::Status, "Zone Shutdown: %s (%i)", zone->GetShortName(), zone->GetZoneID()); petition_list.ClearPetitions(); - zone->GotCurTime(false); + zone->SetZoneHasCurrentTime(false); if (!quite) Log.Out(Logs::General, Logs::Normal, "Zone shutdown: going to sleep"); ZoneLoaded = false; @@ -760,6 +760,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) qGlobals = nullptr; default_ruleset = 0; + is_zone_time_localized = false; + loglevelvar = 0; merchantvar = 0; tradevar = 0; @@ -805,7 +807,7 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) totalBS = 0; aas = nullptr; totalAAs = 0; - gottime = false; + zone_has_current_time = false; Instance_Shutdown_Timer = nullptr; bool is_perma = false; @@ -1484,7 +1486,7 @@ void Zone::Repop(uint32 delay) { void Zone::GetTimeSync() { - if (worldserver.Connected() && !gottime) { + if (worldserver.Connected() && !zone_has_current_time) { ServerPacket* pack = new ServerPacket(ServerOP_GetWorldTime, 0); worldserver.SendPacket(pack); safe_delete(pack); @@ -1508,17 +1510,42 @@ void Zone::SetDate(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute } } -void Zone::SetTime(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)); - eqTimeOfDay* eqtod = (eqTimeOfDay*)pack->pBuffer; - zone_time.getEQTimeOfDay(time(0), &eqtod->start_eqtime); - eqtod->start_eqtime.minute=minute; - eqtod->start_eqtime.hour=hour; - eqtod->start_realtime=time(0); - printf("Setting master time on world server to: %d:%d (%d)\n", hour, minute, (int)eqtod->start_realtime); - worldserver.SendPacket(pack); + eqTimeOfDay* eq_time_of_day = (eqTimeOfDay*)pack->pBuffer; + + zone_time.GetCurrentEQTimeOfDay(time(0), &eq_time_of_day->start_eqtime); + + eq_time_of_day->start_eqtime.minute = minute; + eq_time_of_day->start_eqtime.hour = hour; + eq_time_of_day->start_realtime = time(0); + + /* By Default we update worlds time, but we can optionally no update world which updates the rest of the zone servers */ + if (update_world){ + Log.Out(Logs::General, Logs::Zone_Server, "Setting master time on world server to: %d:%d (%d)\n", hour, minute, (int)eq_time_of_day->start_realtime); + worldserver.SendPacket(pack); + + /* Set Time Localization Flag */ + zone->is_zone_time_localized = false; + } + /* When we don't update world, we are localizing ourselves, we become disjointed from normal syncs and set time locally */ + else{ + + 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)); + TimeOfDay_Struct* time_of_day = (TimeOfDay_Struct*)outapp->pBuffer; + zone->zone_time.GetCurrentEQTimeOfDay(time(0), time_of_day); + entity_list.QueueClients(0, outapp, false); + safe_delete(outapp); + + /* Set Time Localization Flag */ + zone->is_zone_time_localized = true; + } + safe_delete(pack); } } diff --git a/zone/zone.h b/zone/zone.h index 80e0473f2..7b1b855a7 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -43,6 +43,7 @@ struct ZonePoint int32 target_zone_instance; uint32 client_version_mask; }; + struct ZoneClientAuth_Struct { uint32 ip; // client's IP address uint32 wid; // client's WorldID# @@ -85,6 +86,10 @@ public: Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name); ~Zone(); + + /* When zone has its own version of time */ + bool is_zone_time_localized; + bool Init(bool iStaticZone); bool LoadZoneCFG(const char* filename, uint16 instance_id, bool DontLoadDefault = false); bool SaveZoneCFG(); @@ -153,7 +158,7 @@ public: inline bool InstantGrids() { return(!initgrids_timer.Enabled()); } void SetStaticZone(bool sz) { staticzone = sz; } inline bool IsStaticZone() { return staticzone; } - inline void GotCurTime(bool time) { gottime = time; } + inline void SetZoneHasCurrentTime(bool time) { zone_has_current_time = time; } void SpawnConditionChanged(const SpawnCondition &c, int16 old_value); @@ -206,7 +211,7 @@ public: EQTime zone_time; void GetTimeSync(); void SetDate(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute); - void SetTime(uint8 hour, uint8 minute); + void SetTime(uint8 hour, uint8 minute, bool update_world = true); void weatherSend(); bool CanBind() const { return(can_bind); } @@ -319,7 +324,7 @@ private: bool staticzone; - bool gottime; + bool zone_has_current_time; uint32 pQueuedMerchantsWorkID; uint32 pQueuedTempMerchantsWorkID; From d2a1fb7acfeadc391e9d4bde0b9158ea03d9fa29 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 25 May 2015 23:49:11 -0500 Subject: [PATCH 105/846] Add file 2015_05_25_npc_types_texture_fields.sql --- .../git/required/2015_05_25_npc_types_texture_fields.sql | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 utils/sql/git/required/2015_05_25_npc_types_texture_fields.sql diff --git a/utils/sql/git/required/2015_05_25_npc_types_texture_fields.sql b/utils/sql/git/required/2015_05_25_npc_types_texture_fields.sql new file mode 100644 index 000000000..acd8d26b6 --- /dev/null +++ b/utils/sql/git/required/2015_05_25_npc_types_texture_fields.sql @@ -0,0 +1,6 @@ +ALTER TABLE npc_types +ADD COLUMN `armtexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `raid_target`, +ADD COLUMN `bracertexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `armtexture`, +ADD COLUMN `handtexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `bracertexture`, +ADD COLUMN `legtexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `handtexture`, +ADD COLUMN `feettexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `legtexture`; \ No newline at end of file From b6091c19606405a0b5177e9cd9ddcb8cc9afe3a5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 25 May 2015 23:51:23 -0500 Subject: [PATCH 106/846] Update changelog descriptor cause prob not clear enough [skip ci] --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 7d965260c..cdb2fd5f8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,6 +5,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods Akkadius: Added parameter to LUA and Perl method settime(hour, minute, [update_world = true]) - If update_world is false, the zone will then unsubscribe itself from regular worldserver time synchronizations + - Basically this localizes the zones time and keeps it from syncing with world updates Akkadius: Added DB ver 9082 with update to add npc_types texture columns if table does not currently have them == 05/22/2015 == From 5c194c708741663932f344598c2708413bc94a00 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 25 May 2015 23:57:48 -0500 Subject: [PATCH 107/846] Some syntax adjustments to eqtime.cpp [skip ci] --- common/eqtime.cpp | 79 +++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/common/eqtime.cpp b/common/eqtime.cpp index cb3afb37d..e504964b8 100644 --- a/common/eqtime.cpp +++ b/common/eqtime.cpp @@ -43,17 +43,17 @@ EQTime::EQTime(TimeOfDay_Struct start_eq, time_t start_real) EQTime::EQTime() { - timezone=0; + timezone = 0; memset(&eqTime, 0, sizeof(eqTime)); //Defaults for time TimeOfDay_Struct start; - start.day=1; - start.hour=9; - start.minute=0; - start.month=1; - start.year=3100; + start.day = 1; + start.hour = 9; + start.minute = 0; + start.month = 1; + start.year = 3100; //Set default time zone - timezone=0; + timezone = 0; //Start EQTimer SetCurrentEQTimeOfDay(start, time(0)); } @@ -67,10 +67,10 @@ EQTime::~EQTime() //Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to. //Output: 0=Error, 1=Sucess -int EQTime::GetCurrentEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeOfDay ) +int EQTime::GetCurrentEQTimeOfDay(time_t timeConvert, struct TimeOfDay_Struct *eqTimeOfDay) { /* check to see if we have a reference time to go by. */ - if( eqTime.start_realtime == 0 ) + if (eqTime.start_realtime == 0) return 0; unsigned long diff = timeConvert - eqTime.start_realtime; @@ -83,7 +83,7 @@ int EQTime::GetCurrentEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct * int32 ntz = timezone; /* The minutes range from 0 - 59 */ - diff += eqTime.start_eqtime.minute + (ntz%60); + diff += eqTime.start_eqtime.minute + (ntz % 60); eqTimeOfDay->minute = diff % 60; diff /= 60; ntz /= 60; @@ -97,24 +97,24 @@ int EQTime::GetCurrentEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct * // // Modify it so that it works from // 0-23 for our calculations - diff += ( eqTime.start_eqtime.hour - 1) + (ntz%24); - eqTimeOfDay->hour = (diff%24) + 1; + diff += (eqTime.start_eqtime.hour - 1) + (ntz % 24); + eqTimeOfDay->hour = (diff % 24) + 1; diff /= 24; ntz /= 24; // The days range from 1-28 // Modify it so that it works from // 0-27 for our calculations - diff += ( eqTime.start_eqtime.day - 1 ) + (ntz%28); - eqTimeOfDay->day = (diff%28) + 1; + diff += (eqTime.start_eqtime.day - 1) + (ntz % 28); + eqTimeOfDay->day = (diff % 28) + 1; diff /= 28; ntz /= 28; // The months range from 1-12 // Modify it so that it works from // 0-11 for our calculations - diff += ( eqTime.start_eqtime.month - 1 ) + (ntz%12); - eqTimeOfDay->month = (diff%12) + 1; + diff += (eqTime.start_eqtime.month - 1) + (ntz % 12); + eqTimeOfDay->month = (diff % 12) + 1; diff /= 12; ntz /= 12; @@ -126,10 +126,10 @@ int EQTime::GetCurrentEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct * //setEQTimeOfDay int EQTime::SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real) { - if(start_real==0) + if (start_real == 0) return 0; - eqTime.start_eqtime=start_eq; - eqTime.start_realtime=start_real; + eqTime.start_eqtime = start_eq; + eqTime.start_realtime = start_real; return 1; } @@ -139,7 +139,7 @@ bool EQTime::saveFile(const char *filename) { std::ofstream of; of.open(filename); - if(!of) + if (!of) { Log.Out(Logs::General, Logs::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename); return false; @@ -200,24 +200,24 @@ bool EQTime::loadFile(const char *filename) bool EQTime::IsTimeBefore(TimeOfDay_Struct *base, TimeOfDay_Struct *test) { - if(base->year > test->year) + if (base->year > test->year) return(true); - if(base->year < test->year) + if (base->year < test->year) return(false); //same years - if(base->month > test->month) + if (base->month > test->month) return(true); - if(base->month < test->month) + if (base->month < test->month) return(false); //same month - if(base->day > test->day) + if (base->day > test->day) return(true); - if(base->day < test->day) + if (base->day < test->day) return(false); //same day - if(base->hour > test->hour) + if (base->hour > test->hour) return(true); - if(base->hour < test->hour) + if (base->hour < test->hour) return(false); //same hour... return(base->minute > test->minute); @@ -230,7 +230,7 @@ void EQTime::AddMinutes(uint32 minutes, TimeOfDay_Struct *to) { //minutes start at 0, everything else starts at 1 cur = to->minute; cur += minutes; - if(cur < 60) { + if (cur < 60) { to->minute = cur; return; } @@ -238,29 +238,29 @@ void EQTime::AddMinutes(uint32 minutes, TimeOfDay_Struct *to) { //carry hours cur /= 60; cur += to->hour; - if(cur <= 24) { + if (cur <= 24) { to->hour = cur; return; } - to->hour = ((cur-1) % 24) + 1; + to->hour = ((cur - 1) % 24) + 1; //carry days - cur = (cur-1) / 24; + cur = (cur - 1) / 24; cur += to->day; - if(cur <= 28) { + if (cur <= 28) { to->day = cur; return; } - to->day = ((cur-1) % 28) + 1; + to->day = ((cur - 1) % 28) + 1; //carry months - cur = (cur-1) / 28; + cur = (cur - 1) / 28; cur += to->month; - if(cur <= 12) { + if (cur <= 12) { to->month = cur; return; } - to->month = ((cur-1) % 12) + 1; + to->month = ((cur - 1) % 12) + 1; //carry years - to->year += (cur-1) / 12; + to->year += (cur - 1) / 12; } void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) { @@ -269,5 +269,4 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) { t->month, t->day, t->year, t->hour, t->minute); buf[127] = '\0'; str = buf; -} - +} \ No newline at end of file From e7902342ddba8f86d50dc98caeed0a01f9f63f49 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 26 May 2015 00:57:39 -0400 Subject: [PATCH 108/846] EQ seems to round the ticks weird ... A few examples in the comments ... --- zone/effects.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index c814ea554..c1d037670 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -425,8 +425,15 @@ int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) // a level 53 bard reported getting 2 tics if (IsShortDurationBuff(spell_id) && IsBardSong(spell_id) && spells[spell_id].mana == 0 && GetClass() == BARD && GetLevel() > 60) tic_inc++; + float focused = ((duration * increase) / 100.0f) + tic_inc; + int ifocused = static_cast(focused); - return (((duration * increase) / 100) + tic_inc); + // 7.6 is rounded to 7, 8.6 is rounded to 9 + // 6 is 6, etc + if (FCMP(focused, ifocused) || ifocused % 2) // equal or odd + return ifocused; + else // even and not equal round to odd + return ifocused + 1; } int32 Client::GetActSpellCasttime(uint16 spell_id, int32 casttime) From 2b495cea5a67f585d1f902e4db0fbb4f7dcbce76 Mon Sep 17 00:00:00 2001 From: SecretsOTheP Date: Tue, 26 May 2015 01:19:49 -0400 Subject: [PATCH 109/846] bot fixes for compiling --- zone/bot.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 5ddbb1377..8de38f6a4 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3446,7 +3446,7 @@ void Bot::AI_Process() { if(IsMoving()) { SetHeading(0); SetRunAnimSpeed(0); - SetCurrentSpeed(GetRunSpeed()); + SetCurrentSpeed(GetRunspeed()); if(moved) { SetCurrentSpeed(0); @@ -3512,7 +3512,6 @@ void Bot::AI_Process() { if(atCombatRange) { if(IsMoving()) { SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SetRunAnimSpeed(0); SetCurrentSpeed(0); if(moved) { moved = false; From 76d7fe158695c938b194967d7ba566bd6e154268 Mon Sep 17 00:00:00 2001 From: SecretsOTheP Date: Tue, 26 May 2015 02:27:48 -0400 Subject: [PATCH 110/846] Fixes for mobs on pause waypoints dancing around. Fixes for runspeed <= 0 as reported by demonstar55 --- zone/bot.cpp | 56 +++------------------------------------------- zone/mob.cpp | 10 ++++----- zone/mob_ai.cpp | 16 +++++++------ zone/waypoints.cpp | 2 +- 4 files changed, 18 insertions(+), 66 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 8de38f6a4..10e00e3f2 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -373,7 +373,7 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str BotNPCType.d_melee_texture2 = 0; BotNPCType.qglobal = false; BotNPCType.attack_speed = 0; - BotNPCType.runspeed = 1.25; + BotNPCType.runspeed = 0.7f; BotNPCType.bodytype = 1; BotNPCType.findable = 0; BotNPCType.hp_regen = 1; @@ -410,7 +410,7 @@ NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string b Result.drakkin_details = 0; Result.drakkin_heritage = 0; Result.drakkin_tattoo = 0; - Result.runspeed = 1.25; + Result.runspeed = 0.7f; Result.bodytype = 1; Result.findable = 0; Result.hp_regen = 1; @@ -3739,8 +3739,6 @@ void Bot::AI_Process() { if(dist < GetFollowDistance() + 1000) speed = follow->GetWalkspeed(); - SetRunAnimSpeed(0); - if(dist > GetFollowDistance()) { CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); if(rest_timer.Enabled()) @@ -3832,12 +3830,10 @@ void Bot::PetAIProcess() { botPet->GetAIMovementTimer()->Check(); if(botPet->IsMoving()) { - botPet->SetRunAnimSpeed(0); botPet->SetHeading(botPet->GetTarget()->GetHeading()); if(moved) { moved=false; - botPet->SendPosition(); - botPet->SetMoving(false); + botPet->SetRunAnimSpeed(0); } } @@ -10542,52 +10538,6 @@ bool Bot::CanHeal() { } bool Bot::CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ) { - // 2.5625 is the inverse of 0.3902439. The only difference is in implementation. - // NOTE: You can not change just one of the constants below. They are the same number, just expressed inversly of each other. - // const float clientOverServerRatio = 2.5625f; - const float serverOverClientRatio = 0.3902439f; - - // Use this block if using 2.5625 as the ratio. - // const int clientAnimationMovementRateTypeMultiple = 8; - - // WildcardX: These are valid rates and observations based on painstaking testing of the client response to these values - // - // - // 0 * 8 = 0 : No Movement - // 1 * 8 = 8 : Death Walk - // 2 * 8 = 16 : Slow Walk - // 3 * 8 = 24 : Normal Walk - // 4 * 8 = 32 : Jog - // 5 * 8 = 40 : Normal Run - // 6 * 8 = 48 : Faster Run - // 7 * 8 = 56 : Even Faster Run - // 8 * 8 = 64 : Fastest Yet Run (Bard Song Speed?) - // 9 * 8 = 72 : Faster Fastest Yet Run - // 10 * 8 = 80 : .... you get the idea, this is pretty fast - // 11 * 8 = 88 : .... warp speed anyone? - // 12 * 8 = 96 : .... transwarp drive was invented by gnomes in Norrath - // 13 * 8 = 104 : ... who needs warp drives when you can just displace through time and space? - // - // - // You get the idea here with these... These seem to be "benchmark values" of animation movement and how fast - // the client thinks the Mob is moving so it can make it all look seemless between updates from the server. - // This chart is scalable by the client so you can pass an animation rate of 50 and get a "faster run" but not quite a "even faster run" - - // Convert the Bot movement rate to a value the client understands based on the chart above - // Use this block if using 2.5625 as the ratio. - // speed *= clientMovementRateTypeMultiple; - - - // This sets the movement animation rate with the client - // Use this block if using 2.5625 as the ratio. - // pRunAnimSpeed = speed; - pRunAnimSpeed = ((serverOverClientRatio * 10.0f) * speed) * 10.0f; - - // Now convert our "speed" from the value necessary for the client to animate the correct movement type rate to the server side speed - // Use this block if using 2.5625 as the ratio. - // speed *= serverOverClientRatio; - speed = pRunAnimSpeed / serverOverClientRatio; - return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ); } diff --git a/zone/mob.cpp b/zone/mob.cpp index ddad36ff1..f7348a869 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -599,7 +599,7 @@ int Mob::_GetWalkSpeed() const { speed_mod += (base_run * movemod / 100); if(speed_mod < 1) - return(1); + return(0); //runspeed cap. if(IsClient()) @@ -670,7 +670,7 @@ int Mob::_GetRunSpeed() const { // basically stoped if(speed_mod < 1) { - return(1); + return(0); } // moving slowly if (speed_mod < 8) @@ -687,7 +687,7 @@ int Mob::_GetRunSpeed() const { if(speed_mod < 1) { - return(1); + return(0); } //runspeed cap. if(IsClient()) @@ -736,7 +736,7 @@ int Mob::_GetFearSpeed() const { { if (hp_ratio < 25) { - return (1); + return (0); } if (hp_ratio < 50) return (8); @@ -766,7 +766,7 @@ int Mob::_GetFearSpeed() const { } } if (speed_mod < 1) - return (1); + return (0); if (speed_mod < 9) return (8); if (speed_mod < 13) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 9909672de..b3aaad1dc 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1719,14 +1719,16 @@ 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()); - SetWaypointPause(); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - SetMoving(false); - if (m_CurrentWayPoint.w >= 0.0) { - SetHeading(m_CurrentWayPoint.w); + if (cur_wp_pause != 0) { + SetWaypointPause(); + if(GetAppearance() != eaStanding) + SetAppearance(eaStanding, false); + SetMoving(false); + if (m_CurrentWayPoint.w >= 0.0) { + SetHeading(m_CurrentWayPoint.w); + } + SendPosition(); } - SendPosition(); //kick off event_waypoint arrive char temp[16]; diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index a59e49966..c4f37864d 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -492,7 +492,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo if(GetID()==0) return true; - if(speed == 0) + if(speed <= 0) { SetCurrentSpeed(0); return true; From 92c756c8207fc069973956257e83336862394e7d Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 26 May 2015 15:51:18 -0400 Subject: [PATCH 111/846] Fix for character select screen client crashes (fix #418) --- changelog.txt | 2 ++ common/eq_stream.cpp | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/changelog.txt b/changelog.txt index cdb2fd5f8..3af28ecf1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/26/2015 == +Uleat: Fix for packet size adjustment after initial declaration (issue #418) - should clear up some random client crashes and the inability to progress to charsel screen on affected accounts == 05/25/2015 == Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index be1ae50d4..7fa53ae02 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -571,12 +571,25 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) } } + + // The (p->size++) and (length--) modification code inside of the (opcode & 0x00FF == 0) checks are a temporary solution + // to a discongruency in packet size due to an alteration of packet size after the initial declaration. This led to client + // crashes where the original packet size + protocol bytes mod MaxLen() produced a 0 result. + // + // These changes are local-only and there may be other calling methods affected by the EQ##Packet::serialize() issue. + if ((opcode & 0x00FF) == 0) { // this is final..but, had scope issues during early testing at this point + Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting application packet length for high byte opcode 0x%04X (%d to %d)" __L, opcode, p->size++, p->size); + } + // Convert the EQApplicationPacket to 1 or more EQProtocolPackets 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]; length=p->serialize(opcode, tmpbuff); + if ((opcode & 0x00FF) == 0) { // temp solution until all serialize() calls can be evaluated + Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting protocol packet length for high byte opcode 0x%04X (%d to %d)" __L, opcode, length--, length); + } EQProtocolPacket *out=new EQProtocolPacket(OP_Fragment,nullptr,MaxLen-4); *(uint32 *)(out->pBuffer+2)=htonl(p->Size()); @@ -601,6 +614,9 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) unsigned char *tmpbuff=new unsigned char[p->Size()+3]; length=p->serialize(opcode, tmpbuff+2) + 2; + if ((opcode & 0x00FF) == 0) { // temp solution until all serialize() calls can be evaluated + Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting protocol packet length for high byte opcode 0x%04X (%d to %d)" __L, opcode, length--, length); + } EQProtocolPacket *out=new EQProtocolPacket(OP_Packet,tmpbuff,length); From dbd615572ce2beb60ef1e4ba972ef233093e7230 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 26 May 2015 21:19:48 -0400 Subject: [PATCH 112/846] Revert "Fix for character select screen client crashes (fix #418)" This reverts commit 92c756c8207fc069973956257e83336862394e7d. --- changelog.txt | 2 -- common/eq_stream.cpp | 16 ---------------- 2 files changed, 18 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3af28ecf1..cdb2fd5f8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,5 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 05/26/2015 == -Uleat: Fix for packet size adjustment after initial declaration (issue #418) - should clear up some random client crashes and the inability to progress to charsel screen on affected accounts == 05/25/2015 == Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index 7fa53ae02..be1ae50d4 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -571,25 +571,12 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) } } - - // The (p->size++) and (length--) modification code inside of the (opcode & 0x00FF == 0) checks are a temporary solution - // to a discongruency in packet size due to an alteration of packet size after the initial declaration. This led to client - // crashes where the original packet size + protocol bytes mod MaxLen() produced a 0 result. - // - // These changes are local-only and there may be other calling methods affected by the EQ##Packet::serialize() issue. - if ((opcode & 0x00FF) == 0) { // this is final..but, had scope issues during early testing at this point - Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting application packet length for high byte opcode 0x%04X (%d to %d)" __L, opcode, p->size++, p->size); - } - // Convert the EQApplicationPacket to 1 or more EQProtocolPackets 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]; length=p->serialize(opcode, tmpbuff); - if ((opcode & 0x00FF) == 0) { // temp solution until all serialize() calls can be evaluated - Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting protocol packet length for high byte opcode 0x%04X (%d to %d)" __L, opcode, length--, length); - } EQProtocolPacket *out=new EQProtocolPacket(OP_Fragment,nullptr,MaxLen-4); *(uint32 *)(out->pBuffer+2)=htonl(p->Size()); @@ -614,9 +601,6 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) unsigned char *tmpbuff=new unsigned char[p->Size()+3]; length=p->serialize(opcode, tmpbuff+2) + 2; - if ((opcode & 0x00FF) == 0) { // temp solution until all serialize() calls can be evaluated - Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting protocol packet length for high byte opcode 0x%04X (%d to %d)" __L, opcode, length--, length); - } EQProtocolPacket *out=new EQProtocolPacket(OP_Packet,tmpbuff,length); From 24917257e6ae7007a71385b2d89dcadd51be8243 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 27 May 2015 22:24:00 -0400 Subject: [PATCH 113/846] Application packet size fix for high byte opcodes --- common/eq_stream.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index be1ae50d4..c48cba0fd 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -573,16 +573,18 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) // Convert the EQApplicationPacket to 1 or more EQProtocolPackets 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); + Log.Out(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->Size()); unsigned char *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); - *(uint32 *)(out->pBuffer+2)=htonl(p->Size()); + *(uint32 *)(out->pBuffer+2)=htonl(length); used=MaxLen-10; memcpy(out->pBuffer+6,tmpbuff,used); - Log.Out(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Put size %d in the packet" __L, used, p->size, p->Size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Payload size %d in the packet" __L, used, length, p->size); SequencedPush(out); @@ -593,7 +595,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) out->size=chunksize+2; SequencedPush(out); used+=chunksize; - Log.Out(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, length); } delete p; delete[] tmpbuff; From dbbae0e735ad229b5a8b614f2db7f373cfecea5c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 28 May 2015 13:26:55 -0400 Subject: [PATCH 114/846] Crash for no zonemap --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 49b5df187..c5dfcc6d7 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3717,7 +3717,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons // 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); - if (zone->zonemap->CheckLoS(glm::vec3(m_Position), new_pos)) { // If we have LoS on the new loc it should be reachable. + if (zone->zonemap && zone->zonemap->CheckLoS(glm::vec3(m_Position), new_pos)) { // If we have LoS on the new loc it should be reachable. if (IsNPC()) { // Is this adequate? Teleport(new_pos); From 22ef16947cbb015732d1e48cedd9800884430cf4 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Thu, 28 May 2015 11:24:17 -0700 Subject: [PATCH 115/846] Bots will no longer crash when disbanding on death or normal disbanding.. HP values on bots will no longer roll over when checking STAMINA --- zone/bot.cpp | 26 +++++++++++++++++--------- zone/client_packet.cpp | 5 +++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 10e00e3f2..a3e07707c 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -751,9 +751,13 @@ void Bot::GenerateBaseStats() { this->DR = DiseaseResist; this->PR = PoisonResist; this->CR = ColdResist; + this->PhR = 0; this->Corrup = CorruptionResist; SetBotSpellID(BotSpellID); this->size = BotSize; + + this->pAggroRange = 0; + this->pAssistRange = 0; } void Bot::GenerateAppearance() { @@ -1374,20 +1378,20 @@ int32 Bot::GenerateBaseHitPoints() // Calc Base Hit Points int new_base_hp = 0; uint32 lm = GetClassLevelFactor(); - uint32 Post255; - uint32 NormalSTA = GetSTA(); - + int32 Post255; + int32 NormalSTA = GetSTA(); + if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { float SoDPost255; - + if(((NormalSTA - 255) / 2) > 0) SoDPost255 = ((NormalSTA - 255) / 2); else SoDPost255 = 0; - + int hp_factor = GetClassHPFactor(); - + if(level < 41) { new_base_hp = (5 + (GetLevel() * hp_factor / 12) + ((NormalSTA - SoDPost255) * GetLevel() * hp_factor / 3600)); @@ -1415,7 +1419,7 @@ int32 Bot::GenerateBaseHitPoints() new_base_hp = (5)+(GetLevel()*lm/10) + (((NormalSTA-Post255)*GetLevel()*lm/3000)) + ((Post255*1)*lm/6000); } this->base_hp = new_base_hp; - + return new_base_hp; } @@ -5913,7 +5917,12 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att g->members[j] = nullptr; } } - + + //Make sure group still exists if it doesnt they were already updated in RemoveBotFromGroup + g = GetGroup(); + if (!g) + break; + // update the client group EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; @@ -10196,7 +10205,6 @@ int32 Bot::CalcMaxHP() { bot_hp += GenerateBaseHitPoints() + itembonuses.HP; nd += aabonuses.MaxHP; //Natural Durability, Physical Enhancement, Planar Durability - bot_hp = (float)bot_hp * (float)nd / (float)10000; //this is to fix the HP-above-495k issue bot_hp += spellbonuses.HP + aabonuses.HP; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 9f527476c..01046d7fb 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6362,7 +6362,12 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) } } } + + group = GetGroup(); + if (!group) //We must recheck this here.. incase the final bot disbanded the party..otherwise we crash + return; #endif + if (group->GroupCount() < 3) { group->DisbandGroup(); From 95243fd6ce67405ac992291d7ec1501b3788425a Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Thu, 28 May 2015 11:45:07 -0700 Subject: [PATCH 116/846] Modified ZippZipp's bot name fix from the forums. Limited bot name length to fix a crash. Added Filter check too if you use the Name Filter. --- zone/bot.cpp | 42 +++++++++++++++++------------------------- zone/bot.h | 2 +- zone/questmgr.cpp | 10 +++++----- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index a3e07707c..650d6e191 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2327,30 +2327,22 @@ bool Bot::IsValidName() { return Result; } -bool Bot::IsBotNameAvailable(std::string* errorMessage) { +bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { + if (botName == "" || strlen(botName) > 15 || !database.CheckNameFilter(botName) || !database.CheckUsedName(botName)) { + return false; //Check if Botname is Empty / Check if Botname larger than 15 char / Valid to Player standards / Not used by a player! + } - if(!this->GetCleanName()) - return false; - - std::string query = StringFormat("SELECT COUNT(id) FROM vwBotCharacterMobs " - "WHERE name LIKE '%s'", this->GetCleanName()); - auto results = database.QueryDatabase(query); + std::string query = StringFormat("SELECT id FROM vwBotCharacterMobs WHERE name LIKE '%s'", botName); + auto results = database.QueryDatabase(query); if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); + *errorMessage = std::string(results.ErrorMessage()); return false; - } - - uint32 existingNameCount = 0; - - for (auto row = results.begin(); row != results.end(); ++row) { - existingNameCount = atoi(row[0]); - break; - } - - if(existingNameCount != 0) + } + if (results.RowCount()) { //Name already in use! return false; - - return true; + } + + return true; //We made it with a valid name! } bool Bot::Save() { @@ -11330,6 +11322,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[5], "female")) 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); @@ -11344,11 +11341,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - if(!NewBot->IsBotNameAvailable(&TempErrorMessage)) { - c->Message(0, "The name %s is already being used. Please choose a different name.", NewBot->GetCleanName()); - return; - } - if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; diff --git a/zone/bot.h b/zone/bot.h index 871d96df4..33644c8ea 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -154,7 +154,7 @@ public: // Class Methods bool IsValidRaceClassCombo(); bool IsValidName(); - bool IsBotNameAvailable(std::string* errorMessage); + static bool IsBotNameAvailable(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); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 6b5c8978d..825e3b7b1 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2071,6 +2071,11 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level return false; } + if(Bot::IsBotNameAvailable((char*)name,&TempErrorMessage)) { + initiator->Message(0, "The name %s is already being used or is invalid. Please choose a different name.", (char*)name); + return false; + } + NPCType DefaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(name, lastname, level, race, botclass, gender); Bot* NewBot = new Bot(DefaultNPCTypeStruct, initiator); @@ -2086,11 +2091,6 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level return false; } - if(!NewBot->IsBotNameAvailable(&TempErrorMessage)) { - initiator->Message(0, "The name %s is already being used. Please choose a different name.", NewBot->GetCleanName()); - return false; - } - if(!TempErrorMessage.empty()) { initiator->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return false; From 235d6b6c4822d7cb61983259cfd31c269463b278 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Thu, 28 May 2015 13:56:39 -0700 Subject: [PATCH 117/846] Bots will not benefit from heroic stats, focus effects like a client --- zone/bot.cpp | 550 ++++++++++++++++++++++++++++++++++----------------- zone/bot.h | 4 +- 2 files changed, 376 insertions(+), 178 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 650d6e191..a8e645ff9 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -5836,10 +5836,10 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } if(inst) { + client->DeleteItemInInventory(i, 0, UpdateClient); if(!botCanWear[i]) { client->PushItemOnCursor(*inst, true); } - client->DeleteItemInInventory(i, 0, UpdateClient); } } @@ -9564,8 +9564,9 @@ bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 s } void Bot::CalcBonuses() { + memset(&itembonuses, 0, sizeof(StatBonuses)); GenerateBaseStats(); - CalcItemBonuses(); + CalcItemBonuses(&itembonuses); CalcSpellBonuses(&spellbonuses); GenerateAABonuses(&aabonuses); SetAttackTimer(); @@ -10814,191 +10815,386 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { } } -void Bot::CalcItemBonuses() +void Bot::CalcItemBonuses(StatBonuses* newbon) { - memset(&itembonuses, 0, sizeof(StatBonuses)); const Item_Struct* itemtmp = 0; for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { const ItemInst* item = GetBotItem(i); if(item) { - for(int j = AUG_BEGIN; j < EmuConstants::ITEM_COMMON_SIZE; ++j) { - const ItemInst* aug = item->GetAugment(j); - if(aug) { - itemtmp = aug->GetItem(); - if(itemtmp->AC != 0) - itembonuses.AC += itemtmp->AC; - if(itemtmp->HP != 0) - itembonuses.HP += itemtmp->HP; - if(itemtmp->Mana != 0) - itembonuses.Mana += itemtmp->Mana; - if(itemtmp->Endur != 0) - itembonuses.Endurance += itemtmp->Endur; - if(itemtmp->AStr != 0) - itembonuses.STR += itemtmp->AStr; - if(itemtmp->ASta != 0) - itembonuses.STA += itemtmp->ASta; - if(itemtmp->ADex != 0) - itembonuses.DEX += itemtmp->ADex; - if(itemtmp->AAgi != 0) - itembonuses.AGI += itemtmp->AAgi; - if(itemtmp->AInt != 0) - itembonuses.INT += itemtmp->AInt; - if(itemtmp->AWis != 0) - itembonuses.WIS += itemtmp->AWis; - if(itemtmp->ACha != 0) - itembonuses.CHA += itemtmp->ACha; - if(itemtmp->MR != 0) - itembonuses.MR += itemtmp->MR; - if(itemtmp->FR != 0) - itembonuses.FR += itemtmp->FR; - if(itemtmp->CR != 0) - itembonuses.CR += itemtmp->CR; - if(itemtmp->PR != 0) - itembonuses.PR += itemtmp->PR; - if(itemtmp->DR != 0) - itembonuses.DR += itemtmp->DR; - if(itemtmp->SVCorruption != 0) - itembonuses.Corrup += itemtmp->SVCorruption; - if(itemtmp->Regen != 0) - itembonuses.HPRegen += itemtmp->Regen; - if(itemtmp->ManaRegen != 0) - itembonuses.ManaRegen += itemtmp->ManaRegen; - if(itemtmp->Attack != 0) - itembonuses.ATK += itemtmp->Attack; - if(itemtmp->DamageShield != 0) - itembonuses.DamageShield += itemtmp->DamageShield; - if(itemtmp->SpellShield != 0) - itembonuses.SpellDamageShield += itemtmp->SpellShield; - if(itemtmp->Shielding != 0) - itembonuses.MeleeMitigation += itemtmp->Shielding; - if(itemtmp->StunResist != 0) - itembonuses.StunResist += itemtmp->StunResist; - if(itemtmp->StrikeThrough != 0) - itembonuses.StrikeThrough += itemtmp->StrikeThrough; - if(itemtmp->Avoidance != 0) - itembonuses.AvoidMeleeChance += itemtmp->Avoidance; - if(itemtmp->Accuracy != 0) - itembonuses.HitChance += itemtmp->Accuracy; - if(itemtmp->CombatEffects != 0) - itembonuses.ProcChance += itemtmp->CombatEffects; - if(itemtmp->Haste != 0) - if(itembonuses.haste < itemtmp->Haste) - itembonuses.haste = itemtmp->Haste; - if(GetClass() == BARD && itemtmp->BardValue != 0) { - if(itemtmp->BardType == ItemTypeBrassInstrument) - itembonuses.brassMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypePercussionInstrument) - itembonuses.percussionMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypeSinging) - itembonuses.singingMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypeStringedInstrument) - itembonuses.stringedMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypeWindInstrument) - itembonuses.windMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypeAllInstrumentTypes) { - itembonuses.brassMod += itemtmp->BardValue; - itembonuses.percussionMod += itemtmp->BardValue; - itembonuses.singingMod += itemtmp->BardValue; - itembonuses.stringedMod += itemtmp->BardValue; - itembonuses.windMod += itemtmp->BardValue; - } - } - if ((itemtmp->Worn.Effect != 0) && (itemtmp->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(itemtmp->Worn.Effect, itemtmp->Worn.Level, &itembonuses,0,itemtmp->Worn.Type); - } - } - } - itemtmp = item->GetItem(); - if(itemtmp->AC != 0) - itembonuses.AC += itemtmp->AC; - if(itemtmp->HP != 0) - itembonuses.HP += itemtmp->HP; - if(itemtmp->Mana != 0) - itembonuses.Mana += itemtmp->Mana; - if(itemtmp->Endur != 0) - itembonuses.Endurance += itemtmp->Endur; - if(itemtmp->AStr != 0) - itembonuses.STR += itemtmp->AStr; - if(itemtmp->ASta != 0) - itembonuses.STA += itemtmp->ASta; - if(itemtmp->ADex != 0) - itembonuses.DEX += itemtmp->ADex; - if(itemtmp->AAgi != 0) - itembonuses.AGI += itemtmp->AAgi; - if(itemtmp->AInt != 0) - itembonuses.INT += itemtmp->AInt; - if(itemtmp->AWis != 0) - itembonuses.WIS += itemtmp->AWis; - if(itemtmp->ACha != 0) - itembonuses.CHA += itemtmp->ACha; - if(itemtmp->MR != 0) - itembonuses.MR += itemtmp->MR; - if(itemtmp->FR != 0) - itembonuses.FR += itemtmp->FR; - if(itemtmp->CR != 0) - itembonuses.CR += itemtmp->CR; - if(itemtmp->PR != 0) - itembonuses.PR += itemtmp->PR; - if(itemtmp->DR != 0) - itembonuses.DR += itemtmp->DR; - if(itemtmp->SVCorruption != 0) - itembonuses.Corrup += itemtmp->SVCorruption; - if(itemtmp->Regen != 0) - itembonuses.HPRegen += itemtmp->Regen; - if(itemtmp->ManaRegen != 0) - itembonuses.ManaRegen += itemtmp->ManaRegen; - if(itemtmp->Attack != 0) - itembonuses.ATK += itemtmp->Attack; - if(itemtmp->DamageShield != 0) - itembonuses.DamageShield += itemtmp->DamageShield; - if(itemtmp->SpellShield != 0) - itembonuses.SpellDamageShield += itemtmp->SpellShield; - if(itemtmp->Shielding != 0) - itembonuses.MeleeMitigation += itemtmp->Shielding; - if(itemtmp->StunResist != 0) - itembonuses.StunResist += itemtmp->StunResist; - if(itemtmp->StrikeThrough != 0) - itembonuses.StrikeThrough += itemtmp->StrikeThrough; - if(itemtmp->Avoidance != 0) - itembonuses.AvoidMeleeChance += itemtmp->Avoidance; - if(itemtmp->Accuracy != 0) - itembonuses.HitChance += itemtmp->Accuracy; - if(itemtmp->CombatEffects != 0) - itembonuses.ProcChance += itemtmp->CombatEffects; - if(itemtmp->Haste != 0) - if(itembonuses.haste < itemtmp->Haste) - itembonuses.haste = itemtmp->Haste; - if(GetClass() == BARD && itemtmp->BardValue != 0) { - if(itemtmp->BardType == ItemTypeBrassInstrument) - itembonuses.brassMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypePercussionInstrument) - itembonuses.percussionMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypeSinging) - itembonuses.singingMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypeStringedInstrument) - itembonuses.stringedMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypeWindInstrument) - itembonuses.windMod += itemtmp->BardValue; - else if(itemtmp->BardType == ItemTypeAllInstrumentTypes) { - itembonuses.brassMod += itemtmp->BardValue; - itembonuses.percussionMod += itemtmp->BardValue; - itembonuses.singingMod += itemtmp->BardValue; - itembonuses.stringedMod += itemtmp->BardValue; - itembonuses.windMod += itemtmp->BardValue; - } - } - if ((itemtmp->Worn.Effect != 0) && (itemtmp->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(itemtmp->Worn.Effect, itemtmp->Worn.Level, &itembonuses,0,itemtmp->Worn.Type); - } + AddItemBonuses(item, newbon); + } + } +} + +void Bot::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->ATK += item->Attack; + 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->ATK += CalcRecommendedLevelBonus( lvl, reclvl, item->Attack ); + 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 < (int32)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->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, item->Worn.Type); + } + + if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects + ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); + } + + 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(itembonuses.HPRegen > CalcHPRegenCap()) - itembonuses.HPRegen = CalcHPRegenCap(); + 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; + } + } - if(itembonuses.ManaRegen > CalcManaRegenCap()) - itembonuses.ManaRegen = CalcManaRegenCap(); + // 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 < EmuConstants::ITEM_COMMON_SIZE; i++) { + AddItemBonuses(inst->GetAugment(i),newbon,true); + } + } + +} + +int Bot::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; } // This method is intended to call all necessary methods to do all bot stat calculations, including spell buffs, equipment, AA bonsues, etc. diff --git a/zone/bot.h b/zone/bot.h index 33644c8ea..4cf04aa3a 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -190,7 +190,9 @@ public: bool CanDoSpecialAttack(Mob *other); virtual int32 CheckAggroAmount(uint16 spellid); virtual void CalcBonuses(); - void CalcItemBonuses(); + void CalcItemBonuses(StatBonuses* newbon); + void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false); + 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); inline virtual bool IsPet() { return false; } From d7b9d7c990274324dcece76698ac09532c47cf37 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Thu, 28 May 2015 14:08:48 -0700 Subject: [PATCH 118/846] Forgot the Regen caps oops! --- zone/bot.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index a8e645ff9..ebc5f47d3 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -10825,6 +10825,16 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) AddItemBonuses(item, newbon); } } + + // Caps + if(newbon->HPRegen > CalcHPRegenCap()) + newbon->HPRegen = CalcHPRegenCap(); + + if(newbon->ManaRegen > CalcManaRegenCap()) + newbon->ManaRegen = CalcManaRegenCap(); + + if(newbon->EnduranceRegen > CalcEnduranceRegenCap()) + newbon->EnduranceRegen = CalcEnduranceRegenCap(); } void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) { From 5917052a6d5097363d4f714d8b63cc1e090d7c4c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 28 May 2015 18:00:25 -0400 Subject: [PATCH 119/846] I guess short duration buffs needed the extra tick --- 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 d0069683b..9d0fd7858 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3372,7 +3372,7 @@ void Mob::BuffProcess() { --buffs[buffs_i].ticsremaining; - if (buffs[buffs_i].ticsremaining == 0) { + if ((buffs[buffs_i].ticsremaining == 0 && !IsShortDurationBuff(buffs[buffs_i].spellid)) || 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 be210950d7018e8a9b93d3d874315390fe6e3d99 Mon Sep 17 00:00:00 2001 From: regneq Date: Thu, 28 May 2015 15:05:45 -0700 Subject: [PATCH 120/846] readded previous commit smoother pathing. --- zone/client.h | 1 + zone/mob_ai.cpp | 144 +++++++++++++++++++++++---------------------- zone/npc.h | 1 + zone/waypoints.cpp | 11 +++- 4 files changed, 85 insertions(+), 72 deletions(-) diff --git a/zone/client.h b/zone/client.h index ac505ecdb..73bde1a69 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1130,6 +1130,7 @@ public: inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); } void DragCorpses(); inline void ClearDraggedCorpses() { DraggedCorpses.clear(); } + inline void ResetPositionTimer() { position_timer_counter = 0; } void SendAltCurrencies(); void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount); void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b3aaad1dc..650ba350c 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1653,76 +1653,17 @@ void NPC::AI_DoMovement() { 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; - - Log.Out(Logs::Detail, Logs::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) { - Log.Out(Logs::Detail, Logs::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; - } - } + AI_SetupNextWaypoint(); } // endif (movetimercompleted==true) else if (!(AIwalking_timer->Enabled())) { // currently moving + bool doMove = true; 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(); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); SetMoving(false); if (m_CurrentWayPoint.w >= 0.0) { SetHeading(m_CurrentWayPoint.w); @@ -1734,13 +1675,17 @@ void NPC::AI_DoMovement() { char temp[16]; sprintf(temp, "%d", cur_wp); parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0); - + // start moving directly to next waypoint if we're at a 0 pause waypoint and we didn't get quest halted. + if (!AIwalking_timer->Enabled()) + AI_SetupNextWaypoint(); + else + doMove = false; // wipe feign memory since we reached our first waypoint if(cur_wp == 1) ClearFeignMemory(); } - else - { // not at waypoint yet, so keep moving + if (doMove) + { // not at waypoint yet or at 0 pause WP, so keep moving if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0)) CalculateNewPosition2(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true); else @@ -1768,8 +1713,7 @@ void NPC::AI_DoMovement() { SetGrid( 0 - GetGrid()); // revert to AI control Log.Out(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid()); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); CalculateNewWaypoint(); } @@ -1818,15 +1762,73 @@ void NPC::AI_DoMovement() { } } +void NPC::AI_SetupNextWaypoint() { + 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 restart 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; + + Log.Out(Logs::Detail, Logs::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) { + Log.Out(Logs::Detail, Logs::Pathing, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode."); + roamer = false; + cur_wp = 0; + } + + 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 (GetGrid() > 0) { + CastToNPC()->CalculateNewWaypoint(); + } + } + else { + DistractedFromGrid = false; + } + } +} + // 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); - } + SetAppearance(eaStanding); if (iYellForHelp) { if(IsPet()) { diff --git a/zone/npc.h b/zone/npc.h index 95a857460..f960c736e 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -119,6 +119,7 @@ public: virtual void AI_Start(uint32 iMoveDelay = 0); virtual void AI_Stop(); void AI_DoMovement(); + void AI_SetupNextWaypoint(); bool AI_AddNPCSpells(uint32 iDBSpellsID); bool AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID); virtual bool AI_EngagedCastCheck(); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index c4f37864d..7570165a3 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -394,6 +394,7 @@ void NPC::SetWaypointPause() if (cur_wp_pause == 0) { AIwalking_timer->Start(100); + AIwalking_timer->Trigger(); } else { @@ -519,6 +520,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo return true; } + bool send_update = false; int compare_steps = IsBoat() ? 1 : 20; if(tar_ndx < compare_steps && m_TargetLocation.x==x && m_TargetLocation.y==y) { @@ -709,11 +711,18 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f); if (IsClient()) + { SendPosUpdate(1); + CastToClient()->ResetPositionTimer(); + } else + { + // force an update now + move_tic_count = RuleI(Zone, NPCPositonUpdateTicCount); SendPosUpdate(); + SetAppearance(eaStanding, false); + } - SetAppearance(eaStanding, false); pLastChange = Timer::GetCurrentTime(); return true; } From 36de3879f8970d31f1e3be474f5ffa75d7aa3369 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 May 2015 00:40:34 -0400 Subject: [PATCH 121/846] There is a variety to focus messages I'm not 100% sure these are classic, but Tit+ at least. I was able to verify these messages -- crap ton more though. --- zone/spell_effects.cpp | 20 ++++++++++++++++++-- zone/string_ids.h | 3 +++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9d0fd7858..26ebe83c6 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5394,8 +5394,24 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { if(UsedItem && rand_effectiveness && focus_max_real != 0) realTotal = CalcFocusEffect(type, UsedFocusID, spell_id); - if (realTotal != 0 && UsedItem) - Message_StringID(MT_Spells, BEGINS_TO_GLOW, UsedItem->Name); + if (realTotal != 0 && UsedItem) { + // there are a crap ton more of these, I was able to verify these ones though + uint32 string_id = BEGINS_TO_GLOW; + switch (type) { + case focusSpellHaste: + string_id = SHIMMERS_BRIEFLY; + break; + case focusManaCost: + string_id = FLICKERS_PALE_LIGHT; + break; + case focusSpellDuration: + string_id = SPARKLES; + break; + default: + break; + } + Message_StringID(MT_Spells, string_id, UsedItem->Name); + } } //Check if spell focus effect exists for the client. diff --git a/zone/string_ids.h b/zone/string_ids.h index 2db4e34e8..139dc1005 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -233,6 +233,8 @@ #define CORPSE_DECAY_NOW 1227 //This corpse is waiting to expire. #define CORPSE_ITEM_LOST 1228 //Your items will no longer stay with you when you respawn on death. You will now need to return to your corpse for your items. #define CORPSE_EXP_LOST 1229 //You will now lose experience when you die. +#define FLICKERS_PALE_LIGHT 1230 //Your %1 flickers with a pale light. +#define SPARKLES 1236 //Your %1 sparkles. #define SURNAME_REJECTED 1374 //Your new surname was rejected. Please try a different name. #define DUEL_DECLINE 1383 //%1 has declined your challenge to duel to the death. #define DUEL_ACCEPTED 1384 //%1 has already accepted a duel with someone else. @@ -375,6 +377,7 @@ #define GROUP_INVITEE_SELF 12270 //12270 You cannot invite yourself. #define NOT_IN_CONTROL 12368 //You do not have control of yourself right now. #define ALREADY_CASTING 12442 //You are already casting a spell! +#define SHIMMERS_BRIEFLY 12444 //Your %1 shimmers briefly. #define SENSE_CORPSE_NOT_NAME 12446 //You don't sense any corpses of that name. #define SENSE_CORPSE_NONE 12447 //You don't sense any corpses. #define SCREECH_BUFF_BLOCK 12448 //Your immunity buff protected you from the spell %1! From 070183789bdb5124ea13da1b280f3eab6bffd8ce Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 May 2015 01:58:38 -0400 Subject: [PATCH 122/846] More focus messages --- zone/spell_effects.cpp | 8 +++++++- zone/string_ids.h | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 26ebe83c6..ce1d444fb 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5396,7 +5396,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { if (realTotal != 0 && UsedItem) { // there are a crap ton more of these, I was able to verify these ones though - uint32 string_id = BEGINS_TO_GLOW; + uint32 string_id = BEGINS_TO_GLOW; // this is really just clicky message ... switch (type) { case focusSpellHaste: string_id = SHIMMERS_BRIEFLY; @@ -5407,6 +5407,12 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { case focusSpellDuration: string_id = SPARKLES; break; + case focusImprovedDamage: + string_id = ALIVE_WITH_POWER; + break; + case focusRange: + string_id = PULSES_WITH_LIGHT; + break; default: break; } diff --git a/zone/string_ids.h b/zone/string_ids.h index 139dc1005..fb52985c0 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -234,7 +234,14 @@ #define CORPSE_ITEM_LOST 1228 //Your items will no longer stay with you when you respawn on death. You will now need to return to your corpse for your items. #define CORPSE_EXP_LOST 1229 //You will now lose experience when you die. #define FLICKERS_PALE_LIGHT 1230 //Your %1 flickers with a pale light. +#define PULSES_WITH_LIGHT 1231 //Your %1 pulses with light as your vision sharpens. +#define FEEDS_WITH_POWER 1232 //Your %1 feeds you with power. +#define POWER_DRAIN_INTO 1233 //You feel your power drain into your %1. +#define SEEMS_DRAINED 1234 //Your %1 seems drained of power. +#define ALIVE_WITH_POWER 1235 //Your %1 feels alive with power. #define SPARKLES 1236 //Your %1 sparkles. +#define GROWS_DIM 1237 //Your %1 grows dim. +#define BEGINS_TO_SHINE 1238 //Your %1 begins to shine. #define SURNAME_REJECTED 1374 //Your new surname was rejected. Please try a different name. #define DUEL_DECLINE 1383 //%1 has declined your challenge to duel to the death. #define DUEL_ACCEPTED 1384 //%1 has already accepted a duel with someone else. From 8646791d1d7e248806710d3bf2719dbe31007788 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 May 2015 03:26:35 -0400 Subject: [PATCH 123/846] Proc buffs like the shissar rogue poisons have a level override This corrects the level in those cases. Probably should propagate the level overrides a bit more, but this fixes the main issues right now. --- zone/attack.cpp | 2 +- zone/client_packet.cpp | 2 +- zone/common.h | 1 + zone/mob.cpp | 24 ++++++++++++++---------- zone/mob.h | 10 +++++----- zone/spell_effects.cpp | 35 ++++++++++++++++++----------------- zone/spells.cpp | 18 +++++++++++------- 7 files changed, 51 insertions(+), 41 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index c5dfcc6d7..666cb19f8 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4143,7 +4143,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, outapp->priority = 3; entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); safe_delete(outapp); - ExecWeaponProc(nullptr, SpellProcs[i].spellID, on); + ExecWeaponProc(nullptr, SpellProcs[i].spellID, on, SpellProcs[i].level_override); CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, SpellProcs[i].base_spellID); } else { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 01046d7fb..ccb27a188 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -704,7 +704,7 @@ void Client::CompleteConnect() case SE_AddMeleeProc: case SE_WeaponProc: { - AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].base2[x1], buffs[j1].spellid); + AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].base2[x1], buffs[j1].spellid, buffs[j1].casterlevel); break; } case SE_DefensiveProc: diff --git a/zone/common.h b/zone/common.h index b2e4d5ed5..13a65f7c5 100644 --- a/zone/common.h +++ b/zone/common.h @@ -468,6 +468,7 @@ typedef struct uint16 spellID; uint16 chance; uint16 base_spellID; + int level_override; } tProc; struct Shielders_Struct { diff --git a/zone/mob.cpp b/zone/mob.cpp index f7348a869..7f6cb9fbf 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -263,15 +263,19 @@ Mob::Mob(const char* in_name, PermaProcs[j].spellID = SPELL_UNKNOWN; PermaProcs[j].chance = 0; PermaProcs[j].base_spellID = SPELL_UNKNOWN; + PermaProcs[j].level_override = -1; SpellProcs[j].spellID = SPELL_UNKNOWN; SpellProcs[j].chance = 0; SpellProcs[j].base_spellID = SPELL_UNKNOWN; + SpellProcs[j].level_override = -1; DefensiveProcs[j].spellID = SPELL_UNKNOWN; DefensiveProcs[j].chance = 0; DefensiveProcs[j].base_spellID = SPELL_UNKNOWN; + DefensiveProcs[j].level_override = -1; RangedProcs[j].spellID = SPELL_UNKNOWN; RangedProcs[j].chance = 0; RangedProcs[j].base_spellID = SPELL_UNKNOWN; + RangedProcs[j].level_override = -1; } for (i = 0; i < _MaterialCount; i++) @@ -3160,7 +3164,7 @@ int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime) { return casttime; } -void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) { +void Mob::ExecWeaponProc(const ItemInst *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)) { @@ -3199,14 +3203,14 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) { twinproc = true; if (IsBeneficialSpell(spell_id)) { - SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff, true); + SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff, true, level_override); if(twinproc) - SpellOnTarget(spell_id, this, false, false, 0, true); + 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); + SpellFinished(spell_id, on, 10, 0, -1, spells[spell_id].ResistDiff, true, level_override); if(twinproc) - SpellOnTarget(spell_id, on, false, false, 0, true); + SpellOnTarget(spell_id, on, false, false, 0, true, level_override); } return; } @@ -5605,15 +5609,15 @@ void Mob::SendRemovePlayerState(PlayerState old_state) safe_delete(app); } -void Mob::SetCurrentSpeed(int in){ +void Mob::SetCurrentSpeed(int in){ if (current_speed != in) - { - current_speed = in; + { + current_speed = in; tar_ndx = 20; if (in == 0) { SetRunAnimSpeed(0); SetMoving(false); SendPosition(); } - } -} \ No newline at end of file + } +} diff --git a/zone/mob.h b/zone/mob.h index 896b9c71b..944b80d97 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -227,10 +227,10 @@ public: 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); + 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); - virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100); + 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); virtual bool CheckFizzle(uint16 spell_id); @@ -536,7 +536,7 @@ public: 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 AddProcToWeapon(uint16 spell_id, bool bPerma = false, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN, int level_override = -1); bool RemoveProcFromWeapon(uint16 spell_id, bool bAll = false); bool HasProcs() const; bool IsCombatProc(uint16 spell_id); @@ -1077,7 +1077,7 @@ protected: 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 ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on); + 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 GetSpecialProcChances(uint16 hand); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ce1d444fb..28f5518fa 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -44,7 +44,7 @@ extern WorldServer worldserver; // the spell can still fail here, if the buff can't stack // in this case false will be returned, true otherwise -bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) +bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_override) { int caster_level, buffslot, effect, effect_value, i; ItemInst *SummonedItem=nullptr; @@ -59,26 +59,27 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) const SPDat_Spell_Struct &spell = spells[spell_id]; bool c_override = false; - if(caster && caster->IsClient() && GetCastedSpellInvSlot() > 0) - { - const ItemInst* inst = caster->CastToClient()->GetInv().GetItem(GetCastedSpellInvSlot()); - if(inst) - { - if(inst->GetItem()->Click.Level > 0) - { + if (caster && caster->IsClient() && GetCastedSpellInvSlot() > 0) { + const ItemInst *inst = caster->CastToClient()->GetInv().GetItem(GetCastedSpellInvSlot()); + if (inst) { + if (inst->GetItem()->Click.Level > 0) { caster_level = inst->GetItem()->Click.Level; c_override = true; - } - else - { + } else { caster_level = caster ? caster->GetCasterLevel(spell_id) : GetCasterLevel(spell_id); } - } - else + } else if (level_override > 0) { + caster_level = level_override; + c_override = true; + } else { caster_level = caster ? caster->GetCasterLevel(spell_id) : GetCasterLevel(spell_id); - } - else + } + } else if (level_override > 0) { + caster_level = level_override; + c_override = true; + } else { caster_level = caster ? caster->GetCasterLevel(spell_id) : GetCasterLevel(spell_id); + } if(c_override) { @@ -1786,9 +1787,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #endif if(spells[spell_id].base2[i] == 0) - AddProcToWeapon(procid, false, 100, spell_id); + AddProcToWeapon(procid, false, 100, spell_id, level_override); else - AddProcToWeapon(procid, false, spells[spell_id].base2[i]+100, spell_id); + AddProcToWeapon(procid, false, spells[spell_id].base2[i]+100, spell_id, level_override); break; } diff --git a/zone/spells.cpp b/zone/spells.cpp index f90335e31..7286ba0aa 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1897,7 +1897,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce // 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, - uint32 inventory_slot, int16 resist_adjust, bool isproc) + uint32 inventory_slot, int16 resist_adjust, bool isproc, int level_override) { //EQApplicationPacket *outapp = nullptr; Mob *ae_center = nullptr; @@ -2060,14 +2060,14 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 return(false); } if (isproc) { - SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, true); + SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, true, level_override); } else { if (spells[spell_id].targettype == ST_TargetOptional){ if (!TrySpellProjectile(spell_target, spell_id)) return false; } - else if(!SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, false)) { + else if(!SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, false, level_override)) { if(IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) { // Prevent mana usage/timers being set for beneficial buffs if(casting_spell_type == 1) @@ -3292,7 +3292,8 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite) // and if you don't want effects just return false. interrupting here will // break stuff // -bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc) +bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, + bool isproc, int level_override) { // well we can't cast a spell on target without a target @@ -3324,7 +3325,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r if(!IsValidSpell(spell_id)) return false; - uint16 caster_level = GetCasterLevel(spell_id); + 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); @@ -3739,7 +3740,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r } // cause the effects to the target - if(!spelltar->SpellEffect(this, spell_id, spell_effectiveness)) + if(!spelltar->SpellEffect(this, spell_id, spell_effectiveness, level_override)) { // if SpellEffect returned false there's a problem applying the // spell. It's most likely a buff that can't stack. @@ -5098,7 +5099,7 @@ bool Mob::IsCombatProc(uint16 spell_id) { return false; } -bool Mob::AddProcToWeapon(uint16 spell_id, bool bPerma, uint16 iChance, uint16 base_spell_id) { +bool Mob::AddProcToWeapon(uint16 spell_id, bool bPerma, uint16 iChance, uint16 base_spell_id, int level_override) { if(spell_id == SPELL_UNKNOWN) return(false); @@ -5109,6 +5110,7 @@ bool Mob::AddProcToWeapon(uint16 spell_id, bool bPerma, uint16 iChance, uint16 b PermaProcs[i].spellID = spell_id; PermaProcs[i].chance = iChance; PermaProcs[i].base_spellID = base_spell_id; + PermaProcs[i].level_override = level_override; Log.Out(Logs::Detail, Logs::Spells, "Added permanent proc spell %d with chance %d to slot %d", spell_id, iChance, i); return true; @@ -5121,6 +5123,7 @@ bool Mob::AddProcToWeapon(uint16 spell_id, bool bPerma, uint16 iChance, uint16 b SpellProcs[i].spellID = spell_id; SpellProcs[i].chance = iChance; SpellProcs[i].base_spellID = base_spell_id;; + SpellProcs[i].level_override = level_override; Log.Out(Logs::Detail, Logs::Spells, "Added spell-granted proc spell %d with chance %d to slot %d", spell_id, iChance, i); return true; } @@ -5136,6 +5139,7 @@ bool Mob::RemoveProcFromWeapon(uint16 spell_id, bool bAll) { SpellProcs[i].spellID = SPELL_UNKNOWN; SpellProcs[i].chance = 0; SpellProcs[i].base_spellID = SPELL_UNKNOWN; + SpellProcs[i].level_override = -1; Log.Out(Logs::Detail, Logs::Spells, "Removed proc %d from slot %d", spell_id, i); } } From a41fd122bce10ab6c4af7abb42863f4d76a17ff0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 May 2015 13:18:04 -0400 Subject: [PATCH 124/846] Add PetType petNone so IsCharmed stops lying --- zone/common.h | 3 ++- zone/mob.cpp | 8 +++++--- zone/spell_effects.cpp | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/zone/common.h b/zone/common.h index 13a65f7c5..d9e3637a8 100644 --- a/zone/common.h +++ b/zone/common.h @@ -521,7 +521,8 @@ typedef enum { petOther, petCharmed, petNPCFollow, - petTargetLock //remain active as long something is on the hatelist. Don't listen to any commands + petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands + petNone = 0xFF // not a pet } PetType; typedef enum { diff --git a/zone/mob.cpp b/zone/mob.cpp index 7f6cb9fbf..f26a3fb77 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -338,7 +338,7 @@ Mob::Mob(const char* in_name, pLastChange = 0; SetPetID(0); SetOwnerID(0); - typeofpet = petCharmed; //default to charmed... + typeofpet = petNone; // default to not a pet petpower = 0; held = false; nocast = false; @@ -2296,8 +2296,10 @@ 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(); + // if we're setting the owner ID to 0 and they're not either charmed or not-a-pet then + // they're a normal pet and should be despawned + if (ownerid == 0 && IsNPC() && GetPetType() != petCharmed && GetPetType() != petNone) + Depop(); } // used in checking for behind (backstab) and checking in front (melee LoS) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 28f5518fa..e3b4c4a3b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -773,6 +773,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove caster->SetPet(this); SetOwnerID(caster->GetID()); SetPetOrder(SPO_Follow); + SetPetType(petCharmed); if(caster->IsClient()){ EQApplicationPacket *app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); @@ -3915,6 +3916,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) SendAppearancePacket(AT_Pet, 0, true, true); Mob* tempmob = GetOwner(); SetOwnerID(0); + SetPetType(petNone); if(tempmob) { tempmob->SetPet(0); From 0348c0817d1b7bb0514b056035d9f0c823abc6a4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 May 2015 14:39:09 -0400 Subject: [PATCH 125/846] Make ResistSpell aware of the level_override nerf --- zone/mob.h | 3 ++- zone/spells.cpp | 29 +++++++++++++++-------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index 944b80d97..d1563347d 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -211,7 +211,8 @@ public: virtual int32 GetActSpellDuration(uint16 spell_id, int32 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 resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false, + int level_override = -1); int ResistPhysical(int level_diff, uint8 caster_level); uint16 GetSpecializeSkillValue(uint16 spell_id) const; void SendSpellBarDisable(); diff --git a/zone/spells.cpp b/zone/spells.cpp index 7286ba0aa..615239a9e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3665,9 +3665,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r if(IsResistableSpell(spell_id)) { if (IsCharmSpell(spell_id) || IsMezSpell(spell_id) || IsFearSpell(spell_id)) - spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resisttype, spell_id, this, use_resist_adjust, resist_adjust,true); + spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resisttype, spell_id, this, use_resist_adjust, resist_adjust, true, false, false, level_override); else - spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resisttype, spell_id, this, use_resist_adjust, resist_adjust); + spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resisttype, spell_id, this, use_resist_adjust, resist_adjust, false, false, false, level_override); if(spell_effectiveness < 100) { @@ -4208,7 +4208,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) // pvp_resist_base // pvp_resist_calc // pvp_resist_cap -float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override, int resist_override, bool CharismaCheck, bool CharmTick, bool IsRoot) +float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override, int resist_override, bool CharismaCheck, bool CharmTick, bool IsRoot, int level_override) { if(!caster) @@ -4351,18 +4351,19 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use int level_mod = 0; //Adjust our resist chance based on level modifiers - int temp_level_diff = GetLevel() - caster->GetLevel(); + uint8 caster_level = level_override > 0 ? level_override : caster->GetLevel(); + int temp_level_diff = GetLevel() - caster_level; //Physical Resists are calclated using their own formula derived from extensive parsing. if (resist_type == RESIST_PHYSICAL) { - level_mod = ResistPhysical(temp_level_diff, caster->GetLevel()); + level_mod = ResistPhysical(temp_level_diff, caster_level); } else { if(IsNPC() && GetLevel() >= RuleI(Casting,ResistFalloff)) { - int a = (RuleI(Casting,ResistFalloff)-1) - caster->GetLevel(); + int a = (RuleI(Casting,ResistFalloff)-1) - caster_level; if(a > 0) { temp_level_diff = a; @@ -4389,7 +4390,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use level_mod = -level_mod; } - if(IsNPC() && (caster->GetLevel() - GetLevel()) < -20) + if(IsNPC() && (caster_level - GetLevel()) < -20) { level_mod = 1000; } @@ -4400,7 +4401,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use int level_diff; if(GetLevel() >= RuleI(Casting,ResistFalloff)) { - level_diff = (RuleI(Casting,ResistFalloff)-1) - caster->GetLevel(); + level_diff = (RuleI(Casting,ResistFalloff)-1) - caster_level; if(level_diff < 0) { level_diff = 0; @@ -4408,7 +4409,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use } else { - level_diff = GetLevel() - caster->GetLevel(); + level_diff = GetLevel() - caster_level; } level_mod += (2 * level_diff); } @@ -4519,14 +4520,14 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use if(IsNPC()) { - if(GetLevel() > caster->GetLevel() && GetLevel() >= 17 && caster->GetLevel() <= 50) + if(GetLevel() > caster_level && GetLevel() >= 17 && caster_level <= 50) { partial_modifier += 5; } - if(GetLevel() >= 30 && caster->GetLevel() < 50) + if(GetLevel() >= 30 && caster_level < 50) { - partial_modifier += (caster->GetLevel() - 25); + partial_modifier += (caster_level - 25); } if(GetLevel() < 15) @@ -4537,9 +4538,9 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use if(caster->IsNPC()) { - if((GetLevel() - caster->GetLevel()) >= 20) + if((GetLevel() - caster_level) >= 20) { - partial_modifier += (GetLevel() - caster->GetLevel()) * 1.5; + partial_modifier += (GetLevel() - caster_level) * 1.5; } } From b0d85e35587d73370ea4e641b947e4cb49bbbe90 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 May 2015 14:55:32 -0400 Subject: [PATCH 126/846] More focus messages thanks to Google --- zone/spell_effects.cpp | 6 ++++++ zone/string_ids.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e3b4c4a3b..b11b21403 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5416,6 +5416,12 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { case focusRange: string_id = PULSES_WITH_LIGHT; break; + case focusSpellHateMod: + string_id = GLOWS_BLUE; + break; + case focusImprovedHeal: + string_id = FEEDS_WITH_POWER; + break; default: break; } diff --git a/zone/string_ids.h b/zone/string_ids.h index fb52985c0..19d7436d0 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -350,6 +350,8 @@ #define YOU_HEAL 9068 //You have healed %1 for %2 points of damage. #define YOUR_HIT_DOT 9072 //%1 has taken %2 damage from your %3. #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 STRIKETHROUGH_STRING 9078 //You strike through your opponent's defenses! #define SPELL_REFLECT 9082 //%1's spell has been reflected by %2. From 96264cb688a5e60bb830e697adfef8be529d9c48 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 May 2015 15:26:32 -0400 Subject: [PATCH 127/846] Send the BEGIN_TO_GLOW message after OP_BeginCast when casting a clicky --- zone/spells.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 615239a9e..1af93bba5 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -489,6 +489,12 @@ 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) { + auto item = CastToClient()->GetInv().GetItem(item_slot); + if (item && item->GetItem()) + Message_StringID(MT_Spells, BEGINS_TO_GLOW, item->GetItem()->Name); + } + if (!DoCastingChecks()) { InterruptSpell(); return false; From d9cab4820ab2161a1d5faf536ad76e1d22c56766 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 May 2015 21:16:30 -0400 Subject: [PATCH 128/846] More focus messages --- zone/spell_effects.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b11b21403..3336026c7 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5399,6 +5399,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { if (realTotal != 0 && UsedItem) { // there are a crap ton more of these, I was able to verify these ones though + // the RNG effective ones appear to have a different message for failing to focus uint32 string_id = BEGINS_TO_GLOW; // this is really just clicky message ... switch (type) { case focusSpellHaste: @@ -5422,6 +5423,9 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { case focusImprovedHeal: string_id = FEEDS_WITH_POWER; break; + case focusReagentCost: + string_id = BEGINS_TO_SHINE; + break; default: break; } From 38cdea7d7e3e556190e4f3c838090250f4d459f5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 30 May 2015 02:57:03 -0400 Subject: [PATCH 129/846] Furious Bash focus message --- zone/special_attacks.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 0f0a110cd..a3557d021 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -120,7 +120,10 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, hate += item->GetItem()->AC; } const Item_Struct *itm = item->GetItem(); - hate = hate * (100 + GetFuriousBash(itm->Focus.Effect)) / 100; + auto fbash = GetFuriousBash(itm->Focus.Effect); + hate = hate * (100 + fbash) / 100; + if (fbash) + Message_StringID(MT_Spells, GLOWS_RED, itm->Name); } } } From bfb40f6c5f79727ebf7426a27c1cf337e7c4a441 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 30 May 2015 03:08:02 -0400 Subject: [PATCH 130/846] Add failure messages for RNG focus --- zone/spell_effects.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 3336026c7..8b71c7d92 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5397,7 +5397,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { if(UsedItem && rand_effectiveness && focus_max_real != 0) realTotal = CalcFocusEffect(type, UsedFocusID, spell_id); - if (realTotal != 0 && UsedItem) { + if ((rand_effectiveness && UsedItem) || (realTotal != 0 && UsedItem)) { // there are a crap ton more of these, I was able to verify these ones though // the RNG effective ones appear to have a different message for failing to focus uint32 string_id = BEGINS_TO_GLOW; // this is really just clicky message ... @@ -5405,25 +5405,31 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { case focusSpellHaste: string_id = SHIMMERS_BRIEFLY; break; - case focusManaCost: + case focusManaCost: // this might be GROWS_DIM for fail string_id = FLICKERS_PALE_LIGHT; break; case focusSpellDuration: string_id = SPARKLES; break; case focusImprovedDamage: - string_id = ALIVE_WITH_POWER; + if (realTotal) + string_id = ALIVE_WITH_POWER; + else + string_id = SEEMS_DRAINED; break; case focusRange: string_id = PULSES_WITH_LIGHT; break; - case focusSpellHateMod: + case focusSpellHateMod: // GLOWS_RED for increasing hate string_id = GLOWS_BLUE; break; case focusImprovedHeal: - string_id = FEEDS_WITH_POWER; + if (realTotal) + string_id = FEEDS_WITH_POWER; + else + string_id = POWER_DRAIN_INTO; break; - case focusReagentCost: + case focusReagentCost: // this might be GROWS_DIM for fail as well ... string_id = BEGINS_TO_SHINE; break; default: From 03c006bef52914075121d055c765494d993b8c24 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 30 May 2015 15:43:16 -0400 Subject: [PATCH 131/846] Implement ST_AEClientV1 This should at least be as correct as ST_AEBard is, unsure of the differences --- zone/spells.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 1af93bba5..868180dff 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -370,6 +370,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, // and a target wasn't provided, then it's us; unless TGB is on and this // is a TGB compatible spell. if((IsGroupSpell(spell_id) || + spell.targettype == ST_AEClientV1 || spell.targettype == ST_Self || spell.targettype == ST_AECaster || spell.targettype == ST_Ring || @@ -393,7 +394,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, // we checked for spells not requiring targets above if(target_id == 0) { - Log.Out(Logs::Detail, Logs::Spells, "Spell Error: no target. spell=%d\n", GetName(), spell_id); + Log.Out(Logs::Detail, Logs::Spells, "Spell Error: no target. spell=%d", spell_id); if(IsClient()) { //clients produce messages... npcs should not for this case Message_StringID(13, SPELL_NEED_TAR); @@ -1618,6 +1619,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce case ST_AEBard: case ST_AECaster: + case ST_AEClientV1: { spell_target = nullptr; ae_center = this; From 7011395d4c7df74e95ca0d6b394f91699e750207 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 31 May 2015 00:09:59 -0400 Subject: [PATCH 132/846] Pet target in UF+ I think older clients might have something like this that sets some spawn data, but these are the only clients that display something --- common/emu_oplist.h | 1 + utils/patches/patch_RoF.conf | 1 + utils/patches/patch_RoF2.conf | 1 + utils/patches/patch_UF.conf | 1 + zone/pets.cpp | 16 ++++++++++++++++ zone/pets.h | 1 + 6 files changed, 21 insertions(+) diff --git a/common/emu_oplist.h b/common/emu_oplist.h index c51e4b600..e4793826e 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -348,6 +348,7 @@ N(OP_OpenTributeMaster), N(OP_PDeletePetition), N(OP_PetBuffWindow), N(OP_PetCommands), +N(OP_PetHoTT), N(OP_Petition), N(OP_PetitionBug), N(OP_PetitionCheckIn), diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 02d7c9bb8..6e3f0ab1a 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -194,6 +194,7 @@ OP_Consent=0x400e OP_ConsentDeny=0x34c1 OP_AutoFire=0x314e OP_PetCommands=0x0093 +OP_PetHoTT=0x0df4 OP_DeleteSpell=0x305c OP_Surname=0x1a87 OP_ClearSurname=0x17b6 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 312f725fe..1ebf05442 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -193,6 +193,7 @@ OP_Consent=0x1fd1 OP_ConsentDeny=0x7a45 OP_AutoFire=0x241e OP_PetCommands=0x0159 +OP_PetHoTT=0x794a OP_DeleteSpell=0x3358 OP_Surname=0x0423 OP_ClearSurname=0x3fb0 diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index cbe57e399..6f94c92db 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -197,6 +197,7 @@ OP_Consent=0x6bb9 # C OP_ConsentDeny=0x4cd1 # C OP_AutoFire=0x5db5 # C OP_PetCommands=0x7706 # C +OP_PetHoTT=0x2528 OP_DeleteSpell=0x0698 # C OP_Surname=0x44ae # C OP_ClearSurname=0x6705 # C diff --git a/zone/pets.cpp b/zone/pets.cpp index 908b756d4..e096328b9 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -457,6 +457,22 @@ Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 po // Class should use npc constructor to set light properties } +void Pet::SetTarget(Mob *mob) +{ + if (mob == GetTarget()) + return; + + auto owner = GetOwner(); + if (owner && owner->IsClient() && owner->CastToClient()->GetClientVersionBit() & BIT_UFAndLater) { + auto app = new EQApplicationPacket(OP_PetHoTT, sizeof(ClientTarget_Struct)); + auto ct = (ClientTarget_Struct *)app->pBuffer; + ct->new_target = mob ? mob->GetID() : 0; + owner->CastToClient()->QueuePacket(app); + safe_delete(app); + } + NPC::SetTarget(mob); +} + bool ZoneDatabase::GetPetEntry(const char *pet_type, PetRecord *into) { return GetPoweredPetEntry(pet_type, 0, into); } diff --git a/zone/pets.h b/zone/pets.h index f0c71fbe7..32ca00eac 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -39,6 +39,7 @@ struct NPCType; class Pet : public NPC { public: Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power); + virtual void SetTarget(Mob *mob); }; From 46dd1511af6916afee044e27d11fc0adfb979da6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 1 Jun 2015 14:15:45 -0400 Subject: [PATCH 133/846] Fix DoBuffTic crash --- zone/spell_effects.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 8b71c7d92..b331113bd 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3707,6 +3707,8 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) // do we need to do anyting here? } } + if (!IsValidSpell(buff.spellid)) // if we faded we're no longer valid! + break; } } From aacd288ad7709687e5e3ca4f89ed1038fb69a929 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 1 Jun 2015 15:47:04 -0400 Subject: [PATCH 134/846] 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 ff2976607..bf2d23f30 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -151,7 +151,7 @@ typedef enum { } DmgShieldType; //Spell Effect IDs -// full listing: https://forums.station.sony.com/eq/index.php?threads/enumerated-spa-list.206288/ +// https://forums.daybreakgames.com/eq/index.php?threads/enumerated-spa-list.206288/ // mirror: http://pastebin.com/MYeQqGwe #define SE_CurrentHP 0 // implemented - Heals and nukes, repeates every tic if in a buff #define SE_ArmorClass 1 // implemented From c3c6d1897965eb2e794f0fd19d9a6d5ee9307a7b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 1 Jun 2015 16:02:55 -0400 Subject: [PATCH 135/846] Fix RoF+ AA clientver bug --- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- zone/aa.cpp | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 9f9f58ab2..fae650eb5 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2852,7 +2852,7 @@ namespace RoF // Check clientver field to verify this AA should be sent for SoF // clientver 1 is for all clients and 5 is for Live - if (emu->clientver <= 5) + if (emu->clientver <= 7) { OUT(id); eq->unknown004 = 1; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 708c5a6a9..42e97b9eb 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2941,7 +2941,7 @@ namespace RoF2 // Check clientver field to verify this AA should be sent for SoF // clientver 1 is for all clients and 5 is for Live - if (emu->clientver <= 5) + if (emu->clientver <= 8) { OUT(id); eq->unknown004 = 1; diff --git a/zone/aa.cpp b/zone/aa.cpp index b0208326a..b6e220d60 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1309,11 +1309,9 @@ void Client::SendAA(uint32 id, int seq) { SendAA_Struct* saa_next = nullptr; saa_next = zone->FindAA(saa->sof_next_id); - // hard-coding values like this is dangerous and makes adding/updating clients a nightmare... - if (saa_next && - (((GetClientVersionBit() == 4) && (saa_next->clientver > 4)) - || ((GetClientVersionBit() == 8) && (saa_next->clientver > 5)) - || ((GetClientVersionBit() == 16) && (saa_next->clientver > 6)))){ + // this check should work as long as we continue to just add the clients and just increase + // each number .... + if (saa_next && static_cast(GetClientVersion()) < saa_next->clientver - 1) { saa->next_id=0xFFFFFFFF; } } From 9a5ff58213b80ec08f2595b152d7c40b8d2f522b Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 1 Jun 2015 22:20:41 -0400 Subject: [PATCH 136/846] Added GetGlobal() support for all Mobs. - Uses memory (no database hits) - Allows entity-based quest global checks --- zone/lua_mob.cpp | 6 ++++++ zone/lua_mob.h | 1 + zone/mob.cpp | 33 +++++++++++++++++++++++++++++++++ zone/mob.h | 1 + zone/perl_mob.cpp | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 036af2072..60a42760c 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1631,6 +1631,11 @@ void Lua_Mob::TempName(const char *newname) { self->TempName(newname); } +std::string Lua_Mob::GetGlobal(const char *varname) { + Lua_Safe_Call_String(); + return self->GetGlobal(varname); +} + void Lua_Mob::SetGlobal(const char *varname, const char *newvalue, int options, const char *duration) { Lua_Safe_Call_Void(); self->SetGlobal(varname, newvalue, options, duration); @@ -2120,6 +2125,7 @@ luabind::scope lua_register_mob() { .def("SendSpellEffect", (void(Lua_Mob::*)(uint32,uint32,uint32,bool,uint32,bool,Lua_Client))&Lua_Mob::SendSpellEffect) .def("TempName", (void(Lua_Mob::*)(void))&Lua_Mob::TempName) .def("TempName", (void(Lua_Mob::*)(const char*))&Lua_Mob::TempName) + .def("GetGlobal", (std::string(Lua_Mob::*)(const char*))&Lua_Mob::GetGlobal) .def("SetGlobal", (void(Lua_Mob::*)(const char*,const char*,int,const char*))&Lua_Mob::SetGlobal) .def("SetGlobal", (void(Lua_Mob::*)(const char*,const char*,int,const char*,Lua_Mob))&Lua_Mob::SetGlobal) .def("TarGlobal", (void(Lua_Mob::*)(const char*,const char*,const char*,int,int,int))&Lua_Mob::TarGlobal) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 3caf62839..54c388ed4 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -307,6 +307,7 @@ public: uint32 unk020, bool perm_effect, Lua_Client c); void TempName(); void TempName(const char *newname); + std::string GetGlobal(const char *varname); void SetGlobal(const char *varname, const char *newvalue, int options, const char *duration); void SetGlobal(const char *varname, const char *newvalue, int options, const char *duration, Lua_Mob other); void TarGlobal(const char *varname, const char *value, const char *duration, int npc_id, int char_id, int zone_id); diff --git a/zone/mob.cpp b/zone/mob.cpp index f26a3fb77..8a224db0b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4202,6 +4202,39 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier) return stat; } +std::string Mob::GetGlobal(const char *varname) { + int qgCharid = 0; + int qgNpcid = 0; + + if (this->IsNPC()) + qgNpcid = this->GetNPCTypeID(); + + if (this->IsClient()) + qgCharid = this->CastToClient()->CharacterID(); + + QGlobalCache *qglobals = nullptr; + std::list globalMap; + + if (this->IsClient()) + qglobals = this->CastToClient()->GetQGlobals(); + + if (this->IsNPC()) + qglobals = this->CastToNPC()->GetQGlobals(); + + if(qglobals) + QGlobalCache::Combine(globalMap, qglobals->GetBucket(), qgNpcid, qgCharid, zone->GetZoneID()); + + std::list::iterator iter = globalMap.begin(); + while(iter != globalMap.end()) { + if ((*iter).name.compare(varname) == 0) + return (*iter).value; + + ++iter; + } + + return "Undefined"; +} + void Mob::SetGlobal(const char *varname, const char *newvalue, int options, const char *duration, Mob *other) { int qgZoneid = zone->GetZoneID(); diff --git a/zone/mob.h b/zone/mob.h index d1563347d..74a53346e 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -911,6 +911,7 @@ public: inline virtual bool IsBlockedBuff(int16 SpellID) { return false; } inline virtual bool IsBlockedPetBuff(int16 SpellID) { return false; } + std::string GetGlobal(const char *varname); 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); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index f5ab99cd6..f5ef80a4c 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -7321,6 +7321,37 @@ XS(XS_Mob_GetItemStat) XSRETURN(1); } +XS(XS_Mob_GetGlobal); +XS(XS_Mob_GetGlobal) +{ + dXSARGS; + if (items < 2) + Perl_croak(aTHX_ "Usage: GetGlobal(THIS, varname)"); + { + Mob* THIS; + Const_char* varname = (Const_char*)SvPV_nolen(ST(1)); + std::string ret_val = "Undefined"; + Const_char* RETVAL; + dXSTARG; + + 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 (THIS->GetGlobal(varname) != "Undefined") + ret_val = THIS->GetGlobal(varname); + + RETVAL = ret_val.c_str(); + sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; + } + XSRETURN(1); +} + XS(XS_Mob_SetGlobal); XS(XS_Mob_SetGlobal) { @@ -8623,6 +8654,7 @@ XS(boot_Mob) newXSproto(strcpy(buf, "SpellEffect"), XS_Mob_SpellEffect, file, "$$;$$$$$$"); newXSproto(strcpy(buf, "TempName"), XS_Mob_TempName, file, "$:$"); newXSproto(strcpy(buf, "GetItemStat"), XS_Mob_GetItemStat, file, "$$$"); + newXSproto(strcpy(buf, "GetGlobal"), XS_Mob_GetGlobal, file, "$$"); newXSproto(strcpy(buf, "SetGlobal"), XS_Mob_SetGlobal, file, "$$$$$;$"); newXSproto(strcpy(buf, "TarGlobal"), XS_Mob_TarGlobal, file, "$$$$$$$"); newXSproto(strcpy(buf, "DelGlobal"), XS_Mob_DelGlobal, file, "$$"); From 2c6fd44811cc76bb8201d03c96eecfe6381c6a23 Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Tue, 2 Jun 2015 12:25:09 -0700 Subject: [PATCH 137/846] Implemented encounter timers - no spawn required --- zone/encounter.cpp | 53 +++++++++++++++++++++++++++ zone/encounter.h | 62 ++++++++++++++++++++++++++++++++ zone/entity.cpp | 47 ++++++++++++++++++++++++ zone/entity.h | 8 +++++ zone/lua_general.cpp | 22 ++++++++---- zone/lua_parser.cpp | 25 +++++++++---- zone/lua_parser.h | 6 ++-- zone/lua_parser_events.cpp | 11 ++++++ zone/lua_parser_events.h | 8 +++++ zone/net.cpp | 1 + zone/quest_interface.h | 2 +- zone/quest_parser_collection.cpp | 6 ++-- zone/quest_parser_collection.h | 3 +- zone/questmgr.cpp | 2 ++ 14 files changed, 237 insertions(+), 19 deletions(-) create mode 100644 zone/encounter.cpp create mode 100644 zone/encounter.h diff --git a/zone/encounter.cpp b/zone/encounter.cpp new file mode 100644 index 000000000..1f77de43a --- /dev/null +++ b/zone/encounter.cpp @@ -0,0 +1,53 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2003 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 +*/ + +#ifdef _WINDOWS +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + +#include "../common/races.h" +#include "encounter.h" +#include "entity.h" +#include "mob.h" + +class Zone; + +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 + ) +{ + encounter_name[0] = 0; + strn0cpy(encounter_name, enc_name, 64); + remove_me = false; +} + +Encounter::~Encounter() +{ + +} + +bool Encounter::Process() { + if (remove_me) return false; + return true; +} diff --git a/zone/encounter.h b/zone/encounter.h new file mode 100644 index 000000000..a2977d7e0 --- /dev/null +++ b/zone/encounter.h @@ -0,0 +1,62 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2003 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 ENCOUNTER_H +#define ENCOUNTER_H + +#include "mob.h" +#include "../common/types.h" +#include "../common/timer.h" + +class Group; +class Raid; +struct ExtraAttackOptions; + +class Encounter : public Mob +{ +public: + Encounter(const char* enc_name); + ~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) { return; } + virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + ExtraAttackOptions *opts = nullptr) { + return false; + } + virtual bool HasRaid() { return false; } + virtual bool HasGroup() { return false; } + virtual Raid* GetRaid() { return 0; } + virtual Group* GetGroup() { return 0; } + + bool IsEncounter() const { return true; } + const char* GetEncounterName() const { return encounter_name; } + + bool Process(); + virtual void Depop(bool not_used = true) { remove_me = true; } + + +protected: + bool remove_me; + char encounter_name[64]; + +private: +}; + +#endif diff --git a/zone/entity.cpp b/zone/entity.cpp index bf1f6b720..baa4f4354 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -173,6 +173,11 @@ Beacon *Entity::CastToBeacon() return static_cast(this); } +Encounter *Entity::CastToEncounter() +{ + return static_cast(this); +} + const Client *Entity::CastToClient() const { if (this == 0x00) { @@ -263,6 +268,11 @@ const Beacon* Entity::CastToBeacon() const return static_cast(this); } +const Encounter* Entity::CastToEncounter() const +{ + return static_cast(this); +} + #ifdef BOTS Bot *Entity::CastToBot() { @@ -533,6 +543,21 @@ void EntityList::BeaconProcess() } } +void EntityList::EncounterProcess() +{ + auto it = encounter_list.begin(); + while (it != encounter_list.end()) { + if (!it->second->Process()) { + safe_delete(it->second); + free_ids.push(it->first); + it = encounter_list.erase(it); + } + else { + ++it; + } + } +} + void EntityList::AddGroup(Group *group) { if (group == nullptr) //this seems to be happening somehow... @@ -708,6 +733,12 @@ void EntityList::AddBeacon(Beacon *beacon) beacon_list.insert(std::pair(beacon->GetID(), beacon)); } +void EntityList::AddEncounter(Encounter *encounter) +{ + encounter->SetID(GetFreeID()); + encounter_list.insert(std::pair(encounter->GetID(), encounter)); +} + void EntityList::AddToSpawnQueue(uint16 entityid, NewSpawn_Struct **ns) { uint32 count; @@ -935,6 +966,11 @@ Entity *EntityList::GetEntityBeacon(uint16 id) return beacon_list.count(id) ? beacon_list.at(id) : nullptr; } +Entity *EntityList::GetEntityEncounter(uint16 id) +{ + return encounter_list.count(id) ? encounter_list.at(id) : nullptr; +} + Entity *EntityList::GetID(uint16 get_id) { Entity *ent = 0; @@ -950,6 +986,8 @@ Entity *EntityList::GetID(uint16 get_id) return ent; else if ((ent=entity_list.GetEntityBeacon(get_id)) != 0) return ent; + else if ((ent = entity_list.GetEntityEncounter(get_id)) != 0) + return ent; else return 0; } @@ -3424,6 +3462,15 @@ bool EntityList::IsMobInZone(Mob *who) } ++it; } + + auto enc_it = encounter_list.begin(); + while (enc_it != encounter_list.end()) { + if (enc_it->second == who) { + return true; + } + ++enc_it; + } + return false; } diff --git a/zone/entity.h b/zone/entity.h index 8af87f649..446c5d505 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -30,6 +30,7 @@ #include "position.h" #include "zonedump.h" +class Encounter; class Beacon; class Client; class Corpse; @@ -77,6 +78,7 @@ public: virtual bool IsDoor() const { return false; } virtual bool IsTrap() const { return false; } virtual bool IsBeacon() const { return false; } + virtual bool IsEncounter() const { return false; } virtual bool Process() { return false; } virtual bool Save() { return true; } @@ -91,6 +93,7 @@ public: Doors *CastToDoors(); Trap *CastToTrap(); Beacon *CastToBeacon(); + Encounter *CastToEncounter(); const Client *CastToClient() const; const NPC *CastToNPC() const; @@ -101,6 +104,7 @@ public: const Doors *CastToDoors() const; const Trap *CastToTrap() const; const Beacon *CastToBeacon() const; + const Encounter *CastToEncounter() const; inline const uint16& GetID() const { return id; } inline const time_t& GetSpawnTimeStamp() const { return spawn_timestamp; } @@ -203,6 +207,7 @@ public: void MobProcess(); void TrapProcess(); void BeaconProcess(); + void EncounterProcess(); void ProcessMove(Client *c, const glm::vec3& location); void ProcessMove(NPC *n, float x, float y, float z); void AddArea(int id, int type, float min_x, float max_x, float min_y, float max_y, float min_z, float max_z); @@ -228,6 +233,7 @@ public: void AddDoor(Doors* door); void AddTrap(Trap* trap); void AddBeacon(Beacon *beacon); + void AddEncounter(Encounter *encounter); void AddProximity(NPC *proximity_for); void Clear(); bool RemoveMob(uint16 delete_id); @@ -266,6 +272,7 @@ public: Entity *GetEntityCorpse(uint16 id); Entity *GetEntityTrap(uint16 id); Entity *GetEntityBeacon(uint16 id); + Entity *GetEntityEncounter(uint16 id); Entity *GetEntityMob(const char *name); Entity *GetEntityCorpse(const char *name); @@ -448,6 +455,7 @@ private: std::unordered_map door_list; std::unordered_map trap_list; std::unordered_map beacon_list; + std::unordered_map encounter_list; std::list proximity_list; std::list group_list; std::list raid_list; diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 6b290dc03..271bc0a97 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -34,6 +34,8 @@ struct lua_registered_event { extern std::map> lua_encounter_events_registered; extern std::map lua_encounters_loaded; +extern std::map lua_encounters; + extern void MapOpcodes(); extern void ClearMappedOpcode(EmuOpcode op); @@ -42,19 +44,23 @@ 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()); + entity_list.AddEncounter(enc); + lua_encounters[name] = enc; lua_encounters_loaded[name] = true; - parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, 0); + parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, "", 0); } 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()); + entity_list.AddEncounter(enc); + lua_encounters[name] = enc; lua_encounters_loaded[name] = true; std::vector info_ptrs; info_ptrs.push_back(&info_str); - parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, 0, &info_ptrs); + parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, "", 0, &info_ptrs); } void unload_encounter(std::string name) { @@ -80,8 +86,10 @@ void unload_encounter(std::string name) { } } + lua_encounters[name]->Depop(); + lua_encounters.erase(name); lua_encounters_loaded.erase(name); - parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, 0); + parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, "", 0); } void unload_encounter_with_data(std::string name, std::string info_str) { @@ -109,10 +117,12 @@ void unload_encounter_with_data(std::string name, std::string info_str) { } } + lua_encounters[name]->Depop(); + lua_encounters.erase(name); lua_encounters_loaded.erase(name); std::vector info_ptrs; info_ptrs.push_back(&info_str); - parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, 0, &info_ptrs); + parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, "", 0, &info_ptrs); } void register_event(std::string package_name, std::string name, int evt, luabind::adl::object func) { diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 7f6412b0f..383691864 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -128,6 +128,7 @@ struct lua_registered_event { std::map> lua_encounter_events_registered; std::map lua_encounters_loaded; +std::map lua_encounters; LuaParser::LuaParser() { for(int i = 0; i < _LargestEventID; ++i) { @@ -135,6 +136,7 @@ LuaParser::LuaParser() { PlayerArgumentDispatch[i] = handle_player_null; ItemArgumentDispatch[i] = handle_item_null; SpellArgumentDispatch[i] = handle_spell_null; + EncounterArgumentDispatch[i] = handle_encounter_null; } NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say; @@ -213,6 +215,8 @@ LuaParser::LuaParser() { SpellArgumentDispatch[EVENT_SPELL_FADE] = handle_spell_fade; SpellArgumentDispatch[EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE] = handle_translocate_finish; + EncounterArgumentDispatch[EVENT_TIMER] = handle_encounter_timer; + L = nullptr; } @@ -575,7 +579,7 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, return 0; } -int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data, std::vector *extra_pointers) { +int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return 0; @@ -587,10 +591,10 @@ int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, uint return 0; } - return _EventEncounter(package_name, evt, encounter_name, extra_data, extra_pointers); + return _EventEncounter(package_name, evt, encounter_name, data, extra_data, extra_pointers); } -int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, uint32 extra_data, +int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers) { const char *sub_name = LuaEvents[evt]; @@ -604,13 +608,17 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std:: lua_pushstring(L, encounter_name.c_str()); lua_setfield(L, -2, "name"); - if(extra_pointers) { + /*if(extra_pointers) { std::string *str = EQEmu::any_cast(extra_pointers->at(0)); lua_pushstring(L, str->c_str()); lua_setfield(L, -2, "data"); - } + }*/ - quest_manager.StartQuest(nullptr, nullptr, nullptr, encounter_name); + auto arg_function = EncounterArgumentDispatch[evt]; + arg_function(this, L, data, extra_data, extra_pointers); + + Encounter *enc = lua_encounters[encounter_name]; + quest_manager.StartQuest(enc, nullptr, nullptr, encounter_name); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); AddError(error); @@ -786,6 +794,11 @@ void LuaParser::ReloadQuests() { lua_encounter_events_registered.clear(); lua_encounters_loaded.clear(); + for (auto encounter : lua_encounters) { + encounter.second->Depop(); + } + lua_encounters.clear(); + if(L) { lua_close(L); } diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 13cebe0fc..63d9facfe 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -39,7 +39,7 @@ public: std::vector *extra_pointers); virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers); - virtual int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data, + virtual int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers); virtual bool HasQuestSub(uint32 npc_id, QuestEventID evt); @@ -82,7 +82,7 @@ private: 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); - int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, uint32 extra_data, + int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers); void LoadScript(std::string filename, std::string package_name); @@ -99,6 +99,8 @@ private: PlayerArgumentHandler PlayerArgumentDispatch[_LargestEventID]; ItemArgumentHandler ItemArgumentDispatch[_LargestEventID]; SpellArgumentHandler SpellArgumentDispatch[_LargestEventID]; + EncounterArgumentHandler EncounterArgumentDispatch[_LargestEventID]; + }; #endif diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 2780d0212..adccf433b 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -704,4 +704,15 @@ void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl std::vector *extra_pointers) { } +void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, + std::vector *extra_pointers) { + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "timer"); +} + +void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, + std::vector *extra_pointers) { + +} + #endif diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 1965a9189..818bcf5be 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -6,6 +6,7 @@ typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std:: 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(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, uint32, std::vector*); +typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, std::string, uint32, std::vector*); //NPC void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, @@ -127,5 +128,12 @@ void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Cl void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers); + +//Encounter +void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, + std::vector *extra_pointers); +void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, + std::vector *extra_pointers); + #endif #endif diff --git a/zone/net.cpp b/zone/net.cpp index 92f568af0..ef6b46836 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -423,6 +423,7 @@ int main(int argc, char** argv) { entity_list.Process(); entity_list.MobProcess(); entity_list.BeaconProcess(); + entity_list.EncounterProcess(); if (zone) { if(!zone->Process()) { diff --git a/zone/quest_interface.h b/zone/quest_interface.h index 68c79923f..c1cf3dc73 100644 --- a/zone/quest_interface.h +++ b/zone/quest_interface.h @@ -41,7 +41,7 @@ public: 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; } - virtual int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data, + virtual int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers) { return 0; } virtual bool HasQuestSub(uint32 npcid, QuestEventID evt) { return false; } diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 37e518c24..845769532 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -434,14 +434,14 @@ int QuestParserCollection::EventSpell(QuestEventID evt, NPC* npc, Client *client return 0; } -int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data, +int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers) { auto iter = _encounter_quest_status.find(encounter_name); if(iter != _encounter_quest_status.end()) { //loaded or failed to load if(iter->second != QuestFailedToLoad) { std::map::iterator qiter = _interfaces.find(iter->second); - return qiter->second->EventEncounter(evt, encounter_name, extra_data, extra_pointers); + return qiter->second->EventEncounter(evt, encounter_name, data, extra_data, extra_pointers); } } else { std::string filename; @@ -449,7 +449,7 @@ int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounte if(qi) { _encounter_quest_status[encounter_name] = qi->GetIdentifier(); qi->LoadEncounterScript(filename, encounter_name); - return qi->EventEncounter(evt, encounter_name, extra_data, extra_pointers); + return qi->EventEncounter(evt, encounter_name, data, extra_data, extra_pointers); } else { _encounter_quest_status[encounter_name] = QuestFailedToLoad; } diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index 62cb034dc..3ebce378c 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -21,6 +21,7 @@ #include "../common/types.h" +#include "encounter.h" #include "beacon.h" #include "client.h" #include "corpse.h" @@ -71,7 +72,7 @@ public: std::vector *extra_pointers = nullptr); int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers = nullptr); - int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data, + int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers = nullptr); void GetErrors(std::list &err); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 825e3b7b1..67a1f06da 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -84,6 +84,8 @@ void QuestManager::Process() { if(entity_list.IsMobInZone(cur->mob)) { if(cur->mob->IsNPC()) { parse->EventNPC(EVENT_TIMER, cur->mob->CastToNPC(), nullptr, cur->name, 0); + } else if (cur->mob->IsEncounter()) { + parse->EventEncounter(EVENT_TIMER, cur->mob->CastToEncounter()->GetEncounterName(), cur->name, 0, nullptr); } else { //this is inheriently unsafe if we ever make it so more than npc/client start timers parse->EventPlayer(EVENT_TIMER, cur->mob->CastToClient(), cur->name, 0); From 6ff06ded43a5971287ea6c305bb13ca8aac3fbe7 Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Tue, 2 Jun 2015 15:21:27 -0700 Subject: [PATCH 138/846] Fix for extra_pointers in Encounter methods --- zone/lua_parser.cpp | 2 ++ zone/lua_parser_events.cpp | 20 +++++++++++++++++++- zone/lua_parser_events.h | 4 ++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 383691864..2442838a3 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -216,6 +216,8 @@ LuaParser::LuaParser() { SpellArgumentDispatch[EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE] = handle_translocate_finish; EncounterArgumentDispatch[EVENT_TIMER] = handle_encounter_timer; + EncounterArgumentDispatch[EVENT_ENCOUNTER_LOAD] = handle_encounter_load; + EncounterArgumentDispatch[EVENT_ENCOUNTER_UNLOAD] = handle_encounter_unload; L = nullptr; } diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index adccf433b..5428304a6 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -710,8 +710,26 @@ void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string dat lua_setfield(L, -2, "timer"); } +void handle_encounter_load(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, + std::vector *extra_pointers) { + if (extra_pointers) { + std::string *str = EQEmu::any_cast(extra_pointers->at(0)); + lua_pushstring(L, str->c_str()); + lua_setfield(L, -2, "data"); + } +} + +void handle_encounter_unload(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, + std::vector *extra_pointers) { + if (extra_pointers) { + std::string *str = EQEmu::any_cast(extra_pointers->at(0)); + lua_pushstring(L, str->c_str()); + lua_setfield(L, -2, "data"); + } +} + void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, - std::vector *extra_pointers) { + std::vector *extra_pointers) { } diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 818bcf5be..46609fb06 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -132,6 +132,10 @@ void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl //Encounter void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, std::vector *extra_pointers); +void handle_encounter_load(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, + std::vector *extra_pointers); +void handle_encounter_unload(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, + std::vector *extra_pointers); void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, std::vector *extra_pointers); From c351a9b54f74b2b1b1464052ca64fb1c19067d0f Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Tue, 2 Jun 2015 15:27:57 -0700 Subject: [PATCH 139/846] Removed unnecessary commented code. --- zone/lua_parser.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 2442838a3..4b5a1faad 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -610,12 +610,6 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std:: lua_pushstring(L, encounter_name.c_str()); lua_setfield(L, -2, "name"); - /*if(extra_pointers) { - std::string *str = EQEmu::any_cast(extra_pointers->at(0)); - lua_pushstring(L, str->c_str()); - lua_setfield(L, -2, "data"); - }*/ - auto arg_function = EncounterArgumentDispatch[evt]; arg_function(this, L, data, extra_data, extra_pointers); From 328b7bb93c3100526110ec408336d17eb5b943ee Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Tue, 2 Jun 2015 16:32:42 -0700 Subject: [PATCH 140/846] Add encounters header to lua_general.cpp --- zone/lua_general.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 271bc0a97..139951724 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -18,6 +18,7 @@ #include "qglobals.h" #include "../common/timer.h" #include "../common/eqemu_logsys.h" +#include "encounter.h" struct Events { }; struct Factions { }; From dbd07106d7078557b61cb565e4ea76946744d3ab Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Tue, 2 Jun 2015 17:17:40 -0700 Subject: [PATCH 141/846] Updated zone cmakelists.txt --- zone/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 44a6d02c8..2510dcddb 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -20,6 +20,7 @@ SET(zone_sources embparser_api.cpp embperl.cpp embxs.cpp + encounter.cpp entity.cpp exp.cpp fearpath.cpp @@ -137,6 +138,7 @@ SET(zone_headers embparser.h embperl.h embxs.h + encounter.h entity.h errmsg.h event_codes.h From 7f30950fdbbe3b33a0630804abcf8861e0425685 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Wed, 3 Jun 2015 10:08:55 -0700 Subject: [PATCH 142/846] More group related bot crashes fixed. Bots can now be targeted in the group window and kicked from party. They are also no longer raid_targets when conned. --- zone/bot.cpp | 14 ++++++-------- zone/client_packet.cpp | 10 ++++++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index ebc5f47d3..e76389b24 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -758,6 +758,7 @@ void Bot::GenerateBaseStats() { this->pAggroRange = 0; this->pAssistRange = 0; + this->raid_target = false; } void Bot::GenerateAppearance() { @@ -5292,9 +5293,6 @@ bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) { if(group->DelMember(bot)) database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID()); - - if(group->GroupCount() <= 1 && ZoneLoaded) - group->DisbandGroup(); } else { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { @@ -5896,6 +5894,11 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att // delete from group data RemoveBotFromGroup(this, g); + + //Make sure group still exists if it doesnt they were already updated in RemoveBotFromGroup + g = GetGroup(); + if (!g) + break; // if group members exist below this one, move // them all up one slot in the group list @@ -5910,11 +5913,6 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att } } - //Make sure group still exists if it doesnt they were already updated in RemoveBotFromGroup - g = GetGroup(); - if (!g) - break; - // update the client group EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index ccb27a188..b9dfb1c69 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6354,10 +6354,16 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) Bot::ProcessBotGroupDisband(this, std::string()); } else { - Mob* tempMember = entity_list.GetMob(gd->name2); + Mob* tempMember = entity_list.GetMob(gd->name1); //Name1 is the target you are disbanding if (tempMember) { if (tempMember->IsBot()) - Bot::ProcessBotGroupDisband(this, std::string(tempMember->GetCleanName())); + tempMember->CastToBot()->RemoveBotFromGroup(tempMember->CastToBot(), group); + if (LFP) + { + // If we are looking for players, update to show we are on our own now. + UpdateLFP(); + } + return; //No need to continue from here we were removing a bot from party } } } From 64caf298fbe7db7d2d99217677918a57ddbcd694 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Wed, 3 Jun 2015 10:17:28 -0700 Subject: [PATCH 143/846] Only return if the target was a Bot member --- zone/client_packet.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index b9dfb1c69..8a7b8a133 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6355,9 +6355,8 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) } else { Mob* tempMember = entity_list.GetMob(gd->name1); //Name1 is the target you are disbanding - if (tempMember) { - if (tempMember->IsBot()) - tempMember->CastToBot()->RemoveBotFromGroup(tempMember->CastToBot(), group); + if (tempMember && tempMember->IsBot()) { + tempMember->CastToBot()->RemoveBotFromGroup(tempMember->CastToBot(), group); if (LFP) { // If we are looking for players, update to show we are on our own now. From 00d258a952cb17c679036eae374611c29328b0a1 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Wed, 3 Jun 2015 14:18:51 -0700 Subject: [PATCH 144/846] Bot pets will now scale with focus effects. Pets will not scale passed 3x their normal size and stay within 10 levels of their base level unless changed with the rule PetPowerLevelCap --- common/ruletypes.h | 1 + zone/bot.h | 1 + zone/pets.cpp | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index a581e527d..cf77dddf6 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -151,6 +151,7 @@ RULE_CATEGORY_END() RULE_CATEGORY( Pets ) RULE_REAL( Pets, AttackCommandRange, 150 ) RULE_BOOL( Pets, UnTargetableSwarmPet, false ) +RULE_REAL( Pets, PetPowerLevelCap, 10 ) // Max number of levels your pet can go up with pet power RULE_CATEGORY_END() RULE_CATEGORY( GM ) diff --git a/zone/bot.h b/zone/bot.h index 4cf04aa3a..25e0d1c52 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -60,6 +60,7 @@ enum SpellTypeIndex { }; class Bot : public NPC { + friend class Mob; public: // Class enums enum BotfocusType { //focus types diff --git a/zone/pets.cpp b/zone/pets.cpp index e096328b9..f5f741f44 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -28,6 +28,10 @@ #include "pets.h" #include "zonedb.h" +#ifdef BOTS +#include "bot.h" +#endif + #ifndef WIN32 #include #include "../common/unix.h" @@ -231,6 +235,10 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);//Client only act_power = CastToClient()->mod_pet_power(act_power, spell_id); } +#ifdef BOTS + else if (this->IsBot()) + act_power = CastToBot()->GetBotFocusEffect(Bot::BotfocusPetPower, spell_id); +#endif } else if (petpower > 0) act_power = petpower; @@ -260,7 +268,11 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, memcpy(npc_type, base, sizeof(NPCType)); // If pet power is set to -1 in the DB, use stat scaling - if (this->IsClient() && record.petpower == -1) + if ((this->IsClient() +#ifdef BOTS + || this->IsBot() +#endif + ) && record.petpower == -1) { float scale_power = (float)act_power / 100.0f; if(scale_power > 0) @@ -268,10 +280,10 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, npc_type->max_hp *= (1 + scale_power); npc_type->cur_hp = npc_type->max_hp; npc_type->AC *= (1 + scale_power); - npc_type->level += 1 + ((int)act_power / 25); // gains an additional level for every 25 pet power + npc_type->level += 1 + ((int)act_power / 25) > npc_type->level + RuleR(Pets, PetPowerLevelCap) ? RuleR(Pets, PetPowerLevelCap) : 1 + ((int)act_power / 25); // gains an additional level for every 25 pet power npc_type->min_dmg = (npc_type->min_dmg * (1 + (scale_power / 2))); npc_type->max_dmg = (npc_type->max_dmg * (1 + (scale_power / 2))); - npc_type->size *= (1 + (scale_power / 2)); + npc_type->size = npc_type->size * (1 + (scale_power / 2)) > npc_type->size * 3 ? npc_type->size * 3 : (1 + (scale_power / 2)); } record.petpower = act_power; } From a5d9faf8ea69458847cdb83c450319b45f1ddd5c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 Jun 2015 01:02:48 -0400 Subject: [PATCH 145/846] Allow bard DOTs to get random extra tick This extra tick business needs to be figured out more ... bard invul and crescendo songs DO NOT get this extra tick, but DOTs do --- zone/effects.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index c1d037670..55e56cdac 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -423,7 +423,9 @@ int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) // unsure on the exact details, but bard songs that don't cost mana at some point get an extra tick, 60 for now // a level 53 bard reported getting 2 tics - if (IsShortDurationBuff(spell_id) && IsBardSong(spell_id) && spells[spell_id].mana == 0 && GetClass() == BARD && GetLevel() > 60) + // bard DOTs do get this extra tick, but beneficial long bard songs don't? (invul, crescendo) + if ((IsShortDurationBuff(spell_id) || IsDetrimentalSpell(spell_id)) && IsBardSong(spell_id) && + spells[spell_id].mana == 0 && GetClass() == BARD && GetLevel() > 60) tic_inc++; float focused = ((duration * increase) / 100.0f) + tic_inc; int ifocused = static_cast(focused); From 0b17dc73f1bcf2f074a47fbedd45685e07af6986 Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Fri, 5 Jun 2015 12:23:42 -0700 Subject: [PATCH 146/846] Update to encounter timers so they can actually work from hooked events --- zone/CMakeLists.txt | 6 ++++-- zone/lua_encounter.cpp | 14 ++++++++++++++ zone/lua_encounter.h | 30 ++++++++++++++++++++++++++++++ zone/lua_general.cpp | 6 ++++++ zone/lua_parser.cpp | 9 ++++++--- zone/lua_parser_events.cpp | 15 +++++++++++---- zone/lua_parser_events.h | 10 +++++----- 7 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 zone/lua_encounter.cpp create mode 100644 zone/lua_encounter.h diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 2510dcddb..5573e6f4f 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -20,7 +20,7 @@ SET(zone_sources embparser_api.cpp embperl.cpp embxs.cpp - encounter.cpp + encounter.cpp entity.cpp exp.cpp fearpath.cpp @@ -36,6 +36,7 @@ SET(zone_sources lua_corpse.cpp lua_client.cpp lua_door.cpp + lua_encounter.cpp lua_entity.cpp lua_entity_list.cpp lua_general.cpp @@ -138,7 +139,7 @@ SET(zone_headers embparser.h embperl.h embxs.h - encounter.h + encounter.h entity.h errmsg.h event_codes.h @@ -150,6 +151,7 @@ SET(zone_headers lua_bit.h lua_client.h lua_corpse.h + lua_encounter.h lua_entity.h lua_entity_list.h lua_general.h diff --git a/zone/lua_encounter.cpp b/zone/lua_encounter.cpp new file mode 100644 index 000000000..a01c846fb --- /dev/null +++ b/zone/lua_encounter.cpp @@ -0,0 +1,14 @@ +#ifdef LUA_EQEMU + +#include "lua.hpp" +#include +#include "lua_encounter.h" +#include "encounter.h" + + +luabind::scope lua_register_encounter() { + return luabind::class_("Encounter") + .def(luabind::constructor<>()); +} + +#endif \ No newline at end of file diff --git a/zone/lua_encounter.h b/zone/lua_encounter.h new file mode 100644 index 000000000..d4ce63bb9 --- /dev/null +++ b/zone/lua_encounter.h @@ -0,0 +1,30 @@ +#ifndef EQEMU_LUA_ENCOUNTER_H +#define EQEMU_LUA_ENCOUNTER_H +#ifdef LUA_EQEMU + +#include "lua_ptr.h" + +class Encounter; + +namespace luabind { + struct scope; + class object; +} + +luabind::scope lua_register_encounter(); + +class Lua_Encounter : public Lua_Ptr +{ + typedef Encounter NativeType; +public: + Lua_Encounter() { SetLuaPtrData(nullptr); } + Lua_Encounter(Encounter *d) { SetLuaPtrData(reinterpret_cast(d)); } + virtual ~Lua_Encounter() { } + + operator Encounter*() { + return reinterpret_cast(GetLuaPtrData()); + } + +}; +#endif +#endif \ No newline at end of file diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 139951724..777396daa 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -19,6 +19,7 @@ #include "../common/timer.h" #include "../common/eqemu_logsys.h" #include "encounter.h" +#include "lua_encounter.h" struct Events { }; struct Factions { }; @@ -296,6 +297,10 @@ void lua_set_timer(const char *timer, int time_ms, Lua_Mob mob) { quest_manager.settimerMS(timer, time_ms, mob); } +void lua_set_timer(const char *timer, int time_ms, Lua_Encounter enc) { + quest_manager.settimerMS(timer, time_ms, enc); +} + void lua_stop_timer(const char *timer) { quest_manager.stoptimer(timer); } @@ -1457,6 +1462,7 @@ luabind::scope lua_register_general() { luabind::def("set_timer", (void(*)(const char*, int))&lua_set_timer), luabind::def("set_timer", (void(*)(const char*, int, Lua_ItemInst))&lua_set_timer), luabind::def("set_timer", (void(*)(const char*, int, Lua_Mob))&lua_set_timer), + luabind::def("set_timer", (void(*)(const char*, int, Lua_Encounter))&lua_set_timer), luabind::def("stop_timer", (void(*)(const char*))&lua_stop_timer), luabind::def("stop_timer", (void(*)(const char*, Lua_ItemInst))&lua_stop_timer), luabind::def("stop_timer", (void(*)(const char*, Lua_Mob))&lua_stop_timer), diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 4b5a1faad..24f25948e 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -34,6 +34,7 @@ #include "questmgr.h" #include "zone.h" #include "lua_parser.h" +#include "lua_encounter.h" const char *LuaEvents[_LargestEventID] = { "event_say", @@ -610,10 +611,11 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std:: lua_pushstring(L, encounter_name.c_str()); lua_setfield(L, -2, "name"); - auto arg_function = EncounterArgumentDispatch[evt]; - arg_function(this, L, data, extra_data, extra_pointers); - Encounter *enc = lua_encounters[encounter_name]; + + auto arg_function = EncounterArgumentDispatch[evt]; + arg_function(this, L, enc, data, extra_data, extra_pointers); + quest_manager.StartQuest(enc, nullptr, nullptr, encounter_name); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -977,6 +979,7 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_client_version(), lua_register_appearance(), lua_register_entity(), + lua_register_encounter(), lua_register_mob(), lua_register_special_abilities(), lua_register_npc(), diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 5428304a6..840bcb40d 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -22,6 +22,7 @@ #include "lua_door.h" #include "lua_object.h" #include "lua_packet.h" +#include "lua_encounter.h" #include "zone.h" #include "lua_parser_events.h" @@ -704,14 +705,20 @@ void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl std::vector *extra_pointers) { } -void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, +void handle_encounter_timer(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, std::vector *extra_pointers) { lua_pushstring(L, data.c_str()); lua_setfield(L, -2, "timer"); } -void handle_encounter_load(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, +void handle_encounter_load(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, std::vector *extra_pointers) { + if (encounter) { + Lua_Encounter l_enc(encounter); + luabind::adl::object l_enc_o = luabind::adl::object(L, l_enc); + l_enc_o.push(L); + lua_setfield(L, -2, "encounter"); + } if (extra_pointers) { std::string *str = EQEmu::any_cast(extra_pointers->at(0)); lua_pushstring(L, str->c_str()); @@ -719,7 +726,7 @@ void handle_encounter_load(QuestInterface *parse, lua_State* L, std::string data } } -void handle_encounter_unload(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, +void handle_encounter_unload(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, std::vector *extra_pointers) { if (extra_pointers) { std::string *str = EQEmu::any_cast(extra_pointers->at(0)); @@ -728,7 +735,7 @@ void handle_encounter_unload(QuestInterface *parse, lua_State* L, std::string da } } -void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, +void handle_encounter_null(QuestInterface *parse, lua_State* L, Encounter* encounter, 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 46609fb06..0a2ab5ad9 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -6,7 +6,7 @@ typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std:: 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(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, uint32, std::vector*); -typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, std::string, uint32, std::vector*); +typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, Encounter* encounter, std::string, uint32, std::vector*); //NPC void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, @@ -130,13 +130,13 @@ void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl //Encounter -void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, +void handle_encounter_timer(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_encounter_load(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, +void handle_encounter_load(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_encounter_unload(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, +void handle_encounter_unload(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data, +void handle_encounter_null(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data, std::vector *extra_pointers); #endif From 6cb1861c91836b2a9cf41685e65a84ee4c68662b Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Fri, 5 Jun 2015 12:32:58 -0700 Subject: [PATCH 147/846] Update to encounter timers so they can actually work from hooked events --- zone/lua_general.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 777396daa..bf65fea7c 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -313,6 +313,10 @@ void lua_stop_timer(const char *timer, Lua_Mob mob) { quest_manager.stoptimer(timer, mob); } +void lua_stop_timer(const char *timer, Lua_Encounter enc) { + quest_manager.stoptimer(timer, enc); +} + void lua_stop_all_timers() { quest_manager.stopalltimers(); } @@ -325,6 +329,10 @@ void lua_stop_all_timers(Lua_Mob mob) { quest_manager.stopalltimers(mob); } +void lua_stop_all_timers(Lua_Encounter enc) { + quest_manager.stopalltimers(enc); +} + void lua_depop() { quest_manager.depop(0); } @@ -1466,9 +1474,11 @@ luabind::scope lua_register_general() { luabind::def("stop_timer", (void(*)(const char*))&lua_stop_timer), luabind::def("stop_timer", (void(*)(const char*, Lua_ItemInst))&lua_stop_timer), luabind::def("stop_timer", (void(*)(const char*, Lua_Mob))&lua_stop_timer), + luabind::def("stop_timer", (void(*)(const char*, Lua_Encounter))&lua_stop_timer), luabind::def("stop_all_timers", (void(*)(void))&lua_stop_all_timers), luabind::def("stop_all_timers", (void(*)(Lua_ItemInst))&lua_stop_all_timers), luabind::def("stop_all_timers", (void(*)(Lua_Mob))&lua_stop_all_timers), + luabind::def("stop_all_timers", (void(*)(Lua_Encounter))&lua_stop_all_timers), luabind::def("depop", (void(*)(void))&lua_depop), luabind::def("depop", (void(*)(int))&lua_depop), luabind::def("depop_with_timer", (void(*)(void))&lua_depop_with_timer), From b45f0f9dbc4205ca567a37daccba83baaa4fba9c Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Fri, 5 Jun 2015 12:57:53 -0700 Subject: [PATCH 148/846] Lua_Encounter doesn't need to expose constructor --- zone/lua_encounter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/lua_encounter.cpp b/zone/lua_encounter.cpp index a01c846fb..08a4f95d3 100644 --- a/zone/lua_encounter.cpp +++ b/zone/lua_encounter.cpp @@ -7,8 +7,7 @@ luabind::scope lua_register_encounter() { - return luabind::class_("Encounter") - .def(luabind::constructor<>()); + return luabind::class_("Encounter"); } #endif \ No newline at end of file From a9b98ed0577a7916d09435ac7939a85eec798ec6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Jun 2015 19:07:01 -0400 Subject: [PATCH 149/846] Add 64-bit ntoh/hton functions for Linux BSD macros aren't tested, but should work. These should already be defined on Windows. --- common/types.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/common/types.h b/common/types.h index 9064b67e0..2e1b5d3f3 100644 --- a/common/types.h +++ b/common/types.h @@ -83,4 +83,20 @@ typedef const char Const_char; //for perl XS #define DLLFUNC extern "C" #endif +// htonll and ntohll already defined on windows +#ifndef WIN32 +# if defined(__linux__) +# include +# elif defined(__FreeBSD__) || defined(__NetBSD__) +# include +# elif defined (__OpenBSD__) +# include +# define be16toh(x) betoh16(x) +# define be32toh(x) betoh32(x) +# define be64toh(x) betoh64(x) +# endif +# define htonll(x) htobe64(x) +# define ntohll(x) be64toh(x) +#endif + #endif From 03bc245318ad9b5ed9d1c8c60463320dc7c13abf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Jun 2015 21:30:35 -0400 Subject: [PATCH 150/846] Fix fleeing when zones have map files --- zone/pathing.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 8224f3692..32a55d73a 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -16,7 +16,7 @@ #define snprintf _snprintf #endif -//#define PATHDEBUG +//#define PATHDEBUG extern Zone *zone; @@ -205,10 +205,10 @@ glm::vec3 PathManager::GetPathNodeCoordinates(int NodeNumber, bool BestZ) } std::deque PathManager::FindRoute(int startID, int endID) -{ +{ Log.Out(Logs::Detail, Logs::None, "FindRoute from node %i to %i", startID, endID); - memset(ClosedListFlag, 0, sizeof(int) * Head.PathNodeCount); + memset(ClosedListFlag, 0, sizeof(int) * Head.PathNodeCount); std::deque OpenList, ClosedList; @@ -665,6 +665,9 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa bool SameDestination = (To == PathingDestination); + if (Speed <= 0) // our speed is 0, we cant move so lets return the dest + return To; // this will also avoid the teleports cleanly + int NextNode; if(To == From) From 42a5ddcf77ecf81560b2775c906516328951c2f7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 6 Jun 2015 17:46:53 -0400 Subject: [PATCH 151/846] Cut down on some HP update spam This increases the timer that mobs will send out updates (It could probably be increased more) This will also reset the timer every time SendHPUpdate is called to prevent sending like 3+ completely useless updates at once Also skip sending the update to the client if we're sending an OP_Damage with the damage since the client will apply this number --- zone/attack.cpp | 2 +- zone/bot.cpp | 22 +++++++++++----------- zone/client.cpp | 4 ++-- zone/client.h | 2 ++ zone/client_process.cpp | 4 +++- zone/mob.cpp | 20 ++++++++++---------- zone/mob.h | 3 ++- zone/npc.cpp | 5 +++-- zone/npc.h | 1 + 9 files changed, 35 insertions(+), 28 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 666cb19f8..a229f197e 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3693,7 +3693,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons //send an HP update if we are hurt if(GetHP() < GetMaxHP()) - SendHPUpdate(); + SendHPUpdate(!iBuffTic); // the OP_Damage actually updates the client in these cases, so we skill them } //end `if damage was done` //send damage packet... diff --git a/zone/bot.cpp b/zone/bot.cpp index e76389b24..8b3741443 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -755,7 +755,7 @@ void Bot::GenerateBaseStats() { this->Corrup = CorruptionResist; SetBotSpellID(BotSpellID); this->size = BotSize; - + this->pAggroRange = 0; this->pAssistRange = 0; this->raid_target = false; @@ -1381,18 +1381,18 @@ int32 Bot::GenerateBaseHitPoints() uint32 lm = GetClassLevelFactor(); int32 Post255; int32 NormalSTA = GetSTA(); - + if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { float SoDPost255; - + if(((NormalSTA - 255) / 2) > 0) SoDPost255 = ((NormalSTA - 255) / 2); else SoDPost255 = 0; - + int hp_factor = GetClassHPFactor(); - + if(level < 41) { new_base_hp = (5 + (GetLevel() * hp_factor / 12) + ((NormalSTA - SoDPost255) * GetLevel() * hp_factor / 3600)); @@ -1420,7 +1420,7 @@ int32 Bot::GenerateBaseHitPoints() new_base_hp = (5)+(GetLevel()*lm/10) + (((NormalSTA-Post255)*GetLevel()*lm/3000)) + ((Post255*1)*lm/6000); } this->base_hp = new_base_hp; - + return new_base_hp; } @@ -2342,7 +2342,7 @@ bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { if (results.RowCount()) { //Name already in use! return false; } - + return true; //We made it with a valid name! } @@ -2901,7 +2901,7 @@ bool Bot::Process() SetEndurance(GetEndurance() + CalcEnduranceRegen() + RestRegenEndurance); } - if (sendhpupdate_timer.Check()) { + if (sendhpupdate_timer.Check(false)) { SendHPUpdate(); if(HasPet()) @@ -5894,7 +5894,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att // delete from group data RemoveBotFromGroup(this, g); - + //Make sure group still exists if it doesnt they were already updated in RemoveBotFromGroup g = GetGroup(); if (!g) @@ -5912,7 +5912,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att g->members[j] = nullptr; } } - + // update the client group EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; @@ -10823,7 +10823,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) AddItemBonuses(item, newbon); } } - + // Caps if(newbon->HPRegen > CalcHPRegenCap()) newbon->HPRegen = CalcHPRegenCap(); diff --git a/zone/client.cpp b/zone/client.cpp index 7471a6a62..bdcbbbf68 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -116,7 +116,7 @@ Client::Client(EQStreamInterface* ieqs) ), //these must be listed in the order they appear in client.h position_timer(250), - hpupdate_timer(1800), + hpupdate_timer(2000), camp_timer(29000), process_timer(100), stamina_timer(40000), @@ -8631,4 +8631,4 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, QueuePacket(outapp, false, Client::CLIENT_CONNECTED); safe_delete(outapp); -} \ No newline at end of file +} diff --git a/zone/client.h b/zone/client.h index 73bde1a69..2015a52ba 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1257,6 +1257,8 @@ public: int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false); void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false); + + void ResetHPUpdateTimer() { hpupdate_timer.Start(); } protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 42681340b..be2e1321f 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -129,7 +129,9 @@ bool Client::Process() { if(IsTracking() && (GetClientVersion() >= ClientVersion::SoD) && TrackingTimer.Check()) DoTracking(); - if(hpupdate_timer.Check()) + // SendHPUpdate calls hpupdate_timer.Start so it can delay this timer, so lets not reset with the check + // since the function will anyways + if(hpupdate_timer.Check(false)) SendHPUpdate(); if(mana_timer.Check()) diff --git a/zone/mob.cpp b/zone/mob.cpp index 8a224db0b..1591cc057 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1266,7 +1266,7 @@ void Mob::CreateHPPacket(EQApplicationPacket* app) } // sends hp update of this mob to people who might care -void Mob::SendHPUpdate() +void Mob::SendHPUpdate(bool skip_self) { EQApplicationPacket hp_app; Group *group; @@ -1355,8 +1355,7 @@ void Mob::SendHPUpdate() } // send to self - we need the actual hps here - if(IsClient()) - { + if(IsClient() && !skip_self) { 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; @@ -1365,6 +1364,7 @@ void Mob::SendHPUpdate() CastToClient()->QueuePacket(hp_app2); safe_delete(hp_app2); } + ResetHPUpdateTimer(); // delay the timer } // this one just warps the mob to the current location @@ -4205,25 +4205,25 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier) std::string Mob::GetGlobal(const char *varname) { int qgCharid = 0; int qgNpcid = 0; - + if (this->IsNPC()) qgNpcid = this->GetNPCTypeID(); - + if (this->IsClient()) qgCharid = this->CastToClient()->CharacterID(); - + QGlobalCache *qglobals = nullptr; std::list globalMap; - + if (this->IsClient()) qglobals = this->CastToClient()->GetQGlobals(); - + if (this->IsNPC()) qglobals = this->CastToNPC()->GetQGlobals(); if(qglobals) QGlobalCache::Combine(globalMap, qglobals->GetBucket(), qgNpcid, qgCharid, zone->GetZoneID()); - + std::list::iterator iter = globalMap.begin(); while(iter != globalMap.end()) { if ((*iter).name.compare(varname) == 0) @@ -4231,7 +4231,7 @@ std::string Mob::GetGlobal(const char *varname) { ++iter; } - + return "Undefined"; } diff --git a/zone/mob.h b/zone/mob.h index 74a53346e..ded9c04dc 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -508,7 +508,8 @@ public: static void CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); void CreateHPPacket(EQApplicationPacket* app); - void SendHPUpdate(); + void SendHPUpdate(bool skip_self = false); + virtual void ResetHPUpdateTimer() {}; // does nothing //Util static uint32 RandomTimer(int min, int max); diff --git a/zone/npc.cpp b/zone/npc.cpp index 0ece7ab6c..d4a33b6d0 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -115,7 +115,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if knightattack_timer(1000), assist_timer(AIassistcheck_delay), qglobal_purge_timer(30000), - sendhpupdate_timer(1000), + sendhpupdate_timer(2000), enraged_timer(1000), taunt_timer(TauntReuseTime * 1000), m_SpawnPoint(position), @@ -650,7 +650,8 @@ bool NPC::Process() } } - if (sendhpupdate_timer.Check() && (IsTargeted() || (IsPet() && GetOwner() && GetOwner()->IsClient()))) { + // we might actually want to reset in this check ... won't until issues arise at least :P + if (sendhpupdate_timer.Check(false) && (IsTargeted() || (IsPet() && GetOwner() && GetOwner()->IsClient()))) { if(!IsFullHP || cur_hp Date: Sun, 7 Jun 2015 16:53:38 -0700 Subject: [PATCH 152/846] Full group was being excluded from group exp bonus --- zone/exp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/exp.cpp b/zone/exp.cpp index ab8506aca..826b12e67 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -705,7 +705,7 @@ void Group::SplitExp(uint32 exp, Mob* other) { groupmod = 2.16; else groupmod = 1.0; - if(membercount > 1 && membercount < 6) + if(membercount > 1 && membercount <= 6) groupexp += (uint32)((float)exp * groupmod * (RuleR(Character, GroupExpMultiplier))); int conlevel = Mob::GetLevelCon(maxlevel, other->GetLevel()); From c2e436521411c136330845b50383a99eb4aaf1df Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 7 Jun 2015 22:07:40 -0400 Subject: [PATCH 153/846] Implemented rule-based disenchanted bag use --- changelog.txt | 3 + common/ruletypes.h | 1 + .../2014_03_17_EnforceAugmentRules.sql | 2 +- .../2015_06_07_TransformSummonedBagsRule.sql | 1 + zone/client.h | 1 + zone/client_process.cpp | 6 +- zone/inventory.cpp | 181 ++++++++++++++++++ 7 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql diff --git a/changelog.txt b/changelog.txt index cdb2fd5f8..bc96a8ef1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 06/07/2015 == +Uleat: Implemented optional rule for using disenchanted bags. Action triggers at the same point that temporary items are removed. +Optional SQL: utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql == 05/25/2015 == Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods diff --git a/common/ruletypes.h b/common/ruletypes.h index cf77dddf6..d0f198164 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -611,6 +611,7 @@ RULE_BOOL ( Inventory, EnforceAugmentUsability, true) // Forces augmented item u RULE_BOOL ( Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation RULE_BOOL ( Inventory, DeleteTransformationMold, true) //False if you want mold to last forever RULE_BOOL ( Inventory, AllowAnyWeaponTransformation, false) //Weapons can use any weapon transformation +RULE_BOOL ( Inventory, TransformSummonedBags, false) //Transforms summoned bags into disenchanted ones instead of deleting RULE_CATEGORY_END() RULE_CATEGORY( Client ) diff --git a/utils/sql/git/optional/2014_03_17_EnforceAugmentRules.sql b/utils/sql/git/optional/2014_03_17_EnforceAugmentRules.sql index e89d4a437..25ec3734d 100644 --- a/utils/sql/git/optional/2014_03_17_EnforceAugmentRules.sql +++ b/utils/sql/git/optional/2014_03_17_EnforceAugmentRules.sql @@ -1,3 +1,3 @@ INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentRestriction', 'false', 'Forces augment slot restrictions.'); INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentUsability', 'false', 'Forces augmented item usability.'); -INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentWear', 'false', 'Forces augment wear slot validation.'); \ No newline at end of file +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentWear', 'false', 'Forces augment wear slot validation.'); diff --git a/utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql b/utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql new file mode 100644 index 000000000..d0af46a24 --- /dev/null +++ b/utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:TransformSummonedBags', 'true', 'Transforms summoned bags into disenchanted ones instead of deleting.'); diff --git a/zone/client.h b/zone/client.h index 2015a52ba..de093990c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -906,6 +906,7 @@ public: bool DecreaseByID(uint32 type, uint8 amt); uint8 SlotConvert2(uint8 slot); //Maybe not needed. void Escape(); //AA Escape + void DisenchantSummonedBags(bool client_update = true); void RemoveNoRent(bool client_update = true); void RemoveDuplicateLore(bool client_update = true); void MoveSlotNotAllowed(bool client_update = true); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index be2e1321f..4a16e7698 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -838,7 +838,11 @@ void Client::BulkSendInventoryItems() { } bool deletenorent = database.NoRentExpired(GetName()); - if(deletenorent){ RemoveNoRent(false); } //client was offline for more than 30 minutes, delete no rent items + if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items + if (RuleB(Inventory, TransformSummonedBags)) + DisenchantSummonedBags(false); + RemoveNoRent(false); + } RemoveDuplicateLore(false); MoveSlotNotAllowed(false); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 2ce30fe5e..e1904d59f 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -2158,6 +2158,187 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { return true; } +static bool IsSummonedBagID(uint32 item_id) +{ + switch (item_id) { + case 17147: // "Spiritual Prismatic Pack" + case 17303: // "Spirit Pouch" + case 17304: // "Dimensional Pocket" + case 17305: // "Dimensional Hole" + case 17306: // "Glowing Backpack" + case 17307: // "Quiver of Marr" + case 17308: // "Bandoleer of Luclin" + case 17309: // "Pouch of Quellious" + case 17310: // "Phantom Satchel" + case 17510: // "Glowing Chest" + case 17900: // "Grandmaster's Satchel" + case 57260: // "Glowing Backpack" + case 57261: // "Pouch of Quellious" + case 57262: // "Phantom Satchel" + case 60224: // "Faded-Glyph Tablet" + case 95199: // "Beginner Artisan Satchel" + case 95200: // "Apprentice Artisan Satchel" + case 95201: // "Freshman Artisan Satchel" + case 95202: // "Journeyman Artisan Satchel" + case 95203: // "Expert Artisan Satchel" + case 95204: // "Master Artisan Satchel" + //case 96960: // "Artisan Satchel" - no 12-slot disenchanted bags + return true; + default: + return false; + } +} + +static uint32 GetDisenchantedBagID(uint8 bag_slots) +{ + switch (bag_slots) { + case 4: + return 77772; // "Small Disenchanted Backpack" + case 6: + return 77774; // "Disenchanted Backpack" + case 8: + return 77776; // "Large Disenchanted Backpack" + case 10: + return 77778; // "Huge Disenchanted Backpack" + default: + return 0; // no suitable conversions + } +} + +static bool CopyBagContents(ItemInst* new_bag, const ItemInst* old_bag) +{ + if (!new_bag || !old_bag) { return false; } + if (new_bag->GetItem()->BagSlots < old_bag->GetItem()->BagSlots) { return false; } + + // pre-check for size comparisons + for (auto bag_slot = 0; bag_slot < old_bag->GetItem()->BagSlots; ++bag_slot) { + if (!old_bag->GetItem(bag_slot)) { continue; } + if (old_bag->GetItem(bag_slot)->GetItem()->Size > new_bag->GetItem()->BagSize) { + Log.Out(Logs::General, Logs::Inventory, "Copy Bag Contents: Failure due to %s is larger than size capacity of %s (%i > %i)", + old_bag->GetItem(bag_slot)->GetItem()->Name, new_bag->GetItem()->Name, old_bag->GetItem(bag_slot)->GetItem()->Size, new_bag->GetItem()->BagSize); + return false; + } + } + + for (auto bag_slot = 0; bag_slot < old_bag->GetItem()->BagSlots; ++bag_slot) { + if (!old_bag->GetItem(bag_slot)) { continue; } + new_bag->PutItem(bag_slot, *(old_bag->GetItem(bag_slot))); + } + + return true; +} + +void Client::DisenchantSummonedBags(bool client_update) +{ + for (auto slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id) { + auto inst = m_inv[slot_id]; + if (!inst) { continue; } + if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } + if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + if (inst->GetTotalItemCount() == 1) { continue; } + + auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); + if (!new_id) { continue; } + auto new_item = database.GetItem(new_id); + if (!new_item) { continue; } + auto new_inst = database.CreateBaseItem(new_item); + if (!new_inst) { continue; } + + 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, slot_id); + PutItemInInventory(slot_id, *new_inst, client_update); + } + safe_delete(new_inst); + } + + for (auto slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; ++slot_id) { + auto inst = m_inv[slot_id]; + if (!inst) { continue; } + if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } + if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + if (inst->GetTotalItemCount() == 1) { continue; } + + auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); + if (!new_id) { continue; } + auto new_item = database.GetItem(new_id); + if (!new_item) { continue; } + auto new_inst = database.CreateBaseItem(new_item); + if (!new_inst) { continue; } + + 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, slot_id); + PutItemInInventory(slot_id, *new_inst, client_update); + } + safe_delete(new_inst); + } + + for (auto slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; ++slot_id) { + auto inst = m_inv[slot_id]; + if (!inst) { continue; } + if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } + if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + if (inst->GetTotalItemCount() == 1) { continue; } + + auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); + if (!new_id) { continue; } + auto new_item = database.GetItem(new_id); + if (!new_item) { continue; } + auto new_inst = database.CreateBaseItem(new_item); + if (!new_inst) { continue; } + + 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, slot_id); + PutItemInInventory(slot_id, *new_inst, client_update); + } + safe_delete(new_inst); + } + + while (!m_inv.CursorEmpty()) { + auto inst = m_inv[MainCursor]; + if (!inst) { break; } + if (!IsSummonedBagID(inst->GetItem()->ID)) { break; } + if (inst->GetItem()->ItemClass != ItemClassContainer) { break; } + if (inst->GetTotalItemCount() == 1) { break; } + + auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); + if (!new_id) { break; } + auto new_item = database.GetItem(new_id); + if (!new_item) { break; } + auto new_inst = database.CreateBaseItem(new_item); + 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); + std::list local; + local.push_front(new_inst); + m_inv.PopItem(MainCursor); + safe_delete(inst); + + while (!m_inv.CursorEmpty()) { + auto limbo_inst = m_inv.PopItem(MainCursor); + if (limbo_inst == nullptr) { continue; } + local.push_back(limbo_inst); + } + + for (auto iter = local.begin(); iter != local.end(); ++iter) { + auto cur_inst = *iter; + if (cur_inst == nullptr) { continue; } + m_inv.PushCursor(*cur_inst); + safe_delete(cur_inst); + } + local.clear(); + + auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); + database.SaveCursor(this->CharacterID(), s, e); + } + else { + safe_delete(new_inst); // deletes disenchanted bag if not used + } + + break; + } +} + void Client::RemoveNoRent(bool client_update) { for (auto slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; ++slot_id) { From f198ab714f6a5f0093455ec320643e4ea7b094c0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 7 Jun 2015 22:31:21 -0400 Subject: [PATCH 154/846] Make inspect buffs LAA optional for target buffs --- common/ruletypes.h | 1 + .../optional/2015_06_07_SpellsTargetBuffsRule.sql | 1 + zone/client_packet.cpp | 2 +- zone/entity.cpp | 12 +++++++----- 4 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 utils/sql/git/optional/2015_06_07_SpellsTargetBuffsRule.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index d0f198164..9a36b77f4 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -345,6 +345,7 @@ RULE_BOOL ( Spells, SwarmPetTargetLock, false) // Use old method of swarm pets t RULE_BOOL ( Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell derived focus effects. RULE_BOOL ( Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects. RULE_BOOL ( Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot. +RULE_BOOL ( Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if true RULE_CATEGORY_END() RULE_CATEGORY( Combat ) diff --git a/utils/sql/git/optional/2015_06_07_SpellsTargetBuffsRule.sql b/utils/sql/git/optional/2015_06_07_SpellsTargetBuffsRule.sql new file mode 100644 index 000000000..1dcc9d922 --- /dev/null +++ b/utils/sql/git/optional/2015_06_07_SpellsTargetBuffsRule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:AlwaysSendTargetBuffs', 'false', 'Allows the server to send the targets buffs ignoring the LAA.'); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 8a7b8a133..e4ce874fc 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12897,7 +12897,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) inspect_buffs = group->GetLeadershipAA(groupAAInspectBuffs); } } - if (nt == this || inspect_buffs || (nt->IsClient() && !nt->CastToClient()->GetPVP()) || + 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->SendBuffsToClient(this); diff --git a/zone/entity.cpp b/zone/entity.cpp index baa4f4354..c7493b907 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -79,7 +79,7 @@ Client *Entity::CastToClient() } #ifdef _EQDEBUG if (!IsClient()) { - Log.Out(Logs::General, Logs::Error, "CastToClient error (not client)"); + Log.Out(Logs::General, Logs::Error, "CastToClient error (not client)"); return 0; } #endif @@ -268,7 +268,7 @@ const Beacon* Entity::CastToBeacon() const return static_cast(this); } -const Encounter* Entity::CastToEncounter() const +const Encounter* Entity::CastToEncounter() const { return static_cast(this); } @@ -565,7 +565,7 @@ void EntityList::AddGroup(Group *group) uint32 gid = worldserver.NextGroupID(); if (gid == 0) { - Log.Out(Logs::General, Logs::Error, + Log.Out(Logs::General, Logs::Error, "Unable to get new group ID from world server. group is going to be broken."); return; } @@ -594,7 +594,7 @@ void EntityList::AddRaid(Raid *raid) uint32 gid = worldserver.NextGroupID(); if (gid == 0) { - Log.Out(Logs::General, Logs::Error, + Log.Out(Logs::General, Logs::Error, "Unable to get new group ID from world server. group is going to be broken."); return; } @@ -1428,7 +1428,9 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap if (c != sender) { if (Target == sender) { if (inspect_buffs) { // if inspect_buffs is true we're sending a mob's buffs to those with the LAA - if (c->IsRaidGrouped()) { + if (c->GetGM() || RuleB(Spells, AlwaysSendTargetsBuffs)) { + Send = true; + } else if (c->IsRaidGrouped()) { Raid *raid = c->GetRaid(); if (!raid) continue; From 3d1dc6314df3444d090f645a5fdcdcbecf64a1ee Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 7 Jun 2015 19:42:12 -0700 Subject: [PATCH 155/846] New style AA data loading, still rudimentary --- zone/CMakeLists.txt | 1 + zone/aa.cpp | 126 +++++++++++++++++++++++++++++++++++++++++ zone/aa_ability.h | 45 +++++++++++++++ zone/aa_rank.h | 44 ++++++++++++++ zone/aa_rank_effects.h | 37 ++++++++++++ zone/aa_rank_prereqs.h | 33 +++++++++++ zone/client_packet.cpp | 2 + zone/entity.cpp | 1 - zone/net.cpp | 1 - zone/zone.cpp | 7 +-- zone/zone.h | 13 ++++- zone/zonedb.h | 7 ++- 12 files changed, 308 insertions(+), 9 deletions(-) create mode 100644 zone/aa_ability.h create mode 100644 zone/aa_rank.h create mode 100644 zone/aa_rank_effects.h create mode 100644 zone/aa_rank_prereqs.h diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 2510dcddb..4340ff6da 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -125,6 +125,7 @@ SET(zone_sources SET(zone_headers aa.h + aa_ability.h basic_functions.h beacon.h bot.h diff --git a/zone/aa.cpp b/zone/aa.cpp index b6e220d60..c98e31372 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -2070,3 +2070,129 @@ Mob *AA_SwarmPetInfo::GetOwner() { return entity_list.GetMobID(owner_id); } + +//New AA +void Zone::LoadAlternateAdvancement() { + Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Data..."); + if(!database.LoadAlternateAdvancementAbilities(zone->aa_abilities, + zone->aa_ranks)) + { + zone->aa_abilities.clear(); + zone->aa_ranks.clear(); + Log.Out(Logs::General, Logs::Status, "Failed to load Alternate Advancement Data"); + return; + } + + Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Data"); +} + +bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, + std::unordered_map> &ranks) +{ + Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Abilities..."); + abilities.clear(); + std::string query = "SELECT id, name, expansion, category, classes, expendable, first_rank_id FROM aa_ability"; + auto results = QueryDatabase(query); + if(results.Success()) { + for(auto row = results.begin(); row != results.end(); ++row) { + AA::Ability *ability = new AA::Ability; + int id = atoi(row[0]); + + ability->name = row[1]; + ability->expansion = atoi(row[2]); + ability->category = atoi(row[3]); + ability->classes = atoi(row[4]); + ability->expendable = atoi(row[5]) != 0 ? true : false; + ability->first_rank_id = atoi(row[6]); + + abilities[id] = std::unique_ptr(ability); + } + } else { + Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Abilities"); + return false; + } + + Log.Out(Logs::General, Logs::Status, "Loaded %d Alternate Advancement Abilities", (int)abilities.size()); + + Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Ability Ranks..."); + ranks.clear(); + query = "SELECT id, upper_hotkey_sid, lower_hotkey_sid, title_sid, desc_sid, cost, level_req, spell, spell_type, recast_time, " + "prev_id, next_id FROM aa_ranks"; + results = QueryDatabase(query); + if(results.Success()) { + for(auto row = results.begin(); row != results.end(); ++row) { + AA::Rank *rank = new AA::Rank; + int id = atoi(row[0]); + rank->upper_hotkey_sid = atoi(row[1]); + rank->lower_hotkey_sid = atoi(row[2]); + rank->title_sid = atoi(row[3]); + rank->desc_sid = atoi(row[4]); + rank->cost = atoi(row[5]); + rank->level_req = atoi(row[6]); + rank->spell = atoi(row[7]); + rank->spell_type = atoi(row[8]); + rank->recast_time = atoi(row[9]); + rank->prev_id = atoi(row[10]); + rank->next_id = atoi(row[11]); + + ranks[id] = std::unique_ptr(rank); + } + } else { + Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Ability Ranks"); + return false; + } + + Log.Out(Logs::General, Logs::Status, "Loaded %d Alternate Advancement Ability Ranks", (int)ranks.size()); + + Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Ability Rank Effects..."); + query = "SELECT rank_id, slot, effect_id, base1, base2 FROM aa_rank_effects"; + results = QueryDatabase(query); + if(results.Success()) { + for(auto row = results.begin(); row != results.end(); ++row) { + AA::RankEffect effect; + int rank_id = atoi(row[0]); + int slot = atoi(row[1]); + effect.effect_id = atoi(row[2]); + effect.base1 = atoi(row[3]); + effect.base2 = atoi(row[4]); + + if(slot < 1 || slot > 12) + continue; + + if(ranks.count(rank_id) > 0) { + AA::Rank *rank = ranks[rank_id].get(); + rank->effects[slot] = effect; + } + } + } else { + Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Ability Rank Effects"); + return false; + } + + Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Ability Rank Effects"); + + Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Ability Rank Prereqs..."); + query = "SELECT rank_id, aa_id, points FROM aa_rank_prereqs"; + results = QueryDatabase(query); + if(results.Success()) { + for(auto row = results.begin(); row != results.end(); ++row) { + AA::RankPrereq prereq; + int rank_id = atoi(row[0]); + prereq.aa_id = atoi(row[1]); + prereq.points = atoi(row[1]); + + if(ranks.count(rank_id) > 0) { + AA::Rank *rank = ranks[rank_id].get(); + rank->prereqs.push_back(prereq); + } + } + } else { + Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Ability Rank Prereqs"); + return false; + } + + Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Ability Rank Prereqs"); + + return true; +} + diff --git a/zone/aa_ability.h b/zone/aa_ability.h new file mode 100644 index 000000000..bb9148689 --- /dev/null +++ b/zone/aa_ability.h @@ -0,0 +1,45 @@ +/* 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 EQEMU_ZONE_AA_ABILITY_H +#define EQEMU_ZONE_AA_ABILITY_H + +#include "../common/global_define.h" +#include +#include +#include +#include "aa_rank_effects.h" +#include "aa_rank_prereqs.h" +#include "aa_rank.h" + +namespace AA +{ + +struct Ability +{ + std::string name; + int expansion; + int category; + int classes; + bool expendable; + int first_rank_id; +}; + +} + +#endif diff --git a/zone/aa_rank.h b/zone/aa_rank.h new file mode 100644 index 000000000..ec1cc4115 --- /dev/null +++ b/zone/aa_rank.h @@ -0,0 +1,44 @@ +/* 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 EQEMU_ZONE_AA_RANK_H +#define EQEMU_ZONE_AA_RANK_H + +namespace AA +{ + +struct Rank +{ + int upper_hotkey_sid; + int lower_hotkey_sid; + int title_sid; + int desc_sid; + int cost; + int level_req; + int spell; + int spell_type; + int recast_time; + int prev_id; + int next_id; + std::unordered_map effects; + std::vector prereqs; +}; + +} + +#endif diff --git a/zone/aa_rank_effects.h b/zone/aa_rank_effects.h new file mode 100644 index 000000000..fd65d507f --- /dev/null +++ b/zone/aa_rank_effects.h @@ -0,0 +1,37 @@ +/* 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 EQEMU_ZONE_AA_RANK_EFFECTS_H +#define EQEMU_ZONE_AA_RANK_EFFECTS_H + +#include "../common/global_define.h" +#include + +namespace AA +{ + +struct RankEffect +{ + int effect_id; + int base1; + int base2; +}; + +} + +#endif diff --git a/zone/aa_rank_prereqs.h b/zone/aa_rank_prereqs.h new file mode 100644 index 000000000..b1620be6c --- /dev/null +++ b/zone/aa_rank_prereqs.h @@ -0,0 +1,33 @@ +/* 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 EQEMU_ZONE_AA_RANK_PREREQS_H +#define EQEMU_ZONE_AA_RANK_PREREQS_H + +namespace AA +{ + +struct RankPrereq +{ + int aa_id; + int points; +}; + +} + +#endif diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 8a7b8a133..112e8f33f 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1091,6 +1091,7 @@ void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app) void Client::Handle_Connect_OP_SendAATable(const EQApplicationPacket *app) { + Log.Out(Logs::General, Logs::Error, "SendAAList()"); SendAAList(); return; } @@ -1152,6 +1153,7 @@ void Client::Handle_Connect_OP_TGB(const EQApplicationPacket *app) void Client::Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app) { + Log.Out(Logs::General, Logs::Error, "SendAATable()"); SendAATable(); } diff --git a/zone/entity.cpp b/zone/entity.cpp index baa4f4354..a73b21f4d 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -58,7 +58,6 @@ extern uint32 numclients; extern PetitionList petition_list; extern char errorname[32]; -extern uint16 adverrornum; Entity::Entity() { diff --git a/zone/net.cpp b/zone/net.cpp index ef6b46836..0178eff21 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -96,7 +96,6 @@ EntityList entity_list; WorldServer worldserver; uint32 numclients = 0; char errorname[32]; -uint16 adverrornum = 0; extern Zone* zone; EQStreamFactory eqsf(ZoneStream); npcDecayTimes_Struct npcCorpseDecayTimes[100]; diff --git a/zone/zone.cpp b/zone/zone.cpp index e58bea24a..31bc27b41 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -68,7 +68,6 @@ extern bool staticzone; extern NetConnection net; extern PetitionList petition_list; extern QuestParserCollection* parse; -extern uint16 adverrornum; extern uint32 numclients; extern WorldServer worldserver; extern Zone* zone; @@ -954,15 +953,14 @@ bool Zone::Init(bool iStaticZone) { zone->LoadNPCEmotes(&NPCEmoteList); //Load AA information - adverrornum = 500; LoadAAs(); + LoadAlternateAdvancement(); + //Load merchant data - adverrornum = 501; zone->GetMerchantDataForZoneLoad(); //Load temporary merchant data - adverrornum = 502; zone->LoadTempMerchantData(); // Merc data @@ -974,7 +972,6 @@ bool Zone::Init(bool iStaticZone) { if (RuleB(Zone, LevelBasedEXPMods)) zone->LoadLevelEXPMods(); - adverrornum = 503; petition_list.ClearPetitions(); petition_list.ReadDatabase(); diff --git a/zone/zone.h b/zone/zone.h index 7b1b855a7..274a1a021 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -27,6 +27,7 @@ #include "qglobals.h" #include "spawn2.h" #include "spawngroup.h" +#include "aa_ability.h" struct ZonePoint { @@ -113,12 +114,17 @@ public: inline const uint32& GetMaxClients() { return pMaxClients; } + //new AA + void LoadAlternateAdvancement(); + + //old AA void LoadAAs(); int GetTotalAAs() { return totalAAs; } SendAA_Struct* GetAABySequence(uint32 seq) { return aas[seq]; } SendAA_Struct* FindAA(uint32 id); uint8 GetTotalAALevels(uint32 skill_id); - void LoadZoneDoors(const char* zone, int16 version); + + void LoadZoneDoors(const char* zone, int16 version); bool LoadZoneObjects(); bool LoadGroundSpawns(); void ReloadStaticData(); @@ -313,6 +319,11 @@ private: int totalBS; ZoneSpellsBlocked *blocked_spells; + //new AA + std::unordered_map> aa_abilities; + std::unordered_map> aa_ranks; + + //old AA int totalAAs; SendAA_Struct **aas; //array of AA structs diff --git a/zone/zonedb.h b/zone/zonedb.h index cac380a96..dda01b7dc 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -6,6 +6,7 @@ #include "position.h" #include "../common/faction.h" #include "../common/eqemu_logsys.h" +#include "aa_ability.h" class Client; class Corpse; @@ -339,7 +340,11 @@ public: bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // needed for factions Dec, 16 2001 bool LoadFactionData(); - /* AAs */ + /* AAs New */ + bool LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, + std::unordered_map> &ranks); + + /* AAs Old */ bool LoadAAEffects(); bool LoadAAEffects2(); bool LoadSwarmSpells(); From 4bb2bb14389d7218c91d2d3855793cfa992b9779 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 7 Jun 2015 23:41:54 -0400 Subject: [PATCH 156/846] AA packet work mostly and small fix to expendable AAs --- common/eq_packet_structs.h | 13 +++--------- common/patches/rof.cpp | 13 ++++++------ common/patches/rof2.cpp | 13 ++++++------ common/patches/rof2_structs.h | 33 ++++++++++++------------------ common/patches/rof_structs.h | 34 ++++++++++++------------------- common/patches/sod.cpp | 2 ++ common/patches/sod_structs.h | 22 ++++++++++---------- common/patches/sof.cpp | 2 ++ common/patches/sof_structs.h | 20 ++++++++---------- common/patches/titanium.cpp | 4 ++-- common/patches/titanium_structs.h | 9 ++------ common/patches/uf.cpp | 8 +++++--- common/patches/uf_structs.h | 21 ++++++++++--------- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + zone/aa.cpp | 17 +++++++++++----- zone/client.cpp | 8 ++++---- zone/client_packet.cpp | 9 ++++---- zone/zonedb.cpp | 8 ++++---- zone/zonedb.h | 2 +- 20 files changed, 115 insertions(+), 126 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index e5ab88e57..8e9f97138 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -726,6 +726,7 @@ struct AA_Array { uint32 AA; uint32 value; + uint32 charges; }; @@ -4276,14 +4277,6 @@ struct AA_Action { /*12*/ uint32 exp_value; }; - -struct AA_Skills { //this should be removed and changed to AA_Array -/*00*/ uint32 aa_skill; // Total AAs Spent -/*04*/ uint32 aa_value; -/*08*/ uint32 unknown08; -/*12*/ -}; - struct AAExpUpdate_Struct { /*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability /*04*/ uint32 aapoints_unspent; @@ -4301,12 +4294,12 @@ struct AltAdvStats_Struct { }; struct PlayerAA_Struct { // Is this still used? - AA_Skills aa_list[MAX_PP_AA_ARRAY]; + AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct AATable_Struct { /*00*/ int32 aa_spent; // Total AAs Spent -/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY]; +/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct Weather_Struct { diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index fae650eb5..f4f01e300 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2120,7 +2120,7 @@ namespace RoF { outapp->WriteUInt32(emu->aa_array[r].AA); outapp->WriteUInt32(emu->aa_array[r].value); - outapp->WriteUInt32(0); + outapp->WriteUInt32(emu->aa_array[r].charges); } // Fill the other 60 AAs with zeroes @@ -2818,9 +2818,9 @@ namespace RoF for (uint32 i = 0; i < MAX_PP_AA_ARRAY; ++i) { - eq->aa_list[i].aa_skill = emu->aa_list[i].aa_skill; - eq->aa_list[i].aa_value = emu->aa_list[i].aa_value; - eq->aa_list[i].unknown08 = emu->aa_list[i].unknown08; + eq->aa_list[i].AA = emu->aa_list[i].AA; + eq->aa_list[i].value = emu->aa_list[i].value; + eq->aa_list[i].charges = emu->aa_list[i].charges; } FINISH_ENCODE(); @@ -2868,9 +2868,9 @@ namespace RoF OUT(cost); OUT(seq); OUT(current_level); - eq->unknown037 = 1; // Introduced during HoT + eq->prereq_skill_count = 1; // min 1 OUT(prereq_skill); - eq->unknown045 = 1; // New Mar 21 2012 - Seen 1 + eq->prereq_minpoints_count = 1; // min 1 OUT(prereq_minpoints); eq->type = emu->sof_type; OUT(spellid); @@ -2886,6 +2886,7 @@ namespace RoF OUT(cost2); eq->aa_expansion = emu->aa_expansion; eq->special_category = emu->special_category; + eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number OUT(total_abilities); unsigned int r; for (r = 0; r < emu->total_abilities; r++) { diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 42e97b9eb..096467edf 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2200,7 +2200,7 @@ namespace RoF2 { outapp->WriteUInt32(emu->aa_array[r].AA); outapp->WriteUInt32(emu->aa_array[r].value); - outapp->WriteUInt32(0); + outapp->WriteUInt32(emu->aa_array[r].charges); } // Fill the other 60 AAs with zeroes @@ -2907,9 +2907,9 @@ namespace RoF2 for (uint32 i = 0; i < MAX_PP_AA_ARRAY; ++i) { - eq->aa_list[i].aa_skill = emu->aa_list[i].aa_skill; - eq->aa_list[i].aa_value = emu->aa_list[i].aa_value; - eq->aa_list[i].unknown08 = emu->aa_list[i].unknown08; + eq->aa_list[i].AA = emu->aa_list[i].AA; + eq->aa_list[i].value = emu->aa_list[i].value; + eq->aa_list[i].charges = emu->aa_list[i].charges; } FINISH_ENCODE(); @@ -2957,9 +2957,9 @@ namespace RoF2 OUT(cost); OUT(seq); OUT(current_level); - eq->unknown037 = 1; // Introduced during HoT + eq->prereq_skill_count = 1; // min 1 OUT(prereq_skill); - eq->unknown045 = 1; // New Mar 21 2012 - Seen 1 + eq->prereq_minpoints_count = 1; // min 1 OUT(prereq_minpoints); eq->type = emu->sof_type; OUT(spellid); @@ -2976,6 +2976,7 @@ namespace RoF2 eq->aa_expansion = emu->aa_expansion; eq->special_category = emu->special_category; OUT(total_abilities); + eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number unsigned int r; for (r = 0; r < emu->total_abilities; r++) { OUT(abilities[r].skill_id); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index a572a3834..812e9c464 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -877,7 +877,7 @@ struct AA_Array { uint32 AA; uint32 value; - uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live + uint32 charges; // expendable charges }; struct Disciplines_Struct { @@ -4253,9 +4253,9 @@ struct SendAA_Struct { /*0025*/ uint32 cost; /*0029*/ uint32 seq; /*0033*/ uint32 current_level; //1s, MQ2 calls this AARankRequired -/*0037*/ uint32 unknown037; // Introduced during HoT +/*0037*/ uint32 prereq_skill_count; // mutliple prereqs at least 1, even no prereqs /*0041*/ uint32 prereq_skill; //is < 0, abs() is category # -/*0045*/ uint32 unknown045; // New Mar 21 2012 - Seen 1 +/*0045*/ uint32 prereq_minpoints_count; // mutliple prereqs at least 1, even no prereqs /*0049*/ uint32 prereq_minpoints; //min points in the prereq /*0053*/ uint32 type; /*0057*/ uint32 spellid; @@ -4268,10 +4268,16 @@ struct SendAA_Struct { /*0081*/ uint32 last_id; /*0085*/ uint32 next_id; /*0089*/ uint32 cost2; -/*0093*/ uint8 unknown80[7]; +/*0093*/ uint8 unknown93; +/*0094*/ uint8 grant_only; // VetAAs, progression, etc +/*0095*/ uint8 unknown95; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though +/*0096*/ uint32 expendable_charges; // max charges of the AA /*0100*/ uint32 aa_expansion; /*0104*/ uint32 special_category; -/*0108*/ uint32 unknown0096; +/*0108*/ uint8 shroud; +/*0109*/ uint8 unknown109; +/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0111*/ uint8 unknown111; /*0112*/ uint32 total_abilities; /*0116*/ AA_Ability abilities[0]; }; @@ -4288,12 +4294,6 @@ struct AA_Action { /*16*/ }; -struct AA_Skills { //this should be removed and changed to AA_Array -/*00*/ uint32 aa_skill; // Total AAs Spent -/*04*/ uint32 aa_value; -/*08*/ uint32 unknown08; -/*12*/ -}; struct AAExpUpdate_Struct { /*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability @@ -4313,14 +4313,7 @@ struct AltAdvStats_Struct { }; struct PlayerAA_Struct { // Is this still used? - AA_Skills aa_list[MAX_PP_AA_ARRAY]; -}; - -struct AA_Values { -/*00*/ uint32 aa_skill; -/*04*/ uint32 aa_value; -/*08*/ uint32 unknown08; -/*12*/ + AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct AATable_Struct { @@ -4330,7 +4323,7 @@ struct AATable_Struct { /*12*/ uint32 aa_spent_archetype; // Seen 40 /*16*/ uint32 aa_spent_class; // Seen 103 /*20*/ uint32 aa_spent_special; // Seen 0 -/*24*/ AA_Values aa_list[MAX_PP_AA_ARRAY]; +/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct Weather_Struct { diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 7db21597c..a87b530c4 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -866,7 +866,7 @@ struct AA_Array { uint32 AA; uint32 value; - uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live + uint32 charges; // expendable charges }; struct Disciplines_Struct { @@ -4252,9 +4252,9 @@ struct SendAA_Struct { /*0025*/ uint32 cost; /*0029*/ uint32 seq; /*0033*/ uint32 current_level; //1s, MQ2 calls this AARankRequired -/*0037*/ uint32 unknown037; // Introduced during HoT +/*0037*/ uint32 prereq_skill_count; // mutliple prereqs at least 1, even no prereqs /*0041*/ uint32 prereq_skill; //is < 0, abs() is category # -/*0045*/ uint32 unknown045; // New Mar 21 2012 - Seen 1 +/*0045*/ uint32 prereq_minpoints_count; // mutliple prereqs at least 1, even no prereqs /*0049*/ uint32 prereq_minpoints; //min points in the prereq /*0053*/ uint32 type; /*0057*/ uint32 spellid; @@ -4267,10 +4267,16 @@ struct SendAA_Struct { /*0081*/ uint32 last_id; /*0085*/ uint32 next_id; /*0089*/ uint32 cost2; -/*0093*/ uint8 unknown80[7]; +/*0093*/ uint8 unknown93; +/*0094*/ uint8 grant_only; // VetAAs, progression, etc +/*0095*/ uint8 unknown95; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though +/*0096*/ uint32 expendable_charges; // max charges of the AA /*0100*/ uint32 aa_expansion; /*0104*/ uint32 special_category; -/*0108*/ uint32 unknown0096; +/*0108*/ uint8 shroud; +/*0109*/ uint8 unknown109; +/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0111*/ uint8 unknown111; /*0112*/ uint32 total_abilities; /*0116*/ AA_Ability abilities[0]; }; @@ -4287,13 +4293,6 @@ struct AA_Action { /*16*/ }; -struct AA_Skills { //this should be removed and changed to AA_Array -/*00*/ uint32 aa_skill; // Total AAs Spent -/*04*/ uint32 aa_value; -/*08*/ uint32 unknown08; -/*12*/ -}; - struct AAExpUpdate_Struct { /*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability /*04*/ uint32 aapoints_unspent; @@ -4312,14 +4311,7 @@ struct AltAdvStats_Struct { }; struct PlayerAA_Struct { // Is this still used? - AA_Skills aa_list[MAX_PP_AA_ARRAY]; -}; - -struct AA_Values { -/*00*/ uint32 aa_skill; -/*04*/ uint32 aa_value; -/*08*/ uint32 unknown08; -/*12*/ + AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct AATable_Struct { @@ -4329,7 +4321,7 @@ struct AATable_Struct { /*12*/ uint32 aa_spent_archetype; // Seen 40 /*16*/ uint32 aa_spent_class; // Seen 103 /*20*/ uint32 aa_spent_special; // Seen 0 -/*24*/ AA_Values aa_list[MAX_PP_AA_ARRAY]; +/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct Weather_Struct { diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 0a8073131..80201da1e 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1558,6 +1558,7 @@ namespace SoD for (r = 0; r < MAX_PP_AA_ARRAY; r++) { OUT(aa_array[r].AA); OUT(aa_array[r].value); + OUT(aa_array[r].charges); } // OUT(unknown02220[4]); OUT(mana); @@ -1898,6 +1899,7 @@ namespace SoD OUT(cost2); eq->aa_expansion = emu->aa_expansion; eq->special_category = emu->special_category; + eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number OUT(total_abilities); unsigned int r; for (r = 0; r < emu->total_abilities; r++) { diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 2b7178daf..2f5d2c2db 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -666,7 +666,7 @@ struct AA_Array { uint32 AA; uint32 value; - uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live + uint32 charges; // expendable }; @@ -3819,10 +3819,16 @@ struct SendAA_Struct { /*0069*/ uint32 last_id; /*0073*/ uint32 next_id; /*0077*/ uint32 cost2; -/*0081*/ uint8 unknown80[7]; +/*0081*/ uint8 unknown81; +/*0082*/ uint8 grant_only; // VetAAs, progression, etc +/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though +/*0084*/ uint32 expendable_charges; // max charges of the AA /*0088*/ uint32 aa_expansion; /*0092*/ uint32 special_category; -/*0096*/ uint32 unknown0096; +/*0096*/ uint8 shroud; +/*0097*/ uint8 unknown97; +/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0099*/ uint8 unknown99; /*0100*/ uint32 total_abilities; /*0104*/ AA_Ability abilities[0]; }; @@ -3838,12 +3844,6 @@ struct AA_Action { /*12*/ uint32 exp_value; }; -struct AA_Skills { //this should be removed and changed to AA_Array -/*00*/ uint32 aa_skill; // Total AAs Spent -/*04*/ uint32 aa_value; -/*08*/ uint32 unknown08; -}; - struct AAExpUpdate_Struct { /*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability /*04*/ uint32 aapoints_unspent; @@ -3861,12 +3861,12 @@ struct AltAdvStats_Struct { }; struct PlayerAA_Struct { // Is this still used? - AA_Skills aa_list[MAX_PP_AA_ARRAY]; + AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct AATable_Struct { /*00*/ int32 aa_spent; // Total AAs Spent -/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY]; +/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct Weather_Struct { diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index f0e8a2dbe..7b0e14c1c 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1216,6 +1216,7 @@ namespace SoF for (r = 0; r < MAX_PP_AA_ARRAY; r++) { OUT(aa_array[r].AA); OUT(aa_array[r].value); + OUT(aa_array[r].charges); } // OUT(unknown02220[4]); OUT(mana); @@ -1557,6 +1558,7 @@ namespace SoF OUT(cost2); eq->aa_expansion = emu->aa_expansion; eq->special_category = emu->special_category; + eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number OUT(total_abilities); unsigned int r; for (r = 0; r < emu->total_abilities; r++) { diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index f7ad59011..afd34ba68 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -645,7 +645,7 @@ struct AA_Array { uint32 AA; uint32 value; - uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live + uint32 charges; // expendable charges }; @@ -3683,10 +3683,14 @@ struct SendAA_Struct { /*0069*/ uint32 last_id; /*0073*/ uint32 next_id; /*0077*/ uint32 cost2; -/*0081*/ uint8 unknown80[7]; +/*0081*/ uint8 unknown81; +/*0082*/ uint8 grant_only; // VetAAs, progression, etc +/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though +/*0084*/ uint32 expendable_charges; // max charges of the AA /*0088*/ uint32 aa_expansion; /*0092*/ uint32 special_category; -/*0096*/ uint16 unknown0096; +/*0096*/ uint8 shroud; +/*0097*/ uint8 unknown97; /*0098*/ uint32 total_abilities; /*0102*/ AA_Ability abilities[0]; }; @@ -3702,12 +3706,6 @@ struct AA_Action { /*12*/ uint32 exp_value; }; -struct AA_Skills { //this should be removed and changed to AA_Array -/*00*/ uint32 aa_skill; // Total AAs Spent -/*04*/ uint32 aa_value; -/*08*/ uint32 unknown08; -}; - struct AAExpUpdate_Struct { /*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability /*04*/ uint32 aapoints_unspent; @@ -3725,12 +3723,12 @@ struct AltAdvStats_Struct { }; struct PlayerAA_Struct { - AA_Skills aa_list[MAX_PP_AA_ARRAY]; + AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct AATable_Struct { /*00*/ int32 aa_spent; // Total AAs Spent -/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY]; +/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct Weather_Struct { diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index e23202c87..2fda4038a 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1098,8 +1098,8 @@ namespace Titanium unsigned int r; for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { - OUT(aa_list[r].aa_skill); - OUT(aa_list[r].aa_value); + OUT(aa_list[r].AA); + OUT(aa_list[r].value); } FINISH_ENCODE(); diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index bdca057d0..f836395c9 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3179,11 +3179,6 @@ struct AA_Action { /*12*/ uint32 exp_value; }; -struct AA_Skills { //this should be removed and changed to AA_Array -/*00*/ uint32 aa_skill; -/*04*/ uint32 aa_value; -}; - struct AAExpUpdate_Struct { /*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability /*04*/ uint32 aapoints_unspent; @@ -3201,11 +3196,11 @@ struct AltAdvStats_Struct { }; struct PlayerAA_Struct { - AA_Skills aa_list[MAX_PP_AA_ARRAY]; + AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct AATable_Struct { - AA_Skills aa_list[MAX_PP_AA_ARRAY]; + AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct Weather_Struct { diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index e963312e2..deedcec5f 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1807,6 +1807,7 @@ namespace UF for (r = 0; r < MAX_PP_AA_ARRAY; r++) { OUT(aa_array[r].AA); OUT(aa_array[r].value); + OUT(aa_array[r].charges); } // OUT(unknown02220[4]); OUT(mana); @@ -2134,9 +2135,9 @@ namespace UF for (uint32 i = 0; i < MAX_PP_AA_ARRAY; ++i) { - eq->aa_list[i].aa_skill = emu->aa_list[i].aa_skill; - eq->aa_list[i].aa_value = emu->aa_list[i].aa_value; - eq->aa_list[i].unknown08 = emu->aa_list[i].unknown08; + eq->aa_list[i].AA = emu->aa_list[i].AA; + eq->aa_list[i].value = emu->aa_list[i].value; + eq->aa_list[i].charges = emu->aa_list[i].charges; } FINISH_ENCODE(); @@ -2181,6 +2182,7 @@ namespace UF OUT(cost2); eq->aa_expansion = emu->aa_expansion; eq->special_category = emu->special_category; + eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number OUT(total_abilities); unsigned int r; for (r = 0; r < emu->total_abilities; r++) { diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 79363d68a..c943c6ea5 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -713,7 +713,7 @@ struct AA_Array { uint32 AA; uint32 value; - uint32 unknown08; // Looks like AA_Array is now 12 bytes in Underfoot + uint32 charges; // expendable }; @@ -3892,10 +3892,16 @@ struct SendAA_Struct { /*0069*/ uint32 last_id; /*0073*/ uint32 next_id; /*0077*/ uint32 cost2; -/*0081*/ uint8 unknown80[7]; +/*0081*/ uint8 unknown81; +/*0082*/ uint8 grant_only; // VetAAs, progression, etc +/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though +/*0084*/ uint32 expendable_charges; // max charges of the AA /*0088*/ uint32 aa_expansion; /*0092*/ uint32 special_category; -/*0096*/ uint32 unknown0096; +/*0096*/ uint8 shroud; +/*0097*/ uint8 unknown97; +/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0099*/ uint8 unknown99; /*0100*/ uint32 total_abilities; /*0104*/ AA_Ability abilities[0]; }; @@ -3911,11 +3917,6 @@ struct AA_Action { /*12*/ uint32 exp_value; }; -struct AA_Skills { //this should be removed and changed to AA_Array -/*00*/ uint32 aa_skill; // Total AAs Spent -/*04*/ uint32 aa_value; -/*08*/ uint32 unknown08; -}; struct AAExpUpdate_Struct { /*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability @@ -3934,7 +3935,7 @@ struct AltAdvStats_Struct { }; struct PlayerAA_Struct { // Is this still used? - AA_Skills aa_list[MAX_PP_AA_ARRAY]; + AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct AATable_Struct { @@ -3944,7 +3945,7 @@ struct AATable_Struct { /*12*/ int32 unknown012; /*16*/ int32 unknown016; /*20*/ int32 unknown020; -/*24*/ AA_Skills aa_list[MAX_PP_AA_ARRAY]; +/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY]; }; struct Weather_Struct { diff --git a/common/version.h b/common/version.h index 78f7a67b3..1813f77c3 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 9082 +#define CURRENT_BINARY_DATABASE_VERSION 9083 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 5ca25a029..e7aa46221 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -336,6 +336,7 @@ 9080|2015_05_23_PetBuffInstrumentMod.sql|SHOW COLUMNS FROM `character_pet_buffs` LIKE 'instrument_mod'|empty| 9081|2015_05_23_dbstr_us.sql|SHOW TABLES LIKE 'db_str'|empty| 9082|2015_05_25_npc_types_texture_fields.sql|SHOW COLUMNS FROM `npc_types` LIKE 'armtexture'|empty| +9083|2015_06_07_aa_update.sql|SHOW COLUMNS FROM `character_alternate_abilities` LIKE 'charges'|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/aa.cpp b/zone/aa.cpp index b6e220d60..3718e3391 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1104,9 +1104,9 @@ void Client::SendAATable() { 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; + aa2->aa_list[i].AA = aa[i]->AA; + aa2->aa_list[i].value = aa[i]->value; + aa2->aa_list[i].charges = aa[i]->charges; } QueuePacket(outapp); safe_delete(outapp); @@ -1395,6 +1395,8 @@ uint32 Client::GetAA(uint32 aa_id) const { bool Client::SetAA(uint32 aa_id, uint32 new_value) { aa_points[aa_id] = new_value; uint32 cur; + auto sendaa = zone->FindAA(aa_id); // this is a bit hacky + uint32 charges = sendaa->special_category == 7 && new_value ? 1 : 0; 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; @@ -1402,6 +1404,7 @@ bool Client::SetAA(uint32 aa_id, uint32 new_value) { aa[cur]->AA++; else aa[cur]->AA = 0; + aa[cur]->charges = charges; return true; } else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){ @@ -1410,11 +1413,13 @@ bool Client::SetAA(uint32 aa_id, uint32 new_value) { aa[cur]->AA++; else aa[cur]->AA = 0; + aa[cur]->charges = charges; return true; } else if(aa[cur]->AA==0){ //end of list aa[cur]->AA = aa_id; aa[cur]->value = new_value; + aa[cur]->charges = charges; return true; } } @@ -1485,8 +1490,10 @@ void Client::ResetAA(){ for (i=0; i < MAX_PP_AA_ARRAY; i++) { aa[i]->AA = 0; aa[i]->value = 0; - m_pp.aa_array[MAX_PP_AA_ARRAY].AA = 0; - m_pp.aa_array[MAX_PP_AA_ARRAY].value = 0; + aa[i]->charges = 0; + m_pp.aa_array[i].AA = 0; + m_pp.aa_array[i].value = 0; + m_pp.aa_array[i].charges= 0; } std::map::iterator itr; diff --git a/zone/client.cpp b/zone/client.cpp index bdcbbbf68..f7e160851 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -550,13 +550,13 @@ bool Client::SaveAA(){ } m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { - if (aa[a]->AA > 0 && aa[a]->value){ + if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" - " VALUES (%u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value); + rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" + " VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); first_entry = 1; } - rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value); + rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); } } auto results = database.QueryDatabase(rquery); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e4ce874fc..b9ac81d89 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1440,12 +1440,14 @@ 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; } /* Initialize AA's : Move to function eventually */ - for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ aa[a] = &m_pp.aa_array[a]; } + for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++) + aa[a] = &m_pp.aa_array[a]; query = StringFormat( "SELECT " "slot, " "aa_id, " - "aa_value " + "aa_value, " + "charges " "FROM " "`character_alternate_abilities` " "WHERE `id` = %u ORDER BY `slot`", this->CharacterID()); @@ -1454,8 +1456,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) i = atoi(row[0]); m_pp.aa_array[i].AA = atoi(row[1]); m_pp.aa_array[i].value = atoi(row[2]); - aa[i]->AA = atoi(row[1]); - aa[i]->value = atoi(row[2]); + m_pp.aa_array[i].charges = atoi(row[3]); } for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ uint32 id = aa[a]->AA; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e81a66308..08a3dd38a 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1710,10 +1710,10 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru return true; } -bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level){ - std::string rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, aa_id, aa_value)" - " VALUES (%u, %u, %u)", - character_id, aa_id, current_level); +bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges){ + std::string rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, aa_id, aa_value, charges)" + " VALUES (%u, %u, %u, %u)", + character_id, aa_id, current_level, charges); auto results = QueryDatabase(rquery); Log.Out(Logs::General, Logs::None, "Saving AA for character ID: %u, aa_id: %u current_level: %u", character_id, aa_id, current_level); return true; diff --git a/zone/zonedb.h b/zone/zonedb.h index cac380a96..1fb4d3b29 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -278,7 +278,7 @@ public: bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); - bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); + bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges); bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color); From db307d865bd3fbd1bdfcd0d68c5090982f95e09a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 7 Jun 2015 23:42:28 -0400 Subject: [PATCH 157/846] And SQL for last commit --- utils/sql/git/required/2015_06_07_aa_update.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 utils/sql/git/required/2015_06_07_aa_update.sql diff --git a/utils/sql/git/required/2015_06_07_aa_update.sql b/utils/sql/git/required/2015_06_07_aa_update.sql new file mode 100644 index 000000000..a888a75ea --- /dev/null +++ b/utils/sql/git/required/2015_06_07_aa_update.sql @@ -0,0 +1 @@ +ALTER TABLE character_alternate_abilities ADD COLUMN charges SMALLINT(11) UNSIGNED NOT NULL DEFAULT 0; From 6229b90451953f523e508e19ba7a6bf25f332e3f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 8 Jun 2015 02:00:44 -0400 Subject: [PATCH 158/846] Fix exploit with expendable AAs --- changelog.txt | 418 +++++++++++++++++++++-------------------- zone/aa.cpp | 12 +- zone/client.cpp | 7 +- zone/client_packet.cpp | 11 +- 4 files changed, 233 insertions(+), 215 deletions(-) diff --git a/changelog.txt b/changelog.txt index bc96a8ef1..d97f20459 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 06/07/2015 == Uleat: Implemented optional rule for using disenchanted bags. Action triggers at the same point that temporary items are removed. Optional SQL: utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql +mackal: changes to AA packets since more fields have been identified +mackal: fix exploit with expendable AAs punching holes in the aa_array and staying around longer than they are welcomed == 05/25/2015 == Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods @@ -67,7 +69,7 @@ Notes: == 02/23/2015 == Noudess: Allow for a rule to set starting swimming && SenseHeading value. -I moved the swimming override to char create instead of setting it +I moved the swimming override to char create instead of setting it every time a char enters a zone. Also added rules to not ignore, but rather forrce sense heading packets to be @@ -135,7 +137,7 @@ Uleat: Removed 'limbo' from the 'HasItem' series of checks - including lore chec Uleat: Updated command #iteminfo to show light source information and a few other things == 02/05/2015 == -Trevius: Fixed Environmental Damage for RoF2. +Trevius: Fixed Environmental Damage for RoF2. == 02/03/2015 == Trevius: Crashfix for TempName() when numbers are passed at the end of the name. @@ -158,19 +160,19 @@ Akkadius: Add Packet Logging Categories - 39 - Packet: Server -> Client - Logs::Server_Client_Packet - 40 - Packet: Client -> Server Unhandled - Logs::Client_Server_Packet_Unhandled See: http://wiki.eqemulator.org/p?Logging_System_Overhaul#packet-logging - + == 01/31/2015 == Trevius: Fixed FindGroundZ() and GetGroundZ() to once again utilize the X and Y arguments that are passed to them. == 01/30/2015 == Akkadius: Implemented event type "EVENT_ENVIRONMENTAL_DAMAGE" - - This event triggers when taking any sort of environmental damage. Example use: + - This event triggers when taking any sort of environmental damage. Example use: sub EVENT_ENVIRONMENTAL_DAMAGE{ quest::debug("EVENT_ENVIRONMENTAL_DAMAGE"); quest::debug("env_damage is " . $env_damage); quest::debug("env_damage_type is " . $env_damage_type); quest::debug("env_final_damage is " . $env_final_damage); - } + } Result: (Test falling in Velks): http://i.imgur.com/tPRL7yL.png - Implemented LUA counterpart of this same implementation above Akkadius (Bobaski): Add PoK New Merchant sql/git/optional/2015_01_30_poknowledge_spell_vendors.sql @@ -189,7 +191,7 @@ Akkadius: Added Logs::DebugQuest category per request from Trevius (Great idea) quest::debug("This is a test debug message, level 1", 1); quest::debug("This is a test debug message, level 2", 2); quest::debug("This is a test debug message, level 3", 3); - + Result: http://i.imgur.com/6VoafGE.png - Uses traditional logging system to output this category - Required MySQL Source in Database version 9070 @@ -220,7 +222,7 @@ Notes: == 01/22/2015 == Akkadius: Massive Log System overhaul, see: http://wiki.eqemulator.org/p?Logging_System_Overhaul&frm=Main - + == 01/21/2015 == Uleat: Added `light` field to npc_types load query (all six clients tested positive for functionality.) Note: This only affects 'innate' light. Equipment (other) light is still in-work. @@ -262,7 +264,7 @@ Uleat: Added text link translators for OP_Emote Uleat: Added text link translators for OP_FormattedMessage == 01/08/2015 == -Trevius: Added some extra checks and clean-up related to Groups and Mercenaries. +Trevius: Added some extra checks and clean-up related to Groups and Mercenaries. == 01/07/2015 == Uleat: Excluded text link body from message scrambling in Client::GarbleMessage() @@ -434,10 +436,10 @@ Akkadius: Created database revision define, this is located in version.h in comm # empty = If the query results in no results # not_empty = If the query is not empty # 4 = Text to match - - The manifest contains all database updates 'Required' to be made to the schema, and it will contain a working backport all the way back to SVN - + - The manifest contains all database updates 'Required' to be made to the schema, and it will contain a working backport all the way back to SVN - currently it is tested and backported through the beginning of our Github repo - On world bootup or standalone run of db_update.pl, users will be prompted with a simple menu that we will expand upon later: - + ============================================================ EQEmu: Automatic Database Upgrade Check ============================================================ @@ -466,7 +468,7 @@ Database Management Menu (Please Select): Akkadius: Created db_update.pl, placed in utils/scripts folder, used for the automatic database update routine (Linux/Windows) - db_update.pl script created db_version table if not created, if old one is present it will remove it Akkadius: Created db_dumper.pl, placed in utils/scripts folder, used for the automatic database update routine backups and standalone backups (Linux/Windows) -Akkadius: World will now check the db_update.pl script on bootup, if the db_update.pl script is not present, it will fetch it remotely before running - +Akkadius: World will now check the db_update.pl script on bootup, if the db_update.pl script is not present, it will fetch it remotely before running - when db_update.pl is done running, world will continue with bootup == 11/15/2014 == @@ -644,10 +646,10 @@ Akkadius: Removed #refundaa Akkadius: Removed a lot of debug code for blob conversion Akkadius: Changed status logging for loads/saves to Debug category -== 09/21/2014 == +== 09/21/2014 == Akkadius: Player Profile Blob to Database Conversion - Summary: HUGE difference in database speeds reads/writes and 1:10 datasize difference - - The new character storage engine unlike the character_ table before, is able to properly index data and make use of + - The new character storage engine unlike the character_ table before, is able to properly index data and make use of proper MySQL/MariaDB caching optimizations and performance has increased phenominally PERFORMANCE AND STATISTICS FIGURES (Varies on hardware): - EZ Server Character data size of 2.6GB `character_` table alone now takes up approx 600MB @@ -693,7 +695,7 @@ Akkadius: Player Profile Blob to Database Conversion SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); - SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color); + SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color); SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value); SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value); SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id); @@ -704,7 +706,7 @@ Akkadius: Player Profile Blob to Database Conversion - Deletes: DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); - DeleteCharacterDisc(uint32 character_id, uint32 slot_id); + DeleteCharacterDisc(uint32 character_id, uint32 slot_id); DeleteCharacterBandolier(uint32 character_id, uint32 band_id); DeleteCharacterLeadershipAAs(uint32 character_id); - Now occur all over the code and only trigger when necessary @@ -717,17 +719,17 @@ Akkadius: Player Profile Blob to Database Conversion - NOTE: These amount of excessive saves have caused scalability issues that cause the `character_` table to hang which causes process hangs that affect the whole server because of the slowness of the `character_` table and the blob not allowing any indexing to occur - All functions that once depended on the `character_` table are now rewritten to appropriately read from the `character_data` table - - Database query errors that occur during conversion or from and load/save/delete character functions are now leveraged via ThrowDBError and logs now go to + - Database query errors that occur during conversion or from and load/save/delete character functions are now leveraged via ThrowDBError and logs now go to Server_Folder_Root/eqemu_query_error_log.txt (You cannot log errors natively through MySQL) - DBASYNC IS NOW COMPLETELY REMOVED - This was mainly for Character data async loads/saves and merchantlist loads - - Side implementations: + - Side implementations: Perl Exports: - quest::crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var) - Sets entity variables world wide with specified npctype_id - quest::crosszonesignalnpcbynpctypeid(npctype_id, data) - Signals all NPC entities world wide with specified npctype_id - $client->GetTaskActivityDoneCount(TaskID, ActivityID) - Gets task activity done count by task id and activity id for client entity - + VIEW TABLE SIZE AFTER CONVERT: - + SELECT CONCAT(table_schema, '.', table_name) as table_name, CONCAT(ROUND(table_rows / 1000000, 2), 'M') rows, CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G') DATA, @@ -854,10 +856,10 @@ Akkadius: Changed all QS Error related logging to 'QUERYSERV__ERROR' Akkadius: (Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE ( Akkadius: Implemented Perl Quest objects (LUA still needed to be exported): - quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging - - quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events` + - quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events` Akkadius: Added MySQL Tables - `qs_player_aa_rate_hourly` - - `qs_player_events` + - `qs_player_events` - Source table structures from: - utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly To get the complete QueryServ schema, source from here: @@ -866,7 +868,7 @@ Akkadius: Added rules for each logging type, source rules here with them enabled - utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql Akkadius: Spawn related logging cleanup Akkadius: General code cleanup -Akkadius: More to come for QueryServ +Akkadius: More to come for QueryServ == 08/22/2014 == Uleat: Rework of Trade::FinishedTrade() and Trade::ResetTrade() to parse items a little more intelligently. @@ -910,8 +912,8 @@ Uleat (Kingly_Krab): Fix for bot chest armor graphic glitch. (fix also caused Ro == 08/02/2014 == Kayen: Implemented spell_news fields -- npc_no_los (check if LOS is required for spells) -- InCombat, OutofCombat - Used together to restrict spells to only be cast while +- npc_no_los (check if LOS is required for spells) +- InCombat, OutofCombat - Used together to restrict spells to only be cast while in/out of combat (beneficial) or if target is in/out of combat (detrimental). -min_dist, min_dist_mod, max_dist, max_dist_mod - Scales spell power based on targets distance from caster. *This will require further work to fully implement but will work with 90% of live spells as is. @@ -944,7 +946,7 @@ KLS: Changes to CMake build == 07/10/2014 == -Kayen: Updated table npc_spells to now support defensive and ranged procs. +Kayen: Updated table npc_spells to now support defensive and ranged procs. Note: Proc rate modifier work as it does for spell effects (ie 200 = 200% baseline chance modifier) Table is also now contains 12 AI spell casting variables that can be set to fine tune casting behaviors per spell set. Global default rules have also been added that can further fine tune all content if no specific variables are set. @@ -974,7 +976,7 @@ Param2: Percent Chance to Hit modifier Param3: Percent Total Damage modifier Kayen: Updated to Chance to Hit code with how bonuses are applied to be consistent for all effects. -Added field to npc_types 'Avoidance' which will modify chance to avoid melee +Added field to npc_types 'Avoidance' which will modify chance to avoid melee Added rules to set max and min chance to hit from melee/ranged (Default 95% / 5%) Required SQL: utils/sql/git/required/2014_07_10_npc_spells.sql @@ -988,7 +990,7 @@ Sympathetic foci on items with proc rate mod will now benefit from that modifier Sympathetic foci can now be placed on AA's (This should always be slot1 in the AA) Kayen: Implemented SE_IllusionPersistence- Allows illusions to last until you die or the illusion is forcibly removed. Kayen: Added rule 'PreNerftBardAEDot' for SE_BardAEDot to allow it to once again do damage to moving targets. (Set to true) -Kayen: Completely revised SE_SkillProc, SE_LimitToSkill, SE_SkillProcSuccess to overall just work better and more accurately, AA support. +Kayen: Completely revised SE_SkillProc, SE_LimitToSkill, SE_SkillProcSuccess to overall just work better and more accurately, AA support. Required SQL: utils/sql/git/required/2014_07_04_AA_Update.sql @@ -1031,7 +1033,7 @@ Optional SQL: utils/sql/git/optiional/2014_06_29_HeadShotRules.sql == 06/17/2014 == Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker. -These effects when present in buffs prevent each other from stacking, +These effects when present in buffs prevent each other from stacking, Any effect with B prevents A, C prevents B, D prevents C. Kayen: Implemented SE_DamageModifier2 (Stacks with SE_DamageModifier, mods damage by skill type) Kayen: Implemented SE_AddHatePct (Modifies +/- your total hate on NPC by percent) @@ -1081,7 +1083,7 @@ KLS: Implemented new map code based on some of Derision's earlier work. Old map == 04/27/2014 == Kayen: Implemented new table 'npc_spells_effects' and 'npc_spells_effects_entires'. Implemented new field in 'npc_spell_effects_id' in npc_types. - + These are used to directly apply spell effect bonuses to NPC's without requirings spells/buffs. Example: Allow an npc to spawn with an innate 50 pt damage shield and a 5% chance to critical hit. @@ -1098,7 +1100,7 @@ cavedude: Added strict column to spawn_events which will prevent an event from e cavedude: Prevented disabled or strict spawn_events from enabling when the zone first boots. cavedude: Fixed the quest function toggle_spawn_event under Perl. -If you're using the quest function toggle_spawn_event (worked on Lua only) it has changed syntax to: +If you're using the quest function toggle_spawn_event (worked on Lua only) it has changed syntax to: toggle_spawn_event(int event_id, bool enable, bool strict, bool reset_base) Required SQL: utils/sql/git/required/2014_04_25_spawn_events.sql @@ -1163,31 +1165,31 @@ Notes: See this thread for more information and to provide feedback: http://www.eqemulator.org/forums/showthread.php?p=229328#post229328 == 04/05/2014 == -Akkadius: Fix for the Fix for the Fix: Rule Combat:OneProcPerWeapon was created so that you can revert to the original proc functionality - for custom servers that have balanced their content around having more than 1 aug proc on weapons. By having this rule set to 'false' you revert this functionality. +Akkadius: Fix for the Fix for the Fix: Rule Combat:OneProcPerWeapon was created so that you can revert to the original proc functionality + for custom servers that have balanced their content around having more than 1 aug proc on weapons. By having this rule set to 'false' you revert this functionality. This rule is set to 'true' by default as the original functionality from Live was intended to be Akkadius: (Performance Adjustment) Removed AsyncLoadVariables from InterserverTimer.Check() in both zone and world. By watching the MySQL general.log file on mass zone idle activity, you can see that the query 'SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= timestamp' is called every 10 seconds. This function is loading - variables that are initially loaded on World and Zone bootup. When running a large amount of zone servers, the amount of MySQL chatter that is produced is enormous and + variables that are initially loaded on World and Zone bootup. When running a large amount of zone servers, the amount of MySQL chatter that is produced is enormous and unnecessary. For example, if I ran 400 zone servers, I would see 3,456,000 unnecessary queries from all idle or active zone processes in a 24 hour interval. Secrets: Added a rule to enable multiple procs from the same weapon's other slots if a proc is deemed to trigger, Defaults to true. If Combat:OneProcPerWeapon is not enabled, we reset the try for that weapon regardless of if we procced or not. This is for some servers that may want to have as many procs triggering from weapons as possible in a single round. - + Optional SQL: utils/sql/git/optional/2014_04_05_ProcRules.sql - + == 04/04/2014 == Kayen: Implemented 'Physical Resists' (Resist Type 9) to be consistent with live based on extensive parsing. - SQL will add new field to npc_types 'PhR' and fill in database with values consistent with observations. + SQL will add new field to npc_types 'PhR' and fill in database with values consistent with observations. Required SQL: utils/sql/git/optional/2014_04_04_PhysicalResists.sql == 04/03/2014 == -Kayen: Implemented live like spell projectiles (ie. Mage Bolts). +Kayen: Implemented live like spell projectiles (ie. Mage Bolts). 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. Lua quest functions: e.self:MerchantOpenShop() and e.self:MerchantCloseShop() @@ -1293,7 +1295,7 @@ cavedude: Exported TrainDisc to Lua. Kayen: Implemented SE_FrenziedDevestation - increase critical spell chacnce and 2x mana cost for DD spells Kayen: Fixed SE_SpellProcChance - Now works on spell dervived procs cavedude: Added two new NPC special_abilities. ALWAYS_FLEE, which forces the NPC to always flee ignoring FleeIfNotAlone and FLEE_PERCENT which allows you to change the HP an individual NPC will flee at. If no value is set, the rule is used as normal. -cavedude: Fixed an issue where rectangular roamboxes could cause an NPC to get stuck on a single coord. +cavedude: Fixed an issue where rectangular roamboxes could cause an NPC to get stuck on a single coord. cavedude: Added a new roambox column, mindelay allowing you to have more control over the roambox delay. Uleat: Fix for 'sqrt' failure on vs2010 clients image: Added idle zone timer to save CPU cycles. @@ -1317,7 +1319,7 @@ Required SQL: utils/sql/git/2014_02_20_buff_updates.sql == 02/18/2014 == Kayen: Implemented SE_TriggerOnReqCaster - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist) Kayen: Implemented SE_ImprovedTaunt - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y -Kayen: Fixed an error where SE_ChangeAggro was adding its bonus x 2 for spell generated aggro. (this applies also to spell casting subtlety AA reduction) +Kayen: Fixed an error where SE_ChangeAggro was adding its bonus x 2 for spell generated aggro. (this applies also to spell casting subtlety AA reduction) == 02/14/2014 == Kayen: Fixes for buffs not fading under certain conditions in revised numhits system, and other fixes. @@ -1382,9 +1384,9 @@ Kayen: Changed SE_MitigateMeleeDamageSP -> SE_MeleeThresholdGuard Kayen: Implemented SE_SpellThresholdGuard (Partial Spell Rune that only is lowered if spell hits are over X amount of damage) Kayen: Implemented SE_TriggerSpellThreshold (implemented Trigger effect on X amount of spell damage taken) Kayen: Changed SE_ReduceHealing -> SE_FcHealAmtIncoming (focus limited Add/Remove amount of healing on target by X amount) -Kayen: Change SE_CriticalHealChance2 -> SE_CriticalHealDecay -Kayen: Change SE_CriticalHealOverTime2 -> SE_CriticalRegenDecay -Kayen: Implemented SE_CriticalDotDecay +Kayen: Change SE_CriticalHealChance2 -> SE_CriticalHealDecay +Kayen: Change SE_CriticalHealOverTime2 -> SE_CriticalRegenDecay +Kayen: Implemented SE_CriticalDotDecay Note: 'Decay' effects means the chance to critical decays based on the level of the spell using the effect (like focus decay) Kayen: Implemented SE_FfLimitUseMin (focus limit to require a min amount of numhits value) Kayen: Implemented SE_FcLimitUse (focus to increases numhits count by percent) @@ -1407,14 +1409,14 @@ demonstar55: Stuns from beneficial spells (Harvest) ignore immunity demonstar55: 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 -Secrets: Added functionality to Perl for $client->PlayMP3("name of file"). +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 +Secrets: Added functionality to Perl for $client->PlayMP3("name of file"). Usage varies, but typically you can place an MP3/WAV/XMI in the EQDir//sounds, pfs, s3d, or root client folder and it will play through this Perl function. Example, $client->PlayMP3("combattheme1.mp3") or $client->PlayMP3("TUTBTrade1.mp3") - All clients except Secrets of Faydwer and 6.2 have their opcodes identified for this function. The struct + supported params is the same throughout versions. + All clients except Secrets of Faydwer and 6.2 have their opcodes identified for this function. The struct + supported params is the same throughout versions. Use $client->PlayMP3 with an invalid sound file to stop playback or simply wait for it to end. KLS: Added functionality to Lua for Client:PlayMP3(filename) KLS: Added functionality to Lua for Client:SendMarqueeMessage(type, priority/opacity, fade_in_time_ms, fade_out_time_ms, duration_ms, msg) - + == 12/16/2013 == Kayen: Implemented SE_ArcheryDoubleAttack (Chance to do an extra archery attack) Kayen: Implemented SE_ShieldEquipDmgMod (Increase damage in primary hand if shield equiped) @@ -1634,7 +1636,7 @@ Param2: Percent of a normal attack damage to deal (default: 100) Param3: Flat damage bonus to add to the rampage attack (default: 0) Param4: Ignore % armor for this attack (default 0) Param5: Ignore flat armor for this attack (default 0) -Param6: Percent of npc's natual crit that can go toward this rampage (default: 100) +Param6: Percent of npc's natual crit that can go toward this rampage (default: 100) Param7: Flat crit bonus on top of npc's natual crit that can go toward this attack (default 0) SPECATK_AREA_RAMPAGE = 4 @@ -1644,7 +1646,7 @@ Param2: Percent of a normal attack damage to deal (default: 100) Param3: Flat damage bonus to add to the rampage attack (default: 0) Param4: Ignore % armor for this attack (default 0) Param5: Ignore flat armor for this attack (default 0) -Param6: Percent of npc's natual crit that can go toward this rampage (default: 100) +Param6: Percent of npc's natual crit that can go toward this rampage (default: 100) Param7: Flat crit bonus on top of npc's natual crit that can go toward this attack (default 0) SPECATK_FLURRY = 5 @@ -1654,7 +1656,7 @@ Param2: Percent of a normal attack damage to deal (default: 100) Param3: Flat damage bonus to add to the flurry attack (default: 0) Param4: Ignore % armor for this attack (default 0) Param5: Ignore flat armor for this attack (default 0) -Param6: Percent of npc's natual crit that can go toward this attack (default: 100) +Param6: Percent of npc's natual crit that can go toward this attack (default: 100) Param7: Flat crit bonus on top of npc's natual crit that can go toward this attack (default 0) Ex: Normal Flurry with 25% proc rate and 100% crit chance that ignores 500 armor. @@ -1741,7 +1743,7 @@ Upgrade notes: -Some item quests have changed in a subtle way, though it's unlikely any quests are impacted and the thread has more information if you found any of your quests broke. As far as I know for example: PEQ didn't have to update any of its nearly 70 item quests. -Cazic Touch (982) no longer shouts the name of the thing it is targeting without a script. -EVENT_DEATH now triggers before the death is complete. For the old functionality you may use EVENT_DEATH_COMPLETE. It might be a good idea to replace all EVENT_DEATH with EVENT_DEATH_COMPLETE in existing spells. - + We sought to minimize changes required but it's still a bit disruptive so take a few minutes when upgrading to make sure everything is correct. Most notably quest::clearhandin was used in some popular plugins to avoid a dupe involved with its code and now that it's gone those will not function if fixes are not applied. == 06/16/2013 == @@ -1838,7 +1840,7 @@ demonstar55: Fixed stacking issues with SE_Limit* (ex. Unholy Aura Discipline an == 03/18/2013 == Bad_Captain: Fixed zone crash due to merc focus effects & tribute. -Bad_Captain: Fixed merc aggro issues when client in melee range & spell recast timers. +Bad_Captain: Fixed merc aggro issues when client in melee range & spell recast timers. Bad_Captain: Added melee DPS spells/disciplines & support. == 03/17/2013 == @@ -1851,9 +1853,9 @@ Derision: Fixed a couple of memory leaks in Rez code. == 03/14/2013 == JJ: (NatedogEZ) Fix for hate list random never selecting last member of hate list. -Bad_Captain: Fixed Merc spell recast timers. +Bad_Captain: Fixed Merc spell recast timers. Bad_Captain: Changed how Mercs add mobs to their hate lists (should prevent IsEngaged() issues). -Bad_Captain: Initial Caster DPS Merc spell casting AI, including initial Merc stance implementation. +Bad_Captain: Initial Caster DPS Merc spell casting AI, including initial Merc stance implementation. Bad_Captain: Mercs now suspend when their owner dies to prevent them being bugged (until it can be fixed). OPTIONAL SQL: 2013_03_14_Merc_Spells.sql @@ -1887,7 +1889,7 @@ REQUIRED SQL: 2013_03_1_Merc_Rules_and_Equipment.sql KLS: Changed how shared memory works: Instead of System V/windows pagefile shared memory we now have shared memory that's backed by the filesystem. What that means is basically instead of EMuSharedMem(shared library) we now have shared_memory(executable), shared memory will be persistent between runs until you delete or reload it using the shared_memory executable. - + STEPS FOR PEOPLE WHO CAN'T BE BOTHERED TO FIGURE IT OUT: 1) Create a directory in the place you run world/zone named shared and make sure files can write there. 2) Run the shared_memory executable from the same place you run world/zone (it's basically doing the loading we would do on startup so will take a moment). @@ -1946,7 +1948,7 @@ Uleat: Changed conversion of bot armor colors from long to unsigned long. Conver cavedude00: Added heading to start_zones Uleat: Fixed the 'nude' bot issue. Mob::texture was not set to the appropriate value and forcing an unclad body model. Uleat: Fixed the show/hide helm feature. Added rebroadcast of packet so that changes take place immediately instead of after zoning. -KLS: Addressed several (completely stupid and inexcusable) bugs in the avoidance code that made it impossible to dodge and parry in certain situations. +KLS: Addressed several (completely stupid and inexcusable) bugs in the avoidance code that made it impossible to dodge and parry in certain situations. As a note: please don't touch the avoidance code if you don't know what you're doing, seriously. Required SQL: utils/sql/svn/2482_required_start_zones.sql @@ -2033,7 +2035,7 @@ Uleat: Fixed a corpse looting issue where the power source item (slot 9999) was Uleat: Power Source items will now report in 'worn' instead of 'inv' when using #peekinv. == 01/20/2013 == -KLS: intN types have changed to more closely reflect C99 and C++11 types: +KLS: intN types have changed to more closely reflect C99 and C++11 types: intN was an unsigned int of N bits -> it is now a signed int of N bits. sintN was a signed int of N bits -> it has been removed in favor of intN. uintN is still unsigned. @@ -2087,7 +2089,7 @@ Trevius: RoF: Disciplines now update without zoning. == 01/12/2013 == Derision: RoF: Personal Tribute and the Pet Buff Window now work. -Derision: Fixed potential crash in SendPetBuffsToClient. +Derision: Fixed potential crash in SendPetBuffsToClient. Derision: RoF: Accounted for the fact the Duplicate Lore item message now includes the item's name. Trevius: RoF: The Task Selector Window is now functional. @@ -2117,7 +2119,7 @@ REQUIRED SQL: utils/sql/svn/2383_required_group_ismerc.sql -- adds ismerc col OPTIONAL SQL: utils/sql/svn/2380_optional_merc_rules.sql -- Contains rules for mercs including rule to enable mercs OPTIONAL SQL: utils/sql/svn/2380_optional_merc_merchant_npctypes_update.sql -- Contains npc_types & spawn updates for merc merchants in PoK OPTIONAL SQL: utils/sql/svn/2380_optional_merc_data.sql -- Contains basic merc data, template info, & merc merchant entries -OPTIONAL SQL: utils/sql/svn/mercs.sql -- Contains merc stats & armor - to be replaced as needed with updated stats, spells, etc. Allows a complete resourcing of file +OPTIONAL SQL: utils/sql/svn/mercs.sql -- Contains merc stats & armor - to be replaced as needed with updated stats, spells, etc. Allows a complete resourcing of file == 01/07/2013 == Trevius: RoF: /who and /who all now function properly. @@ -2274,7 +2276,7 @@ Secrets/Akkadius: Implemented the customary ability to scale an NPC's spell dama This will allow an NPC to do for example 150% of the damage of their damage spells if spellscale is set to '150' 'healscale' field needs to be set to affect heals in a similar manner Both of these can also be accessed via ModifyNPCStat through 'healscale' and 'spellscale' - + REQUIRED SQL: utils/sql/svn/2283_required_npc_changes.sql ==12/06/2012== @@ -2401,7 +2403,7 @@ Kayen: Fix for crippling blow chance, other minor fixes related to bonuses. ==09/20/2012== Kayen: AA dbase table fixes - Archery Mastery, Fury of Magic. -REQUIRED SQL: utils/sql/svn/2215_required_aa_updates +REQUIRED SQL: utils/sql/svn/2215_required_aa_updates ==09/19/2012== KLS: Faction mods (Race, Class, Deity) can now be added on the fly, without adding database columns or editing the code. Source in the database change, run utils/factionmod.pl, and then drop the faction_list table to convert. @@ -2423,7 +2425,7 @@ Kayen: Removed SE_Twinproc - This is not an actual spell effect, Twin proc is no Kayen: Implemented SE_TwoHandBluntBlock - Chance to block when using two hand blunt weapon (similiar to shield block). Kayen: SE_NegateEffect will now negate all AA, item and spell bonuses for the specified effects. Kayen: Added support to allow for certain bonuses to now properly be calculated when cast as debuffs (ie decrease chance to critical hit) -Kayen: Implemented rule to allow certain bonuses to be calculated by adding together the value from each item, instead of taking the highest value. +Kayen: Implemented rule to allow certain bonuses to be calculated by adding together the value from each item, instead of taking the highest value. *Ie. Add together all worn cleave effects, ferocity effects ect. OPTIONAL SQL: utils/sql/svn/2209_optional_additive_bonus_rule.sql (disabled by default) @@ -2450,7 +2452,7 @@ references: http://www.eqemulator.org/forums/showthread.php?t=35604 - CSD Support Patch 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.) @@ -2474,7 +2476,7 @@ ENC AA: Total Domination now implemented with bonus SE_CharmBreakChance. SK AA: Soul Abrasion now implemented with bonus SE_ImprovedDamage2. *Many fixes to previously implemented AA effects. -REQUIRED SQL: utils/sql/svn/2208_required_aa_updates +REQUIRED SQL: utils/sql/svn/2208_required_aa_updates OPTIONAL SQL: utils/sql/svn/2208_optional_aa_stacking_rule.sql (If false will disable AA stacking for all clients) OPTIONAL SQL: utils/sql/svn/2208_optional_EnableSoulAbrasionAA *If using an older server spell file (pre SOF), will need to run this to correctly populate the 'spellgroups' field. @@ -2528,11 +2530,11 @@ Kayen: Taunt skill updated to work consistent with live. *Taunt success chance should be accurate to live. Penalty of not being at max skill lv can be adjusted with (RULE: Combat:TauntSkillFalloff) *Live messages for taunt success and failure are now implemented. (Note: Only NPC races that can 'talk' will say the success message). Bad_Captain: Bots- Fixed an issue when with bot spell timers that could lead to a crash. -Kayen: Fixed SQL files from rev2185+ that were not saved as .sql +Kayen: Fixed SQL files from rev2185+ that were not saved as .sql -OPTIONAL SQL: utils/sql/svn/2189_optional_taunt_rules +OPTIONAL SQL: utils/sql/svn/2189_optional_taunt_rules OPTIONAL SQL: utils/sql/svn/2185_optional_NPCFlurryChance_rule (run this again) - + ==08/16/2012== Kayen: Complete revision of the Death Save and Divine Save effects and related bonuses to be consistent with live. *Death Save (Death Pact/DI) will no longer fire on death. It should only fire when less 15% HP but not killed. @@ -2542,7 +2544,7 @@ Kayen: Complete revision of the Death Save and Divine Save effects and related b do a portion of the original heal value. (Ie DI=8000HP with ToTD-3(60%) your heal will be 8000*0.6 = 4800HP) *Implemented functionality for later expansion Death Save effects (Divine Intercession ect) These can add heal value to the base heal which is limited by level (ie Heal 10,0000+8000 if client less then level 80) - + *Divine Save (AA Unfailing Divinity) only fire upon death of client with this effect and is independent of Death Save effect. *Increased ranks of AA only increase the chance of firing upon death. Heal value does NOT increase with rank. *Upon firing you will still recieve the Divine Aura like buff, which now also correctly removes all determental effects. @@ -2564,7 +2566,7 @@ DRU AA: Enchanted root/Viscid Root (was implemented completely wrong), now uses Added RULE: RootBreakFromSpells - Baseline is/was set at 20% chance from nukes. -REQUIRED SQL: utils/sql/svn/2188_required_aa_updates +REQUIRED SQL: utils/sql/svn/2188_required_aa_updates OPTIONAL SQL: utils/sql/svn/2188_optional_miscspelleffect_rules ==08/13/2012== @@ -2576,10 +2578,10 @@ Kayen: Minor update to duel wield, chance bonuses will be correctly applied to b Kayen: Implemented Perl MOB Quest Object SetFlurryChance(value) (ie 50 = 50% chance for NPC flurry if special atk "F") Kayen: Implemented Perl MOB Quest Object GetFlurryChance(value) returns flurry chance. Kayen: Added rule to adjust server wide flurry chance (Default = 20%) *Perl object will override this. - + Following AA effects are now implemented as bonuses: You must update your 'aa_effects' table with 'required_aa_updates.sql' for these to work. MISC AA: Dead Aim, Precision of the Hunter, Scout's Efficiency will now calculate from bonus SE_Accuracy. -MISC AA: Combat Agility line will now calculate from bonus SE_AvoidMeleeChance. (Now implemented through SoD) +MISC AA: Combat Agility line will now calculate from bonus SE_AvoidMeleeChance. (Now implemented through SoD) MISC AA: Combat Stability line will now calculate from bonus SE_CombatStability. (Now implemented through SoD) MISC AA: Double Riposte, Return Kick now calculated from bonus SE_GiveDoubleRiposte. (New AA's implemented that use this) MISC AA: Natural Durability, should be working correctly now from bonus SE_MaxHP. @@ -2589,33 +2591,33 @@ MISC AA: Pet AA's that give flurry chance will now be applied by bonus, SE_PetFl MAG AA: Elemental Agility was incorrectly giving melee mitigation instead of avoidance, to now use SE_PetAvoidance. MAG AA: Elemental Durability will now add to pet max hp with bonus, SE_PetMaxHP. -REQUIRED SQL: utils/sql/svn/2185_required_aa_updates +REQUIRED SQL: utils/sql/svn/2185_required_aa_updates OPTIONAL SQL: utils/sql/svn/2185_optional_NPCFlurryChance_rule ==08/12/2012== Bad_Captain: Fixed an issue when using bots where you would not get xp when your pet did most of the damage and you are not grouped. -Bad_Captain: Added rule to enable receiving xp from bots not in your group. Defaults to false. +Bad_Captain: Added rule to enable receiving xp from bots not in your group. Defaults to false. -OPTIONAL SQL: utils/sql/svn/2183_optional_bot_xp_rule.sql +OPTIONAL SQL: utils/sql/svn/2183_optional_bot_xp_rule.sql ==08/08/2012== -Kayen: Updates to critical hit calcuations to be consistent with live. - *Baseline critical rate is determined by DEX stat (255 dex = 2%),this baseline is then modified by item,spell and AA critical chance bonuses. +Kayen: Updates to critical hit calcuations to be consistent with live. + *Baseline critical rate is determined by DEX stat (255 dex = 2%),this baseline is then modified by item,spell and AA critical chance bonuses. *Pet critical baseline is determined by the rate from AA effects that give pets the ability to critical. (Can not crit w/o this effect) -Kayen: Slay Undead effect will now be working consistent with live. - *Slay rate is no longer effected by critical hit rate, it uses it's own predetermined rates from the spell effect data. - *Damage modification will now be much closer to that of lives utilizing the spell effects damage modifier. +Kayen: Slay Undead effect will now be working consistent with live. + *Slay rate is no longer effected by critical hit rate, it uses it's own predetermined rates from the spell effect data. + *Damage modification will now be much closer to that of lives utilizing the spell effects damage modifier. *Example(AA Slay Undead I - Rate: 225 (2.25%) Damage Mod: 680%) *Note that that spell effects using Slay Undead (Holyforge) will stack with AA and increase the damage and the rate. -Kayen: Crippling Blow's derived from spell effects will now be calculated consistent with live. - *Cippling blow chance is determined by modifying your critical hit chance. - *Example (Savage Onslaught - 200% chance to crippling blow) If you have a base chance to critical hit of 10% +Kayen: Crippling Blow's derived from spell effects will now be calculated consistent with live. + *Cippling blow chance is determined by modifying your critical hit chance. + *Example (Savage Onslaught - 200% chance to crippling blow) If you have a base chance to critical hit of 10% and you score a critical hit, you will then have a 20% chance to crippling blow. Kayen: Fixed effect for AA 'War Cry' will now provide group fear immunity for duration. Kayen: Few new AA's added including shaman Ancestral Aid and Spirit Channeling. - + Following AA effects are now implemented as bonuses: You must update your 'aa_effects' table with 'required_aa_updates.sql' for these to work. -MISC AA: 'Combat Fury', 'Fury of the Ages' will now calculate from bonus SE_CriticalHitChance. +MISC AA: 'Combat Fury', 'Fury of the Ages' will now calculate from bonus SE_CriticalHitChance. MISC AA: 'Veteran's Wrath' will now calculate from bonus SE_CriticalDmgMod. MISC AA: All AA that give pet criticals will be calculated from SE_PetCriticalHit. PAL AA: 'Slay Undead', 'Vanquish Undead' will now calculate from bonus SE_SlayUndead. (Holyforge now works correctly) @@ -2626,7 +2628,7 @@ REQUIRED SQL: utils/sql/svn/2178_required_aa_updates Kayen: Fixes to rev2176 - Double Attack, EndlessQuiver, Run Speed. REQUIRED SQL: utils/sql/svn/2176_required_aa_updates will need to be applied again for Run Speed fix. -==08/05/2012== +==08/05/2012== Kayen: Complete revision of how double attack chance is calculate to be consistent with live. Kayen: Berserker 'Frenzy' skill attack will now function as it does on live. Gives a chance for 1-3 attacks using frenzy skill specific damage. *Note: This will be a considerable nerf to bersekers because it was previously coded to give actual melee rounds using weapon damage. @@ -2634,19 +2636,19 @@ Kayen: Implemented a few miscellaneous new AA's, mostly from DODH. (These will s Kayen: Added almost all remaining spell effects into spdat.h (~90% defined). Kayen: Alternate Advancement Update: In the process of coverting most of the hard coded AA data out of the source and into the 'aa_effects' table using live data. These effects are then reimplemented using the bonus system in the broadest possible way, most of these effects will -also be useable as regular spell/item effects. This will allow developers in the future to adjust,implement and customize AA effects -without requiring source changes. Beware in doing this, many AA effects that were previously either implemented incorrectly or with values +also be useable as regular spell/item effects. This will allow developers in the future to adjust,implement and customize AA effects +without requiring source changes. Beware in doing this, many AA effects that were previously either implemented incorrectly or with values not consistent with live data will be adjusted to be as accurate as possible. Following AA effects are now implemented as bonuses: You must update your 'aa_effects' table with 'required_aa_updates.sql' for these to work. -MISC AA: All innate run speed AA's have been converted to use bonus SE_BaseMovementSpeed. +MISC AA: All innate run speed AA's have been converted to use bonus SE_BaseMovementSpeed. MISC AA: All bind wound related AA have been converted to use bonuses, SE_ImprovedBindWound, SE_MaxBindWound. MISC AA: Shield Block will now be calculated using bonuses, SE_ShieldBlock. MISC AA: Sinister Strike will now correctly allow your off hand weapon to recieve a weapon damage bonus, SE_SecondaryDmgInc. MISC AA: Strengthened Strike/Vicious Smash/Kick Mastery will now accurately to live add skill damage to respective special abilities. MISC AA: StrikeThrough, Tactical Mastery - will now be calculated from bonus, SE_Strikethrough2. MISC AA: Ferocity, Knight's Advantage ect - will now be calculated from bonus SE_DoubleAttackChance. -MISC AA: Harmonious Attacks, Bestial Frenzy - will allow double attack chance using bonus SE_GiveDoubleAttack (any class can be given this) +MISC AA: Harmonious Attacks, Bestial Frenzy - will allow double attack chance using bonus SE_GiveDoubleAttack (any class can be given this) MISC AA: Weapon Affinity, will now use SE_ProcChance. MISC AA: PunishingBlade, SpeedoftheKnight will now allow an extra 2 Handed attack using bonus, SE_ExtraAttackChance. BRD AA: Fleet of Foot will now correctly allow bards to run over the speed cap using, SE_IncreaseRunSpeedCap. @@ -2658,42 +2660,42 @@ RNG AA: Endless Quiver - Implemented as SE_ConsumeProjectile which gives a perc RNG AA: Archery Mastery- Implemented as SE_ArcheryDamageModifier which gives a percent increase to archery attacks. BER AA: Throwing Mastery - Implemented using SE_DamageModifier. BER AA: Blur of Axes, Vicious Frenzy - will now correctly add skill damage to 'Frenzy' skill attacks. -ROG AA: Triple Backstab, SiezedOpportunity, Chaotic Stab - as bonus, SE_TripleBackstab, SE_FrontalBackstabChance,SE_FrontalBackstabMinDmg. +ROG AA: Triple Backstab, SiezedOpportunity, Chaotic Stab - as bonus, SE_TripleBackstab, SE_FrontalBackstabChance,SE_FrontalBackstabMinDmg. REQUIRED SQL: utils/sql/svn/2176_required_aa_updates Optional SQL: utils/sql/svn/2176_optional_FrenzyBonus_rule Optional SQL: utils/sql/svn/2176_optional_aa_expansion_sof_fix (Allow AA to show proper expansion in SOF+ clients) -==08/01/2012== +==08/01/2012== Bad_Captain: Fixed bot compile issue introduced in Rev 2171. Bad_Captain: Integrated Kayen's skill attack code with bots' code, as well as other changes from Rev 2171. ==07/31/2012== Akkadius: (KLS) Fix for global_player.pl synchronization. There was an issue where certain subroutines were not passing as global -==07/26/2012== +==07/26/2012== Kayen: Fixed: SE_ImmuneFleeing - Will now disable fleeing if used after mob begins to run, will not effect fleeing from fear. -Kayen: Implemented Perl MOB Quest Object SetDisableMelee(1=Disabled) - Prevents the ability to auto attack. +Kayen: Implemented Perl MOB Quest Object SetDisableMelee(1=Disabled) - Prevents the ability to auto attack. Kayen: Implemented Perl MOB Quest Object IsMeleeDisabled() Sorvani: corrected build name for queryserv project in all the various build types. - -==07/24/2012== + +==07/24/2012== Kayen: Implemented: SE_HundredHands (incorrectly marked as already implemented) - Increases/Decrease actual weapon delay by % of value. Kayen: Implemented: Missing modifications from the Archery/Throw damage pathways. *SkillAmount/SkillDamageTaken mods, ability to Block/Dodge/Parry ranged attacks (Can not riposte), other new focus/mod effects. -Kayen: Fixed: aaThrowingMastery will no longer be applied 2x per throw. +Kayen: Fixed: aaThrowingMastery will no longer be applied 2x per throw. Kayen: Implemented: Damage bonus to skill attacks from specific armor slot AC (ie KICK from BOOT AC) can adjust with rule 'SpecialAttackACBonus' Kayen: SE_MinDamageModifier should now apply to skill specific effects and to special attacks. Kayen: Implemented: Complete revision of SE_SkillAttack. (+ required various fixes/adjustments to functions related to special attacks) *This spell effect performs a physical attack from a specific skill with a set weapon damage value and chance to hit modifier. *Attacks will now calculate correctly and use their actual respected pathways utilizing all skill specific mods/bonus. -Kayen: Implemented Perl MOB Quest Object DoMeleeSkillAttackDmg(target, weapon_damage, skill, chance_mod, focus, CanRiposte) -Kayen: Implemented Perl MOB Quest Object DoArcheryAttackDmg(target,NULL,NULL, weapon_damage, chance_mod, focus) -Kayen: Implemented Perl MOB Quest Object DoThrowingAttackDmg(target,NULL,NULL, weapon_damage, chance_mod, focus) +Kayen: Implemented Perl MOB Quest Object DoMeleeSkillAttackDmg(target, weapon_damage, skill, chance_mod, focus, CanRiposte) +Kayen: Implemented Perl MOB Quest Object DoArcheryAttackDmg(target,NULL,NULL, weapon_damage, chance_mod, focus) +Kayen: Implemented Perl MOB Quest Object DoThrowingAttackDmg(target,NULL,NULL, weapon_damage, chance_mod, focus) Optional SQL: utils/sql/svn/2171_optional_SpecialAttackACBonus_rule - + ==07/18/2012== Kayen: Implemented NPC Special Attack 'K'. Immune to Dispell. Kayen: Fixed SE_RangedProc to be applied after zoning, calculate proc rate correctly, utilize numhits. @@ -2708,7 +2710,7 @@ Kayen: Implemented: SE_SpellProcChance, SE_CharmBreakChance, SE_BalanceMana, SE_ SE_CriticalHealOverTime2, SE_CriticalHealChance2, SE_SkillDamageAmount2, SE_LimitSpellSkill, SE_LimitClass SE_LimitExcludeSkill, SE_ShieldBlock, SE_BlockBehind Kayen: Implemented: SE_Empathy - A focus limited debuff which causes (spells/skill attacks) cast on target to do +X amount more damage. - *This spell effect is often limited using SE_LimitSpellSkill. + *This spell effect is often limited using SE_LimitSpellSkill. *(Ie. If empathy value is 1000 and limited to evocation, all nukes on target using evoc. will get +1000 damage) Kayen: Implemented: SE_SpellPowerIncrease - Can be used to apply a worn/buff focus effect with limits for... 1) Additional bard instrument modifiers. @@ -2716,16 +2718,16 @@ Kayen: Implemented: SE_SpellPowerIncrease - Can be used to apply a worn/buff foc 3) Increase effectiviess of casted/disc Skill Attacks. 4) General use stackable Healing/Damage focus. 5) Increase the value of melee runes by focus amount. -Kayen: SE_HPtoMana will no longer drain your HP before the spell is finished casting. Effect now handled as a bonus using best value. -Kayen: SE_SpellVulunerability will now correctly calculate and apply the highest value if target has mulitple effects. -Kayen: Fixed an issue where DOTs cast by an NPC on another NPC would not generate hate per tick. Improved how we calc damage from DOTs. +Kayen: SE_HPtoMana will no longer drain your HP before the spell is finished casting. Effect now handled as a bonus using best value. +Kayen: SE_SpellVulunerability will now correctly calculate and apply the highest value if target has mulitple effects. +Kayen: Fixed an issue where DOTs cast by an NPC on another NPC would not generate hate per tick. Improved how we calc damage from DOTs. Kayen: SE_BlockSpellEffect was implemented incorrectly and has been revised to SE_NegateSpellEffect. *It is not meant to block buffs, rather it negates the specific spell bonuses or effects from buffs you already have. *Currently functional with any effect that is handled under bonuses, and focus effects. Kayen: Vastly improved how we handle melee/spell runes/partial mitigation runes ect. Should be significantly more efficient. *Melee/Spell Mitigation runes and ManaAbsorbPercentDamage effects will now use the best mitigation value if multiple effects. Kayen: Improved the process we use to get spell/item focus effects. An initial check if the client has a specific focusType -is done while checking for item/spell bonuses. GetFocusEffect will no longer check all inventory and buff slots every cast for the +is done while checking for item/spell bonuses. GetFocusEffect will no longer check all inventory and buff slots every cast for the focusType if that focusType doesn't exist on the client. This should improve performance since these checks are done 10-20x per cast/proc. ==07/15/2012== @@ -2735,7 +2737,7 @@ Secrets: Fixed an issue with saylinks above 255 characters. If you do want to us Bad_Captain: Fixed another bug that allowed pets to steal xp when using bots. Bad_Captain: Bots: Persisting spell & discipline timers. Bad_Captain: Bots: Bot pets will no longer continuously try to get behind a mob if they are tanking. -Bad_Captain: Bots: Fixed potential duplicate lore item bug when trading with bots. +Bad_Captain: Bots: Fixed potential duplicate lore item bug when trading with bots. Bad_Captain: Bots: Fixed bot compile issue from Rev 2160. Bad_Captain: Bots: Fixed multiple issues with #bot spawn and #bot botgroup load (c0ncrete). Bad_Captain: Bots: Implemented new #bot defensive command for Warriors and Knights. Includes most of the code required to implement disciplines for bots. Requires disc AI & disc lists. @@ -2758,9 +2760,9 @@ Kayen: Updated spdat.h with many new live spell effects that were previously 'un ==07/05/2012== Kayen: Implemented: SE_Manaburn: Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana. -Kayen: Implemented: SE_CastonNumHitFade: Casts a spell when a buff fades due to its numhits being depleted. +Kayen: Implemented: SE_CastonNumHitFade: Casts a spell when a buff fades due to its numhits being depleted. Kayen: Implemented: support for all remaining live spell effects that use 'numhits'. - Significantly optimized how all spell effects that utilize 'numhits' are handled throughout the source. + Significantly optimized how all spell effects that utilize 'numhits' are handled throughout the source. Kayen: Fixed: SE_DefensiveProc - Proc rate will now be calculated similiar to live. *Spell specific rate modifcations will now work. Kayen: Added Rule: Combat:AvgDefProcsPerMinute (Default = 2.0) Determine defensive procs per minute. Kayen: Added Rule: Combat:DefProcPerMinAgiContrib (Default = 0.075) Determines how much agility effects proc rate. @@ -2768,9 +2770,9 @@ Kayen: Added Rule: Combat:DefProcPerMinAgiContrib (Default = 0.075) Determines h Optional SQL: utils/sql/svn/2159_optional_defensiveproc_rules ==06/29/2012== -Kayen: Implemented Perl NPC Quest Object GetSlowMitigation() -Kayen: Implemented Perl NPC Quest Object GetAttackSpeed() -Kayen: Implemented Perl NPC Quest Object GetAccuracyRating() +Kayen: Implemented Perl NPC Quest Object GetSlowMitigation() +Kayen: Implemented Perl NPC Quest Object GetAttackSpeed() +Kayen: Implemented Perl NPC Quest Object GetAccuracyRating() Kayen: Fixed: Slow Mitigation (was not loading from dbase),optimized its application in source and added lives slow mitigation messages. Slow mitigation Messages: 'slighty' 0.00 - 0.25 'partial' 0.25-0.75 'mostly' 0.75-1 Kayen: Implemented: SE_AttackSpeed4: 'Inhibit Melee' effect works different then regular haste/slow effect @@ -2781,13 +2783,13 @@ Kayen: Added Rule: Spells:CharismaEffectiveness (Default = 10) Deterimes how muc Kayen: Added Rule: Spells:CharmBreakCheckChance (Default = 25) Determines percent chance for a charm break check to occur each buff tick. Kayen: Reworked code to that handles charm breaks/lull to be accurate to live and more functional in general. 1) Each charm buff tick there is a default 25% [Rule.CharmBreakCheckChance] chance to trigger a spell resistance check. - 2) Spell resistance check then adds an additional bonus resist modification based casters Charisma at a default + 2) Spell resistance check then adds an additional bonus resist modification based casters Charisma at a default ratio of 10 CHA per -1 resist mod [Rule.CharismaEffectiveness] 3) If resisted (ie Charm is to break) Total Domination AA is then applied to give another chance to maintain the charm. Kayen: Implemented: SE_AdditionalHeal: Focus Effect that adds an additional heal amount to the casted spell. Kayen: Implemented: SE_CastOnCure: Casts a spell on cured target. Kayen: Implemented: SE_CastOnCurer: Casts a spell on the curer of the target. -Kayen: Modified: Mob::TryFadeEffect to avoid interaction wtih Twinproc effect. +Kayen: Modified: Mob::TryFadeEffect to avoid interaction wtih Twinproc effect. cavedude: (Uleat) Multiple changes and additions to doors, per the forums. Optional SQL: utils/sql/svn/2156_optional_charm_break_rule.sql @@ -2812,8 +2814,8 @@ Kayen: Implemented SE_FF_Damage_Amount - Focus/Buff that adds damage to the cast Kayen: Adjusted SE_SpellDamage to be handled properly as a focus effect. Kayen: Extra damage from Focuses is now calculated correctly for DoTs Kayen: Implemented Perl NPC Quest Object SetSpellFocusDMG(focus amount) - Focus all npc direct/dot damage spells by value -Kayen: Implemented Perl NPC Quest Object SetSpellFocusHeal(focus amount) - Focus all npc healing spells by value -Kayen: Implemented Perl Mob Quest Object ModSkillDmgTaken(skill_num,value) - Set a weakness/bonus of weapon attacks to a Mob +Kayen: Implemented Perl NPC Quest Object SetSpellFocusHeal(focus amount) - Focus all npc healing spells by value +Kayen: Implemented Perl Mob Quest Object ModSkillDmgTaken(skill_num,value) - Set a weakness/bonus of weapon attacks to a Mob - Example: mob can be set to take 5% more damage from blunt weapons - ModSkillDmgTaken(0,5) - Stacks with spell/item bonuses - Setting skill to -1 will effect all skills Kayen: Implemented Perl Mob Quest Object GetModSkillDmgTaken(skill_num) - Returns only the quest skill mod for specified skill @@ -2825,7 +2827,7 @@ Kayen: Implemented Perl Mob Quest Object ModVulnerability(resist type, value) - - Example: mob can be set to take 5% more damage from Fire spells (2,5); - Applied effect will stack with spell buff effects. - If a resist type SPECIFIC and a resist type ALL mod are applied to the same MOB, the SPECIFIC value will be used if spell cast on MOB is the same resist type. -Kayen: Implemented Perl Mob Quest Object GetModVulnerability(resist type) - Return the quest applied value for each resist (ALL = -1) +Kayen: Implemented Perl Mob Quest Object GetModVulnerability(resist type) - Return the quest applied value for each resist (ALL = -1) Optional SQL: utils/sql/svn/2154_optional_rule_spell_procs_resists_falloff.sql @@ -2885,12 +2887,12 @@ Trevius: VoA - The AA Window now populated AAs. AA hotkeys can be created, but sorvani: Bard AE DoTs should now be affected by mods correctly. ==04/19/2012== -cavedude: quest::buryplayercorpse will now despawn corpses in zones other than the client's current location, preventing dupes. +cavedude: quest::buryplayercorpse will now despawn corpses in zones other than the client's current location, preventing dupes. cavedude: Added quest::summonallplayercorpses (same syntax as quest::summonburriedplayercorpse) which will depop and summon all of the player's corpses, buried or not. cavedude: Fixed a bug that caused some summoned corpses to use a static 5 minute decay timer. cavedude: Changed player_corpses_backup schema to match player_corpses. If the rule is enabled, corpse backups will now be created for players that are high enough level to drop items to their corpses. cavedude: Added a rule to determine whether or not to remove player corpse backups older than 2 weeks. -cavedude: #corpse now has options to depop a single player corpse, or every corpse belonging to a single player. +cavedude: #corpse now has options to depop a single player corpse, or every corpse belonging to a single player. cavedude: You can now specify if a faction hit is temporary (is removed when player camps/zones) or whether or not to display the faction hit to the player in-game. If temp in npc_faction_entries is set to: 0 (Default): Faction is permanent, player recieves a message. (Same functionality as we had previously.) @@ -2898,7 +2900,7 @@ If temp in npc_faction_entries is set to: 2: Faction is temporary, player recieves a message. 3: Faction is permanent, but player does not recieve a message. cavedude: Added an optional argument to quest::faction to utilize the functionality and values listed above. -cavedude: Added minlevel and maxlevel to lootdrop_entries. The player credited with the kill (most hate) has their level checked against both columns, and if they are lower than the specified minlevel, or higer than the max, that item entry if it exists is removed from the NPC before it becomes a corpse. +cavedude: Added minlevel and maxlevel to lootdrop_entries. The player credited with the kill (most hate) has their level checked against both columns, and if they are lower than the specified minlevel, or higer than the max, that item entry if it exists is removed from the NPC before it becomes a corpse. cavedude: You can now specify if a NPC automatically repops (rerolls against their spawngroup) or depops after the reverse spawn timer is up. If despawn in spawngroup is set to: 0 (Default): Do not depop or repop, no depop timer is set. (Same functionality as we had previously.) @@ -2991,10 +2993,10 @@ JJ: Removed additional library and include directories from windows projects as Sorvani: Resurrections effects will again be applied to characters who are in a zone where combat is not allowed (GL, PoK etc) when they receive a rez. ==03/19/2012== -Bad_Captain: Bots: A few fixed for #bot stance command +Bad_Captain: Bots: A few fixed for #bot stance command ==03/19/2012== -Bad_Captain: Bots: Implemented bot stances. See forum post. +Bad_Captain: Bots: Implemented bot stances. See forum post. Required SQL: utils/sql/svn/2107_required_bot_stances.sql @@ -3078,11 +3080,11 @@ Reccomended SQL: (ON QueryServ's database, NOT the main db) utils/sql/queryserve Secrets: v90 toolset bugs reported on forums. In order to use Perl 5.14, you MUST upgrade to VS2010 (preferrably ultimate), if you do not have vs2010, it will default to Perl 5.10 and you will be unable to use the much more stable Perl 5.14, an upgrade is reccomended. Secrets: Fixed Windows x64 rulesys bug where it would store them as an x64 version of an int (long long) and mess up the ordering of pointers, resulting in certain rules not loading properly. NOTE: For those having issues compiling vs2010, there will be a guide up shortly to help you set up your dev environment. In the meantime, make sure your "Additional Include" and "Additional Library" paths -are correct and pointing at the right location. Failure to do so will result in mysql header/lib and perl header/lib issues. If you are looking for zlib x64, it's in SVN. +are correct and pointing at the right location. Failure to do so will result in mysql header/lib and perl header/lib issues. If you are looking for zlib x64, it's in SVN. ==11/30/2011== Secrets: Implemented Visual Studio 11 and Visual Studio 10 project/sln files. -Secrets: Added x64 configuration settings to VS11 and VS10 project files/SLN files. +Secrets: Added x64 configuration settings to VS11 and VS10 project files/SLN files. Secrets: Changed WIN32 define to _WINDOWS across the board. In the case where WIN32 is needed over WIN64 (ie; assembly references) there is still WIN32 defines and a new WIN64 define. Secrets: Upgraded ActiveState Perl lib define to 5.14 -- others still work but it is strongly reccomended to use 5.14 as it contains less memory leaks. Secrets: Added Zlib 1.2.3 x64 to the SVN for use with the windows solution files. @@ -3117,7 +3119,7 @@ Lerxst: Fixed crash when calculating random focus effect from an augment when th Also added some bulletproofing in case that isn't the only place an invalid spell id might be passed. ==11/16/2011== -Akkadius: Added the ability to specify doors/objects/ground spawns to load for all versions of the same zone regardless by setting the value to -1. +Akkadius: Added the ability to specify doors/objects/ground spawns to load for all versions of the same zone regardless by setting the value to -1. This reduces serious redundancy of copying the same data over and over for instances. Required SQL: @@ -3325,8 +3327,8 @@ Congdar: update check for Lore ==07/17/2011== Congdar: (pfyon, Criimson)Various bot tweaks Caryatis: Updated My/Showstats window. - -Required SQL: + +Required SQL: utils/sql/svn/1974_required_bot_spells_update ==07/16/2011== @@ -3468,9 +3470,9 @@ JJ: Implemented New Tanaan Crafting Mastery tradeskill AA. Each rank allows an a Note: For servers with players who have tradeskills already above the limit without previously purchasing these AAs will freeze the chance to increase until they purchase the proper amount of NTCM AAs. ==05/24/2011== -KLS: Changed Mob::NPCSpecialAttacks(atk, perm) to Mob::NPCSpecialAttacks(atk, perm, [reset = 1], [remove = 0]). -This should allow one to add and remove flags individually without having to reset everything each time. -ex: +KLS: Changed Mob::NPCSpecialAttacks(atk, perm) to Mob::NPCSpecialAttacks(atk, perm, [reset = 1], [remove = 0]). +This should allow one to add and remove flags individually without having to reset everything each time. +ex: $npc->NPCSpecialAttacks(RQ, 0); //would enable the npc to rampage and quad. $npc->NPCSpecialAttacks(S, 0, 0); //Would enable the NPC to summon as well as rampage and quad by telling it to set S but don't reset the earlier flags. @@ -3482,11 +3484,11 @@ $npc->NPCSpecialAttacks(S, 0, 0, 1); //Would enable the NPC rampage and quad by JJ: (Akkadius) Fixed camera shake usage output. ==05/22/2011== -KLS and Co: +KLS and Co: -All liquid should count for skill ups. --Finished unified quest interface... this is fairly large and will probably have a few problems here and there; report them to me and ill fix them asap. -The goal behind the system is to allow more than one scripting system to work at a time (though with limited interaction due to pre-existing implementation limitation). -This was a feature requested by the Dalaya community as they plan to merge back to the eqemu codebase and clients but are stuck with an old parser and thousands of files +-Finished unified quest interface... this is fairly large and will probably have a few problems here and there; report them to me and ill fix them asap. +The goal behind the system is to allow more than one scripting system to work at a time (though with limited interaction due to pre-existing implementation limitation). +This was a feature requested by the Dalaya community as they plan to merge back to the eqemu codebase and clients but are stuck with an old parser and thousands of files that can't be realistically rewritten in a short time frame. ==05/20/2011== @@ -3515,7 +3517,7 @@ Optional SQL: utils/sql/svn/1889_optional_skill_cap_rule.sql ==05/02/2011== Secrets: Added OP_CameraEffect for Titanium. -Secrets: Added commands: #reloadallrules, #reloadrulesworld, and #camerashake. These default to +Secrets: Added commands: #reloadallrules, #reloadrulesworld, and #camerashake. These default to Secrets: Added optional "global" flag as item 5 in the $mob->CameraEffect() quest object. This does #camerashake, but in quest form. Secrets: #reloadallrules reloads rules in every single zone plus world. #reloadrulesworld reloads the rules in world only. Secrets: #camerashake shakes the camera in every zone with required args intensity and duration. @@ -3835,7 +3837,7 @@ utils/sql/svn/1747_optional_HoT_zone_and_zonepoints.sql For spawns etc, go to the PEQ logs repo for data collected by robregen. -Optional SQL: +Optional SQL: utils/sql/svn/1750_optional_sql_reflect_rule.sql @@ -3848,7 +3850,7 @@ Caryatis: (bad_captain) Removed the level bonus granted to standing mana regen, Caryatis: (bad_captain) Bots have been updated, see forums for complete details(new command: #bot showstats). Caryatis: (Secrets) Haste values can exceed 127%(ie Can o' Whoop Ass). -Optional SQL: +Optional SQL: utils/sql/svn/1746_optional_sql_bot_manaregen ==11/22/2010== @@ -3865,10 +3867,10 @@ Caryatis: Fix for Healrate effect Caryatis: Implemented ManaAbsorbPercentDamage, ReduceSkillTimer, HpToMana and LimitSpellGroup effects. Caryatis: Updated DamageModifier effect to be more robust. -Required SQL: +Required SQL: utils/sql/svn/1737_required_sql_rule_and_aa_update -Optional SQL: +Optional SQL: utils/sql/svn/1736_optional_sql_feral_swipe ==11/14/2010== @@ -3917,7 +3919,7 @@ Caryatis: hStr = Increases endurance pool, endurance regen(25), and the maximum Caryatis: hSta = Increases hit point pool, hit point regen(25), and the maximum amount of hit point regen a character can have(25). Also increases endurance pool, endurance regen(25), and the maximum amount of endurance regen a character can have(25). Caryatis: hAgi = Increases endurance pool, endurance regen(25), and the maximum amount of endurance regen a character can have(25). Also increases the chance to dodge an attack(25), grants a bonus to defense skill(10). Caryatis: hDex = Increases endurance pool, endurance regen(25), and the maximum amount of endurance regen a character can have(25). Also increases damage done by ranged attacks(1), improves chance to successfully assassinate or headshot(10), and improves the chance to riposte, block, and parry incoming attacks(25). -Caryatis: hCha = Improves reaction rolls with some NPCs(25) and increases the amount of faction you gain or lose when faction is adjusted(5). +Caryatis: hCha = Improves reaction rolls with some NPCs(25) and increases the amount of faction you gain or lose when faction is adjusted(5). Caryatis: AA Focus revamped to support new effects Caryatis: Disciplines will no longer be dispelled @@ -3927,7 +3929,7 @@ utils/sql/svn/1719_optional_triggerOnCastAAs.sql ==11/09/2010== Caryatis: Implemented MaxHPChange, SkillDmgTaken, Endurance Pool and Stun Resist. -Optional SQL: +Optional SQL: utils/sql/svn/1717_optional_rule_bash_stun_chance.sql ==11/07/2010== @@ -4106,9 +4108,9 @@ Trevius: (Secrets) Added quest::creategroundobjectfrommodel(modelname, x, y, z, Trevius: (Secrets) quest::creategroundobject(itemid, x, y, z, heading) now returns object ID. Trevius: (Secrets) Added Object List Iteration functions GetObjectByDBID(id), GetObjectByID(id), GetObjectList(). Trevius: (Secrets) exported Objects to Perl with the following commands: - IsGroundSpawn(), Close(), Delete(reset_state=false), StartDecay(), DeleteItem(index), IsObject(), - Save(), SetID(set_id), ClearUser(), DBID(), GetID(), GetX(), GetY(), GetZ(), GetHeading(), VarSave(), - GetType(), SetType(type), GetIcon(), SetIcon(icon), GetItemID(), SetItemID(itemid), SetLocation(x, y, z), + IsGroundSpawn(), Close(), Delete(reset_state=false), StartDecay(), DeleteItem(index), IsObject(), + Save(), SetID(set_id), ClearUser(), DBID(), GetID(), GetX(), GetY(), GetZ(), GetHeading(), VarSave(), + GetType(), SetType(type), GetIcon(), SetIcon(icon), GetItemID(), SetItemID(itemid), SetLocation(x, y, z), SetX(XPos), SetY(YPos), SetZ(ZPos), SetHeading(heading), SetModelName(name), GetModelName(), Repop(), Depop(). ==07/25/2010== @@ -4429,7 +4431,7 @@ KLS: Other merges from spell branch, some more to come. Tell me if there are an ==04/15/2010== cavedude (Leere): Increased the number of tradeskill favorites that can be stored client side to 500. -cavedude (Leere): Fixed avgcoin. +cavedude (Leere): Fixed avgcoin. cavedude (renoofturks): Fixes to SK harm touch. cavedude: Lowered snare movement speed when fleeing to 41% or higher to allow "Snare" to prevent movement at all levels. gaeorn: multiple login server support in world. protocol to update login server account information from within game. "trusted" field for world accounts in loginserver to limit where account updates can come from. in eqemu_config.xml, use to specify first of multiple login servers. increment the number to specify additional login servers. NOTE: be sure to replace the entry or you will be limited to just one login server. MULTIPLE LOGIN SERVERS WILL NOT WORK WITH MINILOGIN. @@ -5214,7 +5216,7 @@ Derision: Fix for mobs in pathing enabled zones fleeing at low health at full ru Derision: Made rule Map:UseClosestZ default to false. Only set true if using azone2 generated maps (specifically those for EQG zones). realityincarnate: Starting cities are now tracked for newly created characters. realityincarnate: Enabled the /setstartcity command for characters without a start city assigned. -realityincarnate: Added $client->SetStartZone and $client->GetStartZone perl commands. +realityincarnate: Added $client->SetStartZone and $client->GetStartZone perl commands. KLS: Petitions will assign id based on character id instead of this stupid desyncing junk. KLS: Max NPC name length increased to 50 characters up from 30. KLS: Save on zone success will now commit immediately instead of possibly delaying. Hopefully will help with some of the situations where people zone to bad locations. @@ -5277,7 +5279,7 @@ KLS: Implemented OP_ClearSurname KLS: (gaeorn) Several 64-bit compile and runtime fixes KLS: (gaeorn) NPC wander back rules. Trevius: #texture will now allow player races to retain armor tint for both PCs and NPCs. -realityincarnate: bug fix for changing max_hp with the modifynpcstat command +realityincarnate: bug fix for changing max_hp with the modifynpcstat command Required SQL: /utils/sql/svn/704_rules.sql @@ -5361,7 +5363,7 @@ Warning: If you do not have a spells_new table yet, you must create one and load After creating the table, you can import or export your spells from the spells_us.txt file by using the scripts: import_spells.pl export_spells.pl - + The easiest way to import your spell file to the table is to move the import_spells.pl file to your main server directory where your spells_us.txt file and your eqemu_config.xml file are. Then run the following command at a command prompt: perl import_spells.pl @@ -5426,7 +5428,7 @@ KLS: Added support for item clicklevel and item clicklevel2 Trevius: Increased spellbook from 400 to 480 in the Player Profile for use with SoF (60 page spell book) Trevius: SoF - Added new functions to SoF.cpp for converting Slot IDs between Titanium and SoF Trevius: SoF - Corrected the location of the spellbook field in the Player Profile to fix an issue with loading spells -WildcardX: Check in of the start of what will become the new BOTS subsystem/framework. This is far from done so just continue to use the existing EQBOTS code you have been using. +WildcardX: Check in of the start of what will become the new BOTS subsystem/framework. This is far from done so just continue to use the existing EQBOTS code you have been using. KLS: Change to dangerous item inst aug creation, hopefully addresses segfault on 64 bit linux. KLS: Hopefully fix for pets not giving adventure credit to players in ldon instances. @@ -5572,7 +5574,7 @@ KLS: Added Rules: (Character, UseXPConScaling), (Character, LightBlueModifier), Derision: Bandolier bug fix. Derision: Equipped items that should confer an extra potion belt slot now do so in Titanium and the 6.2 client (was already working in SoF). Angelox: Bots- (Congdar) fixed Bot illusion / change form spells as to who is affected. -Angelox: Bots- added check to Bot pacify for casting from a distance. +Angelox: Bots- added check to Bot pacify for casting from a distance. ==05/18/2009== @@ -5653,7 +5655,7 @@ Derision: Fixed a bug where a mob aggroed would sometimes appear to run past it' Trevius: (Erde) The Web Tool now shows the name of the process running each Dynamic zone (example: dynamic_01) ==05/06/2009== -Angelox: Bots: Added command '#bot shrinkme' requires Shaman or Beastlord (defaults to Shaman). +Angelox: Bots: Added command '#bot shrinkme' requires Shaman or Beastlord (defaults to Shaman). Derision: Added redux_aa2, redux_rate2 fields to aa_actions. Derision: Improved Hasty Exit should now reduce the reuse time of Escape. Derision: The reuse timer in the AA window now shows the reuse time reduced by applicable AAs. @@ -5714,7 +5716,7 @@ Cripp: Fix for the web interface for those using Perl 5.10. Congdar: Bots - randomized face/hair etc. so they don't all look the same. Fixed Bard AE songs. ==4/30/2009== -Congdar: Bots - bots can now use bows, new command '#bot archery'. Added Ranger archery AA's. Reduced chat mana spam. Tweaked spell ai. Fixed memory leak. Updated '#bot corpse summon'. +Congdar: Bots - bots can now use bows, new command '#bot archery'. Added Ranger archery AA's. Reduced chat mana spam. Tweaked spell ai. Fixed memory leak. Updated '#bot corpse summon'. Derision: SoF - AAs affecting stats now show the correct stats in the client. Derision: Tweaked base resists to match the client. gatorman: Fix for QuickSummoning AA (to include Call of the Hero) @@ -5733,7 +5735,7 @@ Derision: SoF: Ranged attack animations. Derision: When shooting a bow, there is no longer a superfluous 1HS animation. ==4/23/2009== -Trevius: (realityincarnate) Added new quest command quest::varlink(item_id) for putting item links into variables. +Trevius: (realityincarnate) Added new quest command quest::varlink(item_id) for putting item links into variables. Derision: Fix for Tradeskill combines where a LORE ingredient is returned. Derision: Fix for pet names containing spaces losing the space after zoning/camping. Derision: Fixed bug where Return Home sent players bound in Grobb to Qeynos/Unknown Zone. @@ -5752,7 +5754,7 @@ Wolftousen: Rage Volley no longer requires you to have an thrown weapon in your Wolftousen: Rage Volley now uses the proper damage calculation and is not based on the item you have in the ranged slot Wolftousen: Rave Volley can no longer be dodged/blocked/parried/reposted. Wolftousen: Procs from Buffs have been tweaked to go off more often Wolftousen: Players will now receive the "proper" bonus HP for stamina above 255. -Wolftousen: Knight class Tactical Mastery AA was implemented and should now give the strike through message +Wolftousen: Knight class Tactical Mastery AA was implemented and should now give the strike through message renoofturks: Created rule Aggro:StunAggroMod to dial in on aggro of stun based attacks. cavedude: Reverse DS and some DS will now cause aggro on intial cast. realityincarnate: Controllable boats should now work. Please see: http://eqemulator.net/forums/showthread.php?p=167892#post167892 for additonal information. @@ -5928,7 +5930,7 @@ cavedude: Corrected ZEM for AAs. cavedude: (Thanks to demonstar55) 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. +Please note: XP gain has pretty much been overhauled. You may need tweak the multiplier rules for your server. Optional SQL: @@ -6042,7 +6044,7 @@ cybernine186: Optional system to ensure GMs are logging on from a known IP. Trevious: SoF - Drakkin now gain stats from items and weapons now work for combat Trevious: SoF - Drakkin now start with Common Tongue, Dragon and Elder Dragon Languages maxed -Required SQL: utils/sql/svn/340_gm_ips.sql +Required SQL: utils/sql/svn/340_gm_ips.sql ==02/16/2009== Trevius: SoF - The Item Struct should be aligned almost perfectly now. @@ -6153,9 +6155,9 @@ Note: You must move the patch_SoF.conf file from /utils into your server directo ==01/31/2009== Derision: Tweaks to temp merchant list window updates. -cavedude00: Renamed the AugSlotUnk items columns to AugSlotVisible. +cavedude00: Renamed the AugSlotUnk items columns to AugSlotVisible. -Required SQL: utils/sql/svn/292_augslots.sql +Required SQL: utils/sql/svn/292_augslots.sql ==01/29/2009== KLS: VC71 solution files. @@ -6165,7 +6167,7 @@ Angelox: Bots: Added a directory with the BOT Makefiles for Windows and Linux. ==01/27/2009== Derision: Bazaar bug fix. -Angelox: Bots: Added command '#bot runeme' (Enchanter Rune spells) +Angelox: Bots: Added command '#bot runeme' (Enchanter Rune spells) Optional SQL: utils/sql/svn/285_optional_bot_spell_update.sql (removes auto-runes) @@ -6177,7 +6179,7 @@ Derision: Fixed a buffer overflow problem. ==01/19/2009== cavedude00: Increased itemid limit to 120,000. -cavedude00: Meditate will now skill up at a more Live Like speed. +cavedude00: Meditate will now skill up at a more Live Like speed. ==01/18/2009== Derision: Fixed a cause of zone crashes. @@ -6205,7 +6207,7 @@ Derision: Mapped field in LogServer_Struct to allow voice macro window to be ope Derision: Removed code that stole all your money if you logged on with more than 1 million of any denomination of coin on your person. ==01/11/2009== -Angelox: Bots: Added rule 'EQOffline:BotCount' defaults to 5, for desired amount of bots in the group - values are 0-5 (0 means bots are disabled, max limit is 5). +Angelox: Bots: Added rule 'EQOffline:BotCount' defaults to 5, for desired amount of bots in the group - values are 0-5 (0 means bots are disabled, max limit is 5). Derision: Mail/Chatchannels: Added sanity check on packet size in EQPacket::ChatDecode. Derision: Mail/Chatchannels: Increased stream timeout from 45 to 135 seconds. Derision: Mail: Use correct opcodes for sending Headers. **utils/mail_opcodes.conf updated** @@ -6225,7 +6227,7 @@ Angelox: Bots: '#bot sow wolf' should not affect pets anymore. Derision: Chatserver: Added some extra syntax error checking to prevent crashes. Angelox: Bots: Added Wizard class and level check to the '#bot evac' command Angelox: Bots: Added '#bot invis see' for see invisible -Required SQL: +Required SQL: DELETE FROM npc_spells_entries where (npc_spells_id >=701 and npc_spells_id <=712) AND spellid=80; Congdar: Fix NPC::RemoveItem(uint16 item_id) to uint32 to work with items that have id's larger than 65535. '#npcloot remove [itemid]' will now successfully remove items with larger id's from npc loot. Congdar: Bots: Visible gear will now show correctly when trading/equipping bots. @@ -6245,7 +6247,7 @@ Congdar: Bots: update command #bot inventory list Now shows gear as item links Optional SQL: update npc_types set lastname='' where isbot=1; ==01/01/2009== -Angelox: Bots: Added command '#bot sow' (Druid has options) +Angelox: Bots: Added command '#bot sow' (Druid has options) Angelox: Bots: Added command '#bot levitate'. Angelox: Bots: Added command '#bot invis' - (has options). @@ -6558,8 +6560,8 @@ Congdar: Clone NoDrop removal code to NoRent, Lore, NoTrade. Optionally enabled Congdar: Bot code cleanup, method call reduction Congdar: Bot DoubleAttack method is more like clients Congdar: Remove AFK leveling with bots -Angelox: Added command '#Bot evac' for Druid bots -Angelox: Added command '#Bot target calm' for Enchanter or Cleric bots +Angelox: Added command '#Bot evac' for Druid bots +Angelox: Added command '#Bot target calm' for Enchanter or Cleric bots Trevius: Removed the * 10 multiplier from the SE_ProcChance since it isn't needed KLS: Zone appearance should update for players zoning. KLS: Added command #modifynpcstat @@ -6609,7 +6611,7 @@ AndMetal: (seveianrex) Hate w[h]iped on CoH AndMetal: (via Yeahlight) New command: #aggrozone. Requires 100 status by default ==10/19/2008 -Angelox: Added a start to Bot tracking - Thanks Derision for all the help and know-how. +Angelox: Added a start to Bot tracking - Thanks Derision for all the help and know-how. Derision: Altered damage shield message processing to be more like (the same?) as live. Derision: If it exists, damage shield types are read from a new table (damageshieldtypes) Derision: If no entry exists in the table, a default based on resist type is used. @@ -6627,10 +6629,10 @@ KLS: Disarm trap will no longer fail to disarm traps on success. KLS: Increased range on disarm trap slightly. KLS: Change to MakeRandomInt() and MakeRandomFloat() KLS: Int generation be nearly 100% or more faster in most cases and float generation should be slightly faster in most cases -cavedude00: (seveianrex) Slay Undead Fix -cavedude00: (seveianrex) Levitate effect will no longer be removed in cases where you have two stacked lev spells and the first wears off. +cavedude00: (seveianrex) Slay Undead Fix +cavedude00: (seveianrex) Levitate effect will no longer be removed in cases where you have two stacked lev spells and the first wears off. cavedude00: (seveianrex) Hate list will now be cleared following CoH -cavedude00: (seveianrex) Group members will now see tradeskill emotes. +cavedude00: (seveianrex) Group members will now see tradeskill emotes. Required SQL: ALTER TABLE `traps` DROP `spawnchance`; @@ -6737,7 +6739,7 @@ Derision: (Spoon/Andmetal) Rez spells with effectdescnum != 82 or 39067 (6.2 spe Derision: Corrected message when interrupting a spell with Shift-S. Derision: Fix to display Frogloks correctly in /who all and /who all froglok (half of the change came from a post by Theeper on the forums). -Required SQL: +Required SQL: ALTER TABLE `tasks` ADD `minlevel` TINYINT UNSIGNED NOT NULL DEFAULT '0', ADD `maxlevel` TINYINT UNSIGNED NOT NULL DEFAULT '0'; @@ -6793,7 +6795,7 @@ cavedude00: (AndMetal) Slippery Attacks AA cavedude00: (trevius/Derision) Additional IP limiting rules cavedude00: (Congdar) Further PC main and second hand attack fixes cavedude00: (Derision) Fix for percent heals -cavedude00: (Theeper) Fix for quest:itemlink() +cavedude00: (Theeper) Fix for quest:itemlink() cavedude00: (Rocker8956) More work on zone instancing Optional SQL: @@ -6950,7 +6952,7 @@ KLS: (irv0) Fix for out of order ack not being sent in some situations. KLS: (Derision) Pet bar OOC update fix. KLS: Should have made client pets unable to give experience, untested but should work. KLS: Healing aggro should function better for people not on the hate list. -KLS: Some work on public tradeskill objects saving their content between uses. +KLS: Some work on public tradeskill objects saving their content between uses. ==06/22/2008 KLS: Changed world/clientlist.cpp's line endings back to unix style line endings @@ -7025,7 +7027,7 @@ CREATE TABLE `hackers` ( `zone` text, `date` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, PRIMARY KEY (`id`) -) AUTO_INCREMENT=8; +) AUTO_INCREMENT=8; ==04/26/2008 KLS: Should have fixed discipline and combat ability timer overlap. @@ -7051,7 +7053,7 @@ Rogean: Fixed #hideme, it won't show you zone in and then disappear anymore. (Re Rogean: Fixed /summon. Rogean: Changes to /who all and GM's: * GM * Tags will no longer show up unless your #gm on - You will not show up to players of lower status if your /anon and #gm on, if your #gm off and /anon you will show up as + You will not show up to players of lower status if your /anon and #gm on, if your #gm off and /anon you will show up as a normal player, regardless of statuses. ==04/09/2008 @@ -7158,7 +7160,7 @@ KLS: Ironed out some quirks between min hit and the AC code that was keeping it KLS: (Knightly)#time should no longer be off by an hour, $zonehour, $zonemin and $zonetime are now exported to perl KLS: Added player quests, player quests are quests designed to be attached to player processes such as zoning and clicking objects. KLS: Player quests are loaded as either 'quests/zonename/player.pl' or as a template in 'quests/template/player.pl' -KLS: Player quests will export qglobals the client should be able to see and the following events are available for player quests: +KLS: Player quests will export qglobals the client should be able to see and the following events are available for player quests: EVENT_TIMER with var $timer EVENT_CLICKDOOR with var $doorid EVENT_LOOT with vars $looted_id and $looted_charges @@ -7286,7 +7288,7 @@ NPC:OOCRegen (Default: 0) KLS: Fixed logic on duration 7 formula.. again. ==12/02/2007 -KLS: Reworked buff duration formula 7 calculations. +KLS: Reworked buff duration formula 7 calculations. KLS: (Cripp)Added (Missing?) pathing z rules. ==11/30/2007 @@ -7400,7 +7402,7 @@ KLS: NPCs should now accept signals while engaged in combat. FatherNitwit: Quick fix for Divine Aura on pets exploit (KingMort) ==10/09/2007 -KLS: Tweaked my AC system a bit, should get less default defense and the system should be much more lienent overall, +KLS: Tweaked my AC system a bit, should get less default defense and the system should be much more lienent overall, goal is to allow people to see more of a benefit from having AC. ==09/24/2007 @@ -7412,7 +7414,7 @@ KLS: Small changes to the order in the getweapondamage code to make it a little KLS: Added a field that allows you to override a factions innate desire to assist their own faction in battle to the npc_faction table Required SQL: -alter table npc_faction add column ignore_primary_assist tinyint(3) not null default 0; +alter table npc_faction add column ignore_primary_assist tinyint(3) not null default 0; ==09/02/2007 KLS: Fixed an issue with items adding stats to NPCs exponentially. @@ -7431,7 +7433,7 @@ KLS: The error in acmod() should no longer complain as much. Required: Opcode files have changed, be sure to update to the latest .conf files. ==08/30/2007 -KLS: Reworked Mob::GetWeaponDamage(), it will now return damage done by any item and NULL and will return a +KLS: Reworked Mob::GetWeaponDamage(), it will now return damage done by any item and NULL and will return a value zero or less if we can't hit a mob with said item KLS: Applied new GetWeaponDamage() to Attack and Special Attack code KLS: Seperated Finishing Blow code to it's own function @@ -7601,8 +7603,8 @@ WildcardX: Area of effect beneficial spells will no longer affect non-player cha ==2/16/2007 KLS: Updating Changelog AA work to be more clear as well as the required SQL. -Required SQL: -alter table altadv_vars add column cost_inc tinyint(4) not null default 0; +Required SQL: +alter table altadv_vars add column cost_inc tinyint(4) not null default 0; Optionally: Source in AA_data.sql @@ -7817,7 +7819,7 @@ CREATE TABLE skill_caps ( ); ==11/07/2006 -KLS: Changed how critical hits work, as a result things that could not crit before like special attacks, now can. +KLS: Changed how critical hits work, as a result things that could not crit before like special attacks, now can. KLS: Cleave like effects should be fixed to do an increase of your already standing chance to critical instead of a flat increase. KLS: Reworked much of the special attack code. KLS: Applied haste to combat skill timers, they should give trouble much less often. @@ -7863,7 +7865,7 @@ FatherNitwit: Tweak for 64 bit pointer support in the item code of the struct st FatherNitwit: More const cleanup in npc.h ==10/22/2006 -FatherNitwit: added EVENT_COMBAT triggered when an NPC engages any form of +FatherNitwit: added EVENT_COMBAT triggered when an NPC engages any form of FatherNitwit: combat and when combat is over. $combat_state signals which. FatherNitwit: Hopefully fixed d_meele_texture FatherNitwit: Cleaned up a lot of const related issues (attrs, AAs, and more) @@ -8172,7 +8174,7 @@ FatherNitwit: Fixed countless rediculous things about guilds. FatherNitwit: Any change in guild state should update in real time now. FatherNitwit: Guild leadership may need re-establishing since it changed from account to char based. FatherNitwit: Guild structure in database has changed significantly. -Note: custom rank stuff is too much work for me to preserve in the DB, since I doubt +Note: custom rank stuff is too much work for me to preserve in the DB, since I doubt anybody uses it, so if you have them, you can figure it out yourself or remake them. Required SQL: ALTER TABLE character_ ADD class TINYINT NOT NULL DEFAULT 0; @@ -8515,7 +8517,7 @@ ALTER TABLE npc_types ADD AGI MEDIUMINT UNSIGNED NOT NULL DEFAULT '75'; ALTER TABLE npc_types ADD _INT MEDIUMINT UNSIGNED NOT NULL DEFAULT '75'; ALTER TABLE npc_types ADD WIS MEDIUMINT UNSIGNED NOT NULL DEFAULT '75'; ALTER TABLE npc_types ADD CHA MEDIUMINT UNSIGNED NOT NULL DEFAULT '75'; - + ==09/23/2005 FatherNitwit: Inverted XY coordinates on in zone objects and ground spawns. FatherNitwit: Maybe fixed quests setting a waypoint in EVENT_WAYPOINT @@ -8679,7 +8681,7 @@ Doodman: New item structure is in: Item fields now match the dump from (utils/load_13thfloor_items.pl) eqitems.13th-floor.org Item table convert script: utils/items-0.6.0-DR2-0.6.1-DR1-convert.sql - + ==01/10/2005 FatherNitwit: Disable sleep() in perl, it is bad news. FatherNitwit: Fixed guild MOTD at login (hopefully). @@ -8949,7 +8951,7 @@ WR Merges: - pets should actually taunt now. - rouge pets should backstab now. - optional: group buffs hit group pets now. -- fixed memory blur chances +- fixed memory blur chances - several minor group tweaks, should make groups more stable - improved duel messages - optional random luclin attributes for NPCs with boring faces @@ -9341,7 +9343,7 @@ kathgar: Fixed, SE_Fear, SE_SpinStun, SE_Charm for fixed duration spells and no Added member bool client to Buff_Struct to aid in above fix Fixed solar's changelog entry where he spelled my name wrong No EQLive fixes in this change -solar: fixed a bug that was causing people to be set as gm when they shouldn't +solar: fixed a bug that was causing people to be set as gm when they shouldn't ==2/15/2004 solar: characters being created are checked for validity now. thanks to @@ -9457,7 +9459,7 @@ solar: Buff fading should work for slots besides the first one now. This will solar: sense heading skill will now improve as you move around ==1/19/2004= -Scorpious2k: fixed faction command for quests +Scorpious2k: fixed faction command for quests LethalEncounter: Fixed a problem with queued cursor items. solar: fixes to #gassign @@ -9512,24 +9514,24 @@ LethalEncounter: Fixed loot messages. LethalEncounter: Fixed loot so right click autoequips correctly now. ==1/4/04== -MYRA: changed to new opcode for follow -MYRA: changed to new opcode for taunt -MYRA: use new (5.x) Status labels in who for telnet connection -MYRA: Added code to depop at end of grid for wander type 4 -MYRA: Added wander type 4 (single run) -MYRA: fixed eval in ExportVar per Eglin -MYRA: corrected spelling for var $uguildrank for event_timer (was $uguildrang) -MYRA: added vars $status & $cumflag per Eglin -MYRA: added vars $mobid & $mlevel per Eglin -MYRA: added missing commands + itemlink to perl -MYRA: added EVAL & KEEPERR to eval per Eglin's recommendation -MYRA: restore missing commands for qst type files & add itemlink -MYRA: fixed comma bug for me command -MYRA: fixed comma bug for echo command -MYRA: fixed comma bug for say command -MYRA: fixed comma bug for emote command -MYRA: fixed comma bug for shout command -MYRA: added itemlink(ItemNumber) command +MYRA: changed to new opcode for follow +MYRA: changed to new opcode for taunt +MYRA: use new (5.x) Status labels in who for telnet connection +MYRA: Added code to depop at end of grid for wander type 4 +MYRA: Added wander type 4 (single run) +MYRA: fixed eval in ExportVar per Eglin +MYRA: corrected spelling for var $uguildrank for event_timer (was $uguildrang) +MYRA: added vars $status & $cumflag per Eglin +MYRA: added vars $mobid & $mlevel per Eglin +MYRA: added missing commands + itemlink to perl +MYRA: added EVAL & KEEPERR to eval per Eglin's recommendation +MYRA: restore missing commands for qst type files & add itemlink +MYRA: fixed comma bug for me command +MYRA: fixed comma bug for echo command +MYRA: fixed comma bug for say command +MYRA: fixed comma bug for emote command +MYRA: fixed comma bug for shout command +MYRA: added itemlink(ItemNumber) command ==1/2/04== @@ -9678,7 +9680,7 @@ solar: HP wasn't being updated to client properly and would fall out of sync LethalEncounter: Fixed a bug in doors that would cause triggered doors to go into an endless loop and crash. ==11/13/03== -kathgar: Fixed a crash when calling ZSList::FindByZoneID() when sending an invalid zone number. +kathgar: Fixed a crash when calling ZSList::FindByZoneID() when sending an invalid zone number. Stack was corrupt in the backtrace, so I am not sure what called it in this way. LethalEncounter: Fixed animation bug with attack. LethalEncounter: Fixed Tradeskills (again) @@ -9712,7 +9714,7 @@ IsEngaged(), so it always returned false, now it uses AutoAttackEnabled() in its Image: Reversed the AICheckCloseSpells if statements, now sanity checks before distance check, uses less CPU usage. ==11/05/03== -LethalEncounter: Updated all of the opcodes that were changed in the patch today. +LethalEncounter: Updated all of the opcodes that were changed in the patch today. LethalEncounter: Refined AA's some, added table to hold the timers for AA's so users can exploit them. Look in db.sql for the table. diff --git a/zone/aa.cpp b/zone/aa.cpp index 3718e3391..e81345086 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1104,7 +1104,7 @@ void Client::SendAATable() { uint32 i; for(i=0;i < MAX_PP_AA_ARRAY;i++){ - aa2->aa_list[i].AA = aa[i]->AA; + aa2->aa_list[i].AA = aa[i]->value ? aa[i]->AA : 0; // bit of a hack to prevent expendables punching a hole aa2->aa_list[i].value = aa[i]->value; aa2->aa_list[i].charges = aa[i]->charges; } @@ -1402,8 +1402,6 @@ bool Client::SetAA(uint32 aa_id, uint32 new_value) { aa[cur]->value = new_value; if(new_value > 0) aa[cur]->AA++; - else - aa[cur]->AA = 0; aa[cur]->charges = charges; return true; } @@ -1411,8 +1409,12 @@ bool Client::SetAA(uint32 aa_id, uint32 new_value) { aa[cur]->value = new_value; if(new_value > 0) aa[cur]->AA++; - else - aa[cur]->AA = 0; + aa[cur]->charges = charges; + return true; + } + // hack to prevent expendable exploit, we should probably be reshuffling the array to fix the hole + else if(aa[cur]->value == 0 && new_value == 1 && aa[cur]->AA == aa_id) { + aa[cur]->value = new_value; aa[cur]->charges = charges; return true; } diff --git a/zone/client.cpp b/zone/client.cpp index f7e160851..ef41578ef 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -549,17 +549,22 @@ bool Client::SaveAA(){ } } m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; + int highest = 0; for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" " VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); first_entry = 1; + } else { + rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); } - rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); + highest = a; } } auto results = database.QueryDatabase(rquery); + /* This is another part of the hack to clean up holes left by expendable AAs */ + rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` >= %d", character_id, highest); return true; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index b9ac81d89..5603023e5 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1452,11 +1452,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) "`character_alternate_abilities` " "WHERE `id` = %u ORDER BY `slot`", this->CharacterID()); results = database.QueryDatabase(query); i = 0; + int offset = 0; // offset to fix the hole from expendables for (auto row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]); + i = atoi(row[0]) - offset; m_pp.aa_array[i].AA = atoi(row[1]); m_pp.aa_array[i].value = atoi(row[2]); m_pp.aa_array[i].charges = atoi(row[3]); + /* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use. + We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load! + Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable + and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple + entries for a single AA. + */ + if (m_pp.aa_array[i].value == 0) + offset++; } for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ uint32 id = aa[a]->AA; From 226bb4f3b2dc87bea704d1d47507f61f2ab0c4fc Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 8 Jun 2015 02:08:32 -0400 Subject: [PATCH 159/846] Fix delete statement --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index ef41578ef..53d39ea7b 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -564,7 +564,7 @@ bool Client::SaveAA(){ } auto results = database.QueryDatabase(rquery); /* This is another part of the hack to clean up holes left by expendable AAs */ - rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` >= %d", character_id, highest); + rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest); return true; } From 3ee1c43ac401a612c9dae5f6b2d1bdc38f5dc0bc Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 8 Jun 2015 09:53:21 -0700 Subject: [PATCH 160/846] Remove old aa list send for experiment also want to merge from master... --- common/eq_packet_structs.h | 45 ++++++++++++++++++++++++++++++++++++++ zone/aa.cpp | 8 +++---- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index e5ab88e57..adfa3d9ee 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4218,6 +4218,51 @@ struct UseAA_Struct { uint32 end; }; +//new AA stuff + +struct AARankInfo_Struct +{ + uint32 id; + int32 upper_hotkey_sid; + int32 lower_hotkey_sid; + int32 title_sid; + int32 desc_sid; + int32 level_req; + int32 cost; + uint32 seq; + uint32 current_level; + uint32 type; + int32 spell; + int32 spell_type; + int32 spell_refresh; + int32 classes; + int32 max_level; + int32 prev_id; + int32 next_id; + int32 total_cost; + int32 expansion; + int32 category; + uint8 expendable; + uint32 total_effects; + uint32 total_prereqs; +}; + +struct AARankPrereq_Struct +{ + int32 aa_id; + int32 points; +}; + +struct AARankEffect_Struct +{ + int32 effect_id; + int32 base1; + int32 base2; + int32 slot; +}; + +//old AA stuff + struct AA_Ability { /*00*/ uint32 skill_id; /*04*/ uint32 base1; diff --git a/zone/aa.cpp b/zone/aa.cpp index c98e31372..1a8b5f5c5 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1377,10 +1377,10 @@ void Client::SendAA(uint32 id, int seq) { } void Client::SendAAList(){ - int total = zone->GetTotalAAs(); - for(int i=0;i < total;i++){ - SendAA(0,i); - } +// int total = zone->GetTotalAAs(); +// for(int i=0;i < total;i++){ +// SendAA(0,i); +// } } uint32 Client::GetAA(uint32 aa_id) const { From 5186d3a2eff3a6f8f4bc05097c41469e5dbdc718 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 8 Jun 2015 18:04:08 -0400 Subject: [PATCH 161/846] Make filtering out OP_ClientUpdate less aggressive to fix spinning toons If we are too aggressive filtering out the same position packets it's possible for toons to continue to spin indefinitely. Instead of just not sending the update when the position is the same we keep a tally of how many we get and stop once a threshold (6) is reached. --- zone/client.cpp | 1 + zone/client.h | 3 +++ zone/client_packet.cpp | 13 ++++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 53d39ea7b..e4d49e979 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -208,6 +208,7 @@ Client::Client(EQStreamInterface* ieqs) npclevel = 0; pQueuedSaveWorkID = 0; position_timer_counter = 0; + position_update_same_count = 0; fishing_timer.Disable(); shield_timer.Disable(); dead_timer.Disable(); diff --git a/zone/client.h b/zone/client.h index de093990c..4a166feed 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1447,6 +1447,9 @@ private: Timer position_timer; uint8 position_timer_counter; + // this is used to try to cut back on position update reflections + int position_update_same_count; + PTimerList p_timers; //persistent timers Timer hpupdate_timer; Timer camp_timer; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5603023e5..2ae2babac 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4457,9 +4457,20 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) // Outgoing client packet float tmpheading = EQ19toFloat(ppu->heading); + /* The clients send an update at best every 1.3 seconds + * We want to avoid reflecting these updates to other clients as much as possible + * The client also sends an update every 280 ms while turning, if we prevent + * sending these by checking if the location is the same too aggressively, clients end up spinning + * so keep a count of how many packets are the same within a tolerance and stop when we get there */ - if (!FCMP(ppu->y_pos, m_Position.y) || !FCMP(ppu->x_pos, m_Position.x) || !FCMP(tmpheading, m_Position.w) || ppu->animation != animation) + bool pos_same = FCMP(ppu->y_pos, m_Position.y) && FCMP(ppu->x_pos, m_Position.x) && FCMP(tmpheading, m_Position.w) && ppu->animation == animation; + if (!pos_same || (pos_same && position_update_same_count < 6)) { + if (pos_same) + position_update_same_count++; + else + position_update_same_count = 0; + m_Position.x = ppu->x_pos; m_Position.y = ppu->y_pos; m_Position.z = ppu->z_pos; From 250d0cc9036475d1622893c27321f649b443c69e Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 8 Jun 2015 20:06:14 -0700 Subject: [PATCH 162/846] More aa work, it actually loads yay --- common/eq_packet_structs.h | 3 +- common/patches/uf.cpp | 71 +++++++- common/patches/uf_structs.h | 3 +- zone/CMakeLists.txt | 1 + zone/aa.cpp | 315 +++++++++++++++++++++++++++++++++--- zone/aa_ability.cpp | 69 ++++++++ zone/aa_ability.h | 15 +- zone/aa_rank.h | 12 +- zone/client.h | 6 +- zone/client_packet.cpp | 7 +- zone/zone.h | 5 + 11 files changed, 469 insertions(+), 38 deletions(-) create mode 100644 zone/aa_ability.cpp diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index da965f4ba..d2d9ae8b3 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4220,7 +4220,7 @@ struct UseAA_Struct { }; //new AA stuff - +//reference only struct AARankInfo_Struct { uint32 id; @@ -4244,6 +4244,7 @@ struct AARankInfo_Struct int32 expansion; int32 category; uint8 expendable; + uint8 grant_only; uint32 total_effects; uint32 total_prereqs; }; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index deedcec5f..bbe0c0f0d 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1804,11 +1804,11 @@ namespace UF // OUT(unknown00224[48]); //NOTE: new client supports 300 AAs, our internal rep/PP //only supports 240.. - for (r = 0; r < MAX_PP_AA_ARRAY; r++) { - OUT(aa_array[r].AA); - OUT(aa_array[r].value); - OUT(aa_array[r].charges); - } + //for (r = 0; r < MAX_PP_AA_ARRAY; r++) { + // OUT(aa_array[r].AA); + // OUT(aa_array[r].value); + // OUT(aa_array[r].charges); + //} // OUT(unknown02220[4]); OUT(mana); OUT(cur_hp); @@ -2145,13 +2145,66 @@ namespace UF ENCODE(OP_SendAATable) { +#if 1 + EQApplicationPacket *inapp = *p; + *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)); + structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer; + + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + outapp->SetWritePosition(sizeof(structs::SendAA_Struct)); + + eq->id = emu->id; + eq->unknown004 = 1; + eq->id = emu->id; + eq->hotkey_sid = emu->upper_hotkey_sid; + eq->hotkey_sid2 = emu->lower_hotkey_sid; + eq->desc_sid = emu->desc_sid; + eq->title_sid = emu->title_sid; + eq->class_type = emu->level_req; + eq->cost = emu->cost; + eq->seq = emu->seq; + eq->current_level = emu->current_level; + eq->type = emu->type; + eq->spellid = emu->spell; + eq->spell_type = emu->spell_type; + eq->spell_refresh = emu->spell_refresh; + eq->classes = emu->classes; + eq->max_level = emu->max_level; + eq->last_id = emu->prev_id; + eq->next_id = emu->next_id; + eq->cost2 = emu->total_cost; + eq->grant_only = emu->grant_only > 0 ? true : false; + eq->expendable_charges = emu->expendable ? 1 : 0; + eq->aa_expansion = emu->expansion; + eq->special_category = emu->category; + eq->total_abilities = emu->total_effects; + + for(auto i = 0; i < eq->total_abilities; ++i) { + eq->abilities[i].skill_id = inapp->ReadUInt32(); + eq->abilities[i].base1 = inapp->ReadUInt32(); + eq->abilities[i].base2 = inapp->ReadUInt32(); + eq->abilities[i].slot = inapp->ReadUInt32(); + } + + if(emu->total_prereqs > 0) { + eq->prereq_skill = -(int)inapp->ReadUInt32(); + eq->prereq_minpoints = inapp->ReadUInt32(); + } + + Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); + dest->FastQueuePacket(&outapp); + delete inapp; +#else ENCODE_LENGTH_ATLEAST(SendAA_Struct); SETUP_VAR_ENCODE(SendAA_Struct); ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); // Check clientver field to verify this AA should be sent for SoF // clientver 1 is for all clients and 6 is for Underfoot - if (emu->clientver <= 6) + if(emu->clientver <= 6) { OUT(id); eq->unknown004 = 1; @@ -2174,7 +2227,7 @@ namespace UF OUT(spell_type); OUT(spell_refresh); OUT(classes); - OUT(berserker); + //OUT(berserker); //eq->max_level = emu->sof_max_level; OUT(max_level); OUT(last_id); @@ -2185,7 +2238,7 @@ namespace UF eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number OUT(total_abilities); unsigned int r; - for (r = 0; r < emu->total_abilities; r++) { + for(r = 0; r < emu->total_abilities; r++) { OUT(abilities[r].skill_id); OUT(abilities[r].base1); OUT(abilities[r].base2); @@ -2193,7 +2246,9 @@ namespace UF } } + Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(__packet).c_str()); FINISH_ENCODE(); +#endif } ENCODE(OP_SendCharInfo) diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index c943c6ea5..36d6dea74 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -3886,8 +3886,7 @@ struct SendAA_Struct { /*0049*/ uint32 spellid; /*0053*/ uint32 spell_type; /*0057*/ uint32 spell_refresh; -/*0061*/ uint16 classes; -/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability +/*0061*/ uint32 classes; /*0065*/ uint32 max_level; /*0069*/ uint32 last_id; /*0073*/ uint32 next_id; diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index a68945155..ba9aa8620 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -2,6 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(zone_sources aa.cpp + aa_ability.cpp aggro.cpp attack.cpp beacon.cpp diff --git a/zone/aa.cpp b/zone/aa.cpp index edca1ebdb..88e2a2e56 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1097,22 +1097,24 @@ void Client::SendAATimers() { } void Client::SendAATable() { + Log.Out(Logs::General, Logs::Status, "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 = aa[i]->value ? aa[i]->AA : 0; // bit of a hack to prevent expendables punching a hole - aa2->aa_list[i].value = aa[i]->value; - aa2->aa_list[i].charges = aa[i]->charges; - } + //aa2->aa_spent = GetAAPointsSpent(); + // + //uint32 i; + //for(i=0;i < MAX_PP_AA_ARRAY;i++){ + // aa2->aa_list[i].AA = aa[i]->value ? aa[i]->AA : 0; // bit of a hack to prevent expendables punching a hole + // aa2->aa_list[i].value = aa[i]->value; + // aa2->aa_list[i].charges = aa[i]->charges; + //} QueuePacket(outapp); safe_delete(outapp); } void Client::SendPreviousAA(uint32 id, int seq){ + Log.Out(Logs::General, Logs::Status, "SendPreviousAA(%u, %i)", id, seq); uint32 value=0; SendAA_Struct* saa2 = nullptr; if(id==0) @@ -1148,11 +1150,13 @@ void Client::SendPreviousAA(uint32 id, int seq){ } database.FillAAEffects(saa); + Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); QueuePacket(outapp); safe_delete(outapp); } void Client::SendAA(uint32 id, int seq) { + Log.Out(Logs::General, Logs::Status, "SendAA(%u, %i)", id, seq); uint32 value=0; SendAA_Struct* saa2 = nullptr; @@ -1368,6 +1372,7 @@ void Client::SendAA(uint32 id, int seq) { 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); @@ -1377,10 +1382,13 @@ void Client::SendAA(uint32 id, int seq) { } void Client::SendAAList(){ -// int total = zone->GetTotalAAs(); -// for(int i=0;i < total;i++){ -// SendAA(0,i); -// } + Log.Out(Logs::General, Logs::Status, "SendAAList()"); + int total = zone->GetTotalAAs(); + + total = total > 2 ? 2 : total; + for(int i=0;i < total;i++){ + SendAA(0,i); + } } uint32 Client::GetAA(uint32 aa_id) const { @@ -2080,39 +2088,300 @@ Mob *AA_SwarmPetInfo::GetOwner() return entity_list.GetMobID(owner_id); } +void Client::SendAlternateAdvancementList() { + for(auto &aa : zone->aa_abilities) { + SendAlternateAdvancement(aa.first, true); + } +} + //New AA +void Client::SendAlternateAdvancement(int aa_id, bool first_login) { + if(!zone) + return; + + AA::Ability *ability = zone->GetAlternateAdvancementAbility(aa_id); + + if(!ability) + return; + + if(!(ability->classes & (1 << GetClass()))) { + return; + } + + if(ability->account_time_required) { + if((Timer::GetTimeSeconds() - account_creation) < ability->account_time_required) + { + return; + } + } + + // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). + if(ability->category == 1 || ability->category == 2) { + //if(GetAA(saa2->id) == 0) + // return; + + if(ability->expansion > 0) { + AA::Ability *qaa = zone->GetAlternateAdvancementAbility(aa_id + 1); + //if(qaa && qaa->expansion == ability->expansion && GetAA(aa_id) > 0) { + // return; + //} + } + } + + // Passive and Active Shroud AAs + // For now we skip them + if(ability->category == 3 || ability->category == 4) { + return; + } + + // Check for racial/Drakkin blood line AAs + if(ability->category == 8) + { + uint32 client_race = GetBaseRace(); + + // Drakkin Bloodlines + if(ability->expansion > 522) + { + if(client_race != 522) + return; + + int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline + + if(heritage != ability->expansion) + return; + } + else if(client_race != ability->expansion) + { + return; + } + } + + //Send first rank + AA::Rank *rank = ability->first; + if(!rank) + return; + + //Should move this to another function + int size = sizeof(AARankInfo_Struct)+(sizeof(AARankEffect_Struct)* rank->effects.size()) + (sizeof(AARankPrereq_Struct)* rank->prereqs.size()); + EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size); + AARankInfo_Struct *aai = (AARankInfo_Struct*)outapp->pBuffer; + + aai->id = rank->id; + aai->upper_hotkey_sid = rank->upper_hotkey_sid; + aai->lower_hotkey_sid = rank->lower_hotkey_sid; + aai->title_sid = rank->title_sid; + aai->desc_sid = rank->desc_sid; + aai->level_req = rank->level_req; + aai->cost = rank->cost; + aai->seq = aa_id; + aai->current_level = 1; + aai->type = ability->type; + aai->spell = rank->spell; + aai->spell_type = rank->spell_type; + aai->spell_refresh = rank->recast_time; + aai->classes = ability->classes; + aai->max_level = ability->GetMaxLevel(); + aai->prev_id = rank->prev_id; + aai->next_id = rank->next_id; + aai->total_cost = rank->total_cost; + aai->expansion = ability->expansion; + aai->category = ability->category; + aai->expendable = ability->expendable; + aai->grant_only = ability->grant_only; + aai->total_effects = rank->effects.size(); + aai->total_prereqs = rank->prereqs.size(); + + outapp->SetWritePosition(sizeof(AARankInfo_Struct)); + for(auto effect : rank->effects) { + outapp->WriteSInt32(effect.second.effect_id); + outapp->WriteSInt32(effect.second.base1); + outapp->WriteSInt32(effect.second.base2); + outapp->WriteSInt32(effect.first); + } + + for(auto prereq : rank->prereqs) { + outapp->WriteSInt32(prereq.aa_id); + outapp->WriteSInt32(prereq.points); + } + + //if first_login then also send current rank if not maxed + + QueuePacket(outapp); + safe_delete(outapp); + + // + //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); + // + // // this check should work as long as we continue to just add the clients and just increase + // // each number .... + // if(saa_next && static_cast(GetClientVersion()) < saa_next->clientver - 1) { + // 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 Zone::LoadAlternateAdvancement() { Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Data..."); - if(!database.LoadAlternateAdvancementAbilities(zone->aa_abilities, - zone->aa_ranks)) + if(!database.LoadAlternateAdvancementAbilities(aa_abilities, + aa_ranks)) { - zone->aa_abilities.clear(); - zone->aa_ranks.clear(); + aa_abilities.clear(); + aa_ranks.clear(); Log.Out(Logs::General, Logs::Status, "Failed to load Alternate Advancement Data"); return; } + Log.Out(Logs::General, Logs::Status, "Processing Alternate Advancement Data..."); + for(const auto &ability : aa_abilities) { + ability.second->first = GetAlternateAdvancementRank(ability.second->first_rank_id); + + //process these ranks + AA::Rank *current = ability.second->first; + while(current) { + current->prev = GetAlternateAdvancementRank(current->prev_id); + current->next = GetAlternateAdvancementRank(current->next_id); + current->base_ability = ability.second.get(); + + if(current->prev) { + current->total_cost = current->cost + current->prev->total_cost; + } else { + current->total_cost = current->cost; + } + + current = current->next; + } + + ability.second->GetMaxLevel(true); + } + Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Data"); } +AA::Ability *Zone::GetAlternateAdvancementAbility(int id) { + auto iter = aa_abilities.find(id); + if(iter != aa_abilities.end()) { + return iter->second.get(); + } + + return nullptr; +} + +AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) { + auto iter = aa_ranks.find(rank_id); + if(iter != aa_ranks.end()) { + return iter->second.get(); + } + + return nullptr; +} + bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, std::unordered_map> &ranks) { Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Abilities..."); abilities.clear(); - std::string query = "SELECT id, name, expansion, category, classes, expendable, first_rank_id FROM aa_ability"; + std::string query = "SELECT id, name, expansion, category, classes, type, expendable, account_time_required, grant_only, first_rank_id FROM aa_ability"; auto results = QueryDatabase(query); if(results.Success()) { for(auto row = results.begin(); row != results.end(); ++row) { AA::Ability *ability = new AA::Ability; int id = atoi(row[0]); - ability->name = row[1]; ability->expansion = atoi(row[2]); ability->category = atoi(row[3]); ability->classes = atoi(row[4]); - ability->expendable = atoi(row[5]) != 0 ? true : false; - ability->first_rank_id = atoi(row[6]); + ability->type = atoi(row[5]); + ability->expendable = atoi(row[6]) != 0 ? true : false; + ability->account_time_required = atoul(row[7]); + ability->grant_only = atoi(row[8]) != 0 ? true : false; + ability->first_rank_id = atoi(row[9]); + ability->first = nullptr; abilities[id] = std::unique_ptr(ability); } @@ -2132,6 +2401,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = id; rank->upper_hotkey_sid = atoi(row[1]); rank->lower_hotkey_sid = atoi(row[2]); rank->title_sid = atoi(row[3]); @@ -2143,6 +2413,10 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_maprecast_time = atoi(row[9]); rank->prev_id = atoi(row[10]); rank->next_id = atoi(row[11]); + rank->base_ability = nullptr; + rank->total_cost = 0; + rank->next = nullptr; + rank->prev = nullptr; ranks[id] = std::unique_ptr(rank); } @@ -2204,4 +2478,3 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapnext) { + current = current->next; + } + + return current; +} + +AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) { + if(!first) + return nullptr; + + if(current_level == 0) { + return GetMaxRank(); + } + + int i = 1; + Rank *current = first; + while(current->next) { + if(1 == current_level) { + break; + } + + i++; + current = current->next; + } + + return current; +} + +int AA::Ability::GetMaxLevel(bool force_calc) { + if(!force_calc) + return max_level; + + max_level = 0; + Rank *current = first; + while(current) { + max_level++; + current = current->next; + } + + return max_level; +} \ No newline at end of file diff --git a/zone/aa_ability.h b/zone/aa_ability.h index bb9148689..b2098c408 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -30,14 +30,27 @@ namespace AA { -struct Ability +class Ability { +public: + Ability() { } + ~Ability() { } + + Rank *GetMaxRank(); + Rank *GetRankByPointsSpent(int current_level); + int GetMaxLevel(bool force_calc = false); + std::string name; int expansion; int category; int classes; + uint32 account_time_required; + bool grant_only; + int type; bool expendable; int first_rank_id; + int max_level; + Rank *first; }; } diff --git a/zone/aa_rank.h b/zone/aa_rank.h index ec1cc4115..43b6ef635 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -22,8 +22,14 @@ namespace AA { -struct Rank +class Ability; +class Rank { +public: + Rank() { } + ~Rank() { } + + int id; int upper_hotkey_sid; int lower_hotkey_sid; int title_sid; @@ -34,7 +40,11 @@ struct Rank int spell_type; int recast_time; int prev_id; + Rank *prev; int next_id; + Rank *next; + int total_cost; + Ability *base_ability; std::unordered_map effects; std::vector prereqs; }; diff --git a/zone/client.h b/zone/client.h index de093990c..7bc4aac1e 100644 --- a/zone/client.h +++ b/zone/client.h @@ -759,7 +759,11 @@ public: inline PTimerList &GetPTimers() { return(p_timers); } - //AA Methods + //New AA Methods + void SendAlternateAdvancement(int aa_id, bool first_login = false); + void SendAlternateAdvancementList(); + + //old AA Methods void SendAAList(); void ResetAA(); void SendClearAA(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index df8ef8f12..bfe96fdb3 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1091,8 +1091,10 @@ void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app) void Client::Handle_Connect_OP_SendAATable(const EQApplicationPacket *app) { - Log.Out(Logs::General, Logs::Error, "SendAAList()"); - SendAAList(); + //SendAAList(); + + SendAlternateAdvancementList(); + return; } @@ -1153,7 +1155,6 @@ void Client::Handle_Connect_OP_TGB(const EQApplicationPacket *app) void Client::Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app) { - Log.Out(Logs::General, Logs::Error, "SendAATable()"); SendAATable(); } diff --git a/zone/zone.h b/zone/zone.h index 274a1a021..fbe1b48d1 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -116,6 +116,8 @@ public: //new AA void LoadAlternateAdvancement(); + AA::Ability *GetAlternateAdvancementAbility(int id); + AA::Rank *GetAlternateAdvancementRank(int rank_id); //old AA void LoadAAs(); @@ -319,10 +321,13 @@ private: int totalBS; ZoneSpellsBlocked *blocked_spells; +public: //new AA std::unordered_map> aa_abilities; std::unordered_map> aa_ranks; +private: + //old AA int totalAAs; SendAA_Struct **aas; //array of AA structs From dbbe6b5a91155e55ebbbcfdc597dc0debe4a399d Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 9 Jun 2015 12:39:39 -0700 Subject: [PATCH 163/846] Experimenting with packets --- common/eq_packet_structs.h | 2 +- common/patches/uf.cpp | 2 +- zone/aa.cpp | 168 +++++++++---------------------------- zone/aa_ability.cpp | 9 +- zone/aa_ability.h | 5 +- zone/aa_rank.h | 2 + zone/client.h | 2 +- zone/client_packet.cpp | 3 - zone/command.cpp | 14 ++-- 9 files changed, 59 insertions(+), 148 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index d2d9ae8b3..0c4335016 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4243,7 +4243,7 @@ struct AARankInfo_Struct int32 total_cost; int32 expansion; int32 category; - uint8 expendable; + uint8 charges; uint8 grant_only; uint32 total_effects; uint32 total_prereqs; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index bbe0c0f0d..caea6b933 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2177,7 +2177,7 @@ namespace UF eq->next_id = emu->next_id; eq->cost2 = emu->total_cost; eq->grant_only = emu->grant_only > 0 ? true : false; - eq->expendable_charges = emu->expendable ? 1 : 0; + eq->expendable_charges = emu->charges ? 1 : 0; eq->aa_expansion = emu->expansion; eq->special_category = emu->category; eq->total_abilities = emu->total_effects; diff --git a/zone/aa.cpp b/zone/aa.cpp index 88e2a2e56..57f6df675 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1101,6 +1101,14 @@ void Client::SendAATable() { EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; + aa2->aa_spent = 8; + //aa2->aa_list[0].AA = 11; + //aa2->aa_list[0].value = 4; + //aa2->aa_list[0].charges = 0; + //aa2->aa_list[1].AA = 202; + //aa2->aa_list[1].value = 4; + //aa2->aa_list[1].charges = 0; + //aa2->aa_spent = GetAAPointsSpent(); // //uint32 i; @@ -2089,13 +2097,16 @@ Mob *AA_SwarmPetInfo::GetOwner() } void Client::SendAlternateAdvancementList() { - for(auto &aa : zone->aa_abilities) { - SendAlternateAdvancement(aa.first, true); - } + //for(auto &aa : zone->aa_abilities) { + // SendAlternateAdvancement(aa.first, 5); + //} + + SendAlternateAdvancement(1, 4); + SendAlternateAdvancement(2, 4); } //New AA -void Client::SendAlternateAdvancement(int aa_id, bool first_login) { +void Client::SendAlternateAdvancement(int aa_id, int level) { if(!zone) return; @@ -2108,8 +2119,12 @@ void Client::SendAlternateAdvancement(int aa_id, bool first_login) { return; } - if(ability->account_time_required) { - if((Timer::GetTimeSeconds() - account_creation) < ability->account_time_required) + AA::Rank *rank = ability->GetRankByPointsSpent(level + 1); + if(!rank) + return; + + if(rank->account_time_required) { + if((Timer::GetTimeSeconds() - account_creation) < rank->account_time_required) { return; } @@ -2120,9 +2135,9 @@ void Client::SendAlternateAdvancement(int aa_id, bool first_login) { //if(GetAA(saa2->id) == 0) // return; - if(ability->expansion > 0) { + if(rank->expansion > 0) { AA::Ability *qaa = zone->GetAlternateAdvancementAbility(aa_id + 1); - //if(qaa && qaa->expansion == ability->expansion && GetAA(aa_id) > 0) { + //if(qaa && qaa->expansion == rank->expansion && GetAA(aa_id) > 0) { // return; //} } @@ -2140,33 +2155,28 @@ void Client::SendAlternateAdvancement(int aa_id, bool first_login) { uint32 client_race = GetBaseRace(); // Drakkin Bloodlines - if(ability->expansion > 522) + if(rank->expansion > 522) { if(client_race != 522) return; int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - if(heritage != ability->expansion) + if(heritage != rank->expansion) return; } - else if(client_race != ability->expansion) + else if(client_race != rank->expansion) { return; } } - - //Send first rank - AA::Rank *rank = ability->first; - if(!rank) - return; //Should move this to another function int size = sizeof(AARankInfo_Struct)+(sizeof(AARankEffect_Struct)* rank->effects.size()) + (sizeof(AARankPrereq_Struct)* rank->prereqs.size()); EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size); AARankInfo_Struct *aai = (AARankInfo_Struct*)outapp->pBuffer; - aai->id = rank->id; + aai->id = ability->GetMaxRank()->id; aai->upper_hotkey_sid = rank->upper_hotkey_sid; aai->lower_hotkey_sid = rank->lower_hotkey_sid; aai->title_sid = rank->title_sid; @@ -2174,7 +2184,7 @@ void Client::SendAlternateAdvancement(int aa_id, bool first_login) { aai->level_req = rank->level_req; aai->cost = rank->cost; aai->seq = aa_id; - aai->current_level = 1; + aai->current_level = level + 1; aai->type = ability->type; aai->spell = rank->spell; aai->spell_type = rank->spell_type; @@ -2184,9 +2194,9 @@ void Client::SendAlternateAdvancement(int aa_id, bool first_login) { aai->prev_id = rank->prev_id; aai->next_id = rank->next_id; aai->total_cost = rank->total_cost; - aai->expansion = ability->expansion; + aai->expansion = rank->expansion; aai->category = ability->category; - aai->expendable = ability->expendable; + aai->charges = ability->charges; aai->grant_only = ability->grant_only; aai->total_effects = rank->effects.size(); aai->total_prereqs = rank->prereqs.size(); @@ -2204,106 +2214,8 @@ void Client::SendAlternateAdvancement(int aa_id, bool first_login) { outapp->WriteSInt32(prereq.points); } - //if first_login then also send current rank if not maxed - QueuePacket(outapp); safe_delete(outapp); - - // - //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); - // - // // this check should work as long as we continue to just add the clients and just increase - // // each number .... - // if(saa_next && static_cast(GetClientVersion()) < saa_next->clientver - 1) { - // 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 Zone::LoadAlternateAdvancement() { @@ -2366,21 +2278,19 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapname = row[1]; - ability->expansion = atoi(row[2]); - ability->category = atoi(row[3]); - ability->classes = atoi(row[4]); - ability->type = atoi(row[5]); - ability->expendable = atoi(row[6]) != 0 ? true : false; - ability->account_time_required = atoul(row[7]); - ability->grant_only = atoi(row[8]) != 0 ? true : false; - ability->first_rank_id = atoi(row[9]); + ability->category = atoi(row[2]); + ability->classes = atoi(row[3]); + ability->type = atoi(row[4]); + ability->charges = atoi(row[5]); + ability->grant_only = atoi(row[6]) != 0 ? true : false; + ability->first_rank_id = atoi(row[7]); ability->first = nullptr; abilities[id] = std::unique_ptr(ability); @@ -2395,7 +2305,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_maprecast_time = atoi(row[9]); rank->prev_id = atoi(row[10]); rank->next_id = atoi(row[11]); + rank->expansion = atoi(row[12]); + rank->account_time_required = atoul(row[13]); rank->base_ability = nullptr; rank->total_cost = 0; rank->next = nullptr; diff --git a/zone/aa_ability.cpp b/zone/aa_ability.cpp index 3cc14826a..8f9cb8da4 100644 --- a/zone/aa_ability.cpp +++ b/zone/aa_ability.cpp @@ -33,17 +33,16 @@ AA::Rank *AA::Ability::GetMaxRank() { } AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) { + if(current_level == 0) + return nullptr; + if(!first) return nullptr; - if(current_level == 0) { - return GetMaxRank(); - } - int i = 1; Rank *current = first; while(current->next) { - if(1 == current_level) { + if(i == current_level) { break; } diff --git a/zone/aa_ability.h b/zone/aa_ability.h index b2098c408..d1ef49105 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -37,17 +37,16 @@ public: ~Ability() { } Rank *GetMaxRank(); + Rank *GetRankByLevel(int level); Rank *GetRankByPointsSpent(int current_level); int GetMaxLevel(bool force_calc = false); std::string name; - int expansion; int category; int classes; - uint32 account_time_required; bool grant_only; int type; - bool expendable; + int charges; int first_rank_id; int max_level; Rank *first; diff --git a/zone/aa_rank.h b/zone/aa_rank.h index 43b6ef635..d35582834 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -43,6 +43,8 @@ public: Rank *prev; int next_id; Rank *next; + int expansion; + uint32 account_time_required; int total_cost; Ability *base_ability; std::unordered_map effects; diff --git a/zone/client.h b/zone/client.h index 7bc4aac1e..71fc219fb 100644 --- a/zone/client.h +++ b/zone/client.h @@ -760,7 +760,7 @@ public: inline PTimerList &GetPTimers() { return(p_timers); } //New AA Methods - void SendAlternateAdvancement(int aa_id, bool first_login = false); + void SendAlternateAdvancement(int aa_id, int level); void SendAlternateAdvancementList(); //old AA Methods diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index bfe96fdb3..77431ecd9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1091,10 +1091,7 @@ void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app) void Client::Handle_Connect_OP_SendAATable(const EQApplicationPacket *app) { - //SendAAList(); - SendAlternateAdvancementList(); - return; } diff --git a/zone/command.cpp b/zone/command.cpp index a286f92bd..3210ba070 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -674,12 +674,14 @@ void command_incstat(Client* c, const Seperator* sep){ } void command_resetaa(Client* c,const Seperator *sep){ - if(c->GetTarget()!=0 && c->GetTarget()->IsClient()){ - c->GetTarget()->CastToClient()->ResetAA(); - c->Message(13,"Successfully reset %s's AAs", c->GetTarget()->GetName()); - } - else - c->Message(0,"Usage: Target a client and use #resetaa to reset the AA data in their Profile."); + c->SendAlternateAdvancement(1, 1); + c->SendAlternateAdvancement(2, 1); + //if(c->GetTarget()!=0 && c->GetTarget()->IsClient()){ + // c->GetTarget()->CastToClient()->ResetAA(); + // c->Message(13,"Successfully reset %s's AAs", c->GetTarget()->GetName()); + //} + //else + // c->Message(0,"Usage: Target a client and use #resetaa to reset the AA data in their Profile."); } void command_help(Client *c, const Seperator *sep) From 33c1c7c3e4abbf1e182b85fccd05741284a003f4 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 9 Jun 2015 16:17:09 -0700 Subject: [PATCH 164/846] More packet figuring out... --- common/patches/uf.cpp | 4 +++ zone/aa.cpp | 62 ++++++++++++++++++++++--------------------- zone/client.h | 2 +- zone/command.cpp | 10 +++++-- 4 files changed, 45 insertions(+), 33 deletions(-) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index caea6b933..81ad197d6 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1810,6 +1810,10 @@ namespace UF // OUT(aa_array[r].charges); //} // OUT(unknown02220[4]); + + eq->aa_array[0].AA = 6; + eq->aa_array[0].value = 5; + OUT(mana); OUT(cur_hp); OUT(STR); diff --git a/zone/aa.cpp b/zone/aa.cpp index 57f6df675..2fe75e4fc 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1097,28 +1097,28 @@ void Client::SendAATimers() { } void Client::SendAATable() { - Log.Out(Logs::General, Logs::Status, "SendAATable()"); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); - - AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; - aa2->aa_spent = 8; - //aa2->aa_list[0].AA = 11; + //Log.Out(Logs::General, Logs::Status, "SendAATable()"); + //EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); + // + //AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; + //aa2->aa_spent = 10; + //aa2->aa_list[0].AA = 6; //aa2->aa_list[0].value = 4; //aa2->aa_list[0].charges = 0; - //aa2->aa_list[1].AA = 202; + //aa2->aa_list[1].AA = 11; //aa2->aa_list[1].value = 4; //aa2->aa_list[1].charges = 0; - - //aa2->aa_spent = GetAAPointsSpent(); // - //uint32 i; - //for(i=0;i < MAX_PP_AA_ARRAY;i++){ - // aa2->aa_list[i].AA = aa[i]->value ? aa[i]->AA : 0; // bit of a hack to prevent expendables punching a hole - // aa2->aa_list[i].value = aa[i]->value; - // aa2->aa_list[i].charges = aa[i]->charges; - //} - QueuePacket(outapp); - safe_delete(outapp); + ////aa2->aa_spent = GetAAPointsSpent(); + //// + ////uint32 i; + ////for(i=0;i < MAX_PP_AA_ARRAY;i++){ + //// aa2->aa_list[i].AA = aa[i]->value ? aa[i]->AA : 0; // bit of a hack to prevent expendables punching a hole + //// aa2->aa_list[i].value = aa[i]->value; + //// aa2->aa_list[i].charges = aa[i]->charges; + ////} + //QueuePacket(outapp); + //safe_delete(outapp); } void Client::SendPreviousAA(uint32 id, int seq){ @@ -2101,12 +2101,15 @@ void Client::SendAlternateAdvancementList() { // SendAlternateAdvancement(aa.first, 5); //} - SendAlternateAdvancement(1, 4); - SendAlternateAdvancement(2, 4); + SendAlternateAdvancementRank(1, 5); + SendAlternateAdvancementRank(1, 6); + SendAlternateAdvancementRank(2, 1); + //SendAlternateAdvancement(1, 5); + //SendAlternateAdvancement(2, 5); } //New AA -void Client::SendAlternateAdvancement(int aa_id, int level) { +void Client::SendAlternateAdvancementRank(int aa_id, int level) { if(!zone) return; @@ -2119,7 +2122,7 @@ void Client::SendAlternateAdvancement(int aa_id, int level) { return; } - AA::Rank *rank = ability->GetRankByPointsSpent(level + 1); + AA::Rank *rank = ability->GetRankByPointsSpent(level); if(!rank) return; @@ -2129,12 +2132,12 @@ void Client::SendAlternateAdvancement(int aa_id, int level) { return; } } - + // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). if(ability->category == 1 || ability->category == 2) { //if(GetAA(saa2->id) == 0) // return; - + if(rank->expansion > 0) { AA::Ability *qaa = zone->GetAlternateAdvancementAbility(aa_id + 1); //if(qaa && qaa->expansion == rank->expansion && GetAA(aa_id) > 0) { @@ -2142,7 +2145,7 @@ void Client::SendAlternateAdvancement(int aa_id, int level) { //} } } - + // Passive and Active Shroud AAs // For now we skip them if(ability->category == 3 || ability->category == 4) { @@ -2171,25 +2174,24 @@ void Client::SendAlternateAdvancement(int aa_id, int level) { } } - //Should move this to another function - int size = sizeof(AARankInfo_Struct)+(sizeof(AARankEffect_Struct)* rank->effects.size()) + (sizeof(AARankPrereq_Struct)* rank->prereqs.size()); + int size = sizeof(AARankInfo_Struct) + (sizeof(AARankEffect_Struct) * rank->effects.size()) + (sizeof(AARankPrereq_Struct) * rank->prereqs.size()); EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size); AARankInfo_Struct *aai = (AARankInfo_Struct*)outapp->pBuffer; - aai->id = ability->GetMaxRank()->id; + aai->id = rank->id; aai->upper_hotkey_sid = rank->upper_hotkey_sid; aai->lower_hotkey_sid = rank->lower_hotkey_sid; aai->title_sid = rank->title_sid; aai->desc_sid = rank->desc_sid; - aai->level_req = rank->level_req; aai->cost = rank->cost; aai->seq = aa_id; - aai->current_level = level + 1; aai->type = ability->type; aai->spell = rank->spell; aai->spell_type = rank->spell_type; aai->spell_refresh = rank->recast_time; aai->classes = ability->classes; + aai->level_req = rank->level_req; + aai->current_level = level; aai->max_level = ability->GetMaxLevel(); aai->prev_id = rank->prev_id; aai->next_id = rank->next_id; @@ -2208,7 +2210,7 @@ void Client::SendAlternateAdvancement(int aa_id, int level) { outapp->WriteSInt32(effect.second.base2); outapp->WriteSInt32(effect.first); } - + for(auto prereq : rank->prereqs) { outapp->WriteSInt32(prereq.aa_id); outapp->WriteSInt32(prereq.points); diff --git a/zone/client.h b/zone/client.h index 71fc219fb..1a1e32c6f 100644 --- a/zone/client.h +++ b/zone/client.h @@ -760,7 +760,7 @@ public: inline PTimerList &GetPTimers() { return(p_timers); } //New AA Methods - void SendAlternateAdvancement(int aa_id, int level); + void SendAlternateAdvancementRank(int aa_id, int level); void SendAlternateAdvancementList(); //old AA Methods diff --git a/zone/command.cpp b/zone/command.cpp index 3210ba070..f2a84baaa 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -674,8 +674,14 @@ void command_incstat(Client* c, const Seperator* sep){ } void command_resetaa(Client* c,const Seperator *sep){ - c->SendAlternateAdvancement(1, 1); - c->SendAlternateAdvancement(2, 1); + + //if(sep->IsNumber(1) && atoi(sep->arg[1]) == 1) { + // c->SendAlternateAdvancement(2, 2); + //} + //else if(sep->IsNumber(1) && atoi(sep->arg[1]) == 2) { + // c->SendAlternateAdvancement(2, 3); + //} + //if(c->GetTarget()!=0 && c->GetTarget()->IsClient()){ // c->GetTarget()->CastToClient()->ResetAA(); // c->Message(13,"Successfully reset %s's AAs", c->GetTarget()->GetName()); From d5e697c061df46d38711305405925d3903f13415 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 9 Jun 2015 22:12:31 -0700 Subject: [PATCH 165/846] More work, looks a lot better than before, tomorrow i hope to get actual client implementation done --- zone/aa.cpp | 395 +++++++++++++++++++++-------------------- zone/aa_ability.h | 1 + zone/bonuses.cpp | 29 +-- zone/client.cpp | 84 ++++----- zone/client.h | 8 +- zone/client_packet.cpp | 108 +++++------ zone/mob.h | 11 +- zone/spell_effects.cpp | 68 +++---- zone/zone.h | 1 + 9 files changed, 363 insertions(+), 342 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 2fe75e4fc..a66b533f6 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1254,37 +1254,37 @@ void Client::SendAA(uint32 id, int seq) { 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 - } - } - } - } - } - } + //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) @@ -1399,51 +1399,6 @@ void Client::SendAAList(){ } } -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; - auto sendaa = zone->FindAA(aa_id); // this is a bit hacky - uint32 charges = sendaa->special_category == 7 && new_value ? 1 : 0; - 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++; - aa[cur]->charges = charges; - 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++; - aa[cur]->charges = charges; - return true; - } - // hack to prevent expendable exploit, we should probably be reshuffling the array to fix the hole - else if(aa[cur]->value == 0 && new_value == 1 && aa[cur]->AA == aa_id) { - aa[cur]->value = new_value; - aa[cur]->charges = charges; - return true; - } - else if(aa[cur]->AA==0){ //end of list - aa[cur]->AA = aa_id; - aa[cur]->value = new_value; - aa[cur]->charges = charges; - return true; - } - } - return false; -} - SendAA_Struct* Zone::FindAA(uint32 id) { return aas_send[id]; } @@ -1503,39 +1458,39 @@ bool ZoneDatabase::LoadAAEffects2() { } void Client::ResetAA(){ - RefundAA(); - uint32 i; - for (i=0; i < MAX_PP_AA_ARRAY; i++) { - aa[i]->AA = 0; - aa[i]->value = 0; - aa[i]->charges = 0; - m_pp.aa_array[i].AA = 0; - m_pp.aa_array[i].value = 0; - m_pp.aa_array[i].charges= 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; - - database.DeleteCharacterAAs(this->CharacterID()); - SaveAA(); - SendClearAA(); - SendAAList(); - SendAATable(); - SendAAStats(); - database.DeleteCharacterLeadershipAAs(this->CharacterID()); - // undefined for these clients - if (GetClientVersionBit() & BIT_TitaniumAndEarlier) - Kick(); +// RefundAA(); +// uint32 i; +// for (i=0; i < MAX_PP_AA_ARRAY; i++) { +// aa[i]->AA = 0; +// aa[i]->value = 0; +// aa[i]->charges = 0; +// m_pp.aa_array[i].AA = 0; +// m_pp.aa_array[i].value = 0; +// m_pp.aa_array[i].charges= 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; +// +// database.DeleteCharacterAAs(this->CharacterID()); +// SaveAA(); +// SendClearAA(); +// SendAAList(); +// SendAATable(); +// SendAAStats(); +// database.DeleteCharacterLeadershipAAs(this->CharacterID()); +// // undefined for these clients +// if (GetClientVersionBit() & BIT_TitaniumAndEarlier) +// Kick(); } void Client::SendClearAA() @@ -2096,19 +2051,23 @@ Mob *AA_SwarmPetInfo::GetOwner() return entity_list.GetMobID(owner_id); } -void Client::SendAlternateAdvancementList() { - //for(auto &aa : zone->aa_abilities) { - // SendAlternateAdvancement(aa.first, 5); - //} - - SendAlternateAdvancementRank(1, 5); - SendAlternateAdvancementRank(1, 6); - SendAlternateAdvancementRank(2, 1); - //SendAlternateAdvancement(1, 5); - //SendAlternateAdvancement(2, 5); +//New AA +void Client::SendAlternateAdvancementTable() { + for(auto &aa : zone->aa_abilities) { + auto ranks = GetAA(aa.second->first_rank_id); + if(ranks) { + if(aa.second->GetMaxLevel() == ranks) { + SendAlternateAdvancementRank(aa.first, ranks); + } else { + SendAlternateAdvancementRank(aa.first, ranks); + SendAlternateAdvancementRank(aa.first, ranks + 1); + } + } else { + SendAlternateAdvancementRank(aa.first, 1); + } + } } -//New AA void Client::SendAlternateAdvancementRank(int aa_id, int level) { if(!zone) return; @@ -2126,53 +2085,9 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { if(!rank) return; - if(rank->account_time_required) { - if((Timer::GetTimeSeconds() - account_creation) < rank->account_time_required) - { - return; - } - } - - // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). - if(ability->category == 1 || ability->category == 2) { - //if(GetAA(saa2->id) == 0) - // return; - - if(rank->expansion > 0) { - AA::Ability *qaa = zone->GetAlternateAdvancementAbility(aa_id + 1); - //if(qaa && qaa->expansion == rank->expansion && GetAA(aa_id) > 0) { - // return; - //} - } - } - - // Passive and Active Shroud AAs - // For now we skip them - if(ability->category == 3 || ability->category == 4) { + if(!CanUseAlternateAdvancementRank(rank)) { return; } - - // Check for racial/Drakkin blood line AAs - if(ability->category == 8) - { - uint32 client_race = GetBaseRace(); - - // Drakkin Bloodlines - if(rank->expansion > 522) - { - if(client_race != 522) - return; - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if(heritage != rank->expansion) - return; - } - else if(client_race != rank->expansion) - { - return; - } - } int size = sizeof(AARankInfo_Struct) + (sizeof(AARankEffect_Struct) * rank->effects.size()) + (sizeof(AARankPrereq_Struct) * rank->prereqs.size()); EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size); @@ -2220,10 +2135,126 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { safe_delete(outapp); } +AA::Ability *Zone::GetAlternateAdvancementAbility(int id) { + auto iter = aa_abilities.find(id); + if(iter != aa_abilities.end()) { + return iter->second.get(); + } + + return nullptr; +} + +AA::Ability *Zone::GetAlternateAdvancementAbilityByRank(int rank_id) { + AA::Rank *rank = GetAlternateAdvancementRank(rank_id); + + if(!rank) + return nullptr; + + return rank->base_ability; +} + +AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) { + auto iter = aa_ranks.find(rank_id); + if(iter != aa_ranks.end()) { + return iter->second.get(); + } + + return nullptr; +} + +uint32 Mob::GetAA(uint32 rank_id) const { + if(zone) { + AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); + if(!ability) + return 0; + + auto iter = aa_ranks.find(ability->id); + if(iter != aa_ranks.end()) { + return iter->second; + } + } + return 0; +} + +bool Mob::SetAA(uint32 rank_id, uint32 new_value) { + if(zone) { + AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); + + if(!ability) { + return false; + } + + if(new_value > ability->GetMaxLevel()) { + return false; + } + + aa_ranks[ability->id] = new_value; + } + + return false; +} + + +bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { + AA::Ability *ability = rank->base_ability; + + if(!ability) + return false; + + // Passive and Active Shroud AAs + // For now we skip them + if(ability->category == 3 || ability->category == 4) { + return false; + } + + // Check for racial/Drakkin blood line AAs + if(ability->category == 8) + { + uint32 client_race = GetBaseRace(); + + // Drakkin Bloodlines + if(rank->expansion > 522) + { + if(client_race != 522) + return false; + + int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline + + if(heritage != rank->expansion) + return false; + } + else if(client_race != rank->expansion) + { + return false; + } + } + + return true; +} + +bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { + AA::Ability *ability = rank->base_ability; + + if(!ability) + return false; + + if(!CanUseAlternateAdvancementRank(rank)) { + return false; + } + + //You can't purchase grant only AAs they can only be assigned + if(ability->grant_only) { + return false; + } + + //check other stuff like price later + return true; +} + void Zone::LoadAlternateAdvancement() { Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Data..."); - if(!database.LoadAlternateAdvancementAbilities(aa_abilities, - aa_ranks)) + if(!database.LoadAlternateAdvancementAbilities(aa_abilities, + aa_ranks)) { aa_abilities.clear(); aa_ranks.clear(); @@ -2244,7 +2275,8 @@ void Zone::LoadAlternateAdvancement() { if(current->prev) { current->total_cost = current->cost + current->prev->total_cost; - } else { + } + else { current->total_cost = current->cost; } @@ -2257,24 +2289,6 @@ void Zone::LoadAlternateAdvancement() { Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Data"); } -AA::Ability *Zone::GetAlternateAdvancementAbility(int id) { - auto iter = aa_abilities.find(id); - if(iter != aa_abilities.end()) { - return iter->second.get(); - } - - return nullptr; -} - -AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) { - auto iter = aa_ranks.find(rank_id); - if(iter != aa_ranks.end()) { - return iter->second.get(); - } - - return nullptr; -} - bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, std::unordered_map> &ranks) { @@ -2285,7 +2299,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = atoi(row[0]); ability->name = row[1]; ability->category = atoi(row[2]); ability->classes = atoi(row[3]); @@ -2295,7 +2309,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapfirst_rank_id = atoi(row[7]); ability->first = nullptr; - abilities[id] = std::unique_ptr(ability); + abilities[ability->id] = std::unique_ptr(ability); } } else { Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Abilities"); @@ -2312,8 +2326,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = id; + rank->id = atoi(row[0]); rank->upper_hotkey_sid = atoi(row[1]); rank->lower_hotkey_sid = atoi(row[2]); rank->title_sid = atoi(row[3]); @@ -2332,7 +2345,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapnext = nullptr; rank->prev = nullptr; - ranks[id] = std::unique_ptr(rank); + ranks[rank->id] = std::unique_ptr(rank); } } else { Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Ability Ranks"); diff --git a/zone/aa_ability.h b/zone/aa_ability.h index d1ef49105..a31bc06e3 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -41,6 +41,7 @@ public: Rank *GetRankByPointsSpent(int current_level); int GetMaxLevel(bool force_calc = false); + int id; std::string name; int category; int classes; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 5dd7440f6..a2a180cef 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -639,20 +639,21 @@ void Client::CalcAABonuses(StatBonuses* newbon) { 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 - } - } - } - } + //aa old + //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 + // } + // } + // } + //} } diff --git a/zone/client.cpp b/zone/client.cpp index 53d39ea7b..dc32745e4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -176,7 +176,6 @@ Client::Client(EQStreamInterface* ieqs) admin = 0; lsaccountid = 0; shield_target = nullptr; - SQL_log = nullptr; guild_id = GUILD_NONE; guildrank = 0; GuildBanker = false; @@ -524,47 +523,48 @@ void Client::ReportConnectingState() { } bool Client::SaveAA(){ - int first_entry = 0; - std::string rquery; - /* Save Player AA */ - int spentpoints = 0; - for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { - uint32 points = aa[a]->value; - if (points > HIGHEST_AA_VALUE) { - aa[a]->value = HIGHEST_AA_VALUE; - points = HIGHEST_AA_VALUE; - } - if (points > 0) { - SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1); - if (curAA) { - for (int rank = 0; rank::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank); - if (RequiredLevel != AARequiredLevelAndCost.end()) { - spentpoints += RequiredLevel->second.Cost; - } - else - spentpoints += (curAA->cost + (curAA->cost_inc * rank)); - } - } - } - } - m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; - int highest = 0; - for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { - if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" - " VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); - first_entry = 1; - } else { - rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); - } - highest = a; - } - } - auto results = database.QueryDatabase(rquery); - /* This is another part of the hack to clean up holes left by expendable AAs */ - rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest); + //aa old + //int first_entry = 0; + //std::string rquery; + ///* Save Player AA */ + //int spentpoints = 0; + //for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { + // uint32 points = aa[a]->value; + // if (points > HIGHEST_AA_VALUE) { + // aa[a]->value = HIGHEST_AA_VALUE; + // points = HIGHEST_AA_VALUE; + // } + // if (points > 0) { + // SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1); + // if (curAA) { + // for (int rank = 0; rank::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank); + // if (RequiredLevel != AARequiredLevelAndCost.end()) { + // spentpoints += RequiredLevel->second.Cost; + // } + // else + // spentpoints += (curAA->cost + (curAA->cost_inc * rank)); + // } + // } + // } + //} + //m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; + //int highest = 0; + //for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { + // if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load + // if (first_entry != 1){ + // rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" + // " VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); + // first_entry = 1; + // } else { + // rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); + // } + // highest = a; + // } + //} + //auto results = database.QueryDatabase(rquery); + ///* This is another part of the hack to clean up holes left by expendable AAs */ + //rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest); return true; } diff --git a/zone/client.h b/zone/client.h index 1a1e32c6f..c2d3b1f63 100644 --- a/zone/client.h +++ b/zone/client.h @@ -761,7 +761,7 @@ public: //New AA Methods void SendAlternateAdvancementRank(int aa_id, int level); - void SendAlternateAdvancementList(); + void SendAlternateAdvancementTable(); //old AA Methods void SendAAList(); @@ -787,8 +787,6 @@ public: void DisableAAEffect(aaEffectType type); bool CheckAAEffect(aaEffectType type); void HandleAAAction(aaID activate); - uint32 GetAA(uint32 aa_id) const; - bool SetAA(uint32 aa_id, uint32 new_value); inline uint32 GetAAPointsSpent() { return m_pp.aapoints_spent; } int16 CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id); int16 CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id); @@ -1493,11 +1491,7 @@ private: uint32 tribute_master_id; - FILE *SQL_log; uint32 max_AAXP; - uint32 staminacount; - AA_Array* aa[MAX_PP_AA_ARRAY]; //this list contains pointers into our player profile - std::map aa_points; bool npcflag; uint8 npclevel; bool feigned; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 77431ecd9..c242d50e2 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1091,7 +1091,7 @@ void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app) void Client::Handle_Connect_OP_SendAATable(const EQApplicationPacket *app) { - SendAlternateAdvancementList(); + SendAlternateAdvancementTable(); return; } @@ -1440,58 +1440,60 @@ 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; } /* Initialize AA's : Move to function eventually */ - for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++) - aa[a] = &m_pp.aa_array[a]; - query = StringFormat( - "SELECT " - "slot, " - "aa_id, " - "aa_value, " - "charges " - "FROM " - "`character_alternate_abilities` " - "WHERE `id` = %u ORDER BY `slot`", this->CharacterID()); - results = database.QueryDatabase(query); i = 0; - int offset = 0; // offset to fix the hole from expendables - for (auto row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]) - offset; - m_pp.aa_array[i].AA = atoi(row[1]); - m_pp.aa_array[i].value = atoi(row[2]); - m_pp.aa_array[i].charges = atoi(row[3]); - /* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use. - We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load! - Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable - and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple - entries for a single AA. - */ - if (m_pp.aa_array[i].value == 0) - offset++; - } - for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ - uint32 id = aa[a]->AA; - //watch for invalid AA IDs - if (id == aaNone) - continue; - if (id >= aaHighestID) { - aa[a]->AA = aaNone; - aa[a]->value = 0; - continue; - } - if (aa[a]->value == 0) { - aa[a]->AA = aaNone; - continue; - } - if (aa[a]->value > HIGHEST_AA_VALUE) { - aa[a]->AA = aaNone; - aa[a]->value = 0; - continue; - } - - if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */ - aa_points[(id - aa[a]->value + 1)] = aa[a]->value; - else - aa_points[id] = aa[a]->value; - } + //aa old + //for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++) + // aa[a] = &m_pp.aa_array[a]; + //query = StringFormat( + // "SELECT " + // "slot, " + // "aa_id, " + // "aa_value, " + // "charges " + // "FROM " + // "`character_alternate_abilities` " + // "WHERE `id` = %u ORDER BY `slot`", this->CharacterID()); + //results = database.QueryDatabase(query); i = 0; + //int offset = 0; // offset to fix the hole from expendables + //for (auto row = results.begin(); row != results.end(); ++row) { + // i = atoi(row[0]) - offset; + // m_pp.aa_array[i].AA = atoi(row[1]); + // m_pp.aa_array[i].value = atoi(row[2]); + // m_pp.aa_array[i].charges = atoi(row[3]); + // /* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use. + // We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load! + // Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable + // and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple + // entries for a single AA. + // */ + // if (m_pp.aa_array[i].value == 0) + // offset++; + //} + //for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ + // uint32 id = aa[a]->AA; + // //watch for invalid AA IDs + // if (id == aaNone) + // continue; + // if (id >= aaHighestID) { + // aa[a]->AA = aaNone; + // aa[a]->value = 0; + // continue; + // } + // if (aa[a]->value == 0) { + // aa[a]->AA = aaNone; + // continue; + // } + // if (aa[a]->value > HIGHEST_AA_VALUE) { + // aa[a]->AA = aaNone; + // aa[a]->value = 0; + // continue; + // } + // + // //aa old +// // if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */ +// // aa_points[(id - aa[a]->value + 1)] = aa[a]->value; +// // else +// // aa_points[id] = aa[a]->value; + //} if (SPDAT_RECORDS > 0) { for (uint32 z = 0; z #include #include @@ -860,7 +861,6 @@ public: 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); } 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); @@ -956,6 +956,12 @@ public: 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); + //aa new + uint32 GetAA(uint32 rank_id) const; + bool SetAA(uint32 rank_id, uint32 new_value); + bool CanUseAlternateAdvancementRank(AA::Rank *rank); + bool CanPurchaseAlternateAdvancementRank(AA::Rank *ran); + 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); @@ -969,7 +975,6 @@ protected: virtual bool AI_PursueCastCheck() { return(false); } virtual bool AI_IdleCastCheck() { return(false); } - bool IsFullHP; bool moved; @@ -1311,6 +1316,8 @@ protected: bool bEnraged; bool destructibleobject; + std::unordered_map aa_ranks; + private: void _StopSong(); //this is not what you think it is Mob* target; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b331113bd..7e91550c5 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5231,24 +5231,25 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { uint32 aa_AA = 0; uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) - { - aa_AA = this->aa[i]->AA; - aa_value = this->aa[i]->value; - if (aa_AA < 1 || aa_value < 1) - continue; - - if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) - continue; - - proc_spellid = CalcAAFocus(type, aa_AA, spell_id); - - if (IsValidSpell(proc_spellid)){ - ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1)); - if(zone->random.Roll(ProcChance)) - SympatheticProcList.push_back(proc_spellid); - } - } + //aa old + //for (int i = 0; i < MAX_PP_AA_ARRAY; i++) + //{ + // aa_AA = this->aa[i]->AA; + // aa_value = this->aa[i]->value; + // if (aa_AA < 1 || aa_value < 1) + // continue; + // + // if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) + // continue; + // + // proc_spellid = CalcAAFocus(type, aa_AA, spell_id); + // + // if (IsValidSpell(proc_spellid)){ + // ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1)); + // if(zone->random.Roll(ProcChance)) + // SympatheticProcList.push_back(proc_spellid); + // } + //} } if (SympatheticProcList.size() > 0) @@ -5503,21 +5504,22 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { uint32 aa_AA = 0; uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) - { - aa_AA = this->aa[i]->AA; - aa_value = this->aa[i]->value; - if (aa_AA < 1 || aa_value < 1) - continue; - - Total3 = CalcAAFocus(type, aa_AA, spell_id); - if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { - realTotal3 = Total3; - } - else if (Total3 < 0 && Total3 < realTotal3) { - realTotal3 = Total3; - } - } + //aa old + //for (int i = 0; i < MAX_PP_AA_ARRAY; i++) + //{ + // aa_AA = this->aa[i]->AA; + // aa_value = this->aa[i]->value; + // if (aa_AA < 1 || aa_value < 1) + // continue; + // + // Total3 = CalcAAFocus(type, aa_AA, spell_id); + // if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { + // realTotal3 = Total3; + // } + // else if (Total3 < 0 && Total3 < realTotal3) { + // realTotal3 = Total3; + // } + //} } if(type == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) diff --git a/zone/zone.h b/zone/zone.h index fbe1b48d1..536ff048c 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -117,6 +117,7 @@ public: //new AA void LoadAlternateAdvancement(); AA::Ability *GetAlternateAdvancementAbility(int id); + AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id); AA::Rank *GetAlternateAdvancementRank(int rank_id); //old AA From 8422ce6f25b0f047703e98f31d242609ba9e2686 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 9 Jun 2015 22:46:53 -0700 Subject: [PATCH 166/846] Moved effects to a vector since we dont need the random access by slot --- zone/aa.cpp | 14 +++++++------- zone/aa_rank.h | 2 +- zone/aa_rank_effects.h | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index a66b533f6..c9fa78ab2 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -2120,10 +2120,10 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { outapp->SetWritePosition(sizeof(AARankInfo_Struct)); for(auto effect : rank->effects) { - outapp->WriteSInt32(effect.second.effect_id); - outapp->WriteSInt32(effect.second.base1); - outapp->WriteSInt32(effect.second.base2); - outapp->WriteSInt32(effect.first); + outapp->WriteSInt32(effect.effect_id); + outapp->WriteSInt32(effect.base1); + outapp->WriteSInt32(effect.base2); + outapp->WriteSInt32(effect.slot); } for(auto prereq : rank->prereqs) { @@ -2361,17 +2361,17 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map 12) + if(effect.slot < 1 || effect.slot > 12) continue; if(ranks.count(rank_id) > 0) { AA::Rank *rank = ranks[rank_id].get(); - rank->effects[slot] = effect; + rank->effects.push_back(effect); } } } else { diff --git a/zone/aa_rank.h b/zone/aa_rank.h index d35582834..20628a506 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -47,7 +47,7 @@ public: uint32 account_time_required; int total_cost; Ability *base_ability; - std::unordered_map effects; + std::vector effects; std::vector prereqs; }; diff --git a/zone/aa_rank_effects.h b/zone/aa_rank_effects.h index fd65d507f..d68937078 100644 --- a/zone/aa_rank_effects.h +++ b/zone/aa_rank_effects.h @@ -27,6 +27,7 @@ namespace AA struct RankEffect { + int slot; int effect_id; int base1; int base2; From 81744281895e777b029fd6ef7abdce9c5c58c325 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Jun 2015 23:10:00 -0400 Subject: [PATCH 167/846] Export SetPseudoRoot to Lua --- zone/lua_mob.cpp | 7 ++++++- zone/lua_mob.h | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 60a42760c..f4d7d64cb 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1851,6 +1851,10 @@ int Lua_Mob::CanBuffStack(int spell_id, int caster_level, bool fail_if_overwrite return self->CanBuffStack(spell_id, caster_level, fail_if_overwrite); } +void Lua_Mob::SetPseudoRoot(bool in) { + Lua_Safe_Call_Void(); + self->SetPseudoRoot(in); +} luabind::scope lua_register_mob() { return luabind::class_("Mob") @@ -2168,7 +2172,8 @@ luabind::scope lua_register_mob() { .def("BuffFadeBySlot", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeBySlot) .def("BuffFadeBySlot", (void(Lua_Mob::*)(int,bool))&Lua_Mob::BuffFadeBySlot) .def("CanBuffStack", (int(Lua_Mob::*)(int,int))&Lua_Mob::CanBuffStack) - .def("CanBuffStack", (int(Lua_Mob::*)(int,int,bool))&Lua_Mob::CanBuffStack); + .def("CanBuffStack", (int(Lua_Mob::*)(int,int,bool))&Lua_Mob::CanBuffStack) + .def("SetPseudoRoot", (void(Lua_Mob::*)(bool))&Lua_Mob::SetPseudoRoot); } luabind::scope lua_register_special_abilities() { diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 54c388ed4..023fedd2a 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -169,7 +169,7 @@ public: bool CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost); bool CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot); bool CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer, int timer_duration); - bool CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer, int timer_duration, + bool CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer, int timer_duration, int resist_adjust); bool SpellFinished(int spell_id, Lua_Mob target); bool SpellFinished(int spell_id, Lua_Mob target, int slot); @@ -352,6 +352,7 @@ public: void BuffFadeBySlot(int slot, bool recalc_bonuses); int CanBuffStack(int spell_id, int caster_level); int CanBuffStack(int spell_id, int caster_level, bool fail_if_overwrite); + void SetPseudoRoot(bool in); }; #endif From 8dccc8bf90fbd66b0b99bbc8fe3ad2a6b332c605 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Jun 2015 23:52:56 -0400 Subject: [PATCH 168/846] Fix Pseudo Rooted for runspeed --- zone/mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 1591cc057..b107565bc 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -615,7 +615,7 @@ int Mob::_GetWalkSpeed() const { } int Mob::_GetRunSpeed() const { - if (IsRooted() || IsStunned() || IsMezzed()) + if (IsRooted() || IsStunned() || IsMezzed() || IsPseudoRooted()) return 0; int aa_mod = 0; From 1589169200d3c27cc2e76e5bb21ecaf672dc47fe Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 10 Jun 2015 22:46:57 -0700 Subject: [PATCH 169/846] AAs should load from character data now, though will be fucked up if you already had stacked aas. --- common/eq_packet_structs.h | 2 +- common/patches/rof2.cpp | 3 +- common/patches/sod.cpp | 4 +- common/patches/sof.cpp | 4 +- common/patches/uf.cpp | 79 +- common/ptimer.h | 4 - zone/aa.cpp | 2025 +++++++++++++++------------------- zone/aa.h | 11 - zone/aa_rank.h | 1 + zone/attack.cpp | 63 +- zone/bonuses.cpp | 1533 +++++++++++++------------- zone/bot.cpp | 2126 ++++++++++++++++++------------------ zone/bot.h | 2 - zone/client.cpp | 52 +- zone/client.h | 14 +- zone/client_packet.cpp | 85 +- zone/command.cpp | 99 +- zone/exp.cpp | 2 +- zone/mob.h | 5 +- zone/net.cpp | 3 - zone/perl_client.cpp | 55 +- zone/spell_effects.cpp | 899 +++++++-------- zone/zone.cpp | 15 - zone/zone.h | 24 +- zone/zonedb.h | 13 +- 25 files changed, 3318 insertions(+), 3805 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0c4335016..e562a94e5 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4243,7 +4243,7 @@ struct AARankInfo_Struct int32 total_cost; int32 expansion; int32 category; - uint8 charges; + uint32 charges; uint8 grant_only; uint32 total_effects; uint32 total_prereqs; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 096467edf..a4f484a9e 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2466,7 +2466,8 @@ namespace RoF2 outapp->WriteUInt32(emu->lastlogin); outapp->WriteUInt32(emu->timePlayedMin); outapp->WriteUInt32(emu->timeentitledonaccount); - outapp->WriteUInt32(0x0007ffff); // Expansion bitmask + outapp->WriteUInt32(emu->expansions); + //outapp->WriteUInt32(0x0007ffff); // Expansion bitmask outapp->WriteUInt32(structs::MAX_PP_LANGUAGE); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 80201da1e..69bb7f4c1 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1677,8 +1677,8 @@ namespace SoD OUT(copper_bank); OUT(platinum_shared); // OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 16383; + OUT(expansions); + //eq->expansions = 16383; // OUT(unknown13244[12]); OUT(autosplit); // OUT(unknown13260[16]); diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 7b0e14c1c..2d8ec8d3a 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1335,8 +1335,8 @@ namespace SoF OUT(copper_bank); OUT(platinum_shared); // OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 16383; + OUT(expansions); + //eq->expansions = 16383; // OUT(unknown13244[12]); OUT(autosplit); // OUT(unknown13260[16]); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 81ad197d6..5b879af9d 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1804,15 +1804,13 @@ namespace UF // OUT(unknown00224[48]); //NOTE: new client supports 300 AAs, our internal rep/PP //only supports 240.. - //for (r = 0; r < MAX_PP_AA_ARRAY; r++) { - // OUT(aa_array[r].AA); - // OUT(aa_array[r].value); - // OUT(aa_array[r].charges); - //} - // OUT(unknown02220[4]); + for (r = 0; r < MAX_PP_AA_ARRAY; r++) { + eq->aa_array[r].AA = emu->aa_array[r].AA; + eq->aa_array[r].value = emu->aa_array[r].value; + eq->aa_array[r].charges = emu->aa_array[r].charges; + } - eq->aa_array[0].AA = 6; - eq->aa_array[0].value = 5; + // OUT(unknown02220[4]); OUT(mana); OUT(cur_hp); @@ -1943,8 +1941,8 @@ namespace UF OUT(copper_bank); OUT(platinum_shared); // OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 0xffff; + OUT(expansions); + //eq->expansions = 0x1ffff; // OUT(unknown13244[12]); OUT(autosplit); // OUT(unknown13260[16]); @@ -2149,7 +2147,6 @@ namespace UF ENCODE(OP_SendAATable) { -#if 1 EQApplicationPacket *inapp = *p; *p = nullptr; AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; @@ -2180,8 +2177,8 @@ namespace UF eq->last_id = emu->prev_id; eq->next_id = emu->next_id; eq->cost2 = emu->total_cost; - eq->grant_only = emu->grant_only > 0 ? true : false; - eq->expendable_charges = emu->charges ? 1 : 0; + eq->grant_only = emu->grant_only; + eq->expendable_charges = emu->charges; eq->aa_expansion = emu->expansion; eq->special_category = emu->category; eq->total_abilities = emu->total_effects; @@ -2194,65 +2191,13 @@ namespace UF } if(emu->total_prereqs > 0) { - eq->prereq_skill = -(int)inapp->ReadUInt32(); + eq->prereq_skill = inapp->ReadUInt32(); eq->prereq_minpoints = inapp->ReadUInt32(); } - Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); + //Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); dest->FastQueuePacket(&outapp); delete inapp; -#else - ENCODE_LENGTH_ATLEAST(SendAA_Struct); - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); - - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 6 is for Underfoot - if(emu->clientver <= 6) - { - OUT(id); - eq->unknown004 = 1; - //eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->title_sid = emu->id - emu->current_level + 1; - //eq->desc_sid = emu->id - emu->current_level + 1; - eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - //OUT(berserker); - //eq->max_level = emu->sof_max_level; - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - eq->aa_expansion = emu->aa_expansion; - eq->special_category = emu->special_category; - eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number - OUT(total_abilities); - unsigned int r; - for(r = 0; r < emu->total_abilities; r++) { - OUT(abilities[r].skill_id); - OUT(abilities[r].base1); - OUT(abilities[r].base2); - OUT(abilities[r].slot); - } - } - - Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(__packet).c_str()); - FINISH_ENCODE(); -#endif } ENCODE(OP_SendCharInfo) diff --git a/common/ptimer.h b/common/ptimer.h index 8a559a148..7194ab49b 100644 --- a/common/ptimer.h +++ b/common/ptimer.h @@ -139,8 +139,4 @@ protected: std::map _list; }; -//code prettying macros -#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3)) -#define AA_Choose5(val, v1, v2, v3, v4, v5) (val==1?v1:(val==2?v2:(val==3?v3:(val==4?v4:v5)))) - #endif diff --git a/zone/aa.cpp b/zone/aa.cpp index c9fa78ab2..4bbdf88a6 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -37,35 +37,28 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) extern QueryServ* QServ; - -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; - - 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; + //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; } @@ -96,400 +89,400 @@ int Client::CalcAAReuseTimer(const AA_DBAction *caa) { } 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, USE_ITEM_SPELL_SLOT, -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); - - SaveAA(); /* Save Character AA */ - SendAA(activate); - SendAATable(); - } +// 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, USE_ITEM_SPELL_SLOT, -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); +// +// SaveAA(); /* Save Character AA */ +// 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 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 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: - Log.Out(Logs::General, Logs::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, USE_ITEM_SPELL_SLOT, -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); - } +// 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 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 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: +// Log.Out(Logs::General, Logs::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, USE_ITEM_SPELL_SLOT, -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); +// } } void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg) { @@ -937,130 +930,119 @@ bool Client::CheckAAEffect(aaEffectType type) { 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) { - Log.Out(Logs::Detail, Logs::AA, "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; - Log.Out(Logs::Detail, Logs::AA, "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 - Log.Out(Logs::Detail, Logs::AA, "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; - uint8 req_level; - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); - - if(RequiredLevel != AARequiredLevelAndCost.end()) { - real_cost = RequiredLevel->second.Cost; - req_level = RequiredLevel->second.Level; - } - else { - real_cost = aa2->cost + (aa2->cost_inc * cur_level); - req_level = aa2->class_type + (aa2->level_inc * cur_level); - } - - if (req_level > GetLevel()) - return; //Cheater trying to Buy AA... - - if (m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { - SetAA(aa2->id, cur_level + 1); - - Log.Out(Logs::Detail, Logs::AA, "Set AA %d to level %d", aa2->id, cur_level + 1); - - m_pp.aapoints -= real_cost; - - /* Do Player Profile rank calculations and set player profile */ - SaveAA(); - /* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/ - // database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1)); - - 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 - */ - - /* Initial purchase of an AA ability */ - 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"); - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - } - } - /* Ranked purchase of an AA ability */ - 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"); - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - } - } - - SendAAStats(); - - CalcBonuses(); - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) - NotifyNewTitlesAvailable(); - } + //Log.Out(Logs::Detail, Logs::AA, "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; + //// Log.Out(Logs::Detail, Logs::AA, "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 + // Log.Out(Logs::Detail, Logs::AA, "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; + //uint8 req_level; + ////std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); + //// + ////if(RequiredLevel != AARequiredLevelAndCost.end()) { + //// real_cost = RequiredLevel->second.Cost; + //// req_level = RequiredLevel->second.Level; + ////} + ////else { + //// real_cost = aa2->cost + (aa2->cost_inc * cur_level); + //// req_level = aa2->class_type + (aa2->level_inc * cur_level); + ////} + // + //if (req_level > GetLevel()) + // return; //Cheater trying to Buy AA... + // + //if (m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { + // SetAA(aa2->id, cur_level + 1); + // + // Log.Out(Logs::Detail, Logs::AA, "Set AA %d to level %d", aa2->id, cur_level + 1); + // + // m_pp.aapoints -= real_cost; + // + // /* Do Player Profile rank calculations and set player profile */ + // SaveAA(); + // /* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/ + // // database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1)); + // + // 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 + // */ + // + // /* Initial purchase of an AA ability */ + // 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"); + // + // /* QS: Player_Log_AA_Purchases */ + // if (RuleB(QueryServ, PlayerLogAAPurchases)){ + // std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); + // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + // } + // } + // /* Ranked purchase of an AA ability */ + // 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"); + // + // /* QS: Player_Log_AA_Purchases */ + // if (RuleB(QueryServ, PlayerLogAAPurchases)){ + // std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); + // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + // } + // } + // + // //SendAAStats(); + // + // CalcBonuses(); + // if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) + // NotifyNewTitlesAvailable(); + //} } void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { @@ -1096,114 +1078,50 @@ void Client::SendAATimers() { safe_delete(outapp); } -void Client::SendAATable() { - //Log.Out(Logs::General, Logs::Status, "SendAATable()"); - //EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); - // - //AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; - //aa2->aa_spent = 10; - //aa2->aa_list[0].AA = 6; - //aa2->aa_list[0].value = 4; - //aa2->aa_list[0].charges = 0; - //aa2->aa_list[1].AA = 11; - //aa2->aa_list[1].value = 4; - //aa2->aa_list[1].charges = 0; - // - ////aa2->aa_spent = GetAAPointsSpent(); - //// - ////uint32 i; - ////for(i=0;i < MAX_PP_AA_ARRAY;i++){ - //// aa2->aa_list[i].AA = aa[i]->value ? aa[i]->AA : 0; // bit of a hack to prevent expendables punching a hole - //// aa2->aa_list[i].value = aa[i]->value; - //// aa2->aa_list[i].charges = aa[i]->charges; - ////} - //QueuePacket(outapp); - //safe_delete(outapp); -} - void Client::SendPreviousAA(uint32 id, int seq){ - Log.Out(Logs::General, Logs::Status, "SendPreviousAA(%u, %i)", id, 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); - Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); - QueuePacket(outapp); - safe_delete(outapp); } void Client::SendAA(uint32 id, int seq) { - Log.Out(Logs::General, Logs::Status, "SendAA(%u, %i)", id, 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; - } - } + //Log.Out(Logs::General, Logs::Status, "SendAA(%u, %i)", id, 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 @@ -1211,250 +1129,182 @@ void Client::SendAA(uint32 id, int seq) { 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 (saa2->special_category == 8) + //{ + // uint32 client_race = this->GetBaseRace(); // - // if (aa_AA){ + // // Drakkin Bloodlines + // if (saa2->aa_expansion > 522) + // { + // if (client_race != 522) + // return; // Check for Drakkin Race // - // if (aa_value > 0) - // aa_AA -= aa_value-1; + // int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline // - // 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 - // } - // } - // } - // } + // if (heritage != saa2->aa_expansion) + // return; + // } + // // Racial AAs + // else if (client_race != saa2->aa_expansion) + // { + // return; // } //} - - //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); - - // this check should work as long as we continue to just add the clients and just increase - // each number .... - if (saa_next && static_cast(GetClientVersion()) < saa_next->clientver - 1) { - 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(){ - Log.Out(Logs::General, Logs::Status, "SendAAList()"); - int total = zone->GetTotalAAs(); - - total = total > 2 ? 2 : total; - for(int i=0;i < total;i++){ - SendAA(0,i); - } -} - -SendAA_Struct* Zone::FindAA(uint32 id) { - return aas_send[id]; -} - -void Zone::LoadAAs() { - Log.Out(Logs::General, Logs::Status, "Loading AA information..."); - totalAAs = database.CountAAs(); - if(totalAAs == 0) { - Log.Out(Logs::General, Logs::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 - Log.Out(Logs::General, Logs::Status, "Loading AA Effects..."); - if (database.LoadAAEffects2()) - Log.Out(Logs::General, Logs::Status, "Loaded %d AA Effects.", aa_effects.size()); - else - Log.Out(Logs::General, Logs::Error, "Failed to load AA Effects!"); -} - -bool ZoneDatabase::LoadAAEffects2() { - aa_effects.clear(); //start fresh - - const std::string query = "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - if (!results.RowCount()) { //no results - return false; - } - - for(auto row = results.begin(); row != results.end(); ++row) { - 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 - } - - return true; + // + ///* + //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); + // + // // this check should work as long as we continue to just add the clients and just increase + // // each number .... + // if (saa_next && static_cast(GetClientVersion()) < saa_next->clientver - 1) { + // 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::ResetAA(){ @@ -1768,262 +1618,6 @@ void Client::InspectBuffs(Client* Inspector, int Rank) Inspector->FastQueuePacket(&outapp); } -//this really need to be renamed to LoadAAActions() -bool ZoneDatabase::LoadAAEffects() { - memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size... - - const std::string 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"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - - int aaid = atoi(row[0]); - int rank = atoi(row[1]); - 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[2]); - caction->spell_id = atoi(row[3]); - caction->target = (aaTargetType) atoi(row[4]); - caction->action = (aaNonspellAction) atoi(row[5]); - caction->mana_cost = atoi(row[6]); - caction->duration = atoi(row[7]); - caction->redux_aa = (aaID) atoi(row[8]); - caction->redux_rate = atoi(row[9]); - caction->redux_aa2 = (aaID) atoi(row[10]); - caction->redux_rate2 = atoi(row[11]); - - } - - 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) { - - std::string query = StringFormat("SELECT count(slot) FROM aa_effects WHERE aaid = %i", skill_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); -} - -//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; - - auto it = aa_effects.find(aa_struct->id); - if (it != aa_effects.end()) { - for (uint32 slot = 0; slot < aa_struct->total_abilities; slot++) { - // aa_effects is a map of a map, so the slot reference does not start at 0 - aa_struct->abilities[slot].skill_id = it->second[slot + 1].skill_id; - aa_struct->abilities[slot].base1 = it->second[slot + 1].base1; - aa_struct->abilities[slot].base2 = it->second[slot + 1].base2; - aa_struct->abilities[slot].slot = it->second[slot + 1].slot; - } - } -} - -uint32 ZoneDatabase::CountAAs(){ - - const std::string query = "SELECT count(title_sid) FROM altadv_vars"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - - return atoi(row[0]);; -} - -uint32 ZoneDatabase::CountAAEffects() { - - const std::string query = "SELECT count(id) FROM aa_effects"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); -} - -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; - - std::string query = "SELECT skill_id FROM altadv_vars ORDER BY skill_id"; - auto results = QueryDatabase(query); - if (results.Success()) { - int skill = 0, index = 0; - for (auto row = results.begin(); row != results.end(); ++row, ++index) { - skill = atoi(row[0]); - load[index] = GetAASkillVars(skill); - load[index]->seq = index+1; - } - } else { - } - - AARequiredLevelAndCost.clear(); - query = "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id"; - results = QueryDatabase(query); - if (!results.Success()) { - return; - } - - AALevelCost_Struct aalcs; - for (auto row = results.begin(); row != results.end(); ++row) { - aalcs.Level = atoi(row[1]); - aalcs.Cost = atoi(row[2]); - AARequiredLevelAndCost[atoi(row[0])] = aalcs; - } -} - -SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id) -{ - std::string query = "SET @row = 0"; //initialize "row" variable in database for next query - auto results = QueryDatabase(query); - if (!results.Success()) { - return nullptr; - } - - query = StringFormat("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); - results = QueryDatabase(query); - if (!results.Success()) { - return nullptr; - } - - if (results.RowCount() != 1) - return nullptr; - - 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); - - SendAA_Struct* sendaa = nullptr; - uchar* buffer; - - buffer = new uchar[totalsize]; - memset(buffer,0,totalsize); - sendaa = (SendAA_Struct*)buffer; - - auto row = results.begin(); - - //ATOI IS NOT UNSIGNED 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])); - - return sendaa; -} - void Client::DurationRampage(uint32 duration) { if(duration) { @@ -2032,6 +1626,56 @@ void Client::DurationRampage(uint32 duration) } } +void Client::RefundAA() { +// int cur = 0; +// bool refunded = false; +// +// for(int x = 0; x < aaHighestID; x++) { +// cur = GetAA(x); +// if(cur > 0){ +// SendAA_Struct* curaa = zone->FindAA(x); +// if(cur){ +// SetAA(x, 0); +// for(int j = 0; j < cur; j++) { +// m_pp.aapoints += curaa->cost + (curaa->cost_inc * j); +// refunded = true; +// } +// } +// else +// { +// m_pp.aapoints += cur; +// SetAA(x, 0); +// refunded = true; +// } +// } +// } +// +// if(refunded) { +// SaveAA(); +// Save(); +// // Kick(); +// } +} + +void Client::IncrementAA(int aa_id) { + //SendAA_Struct* aa2 = zone->FindAA(aa_id); + // + //if(aa2 == nullptr) + // return; + // + //if(GetAA(aa_id) == aa2->max_level) + // return; + // + //SetAA(aa_id, GetAA(aa_id) + 1); + // + //SaveAA(); + // + //SendAA(aa_id); + //SendAATable(); + //SendAAStats(); + //CalcBonuses(); +} + AA_SwarmPetInfo::AA_SwarmPetInfo() { target = 0; @@ -2119,14 +1763,14 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { aai->total_prereqs = rank->prereqs.size(); outapp->SetWritePosition(sizeof(AARankInfo_Struct)); - for(auto effect : rank->effects) { + for(auto &effect : rank->effects) { outapp->WriteSInt32(effect.effect_id); outapp->WriteSInt32(effect.base1); outapp->WriteSInt32(effect.base2); outapp->WriteSInt32(effect.slot); } - for(auto prereq : rank->prereqs) { + for(auto &prereq : rank->prereqs) { outapp->WriteSInt32(prereq.aa_id); outapp->WriteSInt32(prereq.points); } @@ -2135,6 +1779,72 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { safe_delete(outapp); } +void Client::SendAlternateAdvancementStats() { + 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::SendAlternateAdvancementPoints() { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); + AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; + + int i = 0; + for(auto &aa : zone->aa_abilities) { + auto ranks = GetAA(aa.second->first_rank_id); + if(ranks) { + AA::Rank *rank = aa.second->GetRankByPointsSpent(ranks); + if(rank) { + aa2->aa_list[i].AA = rank->id; + aa2->aa_list[i].value = ranks; + aa2->aa_list[i].charges = 0; // todo send charges + i++; + } + } + } + + + aa2->aa_spent = GetAAPointsSpent(); + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::PurchaseAlternateAdvancementRank(int rank_id) { +} + +bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { + c->ClearAAs(); + std::string query = StringFormat( + "SELECT " + "aa_id, " + "aa_value, " + "charges " + "FROM " + "`character_alternate_abilities` " + "WHERE `id` = %u ORDER BY `slot`", c->CharacterID()); + MySQLRequestResult results = database.QueryDatabase(query); + + int i = 0; + for(auto row = results.begin(); row != results.end(); ++row) { + uint32 aa = atoi(row[0]); + uint32 value = atoi(row[1]); + uint32 charges = atoi(row[2]); + + c->GetPP().aa_array[i].AA = aa; + c->GetPP().aa_array[i].value = value; + c->GetPP().aa_array[i].charges = charges; + c->SetAA(aa, value, charges); + i++; + } + + return true; +} + AA::Ability *Zone::GetAlternateAdvancementAbility(int id) { auto iter = aa_abilities.find(id); if(iter != aa_abilities.end()) { @@ -2170,13 +1880,13 @@ uint32 Mob::GetAA(uint32 rank_id) const { auto iter = aa_ranks.find(ability->id); if(iter != aa_ranks.end()) { - return iter->second; + return iter->second.first; } } return 0; } -bool Mob::SetAA(uint32 rank_id, uint32 new_value) { +bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) { if(zone) { AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); @@ -2188,10 +1898,10 @@ bool Mob::SetAA(uint32 rank_id, uint32 new_value) { return false; } - aa_ranks[ability->id] = new_value; + aa_ranks[ability->id] = std::make_pair(new_value, charges); } - return false; + return true; } @@ -2201,6 +1911,14 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { if(!ability) return false; + if(!ability->classes & (1 << GetClass())) { + return false; + } + + if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { + return false; + } + // Passive and Active Shroud AAs // For now we skip them if(ability->category == 3 || ability->category == 4) { @@ -2247,7 +1965,15 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { return false; } - //check other stuff like price later + //check that we have previous rank already + if(rank->prev) { + //rank->prev-> + } + + //check prereqs + + //check price + return true; } @@ -2268,10 +1994,12 @@ void Zone::LoadAlternateAdvancement() { //process these ranks AA::Rank *current = ability.second->first; + int i = 1; while(current) { current->prev = GetAlternateAdvancementRank(current->prev_id); current->next = GetAlternateAdvancementRank(current->next_id); current->base_ability = ability.second.get(); + current->current_value = i; if(current->prev) { current->total_cost = current->cost + current->prev->total_cost; @@ -2280,6 +2008,7 @@ void Zone::LoadAlternateAdvancement() { current->total_cost = current->cost; } + i++; current = current->next; } @@ -2366,7 +2095,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map 12) + if(effect.slot < 1) continue; if(ranks.count(rank_id) > 0) { @@ -2389,7 +2118,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map 0) { AA::Rank *rank = ranks[rank_id].get(); diff --git a/zone/aa.h b/zone/aa.h index ad41fc3ae..54d495e6e 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -2137,17 +2137,6 @@ struct AALevelCost_Struct uint32 Cost; }; -//assumes that no activatable aa.has more than 5 ranks -#define MAX_AA_ACTION_RANKS 20 -extern AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] -extern std::map AA_SwarmPets; //key=spell_id - -#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3)) - -extern std::mapaas_send; -extern std::map > aa_effects; -extern std::map AARequiredLevelAndCost; - enum { //values of AA_Action.action aaActionActivate = 0, aaActionSetEXP = 1, diff --git a/zone/aa_rank.h b/zone/aa_rank.h index 20628a506..a824f2c82 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -43,6 +43,7 @@ public: Rank *prev; int next_id; Rank *next; + int current_value; int expansion; uint32 account_time_required; int total_cost; diff --git a/zone/attack.cpp b/zone/attack.cpp index a229f197e..74cb33272 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4659,38 +4659,39 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui proc_spell_id = 0; ProcMod = 0; - std::map >::const_iterator find_iter = aa_effects.find(aaid); - if(find_iter == aa_effects.end()) - break; + //old AA + //std::map >::const_iterator find_iter = aa_effects.find(aaid); + //if(find_iter == aa_effects.end()) + // break; - 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; - - if (effect == SE_SkillProc || effect == SE_SkillProcSuccess) { - proc_spell_id = base1; - ProcMod = static_cast(base2); - } - - else if (effect == SE_LimitToSkill && base1 <= HIGHEST_SKILL) { - - if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { - float final_chance = chance * (ProcMod / 100.0f); - - if (zone->random.Roll(final_chance)) { - ExecWeaponProc(nullptr, proc_spell_id, on); - CanProc = false; - break; - } - } - } - else { - proc_spell_id = 0; - ProcMod = 0; - } - } + //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; + // + // if (effect == SE_SkillProc || effect == SE_SkillProcSuccess) { + // proc_spell_id = base1; + // ProcMod = static_cast(base2); + // } + // + // else if (effect == SE_LimitToSkill && base1 <= HIGHEST_SKILL) { + // + // if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { + // float final_chance = chance * (ProcMod / 100.0f); + // + // if (zone->random.Roll(final_chance)) { + // ExecWeaponProc(nullptr, proc_spell_id, on); + // CanProc = false; + // break; + // } + // } + // } + // else { + // proc_spell_id = 0; + // ProcMod = 0; + // } + //} } } } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index a2a180cef..437befe11 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -671,772 +671,773 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) 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.Out(Logs::Detail, Logs::AA, "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] = static_cast(effect); - continue; - } - - switch (effect) - { - //Note: AA effects that use accuracy are skill limited, while spell effect is not. - case SE_Accuracy: - if ((base2 == ALL_SKILLS) && (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->AvoidMeleeChanceEffect += 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_HitChance: - { - if(base2 == ALL_SKILLS) - newbon->HitChanceEffect[HIGHEST_SKILL+1] += base1; - else - newbon->HitChanceEffect[base2] += base1; - } - - 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 == ALL_SKILLS) - 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 == ALL_SKILLS) - 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 == ALL_SKILLS) - 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 == ALL_SKILLS) - newbon->DamageModifier[HIGHEST_SKILL+1] += base1; - else - newbon->DamageModifier[base2] += base1; - break; - } - - case SE_DamageModifier2: - { - if(base2 == ALL_SKILLS) - 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; - - case SE_MeleeVulnerability: - newbon->MeleeVulnerability += base1; - break; - - case SE_FactionModPct: - { - if((base1 < 0) && (newbon->FactionModPct > base1)) - newbon->FactionModPct = base1; - - else if(newbon->FactionModPct < base1) - newbon->FactionModPct = base1; - break; - } - - case SE_IllusionPersistence: - newbon->IllusionPersistence = true; - break; - - case SE_LimitToSkill:{ - if (base1 <= HIGHEST_SKILL) - newbon->LimitToSkill[base1] = true; - break; - } - - case SE_SkillProc:{ - for(int e = 0; e < MAX_SKILL_PROCS; e++) - { - if(newbon->SkillProc[e] && newbon->SkillProc[e] == aaid) - break; //Do not use the same aa id more than once. - - else if(!newbon->SkillProc[e]){ - newbon->SkillProc[e] = aaid; - break; - } - } - break; - } - - case SE_SkillProcSuccess:{ - - for(int e = 0; e < MAX_SKILL_PROCS; e++) - { - if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid) - break; //Do not use the same spell id more than once. - - else if(!newbon->SkillProcSuccess[e]){ - newbon->SkillProcSuccess[e] = aaid; - break; - } - } - break; - } - - case SE_MeleeMitigation: - newbon->MeleeMitigationEffect -= base1; - break; - - } - } + //AA old + //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.Out(Logs::Detail, Logs::AA, "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] = static_cast(effect); + // continue; + // } + // + // switch (effect) + // { + // //Note: AA effects that use accuracy are skill limited, while spell effect is not. + // case SE_Accuracy: + // if ((base2 == ALL_SKILLS) && (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->AvoidMeleeChanceEffect += 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_HitChance: + // { + // if(base2 == ALL_SKILLS) + // newbon->HitChanceEffect[HIGHEST_SKILL+1] += base1; + // else + // newbon->HitChanceEffect[base2] += base1; + // } + // + // 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 == ALL_SKILLS) + // 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 == ALL_SKILLS) + // 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 == ALL_SKILLS) + // 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 == ALL_SKILLS) + // newbon->DamageModifier[HIGHEST_SKILL+1] += base1; + // else + // newbon->DamageModifier[base2] += base1; + // break; + // } + // + // case SE_DamageModifier2: + // { + // if(base2 == ALL_SKILLS) + // 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; + // + // case SE_MeleeVulnerability: + // newbon->MeleeVulnerability += base1; + // break; + // + // case SE_FactionModPct: + // { + // if((base1 < 0) && (newbon->FactionModPct > base1)) + // newbon->FactionModPct = base1; + // + // else if(newbon->FactionModPct < base1) + // newbon->FactionModPct = base1; + // break; + // } + // + // case SE_IllusionPersistence: + // newbon->IllusionPersistence = true; + // break; + // + // case SE_LimitToSkill:{ + // if (base1 <= HIGHEST_SKILL) + // newbon->LimitToSkill[base1] = true; + // break; + // } + // + // case SE_SkillProc:{ + // for(int e = 0; e < MAX_SKILL_PROCS; e++) + // { + // if(newbon->SkillProc[e] && newbon->SkillProc[e] == aaid) + // break; //Do not use the same aa id more than once. + // + // else if(!newbon->SkillProc[e]){ + // newbon->SkillProc[e] = aaid; + // break; + // } + // } + // break; + // } + // + // case SE_SkillProcSuccess:{ + // + // for(int e = 0; e < MAX_SKILL_PROCS; e++) + // { + // if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid) + // break; //Do not use the same spell id more than once. + // + // else if(!newbon->SkillProcSuccess[e]){ + // newbon->SkillProcSuccess[e] = aaid; + // break; + // } + // } + // break; + // } + // + // case SE_MeleeMitigation: + // newbon->MeleeMitigationEffect -= base1; + // break; + // + // } + //} } void Mob::CalcSpellBonuses(StatBonuses* newbon) diff --git a/zone/bot.cpp b/zone/bot.cpp index 8b3741443..c6c0f6e7f 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -193,7 +193,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to GenerateBaseStats(); LoadTimers(); - LoadAAs(); + //LoadAAs(); old aa, replace this LoadBuffs(); CalcBotStats(false); @@ -1430,114 +1430,103 @@ void Bot::GenerateAABonuses(StatBonuses* newbon) { uint8 botLevel = GetLevel(); memset(newbon, 0, sizeof(StatBonuses)); //start fresh - - if(botLevel >= 51) { - //level 51 = 1 AA level - - int i; - int totalAAs = database.CountAAs(); - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; - for (i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs - std::map::iterator aa = botAAs.find(i); - if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone - aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table - aa_value = aa->second.total_levels; //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 + aa_value -1, slots, newbon); //add the bonuses - } - } - } - } + //old aa + //if(botLevel >= 51) { + // //level 51 = 1 AA level + // + // int i; + // int totalAAs = database.CountAAs(); + // uint32 slots = 0; + // uint32 aa_AA = 0; + // uint32 aa_value = 0; + // for (i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs + // std::map::iterator aa = botAAs.find(i); + // if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone + // aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table + // aa_value = aa->second.total_levels; //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 + aa_value -1, slots, newbon); //add the bonuses + // } + // } + // } + //} } -void Bot::LoadAAs() { - int maxAAExpansion = RuleI(Bots, BotAAExpansion); //get expansion to get AAs up to - botAAs.clear(); //start fresh - - std::string query; - - if(GetClass() == BERSERKER) - query = StringFormat("SELECT skill_id FROM altadv_vars WHERE berserker = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetLevel(), maxAAExpansion); - else - query = StringFormat("SELECT skill_id FROM altadv_vars WHERE ((classes & ( 1 << %i )) >> %i) = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetClass(), GetClass(), GetLevel(), maxAAExpansion); - - auto results = database.QueryDatabase(query); - - if(!results.Success()) { - Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadAAs()"); - return; - } - - int totalAAs = database.CountAAs(); - - for (auto row = results.begin(); row != results.end(); ++row) { - uint32 skill_id = 0; - skill_id = atoi(row[0]); - - if(skill_id <= 0 || skill_id >= totalAAs) - continue; - - SendAA_Struct *sendAA = zone->FindAA(skill_id); - - if(!sendAA) - continue; - - for(int i=0; imax_level; i++) { - //Get AA info & add to list - uint32 aaid = sendAA->id + i; - uint8 total_levels = 0; - uint8 req_level; - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(aaid); - - //Get level required for AA - if(RequiredLevel != AARequiredLevelAndCost.end()) - req_level = RequiredLevel->second.Level; - else - req_level = (sendAA->class_type + i * sendAA->level_inc); - - if(req_level > GetLevel()) - break; - - //Bot is high enough level for AA - std::map::iterator foundAA = botAAs.find(aaid); - - // AA is already in list - if(foundAA != botAAs.end()) - continue; - - if(sendAA->id == aaid) { - BotAA newAA; - - newAA.total_levels = 0; - newAA.aa_id = aaid; - newAA.req_level = req_level; - newAA.total_levels += 1; - - botAAs[aaid] = newAA; //add to list - } - else //update master AA record with number of levels a bot has in AA, based on level. - botAAs[sendAA->id].total_levels+=1; - } - } - -} - -uint32 Bot::GetAA(uint32 aa_id) { - - std::map::const_iterator find_iter = botAAs.find(aa_id); - int aaLevel = 0; - - if(find_iter != botAAs.end()) { - aaLevel = find_iter->second.total_levels; - } - - return aaLevel; -} +//old AA +//void Bot::LoadAAs() { +// int maxAAExpansion = RuleI(Bots, BotAAExpansion); //get expansion to get AAs up to +// botAAs.clear(); //start fresh +// +// std::string query; +// +// if(GetClass() == BERSERKER) +// query = StringFormat("SELECT skill_id FROM altadv_vars WHERE berserker = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetLevel(), maxAAExpansion); +// else +// query = StringFormat("SELECT skill_id FROM altadv_vars WHERE ((classes & ( 1 << %i )) >> %i) = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetClass(), GetClass(), GetLevel(), maxAAExpansion); +// +// auto results = database.QueryDatabase(query); +// +// if(!results.Success()) { +// Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadAAs()"); +// return; +// } +// +// int totalAAs = database.CountAAs(); +// +// for (auto row = results.begin(); row != results.end(); ++row) { +// uint32 skill_id = 0; +// skill_id = atoi(row[0]); +// +// if(skill_id <= 0 || skill_id >= totalAAs) +// continue; +// +// SendAA_Struct *sendAA = zone->FindAA(skill_id); +// +// if(!sendAA) +// continue; +// +// for(int i=0; imax_level; i++) { +// //Get AA info & add to list +// uint32 aaid = sendAA->id + i; +// uint8 total_levels = 0; +// uint8 req_level; +// std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(aaid); +// +// //Get level required for AA +// if(RequiredLevel != AARequiredLevelAndCost.end()) +// req_level = RequiredLevel->second.Level; +// else +// req_level = (sendAA->class_type + i * sendAA->level_inc); +// +// if(req_level > GetLevel()) +// break; +// +// //Bot is high enough level for AA +// std::map::iterator foundAA = botAAs.find(aaid); +// +// // AA is already in list +// if(foundAA != botAAs.end()) +// continue; +// +// if(sendAA->id == aaid) { +// BotAA newAA; +// +// newAA.total_levels = 0; +// newAA.aa_id = aaid; +// newAA.req_level = req_level; +// newAA.total_levels += 1; +// +// botAAs[aaid] = newAA; //add to list +// } +// else //update master AA record with number of levels a bot has in AA, based on level. +// botAAs[sendAA->id].total_levels+=1; +// } +// } +// +//} //current with Client::ApplyAABonuses 9/26/12 void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) @@ -1551,551 +1540,552 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) 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.Out(Logs::Detail, Logs::AA, "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_ArcheryDamageModifier: - newbon->ArcheryDamageModifier += 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_PetCriticalHit: - newbon->PetCriticalHit += base1; - break; - case SE_PetAvoidance: - newbon->PetAvoidance += base1; - break; - case SE_ShieldBlock: - newbon->ShieldBlock += base1; - 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_StrikeThrough2: - newbon->StrikeThrough += base1; - break; - case SE_DoubleAttackChance: - newbon->DoubleAttackChance += base1; - break; - case SE_GiveDoubleAttack: - newbon->GiveDoubleAttack += base1; - break; - case SE_ProcChance: - newbon->ProcChance += 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_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->SpellCritDmgIncrease) - newbon->SpellCritDmgIncrease = 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_SlayUndead: - { - if(newbon->SlayUndead[1] < base1) - newbon->SlayUndead[0] = base1; // Rate - newbon->SlayUndead[1] = base2; // Damage Modifier - break; - } - - 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] || ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < base1)) ){ - newbon->SEResist[e] = base2; - newbon->SEResist[e+1] = base1; - 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; - } - } - } + //old AA + //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.Out(Logs::Detail, Logs::AA, "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_ArcheryDamageModifier: + // newbon->ArcheryDamageModifier += 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_PetCriticalHit: + // newbon->PetCriticalHit += base1; + // break; + // case SE_PetAvoidance: + // newbon->PetAvoidance += base1; + // break; + // case SE_ShieldBlock: + // newbon->ShieldBlock += base1; + // 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_StrikeThrough2: + // newbon->StrikeThrough += base1; + // break; + // case SE_DoubleAttackChance: + // newbon->DoubleAttackChance += base1; + // break; + // case SE_GiveDoubleAttack: + // newbon->GiveDoubleAttack += base1; + // break; + // case SE_ProcChance: + // newbon->ProcChance += 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_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->SpellCritDmgIncrease) + // newbon->SpellCritDmgIncrease = 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_SlayUndead: + // { + // if(newbon->SlayUndead[1] < base1) + // newbon->SlayUndead[0] = base1; // Rate + // newbon->SlayUndead[1] = base2; // Damage Modifier + // break; + // } + // + // 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] || ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < base1)) ){ + // newbon->SEResist[e] = base2; + // newbon->SEResist[e+1] = base1; + // 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; + // } + // } + //} } bool Bot::IsValidRaceClassCombo() { @@ -6326,398 +6316,399 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) bool LimitFound = false; int FocusCount = 0; - std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - if(find_iter == aa_effects.end()) - { - return 0; - } + //old AA + //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); + //if(find_iter == aa_effects.end()) + //{ + // return 0; + //} + // + //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) + //{ + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // //AA Foci's can contain multiple focus effects within the same AA. + // //To handle this we will not automatically return zero if a limit is found. + // //Instead if limit is found and multiple effects, we will reset the limit check + // //when the next valid focus effect is found. + // if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ + // FocusCount++; + // //If limit found on prior check next, else end loop. + // if (FocusCount > 1){ + // if (LimitFound){ + // value = 0; + // LimitFound = false; + // } + // + // else{ + // break; + // } + // } + // } + // + // + // switch (effect) + // { + // case SE_Blank: + // break; + // + // //Handle Focus Limits + // case SE_LimitResist: + // if(base1) + // { + // if(spell.resisttype != base1) + // LimitFound = true; + // } + // break; + // case SE_LimitInstant: + // if(spell.buffduration) + // LimitFound = true; + // break; + // case SE_LimitMaxLevel: + // spell_level = spell.classes[(GetClass()%16) - 1]; + // lvldiff = spell_level - base1; + // //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true + // if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) + // { + // if(base2 > 0) + // { + // lvlModifier -= base2*lvldiff; + // if(lvlModifier < 1) + // LimitFound = true; + // } + // else { + // LimitFound = true; + // } + // } + // break; + // case SE_LimitMinLevel: + // if((spell.classes[(GetClass()%16) - 1]) < base1) + // LimitFound = true; + // break; + // case SE_LimitCastTimeMin: + // if (spell.cast_time < base1) + // LimitFound = true; + // break; + // case SE_LimitSpell: + // // Exclude spell(any but this) + // if(base1 < 0) { + // if (spell_id == (base1*-1)) + // LimitFound = true; + // } + // else { + // // Include Spell(only this) + // if (spell_id != base1) + // LimitFound = true; + // } + // break; + // case SE_LimitMinDur: + // if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + // LimitFound = true; + // break; + // case SE_LimitEffect: + // // Exclude effect(any but this) + // if(base1 < 0) { + // if(IsEffectInSpell(spell_id,(base1*-1))) + // LimitFound = true; + // } + // else { + // // Include effect(only this) + // if(!IsEffectInSpell(spell_id,base1)) + // LimitFound = true; + // } + // break; + // case SE_LimitSpellType: + // switch(base1) + // { + // case 0: + // if (!IsDetrimentalSpell(spell_id)) + // LimitFound = true; + // break; + // case 1: + // if (!IsBeneficialSpell(spell_id)) + // LimitFound = true; + // break; + // } + // break; + // + // case SE_LimitManaMin: + // if(spell.mana < base1) + // LimitFound = true; + // break; + // + // case SE_LimitTarget: + // // Exclude + // if(base1 < 0){ + // if(-base1 == spell.targettype) + // LimitFound = true; + // } + // // Include + // else { + // if(base1 != spell.targettype) + // LimitFound = true; + // } + // break; + // + // case SE_LimitCombatSkills: + // // 1 is for disciplines only + // if(base1 == 1 && !IsDiscipline(spell_id)) + // LimitFound = true; + // // 0 is spells only + // else if(base1 == 0 && IsDiscipline(spell_id)) + // LimitFound = true; + // break; + // + // case SE_LimitSpellGroup: + // if(base1 > 0 && base1 != spell.spellgroup) + // LimitFound = true; + // else if(base1 < 0 && base1 == spell.spellgroup) + // LimitFound = true; + // break; + // + // + // case SE_LimitCastingSkill: + // LimitSpellSkill = true; + // if(base1 == spell.skill) + // SpellSkill_Found = true; + // break; + // + // case SE_LimitClass: + // //Do not use this limit more then once per spell. If multiple class, treat value like items would. + // if (!PassLimitClass(base1, GetClass())) + // LimitFound = true; + // break; + // + // + // //Handle Focus Effects + // case SE_ImprovedDamage: + // if (type == focusImprovedDamage && base1 > value) + // value = base1; + // break; + // + // case SE_ImprovedHeal: + // if (type == focusImprovedHeal && base1 > value) + // value = base1; + // break; + // + // case SE_ReduceManaCost: + // if (type == focusManaCost ) + // value = base1; + // break; + // + // case SE_IncreaseSpellHaste: + // if (type == focusSpellHaste && base1 > value) + // value = base1; + // break; + // + // case SE_IncreaseSpellDuration: + // if (type == focusSpellDuration && base1 > value) + // value = base1; + // break; + // + // case SE_SpellDurationIncByTic: + // if (type == focusSpellDurByTic && base1 > value) + // value = base1; + // break; + // + // case SE_SwarmPetDuration: + // if (type == focusSwarmPetDuration && base1 > value) + // value = base1; + // break; + // + // case SE_IncreaseRange: + // if (type == focusRange && base1 > value) + // value = base1; + // break; + // + // case SE_ReduceReagentCost: + // if (type == focusReagentCost && base1 > value) + // value = base1; + // break; + // + // case SE_PetPowerIncrease: + // if (type == focusPetPower && base1 > value) + // value = base1; + // break; + // + // case SE_SpellResistReduction: + // if (type == focusResistRate && base1 > value) + // value = base1; + // break; + // + // case SE_SpellHateMod: + // if (type == focusSpellHateMod) + // { + // if(value != 0) + // { + // if(value > 0) + // { + // if(base1 > value) + // { + // value = base1; + // } + // } + // else + // { + // if(base1 < value) + // { + // value = base1; + // } + // } + // } + // else + // value = base1; + // } + // break; + // + // case SE_ReduceReuseTimer: + // { + // if(type == focusReduceRecastTime) + // value = base1 / 1000; + // + // break; + // } + // + // case SE_TriggerOnCast: + // { + // if(type == focusTriggerOnCast) + // { + // if(zone->random.Int(0, 100) <= base1){ + // value = base2; + // } + // + // else{ + // value = 0; + // LimitFound = true; + // } + // } + // break; + // } + // case SE_FcSpellVulnerability: + // { + // if(type == focusSpellVulnerability) + // { + // value = base1; + // } + // break; + // } + // case SE_BlockNextSpellFocus: + // { + // if(type == focusBlockNextSpell) + // { + // if(zone->random.Int(1, 100) <= base1) + // value = 1; + // } + // break; + // } + // case SE_FcTwincast: + // { + // if(type == focusTwincast) + // { + // 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); + // + // if(zone->random.Real(0, 1) <= ProcChance) + // value = focus_id; + // + // else + // value = 0; + // } + // break; + // } + // */ + // case SE_FcDamageAmt: + // { + // if(type == focusFcDamageAmt) + // value = base1; + // + // break; + // } + // + // case SE_FcDamageAmtCrit: + // { + // if(type == focusFcDamageAmtCrit) + // value = base1; + // + // break; + // } + // + // case SE_FcDamageAmtIncoming: + // { + // if(type == focusFcDamageAmtIncoming) + // value = base1; + // + // break; + // } + // + // case SE_FcHealAmtIncoming: + // if(type == focusFcHealAmtIncoming) + // value = base1; + // break; + // + // case SE_FcHealPctCritIncoming: + // if (type == focusFcHealPctCritIncoming) + // value = base1; + // break; + // + // case SE_FcHealAmtCrit: + // if(type == focusFcHealAmtCrit) + // value = base1; + // break; + // + // case SE_FcHealAmt: + // if(type == focusFcHealAmt) + // value = base1; + // break; + // + // case SE_FcHealPctIncoming: + // if(type == focusFcHealPctIncoming) + // value = base1; + // break; + // + // case SE_FcBaseEffects: + // { + // if (type == focusFcBaseEffects) + // value = base1; + // + // break; + // } + // case SE_FcDamagePctCrit: + // { + // if(type == focusFcDamagePctCrit) + // value = base1; + // + // break; + // } + // + // case SE_FcIncreaseNumHits: + // { + // if(type == focusIncreaseNumHits) + // value = base1; + // + // break; + // } - for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - //AA Foci's can contain multiple focus effects within the same AA. - //To handle this we will not automatically return zero if a limit is found. - //Instead if limit is found and multiple effects, we will reset the limit check - //when the next valid focus effect is found. - if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ - FocusCount++; - //If limit found on prior check next, else end loop. - if (FocusCount > 1){ - if (LimitFound){ - value = 0; - LimitFound = false; - } - - else{ - break; - } - } - } - - - switch (effect) - { - case SE_Blank: - break; - - //Handle Focus Limits - case SE_LimitResist: - if(base1) - { - if(spell.resisttype != base1) - LimitFound = true; - } - break; - case SE_LimitInstant: - if(spell.buffduration) - LimitFound = true; - break; - case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass()%16) - 1]; - lvldiff = spell_level - base1; - //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) - { - if(base2 > 0) - { - lvlModifier -= base2*lvldiff; - if(lvlModifier < 1) - LimitFound = true; - } - else { - LimitFound = true; - } - } - break; - case SE_LimitMinLevel: - if((spell.classes[(GetClass()%16) - 1]) < base1) - LimitFound = true; - break; - case SE_LimitCastTimeMin: - if (spell.cast_time < base1) - LimitFound = true; - break; - case SE_LimitSpell: - // Exclude spell(any but this) - if(base1 < 0) { - if (spell_id == (base1*-1)) - LimitFound = true; - } - else { - // Include Spell(only this) - if (spell_id != base1) - LimitFound = true; - } - break; - case SE_LimitMinDur: - if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - LimitFound = true; - break; - case SE_LimitEffect: - // Exclude effect(any but this) - if(base1 < 0) { - if(IsEffectInSpell(spell_id,(base1*-1))) - LimitFound = true; - } - else { - // Include effect(only this) - if(!IsEffectInSpell(spell_id,base1)) - LimitFound = true; - } - break; - case SE_LimitSpellType: - switch(base1) - { - case 0: - if (!IsDetrimentalSpell(spell_id)) - LimitFound = true; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) - LimitFound = true; - break; - } - break; - - case SE_LimitManaMin: - if(spell.mana < base1) - LimitFound = true; - break; - - case SE_LimitTarget: - // Exclude - if(base1 < 0){ - if(-base1 == spell.targettype) - LimitFound = true; - } - // Include - else { - if(base1 != spell.targettype) - LimitFound = true; - } - break; - - case SE_LimitCombatSkills: - // 1 is for disciplines only - if(base1 == 1 && !IsDiscipline(spell_id)) - LimitFound = true; - // 0 is spells only - else if(base1 == 0 && IsDiscipline(spell_id)) - LimitFound = true; - break; - - case SE_LimitSpellGroup: - if(base1 > 0 && base1 != spell.spellgroup) - LimitFound = true; - else if(base1 < 0 && base1 == spell.spellgroup) - LimitFound = true; - break; - - - case SE_LimitCastingSkill: - LimitSpellSkill = true; - if(base1 == spell.skill) - SpellSkill_Found = true; - break; - - case SE_LimitClass: - //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(base1, GetClass())) - LimitFound = true; - break; - - - //Handle Focus Effects - case SE_ImprovedDamage: - if (type == focusImprovedDamage && base1 > value) - value = base1; - break; - - case SE_ImprovedHeal: - if (type == focusImprovedHeal && base1 > value) - value = base1; - break; - - case SE_ReduceManaCost: - if (type == focusManaCost ) - value = base1; - break; - - case SE_IncreaseSpellHaste: - if (type == focusSpellHaste && base1 > value) - value = base1; - break; - - case SE_IncreaseSpellDuration: - if (type == focusSpellDuration && base1 > value) - value = base1; - break; - - case SE_SpellDurationIncByTic: - if (type == focusSpellDurByTic && base1 > value) - value = base1; - break; - - case SE_SwarmPetDuration: - if (type == focusSwarmPetDuration && base1 > value) - value = base1; - break; - - case SE_IncreaseRange: - if (type == focusRange && base1 > value) - value = base1; - break; - - case SE_ReduceReagentCost: - if (type == focusReagentCost && base1 > value) - value = base1; - break; - - case SE_PetPowerIncrease: - if (type == focusPetPower && base1 > value) - value = base1; - break; - - case SE_SpellResistReduction: - if (type == focusResistRate && base1 > value) - value = base1; - break; - - case SE_SpellHateMod: - if (type == focusSpellHateMod) - { - if(value != 0) - { - if(value > 0) - { - if(base1 > value) - { - value = base1; - } - } - else - { - if(base1 < value) - { - value = base1; - } - } - } - else - value = base1; - } - break; - - case SE_ReduceReuseTimer: - { - if(type == focusReduceRecastTime) - value = base1 / 1000; - - break; - } - - case SE_TriggerOnCast: - { - if(type == focusTriggerOnCast) - { - if(zone->random.Int(0, 100) <= base1){ - value = base2; - } - - else{ - value = 0; - LimitFound = true; - } - } - break; - } - case SE_FcSpellVulnerability: - { - if(type == focusSpellVulnerability) - { - value = base1; - } - break; - } - case SE_BlockNextSpellFocus: - { - if(type == focusBlockNextSpell) - { - if(zone->random.Int(1, 100) <= base1) - value = 1; - } - break; - } - case SE_FcTwincast: - { - if(type == focusTwincast) - { - 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); - - if(zone->random.Real(0, 1) <= ProcChance) - value = focus_id; - - else - value = 0; - } - break; - } - */ - case SE_FcDamageAmt: - { - if(type == focusFcDamageAmt) - value = base1; - - break; - } - - case SE_FcDamageAmtCrit: - { - if(type == focusFcDamageAmtCrit) - value = base1; - - break; - } - - case SE_FcDamageAmtIncoming: - { - if(type == focusFcDamageAmtIncoming) - value = base1; - - break; - } - - case SE_FcHealAmtIncoming: - if(type == focusFcHealAmtIncoming) - value = base1; - break; - - case SE_FcHealPctCritIncoming: - if (type == focusFcHealPctCritIncoming) - value = base1; - break; - - case SE_FcHealAmtCrit: - if(type == focusFcHealAmtCrit) - value = base1; - break; - - case SE_FcHealAmt: - if(type == focusFcHealAmt) - value = base1; - break; - - case SE_FcHealPctIncoming: - if(type == focusFcHealPctIncoming) - value = base1; - break; - - case SE_FcBaseEffects: - { - if (type == focusFcBaseEffects) - value = base1; - - break; - } - case SE_FcDamagePctCrit: - { - if(type == focusFcDamagePctCrit) - value = base1; - - break; - } - - case SE_FcIncreaseNumHits: - { - if(type == focusIncreaseNumHits) - value = base1; - - break; - } - - //Check for spell skill limits. - if ((LimitSpellSkill) && (!SpellSkill_Found)) - return 0; - - } - } + ////Check for spell skill limits. + //if ((LimitSpellSkill) && (!SpellSkill_Found)) + // return 0; + // + // } + //} if (LimitFound){ return 0; @@ -6885,30 +6876,30 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { // AA Focus if (aabonuses.FocusEffects[bottype]){ - - int totalAAs = database.CountAAs(); - int32 Total3 = 0; - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; - - for (int i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs - std::map::iterator aa = botAAs.find(i); - if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone - aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table - aa_value = aa->second.total_levels; //how many points in it - if (aa_AA < 1 || aa_value < 1) - continue; - - Total3 = CalcBotAAFocus(bottype, aa_AA, spell_id); - if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { - realTotal3 = Total3; - } - else if (Total3 < 0 && Total3 < realTotal3) { - realTotal3 = Total3; - } - } - } + //old aa + //int totalAAs = database.CountAAs(); + //int32 Total3 = 0; + //uint32 slots = 0; + //uint32 aa_AA = 0; + //uint32 aa_value = 0; + // + //for (int i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs + // std::map::iterator aa = botAAs.find(i); + // if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone + // aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table + // aa_value = aa->second.total_levels; //how many points in it + // if (aa_AA < 1 || aa_value < 1) + // continue; + // + // Total3 = CalcBotAAFocus(bottype, aa_AA, spell_id); + // if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { + // realTotal3 = Total3; + // } + // else if (Total3 < 0 && Total3 < realTotal3) { + // realTotal3 = Total3; + // } + // } + //} } if(bottype == BotfocusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) @@ -8940,6 +8931,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { break; } + //aa old bonus += 0.05 * GetAA(aaAdvancedSpellCastingMastery); if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) diff --git a/zone/bot.h b/zone/bot.h index 25e0d1c52..1f1262ffc 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -448,8 +448,6 @@ public: bool IsBotWISCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN); } bool CanHeal(); int GetRawACNoShield(int &shield_ac); - void LoadAAs(); - uint32 GetAA(uint32 aa_id); void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon); bool GetHasBeenSummoned() { return _hasBeenSummoned; } const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; } diff --git a/zone/client.cpp b/zone/client.cpp index f7510f855..24968f005 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -439,7 +439,7 @@ void Client::SendZoneInPackets() //Send AA Exp packet: if (GetLevel() >= 51) - SendAAStats(); + SendAlternateAdvancementStats(); // Send exp packets outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct)); @@ -8040,56 +8040,6 @@ void Client::TryItemTimer(int slot) } } -void Client::RefundAA() { - int cur = 0; - bool refunded = false; - - for(int x = 0; x < aaHighestID; x++) { - cur = GetAA(x); - if(cur > 0){ - SendAA_Struct* curaa = zone->FindAA(x); - if(cur){ - SetAA(x, 0); - for(int j = 0; j < cur; j++) { - m_pp.aapoints += curaa->cost + (curaa->cost_inc * j); - refunded = true; - } - } - else - { - m_pp.aapoints += cur; - SetAA(x, 0); - refunded = true; - } - } - } - - if(refunded) { - SaveAA(); - Save(); - // Kick(); - } -} - -void Client::IncrementAA(int aa_id) { - SendAA_Struct* aa2 = zone->FindAA(aa_id); - - if(aa2 == nullptr) - return; - - if(GetAA(aa_id) == aa2->max_level) - return; - - SetAA(aa_id, GetAA(aa_id) + 1); - - SaveAA(); - - SendAA(aa_id); - SendAATable(); - SendAAStats(); - CalcBonuses(); -} - void Client::SendItemScale(ItemInst *inst) { int slot = m_inv.GetSlotByItemInst(inst); if(slot != -1) { diff --git a/zone/client.h b/zone/client.h index 0b105c3ef..bd2c5371d 100644 --- a/zone/client.h +++ b/zone/client.h @@ -762,9 +762,16 @@ public: //New AA Methods void SendAlternateAdvancementRank(int aa_id, int level); void SendAlternateAdvancementTable(); + void SendAlternateAdvancementStats(); + void PurchaseAlternateAdvancementRank(int rank_id); + void SendAlternateAdvancementPoints(); + + void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } + void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } + int GetAAPoints() { return m_pp.aapoints; } + int GetSpentAA() { return m_pp.aapoints_spent; } //old AA Methods - void SendAAList(); void ResetAA(); void SendClearAA(); void SendAA(uint32 id, int seq=1); @@ -776,7 +783,6 @@ public: void SetTitleSuffix(const char *txt); inline uint32 GetMaxAAXP(void) const { return max_AAXP; } inline uint32 GetAAXP() const { return m_pp.expAA; } - void SendAAStats(); void SendAATable(); void SendAATimers(); int GetAATimerID(aaID activate); @@ -790,10 +796,6 @@ public: inline uint32 GetAAPointsSpent() { return m_pp.aapoints_spent; } int16 CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id); int16 CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id); - void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAAStats(); } - void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAAStats(); } - int GetAAPoints() { return m_pp.aapoints; } - int GetSpentAA() { return m_pp.aapoints_spent; } void RefundAA(); void IncrementAA(int aa_id); int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f97873db3..e7d3b61a7 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1152,7 +1152,7 @@ void Client::Handle_Connect_OP_TGB(const EQApplicationPacket *app) void Client::Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app) { - SendAATable(); + SendAlternateAdvancementPoints(); } void Client::Handle_Connect_OP_WearChange(const EQApplicationPacket *app) @@ -1439,61 +1439,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; } if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; } - /* Initialize AA's : Move to function eventually */ - //aa old - //for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++) - // aa[a] = &m_pp.aa_array[a]; - //query = StringFormat( - // "SELECT " - // "slot, " - // "aa_id, " - // "aa_value, " - // "charges " - // "FROM " - // "`character_alternate_abilities` " - // "WHERE `id` = %u ORDER BY `slot`", this->CharacterID()); - //results = database.QueryDatabase(query); i = 0; - //int offset = 0; // offset to fix the hole from expendables - //for (auto row = results.begin(); row != results.end(); ++row) { - // i = atoi(row[0]) - offset; - // m_pp.aa_array[i].AA = atoi(row[1]); - // m_pp.aa_array[i].value = atoi(row[2]); - // m_pp.aa_array[i].charges = atoi(row[3]); - // /* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use. - // We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load! - // Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable - // and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple - // entries for a single AA. - // */ - // if (m_pp.aa_array[i].value == 0) - // offset++; - //} - //for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ - // uint32 id = aa[a]->AA; - // //watch for invalid AA IDs - // if (id == aaNone) - // continue; - // if (id >= aaHighestID) { - // aa[a]->AA = aaNone; - // aa[a]->value = 0; - // continue; - // } - // if (aa[a]->value == 0) { - // aa[a]->AA = aaNone; - // continue; - // } - // if (aa[a]->value > HIGHEST_AA_VALUE) { - // aa[a]->AA = aaNone; - // aa[a]->value = 0; - // continue; - // } - // - // //aa old -// // if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */ -// // aa_points[(id - aa[a]->value + 1)] = aa[a]->value; -// // else -// // aa_points[id] = aa[a]->value; - //} + if(!database.LoadAlternateAdvancement(this)) { + Log.Out(Logs::General, Logs::Error, "Error loading AA points for %s", GetName()); + } if (SPDAT_RECORDS > 0) { for (uint32 z = 0; zsize != sizeof(AA_Action)){ - printf("Error! OP_AAAction size didnt match!\n"); + Log.Out(Logs::General, Logs::AA, "Error! OP_AAAction size didnt match!"); return; } AA_Action* action = (AA_Action*)app->pBuffer; if (action->action == aaActionActivate) {//AA Hotkey Log.Out(Logs::Detail, Logs::AA, "Activating AA %d", action->ability); - ActivateAA((aaID)action->ability); + //ActivateAlternateAdvancementAbility(action->ability); } else if (action->action == aaActionBuy) { - BuyAA(action); + PurchaseAlternateAdvancementRank(action->ability); } else if (action->action == aaActionDisableEXP){ //Turn Off AA Exp if (m_epp.perAA > 0) Message_StringID(0, AA_OFF); + m_epp.perAA = 0; - SendAAStats(); + SendAlternateAdvancementStats(); } else if (action->action == aaActionSetEXP) { if (m_epp.perAA == 0) Message_StringID(0, AA_ON); m_epp.perAA = action->exp_value; - if (m_epp.perAA<0 || m_epp.perAA>100) m_epp.perAA = 0; // stop exploit with sanity check + if (m_epp.perAA < 0 || m_epp.perAA > 100) + m_epp.perAA = 0; // stop exploit with sanity check + // send an update - SendAAStats(); - SendAATable(); + SendAlternateAdvancementStats(); + SendAlternateAdvancementTable(); } else { - printf("Unknown AA action: %u %u 0x%x %d\n", action->action, action->ability, action->unknown08, action->exp_value); + Log.Out(Logs::General, Logs::AA, "Unknown AA action : %u %u 0x%x %d", action->action, action->ability, action->unknown08, action->exp_value); } - - return; } void Client::Handle_OP_AcceptNewTask(const EQApplicationPacket *app) diff --git a/zone/command.cpp b/zone/command.cpp index f2a84baaa..298022dc9 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5600,8 +5600,8 @@ void command_setaapts(Client *c, const Seperator *sep) t->SetLeadershipEXP(t->GetGroupEXP(), atoi(sep->arg[2])*RAID_EXP_PER_POINT); } else { t->SetEXP(t->GetEXP(),t->GetMaxAAXP()*atoi(sep->arg[2]),false); - t->SendAAStats(); - t->SendAATable(); + t->SendAlternateAdvancementStats(); + t->SendAlternateAdvancementTable(); } } @@ -7684,54 +7684,55 @@ void command_reloadtitles(Client *c, const Seperator *sep) } +//old aa, probably to be removed void command_altactivate(Client *c, const Seperator *sep){ - if(sep->arg[1][0] == '\0'){ - c->Message(10, "Invalid argument, usage:"); - c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); - c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); - c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); - return; - } - if(!strcasecmp(sep->arg[1], "help")){ - c->Message(10, "Usage:"); - c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); - c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); - c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); - return; - } - if(!strcasecmp(sep->arg[1], "list")){ - c->Message(10, "You have access to the following AA Abilities:"); - int x, val; - SendAA_Struct* saa = nullptr; - for(x = 0; x < aaHighestID; x++){ - if(AA_Actions[x][0].spell_id || AA_Actions[x][0].action){ //if there's an action or spell associated we assume it's a valid - val = 0; //and assume if they don't have a value for the first rank then it isn't valid for any rank - saa = nullptr; - val = c->GetAA(x); - if(val){ - saa = zone->FindAA(x); - c->Message(10, "%d: %s %d", x, saa->name, val); - } - } - } - } - else if(!strcasecmp(sep->arg[1], "time")){ - int ability = atoi(sep->arg[2]); - if(c->GetAA(ability)){ - int remain = c->GetPTimers().GetRemainingTime(pTimerAAStart + ability); - if(remain) - c->Message(10, "You may use that ability in %d minutes and %d seconds.", (remain/60), (remain%60)); - else - c->Message(10, "You may use that ability now."); - } - else{ - c->Message(10, "You do not have access to that ability."); - } - } - else - { - c->ActivateAA((aaID) atoi(sep->arg[1])); - } +// if(sep->arg[1][0] == '\0'){ +// c->Message(10, "Invalid argument, usage:"); +// c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); +// c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); +// c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); +// return; +// } +// if(!strcasecmp(sep->arg[1], "help")){ +// c->Message(10, "Usage:"); +// c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); +// c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); +// c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); +// return; +// } +// if(!strcasecmp(sep->arg[1], "list")){ +// c->Message(10, "You have access to the following AA Abilities:"); +// int x, val; +// SendAA_Struct* saa = nullptr; +// for(x = 0; x < aaHighestID; x++){ +// if(AA_Actions[x][0].spell_id || AA_Actions[x][0].action){ //if there's an action or spell associated we assume it's a valid +// val = 0; //and assume if they don't have a value for the first rank then it isn't valid for any rank +// saa = nullptr; +// val = c->GetAA(x); +// if(val){ +// saa = zone->FindAA(x); +// c->Message(10, "%d: %s %d", x, saa->name, val); +// } +// } +// } +// } +// else if(!strcasecmp(sep->arg[1], "time")){ +// int ability = atoi(sep->arg[2]); +// if(c->GetAA(ability)){ +// int remain = c->GetPTimers().GetRemainingTime(pTimerAAStart + ability); +// if(remain) +// c->Message(10, "You may use that ability in %d minutes and %d seconds.", (remain/60), (remain%60)); +// else +// c->Message(10, "You may use that ability now."); +// } +// else{ +// c->Message(10, "You do not have access to that ability."); +// } +// } +// else +// { +// c->ActivateAA((aaID) atoi(sep->arg[1])); +// } } void command_traindisc(Client *c, const Seperator *sep) diff --git a/zone/exp.cpp b/zone/exp.cpp index 826b12e67..0172263e7 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -515,7 +515,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { if (GetLevel() < 51) { m_epp.perAA = 0; // turn off aa exp if they drop below 51 } else - SendAAStats(); //otherwise, send them an AA update + SendAlternateAdvancementStats(); //otherwise, send them an AA update //send the expdata in any case so the xp bar isnt stuck after leveling uint32 tmpxp1 = GetEXPForLevel(GetLevel()+1); diff --git a/zone/mob.h b/zone/mob.h index b074782b3..bbc841f48 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -958,7 +958,8 @@ public: //aa new uint32 GetAA(uint32 rank_id) const; - bool SetAA(uint32 rank_id, uint32 new_value); + bool SetAA(uint32 rank_id, uint32 new_value, uint32 charges = 0); + void ClearAAs() { aa_ranks.clear(); } bool CanUseAlternateAdvancementRank(AA::Rank *rank); bool CanPurchaseAlternateAdvancementRank(AA::Rank *ran); @@ -1316,7 +1317,7 @@ protected: bool bEnraged; bool destructibleobject; - std::unordered_map aa_ranks; + std::unordered_map> aa_ranks; private: void _StopSong(); //this is not what you think it is diff --git a/zone/net.cpp b/zone/net.cpp index 0178eff21..1bca0571b 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -248,9 +248,6 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::Zone_Server, "Loading titles"); title_manager.LoadTitles(); - Log.Out(Logs::General, Logs::Zone_Server, "Loading AA effects"); - database.LoadAAEffects(); - Log.Out(Logs::General, Logs::Zone_Server, "Loading tributes"); database.LoadTributes(); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index eed8305f4..d564a341e 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4077,33 +4077,34 @@ XS(XS_Client_RefundAA) { if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - int curpt = 0; - bool refunded = false; - - for(int x1=0;x1GetAA(x1); - if(curpt > 0){ - SendAA_Struct* curaa = zone->FindAA(x1); - if(curaa){ - THIS->SetAA(x1, 0); - for(int x2=0;x2GetPP().aapoints += curaa->cost + (curaa->cost_inc * x2); - refunded = true; - } - } - else //aa doesn't exist.. but if they bought it then it had at least a cost of 1 point each - { //so give back what we can - THIS->GetPP().aapoints += curpt; - THIS->SetAA(x1, 0); - refunded = true; - } - } - } - - if(refunded){ - THIS->Save(); //save of course - THIS->Kick(); //client gets all buggy if we don't immediatly relog so just force it on them - } + //old aa + //int curpt = 0; + //bool refunded = false; + // + //for(int x1=0;x1GetAA(x1); + // if(curpt > 0){ + // SendAA_Struct* curaa = zone->FindAA(x1); + // if(curaa){ + // THIS->SetAA(x1, 0); + // for(int x2=0;x2GetPP().aapoints += curaa->cost + (curaa->cost_inc * x2); + // refunded = true; + // } + // } + // else //aa doesn't exist.. but if they bought it then it had at least a cost of 1 point each + // { //so give back what we can + // THIS->GetPP().aapoints += curpt; + // THIS->SetAA(x1, 0); + // refunded = true; + // } + // } + //} + // + //if(refunded){ + // THIS->Save(); //save of course + // THIS->Kick(); //client gets all buggy if we don't immediatly relog so just force it on them + //} } XSRETURN_EMPTY; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7e91550c5..8ac60c125 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4157,30 +4157,30 @@ int32 Client::GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect int32 base2 = 0; uint32 slot = 0; - - std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - if(find_iter == aa_effects.end()) - return 0; - - for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - if (slot && slot == slot_id) { - - if (GetEffect) - return effect; - - if (GetBase1) - return base1; - - if (GetBase2) - return base2; - } - } + //old aa + //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); + //if(find_iter == aa_effects.end()) + // return 0; + // + //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) + //{ + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // if (slot && slot == slot_id) { + // + // if (GetEffect) + // return effect; + // + // if (GetBase1) + // return base1; + // + // if (GetBase2) + // return base2; + // } + //} return 0; } @@ -4214,431 +4214,432 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) */ int FocusCount = 0; - std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - if(find_iter == aa_effects.end()) - { - return 0; - } - - for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - /* - AA Foci's can contain multiple focus effects within the same AA. - To handle this we will not automatically return zero if a limit is found. - Instead if limit is found and multiple focus effects, we will reset the limit check - when the next valid focus effect is found. - */ - - if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ - FocusCount++; - //If limit found on prior check next, else end loop. - if (FocusCount > 1){ - - for(int e = 0; e < MaxLimitInclude; e+=2) { - if (LimitInclude[e] && !LimitInclude[e+1]) - LimitFailure = true; - } - - if (LimitFailure){ - value = 0; - LimitFailure = false; - - for(int e = 0; e < MaxLimitInclude; e++) { - LimitInclude[e] = false; //Reset array - } - } - - else{ - break; - } - } - } - - - switch (effect) - { - case SE_Blank: - break; - - //Handle Focus Limits - - case SE_LimitResist: - if(base1 < 0){ - if(spell.resisttype == -base1) //Exclude - LimitFailure = true; - } - else { - LimitInclude[0] = true; - if (spell.resisttype == base1) //Include - LimitInclude[1] = true; - } - break; - - case SE_LimitInstant: - if(base1 == 1 && spell.buffduration) //Fail if not instant - LimitFailure = true; - if(base1 == 0 && (spell.buffduration == 0)) //Fail if instant - LimitFailure = true; - - break; - - case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass()%16) - 1]; - lvldiff = spell_level - base1; - //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { - if(base2 > 0){ - lvlModifier -= base2*lvldiff; - if(lvlModifier < 1) - LimitFailure = true; - } - else - LimitFailure = true; - } - break; - - case SE_LimitMinLevel: - if((spell.classes[(GetClass()%16) - 1]) < base1) - LimitFailure = true; - break; - - case SE_LimitCastTimeMin: - if (static_cast(spell.cast_time) < base1) - LimitFailure = true; - break; - - case SE_LimitCastTimeMax: - if (static_cast(spell.cast_time) > base1) - LimitFailure = true; - break; - - case SE_LimitSpell: - if(base1 < 0) { //Exclude - if (spell_id == -base1) - LimitFailure = true; - } - else { - LimitInclude[2] = true; - if (spell_id == base1) //Include - LimitInclude[3] = true; - } - break; - - case SE_LimitMinDur: - if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - LimitFailure = true; - - break; - - case SE_LimitEffect: - if(base1 < 0){ - if(IsEffectInSpell(spell_id,-base1)) //Exclude - LimitFailure = true; - } - else{ - LimitInclude[4] = true; - if(IsEffectInSpell(spell_id,base1)) //Include - LimitInclude[5] = true; - } - break; - - case SE_LimitSpellType: - switch(base1) - { - case 0: - if (!IsDetrimentalSpell(spell_id)) - LimitFailure = true; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) - LimitFailure = true; - break; - } - break; - - case SE_LimitManaMin: - if(spell.mana < base1) - LimitFailure = true; - break; - - case SE_LimitTarget: - if (base1 < 0) { - if (-base1 == spell.targettype) //Exclude - LimitFailure = true; - } - else { - LimitInclude[6] = true; - if (base1 == spell.targettype) //Include - LimitInclude[7] = true; - } - break; - - case SE_LimitCombatSkills: - if (base1 == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) //Exclude Discs / Procs - LimitFailure = true; - else if (base1 == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) //Exclude Spells - LimitFailure = true; - - break; - - case SE_LimitSpellGroup: - if(base1 < 0) { - if (-base1 == spell.spellgroup) //Exclude - LimitFailure = true; - } - else { - LimitInclude[8] = true; - if (base1 == spell.spellgroup) //Include - LimitInclude[9] = true; - } - break; - - case SE_LimitCastingSkill: - if(base1 < 0) { - if(-base1 == spell.skill) - LimitFailure = true; - } - else { - LimitInclude[10] = true; - if(base1 == spell.skill) - LimitInclude[11] = true; - } - break; - - case SE_LimitSpellClass: - if(base1 < 0) { //Exclude - if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) - return(0); - } - else { - LimitInclude[12] = true; - if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) //Include - LimitInclude[13] = true; - } - break; - - case SE_LimitSpellSubclass: - if(base1 < 0) { //Exclude - if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) - return(0); - } - else { - LimitInclude[14] = true; - if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) //Include - LimitInclude[15] = true; - } - break; - - case SE_LimitClass: - //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(base1, GetClass())) - LimitFailure = true; - break; - - case SE_LimitRace: - if (base1 != GetRace()) - LimitFailure = true; - break; - - case SE_LimitUseMin: - if (base1 > spell.numhits) - LimitFailure = true; - break; - - case SE_LimitUseType: - if (base1 != spell.numhitstype) - LimitFailure = true; - break; - - //Handle Focus Effects - case SE_ImprovedDamage: - if (type == focusImprovedDamage && base1 > value) - value = base1; - break; - - case SE_ImprovedHeal: - if (type == focusImprovedHeal && base1 > value) - value = base1; - break; - - case SE_ReduceManaCost: - if (type == focusManaCost) - value = base1; - break; - - case SE_IncreaseSpellHaste: - if (type == focusSpellHaste && base1 > value) - value = base1; - break; - - case SE_IncreaseSpellDuration: - if (type == focusSpellDuration && base1 > value) - value = base1; - break; - - case SE_SpellDurationIncByTic: - if (type == focusSpellDurByTic && base1 > value) - value = base1; - break; - - case SE_SwarmPetDuration: - if (type == focusSwarmPetDuration && base1 > value) - value = base1; - break; - - case SE_IncreaseRange: - if (type == focusRange && base1 > value) - value = base1; - break; - - case SE_ReduceReagentCost: - if (type == focusReagentCost && base1 > value) - value = base1; - break; - - case SE_PetPowerIncrease: - if (type == focusPetPower && base1 > value) - value = base1; - break; - - case SE_SpellResistReduction: - if (type == focusResistRate && base1 > value) - value = base1; - break; - - case SE_SpellHateMod: - if (type == focusSpellHateMod ) { - if(value != 0) { - if(value > 0){ - if(base1 > value) - value = base1; - } - else{ - if(base1 < value) - value = base1; - } - } - else - value = base1; - } - break; - - case SE_ReduceReuseTimer: - if(type == focusReduceRecastTime) - value = base1 / 1000; - break; - - case SE_TriggerOnCast: - if(type == focusTriggerOnCast){ - if(zone->random.Roll(base1)) { - value = base2; - } else { - value = 0; - LimitFailure = true; - } - break; - } - - case SE_FcSpellVulnerability: - if(type == focusSpellVulnerability) - value = base1; - break; - - case SE_BlockNextSpellFocus: - if(type == focusBlockNextSpell){ - if(zone->random.Roll(base1)) - value = 1; - } - break; - - case SE_FcTwincast: - if(type == focusTwincast) - value = base1; - break; - - //Note if using these as AA, make sure this is first focus used. - case SE_SympatheticProc: - if(type == focusSympatheticProc) - value = base2; - break; - - case SE_FcDamageAmt: - if(type == focusFcDamageAmt) - value = base1; - break; - - case SE_FcDamageAmtCrit: - if(type == focusFcDamageAmtCrit) - value = base1; - break; - - case SE_FcDamageAmtIncoming: - if(type == focusFcDamageAmtIncoming) - value = base1; - break; - - case SE_FcHealAmtIncoming: - if(type == focusFcHealAmtIncoming) - value = base1; - break; - - case SE_FcHealPctCritIncoming: - if (type == focusFcHealPctCritIncoming) - value = base1; - break; - - case SE_FcHealAmtCrit: - if(type == focusFcHealAmtCrit) - value = base1; - break; - - case SE_FcHealAmt: - if(type == focusFcHealAmt) - value = base1; - break; - - case SE_FcHealPctIncoming: - if(type == focusFcHealPctIncoming) - value = base1; - break; - - case SE_FcBaseEffects: - if (type == focusFcBaseEffects) - value = base1; - break; - - case SE_FcDamagePctCrit: - if(type == focusFcDamagePctCrit) - value = base1; - break; - - case SE_FcIncreaseNumHits: - if(type == focusIncreaseNumHits) - value = base1; - break; - - case SE_FcLimitUse: - if(type == focusFcLimitUse) - value = base1; - break; - - case SE_FcMute: - if(type == focusFcMute) - value = base1; - break; - - case SE_FcStunTimeMod: - if(type == focusFcStunTimeMod) - value = base1; - break; - - } - } + //old AA + //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); + //if(find_iter == aa_effects.end()) + //{ + // return 0; + //} + // + //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) + //{ + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // /* + // AA Foci's can contain multiple focus effects within the same AA. + // To handle this we will not automatically return zero if a limit is found. + // Instead if limit is found and multiple focus effects, we will reset the limit check + // when the next valid focus effect is found. + // */ + // + // if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ + // FocusCount++; + // //If limit found on prior check next, else end loop. + // if (FocusCount > 1){ + // + // for(int e = 0; e < MaxLimitInclude; e+=2) { + // if (LimitInclude[e] && !LimitInclude[e+1]) + // LimitFailure = true; + // } + // + // if (LimitFailure){ + // value = 0; + // LimitFailure = false; + // + // for(int e = 0; e < MaxLimitInclude; e++) { + // LimitInclude[e] = false; //Reset array + // } + // } + // + // else{ + // break; + // } + // } + // } + // + // + // switch (effect) + // { + // case SE_Blank: + // break; + // + // //Handle Focus Limits + // + // case SE_LimitResist: + // if(base1 < 0){ + // if(spell.resisttype == -base1) //Exclude + // LimitFailure = true; + // } + // else { + // LimitInclude[0] = true; + // if (spell.resisttype == base1) //Include + // LimitInclude[1] = true; + // } + // break; + // + // case SE_LimitInstant: + // if(base1 == 1 && spell.buffduration) //Fail if not instant + // LimitFailure = true; + // if(base1 == 0 && (spell.buffduration == 0)) //Fail if instant + // LimitFailure = true; + // + // break; + // + // case SE_LimitMaxLevel: + // spell_level = spell.classes[(GetClass()%16) - 1]; + // lvldiff = spell_level - base1; + // //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true + // if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { + // if(base2 > 0){ + // lvlModifier -= base2*lvldiff; + // if(lvlModifier < 1) + // LimitFailure = true; + // } + // else + // LimitFailure = true; + // } + // break; + // + // case SE_LimitMinLevel: + // if((spell.classes[(GetClass()%16) - 1]) < base1) + // LimitFailure = true; + // break; + // + // case SE_LimitCastTimeMin: + // if (static_cast(spell.cast_time) < base1) + // LimitFailure = true; + // break; + // + // case SE_LimitCastTimeMax: + // if (static_cast(spell.cast_time) > base1) + // LimitFailure = true; + // break; + // + // case SE_LimitSpell: + // if(base1 < 0) { //Exclude + // if (spell_id == -base1) + // LimitFailure = true; + // } + // else { + // LimitInclude[2] = true; + // if (spell_id == base1) //Include + // LimitInclude[3] = true; + // } + // break; + // + // case SE_LimitMinDur: + // if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + // LimitFailure = true; + // + // break; + // + // case SE_LimitEffect: + // if(base1 < 0){ + // if(IsEffectInSpell(spell_id,-base1)) //Exclude + // LimitFailure = true; + // } + // else{ + // LimitInclude[4] = true; + // if(IsEffectInSpell(spell_id,base1)) //Include + // LimitInclude[5] = true; + // } + // break; + // + // case SE_LimitSpellType: + // switch(base1) + // { + // case 0: + // if (!IsDetrimentalSpell(spell_id)) + // LimitFailure = true; + // break; + // case 1: + // if (!IsBeneficialSpell(spell_id)) + // LimitFailure = true; + // break; + // } + // break; + // + // case SE_LimitManaMin: + // if(spell.mana < base1) + // LimitFailure = true; + // break; + // + // case SE_LimitTarget: + // if (base1 < 0) { + // if (-base1 == spell.targettype) //Exclude + // LimitFailure = true; + // } + // else { + // LimitInclude[6] = true; + // if (base1 == spell.targettype) //Include + // LimitInclude[7] = true; + // } + // break; + // + // case SE_LimitCombatSkills: + // if (base1 == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) //Exclude Discs / Procs + // LimitFailure = true; + // else if (base1 == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) //Exclude Spells + // LimitFailure = true; + // + // break; + // + // case SE_LimitSpellGroup: + // if(base1 < 0) { + // if (-base1 == spell.spellgroup) //Exclude + // LimitFailure = true; + // } + // else { + // LimitInclude[8] = true; + // if (base1 == spell.spellgroup) //Include + // LimitInclude[9] = true; + // } + // break; + // + // case SE_LimitCastingSkill: + // if(base1 < 0) { + // if(-base1 == spell.skill) + // LimitFailure = true; + // } + // else { + // LimitInclude[10] = true; + // if(base1 == spell.skill) + // LimitInclude[11] = true; + // } + // break; + // + // case SE_LimitSpellClass: + // if(base1 < 0) { //Exclude + // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) + // return(0); + // } + // else { + // LimitInclude[12] = true; + // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) //Include + // LimitInclude[13] = true; + // } + // break; + // + // case SE_LimitSpellSubclass: + // if(base1 < 0) { //Exclude + // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) + // return(0); + // } + // else { + // LimitInclude[14] = true; + // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) //Include + // LimitInclude[15] = true; + // } + // break; + // + // case SE_LimitClass: + // //Do not use this limit more then once per spell. If multiple class, treat value like items would. + // if (!PassLimitClass(base1, GetClass())) + // LimitFailure = true; + // break; + // + // case SE_LimitRace: + // if (base1 != GetRace()) + // LimitFailure = true; + // break; + // + // case SE_LimitUseMin: + // if (base1 > spell.numhits) + // LimitFailure = true; + // break; + // + // case SE_LimitUseType: + // if (base1 != spell.numhitstype) + // LimitFailure = true; + // break; + // + // //Handle Focus Effects + // case SE_ImprovedDamage: + // if (type == focusImprovedDamage && base1 > value) + // value = base1; + // break; + // + // case SE_ImprovedHeal: + // if (type == focusImprovedHeal && base1 > value) + // value = base1; + // break; + // + // case SE_ReduceManaCost: + // if (type == focusManaCost) + // value = base1; + // break; + // + // case SE_IncreaseSpellHaste: + // if (type == focusSpellHaste && base1 > value) + // value = base1; + // break; + // + // case SE_IncreaseSpellDuration: + // if (type == focusSpellDuration && base1 > value) + // value = base1; + // break; + // + // case SE_SpellDurationIncByTic: + // if (type == focusSpellDurByTic && base1 > value) + // value = base1; + // break; + // + // case SE_SwarmPetDuration: + // if (type == focusSwarmPetDuration && base1 > value) + // value = base1; + // break; + // + // case SE_IncreaseRange: + // if (type == focusRange && base1 > value) + // value = base1; + // break; + // + // case SE_ReduceReagentCost: + // if (type == focusReagentCost && base1 > value) + // value = base1; + // break; + // + // case SE_PetPowerIncrease: + // if (type == focusPetPower && base1 > value) + // value = base1; + // break; + // + // case SE_SpellResistReduction: + // if (type == focusResistRate && base1 > value) + // value = base1; + // break; + // + // case SE_SpellHateMod: + // if (type == focusSpellHateMod ) { + // if(value != 0) { + // if(value > 0){ + // if(base1 > value) + // value = base1; + // } + // else{ + // if(base1 < value) + // value = base1; + // } + // } + // else + // value = base1; + // } + // break; + // + // case SE_ReduceReuseTimer: + // if(type == focusReduceRecastTime) + // value = base1 / 1000; + // break; + // + // case SE_TriggerOnCast: + // if(type == focusTriggerOnCast){ + // if(zone->random.Roll(base1)) { + // value = base2; + // } else { + // value = 0; + // LimitFailure = true; + // } + // break; + // } + // + // case SE_FcSpellVulnerability: + // if(type == focusSpellVulnerability) + // value = base1; + // break; + // + // case SE_BlockNextSpellFocus: + // if(type == focusBlockNextSpell){ + // if(zone->random.Roll(base1)) + // value = 1; + // } + // break; + // + // case SE_FcTwincast: + // if(type == focusTwincast) + // value = base1; + // break; + // + // //Note if using these as AA, make sure this is first focus used. + // case SE_SympatheticProc: + // if(type == focusSympatheticProc) + // value = base2; + // break; + // + // case SE_FcDamageAmt: + // if(type == focusFcDamageAmt) + // value = base1; + // break; + // + // case SE_FcDamageAmtCrit: + // if(type == focusFcDamageAmtCrit) + // value = base1; + // break; + // + // case SE_FcDamageAmtIncoming: + // if(type == focusFcDamageAmtIncoming) + // value = base1; + // break; + // + // case SE_FcHealAmtIncoming: + // if(type == focusFcHealAmtIncoming) + // value = base1; + // break; + // + // case SE_FcHealPctCritIncoming: + // if (type == focusFcHealPctCritIncoming) + // value = base1; + // break; + // + // case SE_FcHealAmtCrit: + // if(type == focusFcHealAmtCrit) + // value = base1; + // break; + // + // case SE_FcHealAmt: + // if(type == focusFcHealAmt) + // value = base1; + // break; + // + // case SE_FcHealPctIncoming: + // if(type == focusFcHealPctIncoming) + // value = base1; + // break; + // + // case SE_FcBaseEffects: + // if (type == focusFcBaseEffects) + // value = base1; + // break; + // + // case SE_FcDamagePctCrit: + // if(type == focusFcDamagePctCrit) + // value = base1; + // break; + // + // case SE_FcIncreaseNumHits: + // if(type == focusIncreaseNumHits) + // value = base1; + // break; + // + // case SE_FcLimitUse: + // if(type == focusFcLimitUse) + // value = base1; + // break; + // + // case SE_FcMute: + // if(type == focusFcMute) + // value = base1; + // break; + // + // case SE_FcStunTimeMod: + // if(type == focusFcStunTimeMod) + // value = base1; + // break; + // + // } + //} for(int e = 0; e < MaxLimitInclude; e+=2) { if (LimitInclude[e] && !LimitInclude[e+1]) diff --git a/zone/zone.cpp b/zone/zone.cpp index 31bc27b41..e5e30f01a 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -804,8 +804,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) weather_intensity = 0; blocked_spells = nullptr; totalBS = 0; - aas = nullptr; - totalAAs = 0; zone_has_current_time = false; Instance_Shutdown_Timer = nullptr; @@ -864,16 +862,6 @@ Zone::~Zone() { safe_delete(qGlobals); safe_delete_array(adv_data); safe_delete_array(map_name); - - if(aas != nullptr) { - int r; - for(r = 0; r < totalAAs; r++) { - uchar *data = (uchar *) aas[r]; - safe_delete_array(data); - } - safe_delete_array(aas); - } - safe_delete(GuildBanks); } @@ -952,9 +940,6 @@ bool Zone::Init(bool iStaticZone) { zone->LoadAlternateCurrencies(); zone->LoadNPCEmotes(&NPCEmoteList); - //Load AA information - LoadAAs(); - LoadAlternateAdvancement(); //Load merchant data diff --git a/zone/zone.h b/zone/zone.h index 536ff048c..a4a49b8b2 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -120,14 +120,7 @@ public: AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id); AA::Rank *GetAlternateAdvancementRank(int rank_id); - //old AA - void LoadAAs(); - int GetTotalAAs() { return totalAAs; } - SendAA_Struct* GetAABySequence(uint32 seq) { return aas[seq]; } - SendAA_Struct* FindAA(uint32 id); - uint8 GetTotalAALevels(uint32 skill_id); - - void LoadZoneDoors(const char* zone, int16 version); + void LoadZoneDoors(const char* zone, int16 version); bool LoadZoneObjects(); bool LoadGroundSpawns(); void ReloadStaticData(); @@ -202,6 +195,10 @@ public: char *adv_data; bool did_adventure_actions; + //new AA + std::unordered_map> aa_abilities; + std::unordered_map> aa_ranks; + void DoAdventureCountIncrease(); void DoAdventureAssassinationCountIncrease(); void DoAdventureActions(); @@ -322,17 +319,6 @@ private: int totalBS; ZoneSpellsBlocked *blocked_spells; -public: - //new AA - std::unordered_map> aa_abilities; - std::unordered_map> aa_ranks; - -private: - - //old AA - int totalAAs; - SendAA_Struct **aas; //array of AA structs - /* Spawn related things */ diff --git a/zone/zonedb.h b/zone/zonedb.h index ddd9450d2..35275b654 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -343,18 +343,7 @@ public: /* AAs New */ bool LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, std::unordered_map> &ranks); - - /* AAs Old */ - bool LoadAAEffects(); - bool LoadAAEffects2(); - bool LoadSwarmSpells(); - SendAA_Struct*GetAASkillVars(uint32 skill_id); - uint8 GetTotalAALevels(uint32 skill_id); - uint32 GetSizeAA(); - uint32 CountAAs(); - void LoadAAs(SendAA_Struct **load); - uint32 CountAAEffects(); - void FillAAEffects(SendAA_Struct* aa_struct); + bool LoadAlternateAdvancement(Client *c); /* Zone related */ bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename); From bad4a94b84c31d9f5bec2a357f3acf723e1be1f3 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 11 Jun 2015 01:45:55 -0700 Subject: [PATCH 170/846] Apply RoF2 patch demon gave me for AAs --- common/patches/rof2.cpp | 120 ++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index a4f484a9e..3d96ae182 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2936,58 +2936,80 @@ namespace RoF2 ENCODE(OP_SendAATable) { - ENCODE_LENGTH_ATLEAST(SendAA_Struct); - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; + + // the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs + auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0; + auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size); + inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct)); + - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 5 is for Live - if (emu->clientver <= 8) - { - OUT(id); - eq->unknown004 = 1; - //eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->title_sid = emu->id - emu->current_level + 1; - //eq->desc_sid = emu->id - emu->current_level + 1; - eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? -1 : (emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? -1 : (emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - eq->prereq_skill_count = 1; // min 1 - OUT(prereq_skill); - eq->prereq_minpoints_count = 1; // min 1 - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - eq->unknown057 = 1; // Introduced during HoT - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - OUT(berserker); - //eq->max_level = emu->sof_max_level; - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - eq->aa_expansion = emu->aa_expansion; - eq->special_category = emu->special_category; - OUT(total_abilities); - eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number - unsigned int r; - for (r = 0; r < emu->total_abilities; r++) { - OUT(abilities[r].skill_id); - OUT(abilities[r].base1); - OUT(abilities[r].base2); - OUT(abilities[r].slot); - } + std::vector skill; + std::vector points; + for(auto i = 0; i < emu->total_prereqs; ++i) { + skill.push_back(inapp->ReadUInt32()); + points.push_back(inapp->ReadUInt32()); } - FINISH_ENCODE(); + outapp->WriteUInt32(emu->id); + outapp->WriteUInt8(1); + outapp->WriteSInt32(emu->upper_hotkey_sid); + outapp->WriteSInt32(emu->lower_hotkey_sid); + outapp->WriteSInt32(emu->title_sid); + outapp->WriteSInt32(emu->desc_sid); + outapp->WriteSInt32(emu->level_req); + outapp->WriteSInt32(emu->cost); + outapp->WriteUInt32(emu->seq); + outapp->WriteUInt32(emu->current_level); + + if (emu->total_prereqs) { + outapp->WriteUInt32(emu->total_prereqs); + for (auto &e : skill) + outapp->WriteSInt32(e); + outapp->WriteUInt32(emu->total_prereqs); + for (auto &e : points) + outapp->WriteSInt32(e); + } else { + outapp->WriteUInt32(1); + outapp->WriteUInt32(0); + outapp->WriteUInt32(1); + outapp->WriteUInt32(0); + } + + outapp->WriteSInt32(emu->type); + outapp->WriteSInt32(emu->spell); + outapp->WriteSInt32(1); + outapp->WriteSInt32(emu->spell_type); + outapp->WriteSInt32(emu->spell_refresh); + outapp->WriteSInt32(emu->classes); + outapp->WriteSInt32(emu->max_level); + outapp->WriteSInt32(emu->prev_id); + outapp->WriteSInt32(emu->next_id); + outapp->WriteSInt32(emu->total_cost); + outapp->WriteUInt8(0); + outapp->WriteUInt8(emu->grant_only); + outapp->WriteUInt8(0); + outapp->WriteUInt32(emu->charges); + outapp->WriteSInt32(emu->expansion); + outapp->WriteSInt32(emu->category); + outapp->WriteUInt8(0); // shroud + outapp->WriteUInt8(0); // unknown109 + outapp->WriteUInt8(0); // loh + outapp->WriteUInt8(0); // unknown111 + outapp->WriteUInt32(emu->total_effects); + + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + for(auto i = 0; i < emu->total_effects; ++i) { + outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id + outapp->WriteUInt32(inapp->ReadUInt32()); // base1 + outapp->WriteUInt32(inapp->ReadUInt32()); // base2 + outapp->WriteUInt32(inapp->ReadUInt32()); // slot + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) From 985d969384e9a4b64668f96070cffd843db50224 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 11 Jun 2015 17:04:59 -0700 Subject: [PATCH 171/846] AA purchasing works --- zone/aa.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++----- zone/client.cpp | 80 ++++++++++++++++----------------- zone/mob.h | 2 +- 3 files changed, 143 insertions(+), 54 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 4bbdf88a6..868c1f62c 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1796,13 +1796,14 @@ void Client::SendAlternateAdvancementPoints() { int i = 0; for(auto &aa : zone->aa_abilities) { - auto ranks = GetAA(aa.second->first_rank_id); + uint32 charges = 0; + auto ranks = GetAA(aa.second->first_rank_id, &charges); if(ranks) { AA::Rank *rank = aa.second->GetRankByPointsSpent(ranks); if(rank) { aa2->aa_list[i].AA = rank->id; aa2->aa_list[i].value = ranks; - aa2->aa_list[i].charges = 0; // todo send charges + aa2->aa_list[i].charges = charges; i++; } } @@ -1815,6 +1816,65 @@ void Client::SendAlternateAdvancementPoints() { } void Client::PurchaseAlternateAdvancementRank(int rank_id) { + AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); + if(!rank) { + return; + } + + if(!rank->base_ability) { + return; + } + + if(!CanPurchaseAlternateAdvancementRank(rank)) { + return; + } + + if(rank->base_ability->charges > 0) { + SetAA(rank_id, rank->current_value, rank->base_ability->charges); + } else { + SetAA(rank_id, rank->current_value, 0); + + //if not max then send next aa + if(rank->next) { + SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value); + } + } + + m_pp.aapoints -= rank->cost; + SaveAA(); + + SendAlternateAdvancementPoints(); + SendAlternateAdvancementStats(); + + if(rank->prev) { + Message_StringID(15, AA_IMPROVE, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->prev->current_value).c_str(), + std::to_string(rank->cost).c_str(), + std::to_string(AA_POINTS).c_str()); + + //QS stuff broke with new aa, todo: fix later + /* QS: Player_Log_AA_Purchases */ + // if (RuleB(QueryServ, PlayerLogAAPurchases)){ + // std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); + // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + // } + } else { + Message_StringID(15, AA_GAIN_ABILITY, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->cost).c_str(), + std::to_string(AA_POINTS).c_str()); + //QS stuff broke with new aa, todo: fix later + /* QS: Player_Log_AA_Purchases */ + // if (RuleB(QueryServ, PlayerLogAAPurchases)){ + // std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); + // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + // } + } + + CalcBonuses(); + if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) + NotifyNewTitlesAvailable(); } bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { @@ -1872,7 +1932,7 @@ AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) { return nullptr; } -uint32 Mob::GetAA(uint32 rank_id) const { +uint32 Mob::GetAA(uint32 rank_id, uint32 *charges) const { if(zone) { AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); if(!ability) @@ -1880,6 +1940,9 @@ uint32 Mob::GetAA(uint32 rank_id) const { auto iter = aa_ranks.find(ability->id); if(iter != aa_ranks.end()) { + if(charges) { + *charges = iter->second.second; + } return iter->second.first; } } @@ -1915,10 +1978,6 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return false; } - if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { - return false; - } - // Passive and Active Shroud AAs // For now we skip them if(ability->category == 3 || ability->category == 4) { @@ -1965,14 +2024,50 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { return false; } - //check that we have previous rank already + if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { + return false; + } + + //check level req + if(rank->level_req > GetLevel()) { + return false; + } + + uint32 current_charges = 0; + auto points = GetAA(rank->id, ¤t_charges); + + //check that we are on previous rank already (if exists) if(rank->prev) { - //rank->prev-> + if(points != rank->prev->current_value) { + return false; + } + } + + //if expendable only let us purchase if we have no charges already + //not quite sure on how this functions client side atm + //I intend to look into it later to make sure the behavior is right + if(ability->charges > 0 && current_charges > 0) { + return false; } //check prereqs + for(auto &prereq : rank->prereqs) { + AA::Ability *prereq_ability = zone->GetAlternateAdvancementAbility(prereq.aa_id); - //check price + if(prereq_ability) { + auto ranks = GetAA(prereq_ability->first_rank_id); + if(ranks < prereq.points) { + return false; + } + } + } + + //check price, if client + if(IsClient()) { + if(rank->cost > CastToClient()->GetAAPoints()) { + return false; + } + } return true; } diff --git a/zone/client.cpp b/zone/client.cpp index 24968f005..f36609b9c 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -523,49 +523,43 @@ void Client::ReportConnectingState() { }; } -bool Client::SaveAA(){ - //aa old - //int first_entry = 0; - //std::string rquery; - ///* Save Player AA */ - //int spentpoints = 0; - //for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { - // uint32 points = aa[a]->value; - // if (points > HIGHEST_AA_VALUE) { - // aa[a]->value = HIGHEST_AA_VALUE; - // points = HIGHEST_AA_VALUE; - // } - // if (points > 0) { - // SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1); - // if (curAA) { - // for (int rank = 0; rank::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank); - // if (RequiredLevel != AARequiredLevelAndCost.end()) { - // spentpoints += RequiredLevel->second.Cost; - // } - // else - // spentpoints += (curAA->cost + (curAA->cost_inc * rank)); - // } - // } - // } - //} - //m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; - //int highest = 0; - //for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { - // if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load - // if (first_entry != 1){ - // rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" - // " VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); - // first_entry = 1; - // } else { - // rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); - // } - // highest = a; - // } - //} - //auto results = database.QueryDatabase(rquery); - ///* This is another part of the hack to clean up holes left by expendable AAs */ - //rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest); +bool Client::SaveAA() { + std::string dquery; + std::string iquery; + int spentpoints = 0; + int i = 0; + for(auto &rank : aa_ranks) { + AA::Ability *ability = zone->GetAlternateAdvancementAbility(rank.first); + if(!ability) + continue; + + if(rank.second.first > 0) { + AA::Rank *r = ability->GetRankByPointsSpent(rank.second.first); + + if(!r) + continue; + + spentpoints += r->total_cost; + + if(i == 0) { + iquery = StringFormat("INSERT INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" + " VALUES (%u, %u, %u, %u, %u)", character_id, i, ability->first_rank_id, rank.second.first, rank.second.second); + } else { + iquery += StringFormat(", (%u, %u, %u, %u, %u)", character_id, i, ability->first_rank_id, rank.second.first, rank.second.second); + } + i++; + } + } + + m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; + + dquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE id=%u", character_id); + database.QueryDatabase(dquery); + + if(iquery.length() > 0) { + database.QueryDatabase(iquery); + } + return true; } diff --git a/zone/mob.h b/zone/mob.h index bbc841f48..ce9fe3634 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -957,7 +957,7 @@ public: void Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int acc_override, int Msg = 0); //aa new - uint32 GetAA(uint32 rank_id) const; + uint32 GetAA(uint32 rank_id, uint32 *charges = nullptr) const; bool SetAA(uint32 rank_id, uint32 new_value, uint32 charges = 0); void ClearAAs() { aa_ranks.clear(); } bool CanUseAlternateAdvancementRank(AA::Rank *rank); From 63928caacebd29c4e6eaa6910e37edbafb72a3d3 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 11 Jun 2015 18:38:46 -0700 Subject: [PATCH 172/846] Removing cruft, patches should *all* work now even titanium, incrementaa has been implemented (untested atm) --- common/patches/rof.cpp | 123 ++++++---- common/patches/rof2.cpp | 2 +- common/patches/sod.cpp | 93 ++++---- common/patches/sof.cpp | 94 ++++---- common/patches/titanium.cpp | 82 +++---- common/patches/uf.cpp | 5 +- zone/aa.cpp | 449 +++++++----------------------------- zone/client.h | 6 +- zone/client_packet.cpp | 2 +- zone/lua_client.cpp | 2 +- zone/mob.h | 2 +- zone/perl_client.cpp | 2 +- zone/titles.cpp | 4 +- 13 files changed, 299 insertions(+), 567 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index f4f01e300..0596ee95b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2810,7 +2810,7 @@ namespace RoF eq->aa_spent = emu->aa_spent; // These fields may need to be correctly populated at some point - eq->aapoints_assigned = emu->aa_spent + 1; + eq->aapoints_assigned = 0; eq->aa_spent_general = 0; eq->aa_spent_archetype = 0; eq->aa_spent_class = 0; @@ -2846,58 +2846,81 @@ namespace RoF ENCODE(OP_SendAATable) { - ENCODE_LENGTH_ATLEAST(SendAA_Struct); - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 5 is for Live - if (emu->clientver <= 7) - { - OUT(id); - eq->unknown004 = 1; - //eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->title_sid = emu->id - emu->current_level + 1; - //eq->desc_sid = emu->id - emu->current_level + 1; - eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? -1 : (emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? -1 : (emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - eq->prereq_skill_count = 1; // min 1 - OUT(prereq_skill); - eq->prereq_minpoints_count = 1; // min 1 - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - eq->unknown057 = 1; // Introduced during HoT - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - OUT(berserker); - //eq->max_level = emu->sof_max_level; - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - eq->aa_expansion = emu->aa_expansion; - eq->special_category = emu->special_category; - eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number - OUT(total_abilities); - unsigned int r; - for (r = 0; r < emu->total_abilities; r++) { - OUT(abilities[r].skill_id); - OUT(abilities[r].base1); - OUT(abilities[r].base2); - OUT(abilities[r].slot); - } + // the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs + auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0; + auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size); + inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct)); + + + std::vector skill; + std::vector points; + for(auto i = 0; i < emu->total_prereqs; ++i) { + skill.push_back(inapp->ReadUInt32()); + points.push_back(inapp->ReadUInt32()); } - FINISH_ENCODE(); + outapp->WriteUInt32(emu->id); + outapp->WriteUInt8(1); + outapp->WriteSInt32(emu->upper_hotkey_sid); + outapp->WriteSInt32(emu->lower_hotkey_sid); + outapp->WriteSInt32(emu->title_sid); + outapp->WriteSInt32(emu->desc_sid); + outapp->WriteSInt32(emu->level_req); + outapp->WriteSInt32(emu->cost); + outapp->WriteUInt32(emu->seq); + outapp->WriteUInt32(emu->current_level); + + if(emu->total_prereqs) { + outapp->WriteUInt32(emu->total_prereqs); + for(auto &e : skill) + outapp->WriteSInt32(e); + outapp->WriteUInt32(emu->total_prereqs); + for(auto &e : points) + outapp->WriteSInt32(e); + } + else { + outapp->WriteUInt32(1); + outapp->WriteUInt32(0); + outapp->WriteUInt32(1); + outapp->WriteUInt32(0); + } + + outapp->WriteSInt32(emu->type); + outapp->WriteSInt32(emu->spell); + outapp->WriteSInt32(1); + outapp->WriteSInt32(emu->spell_type); + outapp->WriteSInt32(emu->spell_refresh); + outapp->WriteSInt32(emu->classes); + outapp->WriteSInt32(emu->max_level); + outapp->WriteSInt32(emu->prev_id); + outapp->WriteSInt32(emu->next_id); + outapp->WriteSInt32(emu->total_cost); + outapp->WriteUInt8(0); + outapp->WriteUInt8(emu->grant_only); + outapp->WriteUInt8(0); + outapp->WriteUInt32(emu->charges); + outapp->WriteSInt32(emu->expansion); + outapp->WriteSInt32(emu->category); + outapp->WriteUInt8(0); // shroud + outapp->WriteUInt8(0); // unknown109 + outapp->WriteUInt8(0); // loh + outapp->WriteUInt8(0); // unknown111 + outapp->WriteUInt32(emu->total_effects); + + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + for(auto i = 0; i < emu->total_effects; ++i) { + outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id + outapp->WriteUInt32(inapp->ReadUInt32()); // base1 + outapp->WriteUInt32(inapp->ReadUInt32()); // base2 + outapp->WriteUInt32(inapp->ReadUInt32()); // slot + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 3d96ae182..ba2099710 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2900,7 +2900,7 @@ namespace RoF2 eq->aa_spent = emu->aa_spent; // These fields may need to be correctly populated at some point - eq->aapoints_assigned = emu->aa_spent + 1; + eq->aapoints_assigned = 0; eq->aa_spent_general = 0; eq->aa_spent_archetype = 0; eq->aa_spent_class = 0; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 69bb7f4c1..1910a96e4 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1862,55 +1862,56 @@ namespace SoD ENCODE(OP_SendAATable) { - ENCODE_LENGTH_ATLEAST(SendAA_Struct); - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 5 is for SoD - if (emu->clientver <= 5) - { - OUT(id); - eq->unknown004 = 1; - //eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->title_sid = emu->id - emu->current_level + 1; - //eq->desc_sid = emu->id - emu->current_level + 1; - eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - OUT(berserker); - //eq->max_level = emu->sof_max_level; - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - eq->aa_expansion = emu->aa_expansion; - eq->special_category = emu->special_category; - eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number - OUT(total_abilities); - unsigned int r; - for (r = 0; r < emu->total_abilities; r++) { - OUT(abilities[r].skill_id); - OUT(abilities[r].base1); - OUT(abilities[r].base2); - OUT(abilities[r].slot); - } + EQApplicationPacket *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)); + outapp->SetWritePosition(sizeof(structs::SendAA_Struct)); + + eq->id = emu->id; + eq->unknown004 = 1; + eq->id = emu->id; + eq->hotkey_sid = emu->upper_hotkey_sid; + eq->hotkey_sid2 = emu->lower_hotkey_sid; + eq->desc_sid = emu->desc_sid; + eq->title_sid = emu->title_sid; + eq->class_type = emu->level_req; + eq->cost = emu->cost; + eq->seq = emu->seq; + eq->current_level = emu->current_level; + eq->type = emu->type; + eq->spellid = emu->spell; + eq->spell_type = emu->spell_type; + eq->spell_refresh = emu->spell_refresh; + eq->classes = emu->classes; + eq->max_level = emu->max_level; + eq->last_id = emu->prev_id; + eq->next_id = emu->next_id; + eq->cost2 = emu->total_cost; + eq->grant_only = emu->grant_only; + eq->expendable_charges = emu->charges; + eq->aa_expansion = emu->expansion; + eq->special_category = emu->category; + eq->total_abilities = emu->total_effects; + + for(auto i = 0; i < eq->total_abilities; ++i) { + eq->abilities[i].skill_id = inapp->ReadUInt32(); + eq->abilities[i].base1 = inapp->ReadUInt32(); + eq->abilities[i].base2 = inapp->ReadUInt32(); + eq->abilities[i].slot = inapp->ReadUInt32(); } - FINISH_ENCODE(); + if(emu->total_prereqs > 0) { + eq->prereq_skill = inapp->ReadUInt32(); + eq->prereq_minpoints = inapp->ReadUInt32(); + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 2d8ec8d3a..421903970 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1520,56 +1520,56 @@ namespace SoF ENCODE(OP_SendAATable) { - ENCODE_LENGTH_ATLEAST(SendAA_Struct); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + EQApplicationPacket *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; - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 4 is for SoF - if (emu->clientver <= 4) - { - OUT(id); - eq->unknown004 = 1; - //eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->title_sid = emu->id - emu->current_level + 1; - //eq->desc_sid = emu->id - emu->current_level + 1; - eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - OUT(berserker); - //eq->max_level = emu->sof_max_level; - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - eq->aa_expansion = emu->aa_expansion; - eq->special_category = emu->special_category; - eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number - OUT(total_abilities); - unsigned int r; - for (r = 0; r < emu->total_abilities; r++) { - OUT(abilities[r].skill_id); - OUT(abilities[r].base1); - OUT(abilities[r].base2); - OUT(abilities[r].slot); - } + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + outapp->SetWritePosition(sizeof(structs::SendAA_Struct)); + + eq->id = emu->id; + eq->unknown004 = 1; + eq->id = emu->id; + eq->hotkey_sid = emu->upper_hotkey_sid; + eq->hotkey_sid2 = emu->lower_hotkey_sid; + eq->desc_sid = emu->desc_sid; + eq->title_sid = emu->title_sid; + eq->class_type = emu->level_req; + eq->cost = emu->cost; + eq->seq = emu->seq; + eq->current_level = emu->current_level; + eq->type = emu->type; + eq->spellid = emu->spell; + eq->spell_type = emu->spell_type; + eq->spell_refresh = emu->spell_refresh; + eq->classes = emu->classes; + eq->max_level = emu->max_level; + eq->last_id = emu->prev_id; + eq->next_id = emu->next_id; + eq->cost2 = emu->total_cost; + eq->grant_only = emu->grant_only; + eq->expendable_charges = emu->charges; + eq->aa_expansion = emu->expansion; + eq->special_category = emu->category; + eq->total_abilities = emu->total_effects; + + for(auto i = 0; i < eq->total_abilities; ++i) { + eq->abilities[i].skill_id = inapp->ReadUInt32(); + eq->abilities[i].base1 = inapp->ReadUInt32(); + eq->abilities[i].base2 = inapp->ReadUInt32(); + eq->abilities[i].slot = inapp->ReadUInt32(); } - FINISH_ENCODE(); + if(emu->total_prereqs > 0) { + eq->prereq_skill = inapp->ReadUInt32(); + eq->prereq_minpoints = inapp->ReadUInt32(); + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) @@ -1665,8 +1665,6 @@ namespace SoF emu_ptr += sizeof(CharacterSelectEntry_Struct); eq_ptr += sizeof(structs::CharacterSelectEntry_Struct); } - - FINISH_ENCODE(); } //hack hack hack diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 2fda4038a..ec25aba61 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1107,50 +1107,52 @@ namespace Titanium ENCODE(OP_SendAATable) { - ENCODE_LENGTH_ATLEAST(SendAA_Struct); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + EQApplicationPacket *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; - // Check clientver field to verify this AA should be sent for Titanium - // clientver 1 is for all clients and 3 is for Titanium - if (emu->clientver <= 3) - { - OUT(id); - eq->unknown004 = 1; - eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1); - eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1); - eq->title_sid = emu->id - emu->current_level + 1; - eq->desc_sid = emu->id - emu->current_level + 1; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - OUT(type); - OUT(spellid); - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - OUT(berserker); - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - OUT(unknown80[0]); - OUT(unknown80[1]); - OUT(total_abilities); - unsigned int r; - for (r = 0; r < emu->total_abilities; r++) { - OUT(abilities[r].skill_id); - OUT(abilities[r].base1); - OUT(abilities[r].base2); - OUT(abilities[r].slot); - } + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + outapp->SetWritePosition(sizeof(structs::SendAA_Struct)); + + eq->id = emu->id; + eq->unknown004 = 1; + eq->id = emu->id; + eq->hotkey_sid = emu->upper_hotkey_sid; + eq->hotkey_sid2 = emu->lower_hotkey_sid; + eq->desc_sid = emu->desc_sid; + eq->title_sid = emu->title_sid; + eq->class_type = emu->level_req; + eq->cost = emu->cost; + eq->seq = emu->seq; + eq->current_level = emu->current_level; + eq->type = emu->type; + eq->spellid = emu->spell; + eq->spell_type = emu->spell_type; + eq->spell_refresh = emu->spell_refresh; + eq->classes = emu->classes; + eq->max_level = emu->max_level; + eq->last_id = emu->prev_id; + eq->next_id = emu->next_id; + eq->cost2 = emu->total_cost; + eq->total_abilities = emu->total_effects; + + for(auto i = 0; i < eq->total_abilities; ++i) { + eq->abilities[i].skill_id = inapp->ReadUInt32(); + eq->abilities[i].base1 = inapp->ReadUInt32(); + eq->abilities[i].base2 = inapp->ReadUInt32(); + eq->abilities[i].slot = inapp->ReadUInt32(); } - FINISH_ENCODE(); + if(emu->total_prereqs > 0) { + eq->prereq_skill = inapp->ReadUInt32(); + eq->prereq_minpoints = inapp->ReadUInt32(); + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 5b879af9d..df6fa9615 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2129,8 +2129,8 @@ namespace UF SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); eq->aa_spent = emu->aa_spent; - eq->aa_assigned = emu->aa_spent; - eq->aa_spent3 = emu->aa_spent; + eq->aa_assigned = 0; + eq->aa_spent3 = 0; eq->unknown012 = 0; eq->unknown016 = 0; eq->unknown020 = 0; @@ -2195,7 +2195,6 @@ namespace UF eq->prereq_minpoints = inapp->ReadUInt32(); } - //Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); dest->FastQueuePacket(&outapp); delete inapp; } diff --git a/zone/aa.cpp b/zone/aa.cpp index 868c1f62c..d6be92fe7 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -930,121 +930,6 @@ bool Client::CheckAAEffect(aaEffectType type) { return(false); } -void Client::BuyAA(AA_Action* action) -{ - //Log.Out(Logs::Detail, Logs::AA, "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; - //// Log.Out(Logs::Detail, Logs::AA, "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 - // Log.Out(Logs::Detail, Logs::AA, "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; - //uint8 req_level; - ////std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); - //// - ////if(RequiredLevel != AARequiredLevelAndCost.end()) { - //// real_cost = RequiredLevel->second.Cost; - //// req_level = RequiredLevel->second.Level; - ////} - ////else { - //// real_cost = aa2->cost + (aa2->cost_inc * cur_level); - //// req_level = aa2->class_type + (aa2->level_inc * cur_level); - ////} - // - //if (req_level > GetLevel()) - // return; //Cheater trying to Buy AA... - // - //if (m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { - // SetAA(aa2->id, cur_level + 1); - // - // Log.Out(Logs::Detail, Logs::AA, "Set AA %d to level %d", aa2->id, cur_level + 1); - // - // m_pp.aapoints -= real_cost; - // - // /* Do Player Profile rank calculations and set player profile */ - // SaveAA(); - // /* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/ - // // database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1)); - // - // 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 - // */ - // - // /* Initial purchase of an AA ability */ - // 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"); - // - // /* QS: Player_Log_AA_Purchases */ - // if (RuleB(QueryServ, PlayerLogAAPurchases)){ - // std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - // } - // } - // /* Ranked purchase of an AA ability */ - // 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"); - // - // /* QS: Player_Log_AA_Purchases */ - // if (RuleB(QueryServ, PlayerLogAAPurchases)){ - // std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - // } - // } - // - // //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; @@ -1078,235 +963,6 @@ void Client::SendAATimers() { safe_delete(outapp); } -void Client::SendPreviousAA(uint32 id, int seq){ -} - -void Client::SendAA(uint32 id, int seq) { - //Log.Out(Logs::General, Logs::Status, "SendAA(%u, %i)", id, 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); - // - // // this check should work as long as we continue to just add the clients and just increase - // // each number .... - // if (saa_next && static_cast(GetClientVersion()) < saa_next->clientver - 1) { - // 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::ResetAA(){ // RefundAA(); // uint32 i; @@ -1657,25 +1313,6 @@ void Client::RefundAA() { // } } -void Client::IncrementAA(int aa_id) { - //SendAA_Struct* aa2 = zone->FindAA(aa_id); - // - //if(aa2 == nullptr) - // return; - // - //if(GetAA(aa_id) == aa2->max_level) - // return; - // - //SetAA(aa_id, GetAA(aa_id) + 1); - // - //SaveAA(); - // - //SendAA(aa_id); - //SendAATable(); - //SendAAStats(); - //CalcBonuses(); -} - AA_SwarmPetInfo::AA_SwarmPetInfo() { target = 0; @@ -1753,7 +1390,12 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { aai->current_level = level; aai->max_level = ability->GetMaxLevel(); aai->prev_id = rank->prev_id; - aai->next_id = rank->next_id; + + if(rank->next && !CanUseAlternateAdvancementRank(rank->next)) { + aai->next_id = -1; + } else { + aai->next_id = rank->next_id; + } aai->total_cost = rank->total_cost; aai->expansion = rank->expansion; aai->category = ability->category; @@ -1810,7 +1452,7 @@ void Client::SendAlternateAdvancementPoints() { } - aa2->aa_spent = GetAAPointsSpent(); + aa2->aa_spent = GetSpentAA(); QueuePacket(outapp); safe_delete(outapp); } @@ -1825,7 +1467,7 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { return; } - if(!CanPurchaseAlternateAdvancementRank(rank)) { + if(!CanPurchaseAlternateAdvancementRank(rank, true)) { return; } @@ -1877,6 +1519,67 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { NotifyNewTitlesAvailable(); } +void Client::IncrementAlternateAdvancementRank(int rank_id) { + AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); + if(!rank) { + return; + } + + if(!rank->base_ability) { + return; + } + + if(!CanPurchaseAlternateAdvancementRank(rank, false)) { + return; + } + + if(rank->base_ability->charges > 0) { + SetAA(rank_id, rank->current_value, rank->base_ability->charges); + } + else { + SetAA(rank_id, rank->current_value, 0); + + //if not max then send next aa + if(rank->next) { + SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value); + } + } + + SaveAA(); + + SendAlternateAdvancementPoints(); + SendAlternateAdvancementStats(); + + if(rank->prev) { + Message_StringID(15, AA_IMPROVE, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->prev->current_value).c_str(), + std::to_string(rank->cost).c_str(), + std::to_string(AA_POINTS).c_str()); + + //QS stuff broke with new aa, todo: fix later + /* QS: Player_Log_AA_Purchases */ + // if (RuleB(QueryServ, PlayerLogAAPurchases)){ + // std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); + // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + // } + } + else { + Message_StringID(15, AA_GAIN_ABILITY, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->cost).c_str(), + std::to_string(AA_POINTS).c_str()); + //QS stuff broke with new aa, todo: fix later + /* QS: Player_Log_AA_Purchases */ + // if (RuleB(QueryServ, PlayerLogAAPurchases)){ + // std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); + // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + // } + } + + CalcBonuses(); +} + bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { c->ClearAAs(); std::string query = StringFormat( @@ -1984,6 +1687,16 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return false; } + //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(ability->charges > 0) { + return false; + } + } + + //I might add a races behind the scenes field to take care of this // Check for racial/Drakkin blood line AAs if(ability->category == 8) { @@ -2009,7 +1722,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return true; } -bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { +bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) { AA::Ability *ability = rank->base_ability; if(!ability) @@ -2063,7 +1776,7 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { } //check price, if client - if(IsClient()) { + if(check_price && IsClient()) { if(rank->cost > CastToClient()->GetAAPoints()) { return false; } diff --git a/zone/client.h b/zone/client.h index bd2c5371d..082d86fdc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -764,6 +764,7 @@ public: void SendAlternateAdvancementTable(); void SendAlternateAdvancementStats(); void PurchaseAlternateAdvancementRank(int rank_id); + void IncrementAlternateAdvancementRank(int rank_id); void SendAlternateAdvancementPoints(); void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } @@ -774,9 +775,6 @@ public: //old AA Methods void ResetAA(); void SendClearAA(); - void SendAA(uint32 id, int seq=1); - void SendPreviousAA(uint32 id, int seq=1); - void BuyAA(AA_Action* action); //this function is used by some AA stuff void MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing); void SetAATitle(const char *Title); @@ -793,11 +791,9 @@ public: void DisableAAEffect(aaEffectType type); bool CheckAAEffect(aaEffectType type); void HandleAAAction(aaID activate); - inline uint32 GetAAPointsSpent() { return m_pp.aapoints_spent; } int16 CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id); int16 CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id); void RefundAA(); - void IncrementAA(int aa_id); int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2); int32 GetAAEffectid(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, true, false,false); } int32 GetAABase1(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, true,false); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e7d3b61a7..2068a815c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8801,7 +8801,7 @@ void Client::Handle_OP_LFGuild(const EQApplicationPacket *app) pack->WriteUInt32(QSG_LFGuild_UpdatePlayerInfo); pack->WriteUInt32(GetBaseClass()); pack->WriteUInt32(GetLevel()); - pack->WriteUInt32(GetAAPointsSpent()); + pack->WriteUInt32(GetSpentAA()); pack->WriteString(pts->Comment); pack->WriteUInt32(pts->Toggle); pack->WriteUInt32(pts->TimeZone); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 47607b705..37f379a06 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1024,7 +1024,7 @@ void Lua_Client::AddLevelBasedExp(int exp_pct, int max_level) { void Lua_Client::IncrementAA(int aa) { Lua_Safe_Call_Void(); - self->IncrementAA(aa); + self->IncrementAlternateAdvancementRank(aa); } void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z) { diff --git a/zone/mob.h b/zone/mob.h index ce9fe3634..db3879257 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -961,7 +961,7 @@ public: bool SetAA(uint32 rank_id, uint32 new_value, uint32 charges = 0); void ClearAAs() { aa_ranks.clear(); } bool CanUseAlternateAdvancementRank(AA::Rank *rank); - bool CanPurchaseAlternateAdvancementRank(AA::Rank *ran); + bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price); protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d564a341e..95fc146ae 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4916,7 +4916,7 @@ XS(XS_Client_IncrementAA) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - THIS->IncrementAA(aaskillid); + THIS->IncrementAlternateAdvancementRank(aaskillid); } XSRETURN_EMPTY; } diff --git a/zone/titles.cpp b/zone/titles.cpp index 3a4162060..8e6115aee 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -179,10 +179,10 @@ bool TitleManager::IsClientEligibleForTitle(Client *c, std::vector:: if((Title->Class >= 0) && (c->GetBaseClass() != Title->Class)) return false; - if((Title->MinAAPoints >= 0) && (c->GetAAPointsSpent() < static_cast(Title->MinAAPoints))) + if((Title->MinAAPoints >= 0) && (c->GetSpentAA() < static_cast(Title->MinAAPoints))) return false; - if((Title->MaxAAPoints >= 0) && (c->GetAAPointsSpent() > static_cast(Title->MaxAAPoints))) + if((Title->MaxAAPoints >= 0) && (c->GetSpentAA() > static_cast(Title->MaxAAPoints))) return false; if(Title->SkillID >= 0) From dd345c01de2be23d6dbd711d8e811776e2a5d833 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 11 Jun 2015 21:33:39 -0700 Subject: [PATCH 173/846] Activating AAs now works, don't have expend charges working quite yet so they can just be cast over and over. --- common/eq_packet_structs.h | 2 +- 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_structs.h | 2 +- common/patches/sof_structs.h | 2 +- common/patches/titanium_structs.h | 2 +- common/patches/uf.cpp | 2 +- common/patches/uf_structs.h | 2 +- common/spdat.h | 2 +- zone/aa.cpp | 233 ++++++++++++++++++++---------- zone/client.cpp | 2 +- zone/client.h | 6 +- zone/client_packet.cpp | 8 +- zone/mob.h | 1 + zone/spells.cpp | 5 +- 17 files changed, 176 insertions(+), 101 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index e562a94e5..7b604fc47 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4319,7 +4319,7 @@ struct SendAA_Struct { struct AA_Action { /*00*/ uint32 action; /*04*/ uint32 ability; -/*08*/ uint32 unknown08; +/*08*/ uint32 target_id; /*12*/ uint32 exp_value; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 0596ee95b..e76f33bbe 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2810,7 +2810,7 @@ namespace RoF eq->aa_spent = emu->aa_spent; // These fields may need to be correctly populated at some point - eq->aapoints_assigned = 0; + eq->aapoints_assigned = emu->aa_spent; eq->aa_spent_general = 0; eq->aa_spent_archetype = 0; eq->aa_spent_class = 0; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index ba2099710..ec5752f79 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2900,7 +2900,7 @@ namespace RoF2 eq->aa_spent = emu->aa_spent; // These fields may need to be correctly populated at some point - eq->aapoints_assigned = 0; + eq->aapoints_assigned = emu->aa_spent; eq->aa_spent_general = 0; eq->aa_spent_archetype = 0; eq->aa_spent_class = 0; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 812e9c464..bc49fe88f 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4289,7 +4289,7 @@ struct AA_List { struct AA_Action { /*00*/ uint32 action; /*04*/ uint32 ability; -/*08*/ uint32 unknown08; +/*08*/ uint32 target_id; /*12*/ uint32 exp_value; /*16*/ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index a87b530c4..eb7c6edfb 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4288,7 +4288,7 @@ struct AA_List { struct AA_Action { /*00*/ uint32 action; /*04*/ uint32 ability; -/*08*/ uint32 unknown08; +/*08*/ uint32 target_id; /*12*/ uint32 exp_value; /*16*/ }; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 2f5d2c2db..6e1a77b6b 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -3840,7 +3840,7 @@ struct AA_List { struct AA_Action { /*00*/ uint32 action; /*04*/ uint32 ability; -/*08*/ uint32 unknown08; +/*08*/ uint32 target_id; /*12*/ uint32 exp_value; }; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index afd34ba68..faa306ab0 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3702,7 +3702,7 @@ struct AA_List { struct AA_Action { /*00*/ uint32 action; /*04*/ uint32 ability; -/*08*/ uint32 unknown08; +/*08*/ uint32 target_id; /*12*/ uint32 exp_value; }; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index f836395c9..e5fa44a8e 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3175,7 +3175,7 @@ struct AA_List { struct AA_Action { /*00*/ uint32 action; /*04*/ uint32 ability; -/*08*/ uint32 unknown08; +/*08*/ uint32 target_id; /*12*/ uint32 exp_value; }; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index df6fa9615..ef224d574 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2129,7 +2129,7 @@ namespace UF SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); eq->aa_spent = emu->aa_spent; - eq->aa_assigned = 0; + eq->aa_assigned = emu->aa_spent; eq->aa_spent3 = 0; eq->unknown012 = 0; eq->unknown016 = 0; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 36d6dea74..882158492 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -3912,7 +3912,7 @@ struct AA_List { struct AA_Action { /*00*/ uint32 action; /*04*/ uint32 ability; -/*08*/ uint32 unknown08; +/*08*/ uint32 target_id; /*12*/ uint32 exp_value; }; diff --git a/common/spdat.h b/common/spdat.h index bf2d23f30..bb71c1e88 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -417,7 +417,7 @@ typedef enum { #define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live) #define SE_RaiseStatCap 262 // implemented //#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master. -//#define SE_HastenedAASkill 264 // not implemented as bonus - Use redux field in aa_actions table for this effect +#define SE_HastenedAASkill 264 // implemented #define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled #define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon. #define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast diff --git a/zone/aa.cpp b/zone/aa.cpp index d6be92fe7..368eda225 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -37,32 +37,6 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) extern QueryServ* QServ; -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) @@ -930,39 +904,6 @@ bool Client::CheckAAEffect(aaEffectType type) { return(false); } -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::ResetAA(){ // RefundAA(); // uint32 i; @@ -1457,6 +1398,39 @@ void Client::SendAlternateAdvancementPoints() { safe_delete(outapp); } +void Client::SendAlternateAdvancementTimer(int ability, int begin, int 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::SendAlternateAdvancementTimers() { + //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::PurchaseAlternateAdvancementRank(int rank_id) { AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); if(!rank) { @@ -1495,23 +1469,21 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { std::to_string(rank->cost).c_str(), std::to_string(AA_POINTS).c_str()); - //QS stuff broke with new aa, todo: fix later /* QS: Player_Log_AA_Purchases */ - // if (RuleB(QueryServ, PlayerLogAAPurchases)){ - // std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - // } + if (RuleB(QueryServ, PlayerLogAAPurchases)){ + std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); + QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); + } } else { Message_StringID(15, AA_GAIN_ABILITY, std::to_string(rank->title_sid).c_str(), std::to_string(rank->cost).c_str(), std::to_string(AA_POINTS).c_str()); - //QS stuff broke with new aa, todo: fix later /* QS: Player_Log_AA_Purchases */ - // if (RuleB(QueryServ, PlayerLogAAPurchases)){ - // std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - // } + if (RuleB(QueryServ, PlayerLogAAPurchases)){ + std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); + QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); + } } CalcBonuses(); @@ -1557,29 +1529,132 @@ void Client::IncrementAlternateAdvancementRank(int rank_id) { std::to_string(rank->cost).c_str(), std::to_string(AA_POINTS).c_str()); - //QS stuff broke with new aa, todo: fix later /* QS: Player_Log_AA_Purchases */ - // if (RuleB(QueryServ, PlayerLogAAPurchases)){ - // std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - // } + if (RuleB(QueryServ, PlayerLogAAPurchases)){ + std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); + QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); + } } else { Message_StringID(15, AA_GAIN_ABILITY, std::to_string(rank->title_sid).c_str(), std::to_string(rank->cost).c_str(), std::to_string(AA_POINTS).c_str()); - //QS stuff broke with new aa, todo: fix later + /* QS: Player_Log_AA_Purchases */ - // if (RuleB(QueryServ, PlayerLogAAPurchases)){ - // std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - // } + if (RuleB(QueryServ, PlayerLogAAPurchases)){ + std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); + QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + } } CalcBonuses(); } +void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { + AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); + if(!rank) { + return; + } + + AA::Ability *ability = rank->base_ability; + if(!ability) { + return; + } + + if(!IsValidSpell(rank->spell)) { + return; + } + + if(!CanUseAlternateAdvancementRank(rank)) { + return; + } + + //make sure it's activateable type + if(!(ability->type == 3 || ability->type == 4)) { + return; + } + + //check cooldown + if(!p_timers.Expired(&database, rank->spell_type + pTimerAAStart)) { + uint32 aaremain = p_timers.GetRemainingTime(rank->spell_type + pTimerAAStart); + uint32 aaremain_hr = aaremain / (60 * 60); + uint32 aaremain_min = (aaremain / 60) % 60; + uint32 aaremain_sec = aaremain % 60; + + if(aaremain_hr >= 1) { + Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", + aaremain_hr, aaremain_min, aaremain_sec); + } + else { + Message(13, "You can use this ability again in %u minute(s) %u seconds", + aaremain_min, aaremain_sec); + } + + return; + } + + //calculate cooldown + int cooldown = rank->recast_time - GetAlternateAdvancementCooldownReduction(rank); + if(cooldown < 0) { + cooldown = 0; + } + + // 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), 10, -1, -1, spells[rank->spell].ResistDiff, false)) { + //Reset on failed cast + SendAlternateAdvancementTimer(rank->spell_type, 0, -1); + Message_StringID(15, ABILITY_FAILED); + p_timers.Clear(&database, rank->spell_type + pTimerAAStart); + return; + } + } else { + if(!CastSpell(rank->spell, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, 1)) { + //Reset on failed cast + SendAlternateAdvancementTimer(rank->spell_type, 0, -1); + Message_StringID(15, ABILITY_FAILED); + p_timers.Clear(&database, rank->spell_type + pTimerAAStart); + return; + } + } + + if(cooldown > 0) { + SendAlternateAdvancementTimer(rank->spell_type, 0, 0); + } +} + +int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) { + if(!rank_in) { + return 0; + } + + AA::Ability *ability_in = rank_in->base_ability; + if(!ability_in) { + return 0; + } + + for(auto &aa : aa_ranks) { + AA::Ability *ability = zone->GetAlternateAdvancementAbility(aa.first); + if(!ability) { + continue; + } + + AA::Rank *rank = ability->GetRankByPointsSpent(aa.second.first); + if(!rank) { + continue; + } + + for(auto &effect : rank->effects) { + if(effect.effect_id == SE_HastenedAASkill && effect.base2 == ability_in->id) { + return effect.base1; + } + } + } + + return 0; +} + bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { c->ClearAAs(); std::string query = StringFormat( diff --git a/zone/client.cpp b/zone/client.cpp index f36609b9c..5ef3e84e5 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -456,7 +456,7 @@ void Client::SendZoneInPackets() } safe_delete(outapp); - SendAATimers(); + SendAlternateAdvancementTimers(); outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(ZoneInSendName_Struct)); ZoneInSendName_Struct* zonesendname = (ZoneInSendName_Struct*)outapp->pBuffer; diff --git a/zone/client.h b/zone/client.h index 082d86fdc..dd283596d 100644 --- a/zone/client.h +++ b/zone/client.h @@ -765,7 +765,10 @@ public: void SendAlternateAdvancementStats(); void PurchaseAlternateAdvancementRank(int rank_id); void IncrementAlternateAdvancementRank(int rank_id); + void ActivateAlternateAdvancementAbility(int rank_id, int target_id); void SendAlternateAdvancementPoints(); + void SendAlternateAdvancementTimer(int ability, int begin, int end); + void SendAlternateAdvancementTimers(); void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } @@ -782,11 +785,8 @@ public: inline uint32 GetMaxAAXP(void) const { return max_AAXP; } inline uint32 GetAAXP() const { return m_pp.expAA; } void SendAATable(); - void SendAATimers(); - int GetAATimerID(aaID activate); int CalcAAReuseTimer(const AA_DBAction *caa); void ActivateAA(aaID activate); - void SendAATimer(uint32 ability, uint32 begin, uint32 end); void EnableAAEffect(aaEffectType type, uint32 duration = 0); void DisableAAEffect(aaEffectType type); bool CheckAAEffect(aaEffectType type); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2068a815c..b76c11d8c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1082,7 +1082,7 @@ void Client::Handle_Connect_OP_ReqNewZone(const EQApplicationPacket *app) void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app) { - SendAATimers(); + SendAlternateAdvancementTimers(); EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAAStats, 0); QueuePacket(outapp); safe_delete(outapp); @@ -1749,7 +1749,7 @@ void Client::Handle_OP_AAAction(const EQApplicationPacket *app) if (action->action == aaActionActivate) {//AA Hotkey Log.Out(Logs::Detail, Logs::AA, "Activating AA %d", action->ability); - //ActivateAlternateAdvancementAbility(action->ability); + ActivateAlternateAdvancementAbility(action->ability, action->target_id); } else if (action->action == aaActionBuy) { PurchaseAlternateAdvancementRank(action->ability); @@ -1773,7 +1773,7 @@ void Client::Handle_OP_AAAction(const EQApplicationPacket *app) SendAlternateAdvancementTable(); } else { - Log.Out(Logs::General, Logs::AA, "Unknown AA action : %u %u 0x%x %d", action->action, action->ability, action->unknown08, action->exp_value); + Log.Out(Logs::General, Logs::AA, "Unknown AA action : %u %u %u %d", action->action, action->ability, action->target_id, action->exp_value); } } @@ -3847,8 +3847,6 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) return; } - m_TargetRing = glm::vec3(castspell->x_pos, castspell->y_pos, castspell->z_pos); - CastSpell(spell_to_cast, castspell->target_id, castspell->slot); } /* Spell Slot or Potion Belt Slot */ diff --git a/zone/mob.h b/zone/mob.h index db3879257..08c6cd482 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -962,6 +962,7 @@ public: void ClearAAs() { aa_ranks.clear(); } bool CanUseAlternateAdvancementRank(AA::Rank *rank); bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price); + int GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in); protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); diff --git a/zone/spells.cpp b/zone/spells.cpp index 868180dff..4ef1337a7 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -817,8 +817,8 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) } if(casting_spell_type == 1 && IsClient()) { //Rest AA Timer on failed cast - CastToClient()->SendAATimer(casting_spell_timer - pTimerAAStart, 0, 0xFFFFFF); - CastToClient()->Message_StringID(15,ABILITY_FAILED); + CastToClient()->SendAlternateAdvancementTimer(casting_spell_timer - pTimerAAStart, 0, -1); + CastToClient()->Message_StringID(15, ABILITY_FAILED); CastToClient()->GetPTimers().Clear(&database, casting_spell_timer); } @@ -2276,6 +2276,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 { if(spell_id == casting_spell_id && casting_spell_timer != 0xFFFFFFFF) { + //aa new todo: aa expendable charges here CastToClient()->GetPTimers().Start(casting_spell_timer, casting_spell_timer_duration); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Setting custom reuse timer %d to %d", spell_id, casting_spell_timer, casting_spell_timer_duration); } From afaa9ee6c995dbad567477dac038816fd8fe4fae Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 11 Jun 2015 23:08:17 -0700 Subject: [PATCH 174/846] Expendable aa work --- zone/aa.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++----- zone/bot.cpp | 9 ++++---- zone/bot.h | 5 +++-- zone/mob.cpp | 1 + zone/mob.h | 8 +++++-- zone/spells.cpp | 15 +++++++++---- 6 files changed, 77 insertions(+), 17 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 368eda225..20009d281 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1276,7 +1276,8 @@ Mob *AA_SwarmPetInfo::GetOwner() //New AA void Client::SendAlternateAdvancementTable() { for(auto &aa : zone->aa_abilities) { - auto ranks = GetAA(aa.second->first_rank_id); + uint32 charges = 0; + auto ranks = GetAA(aa.second->first_rank_id, &charges); if(ranks) { if(aa.second->GetMaxLevel() == ranks) { SendAlternateAdvancementRank(aa.first, ranks); @@ -1446,7 +1447,12 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { } if(rank->base_ability->charges > 0) { - SetAA(rank_id, rank->current_value, rank->base_ability->charges); + uint32 charges = 0; + GetAA(rank_id, &charges); + + if(charges == 0) { + SetAA(rank_id, rank->current_value, rank->base_ability->charges); + } } else { SetAA(rank_id, rank->current_value, 0); @@ -1570,11 +1576,21 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { return; } - //make sure it's activateable type - if(!(ability->type == 3 || ability->type == 4)) { + //make sure it is not a passive + if(rank->effects.size() > 0) { return; } + //if expendable make sure we have charges + if(ability->charges > 0) { + uint32 charges = 0; + GetAA(rank_id, &charges); + + if(charges < 0) { + return; + } + } + //check cooldown if(!p_timers.Expired(&database, rank->spell_type + pTimerAAStart)) { uint32 aaremain = p_timers.GetRemainingTime(rank->spell_type + pTimerAAStart); @@ -1609,8 +1625,9 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { p_timers.Clear(&database, rank->spell_type + pTimerAAStart); return; } + ExpendAlternateAdvancementCharge(ability->id); } else { - if(!CastSpell(rank->spell, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, 1)) { + if(!CastSpell(rank->spell, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, 1, nullptr, ability->id)) { //Reset on failed cast SendAlternateAdvancementTimer(rank->spell_type, 0, -1); Message_StringID(15, ABILITY_FAILED); @@ -1655,6 +1672,35 @@ int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) { return 0; } +void Mob::ExpendAlternateAdvancementCharge(uint32 aa_id) { + for(auto &iter : aa_ranks) { + AA::Ability *ability = zone->GetAlternateAdvancementAbility(iter.first); + if(ability && aa_id == ability->id) { + if(iter.second.second > 0) { + iter.second.second -= 1; + + if(iter.second.second == 0) { + aa_ranks.erase(iter.first); + if(IsClient()) { + AA::Rank *r = ability->GetRankByPointsSpent(iter.second.first); + if(r) { + CastToClient()->GetEPP().expended_aa += r->cost; + } + } + } + + if(IsClient()) { + Client *c = CastToClient(); + c->SaveAA(); + c->SendAlternateAdvancementPoints(); + } + } + + return; + } + } +} + bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { c->ClearAAs(); std::string query = StringFormat( diff --git a/zone/bot.cpp b/zone/bot.cpp index c6c0f6e7f..1d8c16f57 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -9078,7 +9078,8 @@ 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, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust) { +bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 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()))) { @@ -9143,7 +9144,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t bardsong_timer.Disable(); } - Result = DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot); + Result = DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, aa_id); } return Result; @@ -9305,7 +9306,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) { +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 Result = false; if(GetClass() == BARD) { @@ -9313,7 +9314,7 @@ bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast cast_time = 0; } - Result = Mob::DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot); + Result = Mob::DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, aa_id); if(oSpellWillFinish) { const SPDat_Spell_Struct &spell = spells[spell_id]; diff --git a/zone/bot.h b/zone/bot.h index 1f1262ffc..4a88c5f18 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -314,11 +314,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, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = 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, + 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 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); + 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); diff --git a/zone/mob.cpp b/zone/mob.cpp index b107565bc..645b42325 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -309,6 +309,7 @@ Mob::Mob(const char* in_name, casting_spell_timer_duration = 0; casting_spell_type = 0; casting_spell_inventory_slot = 0; + casting_spell_aa_id = 0; target = 0; ActiveProjectileATK = false; diff --git a/zone/mob.h b/zone/mob.h index 08c6cd482..ed5d68c2c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -222,10 +222,12 @@ public: virtual void SpellProcess(); 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, uint32 item_slot = 0xFFFFFFFF, - uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr); + uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr, + uint32 aa_id = 0); 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); + uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 resist_adjust = 0, + uint32 aa_id = 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, @@ -963,6 +965,7 @@ public: bool CanUseAlternateAdvancementRank(AA::Rank *rank); bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price); int GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in); + void ExpendAlternateAdvancementCharge(uint32 aa_id); protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); @@ -1152,6 +1155,7 @@ protected: uint32 casting_spell_timer_duration; uint32 casting_spell_type; int16 casting_spell_resist_adjust; + uint32 casting_spell_aa_id; bool casting_spell_checks; uint16 bardsong; uint8 bardsong_slot; diff --git a/zone/spells.cpp b/zone/spells.cpp index 4ef1337a7..ea4d1068b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -146,7 +146,8 @@ void NPC::SpellProcess() // to allow procs to work bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, - uint32 timer, uint32 timer_duration, uint32 type, int16 *resist_adjust) + uint32 timer, uint32 timer_duration, uint32 type, 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); @@ -318,11 +319,11 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, if(resist_adjust) { - return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, type, *resist_adjust)); + return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, type, *resist_adjust, aa_id)); } else { - return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, type, spells[spell_id].ResistDiff)); + return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, type, spells[spell_id].ResistDiff, aa_id)); } } @@ -337,7 +338,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 timer, uint32 timer_duration, uint32 type, - int16 resist_adjust) + int16 resist_adjust, uint32 aa_id) { Mob* pMob = nullptr; int32 orgcasttime; @@ -361,6 +362,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, casting_spell_timer = timer; casting_spell_timer_duration = timer_duration; } + casting_spell_aa_id = aa_id; casting_spell_type = type; SaveSpellLoc(); @@ -786,6 +788,7 @@ void Mob::ZeroCastingVars() casting_spell_type = 0; casting_spell_resist_adjust = 0; casting_spell_checks = false; + casting_spell_aa_id = 0; delaytimer = false; } @@ -2297,6 +2300,10 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Setting long reuse timer to %d s (orig %d)", spell_id, recast, spells[spell_id].recast_time); CastToClient()->GetPTimers().Start(pTimerSpellStart + spell_id, recast); } + + if(casting_spell_aa_id) { + ExpendAlternateAdvancementCharge(casting_spell_aa_id); + } } if(IsClient() && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT) || (slot == TARGET_RING_SPELL_SLOT))) From e5d1e98793dce69f38945452883d7f9a1a3bb44d Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 12 Jun 2015 02:56:51 -0700 Subject: [PATCH 175/846] Added deity and race checking to AAs, doubled over the sanity check code and found a mistake, added code to make boats move smoother after loading into oot 50 times and seeing it skip every time. --- zone/aa.cpp | 92 ++++++++++++++++++++++++++------------------- zone/aa_ability.cpp | 14 ++++--- zone/aa_ability.h | 7 +++- zone/mob.cpp | 4 ++ zone/waypoints.cpp | 4 +- 5 files changed, 72 insertions(+), 49 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 20009d281..fc1923506 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -23,7 +23,7 @@ Copyright (C) 2001-2004 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" @@ -1279,7 +1279,7 @@ void Client::SendAlternateAdvancementTable() { uint32 charges = 0; auto ranks = GetAA(aa.second->first_rank_id, &charges); if(ranks) { - if(aa.second->GetMaxLevel() == ranks) { + if(aa.second->GetMaxLevel(this) == ranks) { SendAlternateAdvancementRank(aa.first, ranks); } else { SendAlternateAdvancementRank(aa.first, ranks); @@ -1330,7 +1330,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { aai->classes = ability->classes; aai->level_req = rank->level_req; aai->current_level = level; - aai->max_level = ability->GetMaxLevel(); + aai->max_level = ability->GetMaxLevel(this); aai->prev_id = rank->prev_id; if(rank->next && !CanUseAlternateAdvancementRank(rank->next)) { @@ -1450,9 +1450,11 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { uint32 charges = 0; GetAA(rank_id, &charges); - if(charges == 0) { - SetAA(rank_id, rank->current_value, rank->base_ability->charges); + if(charges > 0) { + return; } + + SetAA(rank_id, rank->current_value, rank->base_ability->charges); } else { SetAA(rank_id, rank->current_value, 0); @@ -1781,7 +1783,7 @@ bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) { return false; } - if(new_value > ability->GetMaxLevel()) { + if(new_value > ability->GetMaxLevel(this)) { return false; } @@ -1817,29 +1819,44 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { } } - //I might add a races behind the scenes field to take care of this - // Check for racial/Drakkin blood line AAs - if(ability->category == 8) - { - uint32 client_race = GetBaseRace(); - - // Drakkin Bloodlines - if(rank->expansion > 522) - { - if(client_race != 522) - return false; - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if(heritage != rank->expansion) - return false; - } - else if(client_race != rank->expansion) - { - return false; - } + if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { + return false; } + auto race = GetArrayRace(GetBaseRace()); + race = race > 16 ? 1 : race; + if(!(ability->races & (1 << (race - 1)))) { + return false; + } + + auto deity = ConvertDeityToBitDeity((DeityTypes)GetDeity()); + if(!(ability->deities & deity)) { + return false; + } + + // Check for racial/Drakkin blood line AAs + //Commented this out for now, will add a drakkin heritage field later + //if(ability->category == 8) + //{ + // uint32 client_race = GetBaseRace(); + // + // // Drakkin Bloodlines + // if(rank->expansion > 522) + // { + // if(client_race != 522) + // return false; + // + // int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline + // + // if(heritage != rank->expansion) + // return false; + // } + // else if(client_race != rank->expansion) + // { + // return false; + // } + //} + return true; } @@ -1858,10 +1875,6 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) return false; } - if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { - return false; - } - //check level req if(rank->level_req > GetLevel()) { return false; @@ -1940,8 +1953,6 @@ void Zone::LoadAlternateAdvancement() { i++; current = current->next; } - - ability.second->GetMaxLevel(true); } Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Data"); @@ -1952,7 +1963,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = atoi(row[0]); ability->name = row[1]; ability->category = atoi(row[2]); - ability->classes = atoi(row[3]); - ability->type = atoi(row[4]); - ability->charges = atoi(row[5]); - ability->grant_only = atoi(row[6]) != 0 ? true : false; - ability->first_rank_id = atoi(row[7]); + //EQ client has classes left shifted by one bit for some odd reason + ability->classes = atoi(row[3]) << 1; + ability->races = atoi(row[4]); + ability->deities = atoi(row[5]); + ability->type = atoi(row[6]); + ability->charges = atoi(row[7]); + ability->grant_only = atoi(row[8]) != 0 ? true : false; + ability->first_rank_id = atoi(row[9]); ability->first = nullptr; abilities[ability->id] = std::unique_ptr(ability); diff --git a/zone/aa_ability.cpp b/zone/aa_ability.cpp index 8f9cb8da4..3612b00c7 100644 --- a/zone/aa_ability.cpp +++ b/zone/aa_ability.cpp @@ -18,6 +18,7 @@ #include "../common/global_define.h" #include "../common/types.h" +#include "masterentity.h" #include "aa_ability.h" AA::Rank *AA::Ability::GetMaxRank() { @@ -53,16 +54,17 @@ AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) { return current; } -int AA::Ability::GetMaxLevel(bool force_calc) { - if(!force_calc) - return max_level; - - max_level = 0; +int AA::Ability::GetMaxLevel(Mob *who) { + int max_level = 0; Rank *current = first; while(current) { + if(!who->CanUseAlternateAdvancementRank(current)) { + return max_level; + } + max_level++; current = current->next; } - + return max_level; } \ No newline at end of file diff --git a/zone/aa_ability.h b/zone/aa_ability.h index a31bc06e3..bd2b9e306 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -27,6 +27,8 @@ #include "aa_rank_prereqs.h" #include "aa_rank.h" +class Mob; + namespace AA { @@ -39,17 +41,18 @@ public: Rank *GetMaxRank(); Rank *GetRankByLevel(int level); Rank *GetRankByPointsSpent(int current_level); - int GetMaxLevel(bool force_calc = false); + int GetMaxLevel(Mob *who); int id; std::string name; int category; int classes; + int races; + int deities; bool grant_only; int type; int charges; int first_rank_id; - int max_level; Rank *first; }; diff --git a/zone/mob.cpp b/zone/mob.cpp index 645b42325..965007fcf 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1143,6 +1143,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) else ns->spawn.flymode = flymode; + if(IsBoat()) { + ns->spawn.flymode = 1; + } + ns->spawn.lastName[0] = '\0'; strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 7570165a3..834109dd1 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -212,7 +212,7 @@ void NPC::UpdateWaypoint(int wp_index) Log.Out(Logs::Detail, Logs::AI, "Next waypoint %d: (%.3f, %.3f, %.3f, %.3f)", wp_index, m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, m_CurrentWayPoint.w); //fix up pathing Z - if(zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints)) + if(zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints) && !IsBoat()) { if(!RuleB(Watermap, CheckForWaterAtWaypoints) || !zone->HasWaterMap() || @@ -521,7 +521,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo } bool send_update = false; - int compare_steps = IsBoat() ? 1 : 20; + int compare_steps = 20; if(tar_ndx < compare_steps && m_TargetLocation.x==x && m_TargetLocation.y==y) { float new_x = m_Position.x + m_TargetV.x*tar_vector; From 65ac9683a3035691ecdcdfb33cacd3285486a081 Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 12 Jun 2015 13:39:20 -0700 Subject: [PATCH 176/846] Removed fluff code, added drakkin heritage and status can use modifiers to aa abilities --- zone/aa.cpp | 468 ++--------------------------------- zone/aa.h | 605 ---------------------------------------------- zone/aa_ability.h | 2 + zone/client.h | 3 - zone/command.cpp | 83 ------- zone/command.h | 2 - 6 files changed, 20 insertions(+), 1143 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index fc1923506..cf2fb0685 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -37,428 +37,6 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) extern QueryServ* QServ; -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, USE_ITEM_SPELL_SLOT, -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); -// -// SaveAA(); /* Save Character AA */ -// 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 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 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: -// Log.Out(Logs::General, Logs::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, USE_ITEM_SPELL_SLOT, -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); -// } -} - void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg) { //It might not be a bad idea to put these into the database, eventually.. @@ -1333,7 +911,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)) { + if(rank->next && !CanUseAlternateAdvancementRank(rank->next) || ability->charges > 0) { aai->next_id = -1; } else { aai->next_id = rank->next_id; @@ -1834,28 +1412,16 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return false; } - // Check for racial/Drakkin blood line AAs - //Commented this out for now, will add a drakkin heritage field later - //if(ability->category == 8) - //{ - // uint32 client_race = GetBaseRace(); - // - // // Drakkin Bloodlines - // if(rank->expansion > 522) - // { - // if(client_race != 522) - // return false; - // - // int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - // - // if(heritage != rank->expansion) - // return false; - // } - // else if(client_race != rank->expansion) - // { - // return false; - // } - //} + if(IsClient() && CastToClient()->Admin() < ability->status) { + return false; + } + + if(GetBaseRace() == 522) { + //drakkin_heritage + if(!(ability->drakkin_heritage & (1 << GetDrakkinHeritage()))) { + return false; + } + } return true; } @@ -1963,7 +1529,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapclasses = atoi(row[3]) << 1; ability->races = atoi(row[4]); ability->deities = atoi(row[5]); - ability->type = atoi(row[6]); - ability->charges = atoi(row[7]); - ability->grant_only = atoi(row[8]) != 0 ? true : false; - ability->first_rank_id = atoi(row[9]); + ability->drakkin_heritage = atoi(row[6]); + ability->status = atoi(row[7]); + ability->type = atoi(row[8]); + ability->charges = atoi(row[9]); + ability->grant_only = atoi(row[10]) != 0 ? true : false; + ability->first_rank_id = atoi(row[11]); ability->first = nullptr; abilities[ability->id] = std::unique_ptr(ability); diff --git a/zone/aa.h b/zone/aa.h index 54d495e6e..0ee32c99a 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -1,27 +1,8 @@ - #ifndef AA_H #define AA_H -struct AA_Ability; -struct SendAA_Struct; - - -#define MANA_BURN 664 - -#include - #define MAX_SWARM_PETS 12 //this can change as long as you make more coords (swarm_pet_x/swarm_pet_y) -//this might be missing some, and some might not be used... -typedef enum { //AA Targeting Constants - aaTargetUser = 1, - aaTargetCurrent = 2, //use current target - aaTargetGroup = 3, //target group of user - aaTargetCurrentGroup = 4, //target group of current target - aaTargetPet = 5 //target the user's pet -} aaTargetType; - - typedef enum { aaActionNone = 0, aaActionAETaunt = 1, @@ -133,571 +114,6 @@ static const uint8 LeadershipAACosts[_maxLeaderAA][MAX_LEADERSHIP_TIERS] = { { 0, 0, 0, 0, 0, 0 }, //raidAA15 }; -/* -typedef enum { //AA IDs - aaNone = 0, - aaInnateStrength = 2, //works - aaInnateStamina = 7, //works - aaInnateAgility = 12, //works - //aaCompleteHeal = 13,/ //not implemented, but is in dbstr_us.txt - aaInnateDexterity = 17, //works - aaInnateIntelligence = 22, //works - aaInnateWisdom = 27, //works - aaInnateCharisma = 32, //works - aaInnateFireProtection = 37, //works - aaInnateColdProtection = 42, //works - aaInnateMagicProtection = 47, //works - aaInnatePoisonProtection = 52, //works - aaInnateDiseaseProtection = 57, //works - aaInnateRunSpeed = 62, //works - aaInnateRegeneration = 65, //works - aaInnateMetabolism = 68, - aaInnateLungCapacity = 71, //handled by client - aaFirstAid = 74, //untested - aaHealingAdept = 77, //untested - aaHealingGift = 80, //untested - aaSpellCastingMastery = 83, //untested - aaSpellCastingReinforcement = 86, //untested - aaMentalClarity = 89, - aaSpellCastingFury = 92, //untested - aaChanellingFocus = 95, - aaSpellCastingSubtlety = 98, //untested - aaSpellCastingExpertise = 101, //untested - aaSpellCastingDeftness = 104, //untested - aaNaturalDurability = 107, //works - aaNaturalHealing = 110, //untested - aaCombatFury = 113, //untested - aaFearResistance = 116, //untested - aaFinishingBlow = 119, //untested - aaCombatStability = 122, - aaCombatAgility = 125, - aaMassGroupBuff = 128, //untested - aaDivineResurrection = 129, //DB - aaInnateInvisToUndead = 130, //DB - aaCelestialRegeneration = 131, //untested - aaBestowDivineAura = 132, //DB - aaTurnUndead = 133, //DB - aaPurifySoul = 136, //DB - aaQuickEvacuation = 137, //untested - aaExodus = 140, //untested - aaQuickDamage = 141, //untested - aaEnhancedRoot = 144, - aaDireCharm = 145, //untested - aaCannibalization = 146, //DB - aaQuickBuff = 147, //untested - aaAlchemyMastery = 150, - aaRabidBear = 153, //DB - aaManaBurn = 154, //DB - aaImprovedFamiliar = 155, //untested, implemented? - aaNexusGate = 156, //DB - aaUnknown54 = 157, - aaPermanentIllusion = 158, - aaJewelCraftMastery = 159, - aaGatherMana = 162, //DB - aaMendCompanion = 163, //DB - aaQuickSummoning = 164, //untested - aaFrenziedBurnout = 167, //DB - aaElementalFormFire = 168, //DB - aaElementalFormWater = 171, //DB - aaElementalFormEarth = 174, //DB - aaElementalFormAir = 177, //DB - aaImprovedReclaimEnergy = 180, //untested - aaTurnSummoned = 181, //DB - aaElementalPact = 182, //DB - aaLifeBurn = 183, //DB - aaDeadMesmerization = 184, //DB - aaFearstorm = 185, //DB - aaFleshToBone = 186, //DB - aaCallToCorpse = 187, //DB - aaDivineStun = 188, //DB - aaImprovedLayOnHands = 189, - aaSlayUndead = 190, - aaActOfValor = 193, //DB - aaHolySteed = 194, //DB - aaFearless = 195, - aa2HandBash = 196, //works. handled by client? - aaInnateCamouflage = 197, //DB - aaAmbidexterity = 198, //untested - aaArcheryMastery = 199, //untested - aaFletchingMastery = 202, //removed from db? - aaEndlessQuiver = 205, //untested - aaUnholySteed = 206, //DB - aaImprovedHarmTouch = 207, //untested - aaLeechTouch = 208, //DB - aaDeathPeace = 209, - aaSoulAbrasion = 210, //untested - aaInstrumentMastery = 213, //untested - aaUnknown91 = 216, //not used - aaUnknown92 = 219, //not used - aaUnknown93 = 222, //not used - aaJamFest = 225, - aaUnknown95 = 228, - aaSonicCall = 229, - aaCriticalMend = 230, //untested - aaPurifyBody = 233, //DB - aaChainCombo = 234, - aaRapidFeign = 237, //works - aaReturnKick = 240, - aaEscape = 243, //DB - aaPoisonMastery = 244, - aaDoubleRiposte = 247, //untested - aaQuickHide = 250, - aaQuickThrow = 253, //corrected from dbstr_us.txt - aaPurgePoison = 254, //DB - aaFlurry = 255, //untested - aaRampage = 258, //untested - aaAreaTaunt = 259, //untested - aaWarcry = 260, //DB - aaBandageWound = 263, //untested - aaSpellCastingReinforcementMastery = 266, //untested - aaSpellCastingFuryMastery = 267, //untested - aaExtendedNotes = 270, //untested - aaDragonPunch = 273, - aaStrongRoot = 274, //DB - aaSingingMastery = 275, //untested - aaBodyAndMindRejuvenation = 278, //added - aaPhysicalEnhancement = 279, //untested - aaAdvTrapNegotiation = 280, //untested - aaAcrobatics = 283, //untested - aaScribbleNotes = 286, - aaChaoticStab = 287, //untested - aaPetDiscipline = 288, //added - aaHobbleofSpirits = 289, //DB - aaFrenzyofSpirit = 290, //DB - aaParagonofSpirit = 291, //DB - aaAdvancedInnateStrength = 292, //works - aaAdvancedInnateStamina = 302, //works - aaAdvancedInnateAgility = 312, //works - aaAdvancedInnateDexterity = 322, //works - aaAdvancedInnateIntelligence = 332, //works - aaAdvancedInnateWisdom = 342, //works - aaAdvancedInnateCharisma = 352, //works - aaWardingofSolusek = 362, //works - aaBlessingofEci = 372, //works - aaMarrsProtection = 382, //works - aaShroudofTheFaceless = 392, //works - aaBertoxxulousGift = 402, //works - aaNewTanaanCraftingMastery = 412, - aaPlanarPower = 418, //untested - aaPlanarDurability = 423, //added - aaInnateEnlightenment = 426, //added - aaAdvancedSpellCastingMastery = 431,//untested - aaAdvancedHealingAdept = 434, //untested - aaAdvancedHealingGift = 437, //untested - aaCoupdeGrace = 440, //added - aaFuryoftheAges = 443, //added - aaMasteryofthePast = 446, //untested - aaLightningReflexes = 449, //added - aaInnateDefense = 454, //added - aaRadiantCure = 459, //DB - aaHastenedDivinity = 462, //DB - aaHastenedTurning = 465, //DB - aaHastenedPurificationofSoul = 468, //DB - aaHastenedGathering = 471, //DB - aaHastenedRabidity = 474, //DB - aaHastenedExodus = 477, //DB - aaHastenedRoot = 480, //DB - aaHastenedMending = 483, //DB - aaHastenedBanishment = 486, //DB - aaHastenedInstigation = 489, //DB, maybe - aaFuriousRampage = 492, //DB - aaHastenedPurificationoftheBody = 495,//DB - aaHastyExit = 498, //DB - aaHastenedPurification = 501, //DB - aaFlashofSteel = 504, - aaDivineArbitration = 507, //DB - aaWrathoftheWild = 510, //DB - aaVirulentParalysis = 513, //DB - aaHarvestofDruzzil = 516, //DB - aaEldritchRune = 517, //DB - aaServantofRo = 520, //DB - aaWaketheDead = 523, //DB - aaSuspendedMinion = 526, //untested - aaSpiritCall = 528, //DB - aaCelestialRenewal = 531, //DB - aaAllegiantFamiliar = 533, - aaHandofPiety = 534, //DB - aaMithanielsBinding = 537, //untested - aaMendingoftheTranquil = 539, - aaRagingFlurry = 542, - aaGuardianoftheForest = 545, //DB - aaSpiritoftheWood = 548, //DB - aaBestialFrenzy = 551, //untested - aaHarmoniousAttack = 556, //untested - aaKnightsAdvantage = 561, - aaFerocity = 564, - aaViscidRoots = 567, - aaSionachiesCrescendo = 568, //untested - aaAyonaesTutelage = 571, - aaFeignedMinion = 574, - aaUnfailingDivinity = 577, - aaAnimationEmpathy = 580, // Implemented - aaRushtoJudgement = 583, - aaLivingShield = 586, - aaConsumptionoftheSoul = 589, //untested - aaBoastfulBellow = 592, //DB - aaFervrentBlessing = 593, //untested - aaTouchoftheWicked = 596, //untested - aaPunishingBlade = 599, - aaSpeedoftheKnight = 602, - aaShroudofStealth = 605, - aaNimbleEvasion = 606, - aaTechniqueofMasterWu = 611, - aaHostoftheElements = 616, //DB - aaCallofXuzl = 619, //DB - aaHastenedStealth = 622, - aaIngenuity = 625, - aaFleetofFoot = 628, - aaFadingMemories = 630, - aaTacticalMastery = 631, - aaTheftofLife = 634, - aaFuryofMagic = 637, - aaFuryofMagicMastery2 = 640, //whats the difference? - aaProjectIllusion = 643, - aaHeadshot = 644, //added - aaEntrap = 645, //DB - aaUnholyTouch = 646, //untested - aaTotalDomination = 649, // Implemented - aaStalwartEndurance = 652, //implemented as bonus - aaQuickSummoning2 = 655, //whats the difference? - aaMentalClarity2 = 658, //whats the difference? - aaInnateRegeneration2 = 661, //whats the difference? - aaManaBurn2 = 664, //whats the difference? - aaExtendedNotes2 = 665, //not implemented - later expansions replaced Extended Notes with this. - aaSionachiesCrescendo2 = 668, //not implemented - later expansions replaced Sionachies Crescendo with this. - aaImprovedReclaimEnergy2 = 671, //whats the difference? untetsed - aaSwiftJourney = 672, //implemented as bonus - aaConvalescence = 674, //added 9/26/08 - aaLastingBreath = 676, //handled by client - aaPackrat = 678, //added 9/29/08 - aaHeightenedEndurance = 683, - aaWeaponAffinity = 686, //implemented - aaSecondaryForte = 691, - aaPersistantCasting = 692, - aaTuneofPursuance = 695, - aaImprovedInstrumentMastery = 700, - aaImprovedSingingMastery =701, - aaExultantBellowing = 702, - aaEchoofTaelosia = 707, - aaInternalMetronome = 710, //In 2006 this AA was removed. - aaPiousSupplication = 715, - aaBeastialAlignment = 718, //untested - aaWrathofXuzl = 721, - aaFeralSwipe = 723, //DB? - aaWardersFury = 724, - aaWardersAlacrity = 729, - aaPetAffinity = 734, // Implemented - aaMasteryofthePast2 = 735, //whats the difference? - aaSpellCastingSubtlety2 = 738, //whats the difference? - aaTouchoftheDivine = 741, - aaDivineAvatar = 746, //DB - aaExquisiteBenediction = 749, //DB - aaQuickenedCuring = 754, - aaNaturesBoon = 757, //DB - aaAdvancedTracking = 762, - aaCriticalAffliction = 767, - aaFuryofMagicMastery = 770, //whats the difference? - aaDoppelganger = 773, - aaEnchancedForgetfulness = 776, - aaMesmerizationMastery = 781, - aaQuickMassGroupBuff = 782, - aaSharedHealth = 785, - aaElementalFury = 790, - aaElementalAlacrity = 795, - aaElementalAgility = 800, - aaElementalDurability = 803, - aaSinisterStrikes = 806, - aaStrikethrough = 807, - aaStonewall = 810, - aaRapidStrikes = 815, - aaKickMastery = 820, - aaHightenedAwareness = 823, - aaDestructiveForce = 828, //DB - aaSwarmofDecay = 831, //DB - aaDeathsFury = 834, - aaQuickeningofDeath = 839, - aaAdvancedTheftofLife = 844, - aaTripleBackstab = 846, - aaHastenedPiety = 849, - aaImmobilizingBash = 852, - aaViciousSmash = 855, - aaRadiantCure2 = 860, //whats the difference? - aaPurification = 863, - aaPrecisionofthePathfinder = 864, - aaCoatofThistles = 867, - aaFlamingArrows = 872, //untested - aaFrostArrows = 875, //untested - aaSeizedOpportunity = 878, - aaTrapCircumvention = 881, - aaImprovedHastyExit = 886, - aaVirulentVenom = 888, - aaImprovedConsumptionofSoul = 893, - aaIntenseHatred = 895, - aaAdvancedSpiritCall = 900, - aaCalloftheAncients = 902, //DB - aaSturdiness = 907, - aaWarlordsTenacity = 912, //DB - aaStrengthenedStrike = 915, - aaExtendedShielding = 918, - aaRosFlamingFamiliar = 921, //DB - aaEcisIcyFamiliar = 922, //DB - aaDruzzilsMysticalFamiliar = 923, //DB - aaAdvancedFuryofMagicMastery = 924, //added 9/29/08 - aaWardofDestruction = 926, //DB - aaFrenziedDevastation = 931, //DB - aaCombatFury2 = 934, //whats the difference? - aaCombatFury3 = 937, //whats the difference? - aaCombatFury4 = 940, //whats the difference? - aaFuryoftheAges2 = 943, //whats the difference? - aaFuryoftheAges3 = 946, //whats the difference? - aaFuryoftheAges4 = 949, //whats the difference? - aaPlanarDurability2 = 952, //whats the difference? - aaInnateEnlightenment2 = 955, //whats the difference? - aaDireCharm2 = 960, //whats the difference? - aaDireCharm3 = 961, //whats the difference? - aaTouchoftheDivine2 = 962, //whats the difference? - aaTouchofDecay = 967, - aaCalloftheAncients2 = 970, //whats the difference? - aaImprovedVision = 975, - aaEternalBreath = 978, //handled by client - aaBlacksmithingMastery = 979, //added 9/29/08 - aaBakingMastery = 982, //added 9/29/08 - aaBrewingMastery = 985, //added 9/29/08 - aaFletchingMastery2 = 988, //added 9/29/08 - aaPotteryMastery = 991, //added 9/29/08 - aaTailoringMastery = 994, //added 9/29/08 - aaSalvage = 997, - aaOrigin = 1000, //spell - aaChaoticPotential = 1001, //added - aaDiscordantDefiance = 1006, //added 9/29/08 - aaTrialsofMataMuram = 1011, - aaMysticalAttuning = 1021, - aaDelayDeath = 1026, - aaHealthyAura = 1031, - aaFitness = 1036, - aaVeteransWrath = 1041, //added 9/29/08 - aaVeteransWrath2 = 1044, //whats the difference? - aaVeteransWrath3 = 1047, //whats the difference? - aaVeteransWrath4 = 1050, //whats the difference? - aaDeathblow = 1053, - aaReflexiveMastery = 1061, - aaDefensiveInstincts = 1066, - aaMnemonicRetention = 1071, //Implemented - aaExpansiveMind = 1072, //added 9/29/08 - aaSleightofHand = 1077, - aaSleightofHand2 = 1080, //whats the difference? - aaHealingAdeptMastery = 1083, - aaHealingGiftMastery = 1086, - aaArcaneTongues = 1089, - aaMasterofDisguise = 1092, - aaSlipperyAttacks = 1093, - aaImprovedCriticalAffliction = 1099, - aaFortifiedBellowing = 1102, - aaFuryofMagic2 = 1107, //whats the difference? - aaDanceofBlades = 1110, - aaShieldofNotes = 1116, - aaRoarofThunder = 1119, - aaPersistentMinion = 1122, - aaPerfectionofSpirit = 1123, - aaReplentishCompanion = 1126, - aaAdvancedPetDiscipline = 1129, - aaThrowingMastery = 1131, - aaBlurofAxes = 1134, - aaHastenedWarCry = 1137, - aaDeadAim = 1140, - aaFrenziedDefense = 1143, - aaTirelessSprint = 1146, - aaDesperation = 1149, - aaUntamedRage = 1150, - aaEchoingCries = 1155, - aaViciousFrenzy = 1158, - aaCrazedOnslaught = 1163, - aaOverwhelmingAttack = 1172, - aaFuriousRage = 1175, - aaBloodPact = 1178, - aaShieldingResistance = 1181, - aaHealingBoon = 1186, - aaResplendentCure = 1189, - aaCelestialHammer = 1192, - aaDivineRetribution = 1195, - aaCelestialRejuvination = 1203, - aaFerventBenediction = 1206, - aaSanctuary = 1209, - aaDestructiveFury = 1210, //added 9/29/08 - aaDestructiveFury2 = 1213, //whats the difference? - aaBoonoftheForest = 1222, - aaSpiritoftheGrove = 1225, - aaCalloftheWild = 1228, - aaSecondaryRecall = 1229, - aaNaturesBounty = 1230, - aaStasis = 1233, - aaColorShock = 1239, - aaMindOverMatter = 1242, - aaSoothingWords = 1245, - aaElementalSwarm = 1248, - aaHeartofFlames = 1251, - aaHeartofVapor = 1252, - aaHeartofIce = 1253, - aaHeartofStone = 1254, - aaImitateDeath = 1255, - aaCripplingStrike = 1256, - aaStunningKick = 1259, - aaEyeGouge = 1262, - aaIronKicks = 1265, - aaStyleoftheMimic = 1268, - aaDeathPeace2 = 1272, //whats the difference? - aaArmyoftheDead = 1274, - aaCelestialStun = 1277, - aaHandofDevotion = 1278, - aaSteadfastWill = 1284, - aaShieldBlock = 1287, - aaScoutsEfficiency = 1290, - aaGuardianoftheGlade = 1293, - aaTrackingMastery = 1296, - aaFlurryofKnives = 1301, - aaPrecision = 1304, - aaNervesofSteel = 1307, - aaTouchoftheCursed = 1313, - aaSpiritualCorrosion = 1316, - aaSoulThief = 1319, - aaSpiritualChanneling = 1323, - aaBoonoftheAncients = 1324, - aaAncestralAid = 1327, - aaResoluteDefiance = 1330, - aaPresstheAttack = 1333, - aaMindCrash = 1334, - aaProlongedDestruction = 1337, - aaRosGreaterFamiliar = 1340, - aaEcisGreaterFamiliar = 1341, - aaDruzzilsGreaterFamiliar = 1342, - aaTeleportBind = 1343, - aaDevotedFamiliar = 1344, - aaAuspiceoftheHunter = 1345, - aaSavageSpirit = 1348, - aaPresstheAttack2 = 1351, //whats the difference? - aaCripplingStrike2 = 1352, //whats the difference? - aaStunningKick2 = 1353, //whats the difference? - aaEyeGouge2 = 1358, //whats the difference? - - //Dragons of Norrath - //good info here: http://www.eqthieves.com/exp-don-progression.htm and here: http://everquest.allakhazam.com/db/guides.html?guide=811 - aaGiftoftheDarkReign = 1361, //from dbstr_us.txt - aaTenacityoftheDarkReign = 1362, //from dbstr_us.txt - aaEmbraceoftheDarkReign = 1363, //from dbstr_us.txt - aaPoweroftheDarkReign = 1364, //from dbstr_us.txt - aaFervoroftheDarkReign = 1365, //from dbstr_us.txt - aaGiftoftheKeepers = 1366, //from dbstr_us.txt - aaValoroftheKeepers = 1367, //from dbstr_us.txt - aaEmbraceoftheKeepers = 1368, //from dbstr_us.txt - aaPoweroftheKeepers = 1369, //from dbstr_us.txt - aaSanctityoftheKeepers = 1370, //from dbstr_us.txt - - //Veteran AAs - aaLessonoftheDevoted = 1371, //from dbstr_us.txt - aaInfusionoftheFaithful = 1372, //from dbstr_us.txt - aaChaoticJester = 1373, //from dbstr_us.txt - aaExpedientRecovery = 1374, //from dbstr_us.txt - aaSteadfastServant = 1375, //from dbstr_us.txt - aaStaunchRecovery = 1376, //from dbstr_us.txt - aaIntensityoftheResolute = 1377, //from dbstr_us.txt - - //Depths of Darkhollow - - //the following 5 look to be used as flags for completion of the Blood Raids for access to the Demiplane of Blood - //quest info here: http://everquest.allakhazam.com/db/quest.html?quest=3582 - //"You must also complete the five Blood Raids in any order: The Council of Nine, Emperor Draygun, Bloodeye, Matriarch Shyra, Sendaii, the Hive Queen" - //"The AA's you receive are: Curse of Blood (1/5), Affliction of Blood (2/5), Torment of Blood (3/5), Temptation of Blood (4/5), Invitation of Blood (5/5)." - aaCurseofBlood = 1378, //from dbstr_us.txt - aaAfflictionofBlood = 1379, //from dbstr_us.txt - aaTormentofBlood = 1380, //from dbstr_us.txt - aaTemptationofBlood = 1381, //from dbstr_us.txt - aaInvitationofBlood = 1382, //from dbstr_us.txt - - aaTurnUndead2 = 1383, //from dbstr_us.txt, Class AA changed in DoD - aaWrackUndead = 1386, //from dbstr_us.txt, PoP Class AA changed in DoD - aaEradicateUndead = 1387, //from dbstr_us.txt - aaInnateSeeInvis = 1388, //from dbstr_us.txt - aaProlongedMortality = 1389, //from dbstr_us.txt - aaPrecognition = 1394, //from dbstr_us.txt - aaThickSkin = 1399, //from dbstr_us.txt - aaSilentCasting = 1404, //from dbstr_us.txt - aaSilentCasting2 = 1409, //from dbstr_us.txt - aaHastenedMindCrash = 1414, //from dbstr_us.txt - aaFieldDressing = 1417, //from dbstr_us.txt - aaBandageWounds = 1420, //from dbstr_us.txt - aaCascadingRage = 1425, //from dbstr_us.txt - aaElementalFerocity = 1430, //from dbstr_us.txt - aaGiftofMana = 1435, //from dbstr_us.txt - aaRuneofShadows = 1440, //from dbstr_us.txt - aaChannelingMastery = 1445, //from dbstr_us.txt - aaConservation = 1453, //from dbstr_us.txt - aaCryofBattle = 1458, //from dbstr_us.txt - aaWardofPurity = 1459, //from dbstr_us.txt - aaTurnSummoned2 = 1462, //from dbstr_us.txt - aaWrackSummoned = 1465, //from dbstr_us.txt - aaEradicateSummoned = 1466, //from dbstr_us.txt - aaWardersSavagery = 1467, //from dbstr_us.txt - aaShackleofSpirits = 1470, //from dbstr_us.txt - aaHastenedThunder = 1471, //from dbstr_us.txt - aaTranslocationalAnchor = 1474, //from dbstr_us.txt - aaStealthyGetaway = 1477, //from dbstr_us.txt - aaPyromancy = 1478, //from dbstr_us.txt - aaMasteryofFury = 1483, //from dbstr_us.txt - aaAbundantHealing = 1486, //from dbstr_us.txt - aaGreaterAvatar = 1491, //from dbstr_us.txt - aaSharedCamouflage = 1494, //from dbstr_us.txt - aaConvergenceofSpirits = 1495, //from dbstr_us.txt - aaNaturesGuardian = 1498, //from dbstr_us.txt - aaEdictofCommand = 1501, //from dbstr_us.txt - aaExtendedBurnout = 1504, //from dbstr_us.txt - aaGuardianofRo = 1507, //from dbstr_us.txt - aaBloodMagic = 1510, //from dbstr_us.txt - aaGraverobbing = 1511, //from dbstr_us.txt - aaAfflictionMastery = 1514, //from dbstr_us.txt - aaGreaterRabidBear = 1517, //from dbstr_us.txt - aaAncestralGuard = 1520, //from dbstr_us.txt - aaCloakofLight = 1523, //from dbstr_us.txt - aaVanquishUndead = 1524, //from dbstr_us.txt - aaCloakofShadows = 1527, //from dbstr_us.txt - aaWillfulDeath = 1528, //from dbstr_us.txt - aaSwiftBlade = 1533, //from dbstr_us.txt - aaWickedBlade = 1536, //from dbstr_us.txt - aaForcedOpening = 1539, //from dbstr_us.txt - aaAppraisal = 1542, //from dbstr_us.txt - aaPreciseStrikes = 1543, //from dbstr_us.txt - aaHastenedDeath = 1546, //from dbstr_us.txt - aaUnflinchingResolve = 1549, //from dbstr_us.txt - aaWeightlessSteps = 1552, //from dbstr_us.txt - aaHastenedBlades = 1555, //from dbstr_us.txt - aaImprovedHarmoniousAttack = 1563, //from dbstr_us.txt - aaImprovedBestialFrenzy = 1566, //from dbstr_us.txt - aaSongofStone = 1569, //from dbstr_us.txt - aaDeepSleep = 1572, //from dbstr_us.txt - aaCompanionsGift = 1577, //from dbstr_us.txt - aaHastenedDefiance = 1583, //from dbstr_us.txt - aaDauntlessPerseverance = 1586, //from dbstr_us.txt - aaConcentration = 1587, //from dbstr_us.txt - aaEnhancedAggression = 1592, //from dbstr_us.txt - aaCallofChallenge = 1597, //from dbstr_us.txt - aaCacophony = 1598, //from dbstr_us.txt - aaImprovedHeadshot = 1601, //from dbstr_us.txt - aaAnatomy = 1604, //from dbstr_us.txt - aaFetterofSpirits = 1607, //from dbstr_us.txt - aaTrickShot = 1608, //from dbstr_us.txt - aaLightningStrikes = 1616, //from dbstr_us.txt - aaRelentlessAssault = 1621, //from dbstr_us.txt - aaKnightsExpertise = 1624, //from dbstr_us.txt - aaSelosEnduringCadence = 1627, //from dbstr_us.txt - aaHarmTouch = 7800, //from dbstr_us.txt - aaLayonHands = 7850, //from dbstr_us.txt - aaLayonHandsRank16 = 7866, - - aaHighestID //this should always be last, and should always - //follow the highest AA ID -} aaID; -*/ - - typedef enum { //AA IDs aaNone =0, aaInnateStrength =2,//implemented as bonus @@ -2109,21 +1525,6 @@ typedef enum { //AA IDs //follow the highest AA ID } aaID; - -//Structure representing the database's AA actions -struct AA_DBAction { - uint32 reuse_time; //in seconds - uint16 spell_id; //spell to cast, SPELL_UNKNOWN=no spell - aaTargetType target; //from aaTargetType - aaNonspellAction action; //non-spell action to take - uint16 mana_cost; //mana the NON-SPELL action costs - uint16 duration; //duration of NON-SPELL effect, 0=N/A - aaID redux_aa; //AA which reduces reuse time - int32 redux_rate; //%/point in redux_aa reduction in reuse time - aaID redux_aa2; //AA which reduces reuse time - int32 redux_rate2; //%/point in redux_aa reduction in reuse time -}; - //Structure representing the database's swarm pet configs struct AA_SwarmPet { uint8 count; //number to summon @@ -2131,12 +1532,6 @@ struct AA_SwarmPet { uint16 duration; //how long they last, in seconds }; -struct AALevelCost_Struct -{ - uint32 Level; - uint32 Cost; -}; - enum { //values of AA_Action.action aaActionActivate = 0, aaActionSetEXP = 1, diff --git a/zone/aa_ability.h b/zone/aa_ability.h index bd2b9e306..ba152fb06 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -49,6 +49,8 @@ public: int classes; int races; int deities; + int drakkin_heritage; + int status; bool grant_only; int type; int charges; diff --git a/zone/client.h b/zone/client.h index dd283596d..faa4eeb3a 100644 --- a/zone/client.h +++ b/zone/client.h @@ -784,9 +784,6 @@ public: void SetTitleSuffix(const char *txt); inline uint32 GetMaxAAXP(void) const { return max_AAXP; } inline uint32 GetAAXP() const { return m_pp.expAA; } - void SendAATable(); - int CalcAAReuseTimer(const AA_DBAction *caa); - void ActivateAA(aaID activate); void EnableAAEffect(aaEffectType type, uint32 duration = 0); void DisableAAEffect(aaEffectType type); bool CheckAAEffect(aaEffectType type); diff --git a/zone/command.cpp b/zone/command.cpp index 298022dc9..0554a5e68 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -167,7 +167,6 @@ int command_init(void) { command_add("aggro", "(range) [-v] - Display aggro information for all mobs 'range' distance from your target. -v is verbose faction info.", 80, command_aggro) || command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", 100, command_aggrozone) || command_add("ai", "[factionid/spellslist/con/guard/roambox/stop/start] - Modify AI on NPC target", 100, command_ai) || - command_add("altactivate", "[argument] - activates alternate advancement abilities, use altactivate help for more information", 0, command_altactivate) || command_add("appearance", "[type] [value] - Send an appearance packet for you or your target", 150, command_appearance) || command_add("attack", "[targetname] - Make your NPC target attack targetname", 150, command_attack) || command_add("augmentitem", "Force augments an item. Must have the augment item window open.", 250, command_augmentitem) || @@ -273,7 +272,6 @@ int command_init(void) { command_add("los", nullptr,0, command_checklos) || command_add("makepet", "[level] [class] [race] [texture] - Make a pet", 50, command_makepet) || command_add("mana", "- Fill your or your target's mana", 50, command_mana) || - command_add("manaburn", "- Use AA Wizard class skill manaburn on target", 10, command_manaburn) || command_add("maxskills", "Maxes skills for you.", 200, command_max_all_skills) || command_add("memspell", "[slotid] [spellid] - Memorize spellid in the specified slot", 50, command_memspell) || command_add("merchant_close_shop", "Closes a merchant shop", 100, command_merchantcloseshop) || @@ -4848,36 +4846,6 @@ void command_zonestatus(Client *c, const Seperator *sep) } } -void command_manaburn(Client *c, const Seperator *sep) -{ - Mob* target=c->GetTarget(); - - if (c->GetTarget() == 0) - c->Message(0, "#Manaburn needs a target."); - else { - int cur_level=c->GetAA(MANA_BURN);//ManaBurn ID - if (DistanceSquared(c->GetPosition(), target->GetPosition()) > 200) - c->Message(0,"You are too far away from your target."); - else { - if(cur_level == 1) { - if(c->IsAttackAllowed(target)) - { - c->SetMana(0); - int nukedmg=(c->GetMana())*2; - if (nukedmg>0) - { - target->Damage(c, nukedmg, 2751, SkillAbjuration/*hackish*/); - c->Message(4,"You unleash an enormous blast of magical energies."); - } - Log.Out(Logs::General, Logs::Normal, "Manaburn request from %s, damage: %d", c->GetName(), nukedmg); - } - } - else - c->Message(0, "You have not learned this skill."); - } - } -} - void command_doanim(Client *c, const Seperator *sep) { if (!sep->IsNumber(1)) @@ -7684,57 +7652,6 @@ void command_reloadtitles(Client *c, const Seperator *sep) } -//old aa, probably to be removed -void command_altactivate(Client *c, const Seperator *sep){ -// if(sep->arg[1][0] == '\0'){ -// c->Message(10, "Invalid argument, usage:"); -// c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); -// c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); -// c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); -// return; -// } -// if(!strcasecmp(sep->arg[1], "help")){ -// c->Message(10, "Usage:"); -// c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); -// c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); -// c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); -// return; -// } -// if(!strcasecmp(sep->arg[1], "list")){ -// c->Message(10, "You have access to the following AA Abilities:"); -// int x, val; -// SendAA_Struct* saa = nullptr; -// for(x = 0; x < aaHighestID; x++){ -// if(AA_Actions[x][0].spell_id || AA_Actions[x][0].action){ //if there's an action or spell associated we assume it's a valid -// val = 0; //and assume if they don't have a value for the first rank then it isn't valid for any rank -// saa = nullptr; -// val = c->GetAA(x); -// if(val){ -// saa = zone->FindAA(x); -// c->Message(10, "%d: %s %d", x, saa->name, val); -// } -// } -// } -// } -// else if(!strcasecmp(sep->arg[1], "time")){ -// int ability = atoi(sep->arg[2]); -// if(c->GetAA(ability)){ -// int remain = c->GetPTimers().GetRemainingTime(pTimerAAStart + ability); -// if(remain) -// c->Message(10, "You may use that ability in %d minutes and %d seconds.", (remain/60), (remain%60)); -// else -// c->Message(10, "You may use that ability now."); -// } -// else{ -// c->Message(10, "You do not have access to that ability."); -// } -// } -// else -// { -// c->ActivateAA((aaID) atoi(sep->arg[1])); -// } -} - void command_traindisc(Client *c, const Seperator *sep) { uint8 max_level, min_level; diff --git a/zone/command.h b/zone/command.h index 0560b8eff..f44362ea7 100644 --- a/zone/command.h +++ b/zone/command.h @@ -216,7 +216,6 @@ void command_time(Client *c, const Seperator *sep); void command_guild(Client *c, const Seperator *sep); bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value); void command_zonestatus(Client *c, const Seperator *sep); -void command_manaburn(Client *c, const Seperator *sep); void command_doanim(Client *c, const Seperator *sep); void command_randomfeatures(Client *c, const Seperator *sep); void command_face(Client *c, const Seperator *sep); @@ -276,7 +275,6 @@ void command_guildlist(Client *c, const Seperator *sep); void command_rules(Client *c, const Seperator *sep); void command_task(Client *c, const Seperator *sep); void command_reloadtitles(Client *c, const Seperator *sep); -void command_altactivate(Client *c, const Seperator *sep); void command_refundaa(Client *c, const Seperator *sep); void command_traindisc(Client *c, const Seperator *sep); void command_deletegraveyard(Client *c, const Seperator *sep); From b1829e929e641d5f9f0a96a353f368b521d4f2c1 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 12 Jun 2015 19:25:43 -0400 Subject: [PATCH 177/846] Updated SessionStats methodology --- changelog.txt | 3 +++ common/eq_stream.cpp | 42 ++++++++++++++++++++++++++---------------- common/eq_stream.h | 20 +++++++++++++++++++- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/changelog.txt b/changelog.txt index d97f20459..6c42a23ca 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 06/12/2015 == +Uleat: Adjusted SessionStats to better reflect a sister implementation + == 06/07/2015 == Uleat: Implemented optional rule for using disenchanted bags. Action triggers at the same point that temporary items are removed. Optional SQL: utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index c48cba0fd..3438f533c 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -72,6 +72,8 @@ void EQStream::init(bool resetSession) { RateThreshold=RATEBASE/250; DecayRate=DECAYBASE/250; BytesWritten=0; + sent_packet_count = 0; + received_packet_count = 0; SequencedBase = 0; NextSequencedSend = 0; @@ -464,37 +466,45 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) } break; case OP_SessionStatRequest: { - if(p->Size() < sizeof(SessionStats)) + if(p->Size() < sizeof(ClientSessionStats)) { Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatRequest that was of malformed size" __L); break; } #ifndef COLLECTOR - SessionStats *Stats=(SessionStats *)p->pBuffer; + 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(Stats->packets_received), (unsigned long)ntohl(Stats->packets_sent), (unsigned long)ntohl(Stats->last_local_delta), - (unsigned long)ntohl(Stats->low_delta), (unsigned long)ntohl(Stats->average_delta), - (unsigned long)ntohl(Stats->high_delta), (unsigned long)ntohl(Stats->last_remote_delta)); - uint64 x=Stats->packets_received; - Stats->packets_received=Stats->packets_sent; - Stats->packets_sent=x; - NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse,p->pBuffer,p->size)); - AdjustRates(ntohl(Stats->average_delta)); + (unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta), + (unsigned long)ntohl(ClientStats->low_delta), (unsigned long)ntohl(ClientStats->average_delta), + (unsigned long)ntohl(ClientStats->high_delta), (unsigned long)ntohl(ClientStats->last_remote_delta)); + + AdjustRates(ntohl(ClientStats->average_delta)); if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - if(RETRANSMIT_TIMEOUT_MULT && ntohl(Stats->average_delta)) { + if (RETRANSMIT_TIMEOUT_MULT && ntohl(ClientStats->average_delta)) { //recalculate retransmittimeout using the larger of the last rtt or average rtt, which is multiplied by the rule value - if((ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta)) > (ntohl(Stats->average_delta) * 2)) { - retransmittimeout = (ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta)) + if ((ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta)) > (ntohl(ClientStats->average_delta) * 2)) { + retransmittimeout = (ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta)) * RETRANSMIT_TIMEOUT_MULT; } else { - retransmittimeout = ntohl(Stats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT; + retransmittimeout = ntohl(ClientStats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT; } if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX) retransmittimeout = RETRANSMIT_TIMEOUT_MAX; Log.Out(Logs::Detail, Logs::Netcode, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout); } } + + ServerSessionStats *ServerStats = (ServerSessionStats *)p->pBuffer; + + //ServerStats->RequestID = ClientStats->RequestID; // no change + ServerStats->ServerTime = htonl(Timer::GetCurrentTime()); + ServerStats->packets_sent_echo = ClientStats->packets_sent; // still in htonll format + ServerStats->packets_received_echo = ClientStats->packets_received; // still in htonll format + ServerStats->packets_sent = htonll(GetPacketsSent()); + ServerStats->packets_received = htonll(GetPacketsReceived()); + + NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse, p->pBuffer, p->size)); #endif } break; @@ -1103,8 +1113,8 @@ EQProtocolPacket *p=nullptr; void EQStream::Process(const unsigned char *buffer, const uint32 length) { -static unsigned char newbuffer[2048]; -uint32 newlength=0; + static unsigned char newbuffer[2048]; + uint32 newlength=0; if (EQProtocolPacket::ValidateCRC(buffer,length,Key)) { if (compressed) { newlength=EQProtocolPacket::Decompress(buffer,length,newbuffer,2048); diff --git a/common/eq_stream.h b/common/eq_stream.h index 72eb53cdd..0bdfeab53 100644 --- a/common/eq_stream.h +++ b/common/eq_stream.h @@ -71,7 +71,7 @@ struct SessionResponse { }; //Deltas are in ms, representing round trip times -struct SessionStats { +struct ClientSessionStats { /*000*/ uint16 RequestID; /*002*/ uint32 last_local_delta; /*006*/ uint32 average_delta; @@ -83,6 +83,16 @@ struct SessionStats { /*038*/ }; +struct ServerSessionStats { +/*000*/ uint16 RequestID; +/*002*/ uint32 ServerTime; +/*006*/ uint64 packets_sent_echo; +/*014*/ uint64 packets_received_echo; +/*022*/ uint64 packets_sent; +/*030*/ uint64 packets_received; +/*038*/ +}; + #pragma pack() class OpcodeManager; @@ -158,6 +168,9 @@ class EQStream : public EQStreamInterface { int32 BytesWritten; + uint64 sent_packet_count; + uint64 received_packet_count; + Mutex MRate; int32 RateThreshold; int32 DecayRate; @@ -265,11 +278,13 @@ class EQStream : public EQStreamInterface { void AddBytesSent(uint32 bytes) { bytes_sent += bytes; + ++sent_packet_count; } void AddBytesRecv(uint32 bytes) { bytes_recv += bytes; + ++received_packet_count; } virtual const uint32 GetBytesSent() const { return bytes_sent; } @@ -288,6 +303,9 @@ class EQStream : public EQStreamInterface { return bytes_recv / (Timer::GetTimeSeconds() - create_time); } + const uint64 GetPacketsSent() { return sent_packet_count; } + const uint64 GetPacketsReceived() { return received_packet_count; } + //used for dynamic stream identification class Signature { public: From ed11ee8bea0b5a60082cead55a6bf5ec3d44498d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 12 Jun 2015 22:41:18 -0400 Subject: [PATCH 178/846] AA effects and focus should work Still need to verify all effects and implement currently unhandled --- common/spdat.h | 14 +- zone/attack.cpp | 7 + zone/bonuses.cpp | 1588 +++++++++++++++++++------------------- zone/bot.cpp | 6 +- zone/client.h | 4 +- zone/client_mods.cpp | 2 +- zone/common.h | 2 +- zone/mob.cpp | 8 +- zone/special_attacks.cpp | 32 +- zone/spell_effects.cpp | 1145 +++++++++++++-------------- 10 files changed, 1391 insertions(+), 1417 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index bb71c1e88..ab128a37c 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -401,7 +401,7 @@ typedef enum { //#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest #define SE_SetBreathLevel 246 // *not implemented as bonus #define SE_RaiseSkillCap 247 // *not implemented[AA] - adds skill over the skill cap. -//#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100) +#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100) #define SE_SecondaryDmgInc 249 // implemented[AA] Allows off hand weapon to recieve a damage bonus (Sinister Strikes) #define SE_SpellProcChance 250 // implemented - Increase chance to proc from melee proc spells (ie Spirit of Panther) #define SE_ConsumeProjectile 251 // implemented[AA] - chance to not consume an arrow (ConsumeProjectile = 100) @@ -416,12 +416,12 @@ typedef enum { #define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType #define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live) #define SE_RaiseStatCap 262 // implemented -//#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master. +#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master. #define SE_HastenedAASkill 264 // implemented #define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled #define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon. #define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast -//#define SE_ReduceTradeskillFail 268 // *not implemented? - reduces chance to fail with given tradeskill by a percent chance +#define SE_ReduceTradeskillFail 268 // *not implemented? - reduces chance to fail with given tradeskill by a percent chance #define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound. #define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo) #define SE_BaseMovementSpeed 271 // implemented[AA] - mods basemove speed, doesn't stack with other move mods @@ -441,7 +441,7 @@ typedef enum { //#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max #define SE_FcDamageAmt 286 // implemented - adds direct spell damage #define SE_SpellDurationIncByTic 287 // implemented -#define SE_SpecialAttackKBProc 288 // implemented[AA] - Chance to to do a knockback from special attacks [AA Dragon Punch]. +#define SE_SkillAttackProc 288 // implemented[AA] - Chance to proc spell on skill attack usage (ex. Dragon Punch) #define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration. #define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap #define SE_Purify 291 // implemented - Removes determental effects @@ -515,8 +515,8 @@ typedef enum { //#define SE_PassiveSenseTrap 359 // *not implemented - Invulnerability (Brell's Blessing) #define SE_ProcOnKillShot 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level #define SE_SpellOnDeath 361 // implemented - casts spell on death of buffed -//#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank. -//#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank. +#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank. +#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 @@ -525,7 +525,7 @@ typedef enum { #define SE_CorruptionCounter 369 // implemented #define SE_ResistCorruption 370 // implemented #define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee' -//#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not. +#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not. #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 diff --git a/zone/attack.cpp b/zone/attack.cpp index 74cb33272..cecf37ff1 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1372,6 +1372,13 @@ 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 && + IsValidSpell(aabonuses.SkillAttackProc[2])) { + float chance = aabonuses.SkillAttackProc[0] / 1000.0f; + if (zone->random.Roll(chance)) + SpellFinished(aabonuses.SkillAttackProc[2], other, 10, 0, -1, + spells[aabonuses.SkillAttackProc[2]].ResistDiff); + } other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); if (IsDead()) return false; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 437befe11..23a896979 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -632,812 +632,814 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { } } -void Client::CalcAABonuses(StatBonuses* newbon) { - memset(newbon, 0, sizeof(StatBonuses)); //start fresh +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; - //aa old - //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 - // } - // } - // } - //} + for (const auto &aa : aa_ranks) { + auto ability = zone->GetAlternateAdvancementAbility(aa.first); + // zone doesn't know about this! bad data some where + if (!ability) + continue; + + auto rank = ability->GetRankByPointsSpent(aa.second.first); + // bad data or no effects + if (!rank || rank->effects.empty()) + continue; + + ApplyAABonuses(*rank, newbon); + } } - //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) +void Client::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) { - if(slots == 0) //sanity check. why bother if no slots to fill? + if (rank.effects.empty()) // 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 + int32 base2 = 0; // only really used for SE_RaiseStatCap & SE_ReduceSkillTimer in aa_effects table uint32 slot = 0; - //AA old - //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.Out(Logs::Detail, Logs::AA, "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] = static_cast(effect); - // continue; - // } - // - // switch (effect) - // { - // //Note: AA effects that use accuracy are skill limited, while spell effect is not. - // case SE_Accuracy: - // if ((base2 == ALL_SKILLS) && (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->AvoidMeleeChanceEffect += 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_HitChance: - // { - // if(base2 == ALL_SKILLS) - // newbon->HitChanceEffect[HIGHEST_SKILL+1] += base1; - // else - // newbon->HitChanceEffect[base2] += base1; - // } - // - // 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 == ALL_SKILLS) - // 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 == ALL_SKILLS) - // 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 == ALL_SKILLS) - // 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 == ALL_SKILLS) - // newbon->DamageModifier[HIGHEST_SKILL+1] += base1; - // else - // newbon->DamageModifier[base2] += base1; - // break; - // } - // - // case SE_DamageModifier2: - // { - // if(base2 == ALL_SKILLS) - // 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; - // - // case SE_MeleeVulnerability: - // newbon->MeleeVulnerability += base1; - // break; - // - // case SE_FactionModPct: - // { - // if((base1 < 0) && (newbon->FactionModPct > base1)) - // newbon->FactionModPct = base1; - // - // else if(newbon->FactionModPct < base1) - // newbon->FactionModPct = base1; - // break; - // } - // - // case SE_IllusionPersistence: - // newbon->IllusionPersistence = true; - // break; - // - // case SE_LimitToSkill:{ - // if (base1 <= HIGHEST_SKILL) - // newbon->LimitToSkill[base1] = true; - // break; - // } - // - // case SE_SkillProc:{ - // for(int e = 0; e < MAX_SKILL_PROCS; e++) - // { - // if(newbon->SkillProc[e] && newbon->SkillProc[e] == aaid) - // break; //Do not use the same aa id more than once. - // - // else if(!newbon->SkillProc[e]){ - // newbon->SkillProc[e] = aaid; - // break; - // } - // } - // break; - // } - // - // case SE_SkillProcSuccess:{ - // - // for(int e = 0; e < MAX_SKILL_PROCS; e++) - // { - // if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid) - // break; //Do not use the same spell id more than once. - // - // else if(!newbon->SkillProcSuccess[e]){ - // newbon->SkillProcSuccess[e] = aaid; - // break; - // } - // } - // break; - // } - // - // case SE_MeleeMitigation: - // newbon->MeleeMitigationEffect -= base1; - // break; - // - // } - //} + for (const auto &e : rank.effects) { + effect = e.effect_id; + base1 = e.base1; + base2 = e.base2; + slot = e.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.Out(Logs::Detail, Logs::AA, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", + effect, rank.id, slot, base1, base2, GetCleanName()); + + uint8 focus = IsFocusEffect(0, 0, true, effect); + if (focus) { + newbon->FocusEffects[focus] = static_cast(effect); + continue; + } + + switch (effect) { + // Note: AA effects that use accuracy are skill limited, while spell effect is not. + case SE_Accuracy: + if ((base2 == ALL_SKILLS) && (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_ManaPool: + newbon->Mana += 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->AvoidMeleeChanceEffect += 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_HitChance: { + if (base2 == ALL_SKILLS) + newbon->HitChanceEffect[HIGHEST_SKILL + 1] += base1; + else + newbon->HitChanceEffect[base2] += base1; + } + + 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] == rank.id) + break; + + if (!newbon->SpellTriggers[i]) { + // Save the 'rank.id' of each triggerable effect to an array + newbon->SpellTriggers[i] = rank.id; + break; + } + } + break; + + case SE_CriticalHitChance: { + if (base2 == ALL_SKILLS) + 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 == ALL_SKILLS) + 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 == ALL_SKILLS) + newbon->SkillDamageAmount[HIGHEST_SKILL + 1] += base1; + else + newbon->SkillDamageAmount[base2] += base1; + break; + } + + case SE_SkillAttackProc: { + // You can only have one of these per client. [AA Dragon Punch] + newbon->SkillAttackProc[0] = base1; // Chance base 1000 = 100% proc rate + newbon->SkillAttackProc[1] = base2; // Skill to Proc Off + newbon->SkillAttackProc[2] = rank.spell; // spell to proc + break; + } + + case SE_DamageModifier: { + if (base2 == ALL_SKILLS) + newbon->DamageModifier[HIGHEST_SKILL + 1] += base1; + else + newbon->DamageModifier[base2] += base1; + break; + } + + case SE_DamageModifier2: { + if (base2 == ALL_SKILLS) + 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; + + case SE_MeleeVulnerability: + newbon->MeleeVulnerability += base1; + break; + + case SE_FactionModPct: { + if ((base1 < 0) && (newbon->FactionModPct > base1)) + newbon->FactionModPct = base1; + + else if (newbon->FactionModPct < base1) + newbon->FactionModPct = base1; + break; + } + + case SE_IllusionPersistence: + newbon->IllusionPersistence = true; + break; + + case SE_LimitToSkill: { + if (base1 <= HIGHEST_SKILL) + newbon->LimitToSkill[base1] = true; + break; + } + + case SE_SkillProc: { + for (int e = 0; e < MAX_SKILL_PROCS; e++) { + if (newbon->SkillProc[e] && newbon->SkillProc[e] == rank.id) + break; // Do not use the same aa id more than once. + + else if (!newbon->SkillProc[e]) { + newbon->SkillProc[e] = rank.id; + break; + } + } + break; + } + + case SE_SkillProcSuccess: { + + for (int e = 0; e < MAX_SKILL_PROCS; e++) { + if (newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == rank.id) + break; // Do not use the same spell id more than once. + + else if (!newbon->SkillProcSuccess[e]) { + newbon->SkillProcSuccess[e] = rank.id; + break; + } + } + break; + } + + case SE_MeleeMitigation: + newbon->MeleeMitigationEffect -= base1; + break; + + case SE_ATK: + newbon->ATK += base1; + break; + // to do + case SE_ReduceTradeskillFail: + break; + case SE_PotionBeltSlots: + break; + case SE_BandolierSlots: + break; + case SE_ForageSkill: + break; + case SE_TradeSkillMastery: + break; + case SE_SecondaryForte: + break; + + // not handled here + case SE_HastenedAASkill: + // not handled here but don't want to clutter debug log -- these may need to be verified to ignore + case SE_LimitMaxLevel: + case SE_LimitResist: + case SE_LimitTarget: + case SE_LimitEffect: + case SE_LimitSpellType: + case SE_LimitMinDur: + case SE_LimitInstant: + case SE_LimitMinLevel: + case SE_LimitCastTimeMin: + case SE_LimitCastTimeMax: + case SE_LimitSpell: + case SE_LimitCombatSkills: + case SE_LimitManaMin: + case SE_LimitSpellGroup: + case SE_LimitSpellClass: + case SE_LimitSpellSubclass: + case SE_LimitHPPercent: + case SE_LimitManaPercent: + case SE_LimitEndPercent: + case SE_LimitClass: + case SE_LimitRace: + case SE_LimitCastingSkill: + case SE_LimitUseMin: + case SE_LimitUseType: + break; + + default: + Log.Out(Logs::Detail, Logs::AA, "SPA %d not accounted for in AA %s (%d)", effect, rank.base_ability->name.c_str(), rank.id); + break; + } + + } } void Mob::CalcSpellBonuses(StatBonuses* newbon) diff --git a/zone/bot.cpp b/zone/bot.cpp index 1d8c16f57..5200f3e95 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -7712,14 +7712,14 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); //[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill - if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){ +/* 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 (HasSkillProcs()) TrySkillProc(who, skill, ReuseTime*1000); @@ -9078,7 +9078,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, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust, uint32 aa_id) { bool Result = false; diff --git a/zone/client.h b/zone/client.h index faa4eeb3a..014747576 100644 --- a/zone/client.h +++ b/zone/client.h @@ -789,7 +789,7 @@ public: bool CheckAAEffect(aaEffectType type); void HandleAAAction(aaID activate); int16 CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id); - int16 CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id); + int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id); void RefundAA(); int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2); int32 GetAAEffectid(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, true, false,false); } @@ -1265,7 +1265,7 @@ protected: int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); void CalcEdibleBonuses(StatBonuses* newbon); void CalcAABonuses(StatBonuses* newbon); - void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon); + void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon); void ProcessItemCaps(); void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true); bool client_data_loaded; diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index f12c20064..56a22de9a 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1121,7 +1121,7 @@ int32 Client::CalcMaxMana() switch (GetCasterClass()) { case 'I': case 'W': { - max_mana = (CalcBaseMana() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement()); + max_mana = (CalcBaseMana() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement()); break; } case 'N': { diff --git a/zone/common.h b/zone/common.h index d9e3637a8..e658a352d 100644 --- a/zone/common.h +++ b/zone/common.h @@ -412,7 +412,7 @@ struct StatBonuses { int8 BaseMovementSpeed; // Adjust base run speed, does not stack with other movement bonuses. uint8 IncreaseRunSpeedCap; // Increase max run speed above cap. int32 DoubleSpecialAttack; // Chance to to perform a double special attack (ie flying kick 2x) - int32 SpecialAttackKBProc[2]; // Chance to to do a knockback from special attacks. (0 = chance 1 = Skill) + int32 SkillAttackProc[3]; // [0] chance to proc [2] spell on [1] skill usage uint8 FrontalStunResist; // Chance to resist a frontal stun int32 BindWound; // Increase amount of HP by percent. int32 MaxBindWound; // Increase max amount of HP you can bind wound. diff --git a/zone/mob.cpp b/zone/mob.cpp index 965007fcf..35b0d62d2 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3510,9 +3510,11 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) uint32 trigger_spell_id = 0; - if (aa_trigger && IsClient()){ - //focus_spell = aaid - trigger_spell_id = CastToClient()->CalcAAFocus(focusTriggerOnCast, focus_spell, spell_id); + if (aa_trigger && IsClient()) { + // focus_spell = aaid + auto rank = zone->GetAlternateAdvancementRank(focus_spell); + 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); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index a3557d021..0021350a4 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -149,22 +149,19 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, } who->AddToHateList(this, hate, 0, false); + if (max_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, 10, 0, -1, + spells[aabonuses.SkillAttackProc[2]].ResistDiff); + } who->Damage(this, max_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; - //[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 (zone->random.Roll(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); @@ -2442,19 +2439,18 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes } other->AddToHateList(this, hate, 0, false); + if (damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skillinuse && + IsValidSpell(aabonuses.SkillAttackProc[2])) { + float chance = aabonuses.SkillAttackProc[0] / 1000.0f; + if (zone->random.Roll(chance)) + SpellFinished(aabonuses.SkillAttackProc[2], other, 10, 0, -1, + spells[aabonuses.SkillAttackProc[2]].ResistDiff); + } other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); if (HasDied()) return; - if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skillinuse){ - int kb_chance = 25; - kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100; - - if (zone->random.Roll(kb_chance)) - SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff); - } - if (CanSkillProc && HasSkillProcs()) TrySkillProc(other, skillinuse, ReuseTime); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 8ac60c125..0bb7b78b9 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4186,7 +4186,7 @@ int32 Client::GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect } -int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) +int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) { const SPDat_Spell_Struct &spell = spells[spell_id]; @@ -4200,8 +4200,9 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) uint32 slot = 0; bool LimitFailure = false; - bool LimitInclude[MaxLimitInclude] = { false }; - /* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice spells. + bool LimitInclude[MaxLimitInclude] = {false}; + /* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice + spells. 0/1 SE_LimitResist 2/3 SE_LimitSpell 4/5 SE_LimitEffect @@ -4214,452 +4215,431 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) */ int FocusCount = 0; - //old AA - //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - //if(find_iter == aa_effects.end()) - //{ - // return 0; - //} - // - //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - //{ - // effect = iter->second.skill_id; - // base1 = iter->second.base1; - // base2 = iter->second.base2; - // slot = iter->second.slot; - // - // /* - // AA Foci's can contain multiple focus effects within the same AA. - // To handle this we will not automatically return zero if a limit is found. - // Instead if limit is found and multiple focus effects, we will reset the limit check - // when the next valid focus effect is found. - // */ - // - // if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ - // FocusCount++; - // //If limit found on prior check next, else end loop. - // if (FocusCount > 1){ - // - // for(int e = 0; e < MaxLimitInclude; e+=2) { - // if (LimitInclude[e] && !LimitInclude[e+1]) - // LimitFailure = true; - // } - // - // if (LimitFailure){ - // value = 0; - // LimitFailure = false; - // - // for(int e = 0; e < MaxLimitInclude; e++) { - // LimitInclude[e] = false; //Reset array - // } - // } - // - // else{ - // break; - // } - // } - // } - // - // - // switch (effect) - // { - // case SE_Blank: - // break; - // - // //Handle Focus Limits - // - // case SE_LimitResist: - // if(base1 < 0){ - // if(spell.resisttype == -base1) //Exclude - // LimitFailure = true; - // } - // else { - // LimitInclude[0] = true; - // if (spell.resisttype == base1) //Include - // LimitInclude[1] = true; - // } - // break; - // - // case SE_LimitInstant: - // if(base1 == 1 && spell.buffduration) //Fail if not instant - // LimitFailure = true; - // if(base1 == 0 && (spell.buffduration == 0)) //Fail if instant - // LimitFailure = true; - // - // break; - // - // case SE_LimitMaxLevel: - // spell_level = spell.classes[(GetClass()%16) - 1]; - // lvldiff = spell_level - base1; - // //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - // if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { - // if(base2 > 0){ - // lvlModifier -= base2*lvldiff; - // if(lvlModifier < 1) - // LimitFailure = true; - // } - // else - // LimitFailure = true; - // } - // break; - // - // case SE_LimitMinLevel: - // if((spell.classes[(GetClass()%16) - 1]) < base1) - // LimitFailure = true; - // break; - // - // case SE_LimitCastTimeMin: - // if (static_cast(spell.cast_time) < base1) - // LimitFailure = true; - // break; - // - // case SE_LimitCastTimeMax: - // if (static_cast(spell.cast_time) > base1) - // LimitFailure = true; - // break; - // - // case SE_LimitSpell: - // if(base1 < 0) { //Exclude - // if (spell_id == -base1) - // LimitFailure = true; - // } - // else { - // LimitInclude[2] = true; - // if (spell_id == base1) //Include - // LimitInclude[3] = true; - // } - // break; - // - // case SE_LimitMinDur: - // if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - // LimitFailure = true; - // - // break; - // - // case SE_LimitEffect: - // if(base1 < 0){ - // if(IsEffectInSpell(spell_id,-base1)) //Exclude - // LimitFailure = true; - // } - // else{ - // LimitInclude[4] = true; - // if(IsEffectInSpell(spell_id,base1)) //Include - // LimitInclude[5] = true; - // } - // break; - // - // case SE_LimitSpellType: - // switch(base1) - // { - // case 0: - // if (!IsDetrimentalSpell(spell_id)) - // LimitFailure = true; - // break; - // case 1: - // if (!IsBeneficialSpell(spell_id)) - // LimitFailure = true; - // break; - // } - // break; - // - // case SE_LimitManaMin: - // if(spell.mana < base1) - // LimitFailure = true; - // break; - // - // case SE_LimitTarget: - // if (base1 < 0) { - // if (-base1 == spell.targettype) //Exclude - // LimitFailure = true; - // } - // else { - // LimitInclude[6] = true; - // if (base1 == spell.targettype) //Include - // LimitInclude[7] = true; - // } - // break; - // - // case SE_LimitCombatSkills: - // if (base1 == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) //Exclude Discs / Procs - // LimitFailure = true; - // else if (base1 == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) //Exclude Spells - // LimitFailure = true; - // - // break; - // - // case SE_LimitSpellGroup: - // if(base1 < 0) { - // if (-base1 == spell.spellgroup) //Exclude - // LimitFailure = true; - // } - // else { - // LimitInclude[8] = true; - // if (base1 == spell.spellgroup) //Include - // LimitInclude[9] = true; - // } - // break; - // - // case SE_LimitCastingSkill: - // if(base1 < 0) { - // if(-base1 == spell.skill) - // LimitFailure = true; - // } - // else { - // LimitInclude[10] = true; - // if(base1 == spell.skill) - // LimitInclude[11] = true; - // } - // break; - // - // case SE_LimitSpellClass: - // if(base1 < 0) { //Exclude - // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) - // return(0); - // } - // else { - // LimitInclude[12] = true; - // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) //Include - // LimitInclude[13] = true; - // } - // break; - // - // case SE_LimitSpellSubclass: - // if(base1 < 0) { //Exclude - // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) - // return(0); - // } - // else { - // LimitInclude[14] = true; - // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) //Include - // LimitInclude[15] = true; - // } - // break; - // - // case SE_LimitClass: - // //Do not use this limit more then once per spell. If multiple class, treat value like items would. - // if (!PassLimitClass(base1, GetClass())) - // LimitFailure = true; - // break; - // - // case SE_LimitRace: - // if (base1 != GetRace()) - // LimitFailure = true; - // break; - // - // case SE_LimitUseMin: - // if (base1 > spell.numhits) - // LimitFailure = true; - // break; - // - // case SE_LimitUseType: - // if (base1 != spell.numhitstype) - // LimitFailure = true; - // break; - // - // //Handle Focus Effects - // case SE_ImprovedDamage: - // if (type == focusImprovedDamage && base1 > value) - // value = base1; - // break; - // - // case SE_ImprovedHeal: - // if (type == focusImprovedHeal && base1 > value) - // value = base1; - // break; - // - // case SE_ReduceManaCost: - // if (type == focusManaCost) - // value = base1; - // break; - // - // case SE_IncreaseSpellHaste: - // if (type == focusSpellHaste && base1 > value) - // value = base1; - // break; - // - // case SE_IncreaseSpellDuration: - // if (type == focusSpellDuration && base1 > value) - // value = base1; - // break; - // - // case SE_SpellDurationIncByTic: - // if (type == focusSpellDurByTic && base1 > value) - // value = base1; - // break; - // - // case SE_SwarmPetDuration: - // if (type == focusSwarmPetDuration && base1 > value) - // value = base1; - // break; - // - // case SE_IncreaseRange: - // if (type == focusRange && base1 > value) - // value = base1; - // break; - // - // case SE_ReduceReagentCost: - // if (type == focusReagentCost && base1 > value) - // value = base1; - // break; - // - // case SE_PetPowerIncrease: - // if (type == focusPetPower && base1 > value) - // value = base1; - // break; - // - // case SE_SpellResistReduction: - // if (type == focusResistRate && base1 > value) - // value = base1; - // break; - // - // case SE_SpellHateMod: - // if (type == focusSpellHateMod ) { - // if(value != 0) { - // if(value > 0){ - // if(base1 > value) - // value = base1; - // } - // else{ - // if(base1 < value) - // value = base1; - // } - // } - // else - // value = base1; - // } - // break; - // - // case SE_ReduceReuseTimer: - // if(type == focusReduceRecastTime) - // value = base1 / 1000; - // break; - // - // case SE_TriggerOnCast: - // if(type == focusTriggerOnCast){ - // if(zone->random.Roll(base1)) { - // value = base2; - // } else { - // value = 0; - // LimitFailure = true; - // } - // break; - // } - // - // case SE_FcSpellVulnerability: - // if(type == focusSpellVulnerability) - // value = base1; - // break; - // - // case SE_BlockNextSpellFocus: - // if(type == focusBlockNextSpell){ - // if(zone->random.Roll(base1)) - // value = 1; - // } - // break; - // - // case SE_FcTwincast: - // if(type == focusTwincast) - // value = base1; - // break; - // - // //Note if using these as AA, make sure this is first focus used. - // case SE_SympatheticProc: - // if(type == focusSympatheticProc) - // value = base2; - // break; - // - // case SE_FcDamageAmt: - // if(type == focusFcDamageAmt) - // value = base1; - // break; - // - // case SE_FcDamageAmtCrit: - // if(type == focusFcDamageAmtCrit) - // value = base1; - // break; - // - // case SE_FcDamageAmtIncoming: - // if(type == focusFcDamageAmtIncoming) - // value = base1; - // break; - // - // case SE_FcHealAmtIncoming: - // if(type == focusFcHealAmtIncoming) - // value = base1; - // break; - // - // case SE_FcHealPctCritIncoming: - // if (type == focusFcHealPctCritIncoming) - // value = base1; - // break; - // - // case SE_FcHealAmtCrit: - // if(type == focusFcHealAmtCrit) - // value = base1; - // break; - // - // case SE_FcHealAmt: - // if(type == focusFcHealAmt) - // value = base1; - // break; - // - // case SE_FcHealPctIncoming: - // if(type == focusFcHealPctIncoming) - // value = base1; - // break; - // - // case SE_FcBaseEffects: - // if (type == focusFcBaseEffects) - // value = base1; - // break; - // - // case SE_FcDamagePctCrit: - // if(type == focusFcDamagePctCrit) - // value = base1; - // break; - // - // case SE_FcIncreaseNumHits: - // if(type == focusIncreaseNumHits) - // value = base1; - // break; - // - // case SE_FcLimitUse: - // if(type == focusFcLimitUse) - // value = base1; - // break; - // - // case SE_FcMute: - // if(type == focusFcMute) - // value = base1; - // break; - // - // case SE_FcStunTimeMod: - // if(type == focusFcStunTimeMod) - // value = base1; - // break; - // - // } - //} + for (const auto &e : rank.effects) { + effect = e.effect_id; + base1 = e.base1; + base2 = e.base2; + slot = e.slot; - for(int e = 0; e < MaxLimitInclude; e+=2) { - if (LimitInclude[e] && !LimitInclude[e+1]) + /* + AA Foci's can contain multiple focus effects within the same AA. + To handle this we will not automatically return zero if a limit is found. + Instead if limit is found and multiple focus effects, we will reset the limit check + when the next valid focus effect is found. + */ + + if (IsFocusEffect(0, 0, true, effect) || (effect == SE_TriggerOnCast)) { + FocusCount++; + // If limit found on prior check next, else end loop. + if (FocusCount > 1) { + + for (int e = 0; e < MaxLimitInclude; e += 2) { + if (LimitInclude[e] && !LimitInclude[e + 1]) + LimitFailure = true; + } + + if (LimitFailure) { + value = 0; + LimitFailure = false; + + for (int e = 0; e < MaxLimitInclude; e++) { + LimitInclude[e] = false; // Reset array + } + } + + else { + break; + } + } + } + + switch (effect) { + case SE_Blank: + break; + + // Handle Focus Limits + + case SE_LimitResist: + if (base1 < 0) { + if (spell.resisttype == -base1) // Exclude + LimitFailure = true; + } else { + LimitInclude[0] = true; + if (spell.resisttype == base1) // Include + LimitInclude[1] = true; + } + break; + + case SE_LimitInstant: + if (base1 == 1 && spell.buffduration) // Fail if not instant + LimitFailure = true; + if (base1 == 0 && (spell.buffduration == 0)) // Fail if instant + LimitFailure = true; + + break; + + case SE_LimitMaxLevel: + spell_level = spell.classes[(GetClass() % 16) - 1]; + lvldiff = spell_level - base1; + // every level over cap reduces the effect by base2 percent unless from a clicky when + // ItemCastsUseFocus is true + if (lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || + RuleB(Character, ItemCastsUseFocus) == false)) { + if (base2 > 0) { + lvlModifier -= base2 * lvldiff; + if (lvlModifier < 1) + LimitFailure = true; + } else + LimitFailure = true; + } + break; + + case SE_LimitMinLevel: + if ((spell.classes[(GetClass() % 16) - 1]) < base1) + LimitFailure = true; + break; + + case SE_LimitCastTimeMin: + if (static_cast(spell.cast_time) < base1) + LimitFailure = true; + break; + + case SE_LimitCastTimeMax: + if (static_cast(spell.cast_time) > base1) + LimitFailure = true; + break; + + case SE_LimitSpell: + if (base1 < 0) { // Exclude + if (spell_id == -base1) + LimitFailure = true; + } else { + LimitInclude[2] = true; + if (spell_id == base1) // Include + LimitInclude[3] = true; + } + break; + + case SE_LimitMinDur: + if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + LimitFailure = true; + + break; + + case SE_LimitEffect: + if (base1 < 0) { + if (IsEffectInSpell(spell_id, -base1)) // Exclude + LimitFailure = true; + } else { + LimitInclude[4] = true; + if (IsEffectInSpell(spell_id, base1)) // Include + LimitInclude[5] = true; + } + break; + + case SE_LimitSpellType: + switch (base1) { + case 0: + if (!IsDetrimentalSpell(spell_id)) + LimitFailure = true; + break; + case 1: + if (!IsBeneficialSpell(spell_id)) + LimitFailure = true; + break; + } + break; + + case SE_LimitManaMin: + if (spell.mana < base1) + LimitFailure = true; + break; + + case SE_LimitTarget: + if (base1 < 0) { + if (-base1 == spell.targettype) // Exclude + LimitFailure = true; + } else { + LimitInclude[6] = true; + if (base1 == spell.targettype) // Include + LimitInclude[7] = true; + } + break; + + case SE_LimitCombatSkills: + if (base1 == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) // Exclude Discs / Procs + LimitFailure = true; + else if (base1 == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) // Exclude Spells + LimitFailure = true; + + break; + + case SE_LimitSpellGroup: + if (base1 < 0) { + if (-base1 == spell.spellgroup) // Exclude + LimitFailure = true; + } else { + LimitInclude[8] = true; + if (base1 == spell.spellgroup) // Include + LimitInclude[9] = true; + } + break; + + case SE_LimitCastingSkill: + if (base1 < 0) { + if (-base1 == spell.skill) + LimitFailure = true; + } else { + LimitInclude[10] = true; + if (base1 == spell.skill) + LimitInclude[11] = true; + } + break; + + case SE_LimitSpellClass: + if (base1 < 0) { // Exclude + if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) + return (0); + } else { + LimitInclude[12] = true; + if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) // Include + LimitInclude[13] = true; + } + break; + + case SE_LimitSpellSubclass: + if (base1 < 0) { // Exclude + if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) + return (0); + } else { + LimitInclude[14] = true; + if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) // Include + LimitInclude[15] = true; + } + break; + + case SE_LimitClass: + // Do not use this limit more then once per spell. If multiple class, treat value like items + // would. + if (!PassLimitClass(base1, GetClass())) + LimitFailure = true; + break; + + case SE_LimitRace: + if (base1 != GetRace()) + LimitFailure = true; + break; + + case SE_LimitUseMin: + if (base1 > spell.numhits) + LimitFailure = true; + break; + + case SE_LimitUseType: + if (base1 != spell.numhitstype) + LimitFailure = true; + break; + + // Handle Focus Effects + case SE_ImprovedDamage: + if (type == focusImprovedDamage && base1 > value) + value = base1; + break; + + case SE_ImprovedHeal: + if (type == focusImprovedHeal && base1 > value) + value = base1; + break; + + case SE_ReduceManaCost: + if (type == focusManaCost) + value = base1; + break; + + case SE_IncreaseSpellHaste: + if (type == focusSpellHaste && base1 > value) + value = base1; + break; + + case SE_IncreaseSpellDuration: + if (type == focusSpellDuration && base1 > value) + value = base1; + break; + + case SE_SpellDurationIncByTic: + if (type == focusSpellDurByTic && base1 > value) + value = base1; + break; + + case SE_SwarmPetDuration: + if (type == focusSwarmPetDuration && base1 > value) + value = base1; + break; + + case SE_IncreaseRange: + if (type == focusRange && base1 > value) + value = base1; + break; + + case SE_ReduceReagentCost: + if (type == focusReagentCost && base1 > value) + value = base1; + break; + + case SE_PetPowerIncrease: + if (type == focusPetPower && base1 > value) + value = base1; + break; + + case SE_SpellResistReduction: + if (type == focusResistRate && base1 > value) + value = base1; + break; + + case SE_SpellHateMod: + if (type == focusSpellHateMod) { + if (value != 0) { + if (value > 0) { + if (base1 > value) + value = base1; + } else { + if (base1 < value) + value = base1; + } + } else + value = base1; + } + break; + + case SE_ReduceReuseTimer: + if (type == focusReduceRecastTime) + value = base1 / 1000; + break; + + case SE_TriggerOnCast: + if (type == focusTriggerOnCast) { + if (zone->random.Roll(base1)) { + value = base2; + } else { + value = 0; + LimitFailure = true; + } + break; + } + + case SE_FcSpellVulnerability: + if (type == focusSpellVulnerability) + value = base1; + break; + + case SE_BlockNextSpellFocus: + if (type == focusBlockNextSpell) { + if (zone->random.Roll(base1)) + value = 1; + } + break; + + case SE_FcTwincast: + if (type == focusTwincast) + value = base1; + break; + + // Note if using these as AA, make sure this is first focus used. + case SE_SympatheticProc: + if (type == focusSympatheticProc) + value = base2; + break; + + case SE_FcDamageAmt: + if (type == focusFcDamageAmt) + value = base1; + break; + + case SE_FcDamageAmtCrit: + if (type == focusFcDamageAmtCrit) + value = base1; + break; + + case SE_FcDamageAmtIncoming: + if (type == focusFcDamageAmtIncoming) + value = base1; + break; + + case SE_FcHealAmtIncoming: + if (type == focusFcHealAmtIncoming) + value = base1; + break; + + case SE_FcHealPctCritIncoming: + if (type == focusFcHealPctCritIncoming) + value = base1; + break; + + case SE_FcHealAmtCrit: + if (type == focusFcHealAmtCrit) + value = base1; + break; + + case SE_FcHealAmt: + if (type == focusFcHealAmt) + value = base1; + break; + + case SE_FcHealPctIncoming: + if (type == focusFcHealPctIncoming) + value = base1; + break; + + case SE_FcBaseEffects: + if (type == focusFcBaseEffects) + value = base1; + break; + + case SE_FcDamagePctCrit: + if (type == focusFcDamagePctCrit) + value = base1; + break; + + case SE_FcIncreaseNumHits: + if (type == focusIncreaseNumHits) + value = base1; + break; + + case SE_FcLimitUse: + if (type == focusFcLimitUse) + value = base1; + break; + + case SE_FcMute: + if (type == focusFcMute) + value = base1; + break; + + case SE_FcStunTimeMod: + if (type == focusFcStunTimeMod) + value = base1; + break; + } + } + + for (int e = 0; e < MaxLimitInclude; e += 2) { + if (LimitInclude[e] && !LimitInclude[e + 1]) return 0; } if (LimitFailure) return 0; - return(value*lvlModifier/100); + return (value * lvlModifier / 100); } //given an item/spell's focus ID and the spell being cast, determine the focus ammount, if any //assumes that spell_id is not a bard spell and that both ids are valid spell ids -int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus) { - - if(!IsValidSpell(focus_id) || !IsValidSpell(spell_id)) +int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus) +{ + if (!IsValidSpell(focus_id) || !IsValidSpell(spell_id)) return 0; - const SPDat_Spell_Struct &focus_spell = spells[focus_id]; const SPDat_Spell_Struct &spell = spells[spell_id]; @@ -4669,8 +4649,9 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo int lvldiff = 0; uint32 Caston_spell_id = 0; - bool LimitInclude[MaxLimitInclude] = { false }; - /* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice spells. + bool LimitInclude[MaxLimitInclude] = {false}; + /* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice + spells. 0/1 SE_LimitResist 2/3 SE_LimitSpell 4/5 SE_LimitEffect @@ -4690,21 +4671,20 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_LimitResist: - if(focus_spell.base[i] < 0){ - if (spell.resisttype == -focus_spell.base[i]) //Exclude + if (focus_spell.base[i] < 0) { + if (spell.resisttype == -focus_spell.base[i]) // Exclude return 0; - } - else { + } else { LimitInclude[0] = true; - if (spell.resisttype == focus_spell.base[i]) //Include + if (spell.resisttype == focus_spell.base[i]) // Include LimitInclude[1] = true; } break; case SE_LimitInstant: - if(focus_spell.base[i] == 1 && spell.buffduration) //Fail if not instant + if (focus_spell.base[i] == 1 && spell.buffduration) // Fail if not instant return 0; - if(focus_spell.base[i] == 0 && (spell.buffduration == 0)) //Fail if instant + if (focus_spell.base[i] == 0 && (spell.buffduration == 0)) // Fail if instant return 0; break; @@ -4712,16 +4692,17 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_LimitMaxLevel: if (IsNPC()) break; - spell_level = spell.classes[(GetClass()%16) - 1]; + spell_level = spell.classes[(GetClass() % 16) - 1]; lvldiff = spell_level - focus_spell.base[i]; - //every level over cap reduces the effect by focus_spell.base2[i] percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)){ - if(focus_spell.base2[i] > 0){ - lvlModifier -= focus_spell.base2[i]*lvldiff; - if(lvlModifier < 1) + // every level over cap reduces the effect by focus_spell.base2[i] percent unless from a clicky + // when ItemCastsUseFocus is true + if (lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || + RuleB(Character, ItemCastsUseFocus) == false)) { + if (focus_spell.base2[i] > 0) { + lvlModifier -= focus_spell.base2[i] * lvldiff; + if (lvlModifier < 1) return 0; - } - else + } else return 0; } break; @@ -4729,116 +4710,115 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_LimitMinLevel: if (IsNPC()) break; - if (spell.classes[(GetClass()%16) - 1] < focus_spell.base[i]) - return(0); + if (spell.classes[(GetClass() % 16) - 1] < focus_spell.base[i]) + return (0); break; case SE_LimitCastTimeMin: if (spells[spell_id].cast_time < (uint16)focus_spell.base[i]) - return(0); + return (0); break; case SE_LimitCastTimeMax: if (spells[spell_id].cast_time > (uint16)focus_spell.base[i]) - return(0); + return (0); break; case SE_LimitSpell: - if(focus_spell.base[i] < 0) { //Exclude + if (focus_spell.base[i] < 0) { // Exclude if (spell_id == -focus_spell.base[i]) - return(0); - } - else { + return (0); + } else { LimitInclude[2] = true; - if (spell_id == focus_spell.base[i]) //Include + if (spell_id == focus_spell.base[i]) // Include LimitInclude[3] = true; } break; case SE_LimitMinDur: - if (focus_spell.base[i] > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - return(0); + if (focus_spell.base[i] > + CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + return (0); break; case SE_LimitEffect: - if(focus_spell.base[i] < 0){ - if(IsEffectInSpell(spell_id,-focus_spell.base[i])) //Exclude + if (focus_spell.base[i] < 0) { + if (IsEffectInSpell(spell_id, -focus_spell.base[i])) // Exclude return 0; - } - else{ + } else { LimitInclude[4] = true; - if(IsEffectInSpell(spell_id,focus_spell.base[i])) //Include + if (IsEffectInSpell(spell_id, focus_spell.base[i])) // Include LimitInclude[5] = true; } break; - case SE_LimitSpellType: - switch( focus_spell.base[i]){ - case 0: - if (!IsDetrimentalSpell(spell_id)) - return 0; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) - return 0; - break; - default: - Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]); + switch (focus_spell.base[i]) { + case 0: + if (!IsDetrimentalSpell(spell_id)) + return 0; + break; + case 1: + if (!IsBeneficialSpell(spell_id)) + return 0; + break; + default: + Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", + focus_spell.base[i]); } break; case SE_LimitManaMin: - if(spell.mana < focus_spell.base[i]) + if (spell.mana < focus_spell.base[i]) return 0; break; case SE_LimitTarget: if (focus_spell.base[i] < 0) { - if (-focus_spell.base[i] == spell.targettype) //Exclude + if (-focus_spell.base[i] == spell.targettype) // Exclude return 0; - } - else { + } else { LimitInclude[6] = true; - if (focus_spell.base[i] == spell.targettype) //Include + if (focus_spell.base[i] == spell.targettype) // Include LimitInclude[7] = true; } break; case SE_LimitCombatSkills: - if (focus_spell.base[i] == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) //Exclude Discs / Procs + if (focus_spell.base[i] == 0 && + (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) // Exclude Discs / Procs return 0; - else if (focus_spell.base[i] == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) //Exclude Spells + else if (focus_spell.base[i] == 1 && + (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) // Exclude Spells return 0; break; case SE_LimitSpellGroup: - if(focus_spell.base[i] < 0) { - if (-focus_spell.base[i] == spell.spellgroup) //Exclude + if (focus_spell.base[i] < 0) { + if (-focus_spell.base[i] == spell.spellgroup) // Exclude return 0; - } - else { + } else { LimitInclude[8] = true; - if (focus_spell.base[i] == spell.spellgroup) //Include + if (focus_spell.base[i] == spell.spellgroup) // Include LimitInclude[9] = true; } break; case SE_LimitCastingSkill: - if(focus_spell.base[i] < 0) { - if(-focus_spell.base[i] == spell.skill) + if (focus_spell.base[i] < 0) { + if (-focus_spell.base[i] == spell.skill) return 0; - } - else { + } else { LimitInclude[10] = true; - if(focus_spell.base[i] == spell.skill) + if (focus_spell.base[i] == spell.skill) LimitInclude[11] = true; } break; case SE_LimitClass: - //Do not use this limit more then once per spell. If multiple class, treat value like items would. + // Do not use this limit more then once per spell. If multiple class, treat value like items + // would. if (!PassLimitClass(focus_spell.base[i], GetClass())) return 0; break; @@ -4864,40 +4844,38 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_LimitSpellClass: - if(focus_spell.base[i] < 0) { //Exclude + if (focus_spell.base[i] < 0) { // Exclude if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass)) - return(0); - } - else { + return (0); + } else { LimitInclude[12] = true; - if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass)) //Include + if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass)) // Include LimitInclude[13] = true; } break; case SE_LimitSpellSubclass: - if(focus_spell.base[i] < 0) { //Exclude + if (focus_spell.base[i] < 0) { // Exclude if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass)) - return(0); - } - else { + return (0); + } else { LimitInclude[14] = true; - if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass)) //Include + if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass)) // Include LimitInclude[15] = true; } break; - - //handle effects + // handle effects case SE_ImprovedDamage: if (type == focusImprovedDamage) { // This is used to determine which focus should be used for the random calculation - if(best_focus) { + if (best_focus) { // If the spell contains a value in the base2 field then that is the max value if (focus_spell.base2[i] != 0) { value = focus_spell.base2[i]; } - // If the spell does not contain a base2 value, then its a straight non random value + // If the spell does not contain a base2 value, then its a straight non random + // value else { value = focus_spell.base[i]; } @@ -4905,8 +4883,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo // Actual focus calculation starts here else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { value = focus_spell.base[i]; - } - else { + } else { value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } @@ -4914,18 +4891,15 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_ImprovedHeal: if (type == focusImprovedHeal) { - if(best_focus) { + if (best_focus) { if (focus_spell.base2[i] != 0) { value = focus_spell.base2[i]; - } - else { + } else { value = focus_spell.base[i]; } - } - else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { + } else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { value = focus_spell.base[i]; - } - else { + } else { value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } @@ -4933,18 +4907,15 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_ReduceManaCost: if (type == focusManaCost) { - if(best_focus) { + if (best_focus) { if (focus_spell.base2[i] != 0) { value = focus_spell.base2[i]; - } - else { + } else { value = focus_spell.base[i]; } - } - else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { + } else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { value = focus_spell.base[i]; - } - else { + } else { value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } @@ -4991,30 +4962,28 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_SpellHateMod: - if (type == focusSpellHateMod){ - if(value != 0){ - if(value > 0){ - if(focus_spell.base[i] > value) + if (type == focusSpellHateMod) { + if (value != 0) { + if (value > 0) { + if (focus_spell.base[i] > value) + value = focus_spell.base[i]; + } else { + if (focus_spell.base[i] < value) value = focus_spell.base[i]; } - else{ - if(focus_spell.base[i] < value) - value = focus_spell.base[i]; - } - } - else + } else value = focus_spell.base[i]; } break; case SE_ReduceReuseTimer: - if(type == focusReduceRecastTime) + if (type == focusReduceRecastTime) value = focus_spell.base[i] / 1000; break; case SE_TriggerOnCast: - if(type == focusTriggerOnCast){ - if(zone->random.Roll(focus_spell.base[i])) + if (type == focusTriggerOnCast) { + if (zone->random.Roll(focus_spell.base[i])) value = focus_spell.base2[i]; else value = 0; @@ -5022,50 +4991,50 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_BlockNextSpellFocus: - if(type == focusBlockNextSpell){ - if(zone->random.Roll(focus_spell.base[i])) + if (type == focusBlockNextSpell) { + if (zone->random.Roll(focus_spell.base[i])) value = 1; } break; case SE_SympatheticProc: - if(type == focusSympatheticProc) { + if (type == focusSympatheticProc) { value = focus_id; } break; case SE_FcSpellVulnerability: - if(type == focusSpellVulnerability) + if (type == focusSpellVulnerability) value = focus_spell.base[i]; break; case SE_FcTwincast: - if(type == focusTwincast) + if (type == focusTwincast) value = focus_spell.base[i]; break; case SE_FcDamageAmt: - if(type == focusFcDamageAmt) + if (type == focusFcDamageAmt) value = focus_spell.base[i]; break; case SE_FcDamageAmtCrit: - if(type == focusFcDamageAmtCrit) + if (type == focusFcDamageAmtCrit) value = focus_spell.base[i]; break; case SE_FcDamageAmtIncoming: - if(type == focusFcDamageAmtIncoming) + if (type == focusFcDamageAmtIncoming) value = focus_spell.base[i]; break; case SE_FcHealAmtIncoming: - if(type == focusFcHealAmtIncoming) + if (type == focusFcHealAmtIncoming) value = focus_spell.base[i]; break; case SE_FcDamagePctCrit: - if(type == focusFcDamagePctCrit) + if (type == focusFcDamagePctCrit) value = focus_spell.base[i]; break; @@ -5075,17 +5044,17 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_FcHealAmtCrit: - if(type == focusFcHealAmtCrit) + if (type == focusFcHealAmtCrit) value = focus_spell.base[i]; break; - case SE_FcHealAmt: - if(type == focusFcHealAmt) + case SE_FcHealAmt: + if (type == focusFcHealAmt) value = focus_spell.base[i]; break; case SE_FcHealPctIncoming: - if(type == focusFcHealPctIncoming) + if (type == focusFcHealPctIncoming) value = focus_spell.base[i]; break; @@ -5095,51 +5064,51 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_FcIncreaseNumHits: - if(type == focusIncreaseNumHits) + if (type == focusIncreaseNumHits) value = focus_spell.base[i]; break; case SE_FcLimitUse: - if(type == focusFcLimitUse) + if (type == focusFcLimitUse) value = focus_spell.base[i]; break; case SE_FcMute: - if(type == focusFcMute) + if (type == focusFcMute) value = focus_spell.base[i]; break; case SE_FcStunTimeMod: - if(type == focusFcStunTimeMod) + if (type == focusFcStunTimeMod) value = focus_spell.base[i]; break; case SE_FcTimerRefresh: - if(type == focusFcTimerRefresh) + if (type == focusFcTimerRefresh) value = focus_spell.base[i]; break; #if EQDEBUG >= 6 - //this spits up a lot of garbage when calculating spell focuses - //since they have all kinds of extra effects on them. + // this spits up a lot of garbage when calculating spell focuses + // since they have all kinds of extra effects on them. default: - Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]); + Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown effectid %d", + focus_spell.effectid[i]); #endif } - } - for(int e = 0; e < MaxLimitInclude; e+=2) { - if (LimitInclude[e] && !LimitInclude[e+1]) + for (int e = 0; e < MaxLimitInclude; e += 2) { + if (LimitInclude[e] && !LimitInclude[e + 1]) return 0; } - if (Caston_spell_id){ - if(IsValidSpell(Caston_spell_id) && (Caston_spell_id != spell_id)) + 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); } - return(value*lvlModifier/100); + return (value * lvlModifier / 100); } uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { @@ -5501,26 +5470,24 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { if (aabonuses.FocusEffects[type]){ int16 Total3 = 0; - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; - //aa old - //for (int i = 0; i < MAX_PP_AA_ARRAY; i++) - //{ - // aa_AA = this->aa[i]->AA; - // aa_value = this->aa[i]->value; - // if (aa_AA < 1 || aa_value < 1) - // continue; - // - // Total3 = CalcAAFocus(type, aa_AA, spell_id); - // if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { - // realTotal3 = Total3; - // } - // else if (Total3 < 0 && Total3 < realTotal3) { - // realTotal3 = Total3; - // } - //} + for (const auto &aa : aa_ranks) { + auto ability = zone->GetAlternateAdvancementAbility(aa.first); + if (!ability) + continue; + + auto rank = ability->GetRankByPointsSpent(aa.second.first); + if (!rank || rank->effects.empty()) + continue; + + Total3 = CalcAAFocus(type, *rank, spell_id); + if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { + realTotal3 = Total3; + } + else if (Total3 < 0 && Total3 < realTotal3) { + realTotal3 = Total3; + } + } } if(type == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) From 4898bfd822cf1bb08ba6549b7f6c9ab5a1bfbb20 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Jun 2015 02:12:17 -0400 Subject: [PATCH 179/846] Fix focusReagenCost for pets All focus seem to use 33 ... --- zone/spell_effects.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 0bb7b78b9..7fcba77e9 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4332,8 +4332,14 @@ int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) LimitFailure = true; } else { LimitInclude[4] = true; - if (IsEffectInSpell(spell_id, base1)) // Include - LimitInclude[5] = true; + // they use 33 here for all classes ... unsure if the type check is really needed + if (base1 == SE_SummonPet && type == focusReagentCost) { + if (IsSummonPetSpell(spell_id) || IsSummonSkeletonSpell(spell_id)) + LimitInclude[5] = true; + } else { + if (IsEffectInSpell(spell_id, base1)) // Include + LimitInclude[5] = true; + } } break; @@ -5490,9 +5496,6 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { } } - if(type == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) - return 100; - if(type == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) return 0; //Summon Spells that require reagents are typically imbue type spells, enchant metal, sacrifice and shouldn't be affected From 106e0c69abf140dd1b1f15daac2a4bf8e680dcc0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Jun 2015 02:43:00 -0400 Subject: [PATCH 180/846] Added todo list to ApplyAABonuses Probably incomplete --- common/spdat.h | 20 ++++++++++---------- zone/bonuses.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index ab128a37c..a0c74c16a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -381,24 +381,24 @@ typedef enum { #define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance. #define SE_TwoHandBash 226 // *not implemented as bonus #define SE_ReduceSkillTimer 227 // implemented -//#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling +#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling #define SE_PersistantCasting 229 // implemented -//#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability +#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability #define SE_StunBashChance 231 // implemented - increase chance to stun from bash. #define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save) #define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates. -//#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison +#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison #define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live. //#define SE_FreePet 236 // not used #define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity) #define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed. -//#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. +#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. //#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.] #define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet. #define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr #define SE_CharmBreakChance 243 // implemented - Total Domination #define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break. -//#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest +#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest #define SE_SetBreathLevel 246 // *not implemented as bonus #define SE_RaiseSkillCap 247 // *not implemented[AA] - adds skill over the skill cap. #define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100) @@ -408,9 +408,9 @@ typedef enum { #define SE_FrontalBackstabChance 252 // implemented[AA] - chance to perform a full damage backstab from front. #define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage. #define SE_Blank 254 // implemented -//#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield -//#define SE_ShroudofStealth 256 // not implemented as bonus - rogue improved invs -//#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold +#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield +#define SE_ShroudofStealth 256 // not implemented as bonus - rogue improved invs +#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold #define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab #define SE_CombatStability 259 // implemented[AA] - damage mitigation #define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType @@ -434,11 +434,11 @@ typedef enum { #define SE_FinishingBlow 278 // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage) #define SE_Flurry 279 // implemented #define SE_PetFlurry 280 // implemented[AA] -//#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance +#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance #define SE_ImprovedBindWound 282 // implemented[AA] - increase bind wound amount by percent. #define SE_DoubleSpecialAttack 283 // implemented[AA] - Chance to perform second special attack as monk //#define SE_LoHSetHeal 284 // not used -//#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max +#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max #define SE_FcDamageAmt 286 // implemented - adds direct spell damage #define SE_SpellDurationIncByTic 287 // implemented #define SE_SkillAttackProc 288 // implemented[AA] - Chance to proc spell on skill attack usage (ex. Dragon Punch) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 23a896979..8e7b56721 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -816,8 +816,6 @@ void Client::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } break; - case SE_PetDiscipline2: - break; case SE_SpellSlotIncrease: break; case SE_MysticalAttune: @@ -1392,6 +1390,10 @@ void Client::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->ATK += base1; break; // to do + case SE_PetDiscipline: + break; + case SE_PetDiscipline2: + break; case SE_ReduceTradeskillFail: break; case SE_PotionBeltSlots: @@ -1404,7 +1406,25 @@ void Client::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_SecondaryForte: break; + case SE_FeignedCastOnChance: + break; + case SE_ExtendedShielding: + break; + case SE_ShieldDuration: + break; + case SE_ReduceApplyPoisonTime: + break; + case SE_NimbleEvasion: + break; + case SE_TrapCircumvention: + break; + case SE_ShroudofStealth: + break; + case SE_FeignedMinion: + break; + // handled client side + case SE_ReduceFallDamage: // not handled here case SE_HastenedAASkill: // not handled here but don't want to clutter debug log -- these may need to be verified to ignore From 121af489c4c094fc5c6056f48f145bdae4a44dae Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Jun 2015 17:53:21 -0400 Subject: [PATCH 181/846] Support for Eyes Wide Open This probably needs testing on older clients ... --- common/spdat.h | 2 +- zone/bonuses.cpp | 6 ++++++ zone/common.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/common/spdat.h b/common/spdat.h index a0c74c16a..24e982aee 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -579,7 +579,7 @@ typedef enum { #define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type #define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace //#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626) -//#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window +#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window #define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt) #define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc #define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires. diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 8e7b56721..b0c48f205 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -113,6 +113,9 @@ void Client::CalcBonuses() rooted = FindType(SE_Root); XPRate = 100 + spellbonuses.XPRateMod; + + if (GetMaxXTargets() != 5 + aabonuses.extra_xtargets) + SetMaxXTargets(5 + aabonuses.extra_xtargets); } int Client::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) @@ -1389,6 +1392,9 @@ void Client::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_ATK: newbon->ATK += base1; break; + case SE_IncreaseExtTargetWindow: + newbon->extra_xtargets += base1; + break; // to do case SE_PetDiscipline: break; diff --git a/zone/common.h b/zone/common.h index e658a352d..d21a0039d 100644 --- a/zone/common.h +++ b/zone/common.h @@ -461,6 +461,7 @@ struct StatBonuses { uint8 AssassinateLevel; // 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 }; typedef struct From 335470d3dbe040b8de5be739c270c7ea103d9308 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Jun 2015 22:49:32 -0400 Subject: [PATCH 182/846] Port up AA sympathetic procs --- zone/spell_effects.cpp | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7fcba77e9..c78e80be8 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5202,33 +5202,29 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { /*Note: At present, ff designing custom AA to have a sympathetic proc effect, only use one focus effect within the aa_effects data for each AA*[No live AA's use this effect to my knowledge]*/ - if (aabonuses.FocusEffects[type]){ + if (aabonuses.FocusEffects[type]) { + for (const auto &aa : aa_ranks) { + if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) + break; - uint32 aa_AA = 0; - uint32 aa_value = 0; + auto ability = zone->GetAlternateAdvancementAbility(aa.first); + if (!ability) + continue; - //aa old - //for (int i = 0; i < MAX_PP_AA_ARRAY; i++) - //{ - // aa_AA = this->aa[i]->AA; - // aa_value = this->aa[i]->value; - // if (aa_AA < 1 || aa_value < 1) - // continue; - // - // if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) - // continue; - // - // proc_spellid = CalcAAFocus(type, aa_AA, spell_id); - // - // if (IsValidSpell(proc_spellid)){ - // ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1)); - // if(zone->random.Roll(ProcChance)) - // SympatheticProcList.push_back(proc_spellid); - // } - //} + auto rank = ability->GetRankByPointsSpent(aa.second.first); + if (!rank || rank->effects.empty()) + continue; + + proc_spellid = CalcAAFocus(type, *rank, spell_id); + if (IsValidSpell(proc_spellid)) { + ProcChance = GetSympatheticProcChances(spell_id, rank->effects[0].base1); + if (zone->random.Roll(ProcChance)) + SympatheticProcList.push_back(proc_spellid); + } + } } - if (SympatheticProcList.size() > 0) + if (!SympatheticProcList.empty()) { uint8 random = zone->random.Int(0, SympatheticProcList.size()-1); int FinalSympatheticProc = SympatheticProcList[random]; From 34f01064379c192fcf9099b78bb1bb2c098791a0 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 15 Jun 2015 13:57:18 -0700 Subject: [PATCH 183/846] Added reset aa command for rof2 (50 status req), fixed #resetaa command --- common/emu_oplist.h | 1 + utils/patches/patch_RoF2.conf | 1 + zone/aa.cpp | 116 ++++++++++++++++------------------ zone/client_packet.cpp | 10 ++- zone/client_packet.h | 1 + zone/command.cpp | 24 +++---- 6 files changed, 72 insertions(+), 81 deletions(-) diff --git a/common/emu_oplist.h b/common/emu_oplist.h index e4793826e..4ef1761bd 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -548,4 +548,5 @@ N(OP_ZoneServerInfo), N(OP_ZoneServerReady), N(OP_ZoneSpawns), N(OP_ZoneUnavail), +N(OP_ResetAA), // mail and chat opcodes located in ../mail_oplist.h diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 1ebf05442..b22cc66d5 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -353,6 +353,7 @@ OP_OpenContainer=0x0000 OP_Marquee=0x502e OP_ItemRecastDelay=0x15a9 #OP_OpenInventory=0x0000 # Likely does not exist in RoF -U +OP_ResetAA=0x1669 # Expeditions OP_DzAddPlayer=0x4701 diff --git a/zone/aa.cpp b/zone/aa.cpp index cf2fb0685..c2a3d63cf 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -482,40 +482,35 @@ bool Client::CheckAAEffect(aaEffectType type) { return(false); } -void Client::ResetAA(){ -// RefundAA(); -// uint32 i; -// for (i=0; i < MAX_PP_AA_ARRAY; i++) { -// aa[i]->AA = 0; -// aa[i]->value = 0; -// aa[i]->charges = 0; -// m_pp.aa_array[i].AA = 0; -// m_pp.aa_array[i].value = 0; -// m_pp.aa_array[i].charges= 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; -// -// database.DeleteCharacterAAs(this->CharacterID()); -// SaveAA(); -// SendClearAA(); -// SendAAList(); -// SendAATable(); -// SendAAStats(); -// database.DeleteCharacterLeadershipAAs(this->CharacterID()); -// // undefined for these clients -// if (GetClientVersionBit() & BIT_TitaniumAndEarlier) -// Kick(); +void Client::ResetAA() { + RefundAA(); + uint32 i; + for (i=0; i < MAX_PP_AA_ARRAY; i++) { + m_pp.aa_array[i].AA = 0; + m_pp.aa_array[i].value = 0; + m_pp.aa_array[i].charges= 0; + } + + aa_ranks.clear(); + + 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; + + database.DeleteCharacterAAs(CharacterID()); + SaveAA(); + SendClearAA(); + SendAlternateAdvancementTable(); + SendAlternateAdvancementPoints(); + SendAlternateAdvancementStats(); + database.DeleteCharacterLeadershipAAs(this->CharacterID()); + // undefined for these clients + if (GetClientVersionBit() & BIT_TitaniumAndEarlier) + Kick(); } void Client::SendClearAA() @@ -802,34 +797,31 @@ void Client::DurationRampage(uint32 duration) } void Client::RefundAA() { -// int cur = 0; -// bool refunded = false; -// -// for(int x = 0; x < aaHighestID; x++) { -// cur = GetAA(x); -// if(cur > 0){ -// SendAA_Struct* curaa = zone->FindAA(x); -// if(cur){ -// SetAA(x, 0); -// for(int j = 0; j < cur; j++) { -// m_pp.aapoints += curaa->cost + (curaa->cost_inc * j); -// refunded = true; -// } -// } -// else -// { -// m_pp.aapoints += cur; -// SetAA(x, 0); -// refunded = true; -// } -// } -// } -// -// if(refunded) { -// SaveAA(); -// Save(); -// // Kick(); -// } + int refunded = 0; + + for(auto &rank_value : aa_ranks) { + AA::Ability *ability = zone->GetAlternateAdvancementAbility(rank_value.first); + if(!ability) { + continue; + } + + if(ability->charges > 0 && rank_value.second.second < 1) { + continue; + } + + AA::Rank *rank = ability->GetRankByPointsSpent(rank_value.second.first); + if(!rank) { + continue; + } + + refunded += rank->total_cost; + } + + if(refunded > 0) { + m_pp.aapoints += refunded; + SaveAA(); + Save(); + } } AA_SwarmPetInfo::AA_SwarmPetInfo() diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index b76c11d8c..d01bcf109 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -389,6 +389,7 @@ void MapOpcodes() ConnectedOpcodes[OP_XTargetRequest] = &Client::Handle_OP_XTargetRequest; ConnectedOpcodes[OP_YellForHelp] = &Client::Handle_OP_YellForHelp; ConnectedOpcodes[OP_ZoneChange] = &Client::Handle_OP_ZoneChange; + ConnectedOpcodes[OP_ResetAA] = &Client::Handle_OP_ResetAA; } void ClearMappedOpcode(EmuOpcode op) @@ -14163,9 +14164,12 @@ void Client::Handle_OP_YellForHelp(const EQApplicationPacket *app) return; } -/* -void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) +void Client::Handle_OP_ResetAA(const EQApplicationPacket *app) { + if(Admin() >= 50) { + Message(0, "Resetting AA points."); + ResetAA(); + } return; } -*/ + diff --git a/zone/client_packet.h b/zone/client_packet.h index 1a9591f4c..a39e3fb74 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -295,3 +295,4 @@ void Handle_OP_XTargetRequest(const EQApplicationPacket *app); void Handle_OP_YellForHelp(const EQApplicationPacket *app); void Handle_OP_ZoneChange(const EQApplicationPacket *app); + void Handle_OP_ResetAA(const EQApplicationPacket *app); diff --git a/zone/command.cpp b/zone/command.cpp index 0554a5e68..16f50e7d7 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -332,7 +332,7 @@ int command_init(void) { command_add("reloadzonepoints", "- Reload zone points from database", 150, command_reloadzps) || command_add("reloadzps", nullptr,0, command_reloadzps) || command_add("repop", "[delay] - Repop the zone with optional delay", 100, command_repop) || - command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, disconnects player.", 200, command_resetaa) || + command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", 200, command_resetaa) || command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) || command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) || command_add("save", "- Force your player or player corpse target to be saved to the database", 50, command_save) || @@ -671,21 +671,13 @@ void command_incstat(Client* c, const Seperator* sep){ } } -void command_resetaa(Client* c,const Seperator *sep){ - - //if(sep->IsNumber(1) && atoi(sep->arg[1]) == 1) { - // c->SendAlternateAdvancement(2, 2); - //} - //else if(sep->IsNumber(1) && atoi(sep->arg[1]) == 2) { - // c->SendAlternateAdvancement(2, 3); - //} - - //if(c->GetTarget()!=0 && c->GetTarget()->IsClient()){ - // c->GetTarget()->CastToClient()->ResetAA(); - // c->Message(13,"Successfully reset %s's AAs", c->GetTarget()->GetName()); - //} - //else - // c->Message(0,"Usage: Target a client and use #resetaa to reset the AA data in their Profile."); +void command_resetaa(Client* c,const Seperator *sep) { + if(c->GetTarget() && c->GetTarget()->IsClient()){ + c->GetTarget()->CastToClient()->ResetAA(); + c->Message(13,"Successfully reset %s's AAs", c->GetTarget()->GetName()); + } + else + c->Message(0,"Usage: Target a client and use #resetaa to reset the AA data in their Profile."); } void command_help(Client *c, const Seperator *sep) From a984e9bd7c116a07085e279c7745766d43bfbe76 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 15 Jun 2015 15:09:06 -0700 Subject: [PATCH 184/846] Some cleanup as well as fix for a certain type of aa proc --- zone/aa.cpp | 65 +++++++++++++++++++++++++++------------ zone/attack.cpp | 70 ++++++++++++++++++++++-------------------- zone/bonuses.cpp | 14 +++++---- zone/client.h | 24 ++++++--------- zone/mob.h | 1 + zone/perl_client.cpp | 29 +---------------- zone/spell_effects.cpp | 63 ++++++++++--------------------------- zone/zone.h | 1 + 8 files changed, 120 insertions(+), 147 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index c2a3d63cf..1f0b5b086 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -800,7 +800,10 @@ void Client::RefundAA() { int refunded = 0; for(auto &rank_value : aa_ranks) { - AA::Ability *ability = zone->GetAlternateAdvancementAbility(rank_value.first); + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value.first, rank_value.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + if(!ability) { continue; } @@ -809,11 +812,6 @@ void Client::RefundAA() { continue; } - AA::Rank *rank = ability->GetRankByPointsSpent(rank_value.second.first); - if(!rank) { - continue; - } - refunded += rank->total_cost; } @@ -864,20 +862,19 @@ void Client::SendAlternateAdvancementTable() { void Client::SendAlternateAdvancementRank(int aa_id, int level) { if(!zone) return; - - AA::Ability *ability = zone->GetAlternateAdvancementAbility(aa_id); - if(!ability) + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_id, level); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if(!ability) { return; + } if(!(ability->classes & (1 << GetClass()))) { return; } - AA::Rank *rank = ability->GetRankByPointsSpent(level); - if(!rank) - return; - if(!CanUseAlternateAdvancementRank(rank)) { return; } @@ -1224,13 +1221,11 @@ int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) { } for(auto &aa : aa_ranks) { - AA::Ability *ability = zone->GetAlternateAdvancementAbility(aa.first); - if(!ability) { - continue; - } + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; - AA::Rank *rank = ability->GetRankByPointsSpent(aa.second.first); - if(!rank) { + if(!ability) { continue; } @@ -1328,6 +1323,21 @@ AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) { return nullptr; } +std::pair Zone::GetAlternateAdvancementAbilityAndRank(int id, int points_spent) { + AA::Ability *ability = GetAlternateAdvancementAbility(id); + + if(!ability) { + return std::make_pair(nullptr, nullptr); + } + + AA::Rank *rank = ability->GetRankByPointsSpent(points_spent); + if(!rank) { + return std::make_pair(nullptr, nullptr); + } + + return std::make_pair(ability, rank); +} + uint32 Mob::GetAA(uint32 rank_id, uint32 *charges) const { if(zone) { AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); @@ -1345,6 +1355,23 @@ uint32 Mob::GetAA(uint32 rank_id, uint32 *charges) const { return 0; } +uint32 Mob::GetAAByAAID(uint32 aa_id, uint32 *charges) const { + if(zone) { + AA::Ability *ability = zone->GetAlternateAdvancementAbility(aa_id); + + if(!ability) + return 0; + + auto iter = aa_ranks.find(ability->id); + if(iter != aa_ranks.end()) { + if(charges) { + *charges = iter->second.second; + } + return iter->second.first; + } + } +} + bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) { if(zone) { AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); diff --git a/zone/attack.cpp b/zone/attack.cpp index cecf37ff1..fda7837ab 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4647,7 +4647,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (IsClient() && aabonuses.LimitToSkill[skill]){ CanProc = true; - uint32 effect = 0; + uint32 effect_id = 0; int32 base1 = 0; int32 base2 = 0; uint32 slot = 0; @@ -4666,39 +4666,43 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui proc_spell_id = 0; ProcMod = 0; - //old AA - //std::map >::const_iterator find_iter = aa_effects.find(aaid); - //if(find_iter == aa_effects.end()) - // break; + for(auto &rank_info : aa_ranks) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_info.first, rank_info.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; - //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; - // - // if (effect == SE_SkillProc || effect == SE_SkillProcSuccess) { - // proc_spell_id = base1; - // ProcMod = static_cast(base2); - // } - // - // else if (effect == SE_LimitToSkill && base1 <= HIGHEST_SKILL) { - // - // if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { - // float final_chance = chance * (ProcMod / 100.0f); - // - // if (zone->random.Roll(final_chance)) { - // ExecWeaponProc(nullptr, proc_spell_id, on); - // CanProc = false; - // break; - // } - // } - // } - // else { - // proc_spell_id = 0; - // ProcMod = 0; - // } - //} + if(!ability) { + continue; + } + + for(auto &effect : rank->effects) { + effect_id = effect.effect_id; + base1 = effect.base1; + base2 = effect.base2; + slot = effect.slot; + + if(effect_id == SE_SkillProc || effect_id == SE_SkillProcSuccess) { + proc_spell_id = base1; + ProcMod = static_cast(base2); + } + else if(effect_id == SE_LimitToSkill && base1 <= HIGHEST_SKILL) { + + if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { + float final_chance = chance * (ProcMod / 100.0f); + + if (zone->random.Roll(final_chance)) { + ExecWeaponProc(nullptr, proc_spell_id, on); + CanProc = false; + break; + } + } + } + else { + proc_spell_id = 0; + ProcMod = 0; + } + } + } } } } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index b0c48f205..6d12b1eac 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -640,14 +640,16 @@ void Client::CalcAABonuses(StatBonuses *newbon) memset(newbon, 0, sizeof(StatBonuses)); // start fresh for (const auto &aa : aa_ranks) { - auto ability = zone->GetAlternateAdvancementAbility(aa.first); - // zone doesn't know about this! bad data some where - if (!ability) - continue; + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if(!ability) { + continue; + } - auto rank = ability->GetRankByPointsSpent(aa.second.first); // bad data or no effects - if (!rank || rank->effects.empty()) + if (rank->effects.empty()) continue; ApplyAABonuses(*rank, newbon); diff --git a/zone/client.h b/zone/client.h index 014747576..e830edfa8 100644 --- a/zone/client.h +++ b/zone/client.h @@ -774,27 +774,23 @@ public: void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } int GetAAPoints() { return m_pp.aapoints; } int GetSpentAA() { return m_pp.aapoints_spent; } - - //old AA Methods + + //old AA methods that we still use void ResetAA(); + void RefundAA(); void SendClearAA(); - //this function is used by some AA stuff - void MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing); - void SetAATitle(const char *Title); - void SetTitleSuffix(const char *txt); inline uint32 GetMaxAAXP(void) const { return max_AAXP; } inline uint32 GetAAXP() const { return m_pp.expAA; } + int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id); + void SetAATitle(const char *Title); + void SetTitleSuffix(const char *txt); + + //old AA Methods that are slated for removal + void MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing); void EnableAAEffect(aaEffectType type, uint32 duration = 0); void DisableAAEffect(aaEffectType type); bool CheckAAEffect(aaEffectType type); - void HandleAAAction(aaID activate); - int16 CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id); - int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id); - void RefundAA(); - int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2); - int32 GetAAEffectid(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, true, false,false); } - int32 GetAABase1(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, true,false); } - int32 GetAABase2(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, false,true); } + int32 acmod(); // Item methods diff --git a/zone/mob.h b/zone/mob.h index ed5d68c2c..3e4f5ea39 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -960,6 +960,7 @@ public: //aa new uint32 GetAA(uint32 rank_id, uint32 *charges = nullptr) const; + uint32 GetAAByAAID(uint32 aa_id, uint32 *charges = nullptr) const; bool SetAA(uint32 rank_id, uint32 new_value, uint32 charges = 0); void ClearAAs() { aa_ranks.clear(); } bool CanUseAlternateAdvancementRank(AA::Rank *rank); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 95fc146ae..eea9918cd 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4077,34 +4077,7 @@ XS(XS_Client_RefundAA) { if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - //old aa - //int curpt = 0; - //bool refunded = false; - // - //for(int x1=0;x1GetAA(x1); - // if(curpt > 0){ - // SendAA_Struct* curaa = zone->FindAA(x1); - // if(curaa){ - // THIS->SetAA(x1, 0); - // for(int x2=0;x2GetPP().aapoints += curaa->cost + (curaa->cost_inc * x2); - // refunded = true; - // } - // } - // else //aa doesn't exist.. but if they bought it then it had at least a cost of 1 point each - // { //so give back what we can - // THIS->GetPP().aapoints += curpt; - // THIS->SetAA(x1, 0); - // refunded = true; - // } - // } - //} - // - //if(refunded){ - // THIS->Save(); //save of course - // THIS->Kick(); //client gets all buggy if we don't immediatly relog so just force it on them - //} + THIS->RefundAA(); } XSRETURN_EMPTY; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index c78e80be8..a7c5643a1 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4149,43 +4149,6 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) CalcBonuses(); } -int32 Client::GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2) -{ - int32 aa_effects_data[3] = { 0 }; - uint32 effect = 0; - int32 base1 = 0; - int32 base2 = 0; - uint32 slot = 0; - - //old aa - //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - //if(find_iter == aa_effects.end()) - // return 0; - // - //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - //{ - // effect = iter->second.skill_id; - // base1 = iter->second.base1; - // base2 = iter->second.base2; - // slot = iter->second.slot; - // - // if (slot && slot == slot_id) { - // - // if (GetEffect) - // return effect; - // - // if (GetBase1) - // return base1; - // - // if (GetBase2) - // return base2; - // } - //} - - return 0; -} - - int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) { const SPDat_Spell_Struct &spell = spells[spell_id]; @@ -5207,12 +5170,15 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) break; - auto ability = zone->GetAlternateAdvancementAbility(aa.first); - if (!ability) - continue; + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; - auto rank = ability->GetRankByPointsSpent(aa.second.first); - if (!rank || rank->effects.empty()) + if(!ability) { + continue; + } + + if (rank->effects.empty()) continue; proc_spellid = CalcAAFocus(type, *rank, spell_id); @@ -5474,12 +5440,15 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { int16 Total3 = 0; for (const auto &aa : aa_ranks) { - auto ability = zone->GetAlternateAdvancementAbility(aa.first); - if (!ability) - continue; + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; - auto rank = ability->GetRankByPointsSpent(aa.second.first); - if (!rank || rank->effects.empty()) + if(!ability) { + continue; + } + + if (rank->effects.empty()) continue; Total3 = CalcAAFocus(type, *rank, spell_id); diff --git a/zone/zone.h b/zone/zone.h index a4a49b8b2..94bba72e4 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -119,6 +119,7 @@ public: AA::Ability *GetAlternateAdvancementAbility(int id); AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id); AA::Rank *GetAlternateAdvancementRank(int rank_id); + std::pair GetAlternateAdvancementAbilityAndRank(int id, int points_spent); void LoadZoneDoors(const char* zone, int16 version); bool LoadZoneObjects(); From 1b088b7157c4e120fd598890b37474e584c6e3b4 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 16 Jun 2015 11:34:43 -0700 Subject: [PATCH 185/846] AA bonus calc -> Mob from Client, Bots should now work with their aa stuff again (untested) --- zone/bonuses.cpp | 15 +- zone/bot.cpp | 1533 ++++++++++++++-------------------------------- zone/bot.h | 5 +- zone/client.h | 2 - zone/mob.h | 2 + 5 files changed, 463 insertions(+), 1094 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 6d12b1eac..c19755aae 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -42,6 +42,7 @@ void Mob::CalcBonuses() { CalcSpellBonuses(&spellbonuses); + CalcAABonuses(&aabonuses); CalcMaxHP(); CalcMaxMana(); SetAttackTimer(); @@ -51,9 +52,7 @@ void Mob::CalcBonuses() void NPC::CalcBonuses() { - Mob::CalcBonuses(); - memset(&aabonuses, 0, sizeof(StatBonuses)); - + memset(&itembonuses, 0, sizeof(StatBonuses)); if(RuleB(NPC, UseItemBonusesForNonPets)){ memset(&itembonuses, 0, sizeof(StatBonuses)); CalcItemBonuses(&itembonuses); @@ -74,12 +73,8 @@ void Client::CalcBonuses() memset(&itembonuses, 0, sizeof(StatBonuses)); CalcItemBonuses(&itembonuses); CalcEdibleBonuses(&itembonuses); - CalcSpellBonuses(&spellbonuses); - - Log.Out(Logs::Detail, Logs::AA, "Calculating AA Bonuses for %s.", this->GetCleanName()); - CalcAABonuses(&aabonuses); //we're not quite ready for this - Log.Out(Logs::Detail, Logs::AA, "Finished calculating AA Bonuses for %s.", this->GetCleanName()); + CalcAABonuses(&aabonuses); ProcessItemCaps(); // caps that depend on spell/aa bonuses @@ -635,7 +630,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { } } -void Client::CalcAABonuses(StatBonuses *newbon) +void Mob::CalcAABonuses(StatBonuses *newbon) { memset(newbon, 0, sizeof(StatBonuses)); // start fresh @@ -659,7 +654,7 @@ void Client::CalcAABonuses(StatBonuses *newbon) //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(const AA::Rank &rank, StatBonuses *newbon) +void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) { if (rank.effects.empty()) // sanity check. why bother if no slots to fill? return; diff --git a/zone/bot.cpp b/zone/bot.cpp index 5200f3e95..ea6739c79 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -193,7 +193,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to GenerateBaseStats(); LoadTimers(); - //LoadAAs(); old aa, replace this + LoadAAs(); LoadBuffs(); CalcBotStats(false); @@ -1424,668 +1424,41 @@ int32 Bot::GenerateBaseHitPoints() return new_base_hp; } -void Bot::GenerateAABonuses(StatBonuses* newbon) { - // General AA bonus - uint8 botClass = GetClass(); - uint8 botLevel = GetLevel(); +void Bot::LoadAAs() { + int maxAAExpansion = RuleI(Bots, BotAAExpansion); //get expansion to get AAs up to + aa_ranks.clear(); - memset(newbon, 0, sizeof(StatBonuses)); //start fresh - //old aa - //if(botLevel >= 51) { - // //level 51 = 1 AA level - // - // int i; - // int totalAAs = database.CountAAs(); - // uint32 slots = 0; - // uint32 aa_AA = 0; - // uint32 aa_value = 0; - // for (i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs - // std::map::iterator aa = botAAs.find(i); - // if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone - // aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table - // aa_value = aa->second.total_levels; //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 + aa_value -1, slots, newbon); //add the bonuses - // } - // } - // } - //} -} + int id = 0; + int points = 0; + auto iter = zone->aa_abilities.begin(); + while(iter != zone->aa_abilities.end()) { + AA::Ability *ability = (*iter).second.get(); -//old AA -//void Bot::LoadAAs() { -// int maxAAExpansion = RuleI(Bots, BotAAExpansion); //get expansion to get AAs up to -// botAAs.clear(); //start fresh -// -// std::string query; -// -// if(GetClass() == BERSERKER) -// query = StringFormat("SELECT skill_id FROM altadv_vars WHERE berserker = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetLevel(), maxAAExpansion); -// else -// query = StringFormat("SELECT skill_id FROM altadv_vars WHERE ((classes & ( 1 << %i )) >> %i) = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetClass(), GetClass(), GetLevel(), maxAAExpansion); -// -// auto results = database.QueryDatabase(query); -// -// if(!results.Success()) { -// Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadAAs()"); -// return; -// } -// -// int totalAAs = database.CountAAs(); -// -// for (auto row = results.begin(); row != results.end(); ++row) { -// uint32 skill_id = 0; -// skill_id = atoi(row[0]); -// -// if(skill_id <= 0 || skill_id >= totalAAs) -// continue; -// -// SendAA_Struct *sendAA = zone->FindAA(skill_id); -// -// if(!sendAA) -// continue; -// -// for(int i=0; imax_level; i++) { -// //Get AA info & add to list -// uint32 aaid = sendAA->id + i; -// uint8 total_levels = 0; -// uint8 req_level; -// std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(aaid); -// -// //Get level required for AA -// if(RequiredLevel != AARequiredLevelAndCost.end()) -// req_level = RequiredLevel->second.Level; -// else -// req_level = (sendAA->class_type + i * sendAA->level_inc); -// -// if(req_level > GetLevel()) -// break; -// -// //Bot is high enough level for AA -// std::map::iterator foundAA = botAAs.find(aaid); -// -// // AA is already in list -// if(foundAA != botAAs.end()) -// continue; -// -// if(sendAA->id == aaid) { -// BotAA newAA; -// -// newAA.total_levels = 0; -// newAA.aa_id = aaid; -// newAA.req_level = req_level; -// newAA.total_levels += 1; -// -// botAAs[aaid] = newAA; //add to list -// } -// else //update master AA record with number of levels a bot has in AA, based on level. -// botAAs[sendAA->id].total_levels+=1; -// } -// } -// -//} + //skip expendables + if(!ability->first || ability->charges > 0) { + continue; + } -//current with Client::ApplyAABonuses 9/26/12 -void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) -{ - if(slots == 0) //sanity check. why bother if no slots to fill? - return; + id = ability->first->id; + points = 0; - //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; + AA::Rank *current = ability->first; - //old AA - //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.Out(Logs::Detail, Logs::AA, "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_ArcheryDamageModifier: - // newbon->ArcheryDamageModifier += 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_PetCriticalHit: - // newbon->PetCriticalHit += base1; - // break; - // case SE_PetAvoidance: - // newbon->PetAvoidance += base1; - // break; - // case SE_ShieldBlock: - // newbon->ShieldBlock += base1; - // 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_StrikeThrough2: - // newbon->StrikeThrough += base1; - // break; - // case SE_DoubleAttackChance: - // newbon->DoubleAttackChance += base1; - // break; - // case SE_GiveDoubleAttack: - // newbon->GiveDoubleAttack += base1; - // break; - // case SE_ProcChance: - // newbon->ProcChance += 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_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->SpellCritDmgIncrease) - // newbon->SpellCritDmgIncrease = 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_SlayUndead: - // { - // if(newbon->SlayUndead[1] < base1) - // newbon->SlayUndead[0] = base1; // Rate - // newbon->SlayUndead[1] = base2; // Damage Modifier - // break; - // } - // - // 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] || ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < base1)) ){ - // newbon->SEResist[e] = base2; - // newbon->SEResist[e+1] = base1; - // 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; - // } - // } - //} + while(current) { + if(!CanUseAlternateAdvancementRank(current)) { + current = nullptr; + } else { + current = current->next; + points++; + } + } + + if(points > 0) { + SetAA(id, points); + } + + ++iter; + } } bool Bot::IsValidRaceClassCombo() { @@ -6298,7 +5671,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b return false; } -int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) +int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id) { const SPDat_Spell_Struct &spell = spells[spell_id]; @@ -6316,401 +5689,401 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) bool LimitFound = false; int FocusCount = 0; - //old AA - //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - //if(find_iter == aa_effects.end()) - //{ - // return 0; - //} - // - //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - //{ - // effect = iter->second.skill_id; - // base1 = iter->second.base1; - // base2 = iter->second.base2; - // slot = iter->second.slot; - // - // //AA Foci's can contain multiple focus effects within the same AA. - // //To handle this we will not automatically return zero if a limit is found. - // //Instead if limit is found and multiple effects, we will reset the limit check - // //when the next valid focus effect is found. - // if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ - // FocusCount++; - // //If limit found on prior check next, else end loop. - // if (FocusCount > 1){ - // if (LimitFound){ - // value = 0; - // LimitFound = false; - // } - // - // else{ - // break; - // } - // } - // } - // - // - // switch (effect) - // { - // case SE_Blank: - // break; - // - // //Handle Focus Limits - // case SE_LimitResist: - // if(base1) - // { - // if(spell.resisttype != base1) - // LimitFound = true; - // } - // break; - // case SE_LimitInstant: - // if(spell.buffduration) - // LimitFound = true; - // break; - // case SE_LimitMaxLevel: - // spell_level = spell.classes[(GetClass()%16) - 1]; - // lvldiff = spell_level - base1; - // //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - // if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) - // { - // if(base2 > 0) - // { - // lvlModifier -= base2*lvldiff; - // if(lvlModifier < 1) - // LimitFound = true; - // } - // else { - // LimitFound = true; - // } - // } - // break; - // case SE_LimitMinLevel: - // if((spell.classes[(GetClass()%16) - 1]) < base1) - // LimitFound = true; - // break; - // case SE_LimitCastTimeMin: - // if (spell.cast_time < base1) - // LimitFound = true; - // break; - // case SE_LimitSpell: - // // Exclude spell(any but this) - // if(base1 < 0) { - // if (spell_id == (base1*-1)) - // LimitFound = true; - // } - // else { - // // Include Spell(only this) - // if (spell_id != base1) - // LimitFound = true; - // } - // break; - // case SE_LimitMinDur: - // if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - // LimitFound = true; - // break; - // case SE_LimitEffect: - // // Exclude effect(any but this) - // if(base1 < 0) { - // if(IsEffectInSpell(spell_id,(base1*-1))) - // LimitFound = true; - // } - // else { - // // Include effect(only this) - // if(!IsEffectInSpell(spell_id,base1)) - // LimitFound = true; - // } - // break; - // case SE_LimitSpellType: - // switch(base1) - // { - // case 0: - // if (!IsDetrimentalSpell(spell_id)) - // LimitFound = true; - // break; - // case 1: - // if (!IsBeneficialSpell(spell_id)) - // LimitFound = true; - // break; - // } - // break; - // - // case SE_LimitManaMin: - // if(spell.mana < base1) - // LimitFound = true; - // break; - // - // case SE_LimitTarget: - // // Exclude - // if(base1 < 0){ - // if(-base1 == spell.targettype) - // LimitFound = true; - // } - // // Include - // else { - // if(base1 != spell.targettype) - // LimitFound = true; - // } - // break; - // - // case SE_LimitCombatSkills: - // // 1 is for disciplines only - // if(base1 == 1 && !IsDiscipline(spell_id)) - // LimitFound = true; - // // 0 is spells only - // else if(base1 == 0 && IsDiscipline(spell_id)) - // LimitFound = true; - // break; - // - // case SE_LimitSpellGroup: - // if(base1 > 0 && base1 != spell.spellgroup) - // LimitFound = true; - // else if(base1 < 0 && base1 == spell.spellgroup) - // LimitFound = true; - // break; - // - // - // case SE_LimitCastingSkill: - // LimitSpellSkill = true; - // if(base1 == spell.skill) - // SpellSkill_Found = true; - // break; - // - // case SE_LimitClass: - // //Do not use this limit more then once per spell. If multiple class, treat value like items would. - // if (!PassLimitClass(base1, GetClass())) - // LimitFound = true; - // break; - // - // - // //Handle Focus Effects - // case SE_ImprovedDamage: - // if (type == focusImprovedDamage && base1 > value) - // value = base1; - // break; - // - // case SE_ImprovedHeal: - // if (type == focusImprovedHeal && base1 > value) - // value = base1; - // break; - // - // case SE_ReduceManaCost: - // if (type == focusManaCost ) - // value = base1; - // break; - // - // case SE_IncreaseSpellHaste: - // if (type == focusSpellHaste && base1 > value) - // value = base1; - // break; - // - // case SE_IncreaseSpellDuration: - // if (type == focusSpellDuration && base1 > value) - // value = base1; - // break; - // - // case SE_SpellDurationIncByTic: - // if (type == focusSpellDurByTic && base1 > value) - // value = base1; - // break; - // - // case SE_SwarmPetDuration: - // if (type == focusSwarmPetDuration && base1 > value) - // value = base1; - // break; - // - // case SE_IncreaseRange: - // if (type == focusRange && base1 > value) - // value = base1; - // break; - // - // case SE_ReduceReagentCost: - // if (type == focusReagentCost && base1 > value) - // value = base1; - // break; - // - // case SE_PetPowerIncrease: - // if (type == focusPetPower && base1 > value) - // value = base1; - // break; - // - // case SE_SpellResistReduction: - // if (type == focusResistRate && base1 > value) - // value = base1; - // break; - // - // case SE_SpellHateMod: - // if (type == focusSpellHateMod) - // { - // if(value != 0) - // { - // if(value > 0) - // { - // if(base1 > value) - // { - // value = base1; - // } - // } - // else - // { - // if(base1 < value) - // { - // value = base1; - // } - // } - // } - // else - // value = base1; - // } - // break; - // - // case SE_ReduceReuseTimer: - // { - // if(type == focusReduceRecastTime) - // value = base1 / 1000; - // - // break; - // } - // - // case SE_TriggerOnCast: - // { - // if(type == focusTriggerOnCast) - // { - // if(zone->random.Int(0, 100) <= base1){ - // value = base2; - // } - // - // else{ - // value = 0; - // LimitFound = true; - // } - // } - // break; - // } - // case SE_FcSpellVulnerability: - // { - // if(type == focusSpellVulnerability) - // { - // value = base1; - // } - // break; - // } - // case SE_BlockNextSpellFocus: - // { - // if(type == focusBlockNextSpell) - // { - // if(zone->random.Int(1, 100) <= base1) - // value = 1; - // } - // break; - // } - // case SE_FcTwincast: - // { - // if(type == focusTwincast) - // { - // 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); - // - // if(zone->random.Real(0, 1) <= ProcChance) - // value = focus_id; - // - // else - // value = 0; - // } - // break; - // } - // */ - // case SE_FcDamageAmt: - // { - // if(type == focusFcDamageAmt) - // value = base1; - // - // break; - // } - // - // case SE_FcDamageAmtCrit: - // { - // if(type == focusFcDamageAmtCrit) - // value = base1; - // - // break; - // } - // - // case SE_FcDamageAmtIncoming: - // { - // if(type == focusFcDamageAmtIncoming) - // value = base1; - // - // break; - // } - // - // case SE_FcHealAmtIncoming: - // if(type == focusFcHealAmtIncoming) - // value = base1; - // break; - // - // case SE_FcHealPctCritIncoming: - // if (type == focusFcHealPctCritIncoming) - // value = base1; - // break; - // - // case SE_FcHealAmtCrit: - // if(type == focusFcHealAmtCrit) - // value = base1; - // break; - // - // case SE_FcHealAmt: - // if(type == focusFcHealAmt) - // value = base1; - // break; - // - // case SE_FcHealPctIncoming: - // if(type == focusFcHealPctIncoming) - // value = base1; - // break; - // - // case SE_FcBaseEffects: - // { - // if (type == focusFcBaseEffects) - // value = base1; - // - // break; - // } - // case SE_FcDamagePctCrit: - // { - // if(type == focusFcDamagePctCrit) - // value = base1; - // - // break; - // } - // - // case SE_FcIncreaseNumHits: - // { - // if(type == focusIncreaseNumHits) - // value = base1; - // - // break; - // } + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_ID, points); + auto ability = ability_rank.first; + auto rank = ability_rank.second; - ////Check for spell skill limits. - //if ((LimitSpellSkill) && (!SpellSkill_Found)) - // return 0; - // - // } - //} + if(!ability) { + return 0; + } - if (LimitFound){ + for(auto &eff : rank->effects) { + effect = eff.effect_id; + base1 = eff.base1; + base2 = eff.base2; + slot = eff.slot; + + //AA Foci's can contain multiple focus effects within the same AA. + //To handle this we will not automatically return zero if a limit is found. + //Instead if limit is found and multiple effects, we will reset the limit check + //when the next valid focus effect is found. + if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ + FocusCount++; + //If limit found on prior check next, else end loop. + if (FocusCount > 1){ + if (LimitFound){ + value = 0; + LimitFound = false; + } + + else{ + break; + } + } + } + + + switch (effect) + { + case SE_Blank: + break; + + //Handle Focus Limits + case SE_LimitResist: + if(base1) + { + if(spell.resisttype != base1) + LimitFound = true; + } + break; + case SE_LimitInstant: + if(spell.buffduration) + LimitFound = true; + break; + case SE_LimitMaxLevel: + spell_level = spell.classes[(GetClass()%16) - 1]; + lvldiff = spell_level - base1; + //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true + if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) + { + if(base2 > 0) + { + lvlModifier -= base2*lvldiff; + if(lvlModifier < 1) + LimitFound = true; + } + else { + LimitFound = true; + } + } + break; + case SE_LimitMinLevel: + if((spell.classes[(GetClass()%16) - 1]) < base1) + LimitFound = true; + break; + case SE_LimitCastTimeMin: + if (spell.cast_time < base1) + LimitFound = true; + break; + case SE_LimitSpell: + // Exclude spell(any but this) + if(base1 < 0) { + if (spell_id == (base1*-1)) + LimitFound = true; + } + else { + // Include Spell(only this) + if (spell_id != base1) + LimitFound = true; + } + break; + case SE_LimitMinDur: + if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + LimitFound = true; + break; + case SE_LimitEffect: + // Exclude effect(any but this) + if(base1 < 0) { + if(IsEffectInSpell(spell_id,(base1*-1))) + LimitFound = true; + } + else { + // Include effect(only this) + if(!IsEffectInSpell(spell_id,base1)) + LimitFound = true; + } + break; + case SE_LimitSpellType: + switch(base1) + { + case 0: + if (!IsDetrimentalSpell(spell_id)) + LimitFound = true; + break; + case 1: + if (!IsBeneficialSpell(spell_id)) + LimitFound = true; + break; + } + break; + + case SE_LimitManaMin: + if(spell.mana < base1) + LimitFound = true; + break; + + case SE_LimitTarget: + // Exclude + if(base1 < 0){ + if(-base1 == spell.targettype) + LimitFound = true; + } + // Include + else { + if(base1 != spell.targettype) + LimitFound = true; + } + break; + + case SE_LimitCombatSkills: + // 1 is for disciplines only + if(base1 == 1 && !IsDiscipline(spell_id)) + LimitFound = true; + // 0 is spells only + else if(base1 == 0 && IsDiscipline(spell_id)) + LimitFound = true; + break; + + case SE_LimitSpellGroup: + if(base1 > 0 && base1 != spell.spellgroup) + LimitFound = true; + else if(base1 < 0 && base1 == spell.spellgroup) + LimitFound = true; + break; + + + case SE_LimitCastingSkill: + LimitSpellSkill = true; + if(base1 == spell.skill) + SpellSkill_Found = true; + break; + + case SE_LimitClass: + //Do not use this limit more then once per spell. If multiple class, treat value like items would. + if (!PassLimitClass(base1, GetClass())) + LimitFound = true; + break; + + + //Handle Focus Effects + case SE_ImprovedDamage: + if (type == focusImprovedDamage && base1 > value) + value = base1; + break; + + case SE_ImprovedHeal: + if (type == focusImprovedHeal && base1 > value) + value = base1; + break; + + case SE_ReduceManaCost: + if (type == focusManaCost ) + value = base1; + break; + + case SE_IncreaseSpellHaste: + if (type == focusSpellHaste && base1 > value) + value = base1; + break; + + case SE_IncreaseSpellDuration: + if (type == focusSpellDuration && base1 > value) + value = base1; + break; + + case SE_SpellDurationIncByTic: + if (type == focusSpellDurByTic && base1 > value) + value = base1; + break; + + case SE_SwarmPetDuration: + if (type == focusSwarmPetDuration && base1 > value) + value = base1; + break; + + case SE_IncreaseRange: + if (type == focusRange && base1 > value) + value = base1; + break; + + case SE_ReduceReagentCost: + if (type == focusReagentCost && base1 > value) + value = base1; + break; + + case SE_PetPowerIncrease: + if (type == focusPetPower && base1 > value) + value = base1; + break; + + case SE_SpellResistReduction: + if (type == focusResistRate && base1 > value) + value = base1; + break; + + case SE_SpellHateMod: + if (type == focusSpellHateMod) + { + if(value != 0) + { + if(value > 0) + { + if(base1 > value) + { + value = base1; + } + } + else + { + if(base1 < value) + { + value = base1; + } + } + } + else + value = base1; + } + break; + + case SE_ReduceReuseTimer: + { + if(type == focusReduceRecastTime) + value = base1 / 1000; + + break; + } + + case SE_TriggerOnCast: + { + if(type == focusTriggerOnCast) + { + if(zone->random.Int(0, 100) <= base1){ + value = base2; + } + + else{ + value = 0; + LimitFound = true; + } + } + break; + } + case SE_FcSpellVulnerability: + { + if(type == focusSpellVulnerability) + { + value = base1; + } + break; + } + case SE_BlockNextSpellFocus: + { + if(type == focusBlockNextSpell) + { + if(zone->random.Int(1, 100) <= base1) + value = 1; + } + break; + } + case SE_FcTwincast: + { + if(type == focusTwincast) + { + 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); + + if(zone->random.Real(0, 1) <= ProcChance) + value = focus_id; + + else + value = 0; + } + break; + } + */ + case SE_FcDamageAmt: + { + if(type == focusFcDamageAmt) + value = base1; + + break; + } + + case SE_FcDamageAmtCrit: + { + if(type == focusFcDamageAmtCrit) + value = base1; + + break; + } + + case SE_FcDamageAmtIncoming: + { + if(type == focusFcDamageAmtIncoming) + value = base1; + + break; + } + + case SE_FcHealAmtIncoming: + if(type == focusFcHealAmtIncoming) + value = base1; + break; + + case SE_FcHealPctCritIncoming: + if (type == focusFcHealPctCritIncoming) + value = base1; + break; + + case SE_FcHealAmtCrit: + if(type == focusFcHealAmtCrit) + value = base1; + break; + + case SE_FcHealAmt: + if(type == focusFcHealAmt) + value = base1; + break; + + case SE_FcHealPctIncoming: + if(type == focusFcHealPctIncoming) + value = base1; + break; + + case SE_FcBaseEffects: + { + if (type == focusFcBaseEffects) + value = base1; + + break; + } + case SE_FcDamagePctCrit: + { + if(type == focusFcDamagePctCrit) + value = base1; + + break; + } + + case SE_FcIncreaseNumHits: + { + if(type == focusIncreaseNumHits) + value = base1; + + break; + } + } + + //Check for spell skill limits. + if ((LimitSpellSkill) && (!SpellSkill_Found)) { + return 0; + } + } + + if (LimitFound) { return 0; } @@ -6875,31 +6248,34 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } // AA Focus - if (aabonuses.FocusEffects[bottype]){ - //old aa - //int totalAAs = database.CountAAs(); - //int32 Total3 = 0; - //uint32 slots = 0; - //uint32 aa_AA = 0; - //uint32 aa_value = 0; - // - //for (int i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs - // std::map::iterator aa = botAAs.find(i); - // if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone - // aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table - // aa_value = aa->second.total_levels; //how many points in it - // if (aa_AA < 1 || aa_value < 1) - // continue; - // - // Total3 = CalcBotAAFocus(bottype, aa_AA, spell_id); - // if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { - // realTotal3 = Total3; - // } - // else if (Total3 < 0 && Total3 < realTotal3) { - // realTotal3 = Total3; - // } - // } - //} + if (aabonuses.FocusEffects[bottype]) { + int32 Total3 = 0; + uint32 slots = 0; + uint32 aa_AA = 0; + uint32 aa_value = 0; + + for(auto &aa : aa_ranks) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if(!ability) { + continue; + } + + aa_AA = ability->id; + aa_value = aa.second.first; + if (aa_AA < 1 || aa_value < 1) + continue; + + Total3 = CalcBotAAFocus(bottype, aa_AA, aa_value, spell_id); + if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { + realTotal3 = Total3; + } + else if (Total3 < 0 && Total3 < realTotal3) { + realTotal3 = Total3; + } + } } if(bottype == BotfocusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) @@ -8931,7 +8307,6 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { break; } - //aa old bonus += 0.05 * GetAA(aaAdvancedSpellCastingMastery); if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) @@ -9559,7 +8934,7 @@ void Bot::CalcBonuses() { GenerateBaseStats(); CalcItemBonuses(&itembonuses); CalcSpellBonuses(&spellbonuses); - GenerateAABonuses(&aabonuses); + CalcAABonuses(&aabonuses); SetAttackTimer(); CalcATK(); diff --git a/zone/bot.h b/zone/bot.h index 4a88c5f18..6103fa7f2 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -449,7 +449,6 @@ public: bool IsBotWISCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN); } bool CanHeal(); int GetRawACNoShield(int &shield_ac); - void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon); bool GetHasBeenSummoned() { return _hasBeenSummoned; } const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; } bool GetGroupMessagesOn() { return _groupMessagesOn; } @@ -561,7 +560,7 @@ protected: 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); - virtual int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id); + virtual int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id); virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client); virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); virtual float GetMaxMeleeRangeToTarget(Mob* target); @@ -642,12 +641,12 @@ private: uint8 _baseGender; // Bots gender. Necessary to preserve the original value otherwise it can be changed by illusions. // Class Methods + void LoadAAs(); int32 acmod(); void GenerateBaseStats(); void GenerateAppearance(); void GenerateArmorClass(); int32 GenerateBaseHitPoints(); - void GenerateAABonuses(StatBonuses* newbon); int32 GenerateBaseManaPoints(); void GenerateSpecialAttacks(); void SetBotID(uint32 botID); diff --git a/zone/client.h b/zone/client.h index e830edfa8..2689964f0 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1260,8 +1260,6 @@ protected: void AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); void CalcEdibleBonuses(StatBonuses* newbon); - void CalcAABonuses(StatBonuses* newbon); - void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon); void ProcessItemCaps(); void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true); bool client_data_loaded; diff --git a/zone/mob.h b/zone/mob.h index 3e4f5ea39..959c5e543 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -967,6 +967,8 @@ public: bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price); int GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in); void ExpendAlternateAdvancementCharge(uint32 aa_id); + void CalcAABonuses(StatBonuses* newbon); + void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon); protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); From d3280c9676ae24e2d3995c14b1badd7552232bed Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 16 Jun 2015 12:33:14 -0700 Subject: [PATCH 186/846] Removing old code, need to reimplement warcry and rampage still at least --- zone/aa.cpp | 51 ------------------------------------- zone/aa.h | 15 ----------- zone/attack.cpp | 8 ------ zone/client.h | 9 +------ zone/client_process.cpp | 37 ++++++++++++++------------- zone/command.cpp | 15 ++++++++--- zone/spell_effects.cpp | 56 ++++++++++++++++++++--------------------- zone/spells.cpp | 15 ++++++----- 8 files changed, 65 insertions(+), 141 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 1f0b5b086..766057e2f 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -440,48 +440,6 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) 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 > _maxaaEffectType) - 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 > _maxaaEffectType) - 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 > _maxaaEffectType) - 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::ResetAA() { RefundAA(); uint32 i; @@ -788,14 +746,6 @@ void Client::InspectBuffs(Client* Inspector, int Rank) Inspector->FastQueuePacket(&outapp); } -void Client::DurationRampage(uint32 duration) -{ - if(duration) { - m_epp.aa_effects |= 1 << (aaEffectRampage-1); - p_timers.Start(pTimerAAEffectStart + aaEffectRampage, duration); - } -} - void Client::RefundAA() { int refunded = 0; @@ -933,7 +883,6 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { void Client::SendAlternateAdvancementStats() { 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; diff --git a/zone/aa.h b/zone/aa.h index 0ee32c99a..76df0f388 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -23,21 +23,6 @@ typedef enum { aaActionFadingMemories = 16 } aaNonspellAction; -//use these for AAs which dont cast spells, yet need effects -//if this list grows beyond 32, more work is needed in *AAEffect -typedef enum { //AA Effect IDs - aaEffectMassGroupBuff = 1, //unused - Handled via spell effect. - aaEffectRampage, - aaEffectSharedHealth, - aaEffectFlamingArrows, - aaEffectFrostArrows, - aaEffectWarcry, - aaEffectLeechTouch, - aaEffectProjectIllusion, // unused - Handled via spell effect - _maxaaEffectType = 32 -} aaEffectType; - - enum { //leadership AA indexes groupAAMarkNPC = 0, groupAANPCHealth, diff --git a/zone/attack.cpp b/zone/attack.cpp index fda7837ab..864efa3e7 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3519,14 +3519,6 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons 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; diff --git a/zone/client.h b/zone/client.h index 2689964f0..034ff83b4 100644 --- a/zone/client.h +++ b/zone/client.h @@ -541,7 +541,6 @@ public: bool Flurry(); bool Rampage(); - void DurationRampage(uint32 duration); inline uint32 GetEXP() const { return m_pp.exp; } @@ -784,13 +783,7 @@ public: int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id); void SetAATitle(const char *Title); void SetTitleSuffix(const char *txt); - - //old AA Methods that are slated for removal - void MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing); - void EnableAAEffect(aaEffectType type, uint32 duration = 0); - void DisableAAEffect(aaEffectType type); - bool CheckAAEffect(aaEffectType type); - + void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing); int32 acmod(); // Item methods diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 4a16e7698..603636a82 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -391,12 +391,13 @@ bool Client::Process() { } else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP { - if(CheckAAEffect(aaEffectRampage)) - { - entity_list.AEAttack(this, 30); - } else { + //old aa + //if(CheckAAEffect(aaEffectRampage)) + //{ + // entity_list.AEAttack(this, 30); + //} else { Attack(auto_attack_target, MainPrimary); // Kaiyodo - added attacking hand to arguments - } + //} ItemInst *wpn = GetInv().GetItem(MainPrimary); TryWeaponProc(wpn, auto_attack_target, MainPrimary); @@ -406,11 +407,11 @@ bool Client::Process() { CheckIncreaseSkill(SkillDoubleAttack, auto_attack_target, -10); if(CheckDoubleAttack()) { //should we allow rampage on double attack? - if(CheckAAEffect(aaEffectRampage)) { - entity_list.AEAttack(this, 30); - } else { + //if(CheckAAEffect(aaEffectRampage)) { + // entity_list.AEAttack(this, 30); + //} else { Attack(auto_attack_target, MainPrimary, false); - } + //} } //triple attack: rangers, monks, warriors, berserkers over level 60 @@ -499,21 +500,21 @@ bool Client::Process() { float random = zone->random.Real(0, 1); CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10); if (random < DualWieldProbability){ // Max 78% of DW - if(CheckAAEffect(aaEffectRampage)) { - entity_list.AEAttack(this, 30, MainSecondary); - } else { + //if(CheckAAEffect(aaEffectRampage)) { + // entity_list.AEAttack(this, 30, MainSecondary); + //} else { Attack(auto_attack_target, MainSecondary); // Single attack with offhand - } + //} ItemInst *wpn = GetInv().GetItem(MainSecondary); TryWeaponProc(wpn, auto_attack_target, MainSecondary); if( CanThisClassDoubleAttack() && CheckDoubleAttack()) { - if(CheckAAEffect(aaEffectRampage)) { - entity_list.AEAttack(this, 30, MainSecondary); - } else { - if(auto_attack_target && auto_attack_target->GetHP() > -10) + //if(CheckAAEffect(aaEffectRampage)) { + // entity_list.AEAttack(this, 30, MainSecondary); + //} else { + // if(auto_attack_target && auto_attack_target->GetHP() > -10) Attack(auto_attack_target, MainSecondary); // Single attack with offhand - } + //} } } } diff --git a/zone/command.cpp b/zone/command.cpp index 16f50e7d7..ab2b4ad78 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5555,13 +5555,20 @@ void command_setaapts(Client *c, const Seperator *sep) else if(atoi(sep->arg[2]) <= 0 || atoi(sep->arg[2]) > 200) c->Message(0, "You must have a number greater than 0 for points and no more than 200."); else if(!strcasecmp(sep->arg[1], "group")) { - t->SetLeadershipEXP(atoi(sep->arg[2])*GROUP_EXP_PER_POINT, t->GetRaidEXP()); + t->GetPP().group_leadership_points = atoi(sep->arg[2]); + t->GetPP().group_leadership_exp = 0; + t->Message(MT_Experience, "Setting Group AA points to %u", t->GetPP().group_leadership_points); + t->SendLeadershipEXPUpdate(); } else if(!strcasecmp(sep->arg[1], "raid")) { - t->SetLeadershipEXP(t->GetGroupEXP(), atoi(sep->arg[2])*RAID_EXP_PER_POINT); + t->GetPP().raid_leadership_points = atoi(sep->arg[2]); + t->GetPP().raid_leadership_exp = 0; + t->Message(MT_Experience, "Setting Raid AA points to %u", t->GetPP().raid_leadership_points); + t->SendLeadershipEXPUpdate(); } else { - t->SetEXP(t->GetEXP(),t->GetMaxAAXP()*atoi(sep->arg[2]),false); + t->GetPP().aapoints = atoi(sep->arg[2]); + t->GetPP().expAA = 0; + t->Message(MT_Experience, "Setting personal AA points to %u", t->GetPP().aapoints); t->SendAlternateAdvancementStats(); - t->SendAlternateAdvancementTable(); } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a7c5643a1..3c0c8fad4 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -651,27 +651,28 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove group_id_caster = (GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (GetRaid()->GetGroup(CastToClient()) + 1); } } - if(group_id_caster){ - Group *g = entity_list.GetGroupByID(group_id_caster); - uint32 time = spell.base[i]*10; - if(g){ - for(int gi=0; gi < 6; gi++){ - if(g->members[gi] && g->members[gi]->IsClient()) - { - g->members[gi]->CastToClient()->EnableAAEffect(aaEffectWarcry , time); - if (g->members[gi]->GetID() != caster->GetID()) - g->members[gi]->Message(13, "You hear the war cry."); - else - Message(13, "You let loose a fierce war cry."); - } - } - } - } - - else{ - CastToClient()->EnableAAEffect(aaEffectWarcry , time); - Message(13, "You let loose a fierce war cry."); - } + //old aa + //if(group_id_caster){ + // Group *g = entity_list.GetGroupByID(group_id_caster); + // uint32 time = spell.base[i]*10; + // if(g){ + // for(int gi=0; gi < 6; gi++){ + // if(g->members[gi] && g->members[gi]->IsClient()) + // { + // g->members[gi]->CastToClient()->EnableAAEffect(aaEffectWarcry , time); + // if (g->members[gi]->GetID() != caster->GetID()) + // g->members[gi]->Message(13, "You hear the war cry."); + // else + // Message(13, "You let loose a fierce war cry."); + // } + // } + // } + //} + // + //else{ + // CastToClient()->EnableAAEffect(aaEffectWarcry , time); + // Message(13, "You let loose a fierce war cry."); + //} break; } @@ -2232,12 +2233,14 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_AEMelee: { + //old aa + #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Duration Rampage"); #endif - if (caster && caster->IsClient()) { // will tidy this up later so that NPCs can duration ramp from spells too - CastToClient()->DurationRampage(effect_value*12); - } + //if (caster && caster->IsClient()) { // will tidy this up later so that NPCs can duration ramp from spells too + // CastToClient()->DurationRampage(effect_value*12); + //} break; } @@ -3435,11 +3438,6 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) } } - // Check for non buff spell effects to fade - // AE melee effects - if (IsClient()) - CastToClient()->CheckAAEffect(aaEffectRampage); - for (int i = 0; i < EFFECT_COUNT; i++) { if (IsBlankSpellEffect(buff.spellid, i)) continue; diff --git a/zone/spells.cpp b/zone/spells.cpp index ea4d1068b..3ea0a5ddd 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4124,14 +4124,13 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) } return true; } - - else if (IsClient() && CastToClient()->CheckAAEffect(aaEffectWarcry)) - { - Message(13, "Your are immune to fear."); - Log.Out(Logs::Detail, Logs::Spells, "Clients has WarCry effect, immune to fear!"); - caster->Message_StringID(MT_Shout, IMMUNE_FEAR); - return true; - } + //else if (IsClient() && CastToClient()->CheckAAEffect(aaEffectWarcry)) //old aa + //{ + // Message(13, "Your are immune to fear."); + // Log.Out(Logs::Detail, Logs::Spells, "Clients has WarCry effect, immune to fear!"); + // caster->Message_StringID(MT_Shout, IMMUNE_FEAR); + // return true; + //} } if(IsCharmSpell(spell_id)) From f4c22d711144cf339721dc1606c3c1132386fcef Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 16 Jun 2015 17:10:47 -0400 Subject: [PATCH 187/846] Fix double riposte --- zone/attack.cpp | 53 ++++++++++++++++++++++++++++++------------------ zone/bonuses.cpp | 1 + 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 864efa3e7..146bcdce6 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4412,42 +4412,55 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) return false; } -void Mob::DoRiposte(Mob* defender) { +void Mob::DoRiposte(Mob *defender) +{ Log.Out(Logs::Detail, Logs::Combat, "Preforming a riposte"); if (!defender) return; defender->Attack(this, MainPrimary, true); - if (HasDied()) return; + if (HasDied()) + return; - int32 DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] + - defender->spellbonuses.GiveDoubleRiposte[0] + - defender->itembonuses.GiveDoubleRiposte[0]; + // this effect isn't used on live? See no AAs or spells + int32 DoubleRipChance = defender->aabonuses.DoubleRiposte + defender->spellbonuses.DoubleRiposte + + defender->itembonuses.DoubleRiposte; - DoubleRipChance = defender->aabonuses.DoubleRiposte + - defender->spellbonuses.DoubleRiposte + - defender->itembonuses.DoubleRiposte; - - //Live AA - Double Riposte - if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) { - Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposed (%d percent chance)", DoubleRipChance); + 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); - if (HasDied()) return; + 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[0] + defender->spellbonuses.GiveDoubleRiposte[0] + + defender->itembonuses.GiveDoubleRiposte[0]; + + // Live AA - Double Riposte + if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) { + Log.Out(Logs::Detail, Logs::Combat, + "Preforming a double riposted from SE_GiveDoubleRiposte base1 == 0 (%d percent chance)", + DoubleRipChance); + defender->Attack(this, MainPrimary, true); + if (HasDied()) + return; + } + + // Double Riposte effect, allows for a chance to do RIPOSTE with a skill specific 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 && zone->random.Roll(DoubleRipChance)) { - Log.Out(Logs::Detail, Logs::Combat, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance); + if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) { + Log.Out(Logs::Detail, Logs::Combat, "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); + defender->CastToClient()->DoClassAttacks(this, defender->aabonuses.GiveDoubleRiposte[2], true); } } @@ -4678,10 +4691,10 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui ProcMod = static_cast(base2); } else if(effect_id == SE_LimitToSkill && base1 <= HIGHEST_SKILL) { - + if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); - + if (zone->random.Roll(final_chance)) { ExecWeaponProc(nullptr, proc_spell_id, on); CanProc = false; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index c19755aae..e90f9626a 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1156,6 +1156,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_DoubleRiposte: { newbon->DoubleRiposte += base1; + break; } case SE_GiveDoubleRiposte: { From 60f2e312404e679fd432aa48bdc0bf76042dc87f Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 16 Jun 2015 21:43:51 -0700 Subject: [PATCH 188/846] Retooled how cooldowns work so they should be more consistent with how the client shows them --- zone/aa.cpp | 14 ++------------ zone/spells.cpp | 9 +++------ 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 766057e2f..a99a81ada 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1137,26 +1137,16 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { // 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), 10, -1, -1, spells[rank->spell].ResistDiff, false)) { - //Reset on failed cast - SendAlternateAdvancementTimer(rank->spell_type, 0, -1); - Message_StringID(15, ABILITY_FAILED); - p_timers.Clear(&database, rank->spell_type + pTimerAAStart); return; } + CastToClient()->GetPTimers().Start(rank->spell_type, cooldown); + SendAlternateAdvancementTimer(rank->spell_type, 0, 0); ExpendAlternateAdvancementCharge(ability->id); } else { if(!CastSpell(rank->spell, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, 1, nullptr, ability->id)) { - //Reset on failed cast - SendAlternateAdvancementTimer(rank->spell_type, 0, -1); - Message_StringID(15, ABILITY_FAILED); - p_timers.Clear(&database, rank->spell_type + pTimerAAStart); return; } } - - if(cooldown > 0) { - SendAlternateAdvancementTimer(rank->spell_type, 0, 0); - } } int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) { diff --git a/zone/spells.cpp b/zone/spells.cpp index 3ea0a5ddd..5002e8104 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -819,12 +819,6 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot); } - if(casting_spell_type == 1 && IsClient()) { //Rest AA Timer on failed cast - CastToClient()->SendAlternateAdvancementTimer(casting_spell_timer - pTimerAAStart, 0, -1); - CastToClient()->Message_StringID(15, ABILITY_FAILED); - CastToClient()->GetPTimers().Clear(&database, casting_spell_timer); - } - ZeroCastingVars(); // resets all the state keeping stuff Log.Out(Logs::Detail, Logs::Spells, "Spell %d has been interrupted.", spellid); @@ -2282,6 +2276,9 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 //aa new todo: aa expendable charges here CastToClient()->GetPTimers().Start(casting_spell_timer, casting_spell_timer_duration); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Setting custom reuse timer %d to %d", spell_id, casting_spell_timer, casting_spell_timer_duration); + if(casting_spell_aa_id) { + CastToClient()->SendAlternateAdvancementTimer(casting_spell_timer - pTimerAAStart, 0, 0); + } } else if(spells[spell_id].recast_time > 1000 && !spells[spell_id].IsDisciplineBuff) { int recast = spells[spell_id].recast_time/1000; From c445f631869648dfad0bc716ef5a706f8a4ee3df Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 16 Jun 2015 23:41:46 -0700 Subject: [PATCH 189/846] Okay timers now work right, for real this time --- zone/aa.cpp | 5 ++++- zone/lua_mob.cpp | 2 +- zone/mob.cpp | 1 - zone/mob.h | 4 ++-- zone/mob_ai.cpp | 2 +- zone/perl_mob.cpp | 4 ++-- zone/spells.cpp | 39 +++++++++++++++++++++++---------------- 7 files changed, 33 insertions(+), 24 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index a99a81ada..21e1de1b2 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1143,10 +1143,13 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { SendAlternateAdvancementTimer(rank->spell_type, 0, 0); ExpendAlternateAdvancementCharge(ability->id); } else { - if(!CastSpell(rank->spell, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, 1, nullptr, ability->id)) { + if(!CastSpell(rank->spell, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) { return; } } + + CastToClient()->GetPTimers().Start(rank->spell_type + pTimerAAStart, cooldown); + SendAlternateAdvancementTimer(rank->spell_type, 0, 0); } int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) { diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index f4d7d64cb..11124d50f 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -790,7 +790,7 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, in int16 res = resist_adjust; return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast(item_slot), - static_cast(timer), static_cast(timer_duration), 0, &res); + static_cast(timer), static_cast(timer_duration), &res); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target) { diff --git a/zone/mob.cpp b/zone/mob.cpp index 35b0d62d2..4eb87f7ad 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -307,7 +307,6 @@ Mob::Mob(const char* in_name, casting_spell_id = 0; casting_spell_timer = 0; casting_spell_timer_duration = 0; - casting_spell_type = 0; casting_spell_inventory_slot = 0; casting_spell_aa_id = 0; target = 0; diff --git a/zone/mob.h b/zone/mob.h index 959c5e543..20ec928e7 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -222,11 +222,11 @@ public: virtual void SpellProcess(); 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, uint32 item_slot = 0xFFFFFFFF, - uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr, + 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, 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, + 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, uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 650ba350c..fb6714087 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -342,7 +342,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, 0, &(AIspells[i].resist_adjust)); + return CastSpell(AIspells[i].spellid, tar->GetID(), 1, 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) { diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index f5ef80a4c..80ca97484 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -3998,9 +3998,9 @@ XS(XS_Mob_CastSpell) } if (resist_adjust == 0)//If you do not pass resist adjust as nullptr it will ignore the spells default resist adjust - THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0); + THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0); else - THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, &resist_adjust); + THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, &resist_adjust); } XSRETURN_EMPTY; } diff --git a/zone/spells.cpp b/zone/spells.cpp index 5002e8104..310e2bd01 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -146,7 +146,7 @@ void NPC::SpellProcess() // to allow procs to work bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, - uint32 timer, uint32 timer_duration, uint32 type, int16 *resist_adjust, + 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", @@ -319,11 +319,11 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, if(resist_adjust) { - return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, type, *resist_adjust, aa_id)); + return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, *resist_adjust, aa_id)); } else { - return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, type, spells[spell_id].ResistDiff, aa_id)); + return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, spells[spell_id].ResistDiff, aa_id)); } } @@ -337,7 +337,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, // bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, - uint32 item_slot, uint32 timer, uint32 timer_duration, uint32 type, + uint32 item_slot, uint32 timer, uint32 timer_duration, int16 resist_adjust, uint32 aa_id) { Mob* pMob = nullptr; @@ -363,7 +363,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, casting_spell_timer_duration = timer_duration; } casting_spell_aa_id = aa_id; - casting_spell_type = type; 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); @@ -785,7 +784,6 @@ void Mob::ZeroCastingVars() casting_spell_inventory_slot = 0; casting_spell_timer = 0; casting_spell_timer_duration = 0; - casting_spell_type = 0; casting_spell_resist_adjust = 0; casting_spell_checks = false; casting_spell_aa_id = 0; @@ -819,6 +817,15 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot); } + if(casting_spell_aa_id && IsClient()) { //Rest AA Timer on failed cast + AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id); + if(rank) { + CastToClient()->SendAlternateAdvancementTimer(rank->spell_type, 0, 0x7fffffff); + CastToClient()->Message_StringID(15, ABILITY_FAILED); + CastToClient()->GetPTimers().Clear(&database, rank->spell_type + pTimerAAStart); + } + } + ZeroCastingVars(); // resets all the state keeping stuff Log.Out(Logs::Detail, Logs::Spells, "Spell %d has been interrupted.", spellid); @@ -2075,7 +2082,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 else if(!SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, false, level_override)) { if(IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) { // Prevent mana usage/timers being set for beneficial buffs - if(casting_spell_type == 1) + if(casting_spell_aa_id) InterruptSpell(); return false; } @@ -2271,14 +2278,18 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 //set our reuse timer on long ass reuse_time spells... if(IsClient() && !isproc) { - if(spell_id == casting_spell_id && casting_spell_timer != 0xFFFFFFFF) + if(casting_spell_aa_id) { + AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id); + + if(rank && rank->base_ability) { + ExpendAlternateAdvancementCharge(rank->base_ability->id); + } + } + else if(spell_id == casting_spell_id && casting_spell_timer != 0xFFFFFFFF) { //aa new todo: aa expendable charges here CastToClient()->GetPTimers().Start(casting_spell_timer, casting_spell_timer_duration); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Setting custom reuse timer %d to %d", spell_id, casting_spell_timer, casting_spell_timer_duration); - if(casting_spell_aa_id) { - CastToClient()->SendAlternateAdvancementTimer(casting_spell_timer - pTimerAAStart, 0, 0); - } } else if(spells[spell_id].recast_time > 1000 && !spells[spell_id].IsDisciplineBuff) { int recast = spells[spell_id].recast_time/1000; @@ -2297,10 +2308,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Setting long reuse timer to %d s (orig %d)", spell_id, recast, spells[spell_id].recast_time); CastToClient()->GetPTimers().Start(pTimerSpellStart + spell_id, recast); } - - if(casting_spell_aa_id) { - ExpendAlternateAdvancementCharge(casting_spell_aa_id); - } } if(IsClient() && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT) || (slot == TARGET_RING_SPELL_SLOT))) @@ -3758,7 +3765,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r // if SpellEffect returned false there's a problem applying the // spell. It's most likely a buff that can't stack. Log.Out(Logs::Detail, Logs::Spells, "Spell %d could not apply its effects %s -> %s\n", spell_id, GetName(), spelltar->GetName()); - if(casting_spell_type != 1) // AA is handled differently + if(casting_spell_aa_id) Message_StringID(MT_SpellFailure, SPELL_NO_HOLD); safe_delete(action_packet); return false; From 0447321d92f00803ab3bc3611e55f12987a02d33 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 17 Jun 2015 02:47:05 -0400 Subject: [PATCH 190/846] Implement songcap needed for the AA revamp Added rule Character:UseSpellFileSongCap defaulted to true since most servers will probably be updating everything. --- common/ruletypes.h | 1 + common/shareddb.cpp | 5 +++-- common/spdat.h | 4 ++-- zone/client_mods.cpp | 11 ++++++++--- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 9a36b77f4..f066b9115 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -99,6 +99,7 @@ RULE_BOOL ( Character, EnableXTargetting, true) // Enable Extended Targetting Wi 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. +RULE_BOOL ( Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. RULE_INT ( Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type RULE_REAL(Character, EnvironmentDamageMulipliter, 1) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index aa4924665..c9106ea04 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1682,6 +1682,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].not_extendable = atoi(row[197]) != 0; sp[tempid].suspendable = atoi(row[200]) != 0; sp[tempid].viral_range = atoi(row[201]); + sp[tempid].songcap = atoi(row[202]); sp[tempid].no_block = atoi(row[205]); sp[tempid].spellgroup=atoi(row[207]); sp[tempid].rank = atoi(row[208]); @@ -2021,7 +2022,7 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) { std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id); - auto results = QueryDatabase(query); + auto results = QueryDatabase(query); auto row = results.begin(); memset(message, '\0', sizeof(InspectMessage_Struct)); for (auto row = results.begin(); row != results.end(); ++row) { @@ -2031,7 +2032,7 @@ void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMes void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message) { 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); + auto results = QueryDatabase(query); } void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) { diff --git a/common/spdat.h b/common/spdat.h index 24e982aee..c8e039f15 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -735,8 +735,8 @@ struct SPDat_Spell_Struct /* 198- 199 */ /* 200 */ bool suspendable; // buff is suspended in suspended buff zones /* 201 */ int viral_range; -/* 202 */ -/* 203 */ //int songcap; // individual song cap (how live currently does it, not implemented) +/* 202 */ int songcap; // individual song cap +/* 203 */ /* 204 */ /* 205 */ bool no_block; /* 206 */ diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 56a22de9a..76ce5195c 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1978,7 +1978,11 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const return 10; uint32 effectmod = 10; - int effectmodcap = RuleI(Character, BaseInstrumentSoftCap); + int effectmodcap = 0; + if (RuleB(Character, UseSpellFileSongCap)) + effectmodcap = spells[spell_id].songcap / 10; + else + effectmodcap = RuleI(Character, BaseInstrumentSoftCap); // this should never use spell modifiers... // if a spell grants better modifers, they are copied into the item mods // because the spells are supposed to act just like having the intrument. @@ -2048,10 +2052,11 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const effectmod = 10; return effectmod; } - effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; + if (!RuleB(Character, UseSpellFileSongCap)) + effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; if (effectmod < 10) effectmod = 10; - if (effectmod > effectmodcap) + if (effectmodcap && effectmod > effectmodcap) // if the cap is calculated to be 0 using new rules, no cap. effectmod = effectmodcap; Log.Out(Logs::Detail, Logs::Spells, "%s::GetInstrumentMod() spell=%d mod=%d modcap=%d\n", GetName(), spell_id, effectmod, effectmodcap); From 065363480f14c88c5604ea97c692e65e21d82f83 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 17 Jun 2015 12:05:09 -0700 Subject: [PATCH 191/846] Added AA grant to quest system, fixed a bug here or there noticed incrementaa needs to be fixed or removed --- zone/aa.cpp | 55 ++++++++++++++++++++++++++--- zone/aa_ability.h | 1 - zone/aa_rank.h | 1 - zone/client.cpp | 4 +++ zone/lua_mob.cpp | 24 +++++++++++++ zone/lua_mob.h | 4 +++ zone/mob.h | 1 + zone/perl_mob.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++++-- zone/spells.cpp | 2 +- 9 files changed, 171 insertions(+), 11 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 21e1de1b2..741a15aff 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1015,6 +1015,7 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { NotifyNewTitlesAvailable(); } +//need to rewrite this void Client::IncrementAlternateAdvancementRank(int rank_id) { AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); if(!rank) { @@ -1139,8 +1140,6 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), 10, -1, -1, spells[rank->spell].ResistDiff, false)) { return; } - CastToClient()->GetPTimers().Start(rank->spell_type, cooldown); - SendAlternateAdvancementTimer(rank->spell_type, 0, 0); ExpendAlternateAdvancementCharge(ability->id); } else { if(!CastSpell(rank->spell, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) { @@ -1312,6 +1311,8 @@ uint32 Mob::GetAAByAAID(uint32 aa_id, uint32 *charges) const { return iter->second.first; } } + + return 0; } bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) { @@ -1474,9 +1475,14 @@ void Zone::LoadAlternateAdvancement() { current->total_cost = current->cost + current->prev->total_cost; } else { + current->prev_id = -1; current->total_cost = current->cost; } + if(!current->next) { + current->next_id = -1; + } + i++; current = current->next; } @@ -1490,7 +1496,8 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapprev_id = atoi(row[10]); rank->next_id = atoi(row[11]); rank->expansion = atoi(row[12]); - rank->account_time_required = atoul(row[13]); rank->base_ability = nullptr; rank->total_cost = 0; rank->next = nullptr; @@ -1606,3 +1612,42 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapGetAlternateAdvancementAbilityAndRank(aa_id, points); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if(!ability) { + return; + } + + if(ability->charges > 0) { + return; + } + + if(!ability->grant_only) { + return; + } + + if(!CanUseAlternateAdvancementRank(rank)) { + return; + } + + SetAA(ability->first_rank_id, rank->current_value, 0); + + if(IsClient()) { + Client *c = CastToClient(); + + if(rank->next) { + c->SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value); + } + + c->SendAlternateAdvancementPoints(); + c->SendAlternateAdvancementStats(); + c->CalcBonuses(); + } +} \ No newline at end of file diff --git a/zone/aa_ability.h b/zone/aa_ability.h index ba152fb06..4a2d41f3e 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -39,7 +39,6 @@ public: ~Ability() { } Rank *GetMaxRank(); - Rank *GetRankByLevel(int level); Rank *GetRankByPointsSpent(int current_level); int GetMaxLevel(Mob *who); diff --git a/zone/aa_rank.h b/zone/aa_rank.h index a824f2c82..977a07680 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -45,7 +45,6 @@ public: Rank *next; int current_value; int expansion; - uint32 account_time_required; int total_cost; Ability *base_ability; std::vector effects; diff --git a/zone/client.cpp b/zone/client.cpp index 5ef3e84e5..0ce7292ef 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -533,6 +533,10 @@ bool Client::SaveAA() { if(!ability) continue; + if(ability->grant_only) { + continue; + } + if(rank.second.first > 0) { AA::Rank *r = ability->GetRankByPointsSpent(rank.second.first); diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 11124d50f..31719d364 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1195,6 +1195,26 @@ int Lua_Mob::GetAA(int id) { return self->GetAA(id); } +int Lua_Mob::GetAAByAAID(int id) { + Lua_Safe_Call_Int(); + return self->GetAAByAAID(id); +} + +bool Lua_Mob::SetAA(int rank_id, int new_value) { + Lua_Safe_Call_Bool(); + return self->SetAA(rank_id, new_value); +} + +bool Lua_Mob::SetAA(int rank_id, int new_value, int charges) { + Lua_Safe_Call_Bool(); + return self->SetAA(rank_id, new_value, charges); +} + +void Lua_Mob::GrantAlternateAdvancementAbility(int aa_id, int points) { + Lua_Safe_Call_Void(); + self->GrantAlternateAdvancementAbility(aa_id, points); +} + bool Lua_Mob::DivineAura() { Lua_Safe_Call_Bool(); return self->DivineAura(); @@ -2074,6 +2094,10 @@ luabind::scope lua_register_mob() { .def("CheckHealAggroAmount", (int(Lua_Mob::*)(int))&Lua_Mob::CheckHealAggroAmount) .def("CheckHealAggroAmount", (int(Lua_Mob::*)(int,uint32))&Lua_Mob::CheckHealAggroAmount) .def("GetAA", (int(Lua_Mob::*)(int))&Lua_Mob::GetAA) + .def("GetAAByAAID", (int(Lua_Mob::*)(int))&Lua_Mob::GetAAByAAID) + .def("SetAA", (bool(Lua_Mob::*)(int,int))&Lua_Mob::SetAA) + .def("SetAA", (bool(Lua_Mob::*)(int,int,int))&Lua_Mob::SetAA) + .def("GrantAlternateAdvancementAbility", (void(Lua_Mob::*)(int, int))&Lua_Mob::GrantAlternateAdvancementAbility) .def("DivineAura", (bool(Lua_Mob::*)(void))&Lua_Mob::DivineAura) .def("SetOOCRegen", (void(Lua_Mob::*)(int))&Lua_Mob::SetOOCRegen) .def("GetEntityVariable", (const char*(Lua_Mob::*)(const char*))&Lua_Mob::GetEntityVariable) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 023fedd2a..914f46c5d 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -249,6 +249,10 @@ public: int CheckHealAggroAmount(int spell_id); int CheckHealAggroAmount(int spell_id, uint32 heal_possible); int GetAA(int id); + int GetAAByAAID(int id); + bool SetAA(int rank_id, int new_value); + bool SetAA(int rank_id, int new_value, int charges); + void GrantAlternateAdvancementAbility(int aa_id, int points); bool DivineAura(); void SetOOCRegen(int regen); const char* GetEntityVariable(const char *name); diff --git a/zone/mob.h b/zone/mob.h index 20ec928e7..1c3d7ab15 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -969,6 +969,7 @@ public: void ExpendAlternateAdvancementCharge(uint32 aa_id); void CalcAABonuses(StatBonuses* newbon); void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon); + void GrantAlternateAdvancementAbility(int aa_id, int points); protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 80ca97484..612d9f868 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -6360,12 +6360,12 @@ XS(XS_Mob_GetAA) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: Mob::GetAA(THIS, aa_id)"); + Perl_croak(aTHX_ "Usage: Mob::GetAA(THIS, rank_id)"); { Mob * THIS; uint32 RETVAL; dXSTARG; - uint32 aa_id = (uint32)SvUV(ST(1)); + uint32 rank_id = (uint32)SvUV(ST(1)); if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -6376,12 +6376,93 @@ XS(XS_Mob_GetAA) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->GetAA(aa_id); + RETVAL = THIS->GetAA(rank_id); XSprePUSH; PUSHu((UV)RETVAL); } XSRETURN(1); } +XS(XS_Mob_GetAAByAAID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_GetAAByAAID) +{ + dXSARGS; + if(items != 2) + Perl_croak(aTHX_ "Usage: Mob::GetAAByAAID(THIS, aa_id)"); + { + Mob * THIS; + uint32 RETVAL; + dXSTARG; + uint32 aa_id = (uint32)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."); + + RETVAL = THIS->GetAAByAAID(aa_id); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_SetAA); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_SetAA) +{ + dXSARGS; + if(items < 3 || items > 4) + Perl_croak(aTHX_ "Usage: Mob::SetAA(THIS, aa_id, points, [charges])"); + { + Mob * THIS; + bool RETVAL; + int aa_id = (int)SvIV(ST(1)); + int points = (int)SvIV(ST(2)); + int charges = (items == 4) ? (int)SvIV(ST(3)) : 0; + + 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."); + + RETVAL = THIS->SetAA(aa_id, points, charges); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_GrantAlternateAdvancementAbility); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_GrantAlternateAdvancementAbility) +{ + dXSARGS; + if(items != 3) + Perl_croak(aTHX_ "Usage: Mob::GrantAlternateAdvancementAbility(THIS, aa_id, points)"); + { + Mob * THIS; + int aa_id = (int)SvIV(ST(1)); + int points = (int)SvIV(ST(2)); + + 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."); + + THIS->GrantAlternateAdvancementAbility(aa_id, points); + } + XSRETURN_EMPTY; +} + XS(XS_Mob_DivineAura); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_DivineAura) { @@ -8625,6 +8706,9 @@ XS(boot_Mob) newXSproto(strcpy(buf, "CheckAggroAmount"), XS_Mob_CheckAggroAmount, file, "$$"); newXSproto(strcpy(buf, "CheckHealAggroAmount"), XS_Mob_CheckHealAggroAmount, file, "$$"); newXSproto(strcpy(buf, "GetAA"), XS_Mob_GetAA, file, "$$"); + newXSproto(strcpy(buf, "GetAAByAAID"), XS_Mob_GetAAByAAID, file, "$$"); + newXSproto(strcpy(buf, "SetAA"), XS_Mob_SetAA, file, "$$$;$"); + newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Mob_GrantAlternateAdvancementAbility, file, "$$$"); newXSproto(strcpy(buf, "DivineAura"), XS_Mob_DivineAura, file, "$"); newXSproto(strcpy(buf, "AddFeignMemory"), XS_Mob_AddFeignMemory, file, "$$"); newXSproto(strcpy(buf, "RemoveFromFeignMemory"), XS_Mob_RemoveFromFeignMemory, file, "$$"); diff --git a/zone/spells.cpp b/zone/spells.cpp index 310e2bd01..ec872d1c9 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -820,8 +820,8 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) if(casting_spell_aa_id && IsClient()) { //Rest AA Timer on failed cast AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id); if(rank) { + CastToClient()->Message_StringID(MT_SpellFailure, ABILITY_FAILED); CastToClient()->SendAlternateAdvancementTimer(rank->spell_type, 0, 0x7fffffff); - CastToClient()->Message_StringID(15, ABILITY_FAILED); CastToClient()->GetPTimers().Clear(&database, rank->spell_type + pTimerAAStart); } } From de81850dd9f471fa897206d099dc3b8615b9cf81 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Thu, 18 Jun 2015 23:42:59 -0400 Subject: [PATCH 192/846] Fixed possible bot crashes due to nullptr conflict. --- zone/attack.cpp | 2 +- zone/mob_ai.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index a229f197e..ffdb0ec41 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4249,7 +4249,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack } #ifdef BOTS - if (this->IsPet() && this->GetOwner()->IsBot()) { + if (this->IsPet() && this->GetOwner() && this->GetOwner()->IsBot()) { this->TryPetCriticalHit(defender,skill,damage); return; } diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 650ba350c..045c2cb75 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1105,7 +1105,7 @@ void Mob::AI_Process() { } #ifdef BOTS - if (IsPet() && GetOwner()->IsBot() && target == GetOwner()) + if (IsPet() && GetOwner() && GetOwner()->IsBot() && target == GetOwner()) { // this blocks all pet attacks against owner..bot pet test (copied above check) RemoveFromHateList(this); From 56e064751baac7e17ebc7f6f11089306cdebe687 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 19 Jun 2015 01:42:01 -0400 Subject: [PATCH 193/846] Fixed more possible nullptr related bot crashes. --- zone/bot.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 8b3741443..bb711edbf 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -11359,7 +11359,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { // pull if(!strcasecmp(sep->arg[1], "pull")) { Mob *target = c->GetTarget(); - if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner()->IsBot())) + if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { c->Message(15, "You must select a monster"); return; @@ -12381,7 +12381,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "ai") && !strcasecmp(sep->arg[2], "mez")) { Mob *target = c->GetTarget(); - if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner()->IsBot())) + if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { c->Message(15, "You must select a monster"); return; @@ -12631,7 +12631,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { { Mob *target = c->GetTarget(); - if(target == nullptr || target->IsClient() || target->IsBot() || target->IsPet() && target->GetOwner()->IsBot()) + 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()) { @@ -12683,7 +12683,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "charm")) { Mob *target = c->GetTarget(); - if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner()->IsBot())) + if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { c->Message(15, "You must select a monster"); return; @@ -12796,7 +12796,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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()->IsBot())) + if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { c->Message(15, "You must select a monster"); return; From 08f8e2e55c5edbf0464159301d9fe7c67e6b97c4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 19 Jun 2015 01:56:58 -0400 Subject: [PATCH 194/846] Fix some RoF2 ops --- utils/patches/patch_RoF2.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 1ebf05442..49f5f28b3 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -295,8 +295,8 @@ OP_MarkNPC=0x1fb5 OP_MarkRaidNPC=0x5a58 #unimplemented OP_ClearNPCMarks=0x2003 OP_ClearRaidNPCMarks=0x20d3 #unimplemented -OP_DelegateAbility=0x4c9d -OP_SetGroupTarget=0x026 +OP_DelegateAbility=0x76b8 +OP_SetGroupTarget=0x2814 OP_Charm=0x5d92 OP_Stun=0x36a4 OP_SendFindableNPCs=0x4613 From 0dcf34d62b10f2ed38b001dc3d59c9e145ae981e Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 19 Jun 2015 04:06:41 -0400 Subject: [PATCH 195/846] Bot changes. - Added support for Powersource. - Changed all messages to group messages (Defaults to say if they are not in a group) --- zone/bot.cpp | 687 ++++++++++++++++++++++++++------------------------- 1 file changed, 344 insertions(+), 343 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index bb711edbf..c27ae20ce 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -270,7 +270,7 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) { //archerbot->SendWearChange(MATERIAL_PRIMARY); //archerbot->SendWearChange(MATERIAL_SECONDARY); SetAttackTimer(); - Say("My blade is ready."); + BotGroupSay(this, "My blade is ready."); } else { //archerbot->SendWearChange(MATERIAL_PRIMARY); @@ -281,11 +281,11 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) { BotAddEquipItem(MainAmmo, GetBotItemBySlot(MainAmmo)); BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainRange)); SetAttackTimer(); - Say("My bow is true and ready."); + BotGroupSay(this, "My bow is true and ready."); } } else { - Say("I don't know how to use a bow."); + BotGroupSay(this, "I don't know how to use a bow."); } } @@ -4196,10 +4196,10 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { } 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 color = atoul(row[3]); + int16 slot_id = atoi(row[0]); + uint32 item_id = atoi(row[1]); + uint16 charges = atoi(row[2]); + uint32 color = atoul(row[3]); uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoul(row[4]); aug[1] = (uint32)atoul(row[5]); @@ -4216,13 +4216,13 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { int16 put_slot_id = INVALID_INDEX; - if (instnodrop || ((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) && inst->GetItem()->Attuneable)) + if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == 9999) && inst->GetItem()->Attuneable)) inst->SetAttuned(true); if (color > 0) inst->SetColor(color); - if (charges==255) + if (charges == 255) inst->SetCharges(-1); else inst->SetCharges(charges); @@ -5650,7 +5650,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli uint8 charges[MAX_SLOT_ID] = {0}; bool botCanWear[MAX_SLOT_ID] = {0}; - for(int16 i=beginSlotID; i<=endSlotID; ++i) { + for(int16 i = beginSlotID; i <= endSlotID; ++i) { bool BotCanWear = false; bool UpdateClient = false; bool already_returned = false; @@ -5690,13 +5690,16 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli botCanWear[i] = BotCanWear; ItemInst* swap_item = nullptr; - const char* equipped[EmuConstants::EQUIPMENT_SIZE] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + 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" }; + "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; ++j) { + for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= (EmuConstants::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { + if (j == 22) + j = 9999; + how_many_slots++; if(!GetBotItem(j)) { if(j == MainPrimary) { @@ -5726,7 +5729,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli success = true; } else { - Say("I can't Dual Wield yet."); + BotGroupSay(this, "I can't Dual Wield yet."); --how_many_slots; } } @@ -5753,8 +5756,11 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } if(!success) { - for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= EmuConstants::EQUIPMENT_END; ++j) { + for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= (EmuConstants::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) { @@ -5796,7 +5802,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } else { botCanWear[i] = false; - Say("I can't Dual Wield yet."); + BotGroupSay(this, "I can't Dual Wield yet."); } } else { @@ -5842,14 +5848,14 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } const Item_Struct* item2 = 0; - for(int y=beginSlotID; y<=endSlotID; ++y) { + for(int y = beginSlotID; y <= endSlotID; ++y) { item2 = database.GetItem(items[y]); if(item2) { if(botCanWear[y]) { - Say("Thank you for the %s, %s.", item2->Name, client->GetName()); + BotGroupSay(this, "Thank you for the %s, %s!", item2->Name, client->GetName()); } else { - Say("I can't use this %s!", item2->Name); + BotGroupSay(this, "I can't use this %s!", item2->Name); } } } @@ -7752,7 +7758,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { if(inst) botpiercer = inst->GetItem(); if(!botpiercer || (botpiercer->ItemType != ItemType1HPiercing)) { - Say("I can't backstab with this weapon!"); + BotGroupSay(this, "I can't backstab with this weapon!"); return; } @@ -7963,7 +7969,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { //Only taunt if we are not top on target's hate list //This ensures we have taunt available to regain aggro if needed if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { - Say("Taunting %s", target->GetCleanName()); + BotGroupSay(this, "Taunting %s", target->GetCleanName()); Taunt(target->CastToNPC(), false); taunt_timer.Start(TauntReuseTime * 1000); } @@ -9538,7 +9544,7 @@ bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 s //} if(isMainGroupMGB && (GetClass() != BARD)) { - Say("MGB %s", spells[spell_id].name); + BotGroupSay(this, "MGB %s", spells[spell_id].name); SpellOnTarget(spell_id, this); entity_list.AESpell(this, this, spell_id, true); } @@ -10554,11 +10560,11 @@ void Bot::BotGroupOrderFollow(Group* group, Client* client) { if(group->IsLeader(botGroupMember) && botGroupMember->GetBotOwner()) { botGroupMember->SetFollowID(botGroupMember->GetBotOwner()->GetID()); if(botGroupMember->GetBotOwner()) - botGroupMember->Say("Following %s.", botGroupMember->GetBotOwner()->GetName()); + botGroupMember->BotGroupSay(botGroupMember, "Following %s.", botGroupMember->GetBotOwner()->GetName()); } else { botGroupMember->SetFollowID(groupLeader->GetID()); - botGroupMember->Say("Following %s.", groupLeader->GetCleanName()); + botGroupMember->BotGroupSay(botGroupMember, "Following %s.", groupLeader->GetCleanName()); } botGroupMember->WipeHateList(); @@ -10582,7 +10588,7 @@ void Bot::BotGroupOrderGuard(Group* group, Client* client) { if(botGroupMember && botGroupMember->GetBotOwnerCharacterID() == client->CharacterID()) { botGroupMember->SetFollowID(0); - botGroupMember->Say("Guarding here."); + botGroupMember->BotGroupSay(botGroupMember, "Guarding here."); botGroupMember->WipeHateList(); @@ -10817,8 +10823,8 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) { const Item_Struct* itemtmp = 0; - for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { - const ItemInst* item = GetBotItem(i); + for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { + const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); if(item) { AddItemBonuses(item, newbon); } @@ -11262,9 +11268,7 @@ void Bot::CalcBotStats(bool showtext) { } bool Bot::CheckLoreConflict(const Item_Struct* item) { - if (!item) - return false; - if (!(item->LoreFlag)) + if (!item || !(item->LoreFlag)) return false; if (item->LoreGroup == -1) // Standard lore items; look everywhere except the shared bank, return the result @@ -11300,19 +11304,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } if(!strcasecmp( sep->arg[1], "help") && !strcasecmp( sep->arg[2], "\0")){ - c->Message(0, "List of commands availables for bots :"); + 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 your bots all or by class. Classes: 1(Warrior), 2(Cleric), 3(Paladin), 4(Ranger), 5(Sk), 6(Druid), 7(Monk), 8(Bard), 9(Rogue), 10(Shaman), 11(Necro), 12(Wiz), 13(Mag), 14(Ench), 15(Beast), 16(Bersek)"); + c->Message(0, "#bot list [all/class(1-16)] - list your bots all or 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 targetted bot."); - c->Message(0, "#bot inventory remove [slotid] - remove the item at the given slot in the inventory of the targetted bot."); + 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 ai mez - If you're grouped with an enchanter, he will mez 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 ai mez - If you're grouped with an Enchanter, he will mez 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 bindme - 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)"); @@ -11334,7 +11338,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "#bot gate - you need a Druid or Wizard in your group)"); c->Message(0, "#bot archery - Toggle Archery Skilled bots between using a Bow or using Melee weapons."); c->Message(0, "#bot magepet [earth|water|air|fire|monster] - Select the pet type you want your Mage bot to use."); - c->Message(0, "#bot giveitem - Gives your targetted bot the item you have on your cursor."); + c->Message(0, "#bot giveitem - Gives your targeted bot the item you have on your cursor."); c->Message(0, "#bot augmentitem - 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."); @@ -11359,29 +11363,23 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { // 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())) - { + 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()) - { + if(c->IsGrouped()) { bool haspuller = false; Group *g = c->GetGroup(); - for(int i=0; imembers[i] && g->members[i]->IsBot() && !strcasecmp(g->members[i]->GetName() , sep->arg[2])) - { + 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->Say("Trying to Pull %s \n", target->GetCleanName()); + if (puller->CastToBot()->IsArcheryRange(target)) { + puller->CastToBot()->BotGroupSay(puller->CastToBot(), "Trying to Pull %s \n", target->GetCleanName()); puller->CastToBot()->BotRangedAttack(target); - } - else { - puller->Say("Out of Range %s \n", target->GetCleanName()); + } else { + puller->CastToBot()->BotGroupSay(puller->CastToBot(), "Out of Range %s \n", target->GetCleanName()); } } } @@ -11400,7 +11398,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else { uint32 BotFollowDistance = atoi(sep->arg[2]); c->GetTarget()->SetFollowDistance(BotFollowDistance); - } return; @@ -11418,33 +11415,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 = StringFormat("UPDATE botinventory SET color = %u " - "WHERE slotID = %i AND botID = %u", - setcolor, setslot, botid); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; + std::string query; + if (setslot == -1) { + int slots[] = { 2, 7, 9, 12, 17, 18, 19 }; + query = StringFormat("UPDATE botinventory SET color = %u WHERE slotID IN (2, 7, 9, 12, 17, 18, 19) AND botID = %u", setcolor, botid); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + + for (int i = 0; i < 7; i++) { + uint8 slotmaterial = Inventory::CalcMaterialFromSlot((uint8)slots[i]); + c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); + } + } else { + query = StringFormat("UPDATE botinventory SET color = %u WHERE slotID = %i AND botID = %u", setcolor, setslot, botid); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + + uint8 slotmaterial = Inventory::CalcMaterialFromSlot(setslot); + c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); + } - uint8 slotmaterial = Inventory::CalcMaterialFromSlot(setslot); - c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); } else { c->Message(15, "You must target a bot you own to do this."); } return; } - // Help for coloring bot armor - if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "armorcolor") ){ - //read from db - + + if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "armorcolor")){ c->Message(0, "-----------------#bot armorcolor help-----------------------------"); - c->Message(0, "Armor: 17(Chest/Robe), 7(Arms), 9(Bracer), 12(Hands), 18(Legs), 19(Boots), 2(Helm)"); + c->Message(0, "Armor: -1(All), 2(Helm), 7(Arms), 9(Bracer), 12(Hands), 17(Chest/Robe), 18(Legs), 19(Boots)"); c->Message(0, "------------------------------------------------------------------"); c->Message(0, "Color: [red] [green] [blue] (enter a number from 0-255 for each"); c->Message(0, "------------------------------------------------------------------"); @@ -11565,9 +11572,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "create") ){ - c->Message(0, "Classes: 1(Warrior), 2(Cleric), 3(Paladin), 4(Ranger), 5(Sk), 6(Druid), 7(Monk), 8(Bard), 9(Rogue), 10(Shaman), 11(Necro), 12(Wiz), 13(Mag), 14(Ench), 15(Beast), 16(Bersek)"); + 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(Barb), 3(Erudit), 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, "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"); @@ -11640,12 +11647,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { listAll = true; else { std::string botName = std::string(sep->arg[2]); - Bot* tempBot = entity_list.GetBotByBotName(botName); - - if(tempBot && tempBot->GetBotOwner() == c) { + if(tempBot && tempBot->GetBotOwner() == c) bot = tempBot; - } } } else { @@ -11784,7 +11788,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - TempBot->CastToMob()->Say("I am ready for battle."); + TempBot->BotGroupSay(TempBot, "I am ready for battle."); } else { // We did not find a bot for the specified bot id from the database @@ -11844,7 +11848,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } else if((b->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID())) { - b->Say("You can only summon your own bots."); + b->CastToBot()->BotGroupSay(b->CastToBot(), "You can only summon your own bots."); } else { @@ -11868,9 +11872,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - const char* equipped[EmuConstants::EQUIPMENT_SIZE] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + 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" }; + "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; const ItemInst* inst = nullptr; const Item_Struct* item = nullptr; @@ -11880,12 +11884,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { + for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { if((i == MainSecondary) && is2Hweapon) { continue; } - inst = b->CastToBot()->GetBotItem(i); + inst = b->CastToBot()->GetBotItem(i == 22 ? 9999 : i); if (inst) item = inst->GetItem(); else @@ -11896,21 +11900,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } if(item == nullptr) { - c->Message(15, "I need something for my %s (Item %i)", equipped[i], i); + 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; } - // I could not find a difference between the criteria positive code and the criteria negative code.. - // ..so, I deleted the check (old criteria: i = { MainCharm, MainRange, MainPrimary, MainSecondary, MainAmmo }) - linker.SetItemInst(inst); item_link = linker.GenerateLink(); - c->Message(15, "Using %s in my %s (Item %i)", item_link.c_str(), equipped[i], i); + c->Message(15, "Using %s in my %s (Item %i)", item_link.c_str(), equipped[i], (i == 22 ? 9999 : i)); } } else { @@ -11926,7 +11927,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 targetted) "); + 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()) @@ -11935,13 +11936,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; int slotId = atoi(sep->arg[3]); - if(slotId > EmuConstants::EQUIPMENT_END || slotId < EmuConstants::EQUIPMENT_BEGIN) { - c->Message(15, "A bot has 21 slots in its inventory, please choose a slot between 0 and 21."); + 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] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + 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" }; + "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; const Item_Struct* itm = nullptr; const ItemInst* itminst = c->GetTarget()->CastToBot()->GetBotItem(slotId); @@ -12002,16 +12003,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { case MainFinger2: case MainChest: case MainWaist: - //case MainPowerSource: + case MainPowerSource: case MainAmmo: - gearbot->Say("My %s is now unequipped.", equipped[slotId]); + gearbot->BotGroupSay(gearbot, "My %s is now unequipped.", equipped[slotId]); break; case MainShoulders: case MainArms: case MainHands: case MainLegs: case MainFeet: - gearbot->Say("My %s are now unequipped.", equipped[slotId]); + gearbot->BotGroupSay(gearbot, "My %s are now unequipped.", equipped[slotId]); break; default: break; @@ -12035,16 +12036,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { case MainFinger2: case MainChest: case MainWaist: - //case MainPowerSource: + case MainPowerSource: case MainAmmo: - c->GetTarget()->Say("My %s is already unequipped.", equipped[slotId]); + 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()->Say("My %s are already unequipped.", equipped[slotId]); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "My %s are already unequipped.", equipped[slotId]); break; default: break; @@ -12123,7 +12124,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } if(hasbinder) { - binder->Say("Attempting to bind you %s.", c->GetName()); + binder->CastToBot()->BotGroupSay(binder->CastToBot(), "Attempting to bind you %s.", c->GetName()); binder->CastToNPC()->CastSpell(35, c->GetID(), 1, -1, -1); } return; @@ -12152,30 +12153,30 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(hasruneer) { if (c->GetLevel() <= 12) { - runeer->Say("I need to be level 13 or higher for this..."); + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "I need to be level 13 or higher for this..."); } else if ((c->GetLevel() >= 13) && (c->GetLevel() <= 21)) { - runeer->Say("Casting Rune I..."); + 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->Say("Casting Rune II..."); + 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->Say("Casting Rune III..."); + 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->Say("Casting Rune IV..."); + 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->Say("Casting Rune V..."); + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune V..."); runeer->CastSpell(1689, c->GetID(), 1, -1, -1); } else if (c->GetLevel() >= 61){ - runeer->Say("Casting Rune of Zebuxoruk..."); + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune of Zebuxoruk..."); runeer->CastSpell(3343, c->GetID(), 1, -1, -1); } } @@ -12223,33 +12224,33 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(TrackerClass) { case RANGER: if(!strcasecmp(sep->arg[2], "all")) { - Tracker->Say("Tracking everything", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking everything", c->GetName()); entity_list.ShowSpawnWindow(c, RangeR, false); } else if(!strcasecmp(sep->arg[2], "rare")) { - Tracker->Say("Selective tracking", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Selective tracking", c->GetName()); entity_list.ShowSpawnWindow(c, RangeR, true); } else if(!strcasecmp(sep->arg[2], "near")) { - Tracker->Say("Tracking mobs nearby", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking mobs nearby", c->GetName()); entity_list.ShowSpawnWindow(c, RangeD, false); } else - Tracker->Say("You want to [track all], [track near], or [track rare]?", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "You want to [track all], [track near], or [track rare]?", c->GetName()); break; case BARD: if(TrackerClass != RANGER) - Tracker->Say("Tracking up", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up", c->GetName()); entity_list.ShowSpawnWindow(c, RangeB, false); break; case DRUID: if(TrackerClass = BARD) - Tracker->Say("Tracking up", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up", c->GetName()); entity_list.ShowSpawnWindow(c, RangeD, false); break; @@ -12293,80 +12294,80 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(CurerClass) { case CLERIC: if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 1)) { - Curer->Say("Trying to cure us of %s.", sep->arg[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() >= 4)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + 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->Say("Trying to cure us of %s.", sep->arg[2]); + 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->Say("Trying to cure us of %s.", sep->arg[2]); + 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->Say("I don't have the needed level yet", sep->arg[2]); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Curer->Say("Do you want [cure poison], [cure disease], [cure curse], or [cure blindness]?", c->GetName()); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], [cure disease], [cure curse], or [cure blindness]?", c->GetName()); break; case SHAMAN: if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 2)) { - Curer->Say("Trying to cure us of %s.", sep->arg[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->Say("Trying to cure us of %s.", sep->arg[2]); + 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->Say("I don't have that spell", sep->arg[2]); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 7)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + 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->Say("I don't have the needed level yet", sep->arg[2]); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Curer->Say("Do you want [cure poison], [cure disease], or [cure blindness]?", c->GetName()); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], [cure disease], or [cure blindness]?", c->GetName()); break; case DRUID: if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 5)) { - Curer->Say("Trying to cure us of %s.", sep->arg[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() >= 4)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + 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->Say("I don't have that spell", sep->arg[2]); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 13)) { - Curer->Say("I don't have that spell", sep->arg[2]); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 4) || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 5)) { - Curer->Say("I don't have the needed level yet", sep->arg[2]) ; + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]) ; } else - Curer->Say("Do you want [cure poison], or [cure disease]?", c->GetName()); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], or [cure disease]?", c->GetName()); break; @@ -12397,7 +12398,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { { hasmezzer = true; Mob *mezzer = g->members[i]; - mezzer->Say("Trying to mez %s \n", target->GetCleanName()); + mezzer->CastToBot()->BotGroupSay(mezzer->CastToBot(), "Trying to mez %s \n", target->GetCleanName()); mezzer->CastToBot()->MesmerizeTarget(target); } } @@ -12443,7 +12444,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { break; } if(hascaster) { - g->members[i]->Say("Trying to Identify your item..."); + 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; } @@ -12479,7 +12480,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { { hasrezzer = true; Mob *rezzer = g->members[i]; - rezzer->Say("Trying to rez %s", target->GetCleanName()); + rezzer->CastToBot()->BotGroupSay(rezzer->CastToBot(), "Trying to rez %s", target->GetCleanName()); rezzer->CastToBot()->Bot_Command_RezzTarget(target); break; } @@ -12504,7 +12505,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->GetTarget()->CastToBot()->SetPetChooser(true); if(botlevel == 1) { - c->GetTarget()->Say("I don't have any pets yet."); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have any pets yet."); return; } if(!strcasecmp(sep->arg[2], "water")) @@ -12515,7 +12516,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { { if(botlevel < 3) { - c->GetTarget()->Say("I don't have that pet yet."); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); return; } else @@ -12527,7 +12528,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { { if(botlevel < 4) { - c->GetTarget()->Say("I don't have that pet yet."); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); return; } else @@ -12539,7 +12540,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { { if(botlevel < 5) { - c->GetTarget()->Say("I don't have that pet yet."); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); return; } else @@ -12551,7 +12552,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { { if(botlevel < 30) { - c->GetTarget()->Say("I don't have that pet yet."); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); return; } else @@ -12592,27 +12593,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { summonerlevel = g->members[i]->GetLevel(); g->members[i]->InterruptSpell(); if(!t->IsClient()) { - g->members[i]->Say("You have to target a player with a corpse in the zone"); + 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]->Say("I don't have that spell yet."); + 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]->Say("Attempting to summon %s\'s corpse.", t->GetCleanName()); + 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]->Say("Attempting to summon %s\'s corpse.", t->GetCleanName()); + 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]->Say("Attempting to summon %s\'s corpse.", t->GetCleanName()); + 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; } @@ -12641,7 +12642,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { // 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->Say("Trying to pacify %s \n", target->GetCleanName()); + pacer->BotGroupSay(pacer, "Trying to pacify %s \n", target->GetCleanName()); if(pacer->Bot_Command_CalmTarget(target)) { if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_InstantHate)) @@ -12657,7 +12658,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { // 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->Say("Trying to pacify %s \n", target->GetCleanName()); + pacer->BotGroupSay(pacer, "Trying to pacify %s \n", target->GetCleanName()); if(pacer->Bot_Command_CalmTarget(target)) { if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_InstantHate)) @@ -12720,38 +12721,38 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(CharmerClass) { case ENCHANTER: if (c->GetLevel() >= 11) { - Charmer->Say("Trying to charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s \n", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (1,target); } else if (c->GetLevel() <= 10){ - Charmer->Say("I don't have the needed level yet", sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Charmer->Say("Mob level is too high or can't be charmed", c->GetName()); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob level is too high or can't be charmed", c->GetName()); break; case NECROMANCER: if ((c->GetLevel() >= 18) && (DBtype == 3)) { - Charmer->Say("Trying to Charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to Charm %s \n", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (2,target); } else if (c->GetLevel() <= 17){ - Charmer->Say("I don't have the needed level yet", sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Charmer->Say("Mob Is not undead...", c->GetName()); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob Is not undead...", c->GetName()); break; case DRUID: if ((c->GetLevel() >= 13) && (DBtype == 21)) { - Charmer->Say("Trying to charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s \n", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (3,target); } else if (c->GetLevel() <= 12){ - Charmer->Say("I don't have the needed level yet", sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Charmer->Say("Mob is not an animal...", c->GetName()); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not an animal...", c->GetName()); break; default: @@ -12768,7 +12769,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { ((c->GetTarget()->GetClass() == NECROMANCER) || (c->GetTarget()->GetClass() == ENCHANTER) || (c->GetTarget()->GetClass() == DRUID))) { if(c->GetTarget()->CastToBot()->IsBotCharmer()) { c->GetTarget()->CastToBot()->SetBotCharmer(false); - c->GetTarget()->Say("Using a summoned pet."); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "Using a summoned pet."); } else { if(c->GetTarget()->GetPet()) @@ -12779,7 +12780,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->GetTarget()->SetPetID(0); } c->GetTarget()->CastToBot()->SetBotCharmer(true); - c->GetTarget()->Say("Available for Dire Charm command."); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "Available for Dire Charm command."); } } else { @@ -12833,38 +12834,38 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(DirerClass) { case ENCHANTER: if (c->GetLevel() >= 55) { - Direr->Say("Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (1,target); } else if (c->GetLevel() <= 55){ - Direr->Say("I don't have the needed level yet", sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Direr->Say("Mob level is too high or can't be charmed", c->GetName()); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob level is too high or can't be charmed", c->GetName()); break; case NECROMANCER: if ((c->GetLevel() >= 55) && (DBtype == 3)) { - Direr->Say("Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (2,target); } else if (c->GetLevel() <= 55){ - Direr->Say("I don't have the needed level yet", sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Direr->Say("Mob Is not undead...", c->GetName()); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob Is not undead...", c->GetName()); break; case DRUID: if ((c->GetLevel() >= 55) && (DBtype == 21)) { - Direr->Say("Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (3,target); } else if (c->GetLevel() <= 55){ - Direr->Say("I don't have the needed level yet", sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Direr->Say("Mob is not an animal...", c->GetName()); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not an animal...", c->GetName()); break; default: @@ -12897,11 +12898,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } if((hasevac) && (c->GetLevel() >= 18)) { - evac->Say("Attempting to Evac you %s.", c->GetName()); + evac->CastToBot()->BotGroupSay(evac->CastToBot(), "Attempting to Evac you %s.", c->GetName()); evac->CastToClient()->CastSpell(2183, c->GetID(), 1, -1, -1); } else if((hasevac) && (c->GetLevel() <= 17)) { - evac->Say("I'm not level 18 yet.", c->GetName()); + evac->CastToBot()->BotGroupSay(evac->CastToBot(), "I'm not level 18 yet.", c->GetName()); } return; } @@ -12945,87 +12946,87 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(SowerClass) { case DRUID: if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() >= 10) ) { - Sower->Say("Casting sow..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting sow..."); Sower->CastSpell(278, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() <= 10) ) { - Sower->Say("I'm not level 10 yet."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 10 yet."); } else if ((!strcasecmp(sep->arg[2], "wolf")) && zone->CanCastOutdoor() && (c->GetLevel() >= 20)) { - Sower->Say("Casting group wolf..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting group wolf..."); Sower->CastSpell(428, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "wolf")) && (c->GetLevel() <= 20)) { - Sower->Say("I'm not level 20 yet."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 20 yet."); } else if ((!strcasecmp(sep->arg[2], "feral")) && (c->GetLevel() >= 50)) { - Sower->Say("Casting Feral Pack..."); + 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->Say("I'm not level 50 yet."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 50 yet."); } else if ((!strcasecmp(sep->arg[2], "shrew")) && (c->GetLevel() >= 35)) { - Sower->Say("Casting Pack Shrew..."); + 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->Say("I'm not level 35 yet."); + 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->Say("I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); } else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); } else if (zone->CanCastOutdoor()) { - Sower->Say("Do you want [sow regular] or [sow wolf]?", c->GetName()); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Do you want [sow regular] or [sow wolf]?", c->GetName()); } else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); } break; case SHAMAN: if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 9)) { - Sower->Say("Casting SoW..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting SoW..."); Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); } else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors", c->GetName()); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors", c->GetName()); } else if (c->GetLevel() <= 9) { - Sower->Say("I'm not level 9 yet."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 9 yet."); } break; case RANGER: if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 28)){ - Sower->Say("Casting SoW..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting SoW..."); Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); } else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors", c->GetName()); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors", c->GetName()); } else if (c->GetLevel() <= 28) { - Sower->Say("I'm not level 28 yet."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 28 yet."); } break; case BEASTLORD: if((zone->CanCastOutdoor()) && (c->GetLevel() >= 24)) { - Sower->Say("Casting SoW..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting SoW..."); Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); } else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors", c->GetName()); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors", c->GetName()); } else if (c->GetLevel() <= 24) { - Sower->Say("I'm not level 24 yet."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 24 yet."); } break; @@ -13070,22 +13071,22 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { case SHAMAN: if (c->GetLevel() >= 15) { - Shrinker->Say("Casting Shrink..."); + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink..."); Shrinker->CastToBot()->SpellOnTarget(345, target); } else if (c->GetLevel() <= 14) { - Shrinker->Say("I'm not level 15 yet."); + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "I'm not level 15 yet."); } break; case BEASTLORD: if (c->GetLevel() >= 23) { - Shrinker->Say("Casting Shrink..."); + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink..."); Shrinker->CastToBot()->SpellOnTarget(345, target); } else if (c->GetLevel() <= 22) { - Shrinker->Say("I'm not level 23 yet."); + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "I'm not level 23 yet."); } break; @@ -13123,103 +13124,103 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(GaterClass) { case DRUID: if ((!strcasecmp(sep->arg[2], "karana")) && (c->GetLevel() >= 25) ) { - Gater->Say("Casting Circle of Karana..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Karana..."); Gater->CastSpell(550, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Circle of Commons..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Commons..."); Gater->CastSpell(551, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { - Gater->Say("Casting Circle of Toxxulia..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Toxxulia..."); Gater->CastSpell(552, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "butcher")) && (c->GetLevel() >= 25)) { - Gater->Say("Casting Circle of Butcherblock..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Butcherblock..."); Gater->CastSpell(553, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "lava")) && (c->GetLevel() >= 30)) { - Gater->Say("Casting Circle of Lavastorm..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Lavastorm..."); Gater->CastSpell(554, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 32)) { - Gater->Say("Casting Circle of Ro..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Ro..."); Gater->CastSpell(555, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "feerrott")) && (c->GetLevel() >= 32)) { - Gater->Say("Casting Circle of feerrott..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of feerrott..."); Gater->CastSpell(556, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "steamfont")) && (c->GetLevel() >= 31)) { - Gater->Say("Casting Circle of Steamfont..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Steamfont..."); Gater->CastSpell(557, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "misty")) && (c->GetLevel() >= 36)) { - Gater->Say("Casting Circle of Misty..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Misty..."); Gater->CastSpell(558, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 40)) { - Gater->Say("Casting Circle of Wakening Lands..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Wakening Lands..."); Gater->CastSpell(1398, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 32)) { - Gater->Say("Casting Circle of Iceclad Ocean..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Iceclad Ocean..."); Gater->CastSpell(1434, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { - Gater->Say("Casting Circle of The Great Divide..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Great Divide..."); Gater->CastSpell(1438, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 42)) { - Gater->Say("Casting Circle of Cobalt Scar..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Cobalt Scar..."); Gater->CastSpell(1440, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 33)) { - Gater->Say("Casting Circle of The Combines..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Combines..."); Gater->CastSpell(1517, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "surefall")) && (c->GetLevel() >= 26)) { - Gater->Say("Casting Circle of Surefall Glade..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Surefall Glade..."); Gater->CastSpell(2020, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { - Gater->Say("Casting Circle of Grimling Forest..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Grimling Forest..."); Gater->CastSpell(2419, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 33)) { - Gater->Say("Casting Circle of Twilight..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Twilight..."); Gater->CastSpell(2424, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 37)) { - Gater->Say("Casting Circle of Dawnshroud..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Dawnshroud..."); Gater->CastSpell(2429, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 26)) { - Gater->Say("Casting Circle of The Nexus..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Nexus..."); Gater->CastSpell(2432, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 38)) { - Gater->Say("Casting Circle of Knowledge..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Knowledge..."); Gater->CastSpell(3184, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 28)) { - Gater->Say("Casting Circle of Stonebrunt Mountains..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Stonebrunt Mountains..."); Gater->CastSpell(3792, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { - Gater->Say("Casting Circle of Bloodfields..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Bloodfields..."); Gater->CastSpell(6184, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 39)) { - Gater->Say("Casting Wind of the South..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the South..."); Gater->CastSpell(1737, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 44)) { - Gater->Say("Casting Wind of the North..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the North..."); Gater->CastSpell(1736, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "slaughter")) && (c->GetLevel() >= 64)) { - Gater->Say("Casting Circle of Slaughter..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Slaughter..."); Gater->CastSpell(6179, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "karana") @@ -13247,109 +13248,109 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "emerald") && (c->GetLevel() <= 38) || !strcasecmp(sep->arg[2], "skyfire") && (c->GetLevel() <= 43) || !strcasecmp(sep->arg[2], "wos") && (c->GetLevel() <= 64)) { - Gater->Say("I don't have the needed level yet", sep->arg[2]); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else { - Gater->Say("With the proper level I can [gate] to [karana],[commons],[tox],[butcher],[lava],[ro],[feerrott],[steamfont],[misty],[wakening],[iceclad],[divide],[cobalt],[combines],[surefall],[grimling],[twilight],[dawnshroud],[nexus],[pok],[stonebrunt],[bloodfields],[emerald],[skyfire] or [wos].", c->GetName()); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [karana],[commons],[tox],[butcher],[lava],[ro],[feerrott],[steamfont],[misty],[wakening],[iceclad],[divide],[cobalt],[combines],[surefall],[grimling],[twilight],[dawnshroud],[nexus],[pok],[stonebrunt],[bloodfields],[emerald],[skyfire] or [wos].", c->GetName()); } break; case WIZARD: if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 35) ) { - Gater->Say("Casting Common Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Common Portal..."); Gater->CastSpell(566, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "fay")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Fay Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal..."); Gater->CastSpell(563, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 37)) { - Gater->Say("Casting Ro Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Ro Portal..."); Gater->CastSpell(567, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { - Gater->Say("Casting Toxxula Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Toxxula Portal..."); Gater->CastSpell(561, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "nk")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting North Karana Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting North Karana Portal..."); Gater->CastSpell(562, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "nek")) && (c->GetLevel() >= 32)) { - Gater->Say("Casting Nektulos Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nektulos Portal..."); Gater->CastSpell(564, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 43)) { - Gater->Say("Casting Wakening Lands Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wakening Lands Portal..."); Gater->CastSpell(1399, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 33)) { - Gater->Say("Casting Iceclad Ocean Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Iceclad Ocean Portal..."); Gater->CastSpell(1418, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { - Gater->Say("Casting Great Divide Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Great Divide Portal..."); Gater->CastSpell(1423, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 43)) { - Gater->Say("Casting Cobalt Scar Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Cobalt Scar Portal..."); Gater->CastSpell(1425, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 34)) { - Gater->Say("Casting Combines Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Combines Portal..."); Gater->CastSpell(1516, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "wk")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting West Karana Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting West Karana Portal..."); Gater->CastSpell(568, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Twilight Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Twilight Portal..."); Gater->CastSpell(2425, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Dawnshroud Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Dawnshroud Portal..."); Gater->CastSpell(2430, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 29)) { - Gater->Say("Casting Nexus Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nexus Portal..."); Gater->CastSpell(2944, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Plane of Knowledge Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Plane of Knowledge Portal..."); Gater->CastSpell(3180, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "wos")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Wall of Slaughter Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wall of Slaughter Portal..."); Gater->CastSpell(6178, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { - Gater->Say("Casting Fay Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal..."); Gater->CastSpell(2420, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 37)) { - Gater->Say("Porting to Emerald Jungle..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Emerald Jungle..."); Gater->CastSpell(1739, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "hateplane")) && (c->GetLevel() >= 39)) { - Gater->Say("Porting to Hate Plane..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Hate Plane..."); Gater->CastSpell(666, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "airplane")) && (c->GetLevel() >= 39)) { - Gater->Say("Porting to airplane..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to airplane..."); Gater->CastSpell(674, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 36)) { - Gater->Say("Porting to Skyfire..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Skyfire..."); Gater->CastSpell(1738, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { - Gater->Say("Casting Bloodfields Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Bloodfields Portal..."); Gater->CastSpell(6183, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Stonebrunt Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Stonebrunt Portal..."); Gater->CastSpell(3793, c->GetID(), 1, -1, -1); } else if ((!strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 35)) @@ -13376,10 +13377,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "emerald") && (c->GetLevel() <= 36) || !strcasecmp(sep->arg[2], "skyfire") && (c->GetLevel() <= 36) || !strcasecmp(sep->arg[2], "wos") && (c->GetLevel() <= 64)) { - Gater->Say("I don't have the needed level yet", sep->arg[2]); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else { - Gater->Say("With the proper level I can [gate] to [commons],[fay],[ro],[tox],[nk],[wakening],[iceclad],[divide],[cobalt],[combines],[wk],[grimling],[twilight],[dawnshroud],[nexus],[pok],[stonebrunt],[bloodfields],[emerald],[skyfire],[hateplane],[airplane] or [wos].", c->GetName()); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [commons],[fay],[ro],[tox],[nk],[wakening],[iceclad],[divide],[cobalt],[combines],[wk],[grimling],[twilight],[dawnshroud],[nexus],[pok],[stonebrunt],[bloodfields],[emerald],[skyfire],[hateplane],[airplane] or [wos].", c->GetName()); } break; default: @@ -13434,47 +13435,47 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(EndurerClass) { case DRUID: if (c->GetLevel() < 6) { - Endurer->Say("I'm not level 6 yet."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 6 yet."); } else { - Endurer->Say("Casting Enduring Breath..."); + 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->Say("I'm not level 12 yet."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 12 yet."); } else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath..."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case RANGER: if (c->GetLevel() < 20) { - Endurer->Say("I'm not level 20 yet."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 20 yet."); } else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath..."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case ENCHANTER: if (c->GetLevel() < 12) { - Endurer->Say("I'm not level 12 yet."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 12 yet."); } else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath..."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case BEASTLORD: if (c->GetLevel() < 25) { - Endurer->Say("I'm not level 25 yet."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 25 yet."); } else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath..."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; @@ -13531,135 +13532,135 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(InviserClass) { case ENCHANTER: if ((c->GetLevel() <= 14) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->Say("I'm not level 14 yet."); + 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->Say("Casting invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead..."); Inviser->CastSpell(235, c->GetID(), 1, -1, -1); } else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("I'm not level 4 yet."); + 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->Say("Casting invisibilty..."); + 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->Say("I'm not level 6 yet."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 6 yet."); } else if ((c->GetLevel() >= 6) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("Casting see invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible..."); Inviser->CastSpell(80, c->GetID(), 1, -1, -1); } else if ((c->IsInvisible(c)) || (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed..."); } else { - Inviser->Say("Do you want [invis undead], [invis live] or [invis see] ?", c->GetName()); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want [invis undead], [invis live] or [invis see] ?", c->GetName()); } break; case MAGICIAN: if (!strcasecmp(sep->arg[2], "undead")) { - Inviser->Say("I don't have that spell."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); } else if ((c->GetLevel() <= 8) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("I'm not level 8 yet."); + 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->Say("Casting invisibilty..."); + 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->Say("I'm not level 16 yet."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 16 yet."); } else if ((c->GetLevel() >= 16) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("Casting see invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible..."); Inviser->CastSpell(80, c->GetID(), 1, -1, -1); } else if ((c->IsInvisible(c)) || (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed..."); } else { - Inviser->Say("Do you want [invis live] or [invis see] ?", c->GetName()); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want [invis live] or [invis see] ?", c->GetName()); } break; case WIZARD: if ((c->GetLevel() <= 39) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->Say("I'm not level 39 yet."); + 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->Say("Casting invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead..."); Inviser->CastSpell(235, c->GetID(), 1, -1, -1); } else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("I'm not level 16 yet."); + 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->Say("Casting invisibilty..."); + 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->Say("I'm not level 6 yet."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 6 yet."); } else if ((c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("Casting see invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible..."); Inviser->CastSpell(80, c->GetID(), 1, -1, -1); } else if ((c->IsInvisible(c)) || (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed..."); } else { - Inviser->Say("Do you want [invis undead], [invis live] or [invis see] ?", c->GetName()); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want [invis undead], [invis live] or [invis see] ?", c->GetName()); } break; case NECROMANCER: if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->Say("Casting invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead..."); Inviser->CastSpell(235, c->GetID(), 1, -1, -1); } else if (!strcasecmp(sep->arg[2], "see")) { - Inviser->Say("I don't have that spell..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell..."); } else if (!strcasecmp(sep->arg[2], "live")) { - Inviser->Say("I don't have that spell..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell..."); } else if ((c->IsInvisible(c))|| (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed..."); } else { - Inviser->Say("I only have [invis undead]", c->GetName()); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I only have [invis undead]", c->GetName()); } break; case DRUID: if (!strcasecmp(sep->arg[2], "undead")) { - Inviser->Say("I don't have that spell..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell..."); } else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("I'm not level 4 yet."); + 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->Say("Casting Superior Camouflage..."); + 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->Say("Casting Camouflage..."); + 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->Say("I can't cast this spell indoors..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this spell indoors..."); } else if ((c->GetLevel() <= 13) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("I'm not level 13 yet."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 13 yet."); } else if ((c->GetLevel() >= 13) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("Casting see invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible..."); Inviser->CastSpell(80, c->GetID(), 1, -1, -1); } else if ((c->IsInvisible(c)) || (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed..."); } else { - Inviser->Say("Do you want [invis live] or [invis see] ?", c->GetName()); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want [invis live] or [invis see] ?", c->GetName()); } break; default: @@ -13708,57 +13709,57 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(LeverClass) { case DRUID: if (c->GetLevel() <= 14) { - Lever->Say("I'm not level 14 yet."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 14 yet."); } else if (zone->CanCastOutdoor()) { - Lever->Say("Casting Levitate..."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate..."); Lever->CastSpell(261, c->GetID(), 1, -1, -1); break; } else if (!zone->CanCastOutdoor()) { - Lever->Say("I can't cast this spell indoors", c->GetName()); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors", c->GetName()); } break; case SHAMAN: if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 10)) { - Lever->Say("Casting Levitate..."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate..."); Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); } else if (!zone->CanCastOutdoor()) { - Lever->Say("I can't cast this spell indoors", c->GetName()); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors", c->GetName()); } else if (c->GetLevel() <= 10) { - Lever->Say("I'm not level 10 yet."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 10 yet."); } break; case WIZARD: if((zone->CanCastOutdoor()) && (c->GetLevel() >= 22)){ - Lever->Say("Casting Levitate..."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate..."); Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); } else if (!zone->CanCastOutdoor()) { - Lever->Say("I can't cast this spell indoors", c->GetName()); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors", c->GetName()); } else if (c->GetLevel() <= 22) { - Lever->Say("I'm not level 22 yet."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 22 yet."); } break; case ENCHANTER: if((zone->CanCastOutdoor()) && (c->GetLevel() >= 15)) { - Lever->Say("Casting Levitate..."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate..."); Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); } else if (!zone->CanCastOutdoor()) { - Lever->Say("I can't cast this spell indoors", c->GetName()); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors", c->GetName()); } else if (c->GetLevel() <= 15) { - Lever->Say("I'm not level 15 yet."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 15 yet."); } break; @@ -13803,23 +13804,23 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(ResisterClass) { case CLERIC: if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 6)) { - Resister->Say("Casting poison protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(1, Resister->GetLevel()); } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 11)) { - Resister->Say("Casting disease protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting disease protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(2, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "fire") && (c->GetLevel() >= 8)) { - Resister->Say("Casting fire protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting fire protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(3, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 13)) { - Resister->Say("Casting cold protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting cold protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(4, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 16)) { - Resister->Say("Casting magic protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting magic protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(5, Resister->GetLevel()); } else if (!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 16) @@ -13827,32 +13828,32 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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->Say("I don't have the needed level yet", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Resister->Say("Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); break; case SHAMAN: if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 20)) { - Resister->Say("Casting poison protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(12, Resister->GetLevel()); } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 8)) { - Resister->Say("Casting disease protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting disease protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(13, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "fire") && (c->GetLevel() >= 5)) { - Resister->Say("Casting fire protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting fire protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(14, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 1)) { - Resister->Say("Casting cold protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting cold protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(15, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 19)) { - Resister->Say("Casting magic protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting magic protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(16, Resister->GetLevel()); } else if (!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 19) @@ -13860,43 +13861,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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->Say("I don't have the needed level yet", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Resister->Say("Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); break; case DRUID: if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 19)) { - Resister->Say("Casting poison protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(7, Resister->GetLevel()); } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 19)) { - Resister->Say("Casting disease protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting disease protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(8, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "fire")) { // Fire level 1 - Resister->Say("Casting fire protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting fire protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(9, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 13)) { - Resister->Say("Casting cold protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting cold protection...", sep->arg[2]); Resister->CastToBot()->Bot_Command_Resist(10, Resister->GetLevel()); } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 16)) { - Resister->Say("Casting magic protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting magic protection...", sep->arg[2]); 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->Say("I don't have the needed level yet", sep->arg[2]) ; + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the needed level yet", sep->arg[2]) ; } else - Resister->Say("Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); break; @@ -14022,9 +14023,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(Bot::BotGroupCreate(botGroupLeader)) - botGroupLeader->Say("I am prepared to lead."); + botGroupLeader->BotGroupSay(botGroupLeader, "I am prepared to lead."); else - botGroupLeader->Say("I can not lead."); + botGroupLeader->BotGroupSay(botGroupLeader, "I cannot lead."); } else c->Message(13, "You must target a spawned bot first."); @@ -14088,17 +14089,17 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { // invite if(Bot::AddBotToGroup(botGroupMember, g)) { database.SetGroupID(botGroupMember->GetName(), g->GetID(), botGroupMember->GetBotID()); - botGroupMember->Say("I have joined %s\'s group.", botGroupLeader->GetName()); + botGroupMember->BotGroupSay(botGroupMember, "I have joined %s\'s group.", botGroupLeader->GetName()); } else { - botGroupMember->Say("I can not join %s\'s group.", botGroupLeader->GetName()); + botGroupMember->BotGroupSay(botGroupMember, "I can not join %s\'s group.", botGroupLeader->GetName()); } } else { // "I am already in a group." Group* tempGroup = botGroupMember->GetGroup(); if(tempGroup) - botGroupMember->Say("I can not join %s\'s group. I am already a member in %s\'s group.", botGroupLeader->GetName(), tempGroup->GetLeaderName()); + botGroupMember->BotGroupSay(botGroupMember, "I can not join %s\'s group. I am already a member in %s\'s group.", botGroupLeader->GetName(), tempGroup->GetLeaderName()); } } else { @@ -14108,14 +14109,14 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } else { // "My group is full." - botGroupLeader->Say("I have no more openings in my group, %s.", c->GetName()); + botGroupLeader->BotGroupSay(botGroupMember, "I have no more openings in my group, %s.", c->GetName()); } } else { // "I am not a group leader." Group* tempGroup = botGroupLeader->GetGroup(); if(tempGroup) - botGroupLeader->Say("I can not lead anyone because I am a member in %s\'s group.", tempGroup->GetLeaderName()); + botGroupLeader->BotGroupSay(botGroupLeader, "I can not lead anyone because I am a member in %s\'s group.", tempGroup->GetLeaderName()); } } } @@ -14141,12 +14142,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Group* g = botGroupMember->GetGroup(); if(Bot::RemoveBotFromGroup(botGroupMember, g)) - botGroupMember->Say("I am no longer in a group."); + botGroupMember->BotGroupSay(botGroupMember, "I am no longer in a group."); else - botGroupMember->Say("I can not leave %s\'s group.", g->GetLeaderName()); + botGroupMember->BotGroupSay(botGroupMember, "I can not leave %s\'s group.", g->GetLeaderName()); } else - botGroupMember->Say("I am not in a group."); + botGroupMember->BotGroupSay(botGroupMember, "I am not in a group."); } else c->Message(13, "You must target a spawned bot first."); @@ -14173,16 +14174,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(g->IsLeader(botGroupLeader)) { if(Bot::RemoveBotFromGroup(botGroupLeader, g)) - botGroupLeader->Say("I have disbanded my group, %s.", c->GetName()); + botGroupLeader->BotGroupSay(botGroupLeader, "I have disbanded my group, %s.", c->GetName()); else - botGroupLeader->Say("I was not able to disband my group, %s.", c->GetName()); + botGroupLeader->BotGroupSay(botGroupLeader, "I was not able to disband my group, %s.", c->GetName()); } else { - botGroupLeader->Say("I can not disband my group, %s, because I am not the leader. %s is the leader of my group.", c->GetName(), g->GetLeaderName()); + 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->Say("I am not a group leader, %s.", c->GetName()); + 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."); @@ -14633,7 +14634,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "Requires a value."); } } else { - c->Message(0,"A bot needs to be targetted."); + c->Message(0,"A bot needs to be targeted."); } return; } @@ -14667,11 +14668,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(taunt) { if(!targetedBot->taunting) - targetedBot->Say("I am now taunting."); + targetedBot->BotGroupSay(targetedBot, "I am now taunting."); } else { if(targetedBot->taunting) - targetedBot->Say("I am no longer taunting."); + targetedBot->BotGroupSay(targetedBot, "I am no longer taunting."); } targetedBot->SetTaunting(taunt); @@ -15944,7 +15945,7 @@ void EntityList::BotPickLock(Bot* rogue) if((skill+bonus1+bonus2) >= cdoor->GetLockpick()) cdoor->ForceOpen(rogue); else - rogue->Say("I am not skilled enough for this lock."); + rogue->BotGroupSay(rogue, "I am not skilled enough for this lock."); } } @@ -16369,9 +16370,7 @@ void Bot::SetDefaultBotStance() { _botStance = defaultStance; } -void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) -{ - +void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) { char buf[1000]; va_list ap; @@ -16384,6 +16383,8 @@ void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) if(g) g->GroupMessage(speaker->CastToMob(), 0, 100, buf); + } else { + speaker->Say("%s", buf); } } @@ -16408,7 +16409,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { //make sure we can use it.. if(!IsValidSpell(spell_id)) { - Say("Not a valid spell"); + BotGroupSay(this, "Not a valid spell"); return(false); } From 6ffe7a956319eadad56534963bccf8b06c203a26 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 19 Jun 2015 05:25:48 -0400 Subject: [PATCH 196/846] More bot changes. - Added #bot showhelm [on|off] - Allows you to disable your bot's helmet showing up --- zone/bot.cpp | 35 +++++++++++++++++++++++++++++++---- zone/bot.h | 3 +++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index c27ae20ce..4d3c0e75e 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -67,6 +67,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm SetHealRotationTimer(0); SetNumHealRotationMembers(0); SetBardUseOutOfCombatSongs(GetClass() == BARD); + SetShowHelm(true); CalcChanceToCast(); rest_timer.Disable(); @@ -4126,7 +4127,7 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { uint8 materialFromSlot = 0xFF; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); - if(itemID != 0) { + if(itemID != 0) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); if(materialFromSlot != 0xFF) this->SendWearChange(materialFromSlot); @@ -4359,7 +4360,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.is_npc = 0; // 0=no, 1=yes ns->spawn.is_pet = 0; ns->spawn.guildrank = 0; - ns->spawn.showhelm = 1; + ns->spawn.showhelm = GetShowHelm(); ns->spawn.flymode = 0; ns->spawn.size = 0; ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse @@ -4367,7 +4368,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { UpdateActiveLight(); ns->spawn.light = m_Light.Type.Active; - ns->spawn.helm = helmtexture; //0xFF; + ns->spawn.helm = (GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; const Item_Struct* item = 0; @@ -11428,7 +11429,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if (!results.Success()) return; - for (int i = 0; i < 7; i++) { + for (int i = 0; i < 7; i++) { uint8 slotmaterial = Inventory::CalcMaterialFromSlot((uint8)slots[i]); c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); } @@ -15616,6 +15617,32 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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); + c->Message(0, "Your bot will %s show their helmet.", (showhelm ? "now" : "no longer")); + } + } + } else + c->Message(0, "Usage #bot showhelm [on|off]"); + + return; + } } // franck: EQoffline diff --git a/zone/bot.h b/zone/bot.h index 25e0d1c52..19968c394 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -467,6 +467,7 @@ public: uint32 GetHealRotationNextHealTime() { return _healRotationNextHeal; } uint32 GetHealRotationTimer () { return _healRotationTimer; } bool GetBardUseOutOfCombatSongs() { return _bardUseOutOfCombatSongs;} + 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; } @@ -550,6 +551,7 @@ public: void SetHealRotationTimer( uint32 timer ) { _healRotationTimer = timer; } void SetNumHealRotationMembers( uint8 numMembers ) { _numHealRotationMembers = numMembers; } void SetBardUseOutOfCombatSongs(bool useOutOfCombatSongs) { _bardUseOutOfCombatSongs = useOutOfCombatSongs;} + void SetShowHelm(bool showhelm) { _showhelm = showhelm; } // Class Destructors virtual ~Bot(); @@ -622,6 +624,7 @@ private: std::map botAAs; InspectMessage_Struct _botInspectMessage; bool _bardUseOutOfCombatSongs; + bool _showhelm; // Private "base stats" Members int32 _baseMR; From c5609db8d12bdb36b65565cf0708bf86dc309a31 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 19 Jun 2015 15:53:20 -0400 Subject: [PATCH 197/846] Preferential bot formatting changes. --- zone/bot.cpp | 7785 ++++++++++++++++---------------------------------- 1 file changed, 2488 insertions(+), 5297 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 4d3c0e75e..9846173ba 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -13,19 +13,16 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm if(botOwner) { this->SetBotOwner(botOwner); this->_botOwnerCharacterID = botOwner->CharacterID(); - } - else { + } else { this->SetBotOwner(0); this->_botOwnerCharacterID = 0; } _guildRank = 0; _guildId = 0; - _lastTotalPlayTime = 0; _startTotalPlayTime = time(&_startTotalPlayTime); _lastZoneId = 0; - _baseMR = npcTypeData.MR; _baseCR = npcTypeData.CR; _baseDR = npcTypeData.DR; @@ -46,7 +43,6 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; - SetBotID(0); SetBotSpellID(0); SetSpawnStatus(false); @@ -70,53 +66,40 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm SetShowHelm(true); CalcChanceToCast(); rest_timer.Disable(); - SetFollowDistance(184); - // 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(); cur_end = CalcBaseEndurance(); - hp_regen = CalcHPRegen(); mana_regen = CalcManaRegen(); end_regen = CalcEnduranceRegen(); - - for (int i = 0; i < MaxTimer; i++) { + for (int i = 0; i < MaxTimer; i++) timers[i] = 0; - } - for(int i = 0; i < MaxHealRotationTargets; i++) { + for(int i = 0; i < MaxHealRotationTargets; i++) _healRotationTargets[i] = 0; - } strcpy(this->name, this->GetCleanName()); - memset(&m_Light, 0, sizeof(LightProfile_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) { this->_botOwnerCharacterID = botOwnerCharacterID; - - if(this->_botOwnerCharacterID > 0) { + if(this->_botOwnerCharacterID > 0) this->SetBotOwner(entity_list.GetClientByCharID(this->_botOwnerCharacterID)); - } _guildRank = 0; _guildId = 0; - _lastTotalPlayTime = totalPlayTime; _startTotalPlayTime = time(&_startTotalPlayTime); _lastZoneId = lastZoneId; berserk = false; - _baseMR = npcTypeData.MR; _baseCR = npcTypeData.CR; _baseDR = npcTypeData.DR; @@ -136,11 +119,9 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to _baseGender = npcTypeData.gender; cur_hp = npcTypeData.cur_hp; cur_mana = npcTypeData.Mana; - RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; - SetBotID(botID); SetBotSpellID(botSpellsID); SetSpawnStatus(false); @@ -164,61 +145,49 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetNumHealRotationMembers(0); CalcChanceToCast(); rest_timer.Disable(); - SetFollowDistance(184); - strcpy(this->name, this->GetCleanName()); - database.GetBotInspectMessage(this->GetBotID(), &_botInspectMessage); - LoadGuildMembership(&_guildId, &_guildRank, &_guildName); - std::string TempErrorMessage; - EquipBot(&TempErrorMessage); - if(!TempErrorMessage.empty()) { - // TODO: log error message to zone error log if(GetBotOwner()) GetBotOwner()->Message(13, TempErrorMessage.c_str()); } - for (int i = 0; i < MaxTimer; i++) { + for (int i = 0; i < MaxTimer; i++) timers[i] = 0; - } - for(int i = 0; i < MaxHealRotationTargets; i++) { + for(int i = 0; i < MaxHealRotationTargets; i++) _healRotationTargets[i] = 0; - } GenerateBaseStats(); - LoadTimers(); LoadAAs(); LoadBuffs(); - CalcBotStats(false); - hp_regen = CalcHPRegen(); mana_regen = CalcManaRegen(); end_regen = CalcEnduranceRegen(); - if(cur_hp > max_hp) cur_hp = max_hp; + if(cur_hp <= 0) { SetHP(max_hp/5); SetMana(0); BuffFadeAll(); SpellOnTarget(756, this); // Rezz effects } + if(cur_mana > max_mana) cur_mana = max_mana; + cur_end = max_end; } Bot::~Bot() { AI_Stop(); - if(HasGroup()) Bot::RemoveBotFromGroup(this, GetGroup()); @@ -237,57 +206,39 @@ void Bot::SetBotSpellID(uint32 newSpellID) { this->npc_spells_id = newSpellID; } -uint32 Bot::GetBotArcheryRange() -{ +uint32 Bot::GetBotArcheryRange() { const ItemInst *range_inst = GetBotItem(MainRange); const ItemInst *ammo_inst = GetBotItem(MainAmmo); - - // empty slots if (!range_inst || !ammo_inst) return 0; const Item_Struct *range_item = range_inst->GetItem(); const Item_Struct *ammo_item = ammo_inst->GetItem(); - - // no item struct for whatever reason - if (!range_item || !ammo_item) - return 0; - - // bad item types - if (range_item->ItemType != ItemTypeBow || ammo_item->ItemType != ItemTypeArrow) + if (!range_item || !ammo_item || range_item->ItemType != ItemTypeBow || ammo_item->ItemType != ItemTypeArrow) return 0; // everything is good! - return range_item->Range + ammo_item->Range; + return (range_item->Range + ammo_item->Range); } void Bot::ChangeBotArcherWeapons(bool isArcher) { - if((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) - || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) - { + if((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) { if(!isArcher) { BotAddEquipItem(MainPrimary, GetBotItemBySlot(MainPrimary)); BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainSecondary)); - //archerbot->SendWearChange(MATERIAL_PRIMARY); - //archerbot->SendWearChange(MATERIAL_SECONDARY); SetAttackTimer(); BotGroupSay(this, "My blade is ready."); - } - else { - //archerbot->SendWearChange(MATERIAL_PRIMARY); - //archerbot->SendWearChange(MATERIAL_SECONDARY); + } else { BotRemoveEquipItem(MainPrimary); BotRemoveEquipItem(MainSecondary); - //archerbot->SendBotArcheryWearChange(MATERIAL_PRIMARY, archeryMaterial, archeryColor); BotAddEquipItem(MainAmmo, GetBotItemBySlot(MainAmmo)); BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainRange)); SetAttackTimer(); BotGroupSay(this, "My bow is true and ready."); } } - else { + else BotGroupSay(this, "I don't know how to use a bow."); - } } void Bot::Sit() { @@ -306,7 +257,6 @@ void Bot::Stand() { bool Bot::IsSitting() { bool result = false; - if(GetAppearance() == eaSitting && !IsMoving()) result = true; @@ -315,7 +265,6 @@ bool Bot::IsSitting() { bool Bot::IsStanding() { bool result = false; - if(GetAppearance() == eaStanding) result = true; @@ -325,15 +274,12 @@ bool Bot::IsStanding() { NPCType Bot::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) { NPCType BotNPCType; int CopyLength = 0; - CopyLength = botName.copy(BotNPCType.name, 63); BotNPCType.name[CopyLength] = '\0'; CopyLength = 0; - CopyLength = botLastName.copy(BotNPCType.lastname, 69); BotNPCType.lastname[CopyLength] = '\0'; CopyLength = 0; - BotNPCType.npc_spells_id = botSpellsID; BotNPCType.level = botLevel; BotNPCType.race = botRace; @@ -367,7 +313,6 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str BotNPCType.WIS = wis; BotNPCType.CHA = cha; BotNPCType.ATK = attack; - BotNPCType.npc_id = 0; BotNPCType.texture = 0; BotNPCType.d_melee_texture1 = 0; @@ -380,29 +325,23 @@ 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 - return BotNPCType; } NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender) { NPCType Result; int CopyLength = 0; - CopyLength = botName.copy(Result.name, 63); Result.name[CopyLength] = '\0'; CopyLength = 0; - CopyLength = botLastName.copy(Result.lastname, 69); Result.lastname[CopyLength] = '\0'; CopyLength = 0; - Result.level = botLevel; Result.race = botRace; Result.class_ = botClass; Result.gender = gender; - // default values Result.maxlevel = botLevel; Result.size = 6.0; @@ -437,13 +376,11 @@ NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string b Result.CR = 25; Result.Corrup = 15; Result.AC = 12; - return Result; } void Bot::GenerateBaseStats() { int BotSpellID = 0; - // base stats uint32 Strength = _baseSTR; uint32 Stamina = _baseSTA; @@ -459,286 +396,284 @@ void Bot::GenerateBaseStats() { int32 PoisonResist = _basePR; int32 ColdResist = _baseCR; int32 CorruptionResist = _baseCorrup; - switch(this->GetClass()) { - case 1: // Warrior (why not just use 'case WARRIOR:'?) - Strength += 10; - Stamina += 20; - Agility += 10; - Dexterity += 10; - Attack += 12; - break; - case 2: // Cleric - BotSpellID = 701; - Strength += 5; - Stamina += 5; - Agility += 10; - Wisdom += 30; - Attack += 8; - break; - case 3: // Paladin - BotSpellID = 708; - Strength += 15; - Stamina += 5; - Wisdom += 15; - Charisma += 10; - Dexterity += 5; - Attack += 17; - break; - case 4: // Ranger - BotSpellID = 710; - Strength += 15; - Stamina += 10; - Agility += 10; - Wisdom += 15; - Attack += 17; - break; - case 5: // Shadowknight - BotSpellID = 709; - Strength += 10; - Stamina += 15; - Intelligence += 20; - Charisma += 5; - Attack += 17; - break; - case 6: // Druid - BotSpellID = 707; - Stamina += 15; - Wisdom += 35; - Attack += 5; - break; - case 7: // Monk - Strength += 5; - Stamina += 15; - Agility += 15; - Dexterity += 15; - Attack += 17; - break; - case 8: // Bard - BotSpellID = 711; - Strength += 15; - Dexterity += 10; - Charisma += 15; - Intelligence += 10; - Attack += 17; - break; - case 9: // Rogue - Strength += 10; - Stamina += 20; - Agility += 10; - Dexterity += 10; - Attack += 12; - break; - case 10: // Shaman - BotSpellID = 706; - Stamina += 10; - Wisdom += 30; - Charisma += 10; - Attack += 28; - break; - case 11: // Necromancer - BotSpellID = 703; - Dexterity += 10; - Agility += 10; - Intelligence += 30; - Attack += 5; - break; - case 12: // Wizard - BotSpellID = 702; - Stamina += 20; - Intelligence += 30; - Attack += 5; - break; - case 13: // Magician - BotSpellID = 704; - Stamina += 20; - Intelligence += 30; - Attack += 5; - break; - case 14: // Enchanter - BotSpellID = 705; - Intelligence += 25; - Charisma += 25; - Attack += 5; - break; - case 15: // Beastlord - BotSpellID = 712; - Stamina += 10; - Agility += 10; - Dexterity += 5; - Wisdom += 20; - Charisma += 5; - Attack += 31; - break; - case 16: // Berserker - Strength += 10; - Stamina += 15; - Dexterity += 15; - Agility += 10; - Attack += 25; - break; + case 1: // Warrior (why not just use 'case WARRIOR:'?) + Strength += 10; + Stamina += 20; + Agility += 10; + Dexterity += 10; + Attack += 12; + break; + case 2: // Cleric + BotSpellID = 701; + Strength += 5; + Stamina += 5; + Agility += 10; + Wisdom += 30; + Attack += 8; + break; + case 3: // Paladin + BotSpellID = 708; + Strength += 15; + Stamina += 5; + Wisdom += 15; + Charisma += 10; + Dexterity += 5; + Attack += 17; + break; + case 4: // Ranger + BotSpellID = 710; + Strength += 15; + Stamina += 10; + Agility += 10; + Wisdom += 15; + Attack += 17; + break; + case 5: // Shadowknight + BotSpellID = 709; + Strength += 10; + Stamina += 15; + Intelligence += 20; + Charisma += 5; + Attack += 17; + break; + case 6: // Druid + BotSpellID = 707; + Stamina += 15; + Wisdom += 35; + Attack += 5; + break; + case 7: // Monk + Strength += 5; + Stamina += 15; + Agility += 15; + Dexterity += 15; + Attack += 17; + break; + case 8: // Bard + BotSpellID = 711; + Strength += 15; + Dexterity += 10; + Charisma += 15; + Intelligence += 10; + Attack += 17; + break; + case 9: // Rogue + Strength += 10; + Stamina += 20; + Agility += 10; + Dexterity += 10; + Attack += 12; + break; + case 10: // Shaman + BotSpellID = 706; + Stamina += 10; + Wisdom += 30; + Charisma += 10; + Attack += 28; + break; + case 11: // Necromancer + BotSpellID = 703; + Dexterity += 10; + Agility += 10; + Intelligence += 30; + Attack += 5; + break; + case 12: // Wizard + BotSpellID = 702; + Stamina += 20; + Intelligence += 30; + Attack += 5; + break; + case 13: // Magician + BotSpellID = 704; + Stamina += 20; + Intelligence += 30; + Attack += 5; + break; + case 14: // Enchanter + BotSpellID = 705; + Intelligence += 25; + Charisma += 25; + Attack += 5; + break; + case 15: // Beastlord + BotSpellID = 712; + Stamina += 10; + Agility += 10; + Dexterity += 5; + Wisdom += 20; + Charisma += 5; + Attack += 31; + break; + case 16: // Berserker + Strength += 10; + Stamina += 15; + Dexterity += 15; + Agility += 10; + Attack += 25; + break; } float BotSize = GetSize(); switch(this->GetRace()) { - case 1: // Humans have no race bonus - break; - case 2: // Barbarian - Strength += 28; - Stamina += 20; - Agility += 7; - Dexterity -= 5; - Wisdom -= 5; - Intelligence -= 10; - Charisma -= 20; - BotSize = 7.0; - ColdResist += 10; - break; - case 3: // Erudite - Strength -= 15; - Stamina -= 5; - Agility -= 5; - Dexterity -= 5; - Wisdom += 8; - Intelligence += 32; - Charisma -= 5; - MagicResist += 5; - DiseaseResist -= 5; - break; - case 4: // Wood Elf - Strength -= 10; - Stamina -= 10; - Agility += 20; - Dexterity += 5; - Wisdom += 5; - BotSize = 5.0; - break; - case 5: // High Elf - Strength -= 20; - Stamina -= 10; - Agility += 10; - Dexterity -= 5; - Wisdom += 20; - Intelligence += 12; - Charisma += 5; - break; - case 6: // Dark Elf - Strength -= 15; - Stamina -= 10; - Agility += 15; - Wisdom += 8; - Intelligence += 24; - Charisma -= 15; - BotSize = 5.0; - break; - case 7: // Half Elf - Strength -= 5; - Stamina -= 5; - Agility += 15; - Dexterity += 10; - Wisdom -= 15; - BotSize = 5.5; - break; - case 8: // Dwarf - Strength += 15; - Stamina += 15; - Agility -= 5; - Dexterity += 15; - Wisdom += 8; - Intelligence -= 15; - Charisma -= 30; - BotSize = 4.0; - MagicResist -= 5; - PoisonResist += 5; - break; - case 9: // Troll - Strength += 33; - Stamina += 34; - Agility += 8; - Wisdom -= 15; - Intelligence -= 23; - Charisma -= 35; - BotSize = 8.0; - FireResist -= 20; - break; - case 10: // Ogre - Strength += 55; - Stamina += 77; - Agility -= 5; - Dexterity -= 5; - Wisdom -= 8; - Intelligence -= 15; - Charisma -= 38; - BotSize = 9.0; - break; - case 11: // Halfling - Strength -= 5; - Agility += 20; - Dexterity += 15; - Wisdom += 5; - Intelligence -= 8; - Charisma -= 25; - BotSize = 3.5; - PoisonResist += 5; - DiseaseResist += 5; - break; - case 12: // Gnome - Strength -= 15; - Stamina -= 5; - Agility += 10; - Dexterity += 10; - Wisdom -= 8; - Intelligence += 23; - Charisma -= 15; - BotSize = 3.0; - break; - case 128: // Iksar - Strength -= 5; - Stamina -= 5; - Agility += 15; - Dexterity += 10; - Wisdom += 5; - Charisma -= 20; - MagicResist -= 5; - FireResist -= 5; - break; - case 130: // Vah Shir - Strength += 15; - Agility += 15; - Dexterity -= 5; - Wisdom -= 5; - Intelligence -= 10; - Charisma -= 10; - BotSize = 7.0; - MagicResist -= 5; - FireResist -= 5; - break; - case 330: // Froglok - Strength -= 5; - Stamina += 5; - Agility += 25; - Dexterity += 25; - Charisma -= 25; - BotSize = 5.0; - MagicResist -= 5; - FireResist -= 5; - break; - case 522: // Drakkin - Strength -= 5; - Stamina += 5; - Agility += 10; - Intelligence += 10; - Wisdom += 5; - BotSize = 5.0; - PoisonResist += 2; - DiseaseResist += 2; - MagicResist += 2; - FireResist += 2; - ColdResist += 2; - break; + case 1: // Humans have no race bonus + break; + case 2: // Barbarian + Strength += 28; + Stamina += 20; + Agility += 7; + Dexterity -= 5; + Wisdom -= 5; + Intelligence -= 10; + Charisma -= 20; + BotSize = 7.0; + ColdResist += 10; + break; + case 3: // Erudite + Strength -= 15; + Stamina -= 5; + Agility -= 5; + Dexterity -= 5; + Wisdom += 8; + Intelligence += 32; + Charisma -= 5; + MagicResist += 5; + DiseaseResist -= 5; + break; + case 4: // Wood Elf + Strength -= 10; + Stamina -= 10; + Agility += 20; + Dexterity += 5; + Wisdom += 5; + BotSize = 5.0; + break; + case 5: // High Elf + Strength -= 20; + Stamina -= 10; + Agility += 10; + Dexterity -= 5; + Wisdom += 20; + Intelligence += 12; + Charisma += 5; + break; + case 6: // Dark Elf + Strength -= 15; + Stamina -= 10; + Agility += 15; + Wisdom += 8; + Intelligence += 24; + Charisma -= 15; + BotSize = 5.0; + break; + case 7: // Half Elf + Strength -= 5; + Stamina -= 5; + Agility += 15; + Dexterity += 10; + Wisdom -= 15; + BotSize = 5.5; + break; + case 8: // Dwarf + Strength += 15; + Stamina += 15; + Agility -= 5; + Dexterity += 15; + Wisdom += 8; + Intelligence -= 15; + Charisma -= 30; + BotSize = 4.0; + MagicResist -= 5; + PoisonResist += 5; + break; + case 9: // Troll + Strength += 33; + Stamina += 34; + Agility += 8; + Wisdom -= 15; + Intelligence -= 23; + Charisma -= 35; + BotSize = 8.0; + FireResist -= 20; + break; + case 10: // Ogre + Strength += 55; + Stamina += 77; + Agility -= 5; + Dexterity -= 5; + Wisdom -= 8; + Intelligence -= 15; + Charisma -= 38; + BotSize = 9.0; + break; + case 11: // Halfling + Strength -= 5; + Agility += 20; + Dexterity += 15; + Wisdom += 5; + Intelligence -= 8; + Charisma -= 25; + BotSize = 3.5; + PoisonResist += 5; + DiseaseResist += 5; + break; + case 12: // Gnome + Strength -= 15; + Stamina -= 5; + Agility += 10; + Dexterity += 10; + Wisdom -= 8; + Intelligence += 23; + Charisma -= 15; + BotSize = 3.0; + break; + case 128: // Iksar + Strength -= 5; + Stamina -= 5; + Agility += 15; + Dexterity += 10; + Wisdom += 5; + Charisma -= 20; + MagicResist -= 5; + FireResist -= 5; + break; + case 130: // Vah Shir + Strength += 15; + Agility += 15; + Dexterity -= 5; + Wisdom -= 5; + Intelligence -= 10; + Charisma -= 10; + BotSize = 7.0; + MagicResist -= 5; + FireResist -= 5; + break; + case 330: // Froglok + Strength -= 5; + Stamina += 5; + Agility += 25; + Dexterity += 25; + Charisma -= 25; + BotSize = 5.0; + MagicResist -= 5; + FireResist -= 5; + break; + case 522: // Drakkin + Strength -= 5; + Stamina += 5; + Agility += 10; + Intelligence += 10; + Wisdom += 5; + BotSize = 5.0; + PoisonResist += 2; + DiseaseResist += 2; + MagicResist += 2; + FireResist += 2; + ColdResist += 2; + break; } - this->STR = Strength; this->STA = Stamina; this->DEX = Dexterity; @@ -756,7 +691,6 @@ void Bot::GenerateBaseStats() { this->Corrup = CorruptionResist; SetBotSpellID(BotSpellID); this->size = BotSize; - this->pAggroRange = 0; this->pAssistRange = 0; this->raid_target = false; @@ -765,12 +699,10 @@ void Bot::GenerateBaseStats() { void Bot::GenerateAppearance() { // Randomize facial appearance int iFace = 0; - if(this->GetRace() == 2) { // Barbarian w/Tatoo + if(this->GetRace() == 2) // Barbarian w/Tatoo iFace = zone->random.Int(0, 79); - } - else { + else iFace = zone->random.Int(0, 7); - } int iHair = 0; int iBeard = 0; @@ -779,40 +711,32 @@ void Bot::GenerateAppearance() { iHair = zone->random.Int(0, 8); iBeard = zone->random.Int(0, 11); iBeardColor = zone->random.Int(0, 3); - } - else if(this->GetGender()) { + } else if(this->GetGender()) { iHair = zone->random.Int(0, 2); if(this->GetRace() == 8) { // Dwarven Females can have a beard - if(zone->random.Int(1, 100) < 50) { + if(zone->random.Int(1, 100) < 50) iFace += 10; - } } - } - else { + } else { iHair = zone->random.Int(0, 3); iBeard = zone->random.Int(0, 5); iBeardColor = zone->random.Int(0, 19); } int iHairColor = 0; - if(this->GetRace() == 522) { + if(this->GetRace() == 522) iHairColor = zone->random.Int(0, 3); - } - else { + else iHairColor = zone->random.Int(0, 19); - } uint8 iEyeColor1 = (uint8)zone->random.Int(0, 9); uint8 iEyeColor2 = 0; - if(this->GetRace() == 522) { + if(this->GetRace() == 522) iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11); - } - else if(zone->random.Int(1, 100) > 96) { + else if(zone->random.Int(1, 100) > 96) iEyeColor2 = zone->random.Int(0, 9); - } - else { + else iEyeColor2 = iEyeColor1; - } int iHeritage = 0; int iTattoo = 0; @@ -822,7 +746,6 @@ void Bot::GenerateAppearance() { iTattoo = zone->random.Int(0, 7); iDetails = zone->random.Int(0, 7); } - this->luclinface = iFace; this->hairstyle = iHair; this->beard = iBeard; @@ -833,77 +756,71 @@ void Bot::GenerateAppearance() { this->drakkin_heritage = iHeritage; this->drakkin_tattoo = iTattoo; this->drakkin_details = iDetails; - } -int32 Bot::acmod() -{ +int32 Bot::acmod() { int agility = GetAGI(); int level = GetLevel(); if(agility < 1 || level < 1) return 0; - if(agility <= 74) - { + if(agility <= 74) { if(agility == 1) return -24; - else if(agility <=3) + else if(agility <= 3) return -23; else if(agility == 4) return -22; - else if(agility <=6) + else if(agility <= 6) return -21; - else if(agility <=8) + else if(agility <= 8) return -20; else if(agility == 9) return -19; - else if(agility <=11) + else if(agility <= 11) return -18; else if(agility == 12) return -17; - else if(agility <=14) + else if(agility <= 14) return -16; - else if(agility <=16) + else if(agility <= 16) return -15; else if(agility == 17) return -14; - else if(agility <=19) + else if(agility <= 19) return -13; else if(agility == 20) return -12; - else if(agility <=22) + else if(agility <= 22) return -11; - else if(agility <=24) + else if(agility <= 24) return -10; else if(agility == 25) return -9; - else if(agility <=27) + else if(agility <= 27) return -8; else if(agility == 28) return -7; - else if(agility <=30) + else if(agility <= 30) return -6; - else if(agility <=32) + else if(agility <= 32) return -5; else if(agility == 33) return -4; - else if(agility <=35) + else if(agility <= 35) return -3; else if(agility == 36) return -2; - else if(agility <=38) + else if(agility <= 38) return -1; - else if(agility <=65) + else if(agility <= 65) return 0; - else if(agility <=70) + else if(agility <= 70) return 1; - else if(agility <=74) + else if(agility <= 74) return 5; - } - else if(agility <= 137) - { - if(agility == 75) - { + } else if(agility <= 137) { + if(agility == 75) { if(level <= 6) return 9; else if(level <= 19) @@ -912,9 +829,7 @@ int32 Bot::acmod() return 33; else return 39; - } - else if(agility >= 76 && agility <= 79) - { + } else if(agility >= 76 && agility <= 79) { if(level <= 6) return 10; else if(level <= 19) @@ -923,9 +838,7 @@ int32 Bot::acmod() return 33; else return 40; - } - else if(agility == 80) - { + } else if(agility == 80) { if(level <= 6) return 11; else if(level <= 19) @@ -934,9 +847,7 @@ int32 Bot::acmod() return 34; else return 41; - } - else if(agility >= 81 && agility <= 85) - { + } else if(agility >= 81 && agility <= 85) { if(level <= 6) return 12; else if(level <= 19) @@ -945,9 +856,7 @@ int32 Bot::acmod() return 35; else return 42; - } - else if(agility >= 86 && agility <= 90) - { + } else if(agility >= 86 && agility <= 90) { if(level <= 6) return 12; else if(level <= 19) @@ -956,9 +865,7 @@ int32 Bot::acmod() return 36; else return 42; - } - else if(agility >= 91 && agility <= 95) - { + } else if(agility >= 91 && agility <= 95) { if(level <= 6) return 13; else if(level <= 19) @@ -967,8 +874,7 @@ int32 Bot::acmod() return 36; else return 43; - } - else if(agility >= 96 && agility <= 99){ + } else if(agility >= 96 && agility <= 99) { if(level <= 6) return 14; else if(level <= 19) @@ -977,9 +883,7 @@ int32 Bot::acmod() return 37; else return 44; - } - else if(agility == 100 && level >= 7) - { + } else if(agility == 100 && level >= 7) { if(level <= 19) return 28; else if (level <= 39) @@ -988,39 +892,30 @@ int32 Bot::acmod() return 45; } else if(level <= 6) - { return 15; - } //level is >6 - else if(agility >= 101 && agility <= 105) - { + else if(agility >= 101 && agility <= 105) { if(level <= 19) return 29; else if(level <= 39) return 39;// not verified else return 45; - } - else if(agility >= 106 && agility <= 110) - { + } else if(agility >= 106 && agility <= 110) { if(level <= 19) return 29; else if(level <= 39) return 39;// not verified else return 46; - } - else if(agility >= 111 && agility <= 115) - { + } else if(agility >= 111 && agility <= 115) { if(level <= 19) return 30; else if(level <= 39) return 40;// not verified else return 47; - } - else if(agility >= 116 && agility <= 119) - { + } else if(agility >= 116 && agility <= 119) { if(level <= 19) return 31; else if(level <= 39) @@ -1029,307 +924,269 @@ int32 Bot::acmod() return 47; } else if(level <= 19) - { return 32; - } //level is > 19 - else if(agility == 120) - { + else if(agility == 120) { if(level <= 39) return 42; else return 48; - } - else if(agility <= 125) - { + } else if(agility <= 125) { if(level <= 39) return 42; else return 49; - } - else if(agility <= 135) - { + } else if(agility <= 135) { if(level <= 39) return 42; else return 50; - } - else { + } else { if(level <= 39) return 42; else return 51; } - } - else if(agility <= 300) - { + } else if(agility <= 300) { if(level <= 6) { if(agility <= 139) - return(21); + return 21; else if(agility == 140) - return(22); + return 22; else if(agility <= 145) - return(23); + return 23; else if(agility <= 150) - return(23); + return 23; else if(agility <= 155) - return(24); + return 24; else if(agility <= 159) - return(25); + return 25; else if(agility == 160) - return(26); + return 26; else if(agility <= 165) - return(26); + return 26; else if(agility <= 170) - return(27); + return 27; else if(agility <= 175) - return(28); + return 28; else if(agility <= 179) - return(28); + return 28; else if(agility == 180) - return(29); + return 29; else if(agility <= 185) - return(30); + return 30; else if(agility <= 190) - return(31); + return 31; else if(agility <= 195) - return(31); + return 31; else if(agility <= 199) - return(32); + return 32; else if(agility <= 219) - return(33); + return 33; else if(agility <= 239) - return(34); + return 34; else - return(35); - } - else if(level <= 19) - { + return 35; + } else if(level <= 19) { if(agility <= 139) - return(34); + return 34; else if(agility == 140) - return(35); + return 35; else if(agility <= 145) - return(36); + return 36; else if(agility <= 150) - return(37); + return 37; else if(agility <= 155) - return(37); + return 37; else if(agility <= 159) - return(38); + return 38; else if(agility == 160) - return(39); + return 39; else if(agility <= 165) - return(40); + return 40; else if(agility <= 170) - return(40); + return 40; else if(agility <= 175) - return(41); + return 41; else if(agility <= 179) - return(42); + return 42; else if(agility == 180) - return(43); + return 43; else if(agility <= 185) - return(43); + return 43; else if(agility <= 190) - return(44); + return 44; else if(agility <= 195) - return(45); + return 45; else if(agility <= 199) - return(45); + return 45; else if(agility <= 219) - return(46); + return 46; else if(agility <= 239) - return(47); + return 47; else - return(48); - } - else if(level <= 39) - { + return 48; + } else if(level <= 39) { if(agility <= 139) - return(44); + return 44; else if(agility == 140) - return(45); + return 45; else if(agility <= 145) - return(46); + return 46; else if(agility <= 150) - return(47); + return 47; else if(agility <= 155) - return(47); + return 47; else if(agility <= 159) - return(48); + return 48; else if(agility == 160) - return(49); + return 49; else if(agility <= 165) - return(50); + return 50; else if(agility <= 170) - return(50); + return 50; else if(agility <= 175) - return(51); + return 51; else if(agility <= 179) - return(52); + return 52; else if(agility == 180) - return(53); + return 53; else if(agility <= 185) - return(53); + return 53; else if(agility <= 190) - return(54); + return 54; else if(agility <= 195) - return(55); + return 55; else if(agility <= 199) - return(55); + return 55; else if(agility <= 219) - return(56); + return 56; else if(agility <= 239) - return(57); + return 57; else - return(58); - } - else - { //lvl >= 40 + return 58; + } else { //lvl >= 40 if(agility <= 139) - return(51); + return 51; else if(agility == 140) - return(52); + return 52; else if(agility <= 145) - return(53); + return 53; else if(agility <= 150) - return(53); + return 53; else if(agility <= 155) - return(54); + return 54; else if(agility <= 159) - return(55); + return 55; else if(agility == 160) - return(56); + return 56; else if(agility <= 165) - return(56); + return 56; else if(agility <= 170) - return(57); + return 57; else if(agility <= 175) - return(58); + return 58; else if(agility <= 179) - return(58); + return 58; else if(agility == 180) - return(59); + return 59; else if(agility <= 185) - return(60); + return 60; else if(agility <= 190) - return(61); + return 61; else if(agility <= 195) - return(61); + return 61; else if(agility <= 199) - return(62); + return 62; else if(agility <= 219) - return(63); + return 63; else if(agility <= 239) - return(64); + return 64; else - return(65); + return 65; } } else - { - //seems about 21 agil per extra AC pt over 300... - return (65 + ((agility-300) / 21)); - } + return (65 + ((agility - 300) / 21)); #if EQDEBUG >= 11 Log.Out(Logs::General, Logs::Error, "Error in Bot::acmod(): Agility: %i, Level: %i",agility,level); #endif return 0; } -void Bot::GenerateArmorClass() -{ +void Bot::GenerateArmorClass() { /// new formula int avoidance = 0; - avoidance = (acmod() + ((GetSkill(SkillDefense)*16)/9)); + avoidance = (acmod() + ((GetSkill(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); + if(GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == NECROMANCER || GetClass() == ENCHANTER) { + mitigation = (GetSkill(SkillDefense) / 4 + (itembonuses.AC + 1)); mitigation -= 4; - } - else - { - mitigation = GetSkill(SkillDefense)/3 + ((itembonuses.AC*4)/3); + } else { + mitigation = (GetSkill(SkillDefense) / 3 + ((itembonuses.AC * 4) / 3)); if(GetClass() == MONK) - mitigation += GetLevel() * 13/10; //the 13/10 might be wrong, but it is close... + mitigation += (GetLevel() * 13 / 10); //the 13/10 might be wrong, but it is close... } int displayed = 0; - displayed += ((avoidance+mitigation)*1000)/847; //natural AC + displayed += (((avoidance + mitigation) * 1000) / 847); //natural AC //Iksar AC, untested - if(GetRace() == IKSAR) - { + if(GetRace() == IKSAR) { displayed += 12; int iksarlevel = GetLevel(); iksarlevel -= 10; if(iksarlevel > 25) iksarlevel = 25; + if(iksarlevel > 0) - displayed += iksarlevel * 12 / 10; + displayed += (iksarlevel * 12 / 10); } //spell AC bonuses are added directly to natural total displayed += spellbonuses.AC; - this->AC = displayed; } -uint16 Bot::GetPrimarySkillValue() -{ +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); - if(!equiped) - { skill = SkillHandtoHand; - } - else - { + else { uint8 type = m_inv.GetItem(MainPrimary)->GetItem()->ItemType; //is this the best way to do this? - switch(type) - { - case ItemType1HSlash: // 1H Slashing - { + switch(type) { + case ItemType1HSlash: { skill = Skill1HSlashing; break; } - case ItemType2HSlash: // 2H Slashing - { + case ItemType2HSlash: { skill = Skill2HSlashing; break; } - case ItemType1HPiercing: // Piercing - { + case ItemType1HPiercing: { skill = Skill1HPiercing; break; } - case ItemType1HBlunt: // 1H Blunt - { + case ItemType1HBlunt: { skill = Skill1HBlunt; break; } - case ItemType2HBlunt: // 2H Blunt - { + case ItemType2HBlunt: { skill = Skill2HBlunt; break; } - case ItemType2HPiercing: // 2H Piercing - { + case ItemType2HPiercing: { skill = Skill1HPiercing; // change to Skill2HPiercing once activated break; } - case ItemTypeMartial: // Hand to Hand - { + case ItemTypeMartial: { skill = SkillHandtoHand; break; } - default: // All other types default to Hand to Hand - { + default: { skill = SkillHandtoHand; break; } @@ -1343,15 +1200,12 @@ uint16 Bot::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const { return(database.GetSkillCap(class_, skillid, level)); } -uint32 Bot::GetTotalATK() -{ +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 += aabonuses.ATK + GroupLeadershipAAOffenseEnhancement(); - if (AttackRating < 10) AttackRating = 10; } @@ -1359,34 +1213,27 @@ uint32 Bot::GetTotalATK() AttackRating = GetATK(); AttackRating += spellbonuses.ATK; - return AttackRating; } -uint32 Bot::GetATKRating() -{ +uint32 Bot::GetATKRating() { uint32 AttackRating = 0; if(IsBot()) { AttackRating = (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69); - if (AttackRating < 10) AttackRating = 10; } return AttackRating; } -int32 Bot::GenerateBaseHitPoints() -{ +int32 Bot::GenerateBaseHitPoints() { // Calc Base Hit Points int new_base_hp = 0; 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()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { float SoDPost255; - if(((NormalSTA - 255) / 2) > 0) SoDPost255 = ((NormalSTA - 255) / 2); else @@ -1395,33 +1242,20 @@ int32 Bot::GenerateBaseHitPoints() int hp_factor = GetClassHPFactor(); if(level < 41) - { new_base_hp = (5 + (GetLevel() * hp_factor / 12) + ((NormalSTA - SoDPost255) * GetLevel() * hp_factor / 3600)); - } else if(level < 81) - { - new_base_hp = (5 + (40 * hp_factor / 12) + ((GetLevel() - 40) * hp_factor / 6) + - ((NormalSTA - SoDPost255) * hp_factor / 90) + - ((NormalSTA - SoDPost255) * (GetLevel() - 40) * hp_factor / 1800)); - } + new_base_hp = (5 + (40 * hp_factor / 12) + ((GetLevel() - 40) * hp_factor / 6) + ((NormalSTA - SoDPost255) * hp_factor / 90) + ((NormalSTA - SoDPost255) * (GetLevel() - 40) * hp_factor / 1800)); else - { - new_base_hp = (5 + (80 * hp_factor / 8) + ((GetLevel() - 80) * hp_factor / 10) + - ((NormalSTA - SoDPost255) * hp_factor / 90) + - ((NormalSTA - SoDPost255) * hp_factor / 45)); - } - } - else - { - if((NormalSTA-255)/2 > 0) - Post255 = (NormalSTA-255)/2; + new_base_hp = (5 + (80 * hp_factor / 8) + ((GetLevel() - 80) * hp_factor / 10) + ((NormalSTA - SoDPost255) * hp_factor / 90) + ((NormalSTA - SoDPost255) * hp_factor / 45)); + } else { + if(((NormalSTA - 255) / 2) > 0) + Post255 = ((NormalSTA - 255) / 2); else Post255 = 0; - new_base_hp = (5)+(GetLevel()*lm/10) + (((NormalSTA-Post255)*GetLevel()*lm/3000)) + ((Post255*1)*lm/6000); + new_base_hp = (5) + (GetLevel() * lm / 10) + (((NormalSTA - Post255) * GetLevel() * lm / 3000)) + ((Post255 * 1) * lm / 6000); } this->base_hp = new_base_hp; - return new_base_hp; } @@ -1429,12 +1263,9 @@ void Bot::GenerateAABonuses(StatBonuses* newbon) { // General AA bonus uint8 botClass = GetClass(); uint8 botLevel = GetLevel(); - memset(newbon, 0, sizeof(StatBonuses)); //start fresh - if(botLevel >= 51) { //level 51 = 1 AA level - int i; int totalAAs = database.CountAAs(); uint32 slots = 0; @@ -1449,7 +1280,7 @@ void Bot::GenerateAABonuses(StatBonuses* newbon) { //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 + aa_value -1, slots, newbon); //add the bonuses + ApplyAABonuses((aa_AA + aa_value - 1), slots, newbon); //add the bonuses } } } @@ -1461,25 +1292,21 @@ void Bot::LoadAAs() { botAAs.clear(); //start fresh std::string query; - if(GetClass() == BERSERKER) query = StringFormat("SELECT skill_id FROM altadv_vars WHERE berserker = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetLevel(), maxAAExpansion); else query = StringFormat("SELECT skill_id FROM altadv_vars WHERE ((classes & ( 1 << %i )) >> %i) = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetClass(), GetClass(), GetLevel(), maxAAExpansion); auto results = database.QueryDatabase(query); - if(!results.Success()) { Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadAAs()"); return; } int totalAAs = database.CountAAs(); - for (auto row = results.begin(); row != results.end(); ++row) { uint32 skill_id = 0; skill_id = atoi(row[0]); - if(skill_id <= 0 || skill_id >= totalAAs) continue; @@ -1490,11 +1317,10 @@ void Bot::LoadAAs() { for(int i=0; imax_level; i++) { //Get AA info & add to list - uint32 aaid = sendAA->id + i; + uint32 aaid = (sendAA->id + i); uint8 total_levels = 0; uint8 req_level; std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(aaid); - //Get level required for AA if(RequiredLevel != AARequiredLevelAndCost.end()) req_level = RequiredLevel->second.Level; @@ -1506,43 +1332,36 @@ void Bot::LoadAAs() { //Bot is high enough level for AA std::map::iterator foundAA = botAAs.find(aaid); - // AA is already in list if(foundAA != botAAs.end()) continue; if(sendAA->id == aaid) { BotAA newAA; - newAA.total_levels = 0; newAA.aa_id = aaid; newAA.req_level = req_level; newAA.total_levels += 1; - botAAs[aaid] = newAA; //add to list } else //update master AA record with number of levels a bot has in AA, based on level. - botAAs[sendAA->id].total_levels+=1; + botAAs[sendAA->id].total_levels += 1; } } } uint32 Bot::GetAA(uint32 aa_id) { - std::map::const_iterator find_iter = botAAs.find(aa_id); int aaLevel = 0; - - if(find_iter != botAAs.end()) { + if(find_iter != botAAs.end()) aaLevel = find_iter->second.total_levels; - } return aaLevel; } //current with Client::ApplyAABonuses 9/26/12 -void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) -{ +void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) { if(slots == 0) //sanity check. why bother if no slots to fill? return; @@ -1551,38 +1370,27 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) 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) + if ((effect == 0 && base1 == 0 && base2 == 0) || effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) continue; Log.Out(Logs::Detail, Logs::AA, "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) - { + uint8 focus = IsFocusEffect(0, 0, true, effect); + if (focus) { newbon->FocusEffects[focus] = effect; continue; } - switch (effect) - { + 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)) @@ -1597,9 +1405,7 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) 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;*/ + newbon->movementspeed += base1; break; case SE_STR: newbon->STR += base1; @@ -1664,8 +1470,7 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_SetBreathLevel: break; case SE_RaiseStatCap: - switch(base2) - { + switch(base2) { //are these #define'd somewhere? case 0: //str newbon->STRCapMod += base1; @@ -1880,216 +1685,169 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_UnfailingDivinity: newbon->UnfailingDivinity += 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))) - { + 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; + newbon->SpellOnKill[i + 1] = base1; if (GetLevel() > 15) - newbon->SpellOnKill[i+2] = GetLevel() - 15; //AA specifiy "non-trivial" + newbon->SpellOnKill[i + 2] = (GetLevel() - 15); //AA specifiy "non-trivial" else - newbon->SpellOnKill[i+2] = 0; + 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]) - { + 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; + newbon->SpellOnDeath[i + 1] = base2; break; } } - break; - - case SE_TriggerOnCast: - - for(int i = 0; i < MAX_SPELL_TRIGGER; i++) - { + break; + } + case SE_TriggerOnCast: { + for(int i = 0; i < MAX_SPELL_TRIGGER; i++) { if (newbon->SpellTriggers[i] == aaid) break; - if(!newbon->SpellTriggers[i]) - { + if(!newbon->SpellTriggers[i]) { //Save the 'aaid' of each triggerable effect to an array newbon->SpellTriggers[i] = aaid; break; } } - break; - - case SE_CriticalHitChance: - { + break; + } + case SE_CriticalHitChance: { if(base2 == -1) newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1; else newbon->CriticalHitChance[base2] += base1; + break; } - break; - - case SE_CriticalDamageMob: - { + case SE_CriticalDamageMob: { // base1 = effect value, base2 = skill restrictions(-1 for all) if(base2 == -1) - newbon->CritDmgMob[HIGHEST_SKILL+1] += base1; + newbon->CritDmgMob[HIGHEST_SKILL + 1] += base1; else newbon->CritDmgMob[base2] += base1; break; } - - case SE_CriticalSpellChance: - { + case SE_CriticalSpellChance: { newbon->CriticalSpellChance += base1; - if (base2 > newbon->SpellCritDmgIncrease) newbon->SpellCritDmgIncrease = base2; break; } - - case SE_ResistFearChance: - { + 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: - { + case SE_SkillDamageAmount: { if(base2 == -1) - newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1; + newbon->SkillDamageAmount[HIGHEST_SKILL + 1] += base1; else newbon->SkillDamageAmount[base2] += base1; break; } - - case SE_SpecialAttackKBProc: - { + 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: - { + case SE_DamageModifier: { if(base2 == -1) - newbon->DamageModifier[HIGHEST_SKILL+1] += base1; + newbon->DamageModifier[HIGHEST_SKILL + 1] += base1; else newbon->DamageModifier[base2] += base1; break; } - - case SE_SlayUndead: - { + case SE_SlayUndead: { if(newbon->SlayUndead[1] < base1) newbon->SlayUndead[0] = base1; // Rate newbon->SlayUndead[1] = base2; // Damage Modifier break; } - - case SE_GiveDoubleRiposte: - { + case SE_GiveDoubleRiposte: { //0=Regular Riposte 1=Skill Attack Riposte 2=Skill - if(base2 == 0){ + if(base2 == 0) { if(newbon->GiveDoubleRiposte[0] < base1) newbon->GiveDoubleRiposte[0] = base1; } //Only for special attacks. - else if(base2 > 0 && (newbon->GiveDoubleRiposte[1] < base1)){ + 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){ + case SE_RaiseSkillCap: { + if(newbon->RaiseSkillCap[0] < base1) { newbon->RaiseSkillCap[0] = base1; //value newbon->RaiseSkillCap[1] = base2; //skill } break; } - - case SE_MasteryofPast: - { + case SE_MasteryofPast: { if(newbon->MasteryofPast < base1) newbon->MasteryofPast = base1; break; } - case SE_CastingLevel2: - case SE_CastingLevel: - { + case SE_CastingLevel: { newbon->effective_casting_level += base1; break; } - - - case SE_DivineSave: - { - if(newbon->DivineSaveChance[0] < base1) - { + 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] || ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < base1)) ){ + case SE_SpellEffectResistChance: { + for(int e = 0; e < (MAX_RESISTABLE_EFFECTS * 2); e += 2) { + if(!newbon->SEResist[e] || ((newbon->SEResist[e] = base2) && (newbon->SEResist[e + 1] < base1)) ){ newbon->SEResist[e] = base2; - newbon->SEResist[e+1] = base1; - break; + newbon->SEResist[e + 1] = base1; + break; } } break; } - - case SE_MitigateDamageShield: - { + case SE_MitigateDamageShield: { if (base1 < 0) - base1 = base1*(-1); + base1 = (base1 * -1); newbon->DSMitigationOffHand += base1; break; } - - case SE_FinishingBlow: - { - + case SE_FinishingBlow: { //base1 = chance, base2 = damage - if (newbon->FinishingBlow[1] < base2){ + if (newbon->FinishingBlow[1] < base2) { newbon->FinishingBlow[0] = base1; newbon->FinishingBlow[1] = base2; } break; } - - case SE_FinishingBlowLvl: - { + case SE_FinishingBlowLvl: { //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) - if (newbon->FinishingBlowLvl[0] < base1){ + if (newbon->FinishingBlowLvl[0] < base1) { newbon->FinishingBlowLvl[0] = base1; newbon->FinishingBlowLvl[1] = base2; } @@ -2321,18 +2079,16 @@ bool Bot::IsValidName() { std::string TempBotName = std::string(this->GetCleanName()); for(int iCounter = 0; iCounter < TempBotName.length(); iCounter++) { - if(isalpha(TempBotName[iCounter]) || TempBotName[iCounter] == '_') { + if(isalpha(TempBotName[iCounter]) || TempBotName[iCounter] == '_') Result = true; - } } return Result; } bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { - if (botName == "" || strlen(botName) > 15 || !database.CheckNameFilter(botName) || !database.CheckUsedName(botName)) { - return false; //Check if Botname is Empty / Check if Botname larger than 15 char / Valid to Player standards / Not used by a player! - } + if (botName == "" || strlen(botName) > 15 || !database.CheckNameFilter(botName) || !database.CheckUsedName(botName)) + return false; std::string query = StringFormat("SELECT id FROM vwBotCharacterMobs WHERE name LIKE '%s'", botName); auto results = database.QueryDatabase(query); @@ -2340,15 +2096,14 @@ bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { *errorMessage = std::string(results.ErrorMessage()); return false; } - if (results.RowCount()) { //Name already in use! + + 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 bots (BotOwnerCharacterID, BotSpellsID, Name, LastName, " @@ -2374,6 +2129,7 @@ bool Bot::Save() { auto botOwner = GetBotOwner(); if (botOwner) botOwner->Message(13, results.ErrorMessage().c_str()); + return false; } @@ -2412,36 +2168,28 @@ bool Bot::Save() { auto botOwner = GetBotOwner(); if (botOwner) botOwner->Message(13, results.ErrorMessage().c_str()); + return false; } - SaveBuffs(); SavePet(); SaveStance(); SaveTimers(); - return true; } // Returns the current total play time for the bot uint32 Bot::GetTotalPlayTime() { uint32 Result = 0; - double TempTotalPlayTime = 0; - time_t currentTime = time(¤tTime); - TempTotalPlayTime = difftime(currentTime, _startTotalPlayTime); - TempTotalPlayTime += _lastTotalPlayTime; - Result = (uint32)TempTotalPlayTime; - return Result; } void Bot::SaveBuffs() { - // Remove any existing buff saves std::string query = StringFormat("DELETE FROM botbuffs WHERE BotId = %u", GetBotID()); auto results = database.QueryDatabase(query); @@ -2458,7 +2206,7 @@ void Bot::SaveBuffs() { "CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, " "caston_x, Persistent, caston_y, caston_z, ExtraDIChance) " "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %i, %u, " - "%i, %i, %i);", + "%i, %i, %i)", GetBotID(), buffs[buffIndex].spellid, buffs[buffIndex].casterlevel, spells[buffs[buffIndex].spellid].buffdurationformula, buffs[buffIndex].ticsremaining, @@ -2473,24 +2221,16 @@ void Bot::SaveBuffs() { auto results = database.QueryDatabase(query); if(!results.Success()) return; - } - } void Bot::LoadBuffs() { - - std::string query = StringFormat("SELECT SpellId, CasterLevel, DurationFormula, TicsRemaining, " - "PoisonCounters, DiseaseCounters, CurseCounters, CorruptionCounters, " - "HitCount, MeleeRune, MagicRune, dot_rune, caston_x, Persistent, " - "caston_y, caston_z, ExtraDIChance FROM botbuffs WHERE BotId = %u", - GetBotID()); + std::string query = StringFormat("SELECT SpellId, CasterLevel, DurationFormula, TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, caston_x, Persistent, caston_y, caston_z, ExtraDIChance FROM botbuffs WHERE BotId = %u", GetBotID()); auto results = database.QueryDatabase(query); if(!results.Success()) return; int buffCount = 0; - for (auto row = results.begin(); row != results.end(); ++row) { if(buffCount == BUFF_COUNT) break; @@ -2498,7 +2238,6 @@ void Bot::LoadBuffs() { buffs[buffCount].spellid = atoi(row[0]); buffs[buffCount].casterlevel = atoi(row[1]); buffs[buffCount].ticsremaining = atoi(row[3]); - if(CalculatePoisonCounters(buffs[buffCount].spellid) > 0) buffs[buffCount].counters = atoi(row[4]); else if(CalculateDiseaseCounters(buffs[buffCount].spellid) > 0) @@ -2514,49 +2253,35 @@ void Bot::LoadBuffs() { buffs[buffCount].dot_rune = atoi(row[11]); buffs[buffCount].caston_x = atoi(row[12]); buffs[buffCount].casterid = 0; - buffs[buffCount].persistant_buff = atoi(row[13])? true: false; - buffs[buffCount].caston_y = atoi(row[14]); buffs[buffCount].caston_z = atoi(row[15]); buffs[buffCount].ExtraDIChance = atoi(row[16]); - buffCount++; } - query = StringFormat("DELETE FROM botbuffs WHERE BotId = %u", GetBotID()); results = database.QueryDatabase(query); - } uint32 Bot::GetPetSaveId() { - - std::string query = StringFormat("SELECT BotPetsId FROM botpets WHERE BotId = %u;", GetBotID()); + std::string query = StringFormat("SELECT BotPetsId FROM botpets WHERE BotId = %u", GetBotID()); auto results = database.QueryDatabase(query); - if(!results.Success()) + if(!results.Success() || results.RowCount() == 0) return 0; - if (results.RowCount() == 0) - return 0; - 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]; @@ -2571,7 +2296,6 @@ void Bot::LoadPet() { pet->SetHP(petHitPoints); pet->SetMana(petMana); } - DeletePetStats(PetSaveId); } } @@ -2580,18 +2304,12 @@ void Bot::LoadPetStats(std::string* petName, uint32* petMana, uint32* petHitPoin if(botPetSaveId == 0) return; - std::string query = StringFormat("SELECT PetId, Name, Mana, HitPoints " - "FROM botpets WHERE BotPetsId = %u;", - botPetSaveId); + std::string query = StringFormat("SELECT PetId, Name, Mana, HitPoints FROM botpets WHERE BotPetsId = %u", botPetSaveId); auto results = database.QueryDatabase(query); - if(!results.Success()) - return; - - if (results.RowCount() == 0) + if(!results.Success() || results.RowCount() == 0) return; auto row = results.begin(); - *botPetId = atoi(row[0]); *petName = std::string(row[1]); *petMana = atoi(row[2]); @@ -2602,15 +2320,12 @@ void Bot::LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { if(!petBuffs || botPetSaveId == 0) return; - std::string query = StringFormat("SELECT SpellId, CasterLevel, Duration " - "FROM botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("SELECT SpellId, CasterLevel, Duration FROM botpetbuffs WHERE BotPetsId = %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; @@ -2618,39 +2333,31 @@ void Bot::LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { petBuffs[buffIndex].spellid = atoi(row[0]); petBuffs[buffIndex].level = atoi(row[1]); petBuffs[buffIndex].duration = atoi(row[2]); - buffIndex++; } - query = StringFormat("DELETE FROM botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); results = database.QueryDatabase(query); - } void Bot::LoadPetItems(uint32* petItems, uint32 botPetSaveId) { if(!petItems || botPetSaveId == 0) return; - std::string query = StringFormat("SELECT ItemId FROM botpetinventory " - "WHERE BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("SELECT ItemId FROM botpetinventory WHERE BotPetsId = %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 botpetinventory WHERE BotPetsId = %u;", botPetSaveId); + query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u", botPetSaveId); results = database.QueryDatabase(query); - } void Bot::SavePet() { @@ -2662,40 +2369,28 @@ void Bot::SavePet() { 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 botpets SET PetId = %u, BotId = %u, Name = '%s', " - "Mana = %u, HitPoints = %u;", botPetId, GetBotID(), petName.c_str(), - petMana, petHitPoints); + std::string query = StringFormat("REPLACE INTO botpets SET PetId = %u, BotId = %u, Name = '%s', Mana = %u, HitPoints = %u", botPetId, GetBotID(), petName.c_str(), petMana, petHitPoints); auto results = database.QueryDatabase(query); - return 0; } @@ -2704,21 +2399,14 @@ void Bot::SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { return; int buffIndex = 0; - while(buffIndex < BUFF_COUNT) { if(petBuffs[buffIndex].spellid > 0 && petBuffs[buffIndex].spellid != SPELL_UNKNOWN) { - std::string query = StringFormat("INSERT INTO botpetbuffs " - "(BotPetsId, SpellId, CasterLevel, Duration) " - "VALUES(%u, %u, %u, %u);", - botPetSaveId, petBuffs[buffIndex].spellid, - petBuffs[buffIndex].level, petBuffs[buffIndex].duration); + std::string query = StringFormat("INSERT INTO botpetbuffs (BotPetsId, SpellId, CasterLevel, 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++; } @@ -2732,55 +2420,46 @@ void Bot::SavePetItems(uint32* petItems, uint32 botPetSaveId) { if(petItems[itemIndex] == 0) continue; - std::string query = StringFormat("INSERT INTO botpetinventory " - "(BotPetsId, ItemId) VALUES(%u, %u);", - botPetSaveId, petItems[itemIndex]); + std::string query = StringFormat("INSERT INTO botpetinventory (BotPetsId, ItemId) 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 botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("DELETE FROM botpetbuffs WHERE BotPetsId = %u", botPetSaveId); auto results = database.QueryDatabase(query); - } void Bot::DeletePetItems(uint32 botPetSaveId) { if(botPetSaveId == 0) return; - std::string query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u", botPetSaveId); auto results = database.QueryDatabase(query); - } void Bot::DeletePetStats(uint32 botPetSaveId) { if(botPetSaveId == 0) return; - std::string query = StringFormat("DELETE from botpets where BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("DELETE from botpets where BotPetsId = %u", botPetSaveId); auto results = database.QueryDatabase(query); - } void Bot::LoadStance() { - - std::string query = StringFormat("SELECT StanceID FROM botstances WHERE BotID = %u;", GetBotID()); + std::string query = StringFormat("SELECT StanceID FROM botstances WHERE BotID = %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])); } @@ -2788,22 +2467,19 @@ void Bot::SaveStance() { if(_baseBotStance == _botStance) return; - std::string query = StringFormat("REPLACE INTO botstances (BotID, StanceId) " - "VALUES(%u, %u);", GetBotID(), GetBotStance()); + std::string query = StringFormat("REPLACE INTO botstances (BotID, StanceId) 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.TimerID, 0) As TimerID, IfNull(bt.Value, 0) As Value, " "IfNull(MAX(sn.recast_time), 0) AS MaxTimer FROM bottimers bt, spells_new sn " "WHERE bt.BotID = %u AND sn.EndurTimerIndex = " "(SELECT case WHEN TimerID > %i THEN TimerID - %i ELSE TimerID END AS TimerID " "FROM bottimers WHERE TimerID = bt.TimerID AND BotID = bt.BotID ) " - "AND sn.classes%i <= %i;", + "AND sn.classes%i <= %i", GetBotID(), DisciplineReuseStart-1, DisciplineReuseStart-1, GetClass(), GetLevel()); auto results = database.QueryDatabase(query); if(!results.Success()) { @@ -2814,12 +2490,10 @@ void Bot::LoadTimers() { 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; } @@ -2828,8 +2502,7 @@ void Bot::LoadTimers() { void Bot::SaveTimers() { bool hadError = false; - - std::string query = StringFormat("DELETE FROM bottimers WHERE BotID = %u;", GetBotID()); + std::string query = StringFormat("DELETE FROM bottimers WHERE BotID = %u", GetBotID()); auto results = database.QueryDatabase(query); if(!results.Success()) hadError = true; @@ -2838,10 +2511,8 @@ void Bot::SaveTimers() { if(timers[timerIndex] <= Timer::GetCurrentTime()) continue; - query = StringFormat("REPLACE INTO bottimers (BotID, TimerID, Value) VALUES(%u, %u, %u);", - GetBotID(), timerIndex+1, timers[timerIndex]); + query = StringFormat("REPLACE INTO bottimers (BotID, TimerID, Value) VALUES(%u, %u, %u)", GetBotID(), timerIndex + 1, timers[timerIndex]); results = database.QueryDatabase(query); - if(!results.Success()) hadError = true; } @@ -2851,16 +2522,14 @@ void Bot::SaveTimers() { } -bool Bot::Process() -{ +bool Bot::Process() { if(IsStunned() && stunned_timer.Check()) Mob::UnStun(); if(!GetBotOwner()) return false; - if (GetDepop()) - { + if (GetDepop()) { _botOwner = 0; _botOwnerCharacterID = 0; _previousTarget = 0; @@ -2869,25 +2538,18 @@ bool Bot::Process() SpellProcess(); - if(tic_timer.Check()) - { + if(tic_timer.Check()) { //6 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting - if(!IsMoving() && !IsEngaged()) - { + if(!IsMoving() && !IsEngaged()) { SendPosition(); - if(IsSitting()) - { + if(IsSitting()) { if(!rest_timer.Enabled()) - { rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - } } } BuffProcess(); - CalcRestState(); - if(curfp) ProcessFlee(); @@ -2904,7 +2566,6 @@ bool Bot::Process() if (sendhpupdate_timer.Check(false)) { SendHPUpdate(); - if(HasPet()) GetPet()->SendHPUpdate(); } @@ -2915,24 +2576,14 @@ bool Bot::Process() if (IsStunned() || IsMezzed()) return true; - //Handle assists... - /*if(assist_timer.Check() && !Charmed() && GetTarget() != nullptr) { - entity_list.AIYellForHelp(this, GetTarget()); - }*/ - // Bot AI AI_Process(); - return true; } -void Bot::SpellProcess() -{ - // check the rapid recast prevention timer - if(spellend_timer.Check(false)) - { +void Bot::SpellProcess() { + if(spellend_timer.Check(false)) { NPC::SpellProcess(); - if(GetClass() == BARD) { if (casting_spell_id != 0) casting_spell_id = 0; @@ -2942,34 +2593,24 @@ void Bot::SpellProcess() void Bot::BotMeditate(bool isSitting) { if(isSitting) { - // If the bot is a caster has less than 99% mana while its not engaged, he needs to sit to meditate - if(GetManaRatio() < 99.0f || GetHPRatio() < 99.0f) - { + if(GetManaRatio() < 99.0f || GetHPRatio() < 99.0f) { if (!IsEngaged() && !IsSitting()) Sit(); - } - else - { + } else { if(IsSitting()) Stand(); } - } - else - { + } else { if(IsSitting()) Stand(); } - if(IsSitting()) - { + + if(IsSitting()) { if(!rest_timer.Enabled()) - { rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - } } else - { rest_timer.Disable(); - } } void Bot::BotRangedAttack(Mob* other) { @@ -2995,21 +2636,11 @@ void Bot::BotRangedAttack(Mob* other) { return; Log.Out(Logs::Detail, Logs::Combat, "Shooting %s with bow %s (%d) and arrow %s (%d)", other->GetCleanName(), RangeWeapon->Name, RangeWeapon->ID, Ammo->Name, Ammo->ID); - - if(!IsAttackAllowed(other) || - IsCasting() || - DivineAura() || - IsStunned() || - IsMezzed() || - (GetAppearance() == eaDead)) - { + if(!IsAttackAllowed(other) || IsCasting() || DivineAura() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) return; - } SendItemAnimation(other, Ammo, SkillArchery); - DoArcheryAttackDmg(GetTarget(), rangedItem, ammoItem); - //break invis when you attack if(invisible) { Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility due to melee attack."); @@ -3017,13 +2648,15 @@ void Bot::BotRangedAttack(Mob* other) { 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){ + + if(invisible_animals) { Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. animals due to melee attack."); BuffFadeByEffect(SE_InvisVsAnimals); invisible_animals = false; @@ -3046,26 +2679,21 @@ void Bot::BotRangedAttack(Mob* other) { } 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; - + 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)) return false; // You start with no chance of double attacking float chance = 0.0f; - uint16 skill = GetSkill(SkillDoubleAttack); - - int32 bonusDA = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance; - + 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) - chance = (float(skill+GetLevel()) * (float(100.0f+bonusDA+bonusGiveDA) /100.0f)) /500.0f; + 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; + 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 @@ -3073,9 +2701,9 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) { //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] - int32 triple_bonus = spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance; + int32 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. + chance *= (float(100.0f + triple_bonus) / 100.0f); //Apply modifiers. } if((zone->random.Real(0, 1) < chance)) @@ -3084,44 +2712,37 @@ 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, SkillUseTypes 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. - //Kayen: This is unlikely to be completely accurate but use OFFENSE skill value for these effects. if (skillinuse == SkillBegging) skillinuse = SkillOffense; int damage = 0; uint32 hate = 0; int Hand = MainPrimary; - if (hate == 0 && weapon_damage > 1) hate = weapon_damage; + 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; + 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 Item_Struct*) nullptr ); - + int32 max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); + if(GetLevel() >= 28 && IsWarriorClass()) { + int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) 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; - + min_hit += (min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100); if(max_hit < min_hit) max_hit = min_hit; @@ -3130,16 +2751,16 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = zone->random.Int(min_hit, max_hit); - if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) { + if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) damage = 0; - } else { + else { other->AvoidDamage(this, damage, CanRiposte); 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); + damage += ((itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse)); TryCriticalHit(other, skillinuse, damage, nullptr); } } @@ -3150,7 +2771,6 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes return; } } - else damage = -5; @@ -3159,11 +2779,12 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); + if(botweapon) { - if(botweapon->ItemType == ItemTypeShield) { + if(botweapon->ItemType == ItemTypeShield) hate += botweapon->AC; - } - hate = hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100; + + hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); } } @@ -3176,7 +2797,6 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes } other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - if (HasDied()) return; @@ -3196,27 +2816,22 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes } void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) { - int item_slot = -1; //1: Apply bonus from AC (BOOT/SHIELD/HANDS) est. 40AC=6dmg - - switch (skill){ - + switch (skill) { case SkillFlyingKick: case SkillRoundKick: case SkillKick: item_slot = MainFeet; - break; - + break; case SkillBash: item_slot = MainSecondary; - break; - + break; case SkillDragonPunch: case SkillEagleStrike: case SkillTigerClaw: item_slot = MainHands; - break; + break; } if (item_slot >= EmuConstants::EQUIPMENT_BEGIN){ @@ -3224,13 +2839,13 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); + if(botweapon) dmg += botweapon->AC * (RuleI(Combat, SpecialAttackACBonus))/100; } } -bool Bot::CanDoSpecialAttack(Mob *other) -{ +bool Bot::CanDoSpecialAttack(Mob *other) { //Make sure everything is valid before doing any attacks. if (!other) { SetTarget(nullptr); @@ -3240,12 +2855,7 @@ bool Bot::CanDoSpecialAttack(Mob *other) if(!GetTarget()) SetTarget(other); - if ((other == nullptr || ((GetAppearance() == eaDead) || (other->IsClient() && other->CastToClient()->IsDead())) - || HasDied() || (!IsAttackAllowed(other)))) { - return false; - } - - if(other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)) + if ((other == nullptr || ((GetAppearance() == eaDead) || (other->IsClient() && other->CastToClient()->IsDead())) || HasDied() || (!IsAttackAllowed(other))) || other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)) return false; return true; @@ -3262,7 +2872,6 @@ void Bot::SetTarget(Mob* mob) { float Bot::GetMaxMeleeRangeToTarget(Mob* target) { float result = 0; - if(target) { float size_mod = GetSize(); float other_size_mod = target->GetSize(); @@ -3277,22 +2886,19 @@ float Bot::GetMaxMeleeRangeToTarget(Mob* target) { else if (other_size_mod < 6.0) other_size_mod = 8.0f; - if (other_size_mod > size_mod) { + if (other_size_mod > size_mod) size_mod = other_size_mod; - } - - // this could still use some work, but for now it's an improvement.... if (size_mod > 29) size_mod *= size_mod; else if (size_mod > 19) - size_mod *= size_mod * 2; + size_mod *= (size_mod * 2); else - size_mod *= size_mod * 4; + size_mod *= (size_mod * 4); // prevention of ridiculously sized hit boxes if (size_mod > 10000) - size_mod = size_mod / 7; + size_mod = (size_mod / 7); result = size_mod; } @@ -3307,21 +2913,14 @@ void Bot::AI_Process() { uint8 botClass = GetClass(); uint8 botLevel = GetLevel(); - if(IsCasting() && (botClass != BARD)) return; // A bot wont start its AI if not grouped - if(!GetBotOwner() || !IsGrouped()) { - return; - } - - if(GetAppearance() == eaDead) + if(!GetBotOwner() || !IsGrouped() || GetAppearance() == eaDead) return; Mob* BotOwner = GetBotOwner(); - - // The bots need an owner if(!BotOwner) return; @@ -3343,9 +2942,8 @@ void Bot::AI_Process() { SetHasHealedThisCycle(true); NotifyNextHealRotationMember(); } - else { + else NotifyNextHealRotationMember(true); - } } if(GetHasBeenSummoned()) { @@ -3354,11 +2952,10 @@ void Bot::AI_Process() { if(!GetTarget() || (IsBotCaster() && !IsBotCasterCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistanceSquaredNoZ(static_cast(m_Position), m_PreSummonLocation) < 10)) { if(GetTarget()) FaceTarget(GetTarget()); + SetHasBeenSummoned(false); - } - else if(!IsRooted()) { - if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) - { + } 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()); SetHeading(CalculateHeadingToTarget(m_PreSummonLocation.x, m_PreSummonLocation.y)); @@ -3371,35 +2968,29 @@ void Bot::AI_Process() { else SendPosition(); } - } - else { + } else { if(GetTarget()) FaceTarget(GetTarget()); + SetHasBeenSummoned(false); } - return; } if(!IsEngaged()) { if(GetFollowID()) { - if(BotOwner && BotOwner->GetTarget() && BotOwner->GetTarget()->IsNPC() && (BotOwner->GetTarget()->GetHateAmount(BotOwner) - || BotOwner->CastToClient()->AutoAttackEnabled()) && IsAttackAllowed(BotOwner->GetTarget())) { + if(BotOwner && BotOwner->GetTarget() && BotOwner->GetTarget()->IsNPC() && (BotOwner->GetTarget()->GetHateAmount(BotOwner) || BotOwner->CastToClient()->AutoAttackEnabled()) && IsAttackAllowed(BotOwner->GetTarget())) { AddToHateList(BotOwner->GetTarget(), 1); - if(HasPet()) GetPet()->AddToHateList(BotOwner->GetTarget(), 1); - } - else { + } else { Group* g = GetGroup(); - if(g) { for(int counter = 0; counter < g->GroupCount(); counter++) { if(g->members[counter]) { Mob* tar = g->members[counter]->GetTarget(); if(tar && tar->IsNPC() && tar->GetHateAmount(g->members[counter]) && IsAttackAllowed(g->members[counter]->GetTarget())) { AddToHateList(tar, 1); - if(HasPet()) GetPet()->AddToHateList(tar, 1); @@ -3412,9 +3003,7 @@ void Bot::AI_Process() { } } - if(IsEngaged()) - { - + if(IsEngaged()) { if(rest_timer.Enabled()) rest_timer.Disable(); @@ -3440,17 +3029,13 @@ void Bot::AI_Process() { // Else, it was causing the bot to aggro behind wall etc... causing massive trains. if(!CheckLosFN(GetTarget()) || GetTarget()->IsMezzed() || !IsAttackAllowed(GetTarget())) { WipeHateList(); - if(IsMoving()) { SetHeading(0); SetRunAnimSpeed(0); SetCurrentSpeed(GetRunspeed()); - - if(moved) { + if(moved) SetCurrentSpeed(0); - } } - return; } @@ -3458,15 +3043,11 @@ void Bot::AI_Process() { SendAddPlayerState(PlayerState::Aggressive); bool atCombatRange = false; - float meleeDistance = GetMaxMeleeRangeToTarget(GetTarget()); - - if(botClass == SHADOWKNIGHT || botClass == PALADIN || botClass == WARRIOR) { - meleeDistance = meleeDistance * .30; - } - else { + if(botClass == SHADOWKNIGHT || botClass == PALADIN || botClass == WARRIOR) + meleeDistance = (meleeDistance * .30); + else meleeDistance *= (float)zone->random.Real(.50, .85); - } bool atArcheryRange = IsArcheryRange(GetTarget()); @@ -3476,8 +3057,7 @@ void Bot::AI_Process() { if(atArcheryRange && !IsBotArcher()) { SetBotArcher(true); changeWeapons = true; - } - else if(!atArcheryRange && IsBotArcher()) { + } else if(!atArcheryRange && IsBotArcher()) { SetBotArcher(false); changeWeapons = true; } @@ -3496,16 +3076,13 @@ void Bot::AI_Process() { SetCurrentSpeed(0); } } - atCombatRange = true; - } - else if(IsBotCaster() && GetLevel() > 12) { + } else if(IsBotCaster() && GetLevel() > 12) { if(IsBotCasterCombatRange(GetTarget())) atCombatRange = true; } - else if(DistanceSquared(m_Position, GetTarget()->GetPosition()) <= meleeDistance) { + else if(DistanceSquared(m_Position, GetTarget()->GetPosition()) <= meleeDistance) atCombatRange = true; - } if(atCombatRange) { if(IsMoving()) { @@ -3523,7 +3100,6 @@ void Bot::AI_Process() { float newX = 0; float newY = 0; float newZ = 0; - if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); return; @@ -3534,7 +3110,6 @@ void Bot::AI_Process() { 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; @@ -3549,35 +3124,24 @@ void Bot::AI_Process() { if(IsBotArcher() && ranged_timer.Check(false)) { if(GetTarget()->GetHPRatio() <= 99.0f) - // Mob::DoArcheryAttackDmg() takes care of Bot Range and Ammo procs BotRangedAttack(GetTarget()); } else if(!IsBotArcher() && (!(IsBotCaster() && GetLevel() > 12)) && 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()) - return; - - if(GetBotStance() == BotStancePassive) + if((IsEngaged() && !BehindMob(GetTarget(), GetX(), GetY()) && GetTarget()->IsEnraged()) || GetBotStance() == BotStancePassive) return; // First, special attack per class (kick, backstab etc..) DoClassAttacks(GetTarget()); - - //try main hand first if(attack_timer.Check()) { Attack(GetTarget(), MainPrimary); - ItemInst *wpn = GetBotItem(MainPrimary); TryWeaponProc(wpn, GetTarget(), MainPrimary); - bool tripleSuccess = false; - if(BotOwner && GetTarget() && CanThisClassDoubleAttack()) { - - if(BotOwner && CheckBotDoubleAttack()) { + if(BotOwner && CheckBotDoubleAttack()) Attack(GetTarget(), MainPrimary, true); - } if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) { tripleSuccess = true; @@ -3585,37 +3149,27 @@ void Bot::AI_Process() { } //quad attack, does this belong here?? - if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) { + if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) Attack(GetTarget(), MainPrimary, true); - } } //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). - int32 flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance; - - if (GetTarget() && flurrychance) - { - if(zone->random.Int(0, 100) < flurrychance) - { + int32 flurrychance = (aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance); + if (GetTarget() && flurrychance) { + if(zone->random.Int(0, 100) < flurrychance) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); Attack(GetTarget(), MainPrimary, false); Attack(GetTarget(), MainPrimary, false); } } - int32 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; - + int32 ExtraAttackChanceBonus = (spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance); if (GetTarget() && ExtraAttackChanceBonus) { ItemInst *wpn = GetBotItem(MainPrimary); - if(wpn){ - if(wpn->GetItem()->ItemType == ItemType2HSlash || - wpn->GetItem()->ItemType == ItemType2HBlunt || - wpn->GetItem()->ItemType == ItemType2HPiercing ) - { + 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); - } } } } @@ -3626,6 +3180,7 @@ void Bot::AI_Process() { entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); this->berserk = true; } + if (berserk && this->GetHPRatio() > 30) { entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); this->berserk = false; @@ -3643,7 +3198,6 @@ void Bot::AI_Process() { int weapontype = 0; // No weapon type. bool bIsFist = true; - if(weapon) { weapontype = weapon->ItemType; bIsFist = false; @@ -3651,21 +3205,15 @@ void Bot::AI_Process() { if(bIsFist || ((weapontype != ItemType2HSlash) && (weapontype != ItemType2HPiercing) && (weapontype != ItemType2HBlunt))) { float DualWieldProbability = 0.0f; - - int32 Ambidexterity = aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; - DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f; // 78.0 max - int32 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; - DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; - + int32 Ambidexterity = (aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity); + DualWieldProbability = ((GetSkill(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); - if (random < DualWieldProbability){ // Max 78% of DW - Attack(GetTarget(), MainSecondary); // Single attack with offhand - ItemInst *wpn = GetBotItem(MainSecondary); TryWeaponProc(wpn, GetTarget(), MainSecondary); - if( CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) Attack(GetTarget(), MainSecondary); // Single attack with offhand @@ -3675,8 +3223,7 @@ void Bot::AI_Process() { } } } - } // end in combat range - else { + } else { if(GetTarget()->IsFeared() && !spellend_timer.Enabled()){ // This is a mob that is fleeing either because it has been feared or is low on hitpoints if(GetBotStance() != BotStancePassive) @@ -3701,17 +3248,13 @@ void Bot::AI_Process() { if(GetBotStance() == BotStancePassive) return; - if(AI_EngagedCastCheck()) { + if(AI_EngagedCastCheck()) BotMeditate(false); - } else if(GetArchetype() == ARCHETYPE_CASTER) BotMeditate(true); } - } // end IsEngaged() - else { - // Not engaged in combat + } else { SetTarget(0); - if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); @@ -3720,20 +3263,16 @@ void Bot::AI_Process() { if(!AI_IdleCastCheck() && !IsCasting()) BotMeditate(true); } - else { + else BotMeditate(true); - } - } if(AImovement_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(); @@ -3742,11 +3281,8 @@ void Bot::AI_Process() { if(rest_timer.Enabled()) rest_timer.Disable(); return; - } - else - { - if(moved) - { + } else { + if(moved) { moved = false; SetCurrentSpeed(0); } @@ -3759,33 +3295,20 @@ void Bot::AI_Process() { // AI Processing for a Bot object's pet void Bot::PetAIProcess() { - if( !HasPet() || !GetPet() || !GetPet()->IsNPC()) return; Mob* BotOwner = this->GetBotOwner(); NPC* botPet = this->GetPet()->CastToNPC(); - if(!botPet->GetOwner() || !botPet->GetID() || !botPet->GetOwnerID()) { Kill(); return; } - if (!botPet->IsAIControlled()) - return; - - if(botPet->GetAttackTimer().Check(false)) - return; - - if (botPet->IsCasting()) - return; - - // Return if the owner of the bot pet isnt a bot. - if (!botPet->GetOwner()->IsBot()) + if (!botPet->IsAIControlled() || botPet->GetAttackTimer().Check(false) || botPet->IsCasting() || !botPet->GetOwner()->IsBot()) return; if (IsEngaged()) { - if (botPet->IsRooted()) botPet->SetTarget(hate_list.GetClosestEntOnHateList(botPet)); else @@ -3797,40 +3320,22 @@ void Bot::PetAIProcess() { if(!botPet->CheckLosFN(botPet->GetTarget()) || botPet->GetTarget()->IsMezzed() || !botPet->IsAttackAllowed(GetTarget())) { botPet->WipeHateList(); botPet->SetTarget(botPet->GetOwner()); - return; } botPet->FaceTarget(botPet->GetTarget()); - - // Lets see if we can let the main tank build a little aggro - /*if(GetBotRaidID()) { - BotRaids *br = entity_list.GetBotRaidByMob(GetOwner()); - if(br) { - if(br->GetBotMainTank() && (br->GetBotMainTank() != this)) { - if(br->GetBotMainTarget() && (br->GetBotMainTarget()->GetHateAmount(br->GetBotMainTank()) < 5000)) { - if(GetTarget() == br->GetBotMainTarget()) { - return; - } - } - } - } - }*/ - bool is_combat_range = botPet->CombatRange(botPet->GetTarget()); - // Ok, we're engaged, each class type has a special AI // Only melee class will go to melee. Casters and healers will stay behind, following the leader by default. // I should probably make the casters staying in place so they can cast.. // Ok, we 're a melee or any other class lvl<12. Yes, because after it becomes hard to go in melee for casters.. even for bots.. - if( is_combat_range ) { + if(is_combat_range) { botPet->GetAIMovementTimer()->Check(); - if(botPet->IsMoving()) { botPet->SetHeading(botPet->GetTarget()->GetHeading()); if(moved) { - moved=false; + moved = false; botPet->SetRunAnimSpeed(0); } } @@ -3840,10 +3345,8 @@ void Bot::PetAIProcess() { float newY = 0; float newZ = 0; bool petHasAggro = false; - - if(botPet->GetTarget() && botPet->GetTarget()->GetHateTop() && botPet->GetTarget()->GetHateTop() == botPet) { + if(botPet->GetTarget() && botPet->GetTarget()->GetHateTop() && botPet->GetTarget()->GetHateTop() == botPet) petHasAggro = true; - } if(botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) { // Move the rogue to behind the mob @@ -3863,7 +3366,6 @@ void Bot::PetAIProcess() { // Let's try to adjust our melee range so we don't appear to be bunched up bool isBehindMob = false; bool moveBehindMob = false; - if(botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) isBehindMob = true; @@ -3886,14 +3388,11 @@ void Bot::PetAIProcess() { return; if(botPet->Attack(GetTarget(), MainPrimary)) // try the main hand - if (botPet->GetTarget()) // Do we still have a target? - { + 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->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) { + if(botPet->Attack(botPet->GetTarget(), MainPrimary)) {} } } @@ -3906,19 +3405,18 @@ void Bot::PetAIProcess() { aa_skill += botPet->GetOwner()->GetAA(aaQuickeningofDeath); // Beastlord AA aa_skill += botPet->GetOwner()->GetAA(aaWardersAlacrity); - - if(aa_skill >= 1) { - aa_chance += (aa_skill > 5 ? 5 : aa_skill) * 4; - } - if(aa_skill >= 6) { - aa_chance += (aa_skill-5 > 3 ? 3 : aa_skill-5) * 7; - } - if(aa_skill >= 9) { - aa_chance += (aa_skill-8 > 3 ? 3 : aa_skill-8) * 3; - } - if(aa_skill >= 12) { - aa_chance += (aa_skill - 11) * 1; - } + if(aa_skill >= 1) + aa_chance += ((aa_skill > 5 ? 5 : aa_skill) * 4); + + if(aa_skill >= 6) + aa_chance += ((aa_skill - 5 > 3 ? 3 : aa_skill - 5) * 7); + + if(aa_skill >= 9) + aa_chance += ((aa_skill - 8 > 3 ? 3 : aa_skill - 8) * 3); + + if(aa_skill >= 12) + aa_chance += ((aa_skill - 11) * 1); + //aa_chance += botPet->GetOwner()->GetAA(aaCompanionsAlacrity) * 3; @@ -3927,21 +3425,16 @@ 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; + 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); DualWieldProbability -= zone->random.Real(0, 1); - if(DualWieldProbability < 0){ + if(DualWieldProbability < 0) { botPet->Attack(botPet->GetTarget(), MainSecondary); - if (botPet->CanThisClassDoubleAttack()) - { + if (botPet->CanThisClassDoubleAttack()) { int32 RandRoll = zone->random.Int(0, 99); if (RandRoll < (botPet->GetLevel() + 20)) - { botPet->Attack(botPet->GetTarget(), MainSecondary); - } } } } @@ -3955,25 +3448,20 @@ void Bot::PetAIProcess() { // See if the pet can cast any spell botPet->AI_EngagedCastCheck(); } - }// end of the combat in range - else{ + } else { // Now, if we cannot reach our target - if (!botPet->HateSummon()) - { - if(botPet->GetTarget() && botPet->AI_PursueCastCheck()) - {} - else if (botPet->GetTarget() && botPet->GetAIMovementTimer()->Check()) - { + if (!botPet->HateSummon()) { + if(botPet->GetTarget() && botPet->AI_PursueCastCheck()) {} + else if (botPet->GetTarget() && botPet->GetAIMovementTimer()->Check()) { botPet->SetRunAnimSpeed(0); if(!botPet->IsRooted()) { Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", botPet->GetTarget()->GetCleanName()); botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetOwner()->GetRunspeed()); return; - } - else { + } else { botPet->SetHeading(botPet->GetTarget()->GetHeading()); if(moved) { - moved=false; + moved = false; SetCurrentSpeed(0); botPet->SendPosition(); botPet->SetMoving(false); @@ -3982,39 +3470,33 @@ void Bot::PetAIProcess() { } } } - } - else{ - // Franck: EQoffline + } else { // Ok if we're not engaged, what's happening.. - if(botPet->GetTarget() != botPet->GetOwner()) { + if(botPet->GetTarget() != botPet->GetOwner()) botPet->SetTarget(botPet->GetOwner()); - } - if(!IsMoving()) { + if(!IsMoving()) botPet->AI_IdleCastCheck(); - } if(botPet->GetAIMovementTimer()->Check()) { switch(pStandingPetOrder) { - case SPO_Follow: - { - float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition()); - botPet->SetRunAnimSpeed(0); - if(dist > 184) { - botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed()); - return; - } - else { - botPet->SetHeading(botPet->GetTarget()->GetHeading()); - if(moved) { - moved=false; - SetCurrentSpeed(0); - botPet->SendPosition(); - botPet->SetMoving(false); - } + case SPO_Follow: { + float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition()); + botPet->SetRunAnimSpeed(0); + if(dist > 184) { + botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed()); + return; + } else { + botPet->SetHeading(botPet->GetTarget()->GetHeading()); + if(moved) { + moved = false; + SetCurrentSpeed(0); + botPet->SendPosition(); + botPet->SetMoving(false); } } break; + } case SPO_Sit: botPet->SetAppearance(eaSitting); break; @@ -4028,26 +3510,21 @@ void Bot::PetAIProcess() { void Bot::Depop() { WipeHateList(); - entity_list.RemoveFromHateLists(this); - if(HasGroup()) Bot::RemoveBotFromGroup(this, GetGroup()); - if(HasPet()) { + if(HasPet()) GetPet()->Depop(); - } _botOwner = 0; _botOwnerCharacterID = 0; _previousTarget = 0; - NPC::Depop(false); } bool Bot::DeleteBot(std::string* errorMessage) { bool hadError = false; - if(this->GetBotID() == 0) return false; @@ -4107,20 +3584,12 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { // Make the bot look at the bot owner FaceTarget(botCharacterOwner); - - // Level the bot to the same level as the bot owner - //this->SetLevel(botCharacterOwner->GetLevel()); - UpdateEquipmentLight(); UpdateActiveLight(); - entity_list.AddBot(this, true, true); - // Load pet LoadPet(); - this->SendPosition(); - // there is something askew with spawn struct appearance fields... // I re-enabled this until I can sort it out uint32 itemID = 0; @@ -4138,9 +3607,7 @@ 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 }; - if (this->GetBotID() == 0 || slotID < EmuConstants::EQUIPMENT_BEGIN || itemID <= NO_ITEM) return; @@ -4165,13 +3632,10 @@ void Bot::SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, s // 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) return; - std::string query = StringFormat("DELETE FROM botinventory " - "WHERE botid = %i AND slotid = %i", - this->GetBotID(), slotID); + std::string query = StringFormat("DELETE FROM botinventory WHERE botid = %i AND slotid = %i", this->GetBotID(), slotID); auto results = database.QueryDatabase(query); if(!results.Success()) *errorMessage = std::string(results.ErrorMessage()); @@ -4182,7 +3646,6 @@ void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) { // Retrieves all the inventory records from the database for this bot. void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { - if(this->GetBotID() == 0) return; @@ -4208,7 +3671,6 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { aug[3] = (uint32)atoul(row[7]); aug[4] = (uint32)atoul(row[8]); bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; - ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]); if (!inst) { Log.Out(Logs::General, Logs::Error, "Warning: botid %i has an invalid item_id %i in inventory slot %i", this->GetBotID(), item_id, slot_id); @@ -4236,7 +3698,6 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { // Save ptr to item in inventory if (put_slot_id == INVALID_INDEX) Log.Out(Logs::General, Logs::Error, "Warning: Invalid slot_id for item in inventory: botid=%i, item_id=%i, slot_id=%i",this->GetBotID(), item_id, slot_id); - } UpdateEquipmentLight(); @@ -4244,26 +3705,20 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { // 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; - std::string query = StringFormat("SELECT itemid FROM botinventory WHERE botid=%i AND slotid = %i", GetBotID(), slotID); + std::string query = StringFormat("SELECT itemid FROM botinventory WHERE botid = %i AND slotid = %i", GetBotID(), slotID); auto results = database.QueryDatabase(query); - if(!results.Success()) - return 0; - - if(results.RowCount() != 1) + if(!results.Success() || results.RowCount() != 1) return 0; 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; @@ -4283,50 +3738,35 @@ uint32 Bot::GetBotItemsCount(std::string *errorMessage) { bool Bot::MesmerizeTarget(Mob* target) { bool Result = false; - if(target) { int mezid = 0; int mezlevel = GetLevel(); - - if(mezlevel >= 69) { + if(mezlevel >= 69) mezid = 5520; - } - else if(mezlevel == 68) { + else if(mezlevel == 68) mezid = 8035; - } - else if(mezlevel == 67) { + else if(mezlevel == 67) mezid = 5503; - } - else if(mezlevel >= 64) { + else if(mezlevel >= 64) mezid = 3358; - } - else if(mezlevel == 63) { + else if(mezlevel == 63) mezid = 3354; - } - else if(mezlevel >= 61) { + else if(mezlevel >= 61) mezid = 3341; - } - else if(mezlevel == 60) { + else if(mezlevel == 60) mezid = 2120; - } - else if(mezlevel == 59) { + else if(mezlevel == 59) mezid = 1692; - } - else if(mezlevel >= 54) { + else if(mezlevel >= 54) mezid = 1691; - } - else if(mezlevel >= 47) { + else if(mezlevel >= 47) mezid = 190; - } - else if(mezlevel >= 30) { + else if(mezlevel >= 30) mezid = 188; - } - else if(mezlevel >= 13) { + else if(mezlevel >= 13) mezid = 187; - } - else if(mezlevel >= 2) { + else if(mezlevel >= 2) mezid = 292; - } if(mezid > 0) { uint32 DontRootMeBeforeTime = 0; CastSpell(mezid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); @@ -4339,16 +3779,13 @@ bool Bot::MesmerizeTarget(Mob* target) { } void Bot::SetLevel(uint8 in_level, bool command) { - if(in_level > 0) { + if(in_level > 0) Mob::SetLevel(in_level, command); - } } void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { - if(ns) - { + if(ns) { Mob::FillSpawnStruct(ns, ForWho); - ns->spawn.afk = 0; ns->spawn.lfg = 0; ns->spawn.anon = 0; @@ -4364,74 +3801,51 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.flymode = 0; 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.helm = (GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; - const Item_Struct* item = 0; const ItemInst* inst = 0; - uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); - - for (int i = 0; i < MaterialPrimary; i++) - { + for (int i = 0; i < MaterialPrimary; i++) { inst = GetBotItem(i); - if (inst) - { + if (inst) { item = inst->GetItem(); - if (item != 0) - { + 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.colors[i].Color = armor_tint[i]; - - } else - { ns->spawn.colors[i].Color = item->Color; - } - } - else - { + } else { if (armor_tint[i]) - { ns->spawn.colors[i].Color = armor_tint[i]; - } } } } inst = GetBotItem(MainPrimary); - if(inst) - { + if(inst) { item = inst->GetItem(); - if(item) - { + if(item) { if(strlen(item->IDFile) > 2) - { ns->spawn.equipment[MaterialPrimary].Material = atoi(&item->IDFile[2]); - } + ns->spawn.colors[MaterialPrimary].Color = GetEquipmentColor(MaterialPrimary); } } inst = GetBotItem(MainSecondary); - if(inst) - { + if(inst) { item = inst->GetItem(); - if(item) - { + if(item) { if(strlen(item->IDFile) > 2) - { ns->spawn.equipment[MaterialSecondary].Material = atoi(&item->IDFile[2]); - } + ns->spawn.colors[MaterialSecondary].Color = GetEquipmentColor(MaterialSecondary); } } @@ -4444,10 +3858,7 @@ uint32 Bot::GetBotIDByBotName(std::string botName) { std::string query = StringFormat("SELECT BotID FROM bots WHERE Name = '%s'", botName.c_str()); auto results = database.QueryDatabase(query); - if(!results.Success()) - return 0; - - if (results.RowCount() == 0) + if(!results.Success() || results.RowCount() == 0) return 0; auto row = results.begin(); @@ -4456,7 +3867,6 @@ uint32 Bot::GetBotIDByBotName(std::string botName) { Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) { Bot* loadedBot = nullptr; - if(botID == 0) return nullptr; @@ -4477,9 +3887,7 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) { return nullptr; auto row = results.begin(); - NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), - atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7])); - + NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7])); NPCType tempNPCStruct = FillNPCTypeStruct(atoi(row[1]), std::string(row[2]), std::string(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7]), atof(row[8]), atoi(row[9]), atoi(row[10]), atoi(row[11]), atoi(row[12]), atoi(row[13]), atoi(row[14]), @@ -4490,21 +3898,16 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) { defaultNPCTypeStruct.STA, defaultNPCTypeStruct.DEX, defaultNPCTypeStruct.AGI, defaultNPCTypeStruct.INT, defaultNPCTypeStruct.WIS, defaultNPCTypeStruct.CHA, defaultNPCTypeStruct.ATK); - loadedBot = new Bot(botID, atoi(row[0]), atoi(row[1]), atof(row[38]), atoi(row[39]), tempNPCStruct); - 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.mobid AS BotID FROM vwGroups AS g " - "JOIN bots AS b ON g.mobid = b.BotId AND g.mobtype = 'B' " - "WHERE g.groupid = %u", groupId); + std::string query = StringFormat("SELECT g.mobid AS BotID FROM vwGroups AS g JOIN bots AS b ON g.mobid = b.BotId AND g.mobtype = 'B' WHERE g.groupid = %u", groupId); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4526,11 +3929,9 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { uint32 TempGroupId = g->GetID(); std::string errorMessage; std::list ActiveBots = Bot::GetGroupedBotsByGroupId(botOwner->GetGroup()->GetID(), &errorMessage); - if(errorMessage.empty() && !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; @@ -4538,9 +3939,7 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { if(activeBot) { activeBot->Spawn(botOwner, &errorMessage); - g->UpdatePlayer(activeBot); - if(g->GetLeader()) activeBot->SetFollowID(g->GetLeader()->GetID()); } @@ -4549,11 +3948,6 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { database.SetGroupID(activeBot->GetCleanName(), 0, activeBot->GetBotID()); } } - - // Catch all condition for error messages destined for the zone error log - if(!errorMessage.empty()) { - // TODO: Log this error message to zone error log - } } } } @@ -4562,12 +3956,10 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { // Returns TRUE if there is atleast 1 bot in the specified group bool Bot::GroupHasBot(Group* group) { bool Result = false; - if(group) { for(int Counter = 0; Counter < MAX_GROUP_MEMBERS; Counter++) { - if (group->members[Counter] == nullptr) { + if (group->members[Counter] == nullptr) continue; - } if(group->members[Counter]->IsBot()) { Result = true; @@ -4575,18 +3967,15 @@ 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 BotID, Name, Class, BotLevel, Race " - "FROM bots WHERE BotOwnerCharacterID = '%u'", botOwnerCharacterID); + std::string query = StringFormat("SELECT BotID, Name, Class, BotLevel, Race FROM bots WHERE BotOwnerCharacterID = '%u'", botOwnerCharacterID); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4600,20 +3989,17 @@ std::list Bot::GetBotList(uint32 botOwnerCharacterID, std::st availableBot.BotClass = atoi(row[2]); availableBot.BotLevel = atoi(row[3]); availableBot.BotRace = atoi(row[4]); - ownersBots.push_back(availableBot); } - return ownersBots; } std::list Bot::ListSpawnedBots(uint32 characterID, std::string* errorMessage) { std::list spawnedBots; - if(characterID == 0) return spawnedBots; - std::string query = StringFormat("SELECT bot_name, zone_name FROM botleader WHERE leaderid=%i", characterID); + 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()); @@ -4625,7 +4011,6 @@ std::list Bot::ListSpawnedBots(uint32 characterID, std::string* spawnedBotsList.BotLeaderCharID = characterID; strcpy(spawnedBotsList.BotName, row[0]); strcpy(spawnedBotsList.ZoneName, row[1]); - spawnedBots.push_back(spawnedBotsList); } @@ -4637,15 +4022,12 @@ void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* e return; Mob* tempGroupLeader = botGroup->GetLeader(); - if(!tempGroupLeader->IsBot()) return; uint32 botGroupId = 0; uint32 botGroupLeaderBotId = tempGroupLeader->CastToBot()->GetBotID(); - - std::string query = StringFormat("INSERT INTO botgroup (BotGroupLeaderBotId, BotGroupName) " - "VALUES (%u, '%s')", botGroupLeaderBotId, botGroupName.c_str()); + std::string query = StringFormat("INSERT INTO botgroup (BotGroupLeaderBotId, BotGroupName) VALUES (%u, '%s')", botGroupLeaderBotId, botGroupName.c_str()); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4657,14 +4039,11 @@ void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* e 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 botgroupmembers (BotGroupId, BotId) " - "VALUES (%u, %u)", botGroupId, botGroupMemberBotId); + query = StringFormat("INSERT INTO botgroupmembers (BotGroupId, BotId) VALUES (%u, %u)", botGroupId, botGroupMemberBotId); results = database.QueryDatabase(query); if(!results.Success()) *errorMessage = std::string(results.ErrorMessage()); @@ -4673,12 +4052,10 @@ void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* e } void Bot::DeleteBotGroup(std::string botGroupName, std::string* errorMessage) { - if(botGroupName.empty()) return; uint32 botGroupId = GetBotGroupIdByBotGroupName(botGroupName, errorMessage); - if(!errorMessage->empty() || botGroupId== 0) return; @@ -4697,12 +4074,10 @@ void Bot::DeleteBotGroup(std::string botGroupName, std::string* 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; @@ -4717,21 +4092,17 @@ std::list Bot::LoadBotGroup(std::string botGroupName, std::string* err 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 BotGroupName, BotGroupLeaderName FROM vwBotGroups " - "WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); + std::string query = StringFormat("SELECT BotGroupName, BotGroupLeaderName FROM vwBotGroups WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4742,20 +4113,16 @@ std::list Bot::GetBotGroupListByBotOwnerCharacterId(uint32 botOwne 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 BotGroupId FROM vwBotGroups " - "WHERE BotGroupName = '%s'", botGroupName.c_str()); + std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups WHERE BotGroupName = '%s'", botGroupName.c_str()); auto results = database.QueryDatabase(query); if (!results.Success() || results.RowCount() == 0) return false; @@ -4763,7 +4130,6 @@ bool Bot::DoesBotGroupNameExist(std::string botGroupName) { 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; } @@ -4772,12 +4138,10 @@ bool Bot::DoesBotGroupNameExist(std::string botGroupName) { } uint32 Bot::CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName, std::string* errorMessage) { - if(botOwnerCharacterId == 0 || botGroupName.empty()) return 0; - std::string query = StringFormat("SELECT BotGroupId, BotGroupName FROM vwBotGroups " - "WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); + std::string query = StringFormat("SELECT BotGroupId, BotGroupName FROM vwBotGroups WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4788,10 +4152,8 @@ uint32 Bot::CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName return 0; for(auto row = results.begin(); row != results.end(); ++row) { - uint32 tempBotGroupId = atoi(row[0]); - std::string tempBotGroupName = std::string(row[1]); - + std::string tempBotGroupName = std::string(row[1]); if(botGroupName == tempBotGroupName) return tempBotGroupId; } @@ -4800,12 +4162,10 @@ uint32 Bot::CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName } uint32 Bot::GetBotGroupIdByBotGroupName(std::string botGroupName, std::string* errorMessage) { - if(botGroupName.empty()) return 0; - std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups " - "WHERE BotGroupName = '%s'", botGroupName.c_str()); + std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups WHERE BotGroupName = '%s'", botGroupName.c_str()); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4820,7 +4180,6 @@ uint32 Bot::GetBotGroupIdByBotGroupName(std::string botGroupName, std::string* e } uint32 Bot::GetBotGroupLeaderIdByBotGroupName(std::string botGroupName) { - if(botGroupName.empty()) return 0; @@ -4834,13 +4193,10 @@ uint32 Bot::GetBotGroupLeaderIdByBotGroupName(std::string botGroupName) { } 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); + 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()); @@ -4856,23 +4212,18 @@ uint32 Bot::AllowedBotSpawns(uint32 botOwnerCharacterID, std::string* errorMessa uint32 Bot::SpawnedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage) { uint32 Result = 0; - if(botOwnerCharacterID > 0) { std::list SpawnedBots = entity_list.GetBotsByBotOwnerCharacterID(botOwnerCharacterID); - Result = SpawnedBots.size(); } - return Result; } uint32 Bot::CreatedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage) { - if(botOwnerCharacterID == 0) return 0; - std::string query = StringFormat("SELECT COUNT(BotID) FROM bots " - "WHERE BotOwnerCharacterID=%i", botOwnerCharacterID); + std::string query = StringFormat("SELECT COUNT(BotID) FROM bots WHERE BotOwnerCharacterID=%i", botOwnerCharacterID); auto results = database.QueryDatabase(query); if (!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -5061,9 +4412,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); - if(item){ + if(item) return item; - } return nullptr; } @@ -5140,190 +4490,148 @@ bool Bot::Bot_Command_Resist(int resisttype, int level) { int resistid = 0; switch(resisttype) { case 1: // Poison Cleric - if(level >= 30) { + if(level >= 30) resistid = 62; - } - else if(level >= 6) { + else if(level >= 6) resistid = 227; - } break; case 2: // Disease Cleric - if(level >= 36) { + if(level >= 36) resistid = 63; - } - else if(level >= 11) { + else if(level >= 11) resistid = 226; - } break; case 3: // Fire Cleric - if(level >= 33) { + if(level >= 33) resistid = 60; - } - else if(level >= 8) { + else if(level >= 8) resistid = 224; - } break; case 4: // Cold Cleric - if(level >= 38) { + if(level >= 38) resistid = 61; - } - else if(level >= 13) { + else if(level >= 13) resistid = 225; - } break; case 5: // Magic Cleric - if(level >= 43) { + if(level >= 43) resistid = 64; - } - else if(level >= 16) { + else if(level >= 16) resistid = 228; - } break; case 6: // Magic Enchanter - if(level >= 37) { + if(level >= 37) resistid = 64; - } - else if(level >= 17) { + else if(level >= 17) resistid = 228; - } break; case 7: // Poison Druid - if(level >= 44) { + if(level >= 44) resistid = 62; - } - else if(level >= 19) { + else if(level >= 19) resistid = 227; - } break; case 8: // Disease Druid - if(level >= 44) { + if(level >= 44) resistid = 63; - } - else if(level >= 19) { + else if(level >= 19) resistid = 226; - } break; case 9: // Fire Druid - if(level >= 20) { + if(level >= 20) resistid = 60; - } - else if(level >= 1) { + else if(level >= 1) resistid = 224; - } break; case 10: // Cold Druid - if(level >= 30) { + if(level >= 30) resistid = 61; - } - else if(level >= 9) { + else if(level >= 9) resistid = 225; - } break; case 11: // Magic Druid - if(level >= 49) { + if(level >= 49) resistid = 64; - } - else if(level >= 34) { + else if(level >= 34) resistid = 228; - } break; case 12: // Poison Shaman - if(level >= 35) { + if(level >= 35) resistid = 62; - } - else if(level >= 20) { + else if(level >= 20) resistid = 227; - } break; case 13: // Disease Shaman - if(level >= 30) { + if(level >= 30) resistid = 63; - } - else if(level >= 8) { + else if(level >= 8) resistid = 226; - } break; case 14: // Fire Shaman - if(level >= 27) { + if(level >= 27) resistid = 60; - } - else if(level >= 5) { + else if(level >= 5) resistid = 224; - } break; case 15: // Cold Shaman - if(level >= 24) { + if(level >= 24) resistid = 61; - } - else if(level >= 1) { + else if(level >= 1) resistid = 225; - } break; case 16: // Magic Shaman - if(level >= 43) { + if(level >= 43) resistid = 64; - } - else if(level >= 19) { + else if(level >= 19) resistid = 228; - } break; } if(resistid > 0) { Group* g = GetGroup(); if(g) { - for(int k=0; kmembers[k]) { + 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) { if(bot->HasGroup()) { if(!group->IsLeader(bot)) { bot->SetFollowID(0); - if(group->DelMember(bot)) database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID()); - } - else { + } else { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(!group->members[i]) continue; group->members[i]->SetFollowID(0); } - group->DisbandGroup(); database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID()); } - Result = true; } } - return Result; } bool Bot::AddBotToGroup(Bot* bot, Group* group) { bool Result = false; - if(bot && group) { if(!bot->HasGroup()) { // Add bot to this group if(group->AddMember(bot)) { if(group->GetLeader()) { bot->SetFollowID(group->GetLeader()->GetID()); - // Need to send this only once when a group is formed with a bot so the client knows it is also the group leader if(group->GroupCount() == 2 && group->GetLeader()->IsClient()) { group->UpdateGroupAAs(); @@ -5331,45 +4639,35 @@ bool Bot::AddBotToGroup(Bot* bot, Group* group) { group->SendUpdate(groupActUpdate, TempLeader); } } - Result = true; } } } - 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; } @@ -5379,64 +4677,46 @@ bool Bot::Bot_Command_CharmTarget(int charmtype, Mob *target) { if(target) { switch(charmtype) { case 1: // Enchanter - if((charmlevel >= 64) && (charmlevel <= 75)) { + if((charmlevel >= 64) && (charmlevel <= 75)) charmid = 3355; - } - else if((charmlevel >= 62) && (charmlevel <= 63)) { + else if((charmlevel >= 62) && (charmlevel <= 63)) charmid = 3347; - } - else if((charmlevel >= 60) && (charmlevel <= 61)) { + else if((charmlevel >= 60) && (charmlevel <= 61)) charmid = 1707; - } - else if((charmlevel >= 53) && (charmlevel <= 59)) { + else if((charmlevel >= 53) && (charmlevel <= 59)) charmid = 1705; - } - else if((charmlevel >= 37) && (charmlevel <= 52)) { + else if((charmlevel >= 37) && (charmlevel <= 52)) charmid = 183; - } - else if((charmlevel >= 23) && (charmlevel <= 36)) { + else if((charmlevel >= 23) && (charmlevel <= 36)) charmid = 182; - } - else if((charmlevel >= 11) && (charmlevel <= 22)) { + else if((charmlevel >= 11) && (charmlevel <= 22)) charmid = 300; - } break; case 2: // Necromancer - if((charmlevel >= 60) && (charmlevel <= 75)) { + if((charmlevel >= 60) && (charmlevel <= 75)) charmid = 1629; - } - else if((charmlevel >=47) && (charmlevel <= 59)) { + else if((charmlevel >=47) && (charmlevel <= 59)) charmid = 198; - } - else if((charmlevel >= 31) && (charmlevel <= 46)) { + else if((charmlevel >= 31) && (charmlevel <= 46)) charmid = 197; - } - else if((charmlevel >= 18) && (charmlevel <= 30)) { + else if((charmlevel >= 18) && (charmlevel <= 30)) charmid = 196; - } break; case 3: // Druid - if((charmlevel >= 63) && (charmlevel <= 75)) { + if((charmlevel >= 63) && (charmlevel <= 75)) charmid = 3445; - } - else if((charmlevel >= 55) && (charmlevel <= 62)) { + else if((charmlevel >= 55) && (charmlevel <= 62)) charmid = 1556; - } - else if((charmlevel >= 52) && (charmlevel <= 54)) { + else if((charmlevel >= 52) && (charmlevel <= 54)) charmid = 1553; - } - else if((charmlevel >= 43) && (charmlevel <= 51)) { + else if((charmlevel >= 43) && (charmlevel <= 51)) charmid = 142; - } - else if((charmlevel >= 33) && (charmlevel <= 42)) { + else if((charmlevel >= 33) && (charmlevel <= 42)) charmid = 141; - } - else if((charmlevel >= 23) && (charmlevel <= 32)) { + else if((charmlevel >= 23) && (charmlevel <= 32)) charmid = 260; - } - else if((charmlevel >= 13) && (charmlevel <= 22)) { + else if((charmlevel >= 13) && (charmlevel <= 22)) charmid = 242; - } break; } if(charmid > 0) { @@ -5455,28 +4735,22 @@ bool Bot::Bot_Command_DireTarget(int diretype, Mob *target) { if(target) { switch(diretype) { case 1: // Enchanter - if(direlevel >= 65) { + if(direlevel >= 65) direid = 5874; - } - else if(direlevel >= 55) { + else if(direlevel >= 55) direid = 2761; - } break; case 2: // Necromancer - if(direlevel >= 65) { + if(direlevel >= 65) direid = 5876; - } - else if(direlevel >= 55) { + else if(direlevel >= 55) direid = 2759; - } break; case 3: // Druid - if(direlevel >= 65) { + if(direlevel >= 65) direid = 5875; - } - else if(direlevel >= 55) { + else if(direlevel >= 55) direid = 2760; - } break; } if(direid > 0) { @@ -5493,24 +4767,18 @@ bool Bot::Bot_Command_CalmTarget(Mob *target) { if(target) { int calmid = 0; int calmlevel = GetLevel(); - if((calmlevel >= 67) && (calmlevel <= 75)) { + if((calmlevel >= 67) && (calmlevel <= 75)) calmid = 5274; - } - else if((calmlevel >= 62) && (calmlevel <= 66)) { + else if((calmlevel >= 62) && (calmlevel <= 66)) calmid = 3197; - } - else if((calmlevel >= 35) && (calmlevel <= 61)) { + else if((calmlevel >= 35) && (calmlevel <= 61)) calmid = 45; - } - else if((calmlevel >= 18) && (calmlevel <= 34)) { + else if((calmlevel >= 18) && (calmlevel <= 34)) calmid = 47; - } - else if((calmlevel >= 6) && (calmlevel <= 17)) { + else if((calmlevel >= 6) && (calmlevel <= 17)) calmid = 501; - } - else if((calmlevel >= 1) && (calmlevel <= 5)) { + else if((calmlevel >= 1) && (calmlevel <= 5)) calmid = 208; - } if(calmid > 0) { uint32 DontRootMeBeforeTime = 0; CastSpell(calmid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); @@ -5525,30 +4793,22 @@ bool Bot::Bot_Command_RezzTarget(Mob *target) { if(target) { int rezid = 0; int rezlevel = GetLevel(); - if(rezlevel >= 56) { + if(rezlevel >= 56) rezid = 1524; - } - else if(rezlevel >= 47) { + else if(rezlevel >= 47) rezid = 392; - } - else if(rezlevel >= 42) { + else if(rezlevel >= 42) rezid = 2172; - } - else if(rezlevel >= 37) { + else if(rezlevel >= 37) rezid = 388; - } - else if(rezlevel >= 32) { + else if(rezlevel >= 32) rezid = 2171; - } - else if(rezlevel >= 27) { + else if(rezlevel >= 27) rezid = 391; - } - else if(rezlevel >= 22) { + else if(rezlevel >= 22) rezid = 2170; - } - else if(rezlevel >= 18) { + else if(rezlevel >= 18) rezid = 2169; - } if(rezid > 0) { uint32 DontRootMeBeforeTime = 0; CastSpell(rezid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); @@ -5563,58 +4823,45 @@ bool Bot::Bot_Command_Cure(int curetype, int level) { int cureid = 0; switch(curetype) { case 1: // Poison - if(level >= 58) { + if(level >= 58) cureid = 1525; - } - else if(level >= 48) { + else if(level >= 48) cureid = 97; - } - else if(level >= 22) { + else if(level >= 22) cureid = 95; - } - else if(level >= 1) { + else if(level >= 1) cureid = 203; - } break; case 2: // Disease - if(level >= 51) { + if(level >= 51) cureid = 3693; - } - else if(level >= 28) { + else if(level >= 28) cureid = 96; - } - else if(level >= 4) { + else if(level >= 4) cureid = 213; - } break; case 3: // Curse - if(level >= 54) { + if(level >= 54) cureid = 2880; - } - else if(level >= 38) { + else if(level >= 38) cureid = 2946; - } - else if(level >= 23) { + else if(level >= 23) cureid = 4057; - } - else if(level >= 8) { + else if(level >= 8) cureid = 4056; - } break; case 4: // Blindness - if(level >= 3) { + if(level >= 3) cureid = 212; - } break; } if(cureid > 0) { Group* g = GetGroup(); if(g) { - for(int k=0; kmembers[k]) { + for(int k = 0; k < MAX_GROUP_MEMBERS; k++) { + if(g->members[k]) SpellOnTarget(cureid, g->members[k]); - } } return true; } @@ -5868,40 +5115,35 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att return false; Save(); - Mob *give_exp = hate_list.GetDamageTopOnHateList(this); Client *give_exp_client = nullptr; - if(give_exp && give_exp->IsClient()) give_exp_client = give_exp->CastToClient(); bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE); - if(entity_list.GetCorpseByID(GetID())) entity_list.GetCorpseByID(GetID())->Depop(); Group *g = GetGroup(); if(g) { - for(int i=0; imembers[i]) { if(g->members[i] == this) { // If the leader dies, make the next bot the leader // and reset all bots followid if(g->IsLeader(g->members[i])) { - if(g->members[i+1]) { - g->SetLeader(g->members[i+1]); - g->members[i+1]->SetFollowID(g->members[i]->GetFollowID()); - for(int j=0; jmembers[j] && (g->members[j] != g->members[i+1])) { - g->members[j]->SetFollowID(g->members[i+1]->GetID()); - } + if(g->members[i + 1]) { + g->SetLeader(g->members[i + 1]); + g->members[i + 1]->SetFollowID(g->members[i]->GetFollowID()); + for(int j = 0; j < MAX_GROUP_MEMBERS; j++) { + if(g->members[j] && (g->members[j] != g->members[i + 1])) + g->members[j]->SetFollowID(g->members[i + 1]->GetID()); } } } // delete from group data RemoveBotFromGroup(this, g); - //Make sure group still exists if it doesnt they were already updated in RemoveBotFromGroup g = GetGroup(); if (!g) @@ -5909,8 +5151,8 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att // if group members exist below this one, move // them all up one slot in the group list - int j = i+1; - for(; jmembers[j]) { g->members[j-1] = g->members[j]; strcpy(g->membername[j-1], g->members[j]->GetCleanName()); @@ -5926,55 +5168,26 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att gu->action = groupActLeave; strcpy(gu->membername, GetCleanName()); if(g) { - for(int k=0; kmembers[k] && g->members[k]->IsClient()) g->members[k]->CastToClient()->QueuePacket(outapp); } } safe_delete(outapp); - - // now that's done, lets see if all we have left is the client - // and we can clean up the clients raid group and group - /*if(GetBotRaidID()) { - BotRaids* br = entity_list.GetBotRaidByMob(this); - if(br) { - if(this == br->botmaintank) { - br->botmaintank = nullptr; - } - if(this == br->botsecondtank) { - br->botsecondtank = nullptr; - } - } - if(g->GroupCount() == 0) { - uint32 gid = g->GetID(); - if(br) { - br->RemoveEmptyBotGroup(); - } - entity_list.RemoveGroup(gid); - } - if(br && (br->RaidBotGroupsCount() == 1)) { - br->RemoveClientGroup(br->GetRaidBotLeader()); - } - if(br && (br->RaidBotGroupsCount() == 0)) { - br->DisbandBotRaid(); - } - }*/ } } } } - if(GetInHealRotation()) { + if(GetInHealRotation()) GetHealRotationLeader()->RemoveHealRotationMember(this); - } entity_list.RemoveBot(this->GetID()); - return true; } void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) { - if(spell_id==0) + if(spell_id == 0) spell_id = SPELL_UNKNOWN; //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds @@ -5982,13 +5195,8 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ Log.Out(Logs::Detail, Logs::Combat, "Triggering EVENT_ATTACK due to attack by %s", from->GetName()); parse->EventNPC(EVENT_ATTACK, this, from, "", 0); } - + attacked_timer.Start(CombatEventTimer_expire); - - // TODO: A bot doesnt call this, right? - /*if (!IsEngaged()) - zone->AddAggroMob();*/ - // if spell is lifetap add hp to the caster if (spell_id != SPELL_UNKNOWN && IsLifetapSpell(spell_id)) { int healed = GetActSpellHealing(spell_id, damage); @@ -5998,7 +5206,6 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ } CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); - if(GetHP() < 0) { if(IsCasting()) InterruptSpell(); @@ -6006,35 +5213,26 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ } SendHPUpdate(); - - if(this == from) { + if(this == from) return; - } // Aggro the bot's group members - if(IsGrouped()) - { + if(IsGrouped()) { Group *g = GetGroup(); - if(g) - { - for(int i=0; imembers[i] && g->members[i]->IsBot() && from && !g->members[i]->CheckAggro(from) && g->members[i]->IsAttackAllowed(from)) - { g->members[i]->AddToHateList(from, 1); - } } } } } -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*/) { Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic); } -bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) -{ +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!"); @@ -6045,15 +5243,10 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b SetTarget(other); 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 ((IsCasting() && (GetClass() != BARD) && !IsFromSpell) || other == nullptr || (GetHP() < 0) || (GetAppearance() == eaDead) || (!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()); + if(other) { RemoveFromHateList(other); Log.Out(Logs::Detail, Logs::Combat, "I am not allowed to attack %s", other->GetCleanName()); @@ -6065,22 +5258,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Divine Aura is in effect."); return false; } - - // TODO: Uncomment this block after solved the bug that is assigning a null value to GetTarget() for bots while in combat. Appears to happen at random, but frequently. - /*if(HasGroup() && _previousTarget != GetTarget()) { - std::ostringstream attackMessage; - attackMessage << "Attacking " << other->GetCleanName() << "."; - - GetGroup()->GroupMessage(this, 0, 100, attackMessage.str().c_str()); - }*/ - + FaceTarget(GetTarget()); - ItemInst* weapon = nullptr; if(Hand == MainPrimary) { weapon = GetBotItem(MainPrimary); OffHandAtk(false); } + if(Hand == MainSecondary) { weapon = GetBotItem(MainSecondary); OffHandAtk(true); @@ -6089,46 +5274,46 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if(weapon != nullptr) { if (!weapon->IsWeapon()) { Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID()); - return(false); + return false; } Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID()); - } else { - Log.Out(Logs::Detail, Logs::Combat, "Attacking without a weapon."); } + else + Log.Out(Logs::Detail, Logs::Combat, "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); 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 int 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); + int weapon_damage = GetWeaponDamage(other, weapon, &hate); - if (hate == 0 && weapon_damage > 1) hate = weapon_damage; + 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){ - + 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; + 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); - } + if(TryFinishingBlow(other, skillinuse)) + return true; //damage formula needs some work int min_hit = 1; - int max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100; + int max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10)) max_hit = (RuleI(Combat, HitCapPre10)); @@ -6146,16 +5331,11 @@ 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 == MainPrimary && 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 Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -6164,16 +5344,14 @@ 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==MainSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); - + 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; + min_hit = (min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100); if(max_hit < min_hit) max_hit = min_hit; @@ -6203,7 +5381,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b other->MeleeMitigation(this, damage, min_hit, opts); if(damage > 0) { ApplyMeleeDamageBonus(skillinuse, damage); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); + damage += ((itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse)); TryCriticalHit(other, skillinuse, damage, opts); Log.Out(Logs::Detail, Logs::Combat, "Generating hate %d towards %s", hate, GetCleanName()); // now add done damage to the hate list @@ -6217,12 +5395,13 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b //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 (FromRiposte) return false; + if (FromRiposte) + return false; else { if (Hand == MainSecondary) {// 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. - int32 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; + int32 OffhandRiposteFail = (aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail); OffhandRiposteFail *= -1; //Live uses a negative value for this. if (OffhandRiposteFail && @@ -6231,17 +5410,18 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b slippery_attack = true; } else DoRiposte(other); - if (GetHP() < 0) return false; + if (GetHP() < 0) + return false; } else DoRiposte(other); - if (GetHP() < 0) return false; + if (GetHP() < 0) + return false; } } if (((damage < 0) || slippery_attack) && !FromRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA - int32 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; - + int32 bonusStrikeThrough = (itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough); if(bonusStrikeThrough && (zone->random.Int(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 @@ -6249,22 +5429,21 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } } } - else{ + 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 (!FromRiposte) {// Ripostes never generate any aggro. + if (!FromRiposte) other->AddToHateList(this, hate); - } /////////////////////////////////////////////////////////// ////// Send Attack Damage /////////////////////////////////////////////////////////// other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - if (GetHP() < 0) return false; + if (GetHP() < 0) + return false; MeleeLifeTap(damage); @@ -6278,12 +5457,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b 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); @@ -6310,15 +5491,12 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if (damage > 0) return true; - else return false; } -int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) -{ +int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) { const SPDat_Spell_Struct &spell = spells[spell_id]; - int32 value = 0; int lvlModifier = 100; int spell_level = 0; @@ -6329,116 +5507,94 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) int32 base1 = 0; int32 base2 = 0; uint32 slot = 0; - bool LimitFound = false; int FocusCount = 0; - std::map >::const_iterator find_iter = aa_effects.find(aa_ID); if(find_iter == aa_effects.end()) - { return 0; - } - - for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - { + + for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) { effect = iter->second.skill_id; base1 = iter->second.base1; base2 = iter->second.base2; slot = iter->second.slot; - //AA Foci's can contain multiple focus effects within the same AA. //To handle this we will not automatically return zero if a limit is found. //Instead if limit is found and multiple effects, we will reset the limit check //when the next valid focus effect is found. - if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ + if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)) { FocusCount++; //If limit found on prior check next, else end loop. - if (FocusCount > 1){ - if (LimitFound){ + if (FocusCount > 1) { + if (LimitFound) { value = 0; LimitFound = false; } - - else{ + else break; - } } } - switch (effect) - { + switch (effect) { case SE_Blank: break; - - //Handle Focus Limits case SE_LimitResist: - if(base1) - { + if(base1) { if(spell.resisttype != base1) LimitFound = true; } - break; + break; case SE_LimitInstant: if(spell.buffduration) LimitFound = true; - break; + break; case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass()%16) - 1]; + spell_level = spell.classes[(GetClass() % 16) - 1]; lvldiff = spell_level - base1; //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) - { - if(base2 > 0) - { - lvlModifier -= base2*lvldiff; + if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { + if(base2 > 0) { + lvlModifier -= (base2 * lvldiff); if(lvlModifier < 1) LimitFound = true; } - else { + else LimitFound = true; - } } - break; + break; case SE_LimitMinLevel: - if((spell.classes[(GetClass()%16) - 1]) < base1) + if((spell.classes[(GetClass() % 16) - 1]) < base1) LimitFound = true; - break; + break; case SE_LimitCastTimeMin: if (spell.cast_time < base1) LimitFound = true; - break; + break; case SE_LimitSpell: - // Exclude spell(any but this) if(base1 < 0) { if (spell_id == (base1*-1)) LimitFound = true; - } - else { - // Include Spell(only this) + } else { if (spell_id != base1) LimitFound = true; } - break; + break; case SE_LimitMinDur: if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) LimitFound = true; - break; + break; case SE_LimitEffect: - // Exclude effect(any but this) if(base1 < 0) { if(IsEffectInSpell(spell_id,(base1*-1))) LimitFound = true; - } - else { - // Include effect(only this) + } else { if(!IsEffectInSpell(spell_id,base1)) LimitFound = true; } - break; + break; case SE_LimitSpellType: - switch(base1) - { + switch(base1) { case 0: if (!IsDetrimentalSpell(spell_id)) LimitFound = true; @@ -6448,130 +5604,93 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) LimitFound = true; break; } - break; + break; case SE_LimitManaMin: if(spell.mana < base1) LimitFound = true; - break; - + break; case SE_LimitTarget: - // Exclude - if(base1 < 0){ - if(-base1 == spell.targettype) - LimitFound = true; - } - // Include - else { - if(base1 != spell.targettype) - LimitFound = true; - } - break; - + if(base1 < 0) { + if(-base1 == spell.targettype) + LimitFound = true; + } else { + if(base1 != spell.targettype) + LimitFound = true; + } + break; case SE_LimitCombatSkills: - // 1 is for disciplines only - if(base1 == 1 && !IsDiscipline(spell_id)) - LimitFound = true; - // 0 is spells only - else if(base1 == 0 && IsDiscipline(spell_id)) + if((base1 == 1 && !IsDiscipline(spell_id)) || (base1 == 0 && IsDiscipline(spell_id))) LimitFound = true; break; - case SE_LimitSpellGroup: - if(base1 > 0 && base1 != spell.spellgroup) + if((base1 > 0 && base1 != spell.spellgroup) || (base1 < 0 && base1 == spell.spellgroup)) LimitFound = true; - else if(base1 < 0 && base1 == spell.spellgroup) - LimitFound = true; - break; - - + break; case SE_LimitCastingSkill: LimitSpellSkill = true; if(base1 == spell.skill) SpellSkill_Found = true; - break; - + break; case SE_LimitClass: //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(base1, GetClass())) - LimitFound = true; - break; - - + if (!PassLimitClass(base1, GetClass())) + LimitFound = true; + break; //Handle Focus Effects case SE_ImprovedDamage: if (type == focusImprovedDamage && base1 > value) value = base1; - break; - + break; case SE_ImprovedHeal: if (type == focusImprovedHeal && base1 > value) value = base1; - break; - + break; case SE_ReduceManaCost: - if (type == focusManaCost ) + if (type == focusManaCost) value = base1; - break; - + break; case SE_IncreaseSpellHaste: if (type == focusSpellHaste && base1 > value) value = base1; break; - case SE_IncreaseSpellDuration: if (type == focusSpellDuration && base1 > value) value = base1; break; - case SE_SpellDurationIncByTic: if (type == focusSpellDurByTic && base1 > value) value = base1; break; - case SE_SwarmPetDuration: if (type == focusSwarmPetDuration && base1 > value) value = base1; break; - case SE_IncreaseRange: if (type == focusRange && base1 > value) value = base1; break; - case SE_ReduceReagentCost: if (type == focusReagentCost && base1 > value) value = base1; break; - case SE_PetPowerIncrease: if (type == focusPetPower && base1 > value) value = base1; break; - case SE_SpellResistReduction: if (type == focusResistRate && base1 > value) value = base1; break; - case SE_SpellHateMod: - if (type == focusSpellHateMod) - { - if(value != 0) - { - if(value > 0) - { + if (type == focusSpellHateMod) { + if(value != 0) { + if(value > 0) { if(base1 > value) - { value = base1; - } - } - else - { + } else { if(base1 < value) - { value = base1; - } } } else @@ -6579,158 +5698,100 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) } break; - case SE_ReduceReuseTimer: - { + case SE_ReduceReuseTimer: { if(type == focusReduceRecastTime) - value = base1 / 1000; - + value = (base1 / 1000); break; } - - case SE_TriggerOnCast: - { - if(type == focusTriggerOnCast) - { - if(zone->random.Int(0, 100) <= base1){ + case SE_TriggerOnCast: { + if(type == focusTriggerOnCast) { + if(zone->random.Int(0, 100) <= base1) value = base2; - } - - else{ + else { value = 0; LimitFound = true; } } break; } - case SE_FcSpellVulnerability: - { + case SE_FcSpellVulnerability: { if(type == focusSpellVulnerability) - { value = base1; - } break; } - case SE_BlockNextSpellFocus: - { - if(type == focusBlockNextSpell) - { + case SE_BlockNextSpellFocus: { + if(type == focusBlockNextSpell) { if(zone->random.Int(1, 100) <= base1) value = 1; } break; } - case SE_FcTwincast: - { + case SE_FcTwincast: { if(type == focusTwincast) - { 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); - - if(zone->random.Real(0, 1) <= ProcChance) - value = focus_id; - - else - value = 0; - } - break; - } - */ - case SE_FcDamageAmt: - { + case SE_FcDamageAmt: { if(type == focusFcDamageAmt) value = base1; - break; } - - case SE_FcDamageAmtCrit: - { + case SE_FcDamageAmtCrit: { if(type == focusFcDamageAmtCrit) value = base1; - break; } - - case SE_FcDamageAmtIncoming: - { + case SE_FcDamageAmtIncoming: { if(type == focusFcDamageAmtIncoming) value = base1; - break; } - case SE_FcHealAmtIncoming: if(type == focusFcHealAmtIncoming) value = base1; break; - case SE_FcHealPctCritIncoming: if (type == focusFcHealPctCritIncoming) value = base1; break; - case SE_FcHealAmtCrit: if(type == focusFcHealAmtCrit) value = base1; break; - case SE_FcHealAmt: if(type == focusFcHealAmt) value = base1; break; - case SE_FcHealPctIncoming: if(type == focusFcHealPctIncoming) value = base1; break; - - case SE_FcBaseEffects: - { + case SE_FcBaseEffects: { if (type == focusFcBaseEffects) value = base1; - break; } - case SE_FcDamagePctCrit: - { + case SE_FcDamagePctCrit: { if(type == focusFcDamagePctCrit) value = base1; - break; } - - case SE_FcIncreaseNumHits: - { + case SE_FcIncreaseNumHits: { if(type == focusIncreaseNumHits) value = base1; - break; } //Check for spell skill limits. - if ((LimitSpellSkill) && (!SpellSkill_Found)) - return 0; - + if ((LimitSpellSkill) && (!SpellSkill_Found)) + return 0; } } - if (LimitFound){ + if (LimitFound) return 0; - } - return(value*lvlModifier/100); + return (value * lvlModifier / 100); } int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { @@ -6741,18 +5802,13 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { int32 realTotal2 = 0; int32 realTotal3 = 0; bool rand_effectiveness = false; - //Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages //In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance - if((bottype == BotfocusManaCost || bottype == BotfocusImprovedHeal || bottype == BotfocusImprovedDamage) - && RuleB(Spells, LiveLikeFocusEffects)) - { + if((bottype == BotfocusManaCost || bottype == BotfocusImprovedHeal || bottype == BotfocusImprovedDamage) && RuleB(Spells, LiveLikeFocusEffects)) rand_effectiveness = true; - } //Check if item focus effect exists for the client. - if (itembonuses.FocusEffects[bottype]){ - + if (itembonuses.FocusEffects[bottype]) { const Item_Struct* TempItem = 0; const Item_Struct* UsedItem = 0; const ItemInst* TempInst = 0; @@ -6760,35 +5816,25 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { int32 Total = 0; 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 = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) { TempItem = nullptr; ItemInst* ins = GetBotItem(x); if (!ins) continue; + TempItem = ins->GetItem(); if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcBotFocusEffect(bottype, TempItem->Focus.Effect, spell_id, true); - if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { - focus_max_real = focus_max; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; - } else if (focus_max < 0 && focus_max < focus_max_real) { + if ((focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) || (focus_max < 0 && focus_max < focus_max_real)) { focus_max_real = focus_max; UsedItem = TempItem; UsedFocusID = TempItem->Focus.Effect; } - } - else { + } else { Total = CalcBotFocusEffect(bottype, TempItem->Focus.Effect, spell_id); - if (Total > 0 && realTotal >= 0 && Total > realTotal) { - realTotal = Total; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; - } else if (Total < 0 && Total < realTotal) { + if ((Total > 0 && realTotal >= 0 && Total > realTotal) || (Total < 0 && Total < realTotal)) { realTotal = Total; UsedItem = TempItem; UsedFocusID = TempItem->Focus.Effect; @@ -6796,33 +5842,22 @@ 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 < EmuConstants::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); - if(aug) - { + if(aug) { const 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); - if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { - focus_max_real = focus_max; - UsedItem = TempItem; - UsedFocusID = TempItemAug->Focus.Effect; - } else if (focus_max < 0 && focus_max < focus_max_real) { + if ((focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) || (focus_max < 0 && focus_max < focus_max_real)) { focus_max_real = focus_max; UsedItem = TempItem; UsedFocusID = TempItemAug->Focus.Effect; } - } - else { + } else { Total = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id); - if (Total > 0 && realTotal >= 0 && Total > realTotal) { - realTotal = Total; - UsedItem = TempItem; - UsedFocusID = TempItemAug->Focus.Effect; - } else if (Total < 0 && Total < realTotal) { + if ((Total > 0 && realTotal >= 0 && Total > realTotal) || (Total < 0 && Total < realTotal)) { realTotal = Total; UsedItem = TempItem; UsedFocusID = TempItemAug->Focus.Effect; @@ -6838,13 +5873,11 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } //Check if spell focus effect exists for the client. - if (spellbonuses.FocusEffects[bottype]){ - + if (spellbonuses.FocusEffects[bottype]) { //Spell Focus int32 Total2 = 0; int32 focus_max2 = 0; int32 focus_max_real2 = 0; - int buff_tracker = -1; int buff_slot = 0; uint32 focusspellid = 0; @@ -6857,23 +5890,14 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { if(rand_effectiveness) { focus_max2 = CalcBotFocusEffect(bottype, focusspellid, spell_id, true); - if (focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) { - focus_max_real2 = focus_max2; - buff_tracker = buff_slot; - focusspell_tracker = focusspellid; - } else if (focus_max2 < 0 && focus_max2 < focus_max_real2) { + if ((focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) || (focus_max2 < 0 && focus_max2 < focus_max_real2)) { focus_max_real2 = focus_max2; buff_tracker = buff_slot; focusspell_tracker = focusspellid; } - } - else { + } else { Total2 = CalcBotFocusEffect(bottype, focusspellid, spell_id); - if (Total2 > 0 && realTotal2 >= 0 && Total2 > realTotal2) { - realTotal2 = Total2; - buff_tracker = buff_slot; - focusspell_tracker = focusspellid; - } else if (Total2 < 0 && Total2 < realTotal2) { + if ((Total2 > 0 && realTotal2 >= 0 && Total2 > realTotal2) || (Total2 < 0 && Total2 < realTotal2)) { realTotal2 = Total2; buff_tracker = buff_slot; focusspell_tracker = focusspellid; @@ -6885,20 +5909,17 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { realTotal2 = CalcBotFocusEffect(bottype, focusspell_tracker, spell_id); // For effects like gift of mana that only fire once, save the spellid into an array that consists of all available buff slots. - if(buff_tracker >= 0 && buffs[buff_tracker].numhits > 0) { + if(buff_tracker >= 0 && buffs[buff_tracker].numhits > 0) m_spellHitsLeft[buff_tracker] = focusspell_tracker; - } } // AA Focus - if (aabonuses.FocusEffects[bottype]){ - + if (aabonuses.FocusEffects[bottype]) { int totalAAs = database.CountAAs(); int32 Total3 = 0; uint32 slots = 0; uint32 aa_AA = 0; uint32 aa_value = 0; - for (int i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs std::map::iterator aa = botAAs.find(i); if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone @@ -6908,12 +5929,8 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { continue; Total3 = CalcBotAAFocus(bottype, aa_AA, spell_id); - if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { + if ((Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) || (Total3 < 0 && Total3 < realTotal3)) realTotal3 = Total3; - } - else if (Total3 < 0 && Total3 < realTotal3) { - realTotal3 = Total3; - } } } } @@ -6921,13 +5938,10 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { if(bottype == BotfocusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) return 100; - if(bottype == BotfocusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))){ + if(bottype == BotfocusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) return 0; - //Summon Spells that require reagents are typically imbue type spells, enchant metal, sacrifice and shouldn't be affected - //by reagent conservation for obvious reasons. - } - return realTotal + realTotal2; + return (realTotal + realTotal2); } int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus) { @@ -6936,433 +5950,317 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel const SPDat_Spell_Struct &focus_spell = spells[focus_id]; const SPDat_Spell_Struct &spell = spells[spell_id]; - int32 value = 0; int lvlModifier = 100; int spell_level = 0; int lvldiff = 0; bool LimitSpellSkill = false; bool SpellSkill_Found = false; - for (int i = 0; i < EFFECT_COUNT; i++) { switch (focus_spell.effectid[i]) { - case SE_Blank: - break; - //check limits - - case SE_LimitResist:{ - if(focus_spell.base[i]){ - if(spell.resisttype != focus_spell.base[i]) - return(0); - } - break; - } - case SE_LimitInstant:{ - if(spell.buffduration) - return(0); - break; - } - - case SE_LimitMaxLevel:{ - if (IsNPC()) + case SE_Blank: break; - spell_level = spell.classes[(GetClass()%16) - 1]; - lvldiff = spell_level - focus_spell.base[i]; - //every level over cap reduces the effect by focus_spell.base2[i] percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) - { - if(focus_spell.base2[i] > 0) - { - lvlModifier -= focus_spell.base2[i]*lvldiff; - if(lvlModifier < 1) + case SE_LimitResist:{ + if(focus_spell.base[i]) { + if(spell.resisttype != focus_spell.base[i]) return 0; } - else - { - return 0; - } - } - break; - } - - case SE_LimitMinLevel: - if (IsNPC()) break; - if (spell.classes[(GetClass()%16) - 1] < focus_spell.base[i]) - return(0); - break; - - case SE_LimitCastTimeMin: - if (spells[spell_id].cast_time < (uint32)focus_spell.base[i]) - return(0); - break; - - case SE_LimitSpell: - if(focus_spell.base[i] < 0) { //exclude spell - if (spell_id == (focus_spell.base[i]*-1)) - return(0); - } else { - //this makes the assumption that only one spell can be explicitly included... - if (spell_id != focus_spell.base[i]) - return(0); } - break; - - case SE_LimitMinDur: - if (focus_spell.base[i] > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - return(0); - break; - - case SE_LimitEffect: - if(focus_spell.base[i] < 0){ - if(IsEffectInSpell(spell_id,focus_spell.base[i])){ //we limit this effect, can't have + case SE_LimitInstant: { + if(spell.buffduration) return 0; - } + break; } - else{ - if(focus_spell.base[i] == SE_SummonPet) //summoning haste special case - { //must have one of the three pet effects to qualify - if(!IsEffectInSpell(spell_id, SE_SummonPet) && - !IsEffectInSpell(spell_id, SE_NecPet) && - !IsEffectInSpell(spell_id, SE_SummonBSTPet)) - { - return 0; + case SE_LimitMaxLevel:{ + if (IsNPC()) + break; + spell_level = spell.classes[(GetClass() % 16) - 1]; + lvldiff = (spell_level - focus_spell.base[i]); + if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { + if(focus_spell.base2[i] > 0) { + lvlModifier -= (focus_spell.base2[i] * lvldiff); + if(lvlModifier < 1) + return 0; } + else + return 0; } - else if(!IsEffectInSpell(spell_id,focus_spell.base[i])){ //we limit this effect, must have + break; + } + case SE_LimitMinLevel: + if (IsNPC()) + break; + if (spell.classes[(GetClass() % 16) - 1] < focus_spell.base[i]) return 0; + break; + + case SE_LimitCastTimeMin: + if (spells[spell_id].cast_time < (uint32)focus_spell.base[i]) + return 0; + break; + case SE_LimitSpell: + if(focus_spell.base[i] < 0) { + if (spell_id == (focus_spell.base[i] * -1)) + return 0; + } else { + if (spell_id != focus_spell.base[i]) + return 0; } - } - break; - - - case SE_LimitSpellType: - switch( focus_spell.base[i] ) - { - case 0: - if (!IsDetrimentalSpell(spell_id)) + break; + case SE_LimitMinDur: + if (focus_spell.base[i] > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + return 0; + break; + case SE_LimitEffect: + if(focus_spell.base[i] < 0) { + if(IsEffectInSpell(spell_id,focus_spell.base[i])) return 0; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) + } else { + if(focus_spell.base[i] == SE_SummonPet) { + if(!IsEffectInSpell(spell_id, SE_SummonPet) && !IsEffectInSpell(spell_id, SE_NecPet) && !IsEffectInSpell(spell_id, SE_SummonBSTPet)) { + return 0; + } + } else if(!IsEffectInSpell(spell_id,focus_spell.base[i])) return 0; - break; - default: - Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]); - } - break; - - case SE_LimitManaMin: + } + break; + + + case SE_LimitSpellType: + switch(focus_spell.base[i]) { + case 0: + if (!IsDetrimentalSpell(spell_id)) + return 0; + break; + case 1: + if (!IsBeneficialSpell(spell_id)) + return 0; + break; + default: + Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]); + } + break; + + case SE_LimitManaMin: if(spell.mana < focus_spell.base[i]) return 0; - break; - - case SE_LimitTarget: - // Exclude - if((focus_spell.base[i] < 0) && -focus_spell.base[i] == spell.targettype) - return 0; - // Include - else if (focus_spell.base[i] > 0 && focus_spell.base[i] != spell.targettype) - return 0; - - break; - - case SE_LimitCombatSkills: - // 1 is for disciplines only + break; + case SE_LimitTarget: + if((focus_spell.base[i] < 0) && -focus_spell.base[i] == spell.targettype) + return 0; + else if (focus_spell.base[i] > 0 && focus_spell.base[i] != spell.targettype) + return 0; + break; + case SE_LimitCombatSkills: if(focus_spell.base[i] == 1 && !IsDiscipline(spell_id)) return 0; - // 0 is for spells only else if(focus_spell.base[i] == 0 && IsDiscipline(spell_id)) return 0; - break; - - case SE_LimitSpellGroup: + break; + case SE_LimitSpellGroup: if(focus_spell.base[i] > 0 && focus_spell.base[i] != spell.spellgroup) return 0; else if(focus_spell.base[i] < 0 && focus_spell.base[i] == spell.spellgroup) return 0; - break; - - case SE_LimitCastingSkill: + break; + case SE_LimitCastingSkill: LimitSpellSkill = true; if(focus_spell.base[i] == spell.skill) SpellSkill_Found = true; - break; - - case SE_LimitClass: - //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(focus_spell.base[i], GetClass())) - return 0; - break; - - //handle effects - case SE_ImprovedDamage: - // No Spell used this, its handled by different spell effect IDs. - if (bottype == BotfocusImprovedDamage) { - // This is used to determine which focus should be used for the random calculation - if(best_focus) { - // If the spell contains a value in the base2 field then that is the max value - if (focus_spell.base2[i] != 0) { - value = focus_spell.base2[i]; - } - // If the spell does not contain a base2 value, then its a straight non random value - else { - value = focus_spell.base[i]; - } - } - // Actual focus calculation starts here - else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { - value = focus_spell.base[i]; - } - else { - value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); - } - } - break; - case SE_ImprovedHeal: - if (bottype == BotfocusImprovedHeal) { - if(best_focus) { - if (focus_spell.base2[i] != 0) { - value = focus_spell.base2[i]; - } - else { - value = focus_spell.base[i]; - } - } - else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { - value = focus_spell.base[i]; - } - else { - value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); - } - } - break; - case SE_ReduceManaCost: - if (bottype == BotfocusManaCost) { - if(best_focus) { - if (focus_spell.base2[i] != 0) { - value = focus_spell.base2[i]; - } - else { - value = focus_spell.base[i]; - } - } - else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { - value = focus_spell.base[i]; - } - else { - value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); - } - } - break; - - case SE_IncreaseSpellHaste: - if (bottype == BotfocusSpellHaste && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_IncreaseSpellDuration: - if (bottype == BotfocusSpellDuration && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_SpellDurationIncByTic: - if (bottype == BotfocusSpellDurByTic && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_SwarmPetDuration: - if (bottype == BotfocusSwarmPetDuration && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_IncreaseRange: - if (bottype == BotfocusRange && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_ReduceReagentCost: - if (bottype == BotfocusReagentCost && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_PetPowerIncrease: - if (bottype == BotfocusPetPower && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_SpellResistReduction: - if (bottype == BotfocusResistRate && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_SpellHateMod: - if (bottype == BotfocusSpellHateMod) - { - if(value != 0) - { - if(value > 0) - { - if(focus_spell.base[i] > value) - { + break; + case SE_LimitClass: + if (!PassLimitClass(focus_spell.base[i], GetClass())) + return 0; + break; + case SE_ImprovedDamage: + if (bottype == BotfocusImprovedDamage) { + if(best_focus) { + if (focus_spell.base2[i] != 0) + value = focus_spell.base2[i]; + else value = focus_spell.base[i]; - } } + else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) + value = focus_spell.base[i]; else - { - if(focus_spell.base[i] < value) - { - value = focus_spell.base[i]; - } - } + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } - else + break; + case SE_ImprovedHeal: + if (bottype == BotfocusImprovedHeal) { + if(best_focus) { + if (focus_spell.base2[i] != 0) + value = focus_spell.base2[i]; + else + value = focus_spell.base[i]; + } + else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) + value = focus_spell.base[i]; + else + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); + } + break; + case SE_ReduceManaCost: + if (bottype == BotfocusManaCost) { + if(best_focus) { + if (focus_spell.base2[i] != 0) + value = focus_spell.base2[i]; + else + value = focus_spell.base[i]; + } + else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) + value = focus_spell.base[i]; + else + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); + } + break; + case SE_IncreaseSpellHaste: + if (bottype == BotfocusSpellHaste && focus_spell.base[i] > value) value = focus_spell.base[i]; + break; + case SE_IncreaseSpellDuration: + if (bottype == BotfocusSpellDuration && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_SpellDurationIncByTic: + if (bottype == BotfocusSpellDurByTic && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_SwarmPetDuration: + if (bottype == BotfocusSwarmPetDuration && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_IncreaseRange: + if (bottype == BotfocusRange && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_ReduceReagentCost: + if (bottype == BotfocusReagentCost && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_PetPowerIncrease: + if (bottype == BotfocusPetPower && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_SpellResistReduction: + if (bottype == BotfocusResistRate && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_SpellHateMod: + if (bottype == BotfocusSpellHateMod) { + if(value != 0) { + if(value > 0) { + if(focus_spell.base[i] > value) + value = focus_spell.base[i]; + } + else { + if(focus_spell.base[i] < value) + value = focus_spell.base[i]; + } + } else + value = focus_spell.base[i]; + } + break; + case SE_ReduceReuseTimer: { + if(bottype == BotfocusReduceRecastTime) + value = (focus_spell.base[i] / 1000); + break; } - break; - - case SE_ReduceReuseTimer: - { - if(bottype == BotfocusReduceRecastTime) - value = focus_spell.base[i] / 1000; - - break; - } - - case SE_TriggerOnCast: - { - if(bottype == BotfocusTriggerOnCast) - - if(zone->random.Int(0, 100) <= focus_spell.base[i]) - value = focus_spell.base2[i]; - - else - value = 0; - - break; - } - case SE_FcSpellVulnerability: - { - if(bottype == BotfocusSpellVulnerability) - { - value = focus_spell.base[i]; + case SE_TriggerOnCast: { + if(bottype == BotfocusTriggerOnCast) { + if(zone->random.Int(0, 100) <= focus_spell.base[i]) + value = focus_spell.base2[i]; + else + value = 0; + } + break; } - break; - } - case SE_BlockNextSpellFocus: - { - if(bottype == BotfocusBlockNextSpell) - { - if(zone->random.Int(1, 100) <= focus_spell.base[i]) - value = 1; + case SE_FcSpellVulnerability: { + if(bottype == BotfocusSpellVulnerability) + value = focus_spell.base[i]; + break; } - break; - } - case SE_FcTwincast: - { - if(bottype == BotfocusTwincast) - { - value = focus_spell.base[i]; + case SE_BlockNextSpellFocus: { + if(bottype == BotfocusBlockNextSpell) { + if(zone->random.Int(1, 100) <= focus_spell.base[i]) + value = 1; + } + break; } - break; - } - case SE_SympatheticProc: - { - if(bottype == BotfocusSympatheticProc) - { - - float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]); - - if(zone->random.Real(0, 1) <= ProcChance) - value = focus_id; - - else - value = 0; + case SE_FcTwincast: { + if(bottype == BotfocusTwincast) + value = focus_spell.base[i]; + break; } - break; - } - case SE_FcDamageAmt: - { - if(bottype == BotfocusFcDamageAmt) - value = focus_spell.base[i]; - - break; - } - - case SE_FcDamageAmtCrit: - { - if(bottype == BotfocusFcDamageAmtCrit) - value = focus_spell.base[i]; - - break; - } - - case SE_FcHealAmtIncoming: - if(bottype == BotfocusFcHealAmtIncoming) - value = focus_spell.base[i]; - break; - - case SE_FcHealPctCritIncoming: - if (bottype == BotfocusFcHealPctCritIncoming) - value = focus_spell.base[i]; - break; - - case SE_FcHealAmtCrit: - if(bottype == BotfocusFcHealAmtCrit) - value = focus_spell.base[i]; - break; - - case SE_FcHealAmt: - if(bottype == BotfocusFcHealAmt) - value = focus_spell.base[i]; - break; - - case SE_FcHealPctIncoming: - if(bottype == BotfocusFcHealPctIncoming) - value = focus_spell.base[i]; - break; - - case SE_FcBaseEffects: - { - if (bottype == BotfocusFcBaseEffects) - value = focus_spell.base[i]; - - break; - } - case SE_FcDamagePctCrit: - { - if(bottype == BotfocusFcDamagePctCrit) - value = focus_spell.base[i]; - - break; - } - - case SE_FcIncreaseNumHits: - { - if(bottype == BotfocusIncreaseNumHits) - value = focus_spell.base[i]; - - break; - } - //this spits up a lot of garbage when calculating spell focuses - //since they have all kinds of extra effects on them. - default: - Log.Out(Logs::General, Logs::Spells, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]); + case SE_SympatheticProc: { + if(bottype == BotfocusSympatheticProc) { + float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]); + if(zone->random.Real(0, 1) <= ProcChance) + value = focus_id; + else + value = 0; + } + break; + } + case SE_FcDamageAmt: { + if(bottype == BotfocusFcDamageAmt) + value = focus_spell.base[i]; + break; + } + case SE_FcDamageAmtCrit: { + if(bottype == BotfocusFcDamageAmtCrit) + value = focus_spell.base[i]; + break; + } + case SE_FcHealAmtIncoming: + if(bottype == BotfocusFcHealAmtIncoming) + value = focus_spell.base[i]; + break; + case SE_FcHealPctCritIncoming: + if (bottype == BotfocusFcHealPctCritIncoming) + value = focus_spell.base[i]; + break; + case SE_FcHealAmtCrit: + if(bottype == BotfocusFcHealAmtCrit) + value = focus_spell.base[i]; + break; + case SE_FcHealAmt: + if(bottype == BotfocusFcHealAmt) + value = focus_spell.base[i]; + break; + case SE_FcHealPctIncoming: + if(bottype == BotfocusFcHealPctIncoming) + value = focus_spell.base[i]; + break; + case SE_FcBaseEffects: { + if (bottype == BotfocusFcBaseEffects) + value = focus_spell.base[i]; + + break; + } + case SE_FcDamagePctCrit: { + if(bottype == BotfocusFcDamagePctCrit) + value = focus_spell.base[i]; + + break; + } + case SE_FcIncreaseNumHits: { + if(bottype == BotfocusIncreaseNumHits) + value = focus_spell.base[i]; + + break; + } + default: + Log.Out(Logs::General, Logs::Spells, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]); + break; } } //Check for spell skill limits. if ((LimitSpellSkill) && (!SpellSkill_Found)) return 0; - return(value*lvlModifier/100); + return(value * lvlModifier / 100); } //proc chance includes proc bonus @@ -7382,38 +6280,23 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) { 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 + ProcChance = (static_cast(weapon_speed) * RuleR(Combat, AvgProcsPerMinute) / 60000.0f); ProcBonus += static_cast(mydex) * RuleR(Combat, ProcPerMinDexContrib); - ProcChance += ProcChance * ProcBonus / 100.0f; + ProcChance += (ProcChance * ProcBonus / 100.0f); } else { - ProcChance = RuleR(Combat, BaseProcChance) + - static_cast(mydex) / RuleR(Combat, ProcDexDivideBy); - ProcChance += ProcChance*ProcBonus / 100.0f; + ProcChance = (RuleR(Combat, BaseProcChance) + static_cast(mydex) / RuleR(Combat, ProcDexDivideBy)); + ProcChance += (ProcChance * ProcBonus / 100.0f); } Log.Out(Logs::Detail, Logs::Combat, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus); return ProcChance; } -bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) -{ - /* 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 - * - */ +bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) { if(GetAppearance() == eaDead) return false; @@ -7421,76 +6304,52 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) float bonus = 0; float RollTable[4] = {0,0,0,0}; float roll = 0; - Mob *attacker=other; - Mob *defender=this; + Mob *attacker = other; + Mob *defender = this; - //garunteed hit bool ghit = false; if((attacker->GetSpellBonuses().MeleeSkillCheck + attacker->GetItemBonuses().MeleeSkillCheck) > 500) ghit = true; - ////////////////////////////////////////////////////////// - // make enrage same as riposte - ///////////////////////////////////////////////////////// if (IsEnraged() && !other->BehindMob(this, other->GetX(), other->GetY())) { damage = -3; Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); } - - ///////////////////////////////////////////////////////// - // riposte - ///////////////////////////////////////////////////////// + float riposte_chance = 0.0f; - if (CanRiposte && damage > 0 && CanThisClassRiposte() && !other->BehindMob(this, other->GetX(), other->GetY())) - { - riposte_chance = (100.0f + (float)defender->GetAABonuses().RiposteChance + (float)defender->GetSpellBonuses().RiposteChance + (float)defender->GetItemBonuses().RiposteChance) / 100.0f; + if (CanRiposte && damage > 0 && CanThisClassRiposte() && !other->BehindMob(this, other->GetX(), other->GetY())) { + riposte_chance = ((100.0f + (float)defender->GetAABonuses().RiposteChance + (float)defender->GetSpellBonuses().RiposteChance + (float)defender->GetItemBonuses().RiposteChance) / 100.0f); skill = GetSkill(SkillRiposte); - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetDEX()/200); + if (!ghit) { + bonus = (2.0 + skill / 60.0 + (GetDEX() / 200)); bonus *= riposte_chance; - RollTable[0] = bonus + (itembonuses.HeroicDEX / 25); // 25 heroic = 1%, applies to ripo, parry, block + RollTable[0] = (bonus + (itembonuses.HeroicDEX / 25)); } } - - /////////////////////////////////////////////////////// - // block - /////////////////////////////////////////////////////// - + bool bBlockFromRear = false; bool bShieldBlockFromRear = false; - if (this->IsBot()) { 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; - + int BlockBehindChance = (aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind); if (BlockBehindChance && (BlockBehindChance > zone->random.Int(1, 100))){ bBlockFromRear = true; - if (spellbonuses.BlockBehind || itembonuses.BlockBehind) - bShieldBlockFromRear = true; //This bonus should allow a chance to Shield Block from behind. + bShieldBlockFromRear = true; } } float block_chance = 0.0f; if (damage > 0 && CanThisClassBlock() && (!other->BehindMob(this, other->GetX(), other->GetY()) || bBlockFromRear)) { - block_chance = (100.0f + (float)spellbonuses.IncreaseBlockChance + (float)itembonuses.IncreaseBlockChance) / 100.0f; + block_chance = ((100.0f + (float)spellbonuses.IncreaseBlockChance + (float)itembonuses.IncreaseBlockChance) / 100.0f); skill = GetSkill(SkillBlock); - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/35.0 + (GetDEX()/200); - RollTable[1] = RollTable[0] + (bonus * block_chance) - riposte_chance; - block_chance *= bonus; // set this so we can remove it from the parry calcs + if (!ghit) { + bonus = (2.0 + skill / 35.0 + (GetDEX() / 200)); + RollTable[1] = (RollTable[0] + (bonus * block_chance) - riposte_chance); + block_chance *= bonus; } - } - else{ + } else RollTable[1] = RollTable[0]; - } if(damage > 0 && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (!other->BehindMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { @@ -7499,10 +6358,8 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) uint8 shield = GetBotItem(MainSecondary)->GetItem()->ItemType; float bonusShieldBlock = 0.0f; if(shield == ItemTypeShield) { - - //Live AA - Shield Block - bonusShieldBlock = aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock; - RollTable[1] = RollTable[0] + bonusShieldBlock; + bonusShieldBlock = (aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock); + RollTable[1] = (RollTable[0] + bonusShieldBlock); } } } @@ -7514,79 +6371,58 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) uint8 TwoHandBlunt = GetBotItem(MainPrimary)->GetItem()->ItemType; float bonusStaffBlock = 0.0f; if(TwoHandBlunt == ItemType2HBlunt) { - - bonusStaffBlock = aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock; - RollTable[1] = RollTable[0] + bonusStaffBlock; + bonusStaffBlock = (aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock); + RollTable[1] = (RollTable[0] + bonusStaffBlock); } } } - ////////////////////////////////////////////////////// - // parry - ////////////////////////////////////////////////////// float parry_chance = 0.0f; - if (damage > 0 && CanThisClassParry() && !other->BehindMob(this, other->GetX(), other->GetY())) - { - parry_chance = (100.0f + (float)defender->GetSpellBonuses().ParryChance + (float)defender->GetItemBonuses().ParryChance) / 100.0f; + if (damage > 0 && CanThisClassParry() && !other->BehindMob(this, other->GetX(), other->GetY())) { + parry_chance = ((100.0f + (float)defender->GetSpellBonuses().ParryChance + (float)defender->GetItemBonuses().ParryChance) / 100.0f); skill = GetSkill(SkillParry); - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetDEX()/200); + if (!ghit) { + bonus = (2.0 + skill / 60.0 + (GetDEX() / 200)); bonus *= parry_chance; - RollTable[2] = RollTable[1] + bonus - block_chance; + RollTable[2] = (RollTable[1] + bonus - block_chance); } - } - else{ - RollTable[2] = RollTable[1] - block_chance; - } + } else + RollTable[2] = (RollTable[1] - block_chance); - //////////////////////////////////////////////////////// - // dodge - //////////////////////////////////////////////////////// float dodge_chance = 0.0f; - if (damage > 0 && CanThisClassDodge() && !other->BehindMob(this, other->GetX(), other->GetY())) - { - dodge_chance = (100.0f + (float)defender->GetSpellBonuses().DodgeChance + (float)defender->GetItemBonuses().DodgeChance) / 100.0f; + if (damage > 0 && CanThisClassDodge() && !other->BehindMob(this, other->GetX(), other->GetY())) { + dodge_chance = ((100.0f + (float)defender->GetSpellBonuses().DodgeChance + (float)defender->GetItemBonuses().DodgeChance) / 100.0f); skill = GetSkill(SkillDodge); - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetAGI()/200); + if (!ghit) { + bonus = (2.0 + skill / 60.0 + (GetAGI() / 200)); bonus *= dodge_chance; - RollTable[3] = RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance; // Remove the dex as it doesnt count for dodge + RollTable[3] = (RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance); } - } - else{ - RollTable[3] = RollTable[2] - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance; + } else { + RollTable[3] = (RollTable[2] - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance); } - if(damage > 0) - { + if(damage > 0) { roll = zone->random.Real(0,100); - if(roll <= RollTable[0]){ + if(roll <= RollTable[0]) damage = -3; - } - else if(roll <= RollTable[1]){ + else if(roll <= RollTable[1]) damage = -1; - } - else if(roll <= RollTable[2]){ + else if(roll <= RollTable[2]) damage = -2; - } - else if(roll <= RollTable[3]){ + else if(roll <= RollTable[3]) damage = -4; - } } Log.Out(Logs::Detail, Logs::Combat, "Final damage after all avoidances: %d", damage); if (damage < 0) return true; + return false; } -int Bot::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 +int Bot::GetMonkHandToHandDamage(void) { 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, @@ -7594,15 +6430,11 @@ int Bot::GetMonkHandToHandDamage(void) 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 - uint32 botWeaponId = INVALID_ID; botWeaponId = CastToNPC()->GetEquipment(MaterialHands); - if(botWeaponId == 10652) { //Monk Epic ID + if(botWeaponId == 10652) return 9; - } - else - { + else { int Level = GetLevel(); if(Level > 65) return 19; @@ -7612,30 +6444,25 @@ int Bot::GetMonkHandToHandDamage(void) int Level = GetLevel(); if (Level > 65) - return(19); + return 19; else return damage[Level]; } -bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) -{ +bool Bot::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. + 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()); entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse); return true; - } - else - { + } else { Log.Out(Logs::Detail, Logs::Combat, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); return false; } @@ -7645,27 +6472,17 @@ bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) void Bot::DoRiposte(Mob* defender) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a riposte"); - if (!defender) return; defender->Attack(this, MainPrimary, true); - - //double riposte - int32 DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[0] + - defender->GetSpellBonuses().GiveDoubleRiposte[0] + - defender->GetItemBonuses().GiveDoubleRiposte[0]; - + 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); } - //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->GetAABonuses().GiveDoubleRiposte[1]; - if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { if (defender->GetClass() == MONK) defender->MonkSpecialAttack(this, defender->GetAABonuses().GiveDoubleRiposte[2]); @@ -7675,9 +6492,6 @@ 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) { - //this really should go through the same code as normal melee damage to - //pick up all the special behavior there - int32 hate = max_damage; if(hate_override > -1) hate = hate_override; @@ -7687,22 +6501,21 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); + if(botweapon) { - if(botweapon->ItemType == ItemTypeShield) { + if(botweapon->ItemType == ItemTypeShield) hate += botweapon->AC; - } - hate = hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100; + + hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); } } - min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100; - + min_damage += (min_damage * GetMeleeMinDamageMod_SE(skill) / 100); if(HitChance && !who->CheckHitChance(this, skill, MainPrimary)) max_damage = 0; - - else{ + else { bool CanRiposte = true; - if(skill == SkillThrowing || skill == SkillArchery) // changed from '&&' + if(skill == SkillThrowing || skill == SkillArchery) CanRiposte = false; who->AvoidDamage(this, max_damage, CanRiposte); @@ -7711,37 +6524,35 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(max_damage > 0) { 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); + max_damage += ((itembonuses.HeroicSTR / 10) + (max_damage * who->GetSkillDmgTaken(skill) / 100) + GetSkillDmgAmt(skill)); TryCriticalHit(who, skill, max_damage); } } - if(max_damage >= 0) //You should probably get aggro no matter what, but unclear why it was set like this. + if(max_damage >= 0) who->AddToHateList(this, hate); who->Damage(this, max_damage, SPELL_UNKNOWN, skill, false); - if(!GetTarget())return; - if (HasDied()) return; + if(!GetTarget() || HasDied()) + return; if (max_damage > 0) 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; + 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 (HasSkillProcs()) - TrySkillProc(who, skill, ReuseTime*1000); + TrySkillProc(who, skill, (ReuseTime * 1000)); if (max_damage > 0 && HasSkillProcSuccess()) - TrySkillProc(who, skill, ReuseTime*1000, true); + TrySkillProc(who, skill, (ReuseTime * 1000), true); if(max_damage == -3 && !(who->GetHP() <= 0)) DoRiposte(who); @@ -7753,53 +6564,35 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; - const ItemInst* inst = GetBotItem(MainPrimary); const Item_Struct* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); + if(!botpiercer || (botpiercer->ItemType != ItemType1HPiercing)) { BotGroupSay(this, "I can't backstab with this weapon!"); return; } - //Live AA - Triple Backstab - int tripleChance = itembonuses.TripleBackstab + spellbonuses.TripleBackstab + aabonuses.TripleBackstab; - - if (BehindMob(other, GetX(), GetY())) { + int tripleChance = (itembonuses.TripleBackstab + spellbonuses.TripleBackstab + aabonuses.TripleBackstab); + if (BehindMob(other, GetX(), GetY())) bIsBehind = true; - } else { - //Live AA - Seized Opportunity - int FrontalBSChance = itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance; - + int FrontalBSChance = (itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance); if (FrontalBSChance && (FrontalBSChance > zone->random.Int(0, 100))) bCanFrontalBS = true; } - if (bIsBehind || bCanFrontalBS){ // Bot is behind other OR can do Frontal Backstab - - // chance to assassinate - int chance = 10 + (GetDEX()/10) + (itembonuses.HeroicDEX/10); //18.5% chance at 85 dex 40% chance at 300 dex - if( - level >= 60 && // bot is 60 or higher - other->GetLevel() <= 45 && // mob 45 or under - !other->CastToNPC()->IsEngaged() && // not aggro - other->GetHP()<=32000 - && other->IsNPC() - && zone->random.Real(0, 99) < chance // chance - ) { + if (bIsBehind || bCanFrontalBS) { + int chance = (10 + (GetDEX() / 10) + (itembonuses.HeroicDEX / 10)); + if(level >= 60 && other->GetLevel() <= 45 && !other->CastToNPC()->IsEngaged() && other->GetHP()<= 32000 && other->IsNPC() && zone->random.Real(0, 99) < chance) { entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); RogueAssassinate(other); - } - else { + } else { RogueBackstab(other); if (level > 54) { - float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max - // Check for double attack with main hand assuming maxed DA Skill (MS) - - if(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA - { + float DoubleAttackProbability = ((GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f); + if(zone->random.Real(0, 1) < DoubleAttackProbability) { if(other->GetHP() > 0) RogueBackstab(other,false,ReuseTime); @@ -7808,167 +6601,123 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } } } - } - //Live AA - Chaotic Backstab - else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { - - //we can stab from any angle, we do min damage though. + } else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { RogueBackstab(other, true); if (level > 54) { - float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max - // Check for double attack with main hand assuming maxed DA Skill (MS) - if(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA + float DoubleAttackProbability = ((GetSkill(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); + RogueBackstab(other,false,ReuseTime); } } - else { //We do a single regular attack if we attack from the front without chaotic stab + else Attack(other, MainPrimary); - } } -//heko: backstab -void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) -{ +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; - ItemInst* botweaponInst = GetBotItem(MainPrimary); 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 < EmuConstants::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = botweaponInst->GetAugment(i); if(aug) - { backstab_dmg += aug->GetItem()->BackstabDmg; - } } - } - 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); backstab_dmg = primaryweapondamage; } - if(primaryweapondamage > 0){ - if(level > 25){ - max_hit = (((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + ((level-25)/3) + 1; - hate = 20 * backstab_dmg * GetSkill(SkillBackstab) / 355; - } - else{ - max_hit = (((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1; - hate = 20 * backstab_dmg * GetSkill(SkillBackstab) / 355; + if(primaryweapondamage > 0) { + if(level > 25) { + max_hit = ((((2 * backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + ((level - 25) / 3) + 1); + hate = (20 * backstab_dmg * GetSkill(SkillBackstab) / 355); + } else { + max_hit = ((((2 * backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1); + hate = (20 * backstab_dmg * GetSkill(SkillBackstab) / 355); } - // determine minimum hits if (level < 51) - { - min_hit = (level*15/10); - } + 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; - } + min_hit = ((level * ( level * 5 - 105)) / 100); - if(!other->CheckHitChance(this, SkillBackstab, 0)) { + if(!other->CheckHitChance(this, 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)) - ndamage = max_hit; - else - ndamage = zone->random.Int(min_hit, max_hit); - + ndamage = (RuleB(Combat, UseIntervalAC) ? max_hit : zone->random.Int(min_hit, max_hit)); } } - } - else{ + } else ndamage = -5; - } DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime); DoAnim(animPiercing); } -void Bot::RogueAssassinate(Mob* other) -{ +void Bot::RogueAssassinate(Mob* other) { ItemInst* botweaponInst = GetBotItem(MainPrimary); if(botweaponInst) { - if(GetWeaponDamage(other, botweaponInst)) { + if(GetWeaponDamage(other, botweaponInst)) other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab); - } - else { + else other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); - } } - DoAnim(animPiercing); //piercing animation + DoAnim(animPiercing); } void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { - if(!target) - return; - - if(spellend_timer.Enabled() || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0) - return; - - if(!IsAttackAllowed(target)) + if(!target || spellend_timer.Enabled() || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0 || !IsAttackAllowed(target)) return; bool taunt_time = taunt_timer.Check(); bool ca_time = classattack_timer.Check(false); bool ka_time = knightattack_timer.Check(false); - - //only check attack allowed if we are going to do something if((taunt_time || ca_time || ka_time) && !IsAttackAllowed(target)) return; if(ka_time){ - int knightreuse = 1000; //lets give it a small cooldown actually. + int knightreuse = 1000; switch(GetClass()){ - case SHADOWKNIGHT: case SHADOWKNIGHTGM:{ + case SHADOWKNIGHT: + case SHADOWKNIGHTGM: { CastSpell(SPELL_NPC_HARM_TOUCH, target->GetID()); - knightreuse = HarmTouchReuseTime * 1000; + knightreuse = (HarmTouchReuseTime * 1000); break; } - case PALADIN: case PALADINGM:{ + case PALADIN: + case PALADINGM: { if(GetHPRatio() < 20) { CastSpell(SPELL_LAY_ON_HANDS, GetID()); - knightreuse = LayOnHandsReuseTime * 1000; - } else { - knightreuse = 2000; //Check again in two seconds. + knightreuse = (LayOnHandsReuseTime * 1000); } + else + knightreuse = 2000; + break; } } knightattack_timer.Start(knightreuse); } - //general stuff, for all classes.... - //only gets used when their primary ability get used too - - //franck-add: EQoffline. Warrior bots must taunt the target. - if(taunting && target && target->IsNPC() && taunt_time ) { - //Only taunt if we are not top on target's hate list - //This ensures we have taunt available to regain aggro if needed + if(taunting && target && target->IsNPC() && taunt_time) { if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { BotGroupSay(this, "Taunting %s", target->GetCleanName()); Taunt(target->CastToNPC(), false); @@ -7979,287 +6728,193 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(!ca_time) return; - float HasteModifier = GetHaste() * 0.01f; + float HasteModifier = (GetHaste() * 0.01f); int32 dmg = 0; - uint16 skill_to_use = -1; - int level = GetLevel(); - int reuse = TauntReuseTime * 1000; //make this very long since if they dont use it once, they prolly never will + int reuse = (TauntReuseTime * 1000); bool did_attack = false; - - switch(GetClass()) - { - case WARRIOR: - if(level >= RuleI(Combat, NPCBashKickLevel)){ - bool canBash = false; - if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) // Racial Slam - || (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) //Using Shield - || (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)) { //Using 2 hand weapon, but has AA 2 Hand Bash - canBash = true; + switch(GetClass()) { + 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)) + canBash = true; + + if(!canBash || zone->random.Int(0, 100) > 25) + skill_to_use = SkillKick; + else + skill_to_use = SkillBash; } - - if(!canBash || 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. - skill_to_use = SkillKick; - } - else { - skill_to_use = SkillBash; - } - } - case RANGER: - case BEASTLORD: - skill_to_use = SkillKick; - break; - case BERSERKER: - skill_to_use = SkillFrenzy; - break; - case CLERIC: - case SHADOWKNIGHT: - case PALADIN: - if(level >= RuleI(Combat, NPCBashKickLevel)){ - if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) // Racial Slam - || (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) //Using Shield - || (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)) { //Using 2 hand weapon, but has AA 2 Hand Bash - skill_to_use = SkillBash; - } - } - break; - case MONK: - if(GetLevel() >= 30) - { - skill_to_use = SkillFlyingKick; - } - else if(GetLevel() >= 25) - { - skill_to_use = SkillDragonPunch; - } - else if(GetLevel() >= 20) - { - skill_to_use = SkillEagleStrike; - } - else if(GetLevel() >= 10) - { - skill_to_use = SkillTigerClaw; - } - else if(GetLevel() >= 5) - { - skill_to_use = SkillRoundKick; - } - else - { + case RANGER: + case BEASTLORD: skill_to_use = SkillKick; - } - break; - case ROGUE: - skill_to_use = SkillBackstab; - break; + break; + case BERSERKER: + skill_to_use = SkillFrenzy; + break; + case CLERIC: + 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)) + skill_to_use = SkillBash; + } + break; + case MONK: + if(GetLevel() >= 30) + skill_to_use = SkillFlyingKick; + else if(GetLevel() >= 25) + skill_to_use = SkillDragonPunch; + else if(GetLevel() >= 20) + skill_to_use = SkillEagleStrike; + else if(GetLevel() >= 10) + skill_to_use = SkillTigerClaw; + else if(GetLevel() >= 5) + skill_to_use = SkillRoundKick; + else + skill_to_use = SkillKick; + break; + case ROGUE: + skill_to_use = SkillBackstab; + break; } if(skill_to_use == -1) return; - - if(skill_to_use == SkillBash) - { - if (target!=this) - { + 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(MainSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(MainShoulders)) <= 0) dmg = -5; - } - else{ - if(!target->CheckHitChance(this, SkillBash, 0)) { + else { + if(!target->CheckHitChance(this, SkillBash, 0)) dmg = 0; - } - else{ + else { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else dmg = zone->random.Int(1, GetBashDamage()); - } } - - reuse = BashReuseTime * 1000; - //reuse = (reuse*HasteModifier)/100; - - DoSpecialAttackDamage(target, SkillBash, dmg, 1,-1,reuse); - + reuse = (BashReuseTime * 1000); + DoSpecialAttackDamage(target, SkillBash, dmg, 1, -1,reuse); did_attack = true; - - if(reuse > 0 && !IsRiposte) - { - //p_timers.Start(pTimerCombatAbility, reuse); - } } } - if(skill_to_use == SkillFrenzy) - { + if(skill_to_use == SkillFrenzy) { int AtkRounds = 3; int skillmod = 0; - if(MaxSkill(SkillFrenzy) > 0) - skillmod = 100*GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy); + skillmod = (100 * GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy)); - int32 max_dmg = (26 + ((((GetLevel()-6) * 2)*skillmod)/100)) * ((100+RuleI(Combat, FrenzyBonus))/100); + int32 max_dmg = (26 + ((((GetLevel() - 6) * 2) * skillmod) / 100)) * ((100 + RuleI(Combat, FrenzyBonus)) / 100); int32 min_dmg = 0; DoAnim(anim2HSlashing); if (GetLevel() < 51) min_dmg = 1; else - min_dmg = GetLevel()*8/10; + min_dmg = (GetLevel() * 8 / 10); if (min_dmg > max_dmg) max_dmg = min_dmg; - reuse = FrenzyReuseTime * 1000; - //reuse = (reuse * HasteModifier)/100; - + reuse = (FrenzyReuseTime * 1000); did_attack = true; - - //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.Int(0,100) < 75)){ - DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , reuse, true); + if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0, 100) < 75)) { + DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg, reuse, true); } - AtkRounds--; - } - if(reuse > 0 && !IsRiposte) { - //p_timers.Start(pTimerCombatAbility, reuse); + AtkRounds--; } } - if(skill_to_use == SkillKick) - { - if(target!=this) - { + if(skill_to_use == SkillKick) { + if(target != this) { DoAnim(animKick); - - if(GetWeaponDamage(target, GetBotItem(MainFeet)) <= 0){ + if(GetWeaponDamage(target, GetBotItem(MainFeet)) <= 0) dmg = -5; - } - else{ - if(!target->CheckHitChance(this, SkillKick, 0)) { + else { + if(!target->CheckHitChance(this, SkillKick, 0)) dmg = 0; - } - else{ + else { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else dmg = zone->random.Int(1, GetKickDamage()); } } - - reuse = KickReuseTime * 1000; - - DoSpecialAttackDamage(target, SkillKick, dmg, 1,-1, reuse); - + reuse = (KickReuseTime * 1000); + DoSpecialAttackDamage(target, 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) - { - reuse = MonkSpecialAttack(target, skill_to_use) - 1; + if(skill_to_use == SkillFlyingKick || skill_to_use == SkillDragonPunch || skill_to_use == SkillEagleStrike || skill_to_use == SkillTigerClaw || skill_to_use == SkillRoundKick) { + reuse = (MonkSpecialAttack(target, skill_to_use) - 1); MonkSpecialAttack(target, skill_to_use); - - //Live AA - Technique of Master Wu - uint32 bDoubleSpecialAttack = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; - if( bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0,100))) { - + 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 }; - MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]); - + MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]); int TripleChance = 25; - if (bDoubleSpecialAttack > 100) - TripleChance += TripleChance*(100-bDoubleSpecialAttack)/100; + TripleChance += (TripleChance * (100 - bDoubleSpecialAttack) / 100); - if(TripleChance > zone->random.Int(0,100)) { - MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]); - } + if(TripleChance > zone->random.Int(0,100)) + MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]); } reuse *= 1000; did_attack = true; } - if(skill_to_use == SkillBackstab) - { - reuse = BackstabReuseTime * 1000; + if(skill_to_use == SkillBackstab) { + reuse = (BackstabReuseTime * 1000); did_attack = true; - if (IsRiposte) - reuse=0; + reuse = 0; TryBackstab(target,reuse); } - classattack_timer.Start(reuse / HasteModifier); } bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { bool Result = false; - if(defender && (defender->GetBodyType() == BT_Humanoid) && (skillInUse == SkillArchery) && (GetClass() == RANGER) && (GetLevel() >= 62)) { int defenderLevel = defender->GetLevel(); int rangerLevel = GetLevel(); - // Bot Ranger Headshot AA through level 85(Underfoot) - if( GetAA(aaHeadshot) && ((defenderLevel - 46) <= GetAA(aaHeadshot) * 2) ) { - // WildcardX: These chance formula's below are arbitrary. If someone has a better formula that is more - // consistent with live, feel free to update these. + 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); - // WildcardX: At the time I wrote this, there wasnt a string id for something like HEADSHOT_BLOW - //entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); 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 { + } else Log.Out(Logs::Detail, Logs::Combat, "FAILED a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance); - } } } - return Result; } -//offensive spell aggro int32 Bot::CheckAggroAmount(uint16 spellid) { int32 AggroAmount = Mob::CheckAggroAmount(spellid); - int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid); - AggroAmount = (AggroAmount * (100+focusAggro) / 100); - + AggroAmount = (AggroAmount * (100 + focusAggro) / 100); return AggroAmount; } int32 Bot::CheckHealAggroAmount(uint16 spellid, uint32 heal_possible) { int32 AggroAmount = Mob::CheckHealAggroAmount(spellid, heal_possible); - int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid); - AggroAmount = (AggroAmount * (100 + focusAggro) / 100); - return AggroAmount; } @@ -8272,20 +6927,15 @@ void Bot::AI_Stop() { Mob::AI_Stop(); } -//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 Bot::GetReverseFactionCon(Mob* iOther) { - if(iOther->IsBot()) { + if(iOther->IsBot()) return FACTION_ALLY; - } return NPC::GetReverseFactionCon(iOther); } Mob* Bot::GetOwnerOrSelf() { Mob* Result = 0; - if(this->GetBotOwner()) Result = GetBotOwner(); else @@ -8296,103 +6946,61 @@ Mob* Bot::GetOwnerOrSelf() { Mob* Bot::GetOwner() { Mob* Result = 0; - Result = GetBotOwner(); - - if(!Result) { + if(!Result) this->SetBotOwner(0); - } return Result; } -bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) -{ +bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { bool Result = false; - - if(attacker && target) - { - if(attacker == target) - { + if(attacker && target) { + if(attacker == target) { hasRuleDefined = true; Result = false; - } - else if(attacker->IsClient() && target->IsBot() && attacker->CastToClient()->GetPVP() && target->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) - { + } else if(attacker->IsClient() && target->IsBot() && attacker->CastToClient()->GetPVP() && target->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) { hasRuleDefined = true; Result = true; - } - else if(attacker->IsClient() && target->IsBot()) - { + } else if(attacker->IsClient() && target->IsBot()) { hasRuleDefined = true; Result = false; - } - else if(attacker->IsBot() && target->IsNPC()) - { + } else if(attacker->IsBot() && target->IsNPC()) { hasRuleDefined = true; Result = true; - } - else if(attacker->IsBot() && !target->IsNPC()) - { + } else if(attacker->IsBot() && !target->IsNPC()) { hasRuleDefined = true; Result = false; - } - else if(attacker->IsPet() && attacker->IsFamiliar()) - { + } else if(attacker->IsPet() && attacker->IsFamiliar()) { hasRuleDefined = true; Result = false; - } - else if(attacker->IsBot() && attacker->CastToBot()->GetBotOwner() && attacker->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) - { - if(target->IsBot() && target->GetOwner() && target->GetOwner()->CastToClient()->GetPVP()) - { - // my target is a bot and it's owner is pvp + } else if(attacker->IsBot() && attacker->CastToBot()->GetBotOwner() && attacker->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) { + if(target->IsBot() && target->GetOwner() && target->GetOwner()->CastToClient()->GetPVP()) { hasRuleDefined = true; - if(target->GetOwner() == attacker->GetOwner()) - { - // no attacking if my target's owner is my owner Result = false; - } else - { Result = true; - } - } - else if(target->IsClient() && target->CastToClient()->GetPVP()) - { - // my target is a player and it's pvp + } else if(target->IsClient() && target->CastToClient()->GetPVP()) { hasRuleDefined = true; - if(target == attacker->GetOwner()) - { - // my target cannot be my owner Result = false; - } else - { Result = true; - } - } - else if(target->IsNPC()) - { + } else if(target->IsNPC()) { hasRuleDefined = true; Result = true; - } - else if(!target->IsNPC()) - { + } else if(!target->IsNPC()) { hasRuleDefined = true; Result = false; } } } - return Result; } void Bot::EquipBot(std::string* errorMessage) { GetBotItems(errorMessage, m_inv); - const ItemInst* inst = 0; const Item_Struct* item = 0; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { @@ -8404,33 +7012,14 @@ void Bot::EquipBot(std::string* errorMessage) { return; } } - UpdateEquipmentLight(); } -//// This method is meant to be called by zone or client methods to clean up objects when a client camps, goes LD, zones out or something like that. -//void Bot::DestroyBotRaidObjects(Client* client) { -// if(client) { -// if(client->GetBotRaidID() > 0) { -// BotRaids* br = entity_list.GetBotRaidByMob(client); -// if(br) { -// br->RemoveRaidBots(); -// br = nullptr; -// } -// } -// -// //BotOrderCampAll(client); -// } -//} - -// Orders all the bots owned by the specified client bot owner to camp out of the game void Bot::BotOrderCampAll(Client* c) { if(c) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { + for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) (*botListItr)->Camp(); - } } } @@ -8438,11 +7027,9 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) { if(botOwner) { if(botOwner->IsClient()) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(botOwner->CastToClient()->CharacterID()); - if(!BotList.empty()) { for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot) { tempBot->SetTarget(0); tempBot->SetBotOwner(0); @@ -8455,20 +7042,12 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) { void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) { if(guildOfficer && botToGuild) { - // Bots can be only guild member rank if(!botToGuild->IsInAGuild()) { - //they are not in this or any other guild, this is an invite if (!guild_mgr.CheckPermission(guildOfficer->GuildID(), guildOfficer->GuildRank(), GUILD_INVITE)) { guildOfficer->Message(13, "You dont have permission to invite."); return; } - - // Log.Out(Logs::Detail, Logs::Guilds, "Inviting %s (%d) into guild %s (%d)", botToGuild->GetName(), botToGuild->GetBotID(), guild_mgr.GetGuildName(client->GuildID()), client->GuildID()); - SetBotGuildMembership(botToGuild->GetBotID(), guildOfficer->GuildID(), GUILD_MEMBER); - - //Log.LogDebugType(Logs::Detail, Logs::Guilds, "Sending char refresh for BOT %s from guild %d to world", botToGuild->GetName(), guildOfficer->GuildID(); - ServerPacket* pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct)); ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer; s->guild_id = guildOfficer->GuildID(); @@ -8476,9 +7055,7 @@ void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) { s->char_id = botToGuild->GetBotID(); worldserver.SendPacket(pack); safe_delete(pack); - } else { - //they are in some other guild guildOfficer->Message(13, "Player is in a guild."); return; } @@ -8487,18 +7064,14 @@ void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) { bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) { bool Result = false; - if(guildOfficer && !botName.empty()) { Bot* botToUnGuild = entity_list.GetBotByBotName(botName); if(botToUnGuild) { SetBotGuildMembership(botToUnGuild->GetBotID(), 0, 0); Result = true; - } - else { + } else { uint32 botId = GetBotIDByBotName(botName); - if(botId > 0) { - // Bot is camped or in another zone SetBotGuildMembership(botId, 0, 0); Result = true; } @@ -8514,7 +7087,6 @@ bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) { safe_delete(outapp); } } - return Result; } @@ -8523,27 +7095,20 @@ void Bot::SetBotGuildMembership(uint32 botId, uint32 guildid, uint8 rank) { return; if(guildid > 0) { - std::string query = StringFormat("REPLACE INTO botguildmembers " - "SET char_id = %u, guild_id = %u, rank = %u;", - botId, guildid, rank); + std::string query = StringFormat("REPLACE INTO botguildmembers SET char_id = %u, guild_id = %u, rank = %u", botId, guildid, rank); auto results = database.QueryDatabase(query); return; } - std::string query = StringFormat("DELETE FROM botguildmembers WHERE char_id = %u;", botId); + std::string query = StringFormat("DELETE FROM botguildmembers WHERE char_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 vwGuildMembers AS gm JOIN guilds AS g " - "ON gm.guild_id = g.id " - "WHERE gm.char_id = %u AND gm.mobtype = 'B';", - GetBotID()); + std::string query = StringFormat("SELECT gm.guild_id, gm.rank, g.name FROM vwGuildMembers AS gm JOIN guilds AS g ON gm.guild_id = g.id WHERE gm.char_id = %u AND gm.mobtype = 'B'", GetBotID()); auto results = database.QueryDatabase(query); if(!results.Success() || results.RowCount() == 0) return; @@ -8555,56 +7120,44 @@ void Bot::LoadGuildMembership(uint32* guildId, uint8* guildRank, std::string* gu } int32 Bot::CalcMaxMana() { - switch(GetCasterClass()) - { + switch(GetCasterClass()) { case 'I': - case 'W': - { + case 'W': { max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement()); break; } - case 'N': - { + case 'N': { max_mana = 0; break; } - default: - { + default: { Log.Out(Logs::General, Logs::None, "Invalid Class '%c' in CalcMaxMana", GetCasterClass()); max_mana = 0; break; } } - if(cur_mana > max_mana) { + if(cur_mana > max_mana) cur_mana = max_mana; - } - else if(max_mana < 0) { + else if(max_mana < 0) max_mana = 0; - } return max_mana; } void Bot::SetAttackTimer() { - float haste_mod = GetHaste() * 0.01f; - - //default value for attack timer in case they have - //an invalid weapon equipped: + float haste_mod = (GetHaste() * 0.01f); attack_timer.SetAtTrigger(4000, true); - Timer* TimerToUse = nullptr; const Item_Struct* PrimaryWeapon = nullptr; - for (int i = MainRange; i <= MainSecondary; i++) { - //pick a timer if (i == MainPrimary) TimerToUse = &attack_timer; else if (i == MainRange) TimerToUse = &ranged_timer; else if (i == MainSecondary) TimerToUse = &attack_dw_timer; - else //invalid slot (hands will always hit this) + else continue; const Item_Struct* ItemToUse = nullptr; @@ -8612,60 +7165,36 @@ void Bot::SetAttackTimer() { if (ci) ItemToUse = ci->GetItem(); - //special offhand stuff if (i == MainSecondary) { - //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)) { + 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 (!GetSkill(SkillDualWield)) { 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 + if (ItemToUse->ItemClass != ItemClassCommon || ItemToUse->Damage == 0 || ItemToUse->Delay == 0 || ((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing))) ItemToUse = nullptr; - } - // Check to see if skill is valid - else if ((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing)) { - //no weapon - ItemToUse = nullptr; - } } - int hhe = itembonuses.HundredHands + spellbonuses.HundredHands; + int hhe = (itembonuses.HundredHands + spellbonuses.HundredHands); int speed = 0; int delay = 36; - - //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)) delay = GetMonkHandToHandDelay(); } else { - //we have a weapon, use its delay delay = ItemToUse->Delay; } - if (RuleB(Spells, Jun182014HundredHandsRevamp)) - speed = static_cast(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100); - else - speed = static_cast(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100); + + 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) @@ -8674,66 +7203,52 @@ void Bot::SetAttackTimer() { } int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { - if (spells[spell_id].targettype == ST_Self) return value; bool Critical = false; int32 value_BaseEffect = 0; - - value_BaseEffect = value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id)/100); - + value_BaseEffect = (value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id) / 100)); // Need to scale HT damage differently after level 40! It no longer scales by the constant value in the spell file. It scales differently, instead of 10 more damage per level, it does 30 more damage per level. So we multiply the level minus 40 times 20 if they are over level 40. if ( (spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) && GetLevel() > 40) - value -= (GetLevel() - 40) * 20; + value -= ((GetLevel() - 40) * 20); //This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch. if (spell_id == SPELL_IMP_HARM_TOUCH) //Improved Harm Touch - value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch + value -= (GetAA(aaUnholyTouch) * 450); //Unholy Touch int chance = RuleI(Spells, BaseCritChance); - chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance; + chance += (itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance); - if (chance > 0){ + if (chance > 0) { + int32 ratio = RuleI(Spells, BaseCritRatio); + if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) + chance = 100; - int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals. - - //Improved Harm Touch is a guaranteed crit if you have at least one level of SCF. - if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) - chance = 100; - - if (zone->random.Int(1,100) <= chance){ + if (zone->random.Int(1, 100) <= chance){ Critical = true; - ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease; - ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack; - } - - else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Int(1,100) <= RuleI(Spells, WizCritChance))) { - ratio = zone->random.Int(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. + ratio += (itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease); + ratio += (itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack); + } else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Int(1, 100) <= RuleI(Spells, WizCritChance))) { + ratio = zone->random.Int(1, 100); Critical = true; } - - ratio += RuleI(Spells, WizCritRatio); //Default is zero - - if (Critical){ - - value = value_BaseEffect*ratio/100; - - value += value_BaseEffect*GetBotFocusEffect(BotfocusImprovedDamage, spell_id)/100; - - value += int(value_BaseEffect*GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id)/100)*ratio/100; - + ratio += RuleI(Spells, WizCritRatio); + if (Critical) { + value = (value_BaseEffect * ratio / 100); + value += (value_BaseEffect * GetBotFocusEffect(BotfocusImprovedDamage, spell_id) / 100); + value += (int(value_BaseEffect * GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id) / 100) * ratio / 100); if (target) { - value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100; + value += (int(value_BaseEffect * target->GetVulnerability(this, spell_id, 0) / 100) * ratio / 100); value -= target->GetFcDamageAmtIncoming(this, spell_id); } - value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id)*ratio/100; + value -= (GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id) * ratio / 100); value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) - value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100; + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + value += (GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value) * ratio / 100); entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), -value); @@ -8741,29 +7256,23 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { } } - value = value_BaseEffect; - - value += value_BaseEffect*GetBotFocusEffect(BotfocusImprovedDamage, spell_id)/100; - - value += value_BaseEffect*GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id)/100; - - if (target) { - value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100; + value = value_BaseEffect; + value += (value_BaseEffect * GetBotFocusEffect(BotfocusImprovedDamage, spell_id) / 100); + value += (value_BaseEffect * GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id) / 100); + if (target) { + value += (value_BaseEffect * target->GetVulnerability(this, spell_id, 0) / 100); value -= target->GetFcDamageAmtIncoming(this, spell_id); - } + } - value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id); - - value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); - - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) - value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); + value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id); + value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); return value; } int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { - if (target == nullptr) target = this; @@ -8771,72 +7280,52 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { int32 chance = 0; int8 modifier = 1; bool Critical = false; - - value_BaseEffect = value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id)/100); - + value_BaseEffect = (value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id) / 100)); value = value_BaseEffect; - - value += int(value_BaseEffect*GetBotFocusEffect(BotfocusImprovedHeal, spell_id)/100); - - // Instant Heals + value += int(value_BaseEffect*GetBotFocusEffect(BotfocusImprovedHeal, spell_id) / 100); if(spells[spell_id].buffduration < 1) { - - chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance; - + chance += (itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance); chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id); - if (spellbonuses.CriticalHealDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); - if(chance && (zone->random.Int(0,99) < chance)) { + if(chance && (zone->random.Int(0, 99) < chance)) { Critical = true; - modifier = 2; //At present time no critical heal amount modifier SPA exists. + modifier = 2; } value *= modifier; - value += GetBotFocusEffect(BotfocusFcHealAmtCrit, spell_id) * modifier; + value += (GetBotFocusEffect(BotfocusFcHealAmtCrit, spell_id) * modifier); value += GetBotFocusEffect(BotfocusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) - value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier; - - value += value*target->GetHealRate(spell_id, this)/100; + if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + value += (GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier); + value += (value * target->GetHealRate(spell_id, this) / 100); if (Critical) entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), value); return value; - } - - //Heal over time spells. [Heal Rate and Additional Healing effects do not increase this value] - else { - - chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime; - + } else { + chance = (itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime); chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id); - if (spellbonuses.CriticalRegenDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); if(chance && (zone->random.Int(0,99) < chance)) return (value * 2); } - return value; } int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) { int32 cast_reducer = 0; cast_reducer += GetBotFocusEffect(BotfocusSpellHaste, spell_id); - uint8 botlevel = GetLevel(); uint8 botclass = GetClass(); - - if (botlevel >= 51 && casttime >= 3000 && !BeneficialSpell(spell_id) - && (botclass == SHADOWKNIGHT || botclass == RANGER - || botclass == PALADIN || botclass == BEASTLORD )) - cast_reducer += (GetLevel()-50)*3; + if (botlevel >= 51 && casttime >= 3000 && !BeneficialSpell(spell_id) && (botclass == SHADOWKNIGHT || botclass == RANGER || botclass == PALADIN || botclass == BEASTLORD )) + cast_reducer += ((GetLevel() - 50) * 3); if((casttime >= 4000) && BeneficialSpell(spell_id) && IsBuffSpell(spell_id)) { switch (GetAA(aaSpellCastingDeftness)) { @@ -8909,86 +7398,70 @@ int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) { if (cast_reducer > RuleI(Spells, MaxCastTimeReduction)) cast_reducer = RuleI(Spells, MaxCastTimeReduction); - casttime = (casttime*(100 - cast_reducer)/100); - + casttime = (casttime * (100 - cast_reducer) / 100); return casttime; } int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { - // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell - if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) - { - int32 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; - // Doesnt generate mana, so best case is a free spell + if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) { + int32 mana_back = (this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100); if(mana_back > cost) mana_back = cost; cost -= mana_back; } - // This formula was derived from the following resource: - // http://www.eqsummoners.com/eq1/specialization-library.html - // WildcardX float PercentManaReduction = 0; float SpecializeSkill = GetSpecializeSkillValue(spell_id); int SuccessChance = zone->random.Int(0, 100); - float bonus = 1.0; - switch(GetAA(aaSpellCastingMastery)) - { - case 1: - bonus += 0.05; - break; - case 2: - bonus += 0.15; - break; - case 3: - bonus += 0.30; - break; + switch(GetAA(aaSpellCastingMastery)) { + case 1: + bonus += 0.05; + break; + case 2: + bonus += 0.15; + break; + case 3: + bonus += 0.30; + break; } - bonus += 0.05 * GetAA(aaAdvancedSpellCastingMastery); + bonus += (0.05 * GetAA(aaAdvancedSpellCastingMastery)); - if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) - { - PercentManaReduction = 1 + 0.05 * SpecializeSkill; - switch(GetAA(aaSpellCastingMastery)) - { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; + if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) { + PercentManaReduction = (1 + 0.05 * SpecializeSkill); + switch(GetAA(aaSpellCastingMastery)) { + case 1: + PercentManaReduction += 2.5; + break; + case 2: + PercentManaReduction += 5.0; + break; + case 3: + PercentManaReduction += 10.0; + break; } - switch(GetAA(aaAdvancedSpellCastingMastery)) - { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; + switch(GetAA(aaAdvancedSpellCastingMastery)) { + case 1: + PercentManaReduction += 2.5; + break; + case 2: + PercentManaReduction += 5.0; + break; + case 3: + PercentManaReduction += 10.0; + break; } } int32 focus_redux = GetBotFocusEffect(BotfocusManaCost, spell_id); if(focus_redux > 0) - { PercentManaReduction += zone->random.Real(1, (double)focus_redux); - } cost -= (cost * (PercentManaReduction / 100)); - - // Gift of Mana - reduces spell cost to 1 mana if(focus_redux >= 100) { uint32 buff_max = GetMaxTotalSlots(); for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) { @@ -9011,17 +7484,15 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { float Bot::GetActSpellRange(uint16 spell_id, float range) { float extrange = 100; extrange += GetBotFocusEffect(BotfocusRange, spell_id); - return (range * extrange) / 100; + return ((range * extrange) / 100); } int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { int increase = 100; increase += GetBotFocusEffect(BotfocusSpellDuration, spell_id); - int tic_inc = 0; - tic_inc = GetBotFocusEffect(BotfocusSpellDurByTic, spell_id); + int tic_inc = 0; tic_inc = GetBotFocusEffect(BotfocusSpellDurByTic, spell_id); - if(IsBeneficialSpell(spell_id)) - { + if(IsBeneficialSpell(spell_id)) { switch (GetAA(aaSpellCastingReinforcement)) { case 1: increase += 5; @@ -9033,6 +7504,7 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { increase += 30; if (GetAA(aaSpellCastingReinforcementMastery) == 1) increase += 20; + break; } @@ -9040,52 +7512,43 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { increase += 20; } - if(IsMezSpell(spell_id)) { + if(IsMezSpell(spell_id)) tic_inc += GetAA(aaMesmerizationMastery); - } return (((duration * increase) / 100) + tic_inc); } float Bot::GetAOERange(uint16 spell_id) { float range; - range = spells[spell_id].aoerange; - if(range == 0) //for TGB spells, they prolly do not have an aoe range - range = spells[spell_id].range; if(range == 0) - range = 10; //something.... + range = spells[spell_id].range; + + if(range == 0) + range = 10; if(IsBardSong(spell_id) && IsBeneficialSpell(spell_id)) { - //Live AA - Extended Notes, SionachiesCrescendo - float song_bonus = aabonuses.SongRange + spellbonuses.SongRange + itembonuses.SongRange; - range += range*song_bonus /100.0f; + float song_bonus = (aabonuses.SongRange + spellbonuses.SongRange + itembonuses.SongRange); + range += (range * song_bonus / 100.0f); } - range = GetActSpellRange(spell_id, range); - return range; } bool Bot::SpellEffect(Mob* caster, uint16 spell_id, float partial) { bool Result = false; - Result = Mob::SpellEffect(caster, spell_id, partial); - - // Franck-add: If healed/doted, a bot must show its new HP to its leader if(IsGrouped()) { Group *g = GetGroup(); if(g) { EQApplicationPacket hp_app; CreateHPPacket(&hp_app); for(int i=0; imembers[i] && g->members[i]->IsClient()) { + if(g->members[i] && g->members[i]->IsClient()) g->members[i]->CastToClient()->QueuePacket(&hp_app); - } } } } - return Result; } @@ -9095,26 +7558,26 @@ void Bot::DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster) { bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust) { bool Result = false; - if(zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) { - - 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", - spells[spell_id].name, spell_id, target_id, slot, cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot); + 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", spells[spell_id].name, spell_id, target_id, slot, cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot); if(casting_spell_id == spell_id) ZeroCastingVars(); if(GetClass() != BARD) { if(!IsValidSpell(spell_id) || casting_spell_id || delaytimer || spellend_timer.Enabled() || IsStunned() || IsFeared() || IsMezzed() || (IsSilenced() && !IsDiscipline(spell_id)) || (IsAmnesiad() && IsDiscipline(spell_id))) { - Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d", - IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() ); + Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d", IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() ); if(IsSilenced() && !IsDiscipline(spell_id)) Message_StringID(13, SILENCED_STRING); + if(IsAmnesiad() && IsDiscipline(spell_id)) + Message_StringID(13, MELEE_SILENCE); + if(casting_spell_id) AI_Event_SpellCastFinished(false, casting_spell_slot); - return(false); + + return false; } } @@ -9122,60 +7585,45 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t Message_StringID(13, SPELL_WOULDNT_HOLD); if(casting_spell_id) AI_Event_SpellCastFinished(false, casting_spell_slot); - return(false); + + return false; } - //cannot cast under deivne aura if(DivineAura()) { Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: cannot cast while Divine Aura is in effect."); InterruptSpell(173, 0x121, false); - return(false); + return false; } - - // 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 < MAX_PP_MEMSPELL && !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); - return(false); + return false; } if (HasActiveSong()) { Log.Out(Logs::Detail, Logs::Spells, "Casting a new spell/song while singing a song. Killing old song %d.", bardsong); - //Note: this does NOT tell the client - //_StopSong(); bardsong = 0; bardsong_target_id = 0; bardsong_slot = 0; bardsong_timer.Disable(); } - Result = DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot); } - return Result; } bool Bot::SpellOnTarget(uint16 spell_id, Mob* spelltar) { bool Result = false; - if(!IsValidSpell(spell_id)) return false; if(spelltar) { if(spelltar->IsBot() && (spells[spell_id].targettype == ST_GroupTeleport)) { - // So I made this check because teleporting a group of bots tended to crash the zone - // It seems several group spells also show up as ST_GroupTeleport for some - // reason so I now have to check by spell id. These appear to be Group v1 spells and - // Heal over Time spells. switch(spell_id) { // Paladin case 3577: // Wave of Life @@ -9246,50 +7694,39 @@ bool Bot::SpellOnTarget(uint16 spell_id, Mob* spelltar) { } } - //Franck-add: can't detrimental spell on bots and bots can't detriment on you or the others bots if(((IsDetrimentalSpell(spell_id) && spelltar->IsBot()) || (IsDetrimentalSpell(spell_id) && spelltar->IsClient())) && !IsResurrectionEffects(spell_id)) return false; if(spelltar->IsPet()) { - for(int i=0; iGetZoneID() == 202) && !(this == caster)) { Result = Mob::IsImmuneToSpell(spell_id, caster); - if(!Result) { if(caster->IsBot()) { if(spells[spell_id].targettype == ST_Undead) { if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Undead) && (GetBodyType() != BT_Vampire)) { - Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not an undead."); - return true; + Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not an undead."); + return true; } } if(spells[spell_id].targettype == ST_Summoned) { - if((GetBodyType() != BT_SummonedUndead) - && (GetBodyType() != BT_Summoned) - && (GetBodyType() != BT_Summoned2) - && (GetBodyType() != BT_Summoned3) - ) { - Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not a summoned creature."); - return true; + if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Summoned) && (GetBodyType() != BT_Summoned2) && (GetBodyType() != BT_Summoned3)) { + Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not a summoned creature."); + return true; } } } @@ -9303,175 +7740,135 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction) { bool Result = false; - SpellTargetType targetType = spells[spell_id].targettype; - - - // This is so PoK NPC Necro/Shd can create essence emeralds for pc's from perl scripts if(targetType == ST_GroupClientAndPet) { - if(((spell_id == 1768) && (zone->GetZoneID() == 202)) || (!IsDetrimentalSpell(spell_id))) { + if((spell_id == 1768 && zone->GetZoneID() == 202) || (!IsDetrimentalSpell(spell_id))) { CastAction = SingleTarget; return true; } } - Result = Mob::DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction); - return Result; } bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot) { bool Result = false; - - if(GetClass() == BARD) { - // Bard bots casting time is interrupting thier melee + if(GetClass() == BARD) cast_time = 0; - } Result = Mob::DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot); - if(oSpellWillFinish) { const SPDat_Spell_Struct &spell = spells[spell_id]; *oSpellWillFinish = Timer::GetCurrentTime() + ((spell.recast_time > 20000) ? 10000 : spell.recast_time); } - return Result; } -int32 Bot::GenerateBaseManaPoints() -{ - // Now, we need to calc the base mana. +int32 Bot::GenerateBaseManaPoints() { int32 bot_mana = 0; int32 WisInt = 0; int32 MindLesserFactor, MindFactor; int wisint_mana = 0; int base_mana = 0; int ConvertedWisInt = 0; - - switch(GetCasterClass()) - { + switch(GetCasterClass()) { case 'I': WisInt = INT; if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { if(WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); - if(WisInt > 201) { + if(WisInt > 201) ConvertedWisInt -= ((WisInt - 201) * 5 / 4); - } } - else { + else ConvertedWisInt = WisInt; - } + if(GetLevel() < 41) { wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000); base_mana = (GetLevel() * 15); - } - else if(GetLevel() < 81) { + } else if(GetLevel() < 81) { wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100)); base_mana = (600 + ((GetLevel() - 40) * 30)); - } - else { + } else { wisint_mana = (9 * ConvertedWisInt); base_mana = (1800 + ((GetLevel() - 80) * 18)); } - bot_mana = base_mana + wisint_mana; - } - else { - if((( WisInt - 199 ) / 2) > 0) { - MindLesserFactor = ( WisInt - 199 ) / 2; - } - else { + bot_mana = (base_mana + wisint_mana); + } else { + if(((WisInt - 199) / 2) > 0) + MindLesserFactor = ((WisInt - 199) / 2); + else MindLesserFactor = 0; - } + MindFactor = WisInt - MindLesserFactor; - if(WisInt > 100) { + if(WisInt > 100) bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40); - } - else { + else bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100); - } } break; - case 'W': WisInt = WIS; if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { if(WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); - if(WisInt > 201) { + if(WisInt > 201) ConvertedWisInt -= ((WisInt - 201) * 5 / 4); - } - } - else { + } else ConvertedWisInt = WisInt; - } + if(GetLevel() < 41) { wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000); base_mana = (GetLevel() * 15); - } - else if(GetLevel() < 81) { + } else if(GetLevel() < 81) { wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100)); base_mana = (600 + ((GetLevel() - 40) * 30)); - } - else { + } else { wisint_mana = (9 * ConvertedWisInt); base_mana = (1800 + ((GetLevel() - 80) * 18)); } - bot_mana = base_mana + wisint_mana; - } - else { - if((( WisInt - 199 ) / 2) > 0) { - MindLesserFactor = ( WisInt - 199 ) / 2; - } - else { + bot_mana = (base_mana + wisint_mana); + } else { + if(((WisInt - 199) / 2) > 0) + MindLesserFactor = ((WisInt - 199) / 2); + else MindLesserFactor = 0; - } - MindFactor = WisInt - MindLesserFactor; - if(WisInt > 100) { + + MindFactor = (WisInt - MindLesserFactor); + if(WisInt > 100) bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40); - } - else { + else bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100); - } } break; - default: bot_mana = 0; break; } - max_mana = bot_mana; - return bot_mana; } -void Bot::GenerateSpecialAttacks() -{ - // Special Attacks - if(((GetClass() == MONK) || (GetClass() == WARRIOR) || (GetClass() == RANGER) || (GetClass() == BERSERKER)) && (GetLevel() >= 60)) { +void Bot::GenerateSpecialAttacks() { + if(((GetClass() == MONK) || (GetClass() == WARRIOR) || (GetClass() == RANGER) || (GetClass() == BERSERKER)) && (GetLevel() >= 60)) SetSpecialAbility(SPECATK_TRIPLE, 1); - } } bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { if(GetClass() == BARD) { - if(!ApplyNextBardPulse(bardsong, this, bardsong_slot)) { + if(!ApplyNextBardPulse(bardsong, this, bardsong_slot)) InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong); - } + stopLogic = true; } - return true; } bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { if(spellTarget) { if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, BotGroupBuffing)) { - //NPC *bot = this->CastToNPC(); bool noGroupSpell = false; uint16 thespell = spell_id; - for(int i=0; i < AIspells.size(); i++) { int j = BotGetSpells(i); int spelltype = BotGetSpellType(i); @@ -9480,11 +7877,8 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 bool spelltypetargetequal = ((spelltype == 8) && (spells[thespell].targettype == ST_Self)); bool spelltypeclassequal = ((spelltype == 1024) && (GetClass() == SHAMAN)); bool slotequal = (slot == USE_ITEM_SPELL_SLOT); - - // if it's a targeted heal or escape spell or pet spell or it's self only buff or self buff weapon proc, we only want to cast it once if(spellequal || slotequal) { if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) { - // Don't let the Shaman canni themselves to death if(((spells[thespell].effectid[0] == 0) && (spells[thespell].base[0] < 0)) && (spellTarget->GetHP() < ((spells[thespell].base[0] * (-1)) + 100))) { return false; @@ -9500,71 +7894,45 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 if(!noGroupSpell) { Group *g = GetGroup(); if(g) { - for(int i=0; imembers[i]) { - if((g->members[i]->GetClass() == NECROMANCER) && - (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune))) { - // don't cast this on necro's, their health to mana - // spell eats up the rune spell and it just keeps - // getting recast over and over + if((g->members[i]->GetClass() == NECROMANCER) && (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune))) { } else - { SpellOnTarget(thespell, g->members[i]); - } - if(g->members[i] && g->members[i]->GetPetID()) { + + if(g->members[i] && g->members[i]->GetPetID()) SpellOnTarget(thespell, g->members[i]->GetPet()); - } } } SetMana(GetMana() - (GetActSpellCost(thespell, spells[thespell].mana) * (g->GroupCount() - 1))); } } - stopLogic = true; } } - return true; } bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { bool isMainGroupMGB = false; - - //if(GetBotRaidID() > 0) { - // BotRaids *br = entity_list.GetBotRaidByMob(this); - // if(br) { - // for(int n=0; nBotRaidGroups[0] && (br->BotRaidGroups[0]->members[n] == this)) { - // if(GetLevel() >= 59) // MGB AA - // isMainGroupMGB = true; - // break; - // } - // } - // } - //} - if(isMainGroupMGB && (GetClass() != BARD)) { BotGroupSay(this, "MGB %s", spells[spell_id].name); SpellOnTarget(spell_id, this); entity_list.AESpell(this, this, spell_id, true); - } - else { + } else { Group *g = GetGroup(); if(g) { - for(int i=0; imembers[i]) { SpellOnTarget(spell_id, g->members[i]); - if(g->members[i] && g->members[i]->GetPetID()) { + if(g->members[i] && g->members[i]->GetPetID()) SpellOnTarget(spell_id, g->members[i]->GetPet()); - } } } } } - stopLogic = true; - return true; } @@ -9575,7 +7943,6 @@ void Bot::CalcBonuses() { CalcSpellBonuses(&spellbonuses); GenerateAABonuses(&aabonuses); SetAttackTimer(); - CalcATK(); CalcSTR(); CalcSTA(); @@ -9584,16 +7951,13 @@ void Bot::CalcBonuses() { CalcINT(); CalcWIS(); CalcCHA(); - CalcMR(); CalcFR(); CalcDR(); CalcPR(); CalcCR(); CalcCorrup(); - GenerateArmorClass(); - CalcMaxHP(); CalcMaxMana(); CalcMaxEndurance(); @@ -9605,17 +7969,14 @@ void Bot::CalcBonuses() { int32 Bot::CalcHPRegenCap(){ int level = GetLevel(); int32 hpregen_cap = 0; - hpregen_cap = RuleI(Character, ItemHealthRegenCap) + itembonuses.HeroicSTA/25; - - hpregen_cap += aabonuses.ItemHPRegenCap + spellbonuses.ItemHPRegenCap + itembonuses.ItemHPRegenCap; - + hpregen_cap = (RuleI(Character, ItemHealthRegenCap) + itembonuses.HeroicSTA / 25); + hpregen_cap += (aabonuses.ItemHPRegenCap + spellbonuses.ItemHPRegenCap + itembonuses.ItemHPRegenCap); return (hpregen_cap * RuleI(Character, HPRegenMultiplier) / 100); } int32 Bot::CalcManaRegenCap(){ int32 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap; - switch(GetCasterClass()) - { + switch(GetCasterClass()) { case 'I': cap += (itembonuses.HeroicINT / 25); break; @@ -9623,36 +7984,27 @@ int32 Bot::CalcManaRegenCap(){ cap += (itembonuses.HeroicWIS / 25); break; } - return (cap * RuleI(Character, ManaRegenMultiplier) / 100); } -// Return max stat value for level int32 Bot::GetMaxStat() { int level = GetLevel(); int32 base = 0; - - if (level < 61) { + if (level < 61) base = 255; - } - else if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoF) { - base = 255 + 5 * (level - 60); - } - else if (level < 71) { - base = 255 + 5 * (level - 60); - } - else { + else if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoF) + base = (255 + 5 * (level - 60)); + else if (level < 71) + base = (255 + 5 * (level - 60)); + else base = 330; - } - return(base); + return base; } int32 Bot::GetMaxResist() { int level = GetLevel(); - int32 base = 500; - if(level > 60) base += ((level - 60) * 5); @@ -9660,93 +8012,63 @@ int32 Bot::GetMaxResist() { } int32 Bot::GetMaxSTR() { - return GetMaxStat() - + itembonuses.STRCapMod - + spellbonuses.STRCapMod - + aabonuses.STRCapMod; + return (GetMaxStat() + itembonuses.STRCapMod + spellbonuses.STRCapMod + aabonuses.STRCapMod); } + int32 Bot::GetMaxSTA() { - return GetMaxStat() - + itembonuses.STACapMod - + spellbonuses.STACapMod - + aabonuses.STACapMod; + return (GetMaxStat() + itembonuses.STACapMod + spellbonuses.STACapMod + aabonuses.STACapMod); } + int32 Bot::GetMaxDEX() { - return GetMaxStat() - + itembonuses.DEXCapMod - + spellbonuses.DEXCapMod - + aabonuses.DEXCapMod; + return (GetMaxStat() + itembonuses.DEXCapMod + spellbonuses.DEXCapMod + aabonuses.DEXCapMod); } + int32 Bot::GetMaxAGI() { - return GetMaxStat() - + itembonuses.AGICapMod - + spellbonuses.AGICapMod - + aabonuses.AGICapMod; + return (GetMaxStat() + itembonuses.AGICapMod + spellbonuses.AGICapMod + aabonuses.AGICapMod); } + int32 Bot::GetMaxINT() { - return GetMaxStat() - + itembonuses.INTCapMod - + spellbonuses.INTCapMod - + aabonuses.INTCapMod; + return (GetMaxStat() + itembonuses.INTCapMod + spellbonuses.INTCapMod + aabonuses.INTCapMod); } + int32 Bot::GetMaxWIS() { - return GetMaxStat() - + itembonuses.WISCapMod - + spellbonuses.WISCapMod - + aabonuses.WISCapMod; + return (GetMaxStat() + itembonuses.WISCapMod + spellbonuses.WISCapMod + aabonuses.WISCapMod); } int32 Bot::GetMaxCHA() { - return GetMaxStat() - + itembonuses.CHACapMod - + spellbonuses.CHACapMod - + aabonuses.CHACapMod; + return (GetMaxStat() + itembonuses.CHACapMod + spellbonuses.CHACapMod + aabonuses.CHACapMod); } + int32 Bot::GetMaxMR() { - return GetMaxResist() - + itembonuses.MRCapMod - + spellbonuses.MRCapMod - + aabonuses.MRCapMod; + return (GetMaxResist() + itembonuses.MRCapMod + spellbonuses.MRCapMod + aabonuses.MRCapMod); } + int32 Bot::GetMaxPR() { - return GetMaxResist() - + itembonuses.PRCapMod - + spellbonuses.PRCapMod - + aabonuses.PRCapMod; + return (GetMaxResist() + itembonuses.PRCapMod + spellbonuses.PRCapMod + aabonuses.PRCapMod); } + int32 Bot::GetMaxDR() { - return GetMaxResist() - + itembonuses.DRCapMod - + spellbonuses.DRCapMod - + aabonuses.DRCapMod; + return (GetMaxResist() + itembonuses.DRCapMod + spellbonuses.DRCapMod + aabonuses.DRCapMod); } + int32 Bot::GetMaxCR() { - return GetMaxResist() - + itembonuses.CRCapMod - + spellbonuses.CRCapMod - + aabonuses.CRCapMod; + return (GetMaxResist() + itembonuses.CRCapMod + spellbonuses.CRCapMod + aabonuses.CRCapMod); } + int32 Bot::GetMaxFR() { - return GetMaxResist() - + itembonuses.FRCapMod - + spellbonuses.FRCapMod - + aabonuses.FRCapMod; + return (GetMaxResist() + itembonuses.FRCapMod + spellbonuses.FRCapMod + aabonuses.FRCapMod); } + int32 Bot::GetMaxCorrup() { - return GetMaxResist() - + itembonuses.CorrupCapMod - + spellbonuses.CorrupCapMod - + aabonuses.CorrupCapMod; + return (GetMaxResist() + itembonuses.CorrupCapMod + spellbonuses.CorrupCapMod + aabonuses.CorrupCapMod); } int32 Bot::CalcSTR() { - int32 val = STR + itembonuses.STR + spellbonuses.STR; - + int32 val = (STR + itembonuses.STR + spellbonuses.STR); int32 mod = aabonuses.STR; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - STR = val + mod; - + + STR = (val + mod); if(STR < 1) STR = 1; @@ -9754,18 +8076,16 @@ int32 Bot::CalcSTR() { if(STR > m) STR = m; - return(STR); + return STR; } int32 Bot::CalcSTA() { - int32 val = STA + itembonuses.STA + spellbonuses.STA; - + int32 val = (STA + itembonuses.STA + spellbonuses.STA); int32 mod = aabonuses.STA; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - STA = val + mod; - + + STA = (val + mod); if(STA < 1) STA = 1; @@ -9773,18 +8093,16 @@ int32 Bot::CalcSTA() { if(STA > m) STA = m; - return(STA); + return STA; } int32 Bot::CalcAGI() { - int32 val = AGI + itembonuses.AGI + spellbonuses.AGI; + int32 val = (AGI + itembonuses.AGI + spellbonuses.AGI); int32 mod = aabonuses.AGI; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - AGI = val + mod; - + AGI = (val + mod); if(AGI < 1) AGI = 1; @@ -9792,18 +8110,16 @@ int32 Bot::CalcAGI() { if(AGI > m) AGI = m; - return(AGI); + return AGI; } int32 Bot::CalcDEX() { - int32 val = DEX + itembonuses.DEX + spellbonuses.DEX; - + int32 val = (DEX + itembonuses.DEX + spellbonuses.DEX); int32 mod = aabonuses.DEX; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - DEX = val + mod; - + + DEX = (val + mod); if(DEX < 1) DEX = 1; @@ -9811,35 +8127,34 @@ int32 Bot::CalcDEX() { if(DEX > m) DEX = m; - return(DEX); + return DEX; } int32 Bot::CalcINT() { - int32 val = INT + itembonuses.INT + spellbonuses.INT; - + int32 val = (INT + itembonuses.INT + spellbonuses.INT); int32 mod = aabonuses.INT; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - INT = val + mod; + + INT = (val + mod); if(INT < 1) INT = 1; + int m = GetMaxINT(); if(INT > m) INT = m; - return(INT); + return INT; } int32 Bot::CalcWIS() { - int32 val = WIS + itembonuses.WIS + spellbonuses.WIS; - + int32 val = (WIS + itembonuses.WIS + spellbonuses.WIS); int32 mod = aabonuses.WIS; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - WIS = val + mod; + + WIS = (val + mod); if(WIS < 1) WIS = 1; @@ -9848,17 +8163,16 @@ int32 Bot::CalcWIS() { if(WIS > m) WIS = m; - return(WIS); + return WIS; } int32 Bot::CalcCHA() { - int32 val = CHA + itembonuses.CHA + spellbonuses.CHA; - + int32 val = (CHA + itembonuses.CHA + spellbonuses.CHA); int32 mod = aabonuses.CHA; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - CHA = val + mod; + + CHA = (val + mod); if(CHA < 1) CHA = 1; @@ -9867,18 +8181,13 @@ int32 Bot::CalcCHA() { if(CHA > m) CHA = m; - return(CHA); + return CHA; } -//The AA multipliers are set to be 5, but were 2 on WR -//The resistant discipline which I think should be here is implemented -//in Mob::ResistSpell -int32 Bot::CalcMR() -{ - MR += itembonuses.MR + spellbonuses.MR + aabonuses.MR; - +int32 Bot::CalcMR() { + MR += (itembonuses.MR + spellbonuses.MR + aabonuses.MR); if(GetClass() == WARRIOR) - MR += GetLevel() / 2; + MR += (GetLevel() / 2); if(MR < 1) MR = 1; @@ -9886,21 +8195,19 @@ int32 Bot::CalcMR() if(MR > GetMaxMR()) MR = GetMaxMR(); - return(MR); + return MR; } -int32 Bot::CalcFR() -{ +int32 Bot::CalcFR() { int c = GetClass(); if(c == RANGER) { FR += 4; - int l = GetLevel(); if(l > 49) - FR += l - 49; + FR += (l - 49); } - FR += itembonuses.FR + spellbonuses.FR + aabonuses.FR; + FR += (itembonuses.FR + spellbonuses.FR + aabonuses.FR); if(FR < 1) FR = 1; @@ -9908,57 +8215,48 @@ int32 Bot::CalcFR() if(FR > GetMaxFR()) FR = GetMaxFR(); - return(FR); + return FR; } -int32 Bot::CalcDR() -{ +int32 Bot::CalcDR() { int c = GetClass(); if(c == PALADIN) { DR += 8; - int l = GetLevel(); if(l > 49) - DR += l - 49; - + DR += (l - 49); } else if(c == SHADOWKNIGHT) { DR += 4; - int l = GetLevel(); if(l > 49) - DR += l - 49; + DR += (l - 49); } - DR += itembonuses.DR + spellbonuses.DR + aabonuses.DR; - + DR += (itembonuses.DR + spellbonuses.DR + aabonuses.DR); if(DR < 1) DR = 1; if(DR > GetMaxDR()) DR = GetMaxDR(); - return(DR); + return DR; } -int32 Bot::CalcPR() -{ +int32 Bot::CalcPR() { int c = GetClass(); if(c == ROGUE) { PR += 8; - int l = GetLevel(); if(l > 49) - PR += l - 49; - + PR += (l - 49); } else if(c == SHADOWKNIGHT) { PR += 4; - int l = GetLevel(); if(l > 49) - PR += l - 49; + PR += (l - 49); } - PR += itembonuses.PR + spellbonuses.PR + aabonuses.PR; + PR += (itembonuses.PR + spellbonuses.PR + aabonuses.PR); if(PR < 1) PR = 1; @@ -9966,21 +8264,19 @@ int32 Bot::CalcPR() if(PR > GetMaxPR()) PR = GetMaxPR(); - return(PR); + return PR; } -int32 Bot::CalcCR() -{ +int32 Bot::CalcCR() { int c = GetClass(); if(c == RANGER) { CR += 4; - int l = GetLevel(); if(l > 49) - CR += l - 49; + CR += (l - 49); } - CR += itembonuses.CR + spellbonuses.CR + aabonuses.CR; + CR += (itembonuses.CR + spellbonuses.CR + aabonuses.CR); if(CR < 1) CR = 1; @@ -9988,39 +8284,28 @@ int32 Bot::CalcCR() if(CR > GetMaxCR()) CR = GetMaxCR(); - return(CR); + return CR; } -int32 Bot::CalcCorrup() -{ - Corrup = Corrup + itembonuses.Corrup + spellbonuses.Corrup + aabonuses.Corrup; - +int32 Bot::CalcCorrup() { + Corrup = (Corrup + itembonuses.Corrup + spellbonuses.Corrup + aabonuses.Corrup); if(Corrup > GetMaxCorrup()) Corrup = GetMaxCorrup(); - return(Corrup); + return Corrup; } int32 Bot::CalcATK() { - ATK = itembonuses.ATK + spellbonuses.ATK + aabonuses.ATK + GroupLeadershipAAOffenseEnhancement(); - return(ATK); + ATK = (itembonuses.ATK + spellbonuses.ATK + aabonuses.ATK + GroupLeadershipAAOffenseEnhancement()); + return ATK; } void Bot::CalcRestState() { - - // This method calculates rest state HP and mana regeneration. - // The bot must have been out of combat for RuleI(Character, RestRegenTimeToActivate) seconds, - // must be sitting down, and must not have any detrimental spells affecting them. - // if(!RuleI(Character, RestRegenPercent)) return; RestRegenHP = RestRegenMana = RestRegenEndurance = 0; - - if(IsEngaged() || !IsSitting()) - return; - - if(!rest_timer.Check(false)) + if(IsEngaged() || !IsSitting() || !rest_timer.Check(false)) return; uint32 buff_count = GetMaxTotalSlots(); @@ -10033,44 +8318,35 @@ void Bot::CalcRestState() { } RestRegenHP = (GetMaxHP() * RuleI(Character, RestRegenPercent) / 100); - RestRegenMana = (GetMaxMana() * RuleI(Character, RestRegenPercent) / 100); - if(RuleB(Character, RestRegenEndurance)) RestRegenEndurance = (GetMaxEndurance() * RuleI(Character, RestRegenPercent) / 100); } -int32 Bot::LevelRegen() -{ +int32 Bot::LevelRegen() { int level = GetLevel(); bool bonus = GetRaceBitmask(_baseRace) & 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 if (level < 51) { if (IsSitting()) { if (level < 20) - hp += 2 * multiplier1; + hp += (2 * multiplier1); else if (level < 50) - hp += 3 * multiplier1; - else //level == 50 - hp += 4 * multiplier1; - } - else //feigned or standing - hp += 1 * multiplier1; - } - //there may be an easier way to calculate this next part, but I don't know what it is - else { //level >= 51 + hp += (3 * multiplier1); + else + hp += (4 * multiplier1); + } else + hp += (1 * multiplier1); + } else { int32 tmp = 0; float multiplier2 = 1; if (level < 56) { tmp = 2; if (bonus) multiplier2 = 3; - } - else if (level < 60) { - tmp = 3; + } else if (level < 60) { + tmp = 3; if (bonus) multiplier2 = 3.34; } @@ -10078,56 +8354,44 @@ int32 Bot::LevelRegen() tmp = 4; if (bonus) multiplier2 = 3; - } - else if (level < 63) { + } else if (level < 63) { tmp = 5; if (bonus) multiplier2 = 2.8; - } - else if (level < 65) { + } else if (level < 65) { tmp = 6; if (bonus) multiplier2 = 2.67; - } - else { //level >= 65 + } else { tmp = 7; if (bonus) multiplier2 = 2.58; } - - hp += int32(float(tmp) * multiplier2); + hp += (int32(float(tmp) * multiplier2)); } - return hp; } int32 Bot::CalcHPRegen() { - int32 regen = LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen; - regen += aabonuses.HPRegen + GroupLeadershipAAHealthRegeneration(); - - regen = (regen * RuleI(Character, HPRegenMultiplier)) / 100; + int32 regen = (LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen); + regen += (aabonuses.HPRegen + GroupLeadershipAAHealthRegeneration()); + regen = ((regen * RuleI(Character, HPRegenMultiplier)) / 100); return regen; } -int32 Bot::CalcManaRegen() -{ +int32 Bot::CalcManaRegen() { uint8 level = GetLevel(); uint8 botclass = GetClass(); int32 regen = 0; - //this should be changed so we dont med while camping, etc... - if (IsSitting()) - { + if (IsSitting()) { BuffFadeBySitModifier(); if(botclass != WARRIOR && botclass != MONK && botclass != ROGUE && botclass != BERSERKER) { - regen = (((GetSkill(SkillMeditate) / 10) + (level - (level / 4))) / 4) + 4; - regen += spellbonuses.ManaRegen + itembonuses.ManaRegen; - } - else - regen = 2 + spellbonuses.ManaRegen + itembonuses.ManaRegen; - } - else { - regen = 2 + spellbonuses.ManaRegen + itembonuses.ManaRegen; - } + regen = ((((GetSkill(SkillMeditate) / 10) + (level - (level / 4))) / 4) + 4); + regen += (spellbonuses.ManaRegen + itembonuses.ManaRegen); + } else + regen = (2 + spellbonuses.ManaRegen + itembonuses.ManaRegen); + } else + regen = (2 + spellbonuses.ManaRegen + itembonuses.ManaRegen); if(GetCasterClass() == 'I') regen += (itembonuses.HeroicINT / 25); @@ -10137,37 +8401,18 @@ int32 Bot::CalcManaRegen() regen = 0; regen += aabonuses.ManaRegen; - - regen = (regen * RuleI(Character, ManaRegenMultiplier)) / 100; - + regen = ((regen * RuleI(Character, ManaRegenMultiplier)) / 100); float mana_regen_rate = RuleR(Bots, BotManaRegen); if(mana_regen_rate < 0.0f) mana_regen_rate = 0.0f; - regen = regen * mana_regen_rate; // 90% of people wouldnt guess that manaregen would decrease the larger the number they input, this makes more sense - + regen = (regen * mana_regen_rate); return regen; } -// This is for calculating Base HPs + STA bonus for SoD or later clients. uint32 Bot::GetClassHPFactor() { - - int factor; - - // Note: Base HP factor under level 41 is equal to factor / 12, and from level 41 to 80 is factor / 6. - // Base HP over level 80 is factor / 10 - // HP per STA point per level is factor / 30 for level 80+ - // HP per STA under level 40 is the level 80 HP Per STA / 120, and for over 40 it is / 60. - - switch(GetClass()) - { - case DRUID: - case ENCHANTER: - case NECROMANCER: - case MAGICIAN: - case WIZARD: - factor = 240; - break; + uint32 factor; + switch(GetClass()) { case BEASTLORD: case BERSERKER: case MONK: @@ -10199,46 +8444,36 @@ uint32 Bot::GetClassHPFactor() { int32 Bot::CalcMaxHP() { int32 bot_hp = 0; uint32 nd = 10000; - - bot_hp += GenerateBaseHitPoints() + itembonuses.HP; - - nd += aabonuses.MaxHP; //Natural Durability, Physical Enhancement, Planar Durability - bot_hp = (float)bot_hp * (float)nd / (float)10000; //this is to fix the HP-above-495k issue - bot_hp += spellbonuses.HP + aabonuses.HP; - + bot_hp += (GenerateBaseHitPoints() + itembonuses.HP); + nd += aabonuses.MaxHP; + bot_hp = ((float)bot_hp * (float)nd / (float)10000); + bot_hp += (spellbonuses.HP + aabonuses.HP); bot_hp += GroupLeadershipAAHealthEnhancement(); - - bot_hp += bot_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f); + bot_hp += (bot_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f)); max_hp = bot_hp; - if (cur_hp > max_hp) cur_hp = max_hp; int hp_perc_cap = spellbonuses.HPPercCap[0]; if(hp_perc_cap) { - int curHP_cap = (max_hp * hp_perc_cap) / 100; + int curHP_cap = ((max_hp * hp_perc_cap) / 100); if (cur_hp > curHP_cap || (spellbonuses.HPPercCap[1] && cur_hp > spellbonuses.HPPercCap[1])) cur_hp = curHP_cap; } - return max_hp; } -int32 Bot::CalcMaxEndurance() -{ - max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance; - - if (max_end < 0) { +int32 Bot::CalcMaxEndurance() { + max_end = (CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance); + if (max_end < 0) max_end = 0; - } - if (cur_end > max_end) { + if (cur_end > max_end) cur_end = max_end; - } int end_perc_cap = spellbonuses.EndPercCap[0]; if(end_perc_cap) { - int curEnd_cap = (max_end * end_perc_cap) / 100; + int curEnd_cap = ((max_end * end_perc_cap) / 100); if (cur_end > curEnd_cap || (spellbonuses.EndPercCap[1] && cur_end > spellbonuses.EndPercCap[1])) cur_end = curEnd_cap; } @@ -10246,49 +8481,37 @@ int32 Bot::CalcMaxEndurance() return max_end; } -int32 Bot::CalcBaseEndurance() -{ +int32 Bot::CalcBaseEndurance() { int32 base_end = 0; int32 base_endurance = 0; int32 ConvertedStats = 0; int32 sta_end = 0; int Stats = 0; - if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { int HeroicStats = 0; - Stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4); HeroicStats = ((GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4); - if (Stats > 100) { ConvertedStats = (((Stats - 100) * 5 / 2) + 100); - if (Stats > 201) { + if (Stats > 201) ConvertedStats -= ((Stats - 201) * 5 / 4); - } - } - else { + } else ConvertedStats = Stats; - } if (GetLevel() < 41) { sta_end = (GetLevel() * 75 * ConvertedStats / 1000); base_endurance = (GetLevel() * 15); - } - else if (GetLevel() < 81) { + } else if (GetLevel() < 81) { sta_end = ((3 * ConvertedStats) + ((GetLevel() - 40) * 15 * ConvertedStats / 100)); base_endurance = (600 + ((GetLevel() - 40) * 30)); - } - else { + } else { sta_end = (9 * ConvertedStats); base_endurance = (1800 + ((GetLevel() - 80) * 18)); } base_end = (base_endurance + sta_end + (HeroicStats * 10)); - } - else - { - Stats = GetSTR()+GetSTA()+GetDEX()+GetAGI(); - int LevelBase = GetLevel() * 15; - + } else { + Stats = (GetSTR()+GetSTA()+GetDEX()+GetAGI()); + int LevelBase = (GetLevel() * 15); int at_most_800 = Stats; if(at_most_800 > 800) at_most_800 = 800; @@ -10297,57 +8520,45 @@ int32 Bot::CalcBaseEndurance() int HalfBonus400to800 = 0; int Bonus800plus = 0; int HalfBonus800plus = 0; - - int BonusUpto800 = int( at_most_800 / 4 ) ; + int BonusUpto800 = int(at_most_800 / 4) ; if(Stats > 400) { - Bonus400to800 = int( (at_most_800 - 400) / 4 ); - HalfBonus400to800 = int( std::max( ( at_most_800 - 400 ), 0 ) / 8 ); - + Bonus400to800 = int((at_most_800 - 400) / 4); + HalfBonus400to800 = int(std::max((at_most_800 - 400), 0) / 8); if(Stats > 800) { - Bonus800plus = int( (Stats - 800) / 8 ) * 2; - HalfBonus800plus = int( (Stats - 800) / 16 ); + Bonus800plus = (int((Stats - 800) / 8) * 2); + HalfBonus800plus = int((Stats - 800) / 16); } } - int bonus_sum = BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus; - + int bonus_sum = (BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus); base_end = LevelBase; - - //take all of the sums from above, then multiply by level*0.075 - base_end += ( bonus_sum * 3 * GetLevel() ) / 40; + base_end += ((bonus_sum * 3 * GetLevel()) / 40); } return base_end; } int32 Bot::CalcEnduranceRegen() { - int32 regen = int32(GetLevel() * 4 / 10) + 2; - regen += spellbonuses.EnduranceRegen + itembonuses.EnduranceRegen; - + int32 regen = (int32(GetLevel() * 4 / 10) + 2); + regen += (spellbonuses.EnduranceRegen + itembonuses.EnduranceRegen); return (regen * RuleI(Character, EnduranceRegenMultiplier) / 100); } int32 Bot::CalcEnduranceRegenCap() { - int cap = (RuleI(Character, ItemEnduranceRegenCap) + itembonuses.HeroicSTR/25 + itembonuses.HeroicDEX/25 + itembonuses.HeroicAGI/25 + itembonuses.HeroicSTA/25); - + int cap = (RuleI(Character, ItemEnduranceRegenCap) + itembonuses.HeroicSTR / 25 + itembonuses.HeroicDEX / 25 + itembonuses.HeroicAGI / 25 + itembonuses.HeroicSTA / 25); return (cap * RuleI(Character, EnduranceRegenMultiplier) / 100); } -void Bot::SetEndurance(int32 newEnd) -{ - /*Endurance can't be less than 0 or greater than max*/ +void Bot::SetEndurance(int32 newEnd) { if(newEnd < 0) newEnd = 0; - else if(newEnd > GetMaxEndurance()){ + else if(newEnd > GetMaxEndurance()) newEnd = GetMaxEndurance(); - } cur_end = newEnd; } void Bot::DoEnduranceUpkeep() { int upkeep_sum = 0; - - int cost_redux = spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction; - + int cost_redux = (spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction); uint32 buffs_i; uint32 buff_count = GetMaxTotalSlots(); for (buffs_i = 0; buffs_i < buff_count; buffs_i++) { @@ -10356,15 +8567,15 @@ void Bot::DoEnduranceUpkeep() { if(upkeep > 0) { if(cost_redux > 0) { if(upkeep <= cost_redux) - continue; //reduced to 0 + continue; + upkeep -= cost_redux; } - if((upkeep+upkeep_sum) > GetEndurance()) { - //they do not have enough to keep this one going. + + if((upkeep+upkeep_sum) > GetEndurance()) BuffFadeBySlot(buffs_i); - } else { + else upkeep_sum += upkeep; - } } } } @@ -10376,13 +8587,11 @@ void Bot::DoEnduranceUpkeep() { void Bot::Camp(bool databaseSave) { Sit(); - if(IsGrouped()) { + if(IsGrouped()) RemoveBotFromGroup(this, GetGroup()); - } - if(GetInHealRotation()) { + if(GetInHealRotation()) GetHealRotationLeader()->RemoveHealRotationMember(this); - } if(databaseSave) Save(); @@ -10391,9 +8600,8 @@ void Bot::Camp(bool databaseSave) { } void Bot::Zone() { - if(HasGroup()) { + if(HasGroup()) GetGroup()->MemberZoned(this); - } Save(); Depop(); @@ -10401,38 +8609,26 @@ void Bot::Zone() { bool Bot::IsArcheryRange(Mob *target) { bool result = false; - if(target) { - float range = GetBotArcheryRange() + 5.0; //Fudge it a little, client will let you hit something at 0 0 0 when you are at 205 0 0 - + float range = (GetBotArcheryRange() + 5.0); range *= range; - float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition()); - - float minRuleDistance = RuleI(Combat, MinRangedAttackDist) * RuleI(Combat, MinRangedAttackDist); - + float minRuleDistance = (RuleI(Combat, MinRangedAttackDist) * RuleI(Combat, MinRangedAttackDist)); if((targetDistance > range) || (targetDistance < minRuleDistance)) result = false; else result = true; } - return result; } bool Bot::IsBotCasterCombatRange(Mob *target) { bool result = false; - if(target) { float range = BotAISpellRange; - range *= range; - - // half the max so the bot doesn't always stop at max range to allow combat movement range *= .5; - float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition()); - if(targetDistance > range) result = false; else @@ -10445,36 +8641,28 @@ bool Bot::IsBotCasterCombatRange(Mob *target) { bool Bot::IsGroupPrimaryHealer() { bool result = false; uint8 botclass = GetClass(); - if(HasGroup()) { Group *g = GetGroup(); - - switch(botclass) - { - case CLERIC: - { + switch(botclass) { + case CLERIC: { result = true; break; } - case DRUID: - { + case DRUID: { result = GroupHasClericClass(g) ? false : true; break; } - case SHAMAN: - { + case SHAMAN: { result = (GroupHasClericClass(g) || GroupHasDruidClass(g)) ? false : true; break; } case PALADIN: case RANGER: - case BEASTLORD: - { + case BEASTLORD: { result = GroupHasPriestClass(g) ? false : true; break; } - default: - { + default: { result = false; break; } @@ -10487,29 +8675,22 @@ bool Bot::IsGroupPrimaryHealer() { bool Bot::IsGroupPrimarySlower() { bool result = false; uint8 botclass = GetClass(); - if(HasGroup()) { Group *g = GetGroup(); - - switch(botclass) - { - case SHAMAN: - { + switch(botclass) { + case SHAMAN: { result = true; break; } - case ENCHANTER: - { + case ENCHANTER: { result = GroupHasShamanClass(g) ? false : true; break; } - case BEASTLORD: - { + case BEASTLORD: { result = (GroupHasShamanClass(g) || GroupHasEnchanterClass(g)) ? false : true; break; } - default: - { + default: { result = false; break; } @@ -10532,14 +8713,9 @@ bool Bot::CanHeal() { botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); - if(botSpell.SpellId != 0){ + if(botSpell.SpellId != 0) result = true; - } - - /*if(GetFirstBotSpellBySpellType(this, SpellType_Heal)){ - result = true; - }*/ - + return result; } @@ -10547,32 +8723,26 @@ bool Bot::CalculateNewPosition2(float x, float y, float z, float speed, bool che return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ); } -// Orders all bots in the specified group to follow their group leader. 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 { + } else { botGroupMember->SetFollowID(groupLeader->GetID()); botGroupMember->BotGroupSay(botGroupMember, "Following %s.", groupLeader->GetCleanName()); } botGroupMember->WipeHateList(); - - if(botGroupMember->HasPet() && botGroupMember->GetPet()) { + if(botGroupMember->HasPet() && botGroupMember->GetPet()) botGroupMember->GetPet()->WipeHateList(); - } } } } @@ -10580,42 +8750,33 @@ void Bot::BotGroupOrderFollow(Group* group, Client* client) { } } -// Orders all bots in the specified group to guard their current location. 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()) { + if(botGroupMember->HasPet() && botGroupMember->GetPet()) botGroupMember->GetPet()->WipeHateList(); - } } } } } } -// Orders all bots in the specified group to attack their group leader's target. 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); @@ -10627,18 +8788,15 @@ void Bot::BotGroupOrderAttack(Group* group, Mob* target, Client* client) { } } -// Summons all bot group members to ther owners location. 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(); @@ -10650,13 +8808,10 @@ void Bot::BotGroupSummon(Group* group, Client* client) { } } -// Finds a bot in the entitity list by bot owner character id and the bot first name Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { Bot* Result = 0; - if(c) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - if(!BotList.empty()) { for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { if(std::string((*botListItr)->GetCleanName()) == botName) { @@ -10666,11 +8821,9 @@ Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { } } } - return Result; } -// Processes a group invite from a Client for a Bot character. void Bot::ProcessBotGroupInvite(Client* c, std::string botName) { if(c) { Bot* invitedBot = GetBotByBotClientOwnerAndBotName(c, botName); @@ -10685,16 +8838,11 @@ void Bot::ProcessBotGroupInvite(Client* c, std::string botName) { database.SetGroupID(c->GetName(), g->GetID(), c->CharacterID()); database.SetGroupID(invitedBot->GetCleanName(), g->GetID(), invitedBot->GetBotID()); } - } - else { + } else { AddBotToGroup(invitedBot, c->GetGroup()); database.SetGroupID(invitedBot->GetCleanName(), c->GetGroup()->GetID(), invitedBot->GetBotID()); } - - /*if(c->GetBotRaidID() > 0) - invitedBot->SetBotRaidID(c->GetBotRaidID());*/ } - // TODO: if there is a bot but the bot is already in a group, do we send an group invitation cancel message back to the client? } } @@ -11128,52 +9276,6 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, } } - // 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); @@ -11353,8 +9455,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "#bot groupmessages [on|off] [bot name|all] - Turns group messages on/off for named bot/all bots."); c->Message(0, "#bot defensive [bot name] - Causes warrior or knight bot to use defensive discipline / buff."); c->Message(0, "#bot healrotation help - Displays the commands available to manage BOT heal rotations."); - // TODO: - // c->Message(0, "#bot illusion - Enchanter Bot cast an illusion buff spell on you or your target."); c->Message(0, "#bot pull [] [target] - Bot Pulling Target NPC's"); c->Message(0, "#bot setinspectmessage - Copies your inspect message to a targeted bot that you own"); c->Message(0, "#bot bardoutofcombat [on|off] - Determines wheter bard bots use out of combat songs."); @@ -11470,7 +9570,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "giveitem")) { if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) { - // Its a bot targetted and this client is the bots owner Bot* targetedBot = c->GetTarget()->CastToBot(); if(targetedBot) targetedBot->FinishTrade(c, BotTradeClientNoDropNoTrade); @@ -11484,17 +9583,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "camp")) { if(!strcasecmp(sep->arg[2], "all")) { - // Camp out all bots owned by this bot owner BotOrderCampAll(c); - } - else { - // Camp only the targetted bot + } else { if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner()->CastToClient() == c)) { Bot* targetedBot = c->GetTarget()->CastToBot(); if(targetedBot) targetedBot->Camp(); - } - else + } else c->Message(15, "You must target a bot you own to do this."); } @@ -11505,16 +9600,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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)]"); 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")) { + } 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)]"); 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")) { + } 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)]"); return; - } - else if(strcasecmp(sep->arg[5],"male") && strcasecmp(sep->arg[5],"female")) { + } else if(strcasecmp(sep->arg[5],"male") && strcasecmp(sep->arg[5],"female")) { c->Message(0, "Usage: #bot create [name] [class(1-16)] [race(1-12,128,130,330,522)] [gender (male/female)]"); return; } @@ -11558,7 +9650,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Now that all validation is complete, we can save our newly created bot if(!NewBot->Save()) c->Message(0, "Unable to save %s as a bot.", NewBot->GetCleanName()); else @@ -11567,8 +9658,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else { // TODO: Log error message here } - - // Bot creation is complete return; } @@ -11615,7 +9704,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "list")) { bool listAll = true; int iClass = atoi(sep->arg[2]); - if(iClass > 0 && iClass < 17) listAll = false; @@ -11633,8 +9721,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 { + } else { c->Message(0, "You have no bots created. Use the #bot create command to create a bot."); } } @@ -11642,7 +9729,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; @@ -11652,21 +9738,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(tempBot && tempBot->GetBotOwner() == c) bot = tempBot; } - } - else { + } else { if(c->GetTarget() && c->GetTarget()->IsBot()) bot = c->GetTarget()->CastToBot(); } if(bot && !listAll) { - // Specific bot only 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 { - // List all + } 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; @@ -11675,12 +9756,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "Name: %s -- Class: %s -- Mana: %3.1f%%", tempBot->GetCleanName(), ClassIdToString(tempBot->GetClass()).c_str(), tempBot->GetManaRatio()); } } - } - else { + } else { c->Message(0, "You have no spawned bots in this zone."); } } - return; } @@ -11702,16 +9781,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - /*if(c->GetBotRaidID() > 0) { - BotRaids *br = entity_list.GetBotRaidByMob(c->CastToMob()); - if(br) { - if(br->GetBotRaidAggro()) { - c->Message(15, "You can't summon bots while you are engaged."); - return; - } - } - }*/ - if(c->IsGrouped()) { Group *g = entity_list.GetGroupByClient(c); for (int i=0; iSpawn(c, &TempErrorMessage); if(!TempErrorMessage.empty()) { @@ -11790,9 +9858,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } TempBot->BotGroupSay(TempBot, "I am ready for battle."); - } - else { - // We did not find a bot for the specified bot id from the database + } else { c->Message(0, "BotID: %i not found", atoi(sep->arg[2])); } @@ -11841,18 +9907,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else if(c->GetTarget()->IsMob() && !c->GetTarget()->IsPet()) { Mob *b = c->GetTarget(); - if(b) - { - // Is our target "botable" ? + if(b) { if(!b->IsBot()){ c->Message(15, "You must target a bot!"); - } - else if((b->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID())) - { + } else if((b->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID())) { b->CastToBot()->BotGroupSay(b->CastToBot(), "You can only summon your own bots."); - } - else - { + } else { b->SetTarget(c->CastToMob()); b->Warp(glm::vec3(c->GetPosition())); } @@ -11914,12 +9974,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(15, "Using %s in my %s (Item %i)", item_link.c_str(), equipped[i], (i == 22 ? 9999 : i)); } - } - else { + } else { c->Message(15, "You must group your bot first."); } - } - else { + } else { c->Message(15, "You must target a bot first."); } return; @@ -11960,16 +10018,14 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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())) { + if(itma) { + if(c->CheckLoreConflict(itma->GetItem())) failedLoreCheck = true; - } } } - if(c->CheckLoreConflict(itm)) { + + if(c->CheckLoreConflict(itm)) failedLoreCheck = true; - } } if(!failedLoreCheck) { if(itm) { @@ -12061,20 +10117,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(!strcasecmp(sep->arg[1], "update")) { - // Congdar: add IsEngaged check for exploit to keep bots alive by repeatedly using #bot 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()) - { + if(c->IsGrouped()) { Group *g = entity_list.GetGroupByClient(c); - for (int i=0; imembers[i] && g->members[i]->IsEngaged()) - { + for (int i=0; imembers[i] && g->members[i]->IsEngaged()) { c->Message(15, "You can't update bots while you are engaged."); return; } @@ -12083,20 +10135,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if((c->GetTarget()->CastToBot()->GetBotOwner() == c->CastToMob()) && !c->GetFeigned()) { Bot* bot = c->GetTarget()->CastToBot(); - //bot->SetLevel(c->GetLevel()); bot->SetPetChooser(false); bot->CalcBotStats(); - } - else { + } else { if(c->GetFeigned()) { c->Message(15, "You cannot update bots while feigned."); - } - else { + } else { c->Message(15, "You must target your bot first"); } } - } - else { + } else { c->Message(15, "You must target a bot first"); } @@ -12107,23 +10155,21 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "bindme")) { Mob *binder = nullptr; bool hasbinder = false; - if(c->IsGrouped()) - { + if(c->IsGrouped()) { Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC)) - { + 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) { + + 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); @@ -12135,48 +10181,40 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "runeme")) { Mob *runeer = nullptr; bool hasruneer = false; - if(c->IsGrouped()) - { + if(c->IsGrouped()) { Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) - { + 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) { + + 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)) { + } 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)) { + } 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)) { + } 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)) { + } 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)) { + } 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){ + } else if (c->GetLevel() >= 61){ runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune of Zebuxoruk..."); runeer->CastSpell(3343, c->GetID(), 1, -1, -1); } @@ -12188,10 +10226,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "track") && c->IsGrouped()) { Mob *Tracker; uint32 TrackerClass = 0; - Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case RANGER: @@ -12199,14 +10236,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { TrackerClass = RANGER; break; case DRUID: - // Unless we have a ranger, druid is next best. if(TrackerClass != RANGER) { Tracker = g->members[i]; TrackerClass = DRUID; } break; case BARD: - // If we haven't found a tracker yet, use bard. if(TrackerClass == 0) { Tracker = g->members[i]; TrackerClass = BARD; @@ -12219,42 +10254,34 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } int Level = (c->GetLevel()); - int RangeR = (Level*80); //Ranger - int RangeD = (Level*30); //Druid - int RangeB = (Level*20); //Bard + 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", c->GetName()); entity_list.ShowSpawnWindow(c, RangeR, false); - } - else if(!strcasecmp(sep->arg[2], "rare")) { + } else if(!strcasecmp(sep->arg[2], "rare")) { Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Selective tracking", c->GetName()); entity_list.ShowSpawnWindow(c, RangeR, true); - } - else if(!strcasecmp(sep->arg[2], "near")) { + } else if(!strcasecmp(sep->arg[2], "near")) { Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking mobs nearby", c->GetName()); entity_list.ShowSpawnWindow(c, RangeD, false); - } - else + } else Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "You want to [track all], [track near], or [track rare]?", c->GetName()); break; - case BARD: - if(TrackerClass != RANGER) Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up", c->GetName()); entity_list.ShowSpawnWindow(c, RangeB, false); break; - case DRUID: - if(TrackerClass = BARD) Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up", c->GetName()); entity_list.ShowSpawnWindow(c, RangeD, false); break; - default: c->Message(15, "You must have a Ranger, Druid, or Bard in your group."); break; @@ -12268,7 +10295,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 CurerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case CLERIC: @@ -12280,13 +10307,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Curer = g->members[i]; CurerClass = SHAMAN; } + break; case DRUID: if (CurerClass == 0){ Curer = g->members[i]; CurerClass = DRUID; } break; - break; default: break; } @@ -12297,81 +10324,61 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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)) { + } 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)) { + } 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)) { + } 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) + } 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 don't have the needed level yet", sep->arg[2]); - } - else + } else Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], [cure disease], [cure curse], or [cure blindness]?", c->GetName()); 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)) { + } 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")) { + } else if(!strcasecmp(sep->arg[2], "curse")) { Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); - } - else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 7)) { + } 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) + } 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 don't have the needed level yet", sep->arg[2]); - } - else + } else Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], [cure disease], or [cure blindness]?", c->GetName()); 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)) { + } 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 + } else if(!strcasecmp(sep->arg[2], "curse")) { // Fire level 1 Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); - } - else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 13)) { + } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 13)) { Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); - } - else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 4) + } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 4) || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 5)) { Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]) ; - } - else + } else Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], or [cure disease]?", c->GetName()); - break; - default: c->Message(15, "You must have a Cleric, Shaman, or Druid in your group."); break; @@ -12380,66 +10387,59 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } //Mez - if(!strcasecmp(sep->arg[1], "ai") && !strcasecmp(sep->arg[2], "mez")) - { + if(!strcasecmp(sep->arg[1], "ai") && !strcasecmp(sep->arg[2], "mez")) { Mob *target = c->GetTarget(); - if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) - { + 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()) - { + if(c->IsGrouped()) { bool hasmezzer = false; Group *g = c->GetGroup(); - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) - { + 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 mez %s \n", target->GetCleanName()); + mezzer->CastToBot()->BotGroupSay(mezzer->CastToBot(), "Trying to mesmerize %s.", target->GetCleanName()); mezzer->CastToBot()->MesmerizeTarget(target); } } - if(!hasmezzer) { + + 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()) - { + if(c->IsGrouped()) { bool hascaster = false; Group *g = c->GetGroup(); - for(int i=0; imembers[i] && g->members[i]->IsBot()) { uint8 casterlevel = g->members[i]->GetLevel(); switch(g->members[i]->GetClass()) { case ENCHANTER: - if(casterlevel >= 15) { + if(casterlevel >= 15) hascaster = true; - } + break; case WIZARD: - if(casterlevel >= 14) { + if(casterlevel >= 14) hascaster = true; - } + break; case NECROMANCER: - if(casterlevel >= 17) { + if(casterlevel >= 17) hascaster = true; - } + break; case MAGICIAN: - if(casterlevel >= 13) { + if(casterlevel >= 13) hascaster = true; - } + break; default: break; @@ -12451,169 +10451,127 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } } - if(!hascaster) { + + if(!hascaster) c->Message(15, "You don't see anyone in your group that can cast Identify."); - } - } - else { + } else c->Message(15, "You don't see anyone in your group that can cast Identify."); - } + return; } //Resurrect - if(!strcasecmp(sep->arg[1], "resurrectme")) - { + if(!strcasecmp(sep->arg[1], "resurrectme")) { Mob *target = c->GetTarget(); - if(target == nullptr || !target->IsCorpse()) - { - c->Message(15, "You must select a corpse"); + if(target == nullptr || !target->IsCorpse()) { + c->Message(15, "You must select a corpse!"); return; } - if(c->IsGrouped()) - { + if(c->IsGrouped()) { bool hasrezzer = false; Group *g = c->GetGroup(); - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC)) - { + 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 rez %s", target->GetCleanName()); + 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."); - } + + 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], "magepet")) - { - if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->GetClass() == MAGICIAN)) - { - if(c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) - { + if(!strcasecmp(sep->arg[1], "magepet")) { + 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) - { + if(botlevel == 1) { c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have any pets yet."); return; } - if(!strcasecmp(sep->arg[2], "water")) - { + + if(!strcasecmp(sep->arg[2], "water")) { c->GetTarget()->CastToBot()->SetPetChooserID(0); - } - else if(!strcasecmp(sep->arg[2], "fire")) - { - if(botlevel < 3) - { + } 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 - { + } else c->GetTarget()->CastToBot()->SetPetChooserID(1); - } - } - else if(!strcasecmp(sep->arg[2], "air")) - { - if(botlevel < 4) - { + } 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 - { + } else c->GetTarget()->CastToBot()->SetPetChooserID(2); - } - } - else if(!strcasecmp(sep->arg[2], "earth")) - { - if(botlevel < 5) - { + } 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 - { + } else c->GetTarget()->CastToBot()->SetPetChooserID(3); - } - } - else if(!strcasecmp(sep->arg[2], "monster")) - { - if(botlevel < 30) - { + } 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 - { + } else c->GetTarget()->CastToBot()->SetPetChooserID(4); - } } - if(c->GetTarget()->GetPet()) - { - // cast reclaim energy + + 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."); - } + } 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."); + 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; imembers[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"); + g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "You have to target a player with a corpse in the zone!"); return; - } - else { + } 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)) { + } 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)) { + } 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) { + } 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; @@ -12621,59 +10579,48 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } } - if (!hassummoner) { - c->Message(15, "You must have a Necromancer or Shadowknight in your group."); - } + + 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")) - { + 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"); + c->Message(15, "You must select a monster!"); else { if(c->IsGrouped()) { Group *g = c->GetGroup(); - - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) { Bot *pacer = g->members[i]->CastToBot(); - pacer->BotGroupSay(pacer, "Trying to pacify %s \n", target->GetCleanName()); - + 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)) - //if(pacer->IsPacified(target)) c->Message(0, "I have successfully pacified %s.", target->GetCleanName()); - return; - /*else - c->Message(0, "I failed to pacify %s.", target->GetCleanName());*/ - } - else + + 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 \n", target->GetCleanName()); + 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)) - //if(pacer->IsPacified(target)) c->Message(0, "I have successfully pacified %s.", target->GetCleanName()); - return; - /*else - c->Message(0, "I failed to pacify %s.", target->GetCleanName());*/ - } - else + + return; + } else c->Message(0, "I failed to pacify %s.", target->GetCleanName()); } - /*else - c->Message(15, "You must have an Enchanter or Cleric in your group.");*/ } } } @@ -12682,20 +10629,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } //Charm - if(!strcasecmp(sep->arg[1], "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"); + 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; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case ENCHANTER: @@ -12707,13 +10653,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Charmer = g->members[i]; CharmerClass = NECROMANCER; } + break; case DRUID: if (CharmerClass == 0){ Charmer = g->members[i]; CharmerClass = DRUID; } break; - break; default: break; } @@ -12722,42 +10668,33 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(CharmerClass) { case ENCHANTER: if (c->GetLevel() >= 11) { - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (1,target); - } - else if (c->GetLevel() <= 10){ - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); - } - else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob level is too high or can't be charmed", c->GetName()); + } else if (c->GetLevel() <= 10){ + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob level is too high or can't be charmed.", c->GetName()); break; - case NECROMANCER: if ((c->GetLevel() >= 18) && (DBtype == 3)) { - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to Charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (2,target); - } - else if (c->GetLevel() <= 17){ - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); - } - else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob Is not undead...", c->GetName()); + } else if (c->GetLevel() <= 17){ + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not undead.", c->GetName()); break; - case DRUID: if ((c->GetLevel() >= 13) && (DBtype == 21)) { - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (3,target); - } - else if (c->GetLevel() <= 12){ - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); - } - else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not an animal...", c->GetName()); + } else if (c->GetLevel() <= 12){ + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not an animal.", c->GetName()); break; - default: - c->Message(15, "You must have an Enchanter, Necromancer or Druid in your group."); + c->Message(15, "You must have an Enchanter, Necromancer, or Druid in your group."); break; } } @@ -12771,35 +10708,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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()) - { + } else { + if(c->GetTarget()->GetPet()) { c->GetTarget()->GetPet()->Say_StringID(PET_GETLOST_STRING); - // c->GetTarget()->GetPet()->Kill(); 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 { + } else c->Message(15, "You must target your Enchanter, Necromancer, or Druid bot."); - } - } - else { + } 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")) - { + 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())) - { + if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { c->Message(15, "You must select a monster"); return; } @@ -12808,7 +10737,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 DirerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case ENCHANTER: @@ -12820,13 +10749,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Direr = g->members[i]; DirerClass = NECROMANCER; } + break; case DRUID: if (DirerClass == 0){ Direr = g->members[i]; DirerClass = DRUID; } break; - break; default: break; } @@ -12835,42 +10764,33 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(DirerClass) { case ENCHANTER: if (c->GetLevel() >= 55) { - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (1,target); - } - else if (c->GetLevel() <= 55){ - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the needed level yet", sep->arg[2]); - } - else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob level is too high or can't be charmed", c->GetName()); + } else if (c->GetLevel() <= 55){ + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob level is too high or can't be charmed.", c->GetName()); break; - case NECROMANCER: if ((c->GetLevel() >= 55) && (DBtype == 3)) { - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (2,target); - } - else if (c->GetLevel() <= 55){ - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the needed level yet", sep->arg[2]); - } - else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob Is not undead...", c->GetName()); + } else if (c->GetLevel() <= 55){ + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not undead.", c->GetName()); break; - case DRUID: if ((c->GetLevel() >= 55) && (DBtype == 21)) { - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (3,target); - } - else if (c->GetLevel() <= 55){ - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the needed level yet", sep->arg[2]); - } - else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not an animal...", c->GetName()); + } else if (c->GetLevel() <= 55){ + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not an animal.", c->GetName()); break; - default: - c->Message(15, "You must have an Enchanter, Necromancer or Druid in your group."); + c->Message(15, "You must have an Enchanter, Necromancer, or Druid in your group."); break; } } @@ -12880,31 +10800,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "evac")) { Mob *evac = nullptr; bool hasevac = false; - if(c->IsGrouped()) - { + if(c->IsGrouped()) { Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == DRUID)) - || (g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == WIZARD))) - { + 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) { + + 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 Evac you %s.", c->GetName()); + 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)) { + } else if((hasevac) && (c->GetLevel() <= 17)) evac->CastToBot()->BotGroupSay(evac->CastToBot(), "I'm not level 18 yet.", c->GetName()); - } + return; } @@ -12914,7 +10830,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 SowerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case DRUID: @@ -12946,92 +10862,69 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(SowerClass) { case DRUID: - if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() >= 10) ) { + if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() >= 10)) { Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting sow..."); Sower->CastSpell(278, c->GetID(), 1, -1, -1); } - else if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() <= 10) ) { + 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 wolf..."); Sower->CastSpell(428, c->GetID(), 1, -1, -1); } - else if ((!strcasecmp(sep->arg[2], "wolf")) && (c->GetLevel() <= 20)) { + 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)) { + 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)) { + 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 [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); - } - else if (!zone->CanCastOutdoor()) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); - } - else if (zone->CanCastOutdoor()) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Do you want [sow regular] or [sow wolf]?", c->GetName()); - } - else if (!zone->CanCastOutdoor()) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); - } + 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 [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); + else if (!zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); + else if (zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Do you want [sow regular] or [sow wolf]?"); + else if (!zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); break; - case SHAMAN: - if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 9)) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting SoW..."); + 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", c->GetName()); - } - else if (c->GetLevel() <= 9) { + 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 SoW..."); + 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", c->GetName()); - } - else if (c->GetLevel() <= 28) { + 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 SoW..."); + 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", c->GetName()); - } - else if (c->GetLevel() <= 24) { + 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; @@ -13045,12 +10938,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case SHAMAN: @@ -13070,27 +10962,21 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(ShrinkerClass) { case SHAMAN: - if (c->GetLevel() >= 15) { - Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink..."); + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink."); Shrinker->CastToBot()->SpellOnTarget(345, target); } - else if (c->GetLevel() <= 14) { + 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()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink."); Shrinker->CastToBot()->SpellOnTarget(345, target); } - else if (c->GetLevel() <= 22) { + 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; @@ -13104,7 +10990,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 GaterClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case DRUID: @@ -13125,106 +11011,81 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(GaterClass) { case DRUID: if ((!strcasecmp(sep->arg[2], "karana")) && (c->GetLevel() >= 25) ) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Karana..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Karana."); Gater->CastSpell(550, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Commons..."); + } else if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Commons."); Gater->CastSpell(551, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Toxxulia..."); + } else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Toxxulia."); Gater->CastSpell(552, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "butcher")) && (c->GetLevel() >= 25)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Butcherblock..."); + } else if ((!strcasecmp(sep->arg[2], "butcher")) && (c->GetLevel() >= 25)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Butcherblock."); Gater->CastSpell(553, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "lava")) && (c->GetLevel() >= 30)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Lavastorm..."); + } else if ((!strcasecmp(sep->arg[2], "lava")) && (c->GetLevel() >= 30)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Lavastorm."); Gater->CastSpell(554, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 32)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Ro..."); + } else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 32)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Ro."); Gater->CastSpell(555, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "feerrott")) && (c->GetLevel() >= 32)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of feerrott..."); + } else if ((!strcasecmp(sep->arg[2], "feerrott")) && (c->GetLevel() >= 32)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Feerrott."); Gater->CastSpell(556, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "steamfont")) && (c->GetLevel() >= 31)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Steamfont..."); + } else if ((!strcasecmp(sep->arg[2], "steamfont")) && (c->GetLevel() >= 31)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Steamfont."); Gater->CastSpell(557, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "misty")) && (c->GetLevel() >= 36)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Misty..."); + } else if ((!strcasecmp(sep->arg[2], "misty")) && (c->GetLevel() >= 36)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Misty."); Gater->CastSpell(558, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 40)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Wakening Lands..."); + } else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 40)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Wakening Lands."); Gater->CastSpell(1398, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 32)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Iceclad Ocean..."); + } else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 32)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Iceclad Ocean."); Gater->CastSpell(1434, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Great Divide..."); + } else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Great Divide."); Gater->CastSpell(1438, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 42)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Cobalt Scar..."); + } else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 42)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Cobalt Scar."); Gater->CastSpell(1440, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 33)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Combines..."); + } else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 33)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Combines."); Gater->CastSpell(1517, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "surefall")) && (c->GetLevel() >= 26)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Surefall Glade..."); + } else if ((!strcasecmp(sep->arg[2], "surefall")) && (c->GetLevel() >= 26)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Surefall Glade."); Gater->CastSpell(2020, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Grimling Forest..."); + } else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Grimling Forest."); Gater->CastSpell(2419, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 33)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Twilight..."); + } else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 33)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Twilight."); Gater->CastSpell(2424, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 37)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Dawnshroud..."); + } else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 37)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Dawnshroud."); Gater->CastSpell(2429, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 26)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Nexus..."); + } else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 26)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Nexus."); Gater->CastSpell(2432, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 38)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Knowledge..."); + } else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 38)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Knowledge."); Gater->CastSpell(3184, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 28)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Stonebrunt Mountains..."); + } else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 28)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Stonebrunt Mountains."); Gater->CastSpell(3792, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Bloodfields..."); + } else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Bloodfields."); Gater->CastSpell(6184, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 39)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the South..."); + } else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 39)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the South."); Gater->CastSpell(1737, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 44)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the North..."); + } else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 44)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the North."); Gater->CastSpell(1736, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "slaughter")) && (c->GetLevel() >= 64)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Slaughter..."); + } else if ((!strcasecmp(sep->arg[2], "slaughter")) && (c->GetLevel() >= 64)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Slaughter."); Gater->CastSpell(6179, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "karana") + } else if ((!strcasecmp(sep->arg[2], "karana") || !strcasecmp(sep->arg[2], "tox") || !strcasecmp(sep->arg[2], "butcher") && (c->GetLevel() <= 25)) || !strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 27) @@ -13249,112 +11110,84 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "emerald") && (c->GetLevel() <= 38) || !strcasecmp(sep->arg[2], "skyfire") && (c->GetLevel() <= 43) || !strcasecmp(sep->arg[2], "wos") && (c->GetLevel() <= 64)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet", sep->arg[2]); - } - else { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [karana],[commons],[tox],[butcher],[lava],[ro],[feerrott],[steamfont],[misty],[wakening],[iceclad],[divide],[cobalt],[combines],[surefall],[grimling],[twilight],[dawnshroud],[nexus],[pok],[stonebrunt],[bloodfields],[emerald],[skyfire] or [wos].", c->GetName()); - } + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet."); + } else + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [karana], [commons], [tox], [butcher], [lava], [ro], [feerrott], [steamfont], [misty], [wakening], [iceclad], [divide], [cobalt], [combines], [surefall], [grimling], [twilight], [dawnshroud], [nexus], [pok], [stonebrunt], [bloodfields], [emerald], [skyfire] or [wos]."); break; - case WIZARD: - if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 35) ) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Common Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Common Portal."); Gater->CastSpell(566, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "fay")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal..."); + } else if ((!strcasecmp(sep->arg[2], "fay")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal."); Gater->CastSpell(563, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 37)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Ro Portal..."); + } else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 37)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Ro Portal."); Gater->CastSpell(567, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Toxxula Portal..."); + } else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Toxxulia Portal."); Gater->CastSpell(561, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "nk")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting North Karana Portal..."); + } else if ((!strcasecmp(sep->arg[2], "nk")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting North Karana Portal."); Gater->CastSpell(562, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "nek")) && (c->GetLevel() >= 32)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nektulos Portal..."); + } else if ((!strcasecmp(sep->arg[2], "nek")) && (c->GetLevel() >= 32)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nektulos Portal."); Gater->CastSpell(564, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 43)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wakening Lands Portal..."); + } else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 43)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wakening Lands Portal."); Gater->CastSpell(1399, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 33)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Iceclad Ocean Portal..."); + } else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 33)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Iceclad Ocean Portal."); Gater->CastSpell(1418, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Great Divide Portal..."); + } else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Great Divide Portal."); Gater->CastSpell(1423, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 43)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Cobalt Scar Portal..."); + } else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 43)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Cobalt Scar Portal."); Gater->CastSpell(1425, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 34)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Combines Portal..."); + } else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 34)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Combines Portal."); Gater->CastSpell(1516, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wk")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting West Karana Portal..."); + } else if ((!strcasecmp(sep->arg[2], "wk")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting West Karana Portal."); Gater->CastSpell(568, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Twilight Portal..."); + } else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Twilight Portal."); Gater->CastSpell(2425, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Dawnshroud Portal..."); + } else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Dawnshroud Portal."); Gater->CastSpell(2430, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 29)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nexus Portal..."); + } else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 29)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nexus Portal."); Gater->CastSpell(2944, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Plane of Knowledge Portal..."); + } else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Plane of Knowledge Portal."); Gater->CastSpell(3180, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wos")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wall of Slaughter Portal..."); + } else if ((!strcasecmp(sep->arg[2], "wos")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wall of Slaughter Portal."); Gater->CastSpell(6178, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal..."); + } else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal."); Gater->CastSpell(2420, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 37)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Emerald Jungle..."); + } else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 37)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Emerald Jungle."); Gater->CastSpell(1739, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "hateplane")) && (c->GetLevel() >= 39)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Hate Plane..."); + } else if ((!strcasecmp(sep->arg[2], "hateplane")) && (c->GetLevel() >= 39)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Hate Plane."); Gater->CastSpell(666, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "airplane")) && (c->GetLevel() >= 39)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to airplane..."); + } else if ((!strcasecmp(sep->arg[2], "airplane")) && (c->GetLevel() >= 39)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Airplane."); Gater->CastSpell(674, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 36)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Skyfire..."); + } else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 36)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Skyfire."); Gater->CastSpell(1738, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Bloodfields Portal..."); + } else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Bloodfields Portal."); Gater->CastSpell(6183, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Stonebrunt Portal..."); + } else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Stonebrunt Portal."); Gater->CastSpell(3793, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 35)) + } else if ((!strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 35)) || !strcasecmp(sep->arg[2], "fay") && (c->GetLevel() <= 27) || (!strcasecmp(sep->arg[2], "ro") && (c->GetLevel() <= 37)) || !strcasecmp(sep->arg[2], "tox") && (c->GetLevel() <= 25) @@ -13378,11 +11211,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "emerald") && (c->GetLevel() <= 36) || !strcasecmp(sep->arg[2], "skyfire") && (c->GetLevel() <= 36) || !strcasecmp(sep->arg[2], "wos") && (c->GetLevel() <= 64)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet", sep->arg[2]); - } - else { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [commons],[fay],[ro],[tox],[nk],[wakening],[iceclad],[divide],[cobalt],[combines],[wk],[grimling],[twilight],[dawnshroud],[nexus],[pok],[stonebrunt],[bloodfields],[emerald],[skyfire],[hateplane],[airplane] or [wos].", c->GetName()); - } + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet."); + } else + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [commons], [fay], [ro], [tox], [nk], [wakening], [iceclad], [divide], [cobalt], [combines], [wk], [grimling], [twilight], [dawnshroud], [nexus], [pok], [stonebrunt], [bloodfields], [emerald], [skyfire], [hateplane], [airplane] or [wos].", c->GetName()); break; default: c->Message(15, "You must have a Druid or Wizard in your group."); @@ -13397,7 +11228,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 EndurerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case DRUID: @@ -13435,48 +11266,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(EndurerClass) { case DRUID: - if (c->GetLevel() < 6) { + 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->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); break; } break; case SHAMAN: - if (c->GetLevel() < 12) { + 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->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case RANGER: - if (c->GetLevel() < 20) { + 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->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case ENCHANTER: - if (c->GetLevel() < 12) { + 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->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case BEASTLORD: - if (c->GetLevel() < 25) { + 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->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; @@ -13493,7 +11319,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 InviserClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case ENCHANTER: @@ -13532,137 +11358,111 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(InviserClass) { case ENCHANTER: - if ((c->GetLevel() <= 14) && (!strcasecmp(sep->arg[2], "undead"))) { + 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 invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead."); Inviser->CastSpell(235, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) { + 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->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invisibilty."); Inviser->CastSpell(42, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 6) && (!strcasecmp(sep->arg[2], "see"))) { + 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 invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible."); 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 [invis undead], [invis live] or [invis see] ?", c->GetName()); - } + 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 [invis undead], [invis live] or [invis see]?"); break; case MAGICIAN: - if (!strcasecmp(sep->arg[2], "undead")) { + 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"))) { + 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->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invisibilty."); Inviser->CastSpell(42, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "see"))) { + 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 invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible."); 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 [invis live] or [invis see] ?", c->GetName()); - } + 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 [invis live] or [invis see]?"); break; case WIZARD: - if ((c->GetLevel() <= 39) && (!strcasecmp(sep->arg[2], "undead"))) { + 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 invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead."); Inviser->CastSpell(235, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "live"))) { + 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->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invisibilty."); Inviser->CastSpell(42, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "see"))) { + 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 invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible."); 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 [invis undead], [invis live] or [invis see] ?", c->GetName()); - } + 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 [invis undead], [invis live] or [invis see]?"); break; case NECROMANCER: if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis 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 [invis undead]", c->GetName()); - } + 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 [invis undead]"); 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"))) { + 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->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())) { + } 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"))) { + 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 invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible."); 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 [invis live] or [invis see] ?", c->GetName()); - } + 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 [invis live] or [invis see]?"); break; default: c->Message(15, "You must have a Enchanter, Magician, Wizard, Druid, or Necromancer in your group."); @@ -13677,7 +11477,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 LeverClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case DRUID: @@ -13709,62 +11509,46 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(LeverClass) { case DRUID: - if (c->GetLevel() <= 14) { + 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->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", c->GetName()); - } + 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->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", c->GetName()); - } - else if (c->GetLevel() <= 10) { + 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..."); + 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", c->GetName()); - } - else if (c->GetLevel() <= 22) { + 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->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", c->GetName()); - } - else if (c->GetLevel() <= 15) { + 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; @@ -13778,7 +11562,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 ResisterClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case CLERIC: @@ -13790,13 +11574,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Resister = g->members[i]; ResisterClass = SHAMAN; } + break; case DRUID: if (ResisterClass == 0){ Resister = g->members[i]; ResisterClass = DRUID; } break; - break; default: break; } @@ -13804,104 +11588,81 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(ResisterClass) { case CLERIC: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 6)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection...", sep->arg[2]); + 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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) + } 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 don't have the needed level yet", sep->arg[2]); - } - else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the required level yet."); + } else + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); break; - case SHAMAN: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 20)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection...", sep->arg[2]); + 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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) + } 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 don't have the needed level yet", sep->arg[2]); - } - else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the needed level yet."); + } else + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); break; - case DRUID: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 19)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection...", sep->arg[2]); + 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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...", sep->arg[2]); + } 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) + } 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 don't have the needed level yet", sep->arg[2]) ; - } - else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); - + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the required level yet.") ; + } else + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); break; - default: c->Message(15, "You must have a Cleric, Shaman, or Druid in your group."); break; @@ -13909,52 +11670,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } - // debug commands - if(!strcasecmp(sep->arg[1], "debug") && !strcasecmp(sep->arg[2], "inventory")) { - Mob *target = c->GetTarget(); - - if(target && target->IsBot()) { - for(int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) { - c->Message(15,"Equiped slot: %i , item: %i \n", i, target->CastToBot()->GetEquipment(i)); - } - if(target->CastToBot()->GetEquipment(MaterialSecondary) > 0) - c->Message(15,"This bot has an item in off-hand."); - } - return; - } - - if(!strcasecmp(sep->arg[1], "debug") && !strcasecmp(sep->arg[2], "botcaracs")) - { - Mob *target = c->GetTarget(); - if(target && target->IsBot()) - { - if(target->CanThisClassDualWield()) - c->Message(15, "This class can dual wield."); - if(target->CanThisClassDoubleAttack()) - c->Message(15, "This class can double attack."); - } - if(target->GetPetID()) - c->Message(15, "I've a pet and its name is %s", target->GetPet()->GetCleanName() ); - return; - } - - if(!strcasecmp(sep->arg[1], "debug") && !strcasecmp(sep->arg[2], "spells")) - { - Mob *target = c->GetTarget(); - if(target && target->IsBot()) - { - for(int i=0; iCastToBot()->AIspells.size(); i++) - { - if(target->CastToBot()->BotGetSpells(i) != 0) - { - SPDat_Spell_Struct botspell = spells[target->CastToBot()->BotGetSpells(i)]; - c->Message(15, "(DEBUG) %s , Slot(%i), Spell (%s) Priority (%i) \n", target->GetCleanName(), i, botspell.name, target->CastToBot()->BotGetSpellPriority(i)); - } - } - } - return; - } - // #bot group ... if(!strcasecmp(sep->arg[1], "group") && !strcasecmp(sep->arg[2], "help")) { c->Message(0, "#bot group help - will show this help."); @@ -13962,7 +11677,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "#bot group follow "); c->Message(0, "#bot group guard "); c->Message(0, "#bot group attack "); - return; } @@ -13970,23 +11684,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[2], "follow")) { if(c->IsGrouped()) BotGroupOrderFollow(c->GetGroup(), c); - } - else if(!strcasecmp(sep->arg[2], "guard")) { + } 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())) { + } 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")) { + } else if(!strcasecmp(sep->arg[2], "summon")) { if(c->IsGrouped()) BotGroupSummon(c->GetGroup(), c); } - return; } @@ -14013,10 +11722,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* targetMob = c->GetTarget(); std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -14027,8 +11734,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { botGroupLeader->BotGroupSay(botGroupLeader, "I am prepared to lead."); else botGroupLeader->BotGroupSay(botGroupLeader, "I cannot lead."); - } - else + } else c->Message(13, "You must target a spawned bot first."); return; @@ -14036,17 +11742,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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."); @@ -14057,13 +11759,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Bot* botGroupLeader = 0; - if(argCount == 4) { botGroupLeaderName = std::string(sep->arg[4]); - botGroupLeader = entity_list.GetBotByBotName(botGroupLeaderName); - } - else if(c->GetTarget() && c->GetTarget()->IsBot()) + } else if(c->GetTarget() && c->GetTarget()->IsBot()) botGroupLeader = c->GetTarget()->CastToBot(); if(!botGroupLeader) { @@ -14087,41 +11786,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupMember) { if(!botGroupMember->HasGroup()) { - // invite 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 { + } else botGroupMember->BotGroupSay(botGroupMember, "I can not join %s\'s group.", botGroupLeader->GetName()); - } - } - else { - // "I am already in a group." + } 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 { - // must target a bot message + } else c->Message(13, "You must target a spawned bot first."); - } - } - else { - // "My group is full." + } else botGroupLeader->BotGroupSay(botGroupMember, "I have no more openings in my group, %s.", c->GetName()); - } - } - else { - // "I am not a group leader." + } 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; } @@ -14130,9 +11815,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { std::string targetName = std::string(sep->arg[3]); Bot* botGroupMember = 0; - if(!targetName.empty()) { + if(!targetName.empty()) botGroupMember = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupMember = targetMob->CastToBot(); @@ -14141,16 +11825,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 + } else botGroupMember->BotGroupSay(botGroupMember, "I am not in a group."); - } - else + } else c->Message(13, "You must target a spawned bot first."); return; @@ -14160,10 +11841,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* targetMob = c->GetTarget(); std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -14172,21 +11851,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 { + } 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 + } else botGroupLeader->BotGroupSay(botGroupLeader, "I am not a group leader, %s.", c->GetName()); - } - else + } else c->Message(13, "You must target a spawned bot group leader first."); return; @@ -14197,9 +11871,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -14208,12 +11881,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(botGroupLeader->HasGroup()) { Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) BotGroupSummon(g, c); } - } - else if(c->HasGroup()) + } else if(c->HasGroup()) BotGroupSummon(c->GetGroup(), c); return; @@ -14223,10 +11894,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* targetMob = c->GetTarget(); std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -14235,12 +11904,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(botGroupLeader->HasGroup()) { Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) BotGroupOrderFollow(g, c); } - } - else if(c->HasGroup()) + } else if(c->HasGroup()) BotGroupOrderFollow(c->GetGroup(), c); return; @@ -14250,10 +11917,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* targetMob = c->GetTarget(); std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -14262,12 +11927,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(botGroupLeader->HasGroup()) { Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) BotGroupOrderGuard(g, c); } - } - else if(c->HasGroup()) + } else if(c->HasGroup()) BotGroupOrderGuard(c->GetGroup(), c); return; @@ -14278,95 +11941,73 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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()) { + 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()) + } else if(c->HasGroup()) BotGroupOrderAttack(c->GetGroup(), targetMob, c); - } - else + } else c->Message(13, "You must target a monster."); - } - else + } else c->Message(13, "You must target a monster."); - } - else + } 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) { + 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 { + } 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")) { - - // If client is grouped, check for aggro on each group member. Group *g = c->GetGroup(); if(g) { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - // Skip invalid group members. - if(!g->members[i]) { continue; } - - // Fail if current group member is client and has aggro - // OR has a popuplated hate list (assume bot). - if((g->members[i]->IsClient() && g->members[i]->CastToClient()->GetAggroCount()) - || g->members[i]->IsEngaged()) { + 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; } } - } - // Fail if ungrouped client has aggro. - else { + } else { if(c->GetAggroCount() > 0) { c->Message(0, "You can't spawn bots while you are engaged."); return; } } - // Parse botgroup name. std::string botGroupName = std::string(sep->arg[3]); if(botGroupName.empty()) { c->Message(13, "Invalid botgroup name supplied."); return; } - // Get botgroup id. uint32 botGroupID = CanLoadBotGroup(c->CharacterID(), botGroupName, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -14377,59 +12018,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Get list of bots in specified group. std::list botGroup = LoadBotGroup(botGroupName, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - // Count of client's currently spawned bots. int spawnedBots = SpawnedBotCount(c->CharacterID(), &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - // BotQuest rule value in database is True. if(RuleB(Bots, BotQuest)) { - // Max number of allowed spawned bots for client. const int allowedBotsBQ = AllowedBotSpawns(c->CharacterID(), &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - // Fail if no bots allowed for client. if(allowedBotsBQ == 0) { c->Message(0, "You can't spawn any bots."); return; } - // Fail if maximum number of spawned bots allowed for client met or exceeded - // OR will be when bot group is spawned. - if(spawnedBots >= allowedBotsBQ - || spawnedBots + (int)botGroup.size() > allowedBotsBQ) { - c->Message(0, "You can't spawn more than %i bot(s). [Rule:BQ]", allowedBotsBQ); + if(spawnedBots >= allowedBotsBQ || spawnedBots + (int)botGroup.size() > allowedBotsBQ) { + c->Message(0, "You can't spawn more than %i bot(s).", allowedBotsBQ); return; } } - // Fail if maximum number of spawned bots allowed for client met or exceeded - // OR will be when bot group is spawned. const int allowedBotsSBC = RuleI(Bots, SpawnBotCount); - if(spawnedBots >= allowedBotsSBC - || spawnedBots + (int)botGroup.size() > allowedBotsSBC) { - c->Message(0, "You can't spawn more than %i bots. [Rule:SBC]", allowedBotsSBC); + if(spawnedBots >= allowedBotsSBC || spawnedBots + (int)botGroup.size() > allowedBotsSBC) { + c->Message(0, "You can't spawn more than %i bots.", allowedBotsSBC); return; } - // Passed all checks. Spawn requested bot group. - - // Get botgroup's leader's id. uint32 botGroupLeaderBotID = GetBotGroupLeaderIdByBotGroupName(botGroupName); - - // Load botgroup's leader. Bot *botGroupLeader = LoadBot(botGroupLeaderBotID, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -14442,7 +12067,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Spawn botgroup's leader. botGroupLeader->Spawn(c, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -14450,11 +12074,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Create botgroup. 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"); @@ -14462,23 +12086,21 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } for(auto botGroupItr = botGroup.begin(); botGroupItr != botGroup.end(); ++botGroupItr) { - // Don't try to re-spawn the botgroup's leader. - if(botGroupItr->BotID == botGroupLeader->GetBotID()) { continue; } + if(botGroupItr->BotID == botGroupLeader->GetBotID()) + continue; - // Load current botgroup member Bot *botGroupMember = LoadBot(botGroupItr->BotID, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); safe_delete(botGroupMember); return; } - // Skip invalid botgroup members. + if(!botGroupMember) { safe_delete(botGroupMember); continue; } - // Spawn current botgroup member. botGroupMember->Spawn(c, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -14486,19 +12108,15 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Add current botgroup member to botgroup. 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; @@ -14506,24 +12124,20 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 @@ -14532,23 +12146,17 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(groupLeader) { if(groupLeader->HasGroup() && groupLeader->GetGroup()->IsLeader(groupLeader)) { SaveBotGroup(groupLeader->GetGroup(), botGroupName, &TempErrorMessage); - - if(!TempErrorMessage.empty()) { + 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 + } else c->Message(0, "You must target a bot group leader only."); - } - else + } else c->Message(0, "You must target a bot that is in the same zone as you."); - } - else + } else c->Message(0, "The bot group name already exists. Please choose another name to save your bot group as."); } - return; } @@ -14567,22 +12175,23 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 { @@ -14590,6 +12199,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } } + if (!strcasecmp(sep->arg[1], "face")) LuclinFace = atoi(sep->arg[2]); @@ -14597,46 +12207,42 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 { + } 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); - + 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, "Feature changed."); + } else c->Message(0, "You must own the bot to make changes."); - } - } else { + } else c->Message(0, "Requires a value."); - } - } else { - c->Message(0,"A bot needs to be targeted."); - } + } else + c->Message(0, "A bot needs to be targeted."); return; } @@ -14655,7 +12261,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Bot *targetedBot = nullptr; - if(c->GetTarget() != nullptr) { if (c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) targetedBot = c->GetTarget()->CastToBot(); @@ -14670,25 +12275,20 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(taunt) { if(!targetedBot->taunting) targetedBot->BotGroupSay(targetedBot, "I am now taunting."); - } - else { + } else { if(targetedBot->taunting) targetedBot->BotGroupSay(targetedBot, "I am no longer taunting."); } targetedBot->SetTaunting(taunt); - } - else + } else c->Message(13, "You must select a bot with the taunt skill."); - } - else { + } else { c->Message(13, "You must target a spawned bot."); } } - } - else { + } else c->Message(0, "Usage #bot taunt [on|off]"); - } return; } @@ -14697,7 +12297,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3){ Bot* tempBot = nullptr; std::string botName = std::string(sep->arg[2]); - if(!botName.empty()) tempBot = entity_list.GetBotByBotName(botName); else @@ -14706,23 +12305,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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")) { + 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 { + } else { botStance = (BotStanceType)stance; if(botStance != tempBot->GetBotStance()) { tempBot->SetBotStance(botStance); @@ -14767,20 +12362,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } c->Message(0, "Stance for %s: %s.", tempBot->GetCleanName(), stanceName.c_str()); - } - else { + } else c->Message(13, "You must name a valid bot."); - } - } - else { + } 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], "groupmessages")) { bool groupMessages = false; - if(sep->arg[2] && sep->arg[3]){ if(!strcasecmp(sep->arg[2], "on")) groupMessages = true; @@ -14792,10 +12383,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Bot* tempBot; - if(!strcasecmp(sep->arg[3], "all")) { 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; @@ -14803,16 +12392,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { tempBot->SetGroupMessagesOn(groupMessages); } } - } - else { + } else c->Message(0, "You have no spawned bots in this zone."); - } c->Message(0, "Group messages now %s for all bots.", groupMessages?"on":"off"); - } - else { + } else { std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) tempBot = entity_list.GetBotByBotName(botName); else { @@ -14825,25 +12410,21 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(13, "You must target a bot that you own."); return; } - tempBot->SetGroupMessagesOn(groupMessages); c->Message(0, "Group messages now %s.", groupMessages?"on":"off"); - } - else { + } else { c->Message(13, "You must name a valid bot."); } } - } - else { + } else c->Message(0, "Usage #bot groupmessages [on|off] [bot name|all]"); - } + 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 { @@ -14854,7 +12435,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; @@ -14871,7 +12451,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else if(botlevel >= 52) defensiveSpellID = 4503; //Evasive discipline else - c->Message(0, "Error: warrior must be level 52+"); + c->Message(0, "Warrior must be level 52 or higher."); break; case PALADIN: if(botlevel >= 73) @@ -14883,7 +12463,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else if(botlevel >= 56) defensiveSpellID = 7004; //Guard of Piety else - c->Message(0, "Error: paladin must be level 56+"); + c->Message(0, "Paladin must be level 56 or higher."); break; case SHADOWKNIGHT: if(botlevel >= 73) @@ -14895,20 +12475,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else if(botlevel >= 56) defensiveSpellID = 7005; //Ichor guard else - c->Message(0, "Error: shadowknight must be level 56+"); + c->Message(0, "Shadow Knight must be level 56 or higher."); break; default: - c->Message(0, "Error: you must select a warrior or knight"); + c->Message(0, "You must select a Warrior, Paladin, or Shadow Knight."); break; } - if(defensiveSpellID > 0) { + if(defensiveSpellID > 0) tempBot->UseDiscipline(defensiveSpellID, tempBot->GetID()); - } - } - else { + } else c->Message(13, "You must name a valid bot."); - } + return; } @@ -14926,16 +12504,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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) { //allows for target or not + 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 { @@ -14947,14 +12522,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; @@ -14965,7 +12538,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - //get percentage heals if(!strcasecmp(sep->arg[5], "fasthealson")) fastHeals = true; else if(strcasecmp(sep->arg[5], "fasthealsoff")) { @@ -14974,10 +12546,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(!leaderBot->GetInHealRotation()) { - //check for target if(sep->argnum == 6) { std::string targetName = std::string(sep->arg[6]); - if(!targetName.empty()) target = entity_list.GetMob(targetName.c_str()); else { @@ -14990,23 +12560,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } } - - //create rotation leaderBot->CreateHealRotation(target, timer); leaderBot->SetHealRotationUseFastHeals(fastHeals); c->Message(0, "Bot heal rotation created successfully."); - } - else { + } else { c->Message(13, "That bot is already in a heal rotation."); return; } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "Usage #bot healrotation create [target]."); return; } @@ -15016,7 +12581,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 4) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -15027,7 +12591,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; @@ -15051,21 +12614,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - //add to rotation - if(leaderBot->AddHealRotationMember(healer)) { + 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, "Unable to add bot to rotation."); } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation addmember "); return; } @@ -15091,7 +12649,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Bot* healer; std::string healerName = std::string(sep->arg[4]); - if(!healerName.empty()) healer = entity_list.GetBotByBotName(healerName); else { @@ -15105,25 +12662,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - //remove from rotation - if(leaderBot->RemoveHealRotationMember(healer)) { + if(leaderBot->RemoveHealRotationMember(healer)) c->Message(0, "Bot heal rotation member removed successfully."); - } - else { - c->Message(13, "Unable to remove bot from rotation. "); - } - } - else { + else + c->Message(13, "Unable to remove bot from rotation."); + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation removemember "); return; } @@ -15133,7 +12684,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 { @@ -15149,35 +12699,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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) { + if(c->GetTarget() != nullptr) target = c->GetTarget(); - } } if(target) { - //add target - if(leaderBot->AddHealRotationTarget(target)) { + if(leaderBot->AddHealRotationTarget(target)) c->Message(0, "Bot heal rotation target added successfully."); - } - else { - c->Message(13, "Unable to add rotation target. "); - } - } - else { + else + c->Message(13, "Unable to add rotation target."); + } else { c->Message(13, "Invalid target."); return; } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation addtarget [bot healrotation target name to add] "); return; } @@ -15187,7 +12729,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 4) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -15203,7 +12744,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* target; std::string targetName = std::string(sep->arg[4]); - if(!targetName.empty()) target = entity_list.GetMob(targetName.c_str()); else { @@ -15212,21 +12752,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(target) { - //add to rotation - if(leaderBot->RemoveHealRotationTarget(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, "Unable to remove rotation target."); } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation removetarget "); return; } @@ -15236,36 +12771,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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) { - //start all heal rotations 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 { + } else { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -15282,28 +12808,22 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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 { + } else { c->Message(13, "You must name a valid bot."); return; } } - } - else { + } else { c->Message(0, "#bot healrotation start "); return; } @@ -15313,32 +12833,24 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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) { - //start all heal rotations 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 { + } else { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -15354,10 +12866,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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); @@ -15365,14 +12875,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } c->Message(0, "Bot heal rotation stopped successfully."); - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } } - } - else { + } else { c->Message(0, "#bot healrotation stop "); return; } @@ -15383,21 +12891,15 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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) { - //list leaders and number of bots per rotation + 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 { + } else { std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -15413,43 +12915,31 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } botList = GetBotsInHealRotation(leaderBot); - - //list leader and number of members 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()) { - //list rotation members + if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) c->Message(0, "Bot Heal Rotation- Member: %s", tempBot->GetCleanName()); - } } - for(int i=0; iGetHealRotationTarget(i)) { Mob* tempTarget = leaderBot->GetHealRotationTarget(i); - if(tempTarget) { std::string targetInfo = ""; - targetInfo += tempTarget->GetHPRatio() < 0 ? "(dead) " : ""; targetInfo += tempTarget->GetZoneID() != leaderBot->GetZoneID() ? "(not in zone) " : ""; - - //list targets c->Message(0, "Bot Heal Rotation- Target: %s %s", tempTarget->GetCleanName(), targetInfo.c_str()); } } } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } } - } - else { + } else { c->Message(0, "#bot healrotation list "); return; } @@ -15459,7 +12949,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -15475,20 +12964,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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 { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation cleartargets "); return; } @@ -15498,7 +12983,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -15514,7 +12998,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - //get percentage heals & target if(!strcasecmp(sep->arg[4], "on")) fastHeals = true; else if(strcasecmp(sep->arg[4], "off")) { @@ -15523,36 +13006,22 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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 { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation fastheals "); return; } } - - if(!strcasecmp(sep->arg[2], "load")) { - } - - if(!strcasecmp(sep->arg[2], "save")) { - } - - if(!strcasecmp(sep->arg[2], "delete")) { - } } - // #bot setinspectmessage if(!strcasecmp(sep->arg[1], "setinspectmessage")) { if(!strcasecmp(sep->arg[2], "help")) { c->Message(0, "[Titanium clients:]"); @@ -15566,20 +13035,15 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 { + } 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 { + } else { c->Message(0, "Your target must be a bot that you own."); } } @@ -15587,7 +13051,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "bardoutofcombat")) { bool useOutOfCombatSongs = false; - if(sep->arg[2] && sep->arg[3]){ if(!strcasecmp(sep->arg[2], "on")) useOutOfCombatSongs = true; @@ -15599,22 +13062,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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 { + } else c->Message(0, "Your target must be a bot that you own."); - } - } - else { + } else c->Message(0, "Usage #bot bardoutofcombat [on|off]"); - } return; } @@ -15645,25 +13102,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } -// franck: EQoffline -// This function has been reworked for the caster bots, when engaged. -// Healers bots must heal thoses who loose HP. bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* 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.Out(Logs::General, Logs::Error, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); - return(false); + return false; } - if(!caster) - return false; - - if(!caster->AI_HasSpells()) + if(!caster || !caster->AI_HasSpells()) return false; if (iChance < 100) { @@ -15675,30 +13120,22 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl uint8 botCasterClass = caster->GetClass(); if( iSpellTypes == SpellType_Heal ) { - // Changed so heal based on health percentage is different for hybrids if( botCasterClass == CLERIC || botCasterClass == DRUID || botCasterClass == SHAMAN) { - //If AI_EngagedCastCheck() said to the healer that he had to heal - - // check in group if(caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(g->members[i] && !g->members[i]->qglobal) { if(g->members[i]->IsClient() && g->members[i]->GetHPRatio() < 90) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < 95) { + } else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < 95) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < 80) { + } else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < 80) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if(g->members[i]->GetHPRatio() < 70) { + } else if(g->members[i]->GetHPRatio() < 70) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; } @@ -15714,26 +13151,13 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } } - - // TODO: raid heals } - // Changed so heal based on health percentage is different for hybrids if( botCasterClass == PALADIN || botCasterClass == BEASTLORD || botCasterClass == RANGER) { - //If AI_EngagedCastCheck() said to the healer that he had to heal - - // check in group if(caster->HasGroup()) { Group *g = caster->GetGroup(); - float hpRatioToHeal = 25.0f; - - switch(caster->GetBotStance()) - { - case BotStanceAggressive: - case BotStanceEfficient: - hpRatioToHeal = 25.0f; - break; + switch(caster->GetBotStance()) { case BotStanceReactive: case BotStanceBalanced: hpRatioToHeal = 50.0f; @@ -15742,6 +13166,8 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl case BotStanceBurnAE: hpRatioToHeal = 20.0f; break; + case BotStanceAggressive: + case BotStanceEfficient: default: hpRatioToHeal = 25.0f; break; @@ -15753,16 +13179,13 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl if(g->members[i]->IsClient() && g->members[i]->GetHPRatio() < hpRatioToHeal) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < hpRatioToHeal) { + } else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < hpRatioToHeal) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < hpRatioToHeal) { + } else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < hpRatioToHeal) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if(g->members[i]->GetHPRatio() < hpRatioToHeal/2) { + } else if(g->members[i]->GetHPRatio() < hpRatioToHeal/2) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; } @@ -15778,15 +13201,11 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } } - - // TODO: raid heals } } - //Ok for the buffs.. if( iSpellTypes == SpellType_Buff) { - uint8 chanceToCast = caster->IsEngaged()?caster->GetChanceToCastBySpellType(SpellType_Buff):100; - // Let's try to make Bard working... + uint8 chanceToCast = caster->IsEngaged() ? caster->GetChanceToCastBySpellType(SpellType_Buff) : 100; if(botCasterClass == BARD) { if(caster->AICastSpell(caster, chanceToCast, SpellType_Buff)) return true; @@ -15796,29 +13215,22 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl if(caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { - for( int i = 0; i < MAX_GROUP_MEMBERS; i++) { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(g->members[i]) { - if(caster->AICastSpell(g->members[i], chanceToCast, SpellType_Buff)) - return true; - - if(caster->AICastSpell(g->members[i]->GetPet(), chanceToCast, SpellType_Buff)) + if(caster->AICastSpell(g->members[i], chanceToCast, SpellType_Buff) || caster->AICastSpell(g->members[i]->GetPet(), chanceToCast, SpellType_Buff)) return true; } } } } - - // TODO: raid buffs } if( iSpellTypes == SpellType_Cure) { if(caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { - for( int i = 0; i < MAX_GROUP_MEMBERS; i++) { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(g->members[i] && caster->GetNeedsCured(g->members[i])) { if(caster->AICastSpell(g->members[i], caster->GetChanceToCastBySpellType(SpellType_Cure), SpellType_Cure)) return true; @@ -15833,143 +13245,117 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } } - - // TODO: raid buffs } - return false; } Mob* EntityList::GetMobByBotID(uint32 botID) { Mob* Result = 0; - if(botID > 0) { auto it = mob_list.begin(); - - for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { - if(!it->second) continue; + for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { + if(!it->second) + continue; + if(it->second->IsBot() && it->second->CastToBot()->GetBotID() == botID) { Result = it->second; break; } } } - return Result; } Bot* EntityList::GetBotByBotID(uint32 botID) { Bot* Result = 0; - if(botID > 0) { for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotID() == botID) { Result = tempBot; break; } } } - return Result; } Bot* EntityList::GetBotByBotName(std::string botName) { Bot* Result = 0; - if(!botName.empty()) { for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && std::string(tempBot->GetName()) == botName) { Result = tempBot; break; } } } - return Result; } void EntityList::AddBot(Bot *newBot, bool SendSpawnPacket, bool dontqueue) { if(newBot) { newBot->SetID(GetFreeID()); - if(SendSpawnPacket) { if(dontqueue) { - // Send immediately EQApplicationPacket* outapp = new EQApplicationPacket(); newBot->CreateSpawnPacket(outapp); outapp->priority = 6; QueueClients(newBot, outapp, true); safe_delete(outapp); - } - else { - // Queue the packet + } else { NewSpawn_Struct* ns = new NewSpawn_Struct; memset(ns, 0, sizeof(NewSpawn_Struct)); newBot->FillSpawnStruct(ns, newBot); AddToSpawnQueue(newBot->GetID(), &ns); safe_delete(ns); } - parse->EventNPC(EVENT_SPAWN, newBot, nullptr, "", 0); } - bot_list.push_back(newBot); - mob_list.insert(std::pair(newBot->GetID(), newBot)); } } std::list EntityList::GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacterID) { std::list Result; - if(botOwnerCharacterID > 0) { for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == botOwnerCharacterID) Result.push_back(tempBot); } } - return Result; } -void EntityList::BotPickLock(Bot* rogue) -{ +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)) + 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; - // All rogue items with lock pick bonuses are hands or primary 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) // Hand slot item + if(item1) if(item1->GetItem()->SkillModType == SkillPickLock) - bonus1 = skill * (((float)item1->GetItem()->SkillModValue) / 100.0f); + bonus1 = (skill * (((float)item1->GetItem()->SkillModValue) / 100.0f)); - if(item2) // Primary slot item + if(item2) if(item2->GetItem()->SkillModType == SkillPickLock) - bonus2 = skill * (((float)item2->GetItem()->SkillModValue) / 100.0f); + bonus2 = (skill * (((float)item2->GetItem()->SkillModValue) / 100.0f)); - if((skill+bonus1+bonus2) >= cdoor->GetLockpick()) + if((skill + bonus1 + bonus2) >= cdoor->GetLockpick()) cdoor->ForceOpen(rogue); else rogue->BotGroupSay(rogue, "I am not skilled enough for this lock."); @@ -15978,12 +13364,9 @@ void EntityList::BotPickLock(Bot* rogue) bool EntityList::RemoveBot(uint16 entityID) { bool Result = false; - if(entityID > 0) { - for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) - { + for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetID() == entityID) { bot_list.erase(botListItr); Result = true; @@ -15991,23 +13374,17 @@ bool EntityList::RemoveBot(uint16 entityID) { } } } - return Result; } void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { - const char *WindowTitle = "Bot Tracking Window"; - std::string WindowText; int LastCon = -1; int CurrentCon = 0; Mob* curMob = nullptr; - uint32 array_counter = 0; - auto it = mob_list.begin(); - for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { curMob = it->second; if (curMob && DistanceNoZ(curMob->GetPosition(), client->GetPosition()) <= Distance) { @@ -16046,36 +13423,34 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { "stone_","lava_","_","" }; unsigned int MyArraySize; - for ( MyArraySize = 0; true; MyArraySize++) { //Find empty string & get size - if (!(*(MyArray[MyArraySize]))) break; //Checks for null char in 1st pos + for ( MyArraySize = 0; true; MyArraySize++) { + if (!(*(MyArray[MyArraySize]))) + break; }; if (NamedOnly) { bool ContinueFlag = false; - const char *CurEntityName = cur_entity->GetName(); //Call function once + const char *CurEntityName = cur_entity->GetName(); for (int Index = 0; Index < MyArraySize; Index++) { if (!strncasecmp(CurEntityName, MyArray[Index], strlen(MyArray[Index])) || (Extras)) { ContinueFlag = true; - break; //From Index for + break; }; }; - if (ContinueFlag) continue; //Moved here or would apply to Index for + if (ContinueFlag) + continue; }; CurrentCon = client->GetLevelCon(cur_entity->GetLevel()); if(CurrentCon != LastCon) { - if(LastCon != -1) WindowText += ""; LastCon = CurrentCon; - switch(CurrentCon) { - case CON_GREEN: { WindowText += ""; break; } - case CON_LIGHTBLUE: { WindowText += ""; break; @@ -16084,7 +13459,6 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { WindowText += ""; break; } - case CON_YELLOW: { WindowText += ""; break; @@ -16099,66 +13473,50 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { } } } - WindowText += cur_entity->GetCleanName(); WindowText += "
"; - if(strlen(WindowText.c_str()) > 4000) { - // Popup window is limited to 4096 characters. - WindowText += "


List truncated ... too many mobs to display"; + WindowText += "


List truncated... too many mobs to display"; break; } } } } WindowText += "
"; - client->SendPopupToClient(WindowTitle, WindowText.c_str()); - return; } uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { uint8 needHealed = 0; Group *g; - if(this->HasGroup()) { g = this->GetGroup(); - if(g) { for( int i = 0; imembers[i] && !g->members[i]->qglobal) { - if(g->members[i]->GetHPRatio() <= hpr) needHealed++; if(includePets) { - if(g->members[i]->GetPet() && g->members[i]->GetPet()->GetHPRatio() <= hpr) { + if(g->members[i]->GetPet() && g->members[i]->GetPet()->GetHPRatio() <= hpr) needHealed++; - } } } } } } - return needHealed; } -uint32 Bot::GetEquipmentColor(uint8 material_slot) const -{ - //Bot tints +uint32 Bot::GetEquipmentColor(uint8 material_slot) const { int16 slotid = 0; uint32 botid = this->GetBotID(); - - //Translate code slot # to DB slot # slotid = Inventory::CalcSlotFromMaterial(material_slot); if (slotid == INVALID_INDEX) return 0; - //read from db - std::string query = StringFormat("SELECT color FROM botinventory " - "WHERE BotID = %u AND SlotID = %u", botid, slotid); + std::string query = StringFormat("SELECT color FROM botinventory WHERE BotID = %u AND SlotID = %u", botid, slotid); auto results = database.QueryDatabase(query); if (!results.Success() || results.RowCount() != 1) return 0; @@ -16167,21 +13525,16 @@ uint32 Bot::GetEquipmentColor(uint8 material_slot) const return atoul(row[0]); } -int Bot::GetRawACNoShield(int &shield_ac) -{ +int Bot::GetRawACNoShield(int &shield_ac) { int ac = itembonuses.AC + spellbonuses.AC; shield_ac = 0; ItemInst* inst = GetBotItem(MainSecondary); - if(inst) - { - if(inst->GetItem()->ItemType == ItemTypeShield) - { + 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++) - { - if(inst->GetAugment(i)) - { + for (uint8 i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + if(inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; } @@ -16192,38 +13545,32 @@ int Bot::GetRawACNoShield(int &shield_ac) } uint32 Bot::CalcCurrentWeight() { - const Item_Struct* TempItem = 0; ItemInst* inst; uint32 Total = 0; - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { - TempItem = inst->GetItem(); - if (TempItem) - Total += TempItem->Weight; + TempItem = inst->GetItem(); + if (TempItem) + Total += TempItem->Weight; } } - float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat; - + float Packrat = ((float)spellbonuses.Packrat + (float)aabonuses.Packrat); if (Packrat > 0) - Total = (uint32)((float)Total * (1.0f - ((Packrat * 1.0f) / 100.0f))); //AndMetal: 1% per level, up to 5% (calculated from Titanium client). verified thru client that it reduces coin weight by the same % - //without casting to float & back to uint32, this didn't work right - + Total = (uint32)((float)Total * (1.0f - ((Packrat * 1.0f) / 100.0f))); + return Total; } -int Bot::GroupLeadershipAAHealthEnhancement() -{ +int Bot::GroupLeadershipAAHealthEnhancement() { Group *g = GetGroup(); if(!g || (g->GroupCount() < 3)) return 0; - switch(g->GetLeadershipAA(groupAAHealthEnhancement)) - { + switch(g->GetLeadershipAA(groupAAHealthEnhancement)) { case 0: return 0; case 1: @@ -16233,19 +13580,15 @@ int Bot::GroupLeadershipAAHealthEnhancement() case 3: return 100; } - return 0; } -int Bot::GroupLeadershipAAManaEnhancement() -{ +int Bot::GroupLeadershipAAManaEnhancement() { Group *g = GetGroup(); - if(!g || (g->GroupCount() < 3)) return 0; - switch(g->GetLeadershipAA(groupAAManaEnhancement)) - { + switch(g->GetLeadershipAA(groupAAManaEnhancement)) { case 0: return 0; case 1: @@ -16255,19 +13598,15 @@ int Bot::GroupLeadershipAAManaEnhancement() case 3: return 100; } - return 0; } -int Bot::GroupLeadershipAAHealthRegeneration() -{ +int Bot::GroupLeadershipAAHealthRegeneration() { Group *g = GetGroup(); - if(!g || (g->GroupCount() < 3)) return 0; - switch(g->GetLeadershipAA(groupAAHealthRegeneration)) - { + switch(g->GetLeadershipAA(groupAAHealthRegeneration)) { case 0: return 0; case 1: @@ -16281,15 +13620,13 @@ int Bot::GroupLeadershipAAHealthRegeneration() return 0; } -int Bot::GroupLeadershipAAOffenseEnhancement() -{ +int Bot::GroupLeadershipAAOffenseEnhancement() { Group *g = GetGroup(); if(!g || (g->GroupCount() < 3)) return 0; - switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) - { + switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) { case 0: return 0; case 1: @@ -16308,23 +13645,16 @@ int Bot::GroupLeadershipAAOffenseEnhancement() 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(); int buffsWithCounters = 0; needCured = true; - for (unsigned int j = 0; j < buff_count; j++) { 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)) { - // Spell has ticks remaining but may have too many counters to cure in the time remaining; - // We should try to just wait it out. Could spend entire time trying to cure spell instead of healing, buffing, etc. - // Since this is the first buff with counters, don't try to cure. Cure spell will be wasted, as cure will try to - // remove counters from the first buff that has counters remaining. needCured = false; break; } @@ -16333,27 +13663,23 @@ bool Bot::GetNeedsCured(Mob *tar) { } } } - return needCured; } bool Bot::HasOrMayGetAggro() { bool mayGetAggro = false; - if(GetTarget() && GetTarget()->GetHateTop()) { Mob *topHate = GetTarget()->GetHateTop(); - if(topHate == this) - mayGetAggro = true; //I currently have aggro + mayGetAggro = true; else { uint32 myHateAmt = GetTarget()->GetHateAmount(this); uint32 topHateAmt = GetTarget()->GetHateAmount(topHate); - if(myHateAmt > 0 && topHateAmt > 0 && (uint8)((myHateAmt/topHateAmt)*100) > 90) //I have 90% as much hate as top, next action may give me aggro + if(myHateAmt > 0 && topHateAmt > 0 && (uint8)((myHateAmt / topHateAmt) * 100) > 90) mayGetAggro = true; } } - return mayGetAggro; } @@ -16361,38 +13687,13 @@ void Bot::SetHasBeenSummoned(bool wasSummoned) { _hasBeenSummoned = wasSummoned; if(!wasSummoned) m_PreSummonLocation = glm::vec3(); - } void Bot::SetDefaultBotStance() { - BotStanceType defaultStance; - - switch(GetClass()) - { - case DRUID: - case CLERIC: - case SHAMAN: - case ENCHANTER: - case NECROMANCER: - case MAGICIAN: - case WIZARD: - case BEASTLORD: - case BERSERKER: - case MONK: - case ROGUE: - case BARD: - case SHADOWKNIGHT: - case PALADIN: - case RANGER: - defaultStance = BotStanceBalanced; - break; - case WARRIOR: - defaultStance = BotStanceAggressive; - break; - default: - defaultStance = BotStanceBalanced; - break; - } + BotStanceType defaultStance = BotStanceBalanced; + if (GetClass() == WARRIOR) + defaultStance = BotStanceAggressive; + _baseBotStance = BotStancePassive; _botStance = defaultStance; } @@ -16400,76 +13701,42 @@ void Bot::SetDefaultBotStance() { void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) { char buf[1000]; va_list ap; - va_start(ap, msg); vsnprintf(buf, 1000, msg, ap); va_end(ap); - if(speaker->HasGroup()) { Group *g = speaker->GetGroup(); - if(g) g->GroupMessage(speaker->CastToMob(), 0, 100, buf); - } else { + } else speaker->Say("%s", buf); - } } bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { - //make sure we have the spell... - int r; - /*for(r = 0; r < MAX_PP_DISCIPLINES; r++) { - if(m_pp.disciplines.values[r] == spell_id) - break; - } - 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)) { - 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)) { - BotGroupSay(this, "Not a valid spell"); - return(false); + BotGroupSay(this, "Not a valid spell."); + return false; } - //can we use the spell? const SPDat_Spell_Struct &spell = spells[spell_id]; uint8 level_to_use = spell.classes[GetClass() - 1]; - if(level_to_use == 255) { - return(false); + if(level_to_use == 255 || level_to_use > GetLevel()) { + return false; } - if(level_to_use > GetLevel()) { - return(false); - } - - if(GetEndurance() > spell.EndurCost) { + if(GetEndurance() > spell.EndurCost) SetEndurance(GetEndurance() - spell.EndurCost); - } else { - return(false); - } + else + return false; - if(spell.recast_time > 0) - { + if(spell.recast_time > 0) { if(CheckDisciplineRecastTimers(this, spells[spell_id].EndurTimerIndex)) { - - //CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT); - if(spells[spell_id].EndurTimerIndex > 0 && spells[spell_id].EndurTimerIndex < MAX_DISCIPLINE_TIMERS) { + if(spells[spell_id].EndurTimerIndex > 0 && spells[spell_id].EndurTimerIndex < MAX_DISCIPLINE_TIMERS) SetDisciplineRecastTimer(spells[spell_id].EndurTimerIndex, spell.recast_time); - } - } - else { - uint32 remain = GetDisciplineRemainingTime(this, spells[spell_id].EndurTimerIndex) / 1000; - GetOwner()->Message(0, "%s can use this discipline in %d minutes %d seconds.", GetCleanName(), ((remain)/60), (remain%60)); - return(false); + } else { + uint32 remain = (GetDisciplineRemainingTime(this, spells[spell_id].EndurTimerIndex) / 1000); + GetOwner()->Message(0, "%s can use this discipline in %d minutes %d seconds.", GetCleanName(), (remain / 60), (remain % 60)); + return false; } } @@ -16477,8 +13744,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { InterruptSpell(); CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT); - - return(true); + return true; } void Bot::CreateHealRotation( Mob* target, uint32 timer ) { @@ -16490,7 +13756,6 @@ void Bot::CreateHealRotation( Mob* target, uint32 timer ) { SetPrevHealRotationMember(this); SetHealRotationTimer(timer); SetHasHealedThisCycle(false); - if(target) AddHealRotationTarget(target); } @@ -16499,13 +13764,11 @@ bool Bot::AddHealRotationMember( Bot* healer ) { if(healer) { if(GetNumHealRotationMembers() > 0 && GetNumHealRotationMembers() < MaxHealRotationMembers) { Bot* tempBot = GetPrevHealRotationMember(); - if(tempBot) { - //add new healer to rotation at end of list - for(int i=0; i<3; i++){ + for(int i = 0; i < 3; i++){ healer->ClearHealRotationMembers(); healer->ClearHealRotationTargets(); - healer->AddHealRotationTarget(entity_list.GetMob(_healRotationTargets[i])); // add all targets.. + healer->AddHealRotationTarget(entity_list.GetMob(_healRotationTargets[i])); } healer->SetHealRotationTimer(tempBot->GetHealRotationTimer()); healer->SetHealRotationLeader(this); @@ -16514,27 +13777,18 @@ bool Bot::AddHealRotationMember( Bot* healer ) { healer->SetInHealRotation(true); healer->SetHasHealedThisCycle(false); healer->SetHealRotationUseFastHeals(tempBot->GetHealRotationUseFastHeals()); - - //set previous rotation member's next member to new member tempBot->SetNextHealRotationMember(healer); - - //update leader's previous member (end of list) to new member and update rotation data 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; } @@ -16543,15 +13797,11 @@ bool Bot::RemoveHealRotationMember( Bot* healer ) { Bot* leader = healer->GetHealRotationLeader(); Bot* prevBot = healer->GetPrevHealRotationMember(); Bot* nextBot = healer->GetNextHealRotationMember(); - if(healer == this) { - if(nextBot != this) { - //get new leader + if(nextBot != this) leader = nextBot; - } } - //remove healer from list healer->SetHealRotationTimer(0); healer->ClearHealRotationMembers(); healer->ClearHealRotationTargets(); @@ -16559,34 +13809,22 @@ bool Bot::RemoveHealRotationMember( Bot* healer ) { healer->SetHasHealedThisCycle(false); healer->SetHealRotationActive(false); healer->SetInHealRotation(false); - if(prevBot && nextBot && GetNumHealRotationMembers() > 1) { - //set previous rotation member's next member to new member prevBot->SetNextHealRotationMember(nextBot); - - //set previous rotation member's next member to new member nextBot->SetPrevHealRotationMember(prevBot); } - //update rotation data 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) { - // change leader if leader is being removed + tempBot->SetNumHealRotationMembers(GetNumHealRotationMembers() - 1); + if(tempBot->GetHealRotationLeader() != leader) tempBot->SetHealRotationLeader(leader); - } } } - return true; } - return false; } @@ -16605,67 +13843,56 @@ void Bot::SetPrevHealRotationMember( Bot* healer ) { Bot* Bot::GetHealRotationLeader( ) { if(_healRotationLeader) return entity_list.GetBotByBotID(_healRotationLeader); + return 0; } Bot* Bot::GetNextHealRotationMember( ) { if(_healRotationMemberNext) return entity_list.GetBotByBotID(_healRotationMemberNext); + return 0; } Bot* Bot::GetPrevHealRotationMember( ) { if(_healRotationMemberNext) return entity_list.GetBotByBotID(_healRotationMemberPrev); + return 0; } 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())) { - //check to see if target's ID is incorrect (could have zoned, died, etc) - if(tempTarget->GetID() != target->GetID()) { + } else if(!strcasecmp(tempTarget->GetCleanName(), target->GetCleanName())) { + if(tempTarget->GetID() != target->GetID()) _healRotationTargets[i] = target->GetID(); - } - //target already in list + return false; } } - if (_healRotationTargets[i] == 0) - { + 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) { - //add target to all members + if(tempBot && tempBot != this) tempBot->AddHealRotationTarget(target, i); - } } - return true; } } } - return false; } bool Bot::AddHealRotationTarget( Mob *target, int index ) { if (target && index < MaxHealRotationTargets) { - //add target to list of targets at specified index _healRotationTargets[index] = target->GetID(); return true; } @@ -16676,37 +13903,30 @@ bool Bot::RemoveHealRotationTarget( Mob* target ) { int index = 0; bool removed = false; if(target) { - //notify all heal rotation members to remove target - for(int i=0; iGetID()) { 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; } bool Bot::RemoveHealRotationTarget( int index ) { if(index >= 0) { - //clear rotation target at index _healRotationTargets[index] = 0; - if(index < MaxHealRotationTargets) { - for(int i=index; i 0) { - - //get first target in list target = entity_list.GetMob(_healRotationTargets[i]); - if(target) { - //check if valid target - if(target->GetZoneID() == GetZoneID() - && !(target->GetAppearance() == eaDead - && !(target->IsClient() && target->CastToClient()->GetFeigned()))) { - + if(target->GetZoneID() == GetZoneID() && !(target->GetAppearance() == eaDead && !(target->IsClient() && target->CastToClient()->GetFeigned()))) { count++; - - //get first valid target - if(!first) { + if(!first) first = target; - } - //check to see if target is group main tank - //(target first, in case top target has died and was rez'd - - //we don't want to heal them then) if(!tank) { Group* g = target->GetGroup(); - if(g && !strcasecmp(g->GetMainTankName(), target->GetCleanName())) { + if(g && !strcasecmp(g->GetMainTankName(), target->GetCleanName())) tank = target; - } } } - } - else { - //if not valid target, remove from list + } else { if(removeIndex == 0) removeIndex = i; } } } - if (removeIndex > 0) { - RemoveHealRotationTarget( removeIndex ); - } + if (removeIndex > 0) + RemoveHealRotationTarget(removeIndex); if(tank) return tank; @@ -16783,35 +13984,27 @@ Mob* Bot::GetHealRotationTarget( ) { Mob* Bot::GetHealRotationTarget( uint8 index ) { Mob* target = nullptr; - - if(_healRotationTargets[index] > 0) { - //get target at specified index + 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) { - //check if we need to notify to start now, or after timer uint32 nextHealTime = notifyNow ? Timer::GetCurrentTime() : Timer::GetCurrentTime() + GetHealRotationTimer(); - Bot* nextMember = GetNextHealRotationMember(); if(nextMember && nextMember != this) { nextMember->SetHealRotationNextHealTime(nextHealTime); @@ -16822,11 +14015,9 @@ void Bot::NotifyNextHealRotationMember(bool notifyNow) { 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()) { - //clear all heal rotation data for bots in a heal rotation tempBot->SetInHealRotation(false); tempBot->SetHealRotationActive(false); tempBot->SetHasHealedThisCycle(false); @@ -16840,4 +14031,4 @@ void Bot::BotHealRotationsClear(Client* c) { } } -#endif +#endif \ No newline at end of file From 6503e6371af3b90972b47b68b573946c8311d3eb Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 19 Jun 2015 19:55:10 -0400 Subject: [PATCH 198/846] Added Combat:BackstabBonus rule. - 0 = 0%, 5 = 5%, 50 = 50%, 200 = 200% --- common/ruletypes.h | 1033 +++++++++++++++++++------------------- zone/bot.cpp | 4 +- zone/special_attacks.cpp | 4 +- 3 files changed, 521 insertions(+), 520 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 9a36b77f4..1919c7168 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -20,603 +20,604 @@ -RULE_CATEGORY( Character ) -RULE_INT ( Character, MaxLevel, 65 ) -RULE_BOOL ( Character, PerCharacterQglobalMaxLevel, false) // This will check for qglobal 'CharMaxLevel' character qglobal (Type 5), if player tries to level beyond that point, it will not go beyond that level -RULE_INT ( Character, MaxExpLevel, 0 ) //Sets the Max Level attainable via Experience -RULE_INT ( Character, DeathExpLossLevel, 10 ) // Any level greater than this will lose exp on death -RULE_INT ( Character, DeathExpLossMaxLevel, 255 ) // Any level greater than this will no longer lose exp on death -RULE_INT ( Character, DeathItemLossLevel, 10 ) -RULE_INT ( Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost -RULE_BOOL( Character, UseDeathExpLossMult, false ) //Adjust to use the above multiplier or to use code default. -RULE_INT ( Character, CorpseDecayTimeMS, 10800000 ) -RULE_INT ( Character, CorpseResTimeMS, 10800000 ) // time before cant res corpse(3 hours) -RULE_BOOL( Character, LeaveCorpses, true ) -RULE_BOOL( Character, LeaveNakedCorpses, false ) -RULE_INT ( Character, MaxDraggedCorpses, 2 ) -RULE_REAL( Character, DragCorpseDistance, 400) // If the corpse is <= this distance from the player, it won't move -RULE_REAL( Character, ExpMultiplier, 0.5 ) -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, LightBlueModifier, 40 ) -RULE_INT ( Character, BlueModifier, 90 ) -RULE_INT ( Character, WhiteModifier, 100 ) -RULE_INT ( Character, YellowModifier, 125 ) -RULE_INT ( Character, RedModifier, 150 ) -RULE_INT ( Character, AutosaveIntervalS, 300 ) //0=disabled -RULE_INT ( Character, HPRegenMultiplier, 100) -RULE_INT ( Character, ManaRegenMultiplier, 100) -RULE_INT ( Character, EnduranceRegenMultiplier, 100) -RULE_INT ( Character, ConsumptionMultiplier, 100) //item's hunger restored = this value * item's food level, 100 = normal, 50 = people eat 2x as fast, 200 = people eat 2x as slow -RULE_BOOL( Character, HealOnLevel, false) -RULE_BOOL( Character, FeignKillsPet, false) -RULE_INT ( Character, ItemManaRegenCap, 15) -RULE_INT ( Character, ItemHealthRegenCap, 35) -RULE_INT ( Character, ItemDamageShieldCap, 30) -RULE_INT ( Character, ItemAccuracyCap, 150) -RULE_INT ( Character, ItemAvoidanceCap, 100) -RULE_INT ( Character, ItemCombatEffectsCap, 100) -RULE_INT ( Character, ItemShieldingCap, 35) -RULE_INT ( Character, ItemSpellShieldingCap, 35) -RULE_INT ( Character, ItemDoTShieldingCap, 35) -RULE_INT ( Character, ItemStunResistCap, 35) -RULE_INT ( Character, ItemStrikethroughCap, 35) -RULE_INT ( Character, ItemATKCap, 250) -RULE_INT ( Character, ItemHealAmtCap, 250) -RULE_INT ( Character, ItemSpellDmgCap, 250) -RULE_INT ( Character, ItemClairvoyanceCap, 250) -RULE_INT ( Character, ItemDSMitigationCap, 50) -RULE_INT ( Character, ItemEnduranceRegenCap, 15) -RULE_INT ( Character, ItemExtraDmgCap, 150) // Cap for bonuses to melee skills like Bash, Frenzy, etc -RULE_INT ( Character, HasteCap, 100) // Haste cap for non-v3(overhaste) haste. -RULE_INT ( Character, SkillUpModifier, 100) //skill ups are at 100% -RULE_BOOL ( Character, SharedBankPlat, false) //off by default to prevent duping for now -RULE_BOOL ( Character, BindAnywhere, false) -RULE_INT ( Character, RestRegenPercent, 0) // Set to >0 to enable rest state bonus HP and mana regen. -RULE_INT ( Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in. -RULE_INT ( Character, RestRegenRaidTimeToActivate, 300) // Time in seconds for rest state regen to kick in with a raid target. -RULE_BOOL ( Character, RestRegenEndurance, false) // Whether rest regen will work for endurance or not. -RULE_INT ( Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA -RULE_INT ( Character, KillsPerRaidLeadershipAA, 250) // Number of dark blues or above per Raid Leadership AA -RULE_INT ( Character, MaxFearDurationForPlayerCharacter, 4) //4 tics, each tic calculates every 6 seconds. -RULE_INT ( Character, MaxCharmDurationForPlayerCharacter, 15) -RULE_INT ( Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values -RULE_BOOL ( Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas -RULE_BOOL ( Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses -RULE_BOOL ( Character, RespawnFromHover, false) // Use Respawn window, or not. -RULE_INT ( Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS -RULE_BOOL ( Character, UseNewStatsWindow, true) // New stats window shows everything -RULE_BOOL ( Character, ItemCastsUseFocus, false) // If true, this allows item clickies to use focuses that have limited max levels on them -RULE_INT ( Character, MinStatusForNoDropExemptions, 80) // This allows status x and higher to trade no drop items. -RULE_INT ( Character, SkillCapMaxLevel, 75 ) // Sets the Max Level used for Skill Caps (from skill_caps table). -1 makes it use MaxLevel rule value. It is set to 75 because PEQ only has skillcaps up to that level, and grabbing the players' skill past 75 will return 0, breaking all skills past that level. This helps servers with obsurd level caps (75+ level cap) function without any modifications. -RULE_INT ( Character, StatCap, 0 ) -RULE_BOOL ( Character, CheckCursorEmptyWhenLooting, true ) // If true, a player cannot loot a corpse (player or NPC) with an item on their cursor -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, 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. -RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. -RULE_INT ( Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type +RULE_CATEGORY(Character) +RULE_INT(Character, MaxLevel, 65) +RULE_BOOL(Character, PerCharacterQglobalMaxLevel, false) // This will check for qglobal 'CharMaxLevel' character qglobal (Type 5), if player tries to level beyond that point, it will not go beyond that level +RULE_INT(Character, MaxExpLevel, 0) //Sets the Max Level attainable via Experience +RULE_INT(Character, DeathExpLossLevel, 10) // Any level greater than this will lose exp on death +RULE_INT(Character, DeathExpLossMaxLevel, 255) // Any level greater than this will no longer lose exp on death +RULE_INT(Character, DeathItemLossLevel, 10) +RULE_INT(Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost +RULE_BOOL(Character, UseDeathExpLossMult, false) //Adjust to use the above multiplier or to use code default. +RULE_INT(Character, CorpseDecayTimeMS, 10800000) +RULE_INT(Character, CorpseResTimeMS, 10800000) // time before cant res corpse(3 hours) +RULE_BOOL(Character, LeaveCorpses, true) +RULE_BOOL(Character, LeaveNakedCorpses, false) +RULE_INT(Character, MaxDraggedCorpses, 2) +RULE_REAL(Character, DragCorpseDistance, 400) // If the corpse is <= this distance from the player, it won't move +RULE_REAL(Character, ExpMultiplier, 0.5) +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, LightBlueModifier, 40) +RULE_INT(Character, BlueModifier, 90) +RULE_INT(Character, WhiteModifier, 100) +RULE_INT(Character, YellowModifier, 125) +RULE_INT(Character, RedModifier, 150) +RULE_INT(Character, AutosaveIntervalS, 300) //0=disabled +RULE_INT(Character, HPRegenMultiplier, 100) +RULE_INT(Character, ManaRegenMultiplier, 100) +RULE_INT(Character, EnduranceRegenMultiplier, 100) +RULE_INT(Character, ConsumptionMultiplier, 100) //item's hunger restored = this value * item's food level, 100 = normal, 50 = people eat 2x as fast, 200 = people eat 2x as slow +RULE_BOOL(Character, HealOnLevel, false) +RULE_BOOL(Character, FeignKillsPet, false) +RULE_INT(Character, ItemManaRegenCap, 15) +RULE_INT(Character, ItemHealthRegenCap, 35) +RULE_INT(Character, ItemDamageShieldCap, 30) +RULE_INT(Character, ItemAccuracyCap, 150) +RULE_INT(Character, ItemAvoidanceCap, 100) +RULE_INT(Character, ItemCombatEffectsCap, 100) +RULE_INT(Character, ItemShieldingCap, 35) +RULE_INT(Character, ItemSpellShieldingCap, 35) +RULE_INT(Character, ItemDoTShieldingCap, 35) +RULE_INT(Character, ItemStunResistCap, 35) +RULE_INT(Character, ItemStrikethroughCap, 35) +RULE_INT(Character, ItemATKCap, 250) +RULE_INT(Character, ItemHealAmtCap, 250) +RULE_INT(Character, ItemSpellDmgCap, 250) +RULE_INT(Character, ItemClairvoyanceCap, 250) +RULE_INT(Character, ItemDSMitigationCap, 50) +RULE_INT(Character, ItemEnduranceRegenCap, 15) +RULE_INT(Character, ItemExtraDmgCap, 150) // Cap for bonuses to melee skills like Bash, Frenzy, etc +RULE_INT(Character, HasteCap, 100) // Haste cap for non-v3(overhaste) haste. +RULE_INT(Character, SkillUpModifier, 100) //skill ups are at 100% +RULE_BOOL(Character, SharedBankPlat, false) //off by default to prevent duping for now +RULE_BOOL(Character, BindAnywhere, false) +RULE_INT(Character, RestRegenPercent, 0) // Set to >0 to enable rest state bonus HP and mana regen. +RULE_INT(Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in. +RULE_INT(Character, RestRegenRaidTimeToActivate, 300) // Time in seconds for rest state regen to kick in with a raid target. +RULE_BOOL(Character, RestRegenEndurance, false) // Whether rest regen will work for endurance or not. +RULE_INT(Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA +RULE_INT(Character, KillsPerRaidLeadershipAA, 250) // Number of dark blues or above per Raid Leadership AA +RULE_INT(Character, MaxFearDurationForPlayerCharacter, 4) //4 tics, each tic calculates every 6 seconds. +RULE_INT(Character, MaxCharmDurationForPlayerCharacter, 15) +RULE_INT(Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values +RULE_BOOL(Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas +RULE_BOOL(Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses +RULE_BOOL(Character, RespawnFromHover, false) // Use Respawn window, or not. +RULE_INT(Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS +RULE_BOOL(Character, UseNewStatsWindow, true) // New stats window shows everything +RULE_BOOL(Character, ItemCastsUseFocus, false) // If true, this allows item clickies to use focuses that have limited max levels on them +RULE_INT(Character, MinStatusForNoDropExemptions, 80) // This allows status x and higher to trade no drop items. +RULE_INT(Character, SkillCapMaxLevel, 75) // Sets the Max Level used for Skill Caps (from skill_caps table). -1 makes it use MaxLevel rule value. It is set to 75 because PEQ only has skillcaps up to that level, and grabbing the players' skill past 75 will return 0, breaking all skills past that level. This helps servers with obsurd level caps (75+ level cap) function without any modifications. +RULE_INT(Character, StatCap, 0) +RULE_BOOL(Character, CheckCursorEmptyWhenLooting, true) // If true, a player cannot loot a corpse (player or NPC) with an item on their cursor +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, 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. +RULE_INT(Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. +RULE_INT(Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type RULE_REAL(Character, EnvironmentDamageMulipliter, 1) RULE_BOOL(Character, UnmemSpellsOnDeath, true) -RULE_INT ( Character, TradeskillUpAlchemy, 2 ) // Alchemy skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpBaking, 2 ) // Baking skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpBlacksmithing, 2 ) // Blacksmithing skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpBrewing, 3 ) // Brewing skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpFletching, 2 ) // Fletching skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpJewelcrafting, 2 ) // Jewelcrafting skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpMakePoison, 2 ) // Make Poison skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpPottery, 4 ) // Pottery skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpResearch, 1 ) // Research skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpTinkering, 2 ) // Tinkering skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpAlchemy, 2) // Alchemy skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpBaking, 2) // Baking skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpBlacksmithing, 2) // Blacksmithing skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpBrewing, 3) // Brewing skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpFletching, 2) // Fletching skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpJewelcrafting, 2) // Jewelcrafting skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpMakePoison, 2) // Make Poison skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster. RULE_CATEGORY_END() -RULE_CATEGORY( Mercs ) -RULE_INT (Mercs, SuspendIntervalMS, 10000) -RULE_INT (Mercs, UpkeepIntervalMS, 180000) -RULE_INT (Mercs, SuspendIntervalS, 10) -RULE_INT (Mercs, UpkeepIntervalS, 180) -RULE_BOOL (Mercs, AllowMercs, false) -RULE_BOOL (Mercs, ChargeMercPurchaseCost, false) -RULE_BOOL (Mercs, ChargeMercUpkeepCost, false) -RULE_INT (Mercs, AggroRadius, 100) // Determines the distance from which a merc will aggro group member's target(also used to determine the distance at which a healer merc will begin healing a group member) -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_CATEGORY(Mercs) +RULE_INT(Mercs, SuspendIntervalMS, 10000) +RULE_INT(Mercs, UpkeepIntervalMS, 180000) +RULE_INT(Mercs, SuspendIntervalS, 10) +RULE_INT(Mercs, UpkeepIntervalS, 180) +RULE_BOOL(Mercs, AllowMercs, false) +RULE_BOOL(Mercs, ChargeMercPurchaseCost, false) +RULE_BOOL(Mercs, ChargeMercUpkeepCost, false) +RULE_INT(Mercs, AggroRadius, 100) // Determines the distance from which a merc will aggro group member's target(also used to determine the distance at which a healer merc will begin healing a group member) +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_CATEGORY_END() -RULE_CATEGORY( Guild ) -RULE_INT ( Guild, MaxMembers, 2048 ) -RULE_BOOL ( Guild, PlayerCreationAllowed, false) // Allow players to create a guild using the window in Underfoot+ -RULE_INT ( Guild, PlayerCreationLimit, 1) // Only allow use of the UF+ window if the account has < than this number of guild leaders on it -RULE_INT ( Guild, PlayerCreationRequiredStatus, 0) // Required admin status. -RULE_INT ( Guild, PlayerCreationRequiredLevel, 0) // Required Level of the player attempting to create the guild. -RULE_INT ( Guild, PlayerCreationRequiredTime, 0) // Required Time Entitled On Account (in Minutes) to create the guild. +RULE_CATEGORY(Guild) +RULE_INT(Guild, MaxMembers, 2048) +RULE_BOOL(Guild, PlayerCreationAllowed, false) // Allow players to create a guild using the window in Underfoot+ +RULE_INT(Guild, PlayerCreationLimit, 1) // Only allow use of the UF+ window if the account has < than this number of guild leaders on it +RULE_INT(Guild, PlayerCreationRequiredStatus, 0) // Required admin status. +RULE_INT(Guild, PlayerCreationRequiredLevel, 0) // Required Level of the player attempting to create the guild. +RULE_INT(Guild, PlayerCreationRequiredTime, 0) // Required Time Entitled On Account (in Minutes) to create the guild. RULE_CATEGORY_END() -RULE_CATEGORY( Skills ) -RULE_INT ( Skills, MaxTrainTradeskills, 21 ) -RULE_BOOL ( Skills, UseLimitTradeskillSearchSkillDiff, true ) -RULE_INT ( Skills, MaxTradeskillSearchSkillDiff, 50 ) -RULE_INT ( Skills, MaxTrainSpecializations, 50 ) // Max level a GM trainer will train casting specializations -RULE_INT ( Skills, SwimmingStartValue, 100 ) -RULE_BOOL ( Skills, TrainSenseHeading, false ) -RULE_INT ( Skills, SenseHeadingStartValue, 200 ) +RULE_CATEGORY(Skills) +RULE_INT(Skills, MaxTrainTradeskills, 21) +RULE_BOOL(Skills, UseLimitTradeskillSearchSkillDiff, true) +RULE_INT(Skills, MaxTradeskillSearchSkillDiff, 50) +RULE_INT(Skills, MaxTrainSpecializations, 50) // Max level a GM trainer will train casting specializations +RULE_INT(Skills, SwimmingStartValue, 100) +RULE_BOOL(Skills, TrainSenseHeading, false) +RULE_INT(Skills, SenseHeadingStartValue, 200) RULE_CATEGORY_END() -RULE_CATEGORY( Pets ) -RULE_REAL( Pets, AttackCommandRange, 150 ) -RULE_BOOL( Pets, UnTargetableSwarmPet, false ) -RULE_REAL( Pets, PetPowerLevelCap, 10 ) // Max number of levels your pet can go up with pet power +RULE_CATEGORY(Pets) +RULE_REAL(Pets, AttackCommandRange, 150) +RULE_BOOL(Pets, UnTargetableSwarmPet, false) +RULE_REAL(Pets, PetPowerLevelCap, 10) // Max number of levels your pet can go up with pet power RULE_CATEGORY_END() -RULE_CATEGORY( GM ) -RULE_INT ( GM, MinStatusToSummonItem, 250) -RULE_INT ( GM, MinStatusToZoneAnywhere, 250 ) +RULE_CATEGORY(GM) +RULE_INT(GM, MinStatusToSummonItem, 250) +RULE_INT(GM, MinStatusToZoneAnywhere, 250) RULE_CATEGORY_END() -RULE_CATEGORY( World ) -RULE_INT ( World, ZoneAutobootTimeoutMS, 60000 ) -RULE_INT ( World, ClientKeepaliveTimeoutMS, 65000 ) -RULE_BOOL ( World, UseBannedIPsTable, false ) // Toggle whether or not to check incoming client connections against the Banned_IPs table. Set this value to false to disable this feature. -RULE_BOOL ( World, EnableTutorialButton, true) -RULE_BOOL ( World, EnableReturnHomeButton, true) -RULE_INT ( World, MaxLevelForTutorial, 10) -RULE_INT ( World, TutorialZoneID, 189) -RULE_INT ( World, GuildBankZoneID, 345) -RULE_INT ( World, MinOfflineTimeToReturnHome, 21600) // 21600 seconds is 6 Hours -RULE_INT ( World, MaxClientsPerIP, -1 ) // Maximum number of clients allowed to connect per IP address if account status is < AddMaxClientsStatus. Default value: -1 (feature disabled) -RULE_INT ( World, ExemptMaxClientsStatus, -1 ) // Exempt accounts from the MaxClientsPerIP and AddMaxClientsStatus rules, if their status is >= this value. Default value: -1 (feature disabled) -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, 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) -RULE_INT ( World, ExemptAccountLimitStatus, -1 ) //Min status required to be exempt from multi-session per account limiting (-1 is disabled) -RULE_BOOL ( World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts. -RULE_INT ( World, MinGMAntiHackStatus, 1 ) //Minimum GM status to check against AntiHack list -RULE_INT ( World, SoFStartZoneID, -1 ) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) -RULE_INT ( World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method. -RULE_INT ( World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS. -RULE_INT ( World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules. +RULE_CATEGORY(World) +RULE_INT(World, ZoneAutobootTimeoutMS, 60000) +RULE_INT(World, ClientKeepaliveTimeoutMS, 65000) +RULE_BOOL(World, UseBannedIPsTable, false) // Toggle whether or not to check incoming client connections against the Banned_IPs table. Set this value to false to disable this feature. +RULE_BOOL(World, EnableTutorialButton, true) +RULE_BOOL(World, EnableReturnHomeButton, true) +RULE_INT(World, MaxLevelForTutorial, 10) +RULE_INT(World, TutorialZoneID, 189) +RULE_INT(World, GuildBankZoneID, 345) +RULE_INT(World, MinOfflineTimeToReturnHome, 21600) // 21600 seconds is 6 Hours +RULE_INT(World, MaxClientsPerIP, -1) // Maximum number of clients allowed to connect per IP address if account status is < AddMaxClientsStatus. Default value: -1 (feature disabled) +RULE_INT(World, ExemptMaxClientsStatus, -1) // Exempt accounts from the MaxClientsPerIP and AddMaxClientsStatus rules, if their status is >= this value. Default value: -1 (feature disabled) +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, 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) +RULE_INT(World, ExemptAccountLimitStatus, -1) //Min status required to be exempt from multi-session per account limiting (-1 is disabled) +RULE_BOOL(World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts. +RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against AntiHack list +RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) +RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method. +RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS. +RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules. 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_CATEGORY_END() -RULE_CATEGORY( Zone ) -RULE_INT ( Zone, NPCPositonUpdateTicCount, 32 ) //ms between intervals of sending a position update to the entire zone. -RULE_INT ( Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection -RULE_INT ( Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone -RULE_BOOL ( Zone, EnableShadowrest, 1 ) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. -RULE_BOOL ( Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses. -RULE_INT ( Zone, MQWarpExemptStatus, -1 ) // Required status level to exempt the MQWarpDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQZoneExemptStatus, -1 ) // Required status level to exempt the MQZoneDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQGateExemptStatus, -1 ) // Required status level to exempt the MQGateDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQGhostExemptStatus, -1 ) // Required status level to exempt the MGhostDetector. Set to -1 to disable this feature. -RULE_BOOL ( Zone, EnableMQWarpDetector, true ) // Enable the MQWarp Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQZoneDetector, true ) // Enable the MQZone Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQGateDetector, true ) // Enable the MQGate Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQGhostDetector, true ) // Enable the MQGhost Detector. Set to False to disable this feature. -RULE_REAL ( Zone, MQWarpDetectionDistanceFactor, 9.0) //clients move at 4.4 about if in a straight line but with movement and to acct for lag we raise it a bit -RULE_BOOL ( Zone, MarkMQWarpLT, false ) -RULE_INT ( Zone, AutoShutdownDelay, 5000 ) //How long a dynamic zone stays loaded while empty -RULE_INT ( Zone, PEQZoneReuseTime, 900 ) //How long, in seconds, until you can reuse the #peqzone command. -RULE_INT ( Zone, PEQZoneDebuff1, 4454 ) //First debuff casted by #peqzone Default is Cursed Keeper's Blight. -RULE_INT ( Zone, PEQZoneDebuff2, 2209 ) //Second debuff casted by #peqzone Default is Tendrils of Apathy. -RULE_BOOL ( Zone, UsePEQZoneDebuffs, true ) //Will determine if #peqzone will debuff players or not when used. -RULE_REAL ( Zone, HotZoneBonus, 0.75 ) -RULE_INT ( Zone, ReservedInstances, 30 ) //Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running. -RULE_INT ( Zone, EbonCrystalItemID, 40902) -RULE_INT ( Zone, RadiantCrystalItemID, 40903) -RULE_BOOL ( Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mods table in consideration to your players EXP hits -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_CATEGORY(Zone) +RULE_INT(Zone, NPCPositonUpdateTicCount, 32) //ms between intervals of sending a position update to the entire zone. +RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection +RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone +RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. +RULE_BOOL(Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses. +RULE_INT(Zone, MQWarpExemptStatus, -1) // Required status level to exempt the MQWarpDetector. Set to -1 to disable this feature. +RULE_INT(Zone, MQZoneExemptStatus, -1) // Required status level to exempt the MQZoneDetector. Set to -1 to disable this feature. +RULE_INT(Zone, MQGateExemptStatus, -1) // Required status level to exempt the MQGateDetector. Set to -1 to disable this feature. +RULE_INT(Zone, MQGhostExemptStatus, -1) // Required status level to exempt the MGhostDetector. Set to -1 to disable this feature. +RULE_BOOL(Zone, EnableMQWarpDetector, true) // Enable the MQWarp Detector. Set to False to disable this feature. +RULE_BOOL(Zone, EnableMQZoneDetector, true) // Enable the MQZone Detector. Set to False to disable this feature. +RULE_BOOL(Zone, EnableMQGateDetector, true) // Enable the MQGate Detector. Set to False to disable this feature. +RULE_BOOL(Zone, EnableMQGhostDetector, true) // Enable the MQGhost Detector. Set to False to disable this feature. +RULE_REAL(Zone, MQWarpDetectionDistanceFactor, 9.0) //clients move at 4.4 about if in a straight line but with movement and to acct for lag we raise it a bit +RULE_BOOL(Zone, MarkMQWarpLT, false) +RULE_INT(Zone, AutoShutdownDelay, 5000) //How long a dynamic zone stays loaded while empty +RULE_INT(Zone, PEQZoneReuseTime, 900) //How long, in seconds, until you can reuse the #peqzone command. +RULE_INT(Zone, PEQZoneDebuff1, 4454) //First debuff casted by #peqzone Default is Cursed Keeper's Blight. +RULE_INT(Zone, PEQZoneDebuff2, 2209) //Second debuff casted by #peqzone Default is Tendrils of Apathy. +RULE_BOOL(Zone, UsePEQZoneDebuffs, true) //Will determine if #peqzone will debuff players or not when used. +RULE_REAL(Zone, HotZoneBonus, 0.75) +RULE_INT(Zone, ReservedInstances, 30) //Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running. +RULE_INT(Zone, EbonCrystalItemID, 40902) +RULE_INT(Zone, RadiantCrystalItemID, 40903) +RULE_BOOL(Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mods table in consideration to your players EXP hits +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_CATEGORY_END() -RULE_CATEGORY( Map ) +RULE_CATEGORY(Map) //enable these to help prevent mob hopping when they are pathing -RULE_BOOL ( Map, FixPathingZWhenLoading, true ) //increases zone boot times a bit to reduce hopping. -RULE_BOOL ( Map, FixPathingZAtWaypoints, false ) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time. -RULE_BOOL ( Map, FixPathingZWhenMoving, false ) //very CPU intensive, but helps hopping with widely spaced waypoints. -RULE_BOOL ( Map, FixPathingZOnSendTo, false ) //try to repair Z coords in the SendTo routine as well. -RULE_REAL ( Map, FixPathingZMaxDeltaMoving, 20 ) //at runtime while pathing: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaWaypoint, 20 ) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaSendTo, 20 ) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaLoading, 45 ) //while loading each waypoint: max change in Z to allow the BestZ code to apply. -RULE_INT ( Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position +RULE_BOOL(Map, FixPathingZWhenLoading, true) //increases zone boot times a bit to reduce hopping. +RULE_BOOL(Map, FixPathingZAtWaypoints, false) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time. +RULE_BOOL(Map, FixPathingZWhenMoving, false) //very CPU intensive, but helps hopping with widely spaced waypoints. +RULE_BOOL(Map, FixPathingZOnSendTo, false) //try to repair Z coords in the SendTo routine as well. +RULE_REAL(Map, FixPathingZMaxDeltaMoving, 20) //at runtime while pathing: max change in Z to allow the BestZ code to apply. +RULE_REAL(Map, FixPathingZMaxDeltaWaypoint, 20) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. +RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. +RULE_REAL(Map, FixPathingZMaxDeltaLoading, 45) //while loading each waypoint: max change in Z to allow the BestZ code to apply. +RULE_INT(Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position RULE_CATEGORY_END() -RULE_CATEGORY( Pathing ) +RULE_CATEGORY(Pathing) // Some of these rules may benefit by being made into columns in the zone table, // for instance, in dungeons, the min LOS distances could be substantially lowered. -RULE_BOOL ( Pathing, Aggro, true ) // Enable pathing for aggroed mobs. -RULE_BOOL ( Pathing, AggroReturnToGrid, true ) // Enable pathing for aggroed roaming mobs returning to their previous waypoint. -RULE_BOOL ( Pathing, Guard, true ) // Enable pathing for mobs moving to their guard point. -RULE_BOOL ( Pathing, Find, true ) // Enable pathing for FindPerson requests from the client. -RULE_BOOL ( Pathing, Fear, true ) // Enable pathing for fear -RULE_REAL ( Pathing, ZDiffThreshold, 10) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. -RULE_INT ( Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds). -RULE_INT ( Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved. -RULE_INT ( Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved. +RULE_BOOL(Pathing, Aggro, true) // Enable pathing for aggroed mobs. +RULE_BOOL(Pathing, AggroReturnToGrid, true) // Enable pathing for aggroed roaming mobs returning to their previous waypoint. +RULE_BOOL(Pathing, Guard, true) // Enable pathing for mobs moving to their guard point. +RULE_BOOL(Pathing, Find, true) // Enable pathing for FindPerson requests from the client. +RULE_BOOL(Pathing, Fear, true) // Enable pathing for fear +RULE_REAL(Pathing, ZDiffThreshold, 10) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. +RULE_INT(Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds). +RULE_INT(Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved. +RULE_INT(Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved. // When a path has a path node route and it's target changes position, if it has RouteUpdateFrequencyNodeCount or less nodes to go on it's // current path, it will recalculate it's path based on the RouteUpdateFrequencyShort timer, otherwise it will use the // RouteUpdateFrequencyLong timer. -RULE_INT ( Pathing, RouteUpdateFrequencyNodeCount, 5) -RULE_REAL ( Pathing, MinDistanceForLOSCheckShort, 40000) // (NoRoot). While following a path, only check for LOS to target within this distance. -RULE_REAL ( Pathing, MinDistanceForLOSCheckLong, 1000000) // (NoRoot). Min distance when initially attempting to acquire the target. -RULE_INT ( Pathing, MinNodesLeftForLOSCheck, 4) // Only check for LOS when we are down to this many path nodes left to run. +RULE_INT(Pathing, RouteUpdateFrequencyNodeCount, 5) +RULE_REAL(Pathing, MinDistanceForLOSCheckShort, 40000) // (NoRoot). While following a path, only check for LOS to target within this distance. +RULE_REAL(Pathing, MinDistanceForLOSCheckLong, 1000000) // (NoRoot). Min distance when initially attempting to acquire the target. +RULE_INT(Pathing, MinNodesLeftForLOSCheck, 4) // Only check for LOS when we are down to this many path nodes left to run. // This next rule was put in for situations where the mob and it's target may be on different sides of a 'hazard', e.g. a pit // If the mob has LOS to it's target, even though there is a hazard in it's way, it may break off from the node path and run at // the target, only to later detect the hazard and re-acquire a node path. Depending upon the placement of the path nodes, this // can lead to the mob looping. The rule is intended to allow the mob to at least get closer to it's target each time before // checking LOS and trying to head straight for it. -RULE_INT ( Pathing, MinNodesTraversedForLOSCheck, 3) // Only check for LOS after we have traversed this many path nodes. -RULE_INT ( Pathing, CullNodesFromStart, 1) // Checks LOS from Start point to second node for this many nodes and removes first node if there is LOS -RULE_INT ( Pathing, CullNodesFromEnd, 1) // Checks LOS from End point to second to last node for this many nodes and removes last node if there is LOS -RULE_REAL ( Pathing, CandidateNodeRangeXY, 400) // When searching for path start/end nodes, only nodes within this range will be considered. -RULE_REAL ( Pathing, CandidateNodeRangeZ, 10) // When searching for path start/end nodes, only nodes within this range will be considered. +RULE_INT(Pathing, MinNodesTraversedForLOSCheck, 3) // Only check for LOS after we have traversed this many path nodes. +RULE_INT(Pathing, CullNodesFromStart, 1) // Checks LOS from Start point to second node for this many nodes and removes first node if there is LOS +RULE_INT(Pathing, CullNodesFromEnd, 1) // Checks LOS from End point to second to last node for this many nodes and removes last node if there is LOS +RULE_REAL(Pathing, CandidateNodeRangeXY, 400) // When searching for path start/end nodes, only nodes within this range will be considered. +RULE_REAL(Pathing, CandidateNodeRangeZ, 10) // When searching for path start/end nodes, only nodes within this range will be considered. RULE_CATEGORY_END() -RULE_CATEGORY( Watermap ) +RULE_CATEGORY(Watermap) // enable these to use the water detection code. Requires Water Maps generated by awater utility -RULE_BOOL ( Watermap, CheckWaypointsInWaterWhenLoading, false ) // Does not apply BestZ as waypoints are loaded if they are in water -RULE_BOOL ( Watermap, CheckForWaterAtWaypoints, false) // Check if a mob has moved into/out of water when at waypoints and sets flymode -RULE_BOOL ( Watermap, CheckForWaterWhenMoving, false) // Checks if a mob has moved into/out of water each time it's loc is recalculated -RULE_BOOL ( Watermap, CheckForWaterOnSendTo, false) // Checks if a mob has moved into/out of water on SendTo -RULE_BOOL ( Watermap, CheckForWaterWhenFishing, false) // Only lets a player fish near water (if a water map exists for the zone) -RULE_REAL ( Watermap, FishingRodLength, 30) // How far in front of player water must be for fishing to work -RULE_REAL ( Watermap, FishingLineLength, 100) // If water is more than this far below the player, it is considered too far to fish -RULE_REAL ( Watermap, FishingLineStepSize, 1) // Basic step size for fishing calc, too small and it will eat cpu, too large and it will miss potential water +RULE_BOOL(Watermap, CheckWaypointsInWaterWhenLoading, false) // Does not apply BestZ as waypoints are loaded if they are in water +RULE_BOOL(Watermap, CheckForWaterAtWaypoints, false) // Check if a mob has moved into/out of water when at waypoints and sets flymode +RULE_BOOL(Watermap, CheckForWaterWhenMoving, false) // Checks if a mob has moved into/out of water each time it's loc is recalculated +RULE_BOOL(Watermap, CheckForWaterOnSendTo, false) // Checks if a mob has moved into/out of water on SendTo +RULE_BOOL(Watermap, CheckForWaterWhenFishing, false) // Only lets a player fish near water (if a water map exists for the zone) +RULE_REAL(Watermap, FishingRodLength, 30) // How far in front of player water must be for fishing to work +RULE_REAL(Watermap, FishingLineLength, 100) // If water is more than this far below the player, it is considered too far to fish +RULE_REAL(Watermap, FishingLineStepSize, 1) // Basic step size for fishing calc, too small and it will eat cpu, too large and it will miss potential water RULE_CATEGORY_END() -RULE_CATEGORY( Spells ) -RULE_INT ( Spells, AutoResistDiff, 15) -RULE_REAL ( Spells, ResistChance, 2.0) //chance to resist given no resists and same level -RULE_REAL ( Spells, ResistMod, 0.40) //multiplier, chance to resist = this * ResistAmount -RULE_REAL ( Spells, PartialHitChance, 0.7) //The chance when a spell is resisted that it will partial hit. -RULE_REAL ( Spells, PartialHitChanceFear, 0.25) //The chance when a fear spell is resisted that it will partial hit. -RULE_INT ( Spells, BaseCritChance, 0) //base % chance that everyone has to crit a spell -RULE_INT ( Spells, BaseCritRatio, 100) //base % bonus to damage on a successful spell crit. 100 = 2x damage -RULE_INT ( Spells, WizCritLevel, 12) //level wizards first get spell crits -RULE_INT ( Spells, WizCritChance, 7) //wiz's crit chance, on top of BaseCritChance -RULE_INT ( Spells, WizCritRatio, 0) //wiz's crit bonus, on top of BaseCritRatio (should be 0 for Live-like) -RULE_INT ( Spells, ResistPerLevelDiff, 85) //8.5 resist per level difference. -RULE_INT ( Spells, TranslocateTimeLimit, 0) // If not zero, time in seconds to accept a Translocate. -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, 25) // do not set this higher than 25 until the player profile is removed from the blob +RULE_CATEGORY(Spells) +RULE_INT(Spells, AutoResistDiff, 15) +RULE_REAL(Spells, ResistChance, 2.0) //chance to resist given no resists and same level +RULE_REAL(Spells, ResistMod, 0.40) //multiplier, chance to resist = this * ResistAmount +RULE_REAL(Spells, PartialHitChance, 0.7) //The chance when a spell is resisted that it will partial hit. +RULE_REAL(Spells, PartialHitChanceFear, 0.25) //The chance when a fear spell is resisted that it will partial hit. +RULE_INT(Spells, BaseCritChance, 0) //base % chance that everyone has to crit a spell +RULE_INT(Spells, BaseCritRatio, 100) //base % bonus to damage on a successful spell crit. 100 = 2x damage +RULE_INT(Spells, WizCritLevel, 12) //level wizards first get spell crits +RULE_INT(Spells, WizCritChance, 7) //wiz's crit chance, on top of BaseCritChance +RULE_INT(Spells, WizCritRatio, 0) //wiz's crit bonus, on top of BaseCritRatio (should be 0 for Live-like) +RULE_INT(Spells, ResistPerLevelDiff, 85) //8.5 resist per level difference. +RULE_INT(Spells, TranslocateTimeLimit, 0) // If not zero, time in seconds to accept a Translocate. +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, 25) // 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 -RULE_BOOL( Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized -RULE_INT ( Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0. -RULE_BOOL ( Spells, NPCIgnoreBaseImmunity, true) // Whether or not NPCs get to ignore the BaseImmunityLevel for their spells. -RULE_REAL ( Spells, AvgSpellProcsPerMinute, 6.0) //Adjust rate for sympathetic spell procs -RULE_INT ( Spells, ResistFalloff, 67) //Max that level that will adjust our resist chance based on level modifiers -RULE_INT ( Spells, CharismaEffectiveness, 10) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. -RULE_INT ( Spells, CharismaEffectivenessCap, 255) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. -RULE_BOOL ( Spells, CharismaCharmDuration, false) // Allow CHA resist mod to extend charm duration. -RULE_INT ( Spells, CharmBreakCheckChance, 25) //Determines chance for a charm break check to occur each buff tick. -RULE_INT ( Spells, MaxCastTimeReduction, 50) //Max percent your spell cast time can be reduced by spell haste -RULE_INT ( Spells, RootBreakFromSpells, 55) //Chance for root to break when cast on. -RULE_INT ( Spells, DeathSaveCharismaMod, 3) //Determines how much charisma effects chance of death save firing. -RULE_INT ( Spells, DivineInterventionHeal, 8000) //Divine intervention heal amount. -RULE_INT ( Spells, AdditiveBonusWornType, 0) //Calc worn bonuses to add together (instead of taking highest) if set to THIS worn type. (2=Will covert live items automatically) -RULE_BOOL ( Spells, UseCHAScribeHack, false) //ScribeSpells and TrainDiscs quest functions will ignore entries where field 12 is CHA. What's the best way to do this? -RULE_BOOL ( Spells, BuffLevelRestrictions, true) //Buffs will not land on low level toons like live -RULE_INT ( Spells, RootBreakCheckChance, 70) //Determines chance for a root break check to occur each buff tick. -RULE_INT ( Spells, FearBreakCheckChance, 70) //Determines chance for a fear break check to occur each buff tick. -RULE_INT ( Spells, SuccorFailChance, 2) //Determines chance for a succor spell not to teleport an invidual player -RULE_INT ( Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clients for Fire 'spell projectile'. -RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'. -RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'. -RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file. -RULE_BOOL ( Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects. -RULE_BOOL ( Spells, PreNerfBardAEDoT, false) //Allow bard AOE dots to damage targets when moving. -RULE_INT ( Spells, AI_SpellCastFinishedFailRecast, 800) // AI spell recast time(MS) when an spell is cast but fails (ie stunned). -RULE_INT ( Spells, AI_EngagedNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while engaged. (min time in random) -RULE_INT ( Spells, AI_EngagedNoSpellMaxRecast, 1000) // AI spell recast time(MS) check when no spell is cast engaged.(max time in random) -RULE_INT ( Spells, AI_EngagedBeneficialSelfChance, 100) // Chance during first AI Cast check to do a beneficial spell on self. -RULE_INT ( Spells, AI_EngagedBeneficialOtherChance, 25) // Chance during second AI Cast check to do a beneficial spell on others. -RULE_INT ( Spells, AI_EngagedDetrimentalChance, 20) // Chance during third AI Cast check to do a determental spell on others. -RULE_INT ( Spells, AI_PursueNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while chasing target. (min time in random) -RULE_INT ( Spells, AI_PursueNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) -RULE_INT ( Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target to cast a detrimental spell. -RULE_INT ( Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random) -RULE_INT ( Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) -RULE_INT ( Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others. -RULE_BOOL ( Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false) -RULE_BOOL ( Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014 -RULE_BOOL ( Spells, SwarmPetTargetLock, false) // Use old method of swarm pets target locking till target dies then despawning. -RULE_BOOL ( Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell derived focus effects. -RULE_BOOL ( Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects. -RULE_BOOL ( Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot. -RULE_BOOL ( Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if 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 +RULE_BOOL(Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized +RULE_INT(Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0. +RULE_BOOL(Spells, NPCIgnoreBaseImmunity, true) // Whether or not NPCs get to ignore the BaseImmunityLevel for their spells. +RULE_REAL(Spells, AvgSpellProcsPerMinute, 6.0) //Adjust rate for sympathetic spell procs +RULE_INT(Spells, ResistFalloff, 67) //Max that level that will adjust our resist chance based on level modifiers +RULE_INT(Spells, CharismaEffectiveness, 10) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. +RULE_INT(Spells, CharismaEffectivenessCap, 255) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. +RULE_BOOL(Spells, CharismaCharmDuration, false) // Allow CHA resist mod to extend charm duration. +RULE_INT(Spells, CharmBreakCheckChance, 25) //Determines chance for a charm break check to occur each buff tick. +RULE_INT(Spells, MaxCastTimeReduction, 50) //Max percent your spell cast time can be reduced by spell haste +RULE_INT(Spells, RootBreakFromSpells, 55) //Chance for root to break when cast on. +RULE_INT(Spells, DeathSaveCharismaMod, 3) //Determines how much charisma effects chance of death save firing. +RULE_INT(Spells, DivineInterventionHeal, 8000) //Divine intervention heal amount. +RULE_INT(Spells, AdditiveBonusWornType, 0) //Calc worn bonuses to add together (instead of taking highest) if set to THIS worn type. (2=Will covert live items automatically) +RULE_BOOL(Spells, UseCHAScribeHack, false) //ScribeSpells and TrainDiscs quest functions will ignore entries where field 12 is CHA. What's the best way to do this? +RULE_BOOL(Spells, BuffLevelRestrictions, true) //Buffs will not land on low level toons like live +RULE_INT(Spells, RootBreakCheckChance, 70) //Determines chance for a root break check to occur each buff tick. +RULE_INT(Spells, FearBreakCheckChance, 70) //Determines chance for a fear break check to occur each buff tick. +RULE_INT(Spells, SuccorFailChance, 2) //Determines chance for a succor spell not to teleport an invidual player +RULE_INT(Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clients for Fire 'spell projectile'. +RULE_INT(Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'. +RULE_INT(Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'. +RULE_BOOL(Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file. +RULE_BOOL(Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects. +RULE_BOOL(Spells, PreNerfBardAEDoT, false) //Allow bard AOE dots to damage targets when moving. +RULE_INT(Spells, AI_SpellCastFinishedFailRecast, 800) // AI spell recast time(MS) when an spell is cast but fails (ie stunned). +RULE_INT(Spells, AI_EngagedNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while engaged. (min time in random) +RULE_INT(Spells, AI_EngagedNoSpellMaxRecast, 1000) // AI spell recast time(MS) check when no spell is cast engaged.(max time in random) +RULE_INT(Spells, AI_EngagedBeneficialSelfChance, 100) // Chance during first AI Cast check to do a beneficial spell on self. +RULE_INT(Spells, AI_EngagedBeneficialOtherChance, 25) // Chance during second AI Cast check to do a beneficial spell on others. +RULE_INT(Spells, AI_EngagedDetrimentalChance, 20) // Chance during third AI Cast check to do a determental spell on others. +RULE_INT(Spells, AI_PursueNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while chasing target. (min time in random) +RULE_INT(Spells, AI_PursueNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) +RULE_INT(Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target to cast a detrimental spell. +RULE_INT(Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random) +RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) +RULE_INT(Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others. +RULE_BOOL(Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false) +RULE_BOOL(Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014 +RULE_BOOL(Spells, SwarmPetTargetLock, false) // Use old method of swarm pets target locking till target dies then despawning. +RULE_BOOL(Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell derived focus effects. +RULE_BOOL(Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects. +RULE_BOOL(Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot. +RULE_BOOL(Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if true 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, 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_BOOL ( Combat, UseIntervalAC, true) -RULE_INT ( Combat, PetAttackMagicLevel, 30) -RULE_BOOL ( Combat, EnableFearPathing, true) -RULE_REAL ( Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker. -RULE_INT ( Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee. -RULE_BOOL ( Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it. -RULE_BOOL ( Combat, AdjustProcPerMinute, true) -RULE_REAL ( Combat, AvgProcsPerMinute, 2.0) -RULE_REAL ( Combat, ProcPerMinDexContrib, 0.075) -RULE_REAL ( Combat, BaseProcChance, 0.035) -RULE_REAL ( Combat, ProcDexDivideBy, 11000) -RULE_BOOL ( Combat, AdjustSpecialProcPerMinute, true) //Set PPM for special abilities like HeadShot (Live does this as of 4-14) -RULE_REAL ( Combat, AvgSpecialProcsPerMinute, 2.0) //Unclear what best value is atm. -RULE_REAL ( Combat, BaseHitChance, 69.0) -RULE_REAL ( Combat, NPCBonusHitChance, 26.0) -RULE_REAL ( Combat, HitFalloffMinor, 5.0) //hit will fall off up to 5% over the initial level range -RULE_REAL ( Combat, HitFalloffModerate, 7.0) //hit will fall off up to 7% over the three levels after the initial level range -RULE_REAL ( Combat, HitFalloffMajor, 50.0) //hit will fall off sharply if we're outside the minor and moderate range -RULE_REAL ( Combat, HitBonusPerLevel, 1.2) //You gain this % of hit for every level you are above your target -RULE_REAL ( Combat, WeaponSkillFalloff, 0.33) //For every weapon skill point that's not maxed you lose this % of hit -RULE_REAL ( Combat, ArcheryHitPenalty, 0.25) //Archery has a hit penalty to try to help balance it with the plethora of long term +hit modifiers for it -RULE_REAL ( Combat, AgiHitFactor, 0.01) -RULE_REAL ( Combat, MinChancetoHit, 5.0) //Minimum % chance to hit with regular melee/ranged -RULE_REAL ( Combat, MaxChancetoHit, 95.0) //Maximum % chance to hit with regular melee/ranged -RULE_INT ( Combat, MinRangedAttackDist, 25) //Minimum Distance to use Ranged Attacks -RULE_BOOL ( Combat, ArcheryBonusRequiresStationary, true) //does the 2x archery bonus chance require a stationary npc -RULE_REAL ( Combat, ArcheryBaseDamageBonus, 1) // % Modifier to Base Archery Damage (.5 = 50% base damage, 1 = 100%, 2 = 200%) -RULE_REAL ( Combat, ArcheryNPCMultiplier, 1.0) // this is multiplied by the regular dmg to get the archery dmg -RULE_BOOL ( Combat, AssistNoTargetSelf, true) //when assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like) -RULE_INT ( Combat, MaxRampageTargets, 3) //max number of people hit with rampage -RULE_INT ( Combat, DefaultRampageTargets, 1) // default number of people to hit with rampage -RULE_BOOL ( Combat, RampageHitsTarget, false) // rampage will hit the target if it still has targets left -RULE_INT ( Combat, MaxFlurryHits, 2) //max number of extra hits from flurry -RULE_INT ( Combat, MonkDamageTableBonus, 5) //% bonus monks get to their damage table calcs -RULE_INT ( Combat, FlyingKickBonus, 25) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, DragonPunchBonus, 20) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, EagleStrikeBonus, 15) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, TigerClawBonus, 10) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, RoundKickBonus, 5) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, FrenzyBonus, 0) //% Modifier to damage -RULE_BOOL ( Combat, ProcTargetOnly, true) //true = procs will only affect our target, false = procs will affect all of our targets -RULE_REAL ( Combat, NPCACFactor, 2.25) -RULE_INT ( Combat, ClothACSoftcap, 75) -RULE_INT ( Combat, LeatherACSoftcap, 100) -RULE_INT ( Combat, MonkACSoftcap, 120) -RULE_INT ( Combat, ChainACSoftcap, 200) -RULE_INT ( Combat, PlateACSoftcap, 300) -RULE_REAL ( Combat, AAMitigationACFactor, 3.0) -RULE_REAL ( Combat, WarriorACSoftcapReturn, 0.45) -RULE_REAL ( Combat, KnightACSoftcapReturn, 0.33) -RULE_REAL ( Combat, LowPlateChainACSoftcapReturn, 0.23) -RULE_REAL ( Combat, LowChainLeatherACSoftcapReturn, 0.17) -RULE_REAL ( Combat, CasterACSoftcapReturn, 0.06) -RULE_REAL ( Combat, MiscACSoftcapReturn, 0.3) -RULE_BOOL ( Combat, OldACSoftcapRules, false) // use old softcaps -RULE_BOOL ( Combat, UseOldDamageIntervalRules, false) // use old damage formulas for everything -RULE_REAL ( Combat, WarACSoftcapReturn, 0.3448) // new AC returns -RULE_REAL ( Combat, ClrRngMnkBrdACSoftcapReturn, 0.3030) -RULE_REAL ( Combat, PalShdACSoftcapReturn, 0.3226) -RULE_REAL ( Combat, DruNecWizEncMagACSoftcapReturn, 0.2000) -RULE_REAL ( Combat, RogShmBstBerACSoftcapReturn, 0.2500) -RULE_REAL ( Combat, SoftcapFactor, 1.88) -RULE_REAL ( Combat, ACthac0Factor, 0.55) -RULE_REAL ( Combat, ACthac20Factor, 0.55) -RULE_INT ( Combat, HitCapPre20, 40) // live has it capped at 40 for whatever dumb reason... this is mainly for custom servers -RULE_INT ( Combat, HitCapPre10, 20) // live has it capped at 20, see above :p -RULE_INT ( Combat, MinHastedDelay, 400) // how fast we can get with haste. -RULE_REAL ( Combat, AvgDefProcsPerMinute, 2.0) -RULE_REAL ( Combat, DefProcPerMinAgiContrib, 0.075) //How much agility contributes to defensive proc rate -RULE_INT ( Combat, SpecialAttackACBonus, 15) //Percent amount of damage per AC gained for certain special attacks (damage = AC*SpecialAttackACBonus/100). -RULE_INT ( Combat, NPCFlurryChance, 20) // Chance for NPC to flurry. +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, 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_BOOL(Combat, UseIntervalAC, true) +RULE_INT(Combat, PetAttackMagicLevel, 30) +RULE_BOOL(Combat, EnableFearPathing, true) +RULE_REAL(Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker. +RULE_INT(Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee. +RULE_BOOL(Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it. +RULE_BOOL(Combat, AdjustProcPerMinute, true) +RULE_REAL(Combat, AvgProcsPerMinute, 2.0) +RULE_REAL(Combat, ProcPerMinDexContrib, 0.075) +RULE_REAL(Combat, BaseProcChance, 0.035) +RULE_REAL(Combat, ProcDexDivideBy, 11000) +RULE_BOOL(Combat, AdjustSpecialProcPerMinute, true) //Set PPM for special abilities like HeadShot (Live does this as of 4-14) +RULE_REAL(Combat, AvgSpecialProcsPerMinute, 2.0) //Unclear what best value is atm. +RULE_REAL(Combat, BaseHitChance, 69.0) +RULE_REAL(Combat, NPCBonusHitChance, 26.0) +RULE_REAL(Combat, HitFalloffMinor, 5.0) //hit will fall off up to 5% over the initial level range +RULE_REAL(Combat, HitFalloffModerate, 7.0) //hit will fall off up to 7% over the three levels after the initial level range +RULE_REAL(Combat, HitFalloffMajor, 50.0) //hit will fall off sharply if we're outside the minor and moderate range +RULE_REAL(Combat, HitBonusPerLevel, 1.2) //You gain this % of hit for every level you are above your target +RULE_REAL(Combat, WeaponSkillFalloff, 0.33) //For every weapon skill point that's not maxed you lose this % of hit +RULE_REAL(Combat, ArcheryHitPenalty, 0.25) //Archery has a hit penalty to try to help balance it with the plethora of long term +hit modifiers for it +RULE_REAL(Combat, AgiHitFactor, 0.01) +RULE_REAL(Combat, MinChancetoHit, 5.0) //Minimum % chance to hit with regular melee/ranged +RULE_REAL(Combat, MaxChancetoHit, 95.0) //Maximum % chance to hit with regular melee/ranged +RULE_INT(Combat, MinRangedAttackDist, 25) //Minimum Distance to use Ranged Attacks +RULE_BOOL(Combat, ArcheryBonusRequiresStationary, true) //does the 2x archery bonus chance require a stationary npc +RULE_REAL(Combat, ArcheryBaseDamageBonus, 1) // % Modifier to Base Archery Damage (.5 = 50% base damage, 1 = 100%, 2 = 200%) +RULE_REAL(Combat, ArcheryNPCMultiplier, 1.0) // this is multiplied by the regular dmg to get the archery dmg +RULE_BOOL(Combat, AssistNoTargetSelf, true) //when assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like) +RULE_INT(Combat, MaxRampageTargets, 3) //max number of people hit with rampage +RULE_INT(Combat, DefaultRampageTargets, 1) // default number of people to hit with rampage +RULE_BOOL(Combat, RampageHitsTarget, false) // rampage will hit the target if it still has targets left +RULE_INT(Combat, MaxFlurryHits, 2) //max number of extra hits from flurry +RULE_INT(Combat, MonkDamageTableBonus, 5) //% bonus monks get to their damage table calcs +RULE_INT(Combat, FlyingKickBonus, 25) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, DragonPunchBonus, 20) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, EagleStrikeBonus, 15) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, TigerClawBonus, 10) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, RoundKickBonus, 5) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, FrenzyBonus, 0) //% Modifier to damage +RULE_INT(Combat, BackstabBonus, 0) //% Modifier to damage +RULE_BOOL(Combat, ProcTargetOnly, true) //true = procs will only affect our target, false = procs will affect all of our targets +RULE_REAL(Combat, NPCACFactor, 2.25) +RULE_INT(Combat, ClothACSoftcap, 75) +RULE_INT(Combat, LeatherACSoftcap, 100) +RULE_INT(Combat, MonkACSoftcap, 120) +RULE_INT(Combat, ChainACSoftcap, 200) +RULE_INT(Combat, PlateACSoftcap, 300) +RULE_REAL(Combat, AAMitigationACFactor, 3.0) +RULE_REAL(Combat, WarriorACSoftcapReturn, 0.45) +RULE_REAL(Combat, KnightACSoftcapReturn, 0.33) +RULE_REAL(Combat, LowPlateChainACSoftcapReturn, 0.23) +RULE_REAL(Combat, LowChainLeatherACSoftcapReturn, 0.17) +RULE_REAL(Combat, CasterACSoftcapReturn, 0.06) +RULE_REAL(Combat, MiscACSoftcapReturn, 0.3) +RULE_BOOL(Combat, OldACSoftcapRules, false) // use old softcaps +RULE_BOOL(Combat, UseOldDamageIntervalRules, false) // use old damage formulas for everything +RULE_REAL(Combat, WarACSoftcapReturn, 0.3448) // new AC returns +RULE_REAL(Combat, ClrRngMnkBrdACSoftcapReturn, 0.3030) +RULE_REAL(Combat, PalShdACSoftcapReturn, 0.3226) +RULE_REAL(Combat, DruNecWizEncMagACSoftcapReturn, 0.2000) +RULE_REAL(Combat, RogShmBstBerACSoftcapReturn, 0.2500) +RULE_REAL(Combat, SoftcapFactor, 1.88) +RULE_REAL(Combat, ACthac0Factor, 0.55) +RULE_REAL(Combat, ACthac20Factor, 0.55) +RULE_INT(Combat, HitCapPre20, 40) // live has it capped at 40 for whatever dumb reason... this is mainly for custom servers +RULE_INT(Combat, HitCapPre10, 20) // live has it capped at 20, see above :p +RULE_INT(Combat, MinHastedDelay, 400) // how fast we can get with haste. +RULE_REAL(Combat, AvgDefProcsPerMinute, 2.0) +RULE_REAL(Combat, DefProcPerMinAgiContrib, 0.075) //How much agility contributes to defensive proc rate +RULE_INT(Combat, SpecialAttackACBonus, 15) //Percent amount of damage per AC gained for certain special attacks (damage = AC*SpecialAttackACBonus/100). +RULE_INT(Combat, NPCFlurryChance, 20) // Chance for NPC to flurry. RULE_BOOL (Combat,TauntOverLevel, 1) //Allows you to taunt NPC's over warriors level. RULE_REAL (Combat,TauntSkillFalloff, 0.33)//For every taunt skill point that's not maxed you lose this % chance to taunt. RULE_BOOL (Combat,EXPFromDmgShield, false) //Determine if damage from a damage shield counts for EXP gain. -RULE_INT ( Combat, MonkACBonusWeight, 15) -RULE_INT ( Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target -RULE_INT ( Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers -RULE_BOOL ( Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll -RULE_INT ( Combat, ArcheryBonusChance, 50) -RULE_INT ( Combat, BerserkerFrenzyStart, 35) -RULE_INT ( Combat, BerserkerFrenzyEnd, 45) -RULE_BOOL ( Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round -RULE_BOOL ( Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly. -RULE_BOOL ( Combat, MeleePush, true) // enable melee push -RULE_INT ( Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad +RULE_INT(Combat, MonkACBonusWeight, 15) +RULE_INT(Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target +RULE_INT(Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers +RULE_BOOL(Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll +RULE_INT(Combat, ArcheryBonusChance, 50) +RULE_INT(Combat, BerserkerFrenzyStart, 35) +RULE_INT(Combat, BerserkerFrenzyEnd, 45) +RULE_BOOL(Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round +RULE_BOOL(Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly. +RULE_BOOL(Combat, MeleePush, true) // enable melee push +RULE_INT(Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad RULE_CATEGORY_END() -RULE_CATEGORY( NPC ) -RULE_INT ( NPC, MinorNPCCorpseDecayTimeMS, 450000 ) //level<55 -RULE_INT ( NPC, MajorNPCCorpseDecayTimeMS, 1500000 ) //level>=55 -RULE_INT ( NPC, CorpseUnlockTimer, 150000 ) -RULE_INT ( NPC, EmptyNPCCorpseDecayTimeMS, 0 ) +RULE_CATEGORY(NPC) +RULE_INT(NPC, MinorNPCCorpseDecayTimeMS, 450000) //level<55 +RULE_INT(NPC, MajorNPCCorpseDecayTimeMS, 1500000) //level>=55 +RULE_INT(NPC, CorpseUnlockTimer, 150000) +RULE_INT(NPC, EmptyNPCCorpseDecayTimeMS, 0) RULE_BOOL (NPC, UseItemBonusesForNonPets, true) -RULE_INT ( NPC, SayPauseTimeInSec, 5) -RULE_INT ( NPC, OOCRegen, 0) -RULE_BOOL ( NPC, BuffFriends, false ) -RULE_BOOL ( NPC, EnableNPCQuestJournal, false) -RULE_INT ( NPC, LastFightingDelayMovingMin, 10000) -RULE_INT ( NPC, LastFightingDelayMovingMax, 20000) -RULE_BOOL ( NPC, SmartLastFightingDelayMoving, true) -RULE_BOOL ( NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPCs that don't have an EVENT_TRADE sub in their script -RULE_INT ( NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage -RULE_BOOL ( NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage -RULE_BOOL ( NPC, EnableMeritBasedFaction, false) // If set to true, faction will given in the same way as experience (solo/group/raid) +RULE_INT(NPC, SayPauseTimeInSec, 5) +RULE_INT(NPC, OOCRegen, 0) +RULE_BOOL(NPC, BuffFriends, false) +RULE_BOOL(NPC, EnableNPCQuestJournal, false) +RULE_INT(NPC, LastFightingDelayMovingMin, 10000) +RULE_INT(NPC, LastFightingDelayMovingMax, 20000) +RULE_BOOL(NPC, SmartLastFightingDelayMoving, true) +RULE_BOOL(NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPCs that don't have an EVENT_TRADE sub in their script +RULE_INT(NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage +RULE_BOOL(NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage +RULE_BOOL(NPC, EnableMeritBasedFaction, false) // If set to true, faction will given in the same way as experience (solo/group/raid) RULE_CATEGORY_END() -RULE_CATEGORY ( Aggro ) -RULE_BOOL ( Aggro, SmartAggroList, true ) -RULE_INT ( Aggro, SittingAggroMod, 35 ) //35% -RULE_INT ( Aggro, MeleeRangeAggroMod, 10 ) //10% -RULE_INT ( Aggro, CurrentTargetAggroMod, 0 ) //0% -- will prefer our current target to any other; makes it harder for our npcs to switch targets. -RULE_INT ( Aggro, CriticallyWoundedAggroMod, 100 ) //100% -RULE_INT ( Aggro, SpellAggroMod, 100 ) -RULE_INT ( Aggro, SongAggroMod, 33 ) -RULE_INT ( Aggro, PetSpellAggroMod, 10 ) -RULE_REAL ( Aggro, TunnelVisionAggroMod, 0.75 ) //people not currently the top hate generate this much hate on a Tunnel Vision mob -RULE_INT ( Aggro, MaxStunProcAggro, 400 ) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add. -RULE_INT ( Aggro, IntAggroThreshold, 75 ) // Int <= this will aggro regardless of level difference. +RULE_CATEGORY(Aggro) +RULE_BOOL(Aggro, SmartAggroList, true) +RULE_INT(Aggro, SittingAggroMod, 35) //35% +RULE_INT(Aggro, MeleeRangeAggroMod, 10) //10% +RULE_INT(Aggro, CurrentTargetAggroMod, 0) //0% -- will prefer our current target to any other; makes it harder for our npcs to switch targets. +RULE_INT(Aggro, CriticallyWoundedAggroMod, 100) //100% +RULE_INT(Aggro, SpellAggroMod, 100) +RULE_INT(Aggro, SongAggroMod, 33) +RULE_INT(Aggro, PetSpellAggroMod, 10) +RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate generate this much hate on a Tunnel Vision mob +RULE_INT(Aggro, MaxStunProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add. +RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference. RULE_CATEGORY_END() -RULE_CATEGORY ( TaskSystem) -RULE_BOOL ( TaskSystem, EnableTaskSystem, true) // Globally enable or disable the Task system -RULE_INT ( TaskSystem, PeriodicCheckTimer, 5) // Seconds between checks for failed tasks. Also used by the 'Touch' activity -RULE_BOOL ( TaskSystem, RecordCompletedTasks, true) -RULE_BOOL ( TaskSystem, RecordCompletedOptionalActivities, false) -RULE_BOOL ( TaskSystem, KeepOneRecordPerCompletedTask, true) -RULE_BOOL ( TaskSystem, EnableTaskProximity, true) +RULE_CATEGORY(TaskSystem) +RULE_BOOL(TaskSystem, EnableTaskSystem, true) // Globally enable or disable the Task system +RULE_INT(TaskSystem, PeriodicCheckTimer, 5) // Seconds between checks for failed tasks. Also used by the 'Touch' activity +RULE_BOOL(TaskSystem, RecordCompletedTasks, true) +RULE_BOOL(TaskSystem, RecordCompletedOptionalActivities, false) +RULE_BOOL(TaskSystem, KeepOneRecordPerCompletedTask, true) +RULE_BOOL(TaskSystem, EnableTaskProximity, true) RULE_CATEGORY_END() #ifdef BOTS -RULE_CATEGORY ( Bots ) -RULE_REAL ( Bots, BotManaRegen, 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, BotFinishBuffing, false ) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. -RULE_INT ( Bots, CreateBotCount, 150 ) // Number of bots that each account can create -RULE_INT ( Bots, SpawnBotCount, 71 ) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid -RULE_BOOL ( Bots, BotQuest, 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, BotGroupBuffing, 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_BOOL ( Bots, BotSpellQuest, false ) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. -RULE_INT ( Bots, BotAAExpansion, 8 ) // Bots get AAs through this expansion -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. -RULE_BOOL ( Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) +RULE_CATEGORY(Bots) +RULE_REAL(Bots, BotManaRegen, 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, BotFinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. +RULE_INT(Bots, CreateBotCount, 150) // Number of bots that each account can create +RULE_INT(Bots, SpawnBotCount, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid +RULE_BOOL(Bots, BotQuest, 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, BotGroupBuffing, 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_BOOL(Bots, BotSpellQuest, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. +RULE_INT(Bots, BotAAExpansion, 8) // Bots get AAs through this expansion +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. +RULE_BOOL(Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) RULE_CATEGORY_END() #endif -RULE_CATEGORY ( Chat ) -RULE_BOOL ( Chat, ServerWideOOC, true) -RULE_BOOL ( Chat, ServerWideAuction, true) -RULE_BOOL ( Chat, EnableVoiceMacros, true) -RULE_BOOL ( Chat, EnableMailKeyIPVerification, true) -RULE_BOOL ( Chat, EnableAntiSpam, true) -RULE_BOOL ( Chat, SuppressCommandErrors, false) // Do not suppress by default -RULE_INT ( Chat, MinStatusToBypassAntiSpam, 100) -RULE_INT ( Chat, MinimumMessagesPerInterval, 4) -RULE_INT ( Chat, MaximumMessagesPerInterval, 12) -RULE_INT ( Chat, MaxMessagesBeforeKick, 20) -RULE_INT ( Chat, IntervalDurationMS, 60000) -RULE_INT ( Chat, KarmaUpdateIntervalMS, 1200000) -RULE_INT ( Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able to talk in ooc/auction/chat below the level limit -RULE_INT ( Chat, GlobalChatLevelLimit, 8) //level limit you need to of reached to talk in ooc/auction/chat if your karma is too low. +RULE_CATEGORY(Chat) +RULE_BOOL(Chat, ServerWideOOC, true) +RULE_BOOL(Chat, ServerWideAuction, true) +RULE_BOOL(Chat, EnableVoiceMacros, true) +RULE_BOOL(Chat, EnableMailKeyIPVerification, true) +RULE_BOOL(Chat, EnableAntiSpam, true) +RULE_BOOL(Chat, SuppressCommandErrors, false) // Do not suppress by default +RULE_INT(Chat, MinStatusToBypassAntiSpam, 100) +RULE_INT(Chat, MinimumMessagesPerInterval, 4) +RULE_INT(Chat, MaximumMessagesPerInterval, 12) +RULE_INT(Chat, MaxMessagesBeforeKick, 20) +RULE_INT(Chat, IntervalDurationMS, 60000) +RULE_INT(Chat, KarmaUpdateIntervalMS, 1200000) +RULE_INT(Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able to talk in ooc/auction/chat below the level limit +RULE_INT(Chat, GlobalChatLevelLimit, 8) //level limit you need to of reached to talk in ooc/auction/chat if your karma is too low. RULE_CATEGORY_END() -RULE_CATEGORY ( Merchant ) -RULE_BOOL ( Merchant, UsePriceMod, true) // Use faction/charisma price modifiers. -RULE_REAL ( Merchant, SellCostMod, 1.05) // Modifier for NPC sell price. -RULE_REAL ( Merchant, BuyCostMod, 0.95) // Modifier for NPC buy price. -RULE_INT ( Merchant, PriceBonusPct, 4) // Determines maximum price bonus from having good faction/CHA. Value is a percent. -RULE_INT ( Merchant, PricePenaltyPct, 4) // Determines maximum price penalty from having bad faction/CHA. Value is a percent. -RULE_REAL( Merchant, ChaBonusMod, 3.45) // Determines CHA cap, from 104 CHA. 3.45 is 132 CHA at apprehensive. 0.34 is 400 CHA at apprehensive. -RULE_REAL ( Merchant, ChaPenaltyMod, 1.52) // Determines CHA bottom, up to 102 CHA. 1.52 is 37 CHA at apprehensive. 0.98 is 0 CHA at apprehensive. -RULE_BOOL ( Merchant, EnableAltCurrencySell, true) // Enables the ability to resell items to alternate currency merchants +RULE_CATEGORY(Merchant) +RULE_BOOL(Merchant, UsePriceMod, true) // Use faction/charisma price modifiers. +RULE_REAL(Merchant, SellCostMod, 1.05) // Modifier for NPC sell price. +RULE_REAL(Merchant, BuyCostMod, 0.95) // Modifier for NPC buy price. +RULE_INT(Merchant, PriceBonusPct, 4) // Determines maximum price bonus from having good faction/CHA. Value is a percent. +RULE_INT(Merchant, PricePenaltyPct, 4) // Determines maximum price penalty from having bad faction/CHA. Value is a percent. +RULE_REAL(Merchant, ChaBonusMod, 3.45) // Determines CHA cap, from 104 CHA. 3.45 is 132 CHA at apprehensive. 0.34 is 400 CHA at apprehensive. +RULE_REAL(Merchant, ChaPenaltyMod, 1.52) // Determines CHA bottom, up to 102 CHA. 1.52 is 37 CHA at apprehensive. 0.98 is 0 CHA at apprehensive. +RULE_BOOL(Merchant, EnableAltCurrencySell, true) // Enables the ability to resell items to alternate currency merchants RULE_CATEGORY_END() -RULE_CATEGORY ( Bazaar ) -RULE_BOOL ( Bazaar, AuditTrail, false) -RULE_INT ( Bazaar, MaxSearchResults, 50) -RULE_BOOL ( Bazaar, EnableWarpToTrader, true) -RULE_INT ( Bazaar, MaxBarterSearchResults, 200) // The max results returned in the /barter search +RULE_CATEGORY(Bazaar) +RULE_BOOL(Bazaar, AuditTrail, false) +RULE_INT(Bazaar, MaxSearchResults, 50) +RULE_BOOL(Bazaar, EnableWarpToTrader, true) +RULE_INT(Bazaar, MaxBarterSearchResults, 200) // The max results returned in the /barter search RULE_CATEGORY_END() -RULE_CATEGORY ( Mail ) -RULE_BOOL ( Mail, EnableMailSystem, true) // If false, client won't bring up the Mail window. -RULE_INT ( Mail, ExpireTrash, 0) // Time in seconds. 0 will delete all messages in the trash when the mailserver starts -RULE_INT ( Mail, ExpireRead, 31536000 ) // 1 Year. Set to -1 for never -RULE_INT ( Mail, ExpireUnread, 31536000 ) // 1 Year. Set to -1 for never +RULE_CATEGORY(Mail) +RULE_BOOL(Mail, EnableMailSystem, true) // If false, client won't bring up the Mail window. +RULE_INT(Mail, ExpireTrash, 0) // Time in seconds. 0 will delete all messages in the trash when the mailserver starts +RULE_INT(Mail, ExpireRead, 31536000) // 1 Year. Set to -1 for never +RULE_INT(Mail, ExpireUnread, 31536000) // 1 Year. Set to -1 for never RULE_CATEGORY_END() -RULE_CATEGORY ( Channels ) -RULE_INT ( Channels, RequiredStatusAdmin, 251) // Required status to administer chat channels -RULE_INT ( Channels, RequiredStatusListAll, 251) // Required status to list all chat channels -RULE_INT ( Channels, DeleteTimer, 1440) // Empty password protected channels will be deleted after this many minutes +RULE_CATEGORY(Channels) +RULE_INT(Channels, RequiredStatusAdmin, 251) // Required status to administer chat channels +RULE_INT(Channels, RequiredStatusListAll, 251) // Required status to list all chat channels +RULE_INT(Channels, DeleteTimer, 1440) // Empty password protected channels will be deleted after this many minutes RULE_CATEGORY_END() -RULE_CATEGORY ( EventLog ) -RULE_BOOL ( EventLog, RecordSellToMerchant, false ) // Record sales from a player to an NPC merchant in eventlog table -RULE_BOOL ( EventLog, RecordBuyFromMerchant, false ) // Record purchases by a player from an NPC merchant in eventlog table +RULE_CATEGORY(EventLog) +RULE_BOOL(EventLog, RecordSellToMerchant, false) // Record sales from a player to an NPC merchant in eventlog table +RULE_BOOL(EventLog, RecordBuyFromMerchant, false) // Record purchases by a player from an NPC merchant in eventlog table RULE_CATEGORY_END() -RULE_CATEGORY ( Adventure ) -RULE_INT ( Adventure, MinNumberForGroup, 2 ) -RULE_INT ( Adventure, MaxNumberForGroup, 6 ) -RULE_INT ( Adventure, MinNumberForRaid, 18 ) -RULE_INT ( Adventure, MaxNumberForRaid, 36 ) -RULE_INT ( Adventure, MaxLevelRange, 9 ) -RULE_INT ( Adventure, NumberKillsForBossSpawn, 45) -RULE_REAL ( Adventure, DistanceForRescueAccept, 10000.0) -RULE_REAL ( Adventure, DistanceForRescueComplete, 2500.0) -RULE_INT ( Adventure, ItemIDToEnablePorts, 41000 ) //0 to disable, otherwise using a LDoN portal will require the user to have this item. -RULE_INT ( Adventure, LDoNTrapDistanceUse, 625 ) -RULE_REAL ( Adventure, LDoNBaseTrapDifficulty, 15.0 ) -RULE_REAL ( Adventure, LDoNCriticalFailTrapThreshold, 10.0 ) -RULE_INT ( Adventure, LDoNAdventureExpireTime, 1800) //30 minutes to expire +RULE_CATEGORY(Adventure) +RULE_INT(Adventure, MinNumberForGroup, 2) +RULE_INT(Adventure, MaxNumberForGroup, 6) +RULE_INT(Adventure, MinNumberForRaid, 18) +RULE_INT(Adventure, MaxNumberForRaid, 36) +RULE_INT(Adventure, MaxLevelRange, 9) +RULE_INT(Adventure, NumberKillsForBossSpawn, 45) +RULE_REAL(Adventure, DistanceForRescueAccept, 10000.0) +RULE_REAL(Adventure, DistanceForRescueComplete, 2500.0) +RULE_INT(Adventure, ItemIDToEnablePorts, 41000) //0 to disable, otherwise using a LDoN portal will require the user to have this item. +RULE_INT(Adventure, LDoNTrapDistanceUse, 625) +RULE_REAL(Adventure, LDoNBaseTrapDifficulty, 15.0) +RULE_REAL(Adventure, LDoNCriticalFailTrapThreshold, 10.0) +RULE_INT(Adventure, LDoNAdventureExpireTime, 1800) //30 minutes to expire RULE_CATEGORY_END() -RULE_CATEGORY ( AA ) -RULE_INT ( AA, ExpPerPoint, 23976503) //Amount of exp per AA. Is the same as the amount of exp to go from level 51 to level 52. -RULE_BOOL ( AA, Stacking, true) //Allow AA that belong to the same group to stack on SOF+ clients. +RULE_CATEGORY(AA) +RULE_INT(AA, ExpPerPoint, 23976503) //Amount of exp per AA. Is the same as the amount of exp to go from level 51 to level 52. +RULE_BOOL(AA, Stacking, true) //Allow AA that belong to the same group to stack on SOF+ clients. RULE_CATEGORY_END() -RULE_CATEGORY( Console ) -RULE_INT ( Console, SessionTimeOut, 600000 ) // Amount of time in ms for the console session to time out +RULE_CATEGORY(Console) +RULE_INT(Console, SessionTimeOut, 600000) // Amount of time in ms for the console session to time out RULE_CATEGORY_END() -RULE_CATEGORY( QueryServ ) -RULE_BOOL( QueryServ, PlayerLogChat, false) // Logs Player Chat -RULE_BOOL( QueryServ, PlayerLogTrades, false) // Logs Player Trades -RULE_BOOL( QueryServ, PlayerLogHandins, false) // Logs Player Handins -RULE_BOOL( QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills -RULE_BOOL( QueryServ, PlayerLogDeletes, false) // Logs Player Deletes -RULE_BOOL( QueryServ, PlayerLogMoves, false) // Logs Player Moves -RULE_BOOL( QueryServ, PlayerLogMerchantTransactions, false) // Logs Merchant Transactions -RULE_BOOL( QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events -RULE_BOOL( QueryServ, PlayerLogDropItem, false) // Logs Player Drop Item -RULE_BOOL( QueryServ, PlayerLogZone, false) // Logs Player Zone Events -RULE_BOOL( QueryServ, PlayerLogDeaths, false) // Logs Player Deaths -RULE_BOOL( QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State -RULE_BOOL( QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling -RULE_BOOL( QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates -RULE_BOOL( QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates -RULE_BOOL( QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates -RULE_BOOL( QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions -RULE_BOOL( QueryServ, PlayerLogAAPurchases, false) // Log Player AA Purchases -RULE_BOOL( QueryServ, PlayerLogTradeSkillEvents, false) // Log Player Tradeskill Transactions -RULE_BOOL( QueryServ, PlayerLogIssuedCommandes, false ) // Log Player Issued Commands -RULE_BOOL( QueryServ, PlayerLogMoneyTransactions, false) // Log Player Money Transaction/Splits -RULE_BOOL( QueryServ, PlayerLogAlternateCurrencyTransactions, false) // Log Ploayer Alternate Currency Transactions +RULE_CATEGORY(QueryServ) +RULE_BOOL(QueryServ, PlayerLogChat, false) // Logs Player Chat +RULE_BOOL(QueryServ, PlayerLogTrades, false) // Logs Player Trades +RULE_BOOL(QueryServ, PlayerLogHandins, false) // Logs Player Handins +RULE_BOOL(QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills +RULE_BOOL(QueryServ, PlayerLogDeletes, false) // Logs Player Deletes +RULE_BOOL(QueryServ, PlayerLogMoves, false) // Logs Player Moves +RULE_BOOL(QueryServ, PlayerLogMerchantTransactions, false) // Logs Merchant Transactions +RULE_BOOL(QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events +RULE_BOOL(QueryServ, PlayerLogDropItem, false) // Logs Player Drop Item +RULE_BOOL(QueryServ, PlayerLogZone, false) // Logs Player Zone Events +RULE_BOOL(QueryServ, PlayerLogDeaths, false) // Logs Player Deaths +RULE_BOOL(QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State +RULE_BOOL(QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling +RULE_BOOL(QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates +RULE_BOOL(QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates +RULE_BOOL(QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates +RULE_BOOL(QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions +RULE_BOOL(QueryServ, PlayerLogAAPurchases, false) // Log Player AA Purchases +RULE_BOOL(QueryServ, PlayerLogTradeSkillEvents, false) // Log Player Tradeskill Transactions +RULE_BOOL(QueryServ, PlayerLogIssuedCommandes, false) // Log Player Issued Commands +RULE_BOOL(QueryServ, PlayerLogMoneyTransactions, false) // Log Player Money Transaction/Splits +RULE_BOOL(QueryServ, PlayerLogAlternateCurrencyTransactions, false) // Log Ploayer Alternate Currency Transactions RULE_CATEGORY_END() -RULE_CATEGORY( Inventory ) -RULE_BOOL ( Inventory, EnforceAugmentRestriction, true) // Forces augment slot restrictions -RULE_BOOL ( Inventory, EnforceAugmentUsability, true) // Forces augmented item usability -RULE_BOOL ( Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation -RULE_BOOL ( Inventory, DeleteTransformationMold, true) //False if you want mold to last forever -RULE_BOOL ( Inventory, AllowAnyWeaponTransformation, false) //Weapons can use any weapon transformation -RULE_BOOL ( Inventory, TransformSummonedBags, false) //Transforms summoned bags into disenchanted ones instead of deleting +RULE_CATEGORY(Inventory) +RULE_BOOL(Inventory, EnforceAugmentRestriction, true) // Forces augment slot restrictions +RULE_BOOL(Inventory, EnforceAugmentUsability, true) // Forces augmented item usability +RULE_BOOL(Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation +RULE_BOOL(Inventory, DeleteTransformationMold, true) //False if you want mold to last forever +RULE_BOOL(Inventory, AllowAnyWeaponTransformation, false) //Weapons can use any weapon transformation +RULE_BOOL(Inventory, TransformSummonedBags, false) //Transforms summoned bags into disenchanted ones instead of deleting RULE_CATEGORY_END() -RULE_CATEGORY( Client ) -RULE_BOOL( Client, UseLiveFactionMessage, false) // Allows players to see faction adjustments like Live +RULE_CATEGORY(Client) +RULE_BOOL(Client, UseLiveFactionMessage, false) // Allows players to see faction adjustments like Live RULE_CATEGORY_END() #undef RULE_CATEGORY diff --git a/zone/bot.cpp b/zone/bot.cpp index 9846173ba..3a9d46e97 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6640,10 +6640,10 @@ 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); + 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); } else { - max_hit = ((((2 * backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1); + 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); } diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index a3557d021..b844e9ca1 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -618,11 +618,11 @@ 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; + 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; } else{ - max_hit = (((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1;; + 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; } From 635ac692eaa3492cdd9a36c62b19612ece91df55 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 19 Jun 2015 21:48:34 -0400 Subject: [PATCH 199/846] Fix merge ... --- zone/bot.cpp | 271 +++++++++++++++++++++++++-------------------------- 1 file changed, 134 insertions(+), 137 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 0d601dec7..9dae2fc6a 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -172,17 +172,17 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to end_regen = CalcEnduranceRegen(); if(cur_hp > max_hp) cur_hp = max_hp; - + if(cur_hp <= 0) { SetHP(max_hp/5); SetMana(0); BuffFadeAll(); SpellOnTarget(756, this); // Rezz effects } - + if(cur_mana > max_mana) cur_mana = max_mana; - + cur_end = max_end; } @@ -1140,7 +1140,7 @@ void Bot::GenerateArmorClass() { iksarlevel -= 10; if(iksarlevel > 25) iksarlevel = 25; - + if(iksarlevel > 0) displayed += (iksarlevel * 12 / 10); } @@ -1535,7 +1535,7 @@ bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { *errorMessage = std::string(results.ErrorMessage()); return false; } - + if (results.RowCount()) return false; @@ -1568,7 +1568,7 @@ bool Bot::Save() { auto botOwner = GetBotOwner(); if (botOwner) botOwner->Message(13, results.ErrorMessage().c_str()); - + return false; } @@ -1607,7 +1607,7 @@ bool Bot::Save() { auto botOwner = GetBotOwner(); if (botOwner) botOwner->Message(13, results.ErrorMessage().c_str()); - + return false; } SaveBuffs(); @@ -2043,7 +2043,7 @@ void Bot::BotMeditate(bool isSitting) { if(IsSitting()) Stand(); } - + if(IsSitting()) { if(!rest_timer.Enabled()) rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); @@ -2087,14 +2087,14 @@ void Bot::BotRangedAttack(Mob* other) { 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); @@ -2218,11 +2218,11 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); - + if(botweapon) { if(botweapon->ItemType == ItemTypeShield) hate += botweapon->AC; - + hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); } } @@ -2278,7 +2278,7 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); - + if(botweapon) dmg += botweapon->AC * (RuleI(Combat, SpecialAttackACBonus))/100; } @@ -2391,7 +2391,7 @@ void Bot::AI_Process() { if(!GetTarget() || (IsBotCaster() && !IsBotCasterCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistanceSquaredNoZ(static_cast(m_Position), m_PreSummonLocation) < 10)) { if(GetTarget()) FaceTarget(GetTarget()); - + SetHasBeenSummoned(false); } else if(!IsRooted()) { if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { @@ -2410,7 +2410,7 @@ void Bot::AI_Process() { } else { if(GetTarget()) FaceTarget(GetTarget()); - + SetHasBeenSummoned(false); } return; @@ -2619,7 +2619,7 @@ void Bot::AI_Process() { entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); this->berserk = true; } - + if (berserk && this->GetHPRatio() > 30) { entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); this->berserk = false; @@ -2846,16 +2846,16 @@ void Bot::PetAIProcess() { aa_skill += botPet->GetOwner()->GetAA(aaWardersAlacrity); if(aa_skill >= 1) aa_chance += ((aa_skill > 5 ? 5 : aa_skill) * 4); - + if(aa_skill >= 6) aa_chance += ((aa_skill - 5 > 3 ? 3 : aa_skill - 5) * 7); - + if(aa_skill >= 9) aa_chance += ((aa_skill - 8 > 3 ? 3 : aa_skill - 8) * 3); - + if(aa_skill >= 12) aa_chance += ((aa_skill - 11) * 1); - + //aa_chance += botPet->GetOwner()->GetAA(aaCompanionsAlacrity) * 3; @@ -3035,7 +3035,7 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { uint8 materialFromSlot = 0xFF; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); - if(itemID != 0) { + if(itemID != 0) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); if(materialFromSlot != 0xFF) this->SendWearChange(materialFromSlot); @@ -3273,7 +3273,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { if(item) { if(strlen(item->IDFile) > 2) ns->spawn.equipment[MaterialPrimary].Material = atoi(&item->IDFile[2]); - + ns->spawn.colors[MaterialPrimary].Color = GetEquipmentColor(MaterialPrimary); } } @@ -3284,7 +3284,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { if(item) { if(strlen(item->IDFile) > 2) ns->spawn.equipment[MaterialSecondary].Material = atoi(&item->IDFile[2]); - + ns->spawn.colors[MaterialSecondary].Color = GetEquipmentColor(MaterialSecondary); } } @@ -4138,7 +4138,7 @@ bool Bot::Bot_Command_CharmTarget(int charmtype, Mob *target) { charmid = 198; else if((charmlevel >= 31) && (charmlevel <= 46)) charmid = 197; - else if((charmlevel >= 18) && (charmlevel <= 30)) + else if((charmlevel >= 18) && (charmlevel <= 30)) charmid = 196; break; case 3: // Druid @@ -4240,7 +4240,7 @@ bool Bot::Bot_Command_RezzTarget(Mob *target) { rezid = 2172; else if(rezlevel >= 37) rezid = 388; - else if(rezlevel >= 32) + else if(rezlevel >= 32) rezid = 2171; else if(rezlevel >= 27) rezid = 391; @@ -4382,11 +4382,11 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli "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 = EmuConstants::EQUIPMENT_BEGIN; j <= (EmuConstants::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { if (j == 22) j = 9999; - + how_many_slots++; if(!GetBotItem(j)) { if(j == MainPrimary) { @@ -4447,7 +4447,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli 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) { @@ -4634,7 +4634,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ Log.Out(Logs::Detail, Logs::Combat, "Triggering EVENT_ATTACK due to attack by %s", from->GetName()); parse->EventNPC(EVENT_ATTACK, this, from, "", 0); } - + attacked_timer.Start(CombatEventTimer_expire); // if spell is lifetap add hp to the caster if (spell_id != SPELL_UNKNOWN && IsLifetapSpell(spell_id)) { @@ -4685,7 +4685,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if ((IsCasting() && (GetClass() != BARD) && !IsFromSpell) || other == nullptr || (GetHP() < 0) || (GetAppearance() == eaDead) || (!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()); - + if(other) { RemoveFromHateList(other); Log.Out(Logs::Detail, Logs::Combat, "I am not allowed to attack %s", other->GetCleanName()); @@ -4697,14 +4697,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Divine Aura is in effect."); return false; } - + FaceTarget(GetTarget()); ItemInst* weapon = nullptr; if(Hand == MainPrimary) { weapon = GetBotItem(MainPrimary); OffHandAtk(false); } - + if(Hand == MainSecondary) { weapon = GetBotItem(MainSecondary); OffHandAtk(true); @@ -4731,7 +4731,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b 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; @@ -4896,14 +4896,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b 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); @@ -4963,7 +4963,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 base1 = eff.base1; base2 = eff.base2; slot = eff.slot; - + //AA Foci's can contain multiple focus effects within the same AA. //To handle this we will not automatically return zero if a limit is found. //Instead if limit is found and multiple effects, we will reset the limit check @@ -5175,10 +5175,8 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 case SE_FcTwincast: { if(type == focusTwincast) value = base1; - } break; } - /* case SE_SympatheticProc: { @@ -5188,10 +5186,10 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 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; - + else value = 0; } @@ -5247,7 +5245,6 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 value = base1; break; } - } //Check for spell skill limits. if ((LimitSpellSkill) && (!SpellSkill_Found)) @@ -5289,7 +5286,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { ItemInst* ins = GetBotItem(x); if (!ins) continue; - + TempItem = ins->GetItem(); if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { @@ -5400,7 +5397,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { aa_value = aa.second.first; if (aa_AA < 1 || aa_value < 1) continue; - + Total3 = CalcBotAAFocus(bottype, aa_AA, aa_value, spell_id); if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { realTotal3 = Total3; @@ -5470,7 +5467,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel if (spell.classes[(GetClass() % 16) - 1] < focus_spell.base[i]) return 0; break; - + case SE_LimitCastTimeMin: if (spells[spell_id].cast_time < (uint32)focus_spell.base[i]) return 0; @@ -5501,8 +5498,8 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel return 0; } break; - - + + case SE_LimitSpellType: switch(focus_spell.base[i]) { case 0: @@ -5517,7 +5514,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]); } break; - + case SE_LimitManaMin: if(spell.mana < focus_spell.base[i]) return 0; @@ -5712,19 +5709,19 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel case SE_FcBaseEffects: { if (bottype == BotfocusFcBaseEffects) value = focus_spell.base[i]; - + break; } case SE_FcDamagePctCrit: { if(bottype == BotfocusFcDamagePctCrit) value = focus_spell.base[i]; - + break; } case SE_FcIncreaseNumHits: { if(bottype == BotfocusIncreaseNumHits) value = focus_spell.base[i]; - + break; } default: @@ -5791,7 +5788,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) { damage = -3; Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); } - + float riposte_chance = 0.0f; if (CanRiposte && damage > 0 && CanThisClassRiposte() && !other->BehindMob(this, other->GetX(), other->GetY())) { riposte_chance = ((100.0f + (float)defender->GetAABonuses().RiposteChance + (float)defender->GetSpellBonuses().RiposteChance + (float)defender->GetItemBonuses().RiposteChance) / 100.0f); @@ -5802,7 +5799,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) { RollTable[0] = (bonus + (itembonuses.HeroicDEX / 25)); } } - + bool bBlockFromRear = false; bool bShieldBlockFromRear = false; if (this->IsBot()) { @@ -5894,7 +5891,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) { if (damage < 0) return true; - + return false; } @@ -5977,11 +5974,11 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); - + if(botweapon) { if(botweapon->ItemType == ItemTypeShield) hate += botweapon->AC; - + hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); } } @@ -6046,7 +6043,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { const Item_Struct* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); - + if(!botpiercer || (botpiercer->ItemType != ItemType1HPiercing)) { BotGroupSay(this, "I can't backstab with this weapon!"); return; @@ -6218,7 +6215,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { 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)) canBash = true; - + if(!canBash || zone->random.Int(0, 100) > 25) skill_to_use = SkillKick; else @@ -6671,7 +6668,7 @@ void Bot::SetAttackTimer() { } else { delay = ItemToUse->Delay; } - + 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); @@ -6982,7 +6979,7 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { increase += 30; if (GetAA(aaSpellCastingReinforcementMastery) == 1) increase += 20; - + break; } @@ -7001,7 +6998,7 @@ float Bot::GetAOERange(uint16 spell_id) { range = spells[spell_id].aoerange; if(range == 0) range = spells[spell_id].range; - + if(range == 0) range = 10; @@ -7048,14 +7045,14 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d", IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() ); if(IsSilenced() && !IsDiscipline(spell_id)) Message_StringID(13, SILENCED_STRING); - + if(IsAmnesiad() && IsDiscipline(spell_id)) - + Message_StringID(13, MELEE_SILENCE); - + if(casting_spell_id) AI_Event_SpellCastFinished(false, casting_spell_slot); - + return false; } } @@ -7064,7 +7061,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t Message_StringID(13, SPELL_WOULDNT_HOLD); if(casting_spell_id) AI_Event_SpellCastFinished(false, casting_spell_slot); - + return false; } @@ -7073,7 +7070,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t InterruptSpell(173, 0x121, false); return false; } - + if(slot < MAX_PP_MEMSPELL && !CheckFizzle(spell_id)) { int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE; InterruptSpell(fizzle_msg, 0x121, spell_id); @@ -7233,7 +7230,7 @@ bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce 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 Result = false; - if(GetClass() == BARD) + if(GetClass() == BARD) cast_time = 0; Result = Mob::DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, aa_id); @@ -7263,7 +7260,7 @@ int32 Bot::GenerateBaseManaPoints() { } else ConvertedWisInt = WisInt; - + if(GetLevel() < 41) { wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000); base_mana = (GetLevel() * 15); @@ -7280,7 +7277,7 @@ int32 Bot::GenerateBaseManaPoints() { MindLesserFactor = ((WisInt - 199) / 2); else MindLesserFactor = 0; - + MindFactor = WisInt - MindLesserFactor; if(WisInt > 100) bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40); @@ -7297,7 +7294,7 @@ int32 Bot::GenerateBaseManaPoints() { ConvertedWisInt -= ((WisInt - 201) * 5 / 4); } else ConvertedWisInt = WisInt; - + if(GetLevel() < 41) { wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000); base_mana = (GetLevel() * 15); @@ -7314,7 +7311,7 @@ int32 Bot::GenerateBaseManaPoints() { MindLesserFactor = ((WisInt - 199) / 2); else MindLesserFactor = 0; - + MindFactor = (WisInt - MindLesserFactor); if(WisInt > 100) bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40); @@ -7339,7 +7336,7 @@ bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, uint16 slot if(GetClass() == BARD) { if(!ApplyNextBardPulse(bardsong, this, bardsong_slot)) InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong); - + stopLogic = true; } return true; @@ -7381,7 +7378,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 } else SpellOnTarget(thespell, g->members[i]); - + if(g->members[i] && g->members[i]->GetPetID()) SpellOnTarget(thespell, g->members[i]->GetPet()); } @@ -7548,7 +7545,7 @@ int32 Bot::CalcSTR() { int32 mod = aabonuses.STR; if(val > 255 && GetLevel() <= 60) val = 255; - + STR = (val + mod); if(STR < 1) STR = 1; @@ -7565,7 +7562,7 @@ int32 Bot::CalcSTA() { int32 mod = aabonuses.STA; if(val > 255 && GetLevel() <= 60) val = 255; - + STA = (val + mod); if(STA < 1) STA = 1; @@ -7599,7 +7596,7 @@ int32 Bot::CalcDEX() { int32 mod = aabonuses.DEX; if(val > 255 && GetLevel() <= 60) val = 255; - + DEX = (val + mod); if(DEX < 1) DEX = 1; @@ -7616,12 +7613,12 @@ int32 Bot::CalcINT() { int32 mod = aabonuses.INT; if(val > 255 && GetLevel() <= 60) val = 255; - + INT = (val + mod); if(INT < 1) INT = 1; - + int m = GetMaxINT(); if(INT > m) INT = m; @@ -7634,7 +7631,7 @@ int32 Bot::CalcWIS() { int32 mod = aabonuses.WIS; if(val > 255 && GetLevel() <= 60) val = 255; - + WIS = (val + mod); if(WIS < 1) @@ -7652,7 +7649,7 @@ int32 Bot::CalcCHA() { int32 mod = aabonuses.CHA; if(val > 255 && GetLevel() <= 60) val = 255; - + CHA = (val + mod); if(CHA < 1) @@ -8049,10 +8046,10 @@ void Bot::DoEnduranceUpkeep() { if(cost_redux > 0) { if(upkeep <= cost_redux) continue; - + upkeep -= cost_redux; } - + if((upkeep+upkeep_sum) > GetEndurance()) BuffFadeBySlot(buffs_i); else @@ -8196,7 +8193,7 @@ bool Bot::CanHeal() { if(botSpell.SpellId != 0) result = true; - + return result; } @@ -9010,7 +9007,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if (!results.Success()) return; - for (int i = 0; i < 7; i++) { + for (int i = 0; i < 7; i++) { uint8 slotmaterial = Inventory::CalcMaterialFromSlot((uint8)slots[i]); c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); } @@ -9030,7 +9027,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } return; } - + if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "armorcolor")){ c->Message(0, "-----------------#bot armorcolor help-----------------------------"); c->Message(0, "Armor: -1(All), 2(Helm), 7(Arms), 9(Bracer), 12(Hands), 17(Chest/Robe), 18(Legs), 19(Boots)"); @@ -9504,7 +9501,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { failedLoreCheck = true; } } - + if(c->CheckLoreConflict(itm)) failedLoreCheck = true; } @@ -9645,12 +9642,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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); @@ -9671,12 +9668,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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..."); @@ -9886,7 +9883,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { mezzer->CastToBot()->MesmerizeTarget(target); } } - + if(!hasmezzer) c->Message(15, "You must have an Enchanter in your group."); } @@ -9905,22 +9902,22 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; @@ -9932,12 +9929,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } } - + 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; } @@ -9961,12 +9958,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; } @@ -9979,7 +9976,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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")) { @@ -10007,7 +10004,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } else c->GetTarget()->CastToBot()->SetPetChooserID(4); } - + if(c->GetTarget()->GetPet()) { uint16 id = c->GetTarget()->GetPetID(); c->GetTarget()->SetPetID(0); @@ -10016,7 +10013,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } else c->Message(15, "You must target your Magician bot!"); - + return; } @@ -10026,7 +10023,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(15, "You must select player with his corpse in the zone!"); return; } - + if(c->IsGrouped()) { bool hassummoner = false; Mob *t = c->GetTarget(); @@ -10060,10 +10057,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } } - + if (!hassummoner) c->Message(15, "You must have a Necromancer or Shadow Knight in your group."); - + return; } } @@ -10084,7 +10081,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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()); @@ -10097,7 +10094,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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()); @@ -10116,7 +10113,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(15, "You must select a monster!"); return; } - + uint32 DBtype = c->GetTarget()->GetBodyType(); Mob *Charmer; uint32 CharmerClass = 0; @@ -10202,7 +10199,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; } @@ -10290,18 +10287,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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.", c->GetName()); - + return; } @@ -11470,7 +11467,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; @@ -11559,7 +11556,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(13, "Unable to create botgroup."); return; } - + Group *newBotGroup = botGroupLeader->GetGroup(); if(!newBotGroup) { c->Message(13, "Unable to find valid botgroup"); @@ -11576,7 +11573,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { safe_delete(botGroupMember); return; } - + if(!botGroupMember) { safe_delete(botGroupMember); continue; @@ -11664,15 +11661,15 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 { @@ -11680,7 +11677,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } } - + if (!strcasecmp(sep->arg[1], "face")) LuclinFace = atoi(sep->arg[2]); @@ -11688,19 +11685,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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"); @@ -11847,7 +11844,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; } @@ -11899,7 +11896,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } else c->Message(0, "Usage #bot groupmessages [on|off] [bot name|all]"); - + return; } @@ -11967,7 +11964,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { tempBot->UseDiscipline(defensiveSpellID, tempBot->GetID()); } else c->Message(13, "You must name a valid bot."); - + return; } @@ -12555,7 +12552,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "Usage #bot bardoutofcombat [on|off]"); return; } - + if(!strcasecmp(sep->arg[1], "showhelm")) { bool showhelm = true; if (sep->arg[2]) { @@ -12567,10 +12564,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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(); + Bot* b = target->CastToBot(); if (b) { b->SetShowHelm(showhelm); c->Message(0, "Your bot will %s show their helmet.", (showhelm ? "now" : "no longer")); @@ -12578,7 +12575,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } else c->Message(0, "Usage #bot showhelm [on|off]"); - + return; } } @@ -12738,7 +12735,7 @@ Mob* EntityList::GetMobByBotID(uint32 botID) { for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { if(!it->second) continue; - + if(it->second->IsBot() && it->second->CastToBot()->GetBotID() == botID) { Result = it->second; break; @@ -13032,7 +13029,7 @@ uint32 Bot::CalcCurrentWeight() { for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { - TempItem = inst->GetItem(); + TempItem = inst->GetItem(); if (TempItem) Total += TempItem->Weight; } @@ -13041,7 +13038,7 @@ uint32 Bot::CalcCurrentWeight() { float Packrat = ((float)spellbonuses.Packrat + (float)aabonuses.Packrat); if (Packrat > 0) Total = (uint32)((float)Total * (1.0f - ((Packrat * 1.0f) / 100.0f))); - + return Total; } @@ -13174,7 +13171,7 @@ void Bot::SetDefaultBotStance() { BotStanceType defaultStance = BotStanceBalanced; if (GetClass() == WARRIOR) defaultStance = BotStanceAggressive; - + _baseBotStance = BotStancePassive; _botStance = defaultStance; } @@ -13324,21 +13321,21 @@ void Bot::SetPrevHealRotationMember( Bot* healer ) { Bot* Bot::GetHealRotationLeader( ) { if(_healRotationLeader) return entity_list.GetBotByBotID(_healRotationLeader); - + return 0; } Bot* Bot::GetNextHealRotationMember( ) { if(_healRotationMemberNext) return entity_list.GetBotByBotID(_healRotationMemberNext); - + return 0; } Bot* Bot::GetPrevHealRotationMember( ) { if(_healRotationMemberNext) return entity_list.GetBotByBotID(_healRotationMemberPrev); - + return 0; } @@ -13352,7 +13349,7 @@ bool Bot::AddHealRotationTarget( Mob* target ) { } else if(!strcasecmp(tempTarget->GetCleanName(), target->GetCleanName())) { if(tempTarget->GetID() != target->GetID()) _healRotationTargets[i] = target->GetID(); - + return false; } } From 32e880f571f962a74589c6be2358fec8f31db0d8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 20 Jun 2015 14:05:32 -0400 Subject: [PATCH 200/846] Identified the extra byte at the end of OP_TargetBuffs/OP_BuffCreate --- common/eq_packet_structs.h | 1 + common/patches/rof.cpp | 4 ++-- common/patches/rof2.cpp | 4 ++-- common/patches/uf.cpp | 2 +- zone/spells.cpp | 6 ++++++ 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 8e9f97138..f9f75838f 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4733,6 +4733,7 @@ struct BuffIcon_Struct uint32 entity_id; uint8 all_buffs; uint16 count; + uint8 type; // 0 = self buff window, 1 = self target window, 4 = group, 5 = PC, 7 = NPC BuffIconEntry_Struct entries[0]; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index f4f01e300..8080bfce1 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -417,7 +417,7 @@ namespace RoF outapp->WriteUInt32(0); // Duration outapp->WriteUInt32(0); // ? outapp->WriteUInt8(0); // Caster name - outapp->WriteUInt8(0); // Terminating byte + outapp->WriteUInt8(0); // Type } FINISH_ENCODE(); @@ -454,7 +454,7 @@ namespace RoF __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown __packet->WriteString(""); } - __packet->WriteUInt8(!emu->all_buffs); // Unknown + __packet->WriteUInt8(emu->type); // Unknown FINISH_ENCODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 096467edf..68ff8bf44 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -483,7 +483,7 @@ namespace RoF2 outapp->WriteUInt32(0); // Duration outapp->WriteUInt32(0); // ? outapp->WriteUInt8(0); // Caster name - outapp->WriteUInt8(0); // Terminating byte + outapp->WriteUInt8(0); // Type } FINISH_ENCODE(); @@ -525,7 +525,7 @@ namespace RoF2 __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown __packet->WriteString(""); } - __packet->WriteUInt8(!emu->all_buffs); // Unknown + __packet->WriteUInt8(emu->type); // Unknown FINISH_ENCODE(); } diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index deedcec5f..d63a1bc04 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -387,7 +387,7 @@ namespace UF __packet->WriteUInt32(emu->entries[i].num_hits); __packet->WriteString(""); } - __packet->WriteUInt8(!emu->all_buffs); + __packet->WriteUInt8(emu->type); FINISH_ENCODE(); /* diff --git a/zone/spells.cpp b/zone/spells.cpp index 868180dff..faaace669 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5396,6 +5396,12 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) buff->entity_id = GetID(); buff->count = count; buff->all_buffs = 1; + // 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) + buff->type = IsClient() ? 5 : 7; + else + buff->type = 0; uint32 index = 0; for(unsigned int i = 0; i < buff_count; ++i) From d5098a56e0d50af6b687874b5e7374b3d43055d9 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 20 Jun 2015 19:44:00 -0700 Subject: [PATCH 201/846] Timers and some more loading stuff --- common/clientversions.h | 22 ++++++++ common/ruletypes.h | 1 + world/client.cpp | 8 ++- zone/aa.cpp | 122 ++++++++++++++++++++++++++++++++-------- zone/aa.h | 7 +++ zone/aa_ability.h | 1 - zone/aa_rank.h | 2 +- zone/aa_rank_prereqs.h | 33 ----------- zone/client.cpp | 10 +--- zone/client.h | 3 +- zone/client_packet.cpp | 10 +++- zone/command.cpp | 34 +++++++++++ zone/command.h | 4 +- zone/entity.cpp | 8 +++ zone/entity.h | 2 +- zone/mob.h | 2 + zone/npc.cpp | 1 - zone/spells.cpp | 8 +-- 18 files changed, 199 insertions(+), 79 deletions(-) delete mode 100644 zone/aa_rank_prereqs.h diff --git a/common/clientversions.h b/common/clientversions.h index 675429eab..4e575f8f4 100644 --- a/common/clientversions.h +++ b/common/clientversions.h @@ -150,4 +150,26 @@ static ClientVersion ClientVersionFromBit(uint32 clientVersionBit) } } +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/ruletypes.h b/common/ruletypes.h index 4c9430998..8dffc82e5 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -184,6 +184,7 @@ RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against Ant RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method. RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS. +RULE_BOOL(World, UseClientBasedExpansionSettings, true) // if true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules. 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. diff --git a/world/client.cpp b/world/client.cpp index 26a69222b..2c476902a 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -152,7 +152,13 @@ void Client::SendEnterWorld(std::string name) void Client::SendExpansionInfo() { auto outapp = new EQApplicationPacket(OP_ExpansionInfo, sizeof(ExpansionInfo_Struct)); ExpansionInfo_Struct *eis = (ExpansionInfo_Struct*)outapp->pBuffer; - eis->Expansions = (RuleI(World, ExpansionSettings)); + if(RuleB(World, UseClientBasedExpansionSettings)) { + eis->Expansions = ExpansionFromClientVersion(eqs->GetClientVersion()); + //eis->Expansions = ExpansionFromClientVersion(this->GetCLE. + } else { + eis->Expansions = (RuleI(World, ExpansionSettings)); + } + QueuePacket(outapp); safe_delete(outapp); } diff --git a/zone/aa.cpp b/zone/aa.cpp index 741a15aff..0c31034c7 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -872,8 +872,8 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { } for(auto &prereq : rank->prereqs) { - outapp->WriteSInt32(prereq.aa_id); - outapp->WriteSInt32(prereq.points); + outapp->WriteSInt32(prereq.first); + outapp->WriteSInt32(prereq.second); } QueuePacket(outapp); @@ -948,6 +948,41 @@ void Client::SendAlternateAdvancementTimers() { safe_delete(outapp); } +void Client::ResetAlternateAdvancementTimer(int ability) { + AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id); + if(rank) { + SendAlternateAdvancementTimer(rank->spell_type, 0, time(0)); + p_timers.Clear(&database, rank->spell_type + pTimerAAStart); + } +} + +void Client::ResetAlternateAdvancementTimers() { + 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(); + std::vector r_timers; + for(; c != e; ++c) { + PersistentTimer *cur = c->second; + if(cur->GetType() < pTimerAAStart || cur->GetType() > pTimerAAEnd) + continue; + //send timer + uaaout->begin = 0; + uaaout->end = static_cast(time(nullptr)); + uaaout->ability = cur->GetType() - pTimerAAStart; + r_timers.push_back(cur->GetType()); + QueuePacket(outapp); + } + + for(auto &i : r_timers) { + p_timers.Clear(&database, i); + } + + safe_delete(outapp); +} + void Client::PurchaseAlternateAdvancementRank(int rank_id) { AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); if(!rank) { @@ -1212,13 +1247,13 @@ void Mob::ExpendAlternateAdvancementCharge(uint32 aa_id) { bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { c->ClearAAs(); std::string query = StringFormat( - "SELECT " - "aa_id, " - "aa_value, " - "charges " - "FROM " - "`character_alternate_abilities` " - "WHERE `id` = %u ORDER BY `slot`", c->CharacterID()); + "SELECT " + "aa_id, " + "aa_value, " + "charges " + "FROM " + "`character_alternate_abilities` " + "WHERE `id` = %u", c->CharacterID()); MySQLRequestResult results = database.QueryDatabase(query); int i = 0; @@ -1227,11 +1262,25 @@ bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { uint32 value = atoi(row[1]); uint32 charges = atoi(row[2]); - c->GetPP().aa_array[i].AA = aa; - c->GetPP().aa_array[i].value = value; - c->GetPP().aa_array[i].charges = charges; - c->SetAA(aa, value, charges); - i++; + auto rank = zone->GetAlternateAdvancementRank(aa); + if(!rank) { + continue; + } + + auto ability = rank->base_ability; + if(!ability) { + continue; + } + + rank = ability->GetRankByPointsSpent(value); + + if(c->CanUseAlternateAdvancementRank(rank)) { + c->GetPP().aa_array[i].AA = aa; + c->GetPP().aa_array[i].value = value; + c->GetPP().aa_array[i].charges = charges; + c->SetAA(aa, value, charges); + i++; + } } return true; @@ -1359,8 +1408,14 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { } } - if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { - return false; + if(IsClient()) { + if(!(CastToClient()->GetPP().expansions & (1 << rank->expansion))) { + return false; + } + } else { + if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { + return false; + } } auto race = GetArrayRace(GetBaseRace()); @@ -1427,11 +1482,11 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) //check prereqs for(auto &prereq : rank->prereqs) { - AA::Ability *prereq_ability = zone->GetAlternateAdvancementAbility(prereq.aa_id); + AA::Ability *prereq_ability = zone->GetAlternateAdvancementAbility(prereq.first); if(prereq_ability) { auto ranks = GetAA(prereq_ability->first_rank_id); - if(ranks < prereq.points) { + if(ranks < prereq.second) { return false; } } @@ -1473,6 +1528,24 @@ void Zone::LoadAlternateAdvancement() { if(current->prev) { current->total_cost = current->cost + current->prev->total_cost; + + //check prereqs here + for(auto &prev_prereq : current->prev->prereqs) { + // //if prev has an aa we dont have set + // // then set it here too + // //if prev has an aa we have and the count is different + // // then set to whichever is highest + // + auto iter = current->prereqs.find(prev_prereq.first); + if(iter == current->prereqs.end()) { + //not found + current->prereqs[prev_prereq.first] = prev_prereq.second; + } else { + //they already have it too! + auto points = std::max(iter->second, prev_prereq.second); + current->prereqs[iter->first] = points; + } + } } else { current->prev_id = -1; @@ -1593,14 +1666,17 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map 0) { AA::Rank *rank = ranks[rank_id].get(); - rank->prereqs.push_back(prereq); + rank->prereqs[aa_id] = points; } } } else { @@ -1650,4 +1726,4 @@ void Mob::GrantAlternateAdvancementAbility(int aa_id, int points) { c->SendAlternateAdvancementStats(); c->CalcBonuses(); } -} \ No newline at end of file +} diff --git a/zone/aa.h b/zone/aa.h index 76df0f388..280f56d53 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -1536,4 +1536,11 @@ public: uint32 owner_id; }; +enum AATimers +{ + aaTimerRampage, + aaTimerWarcry, + aaTimerMax +}; + #endif diff --git a/zone/aa_ability.h b/zone/aa_ability.h index 4a2d41f3e..0d6a240c4 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -24,7 +24,6 @@ #include #include #include "aa_rank_effects.h" -#include "aa_rank_prereqs.h" #include "aa_rank.h" class Mob; diff --git a/zone/aa_rank.h b/zone/aa_rank.h index 977a07680..c328e4ebb 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -48,7 +48,7 @@ public: int total_cost; Ability *base_ability; std::vector effects; - std::vector prereqs; + std::map prereqs; }; } diff --git a/zone/aa_rank_prereqs.h b/zone/aa_rank_prereqs.h deleted file mode 100644 index b1620be6c..000000000 --- a/zone/aa_rank_prereqs.h +++ /dev/null @@ -1,33 +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 EQEMU_ZONE_AA_RANK_PREREQS_H -#define EQEMU_ZONE_AA_RANK_PREREQS_H - -namespace AA -{ - -struct RankPrereq -{ - int aa_id; - int points; -}; - -} - -#endif diff --git a/zone/client.cpp b/zone/client.cpp index 0ce7292ef..ae0ceedff 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -524,7 +524,6 @@ void Client::ReportConnectingState() { } bool Client::SaveAA() { - std::string dquery; std::string iquery; int spentpoints = 0; int i = 0; @@ -546,10 +545,10 @@ bool Client::SaveAA() { spentpoints += r->total_cost; if(i == 0) { - iquery = StringFormat("INSERT INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" - " VALUES (%u, %u, %u, %u, %u)", character_id, i, ability->first_rank_id, rank.second.first, rank.second.second); + iquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, aa_id, aa_value, charges)" + " VALUES (%u, %u, %u, %u)", character_id, ability->first_rank_id, rank.second.first, rank.second.second); } else { - iquery += StringFormat(", (%u, %u, %u, %u, %u)", character_id, i, ability->first_rank_id, rank.second.first, rank.second.second); + iquery += StringFormat(", (%u, %u, %u, %u)", character_id, ability->first_rank_id, rank.second.first, rank.second.second); } i++; } @@ -557,9 +556,6 @@ bool Client::SaveAA() { m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; - dquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE id=%u", character_id); - database.QueryDatabase(dquery); - if(iquery.length() > 0) { database.QueryDatabase(iquery); } diff --git a/zone/client.h b/zone/client.h index 034ff83b4..07d42a313 100644 --- a/zone/client.h +++ b/zone/client.h @@ -45,7 +45,6 @@ struct Item_Struct; #include "../common/item_struct.h" #include "../common/clientversions.h" -#include "aa.h" #include "common.h" #include "merc.h" #include "mob.h" @@ -768,6 +767,8 @@ public: void SendAlternateAdvancementPoints(); void SendAlternateAdvancementTimer(int ability, int begin, int end); void SendAlternateAdvancementTimers(); + void ResetAlternateAdvancementTimer(int ability); + void ResetAlternateAdvancementTimers(); void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index d01bcf109..8f4b55004 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1440,6 +1440,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; } 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()); + } + else { + m_pp.expansions = RuleI(World, ExpansionSettings); + } + if(!database.LoadAlternateAdvancement(this)) { Log.Out(Logs::General, Logs::Error, "Error loading AA points for %s", GetName()); } @@ -1566,9 +1573,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* Update LFP in case any (or all) of our group disbanded while we were zoning. */ if (IsLFP()) { UpdateLFP(); } - /* Get Expansions from variables table and ship via PP */ - m_pp.expansions = RuleI(World, ExpansionSettings); - p_timers.SetCharID(CharacterID()); if (!p_timers.Load(&database)) { Log.Out(Logs::General, Logs::Error, "Unable to load ability timers from the database for %s (%i)!", GetCleanName(), CharacterID()); diff --git a/zone/command.cpp b/zone/command.cpp index ab2b4ad78..59f4bfa8a 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -320,6 +320,7 @@ int command_init(void) { command_add("raidloot", "LEADER|GROUPLEADER|SELECTED|ALL - Sets your raid loot settings if you have permission to do so.", 0, command_raidloot) || command_add("randomfeatures", "- Temporarily randomizes the Facial Features of your target", 80, command_randomfeatures) || command_add("refreshgroup", "- Refreshes Group.", 0, command_refreshgroup) || + command_add("reloadaa", "Reloads AA data", 200, command_reloadaa) || command_add("reloadallrules", "Executes a reload of all rules.", 80, command_reloadallrules) || command_add("reloademote", "Reloads NPC Emotes", 80, command_reloademote) || command_add("reloadlevelmods", nullptr,255, command_reloadlevelmods) || @@ -333,6 +334,7 @@ int command_init(void) { command_add("reloadzps", nullptr,0, command_reloadzps) || command_add("repop", "[delay] - Repop the zone with optional delay", 100, command_repop) || command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", 200, command_resetaa) || + command_add("resetaa_timer", "Command to reset AA cooldown timers.", 200, command_resetaa_timer) || command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) || command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) || command_add("save", "- Force your player or player corpse target to be saved to the database", 50, command_save) || @@ -10580,3 +10582,35 @@ void command_mysqltest(Client *c, const Seperator *sep) } Log.Out(Logs::General, Logs::Debug, "MySQL Test... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); } + +void command_resetaa_timer(Client *c, const Seperator *sep) { + Client *target = nullptr; + if(!c->GetTarget() || !c->GetTarget()->IsClient()) { + target = c; + } else { + target = c->GetTarget()->CastToClient(); + } + + if(sep->IsNumber(1)) + { + int timer_id = atoi(sep->arg[1]); + c->Message(0, "Reset of timer %i for %s", timer_id, c->GetName()); + c->ResetAlternateAdvancementTimer(timer_id); + } + else if(!strcasecmp(sep->arg[1], "all")) + { + c->Message(0, "Reset all timers for %s", c->GetName()); + c->ResetAlternateAdvancementTimers(); + } + else + { + c->Message(0, "usage: #resetaa_timer [all | timer_id]"); + } +} + +void command_reloadaa(Client *c, const Seperator *sep) { + c->Message(0, "Reloading Alternate Advancement Data..."); + zone->LoadAlternateAdvancement(); + c->Message(0, "Alternate Advancement Data Reloaded"); + entity_list.SendAlternateAdvancementStats(); +} \ No newline at end of file diff --git a/zone/command.h b/zone/command.h index f44362ea7..795f75919 100644 --- a/zone/command.h +++ b/zone/command.h @@ -323,7 +323,9 @@ void command_tune(Client *c, const Seperator *sep); void command_logtest(Client *c, const Seperator *sep); void command_mysqltest(Client *c, const Seperator *sep); void command_logs(Client *c, const Seperator *sep); - +void command_resetaa_timer(Client *c, const Seperator *sep); +void command_reloadaa(Client *c, const Seperator *sep); + #ifdef EQPROFILE void command_profiledump(Client *c, const Seperator *sep); void command_profilereset(Client *c, const Seperator *sep); diff --git a/zone/entity.cpp b/zone/entity.cpp index 5033c52fe..8749b102c 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4704,3 +4704,11 @@ void EntityList::StopMobAI() mob.second->AI_ShutDown(); } } + +void EntityList::SendAlternateAdvancementStats() { + for(auto &c : client_list) { + c.second->SendAlternateAdvancementTable(); + c.second->SendAlternateAdvancementStats(); + c.second->SendAlternateAdvancementPoints(); + } +} diff --git a/zone/entity.h b/zone/entity.h index 446c5d505..1adf23783 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -398,7 +398,6 @@ public: void SaveAllClientsTaskState(); void ReloadAllClientsTaskState(int TaskID=0); - uint16 CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time = 300000); uint16 CreateGroundObjectFromModel(const char *model, const glm::vec4& position, uint8 type = 0x00, uint32 decay_time = 0); uint16 CreateDoor(const char *model, const glm::vec4& position, uint8 type = 0, uint16 size = 100); @@ -429,6 +428,7 @@ public: uint16 GetFreeID(); void RefreshAutoXTargets(Client *c); void RefreshClientXTargets(Client *c); + void SendAlternateAdvancementStats(); protected: friend class Zone; diff --git a/zone/mob.h b/zone/mob.h index 1c3d7ab15..8352d764e 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -24,6 +24,7 @@ #include "pathing.h" #include "position.h" #include "aa_ability.h" +#include "aa.h" #include #include #include @@ -1327,6 +1328,7 @@ protected: bool destructibleobject; std::unordered_map> aa_ranks; + Timer aa_timers[aaTimerMax]; private: void _StopSong(); //this is not what you think it is diff --git a/zone/npc.cpp b/zone/npc.cpp index d4a33b6d0..2d0c1f13b 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -31,7 +31,6 @@ #include "../common/linked_list.h" #include "../common/servertalk.h" -#include "aa.h" #include "client.h" #include "entity.h" #include "npc.h" diff --git a/zone/spells.cpp b/zone/spells.cpp index ec872d1c9..4f492c343 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -818,12 +818,8 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) } if(casting_spell_aa_id && IsClient()) { //Rest AA Timer on failed cast - AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id); - if(rank) { - CastToClient()->Message_StringID(MT_SpellFailure, ABILITY_FAILED); - CastToClient()->SendAlternateAdvancementTimer(rank->spell_type, 0, 0x7fffffff); - CastToClient()->GetPTimers().Clear(&database, rank->spell_type + pTimerAAStart); - } + CastToClient()->Message_StringID(MT_SpellFailure, ABILITY_FAILED); + CastToClient()->ResetAlternateAdvancementTimer(casting_spell_aa_id); } ZeroCastingVars(); // resets all the state keeping stuff From d34b4a786b63e39d9705ae35f736da119ad0b03d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 21 Jun 2015 02:01:48 -0400 Subject: [PATCH 202/846] Implement duration ramp and war cry with new AA system Rampage also correctly does a full attack round for classes other than monk and ranger --- zone/aa.cpp | 43 ++++++++++++++------- zone/attack.cpp | 36 ++++++++++++++++++ zone/client.h | 3 +- zone/client_process.cpp | 84 +++-------------------------------------- zone/effects.cpp | 7 +++- zone/mob.h | 1 + zone/spell_effects.cpp | 53 ++++++++------------------ zone/spells.cpp | 16 ++++---- 8 files changed, 102 insertions(+), 141 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 0c31034c7..41be9a0cf 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -828,7 +828,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { if(!CanUseAlternateAdvancementRank(rank)) { return; } - + int size = sizeof(AARankInfo_Struct) + (sizeof(AARankEffect_Struct) * rank->effects.size()) + (sizeof(AARankPrereq_Struct) * rank->prereqs.size()); EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size); AARankInfo_Struct *aai = (AARankInfo_Struct*)outapp->pBuffer; @@ -996,7 +996,7 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { if(!CanPurchaseAlternateAdvancementRank(rank, true)) { return; } - + if(rank->base_ability->charges > 0) { uint32 charges = 0; GetAA(rank_id, &charges); @@ -1004,7 +1004,7 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { if(charges > 0) { return; } - + SetAA(rank_id, rank->current_value, rank->base_ability->charges); } else { SetAA(rank_id, rank->current_value, 0); @@ -1022,10 +1022,10 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { SendAlternateAdvancementStats(); if(rank->prev) { - Message_StringID(15, AA_IMPROVE, - std::to_string(rank->title_sid).c_str(), - std::to_string(rank->prev->current_value).c_str(), - std::to_string(rank->cost).c_str(), + Message_StringID(15, AA_IMPROVE, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->prev->current_value).c_str(), + std::to_string(rank->cost).c_str(), std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ @@ -1034,9 +1034,9 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } } else { - Message_StringID(15, AA_GAIN_ABILITY, - std::to_string(rank->title_sid).c_str(), - std::to_string(rank->cost).c_str(), + Message_StringID(15, AA_GAIN_ABILITY, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->cost).c_str(), std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ if (RuleB(QueryServ, PlayerLogAAPurchases)){ @@ -1125,7 +1125,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { if(!IsValidSpell(rank->spell)) { return; } - + if(!CanUseAlternateAdvancementRank(rank)) { return; } @@ -1448,7 +1448,7 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) if(!ability) return false; - + if(!CanUseAlternateAdvancementRank(rank)) { return false; } @@ -1474,7 +1474,7 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) } //if expendable only let us purchase if we have no charges already - //not quite sure on how this functions client side atm + //not quite sure on how this functions client side atm //I intend to look into it later to make sure the behavior is right if(ability->charges > 0 && current_charges > 0) { return false; @@ -1565,7 +1565,7 @@ void Zone::LoadAlternateAdvancement() { } bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, - std::unordered_map> &ranks) + std::unordered_map> &ranks) { Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Abilities..."); abilities.clear(); @@ -1727,3 +1727,18 @@ void Mob::GrantAlternateAdvancementAbility(int aa_id, int points) { c->CalcBonuses(); } } + +bool Mob::CheckAATimer(int timer) +{ + if (timer >= aaTimerMax) + return false; + if (aa_timers[timer].Enabled()) { + if (aa_timers[timer].Check(false)) { + aa_timers[timer].Disable(); + return false; + } else { + return true; + } + } + return false; +} diff --git a/zone/attack.cpp b/zone/attack.cpp index 6a8125507..202ad77b6 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5056,3 +5056,39 @@ void NPC::SetAttackTimer() TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true, true); } } + +void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) +{ + if (!target) + return; + + Attack(target, hand, false, false, IsFromSpell); + + if (CanThisClassDoubleAttack()) { + CheckIncreaseSkill(SkillDoubleAttack, target, -10); + if (CheckDoubleAttack()) + Attack(target, hand, false, false, IsFromSpell); + if (hand == MainPrimary && GetLevel() >= 60 && + (GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER) && + CheckDoubleAttack(true)) + Attack(target, hand, false, false, IsFromSpell); + } + if (hand == MainPrimary) { + auto flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance; + if (flurrychance && zone->random.Roll(flurrychance)) { + Message_StringID(MT_NPCFlurry, YOU_FLURRY); + Attack(target, hand, false, false, IsFromSpell); + Attack(target, hand, false, false, IsFromSpell); + } + + auto extraattackchance = aabonuses.ExtraAttackChance + spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance; + if (extraattackchance) { + auto wpn = GetInv().GetItem(MainPrimary); + if (wpn && (wpn->GetItem()->ItemType == ItemType2HBlunt || + wpn->GetItem()->ItemType == ItemType2HSlash || + wpn->GetItem()->ItemType == ItemType2HPiercing)) + if (zone->random.Roll(extraattackchance)) + Attack(target, hand, false, false, IsFromSpell); + } + } +} diff --git a/zone/client.h b/zone/client.h index 07d42a313..44e86f971 100644 --- a/zone/client.h +++ b/zone/client.h @@ -226,6 +226,7 @@ public: virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); virtual void SetAttackTimer(); float GetQuiverHaste(); + void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false); void AI_Init(); void AI_Start(uint32 iMoveDelay = 0); @@ -774,7 +775,7 @@ public: void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } int GetAAPoints() { return m_pp.aapoints; } int GetSpentAA() { return m_pp.aapoints_spent; } - + //old AA methods that we still use void ResetAA(); void RefundAA(); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 603636a82..42c244e6b 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -391,74 +391,12 @@ bool Client::Process() { } else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP { - //old aa - //if(CheckAAEffect(aaEffectRampage)) - //{ - // entity_list.AEAttack(this, 30); - //} else { - Attack(auto_attack_target, MainPrimary); // Kaiyodo - added attacking hand to arguments - //} ItemInst *wpn = GetInv().GetItem(MainPrimary); TryWeaponProc(wpn, auto_attack_target, MainPrimary); - bool tripleAttackSuccess = false; - if( auto_attack_target && CanThisClassDoubleAttack() ) { - - CheckIncreaseSkill(SkillDoubleAttack, auto_attack_target, -10); - if(CheckDoubleAttack()) { - //should we allow rampage on double attack? - //if(CheckAAEffect(aaEffectRampage)) { - // entity_list.AEAttack(this, 30); - //} else { - Attack(auto_attack_target, MainPrimary, false); - //} - } - - //triple attack: rangers, monks, warriors, berserkers over level 60 - if((((GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER) - && GetLevel() >= 60) || GetSpecialAbility(SPECATK_TRIPLE)) - && CheckDoubleAttack(true)) - { - tripleAttackSuccess = true; - Attack(auto_attack_target, MainPrimary, false); - } - - //quad attack, does this belong here?? - if(GetSpecialAbility(SPECATK_QUAD) && CheckDoubleAttack(true)) - { - Attack(auto_attack_target, MainPrimary, false); - } - } - - //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). - int16 flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance; - - if (auto_attack_target && flurrychance) - { - if(zone->random.Int(0, 99) < flurrychance) - { - Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(auto_attack_target, MainPrimary, false); - Attack(auto_attack_target, MainPrimary, false); - } - } - - int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; - - if (auto_attack_target && ExtraAttackChanceBonus) { - ItemInst *wpn = GetInv().GetItem(MainPrimary); - if(wpn){ - if(wpn->GetItem()->ItemType == ItemType2HSlash || - wpn->GetItem()->ItemType == ItemType2HBlunt || - wpn->GetItem()->ItemType == ItemType2HPiercing ) - { - if(zone->random.Int(0, 99) < ExtraAttackChanceBonus) - { - Attack(auto_attack_target, MainPrimary, false); - } - } - } - } + DoAttackRounds(auto_attack_target, MainPrimary); + if (CheckAATimer(aaTimerRampage)) + entity_list.AEAttack(this, 30); } } @@ -499,23 +437,11 @@ bool Client::Process() { float random = zone->random.Real(0, 1); CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10); - if (random < DualWieldProbability){ // Max 78% of DW - //if(CheckAAEffect(aaEffectRampage)) { - // entity_list.AEAttack(this, 30, MainSecondary); - //} else { - Attack(auto_attack_target, MainSecondary); // Single attack with offhand - //} + if (random < DualWieldProbability) { // Max 78% of DW ItemInst *wpn = GetInv().GetItem(MainSecondary); TryWeaponProc(wpn, auto_attack_target, MainSecondary); - if( CanThisClassDoubleAttack() && CheckDoubleAttack()) { - //if(CheckAAEffect(aaEffectRampage)) { - // entity_list.AEAttack(this, 30, MainSecondary); - //} else { - // if(auto_attack_target && auto_attack_target->GetHP() > -10) - Attack(auto_attack_target, MainSecondary); // Single attack with offhand - //} - } + DoAttackRounds(auto_attack_target, MainSecondary); } } } diff --git a/zone/effects.cpp b/zone/effects.cpp index 55e56cdac..68e68e78d 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -878,7 +878,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff caster->CastToClient()->CheckSongSkillIncrease(spell_id); } -//Dook- Rampage and stuff for clients. +// Rampage and stuff for clients. Normal and Duration rampages //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 @@ -896,7 +896,10 @@ void EntityList::AEAttack(Mob *attacker, float dist, int Hand, int count, bool I && curmob->GetRace() != 216 && curmob->GetRace() != 472 /* dont attack horses */ && (DistanceSquared(curmob->GetPosition(), attacker->GetPosition()) <= dist2) ) { - attacker->Attack(curmob, Hand, false, false, IsFromSpell); + if (!attacker->IsClient() || attacker->GetClass() == MONK || attacker->GetClass() == RANGER) + attacker->Attack(curmob, Hand, false, false, IsFromSpell); + else + attacker->CastToClient()->DoAttackRounds(curmob, Hand, IsFromSpell); hit++; if (count != 0 && hit >= count) return; diff --git a/zone/mob.h b/zone/mob.h index 8352d764e..c9ba4471d 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -971,6 +971,7 @@ public: void CalcAABonuses(StatBonuses* newbon); void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon); void GrantAlternateAdvancementAbility(int aa_id, int points); + bool CheckAATimer(int timer); protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 3c0c8fad4..5c30185aa 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -638,42 +638,23 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Group Fear Immunity"); #endif //Added client messages to give some indication this effect is active. - uint32 group_id_caster = 0; - uint32 time = spell.base[i]*10; - if(caster->IsClient()) - { - if(caster->IsGrouped()) - { - group_id_caster = GetGroup()->GetID(); - } - else if(caster->IsRaidGrouped()) - { - group_id_caster = (GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (GetRaid()->GetGroup(CastToClient()) + 1); + // Is there a message generated? Too disgusted by raids. + uint32 time = spell.base[i] * 10 * 1000; + if (caster->IsClient()) { + if (caster->IsGrouped()) { + auto group = caster->GetGroup(); + for (int i = 0; i < 6; ++i) + if (group->members[i]) + group->members[i]->aa_timers[aaTimerWarcry].Start(time); + } else if (caster->IsRaidGrouped()) { + auto raid = caster->GetRaid(); + uint32 gid = raid->GetGroup(caster->CastToClient()); + if (gid < 12) + for (int i = 0; i < MAX_RAID_MEMBERS; ++i) + if (raid->members[i].member && raid->members[i].GroupNumber == gid) + raid->members[i].member->aa_timers[aaTimerWarcry].Start(time); } } - //old aa - //if(group_id_caster){ - // Group *g = entity_list.GetGroupByID(group_id_caster); - // uint32 time = spell.base[i]*10; - // if(g){ - // for(int gi=0; gi < 6; gi++){ - // if(g->members[gi] && g->members[gi]->IsClient()) - // { - // g->members[gi]->CastToClient()->EnableAAEffect(aaEffectWarcry , time); - // if (g->members[gi]->GetID() != caster->GetID()) - // g->members[gi]->Message(13, "You hear the war cry."); - // else - // Message(13, "You let loose a fierce war cry."); - // } - // } - // } - //} - // - //else{ - // CastToClient()->EnableAAEffect(aaEffectWarcry , time); - // Message(13, "You let loose a fierce war cry."); - //} - break; } @@ -2238,9 +2219,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Duration Rampage"); #endif - //if (caster && caster->IsClient()) { // will tidy this up later so that NPCs can duration ramp from spells too - // CastToClient()->DurationRampage(effect_value*12); - //} + aa_timers[aaTimerRampage].Start(effect_value * 10 * 1000); // Live bug, was suppose to be 1 second per value break; } diff --git a/zone/spells.cpp b/zone/spells.cpp index 4f492c343..c3e777b5c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2280,7 +2280,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 if(rank && rank->base_ability) { ExpendAlternateAdvancementCharge(rank->base_ability->id); } - } + } else if(spell_id == casting_spell_id && casting_spell_timer != 0xFFFFFFFF) { //aa new todo: aa expendable charges here @@ -4124,13 +4124,13 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) } return true; } - //else if (IsClient() && CastToClient()->CheckAAEffect(aaEffectWarcry)) //old aa - //{ - // Message(13, "Your are immune to fear."); - // Log.Out(Logs::Detail, Logs::Spells, "Clients has WarCry effect, immune to fear!"); - // caster->Message_StringID(MT_Shout, IMMUNE_FEAR); - // return true; - //} + else if (CheckAATimer(aaTimerWarcry)) + { + Message(13, "Your are immune to fear."); + Log.Out(Logs::Detail, Logs::Spells, "Clients has WarCry effect, immune to fear!"); + caster->Message_StringID(MT_Shout, IMMUNE_FEAR); + return true; + } } if(IsCharmSpell(spell_id)) From c0ea82f9e108a43c6bede64a6c5a05bf46917e08 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 21 Jun 2015 02:58:43 -0400 Subject: [PATCH 203/846] SE_MeleeVulnerability really really is Max Mana limit Also found the cause of bard song tick increase and removed the uneeded code Also removed the IsBardSong check from GetFocusEffect, it really shouldn't be needed, but will need to keep an eye out. The focus effects should most often limit out the bard songs anyways --- common/spdat.h | 2 +- zone/bonuses.cpp | 14 -------------- zone/common.h | 1 - zone/effects.cpp | 6 ------ zone/mob.cpp | 3 --- zone/spell_effects.cpp | 21 ++++++++++++++------- 6 files changed, 15 insertions(+), 32 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index c8e039f15..938b659e1 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -544,7 +544,7 @@ typedef enum { //#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA) #define SE_FcTimerRefresh 389 // implemented - Refresh spell icons //#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited. -#define SE_MeleeVulnerability 391 // implemented [Live SPA has this as LimitManaMax however that is clearly not the effect used] +#define SE_LimitManaMax 391 // implemented #define SE_FcHealAmt 392 // implemented - Adds or removes healing from spells #define SE_FcHealPctIncoming 393 // implemented - HealRate with focus restrictions. #define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions. diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index e90f9626a..7ff8e7fc7 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1333,10 +1333,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->PetMeleeMitigation += base1; break; - case SE_MeleeVulnerability: - newbon->MeleeVulnerability += base1; - break; - case SE_FactionModPct: { if ((base1 < 0) && (newbon->FactionModPct > base1)) newbon->FactionModPct = base1; @@ -3008,10 +3004,6 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->PetMeleeMitigation += effect_value; break; - case SE_MeleeVulnerability: - new_bonus->MeleeVulnerability += effect_value; - break; - case SE_Sanctuary: new_bonus->Sanctuary = true; break; @@ -4588,12 +4580,6 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.FactionModPct = effect_value; break; - case SE_MeleeVulnerability: - spellbonuses.MeleeVulnerability = effect_value; - itembonuses.MeleeVulnerability = effect_value; - aabonuses.MeleeVulnerability = effect_value; - break; - case SE_IllusionPersistence: spellbonuses.IllusionPersistence = false; itembonuses.IllusionPersistence = false; diff --git a/zone/common.h b/zone/common.h index d21a0039d..e9521cb94 100644 --- a/zone/common.h +++ b/zone/common.h @@ -400,7 +400,6 @@ 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. - int32 MeleeVulnerability; // Weakness/mitigation to melee damage bool LimitToSkill[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. diff --git a/zone/effects.cpp b/zone/effects.cpp index 68e68e78d..85a858c94 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -421,12 +421,6 @@ int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) int tic_inc = 0; tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id); - // unsure on the exact details, but bard songs that don't cost mana at some point get an extra tick, 60 for now - // a level 53 bard reported getting 2 tics - // bard DOTs do get this extra tick, but beneficial long bard songs don't? (invul, crescendo) - if ((IsShortDurationBuff(spell_id) || IsDetrimentalSpell(spell_id)) && IsBardSong(spell_id) && - spells[spell_id].mana == 0 && GetClass() == BARD && GetLevel() > 60) - tic_inc++; float focused = ((duration * increase) / 100.0f) + tic_inc; int ifocused = static_cast(focused); diff --git a/zone/mob.cpp b/zone/mob.cpp index 4eb87f7ad..1777bb7a3 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3769,11 +3769,8 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used) skilldmg_mod += itembonuses.SkillDmgTaken[HIGHEST_SKILL+1] + spellbonuses.SkillDmgTaken[HIGHEST_SKILL+1] + itembonuses.SkillDmgTaken[skill_used] + spellbonuses.SkillDmgTaken[skill_used]; - skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1]; - skilldmg_mod += spellbonuses.MeleeVulnerability + itembonuses.MeleeVulnerability + aabonuses.MeleeVulnerability; - if(skilldmg_mod < -100) skilldmg_mod = -100; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 5c30185aa..71740e589 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2948,7 +2948,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_FcIncreaseNumHits: case SE_CastonFocusEffect: case SE_FcHealAmtIncoming: - case SE_MeleeVulnerability: + case SE_LimitManaMax: case SE_DoubleRangedAttack: case SE_ShieldEquipHateMod: case SE_ShieldEquipDmgMod: @@ -3356,7 +3356,7 @@ void Mob::BuffProcess() { --buffs[buffs_i].ticsremaining; - if ((buffs[buffs_i].ticsremaining == 0 && !IsShortDurationBuff(buffs[buffs_i].spellid)) || buffs[buffs_i].ticsremaining < 0) { + if ((buffs[buffs_i].ticsremaining == 0 && !(IsShortDurationBuff(buffs[buffs_i].spellid) || IsBardSong(buffs[buffs_i].spellid))) || 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); } @@ -4301,6 +4301,11 @@ int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) LimitFailure = true; break; + case SE_LimitManaMax: + if (spell.mana > base1) + LimitFailure = true; + break; + case SE_LimitTarget: if (base1 < 0) { if (-base1 == spell.targettype) // Exclude @@ -4719,6 +4724,11 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo return 0; break; + case SE_LimitManaMax: + if (spell.mana > focus_spell.base[i]) + return 0; + break; + case SE_LimitTarget: if (focus_spell.base[i] < 0) { if (-focus_spell.base[i] == spell.targettype) // Exclude @@ -5178,11 +5188,8 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { return 0; } -int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { - - if (IsBardSong(spell_id) && type != focusFcBaseEffects) - return 0; - +int16 Client::GetFocusEffect(focusType type, uint16 spell_id) +{ int16 realTotal = 0; int16 realTotal2 = 0; int16 realTotal3 = 0; From 77f050b653e77ea1cde5b3aea90f1f4513f77186 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 21 Jun 2015 01:25:34 -0700 Subject: [PATCH 204/846] setaapts command will now let you have up to 5k AA points, from 200. Removed the need to specify a prev_id in alternate_abilities table it can deduce that by itself. --- zone/aa.cpp | 21 ++++++++++++--------- zone/command.cpp | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 0c31034c7..974ccef13 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1520,7 +1520,9 @@ void Zone::LoadAlternateAdvancement() { //process these ranks AA::Rank *current = ability.second->first; int i = 1; + int prev_id = -1; while(current) { + current->prev_id = prev_id; current->prev = GetAlternateAdvancementRank(current->prev_id); current->next = GetAlternateAdvancementRank(current->next_id); current->base_ability = ability.second.get(); @@ -1531,11 +1533,11 @@ void Zone::LoadAlternateAdvancement() { //check prereqs here for(auto &prev_prereq : current->prev->prereqs) { - // //if prev has an aa we dont have set - // // then set it here too - // //if prev has an aa we have and the count is different - // // then set to whichever is highest - // + //if prev has an aa we dont have set + // then set it here too + //if prev has an aa we have + // then set to whichever is highest + auto iter = current->prereqs.find(prev_prereq.first); if(iter == current->prereqs.end()) { //not found @@ -1557,6 +1559,7 @@ void Zone::LoadAlternateAdvancement() { } i++; + prev_id = current->id; current = current->next; } } @@ -1602,7 +1605,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapspell = atoi(row[7]); rank->spell_type = atoi(row[8]); rank->recast_time = atoi(row[9]); - rank->prev_id = atoi(row[10]); - rank->next_id = atoi(row[11]); - rank->expansion = atoi(row[12]); + rank->next_id = atoi(row[10]); + rank->expansion = atoi(row[11]); rank->base_ability = nullptr; rank->total_cost = 0; + rank->prev_id = -1; rank->next = nullptr; rank->prev = nullptr; diff --git a/zone/command.cpp b/zone/command.cpp index 59f4bfa8a..7114244b3 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5554,8 +5554,8 @@ void command_setaapts(Client *c, const Seperator *sep) if(sep->arg[1][0] == '\0' || sep->arg[2][0] == '\0') c->Message(0, "Usage: #setaapts "); - else if(atoi(sep->arg[2]) <= 0 || atoi(sep->arg[2]) > 200) - c->Message(0, "You must have a number greater than 0 for points and no more than 200."); + else if(atoi(sep->arg[2]) <= 0 || atoi(sep->arg[2]) > 5000) + c->Message(0, "You must have a number greater than 0 for points and no more than 5000."); else if(!strcasecmp(sep->arg[1], "group")) { t->GetPP().group_leadership_points = atoi(sep->arg[2]); t->GetPP().group_leadership_exp = 0; From fd989cdbc84447a026d084e99ac258f0f2eea477 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 22 Jun 2015 00:08:21 -0400 Subject: [PATCH 205/846] Add back in the bard song focus check But also allowed focusSpellDuration through for that AA --- zone/spell_effects.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 71740e589..9134e8ff7 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5190,6 +5190,9 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { + if (IsBardSong(spell_id) && type != focusFcBaseEffects && type != focusSpellDuration) + return 0; + int16 realTotal = 0; int16 realTotal2 = 0; int16 realTotal3 = 0; From ce5e185738a4d0f643a7a925c4f9654746951e2a Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 23 Jun 2015 00:36:43 -0700 Subject: [PATCH 206/846] Reworked how grant aa works --- zone/aa.cpp | 86 ++++++++++++++++++++------------------------ zone/client.cpp | 4 --- zone/client.h | 3 ++ zone/lua_client.cpp | 6 ++++ zone/lua_client.h | 1 + zone/lua_mob.cpp | 6 ---- zone/lua_mob.h | 1 - zone/mob.h | 3 +- zone/perl_client.cpp | 29 +++++++++++++++ zone/perl_mob.cpp | 26 -------------- 10 files changed, 78 insertions(+), 87 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 5cbb5da14..8a4df6293 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -902,7 +902,7 @@ void Client::SendAlternateAdvancementPoints() { AA::Rank *rank = aa.second->GetRankByPointsSpent(ranks); if(rank) { aa2->aa_list[i].AA = rank->id; - aa2->aa_list[i].value = ranks; + aa2->aa_list[i].value = rank->total_cost; aa2->aa_list[i].charges = charges; i++; } @@ -993,10 +993,37 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { return; } - if(!CanPurchaseAlternateAdvancementRank(rank, true)) { + if(!CanPurchaseAlternateAdvancementRank(rank, true, true)) { return; } + FinishAlternateAdvancementPurchase(rank); +} + +bool Client::GrantAlternateAdvancementAbility(int aa_id, int points) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_id, points); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if(!rank) { + return false; + } + + if(!rank->base_ability) { + return false; + } + + if(!CanPurchaseAlternateAdvancementRank(rank, true, false)) { + return false; + } + + FinishAlternateAdvancementPurchase(rank); + return true; +} + +void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank) { + int rank_id = rank->base_ability->first_rank_id; + if(rank->base_ability->charges > 0) { uint32 charges = 0; GetAA(rank_id, &charges); @@ -1006,7 +1033,8 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { } SetAA(rank_id, rank->current_value, rank->base_ability->charges); - } else { + } + else { SetAA(rank_id, rank->current_value, 0); //if not max then send next aa @@ -1029,17 +1057,18 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ + if(RuleB(QueryServ, PlayerLogAAPurchases)){ std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } - } else { + } + else { Message_StringID(15, AA_GAIN_ABILITY, std::to_string(rank->title_sid).c_str(), std::to_string(rank->cost).c_str(), std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ + if(RuleB(QueryServ, PlayerLogAAPurchases)){ std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } @@ -1061,7 +1090,7 @@ void Client::IncrementAlternateAdvancementRank(int rank_id) { return; } - if(!CanPurchaseAlternateAdvancementRank(rank, false)) { + if(!CanPurchaseAlternateAdvancementRank(rank, false, true)) { return; } @@ -1443,7 +1472,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return true; } -bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) { +bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, bool check_grant) { AA::Ability *ability = rank->base_ability; if(!ability) @@ -1454,7 +1483,7 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) } //You can't purchase grant only AAs they can only be assigned - if(ability->grant_only) { + if(check_grant && ability->grant_only) { return false; } @@ -1692,45 +1721,6 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapGetAlternateAdvancementAbilityAndRank(aa_id, points); - auto ability = ability_rank.first; - auto rank = ability_rank.second; - - if(!ability) { - return; - } - - if(ability->charges > 0) { - return; - } - - if(!ability->grant_only) { - return; - } - - if(!CanUseAlternateAdvancementRank(rank)) { - return; - } - - SetAA(ability->first_rank_id, rank->current_value, 0); - - if(IsClient()) { - Client *c = CastToClient(); - - if(rank->next) { - c->SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value); - } - - c->SendAlternateAdvancementPoints(); - c->SendAlternateAdvancementStats(); - c->CalcBonuses(); - } -} - bool Mob::CheckAATimer(int timer) { if (timer >= aaTimerMax) diff --git a/zone/client.cpp b/zone/client.cpp index ae0ceedff..240902d09 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -532,10 +532,6 @@ bool Client::SaveAA() { if(!ability) continue; - if(ability->grant_only) { - continue; - } - if(rank.second.first > 0) { AA::Rank *r = ability->GetRankByPointsSpent(rank.second.first); diff --git a/zone/client.h b/zone/client.h index 44e86f971..8b0522162 100644 --- a/zone/client.h +++ b/zone/client.h @@ -763,6 +763,7 @@ public: void SendAlternateAdvancementTable(); void SendAlternateAdvancementStats(); void PurchaseAlternateAdvancementRank(int rank_id); + bool GrantAlternateAdvancementAbility(int aa_id, int points); void IncrementAlternateAdvancementRank(int rank_id); void ActivateAlternateAdvancementAbility(int rank_id, int target_id); void SendAlternateAdvancementPoints(); @@ -1262,6 +1263,8 @@ protected: int16 GetFocusEffect(focusType type, uint16 spell_id); uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); + void FinishAlternateAdvancementPurchase(AA::Rank *rank); + Mob* bind_sight_target; glm::vec4 m_AutoAttackPosition; diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 37f379a06..8f2106b04 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1027,6 +1027,11 @@ void Lua_Client::IncrementAA(int aa) { self->IncrementAlternateAdvancementRank(aa); } +bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points) { + Lua_Safe_Call_Bool(); + self->GrantAlternateAdvancementAbility(aa_id, points); +} + void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z) { Lua_Safe_Call_Void(); self->MarkSingleCompassLoc(in_x, in_y, in_z); @@ -1500,6 +1505,7 @@ luabind::scope lua_register_client() { .def("AddLevelBasedExp", (void(Lua_Client::*)(int))&Lua_Client::AddLevelBasedExp) .def("AddLevelBasedExp", (void(Lua_Client::*)(int,int))&Lua_Client::AddLevelBasedExp) .def("IncrementAA", (void(Lua_Client::*)(int))&Lua_Client::IncrementAA) + .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int))&Lua_Client::GrantAlternateAdvancementAbility) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float))&Lua_Client::MarkSingleCompassLoc) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float,int))&Lua_Client::MarkSingleCompassLoc) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(void))&Lua_Client::GetNextAvailableSpellBookSlot) diff --git a/zone/lua_client.h b/zone/lua_client.h index 8f930fc26..a20f4fb57 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -233,6 +233,7 @@ public: void AddLevelBasedExp(int exp_pct); void AddLevelBasedExp(int exp_pct, int max_level); void IncrementAA(int aa); + bool GrantAlternateAdvancementAbility(int aa_id, int points); void MarkSingleCompassLoc(float in_x, float in_y, float in_z); void MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count); int GetNextAvailableSpellBookSlot(); diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 31719d364..9662d1931 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1210,11 +1210,6 @@ bool Lua_Mob::SetAA(int rank_id, int new_value, int charges) { return self->SetAA(rank_id, new_value, charges); } -void Lua_Mob::GrantAlternateAdvancementAbility(int aa_id, int points) { - Lua_Safe_Call_Void(); - self->GrantAlternateAdvancementAbility(aa_id, points); -} - bool Lua_Mob::DivineAura() { Lua_Safe_Call_Bool(); return self->DivineAura(); @@ -2097,7 +2092,6 @@ luabind::scope lua_register_mob() { .def("GetAAByAAID", (int(Lua_Mob::*)(int))&Lua_Mob::GetAAByAAID) .def("SetAA", (bool(Lua_Mob::*)(int,int))&Lua_Mob::SetAA) .def("SetAA", (bool(Lua_Mob::*)(int,int,int))&Lua_Mob::SetAA) - .def("GrantAlternateAdvancementAbility", (void(Lua_Mob::*)(int, int))&Lua_Mob::GrantAlternateAdvancementAbility) .def("DivineAura", (bool(Lua_Mob::*)(void))&Lua_Mob::DivineAura) .def("SetOOCRegen", (void(Lua_Mob::*)(int))&Lua_Mob::SetOOCRegen) .def("GetEntityVariable", (const char*(Lua_Mob::*)(const char*))&Lua_Mob::GetEntityVariable) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 914f46c5d..4f427aca5 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -252,7 +252,6 @@ public: int GetAAByAAID(int id); bool SetAA(int rank_id, int new_value); bool SetAA(int rank_id, int new_value, int charges); - void GrantAlternateAdvancementAbility(int aa_id, int points); bool DivineAura(); void SetOOCRegen(int regen); const char* GetEntityVariable(const char *name); diff --git a/zone/mob.h b/zone/mob.h index c9ba4471d..60a40711b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -965,12 +965,11 @@ public: bool SetAA(uint32 rank_id, uint32 new_value, uint32 charges = 0); void ClearAAs() { aa_ranks.clear(); } bool CanUseAlternateAdvancementRank(AA::Rank *rank); - bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price); + bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, bool check_grant); int GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in); void ExpendAlternateAdvancementCharge(uint32 aa_id); void CalcAABonuses(StatBonuses* newbon); void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon); - void GrantAlternateAdvancementAbility(int aa_id, int points); bool CheckAATimer(int timer); protected: diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index eea9918cd..c836e378e 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4894,6 +4894,34 @@ XS(XS_Client_IncrementAA) XSRETURN_EMPTY; } +XS(XS_Client_GrantAlternateAdvancementAbility); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GrantAlternateAdvancementAbility) +{ + dXSARGS; + if(items != 3) + Perl_croak(aTHX_ "Usage: Client::GrantAlternateAdvancementAbility(THIS, aa_id, points)"); + { + Client * THIS; + bool RETVAL; + int aa_id = (int)SvIV(ST(1)); + int points = (int)SvIV(ST(2)); + + 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->GrantAlternateAdvancementAbility(aa_id, points); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + XS(XS_Client_GetAALevel); XS(XS_Client_GetAALevel) { @@ -6437,6 +6465,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetIP"), XS_Client_GetIP, file, "$"); newXSproto(strcpy(buf, "AddLevelBasedExp"), XS_Client_AddLevelBasedExp, file, "$$;$"); newXSproto(strcpy(buf, "IncrementAA"), XS_Client_IncrementAA, file, "$$"); + newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file, "$$$"); newXSproto(strcpy(buf, "GetAALevel"), XS_Client_GetAALevel, file, "$$"); newXSproto(strcpy(buf, "MarkCompassLoc"), XS_Client_MarkCompassLoc, file, "$$$$"); newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$"); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 612d9f868..dcd999a3e 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -6438,31 +6438,6 @@ XS(XS_Mob_SetAA) XSRETURN(1); } -XS(XS_Mob_GrantAlternateAdvancementAbility); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GrantAlternateAdvancementAbility) -{ - dXSARGS; - if(items != 3) - Perl_croak(aTHX_ "Usage: Mob::GrantAlternateAdvancementAbility(THIS, aa_id, points)"); - { - Mob * THIS; - int aa_id = (int)SvIV(ST(1)); - int points = (int)SvIV(ST(2)); - - 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."); - - THIS->GrantAlternateAdvancementAbility(aa_id, points); - } - XSRETURN_EMPTY; -} - XS(XS_Mob_DivineAura); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_DivineAura) { @@ -8708,7 +8683,6 @@ XS(boot_Mob) newXSproto(strcpy(buf, "GetAA"), XS_Mob_GetAA, file, "$$"); newXSproto(strcpy(buf, "GetAAByAAID"), XS_Mob_GetAAByAAID, file, "$$"); newXSproto(strcpy(buf, "SetAA"), XS_Mob_SetAA, file, "$$$;$"); - newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Mob_GrantAlternateAdvancementAbility, file, "$$$"); newXSproto(strcpy(buf, "DivineAura"), XS_Mob_DivineAura, file, "$"); newXSproto(strcpy(buf, "AddFeignMemory"), XS_Mob_AddFeignMemory, file, "$$"); newXSproto(strcpy(buf, "RemoveFromFeignMemory"), XS_Mob_RemoveFromFeignMemory, file, "$$"); From a41570677f698805c0d86cc525bcbea73db05dc4 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 23 Jun 2015 12:53:46 -0700 Subject: [PATCH 207/846] More work on Granting, incrementaa now uses grant internally which should make it work more consistently with its old behavior --- zone/aa.cpp | 130 +++++++++++++++++-------------------------- zone/client.h | 4 +- zone/lua_client.cpp | 6 ++ zone/lua_client.h | 1 + zone/perl_client.cpp | 13 +++-- 5 files changed, 70 insertions(+), 84 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 8a4df6293..c97ff7af4 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -762,6 +762,10 @@ void Client::RefundAA() { continue; } + if(ability->grant_only) { + continue; + } + refunded += rank->total_cost; } @@ -997,31 +1001,36 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { return; } - FinishAlternateAdvancementPurchase(rank); + FinishAlternateAdvancementPurchase(rank, false); } -bool Client::GrantAlternateAdvancementAbility(int aa_id, int points) { - auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_id, points); - auto ability = ability_rank.first; - auto rank = ability_rank.second; +bool Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost) { + bool ret = false; + for(int i = 1; i <= points; ++i) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_id, i); + auto ability = ability_rank.first; + auto rank = ability_rank.second; - if(!rank) { - return false; + if(!rank) { + continue; + } + + if(!rank->base_ability) { + continue; + } + + if(!CanPurchaseAlternateAdvancementRank(rank, !ignore_cost, false)) { + continue; + } + + ret = true; + FinishAlternateAdvancementPurchase(rank, ignore_cost); } - if(!rank->base_ability) { - return false; - } - - if(!CanPurchaseAlternateAdvancementRank(rank, true, false)) { - return false; - } - - FinishAlternateAdvancementPurchase(rank); - return true; + return ret; } -void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank) { +void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost) { int rank_id = rank->base_ability->first_rank_id; if(rank->base_ability->charges > 0) { @@ -1043,7 +1052,9 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank) { } } - m_pp.aapoints -= rank->cost; + int cost = !ignore_cost ? rank->cost : 0; + + m_pp.aapoints -= cost ; SaveAA(); SendAlternateAdvancementPoints(); @@ -1053,30 +1064,33 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank) { Message_StringID(15, AA_IMPROVE, std::to_string(rank->title_sid).c_str(), std::to_string(rank->prev->current_value).c_str(), - std::to_string(rank->cost).c_str(), - std::to_string(AA_POINTS).c_str()); + std::to_string(cost).c_str(), + cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ - if(RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); + if(RuleB(QueryServ, PlayerLogAAPurchases)) { + std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, cost, GetZoneID(), GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } } else { Message_StringID(15, AA_GAIN_ABILITY, std::to_string(rank->title_sid).c_str(), - std::to_string(rank->cost).c_str(), - std::to_string(AA_POINTS).c_str()); + std::to_string(cost).c_str(), + cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ - if(RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); + if(RuleB(QueryServ, PlayerLogAAPurchases)) { + std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, cost, GetZoneID(), GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } } CalcBonuses(); - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) - NotifyNewTitlesAvailable(); + + if(cost > 0) { + if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) + NotifyNewTitlesAvailable(); + } } //need to rewrite this @@ -1090,54 +1104,8 @@ void Client::IncrementAlternateAdvancementRank(int rank_id) { return; } - if(!CanPurchaseAlternateAdvancementRank(rank, false, true)) { - return; - } - - if(rank->base_ability->charges > 0) { - SetAA(rank_id, rank->current_value, rank->base_ability->charges); - } - else { - SetAA(rank_id, rank->current_value, 0); - - //if not max then send next aa - if(rank->next) { - SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value); - } - } - - SaveAA(); - - SendAlternateAdvancementPoints(); - SendAlternateAdvancementStats(); - - if(rank->prev) { - Message_StringID(15, AA_IMPROVE, - std::to_string(rank->title_sid).c_str(), - std::to_string(rank->prev->current_value).c_str(), - std::to_string(rank->cost).c_str(), - std::to_string(AA_POINTS).c_str()); - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); - } - } - else { - Message_StringID(15, AA_GAIN_ABILITY, - std::to_string(rank->title_sid).c_str(), - std::to_string(rank->cost).c_str(), - std::to_string(AA_POINTS).c_str()); - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - } - } - - CalcBonuses(); + int points = GetAA(rank_id); + GrantAlternateAdvancementAbility(rank->base_ability->id, points + 1, true); } void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { @@ -1496,12 +1464,18 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, auto points = GetAA(rank->id, ¤t_charges); //check that we are on previous rank already (if exists) - if(rank->prev) { + //grant ignores the req to own the previous rank. + if(check_grant && rank->prev) { if(points != rank->prev->current_value) { return false; } } + //check that we aren't already on this rank or one ahead of us + if(points >= rank->current_value) { + return false; + } + //if expendable only let us purchase if we have no charges already //not quite sure on how this functions client side atm //I intend to look into it later to make sure the behavior is right diff --git a/zone/client.h b/zone/client.h index 8b0522162..7ab3749e1 100644 --- a/zone/client.h +++ b/zone/client.h @@ -763,7 +763,7 @@ public: void SendAlternateAdvancementTable(); void SendAlternateAdvancementStats(); void PurchaseAlternateAdvancementRank(int rank_id); - bool GrantAlternateAdvancementAbility(int aa_id, int points); + bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost = false); void IncrementAlternateAdvancementRank(int rank_id); void ActivateAlternateAdvancementAbility(int rank_id, int target_id); void SendAlternateAdvancementPoints(); @@ -1263,7 +1263,7 @@ protected: int16 GetFocusEffect(focusType type, uint16 spell_id); uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); - void FinishAlternateAdvancementPurchase(AA::Rank *rank); + void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost); Mob* bind_sight_target; diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 8f2106b04..0c5bf8cc1 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1032,6 +1032,11 @@ bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points) { 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); +} + void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z) { Lua_Safe_Call_Void(); self->MarkSingleCompassLoc(in_x, in_y, in_z); @@ -1506,6 +1511,7 @@ luabind::scope lua_register_client() { .def("AddLevelBasedExp", (void(Lua_Client::*)(int,int))&Lua_Client::AddLevelBasedExp) .def("IncrementAA", (void(Lua_Client::*)(int))&Lua_Client::IncrementAA) .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int))&Lua_Client::GrantAlternateAdvancementAbility) + .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int, bool))&Lua_Client::GrantAlternateAdvancementAbility) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float))&Lua_Client::MarkSingleCompassLoc) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float,int))&Lua_Client::MarkSingleCompassLoc) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(void))&Lua_Client::GetNextAvailableSpellBookSlot) diff --git a/zone/lua_client.h b/zone/lua_client.h index a20f4fb57..0639cd6da 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -234,6 +234,7 @@ public: void AddLevelBasedExp(int exp_pct, int max_level); void IncrementAA(int aa); bool GrantAlternateAdvancementAbility(int aa_id, int points); + bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost); void MarkSingleCompassLoc(float in_x, float in_y, float in_z); void MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count); int GetNextAvailableSpellBookSlot(); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index c836e378e..ee4ee943d 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4898,13 +4898,14 @@ XS(XS_Client_GrantAlternateAdvancementAbility); /* prototype to pass -Wmissing-p XS(XS_Client_GrantAlternateAdvancementAbility) { dXSARGS; - if(items != 3) - Perl_croak(aTHX_ "Usage: Client::GrantAlternateAdvancementAbility(THIS, aa_id, points)"); + if(items < 3 || items > 4) + Perl_croak(aTHX_ "Usage: Client::GrantAlternateAdvancementAbility(THIS, aa_id, points, [ignore_cost])"); { Client * THIS; bool RETVAL; int aa_id = (int)SvIV(ST(1)); int points = (int)SvIV(ST(2)); + bool ignore_cost = false; if(sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -4915,7 +4916,11 @@ XS(XS_Client_GrantAlternateAdvancementAbility) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->GrantAlternateAdvancementAbility(aa_id, points); + if(items > 3) { + ignore_cost = (bool)SvTRUE(ST(3)); + } + + RETVAL = THIS->GrantAlternateAdvancementAbility(aa_id, points, ignore_cost); ST(0) = boolSV(RETVAL); sv_2mortal(ST(0)); } @@ -6465,7 +6470,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetIP"), XS_Client_GetIP, file, "$"); newXSproto(strcpy(buf, "AddLevelBasedExp"), XS_Client_AddLevelBasedExp, file, "$$;$"); newXSproto(strcpy(buf, "IncrementAA"), XS_Client_IncrementAA, file, "$$"); - newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file, "$$$"); + newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file, "$$$;$"); newXSproto(strcpy(buf, "GetAALevel"), XS_Client_GetAALevel, file, "$$"); newXSproto(strcpy(buf, "MarkCompassLoc"), XS_Client_MarkCompassLoc, file, "$$$$"); newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$"); From 8f156b3c91a2fef24b1ca7c86cd050784f83f7c3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 23 Jun 2015 18:37:24 -0400 Subject: [PATCH 208/846] Add Client:GetAccountAge to Lua --- zone/client.h | 1 + zone/lua_client.cpp | 6 ++++++ zone/lua_client.h | 5 +++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/zone/client.h b/zone/client.h index 7ab3749e1..4298bcc46 100644 --- a/zone/client.h +++ b/zone/client.h @@ -622,6 +622,7 @@ public: inline uint32 AccountID() const { return account_id; } inline const char* AccountName()const { return account_name; } + inline int GetAccountCreation() const { return account_creation; } inline int16 Admin() const { return admin; } inline uint32 CharacterID() const { return character_id; } void UpdateAdmin(bool iFromDB = true); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 0c5bf8cc1..d69924577 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -350,6 +350,11 @@ const char *Lua_Client::AccountName() { return self->AccountName(); } +int Lua_Client::GetAccountAge() { + Lua_Safe_Call_Int(); + return time(nullptr) - self->GetAccountCreation(); +} + int Lua_Client::Admin() { Lua_Safe_Call_Bool(); return self->Admin(); @@ -1375,6 +1380,7 @@ luabind::scope lua_register_client() { .def("GetRawItemAC", (int(Lua_Client::*)(void))&Lua_Client::GetRawItemAC) .def("AccountID", (uint32(Lua_Client::*)(void))&Lua_Client::AccountID) .def("AccountName", (const char *(Lua_Client::*)(void))&Lua_Client::AccountName) + .def("GetAccountAge", (int(Lua_Client::*)(void))&Lua_Client::GetAccountAge) .def("Admin", (int(Lua_Client::*)(void))&Lua_Client::Admin) .def("CharacterID", (uint32(Lua_Client::*)(void))&Lua_Client::CharacterID) .def("GuildRank", (int(Lua_Client::*)(void))&Lua_Client::GuildRank) diff --git a/zone/lua_client.h b/zone/lua_client.h index 0639cd6da..dd1059a0a 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -166,9 +166,9 @@ public: void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3); void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4); void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5); - void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, + void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned); - void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, + void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, int to_slot); void SetStats(int type, int value); void IncStats(int type, int value); @@ -262,6 +262,7 @@ public: bool HasSpellScribed(int spell_id); void SetAccountFlag(std::string flag, std::string val); std::string GetAccountFlag(std::string flag); + int GetAccountAge(); Lua_Group GetGroup(); Lua_Raid GetRaid(); bool PutItemInInventory(int slot_id, Lua_ItemInst inst); From 67143f1b8afbb0a0661d2b34bd46d43f5d71ddda Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 23 Jun 2015 17:39:06 -0700 Subject: [PATCH 209/846] Initial work on shared memory hotfixes --- common/item.cpp | 20 ++++- common/servertalk.h | 1 + common/shareddb.cpp | 137 ++++++++++++++-------------------- common/shareddb.h | 33 ++++---- shared_memory/base_data.cpp | 7 +- shared_memory/base_data.h | 3 +- shared_memory/items.cpp | 6 +- shared_memory/items.h | 4 +- shared_memory/loot.cpp | 9 ++- shared_memory/loot.h | 4 +- shared_memory/main.cpp | 67 ++++++++++------- shared_memory/npc_faction.cpp | 6 +- shared_memory/npc_faction.h | 4 +- shared_memory/skill_caps.cpp | 6 +- shared_memory/skill_caps.h | 4 +- shared_memory/spells.cpp | 8 +- shared_memory/spells.h | 4 +- world/net.cpp | 10 ++- world/zoneserver.cpp | 21 +++++- zone/command.cpp | 14 ++++ zone/command.h | 3 +- zone/net.cpp | 45 ++++------- zone/worldserver.cpp | 35 +++++++++ 23 files changed, 266 insertions(+), 185 deletions(-) diff --git a/common/item.cpp b/common/item.cpp index 3e8be66ca..7c871e630 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1440,7 +1440,11 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) // ItemInst::ItemInst(const Item_Struct* item, int16 charges) { m_use_type = ItemInstNormal; - m_item = item; + if(item) { + m_item = new Item_Struct(*item); + } else { + m_item = nullptr; + } m_charges = charges; m_price = 0; m_attuned = false; @@ -1467,6 +1471,13 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) { 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); + } + else { + m_item = nullptr; + } + m_charges = charges; m_price = 0; m_merchantslot = 0; @@ -1515,7 +1526,11 @@ ItemInst::ItemInst(ItemInstTypes use_type) { ItemInst::ItemInst(const ItemInst& copy) { m_use_type=copy.m_use_type; - m_item=copy.m_item; + if(copy.m_item) + m_item = new Item_Struct(*copy.m_item); + else + m_item = nullptr; + m_charges=copy.m_charges; m_price=copy.m_price; m_color=copy.m_color; @@ -1568,6 +1583,7 @@ ItemInst::ItemInst(const ItemInst& copy) ItemInst::~ItemInst() { Clear(); + safe_delete(m_item); safe_delete(m_scaledItem); safe_delete(m_evolveInfo); } diff --git a/common/servertalk.h b/common/servertalk.h index af39bfaa4..586712110 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -84,6 +84,7 @@ #define ServerOP_QGlobalDelete 0x0064 #define ServerOP_DepopPlayerCorpse 0x0065 #define ServerOP_RequestTellQueue 0x0066 // client asks for it's tell queues +#define ServerOP_ChangeSharedMem 0x0067 #define ServerOP_RaidAdd 0x0100 //in use #define ServerOP_RaidRemove 0x0101 //in use diff --git a/common/shareddb.cpp b/common/shareddb.cpp index aa4924665..40bb471d4 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -16,29 +16,16 @@ #include "string_util.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) +: Database() { } 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) +: Database(host, user, passwd, database, port) { } 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) @@ -797,28 +784,15 @@ void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id) item_count = atoi(row[1]); } -bool SharedDatabase::LoadItems() { - if(items_mmf) { - return true; - } +bool SharedDatabase::LoadItems(const std::string &prefix) { + items_mmf.reset(nullptr); 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); + 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())); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what()); @@ -1229,27 +1203,16 @@ void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_co } -bool SharedDatabase::LoadNPCFactionLists() { - if(faction_hash) { - return true; - } +bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { + faction_mmf.reset(nullptr); + faction_hash.reset(nullptr); 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); - 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); + std::string file_name = std::string("shared/") + 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(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading npc factions: %s", ex.what()); @@ -1378,9 +1341,8 @@ bool SharedDatabase::GetCommandSettings(std::map &commands) { return true; } -bool SharedDatabase::LoadSkillCaps() { - if(skill_caps_mmf) - return true; +bool SharedDatabase::LoadSkillCaps(const std::string &prefix) { + skill_caps_mmf.reset(nullptr); uint32 class_count = PLAYER_CLASS_COUNT; uint32 skill_count = HIGHEST_SKILL + 1; @@ -1390,11 +1352,8 @@ bool SharedDatabase::LoadSkillCaps() { 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"); - } - + std::string file_name = std::string("shared/") + prefix + std::string("skill_caps"); + skill_caps_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); mutex.Unlock(); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "Error loading skill caps: %s", ex.what()); @@ -1542,8 +1501,29 @@ int SharedDatabase::GetMaxSpellID() { return atoi(row[0]); } +bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) { + spells_mmf.reset(nullptr); + + try { + EQEmu::IPCMutex mutex("spells"); + mutex.Lock(); + + std::string file_name = std::string("shared/") + 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); + mutex.Unlock(); + } + catch(std::exception& ex) { + Log.Out(Logs::General, Logs::Error, "Error Loading Spells: %s", ex.what()); + return false; + } + return true; +} + void SharedDatabase::LoadSpells(void *data, int max_spells) { - SPDat_Spell_Struct *sp = reinterpret_cast(data); + *(uint32*)data = max_spells; + SPDat_Spell_Struct *sp = reinterpret_cast((char*)data + sizeof(uint32)); const std::string query = "SELECT * FROM spells_new ORDER BY id ASC"; auto results = QueryDatabase(query); @@ -1719,25 +1699,15 @@ int SharedDatabase::GetMaxBaseDataLevel() { return atoi(row[0]); } -bool SharedDatabase::LoadBaseData() { - if(base_data_mmf) { - return true; - } +bool SharedDatabase::LoadBaseData(const std::string &prefix) { + base_data_mmf.reset(nullptr); 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"); - } + std::string file_name = std::string("shared/") + prefix + std::string("base_data"); + base_data_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading Base Data: %s", ex.what()); @@ -1793,7 +1763,6 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) { bd->mana_factor = atof(row[8]); bd->endurance_factor = atof(row[9]); } - } const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) { @@ -1967,21 +1936,23 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { } -bool SharedDatabase::LoadLoot() { - if(loot_table_mmf || loot_drop_mmf) - return true; +bool SharedDatabase::LoadLoot(const std::string &prefix) { + loot_table_mmf.reset(nullptr); + loot_drop_mmf.reset(nullptr); try { EQEmu::IPCMutex mutex("loot"); mutex.Lock(); - loot_table_mmf = new EQEmu::MemoryMappedFile("shared/loot_table"); - loot_table_hash = new EQEmu::FixedMemoryVariableHashSet( + std::string file_name_lt = std::string("shared/") + 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()); - loot_drop_mmf = new EQEmu::MemoryMappedFile("shared/loot_drop"); - loot_drop_hash = new EQEmu::FixedMemoryVariableHashSet( + loot_table_mmf->Size())); + std::string file_name_ld = std::string("shared/") + 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()), - loot_drop_mmf->Size()); + loot_drop_mmf->Size())); mutex.Unlock(); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "Error loading loot: %s", ex.what()); diff --git a/common/shareddb.h b/common/shareddb.h index aef325380..923e5b775 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -12,6 +12,7 @@ #include #include +#include class EvolveInfo; class Inventory; @@ -92,7 +93,7 @@ class SharedDatabase : public Database //items void GetItemsCount(int32 &item_count, uint32 &max_id); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); - bool LoadItems(); + bool LoadItems(const std::string &prefix); const Item_Struct* IterateItems(uint32* id); const Item_Struct* GetItem(uint32 id); const EvolveInfo* GetEvolveInfo(uint32 loregroup); @@ -101,43 +102,45 @@ class SharedDatabase : public Database void GetFactionListInfo(uint32 &list_count, uint32 &max_lists); const NPCFactionList* GetNPCFactionEntry(uint32 id); void LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists); - bool LoadNPCFactionLists(); + bool LoadNPCFactionLists(const std::string &prefix); //loot void GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries); void GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries); void LoadLootTables(void *data, uint32 size); void LoadLootDrops(void *data, uint32 size); - bool LoadLoot(); + bool LoadLoot(const std::string &prefix); const LootTable_Struct* GetLootTable(uint32 loottable_id); const LootDrop_Struct* GetLootDrop(uint32 lootdrop_id); void LoadSkillCaps(void *data); - bool LoadSkillCaps(); + bool LoadSkillCaps(const std::string &prefix); uint16 GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level); uint8 GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level); int GetMaxSpellID(); + bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp); void LoadSpells(void *data, int max_spells); void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID); int GetMaxBaseDataLevel(); - bool LoadBaseData(); + bool LoadBaseData(const std::string &prefix); void LoadBaseData(void *data, int max_level); const BaseDataStruct* GetBaseData(int lvl, int cl); protected: - EQEmu::MemoryMappedFile *skill_caps_mmf; - EQEmu::MemoryMappedFile *items_mmf; - EQEmu::FixedMemoryHashSet *items_hash; - EQEmu::MemoryMappedFile *faction_mmf; - EQEmu::FixedMemoryHashSet *faction_hash; - EQEmu::MemoryMappedFile *loot_table_mmf; - EQEmu::FixedMemoryVariableHashSet *loot_table_hash; - EQEmu::MemoryMappedFile *loot_drop_mmf; - EQEmu::FixedMemoryVariableHashSet *loot_drop_hash; - EQEmu::MemoryMappedFile *base_data_mmf; + std::unique_ptr skill_caps_mmf; + std::unique_ptr items_mmf; + std::unique_ptr> items_hash; + std::unique_ptr faction_mmf; + std::unique_ptr> faction_hash; + std::unique_ptr loot_table_mmf; + std::unique_ptr> loot_table_hash; + std::unique_ptr loot_drop_mmf; + std::unique_ptr> loot_drop_hash; + std::unique_ptr base_data_mmf; + std::unique_ptr spells_mmf; }; #endif /*SHAREDDB_H_*/ diff --git a/shared_memory/base_data.cpp b/shared_memory/base_data.cpp index 086256cda..e82c5a2c1 100644 --- a/shared_memory/base_data.cpp +++ b/shared_memory/base_data.cpp @@ -23,7 +23,7 @@ #include "../common/memory_mapped_file.h" #include "../common/eqemu_exception.h" -void LoadBaseData(SharedDatabase *database) { +void LoadBaseData(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("base_data"); mutex.Lock(); int records = (database->GetMaxBaseDataLevel() + 1); @@ -32,11 +32,12 @@ void LoadBaseData(SharedDatabase *database) { } uint32 size = records * 16 * sizeof(BaseDataStruct); - EQEmu::MemoryMappedFile mmf("shared/base_data", size); + + std::string file_name = std::string("shared/") + prefix + std::string("base_data"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); database->LoadBaseData(ptr, records); mutex.Unlock(); } - diff --git a/shared_memory/base_data.h b/shared_memory/base_data.h index c1f6c87ea..afa799eea 100644 --- a/shared_memory/base_data.h +++ b/shared_memory/base_data.h @@ -19,7 +19,8 @@ #ifndef __EQEMU_SHARED_MEMORY_BASE_DATA_H #define __EQEMU_SHARED_MEMORY_BASE_DATA_H +#include class SharedDatabase; -void LoadBaseData(SharedDatabase *database); +void LoadBaseData(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index 48b81b6fc..02a102a8f 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -24,7 +24,7 @@ #include "../common/eqemu_exception.h" #include "../common/item_struct.h" -void LoadItems(SharedDatabase *database) { +void LoadItems(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("items"); mutex.Lock(); @@ -36,7 +36,9 @@ void LoadItems(SharedDatabase *database) { } uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); - EQEmu::MemoryMappedFile mmf("shared/items", size); + + std::string file_name = std::string("shared/") + prefix + std::string("items"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); diff --git a/shared_memory/items.h b/shared_memory/items.h index 21702eb50..cff9794fd 100644 --- a/shared_memory/items.h +++ b/shared_memory/items.h @@ -19,7 +19,9 @@ #ifndef __EQEMU_SHARED_MEMORY_ITEMS_H #define __EQEMU_SHARED_MEMORY_ITEMS_H +#include + class SharedDatabase; -void LoadItems(SharedDatabase *database); +void LoadItems(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/loot.cpp b/shared_memory/loot.cpp index 66982c05a..956383cd3 100644 --- a/shared_memory/loot.cpp +++ b/shared_memory/loot.cpp @@ -25,7 +25,7 @@ #include "../common/fixed_memory_variable_hash_set.h" #include "../common/loottable.h" -void LoadLoot(SharedDatabase *database) { +void LoadLoot(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("loot"); mutex.Lock(); @@ -44,8 +44,11 @@ void LoadLoot(SharedDatabase *database) { (loot_drop_count * sizeof(LootDrop_Struct)) + //loot table headers (loot_drop_entries_count * sizeof(LootDropEntries_Struct)); //number of loot table entries - EQEmu::MemoryMappedFile mmf_loot_table("shared/loot_table", loot_table_size); - EQEmu::MemoryMappedFile mmf_loot_drop("shared/loot_drop", loot_drop_size); + 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"); + + EQEmu::MemoryMappedFile mmf_loot_table(file_name_lt, loot_table_size); + EQEmu::MemoryMappedFile mmf_loot_drop(file_name_ld, loot_drop_size); mmf_loot_table.ZeroFile(); mmf_loot_drop.ZeroFile(); diff --git a/shared_memory/loot.h b/shared_memory/loot.h index df97ad321..27e812185 100644 --- a/shared_memory/loot.h +++ b/shared_memory/loot.h @@ -19,7 +19,9 @@ #ifndef __EQEMU_SHARED_MEMORY_LOOT_H #define __EQEMU_SHARED_MEMORY_LOOT_H +#include + class SharedDatabase; -void LoadLoot(SharedDatabase *database); +void LoadLoot(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 2623ccd26..3d47f217f 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -26,6 +26,7 @@ #include "../common/crash.h" #include "../common/rulesys.h" #include "../common/eqemu_exception.h" +#include "../common/string_util.h" #include "items.h" #include "npc_faction.h" #include "loot.h" @@ -61,6 +62,7 @@ int main(int argc, char **argv) { database.LoadLogSettings(Log.log_settings); Log.StartFileLogs(); + std::string hotfix_name = ""; bool load_all = true; bool load_items = false; bool load_factions = false; @@ -69,112 +71,125 @@ int main(int argc, char **argv) { bool load_spells = false; bool load_bd = false; if(argc > 1) { - load_all = false; - for(int i = 1; i < argc; ++i) { - switch(argv[i][0]) { - case 'a': - if(strcasecmp("all", argv[i]) == 0) { - load_all = true; - } - break; - + switch(argv[i][0]) { case 'b': if(strcasecmp("base_data", argv[i]) == 0) { load_bd = true; + load_all = false; } break; - + case 'i': if(strcasecmp("items", argv[i]) == 0) { load_items = true; + load_all = false; } break; - + case 'f': if(strcasecmp("factions", argv[i]) == 0) { load_factions = true; + load_all = false; } break; - + case 'l': if(strcasecmp("loot", argv[i]) == 0) { load_loot = true; + load_all = false; } break; - + case 's': if(strcasecmp("skill_caps", argv[i]) == 0) { load_skill_caps = true; + load_all = false; } else if(strcasecmp("spells", argv[i]) == 0) { load_spells = true; + load_all = false; } break; + case '-': { + auto split = SplitString(argv[i], '='); + if(split.size() >= 2) { + auto command = split[0]; + auto argument = split[1]; + if(strcasecmp("-hotfix", command.c_str()) == 0) { + hotfix_name = argument; + load_all = true; + } + } + break; + } } } } + if(hotfix_name.length() > 0) { + Log.Out(Logs::General, Logs::Status, "Writing data for hotfix '%s'", hotfix_name.c_str()); + } + if(load_all || load_items) { Log.Out(Logs::General, Logs::Status, "Loading items..."); try { - LoadItems(&database); + LoadItems(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_factions) { Log.Out(Logs::General, Logs::Status, "Loading factions..."); try { - LoadFactions(&database); + LoadFactions(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_loot) { Log.Out(Logs::General, Logs::Status, "Loading loot..."); try { - LoadLoot(&database); + LoadLoot(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_skill_caps) { Log.Out(Logs::General, Logs::Status, "Loading skill caps..."); try { - LoadSkillCaps(&database); + LoadSkillCaps(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_spells) { Log.Out(Logs::General, Logs::Status, "Loading spells..."); try { - LoadSpells(&database); + LoadSpells(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_bd) { Log.Out(Logs::General, Logs::Status, "Loading base data..."); try { - LoadBaseData(&database); + LoadBaseData(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + Log.CloseFileLogs(); - return 0; } diff --git a/shared_memory/npc_faction.cpp b/shared_memory/npc_faction.cpp index ebaeb3457..9ac8510bd 100644 --- a/shared_memory/npc_faction.cpp +++ b/shared_memory/npc_faction.cpp @@ -24,7 +24,7 @@ #include "../common/eqemu_exception.h" #include "../common/faction.h" -void LoadFactions(SharedDatabase *database) { +void LoadFactions(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("faction"); mutex.Lock(); @@ -33,7 +33,9 @@ void LoadFactions(SharedDatabase *database) { database->GetFactionListInfo(lists, max_list); uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(lists, max_list)); - EQEmu::MemoryMappedFile mmf("shared/faction", size); + + std::string file_name = std::string("shared/") + prefix + std::string("faction"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); diff --git a/shared_memory/npc_faction.h b/shared_memory/npc_faction.h index 52038dd9b..8fe5dbadb 100644 --- a/shared_memory/npc_faction.h +++ b/shared_memory/npc_faction.h @@ -19,7 +19,9 @@ #ifndef __EQEMU_SHARED_MEMORY_NPC_FACTION_H #define __EQEMU_SHARED_MEMORY_NPC_FACTION_H +#include + class SharedDatabase; -void LoadFactions(SharedDatabase *database); +void LoadFactions(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/skill_caps.cpp b/shared_memory/skill_caps.cpp index 94205ce72..153d06e13 100644 --- a/shared_memory/skill_caps.cpp +++ b/shared_memory/skill_caps.cpp @@ -25,7 +25,7 @@ #include "../common/classes.h" #include "../common/features.h" -void LoadSkillCaps(SharedDatabase *database) { +void LoadSkillCaps(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("skill_caps"); mutex.Lock(); @@ -33,7 +33,9 @@ void LoadSkillCaps(SharedDatabase *database) { uint32 skill_count = HIGHEST_SKILL + 1; uint32 level_count = HARD_LEVEL_CAP + 1; uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); - EQEmu::MemoryMappedFile mmf("shared/skill_caps", size); + + std::string file_name = std::string("shared/") + prefix + std::string("skill_caps"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); diff --git a/shared_memory/skill_caps.h b/shared_memory/skill_caps.h index e01dab4f4..90ae5733c 100644 --- a/shared_memory/skill_caps.h +++ b/shared_memory/skill_caps.h @@ -19,8 +19,10 @@ #ifndef __EQEMU_SHARED_MEMORY_SKILL_CAPS_H #define __EQEMU_SHARED_MEMORY_SKILL_CAPS_H +#include + class SharedDatabase; -void LoadSkillCaps(SharedDatabase *database); +void LoadSkillCaps(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/spells.cpp b/shared_memory/spells.cpp index 444f3b466..34cce35bc 100644 --- a/shared_memory/spells.cpp +++ b/shared_memory/spells.cpp @@ -24,7 +24,7 @@ #include "../common/eqemu_exception.h" #include "../common/spdat.h" -void LoadSpells(SharedDatabase *database) { +void LoadSpells(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("spells"); mutex.Lock(); int records = database->GetMaxSpellID() + 1; @@ -32,8 +32,10 @@ void LoadSpells(SharedDatabase *database) { EQ_EXCEPT("Shared Memory", "Unable to get any spells from the database."); } - uint32 size = records * sizeof(SPDat_Spell_Struct); - EQEmu::MemoryMappedFile mmf("shared/spells", size); + uint32 size = records * sizeof(SPDat_Spell_Struct) + sizeof(uint32); + + std::string file_name = std::string("shared/") + prefix + std::string("spells"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); diff --git a/shared_memory/spells.h b/shared_memory/spells.h index 590ee0536..bde0f8233 100644 --- a/shared_memory/spells.h +++ b/shared_memory/spells.h @@ -19,7 +19,9 @@ #ifndef __EQEMU_SHARED_MEMORY_SPELLS_H #define __EQEMU_SHARED_MEMORY_SPELLS_H +#include + class SharedDatabase; -void LoadSpells(SharedDatabase *database); +void LoadSpells(SharedDatabase *database, const std::string &prefix); #endif diff --git a/world/net.cpp b/world/net.cpp index 434491a0a..135012f3c 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -294,6 +294,12 @@ 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)) { + Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: %s", hotfix_name); + } + Log.Out(Logs::General, Logs::World_Server, "Loading zones.."); database.LoadZoneNames(); Log.Out(Logs::General, Logs::World_Server, "Clearing groups.."); @@ -303,10 +309,10 @@ int main(int argc, char** argv) { database.ClearRaidDetails(); database.ClearRaidLeader(); Log.Out(Logs::General, Logs::World_Server, "Loading items.."); - if (!database.LoadItems()) + if(!database.LoadItems(hotfix_name)) Log.Out(Logs::General, Logs::World_Server, "Error: Could not load item data. But ignoring"); Log.Out(Logs::General, Logs::World_Server, "Loading skill caps.."); - if (!database.LoadSkillCaps()) + if(!database.LoadSkillCaps(std::string(hotfix_name))) Log.Out(Logs::General, Logs::World_Server, "Error: Could not load skill cap data. But ignoring"); Log.Out(Logs::General, Logs::World_Server, "Loading guilds.."); guild_mgr.LoadGuilds(); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 17cac7f62..943f99bfb 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1286,10 +1286,6 @@ bool ZoneServer::Process() { case ServerOP_CZSignalNPC: case ServerOP_CZSetEntityVariableByNPCTypeID: case ServerOP_CZSignalClient: - { - zoneserver_list.SendPacket(pack); - break; - } case ServerOP_DepopAllPlayersCorpses: case ServerOP_DepopPlayerCorpse: case ServerOP_ReloadTitles: @@ -1301,6 +1297,23 @@ bool ZoneServer::Process() { zoneserver_list.SendPacket(pack); break; } + case ServerOP_ChangeSharedMem: { + std::string hotfix_name = std::string((char*)pack->pBuffer); + + Log.Out(Logs::General, Logs::World_Server, "Loading items..."); + if(!database.LoadItems(hotfix_name)) { + Log.Out(Logs::General, Logs::World_Server, "Error: Could not load item data. But ignoring"); + } + + Log.Out(Logs::General, Logs::World_Server, "Loading skill caps..."); + if(!database.LoadSkillCaps(hotfix_name)) { + Log.Out(Logs::General, Logs::World_Server, "Error: Could not load skill cap data. But ignoring"); + } + + zoneserver_list.SendPacket(pack); + break; + } + case ServerOP_RequestTellQueue: { ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer; diff --git a/zone/command.cpp b/zone/command.cpp index a286f92bd..6e1ca52e3 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -361,6 +361,7 @@ int command_init(void) { command_add("setlsinfo", "[email] [password] - Set login server email address and password (if supported by login server)", 10, command_setlsinfo) || command_add("setpass", "[accountname] [password] - Set local password for accountname", 150, command_setpass) || command_add("setpvppoints", "[value] - Set your or your player target's PVP points", 100, command_setpvppoints) || + command_add("setsharedmem", "[hotfix_name] - Set your shared memory mapping to a specific hotfix", 250, command_set_shared_memory) || command_add("setskill", "[skillnum] [value] - Set your target's skill skillnum to value", 50, command_setskill) || command_add("setskillall", "[value] - Set all of your target's skills to value", 50, command_setskillall) || command_add("setstartzone", "[zoneid] - Set target's starting zone. Set to zero to allow the player to use /setstartcity", 80, command_setstartzone) || @@ -10655,3 +10656,16 @@ void command_mysqltest(Client *c, const Seperator *sep) } Log.Out(Logs::General, Logs::Debug, "MySQL Test... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); } + +void command_set_shared_memory(Client *c, const Seperator *sep) { + std::string hotfix_name = sep->arg[1]; + c->Message(0, "Setting shared memory hotfix mapping to '%s'", hotfix_name.c_str()); + + database.SetVariable("hotfix_name", hotfix_name.c_str()); + + ServerPacket pack(ServerOP_ChangeSharedMem, hotfix_name.length() + 1); + if(hotfix_name.length() > 0) { + strcpy((char*)pack.pBuffer, hotfix_name.c_str()); + } + worldserver.SendPacket(&pack); +} diff --git a/zone/command.h b/zone/command.h index 0560b8eff..6b9bb5fc9 100644 --- a/zone/command.h +++ b/zone/command.h @@ -325,7 +325,8 @@ void command_tune(Client *c, const Seperator *sep); void command_logtest(Client *c, const Seperator *sep); void command_mysqltest(Client *c, const Seperator *sep); void command_logs(Client *c, const Seperator *sep); - +void command_set_shared_memory(Client *c, const Seperator *sep); + #ifdef EQPROFILE void command_profiledump(Client *c, const Seperator *sep); void command_profilereset(Client *c, const Seperator *sep); diff --git a/zone/net.cpp b/zone/net.cpp index ef6b46836..658f0d308 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -107,7 +107,6 @@ QuestParserCollection *parse = 0; EQEmuLogSys Log; const SPDat_Spell_Struct* spells; -void LoadSpells(EQEmu::MemoryMappedFile **mmf); int32 SPDAT_RECORDS = -1; void Shutdown(); @@ -205,37 +204,44 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::Zone_Server, "Loading Variables"); database.LoadVariables(); + char hotfix_name[256] = { 0 }; + if(database.GetVariable("hotfix_name", hotfix_name, 256)) { + Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: %s", hotfix_name); + } + Log.Out(Logs::General, Logs::Zone_Server, "Loading zone names"); database.LoadZoneNames(); Log.Out(Logs::General, Logs::Zone_Server, "Loading items"); - if (!database.LoadItems()) { + if(!database.LoadItems(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading items FAILED!"); Log.Out(Logs::General, Logs::Error, "Failed. But ignoring error and going on..."); } Log.Out(Logs::General, Logs::Zone_Server, "Loading npc faction lists"); - if (!database.LoadNPCFactionLists()) { + if(!database.LoadNPCFactionLists(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading npcs faction lists FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading loot tables"); - if (!database.LoadLoot()) { + if(!database.LoadLoot(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading loot FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading skill caps"); - if (!database.LoadSkillCaps()) { + if(!database.LoadSkillCaps(std::string(hotfix_name))) { Log.Out(Logs::General, Logs::Error, "Loading skill caps FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading spells"); - EQEmu::MemoryMappedFile *mmf = nullptr; - LoadSpells(&mmf); + if(!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) { + Log.Out(Logs::General, Logs::Error, "Loading spells FAILED!"); + return 1; + } Log.Out(Logs::General, Logs::Zone_Server, "Loading base data"); - if (!database.LoadBaseData()) { + if(!database.LoadBaseData(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading base data FAILED!"); return 1; } @@ -468,7 +474,6 @@ int main(int argc, char** argv) { safe_delete(lua_parser); #endif - safe_delete(mmf); safe_delete(Config); if (zone != 0) @@ -571,28 +576,6 @@ NetConnection::~NetConnection() { 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) { - Log.Out(Logs::General, Logs::Error, "Error loading spells: %s", ex.what()); - return; - } - - SPDAT_RECORDS = records; -} - /* Update Window Title with relevant information */ void UpdateWindowTitle(char* iNewTitle) { #ifdef _WINDOWS diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 517106aca..a1820366a 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1841,6 +1841,41 @@ void WorldServer::Process() { } break; } + + case ServerOP_ChangeSharedMem: + { + std::string hotfix_name = std::string((char*)pack->pBuffer); + Log.Out(Logs::General, Logs::Zone_Server, "Loading items"); + if(!database.LoadItems(hotfix_name)) { + Log.Out(Logs::General, Logs::Error, "Loading items FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading npc faction lists"); + if(!database.LoadNPCFactionLists(hotfix_name)) { + Log.Out(Logs::General, Logs::Error, "Loading npcs faction lists FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading loot tables"); + if(!database.LoadLoot(hotfix_name)) { + Log.Out(Logs::General, Logs::Error, "Loading loot FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading skill caps"); + if(!database.LoadSkillCaps(std::string(hotfix_name))) { + Log.Out(Logs::General, Logs::Error, "Loading skill caps FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading spells"); + if(!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) { + Log.Out(Logs::General, Logs::Error, "Loading spells FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading base data"); + if(!database.LoadBaseData(hotfix_name)) { + Log.Out(Logs::General, Logs::Error, "Loading base data FAILED!"); + } + break; + } default: { std::cout << " Unknown ZSopcode:" << (int)pack->opcode; std::cout << " size:" << pack->size << std::endl; From 3dd89b0daae9887a5846d6c97c7f6577636ca2bf Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 23 Jun 2015 22:04:48 -0700 Subject: [PATCH 210/846] Polishing shared memory hotfix code --- world/net.cpp | 4 +++- zone/command.cpp | 53 +++++++++++++++++++++++++++++++++++++++--------- zone/command.h | 2 +- zone/net.cpp | 4 +++- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/world/net.cpp b/world/net.cpp index 135012f3c..3032e4c97 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -297,7 +297,9 @@ int main(int argc, char** argv) { char hotfix_name[256] = { 0 }; if(database.GetVariable("hotfix_name", hotfix_name, 256)) { - Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: %s", hotfix_name); + if(strlen(hotfix_name) > 0) { + Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name); + } } Log.Out(Logs::General, Logs::World_Server, "Loading zones.."); diff --git a/zone/command.cpp b/zone/command.cpp index 6e1ca52e3..82aae6e25 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef _WINDOWS #define strcasecmp _stricmp @@ -249,6 +250,7 @@ int command_init(void) { command_add("heromodel", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.", 200, command_heromodel) || command_add("hideme", "[on/off] - Hide yourself from spawn lists.", 80, command_hideme) || command_add("hm", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.)", 200, command_heromodel) || + command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix", 250, command_hotfix) || command_add("hp", "- Refresh your HP bar from the server.", 0, command_hp) || command_add("incstat", "- Increases or Decreases a client's stats permanently.", 200, command_incstat) || command_add("instance", "- Modify Instances", 200, command_instance) || @@ -361,7 +363,6 @@ int command_init(void) { command_add("setlsinfo", "[email] [password] - Set login server email address and password (if supported by login server)", 10, command_setlsinfo) || command_add("setpass", "[accountname] [password] - Set local password for accountname", 150, command_setpass) || command_add("setpvppoints", "[value] - Set your or your player target's PVP points", 100, command_setpvppoints) || - command_add("setsharedmem", "[hotfix_name] - Set your shared memory mapping to a specific hotfix", 250, command_set_shared_memory) || command_add("setskill", "[skillnum] [value] - Set your target's skill skillnum to value", 50, command_setskill) || command_add("setskillall", "[value] - Set all of your target's skills to value", 50, command_setskillall) || command_add("setstartzone", "[zoneid] - Set target's starting zone. Set to zero to allow the player to use /setstartcity", 80, command_setstartzone) || @@ -10657,15 +10658,47 @@ void command_mysqltest(Client *c, const Seperator *sep) Log.Out(Logs::General, Logs::Debug, "MySQL Test... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); } -void command_set_shared_memory(Client *c, const Seperator *sep) { - std::string hotfix_name = sep->arg[1]; - c->Message(0, "Setting shared memory hotfix mapping to '%s'", hotfix_name.c_str()); +void command_hotfix(Client *c, const Seperator *sep) { + char hotfix[256] = { 0 }; + database.GetVariable("hotfix_name", hotfix, 256); + std::string current_hotfix = hotfix; - database.SetVariable("hotfix_name", hotfix_name.c_str()); - - ServerPacket pack(ServerOP_ChangeSharedMem, hotfix_name.length() + 1); - if(hotfix_name.length() > 0) { - strcpy((char*)pack.pBuffer, hotfix_name.c_str()); + std::string hotfix_name; + if(!strcasecmp(current_hotfix.c_str(), "hotfix_")) { + hotfix_name = ""; + } else { + hotfix_name = "hotfix_"; } - worldserver.SendPacket(&pack); + + + c->Message(0, "Creating and applying hotfix"); + //Not 100% certain on the thread safety of this. + //I think it's okay however + std::thread t1([c,hotfix_name]() { +#ifdef WIN32 + if(hotfix_name.length() > 0) { + system(StringFormat("shared_memory -hotfix=%s", hotfix_name.c_str()).c_str()); + } else { + system(StringFormat("shared_memory").c_str()); + } +#else + if(hotfix_name.length() > 0) { + system(StringFormat("./shared_memory -hotfix=%s", hotfix_name.c_str()).c_str()); + } + else { + system(StringFormat("./shared_memory").c_str()); + } +#endif + database.SetVariable("hotfix_name", hotfix_name.c_str()); + + ServerPacket pack(ServerOP_ChangeSharedMem, hotfix_name.length() + 1); + if(hotfix_name.length() > 0) { + strcpy((char*)pack.pBuffer, hotfix_name.c_str()); + } + worldserver.SendPacket(&pack); + + c->Message(0, "Hotfix applied"); + }); + + t1.detach(); } diff --git a/zone/command.h b/zone/command.h index 6b9bb5fc9..7c33ef49a 100644 --- a/zone/command.h +++ b/zone/command.h @@ -325,7 +325,7 @@ void command_tune(Client *c, const Seperator *sep); void command_logtest(Client *c, const Seperator *sep); void command_mysqltest(Client *c, const Seperator *sep); void command_logs(Client *c, const Seperator *sep); -void command_set_shared_memory(Client *c, const Seperator *sep); +void command_hotfix(Client *c, const Seperator *sep); #ifdef EQPROFILE void command_profiledump(Client *c, const Seperator *sep); diff --git a/zone/net.cpp b/zone/net.cpp index 658f0d308..4a95e487f 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -206,7 +206,9 @@ int main(int argc, char** argv) { char hotfix_name[256] = { 0 }; if(database.GetVariable("hotfix_name", hotfix_name, 256)) { - Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: %s", hotfix_name); + if(strlen(hotfix_name) > 0) { + Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name); + } } Log.Out(Logs::General, Logs::Zone_Server, "Loading zone names"); From 31301e0a2603fa665a6659d8bbbf3e0b77a48273 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 24 Jun 2015 01:25:49 -0700 Subject: [PATCH 211/846] ResetAA should hopefully play better with granted AA points now --- zone/aa.cpp | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index c97ff7af4..07adc2805 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -441,15 +441,26 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) } void Client::ResetAA() { + SendClearAA(); RefundAA(); - uint32 i; - for (i=0; i < MAX_PP_AA_ARRAY; i++) { - m_pp.aa_array[i].AA = 0; - m_pp.aa_array[i].value = 0; - m_pp.aa_array[i].charges= 0; - } - aa_ranks.clear(); + memset(&m_pp.aa_array[0], 0, sizeof(AA_Array) * MAX_PP_AA_ARRAY); + + int i = 0; + for(auto &rank_value : aa_ranks) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value.first, rank_value.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if(!rank) { + continue; + } + + m_pp.aa_array[i].AA = rank_value.first; + m_pp.aa_array[i].value = rank_value.second.first; + m_pp.aa_array[i].charges = rank_value.second.second; + ++i; + } for(int i = 0; i < _maxLeaderAA; ++i) m_pp.leader_abilities.ranks[i] = 0; @@ -459,13 +470,7 @@ void Client::ResetAA() { m_pp.group_leadership_exp = 0; m_pp.raid_leadership_exp = 0; - database.DeleteCharacterAAs(CharacterID()); - SaveAA(); - SendClearAA(); - SendAlternateAdvancementTable(); - SendAlternateAdvancementPoints(); - SendAlternateAdvancementStats(); - database.DeleteCharacterLeadershipAAs(this->CharacterID()); + database.DeleteCharacterLeadershipAAs(CharacterID()); // undefined for these clients if (GetClientVersionBit() & BIT_TitaniumAndEarlier) Kick(); @@ -749,24 +754,29 @@ void Client::InspectBuffs(Client* Inspector, int Rank) void Client::RefundAA() { int refunded = 0; - for(auto &rank_value : aa_ranks) { - auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value.first, rank_value.second.first); + auto rank_value = aa_ranks.begin(); + while(rank_value != aa_ranks.end()) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value->first, rank_value->second.first); auto ability = ability_rank.first; auto rank = ability_rank.second; if(!ability) { + ++rank_value; continue; } - if(ability->charges > 0 && rank_value.second.second < 1) { + if(ability->charges > 0 && rank_value->second.second < 1) { + ++rank_value; continue; } if(ability->grant_only) { + ++rank_value; continue; } refunded += rank->total_cost; + rank_value = aa_ranks.erase(rank_value); } if(refunded > 0) { @@ -774,6 +784,10 @@ void Client::RefundAA() { SaveAA(); Save(); } + + SendAlternateAdvancementTable(); + SendAlternateAdvancementPoints(); + SendAlternateAdvancementStats(); } AA_SwarmPetInfo::AA_SwarmPetInfo() From 476ee10ca02b6d4bfee8a4126f87e393d9e7c260 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 24 Jun 2015 20:02:11 -0700 Subject: [PATCH 212/846] Fix for Berserkers not seeing AAs on SoD and below clients. --- common/patches/sod_structs.h | 3 +-- common/patches/sof_structs.h | 3 +-- common/patches/titanium_structs.h | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 6e1a77b6b..816bff323 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -3813,8 +3813,7 @@ struct SendAA_Struct { /*0049*/ uint32 spellid; /*0053*/ uint32 spell_type; /*0057*/ uint32 spell_refresh; -/*0061*/ uint16 classes; -/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability +/*0061*/ uint32 classes; /*0065*/ uint32 max_level; /*0069*/ uint32 last_id; /*0073*/ uint32 next_id; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index faa306ab0..49ad7ba3e 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3677,8 +3677,7 @@ struct SendAA_Struct { /*0049*/ uint32 spellid; /*0053*/ uint32 spell_type; /*0057*/ uint32 spell_refresh; -/*0061*/ uint16 classes; -/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability +/*0061*/ uint32 classes; /*0065*/ uint32 max_level; /*0069*/ uint32 last_id; /*0073*/ uint32 next_id; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index e5fa44a8e..36cf2df3d 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3157,8 +3157,7 @@ struct SendAA_Struct { /*0052*/ uint32 spellid; /*0056*/ uint32 spell_type; /*0060*/ uint32 spell_refresh; -/*0064*/ uint16 classes; -/*0066*/ uint16 berserker; //seems to be 1 if its a berserker ability +/*0064*/ uint32 classes; /*0068*/ uint32 max_level; /*0072*/ uint32 last_id; /*0076*/ uint32 next_id; From c3a805923ca940faa713ab59b59d148edb595f63 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 25 Jun 2015 13:21:02 -0400 Subject: [PATCH 213/846] Up the bard level check to 255 again 1-254 actually has special bard logic and client expects it --- common/spdat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 7dd21479c..bb6097566 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -447,7 +447,7 @@ bool IsTGBCompatibleSpell(uint16 spell_id) bool IsBardSong(uint16 spell_id) { - if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 127 && !spells[spell_id].IsDisciplineBuff) + if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255 && !spells[spell_id].IsDisciplineBuff) return true; return false; From 4b64e8c39c4abdbe75e5520085fb5768e37d9338 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 26 Jun 2015 02:04:33 -0400 Subject: [PATCH 214/846] Ignore skills out of range for bonuses --- zone/bonuses.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 7ff8e7fc7..1e719dceb 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -691,6 +691,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) switch (effect) { // 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) + break; if ((base2 == ALL_SKILLS) && (newbon->Accuracy[HIGHEST_SKILL + 1] < base1)) newbon->Accuracy[HIGHEST_SKILL + 1] = base1; else if (newbon->Accuracy[base2] < base1) @@ -1031,6 +1034,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_HitChance: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (base2 == ALL_SKILLS) newbon->HitChanceEffect[HIGHEST_SKILL + 1] += base1; else @@ -1082,6 +1088,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_CriticalHitChance: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (base2 == ALL_SKILLS) newbon->CriticalHitChance[HIGHEST_SKILL + 1] += base1; else @@ -1089,6 +1098,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } break; case SE_CriticalDamageMob: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; // base1 = effect value, base2 = skill restrictions(-1 for all) if (base2 == ALL_SKILLS) newbon->CritDmgMob[HIGHEST_SKILL + 1] += base1; @@ -1116,6 +1128,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } case SE_SkillDamageAmount: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (base2 == ALL_SKILLS) newbon->SkillDamageAmount[HIGHEST_SKILL + 1] += base1; else @@ -1132,6 +1147,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } case SE_DamageModifier: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (base2 == ALL_SKILLS) newbon->DamageModifier[HIGHEST_SKILL + 1] += base1; else @@ -1140,6 +1158,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } case SE_DamageModifier2: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (base2 == ALL_SKILLS) newbon->DamageModifier2[HIGHEST_SKILL + 1] += base1; else @@ -1347,6 +1368,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_LimitToSkill: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (base1 <= HIGHEST_SKILL) newbon->LimitToSkill[base1] = true; break; @@ -1899,6 +1923,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_CriticalHitChance: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (AdditiveWornBonus) { if(base2 == ALL_SKILLS) new_bonus->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; @@ -2102,6 +2129,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_HitChance: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (AdditiveWornBonus){ if(base2 == ALL_SKILLS) @@ -2136,6 +2166,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_DamageModifier: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if(base2 == ALL_SKILLS) new_bonus->DamageModifier[HIGHEST_SKILL+1] += effect_value; else @@ -2145,6 +2178,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_DamageModifier2: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if(base2 == ALL_SKILLS) new_bonus->DamageModifier2[HIGHEST_SKILL+1] += effect_value; else @@ -2154,6 +2190,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_MinDamageModifier: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if(base2 == ALL_SKILLS) new_bonus->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; else @@ -2227,6 +2266,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_Accuracy: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if ((effect_value < 0) && (new_bonus->Accuracy[HIGHEST_SKILL+1] > effect_value)) new_bonus->Accuracy[HIGHEST_SKILL+1] = effect_value; @@ -2250,6 +2292,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_SkillDamageTaken: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; //When using npc_spells_effects if MAX value set, use stackable quest based modifier. if (IsAISpellEffect && max){ if(base2 == ALL_SKILLS) @@ -2368,6 +2413,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_CriticalDamageMob: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if(base2 == ALL_SKILLS) new_bonus->CritDmgMob[HIGHEST_SKILL+1] += effect_value; else @@ -2384,6 +2432,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_SkillDamageAmount: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if(base2 == ALL_SKILLS) new_bonus->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value; else @@ -2489,6 +2540,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_SkillDamageAmount2: { + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if(base2 == ALL_SKILLS) new_bonus->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value; else @@ -3023,6 +3077,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; case SE_LimitToSkill:{ + // Bad data or unsupported new skill + if (base2 > HIGHEST_SKILL) + break; if (effect_value <= HIGHEST_SKILL){ new_bonus->LimitToSkill[effect_value] = true; } From cee7e401dd87c50cac3272c6f722a3aa10c7217c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 26 Jun 2015 02:19:13 -0400 Subject: [PATCH 215/846] Fix issue with initial cast of level override proc buffs --- zone/spell_effects.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9134e8ff7..4c1f1fa45 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1770,9 +1770,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #endif if(spells[spell_id].base2[i] == 0) - AddProcToWeapon(procid, false, 100, spell_id, level_override); + AddProcToWeapon(procid, false, 100, spell_id, caster_level); else - AddProcToWeapon(procid, false, spells[spell_id].base2[i]+100, spell_id, level_override); + AddProcToWeapon(procid, false, spells[spell_id].base2[i]+100, spell_id, caster_level); break; } From 337ce2d74b6b911213e963679f838e3ba92845c0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 26 Jun 2015 18:00:15 -0400 Subject: [PATCH 216/846] Fix crash for Bard Furious Refrain This does a frenzy, which bards don't have. Live this AA is broken. --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 202ad77b6..f6690c58f 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4459,7 +4459,7 @@ void Mob::DoRiposte(Mob *defender) if (defender->GetClass() == MONK) defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]); - else if (defender->IsClient()) + else if (defender->IsClient() && defender->CastToClient()->HasSkill((SkillUseTypes)defender->aabonuses.GiveDoubleRiposte[2])) defender->CastToClient()->DoClassAttacks(this, defender->aabonuses.GiveDoubleRiposte[2], true); } } From 5a6685d12951acde8d6bc4a607fdf60992e6f580 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 27 Jun 2015 18:39:13 -0400 Subject: [PATCH 217/846] Fix issue with AA cast mana consumption AAs will now cast from slot "0xFF" instead of the itemslot to avoid special behavior of items. Mana reduction also moved down to the same place consumption takes place like live. --- zone/aa.cpp | 6 +++--- zone/common.h | 1 + zone/spells.cpp | 27 +++++++++++++++------------ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 07adc2805..db765e813 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1183,12 +1183,12 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { // 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), 10, -1, -1, spells[rank->spell].ResistDiff, false)) { + if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), ALTERNATE_ABILITY_SPELL_SLOT, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { return; } ExpendAlternateAdvancementCharge(ability->id); } else { - if(!CastSpell(rank->spell, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) { + if(!CastSpell(rank->spell, target_id, ALTERNATE_ABILITY_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) { return; } } @@ -1554,7 +1554,7 @@ void Zone::LoadAlternateAdvancement() { // then set it here too //if prev has an aa we have // then set to whichever is highest - + auto iter = current->prereqs.find(prev_prereq.first); if(iter == current->prereqs.end()) { //not found diff --git a/zone/common.h b/zone/common.h index e9521cb94..0b875456b 100644 --- a/zone/common.h +++ b/zone/common.h @@ -22,6 +22,7 @@ #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 diff --git a/zone/spells.cpp b/zone/spells.cpp index 30e3b02d9..0a4dc29b3 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -409,24 +409,19 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, // ok now we know the target casting_spell_targetid = target_id; - if (mana_cost == -1) { + // We don't get actual mana cost here, that's done when we consume the mana + if (mana_cost == -1) mana_cost = spell.mana; - mana_cost = GetActSpellCost(spell_id, mana_cost); - } - - if(HasMGB() && spells[spell_id].can_mgb) - mana_cost *= 2; // mana is checked for clients on the frontend. we need to recheck it for NPCs though - // fix: items dont need mana :-/ // 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 != 10) + if(mana_cost > 0 && slot != USE_ITEM_SPELL_SLOT) { int my_curmana = GetMana(); int my_maxmana = GetMaxMana(); - if(my_curmana < spell.mana) // not enough mana + if(my_curmana < mana_cost) // not enough mana { //this is a special case for NPCs with no mana... if(IsNPC() && my_curmana == my_maxmana) @@ -2157,11 +2152,11 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } #endif //BOTS + // We hold off turning MBG off so we can still use it to calc the mana cost if(spells[spell_id].can_mgb && HasMGB()) { SpellOnTarget(spell_id, this); entity_list.MassGroupBuff(this, this, spell_id, true); - SetMGB(false); } else { @@ -2262,13 +2257,21 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } // if this was a spell slot or an ability use up the mana for it - // CastSpell already reduced the cost for it if we're a client with focus if(slot != USE_ITEM_SPELL_SLOT && slot != POTION_BELT_SPELL_SLOT && slot != TARGET_RING_SPELL_SLOT && mana_used > 0) { + mana_used = GetActSpellCost(spell_id, mana_used); + if (HasMGB() && spells[spell_id].can_mgb) { + mana_used *= 2; + SetMGB(false); + } + // clamp if we some how got focused above our current mana + if (GetMana() < mana_used) + mana_used = GetMana(); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: consuming %d mana", spell_id, mana_used); - if (!DoHPToManaCovert(mana_used)) + if (!DoHPToManaCovert(mana_used)) { SetMana(GetMana() - mana_used); TryTriggerOnValueAmount(false, true); + } } //set our reuse timer on long ass reuse_time spells... From 009918cbd10fdfe3e4ce9a7ea587e44b83e31d90 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 27 Jun 2015 22:43:00 -0400 Subject: [PATCH 218/846] Fix songcap implementation --- zone/client_mods.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 76ce5195c..13a8130bd 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1979,10 +1979,17 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const uint32 effectmod = 10; int effectmodcap = 0; - if (RuleB(Character, UseSpellFileSongCap)) + bool nocap = false; + if (RuleB(Character, UseSpellFileSongCap)) { effectmodcap = spells[spell_id].songcap / 10; - else + // this looks a bit weird, but easiest way I could think to keep both systems working + if (effectmodcap == 0) + nocap = true; + else + effectmodcap += 10; + } else { effectmodcap = RuleI(Character, BaseInstrumentSoftCap); + } // this should never use spell modifiers... // if a spell grants better modifers, they are copied into the item mods // because the spells are supposed to act just like having the intrument. @@ -2056,7 +2063,7 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; if (effectmod < 10) effectmod = 10; - if (effectmodcap && effectmod > effectmodcap) // if the cap is calculated to be 0 using new rules, no cap. + if (!nocap && effectmod > effectmodcap) // if the cap is calculated to be 0 using new rules, no cap. effectmod = effectmodcap; Log.Out(Logs::Detail, Logs::Spells, "%s::GetInstrumentMod() spell=%d mod=%d modcap=%d\n", GetName(), spell_id, effectmod, effectmodcap); From b11fea91a6dfb021bc6f7d30883d30c2ed7d2a8b Mon Sep 17 00:00:00 2001 From: ngdeao Date: Sun, 28 Jun 2015 00:35:55 -0600 Subject: [PATCH 219/846] Fixed some mob speed scaling. --- zone/waypoints.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 7570165a3..b0c74a9e8 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -621,9 +621,9 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo if (numsteps>1) { tar_vector=1.0f ; - m_TargetV.x = 1.25f * m_TargetV.x/(float)numsteps; - m_TargetV.y = 1.25f * m_TargetV.y/(float)numsteps; - m_TargetV.z = 1.25f *m_TargetV.z/(float)numsteps; + m_TargetV.x = m_TargetV.x/(float)numsteps; + m_TargetV.y = m_TargetV.y/(float)numsteps; + m_TargetV.z = m_TargetV.z/(float)numsteps; float new_x = m_Position.x + m_TargetV.x; float new_y = m_Position.y + m_TargetV.y; @@ -636,7 +636,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_Position.y = new_y; m_Position.z = new_z; m_Position.w = CalculateHeadingToTarget(x, y); - tar_ndx = 22 - numsteps; + tar_ndx = 20 - numsteps; Log.Out(Logs::Detail, Logs::AI, "Next position2 (%.3f, %.3f, %.3f) (%d steps)", m_Position.x, m_Position.y, m_Position.z, numsteps); } else From 74aec82d2a7a3a8eb8f01bf4f5983283f4fb063d Mon Sep 17 00:00:00 2001 From: ngdeao Date: Sun, 28 Jun 2015 00:58:03 -0600 Subject: [PATCH 220/846] Optional SQL for adjusting mob speeds. The base runspeeds for mobs were about 80% high. This scales them to values appropriate for new speed calculations. The RescaleRunspeeds regroups speeds into common seen speed bins. Higher speeds it lowers them by 20%. This should only be run once against a db. The Set specific speeds is tailored to specific mob run speeds, based on data taken from eqlive. --- ...015_06_28_RescaleRunspeeds_RunOnceOnly.sql | 7 +++ ...MobSpecificRunSpeeds_AfterAnyRescaling.sql | 61 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 utils/sql/git/optional/2015_06_28_RescaleRunspeeds_RunOnceOnly.sql create mode 100644 utils/sql/git/optional/2015_06_28_SetMobSpecificRunSpeeds_AfterAnyRescaling.sql diff --git a/utils/sql/git/optional/2015_06_28_RescaleRunspeeds_RunOnceOnly.sql b/utils/sql/git/optional/2015_06_28_RescaleRunspeeds_RunOnceOnly.sql new file mode 100644 index 000000000..2810d3291 --- /dev/null +++ b/utils/sql/git/optional/2015_06_28_RescaleRunspeeds_RunOnceOnly.sql @@ -0,0 +1,7 @@ +/* This rescales the old peq runspeeds which were about 80 percent too high to new values */ +/* This section should only ever be run once */ +UPDATE npc_types SET npc_types.runspeed = 1.050 WHERE (npc_types.runspeed > 0 and npc_types.runspeed < 1.2); +UPDATE npc_types SET npc_types.runspeed = 1.325 WHERE (npc_types.runspeed > 1.19 and npc_types.runspeed < 1.75 and race != 73 and race != 72); +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE (npc_types.runspeed > 1.69 and npc_types.runspeed < 2.2); +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE (npc_types.runspeed > 2.19 and npc_types.runspeed < 3); +UPDATE npc_types SET npc_types.runspeed = (npc_types.runspeed * 0.8) WHERE (npc_types.runspeed > 2.99 and npc_types.runspeed < 20); \ No newline at end of file diff --git a/utils/sql/git/optional/2015_06_28_SetMobSpecificRunSpeeds_AfterAnyRescaling.sql b/utils/sql/git/optional/2015_06_28_SetMobSpecificRunSpeeds_AfterAnyRescaling.sql new file mode 100644 index 000000000..064c39ce4 --- /dev/null +++ b/utils/sql/git/optional/2015_06_28_SetMobSpecificRunSpeeds_AfterAnyRescaling.sql @@ -0,0 +1,61 @@ +/* some specific by name */ +UPDATE npc_types SET npc_types.runspeed = 3.175 WHERE npc_types.name = 'a_shadowed_man'; +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE npc_types.name = 'aviak_egret'; +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE npc_types.name = 'froglok_hunter'; +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE npc_types.name = 'froglok_forager'; +/* rhinos */ +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE npc_types.race = 135; +/* centaurs */ +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE npc_types.race = 16; +/* griffins */ +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE npc_types.race = 47; +/* wolves - use size, to not change cubs*/ +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE (npc_types.race = 42 and npc_types.size > 5); +/* sarnaks */ +UPDATE npc_types SET npc_types.runspeed = 1.325 WHERE npc_types.race = 131; +/* sabertooth tigers - use size, to not change cubs*/ +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE (npc_types.race = 119 and npc_types.size > 6); +/* lions */ +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE (npc_types.race = 50 and npc_types.size > 7); +/* panthers/pumas */ +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE npc_types.race = 76; +/* beetles */ +UPDATE npc_types SET npc_types.runspeed = 1.05 WHERE npc_types.race = 22; +/*leeches*/ +UPDATE npc_types SET npc_types.runspeed = 1.05 WHERE npc_types.race = 104; +/*a_brontotherium*/ +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE npc_types.race = 169; +/* raptors */ +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE npc_types.race = 163; +/* vicious plants */ +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE npc_types.race = 162; +/* western wastes, drakes, cragwyrms and wyvern */ +UPDATE npc_types +JOIN spawnentry ON npc_types.id = spawnentry.npcID +JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID +SET npc_types.runspeed = 1.575 +WHERE ((npc_types.race = 89 OR npc_types.race = 157 OR npc_types.race = 158) AND spawn2.zone = 'westwastes'); +/* velium hounds/wolves */ +UPDATE npc_types +JOIN spawnentry ON npc_types.id = spawnentry.npcID +JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID +SET npc_types.runspeed = 1.850 +WHERE (npc_types.race = 42 AND spawn2.zone = 'westwastes'); +/* Overthere Specials, goons, etc. */ +UPDATE npc_types +JOIN spawnentry ON npc_types.id = spawnentry.npcID +JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID +SET npc_types.runspeed = 1.850 +WHERE ((npc_types.race = 77 or npc_types.race = 147) AND spawn2.zone = 'overthere'); +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE npc_types.name = 'Captain_Rottgrime'; +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE npc_types.name = 'an_undead_marine'; +/* Pet Speeds. */ +UPDATE npc_types +JOIN pets ON npc_types.id = pets.npcID +SET npc_types.runspeed = 1.575; +/* raptors in tim are slower than other raptors in kunark */ +UPDATE npc_types +JOIN spawnentry ON npc_types.id = spawnentry.npcID +JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID +SET npc_types.runspeed = 1.325 +WHERE ( npc_types.race = 163 AND spawn2.zone = 'timorous' ); From 850a90887425145f0d3cdc085a258267f029de21 Mon Sep 17 00:00:00 2001 From: ngdeao Date: Mon, 29 Jun 2015 22:57:37 -0600 Subject: [PATCH 221/846] Fixed #modifynpcstat runspeed , to work with new speed calculations. Updated #showstats and #npcstats for new speed calcs to display speeds again in familiar float format. Improved client movement while AI Controlled, such as feared and charmed. Movement will be much smoother from clients perspective. --- common/opcode_dispatch.h | 1 + zone/client.cpp | 1 + zone/client.h | 2 ++ zone/client_packet.cpp | 12 ++++++++++++ zone/client_process.cpp | 4 +--- zone/command.cpp | 2 +- zone/mob.cpp | 6 +++--- zone/mob.h | 2 +- zone/mob_ai.cpp | 28 ++++++++++++++++++---------- zone/npc.cpp | 10 +++++++++- zone/waypoints.cpp | 4 ++-- 11 files changed, 51 insertions(+), 21 deletions(-) diff --git a/common/opcode_dispatch.h b/common/opcode_dispatch.h index 657d9a525..a88391bce 100644 --- a/common/opcode_dispatch.h +++ b/common/opcode_dispatch.h @@ -146,6 +146,7 @@ INr(OP_GuildDelete); //? IN(OP_GuildPublicNote, GuildUpdate_PublicNote); INz(OP_GetGuildsList); //? IN(OP_SetGuildMOTD, GuildMOTD_Struct); +IN(OP_SetRunMode, SetRunMode_Struct); INz(OP_GuildPeace); //? INz(OP_GuildWar); //? IN(OP_GuildLeader, GuildMakeLeader); diff --git a/zone/client.cpp b/zone/client.cpp index e4d49e979..7c73db5cc 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -198,6 +198,7 @@ Client::Client(EQStreamInterface* ieqs) SetTarget(0); auto_attack = false; auto_fire = false; + runmode = false; linkdead_timer.Disable(); zonesummon_id = 0; zonesummon_ignorerestrictions = 0; diff --git a/zone/client.h b/zone/client.h index 4a166feed..4f31aee23 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1157,6 +1157,7 @@ public: void RemoveAutoXTargets(); void ShowXTargets(Client *c); bool GroupFollow(Client* inviter); + inline bool GetRunMode() const { return runmode; } void InitializeMercInfo(); bool CheckCanSpawnMerc(uint32 template_id); @@ -1385,6 +1386,7 @@ private: bool AFK; bool auto_attack; bool auto_fire; + bool runmode; uint8 gmspeed; bool medding; uint16 horseId; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2ae2babac..b33148d45 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -11836,6 +11836,18 @@ void Client::Handle_OP_SetGuildMOTD(const EQApplicationPacket *app) void Client::Handle_OP_SetRunMode(const EQApplicationPacket *app) { + if (app->size < sizeof(SetRunMode_Struct)) { + Log.Out(Logs::General, Logs::Error, "Received invalid sized " + "OP_SetRunMode: got %d, expected %d", app->size, + sizeof(SetRunMode_Struct)); + DumpPacket(app); + return; + } + SetRunMode_Struct* rms = (SetRunMode_Struct*)app->pBuffer; + if (rms->mode) + runmode = true; + else + runmode = false; return; } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 4a16e7698..27567f998 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -522,9 +522,7 @@ bool Client::Process() { if (position_timer.Check()) { if (IsAIControlled()) { - if(IsMoving()) - SendPosUpdate(2); - else + if(!IsMoving()) { animation = 0; m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w); diff --git a/zone/command.cpp b/zone/command.cpp index a286f92bd..2226a87f5 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1484,7 +1484,7 @@ void command_npcstats(Client *c, const Seperator *sep) 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: %i Walkspeed: %i", c->GetTarget()->GetRunspeed(), c->GetTarget()->GetWalkspeed()); + 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); diff --git a/zone/mob.cpp b/zone/mob.cpp index b107565bc..cab28ff7b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -725,7 +725,7 @@ int Mob::_GetFearSpeed() const { movemod = -85; if (IsClient()) { - if (CastToClient()->IsRunning()) + if (CastToClient()->GetRunMode()) speed_mod = GetBaseRunspeed(); else speed_mod = GetBaseWalkspeed(); @@ -1085,7 +1085,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) 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.walkspeed = walkspeed; ns->spawn.class_ = class_; ns->spawn.gender = gender; ns->spawn.level = level; @@ -1475,7 +1475,7 @@ void Mob::ShowStats(Client* client) 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: %u Walkspeed: %u", n->GetAccuracyRating(), n->MerchantType, n->GetEmoteID(), n->GetRunspeed(), n->GetWalkspeed()); + 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())); n->QueryLoot(client); } if (IsAIControlled()) { diff --git a/zone/mob.h b/zone/mob.h index ded9c04dc..9a51b5436 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -365,7 +365,7 @@ public: 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); } - virtual inline float GetIntHPRatio() const { return max_hp == 0 ? 0 : (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 virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 045c2cb75..85217905d 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -772,7 +772,10 @@ void Client::AI_Process() engaged = true; } else { if(AImovement_timer->Check()) { - //animation = GetFearSpeed() * 21; + int speed = GetFearSpeed(); + animation = speed; + speed *= 2; + SetCurrentSpeed(speed); // Check if we have reached the last fear point if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) && (std::abs(GetY() - m_FearWalkTarget.y) < 0.1)) { @@ -780,18 +783,18 @@ void Client::AI_Process() CalculateNewFearpoint(); } if(!RuleB(Pathing, Fear) || !zone->pathing) - CalculateNewPosition2(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, GetFearSpeed(), true); + CalculateNewPosition2(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, speed, true); else { bool WaypointChanged, NodeReached; glm::vec3 Goal = UpdatePath(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, - GetFearSpeed(), WaypointChanged, NodeReached); + speed, WaypointChanged, NodeReached); if(WaypointChanged) tar_ndx = 20; - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed()); + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); } } return; @@ -934,8 +937,12 @@ void Client::AI_Process() { if(AImovement_timer->Check()) { + int newspeed = GetRunspeed(); + animation = newspeed; + newspeed *= 2; + SetCurrentSpeed(newspeed); if(!RuleB(Pathing, Aggro) || !zone->pathing) - CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed()); + CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), newspeed); else { bool WaypointChanged, NodeReached; @@ -945,7 +952,7 @@ void Client::AI_Process() if(WaypointChanged) tar_ndx = 20; - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, newspeed); } } } @@ -989,11 +996,12 @@ void Client::AI_Process() { if(AImovement_timer->Check()) { - int speed = GetWalkspeed(); - if (dist >= 5625) - speed = GetRunspeed(); + int nspeed = (dist >= 5625 ? GetRunspeed() : GetWalkspeed()); + animation = nspeed; + nspeed *= 2; + SetCurrentSpeed(nspeed); - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); + CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed); } } else diff --git a/zone/npc.cpp b/zone/npc.cpp index d4a33b6d0..1efd2beb6 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1929,7 +1929,15 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) 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 == "runspeed") { runspeed = (float)atof(val.c_str()); CalcBonuses(); return; } + else if(id == "runspeed") { + runspeed = (float)atof(val.c_str()); + base_runspeed = (int)((float)runspeed * 40.0f); + base_walkspeed = base_runspeed * 100 / 265; + walkspeed = ((float)base_walkspeed) * 0.025f; + base_fearspeed = base_runspeed * 100 / 127; + fearspeed = ((float)base_fearspeed) * 0.025f; + CalcBonuses(); return; + } 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; } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index b0c74a9e8..75b894ca6 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -597,7 +597,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo pRunAnimSpeed = speed; if(IsClient()) { - animation = speed; + animation = speed / 2; } //pRunAnimSpeed = (int8)(speed*NPC_RUNANIM_RATIO); //speed *= NPC_SPEED_MULTIPLIER; @@ -611,7 +611,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo tar_vector = (float)speed / mag; // mob move fix - int numsteps = (int) ( mag * 16.0f / (float)speed); + int numsteps = (int) ( mag * 16.0f / (float)speed + 0.5f); // mob move fix From 56b57d2ca688907621c7fa27f7cb34f3c7b90677 Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 30 Jun 2015 20:05:35 -0400 Subject: [PATCH 222/846] Fix moving character to zone using character id and zone name. (bheam) --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index 31566d82f..b27722fe9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1384,7 +1384,7 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) { } bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { - std::string query = StringFormat("UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", iZonename, GetZoneID(iZonename), iCharID); + std::string query = StringFormat("UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", GetZoneID(iZonename), iCharID); auto results = QueryDatabase(query); if (!results.Success()) { From ea18238a127d5fbd2d9d5712089df12fce74509c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 30 Jun 2015 20:35:28 -0400 Subject: [PATCH 223/846] Some servers apparently relied on the HP update spam --- common/ruletypes.h | 1 + zone/attack.cpp | 4 ++-- zone/mob.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 1919c7168..372224f2c 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -113,6 +113,7 @@ RULE_INT(Character, TradeskillUpMakePoison, 2) // Make Poison skillup rate adjus RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster. RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster. RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster. +RULE_BOOL(Character, SpamHPUpdates, false) // if your server has stupid amounts of HP that causes client display issues, turn this on! RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/zone/attack.cpp b/zone/attack.cpp index ffdb0ec41..a810ccebb 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3693,11 +3693,11 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons //send an HP update if we are hurt if(GetHP() < GetMaxHP()) - SendHPUpdate(!iBuffTic); // the OP_Damage actually updates the client in these cases, so we skill them + SendHPUpdate(!iBuffTic); // the OP_Damage actually updates the client in these cases, so we skip the HP update for them } //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 + 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)); CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer; a->target = GetID(); diff --git a/zone/mob.cpp b/zone/mob.cpp index cab28ff7b..ac5e37a8e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1354,8 +1354,9 @@ void Mob::SendHPUpdate(bool skip_self) } } + bool dospam = RuleB(Character, SpamHPUpdates); // send to self - we need the actual hps here - if(IsClient() && !skip_self) { + if(IsClient() && (!skip_self || dospam)) { 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; @@ -1364,7 +1365,8 @@ void Mob::SendHPUpdate(bool skip_self) CastToClient()->QueuePacket(hp_app2); safe_delete(hp_app2); } - ResetHPUpdateTimer(); // delay the timer + if (!dospam) + ResetHPUpdateTimer(); // delay the timer } // this one just warps the mob to the current location From 895f27a6c1bc948e441f3dfde3458c8b83d207c0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 30 Jun 2015 23:42:21 -0500 Subject: [PATCH 224/846] Fix an issue with Guild messages sent via gmsay that are too long --- zone/worldserver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 517106aca..d9af83d87 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1907,10 +1907,10 @@ bool WorldServer::SendEmoteMessage(const char* to, uint32 to_guilddbid, uint32 t bool WorldServer::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...) { va_list argptr; - char buffer[256]; + char buffer[256] = { 0 }; va_start(argptr, message); - vsnprintf(buffer, 256, message, argptr); + vsnprintf(buffer, sizeof(buffer) - 1, message, argptr); va_end(argptr); if (!Connected() && to == 0) { From 88659b5f7e33a4b6a231b94857d93a1614875fe0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 30 Jun 2015 23:57:13 -0500 Subject: [PATCH 225/846] Runspeed changes added to database update manifest --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 2 ++ utils/sql/git/required/2015_06_30_runspeed_adjustments.sql | 7 +++++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2015_06_30_runspeed_adjustments.sql diff --git a/common/version.h b/common/version.h index 1813f77c3..00f74e801 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 9083 +#define CURRENT_BINARY_DATABASE_VERSION 9084 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index e7aa46221..c2f8242c3 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -337,6 +337,8 @@ 9081|2015_05_23_dbstr_us.sql|SHOW TABLES LIKE 'db_str'|empty| 9082|2015_05_25_npc_types_texture_fields.sql|SHOW COLUMNS FROM `npc_types` LIKE 'armtexture'|empty| 9083|2015_06_07_aa_update.sql|SHOW COLUMNS FROM `character_alternate_abilities` LIKE 'charges'|empty| +9084|2015_06_30_runspeed_adjustments.sql|SELECT `runspeed` FROM `npc_types` WHERE `runspeed` > 3|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/2015_06_30_runspeed_adjustments.sql b/utils/sql/git/required/2015_06_30_runspeed_adjustments.sql new file mode 100644 index 000000000..f3feaec1a --- /dev/null +++ b/utils/sql/git/required/2015_06_30_runspeed_adjustments.sql @@ -0,0 +1,7 @@ +/* This rescales the old peq runspeeds which were about 80 percent too high to new values */ +/* This section should only ever be run once */ +UPDATE npc_types SET npc_types.runspeed = 1.050 WHERE (npc_types.runspeed > 0 and npc_types.runspeed < 1.2); +UPDATE npc_types SET npc_types.runspeed = 1.325 WHERE (npc_types.runspeed > 1.19 and npc_types.runspeed < 1.75 and race != 73 and race != 72); +UPDATE npc_types SET npc_types.runspeed = 1.575 WHERE (npc_types.runspeed > 1.69 and npc_types.runspeed < 2.2); +UPDATE npc_types SET npc_types.runspeed = 1.850 WHERE (npc_types.runspeed > 2.19 and npc_types.runspeed < 3); +UPDATE npc_types SET npc_types.runspeed = 3 WHERE npc_types.runspeed > 3; \ No newline at end of file From b71e856c8cd8e23fba27619d15fbd64f88b5508c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 1 Jul 2015 00:19:44 -0500 Subject: [PATCH 226/846] Increase emote buffer to 4096 --- zone/worldserver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index d9af83d87..d3e3ee289 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1896,10 +1896,10 @@ bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_nu bool WorldServer::SendEmoteMessage(const char* to, uint32 to_guilddbid, uint32 type, const char* message, ...) { va_list argptr; - char buffer[256]; + char buffer[4096] = { 0 }; va_start(argptr, message); - vsnprintf(buffer, 256, message, argptr); + vsnprintf(buffer, sizeof(buffer) - 1, message, argptr); va_end(argptr); return SendEmoteMessage(to, to_guilddbid, 0, type, buffer); @@ -1907,7 +1907,7 @@ bool WorldServer::SendEmoteMessage(const char* to, uint32 to_guilddbid, uint32 t bool WorldServer::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...) { va_list argptr; - char buffer[256] = { 0 }; + char buffer[4096] = { 0 }; va_start(argptr, message); vsnprintf(buffer, sizeof(buffer) - 1, message, argptr); From 2bf49be8555291d552ba25763e3e1d86a52d3cf0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 1 Jul 2015 01:23:00 -0500 Subject: [PATCH 227/846] Fix an issue where emote messages would overflow the buffer of 256 by increasing the size and changing some of the initialization Added a custom Health Update message that will display in the middle of the players screen, to enable this server wide you must enable rule 'Character:MarqueeHPUpdates' (Haynar) Fixed some runspeed issues with Perl and LUA scripts (Haynar) Updated #showstats and #npcstats for new speed calcs to display speeds again in familiar float format. (Haynar) Improved client movement while AI Controlled, such as feared and charmed. Movement will be much smoother from clients perspective. --- changelog.txt | 7 +++++++ common/ruletypes.h | 1 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + utils/sql/git/required/2015_7_1_Marquee_Rule.sql | 1 + zone/attack.cpp | 3 +++ zone/client.cpp | 13 +++++++++++++ zone/client.h | 3 +++ zone/mob.cpp | 3 +++ 9 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2015_7_1_Marquee_Rule.sql diff --git a/changelog.txt b/changelog.txt index 6c42a23ca..887731565 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 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 +Akkadius: Added a custom Health Update message that will display in the middle of the players screen, to enable this server wide you must enable rule 'Character:MarqueeHPUpdates' +Akkadius: (Haynar) Fixed some runspeed issues with Perl and LUA scripts +Akkadius: (Haynar) Updated #showstats and #npcstats for new speed calcs to display speeds again in familiar float format. +Akkadius: (Haynar) Improved client movement while AI Controlled, such as feared and charmed. Movement will be much smoother from clients perspective. + == 06/12/2015 == Uleat: Adjusted SessionStats to better reflect a sister implementation diff --git a/common/ruletypes.h b/common/ruletypes.h index 372224f2c..6aea84edf 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -114,6 +114,7 @@ RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lowe RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster. RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster. RULE_BOOL(Character, SpamHPUpdates, false) // if your server has stupid amounts of HP that causes client display issues, turn this on! +RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100% RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/common/version.h b/common/version.h index 00f74e801..3631639d5 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 9084 +#define CURRENT_BINARY_DATABASE_VERSION 9085 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index c2f8242c3..2e94567ad 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -338,6 +338,7 @@ 9082|2015_05_25_npc_types_texture_fields.sql|SHOW COLUMNS FROM `npc_types` LIKE 'armtexture'|empty| 9083|2015_06_07_aa_update.sql|SHOW COLUMNS FROM `character_alternate_abilities` LIKE 'charges'|empty| 9084|2015_06_30_runspeed_adjustments.sql|SELECT `runspeed` FROM `npc_types` WHERE `runspeed` > 3|not_empty| +9085|2015_7_1_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty| # Upgrade conditions: diff --git a/utils/sql/git/required/2015_7_1_Marquee_Rule.sql b/utils/sql/git/required/2015_7_1_Marquee_Rule.sql new file mode 100644 index 000000000..039a34412 --- /dev/null +++ b/utils/sql/git/required/2015_7_1_Marquee_Rule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`rule_name`, `rule_value`, `notes`) VALUES ('Character:MarqueeHPUpdates', 'false', 'Will show Health % in center of screen < 100%'); \ No newline at end of file diff --git a/zone/attack.cpp b/zone/attack.cpp index a810ccebb..921353dff 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3582,6 +3582,9 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons //final damage has been determined. SetHP(GetHP() - damage); + + if (IsClient()) + this->CastToClient()->SendHPUpdateMarquee(); if(HasDied()) { bool IsSaved = false; diff --git a/zone/client.cpp b/zone/client.cpp index 7c73db5cc..ee9dfad22 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8639,3 +8639,16 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, QueuePacket(outapp, false, Client::CLIENT_CONNECTED); safe_delete(outapp); } + +void Client::SendHPUpdateMarquee(){ + if (!RuleB(Character, MarqueeHPUpdates)) + return; + + /* Health Update Marquee Display: Custom*/ + uint32 health_percentage = (uint32)(this->cur_hp * 100 / this->max_hp); + if (health_percentage == 100) + return; + + std::string health_update_notification = StringFormat("Health: %u%%", health_percentage); + this->SendMarqueeMessage(15, 510, 0, 3000, 3000, health_update_notification); +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index 4f31aee23..e70190ccc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1261,6 +1261,9 @@ public: void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false); void ResetHPUpdateTimer() { hpupdate_timer.Start(); } + + void SendHPUpdateMarquee(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); diff --git a/zone/mob.cpp b/zone/mob.cpp index ac5e37a8e..4c2966097 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1357,6 +1357,9 @@ void Mob::SendHPUpdate(bool skip_self) bool dospam = RuleB(Character, SpamHPUpdates); // send to self - we need the actual hps here if(IsClient() && (!skip_self || dospam)) { + + this->CastToClient()->SendHPUpdateMarquee(); + 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; From da1167671b26efa0c1a26210636e38b2ce63a2a9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 1 Jul 2015 01:25:56 -0500 Subject: [PATCH 228/846] changelog addition [skip ci] --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 887731565..eaaa6fb7a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 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 Akkadius: Added a custom Health Update message that will display in the middle of the players screen, to enable this server wide you must enable rule 'Character:MarqueeHPUpdates' + Example: https://www.youtube.com/watch?v=KUVdbPxLIn0 Akkadius: (Haynar) Fixed some runspeed issues with Perl and LUA scripts Akkadius: (Haynar) Updated #showstats and #npcstats for new speed calcs to display speeds again in familiar float format. Akkadius: (Haynar) Improved client movement while AI Controlled, such as feared and charmed. Movement will be much smoother from clients perspective. From 35991b68a0c021d21b665ff63ecfeecb2838358f Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 2 Jul 2015 19:36:38 -0700 Subject: [PATCH 229/846] First sql, need to merge from master first before i finish. --- .../sql/git/required/2015_07_02_aa_rework.sql | 20659 ++++++++++++++++ 1 file changed, 20659 insertions(+) create mode 100644 utils/sql/git/required/2015_07_02_aa_rework.sql diff --git a/utils/sql/git/required/2015_07_02_aa_rework.sql b/utils/sql/git/required/2015_07_02_aa_rework.sql new file mode 100644 index 000000000..41a67f7c0 --- /dev/null +++ b/utils/sql/git/required/2015_07_02_aa_rework.sql @@ -0,0 +1,20659 @@ +DROP TABLE IF EXISTS `aa_ability`; +CREATE TABLE IF NOT EXISTS `aa_ability` ( + `id` int(10) unsigned NOT NULL, + `name` text NOT NULL, + `category` int(10) NOT NULL DEFAULT '-1', + `classes` int(10) NOT NULL DEFAULT '131070', + `races` int(10) NOT NULL DEFAULT '65535', + `drakkin_heritage` int(10) NOT NULL DEFAULT '127', + `deities` int(10) NOT NULL DEFAULT '131071', + `status` int(10) NOT NULL DEFAULT '0', + `type` int(10) NOT NULL DEFAULT '0', + `charges` int(11) NOT NULL DEFAULT '0', + `grant_only` tinyint(4) NOT NULL DEFAULT '0', + `first_rank_id` int(10) NOT NULL DEFAULT '-1', + `enabled` tinyint(3) unsigned NOT NULL DEFAULT '1', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `aa_ability` (`id`, `name`, `category`, `classes`, `races`, `drakkin_heritage`, `deities`, `status`, `type`, `charges`, `grant_only`, `first_rank_id`, `enabled`) VALUES + (0, 'Unknown AA -1', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 49999, 1), + (1, 'Innate Strength', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 2, 1), + (2, 'Innate Stamina', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 7, 1), + (3, 'Innate Agility', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 12, 1), + (4, 'Innate Dexterity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 17, 1), + (5, 'Innate Intelligence', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 22, 1), + (6, 'Innate Wisdom', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 27, 1), + (7, 'Innate Charisma', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 32, 1), + (8, 'Innate Fire Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 37, 1), + (9, 'Innate Cold Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 42, 1), + (10, 'Innate Magic Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 47, 1), + (11, 'Innate Poison Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 52, 1), + (12, 'Innate Disease Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 57, 1), + (13, 'Innate Run Speed', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 62, 1), + (15, 'Innate Metabolism', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 68, 1), + (16, 'Innate Lung Capacity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 71, 1), + (17, 'First Aid', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 74, 1), + (18, 'Healing Adept', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 77, 1), + (19, 'Healing Gift', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 80, 1), + (20, 'Spell Casting Mastery', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 83, 1), + (21, 'Spell Casting Reinforcement', -1, 25150, 65535, 127, 131071, 0, 2, 0, 0, 86, 1), + (23, 'Spell Casting Fury', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 92, 1), + (25, 'Spell Casting Subtlety', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 98, 1), + (26, 'Spell Casting Expertise', -1, 15504, 65535, 127, 131071, 0, 2, 0, 0, 101, 1), + (27, 'Spell Casting Deftness', -1, 7184, 65535, 127, 131071, 0, 2, 0, 0, 104, 1), + (28, 'Natural Durability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 107, 1), + (29, 'Natural Healing', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 110, 1), + (30, 'Combat Fury', -1, 16596, 65535, 127, 131071, 0, 2, 0, 0, 113, 1), + (31, 'Fear Resistance', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 116, 1), + (32, 'Finishing Blow', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 119, 1), + (33, 'Combat Stability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 122, 1), + (34, 'Combat Agility', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 125, 1), + (35, 'Mass Group Buff', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 128, 1), + (36, 'Divine Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 129, 1), + (37, 'Innate Invis to Undead', -1, 1026, 65535, 127, 131071, 0, 3, 0, 0, 130, 1), + (38, 'Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 131, 1), + (39, 'Bestow Divine Aura', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 132, 1), + (41, 'Purify Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 136, 1), + (42, 'Quick Evacuation', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 137, 1), + (43, 'Exodus', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 140, 1), + (44, 'Quick Damage', -1, 6176, 65535, 127, 131071, 0, 3, 0, 0, 141, 1), + (45, 'Enhanced Root', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 144, 1), + (46, 'Dire Charm', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 145, 1), + (47, 'Cannibalization', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 146, 1), + (48, 'Quick Buff', -1, 25134, 65535, 127, 131071, 0, 2, 0, 0, 147, 1), + (49, 'Alchemy Mastery', 6, 512, 65535, 127, 131071, 0, 1, 0, 0, 150, 1), + (50, 'Rabid Bear', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 153, 1), + (52, 'Improved Familiar', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 155, 1), + (53, 'Nexus Gate', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 156, 1), + (55, 'Permanent Illusion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 158, 1), + (56, 'Jewel Craft Mastery', 6, 8192, 65535, 127, 131071, 0, 1, 0, 0, 159, 1), + (57, 'Gather Mana', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 162, 1), + (58, 'Mend Companion', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 163, 1), + (60, 'Frenzied Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 167, 1), + (61, 'Elemental Form: Fire', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 168, 1), + (62, 'Elemental Form: Water', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 171, 1), + (63, 'Elemental Form: Earth', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 174, 1), + (64, 'Elemental Form: Air', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 177, 1), + (67, 'Elemental Pact', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 182, 1), + (68, 'Life Burn', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 183, 1), + (69, 'Dead Mesmerization', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 184, 1), + (70, 'Fear Storm', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 185, 1), + (71, 'Flesh to Bone', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 186, 1), + (72, 'Call to Corpse', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 187, 1), + (73, 'Divine Stun', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 188, 1), + (75, 'Slay Undead', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 190, 1), + (76, 'Act of Valor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 193, 1), + (77, 'Holy Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 194, 1), + (78, 'Fearless', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 195, 1), + (79, '2 Hand Bash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 196, 1), + (80, 'Innate Camouflage', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 197, 1), + (81, 'Ambidexterity', -1, 16841, 65535, 127, 131071, 0, 3, 0, 0, 198, 1), + (82, 'Archery Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 199, 1), + (84, 'Endless Quiver', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 205, 1), + (85, 'Unholy Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 206, 1), + (87, 'Leech Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 208, 1), + (89, 'Soul Abrasion', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 210, 1), + (90, 'Instrument Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 213, 1), + (94, 'Jam Fest', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 225, 1), + (97, 'Critical Mend', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 230, 1), + (98, 'Purify Body', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 233, 1), + (100, 'Rapid Feign', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 237, 1), + (101, 'Return Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 240, 1), + (102, 'Escape', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 243, 1), + (103, 'Poison Mastery', 6, 256, 65535, 127, 131071, 0, 1, 0, 0, 244, 1), + (104, 'Double Riposte', -1, 49501, 65535, 127, 131071, 0, 2, 0, 0, 247, 1), + (107, 'Purge Poison', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 254, 1), + (108, 'Flurry', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 255, 1), + (109, 'Rampage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 258, 1), + (110, 'Area Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 259, 1), + (111, 'War Cry', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 260, 1), + (112, 'Bandage Wound', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 263, 1), + (114, 'Spell Casting Fury Mastery', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 267, 1), + (116, 'Dragon Punch', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 273, 1), + (117, 'Strong Root', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 274, 1), + (118, 'Singing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 275, 1), + (119, 'Body and Mind Rejuvenation', -1, 16540, 65535, 127, 131071, 0, 3, 0, 0, 278, 1), + (120, 'Physical Enhancement', -1, 49629, 65535, 127, 131071, 0, 3, 0, 0, 279, 1), + (121, 'Adv. Trap Negotiation', -1, 384, 65535, 127, 131071, 0, 3, 0, 0, 280, 1), + (122, 'Acrobatics', -1, 448, 65535, 127, 131071, 0, 3, 0, 0, 283, 1), + (123, 'Scribble Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 286, 1), + (124, 'Chaotic Stab', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 287, 1), + (125, 'Pet Discipline', -1, 22032, 65535, 127, 131071, 0, 3, 0, 0, 288, 1), + (126, 'Hobble of Spirits', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 289, 1), + (127, 'Frenzy of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 290, 1), + (128, 'Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 291, 1), + (129, 'Chains of Purity', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10348, 1), + (130, 'Resplendent Glory', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8300, 1), + (131, 'Rage of Rallos Zek', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8303, 1), + (132, 'Enhanced Area Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8312, 1), + (133, 'Decapitation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 14200, 1), + (134, 'Hastened Berserking Disciplines', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 14203, 1), + (135, 'Quiet Miracle', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14206, 1), + (136, 'Repel the Wicked', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14207, 1), + (137, 'Beacon of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14208, 1), + (138, 'Blessed Chains', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14209, 1), + (139, 'Hastened Focused Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14213, 1), + (140, 'Quickened Spirit Calling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14225, 1), + (141, 'New Tanaan Crafting Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 412, 1), + (142, 'Planar Power', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 418, 1), + (143, 'Planar Durability', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 423, 1), + (144, 'Innate Enlightenment', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 426, 1), + (146, 'Unknown AA 8001', 9, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8000, 0), + (147, 'Spiritual Rebuke', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14231, 1), + (148, 'Pathosis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14232, 1), + (149, 'Preincarnation', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 14233, 1), + (150, 'Mastery of the Past', -1, 15504, 65535, 127, 131071, 0, 2, 0, 0, 446, 1), + (151, 'Spiritual Blessing', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14234, 1), + (152, 'Communion of the Cheetah', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14237, 1), + (153, 'Radiant Cure', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 459, 1), + (154, 'Hastened Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 462, 1), + (156, 'Hastened Purification of the Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 468, 1), + (157, 'Hastened Gathering', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 471, 1), + (158, 'Hastened Rabidity', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 474, 1), + (159, 'Hastened Exodus', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 477, 1), + (160, 'Hastened Root', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 480, 1), + (161, 'Hastened Mending', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 483, 1), + (163, 'Hastened Instigation', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 489, 1), + (164, 'Hastened Rampage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 492, 1), + (165, 'Hastened Purification of the Body', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 495, 1), + (166, 'Hasty Exit', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 498, 1), + (167, 'Hastened Purification', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 501, 1), + (168, 'Hastened Nature\'s Fury', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14241, 1), + (169, 'Divine Arbitration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 507, 1), + (170, 'Wrath of the Wild', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 510, 1), + (171, 'Virulent Paralysis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 513, 1), + (172, 'Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 516, 1), + (173, 'Eldritch Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 517, 1), + (174, 'Servant of Ro', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 520, 1), + (175, 'Wake the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 523, 1), + (176, 'Suspended Minion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 526, 1), + (177, 'Spirit Call', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 528, 1), + (178, 'Wrath of the Forest Walker', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14244, 1), + (179, 'Gift of Sylvan Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14249, 1), + (180, 'Hand of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 534, 1), + (181, 'Mithaniel\'s Binding', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 537, 1), + (182, 'Summon Personal Tribute Master', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5006, 1), + (183, 'Extended Vinelash Cascade', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14254, 1), + (184, 'Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 545, 1), + (185, 'Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 548, 1), + (186, 'Bestial Frenzy', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 551, 1), + (187, 'Harmonious Attack', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 556, 1), + (188, 'Knight\'s Advantage', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 561, 1), + (189, 'Ferocity', -1, 33097, 65535, 127, 131071, 0, 2, 0, 0, 564, 1), + (190, 'Viscid Roots', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 567, 1), + (193, 'Feigned Minion', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 574, 1), + (194, 'Unfailing Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 577, 1), + (195, 'Animation Empathy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 580, 1), + (196, 'Rush to Judgment', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 583, 1), + (197, 'Living Shield', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 586, 1), + (198, 'Consumption of the Soul', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 589, 1), + (199, 'Boastful Bellow', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 592, 1), + (200, 'Fervent Blessing', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 593, 1), + (201, 'Touch of the Wicked', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 596, 1), + (202, 'Punishing Blade', -1, 32841, 65535, 127, 131071, 0, 2, 0, 0, 599, 1), + (203, 'Speed of the Knight', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 602, 1), + (204, 'Shroud of Stealth', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 605, 1), + (205, 'Nimble Evasion', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 606, 1), + (206, 'Technique of Master Wu', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 611, 1), + (207, 'Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 616, 1), + (208, 'Call of Xuzl', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 619, 1), + (209, 'Hastened Stealth', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 622, 1), + (210, 'Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 625, 1), + (211, 'Fleet of Foot', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 628, 1), + (212, 'Fading Memories', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 630, 1), + (213, 'Tactical Mastery', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 631, 1), + (214, 'Theft of Life', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 634, 1), + (215, 'Fury of Magic', -1, 13858, 65535, 127, 131071, 0, 2, 0, 0, 637, 1), + (216, 'Extended Spirit of the Bear', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14259, 1), + (217, 'Project Illusion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 643, 1), + (218, 'Headshot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 644, 1), + (219, 'Entrap', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 645, 1), + (220, 'Sonic Displacement', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13528, 1), + (221, 'Total Domination', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 649, 1), + (222, 'Stalwart Endurance', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 652, 1), + (223, 'Quick Summoning', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 655, 1), + (224, 'Mental Clarity', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 658, 1), + (225, 'Innate Regeneration', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 661, 1), + (227, 'Extended Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 665, 1), + (228, 'Hastened Warder\'s Gift', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13463, 1), + (229, 'Improved Reclaim Energy', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 671, 1), + (230, 'Hastened Possum', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13449, 1), + (231, 'Shauri\'s Sonorious Clouding', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13527, 1), + (232, 'Veil of the Underbrush', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14262, 1), + (233, 'Packrat', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 678, 1), + (234, 'Heightened Endurance ', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 683, 1), + (235, 'Weapon Affinity', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 686, 1), + (236, 'Secondary Forte', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 691, 1), + (237, 'Persistent Casting', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 692, 1), + (238, 'Tune of Pursuance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 695, 1), + (239, 'Hastened Companion\'s Sacrifice', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13474, 1), + (240, 'Cheetah\'s Pounce', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13483, 1), + (241, 'Bloodlust', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13484, 1), + (242, 'Primal Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13485, 1), + (244, 'Lure of the Siren\'s Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13529, 1), + (245, 'Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 718, 1), + (246, 'Hidden Communion of the Cheetah', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14265, 1), + (247, 'Feral Swipe', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 723, 1), + (248, 'Warder\'s Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 724, 1), + (249, 'Warder\'s Alacrity', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 729, 1), + (250, 'Pet Affinity', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 734, 1), + (251, 'Mastery of the Past', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 735, 1), + (252, 'Spell Casting Subtlety', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 738, 1), + (254, 'Divine Avatar', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 746, 1), + (255, 'Exquisite Benediction', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 749, 1), + (256, 'Hastened Curing', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 754, 1), + (257, 'Nature\'s Boon', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 757, 1), + (258, 'Advanced Tracking', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 762, 1), + (259, 'Critical Affliction', -1, 18104, 65535, 127, 131071, 0, 2, 0, 0, 767, 1), + (260, 'Glacial Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13549, 1), + (261, 'Doppelganger', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 773, 1), + (262, 'Enhanced Forgetfulness', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 776, 1), + (263, 'Mesmerization Mastery', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 781, 1), + (264, 'Quick Mass Group Buff', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 782, 1), + (265, 'Shared Health', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 785, 1), + (266, 'Elemental Fury', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 790, 1), + (267, 'Elemental Alacrity ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 795, 1), + (268, 'Elemental Agility', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 800, 1), + (269, 'Elemental Durability', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 803, 1), + (270, 'Sinister Strikes', -1, 16841, 65535, 127, 131071, 0, 3, 0, 0, 806, 1), + (271, 'Strikethrough', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 807, 1), + (272, 'Stonewall', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 810, 1), + (273, 'Rapid Strikes ', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 815, 1), + (274, 'Kick Mastery', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 820, 1), + (275, 'Heightened Awareness', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 823, 1), + (276, 'Destructive Force ', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 828, 1), + (278, 'Death\'s Fury ', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 834, 1), + (279, 'Quickening of Death ', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 839, 1), + (280, 'Group Perfected Invisibility to Undead', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 14281, 1), + (281, 'Triple Backstab', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 846, 1), + (282, 'Hastened Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 849, 1), + (283, 'Immobilizing Bash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 852, 1), + (284, 'Vicious Smash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 855, 1), + (285, 'Radiant Cure', -1, 4, 65535, 127, 131071, 0, 2, 0, 0, 860, 1), + (286, 'Purification ', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 863, 1), + (287, 'Precision of the Pathfinder', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 864, 1), + (288, 'Coat of Thistles', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 867, 1), + (289, 'Flaming Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 872, 1), + (290, 'Frost Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 875, 1), + (291, 'Perfected Invisibility to Undead', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 14282, 1), + (292, 'Trap Circumvention ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 881, 1), + (293, 'Quickened Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14283, 1), + (294, 'Virulent Venom ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 888, 1), + (295, 'Extended Dreary Deeds', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14286, 1), + (296, 'Intense Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 895, 1), + (297, 'Quickened Frenzied Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14289, 1), + (299, 'Sturdiness', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 907, 1), + (300, 'Warlord\'s Tenacity ', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 912, 1), + (301, 'Strengthened Strike', -1, 9, 65535, 127, 131071, 0, 3, 0, 0, 915, 1), + (302, 'Extended Shielding', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 918, 1), + (303, 'Ro\'s Flaming Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 921, 1), + (304, 'E\'ci\'s Icy Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 922, 1), + (305, 'Druzzil\'s Mystical Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 923, 1), + (306, 'Unknown AA 15819', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15819, 1), + (307, 'Ward of Destruction ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 926, 1), + (308, 'Frenzied Devastation', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 931, 1), + (309, 'Combat Fury', -1, 32769, 65535, 127, 131071, 0, 2, 0, 0, 934, 1), + (310, 'Combat Fury', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 937, 1), + (311, 'Combat Fury', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 940, 1), + (312, 'Quickened Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14292, 1), + (313, 'Hastened Companion\'s Relocation', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 14295, 1), + (314, 'Veteran\'s Wrath', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1047, 1), + (315, 'Planar Durability', -1, 32788, 65535, 127, 131071, 0, 3, 0, 0, 952, 1), + (316, 'Innate Enlightenment', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 955, 1), + (317, 'Dire Charm', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 960, 1), + (318, 'Dire Charm', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 961, 1), + (319, 'Touch of the Divine', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 962, 1), + (320, 'Swarm of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 967, 1), + (321, 'Call of the Ancients', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 970, 1), + (322, 'Innate See Invis', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1388, 1), + (323, 'Virulent Talon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14307, 1), + (324, 'Blacksmithing Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 979, 1), + (325, 'Baking Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 982, 1), + (326, 'Brewing Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 985, 1), + (327, 'Fletching Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 988, 1), + (328, 'Pottery Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 991, 1), + (329, 'Tailoring Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 994, 1), + (330, 'Salvage', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 997, 1), + (331, 'Origin', 9, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1000, 1), + (333, 'Discordant Defiance', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1006, 1), + (334, 'Mystical Attuning', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1021, 1), + (335, 'Delay Death', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1026, 1), + (336, 'Earthen Brawn', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8263, 1), + (337, 'Unknown AA 15798', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15798, 1), + (338, 'Veteran\'s Wrath', -1, 16596, 65535, 127, 131071, 0, 2, 0, 0, 1041, 1), + (339, 'Veteran\'s Wrath', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1044, 1), + (340, 'Unknown AA 15833', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15833, 1), + (341, 'Veteran\'s Wrath', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 1050, 1), + (342, 'Staff Block', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 14301, 1), + (343, 'Hastened Pestilent Paralysis', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14308, 1), + (344, 'Hastened Mercurial Torment', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14311, 1), + (345, 'Unknown AA 15768', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15768, 1), + (346, 'Unknown AA 15771', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 15771, 1), + (347, 'Mnemonic Retention', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 1071, 1), + (348, 'Expansive Mind', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 1072, 1), + (350, 'Death\'s Malaise', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14321, 1), + (351, 'Dying Grasp', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14322, 1), + (352, 'Arcane Tongues', 6, 15360, 65535, 127, 131071, 0, 2, 0, 0, 1089, 1), + (353, 'Master of Disguise', -1, 384, 65535, 127, 131071, 0, 3, 0, 0, 1092, 1), + (354, 'Slippery Attacks', -1, 16841, 65535, 127, 131071, 0, 2, 0, 0, 1093, 1), + (355, 'Unknown AA 15836', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15836, 1), + (357, 'Unknown AA 16176', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16176, 1), + (358, 'Fury of Magic', -1, 16540, 65535, 127, 131071, 0, 2, 0, 0, 1107, 1), + (359, 'Dance of Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1110, 1), + (360, 'Bloodthirsty Blade', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13616, 1), + (361, 'Shield of Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1116, 1), + (362, 'Roar of Thunder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 1119, 1), + (363, 'Unknown AA 16179', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16179, 1), + (364, 'Persistent Minion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 1122, 1), + (365, 'A Hole In Space', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 14323, 1), + (366, 'Advanced Pet Discipline', -1, 22032, 65535, 127, 131071, 0, 3, 0, 0, 1129, 1), + (367, 'Throwing Mastery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1131, 1), + (368, 'Blur of Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1134, 1), + (369, 'Hastened War Cry', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1137, 1), + (370, 'Dead Aim', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1140, 1), + (371, 'Frenzied Defense', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1166, 1), + (372, 'Tireless Sprint', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1146, 1), + (373, 'Desperation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1149, 1), + (374, 'Untamed Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1150, 1), + (375, 'Echoing Cries', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1155, 1), + (376, 'Distant Strike', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14372, 1), + (377, 'Earthen Stability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8268, 1), + (378, 'Earthen Alacrity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8273, 1), + (379, 'Earthen Artistry', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8278, 1), + (380, 'Earthen Sagacity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8283, 1), + (381, 'Earthen Brilliance', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8288, 1), + (382, 'Earthen Allure', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8293, 1), + (383, 'Extended Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12646, 1), + (384, 'Spirit of the Bear', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12651, 1), + (385, 'Twinheal', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 12652, 1), + (386, 'Nature\'s Fury', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12661, 1), + (387, 'Blood Pact', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1178, 1), + (388, 'Shielding Resistance', -1, 16841, 65535, 127, 131071, 0, 2, 0, 0, 1181, 1), + (389, 'Healing Boon', -1, 518, 65535, 127, 131071, 0, 2, 0, 0, 1186, 1), + (390, 'Elemental Union', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 13695, 1), + (391, 'Celestial Hammer', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1192, 1), + (392, 'Divine Retribution', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1195, 1), + (393, 'Nature\'s Blessing', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12655, 1), + (394, 'Extended Convergence of Spirit', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12645, 1), + (395, 'Hastened Storm Strike', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12664, 1), + (396, 'Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1209, 1), + (397, 'Destructive Fury', -1, 2048, 65535, 127, 131071, 0, 2, 0, 0, 1210, 1), + (398, 'Destructive Fury', -1, 13858, 65535, 127, 131071, 0, 2, 0, 0, 1213, 1), + (399, 'Unknown AA 16180', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16180, 1), + (400, 'Hastened Improved Twincast', -1, 14370, 65535, 127, 131071, 0, 3, 0, 0, 14331, 1), + (401, 'Extended Heel of Kanji', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12688, 1), + (402, 'Extended Scaledfist', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12691, 1), + (403, 'Paralytic Spores', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 14264, 1), + (404, 'Call of the Wild', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 1228, 1), + (405, 'Secondary Recall', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 1229, 1), + (406, 'Nature\'s Bounty', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 1230, 1), + (407, 'Extended Speed Focus', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7884, 1), + (408, 'Extended Crystalpalm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7885, 1), + (409, 'Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1233, 1), + (410, 'Fists of Steel', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12706, 1), + (411, 'Extended Deftdance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12709, 1), + (412, 'Color Shock', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1239, 1), + (413, 'Mind Over Matter', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1242, 1), + (414, 'Soothing Words', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1245, 1), + (415, 'Hastened Deftdance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12710, 1), + (416, 'Hastened Lyre Leap', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12713, 1), + (417, 'Hastened Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12716, 1), + (418, 'Replenish Companion', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 1126, 1), + (419, 'Extended Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12719, 1), + (420, 'Imitate Death', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1255, 1), + (424, 'Extended Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12720, 1), + (425, 'Hastened Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12721, 1), + (426, 'Unknown AA 15904', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 15904, 1), + (427, 'Resounding Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12737, 1), + (428, 'Death Peace', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1272, 1), + (429, 'Unknown AA 15908', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15908, 1), + (430, 'Mercurial Torment', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12766, 1), + (431, 'Pestilent Paralysis', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12770, 1), + (432, 'Hastened Divine Companion Aura', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 12773, 1), + (433, 'Embalmer\'s Carapace', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12778, 1), + (434, 'Steadfast Will', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 1284, 1), + (435, 'Shield Block', -1, 21, 65535, 127, 131071, 0, 2, 0, 0, 1287, 1), + (436, 'Hastened Encroaching Darkness', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12779, 1), + (437, 'Tracking Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1296, 1), + (438, 'Expanding Darkness', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12782, 1), + (439, 'Precision', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1304, 1), + (440, 'Nerves of Steel', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1307, 1), + (441, 'Aegis of Kildrukaun', -1, 5120, 65535, 127, 131071, 0, 3, 0, 0, 12785, 1), + (442, 'Touch of the Cursed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 1313, 1), + (443, 'Bestial Bloodrage', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12804, 1), + (444, 'Companion\'s Sacrifice', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12807, 1), + (445, 'Shield Block', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 12813, 1), + (446, 'Spiritual Channeling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1323, 1), + (447, 'Ancestral Aid', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1327, 1), + (448, 'Extended Feralgia', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12816, 1), + (450, 'Hastened Protective Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12819, 1), + (451, 'Mind Crash', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1334, 1), + (452, 'Prolonged Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1337, 1), + (453, 'Summon Permutation Peddler', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9032, 1), + (454, 'Hastened Empathic Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12822, 1), + (455, 'Convergence of Spirits', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13556, 1), + (456, 'Teleport Bind', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1343, 1), + (457, 'Quickened Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12831, 1), + (458, 'Warder\'s Gift', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12837, 1), + (459, 'Gelid Rending', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12846, 1), + (460, 'Quickened Nature\'s Salve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12849, 1), + (462, 'Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1345, 1), + (463, 'Divine Guardian', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13385, 1), + (464, 'Divine Peace', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13388, 1), + (465, 'Savage Spirit', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1348, 1), + (466, 'Trials of Mata Muram', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1011, 1), + (467, 'Press the Attack', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1351, 1), + (468, 'Crippling Strike', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1352, 1), + (469, 'Stunning Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1355, 1), + (470, 'Eye Gouge', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1358, 1), + (471, 'Gift of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1361, 1), + (472, 'Tenacity of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1362, 1), + (473, 'Embrace of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1363, 1), + (474, 'Power of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1364, 1), + (475, 'Fervor of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1365, 1), + (476, 'Gift of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1366, 1), + (477, 'Valor of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1367, 1), + (478, 'Embrace of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1368, 1), + (479, 'Power of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1369, 1), + (480, 'Sanctity of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1370, 1), + (481, 'Lesson of the Devoted', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1371, 1), + (482, 'Infusion of the Faithful', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1372, 1), + (483, 'Chaotic Jester', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1373, 1), + (484, 'Expedient Recovery', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1374, 1), + (485, 'Steadfast Servant', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1375, 1), + (486, 'Staunch Recovery', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1376, 1), + (487, 'Intensity of the Resolute', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1377, 1), + (488, 'Curse of Blood', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1378, 1), + (489, 'Yaulp', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 13389, 1), + (490, 'Abscond', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12864, 1), + (491, 'Atol\'s Unresistable Shackles', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12865, 1), + (492, 'Dimensional Shield', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 12866, 1), + (493, 'Improved Sustained Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12867, 1), + (494, 'Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 1409, 1), + (495, 'Gift of Mana', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 1435, 1), + (496, 'Field Dressing', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 1611, 1), + (497, 'Bandage Wounds', -1, 32766, 65535, 127, 131071, 0, 1, 0, 0, 1420, 1), + (498, 'Enhanced Aggression', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 1592, 1), + (499, 'Cascading Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1425, 1), + (500, 'Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 1404, 1), + (501, 'E\'ci\'s Icy Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12886, 1), + (503, 'Hastened Thunder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 1471, 1), + (504, 'Conservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1453, 1), + (505, 'Cry of Battle', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1458, 1), + (506, 'Ward of Purity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1459, 1), + (507, 'Ro\'s Fiery Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12887, 1), + (508, 'Druzzil\'s Mystical Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12888, 1), + (509, 'Kerafyrm\'s Favor', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12889, 1), + (510, 'Kerafyrm\'s Prismatic Familiar', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12892, 1), + (511, 'Throne of Heroes', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 4665, 1), + (512, 'Translocational Anchor', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1630, 1), + (513, 'Hastened Phantasmal Opponent', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12894, 1), + (514, 'Pyromancy', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1478, 1), + (515, 'Improved Twincast', -1, 14370, 65535, 127, 131071, 0, 3, 0, 0, 12893, 1), + (516, 'Abundant Healing', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 1486, 1), + (517, 'Hastened First Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12902, 1), + (518, 'Shared Camouflage', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 1494, 1), + (519, 'Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1495, 1), + (520, 'Nature\'s Guardian', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1498, 1), + (521, 'Edict of Command', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1501, 1), + (522, 'Extended Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1504, 1), + (523, 'Hastened Second Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12907, 1), + (524, 'Blood Magic', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1510, 1), + (525, 'Graverobbing', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1511, 1), + (526, 'Affliction Mastery', -1, 1568, 65535, 127, 131071, 0, 3, 0, 0, 1514, 1), + (527, 'Hastened Third Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12912, 1), + (528, 'Ancestral Guard', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1520, 1), + (529, 'Cloak of Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1523, 1), + (530, 'Profound Visage', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12920, 1), + (531, 'Cloak of Shadows', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1527, 1), + (532, 'Willful Death', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1528, 1), + (533, 'Unknown AA 16016', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16016, 1), + (534, 'Calculated Insanity', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12931, 1), + (535, 'Crippling Aurora', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12937, 1), + (536, 'Appraisal', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1542, 1), + (537, 'Precise Strikes', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1543, 1), + (538, 'Hastened Death', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1546, 1), + (539, 'Unflinching Resolve', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1549, 1), + (540, 'Weightless Steps', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1552, 1), + (541, 'Hastened Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1555, 1), + (542, 'Unknown AA 16071', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16071, 1), + (543, 'Diminutive Companion', -1, 20480, 65535, 127, 131071, 0, 3, 0, 0, 12941, 1), + (544, 'Song of Stone', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1569, 1), + (545, 'Deep Sleep', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1572, 1), + (546, 'Companion\'s Gift', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1577, 1), + (547, 'Unknown AA 16081', -1, 15360, 65535, 127, 131071, 0, 3, 0, 0, 16081, 1), + (548, 'Hastened Defiance', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1583, 1), + (549, 'Dauntless Perseverance', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1591, 1), + (550, 'Steadfast Resolve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 14275, 1), + (551, 'Hastened Mind Crash', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1414, 1), + (552, 'Call of Challenge', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1597, 1), + (553, 'Cacophony', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1598, 1), + (554, 'Hastened Nightmare Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14341, 1), + (555, 'Anatomy', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1604, 1), + (556, 'Scintillating Beam', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14346, 1), + (557, 'Trick Shot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1608, 1), + (558, 'Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1383, 1), + (559, 'Turn Summoned', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1462, 1), + (560, 'Selo\'s Enduring Cadence', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1627, 1), + (561, 'Hastened Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12881, 1), + (562, 'Lightning Strikes', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1616, 1), + (563, 'Concentration', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 1588, 1), + (565, 'Mana Burn', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1638, 1), + (567, 'Unknown AA 16146', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16146, 1), + (568, 'Thief\'s Intuition', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1641, 1), + (569, 'Thief\'s Intuition', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1642, 1), + (570, 'Valiant Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1645, 1), + (571, 'Abyssal Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 1646, 1), + (572, 'Holy Warhorse', -1, 4, 65535, 127, 131071, 0, 3, 0, 1, 1643, 1), + (573, 'Unholy Warhorse', -1, 16, 65535, 127, 131071, 0, 3, 0, 1, 1644, 1), + (574, 'Harmonic Dissonance', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1647, 1), + (575, 'Tinkering Mastery', 6, 15639, 65535, 127, 131071, 0, 1, 0, 1, 4672, 1), + (576, 'Jewel Craft Mastery ', 6, 57343, 65535, 127, 131071, 0, 1, 0, 0, 4675, 1), + (577, 'Concussive Intuition', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12885, 1), + (578, 'Glyph Spray', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12939, 1), + (579, 'Combat Medic ', -1, 32766, 65535, 127, 131071, 0, 1, 0, 0, 4688, 1), + (580, 'Hastened Outrider\'s Accuracy', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13565, 1), + (581, 'Quick Draw', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 4698, 1), + (582, 'Battle Ready', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 4699, 1), + (583, 'Hastened Outrider\'s Evasion', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13568, 1), + (584, 'Grasp of Sylvan Spirits', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13571, 1), + (585, 'Glyph of Dragon Scales', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4702, 1), + (586, 'Glyph of Indeterminable Reward', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 13788, 1), + (587, 'Glyph of Arcane Secrets', 7, 32318, 65535, 127, 131071, 0, 4, 1, 0, 4704, 1), + (588, 'Glyph of Draconic Potential', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4705, 1), + (589, 'Glyph of Destruction', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4706, 1), + (590, 'Breath of Atathus', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5150, 1), + (591, 'Breath of Draton\'ra', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5165, 1), + (592, 'Breath of Osh\'vir', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5180, 1), + (593, 'Breath of Venesh', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5195, 1), + (594, 'Breath of Mysaphar', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5210, 1), + (595, 'Breath of Keikolin', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5225, 1), + (596, 'Small Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12963, 1), + (597, 'Medium Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12964, 1), + (598, 'Large Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12965, 1), + (599, 'Hastened Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 12968, 1), + (600, 'Blessing of the Devoted', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9033, 1), + (601, 'Grappling Strike', -1, 65, 65535, 127, 131071, 0, 3, 0, 0, 4836, 1), + (602, 'Mental Contortion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12938, 1), + (603, 'Shield of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12971, 1), + (604, 'Extended Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 12977, 1), + (605, 'Shield Specialist', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 4844, 1), + (606, 'Mark of the Mage Hunter', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 4849, 1), + (609, 'Uncanny Resilience', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4854, 1), + (610, 'Blinding Fury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4857, 1), + (611, 'Battle Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 4860, 1), + (612, 'Soul Seeker', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4861, 1), + (613, 'Lingering Death', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13096, 1), + (614, 'Spirit Guardian', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5369, 1), + (615, 'Surreality', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4887, 1), + (616, 'Mana Draw', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4890, 1), + (617, 'Doppelganger\'s Beckon', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5127, 1), + (618, 'Armor of Ancestral Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 12989, 1), + (619, 'Group Pact of the Wolf', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 12992, 1), + (620, 'Hastened Inconspicuous Totem', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13001, 1), + (621, 'Fire Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4903, 1), + (622, 'Vapor Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4906, 1), + (623, 'Ice Core ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4909, 1), + (624, 'Stone Core ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4912, 1), + (625, 'Volatile Mana Blaze', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 4915, 1), + (626, 'Purified Spirits', -1, 546, 65535, 127, 131071, 0, 3, 0, 0, 13004, 1), + (627, 'Group Spirit Walk', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13008, 1), + (628, 'Greater Blood Tithe', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4924, 1), + (629, 'Gathering Dusk', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4927, 1), + (630, 'Group Silent Presence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13009, 1), + (631, 'Double Attack', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5366, 1), + (632, 'Sanguine Mind Crystal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4934, 1), + (633, 'Azure Mind Crystal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4935, 1), + (634, 'Hastened Cannibalization', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13010, 1), + (635, 'Hastened Spirit Channeling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13013, 1), + (636, 'Arcane Whisper', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 4938, 1), + (637, 'Vengeful Spirits', -1, 9776, 65535, 127, 131071, 0, 3, 0, 0, 13017, 1), + (638, 'Crippling Apparition', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13020, 1), + (639, 'Dimensional Instability', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 4943, 1), + (640, 'Cryomancy', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 4944, 1), + (641, 'Hastened Self Preservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13055, 1), + (642, 'Binding Axe', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13065, 1), + (643, 'Agony of Absolution', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13066, 1), + (644, 'Hastened Absolution', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13067, 1), + (645, 'Hastened Calculated Insanity', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13753, 1), + (646, 'Hastened Mental Contortion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13758, 1), + (647, 'Hastened Crippling Aurora', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13764, 1), + (649, 'Hastened Leech Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14046, 1), + (650, 'Bony Grasp of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14051, 1), + (651, 'Thought Leech', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14052, 1), + (652, 'Hastened Leechcurse Discipline', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14056, 1), + (653, 'Hastened Unholy Aura Discipline', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14059, 1), + (654, 'Hastened Harmshield', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 14062, 1), + (655, 'Hastened Projection of Doom', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14065, 1), + (656, 'Hastened Projection of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14068, 1), + (657, 'Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14071, 1), + (658, 'Hastened Sanctification Discipline', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14076, 1), + (659, 'Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14080, 1), + (660, 'Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14081, 1), + (661, 'Hunter\'s Fury', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 5248, 1), + (662, 'Union of Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5251, 1), + (663, 'Quickened Stuns', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14100, 1), + (664, 'Extended Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 14115, 1), + (665, 'Death\'s Wrath', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 5264, 1), + (666, 'Taste of Blood', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 5015, 1), + (667, 'Summoner\'s Beckon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 5269, 1), + (668, 'Hymn of the Last Stand', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5017, 1), + (669, 'Bladed Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5020, 1), + (670, 'Twisted Shank', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5021, 1), + (671, 'Dirty Fighting', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5022, 1), + (672, 'Ligament Slice', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5025, 1), + (673, 'Tumble', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5028, 1), + (674, 'Unknown AA 16149', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16149, 1), + (675, 'Shrink', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14224, 1), + (676, 'Convergence', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14358, 1), + (677, 'Gift of Deathly Resolve', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14359, 1), + (678, 'Unknown AA 16082', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 16082, 1), + (679, 'Unknown AA 16083', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 16083, 1), + (680, 'Unknown AA 16084', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16084, 1), + (681, 'Unknown AA 16087', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16087, 1), + (682, 'Unknown AA 16096', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16096, 1), + (683, 'Unknown AA 16097', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16097, 1), + (684, 'Unknown AA 16104', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16104, 1), + (685, 'Unknown AA 16105', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16105, 1), + (686, 'Unknown AA 16106', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16106, 1), + (687, 'Unknown AA 16107', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16107, 1), + (688, 'Unknown AA 16108', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16108, 1), + (689, 'Combat Medic ', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 5136, 1), + (690, 'Unknown AA 16109', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16109, 1), + (691, 'Unknown AA 16113', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16113, 1), + (692, 'Unknown AA 16114', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16114, 1), + (693, 'Unknown AA 16117', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16117, 1), + (694, 'Unknown AA 16120', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16120, 1), + (695, 'Unknown AA 16152', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16152, 1), + (696, 'Unknown AA 16156', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16156, 1), + (697, 'Mortal Coil', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 5085, 1), + (698, 'Hastened Purified Spirits', -1, 546, 65535, 127, 131071, 0, 3, 0, 0, 13416, 1), + (699, 'Swarm of Fireflies', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 13419, 1), + (700, 'Unknown AA 16159', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16159, 1), + (701, 'Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5095, 1), + (702, 'Hand of Disruption', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5098, 1), + (703, 'Quickened Death Bloom', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14318, 1), + (704, 'Hero\'s Barracks', 9, 65535, 65535, 127, 131071, 0, 4, 0, 1, 14367, 1), + (705, 'Spirit of the White Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 5105, 1), + (706, 'Unknown AA 16160', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16160, 1), + (707, 'Pact of the Wolf', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5109, 1), + (708, 'Enchant Alaran Metal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13271, 1), + (709, 'Mass Enchant Alaran Metal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13272, 1), + (710, 'Funeral Pyre', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14360, 1), + (711, 'Unknown AA 16162', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16162, 1), + (712, 'Hastened Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 5118, 1), + (713, 'Etherium Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14129, 1), + (714, 'Hastened Assassination Disciplines', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14135, 1), + (715, 'Cunning Disguise: Shissar', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14139, 1), + (716, 'Scout\'s Mastery of Piercing', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14141, 1), + (717, 'Extended Envenomed Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14144, 1), + (718, 'Heel of Brithrax', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14151, 1), + (719, 'Extended Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14163, 1), + (720, 'Hastened Marr\'s Salvation', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14088, 1), + (721, 'Hastened Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14091, 1), + (722, 'Hastened Drape of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14304, 1), + (723, 'Unknown AA 16185', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16185, 1), + (724, 'Hastened Eldritch Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14364, 1), + (725, 'Unknown AA 16124', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16124, 1), + (726, 'Unknown AA 16128', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16128, 1), + (727, 'Unknown AA 16131', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16131, 1), + (728, 'Unknown AA 16137', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16137, 1), + (729, 'Unknown AA 16140', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 16140, 1), + (730, 'Unknown AA 16186', -1, 9, 65535, 127, 131071, 0, 3, 0, 0, 16186, 1), + (731, 'Unknown AA 16188', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16188, 1), + (732, 'Unknown AA 16195', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16195, 1), + (733, 'Killing Spree', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 4739, 1), + (734, 'Hold the Line', -1, 32833, 65535, 127, 131071, 0, 3, 0, 0, 4742, 1), + (735, 'Battle Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13134, 1), + (737, 'Quickened Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 13143, 1), + (738, 'Quickened Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 13146, 1), + (739, 'Balefire Burst', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13164, 1), + (740, 'Blood Tithe', -1, 1568, 65535, 127, 131071, 0, 3, 0, 0, 4761, 1), + (741, 'Leap of Faith', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13202, 1), + (742, 'Unknown AA 16196', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16196, 1), + (743, 'Hastened Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13166, 1), + (744, 'Howl of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13169, 1), + (745, 'Hastened Tune In Your Head', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13204, 1), + (746, 'Unknown AA 16197', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16197, 1), + (747, 'Unknown AA 16200', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16200, 1), + (748, 'Nightmare Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4894, 1), + (749, 'Explosion of Spite', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13165, 1), + (751, 'Scent of Terris', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13225, 1), + (752, 'Bloodfury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13224, 1), + (753, 'Dreary Deeds', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13252, 1), + (754, 'Enchant Feymetal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13260, 1), + (755, 'Mass Enchant Feymetal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13261, 1), + (756, 'Enlightened Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 13646, 1), + (757, 'Shifting Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 5276, 1), + (758, 'Extended Silent Casting', -1, 15360, 65535, 127, 131071, 0, 3, 0, 0, 13667, 1), + (759, 'Fury of Kerafyrm', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 13670, 1), + (760, 'Unknown AA 16203', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 16203, 1), + (761, 'Unknown AA 16208', -1, 552, 65535, 127, 131071, 0, 3, 0, 0, 16208, 1), + (762, 'Shield Block', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 5283, 1), + (763, 'Mirrored Pestilence', -1, 1552, 65535, 127, 131071, 0, 3, 0, 0, 13684, 1), + (764, 'Embrace The Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13687, 1), + (765, 'Quickened Scent of Terris', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13689, 1), + (766, 'Frenzy of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13693, 1), + (767, 'Unknown AA 16211', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 16211, 1), + (768, 'Unknown AA 16215', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16215, 1), + (769, 'Marr\'s Salvation', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13100, 1), + (770, 'Blessing of the Faithful', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13101, 1), + (771, 'Unbridled Strike of Fear', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13108, 1), + (772, 'Noteworthy Disguise: Drake', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14192, 1), + (773, 'Death\'s Effigy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13133, 1), + (774, 'Empowered Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 14690, 1), + (775, 'Unknown AA 16342', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16342, 1), + (776, 'Arcane Overkill', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 5295, 1), + (777, 'Funeral Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5298, 1), + (778, 'Protection of the Spirit Wolf', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 5007, 1), + (779, 'Hastened Juggernaut Surge', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13873, 1), + (780, 'Hastened Resilience', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13878, 1), + (781, 'Hastened Blood Pact', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13881, 1), + (782, 'Unknown AA 16317', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16317, 1), + (783, 'Energetic Attunement', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1056, 1), + (784, 'Heart of Flames', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1251, 1), + (785, 'Heart of Vapor', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1252, 1), + (786, 'Heart of Ice', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1253, 1), + (787, 'Heart of Stone', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1254, 1), + (789, 'Stealthy Getaway', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1477, 1), + (790, 'Seized Opportunity', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 878, 1), + (791, 'Veil of Mindshadow', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4931, 1), + (792, 'Army of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1274, 1), + (793, 'Mana Blast', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1639, 1), + (794, 'Mana Blaze', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1640, 1), + (795, 'Innate Corruption Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1662, 1), + (796, 'Hastened Five Point Palm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 13889, 1), + (797, 'Moving Mountains', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 13130, 1), + (798, 'Veturika\'s Perseverance', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14229, 1), + (799, 'Unknown AA 16644', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16644, 1), + (800, 'Vehement Rage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6607, 1), + (801, 'Knee Strike', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6610, 1), + (802, 'Hastened Fortitude Discipline', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6611, 1), + (803, 'Hastened Furious Discipline', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6614, 1), + (804, 'Warlord\'s Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6617, 1), + (805, 'Hastened Speed Focus', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14148, 1), + (806, 'Hastened Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14160, 1), + (807, 'Pressure Points', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14157, 1), + (808, 'Hastened Thunder', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14166, 1), + (809, 'Allegretto of Battle', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14181, 1), + (810, 'Vivace of Conflict', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14186, 1), + (811, 'Unknown AA 16218', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 16218, 1), + (812, 'Unknown AA 16221', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16221, 1), + (813, 'Unknown AA 16222', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16222, 1), + (814, 'Unknown AA 16225', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16225, 1), + (815, 'Unknown AA 16230', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16230, 1), + (816, 'Unknown AA 16235', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16235, 1), + (817, 'Unknown AA 16238', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16238, 1), + (818, 'Unknown AA 16257', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 16257, 1), + (819, 'Unknown AA 16666', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16666, 1), + (820, 'Death\'s Revenge', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6630, 1), + (821, 'Harmshield', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 6635, 1), + (822, 'Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6640, 1), + (823, 'Cascading Theft of Defense', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6641, 1), + (824, 'Hate Step', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6644, 1), + (825, 'Vicious Bite of Chaos', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6645, 1), + (826, 'Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 6646, 1), + (827, 'Unknown AA 16745', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16745, 1), + (828, 'Unknown AA 16260', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 16260, 1), + (829, 'Unknown AA 16263', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16263, 1), + (830, 'Unknown AA 16272', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16272, 1), + (831, 'Unknown AA 16276', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16276, 1), + (832, 'Unknown AA 16287', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16287, 1), + (833, 'Unknown AA 17252', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17252, 1), + (834, 'Unknown AA 16296', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16296, 1), + (835, 'Unknown AA 16300', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16300, 1), + (836, 'Unknown AA 16310', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16310, 1), + (837, 'Unknown AA 16330', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16330, 1), + (838, 'Unknown AA 16163', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16163, 1), + (839, 'Unknown AA 16360', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 16360, 1), + (840, 'Unknown AA 16363', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16363, 1), + (841, 'Sleight of Hand', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6663, 1), + (842, 'Enduring Vision', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6666, 1), + (843, 'Expertise of Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6668, 1), + (844, 'Cunning Disguise: Human', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6671, 1), + (845, 'Cunning Disguise: Half-Elf', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6672, 1), + (846, 'Cunning Disguise: Barbarian', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6673, 1), + (847, 'Cunning Disguise: Erudite', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6674, 1), + (848, 'Cunning Disguise: Troll', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6675, 1), + (849, 'Cunning Disguise: Goblin', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6676, 1), + (850, 'Unknown AA 16366', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16366, 1), + (851, 'Unknown AA 16369', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16369, 1), + (852, 'Unknown AA 16370', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16370, 1), + (853, 'Unknown AA 16371', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16371, 1), + (854, 'Unknown AA 17256', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17256, 1), + (856, 'Tigir\'s Insect Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6691, 1), + (857, 'Dampen Resistance', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6692, 1), + (858, 'Hastened Dampen Resistance', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6697, 1), + (859, 'Spirit Walk', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6702, 1), + (860, 'Hastened Virulent Paralysis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6703, 1), + (861, 'Languid Bite', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6706, 1), + (862, 'Quickened Blood of Nadox', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6709, 1), + (863, 'Hastened Spirit Call', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6712, 1), + (864, 'Hastened Thousand Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14169, 1), + (865, 'Unknown AA 17257', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17257, 1), + (866, 'Extended Dance of Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14179, 1), + (867, 'Extended Thousand Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14180, 1), + (868, 'Unknown AA 16380', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16380, 1), + (869, 'Unknown AA 16386', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 16386, 1), + (870, 'Harmonious Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6750, 1), + (871, 'Hastened Weapon Shield', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6751, 1), + (872, 'Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6754, 1), + (873, 'Group Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6755, 1), + (874, 'Pack Hunt', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6758, 1), + (875, 'Keen Blade', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6761, 1), + (876, 'Outrider\'s Evasion', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6764, 1), + (877, 'Ranged Finesse', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6765, 1), + (878, 'Bow Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1196, 1), + (879, 'Unknown AA 17258', -1, 1040, 65535, 127, 131071, 0, 2, 0, 0, 17258, 1), + (880, 'Unknown AA 16392', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16392, 1), + (881, 'Unknown AA 16395', -1, 10248, 65535, 127, 131071, 0, 3, 0, 0, 16395, 1), + (882, 'Unknown AA 16396', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16396, 1), + (883, 'Unknown AA 16536', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 16536, 1), + (884, 'Unknown AA 17209', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17209, 1), + (885, 'Unknown AA 17212', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 17212, 1), + (886, 'Unknown AA 17218', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17218, 1), + (888, 'Unknown AA 17555', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17555, 1), + (889, 'Unknown AA 17229', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17229, 1), + (890, 'Unknown AA 17235', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17235, 1), + (891, 'Healing Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6791, 1), + (892, 'Halt the Dead', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6794, 1), + (894, 'Unknown AA 17242', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17242, 1), + (895, 'Unknown AA 17245', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17245, 1), + (896, 'Unknown AA 17249', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17249, 1), + (897, 'Unknown AA 17199', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 17199, 1), + (898, 'Unknown AA 17267', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17267, 1), + (899, 'Unknown AA 17273', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17273, 1), + (900, 'Rise of Bones', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6815, 1), + (901, 'Whisperwind', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6818, 1), + (902, 'Hastened Blood Magic', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6819, 1), + (903, 'Overpower Undead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6822, 1), + (904, 'Hastened Swarm of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6823, 1), + (905, 'Gift of the Grave', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6828, 1), + (906, 'Hastened Gut Punch', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10522, 1), + (907, 'Hastened First Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10527, 1), + (908, 'Hastened Second Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10532, 1), + (909, 'Hastened Third Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10537, 1), + (910, 'Unknown AA 17280', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17280, 1), + (911, 'Warlord\'s Resurgence', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10545, 1), + (912, 'Warlord\'s Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10546, 1), + (914, 'Improved Shield Specialist', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10548, 1), + (915, 'Unknown AA 17281', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17281, 1), + (917, 'Hastened Grappling Strike', -1, 65, 65535, 127, 131071, 0, 3, 0, 0, 10588, 1), + (918, 'Furious Refrain', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10627, 1), + (919, 'Unknown AA 17554', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17554, 1), + (920, 'Valorous Rage', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10711, 1), + (921, 'Hastened Group Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10714, 1), + (922, 'Hastened Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10719, 1), + (923, 'Hastened Protection of the Spirit Wolf', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10722, 1), + (924, 'Hastened Imbued Ferocity', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10727, 1), + (925, 'Hastened Harmonious Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10730, 1), + (926, 'Hastened Entrap', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10733, 1), + (927, 'Poison Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10736, 1), + (928, 'Merciless Blade', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14026, 1), + (929, 'Combatant\'s Pact', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14029, 1), + (930, 'Warlord\'s Resolve', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14032, 1), + (931, 'Hastened Hate\'s Attraction', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 12582, 1), + (932, 'Unknown AA 17289', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 17289, 1), + (933, 'Improved Death Peace', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 12635, 1), + (934, 'Unknown AA 17307', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 17307, 1), + (935, 'Blessing of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10789, 1), + (936, 'Extended Wild Growth', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 10792, 1), + (937, 'Unknown AA 17317', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17317, 1), + (938, 'Eyes Wide Open', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 12636, 1), + (939, 'Communion of the Cheetah', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12638, 1), + (940, 'Hastened Song of Stone', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6870, 1), + (941, 'Flurry', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6873, 1), + (942, 'Destructive Cascade', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6876, 1), + (943, 'Total Domination', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6879, 1), + (944, 'Enhanced Forgetfulness', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6882, 1), + (945, 'Infusion of Thunder', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10346, 1), + (946, 'Hastened Warlord\'s Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14037, 1), + (947, 'Hastened Warlord\'s Tenacity', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14040, 1), + (948, 'Unknown AA 17328', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17328, 1), + (949, 'Unknown AA 17329', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17329, 1), + (950, 'Unknown AA 17336', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17336, 1), + (951, 'Unknown AA 17339', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 17339, 1), + (952, 'Unknown AA 17342', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17342, 1), + (953, 'Unknown AA 17344', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17344, 1), + (954, 'Unknown AA 17347', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17347, 1), + (955, 'Unknown AA 17357', -1, 514, 65535, 127, 131071, 0, 2, 0, 0, 17357, 1), + (956, 'Unknown AA 17361', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 17361, 1), + (957, 'Unknown AA 17364', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17364, 1), + (958, 'Unknown AA 17370', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17370, 1), + (959, 'Unknown AA 17372', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17372, 1), + (960, 'Stomping Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6930, 1), + (961, 'Juggernaut Surge', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6931, 1), + (962, 'Distraction Attack', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6932, 1), + (963, 'Hastened Savage Spirit', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6935, 1), + (964, 'Dying Blow', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6938, 1), + (965, 'Hastened Projection of Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10519, 1), + (966, 'Unknown AA 17373', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17373, 1), + (967, 'Blade Guardian', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13444, 1), + (968, 'Unknown AA 17375', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17375, 1), + (969, 'Unknown AA 17378', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 17378, 1), + (970, 'Unknown AA 17378', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 17379, 1), + (971, 'Unknown AA 17378', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 17380, 1), + (972, 'Unknown AA 17384', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17384, 1), + (974, 'Unknown AA 17409', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 17409, 1), + (975, 'Unknown AA 17414', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 17414, 1), + (976, 'Unknown AA 17418', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17418, 1), + (977, 'Unknown AA 17558', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17558, 1), + (978, 'Unknown AA 17428', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17428, 1), + (979, 'Unknown AA 17436', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17436, 1), + (980, 'Natural Invisibility', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6970, 1), + (981, 'Attack of the Warders', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6971, 1), + (982, 'Hastened Feral Attacks', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6974, 1), + (983, 'Hastened Focused Paragon', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6977, 1), + (984, 'Hastened Paragon', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6980, 1), + (985, 'Group Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6983, 1), + (986, 'Bite of the Asp', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6984, 1), + (987, 'Raven\'s Claw', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6985, 1), + (988, 'Gorilla Smash', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6986, 1), + (989, 'Stonefoot', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10340, 1), + (990, 'Hastened Stunning Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10343, 1), + (991, 'Quickened Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10470, 1), + (992, 'Tranquil Blessings', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 3676, 1), + (993, 'Righteous Zeal', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6082, 1), + (994, 'Hastened Divine Retribution', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6088, 1), + (995, 'Intrinsic Efficiency', -1, 15386, 65535, 127, 131071, 0, 2, 0, 0, 6112, 1), + (996, 'Powerful Elixirs', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6113, 1), + (997, 'Celestial Rapidity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6534, 1), + (998, 'Hastened Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 2400, 1), + (999, 'Improved Burst of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7765, 1), + (1000, 'Unknown AA 17439', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17439, 1), + (1001, 'Unknown AA 17445', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17445, 1), + (1002, 'Unknown AA 17448', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17448, 1), + (1003, 'Unknown AA 10478', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10478, 1), + (1004, 'Unknown AA 17492', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 17492, 1), + (1005, 'Unknown AA 17495', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 17495, 1), + (1006, 'Unknown AA 17515', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 17515, 1), + (1007, 'Unknown AA 17517', -1, 5120, 65535, 127, 131071, 0, 3, 0, 0, 17517, 1), + (1008, 'Unknown AA 17522', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17522, 1), + (1009, 'Unknown AA 17533', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17533, 1), + (1011, 'Neshika\'s Blink', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7869, 1), + (1012, 'Five Point Palm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7875, 1), + (1013, 'War Cry of the Braxi', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13872, 1), + (1014, 'Unknown AA 17538', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17538, 1), + (1015, 'Unknown AA 17547', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17547, 1), + (1016, 'Unknown AA 17549', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17549, 1), + (1017, 'Unknown AA 17238', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17238, 1), + (1018, 'Unknown AA 17553', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17553, 1), + (1019, 'Unknown AA 17248', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17248, 1), + (1020, 'Hastened Companion\'s Blessing', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 12478, 1), + (1021, 'Unknown AA 17215', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17215, 1), + (1022, 'Destructive Fury', -1, 16540, 65535, 127, 131071, 0, 2, 0, 0, 6636, 1), + (1023, 'Restoration of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14010, 1), + (1024, 'Hastened Leap of Faith', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14085, 1), + (1025, 'Hastened Beacon of the Righteous', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14011, 1), + (1026, 'Unknown AA 17561', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17561, 1), + (1027, 'Unknown AA 17564', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17564, 1), + (1028, 'Unknown AA 17567', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17567, 1), + (1029, 'Unknown AA 17570', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17570, 1), + (1030, 'Unknown AA 17573', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17573, 1), + (1031, 'Unknown AA 17576', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17576, 1), + (1032, 'Unknown AA 17579', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17579, 1), + (1033, 'Unknown AA 17582', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17582, 1), + (1034, 'Unknown AA 17585', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17585, 1), + (1035, 'Unknown AA 17588', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17588, 1), + (1036, 'Unknown AA 17591', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17591, 1), + (1037, 'Unknown AA 17594', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17594, 1), + (1038, 'Unknown AA 17597', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17597, 1), + (1039, 'Unknown AA 17600', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17600, 1), + (1040, 'Theft of Essence', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7900, 1), + (1041, 'Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 7903, 1), + (1042, 'Unknown AA 17603', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17603, 1), + (1043, 'Unknown AA 17606', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17606, 1), + (1044, 'Unknown AA 17609', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17609, 1), + (1045, 'Unknown AA 17612', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17612, 1), + (1046, 'Unknown AA 17615', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17615, 1), + (1047, 'Unknown AA 17618', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17618, 1), + (1048, 'Unknown AA 17621', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17621, 1), + (1049, 'Unknown AA 17624', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17624, 1), + (1050, 'Unknown AA 17627', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17627, 1), + (1051, 'Unknown AA 17630', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17630, 1), + (1052, 'Unknown AA 17633', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17633, 1), + (1053, 'Unknown AA 10481', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10481, 1), + (1054, 'Unknown AA 17639', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17639, 1), + (1060, 'Hastened Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7940, 1), + (1061, 'Cascading Divine Aura', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7943, 1), + (1062, 'Group Purify Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7944, 1), + (1063, 'Hastened Renewal', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7945, 1), + (1064, 'Sanctified Blessing', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7948, 1), + (1065, 'Focused Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7951, 1), + (1090, 'Mastery of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7980, 1), + (1091, 'Hastened Nature\'s Guardian', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7983, 1), + (1092, 'Spirit of the Black Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7986, 1), + (1093, 'Hastened Lycan Soul', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7989, 1), + (1113, 'Hastened Mass Group Buff', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 5010, 1), + (1115, 'Mystical Shield', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 5045, 1), + (1120, 'Self Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8030, 1), + (1121, 'Hastened Veil of Mindshadow', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8031, 1), + (1122, 'Phantasmal Opponent', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8034, 1), + (1123, 'Hastened Edict of Command', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8035, 1), + (1124, 'Fog of Memories', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8038, 1), + (1125, 'Bite of Tashani', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8039, 1), + (1150, 'Fury of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8060, 1), + (1151, 'Fury of Eci', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8063, 1), + (1152, 'Fury of Ro', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8066, 1), + (1153, 'Fortified Entanglement', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8069, 1), + (1154, 'Force of Will', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8072, 1), + (1155, 'Atol\'s Shackles', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8075, 1), + (1156, 'Hastened Manaburn', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8076, 1), + (1157, 'Hastened Call of Xuzl', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8082, 1), + (1158, 'Divine Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1667, 1), + (1159, 'Hastened Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 11014, 1), + (1169, 'Unknown AA 16336', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16336, 1), + (1170, 'Unknown AA 16339', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16339, 1), + (1171, 'Hastened Counterattack Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15502, 1), + (1173, 'Hastened Onslaught', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15509, 1), + (1174, 'Mrylokar\'s Rigor', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15512, 1), + (1175, 'Absorbing Agent', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15515, 1), + (1176, 'Improved Requiem of Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15516, 1), + (1177, 'Quickened Requiem of Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15517, 1), + (1178, 'Silent Displacement', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15521, 1), + (1200, 'Companion\'s Alacrity', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8190, 1), + (1201, 'Improved Intimidation', -1, 41408, 65535, 127, 131071, 0, 2, 0, 1, 8193, 1), + (1202, 'Perfected Levitation', -1, 31272, 65535, 127, 131071, 0, 2, 0, 0, 8194, 1), + (1203, 'Hastened Fortify Companion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8195, 1), + (1204, 'Empowered Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8198, 1), + (1205, 'Companion\'s Fury', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8201, 1), + (1206, 'Quickened Radiant Cure', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 8204, 1), + (1207, 'Quickened Radiant Cure', -1, 4, 65535, 127, 131071, 0, 2, 0, 0, 8207, 1), + (1208, 'Mental Stamina', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 8210, 1), + (1209, 'Hardy Endurance', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8215, 1), + (1210, 'Group Perfected Invisibility', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 8220, 1), + (1211, 'Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 8221, 1), + (1212, 'Group Perfected Invisibility to Undead', -1, 1046, 65535, 127, 131071, 0, 2, 0, 0, 8222, 1), + (1214, 'Cascade of Life', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 8224, 1), + (1215, 'Summon Companion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8227, 1), + (1216, 'Mental Fortitude', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8228, 1), + (1217, 'Gate', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 8231, 1), + (1218, 'Extended Ingenuity', -1, 128, 65535, 127, 131071, 0, 2, 0, 0, 8040, 1), + (1219, 'Armor of Wisdom', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 8235, 1), + (1220, 'Armor of Wisdom', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 8240, 1), + (1221, 'Armor of Wisdom', -1, 202, 65535, 127, 131071, 0, 2, 0, 0, 8245, 1), + (1222, 'Armor of Wisdom', -1, 49920, 65535, 127, 131071, 0, 2, 0, 0, 8250, 1), + (1223, 'Armor of Wisdom', -1, 15392, 65535, 127, 131071, 0, 2, 0, 0, 8255, 1), + (1232, 'Way of the Katori', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15429, 1), + (1233, 'Harmony of Battle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15432, 1), + (1234, 'Hastened Ironfist', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15438, 1), + (1235, 'Two-Finger Wasp Touch', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15447, 1), + (1236, 'Thunderfoot', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15444, 1), + (1237, 'Extended Bloodlust', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15414, 1), + (1239, 'Consumption of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15423, 1), + (1240, 'Frenzied Swipes', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15424, 1), + (1242, 'Hastened Synergy', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15450, 1), + (1243, 'Hastened Crane Stance', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15453, 1), + (1244, 'Hastened Eye Gouge', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15456, 1), + (1245, 'Troubadour\'s Slashing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15540, 1), + (1246, 'Troubadour\'s Blunt Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15543, 1), + (1247, 'Troubadour\'s Piercing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15546, 1), + (1248, 'Hastened Lure of the Siren\'s Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15549, 1), + (1249, 'Frenzied Axe of Rallos', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15555, 1), + (1250, 'Juggernaut\'s Mastery of Throwing', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15564, 1), + (1251, 'Furious Rampage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15567, 1), + (1252, 'Battle Stomp', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15569, 1), + (1253, 'Communion of Blood', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15570, 1), + (1254, 'Hastened Dying Grasp', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15571, 1), + (1255, 'Rest the Dead', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 15574, 1), + (1256, 'Extended Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 15579, 1), + (1257, 'Hand of Death', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15582, 1), + (1258, 'Quickened Levant', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15591, 1), + (1259, 'Cascade of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15594, 1), + (1261, 'Hastened Fury of the Gods', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15598, 1), + (1262, 'Lower Element', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15601, 1), + (1263, 'Destructive Adept', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15602, 1), + (1264, 'Arcane Fusion', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15609, 1), + (1265, 'Arcane Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15611, 1), + (1266, 'Force of Flame', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15612, 1), + (1267, 'Force of Ice', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15615, 1), + (1269, 'Sha\'s Reprisal', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15425, 1), + (1270, 'Crippling Spirit', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15377, 1), + (1271, 'Quick Damage', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15622, 1), + (1272, 'Assassin\'s Wrath', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15625, 1), + (1273, 'Hastened Swiftblade', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15634, 1), + (1274, 'Improved Explosion of Spite', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15639, 1), + (1275, 'Improved Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15640, 1), + (1277, 'Soul Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15642, 1), + (1278, 'Soul Flay', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15643, 1), + (1279, 'Ragged Bite of Agony', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15646, 1), + (1281, 'Everburn', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15648, 1), + (1282, 'Marr\'s Gift', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15619, 1), + (1300, 'Fundament of Intellect', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9100, 1), + (1301, 'Fundament of Intellect', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9109, 1), + (1302, 'Fundament of Intellect', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9118, 1), + (1303, 'Fundament of Intellect', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9127, 1), + (1304, 'Fundament of Wisdom', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9136, 1), + (1305, 'Fundament of Wisdom', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9145, 1), + (1306, 'Fundament of Wisdom', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9154, 1), + (1307, 'Fundament of Power', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9163, 1), + (1308, 'Fundament of Power', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9172, 1), + (1309, 'Fundament of Power', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9181, 1), + (1310, 'Fundament of Power', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9190, 1), + (1311, 'Fundament of Power', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9199, 1), + (1312, 'Fundament of Combat', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9208, 1), + (1313, 'Fundament of Combat', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9217, 1), + (1314, 'Fundament of Combat', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9226, 1), + (1315, 'Fundament of Combat', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9235, 1), + (1350, 'Fundament: First Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9300, 1), + (1351, 'Fundament: Second Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9303, 1), + (1352, 'Fundament: Third Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9306, 1), + (1360, 'Fundament: First Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9309, 1), + (1361, 'Fundament: Second Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9312, 1), + (1362, 'Fundament: Third Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9315, 1), + (1370, 'Fundament: First Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9318, 1), + (1371, 'Fundament: Second Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9321, 1), + (1372, 'Fundament: Third Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9324, 1), + (1380, 'Fundament: First Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9327, 1), + (1381, 'Fundament: Second Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9330, 1), + (1382, 'Fundament: Third Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9333, 1), + (1390, 'Fundament: First Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9336, 1), + (1391, 'Fundament: Second Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9339, 1), + (1392, 'Fundament: Third Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9342, 1), + (1400, 'Fundament: First Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9345, 1), + (1401, 'Fundament: Second Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9348, 1), + (1402, 'Fundament: Third Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9351, 1), + (1403, 'Sturdy Companion', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 9503, 1), + (1404, 'Extended Swarm', -1, 32306, 65535, 127, 131071, 0, 3, 0, 0, 9506, 1), + (1405, 'Twincast', -1, 15906, 65535, 127, 131071, 0, 3, 0, 0, 9509, 1), + (1406, 'Staff Block', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9512, 1), + (1410, 'Fundament: First Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9354, 1), + (1411, 'Fundament: Second Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9357, 1), + (1412, 'Fundament: Third Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9360, 1), + (1420, 'Fundament: First Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9363, 1), + (1421, 'Fundament: Second Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9366, 1), + (1422, 'Fundament: Third Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9369, 1), + (1430, 'Fundament: First Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9372, 1), + (1431, 'Fundament: Second Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9375, 1), + (1432, 'Fundament: Third Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9378, 1), + (1433, 'Extended Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8232, 1), + (1440, 'Fundament: First Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9381, 1), + (1441, 'Fundament: Second Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9384, 1), + (1442, 'Fundament: Third Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9387, 1), + (1450, 'Fundament: First Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9390, 1), + (1451, 'Fundament: Second Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9393, 1), + (1452, 'Fundament: Third Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9396, 1), + (1460, 'Fundament: First Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9399, 1), + (1461, 'Fundament: Second Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9402, 1), + (1462, 'Fundament: Third Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9405, 1), + (1470, 'Fundament: First Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9408, 1), + (1471, 'Fundament: Second Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9411, 1), + (1472, 'Fundament: Third Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9414, 1), + (1480, 'Fundament: First Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9417, 1), + (1481, 'Fundament: Second Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9420, 1), + (1482, 'Fundament: Third Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9423, 1), + (1490, 'Fundament: First Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9426, 1), + (1491, 'Fundament: Second Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9429, 1), + (1492, 'Fundament: Third Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9432, 1), + (1500, 'Fundament: First Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9435, 1), + (1501, 'Fundament: Second Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9438, 1), + (1502, 'Fundament: Third Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9441, 1), + (1503, 'Hallowed Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13673, 1), + (1504, 'Wicked Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13674, 1), + (1505, 'Unknown AA 16103', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16103, 1), + (1580, 'Divine Companion Aura', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 5809, 1), + (1662, 'Spell Casting Mastery', -1, 16412, 65535, 127, 131071, 0, 2, 0, 0, 1216, 1), + (1663, 'Gift of Mana', -1, 16412, 65535, 127, 131071, 0, 2, 0, 0, 1219, 1), + (1664, 'Twinproc', -1, 50175, 65535, 127, 131071, 0, 3, 0, 0, 12416, 1), + (1665, 'Tactical Mastery', -1, 16596, 65535, 127, 131071, 0, 3, 0, 0, 12419, 1), + (1666, 'Group Perfected Levitation', -1, 31272, 65535, 127, 131071, 0, 2, 0, 0, 12422, 1), + (1667, 'Quickened Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 2, 0, 0, 6026, 1), + (1668, 'Acute Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 8260, 1), + (1669, 'Flurry', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 5806, 1), + (1680, 'Hastened Flash of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13905, 1), + (1681, 'Hastened Bazu Roar', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13908, 1), + (1682, 'Hastened Scowl', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13911, 1), + (1683, 'Hastened Mark of the Mage Hunter', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13917, 1), + (1684, 'Knowledge of Alaran Culture', 2, 65535, 65535, 127, 131071, 0, 4, 0, 0, 14017, 1), + (1685, 'Knowledge of Alaran Culture - Advanced', 2, 65535, 65535, 127, 131071, 0, 4, 0, 0, 14018, 1), + (1686, 'Brace For Impact', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14019, 1), + (1687, 'Summon Tome of the Hero\'s Journey', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 14371, 1), + (1800, 'Enchant Planar Alloy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 14373, 1), + (1801, 'Mass Enchant Planar Alloy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 14374, 1), + (2000, 'Armor of Experience', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 4700, 1), + (2001, 'Sneering Grin', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15096, 1), + (2002, 'Warlord\'s Grasp', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15099, 1), + (2003, 'Hastened Press the Attack', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15100, 1), + (2004, 'Hastened Rage of Rallos Zek', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15105, 1), + (2005, 'Hastened Unbroken Attention', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15108, 1), + (2006, 'Extended Resplendant Glory', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15113, 1), + (2007, 'Wars Sheol\'s Heroic Blade', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15119, 1), + (2008, 'Hastened Vehement Rage', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15120, 1), + (2009, 'Hastened Barbed Tongue', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15123, 1), + (2010, 'Hastened Shield Topple', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15126, 1), + (2011, 'Imperator\'s Command', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15129, 1), + (2012, 'Imperator\'s Charge', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15130, 1), + (2013, 'Imperator\'s Precision', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15131, 1), + (2014, 'Hastened Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15132, 1), + (2015, 'Extended Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15135, 1), + (2016, 'Heroic Leap', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15136, 1), + (2018, 'Helix of the Undying', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 15146, 1), + (2019, 'Group Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15147, 1), + (2020, 'Quickened Demand For Honor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15150, 1), + (2021, 'Extended Sanctification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15153, 1), + (2022, 'Extended Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15154, 1), + (2023, 'Extended Preservation of Marr', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15155, 1), + (2024, 'Extended Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15158, 1), + (2025, 'Extended Blessing of the Faithful', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15159, 1), + (2026, 'Hastened Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15162, 1), + (2028, 'Hastened Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15168, 1), + (2031, 'Purity of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15177, 1), + (2032, 'Quickened Scourge Skin', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15179, 1), + (2034, 'Gift of the Quick Spear', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15193, 1), + (2035, 'Extended Provocation for Power', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15194, 1), + (2036, 'Quickened Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15253, 1), + (2037, 'Chameleon\'s Gift', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15304, 1), + (2040, 'Hastened Enraging Kicks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15283, 1), + (2041, 'Close Combat Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15288, 1), + (2042, 'Quickened Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15295, 1), + (2045, 'Shield of Reverence', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15338, 1), + (2046, 'Extended Healing Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15342, 1), + (2047, 'Call of the Herald', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15343, 1), + (2048, 'Covenant of Spirit', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 15356, 1), + (2049, 'Talisman of Celerity', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15357, 1), + (2050, 'Extended Spiritual Blessing', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15358, 1), + (2051, 'Rejuvenation of Spirit', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 15362, 1), + (2053, 'Hastened Turgur\'s Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15371, 1), + (2054, 'Shielding of Spirits', -1, 16930, 65535, 127, 131071, 0, 2, 0, 0, 15374, 1), + (2055, 'Hastened Lunar Healing', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15383, 1), + (2056, 'Quickened Blessing of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15389, 1), + (2057, 'Hastened Wall of Wind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15403, 1), + (2059, 'Quickened Focused Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15406, 1), + (2060, 'Elemental Ward', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15200, 1), + (2061, 'Cloak of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15203, 1), + (2062, 'Hastened Elemental Union', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15204, 1), + (2063, 'Hastened Virulent Talon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15207, 1), + (2064, 'Wind of Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 15210, 1), + (2065, 'Mana Reserve', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15213, 1), + (2066, 'Second Wind Ward', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15214, 1), + (2076, 'Steel Vengeance', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15217, 1), + (2077, 'Extended Vapor Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15220, 1), + (2078, 'Extended Stone Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15223, 1), + (2079, 'Extended Fire Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15226, 1), + (2080, 'Extended Ice Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15229, 1), + (2081, 'Flames of Power', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15232, 1), + (2200, 'Rune of Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15475, 1), + (2201, 'Hastened Glyph Spray', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15478, 1), + (2202, 'Illusions of Grandeur', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15481, 1), + (2203, 'Illusory Ally', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15482, 1), + (2204, 'Gracious Gift of Mana', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15485, 1), + (2205, 'Chromatic Haze', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15486, 1), + (2206, 'Blanket of Forgetfulness', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15489, 1), + (2207, 'Ethereal Manipulation', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15490, 1), + (2208, 'Quick Mezz', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15493, 1), + (2209, 'Reactive Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15496, 1), + (2234, 'Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10368, 1), + (2235, 'Imbued Ferocity', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10387, 1), + (2709, 'Perfected Dead Man Floating', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13692, 1), + (2899, 'Levant', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10700, 1), + (3000, 'Auroria Mastery', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6987, 1), + (3202, 'Pet Discipline', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 7733, 1), + (3203, 'Enchant Palladium Trio', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7736, 1), + (3204, 'Mass Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7737, 1), + (3205, 'Greater Mass Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7738, 1), + (3206, 'Enchant Dwerium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7732, 1), + (3207, 'Mass Enchant Dwerium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7734, 1), + (3208, 'Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7735, 1), + (3209, 'Enchant Temporite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7739, 1), + (3210, 'Mass Enchant Temporite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7740, 1), + (3211, 'Nature\'s Reprieve', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10388, 1), + (3212, 'Hastened Divine Intervention', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10358, 1), + (3213, 'Projection of Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10351, 1), + (3214, 'Improved Atone', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10364, 1), + (3215, 'Projection of Doom', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10352, 1), + (3216, 'Projection of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10353, 1), + (3217, 'Hastened Jolting Kicks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 12500, 1), + (3218, 'Enchant Cosgrite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7741, 1), + (3219, 'Mass Enchant Cosgrite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7742, 1), + (3500, 'Blessing of Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10355, 1), + (3506, 'Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5717, 1), + (3511, 'Punch Mastery', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 6020, 1), + (3512, 'Companion\'s Durability', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6051, 1), + (3513, 'Rake\'s Deadly Aim', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6322, 1), + (3514, 'Rogue\'s Fury', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6325, 1), + (3515, 'Envenomed Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6328, 1), + (3516, 'Companion of Necessity', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 6333, 1), + (3517, 'Rake\'s Powerful Aim', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6334, 1), + (3518, 'Hastened Cacophony', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6337, 1), + (3519, 'Hastened Funeral Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6340, 1), + (3520, 'Master\'s Hastened Combination', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 6343, 1), + (3521, 'Hastened Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 6346, 1), + (3522, 'Hastened Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 6349, 1), + (3525, 'Precise Blow', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 5776, 1), + (3550, 'Beguiler\'s Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5849, 1), + (3551, 'Beguiler\'s Directed Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5870, 1), + (3600, 'Rapid Defiance', 1, 1, 65535, 127, 131071, 0, 3, 0, 1, 6136, 1), + (3646, 'Blast of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6135, 1), + (3676, 'Gift of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10354, 1), + (3701, 'Dirge of the Sleepwalker', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6200, 1), + (3702, 'Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6201, 1), + (3703, 'Steady Hands ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6202, 1), + (3704, 'Selo\'s Sonata', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6205, 1), + (3705, 'Companion\'s Blessing ', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6206, 1), + (3706, 'Hastened Bestial Alignment ', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6209, 1), + (3707, 'Fortify Companion ', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6212, 1), + (3708, 'Burst of Power ', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 6215, 1), + (3709, 'Pact of the Wurine', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6218, 1), + (3710, 'Reckless Abandon ', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6219, 1), + (3711, 'Gift of Resurrection', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6222, 1), + (3713, 'Hastened Call of the Wild ', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 6228, 1), + (3714, 'Protection of Direwood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6232, 1), + (3716, 'Clinging Root ', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6236, 1), + (3718, 'Critical Affliction', -1, 8194, 65535, 127, 131071, 0, 2, 0, 0, 6240, 1), + (3720, 'Mana Overburn ', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6249, 1), + (3724, 'Knight\'s Return Strike ', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 6266, 1), + (3725, 'Hunter\'s Return Kick ', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6269, 1), + (3726, 'Hastened Ligament Slice ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6272, 1), + (3727, 'Knave\'s Return Strike', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6275, 1), + (3728, 'Storm Strike', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6278, 1), + (3729, 'Turgur\'s Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6281, 1), + (3730, 'Silent Presence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6282, 1), + (3731, 'Infused by Rage ', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6283, 1), + (3732, 'Gut Punch', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6286, 1), + (3733, 'Warlord\'s Return Kick', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6287, 1), + (3734, 'Arcomancy ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6290, 1), + (3800, 'Blessing of Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6299, 1), + (3801, 'General Sturdiness', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 6119, 1), + (3802, 'Shield Block', -1, 392, 65535, 127, 131071, 0, 2, 0, 0, 6124, 1), + (3803, 'Hastened Trueshot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6355, 1), + (3804, 'Outrider\'s Accuracy', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6370, 1), + (3805, 'Hastened Mend', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 4801, 1), + (3812, 'Perfected Invisibility', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 7069, 1), + (3813, 'Spell Casting Reinforcement', -1, 7168, 65535, 127, 131071, 0, 2, 0, 0, 6257, 1), + (3815, 'Destructive Cascade', -1, 9776, 65535, 127, 131071, 0, 3, 0, 0, 6375, 1), + (3816, 'Companion\'s Relocation', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6379, 1), + (3817, 'Focused Paragon of Spirits', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6380, 1), + (3818, 'Companion\'s Agility', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6383, 1), + (3819, 'Maestro\'s Concentration', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6386, 1), + (3820, 'Blessing of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6395, 1), + (3821, 'Quickened Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6503, 1), + (3822, 'Chattering Bones', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6508, 1), + (3823, 'Warlord\'s Deadly Aim', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6511, 1), + (3824, 'Quickened Call of the Wild', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 6514, 1), + (3826, 'Force of Disruption', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5984, 1), + (3830, 'Hastened Divine Avatar', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7100, 1), + (3831, 'Hastened Purification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 7103, 1), + (3832, 'Beastlords Feral Kick', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 7106, 1), + (3833, 'Burst of Power ', -1, 32841, 65535, 127, 131071, 0, 2, 0, 0, 6409, 1), + (3834, 'Burst of Power ', -1, 256, 65535, 127, 131071, 0, 2, 0, 0, 6419, 1), + (3835, 'Shield Block', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 6428, 1), + (3836, 'Holy Root', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6436, 1), + (3837, 'Burst of Power ', -1, 16512, 65535, 127, 131071, 0, 2, 0, 0, 6060, 1), + (3838, 'Quickened Suspend Minion', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6445, 1), + (3839, 'Quickened Summon Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6452, 1), + (3840, 'Recourse of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6601, 1), + (3841, 'Call Hither', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 6455, 1), + (3842, 'Fortified Survival', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6458, 1), + (3843, 'Fortified Intervention', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6461, 1), + (3865, 'Planar Durability', -1, 72, 65535, 127, 131071, 0, 3, 0, 0, 6422, 1), + (3890, 'Hastened Force of Will', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 7822, 1), + (3891, 'Hastened Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7832, 1), + (3892, 'Hastened Rumbling Servant', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7828, 1), + (3893, 'Extended Rumbling Servant', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7827, 1), + (3899, 'Furious Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6499, 1), + (4001, 'Undaunted Fury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 7407, 1), + (4002, 'Frenzied Volley', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 7818, 1), + (4200, 'Hastened Forceful Rejuvenation', -1, 32318, 65535, 127, 131071, 0, 2, 0, 0, 12475, 1), + (4666, 'Shield Specialist', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 4666, 1), + (5000, 'Glyph of Courage', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7000, 1), + (5002, 'Glyph of Stored Life', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7002, 1), + (5003, 'Glyph of Frantic Infusion', 7, 30224, 65535, 127, 131071, 0, 4, 1, 0, 7003, 1), + (5004, 'Glyph of Angry Thoughts', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7004, 1), + (5005, 'Foraging', 8, 65535, 65535, 127, 131071, 0, 1, 0, 0, 7062, 1), + (6000, 'Harm Touch', 9, 16, 65535, 127, 131071, 0, 3, 0, 0, 7800, 1), + (6001, 'Lay on Hands', 9, 4, 65535, 127, 131071, 0, 3, 0, 0, 7850, 1), + (6002, 'Hunter\'s Attack Power', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6546, 1), + (6106, 'Sustained Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6106, 1), + (6302, 'Hastened Reckless Abandon', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6302, 1), + (6362, 'Hastened Recklessness', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6362, 1), + (6478, 'Hastened Blessing of Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6478, 1), + (6481, 'Hastened Divine Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6481, 1), + (6488, 'Flurry of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6488, 1), + (6489, 'Hastened Holyforge', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6489, 1), + (6492, 'Inquisitor\'s Judgement', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6492, 1), + (6988, 'Extended Group Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6988, 1), + (7000, 'Voice of Thule', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6639, 1), + (7001, 'Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7872, 1), + (7002, 'Summon Remains', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9500, 1), + (7003, 'Forceful Rejuvenation', -1, 32318, 65535, 127, 131071, 0, 2, 0, 0, 9502, 1), + (7007, 'Summon Remains', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9501, 1), + (7009, 'Teleport Bind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1419, 1), + (7016, 'Glyph of the Master', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7016, 1), + (7017, 'Glyph of Lost Secrets', 7, 32318, 65535, 127, 131071, 0, 4, 1, 0, 7017, 1), + (7018, 'Glyph of Genari Might', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7018, 1), + (7019, 'Glyph of the Cataclysm', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7019, 1), + (7025, 'Group Shrink', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 7669, 1), + (7033, 'Lasting Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 7033, 1), + (7036, 'Hastened Blast of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 7036, 1), + (7050, 'Call of the Hero', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1017, 1), + (7060, 'Precision of Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4809, 1), + (7070, 'Hastened Distraction Attack', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6941, 1), + (7105, 'Deathly Pact', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 976, 1), + (7106, 'Planar Durability', -1, 16768, 65535, 127, 131071, 0, 3, 0, 0, 6467, 1), + (7107, 'Hastened Getaway', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 7005, 1), + (7108, 'Divine Aura', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 977, 1), + (7109, 'Hastened Wrath of the Wild', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7664, 1), + (7689, 'Burst of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7689, 1), + (7690, 'Spirit Mastery', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7690, 1), + (7695, 'Quickened Blood of Avoling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 7695, 1), + (7698, 'Dead Man Floating', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7698, 1), + (7699, 'Dread Incarnate', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7699, 1), + (7700, 'Flurry', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 7700, 1), + (7703, 'Death Bloom', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7703, 1), + (7712, 'Disruptive Persecution', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 7712, 1), + (7715, 'Hastened Whisperwind', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7715, 1), + (7743, 'Hastened Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7743, 1), + (7746, 'Hastened Flusterbolt', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7746, 1), + (7747, 'Volatile Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7747, 1), + (7748, 'Pathfinder\'s Grace', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7748, 1), + (7751, 'Hastened Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7751, 1), + (7754, 'Steed of Souls', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7754, 1), + (7755, 'Scourge Skin', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7755, 1), + (7756, 'Death\'s Effigy', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7756, 1), + (7757, 'Hastened Visage of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7757, 1), + (7760, 'Hastened Hate Step', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7760, 1), + (7801, 'Songwriting', 6, 128, 65535, 127, 131071, 0, 3, 0, 0, 9001, 1), + (7809, 'Hybrid Research', 6, 16412, 65535, 127, 131071, 0, 2, 0, 0, 9011, 1), + (7819, 'Written Prayer', 6, 546, 65535, 127, 131071, 0, 2, 0, 0, 9021, 1), + (7925, 'Sionachie\'s Crescendo', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1018, 1), + (8081, 'Summon Resupply Agent', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9000, 1), + (8130, 'Summon Clockwork Banker', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9031, 1), + (8200, 'Hastened Dirge of the Sleepwalker', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10329, 1), + (8201, 'Vainglorious Shout ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10330, 1), + (8202, 'Lyre Leap ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10331, 1), + (8203, 'Domination Mastery ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10332, 1), + (8204, 'Lyrical Prankster', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10333, 1), + (8205, 'Selo\'s Kick ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10336, 1), + (8261, 'A Tune Stuck In Your Head', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10339, 1), + (8262, 'The Show Must Go On', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 7010, 1), + (8300, 'Spell Casting Subtlety', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 10370, 1), + (8301, 'Improved Natural Invisibility', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10373, 1), + (8302, 'Protection of the Warder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10374, 1), + (8303, 'Nature\'s Salve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10377, 1), + (8304, 'Focus of Animus', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10380, 1), + (8314, 'Fluid March', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8314, 1), + (8317, 'Hastened Selo\'s Kick', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8317, 1), + (8319, 'Hastened Bellow', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8319, 1), + (8322, 'Belltone Mind', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8322, 1), + (8325, 'Subtle Blows', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 8325, 1), + (8331, 'Enhanced Thief\'s Eyes', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 8331, 1), + (8332, 'Extended Languid Bite', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 8332, 1), + (8335, 'Quickened Malosinete', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 8335, 1), + (8341, 'Drape of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 8341, 1), + (8342, 'Host in the Shell', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 8342, 1), + (8347, 'Hastened Mana Draw', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8347, 1), + (8350, 'Hastened Mezmerization', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8350, 1), + (8400, 'Self Preservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10400, 1), + (8401, 'Hastened Frenzy', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10401, 1), + (8402, 'Extended Havoc', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10404, 1), + (8500, 'Healing Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10450, 1), + (8501, 'Overpowering Strikes', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 10453, 1), + (8502, 'Quickened Blessing of Ressurection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10456, 1), + (8503, 'Hastened Atonement', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10459, 1), + (8504, 'Improved Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10462, 1), + (8505, 'Blessing of Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10463, 1), + (8506, 'Hastened Celestial Hammer', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10464, 1), + (8600, 'Spirit of Eagle', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 10500, 1), + (8601, 'Flight of Eagles', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10501, 1), + (8602, 'Egress', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10502, 1), + (8603, 'Spirits of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10503, 1), + (8604, 'Wall of Wind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10506, 1), + (8605, 'Hastened Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10511, 1), + (8606, 'Hastened Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10514, 1), + (8700, 'Beam of Slumber', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10550, 1), + (8701, 'Phantasmic Reflex', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10551, 1), + (8702, 'Friendly Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10557, 1), + (8703, 'Hastened Self Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10558, 1), + (8704, 'Forceful Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10561, 1), + (8708, 'Hastened Cascading Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6908, 1), + (8800, 'Force of Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10600, 1), + (8801, 'Aspect of Zomm', -1, 6144, 65535, 127, 131071, 0, 3, 0, 0, 10603, 1), + (8802, 'Extended Shared Health', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10610, 1), + (8900, 'Agile Feet', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10650, 1), + (8901, 'Hastened Defensive Poses', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10653, 1), + (8902, 'Extended Impenetrable Discipline', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10656, 1), + (8903, 'Hastened Destructive Force', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10657, 1), + (9001, 'Reluctant Benevolence', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10701, 1), + (9100, 'Bestow Divine Aura', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10752, 1), + (9101, 'Blessing of Purification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10753, 1), + (9102, 'Sense the Dead', -1, 1030, 65535, 127, 131071, 0, 3, 0, 0, 10754, 1), + (9200, 'Hastened Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10800, 1), + (9201, 'Clenched Jaw', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10803, 1), + (9202, 'Scout\'s Mastery of Fire', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10806, 1), + (9203, 'Scout\'s Mastery of Ice', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10809, 1), + (9205, 'Scout\'s Mastery of Slashing', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10815, 1), + (9206, 'Scout\'s Mastery of Piercing', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10818, 1), + (9207, 'Scout\'s Mastery of Blunt Weapons', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10821, 1), + (9300, 'Massive Strike', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10850, 1), + (9301, 'Strikethrough', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10853, 1), + (9400, 'Hate\'s Attraction', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10900, 1), + (9401, 'Feigned Minion', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10903, 1), + (9402, 'Hastened Summon Remains', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10909, 1), + (9403, 'Visage of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10912, 1), + (9404, 'Cascading Theft of Life', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10915, 1), + (9500, 'Extended Sloth', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10950, 1), + (9501, 'Hastened Ancestral Aid', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10951, 1), + (9502, 'Hastened Union of Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10954, 1), + (9503, 'Group Shrink', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10957, 1), + (9504, 'Inconspicuous Totem', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10958, 1), + (9505, 'Extended Pestilence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10959, 1), + (9600, 'Hastened Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11000, 1), + (9601, 'Extended Shield Reflect', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11003, 1), + (9602, 'Extended Commanding Voice', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11004, 1), + (9700, 'Hastened Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11050, 1), + (9701, 'Netherstep', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11055, 1), + (9702, 'Beam of Displacement', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11056, 1), + (9703, 'Translocate', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11057, 1), + (9704, 'Teleport', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11058, 1), + (10367, 'Ageless Enmity', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 10367, 1), + (10389, 'Extended Trickery', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10389, 1), + (10392, 'Ageless Enmity', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 10392, 1), + (10393, 'Shackles of Tunare', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10393, 1), + (10394, 'Beacon of the Righteous', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10394, 1), + (10395, 'Bobbing Corpse', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10395, 1), + (10396, 'Group Spirit of the White Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10396, 1), + (10397, 'Group Spirit of the Black Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10397, 1), + (10405, 'Hastened Deflection Discipline', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 10405, 1), + (10410, 'Rogue Triple Attack Skillup Test', -1, 256, 65535, 127, 131071, 0, 3, 0, 1, 10410, 1), + (10413, 'Hastened Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10413, 1), + (10424, 'Hand of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10424, 1), + (10425, 'Fixation of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10425, 1), + (10426, 'Peaceful Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10426, 1), + (10427, 'Peaceful Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10427, 1), + (10434, 'Quickened Army of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10434, 1), + (11073, 'Playing Possum', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11073, 1), + (11074, 'Cat-like Reflexes', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11074, 1), + (11077, 'Hastened Bite of the Asp', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11077, 1), + (11078, 'Hastened Gorilla Smash', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11078, 1), + (11079, 'Hastened Raven\'s Claw', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11079, 1), + (11080, 'Chameleon Strike', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11080, 1), + (11085, 'Two Hands, No Mercy!', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 11085, 1), + (11088, 'Hastened Cry of Battle', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 11088, 1), + (12600, 'Hastened Frenzied Stabbing', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12600, 1), + (12603, 'Extended Frenzied Stabbing Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12603, 1), + (12606, 'Speed of the Scoundrel', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12606, 1), + (12607, 'Hastened Pinpoint', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12607, 1), + (12615, 'Hastened Twisted Chance Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12615, 1), + (15073, 'Banestrike', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 15073, 1), + (15074, 'Hastened Banestrike', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 15074, 1), + (30050, 'Unknown AA 30050', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30050, 1), + (30100, 'Unknown AA 30100', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30100, 1), + (30150, 'Unknown AA 30150', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30150, 1), + (30175, 'Unknown AA 30175', 2, 65335, 65535, 127, 131071, 0, 4, 0, 1, 30175, 1), + (30180, 'Unknown AA 30180', 2, 128, 65535, 127, 131071, 0, 4, 0, 1, 30180, 1), + (30185, 'Unknown AA 30185', 2, 64, 65535, 127, 131071, 0, 4, 0, 1, 30185, 1), + (30190, 'Unknown AA 30190', 2, 8, 65535, 127, 131071, 0, 4, 0, 1, 30190, 1), + (30195, 'Unknown AA 30195', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30195, 1); + +DROP TABLE IF EXISTS `aa_ranks`; +CREATE TABLE IF NOT EXISTS `aa_ranks` ( + `id` int(10) unsigned NOT NULL, + `upper_hotkey_sid` int(10) NOT NULL DEFAULT '-1', + `lower_hotkey_sid` int(10) NOT NULL DEFAULT '-1', + `title_sid` int(10) NOT NULL DEFAULT '-1', + `desc_sid` int(10) NOT NULL DEFAULT '-1', + `cost` int(10) NOT NULL DEFAULT '1', + `level_req` int(10) NOT NULL DEFAULT '51', + `spell` int(10) NOT NULL DEFAULT '-1', + `spell_type` int(10) NOT NULL DEFAULT '0', + `recast_time` int(10) NOT NULL DEFAULT '0', + `expansion` int(10) NOT NULL DEFAULT '0', + `prev_id` int(10) NOT NULL DEFAULT '-1', + `next_id` int(10) NOT NULL DEFAULT '-1', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `aa_ranks` (`id`, `upper_hotkey_sid`, `lower_hotkey_sid`, `title_sid`, `desc_sid`, `cost`, `level_req`, `spell`, `spell_type`, `recast_time`, `expansion`, `prev_id`, `next_id`) VALUES + (2, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, -1, 3), + (3, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 2, 4), + (4, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 3, 5), + (5, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 4, 6), + (6, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 5, 292), + (7, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, -1, 8), + (8, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 7, 9), + (9, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 8, 10), + (10, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 9, 11), + (11, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 10, 302), + (12, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, -1, 13), + (13, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 12, 14), + (14, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 13, 15), + (15, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 14, 16), + (16, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 15, 312), + (17, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, -1, 18), + (18, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 17, 19), + (19, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 18, 20), + (20, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 19, 21), + (21, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 20, 322), + (22, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, -1, 23), + (23, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 22, 24), + (24, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 23, 25), + (25, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 24, 26), + (26, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 25, 332), + (27, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, -1, 28), + (28, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 27, 29), + (29, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 28, 30), + (30, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 29, 31), + (31, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 30, 342), + (32, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, -1, 33), + (33, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 32, 34), + (34, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 33, 35), + (35, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 34, 36), + (36, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 35, 352), + (37, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, -1, 38), + (38, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 37, 39), + (39, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 38, 40), + (40, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 39, 41), + (41, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 40, 362), + (42, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, -1, 43), + (43, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 42, 44), + (44, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 43, 45), + (45, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 44, 46), + (46, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 45, 372), + (47, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, -1, 48), + (48, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 47, 49), + (49, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 48, 50), + (50, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 49, 51), + (51, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 50, 382), + (52, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, -1, 53), + (53, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 52, 54), + (54, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 53, 55), + (55, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 54, 56), + (56, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 55, 392), + (57, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, -1, 58), + (58, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 57, 59), + (59, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 58, 60), + (60, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 59, 61), + (61, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 60, 402), + (62, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, -1, 63), + (63, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, 62, 64), + (64, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, 63, 672), + (68, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, -1, 69), + (69, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, 68, 70), + (70, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, 69, -1), + (71, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, -1, 72), + (72, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, 71, 73), + (73, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, 72, 676), + (74, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, -1, 75), + (75, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, 74, 76), + (76, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, 75, -1), + (77, -1, -1, 77, 77, 2, 55, -1, 0, 0, 3, -1, 78), + (78, -1, -1, 77, 77, 4, 55, -1, 0, 0, 3, 77, 79), + (79, -1, -1, 77, 77, 6, 55, -1, 0, 0, 3, 78, 434), + (80, -1, -1, 80, 80, 2, 55, -1, 0, 0, 3, -1, 81), + (81, -1, -1, 80, 80, 4, 55, -1, 0, 0, 3, 80, 82), + (82, -1, -1, 80, 80, 6, 55, -1, 0, 0, 3, 81, 437), + (83, -1, -1, 83, 83, 2, 55, -1, 0, 0, 3, -1, 84), + (84, -1, -1, 83, 83, 4, 55, -1, 0, 0, 3, 83, 85), + (85, -1, -1, 83, 83, 6, 55, -1, 0, 0, 3, 84, 13099), + (86, -1, -1, 86, 86, 2, 55, -1, 0, 0, 3, -1, 87), + (87, -1, -1, 86, 86, 4, 55, -1, 0, 0, 3, 86, 88), + (88, -1, -1, 86, 86, 6, 55, -1, 0, 0, 3, 87, 266), + (92, -1, -1, 92, 92, 2, 55, -1, 0, 0, 3, -1, 93), + (93, -1, -1, 92, 92, 4, 55, -1, 0, 0, 3, 92, 94), + (94, -1, -1, 92, 92, 6, 55, -1, 0, 0, 3, 93, -1), + (98, -1, -1, 98, 98, 2, 55, -1, 0, 0, 3, -1, 99), + (99, -1, -1, 98, 98, 4, 55, -1, 0, 0, 3, 98, 100), + (100, -1, -1, 98, 98, 6, 55, -1, 0, 0, 3, 99, 4767), + (101, -1, -1, 101, 101, 2, 55, -1, 0, 0, 3, -1, 102), + (102, -1, -1, 101, 101, 4, 55, -1, 0, 0, 3, 101, 103), + (103, -1, -1, 101, 101, 6, 55, -1, 0, 0, 3, 102, -1), + (104, -1, -1, 104, 104, 2, 55, -1, 0, 0, 3, -1, 105), + (105, -1, -1, 104, 104, 4, 55, -1, 0, 0, 3, 104, 106), + (106, -1, -1, 104, 104, 6, 55, -1, 0, 0, 3, 105, -1), + (107, -1, -1, 107, 107, 2, 55, -1, 0, 0, 3, -1, 108), + (108, -1, -1, 107, 107, 4, 55, -1, 0, 0, 3, 107, 109), + (109, -1, -1, 107, 107, 6, 55, -1, 0, 0, 3, 108, 7541), + (110, -1, -1, 110, 110, 2, 55, -1, 0, 0, 3, -1, 111), + (111, -1, -1, 110, 110, 4, 55, -1, 0, 0, 3, 110, 112), + (112, -1, -1, 110, 110, 6, 55, -1, 0, 0, 3, 111, -1), + (113, -1, -1, 113, 113, 2, 55, -1, 0, 0, 3, -1, 114), + (114, -1, -1, 113, 113, 4, 55, -1, 0, 0, 3, 113, 115), + (115, -1, -1, 113, 113, 6, 55, -1, 0, 0, 3, 114, 443), + (116, -1, -1, 116, 116, 2, 55, -1, 0, 0, 3, -1, 117), + (117, -1, -1, 116, 116, 4, 55, -1, 0, 0, 3, 116, 118), + (118, -1, -1, 116, 116, 6, 55, -1, 0, 0, 3, 117, -1), + (119, -1, -1, 119, 119, 2, 55, -1, 0, 0, 3, -1, 120), + (120, -1, -1, 119, 119, 4, 55, -1, 0, 0, 3, 119, 121), + (121, -1, -1, 119, 119, 6, 55, -1, 0, 0, 3, 120, 440), + (122, -1, -1, 122, 122, 2, 55, -1, 0, 0, 3, -1, 123), + (123, -1, -1, 122, 122, 4, 55, -1, 0, 0, 3, 122, 124), + (124, -1, -1, 122, 122, 6, 55, -1, 0, 0, 3, 123, 454), + (125, -1, -1, 125, 125, 2, 55, -1, 0, 0, 3, -1, 126), + (126, -1, -1, 125, 125, 4, 55, -1, 0, 0, 3, 125, 127), + (127, -1, -1, 125, 125, 6, 55, -1, 0, 0, 3, 126, 449), + (128, 128, 128, 128, 128, 9, 59, 5228, 1, 4320, 3, -1, -1), + (129, 129, 129, 129, 129, 5, 59, 2738, 2, 64800, 3, -1, -1), + (130, 130, 130, 130, 130, 3, 59, 2739, 3, 7, 3, -1, -1), + (131, 131, 131, 131, 131, 5, 59, 2740, 4, 900, 3, -1, 531), + (132, 132, 132, 132, 132, 6, 59, 2741, 5, 600, 3, -1, -1), + (136, 136, -1, 136, 136, 5, 59, 2742, 7, 1800, 3, -1, 15341), + (137, -1, -1, 137, 137, 3, 59, -1, 0, 0, 3, -1, 138), + (138, -1, -1, 137, 137, 6, 59, -1, 0, 0, 3, 137, 139), + (139, -1, -1, 137, 137, 9, 59, -1, 0, 0, 3, 138, -1), + (140, 140, -1, 140, 140, 6, 59, 2771, 3, 4320, 3, -1, -1), + (141, -1, -1, 141, 12863, 3, 59, -1, 0, 0, 3, -1, 142), + (142, -1, -1, 141, 12863, 6, 59, -1, 0, 0, 3, 141, 143), + (143, -1, -1, 141, 12863, 9, 59, -1, 0, 0, 3, 142, 12863), + (144, -1, -1, 144, 144, 5, 59, -1, 0, 0, 3, -1, -1), + (145, 145, 145, 145, 145, 9, 59, 2761, 2, 4320, 3, -1, -1), + (146, 146, 146, 146, 146, 5, 59, 2749, 2, 180, 3, -1, 5069), + (147, -1, -1, 147, 147, 3, 59, -1, 0, 0, 3, -1, 148), + (148, -1, -1, 147, 147, 6, 59, -1, 0, 0, 3, 147, 149), + (149, -1, -1, 147, 147, 9, 59, -1, 0, 0, 3, 148, -1), + (150, -1, -1, 150, 150, 3, 59, -1, 0, 0, 3, -1, 151), + (151, -1, -1, 150, 150, 6, 59, -1, 0, 0, 3, 150, 152), + (152, -1, -1, 150, 150, 9, 59, -1, 0, 0, 3, 151, -1), + (153, 153, 153, 153, 153, 5, 59, 2750, 3, 2160, 3, -1, 1519), + (155, 155, 155, 155, 155, 9, 59, 2758, 8, 60, 3, -1, 533), + (156, 156, 156, 156, 156, 6, 59, 2734, 2, 4320, 3, -1, -1), + (158, -1, -1, 158, 158, 3, 59, -1, 0, 0, 3, -1, -1), + (159, -1, -1, 159, 159, 2, 59, -1, 0, 0, 3, -1, 160), + (160, -1, -1, 159, 159, 4, 59, -1, 0, 0, 3, 159, 161), + (161, -1, -1, 159, 159, 6, 59, -1, 0, 0, 3, 160, -1), + (162, 162, 162, 162, 162, 5, 59, 2753, 3, 8640, 3, -1, -1), + (163, 163, 163, 163, 163, 5, 59, 2752, 2, 2160, 3, -1, -1), + (167, 167, 167, 167, 167, 6, 59, 2754, 14, 900, 3, -1, 5879), + (168, 168, 168, 168, 168, 3, 59, 2795, 4, 10, 3, -1, 169), + (169, 168, 168, 168, 168, 6, 59, 2796, 4, 10, 3, 168, 170), + (170, 168, 168, 168, 168, 9, 59, 2797, 4, 10, 3, 169, 15241), + (171, 171, 171, 171, 171, 3, 59, 2798, 4, 10, 3, -1, 172), + (172, 171, 171, 171, 171, 6, 59, 2799, 4, 10, 3, 171, 173), + (173, 171, 171, 171, 171, 9, 59, 2800, 4, 10, 3, 172, 15244), + (174, 174, 174, 174, 174, 3, 59, 2792, 4, 10, 3, -1, 175), + (175, 174, 174, 174, 174, 6, 59, 2793, 4, 10, 3, 174, 176), + (176, 174, 174, 174, 174, 9, 59, 2794, 4, 10, 3, 175, 15247), + (177, 177, 177, 177, 177, 3, 59, 2789, 4, 10, 3, -1, 178), + (178, 177, 177, 177, 177, 6, 59, 2790, 4, 10, 3, 177, 179), + (179, 177, 177, 177, 177, 9, 59, 2791, 4, 10, 3, 178, 15250), + (182, -1, -1, 182, 182, 5, 59, -1, 0, 0, 3, -1, -1), + (183, 183, 183, 183, 183, 9, 59, 2755, 4, 8640, 3, -1, -1), + (184, 184, 184, 184, 184, 3, 59, 2756, 5, 4320, 3, -1, 5953), + (185, 185, 185, 185, 185, 5, 59, 2757, 6, 4320, 3, -1, -1), + (186, 186, 186, 186, 186, 3, 59, 2772, 7, 7, 3, -1, -1), + (187, 187, 187, 187, 187, 6, 59, 2764, 8, 4320, 3, -1, -1), + (188, 188, 188, 188, 188, 9, 59, 2190, 2, 30, 3, -1, 1277), + (190, -1, -1, 190, 190, 3, 59, -1, 0, 0, 3, -1, 191), + (191, -1, -1, 190, 190, 6, 59, -1, 0, 0, 3, 190, 192), + (192, -1, -1, 190, 190, 9, 59, -1, 0, 0, 3, 191, 1524), + (193, 193, 193, 193, 193, 3, 59, 2775, 3, 4320, 3, -1, -1), + (194, 194, 194, 194, 194, 5, 59, 2874, 0, 1, 3, -1, -1), + (195, -1, -1, 195, 195, 6, 59, -1, 0, 0, 3, -1, -1), + (196, -1, -1, 196, 196, 6, 59, -1, 0, 0, 3, -1, -1), + (197, 197, 197, 197, 197, 5, 59, 2765, 2, 7, 3, -1, -1), + (198, -1, -1, 198, 198, 9, 59, -1, 0, 0, 3, -1, -1), + (199, -1, -1, 199, 199, 3, 59, -1, 0, 0, 3, -1, 200), + (200, -1, -1, 199, 199, 6, 59, -1, 0, 0, 3, 199, 201), + (201, -1, -1, 199, 199, 9, 59, -1, 0, 0, 3, 200, 12507), + (205, -1, -1, 205, 205, 9, 59, -1, 0, 0, 3, -1, -1), + (206, 206, 206, 206, 206, 5, 59, 2875, 0, 1, 3, -1, -1), + (208, 208, 208, 208, 208, 6, 59, 2766, 2, 4320, 3, -1, -1), + (210, -1, -1, 210, 210, 3, 59, -1, 0, 0, 3, -1, 211), + (211, -1, -1, 210, 210, 6, 59, -1, 0, 0, 3, 210, 212), + (212, -1, -1, 210, 210, 9, 59, -1, 0, 0, 3, 211, 1316), + (213, -1, -1, 213, 213, 3, 59, -1, 0, 0, 3, -1, 214), + (214, -1, -1, 213, 213, 6, 59, -1, 0, 0, 3, 213, 215), + (215, -1, -1, 213, 213, 9, 59, -1, 0, 0, 3, 214, 700), + (225, -1, -1, 225, 225, 3, 59, -1, 0, 0, 3, -1, 226), + (226, -1, -1, 225, 225, 6, 59, -1, 0, 0, 3, 225, 227), + (227, -1, -1, 225, 225, 9, 59, -1, 0, 0, 3, 226, -1), + (230, -1, -1, 230, 230, 3, 59, -1, 0, 0, 3, -1, 231), + (231, -1, -1, 230, 230, 6, 59, -1, 0, 0, 3, 230, 232), + (232, -1, -1, 230, 230, 9, 59, -1, 0, 0, 3, 231, 539), + (233, 233, 233, 233, 233, 9, 59, 5248, 1, 1800, 3, -1, -1), + (237, -1, -1, 237, 237, 3, 59, -1, 0, 0, 3, -1, 238), + (238, -1, -1, 237, 237, 6, 59, -1, 0, 0, 3, 237, 239), + (239, -1, -1, 237, 237, 9, 59, -1, 0, 0, 3, 238, -1), + (240, -1, -1, 240, 240, 3, 59, -1, 0, 0, 3, -1, 241), + (241, -1, -1, 240, 240, 6, 59, -1, 0, 0, 3, 240, 242), + (242, -1, -1, 240, 240, 9, 59, -1, 0, 0, 3, 241, -1), + (243, 243, -1, 243, 243, 9, 59, 5244, 1, 1440, 3, -1, -1), + (244, -1, -1, 244, 244, 3, 59, -1, 0, 0, 3, -1, 245), + (245, -1, -1, 244, 244, 6, 59, -1, 0, 0, 3, 244, 246), + (246, -1, -1, 244, 244, 9, 59, -1, 0, 0, 3, 245, 8328), + (247, -1, -1, 247, 247, 3, 59, -1, 0, 0, 3, -1, 248), + (248, -1, -1, 247, 247, 6, 59, -1, 0, 0, 3, 247, 249), + (249, -1, -1, 247, 247, 9, 59, -1, 0, 0, 3, 248, 504), + (254, 254, 254, 254, 254, 5, 59, 5232, 12, 4320, 3, -1, -1), + (255, -1, -1, 255, 255, 3, 59, -1, 0, 0, 3, -1, 256), + (256, -1, -1, 255, 255, 6, 59, -1, 0, 0, 3, 255, 257), + (257, -1, -1, 255, 255, 9, 59, -1, 0, 0, 3, 256, 542), + (258, 258, -1, 258, 258, 5, 59, 5233, 1, 600, 3, -1, 10578), + (259, 259, 259, 259, 259, 5, 59, 5234, 2, 900, 3, -1, -1), + (260, 260, -1, 260, 260, 3, 59, 5229, 3, 2160, 3, -1, 261), + (261, 260, -1, 260, 260, 6, 59, 5230, 3, 2160, 3, 260, 262), + (262, 260, -1, 260, 260, 9, 59, 5231, 3, 2160, 3, 261, 8309), + (263, -1, -1, 263, 263, 3, 59, -1, 0, 0, 3, -1, 264), + (264, -1, -1, 263, 263, 6, 59, -1, 0, 0, 3, 263, 265), + (265, -1, -1, 263, 263, 9, 59, -1, 0, 0, 3, 264, -1), + (266, -1, -1, 86, 86, 8, 59, -1, 0, 0, 3, 88, 10467), + (267, -1, -1, 267, 267, 3, 59, -1, 0, 0, 3, -1, 268), + (268, -1, -1, 267, 267, 6, 59, -1, 0, 0, 3, 267, 269), + (269, -1, -1, 267, 267, 9, 59, -1, 0, 0, 3, 268, 640), + (273, -1, -1, 273, 273, 5, 59, 2767, 0, 0, 3, -1, -1), + (274, 274, 274, 274, 274, 5, 59, 2748, 4, 4320, 3, -1, -1), + (275, -1, -1, 275, 275, 3, 59, -1, 0, 0, 3, -1, 276), + (276, -1, -1, 275, 275, 6, 59, -1, 0, 0, 3, 275, 277), + (277, -1, -1, 275, 275, 9, 59, -1, 0, 0, 3, 276, 701), + (278, -1, -1, 278, 278, 5, 59, -1, 0, 0, 3, -1, -1), + (279, -1, -1, 279, 279, 5, 59, -1, 0, 0, 3, -1, 18972), + (280, -1, -1, 280, 280, 3, 59, -1, 0, 0, 3, -1, 281), + (281, -1, -1, 280, 280, 6, 59, -1, 0, 0, 3, 280, 282), + (282, -1, -1, 280, 280, 9, 59, -1, 0, 0, 3, 281, -1), + (283, -1, -1, 283, 283, 3, 59, -1, 0, 0, 3, -1, 284), + (284, -1, -1, 283, 283, 6, 59, -1, 0, 0, 3, 283, 285), + (285, -1, -1, 283, 283, 9, 59, -1, 0, 0, 3, 284, -1), + (286, -1, -1, 286, 286, 3, 59, -1, 0, 0, 3, -1, -1), + (287, -1, -1, 287, 287, 6, 59, -1, 0, 0, 3, -1, -1), + (288, -1, -1, 288, 288, 6, 59, -1, 0, 0, 3, -1, -1), + (289, 289, 289, 289, 289, 5, 59, 3290, 3, 300, 3, -1, 1607), + (290, 290, 290, 290, 290, 4, 59, 3289, 4, 720, 3, -1, 13173), + (291, 291, 291, 291, 291, 6, 59, 3291, 5, 900, 3, -1, 1123), + (292, -1, -1, 2, 2, 1, 61, -1, 0, 0, 4, 6, 293), + (293, -1, -1, 2, 2, 1, 61, -1, 0, 0, 4, 292, 294), + (294, -1, -1, 2, 2, 1, 62, -1, 0, 0, 4, 293, 295), + (295, -1, -1, 2, 2, 1, 62, -1, 0, 0, 4, 294, 296), + (296, -1, -1, 2, 2, 1, 63, -1, 0, 0, 4, 295, 297), + (297, -1, -1, 2, 2, 1, 63, -1, 0, 0, 4, 296, 298), + (298, -1, -1, 2, 2, 1, 64, -1, 0, 0, 4, 297, 299), + (299, -1, -1, 2, 2, 1, 64, -1, 0, 0, 4, 298, 300), + (300, -1, -1, 2, 2, 1, 65, -1, 0, 0, 4, 299, 301), + (301, -1, -1, 2, 2, 1, 65, -1, 0, 0, 4, 300, -1), + (302, -1, -1, 7, 7, 1, 61, -1, 0, 0, 4, 11, 303), + (303, -1, -1, 7, 7, 1, 61, -1, 0, 0, 4, 302, 304), + (304, -1, -1, 7, 7, 1, 62, -1, 0, 0, 4, 303, 305), + (305, -1, -1, 7, 7, 1, 62, -1, 0, 0, 4, 304, 306), + (306, -1, -1, 7, 7, 1, 63, -1, 0, 0, 4, 305, 307), + (307, -1, -1, 7, 7, 1, 63, -1, 0, 0, 4, 306, 308), + (308, -1, -1, 7, 7, 1, 64, -1, 0, 0, 4, 307, 309), + (309, -1, -1, 7, 7, 1, 64, -1, 0, 0, 4, 308, 310), + (310, -1, -1, 7, 7, 1, 65, -1, 0, 0, 4, 309, 311), + (311, -1, -1, 7, 7, 1, 65, -1, 0, 0, 4, 310, -1), + (312, -1, -1, 12, 12, 1, 61, -1, 0, 0, 4, 16, 313), + (313, -1, -1, 12, 12, 1, 61, -1, 0, 0, 4, 312, 314), + (314, -1, -1, 12, 12, 1, 62, -1, 0, 0, 4, 313, 315), + (315, -1, -1, 12, 12, 1, 62, -1, 0, 0, 4, 314, 316), + (316, -1, -1, 12, 12, 1, 63, -1, 0, 0, 4, 315, 317), + (317, -1, -1, 12, 12, 1, 63, -1, 0, 0, 4, 316, 318), + (318, -1, -1, 12, 12, 1, 64, -1, 0, 0, 4, 317, 319), + (319, -1, -1, 12, 12, 1, 64, -1, 0, 0, 4, 318, 320), + (320, -1, -1, 12, 12, 1, 65, -1, 0, 0, 4, 319, 321), + (321, -1, -1, 12, 12, 1, 65, -1, 0, 0, 4, 320, -1), + (322, -1, -1, 17, 17, 1, 61, -1, 0, 0, 4, 21, 323), + (323, -1, -1, 17, 17, 1, 61, -1, 0, 0, 4, 322, 324), + (324, -1, -1, 17, 17, 1, 62, -1, 0, 0, 4, 323, 325), + (325, -1, -1, 17, 17, 1, 62, -1, 0, 0, 4, 324, 326), + (326, -1, -1, 17, 17, 1, 63, -1, 0, 0, 4, 325, 327), + (327, -1, -1, 17, 17, 1, 63, -1, 0, 0, 4, 326, 328), + (328, -1, -1, 17, 17, 1, 64, -1, 0, 0, 4, 327, 329), + (329, -1, -1, 17, 17, 1, 64, -1, 0, 0, 4, 328, 330), + (330, -1, -1, 17, 17, 1, 65, -1, 0, 0, 4, 329, 331), + (331, -1, -1, 17, 17, 1, 65, -1, 0, 0, 4, 330, -1), + (332, -1, -1, 22, 22, 1, 61, -1, 0, 0, 4, 26, 333), + (333, -1, -1, 22, 22, 1, 61, -1, 0, 0, 4, 332, 334), + (334, -1, -1, 22, 22, 1, 62, -1, 0, 0, 4, 333, 335), + (335, -1, -1, 22, 22, 1, 62, -1, 0, 0, 4, 334, 336), + (336, -1, -1, 22, 22, 1, 63, -1, 0, 0, 4, 335, 337), + (337, -1, -1, 22, 22, 1, 63, -1, 0, 0, 4, 336, 338), + (338, -1, -1, 22, 22, 1, 64, -1, 0, 0, 4, 337, 339), + (339, -1, -1, 22, 22, 1, 64, -1, 0, 0, 4, 338, 340), + (340, -1, -1, 22, 22, 1, 65, -1, 0, 0, 4, 339, 341), + (341, -1, -1, 22, 22, 1, 65, -1, 0, 0, 4, 340, -1), + (342, -1, -1, 27, 27, 1, 61, -1, 0, 0, 4, 31, 343), + (343, -1, -1, 27, 27, 1, 61, -1, 0, 0, 4, 342, 344), + (344, -1, -1, 27, 27, 1, 62, -1, 0, 0, 4, 343, 345), + (345, -1, -1, 27, 27, 1, 62, -1, 0, 0, 4, 344, 346), + (346, -1, -1, 27, 27, 1, 63, -1, 0, 0, 4, 345, 347), + (347, -1, -1, 27, 27, 1, 63, -1, 0, 0, 4, 346, 348), + (348, -1, -1, 27, 27, 1, 64, -1, 0, 0, 4, 347, 349), + (349, -1, -1, 27, 27, 1, 64, -1, 0, 0, 4, 348, 350), + (350, -1, -1, 27, 27, 1, 65, -1, 0, 0, 4, 349, 351), + (351, -1, -1, 27, 27, 1, 65, -1, 0, 0, 4, 350, -1), + (352, -1, -1, 32, 32, 1, 61, -1, 0, 0, 4, 36, 353), + (353, -1, -1, 32, 32, 1, 61, -1, 0, 0, 4, 352, 354), + (354, -1, -1, 32, 32, 1, 62, -1, 0, 0, 4, 353, 355), + (355, -1, -1, 32, 32, 1, 62, -1, 0, 0, 4, 354, 356), + (356, -1, -1, 32, 32, 1, 63, -1, 0, 0, 4, 355, 357), + (357, -1, -1, 32, 32, 1, 63, -1, 0, 0, 4, 356, 358), + (358, -1, -1, 32, 32, 1, 64, -1, 0, 0, 4, 357, 359), + (359, -1, -1, 32, 32, 1, 64, -1, 0, 0, 4, 358, 360), + (360, -1, -1, 32, 32, 1, 65, -1, 0, 0, 4, 359, 361), + (361, -1, -1, 32, 32, 1, 65, -1, 0, 0, 4, 360, -1), + (362, -1, -1, 37, 37, 1, 61, -1, 0, 0, 4, 41, 363), + (363, -1, -1, 37, 37, 1, 61, -1, 0, 0, 4, 362, 364), + (364, -1, -1, 37, 37, 1, 62, -1, 0, 0, 4, 363, 365), + (365, -1, -1, 37, 37, 1, 62, -1, 0, 0, 4, 364, 366), + (366, -1, -1, 37, 37, 1, 63, -1, 0, 0, 4, 365, 367), + (367, -1, -1, 37, 37, 1, 63, -1, 0, 0, 4, 366, 368), + (368, -1, -1, 37, 37, 1, 64, -1, 0, 0, 4, 367, 369), + (369, -1, -1, 37, 37, 1, 64, -1, 0, 0, 4, 368, 370), + (370, -1, -1, 37, 37, 1, 65, -1, 0, 0, 4, 369, 371), + (371, -1, -1, 37, 37, 1, 65, -1, 0, 0, 4, 370, -1), + (372, -1, -1, 42, 42, 1, 61, -1, 0, 0, 4, 46, 373), + (373, -1, -1, 42, 42, 1, 61, -1, 0, 0, 4, 372, 374), + (374, -1, -1, 42, 42, 1, 62, -1, 0, 0, 4, 373, 375), + (375, -1, -1, 42, 42, 1, 62, -1, 0, 0, 4, 374, 376), + (376, -1, -1, 42, 42, 1, 63, -1, 0, 0, 4, 375, 377), + (377, -1, -1, 42, 42, 1, 63, -1, 0, 0, 4, 376, 378), + (378, -1, -1, 42, 42, 1, 64, -1, 0, 0, 4, 377, 379), + (379, -1, -1, 42, 42, 1, 64, -1, 0, 0, 4, 378, 380), + (380, -1, -1, 42, 42, 1, 65, -1, 0, 0, 4, 379, 381), + (381, -1, -1, 42, 42, 1, 65, -1, 0, 0, 4, 380, -1), + (382, -1, -1, 47, 47, 1, 61, -1, 0, 0, 4, 51, 383), + (383, -1, -1, 47, 47, 1, 61, -1, 0, 0, 4, 382, 384), + (384, -1, -1, 47, 47, 1, 62, -1, 0, 0, 4, 383, 385), + (385, -1, -1, 47, 47, 1, 62, -1, 0, 0, 4, 384, 386), + (386, -1, -1, 47, 47, 1, 63, -1, 0, 0, 4, 385, 387), + (387, -1, -1, 47, 47, 1, 63, -1, 0, 0, 4, 386, 388), + (388, -1, -1, 47, 47, 1, 64, -1, 0, 0, 4, 387, 389), + (389, -1, -1, 47, 47, 1, 64, -1, 0, 0, 4, 388, 390), + (390, -1, -1, 47, 47, 1, 65, -1, 0, 0, 4, 389, 391), + (391, -1, -1, 47, 47, 1, 65, -1, 0, 0, 4, 390, -1), + (392, -1, -1, 52, 52, 1, 61, -1, 0, 0, 4, 56, 393), + (393, -1, -1, 52, 52, 1, 61, -1, 0, 0, 4, 392, 394), + (394, -1, -1, 52, 52, 1, 62, -1, 0, 0, 4, 393, 395), + (395, -1, -1, 52, 52, 1, 62, -1, 0, 0, 4, 394, 396), + (396, -1, -1, 52, 52, 1, 63, -1, 0, 0, 4, 395, 397), + (397, -1, -1, 52, 52, 1, 63, -1, 0, 0, 4, 396, 398), + (398, -1, -1, 52, 52, 1, 64, -1, 0, 0, 4, 397, 399), + (399, -1, -1, 52, 52, 1, 64, -1, 0, 0, 4, 398, 400), + (400, -1, -1, 52, 52, 1, 65, -1, 0, 0, 4, 399, 401), + (401, -1, -1, 52, 52, 1, 65, -1, 0, 0, 4, 400, -1), + (402, -1, -1, 57, 57, 1, 61, -1, 0, 0, 4, 61, 403), + (403, -1, -1, 57, 57, 1, 61, -1, 0, 0, 4, 402, 404), + (404, -1, -1, 57, 57, 1, 62, -1, 0, 0, 4, 403, 405), + (405, -1, -1, 57, 57, 1, 62, -1, 0, 0, 4, 404, 406), + (406, -1, -1, 57, 57, 1, 63, -1, 0, 0, 4, 405, 407), + (407, -1, -1, 57, 57, 1, 63, -1, 0, 0, 4, 406, 408), + (408, -1, -1, 57, 57, 1, 64, -1, 0, 0, 4, 407, 409), + (409, -1, -1, 57, 57, 1, 64, -1, 0, 0, 4, 408, 410), + (410, -1, -1, 57, 57, 1, 65, -1, 0, 0, 4, 409, 411), + (411, -1, -1, 57, 57, 1, 65, -1, 0, 0, 4, 410, -1), + (412, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, -1, 413), + (413, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 412, 414), + (414, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 413, 415), + (415, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 414, 416), + (416, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 415, 417), + (417, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 416, -1), + (418, -1, -1, 418, 418, 2, 61, -1, 0, 0, 4, -1, 419), + (419, -1, -1, 418, 418, 2, 62, -1, 0, 0, 4, 418, 420), + (420, -1, -1, 418, 418, 2, 63, -1, 0, 0, 4, 419, 421), + (421, -1, -1, 418, 418, 2, 64, -1, 0, 0, 4, 420, 422), + (422, -1, -1, 418, 418, 2, 65, -1, 0, 0, 4, 421, 1001), + (423, -1, -1, 423, 423, 3, 61, -1, 0, 0, 4, -1, 424), + (424, -1, -1, 423, 423, 3, 63, -1, 0, 0, 4, 423, 425), + (425, -1, -1, 423, 423, 3, 65, -1, 0, 0, 4, 424, -1), + (426, -1, -1, 426, 426, 3, 61, -1, 0, 0, 4, -1, 427), + (427, -1, -1, 426, 426, 3, 62, -1, 0, 0, 4, 426, 428), + (428, -1, -1, 426, 426, 3, 63, -1, 0, 0, 4, 427, 429), + (429, -1, -1, 426, 426, 3, 64, -1, 0, 0, 4, 428, 430), + (430, -1, -1, 426, 426, 3, 65, -1, 0, 0, 4, 429, -1), + (434, -1, -1, 77, 77, 2, 62, -1, 0, 0, 4, 79, 435), + (435, -1, -1, 77, 77, 4, 63, -1, 0, 0, 4, 434, 436), + (436, -1, -1, 77, 77, 6, 64, -1, 0, 0, 4, 435, 1083), + (437, -1, -1, 80, 80, 2, 62, -1, 0, 0, 4, 82, 438), + (438, -1, -1, 80, 80, 3, 63, -1, 0, 0, 4, 437, 439), + (439, -1, -1, 80, 80, 4, 64, -1, 0, 0, 4, 438, 1086), + (440, -1, -1, 119, 119, 2, 62, -1, 0, 0, 4, 121, 441), + (441, -1, -1, 119, 119, 2, 63, -1, 0, 0, 4, 440, 442), + (442, -1, -1, 119, 119, 2, 64, -1, 0, 0, 4, 441, 1053), + (443, -1, -1, 113, 113, 3, 62, -1, 0, 0, 4, 115, 444), + (444, -1, -1, 113, 113, 3, 63, -1, 0, 0, 4, 443, 445), + (445, -1, -1, 113, 113, 3, 64, -1, 0, 0, 4, 444, -1), + (446, -1, -1, 446, 735, 3, 62, -1, 0, 0, 4, -1, 447), + (447, -1, -1, 446, 735, 3, 63, -1, 0, 0, 4, 446, 448), + (448, -1, -1, 446, 735, 3, 64, -1, 0, 0, 4, 447, 7050), + (449, -1, -1, 125, 125, 3, 61, -1, 0, 0, 4, 127, 450), + (450, -1, -1, 125, 125, 3, 62, -1, 0, 0, 4, 449, 451), + (451, -1, -1, 125, 125, 3, 63, -1, 0, 0, 4, 450, 452), + (452, -1, -1, 125, 125, 3, 64, -1, 0, 0, 4, 451, 453), + (453, -1, -1, 125, 125, 3, 65, -1, 0, 0, 4, 452, 1061), + (454, -1, -1, 122, 122, 3, 61, -1, 0, 0, 4, 124, 455), + (455, -1, -1, 122, 122, 3, 62, -1, 0, 0, 4, 454, 456), + (456, -1, -1, 122, 122, 3, 63, -1, 0, 0, 4, 455, 457), + (457, -1, -1, 122, 122, 3, 64, -1, 0, 0, 4, 456, 458), + (458, -1, -1, 122, 122, 3, 65, -1, 0, 0, 4, 457, 1066), + (459, 459, 459, 459, 459, 2, 61, 3297, 8, 180, 4, -1, 460), + (460, 459, 459, 459, 459, 4, 63, 3298, 8, 180, 4, 459, 461), + (461, 459, 459, 459, 459, 6, 65, 3299, 8, 180, 4, 460, 1189), + (462, -1, -1, 462, 462, 2, 63, -1, 0, 0, 4, -1, 463), + (463, -1, -1, 462, 462, 2, 64, -1, 0, 0, 4, 462, 464), + (464, -1, -1, 462, 462, 2, 65, -1, 0, 0, 4, 463, 7994), + (468, -1, -1, 468, 468, 2, 63, -1, 0, 0, 4, -1, 469), + (469, -1, -1, 468, 468, 2, 64, -1, 0, 0, 4, 468, 470), + (470, -1, -1, 468, 468, 2, 65, -1, 0, 0, 4, 469, 6439), + (471, -1, -1, 471, 471, 2, 63, -1, 0, 0, 4, -1, 472), + (472, -1, -1, 471, 471, 2, 64, -1, 0, 0, 4, 471, 473), + (473, -1, -1, 471, 471, 2, 65, -1, 0, 0, 4, 472, 12899), + (474, -1, -1, 474, 474, 2, 63, -1, 0, 0, 4, -1, 475), + (475, -1, -1, 474, 474, 2, 64, -1, 0, 0, 4, 474, 476), + (476, -1, -1, 474, 474, 2, 65, -1, 0, 0, 4, 475, 15359), + (477, -1, -1, 477, 477, 2, 63, -1, 0, 0, 4, -1, 478), + (478, -1, -1, 477, 477, 2, 64, -1, 0, 0, 4, 477, 479), + (479, -1, -1, 477, 477, 2, 65, -1, 0, 0, 4, 478, 6233), + (480, -1, -1, 480, 480, 2, 63, -1, 0, 0, 4, -1, 481), + (481, -1, -1, 480, 480, 2, 64, -1, 0, 0, 4, 480, 482), + (482, -1, -1, 480, 480, 2, 65, -1, 0, 0, 4, 481, 4921), + (483, -1, -1, 483, 483, 2, 63, -1, 0, 0, 4, -1, 484), + (484, -1, -1, 483, 483, 2, 64, -1, 0, 0, 4, 483, 485), + (485, -1, -1, 483, 483, 2, 65, -1, 0, 0, 4, 484, -1), + (489, -1, -1, 489, 489, 3, 63, -1, 0, 0, 4, -1, 490), + (490, -1, -1, 489, 489, 3, 64, -1, 0, 0, 4, 489, 491), + (491, -1, -1, 489, 489, 3, 65, -1, 0, 0, 4, 490, 7116), + (492, -1, -1, 492, 492, 2, 63, -1, 0, 0, 4, -1, 493), + (493, -1, -1, 492, 492, 2, 64, -1, 0, 0, 4, 492, 494), + (494, -1, -1, 492, 492, 2, 65, -1, 0, 0, 4, 493, 7128), + (495, -1, -1, 495, 495, 2, 63, -1, 0, 0, 4, -1, 496), + (496, -1, -1, 495, 495, 2, 64, -1, 0, 0, 4, 495, 497), + (497, -1, -1, 495, 495, 2, 65, -1, 0, 0, 4, 496, 6260), + (498, -1, -1, 498, 498, 2, 63, -1, 0, 0, 4, -1, 499), + (499, -1, -1, 498, 498, 2, 64, -1, 0, 0, 4, 498, 500), + (500, -1, -1, 498, 498, 2, 65, -1, 0, 0, 4, 499, 886), + (501, -1, -1, 501, 501, 2, 63, -1, 0, 0, 4, -1, 502), + (502, -1, -1, 501, 501, 2, 64, -1, 0, 0, 4, 501, 503), + (503, -1, -1, 501, 501, 2, 65, -1, 0, 0, 4, 502, 6319), + (504, -1, -1, 247, 247, 3, 62, -1, 0, 0, 4, 249, 505), + (505, -1, -1, 247, 247, 3, 63, -1, 0, 0, 4, 504, 506), + (506, -1, -1, 247, 247, 3, 64, -1, 0, 0, 4, 505, -1), + (507, 507, 507, 507, 507, 3, 61, 3252, 9, 180, 4, -1, 508), + (508, 507, 507, 507, 507, 3, 63, 3253, 9, 180, 4, 507, 509), + (509, 507, 507, 507, 507, 3, 65, 3254, 9, 180, 4, 508, -1), + (510, 510, 510, 510, 510, 3, 61, 3255, 37, 240, 4, -1, 511), + (511, 510, 510, 510, 510, 3, 63, 3256, 37, 240, 4, 510, 512), + (512, 510, 510, 510, 510, 3, 65, 3257, 37, 240, 4, 511, 7425), + (513, 513, 513, 513, 513, 3, 61, 3274, 4, 120, 4, -1, 514), + (514, 513, 513, 513, 513, 3, 63, 3275, 4, 120, 4, 513, 515), + (515, 513, 513, 513, 513, 3, 65, 3276, 4, 120, 4, 514, 6095), + (516, 516, 516, 516, 516, 2, 62, 3338, 5, 480, 4, -1, 6398), + (517, 517, 517, 517, 517, 3, 61, 3258, 12, 600, 4, -1, 518), + (518, 517, 517, 517, 517, 3, 63, 3259, 12, 600, 4, 517, 519), + (519, 517, 517, 517, 517, 3, 65, 3260, 12, 600, 4, 518, 1440), + (520, 520, 520, 520, 520, 3, 61, 3265, 6, 540, 4, -1, 521), + (521, 520, 520, 520, 520, 3, 63, 3266, 6, 540, 4, 520, 522), + (522, 520, 520, 520, 520, 3, 65, 3267, 6, 540, 4, 521, 1507), + (523, 523, 523, 523, 523, 5, 61, 3268, 9, 540, 4, -1, 524), + (524, 523, 523, 523, 523, 4, 63, 3269, 9, 540, 4, 523, 525), + (525, 523, 523, 523, 523, 3, 65, 3270, 9, 540, 4, 524, -1), + (526, 526, 526, 526, 526, 5, 62, 3248, 0, 1, 4, -1, 527), + (527, 526, 526, 526, 526, 3, 64, 3249, 0, 1, 4, 526, -1), + (528, 528, 528, 528, 528, 4, 61, 3283, 5, 720, 4, -1, 529), + (529, 528, 528, 528, 528, 3, 63, 3284, 5, 720, 4, 528, 530), + (530, 528, 528, 528, 528, 2, 65, 3285, 5, 720, 4, 529, 900), + (531, 131, 131, 131, 131, 3, 63, 3250, 4, 900, 4, 131, 532), + (532, 131, 131, 131, 131, 6, 64, 3251, 4, 900, 4, 531, 1203), + (533, 155, 155, 155, 155, 6, 64, 3264, 8, 60, 4, 155, 1344), + (534, 534, 534, 534, 534, 3, 61, 3261, 4, 2160, 4, -1, 535), + (535, 534, 534, 534, 534, 3, 63, 3262, 4, 2160, 4, 534, 536), + (536, 534, 534, 534, 534, 3, 65, 3263, 4, 2160, 4, 535, 715), + (537, -1, -1, 537, 537, 3, 63, -1, 0, 0, 4, -1, 538), + (538, -1, -1, 537, 537, 3, 64, -1, 0, 0, 4, 537, -1), + (539, -1, -1, 230, 230, 2, 63, -1, 0, 0, 4, 232, 540), + (540, -1, -1, 230, 230, 4, 64, -1, 0, 0, 4, 539, 541), + (541, -1, -1, 230, 230, 6, 65, -1, 0, 0, 4, 540, 12677), + (542, -1, -1, 255, 255, 2, 63, -1, 0, 0, 4, 257, 543), + (543, -1, -1, 255, 255, 4, 64, -1, 0, 0, 4, 542, 544), + (544, -1, -1, 255, 255, 6, 65, -1, 0, 0, 4, 543, 1163), + (545, 545, 545, 545, 545, 3, 61, 3271, 3, 900, 4, -1, 546), + (546, 545, 545, 545, 545, 3, 63, 3272, 3, 900, 4, 545, 547), + (547, 545, 545, 545, 545, 3, 65, 3273, 3, 900, 4, 546, 1293), + (548, 548, 548, 548, 548, 4, 61, 3277, 5, 900, 4, -1, 549), + (549, 548, 548, 548, 548, 3, 63, 3278, 5, 900, 4, 548, 550), + (550, 548, 548, 548, 548, 2, 65, 3279, 5, 900, 4, 549, 1225), + (551, -1, -1, 551, 551, 2, 61, -1, 0, 0, 4, -1, 552), + (552, -1, -1, 551, 551, 2, 62, -1, 0, 0, 4, 551, 553), + (553, -1, -1, 551, 551, 2, 63, -1, 0, 0, 4, 552, 554), + (554, -1, -1, 551, 551, 2, 64, -1, 0, 0, 4, 553, 555), + (555, -1, -1, 551, 551, 2, 65, -1, 0, 0, 4, 554, 1633), + (556, -1, -1, 556, 556, 2, 61, -1, 0, 0, 4, -1, 557), + (557, -1, -1, 556, 556, 2, 62, -1, 0, 0, 4, 556, 558), + (558, -1, -1, 556, 556, 2, 63, -1, 0, 0, 4, 557, 559), + (559, -1, -1, 556, 556, 2, 64, -1, 0, 0, 4, 558, 560), + (560, -1, -1, 556, 556, 2, 65, -1, 0, 0, 4, 559, 1563), + (561, -1, -1, 561, 561, 2, 61, -1, 0, 0, 4, -1, 562), + (562, -1, -1, 561, 561, 4, 63, -1, 0, 0, 4, 561, 563), + (563, -1, -1, 561, 561, 6, 65, -1, 0, 0, 4, 562, 1624), + (564, -1, -1, 564, 564, 3, 61, -1, 0, 0, 4, -1, 565), + (565, -1, -1, 564, 564, 3, 63, -1, 0, 0, 4, 564, 566), + (566, -1, -1, 564, 564, 3, 65, -1, 0, 0, 4, 565, 1621), + (567, -1, -1, 567, 567, 5, 63, -1, 0, 0, 4, -1, 5061), + (574, -1, -1, 574, 574, 3, 61, -1, 0, 0, 4, -1, 575), + (575, -1, -1, 574, 574, 3, 63, -1, 0, 0, 4, 574, 576), + (576, -1, -1, 574, 574, 3, 65, -1, 0, 0, 4, 575, 7718), + (577, -1, -1, 577, 577, 2, 61, -1, 0, 0, 4, -1, 578), + (578, -1, -1, 577, 577, 4, 63, -1, 0, 0, 4, 577, 579), + (579, -1, -1, 577, 577, 6, 65, -1, 0, 0, 4, 578, -1), + (580, -1, -1, 580, 580, 4, 61, -1, 0, 0, 4, -1, 581), + (581, -1, -1, 580, 580, 3, 63, -1, 0, 0, 4, 580, 582), + (582, -1, -1, 580, 580, 2, 65, -1, 0, 0, 4, 581, -1), + (583, -1, -1, 583, 583, 2, 63, -1, 0, 0, 4, -1, 584), + (584, -1, -1, 583, 583, 2, 64, -1, 0, 0, 4, 583, 585), + (585, -1, -1, 583, 583, 2, 65, -1, 0, 0, 4, 584, -1), + (586, -1, -1, 586, 586, 2, 61, -1, 0, 0, 4, -1, 587), + (587, -1, -1, 586, 586, 4, 63, -1, 0, 0, 4, 586, 588), + (588, -1, -1, 586, 586, 6, 65, -1, 0, 0, 4, 587, 6130), + (589, -1, -1, 589, 589, 3, 61, -1, 0, 0, 4, -1, 590), + (590, -1, -1, 589, 589, 3, 63, -1, 0, 0, 4, 589, 591), + (591, -1, -1, 589, 589, 3, 65, -1, 0, 0, 4, 590, 893), + (592, 592, 592, 592, 592, 6, 63, 3282, 2, 18, 4, -1, 702), + (593, -1, -1, 593, 593, 3, 61, -1, 0, 0, 4, -1, 594), + (594, -1, -1, 593, 593, 3, 63, -1, 0, 0, 4, 593, 595), + (595, -1, -1, 593, 593, 3, 65, -1, 0, 0, 4, 594, 5972), + (596, -1, -1, 596, 596, 2, 61, -1, 0, 0, 4, -1, 597), + (597, -1, -1, 596, 596, 4, 63, -1, 0, 0, 4, 596, 598), + (598, -1, -1, 596, 596, 6, 65, -1, 0, 0, 4, 597, 5973), + (599, -1, -1, 599, 599, 2, 61, -1, 0, 0, 4, -1, 600), + (600, -1, -1, 599, 599, 4, 63, -1, 0, 0, 4, 599, 601), + (601, -1, -1, 599, 599, 6, 65, -1, 0, 0, 4, 600, 1536), + (602, -1, -1, 602, 602, 3, 61, -1, 0, 0, 4, -1, 603), + (603, -1, -1, 602, 602, 3, 63, -1, 0, 0, 4, 602, 604), + (604, -1, -1, 602, 602, 3, 65, -1, 0, 0, 4, 603, 1533), + (605, -1, -1, 605, 605, 6, 63, -1, 0, 0, 4, -1, -1), + (606, -1, -1, 606, 606, 1, 61, -1, 0, 0, 4, -1, 607), + (607, -1, -1, 606, 606, 1, 62, -1, 0, 0, 4, 606, 608), + (608, -1, -1, 606, 606, 1, 63, -1, 0, 0, 4, 607, 609), + (609, -1, -1, 606, 606, 1, 64, -1, 0, 0, 4, 608, 610), + (610, -1, -1, 606, 606, 1, 65, -1, 0, 0, 4, 609, -1), + (611, -1, -1, 611, 611, 2, 61, -1, 0, 0, 4, -1, 612), + (612, -1, -1, 611, 611, 2, 62, -1, 0, 0, 4, 611, 613), + (613, -1, -1, 611, 611, 2, 63, -1, 0, 0, 4, 612, 614), + (614, -1, -1, 611, 611, 2, 64, -1, 0, 0, 4, 613, 615), + (615, -1, -1, 611, 611, 2, 65, -1, 0, 0, 4, 614, 7175), + (616, 616, 616, 616, 616, 5, 63, 3286, 7, 900, 4, -1, 617), + (617, 616, 616, 616, 616, 4, 64, 3287, 7, 900, 4, 616, 618), + (618, 616, 616, 616, 616, 3, 65, 3288, 7, 900, 4, 617, 1248), + (619, 619, 619, 619, 619, 3, 61, 3292, 6, 900, 4, -1, 620), + (620, 619, 619, 619, 619, 2, 63, 3293, 6, 900, 4, 619, 621), + (621, 619, 619, 619, 619, 1, 65, 3294, 6, 900, 4, 620, 721), + (622, -1, -1, 622, 622, 3, 61, -1, 0, 0, 4, -1, 623), + (623, -1, -1, 622, 622, 3, 62, -1, 0, 0, 4, 622, 624), + (624, -1, -1, 622, 622, 3, 63, -1, 0, 0, 4, 623, 8329), + (625, -1, -1, 625, 625, 1, 61, -1, 0, 0, 4, -1, 626), + (626, -1, -1, 625, 625, 2, 63, -1, 0, 0, 4, 625, 627), + (627, -1, -1, 625, 625, 3, 65, -1, 0, 0, 4, 626, 4733), + (628, -1, -1, 628, 628, 2, 62, -1, 0, 0, 4, -1, 629), + (629, -1, -1, 628, 628, 4, 64, -1, 0, 0, 4, 628, -1), + (630, 630, 630, 630, 630, 6, 63, 5243, 7, 1, 4, -1, -1), + (631, -1, -1, 631, 631, 2, 61, -1, 0, 0, 4, -1, 632), + (632, -1, -1, 631, 631, 3, 63, -1, 0, 0, 4, 631, 633), + (633, -1, -1, 631, 631, 4, 65, -1, 0, 0, 4, 632, 1172), + (634, -1, -1, 634, 634, 1, 61, -1, 0, 0, 4, -1, 635), + (635, -1, -1, 634, 634, 2, 63, -1, 0, 0, 4, 634, 636), + (636, -1, -1, 634, 634, 3, 65, -1, 0, 0, 4, 635, 844), + (637, -1, -1, 637, 637, 3, 61, -1, 0, 0, 4, -1, 638), + (638, -1, -1, 637, 637, 6, 63, -1, 0, 0, 4, 637, 639), + (639, -1, -1, 637, 637, 9, 65, -1, 0, 0, 4, 638, 770), + (640, -1, -1, 267, 267, 2, 61, -1, 0, 0, 4, 269, 641), + (641, -1, -1, 267, 267, 4, 63, -1, 0, 0, 4, 640, 642), + (642, -1, -1, 267, 267, 6, 65, -1, 0, 0, 4, 641, 924), + (643, 643, 643, 643, 643, 4, 62, 5227, 0, 1, 4, -1, -1), + (644, -1, -1, 644, 644, 4, 60, -1, 0, 0, 4, -1, 1601), + (645, 645, -1, 645, 645, 4, 64, 3614, 4, 5, 4, -1, 5999), + (649, -1, -1, 649, 649, 2, 61, -1, 0, 0, 4, -1, 650), + (650, -1, -1, 649, 649, 4, 63, -1, 0, 0, 4, 649, 651), + (651, -1, -1, 649, 649, 6, 65, -1, 0, 0, 4, 650, 5860), + (652, -1, -1, 652, 652, 2, 61, -1, 0, 0, 4, -1, 653), + (653, -1, -1, 652, 652, 4, 63, -1, 0, 0, 4, 652, 654), + (654, -1, -1, 652, 652, 6, 65, -1, 0, 0, 4, 653, -1), + (655, -1, -1, 655, 655, 3, 59, -1, 0, 0, 3, -1, 656), + (656, -1, -1, 655, 655, 6, 59, -1, 0, 0, 3, 655, 657), + (657, -1, -1, 655, 655, 9, 59, -1, 0, 0, 3, 656, -1), + (658, -1, -1, 658, 658, 2, 55, -1, 0, 0, 3, -1, 659), + (659, -1, -1, 658, 658, 4, 55, -1, 0, 0, 3, 658, 660), + (660, -1, -1, 658, 658, 6, 55, -1, 0, 0, 3, 659, 5306), + (661, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, -1, 662), + (662, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, 661, 663), + (663, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, 662, 674), + (665, -1, -1, 270, 665, 3, 59, -1, 0, 0, 3, -1, 666), + (666, -1, -1, 270, 665, 6, 59, -1, 0, 0, 3, 665, 667), + (667, -1, -1, 270, 665, 9, 59, -1, 0, 0, 3, 666, 668), + (668, -1, -1, 270, 665, 2, 63, -1, 0, 0, 4, 667, 669), + (669, -1, -1, 270, 665, 2, 64, -1, 0, 0, 4, 668, 670), + (670, -1, -1, 270, 665, 2, 65, -1, 0, 0, 4, 669, 7612), + (671, -1, -1, 671, 671, 3, 59, -1, 0, 0, 3, -1, -1), + (672, -1, -1, 62, 62, 5, 61, -1, 0, 0, 7, 64, 673), + (673, -1, -1, 62, 62, 5, 61, -1, 0, 0, 7, 672, -1), + (674, -1, -1, 65, 661, 3, 61, -1, 0, 0, 7, 663, 675), + (675, -1, -1, 65, 661, 3, 61, -1, 0, 0, 7, 674, 1031), + (676, -1, -1, 71, 71, 2, 61, -1, 0, 0, 7, 73, 677), + (677, -1, -1, 71, 71, 3, 61, -1, 0, 0, 7, 676, 978), + (678, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, -1, 679), + (679, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 678, 680), + (680, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 679, 681), + (681, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 680, 682), + (682, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 681, 6518), + (683, -1, -1, 683, 683, 3, 61, -1, 0, 0, 7, -1, 684), + (684, -1, -1, 683, 683, 6, 61, -1, 0, 0, 7, 683, 685), + (685, -1, -1, 683, 683, 9, 61, -1, 0, 0, 7, 684, 1036), + (686, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, -1, 687), + (687, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 686, 688), + (688, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 687, 689), + (689, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 688, 690), + (690, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 689, 7640), + (691, -1, -1, 691, 691, 9, 55, -1, 0, 0, 7, -1, -1), + (692, -1, -1, 692, 692, 3, 55, -1, 0, 0, 7, -1, 693), + (693, -1, -1, 692, 692, 6, 55, -1, 0, 0, 7, 692, 694), + (694, -1, -1, 692, 692, 9, 55, -1, 0, 0, 7, 693, 7647), + (695, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, -1, 696), + (696, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 695, 697), + (697, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 696, 698), + (698, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 697, 699), + (699, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 698, 15529), + (700, -1, -1, 213, 213, 9, 61, -1, 0, 0, 7, 215, -1), + (701, -1, -1, 275, 275, 9, 61, -1, 0, 0, 7, 277, -1), + (702, 592, 592, 592, 592, 3, 65, 4842, 2, 18, 7, 592, 703), + (703, 592, 592, 592, 592, 3, 65, 4843, 2, 18, 7, 702, 704), + (704, 592, 592, 592, 592, 3, 65, 4844, 2, 18, 7, 703, 705), + (705, 592, 592, 592, 592, 3, 65, 4845, 2, 18, 7, 704, 706), + (706, 592, 592, 592, 592, 3, 65, 4846, 2, 18, 7, 705, 1102), + (715, 534, 534, 534, 534, 3, 65, 5112, 4, 2160, 7, 536, 716), + (716, 534, 534, 534, 534, 6, 65, 5113, 4, 2160, 7, 715, 717), + (717, 534, 534, 534, 534, 9, 65, 5114, 4, 2160, 7, 716, 1278), + (718, 718, 718, 718, 718, 3, 65, 4521, 7, 4320, 7, -1, 719), + (719, 718, 718, 718, 718, 6, 65, 4522, 7, 4320, 7, 718, 720), + (720, 718, 718, 718, 718, 9, 65, 4523, 7, 4320, 7, 719, 1019), + (721, 619, 619, 619, 619, 5, 65, 5110, 6, 900, 7, 621, 722), + (722, 619, 619, 619, 619, 5, 65, 5111, 6, 900, 7, 721, 6296), + (723, 723, 723, 723, 723, 9, 65, 4788, 6, 30, 7, -1, 4963), + (724, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, -1, 725), + (725, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 724, 726), + (726, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 725, 727), + (727, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 726, 728), + (728, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 727, 5254), + (729, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, -1, 730), + (730, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 729, 731), + (731, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 730, 732), + (732, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 731, 733), + (733, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 732, 1467), + (734, -1, -1, 734, 734, 12, 65, -1, 0, 0, 7, -1, -1), + (735, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, -1, 736), + (736, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, 735, 737), + (737, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, 736, 7056), + (738, -1, -1, 98, 738, 3, 55, -1, 0, 0, 7, -1, 739), + (739, -1, -1, 98, 738, 6, 55, -1, 0, 0, 7, 738, 740), + (740, -1, -1, 98, 738, 9, 55, -1, 0, 0, 7, 739, 5317), + (746, 746, 746, 746, 746, 3, 65, 4549, 10, 2160, 7, -1, 747), + (747, 746, 746, 746, 746, 6, 65, 4550, 10, 2160, 7, 746, 748), + (748, 746, 746, 746, 746, 9, 65, 4551, 10, 2160, 7, 747, 1491), + (749, 749, 749, 749, 749, 5, 65, 4790, 11, 1800, 7, -1, 750), + (750, 749, 749, 749, 749, 5, 65, 4791, 11, 1800, 7, 749, 751), + (751, 749, 749, 749, 749, 5, 65, 4792, 11, 1800, 7, 750, 752), + (752, 749, 749, 749, 749, 5, 65, 4793, 11, 1800, 7, 751, 753), + (753, 749, 749, 749, 749, 5, 65, 4794, 11, 1800, 7, 752, 1206), + (754, -1, -1, 754, 754, 3, 65, -1, 0, 0, 7, -1, 755), + (755, -1, -1, 754, 754, 6, 65, -1, 0, 0, 7, 754, 756), + (756, -1, -1, 754, 754, 9, 65, -1, 0, 0, 7, 755, 7659), + (757, 757, -1, 757, 757, 5, 65, 4796, 6, 1800, 7, -1, 758), + (758, 757, -1, 757, 757, 5, 65, 4797, 6, 1800, 7, 757, 759), + (759, 757, -1, 757, 757, 5, 65, 4798, 6, 1800, 7, 758, 760), + (760, 757, -1, 757, 757, 5, 65, 4799, 6, 1800, 7, 759, 761), + (761, 757, -1, 757, 757, 5, 65, 4800, 6, 1800, 7, 760, 1222), + (762, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, -1, 763), + (763, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 762, 764), + (764, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 763, 765), + (765, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 764, 766), + (766, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 765, -1), + (767, -1, -1, 767, 767, 3, 65, -1, 0, 0, 7, -1, 768), + (768, -1, -1, 767, 767, 6, 65, -1, 0, 0, 7, 767, 769), + (769, -1, -1, 767, 767, 9, 65, -1, 0, 0, 7, 768, 1099), + (770, -1, -1, 637, 637, 3, 65, -1, 0, 0, 7, 639, 771), + (771, -1, -1, 637, 637, 6, 65, -1, 0, 0, 7, 770, 772), + (772, -1, -1, 637, 637, 9, 65, -1, 0, 0, 7, 771, 4749), + (773, 773, -1, 773, 773, 3, 65, 4552, 5, 1800, 7, -1, 774), + (774, 773, -1, 773, 773, 6, 65, 4553, 5, 1800, 7, 773, 775), + (775, 773, -1, 773, 773, 9, 65, 4554, 5, 1800, 7, 774, 5854), + (776, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, -1, 777), + (777, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 776, 778), + (778, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 777, 779), + (779, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 778, 780), + (780, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 779, -1), + (781, -1, -1, 781, 781, 12, 65, -1, 0, 0, 7, -1, 5850), + (782, -1, -1, 782, 782, 3, 65, -1, 0, 0, 7, -1, 783), + (783, -1, -1, 782, 782, 6, 65, -1, 0, 0, 7, 782, 784), + (784, -1, -1, 782, 782, 9, 65, -1, 0, 0, 7, 783, -1), + (785, 785, 785, 785, 785, 5, 65, 5235, 8, 900, 7, -1, 786), + (786, 785, 785, 785, 785, 5, 65, 5236, 8, 900, 7, 785, 787), + (787, 785, 785, 785, 785, 5, 65, 5237, 8, 900, 7, 786, 788), + (788, 785, 785, 785, 785, 5, 65, 5238, 8, 900, 7, 787, 789), + (789, 785, 785, 785, 785, 5, 65, 5239, 8, 900, 7, 788, 15235), + (790, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, -1, 791), + (791, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 790, 792), + (792, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 791, 793), + (793, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 792, 794), + (794, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 793, 5259), + (795, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, -1, 796), + (796, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 795, 797), + (797, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 796, 798), + (798, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 797, 799), + (799, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 798, 1430), + (800, -1, -1, 800, 800, 3, 65, -1, 0, 0, 7, -1, 801), + (801, -1, -1, 800, 800, 6, 65, -1, 0, 0, 7, 800, 802), + (802, -1, -1, 800, 800, 9, 65, -1, 0, 0, 7, 801, -1), + (803, -1, -1, 803, 803, 3, 65, -1, 0, 0, 7, -1, 804), + (804, -1, -1, 803, 803, 6, 65, -1, 0, 0, 7, 803, 805), + (805, -1, -1, 803, 803, 9, 65, -1, 0, 0, 7, 804, -1), + (806, -1, -1, 806, 806, 12, 65, -1, 0, 0, 7, -1, -1), + (807, -1, -1, 807, 807, 3, 65, -1, 0, 0, 7, -1, 808), + (808, -1, -1, 807, 807, 6, 65, -1, 0, 0, 7, 807, 809), + (809, -1, -1, 807, 807, 9, 65, -1, 0, 0, 7, 808, 1268), + (810, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, -1, 811), + (811, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 810, 812), + (812, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 811, 813), + (813, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 812, 814), + (814, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 813, 4824), + (815, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, -1, 816), + (816, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 815, 817), + (817, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 816, 818), + (818, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 817, 819), + (819, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 818, 5141), + (820, -1, -1, 820, 820, 3, 65, -1, 0, 0, 7, -1, 821), + (821, -1, -1, 820, 820, 6, 65, -1, 0, 0, 7, 820, 822), + (822, -1, -1, 820, 820, 9, 65, -1, 0, 0, 7, 821, 1265), + (823, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, -1, 824), + (824, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 823, 825), + (825, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 824, 826), + (826, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 825, 827), + (827, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 826, -1), + (828, 828, 828, 828, 828, 3, 65, 5240, 2, 3600, 7, -1, 829), + (829, 828, 828, 828, 828, 6, 65, 5241, 2, 3600, 7, 828, 830), + (830, 828, 828, 828, 828, 9, 65, 5242, 2, 3600, 7, 829, 16250), + (834, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, -1, 835), + (835, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 834, 836), + (836, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 835, 837), + (837, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 836, 838), + (838, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 837, -1), + (839, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, -1, 840), + (840, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 839, 841), + (841, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 840, 842), + (842, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 841, 843), + (843, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 842, 5325), + (844, -1, -1, 634, 634, 5, 65, -1, 0, 0, 7, 636, 845), + (845, -1, -1, 634, 634, 5, 65, -1, 0, 0, 7, 844, 1319), + (846, -1, -1, 846, 846, 3, 65, -1, 0, 0, 7, -1, 847), + (847, -1, -1, 846, 846, 6, 65, -1, 0, 0, 7, 846, 848), + (848, -1, -1, 846, 846, 9, 65, -1, 0, 0, 7, 847, 1301), + (849, -1, -1, 849, 849, 3, 65, -1, 0, 0, 7, -1, 850), + (850, -1, -1, 849, 849, 6, 65, -1, 0, 0, 7, 849, 851), + (851, -1, -1, 849, 849, 9, 65, -1, 0, 0, 7, 850, 10621), + (852, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, -1, 853), + (853, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, 852, 854), + (854, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, 853, 5500), + (855, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, -1, 856), + (856, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 855, 857), + (857, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 856, 858), + (858, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 857, 859), + (859, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 858, 7673), + (860, 860, 860, 860, 860, 3, 65, 3297, 5, 180, 7, -1, 861), + (861, 860, 860, 860, 860, 6, 65, 3298, 5, 180, 7, 860, 862), + (862, 860, 860, 860, 860, 9, 65, 3299, 5, 180, 7, 861, 5130), + (863, 863, -1, 863, 863, 12, 65, 5248, 6, 4320, 7, -1, -1), + (864, -1, -1, 864, 864, 3, 65, -1, 0, 0, 7, -1, 865), + (865, -1, -1, 864, 864, 6, 65, -1, 0, 0, 7, 864, 866), + (866, -1, -1, 864, 864, 9, 65, -1, 0, 0, 7, 865, 1290), + (867, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, -1, 868), + (868, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 867, 869), + (869, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 868, 870), + (870, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 869, 871), + (871, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 870, 7362), + (872, 872, 872, 872, 872, 3, 65, 4802, 5, 180, 7, -1, 873), + (873, 872, 872, 872, 872, 6, 65, 4803, 5, 180, 7, 872, 874), + (874, 872, 872, 872, 872, 9, 65, 4804, 5, 180, 7, 873, 7367), + (875, 875, 875, 875, 875, 3, 65, 4805, 5, 180, 7, -1, 876), + (876, 875, 875, 875, 875, 6, 65, 4806, 5, 180, 7, 875, 877), + (877, 875, 875, 875, 875, 9, 65, 4807, 5, 180, 7, 876, 7370), + (878, -1, -1, 878, 878, 3, 65, -1, 0, 0, 7, -1, 879), + (879, -1, -1, 878, 878, 6, 65, -1, 0, 0, 7, 878, 880), + (880, -1, -1, 878, 878, 9, 65, -1, 0, 0, 7, 879, 1539), + (881, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, -1, 882), + (882, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 881, 883), + (883, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 882, 884), + (884, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 883, 885), + (885, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 884, -1), + (886, -1, -1, 498, 498, 5, 65, -1, 0, 0, 7, 500, 887), + (887, -1, -1, 498, 498, 5, 65, -1, 0, 0, 7, 886, 975), + (888, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, -1, 889), + (889, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 888, 890), + (890, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 889, 891), + (891, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 890, 892), + (892, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 891, 16267), + (893, -1, -1, 589, 589, 5, 65, -1, 0, 0, 7, 591, 894), + (894, -1, -1, 589, 589, 5, 65, -1, 0, 0, 7, 893, 5270), + (895, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, -1, 896), + (896, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 895, 897), + (897, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 896, 898), + (898, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 897, 899), + (899, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 898, 6075), + (900, 528, 528, 528, 528, 5, 65, 4826, 5, 720, 7, 530, 901), + (901, 528, 528, 528, 528, 5, 65, 4827, 5, 720, 7, 900, 6103), + (907, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, -1, 908), + (908, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 907, 909), + (909, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 908, 910), + (910, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 909, 911), + (911, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 910, 5243), + (912, 912, 912, 912, 912, 3, 65, 4925, 4, 3600, 7, -1, 913), + (913, 912, 912, 912, 912, 6, 65, 4926, 4, 3600, 7, 912, 914), + (914, 912, 912, 912, 912, 9, 65, 4927, 4, 3600, 7, 913, 1330), + (915, -1, -1, 915, 915, 3, 65, -1, 0, 0, 7, -1, 916), + (916, -1, -1, 915, 915, 6, 65, -1, 0, 0, 7, 915, 917), + (917, -1, -1, 915, 915, 9, 65, -1, 0, 0, 7, 916, -1), + (918, -1, -1, 918, 918, 3, 65, -1, 0, 0, 7, -1, 919), + (919, -1, -1, 918, 918, 6, 65, -1, 0, 0, 7, 918, 920), + (920, -1, -1, 918, 918, 9, 65, -1, 0, 0, 7, 919, -1), + (921, 921, 921, 921, 921, 12, 65, 4833, 8, 60, 7, -1, 1340), + (922, 922, 922, 922, 922, 12, 65, 4834, 8, 60, 7, -1, 1341), + (923, 923, 923, 923, 923, 12, 65, 4835, 8, 60, 7, -1, 1342), + (924, -1, -1, 267, 267, 5, 65, -1, 0, 0, 7, 642, 925), + (925, -1, -1, 267, 267, 5, 65, -1, 0, 0, 7, 924, 5133), + (926, 926, 926, 926, 926, 3, 65, 4836, 12, 1800, 7, -1, 927), + (927, 926, 926, 926, 926, 3, 65, 4837, 12, 1800, 7, 926, 928), + (928, 926, 926, 926, 926, 3, 65, 4838, 12, 1800, 7, 927, 929), + (929, 926, 926, 926, 926, 3, 65, 4839, 12, 1800, 7, 928, 930), + (930, 926, 926, 926, 926, 3, 65, 4840, 12, 1800, 7, 929, 14991), + (931, 931, 931, 931, 931, 3, 65, 5245, 13, 4320, 7, -1, 932), + (932, 931, 931, 931, 931, 6, 65, 5246, 13, 4320, 7, 931, 933), + (933, 931, 931, 931, 931, 9, 65, 5247, 13, 4320, 7, 932, -1), + (934, -1, -1, 113, 934, 2, 55, -1, 0, 0, 3, -1, 935), + (935, -1, -1, 113, 934, 4, 55, -1, 0, 0, 3, 934, 936), + (936, -1, -1, 113, 934, 6, 55, -1, 0, 0, 3, 935, 943), + (937, -1, -1, 113, 937, 2, 55, -1, 0, 0, 3, -1, 938), + (938, -1, -1, 113, 937, 4, 55, -1, 0, 0, 3, 937, 939), + (939, -1, -1, 113, 937, 6, 55, -1, 0, 0, 3, 938, 946), + (940, -1, -1, 113, 940, 2, 55, -1, 0, 0, 3, -1, 941), + (941, -1, -1, 113, 940, 4, 55, -1, 0, 0, 3, 940, 942), + (942, -1, -1, 113, 940, 6, 55, -1, 0, 0, 3, 941, 949), + (943, -1, -1, 113, 934, 3, 62, -1, 0, 0, 4, 936, 944), + (944, -1, -1, 113, 934, 3, 63, -1, 0, 0, 4, 943, 945), + (945, -1, -1, 113, 934, 3, 64, -1, 0, 0, 4, 944, -1), + (946, -1, -1, 113, 937, 3, 62, -1, 0, 0, 4, 939, 947), + (947, -1, -1, 113, 937, 3, 63, -1, 0, 0, 4, 946, 948), + (948, -1, -1, 113, 937, 3, 64, -1, 0, 0, 4, 947, -1), + (949, -1, -1, 113, 940, 3, 62, -1, 0, 0, 4, 942, 950), + (950, -1, -1, 113, 940, 3, 63, -1, 0, 0, 4, 949, 951), + (951, -1, -1, 113, 940, 3, 64, -1, 0, 0, 4, 950, -1), + (952, -1, -1, 952, 952, 3, 61, -1, 0, 0, 4, -1, 953), + (953, -1, -1, 952, 952, 3, 63, -1, 0, 0, 4, 952, 954), + (954, -1, -1, 952, 952, 3, 65, -1, 0, 0, 4, 953, -1), + (955, -1, -1, 955, 955, 3, 61, -1, 0, 0, 4, -1, 956), + (956, -1, -1, 955, 955, 3, 62, -1, 0, 0, 4, 955, 957), + (957, -1, -1, 955, 955, 3, 63, -1, 0, 0, 4, 956, 958), + (958, -1, -1, 955, 955, 3, 64, -1, 0, 0, 4, 957, 959), + (959, -1, -1, 955, 955, 3, 65, -1, 0, 0, 4, 958, -1), + (960, 960, 960, 960, 960, 9, 59, 2760, 7, 4320, 3, -1, -1), + (961, 961, 961, 961, 961, 9, 59, 2759, 11, 4320, 3, -1, -1), + (962, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, -1, 963), + (963, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 962, 964), + (964, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 963, 965), + (965, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 964, 966), + (966, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 965, 6223), + (967, 967, 967, 967, 967, 3, 65, 4564, 10, 1800, 7, -1, 968), + (968, 967, 967, 967, 967, 6, 65, 4565, 10, 1800, 7, 967, 969), + (969, 967, 967, 967, 967, 9, 65, 4566, 10, 1800, 7, 968, 6464), + (970, 970, 970, 970, 970, 5, 65, 4828, 6, 1800, 7, -1, 971), + (971, 970, 970, 970, 970, 5, 65, 4829, 6, 1800, 7, 970, 972), + (972, 970, 970, 970, 970, 5, 65, 4830, 6, 1800, 7, 971, 973), + (973, 970, 970, 970, 970, 5, 65, 4831, 6, 1800, 7, 972, 974), + (974, 970, 970, 970, 970, 5, 65, 4832, 6, 1800, 7, 973, 1324), + (975, -1, -1, 498, 498, 5, 65, -1, 0, 0, 15, 887, 13262), + (976, -1, -1, 976, 976, 5, 59, -1, 0, 0, 15, -1, -1), + (977, 977, 977, 977, 977, 6, 64, 13835, 72, 600, 15, -1, -1), + (978, -1, -1, 71, 71, 5, 68, -1, 0, 0, 8, 677, -1), + (979, -1, -1, 979, 979, 3, 59, -1, 0, 0, 8, -1, 980), + (980, -1, -1, 979, 979, 6, 59, -1, 0, 0, 8, 979, 981), + (981, -1, -1, 979, 979, 9, 59, -1, 0, 0, 8, 980, -1), + (982, -1, -1, 982, 982, 3, 59, -1, 0, 0, 8, -1, 983), + (983, -1, -1, 982, 982, 6, 59, -1, 0, 0, 8, 982, 984), + (984, -1, -1, 982, 982, 9, 59, -1, 0, 0, 8, 983, -1), + (985, -1, -1, 985, 985, 3, 59, -1, 0, 0, 8, -1, 986), + (986, -1, -1, 985, 985, 6, 59, -1, 0, 0, 8, 985, 987), + (987, -1, -1, 985, 985, 9, 59, -1, 0, 0, 8, 986, -1), + (988, -1, -1, 988, 988, 3, 59, -1, 0, 0, 8, -1, 989), + (989, -1, -1, 988, 988, 6, 59, -1, 0, 0, 8, 988, 990), + (990, -1, -1, 988, 988, 9, 59, -1, 0, 0, 8, 989, -1), + (991, -1, -1, 991, 991, 3, 59, -1, 0, 0, 8, -1, 992), + (992, -1, -1, 991, 991, 6, 59, -1, 0, 0, 8, 991, 993), + (993, -1, -1, 991, 991, 9, 59, -1, 0, 0, 8, 992, -1), + (994, -1, -1, 994, 994, 3, 59, -1, 0, 0, 8, -1, 995), + (995, -1, -1, 994, 994, 6, 59, -1, 0, 0, 8, 994, 996), + (996, -1, -1, 994, 994, 9, 59, -1, 0, 0, 8, 995, -1), + (997, -1, -1, 997, 997, 5, 60, -1, 0, 0, 8, -1, 998), + (998, -1, -1, 997, 997, 5, 65, -1, 0, 0, 8, 997, 999), + (999, -1, -1, 997, 997, 5, 70, -1, 0, 0, 8, 998, 1113), + (1000, 1000, -1, 1000, 1000, 0, 5, 5824, 20, 1080, 0, -1, -1), + (1001, -1, -1, 418, 418, 5, 66, -1, 0, 0, 8, 422, 1002), + (1002, -1, -1, 418, 418, 5, 67, -1, 0, 0, 8, 1001, 1003), + (1003, -1, -1, 418, 418, 5, 68, -1, 0, 0, 8, 1002, 1004), + (1004, -1, -1, 418, 418, 5, 69, -1, 0, 0, 8, 1003, 1005), + (1005, -1, -1, 418, 418, 5, 70, -1, 0, 0, 8, 1004, 4678), + (1006, -1, -1, 1006, 1006, 5, 66, -1, 0, 0, 8, -1, 1007), + (1007, -1, -1, 1006, 1006, 5, 67, -1, 0, 0, 8, 1006, 1008), + (1008, -1, -1, 1006, 1006, 5, 68, -1, 0, 0, 8, 1007, 1009), + (1009, -1, -1, 1006, 1006, 5, 69, -1, 0, 0, 8, 1008, 1010), + (1010, -1, -1, 1006, 1006, 5, 70, -1, 0, 0, 8, 1009, 7516), + (1011, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, -1, 1012), + (1012, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1011, 1013), + (1013, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1012, 1014), + (1014, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1013, 1015), + (1016, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1015, -1), + (1017, 1017, 1017, 1017, 1017, 6, 59, 16531, 75, 15, 15, -1, 13726), + (1018, 1018, 1018, 1018, 1018, 2, 63, 16455, 69, 1, 15, -1, -1), + (1019, 718, 718, 718, 718, 12, 65, 21746, 7, 4320, 16, 720, 13454), + (1021, -1, -1, 1021, 1021, 5, 51, -1, 0, 0, 8, -1, 1022), + (1022, -1, -1, 1021, 1021, 5, 55, -1, 0, 0, 8, 1021, 1023), + (1023, -1, -1, 1021, 1021, 5, 60, -1, 0, 0, 8, 1022, 1024), + (1024, -1, -1, 1021, 1021, 5, 65, -1, 0, 0, 8, 1023, 1025), + (1025, -1, -1, 1021, 1021, 5, 70, -1, 0, 0, 8, 1024, 6521), + (1026, -1, -1, 1026, 1026, 3, 66, -1, 0, 0, 8, -1, 1027), + (1027, -1, -1, 1026, 1026, 3, 67, -1, 0, 0, 8, 1026, 1028), + (1028, -1, -1, 1026, 1026, 3, 68, -1, 0, 0, 8, 1027, 1029), + (1029, -1, -1, 1026, 1026, 3, 69, -1, 0, 0, 8, 1028, 1030), + (1030, -1, -1, 1026, 1026, 3, 70, -1, 0, 0, 8, 1029, 1389), + (1031, -1, -1, 65, 661, 3, 66, -1, 0, 0, 8, 675, 1032), + (1032, -1, -1, 65, 661, 3, 67, -1, 0, 0, 8, 1031, 1033), + (1033, -1, -1, 65, 661, 3, 68, -1, 0, 0, 8, 1032, 1034), + (1034, -1, -1, 65, 661, 3, 69, -1, 0, 0, 8, 1033, 1035), + (1035, -1, -1, 65, 661, 3, 70, -1, 0, 0, 8, 1034, 4693), + (1036, -1, -1, 683, 683, 5, 66, -1, 0, 0, 8, 685, 1037), + (1037, -1, -1, 683, 683, 5, 68, -1, 0, 0, 8, 1036, 1038), + (1038, -1, -1, 683, 683, 5, 70, -1, 0, 0, 8, 1037, 5301), + (1041, -1, -1, 1041, 1041, 3, 67, -1, 0, 0, 8, -1, 1042), + (1042, -1, -1, 1041, 1041, 6, 68, -1, 0, 0, 8, 1041, 1043), + (1043, -1, -1, 1041, 1041, 9, 69, -1, 0, 0, 8, 1042, 4707), + (1044, -1, -1, 1044, 1044, 3, 67, -1, 0, 0, 8, -1, 1045), + (1045, -1, -1, 1044, 1044, 6, 68, -1, 0, 0, 8, 1044, 1046), + (1046, -1, -1, 1044, 1044, 9, 69, -1, 0, 0, 8, 1045, 4710), + (1047, -1, -1, 1047, 1047, 3, 67, -1, 0, 0, 8, -1, 1048), + (1048, -1, -1, 1047, 1047, 6, 68, -1, 0, 0, 8, 1047, 1049), + (1049, -1, -1, 1047, 1047, 9, 69, -1, 0, 0, 8, 1048, 4713), + (1050, -1, -1, 1050, 1050, 3, 67, -1, 0, 0, 8, -1, 1051), + (1051, -1, -1, 1050, 1050, 6, 68, -1, 0, 0, 8, 1050, 1052), + (1052, -1, -1, 1050, 1050, 9, 69, -1, 0, 0, 8, 1051, 4716), + (1053, -1, -1, 119, 119, 3, 66, -1, 0, 0, 8, 442, 1054), + (1054, -1, -1, 119, 119, 3, 68, -1, 0, 0, 8, 1053, 1055), + (1055, -1, -1, 119, 119, 3, 70, -1, 0, 0, 8, 1054, 4722), + (1056, -1, -1, 1056, 1056, 5, 71, -1, 0, 0, 12, -1, 1057), + (1057, -1, -1, 1056, 1056, 5, 72, -1, 0, 0, 12, 1056, 1058), + (1058, -1, -1, 1056, 1056, 5, 73, -1, 0, 0, 12, 1057, 1059), + (1059, -1, -1, 1056, 1056, 5, 74, -1, 0, 0, 12, 1058, 1060), + (1060, -1, -1, 1056, 1056, 5, 75, -1, 0, 0, 12, 1059, 6431), + (1061, -1, -1, 125, 125, 5, 66, -1, 0, 0, 8, 453, 1062), + (1062, -1, -1, 125, 125, 5, 67, -1, 0, 0, 8, 1061, 1063), + (1063, -1, -1, 125, 125, 5, 68, -1, 0, 0, 8, 1062, 1064), + (1064, -1, -1, 125, 125, 5, 69, -1, 0, 0, 8, 1063, 1065), + (1065, -1, -1, 125, 125, 5, 70, -1, 0, 0, 8, 1064, 1394), + (1066, -1, -1, 122, 122, 5, 66, -1, 0, 0, 8, 458, 1067), + (1067, -1, -1, 122, 122, 5, 67, -1, 0, 0, 8, 1066, 1068), + (1068, -1, -1, 122, 122, 5, 68, -1, 0, 0, 8, 1067, 1069), + (1069, -1, -1, 122, 122, 5, 69, -1, 0, 0, 8, 1068, 1070), + (1070, -1, -1, 122, 122, 5, 70, -1, 0, 0, 8, 1069, 1399), + (1071, -1, -1, 1071, 1071, 3, 55, -1, 0, 0, 8, -1, 4764), + (1072, -1, -1, 1072, 1072, 5, 66, -1, 0, 0, 8, -1, 1073), + (1073, -1, -1, 1072, 1072, 5, 67, -1, 0, 0, 8, 1072, 1074), + (1074, -1, -1, 1072, 1072, 5, 68, -1, 0, 0, 8, 1073, 1075), + (1075, -1, -1, 1072, 1072, 5, 69, -1, 0, 0, 8, 1074, 1076), + (1076, -1, -1, 1072, 1072, 5, 70, -1, 0, 0, 8, 1075, 4744), + (1083, -1, -1, 77, 77, 3, 66, -1, 0, 0, 8, 436, 1084), + (1084, -1, -1, 77, 77, 6, 68, -1, 0, 0, 8, 1083, 1085), + (1085, -1, -1, 77, 77, 9, 70, -1, 0, 0, 8, 1084, 12449), + (1086, -1, -1, 80, 80, 3, 66, -1, 0, 0, 8, 439, 1087), + (1087, -1, -1, 80, 80, 6, 68, -1, 0, 0, 8, 1086, 1088), + (1088, -1, -1, 80, 80, 9, 70, -1, 0, 0, 8, 1087, 4779), + (1089, -1, -1, 1089, 1089, 3, 59, -1, 0, 0, 8, -1, 1090), + (1090, -1, -1, 1089, 1089, 6, 59, -1, 0, 0, 8, 1089, 1091), + (1091, -1, -1, 1089, 1089, 9, 59, -1, 0, 0, 8, 1090, -1), + (1092, -1, -1, 1092, 1092, 7, 67, -1, 0, 0, 8, -1, -1), + (1093, -1, -1, 1093, 1093, 3, 66, -1, 0, 0, 8, -1, 1094), + (1094, -1, -1, 1093, 1093, 3, 67, -1, 0, 0, 8, 1093, 1095), + (1095, -1, -1, 1093, 1093, 3, 68, -1, 0, 0, 8, 1094, 1096), + (1096, -1, -1, 1093, 1093, 3, 69, -1, 0, 0, 8, 1095, 1097), + (1097, -1, -1, 1093, 1093, 3, 70, -1, 0, 0, 8, 1096, -1), + (1099, -1, -1, 767, 767, 3, 67, -1, 0, 0, 8, 769, 1100), + (1100, -1, -1, 767, 767, 6, 68, -1, 0, 0, 8, 1099, 1101), + (1101, -1, -1, 767, 767, 9, 69, -1, 0, 0, 8, 1100, 12423), + (1102, 592, 592, 592, 592, 3, 66, 5825, 2, 18, 8, 706, 1103), + (1103, 592, 592, 592, 592, 3, 67, 5826, 2, 18, 8, 1102, 1104), + (1104, 592, 592, 592, 592, 3, 68, 5827, 2, 18, 8, 1103, 1105), + (1105, 592, 592, 592, 592, 3, 69, 5828, 2, 18, 8, 1104, 1106), + (1106, 592, 592, 592, 592, 3, 70, 5829, 2, 18, 8, 1105, 4975), + (1107, -1, -1, 1107, 1107, 3, 66, -1, 0, 0, 8, -1, 1108), + (1108, -1, -1, 1107, 1107, 6, 68, -1, 0, 0, 8, 1107, 1109), + (1109, -1, -1, 1107, 1107, 9, 70, -1, 0, 0, 8, 1108, 5286), + (1110, 1110, 1110, 1110, 1110, 3, 68, 5830, 3, 2160, 8, -1, 1111), + (1111, 1110, 1110, 1110, 1110, 6, 69, 5831, 3, 2160, 8, 1110, 1112), + (1112, 1110, 1110, 1110, 1110, 9, 70, 5832, 3, 2160, 8, 1111, 6400), + (1113, -1, -1, 997, 997, 5, 75, -1, 0, 0, 16, 999, 1114), + (1114, -1, -1, 997, 997, 5, 80, -1, 0, 0, 16, 1113, 1115), + (1115, -1, -1, 997, 997, 5, 85, -1, 0, 0, 16, 1114, -1), + (1116, 1116, 1116, 1116, 1116, 3, 68, 5837, 4, 2160, 8, -1, 1117), + (1117, 1116, 1116, 1116, 1116, 6, 69, 5838, 4, 2160, 8, 1116, 1118), + (1118, 1116, 1116, 1116, 1116, 9, 70, 5839, 4, 2160, 8, 1117, 4980), + (1119, 1119, 1119, 1119, 1119, 3, 68, 5841, 8, 900, 8, -1, 1120), + (1120, 1119, 1119, 1119, 1119, 6, 69, 5842, 8, 900, 8, 1119, 1121), + (1121, 1119, 1119, 1119, 1119, 9, 70, 5843, 8, 900, 8, 1120, 4964), + (1122, -1, -1, 1122, 1122, 7, 67, -1, 0, 0, 8, -1, -1), + (1123, 291, 291, 291, 291, 5, 66, 5854, 5, 900, 8, 291, 1124), + (1124, 291, 291, 291, 291, 5, 68, 5855, 5, 900, 8, 1123, 1125), + (1125, 291, 291, 291, 291, 5, 70, 5856, 5, 900, 8, 1124, 4969), + (1126, 1126, 1126, 1126, 1126, 3, 67, 5845, 2, 2160, 8, -1, 1127), + (1127, 1126, 1126, 1126, 1126, 6, 68, 5846, 2, 2160, 8, 1126, 1128), + (1128, 1126, 1126, 1126, 1126, 9, 69, 5847, 2, 2160, 8, 1127, 5513), + (1129, -1, -1, 1129, 1129, 5, 67, -1, 0, 0, 8, -1, 1130), + (1130, -1, -1, 1129, 1129, 3, 69, -1, 0, 0, 8, 1129, -1), + (1131, -1, -1, 1131, 1131, 3, 59, -1, 0, 0, 3, -1, 1132), + (1132, -1, -1, 1131, 1131, 6, 59, -1, 0, 0, 3, 1131, 1133), + (1133, -1, -1, 1131, 1131, 9, 59, -1, 0, 0, 3, 1132, 11082), + (1134, -1, -1, 1134, 1134, 3, 61, -1, 0, 0, 4, -1, 1135), + (1135, -1, -1, 1134, 1134, 4, 63, -1, 0, 0, 4, 1134, 1136), + (1136, -1, -1, 1134, 1134, 5, 65, -1, 0, 0, 4, 1135, 1158), + (1137, -1, -1, 1137, 1137, 3, 59, -1, 0, 0, 3, -1, 1138), + (1138, -1, -1, 1137, 1137, 6, 59, -1, 0, 0, 3, 1137, 1139), + (1139, -1, -1, 1137, 1137, 9, 59, -1, 0, 0, 3, 1138, -1), + (1140, -1, -1, 1140, 1140, 3, 61, -1, 0, 0, 4, -1, 1141), + (1141, -1, -1, 1140, 1140, 3, 63, -1, 0, 0, 4, 1140, 1142), + (1142, -1, -1, 1140, 1140, 3, 65, -1, 0, 0, 4, 1141, -1), + (1146, 1146, 1146, 1146, 1146, 3, 59, 6040, 3, 1500, 3, -1, 1147), + (1147, 1146, 1146, 1146, 1146, 6, 59, 6041, 3, 1200, 3, 1146, 1148), + (1148, 1146, 1146, 1146, 1146, 9, 59, 6042, 3, 900, 3, 1147, -1), + (1149, 1149, -1, 1149, 1149, 12, 65, 5853, 5, 1320, 7, -1, -1), + (1150, 1150, 1150, 1150, 1150, 3, 65, 5848, 2, 2160, 7, -1, 1151), + (1151, 1150, 1150, 1150, 1150, 6, 65, 5849, 2, 2160, 7, 1150, 1152), + (1152, 1150, 1150, 1150, 1150, 9, 65, 5850, 2, 2160, 7, 1151, -1), + (1155, -1, -1, 1155, 1155, 3, 65, -1, 0, 0, 7, -1, 1156), + (1156, -1, -1, 1155, 1155, 6, 65, -1, 0, 0, 7, 1155, 1157), + (1157, -1, -1, 1155, 1155, 9, 65, -1, 0, 0, 7, 1156, -1), + (1158, -1, -1, 1134, 1134, 4, 66, -1, 0, 0, 8, 1136, 1159), + (1159, -1, -1, 1134, 1134, 4, 67, -1, 0, 0, 8, 1158, 1160), + (1160, -1, -1, 1134, 1134, 4, 68, -1, 0, 0, 8, 1159, 1161), + (1161, -1, -1, 1134, 1134, 4, 69, -1, 0, 0, 8, 1160, 1162), + (1162, -1, -1, 1134, 1134, 4, 70, -1, 0, 0, 8, 1161, 4790), + (1163, -1, -1, 255, 255, 5, 67, -1, 0, 0, 8, 544, 1164), + (1164, -1, -1, 255, 255, 5, 68, -1, 0, 0, 8, 1163, 1165), + (1165, -1, -1, 255, 255, 5, 69, -1, 0, 0, 8, 1164, 4795), + (1166, -1, -1, 1143, 1143, 3, 65, -1, 0, 0, 15, -1, 1167), + (1167, -1, -1, 1143, 1143, 6, 65, -1, 0, 0, 15, 1166, 1168), + (1168, -1, -1, 1143, 1143, 9, 65, -1, 0, 0, 15, 1167, 6911), + (1172, -1, -1, 631, 631, 5, 67, -1, 0, 0, 8, 633, 1173), + (1173, -1, -1, 631, 631, 5, 68, -1, 0, 0, 8, 1172, 1174), + (1174, -1, -1, 631, 631, 5, 69, -1, 0, 0, 8, 1173, 4798), + (1178, 1178, 1178, 1178, 1178, 3, 68, 5857, 4, 900, 8, -1, 1179), + (1179, 1178, 1178, 1178, 1178, 6, 69, 5858, 4, 900, 8, 1178, 1180), + (1180, 1178, 1178, 1178, 1178, 9, 70, 5859, 4, 900, 8, 1179, 5779), + (1181, -1, -1, 1181, 1181, 3, 66, -1, 0, 0, 8, -1, 1182), + (1182, -1, -1, 1181, 1181, 3, 67, -1, 0, 0, 8, 1181, 1183), + (1183, -1, -1, 1181, 1181, 3, 68, -1, 0, 0, 8, 1182, 1184), + (1184, -1, -1, 1181, 1181, 3, 69, -1, 0, 0, 8, 1183, 1185), + (1185, -1, -1, 1181, 1181, 3, 70, -1, 0, 0, 8, 1184, -1), + (1186, -1, -1, 1186, 1186, 3, 66, -1, 0, 0, 8, -1, 1187), + (1187, -1, -1, 1186, 1186, 6, 68, -1, 0, 0, 8, 1186, 1188), + (1188, -1, -1, 1186, 1186, 9, 70, -1, 0, 0, 8, 1187, 4776), + (1189, 459, 459, 459, 459, 3, 66, 5860, 8, 180, 8, 461, 1190), + (1190, 459, 459, 459, 459, 6, 68, 5861, 8, 180, 8, 1189, 1191), + (1191, 459, 459, 459, 459, 9, 70, 5862, 8, 180, 8, 1190, 5062), + (1192, 1192, 1192, 1192, 1192, 5, 67, 5863, 12, 1320, 8, -1, 1193), + (1193, 1192, 1192, 1192, 1192, 5, 68, 5864, 12, 1320, 8, 1192, 1194), + (1194, 1192, 1192, 1192, 1192, 5, 69, 5865, 12, 1320, 8, 1193, 5076), + (1195, 1195, 1195, 1195, 1195, 12, 70, 5866, 13, 2160, 8, -1, 5079), + (1196, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, -1, 1197), + (1197, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1196, 1198), + (1198, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1197, 1199), + (1199, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1198, 1200), + (1200, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1199, 10743), + (1203, 131, 131, 131, 131, 5, 67, 5869, 4, 900, 8, 532, 1204), + (1204, 131, 131, 131, 131, 5, 68, 5870, 4, 900, 8, 1203, 1205), + (1205, 131, 131, 131, 131, 5, 69, 5988, 4, 900, 8, 1204, 5070), + (1206, 749, 749, 749, 749, 5, 66, 5871, 11, 1800, 8, 753, 1207), + (1207, 749, 749, 749, 749, 5, 68, 5872, 11, 1800, 8, 1206, 1208), + (1208, 749, 749, 749, 749, 5, 70, 5873, 11, 1800, 8, 1207, 17298), + (1209, 1209, -1, 1209, 1209, 12, 70, 5912, 14, 4320, 8, -1, -1), + (1210, -1, -1, 1210, 1210, 3, 66, -1, 0, 0, 8, -1, 1211), + (1211, -1, -1, 1210, 1210, 6, 68, -1, 0, 0, 8, 1210, 1212), + (1212, -1, -1, 1210, 1210, 9, 70, -1, 0, 0, 8, 1211, 1483), + (1213, -1, -1, 1210, 1213, 3, 66, -1, 0, 0, 8, -1, 1214), + (1214, -1, -1, 1210, 1213, 6, 68, -1, 0, 0, 8, 1213, 1215), + (1215, -1, -1, 1210, 1213, 9, 70, -1, 0, 0, 8, 1214, 4755), + (1216, -1, -1, 83, 83, 3, 81, -1, 0, 0, 16, -1, 1217), + (1217, -1, -1, 83, 83, 6, 81, -1, 0, 0, 16, 1216, 1218), + (1218, -1, -1, 83, 83, 9, 81, -1, 0, 0, 16, 1217, 15422), + (1219, -1, -1, 1435, 1435, 10, 71, -1, 0, 0, 16, -1, 1220), + (1220, -1, -1, 1435, 1435, 11, 71, -1, 0, 0, 16, 1219, 1221), + (1221, -1, -1, 1435, 1435, 12, 71, -1, 0, 0, 16, 1220, 1648), + (1222, 757, -1, 757, 1222, 5, 66, 5877, 6, 1800, 8, 761, 1223), + (1223, 757, -1, 757, 1222, 5, 68, 5878, 6, 1800, 8, 1222, 1224), + (1224, 757, -1, 757, 1222, 5, 70, 5879, 6, 1800, 8, 1223, 5051), + (1225, 548, 548, 548, 548, 5, 67, 5881, 5, 900, 8, 550, 1226), + (1226, 548, 548, 548, 548, 5, 68, 5882, 5, 900, 8, 1225, 1227), + (1227, 548, 548, 548, 548, 5, 69, 5883, 5, 900, 8, 1226, 5054), + (1228, 1228, 1228, 1228, 1228, 9, 70, 5880, 9, 600, 8, -1, -1), + (1229, 1229, 1229, 1229, 1229, 7, 66, 6094, 10, 600, 8, -1, -1), + (1230, -1, -1, 1230, 1230, 1, 51, -1, 0, 0, 8, -1, 1231), + (1231, -1, -1, 1230, 1230, 2, 53, -1, 0, 0, 8, 1230, 1232), + (1232, -1, -1, 1230, 1230, 3, 55, -1, 0, 0, 8, 1231, 5000), + (1233, 1233, -1, 1233, 1233, 3, 68, 5887, 7, 2160, 8, -1, 1234), + (1234, 1233, -1, 1233, 1233, 6, 69, 5888, 7, 2160, 8, 1233, 1235), + (1235, 1233, -1, 1233, 1233, 9, 70, 5889, 7, 2160, 8, 1234, -1), + (1239, 1239, 1239, 1239, 1239, 12, 70, 5903, 6, 600, 8, -1, 5868), + (1242, 1242, 1242, 1242, 1242, 3, 67, 5906, 9, 1320, 8, -1, 1243), + (1243, 1242, 1242, 1242, 1242, 6, 68, 5907, 9, 1320, 8, 1242, 1244), + (1244, 1242, 1242, 1242, 1242, 9, 69, 5908, 9, 1320, 8, 1243, 5857), + (1245, 1245, 1245, 1245, 1245, 3, 66, 5909, 8, 2160, 8, -1, 1246), + (1246, 1245, 1245, 1245, 1245, 6, 68, 5910, 8, 2160, 8, 1245, 1247), + (1247, 1245, 1245, 1245, 1245, 9, 70, 5911, 8, 2160, 8, 1246, 15459), + (1248, 616, 616, 616, 616, 3, 68, 6226, 7, 900, 8, 618, 1249), + (1249, 616, 616, 616, 616, 6, 69, 6227, 7, 900, 8, 1248, 1250), + (1250, 616, 616, 616, 616, 9, 70, 6228, 7, 900, 8, 1249, 6254), + (1251, 1251, 1251, 1251, 1251, 9, 70, 5915, 9, 1320, 8, -1, -1), + (1252, 1252, 1252, 1252, 1252, 9, 68, 5913, 9, 1320, 8, -1, -1), + (1253, 1253, 1253, 1253, 1253, 9, 67, 5916, 16, 1320, 8, -1, -1), + (1254, 1254, 1254, 1254, 1254, 9, 69, 5914, 16, 1320, 8, -1, -1), + (1255, 1255, 1255, 1255, 1255, 9, 70, 5918, 4, 1080, 8, -1, -1), + (1265, -1, -1, 820, 820, 5, 66, -1, 0, 0, 8, 822, 1266), + (1266, -1, -1, 820, 820, 5, 68, -1, 0, 0, 8, 1265, 1267), + (1267, -1, -1, 820, 820, 5, 70, -1, 0, 0, 8, 1266, 4813), + (1268, -1, -1, 807, 807, 5, 66, -1, 0, 0, 8, 809, 1269), + (1269, -1, -1, 807, 807, 5, 68, -1, 0, 0, 8, 1268, 1270), + (1270, -1, -1, 807, 807, 5, 70, -1, 0, 0, 8, 1269, 5922), + (1272, 209, 209, 209, 1272, 5, 66, 5919, 12, 5, 8, -1, 6378), + (1274, 1274, 1274, 1274, 1274, 3, 68, 5921, 9, 540, 8, -1, 1275), + (1275, 1274, 1274, 1274, 1274, 6, 69, 5922, 9, 540, 8, 1274, 1276), + (1276, 1274, 1274, 1274, 1274, 9, 70, 5923, 9, 540, 8, 1275, 4864), + (1277, 188, 188, 188, 188, 9, 68, 5924, 2, 30, 8, 188, 5044), + (1278, 534, 534, 534, 534, 5, 67, 5927, 4, 2160, 8, 717, 1279), + (1279, 534, 534, 534, 534, 5, 68, 5928, 4, 2160, 8, 1278, 1280), + (1280, 534, 534, 534, 534, 5, 69, 5929, 4, 2160, 8, 1279, 5041), + (1284, -1, -1, 1284, 1284, 3, 66, -1, 0, 0, 8, -1, 1285), + (1285, -1, -1, 1284, 1284, 6, 68, -1, 0, 0, 8, 1284, 1286), + (1286, -1, -1, 1284, 1284, 9, 70, -1, 0, 0, 8, 1285, 5035), + (1287, -1, -1, 1287, 1287, 3, 67, -1, 0, 0, 8, -1, 1288), + (1288, -1, -1, 1287, 1287, 6, 68, -1, 0, 0, 8, 1287, 1289), + (1289, -1, -1, 1287, 1287, 9, 69, -1, 0, 0, 8, 1288, 5516), + (1290, -1, -1, 864, 864, 3, 66, -1, 0, 0, 8, 866, 1291), + (1291, -1, -1, 864, 864, 6, 68, -1, 0, 0, 8, 1290, 1292), + (1292, -1, -1, 864, 864, 9, 70, -1, 0, 0, 8, 1291, 4983), + (1293, 545, 545, 545, 545, 3, 68, 6079, 3, 900, 8, 547, 1294), + (1294, 545, 545, 545, 545, 6, 69, 6080, 3, 900, 8, 1293, 1295), + (1295, 545, 545, 545, 545, 9, 70, 6081, 3, 900, 8, 1294, 4997), + (1296, -1, -1, 1296, 1296, 3, 66, -1, 0, 0, 8, -1, 1297), + (1297, -1, -1, 1296, 1296, 3, 67, -1, 0, 0, 8, 1296, 1298), + (1298, -1, -1, 1296, 1296, 3, 68, -1, 0, 0, 8, 1297, 1299), + (1299, -1, -1, 1296, 1296, 3, 69, -1, 0, 0, 8, 1298, 1300), + (1300, -1, -1, 1296, 1296, 3, 70, -1, 0, 0, 8, 1299, -1), + (1301, -1, -1, 846, 846, 3, 66, -1, 0, 0, 8, 848, 1302), + (1302, -1, -1, 846, 846, 6, 68, -1, 0, 0, 8, 1301, 1303), + (1303, -1, -1, 846, 846, 9, 70, -1, 0, 0, 8, 1302, 4948), + (1304, -1, -1, 1304, 1304, 3, 66, -1, 0, 0, 8, -1, 1305), + (1305, -1, -1, 1304, 1304, 6, 68, -1, 0, 0, 8, 1304, 1306), + (1306, -1, -1, 1304, 1304, 9, 70, -1, 0, 0, 8, 1305, 6029), + (1307, -1, -1, 1307, 1307, 5, 66, -1, 0, 0, 8, -1, 1308), + (1308, -1, -1, 1307, 1307, 5, 67, -1, 0, 0, 8, 1307, 1309), + (1309, -1, -1, 1307, 1307, 5, 68, -1, 0, 0, 8, 1308, 1310), + (1310, -1, -1, 1307, 1307, 5, 69, -1, 0, 0, 8, 1309, 1311), + (1311, -1, -1, 1307, 1307, 5, 70, -1, 0, 0, 8, 1310, 6660), + (1313, -1, -1, 1313, 1313, 3, 68, -1, 0, 0, 8, -1, 1314), + (1314, -1, -1, 1313, 1313, 6, 69, -1, 0, 0, 8, 1313, 1315), + (1315, -1, -1, 1313, 1313, 9, 70, -1, 0, 0, 8, 1314, 5029), + (1316, -1, -1, 210, 210, 5, 67, -1, 0, 0, 8, 212, 1317), + (1317, -1, -1, 210, 210, 5, 68, -1, 0, 0, 8, 1316, 1318), + (1318, -1, -1, 210, 210, 5, 69, -1, 0, 0, 8, 1317, 6072), + (1319, -1, -1, 634, 634, 5, 67, -1, 0, 0, 8, 845, 1320), + (1320, -1, -1, 634, 634, 5, 68, -1, 0, 0, 8, 1319, 1321), + (1321, -1, -1, 634, 634, 5, 69, -1, 0, 0, 8, 1320, 5032), + (1323, 1323, 1323, 1323, 1323, 12, 70, 5932, 7, 2160, 8, -1, -1), + (1324, 970, 970, 970, 970, 5, 66, 6030, 6, 1800, 8, 974, 1325), + (1325, 970, 970, 970, 970, 5, 68, 6031, 6, 1800, 8, 1324, 1326), + (1326, 970, 970, 970, 970, 5, 70, 6032, 6, 1800, 8, 1325, 17311), + (1327, 1327, 1327, 1327, 1327, 5, 67, 5933, 10, 900, 8, -1, 1328), + (1328, 1327, 1327, 1327, 1327, 5, 68, 5934, 10, 900, 8, 1327, 1329), + (1329, 1327, 1327, 1327, 1327, 5, 69, 5935, 10, 900, 8, 1328, 5314), + (1330, 912, 912, 912, 912, 3, 66, 5936, 4, 3600, 8, 914, 1331), + (1331, 912, 912, 912, 912, 6, 68, 5937, 4, 3600, 8, 1330, 1332), + (1332, 912, 912, 912, 912, 9, 70, 5938, 4, 3600, 8, 1331, 7119), + (1334, 1334, 1334, 1334, 1334, 3, 66, 5943, 11, 4320, 8, -1, 1335), + (1335, 1334, 1334, 1334, 1334, 6, 68, 5944, 11, 4320, 8, 1334, 1336), + (1336, 1334, 1334, 1334, 1334, 9, 70, 5945, 11, 4320, 8, 1335, 6152), + (1337, 1337, 1337, 1337, 1337, 5, 67, 5946, 13, 4320, 8, -1, 1338), + (1338, 1337, 1337, 1337, 1337, 5, 68, 5947, 13, 4320, 8, 1337, 1339), + (1339, 1337, 1337, 1337, 1337, 5, 69, 5948, 13, 4320, 8, 1338, 6158), + (1340, 921, 921, 921, 921, 12, 69, 5950, 8, 60, 8, 921, 5280), + (1341, 922, 922, 922, 922, 12, 68, 5951, 8, 60, 8, 922, 5281), + (1342, 923, 923, 923, 923, 12, 67, 5952, 8, 60, 8, 923, 5282), + (1343, 1343, 1343, 1343, 1343, 9, 69, 5953, 9, 300, 8, -1, -1), + (1344, 155, 155, 155, 155, 12, 70, 5949, 8, 60, 8, 533, 5279), + (1345, 1345, 1345, 1345, 1345, 5, 67, 6132, 6, 900, 8, -1, 1346), + (1346, 1345, 1345, 1345, 1345, 5, 68, 6133, 6, 900, 8, 1345, 1347), + (1347, 1345, 1345, 1345, 1345, 5, 69, 6134, 6, 900, 8, 1346, 5003), + (1348, 1348, 1348, 1348, 1348, 3, 68, 6090, 0, 3600, 8, -1, 1349), + (1349, 1348, 1348, 1348, 1348, 6, 69, 6091, 0, 3600, 8, 1348, 1350), + (1350, 1348, 1348, 1348, 1348, 9, 70, 6092, 0, 3600, 8, 1349, 5770), + (1351, 1351, 1351, 1351, 1351, 5, 67, 5939, 5, 30, 8, -1, 6133), + (1352, 1352, 1352, 1352, 1352, 3, 67, 6067, 3, 60, 8, -1, 1353), + (1353, 1352, 1352, 1352, 1352, 6, 68, 6068, 3, 60, 8, 1352, 1354), + (1354, 1352, 1352, 1352, 1352, 9, 69, 6069, 3, 60, 8, 1353, 6313), + (1355, 1355, 1355, 1355, 1355, 3, 68, 6070, 3, 60, 8, -1, 1356), + (1356, 1355, 1355, 1355, 1355, 6, 69, 6071, 3, 60, 8, 1355, 1357), + (1357, 1355, 1355, 1355, 1355, 9, 70, 6072, 3, 60, 8, 1356, 5240), + (1358, 1358, 1358, 1358, 1358, 3, 66, 6073, 3, 60, 8, -1, 1359), + (1359, 1358, 1358, 1358, 1358, 6, 67, 6074, 3, 60, 8, 1358, 1360), + (1360, 1358, 1358, 1358, 1358, 9, 68, 6075, 3, 60, 8, 1359, 6307), + (1361, -1, -1, 1361, 1361, 0, 65, -1, 0, 0, 3, -1, -1), + (1362, -1, -1, 1362, 1362, 0, 65, -1, 0, 0, 3, -1, -1), + (1363, -1, -1, 1363, 1363, 0, 68, -1, 0, 0, 3, -1, -1), + (1364, -1, -1, 1364, 1364, 0, 68, -1, 0, 0, 3, -1, -1), + (1365, -1, -1, 1365, 1365, 0, 68, -1, 0, 0, 3, -1, -1), + (1366, -1, -1, 1366, 1366, 0, 65, -1, 0, 0, 3, -1, -1), + (1367, -1, -1, 1367, 1367, 0, 65, -1, 0, 0, 3, -1, -1), + (1368, -1, -1, 1368, 1368, 0, 68, -1, 0, 0, 3, -1, -1), + (1369, -1, -1, 1369, 1369, 0, 68, -1, 0, 0, 3, -1, -1), + (1370, -1, -1, 1370, 1370, 0, 68, -1, 0, 0, 3, -1, -1), + (1371, 1371, 1371, 1371, 1371, 0, 1, 6880, 23, 72000, 0, -1, -1), + (1372, 1372, 1372, 1372, 1372, 0, 1, 6881, 24, 72000, 0, -1, -1), + (1373, 1373, 1373, 1373, 1373, 0, 1, 6882, 25, 72000, 0, -1, -1), + (1374, 1374, 1374, 1374, 1374, 0, 1, 6883, 26, 590400, 0, -1, -1), + (1375, 1375, 1375, 1375, 1375, 0, 1, 6884, 27, 72000, 0, -1, -1), + (1376, 1376, 1376, 1376, 1376, 0, 1, 6885, 28, 244800, 0, -1, -1), + (1377, 1377, 1377, 1377, 1377, 0, 1, 6886, 29, 14400, 0, -1, -1), + (1378, -1, -1, 1378, 1378, 0, 1, -1, 0, 0, 10, -1, 1379), + (1379, -1, -1, 1379, 1379, 0, 1, -1, 0, 0, 10, 1378, 1380), + (1380, -1, -1, 1380, 1380, 0, 1, -1, 0, 0, 10, 1379, 1381), + (1382, -1, -1, 1382, 1382, 0, 1, -1, 0, 0, 10, 1381, -1), + (1383, 1383, 1383, 1383, 1383, 3, 59, 8048, 6, 300, 3, -1, 1384), + (1384, 1383, 1383, 1383, 1383, 6, 59, 8049, 6, 300, 3, 1383, 1385), + (1385, 1383, 1383, 1383, 1383, 9, 59, 8050, 6, 300, 3, 1384, 1386), + (1386, 1383, 1383, 1383, 1383, 9, 65, 8052, 6, 300, 4, 1385, 1387), + (1387, 1383, 1383, 1383, 1383, 9, 70, 8053, 6, 300, 10, 1386, 5084), + (1388, -1, -1, 1388, 1388, 9, 70, -1, 0, 0, 10, -1, -1), + (1389, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1030, 1390), + (1390, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1389, 1391), + (1391, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1390, 1392), + (1392, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1391, 1393), + (1393, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1392, 4683), + (1394, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1065, 1395), + (1395, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1394, 1396), + (1396, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1395, 1397), + (1397, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1396, 1398), + (1398, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1397, 5519), + (1399, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1070, 1400), + (1400, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1399, 1401), + (1401, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1400, 1402), + (1402, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1401, 1403), + (1403, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1402, 5524), + (1404, 1404, 1404, 1404, 1404, 5, 66, 8054, 15, 2160, 10, -1, 1405), + (1405, 1404, 1404, 1404, 1404, 5, 67, 8055, 15, 2160, 10, 1404, 1406), + (1406, 1404, 1404, 1404, 1404, 5, 68, 8056, 15, 2160, 10, 1405, 1407), + (1407, 1404, 1404, 1404, 1404, 5, 69, 8057, 15, 2160, 10, 1406, 1408), + (1408, 1404, 1404, 1404, 1404, 5, 70, 8058, 15, 2160, 10, 1407, 12880), + (1409, 1409, 1409, 1409, 1409, 5, 66, 8054, 15, 2160, 10, -1, 1410), + (1410, 1409, 1409, 1409, 1409, 5, 67, 8055, 15, 2160, 10, 1409, 1411), + (1411, 1409, 1409, 1409, 1409, 5, 68, 8056, 15, 2160, 10, 1410, 1412), + (1412, 1409, 1409, 1409, 1409, 5, 69, 8057, 15, 2160, 10, 1411, 1413), + (1413, 1409, 1409, 1409, 1409, 5, 70, 8058, 15, 2160, 10, 1412, -1), + (1414, -1, -1, 1414, 1414, 5, 66, -1, 0, 0, 10, -1, 1415), + (1415, -1, -1, 1414, 1414, 5, 67, -1, 0, 0, 10, 1414, 1416), + (1416, -1, -1, 1414, 1414, 5, 68, -1, 0, 0, 10, 1415, 1417), + (1417, -1, -1, 1414, 1414, 5, 69, -1, 0, 0, 10, 1416, 1418), + (1418, -1, -1, 1414, 1414, 5, 70, -1, 0, 0, 10, 1417, 12874), + (1419, 1419, 1419, 1419, 1419, 9, 74, 16441, 52, 300, 15, -1, -1), + (1420, -1, -1, 1420, 1420, 3, 66, -1, 0, 0, 10, -1, 1421), + (1421, -1, -1, 1420, 1420, 3, 67, -1, 0, 0, 10, 1420, 1422), + (1422, -1, -1, 1420, 1420, 3, 68, -1, 0, 0, 10, 1421, 1423), + (1423, -1, -1, 1420, 1420, 3, 69, -1, 0, 0, 10, 1422, 1424), + (1424, -1, -1, 1420, 1420, 3, 70, -1, 0, 0, 10, 1423, -1), + (1425, 1425, 1425, 1425, 1425, 5, 70, 8060, 2, 2160, 10, -1, 1426), + (1426, 1425, 1425, 1425, 1425, 5, 70, 8061, 2, 2160, 10, 1425, 1427), + (1427, 1425, 1425, 1425, 1425, 5, 70, 8063, 2, 2160, 10, 1426, 1428), + (1428, 1425, 1425, 1425, 1425, 5, 70, 8066, 2, 2160, 10, 1427, 1429), + (1429, 1425, 1425, 1425, 1425, 5, 70, 8070, 2, 2160, 10, 1428, 5759), + (1430, -1, -1, 795, 795, 3, 70, -1, 0, 0, 10, 799, 1431), + (1431, -1, -1, 795, 795, 6, 70, -1, 0, 0, 10, 1430, 1432), + (1432, -1, -1, 795, 795, 9, 70, -1, 0, 0, 10, 1431, 4897), + (1435, -1, -1, 1435, 1435, 3, 66, -1, 0, 0, 10, -1, 1436), + (1436, -1, -1, 1435, 1435, 6, 68, -1, 0, 0, 10, 1435, 1437), + (1437, -1, -1, 1435, 1435, 9, 70, -1, 0, 0, 10, 1436, 4773), + (1440, 517, 517, 517, 517, 5, 66, 8109, 12, 600, 10, 519, 1441), + (1441, 517, 517, 517, 517, 5, 67, 8110, 12, 600, 10, 1440, 1442), + (1442, 517, 517, 517, 517, 5, 68, 8111, 12, 600, 10, 1441, 1443), + (1443, 517, 517, 517, 517, 5, 69, 8112, 12, 600, 10, 1442, 1444), + (1444, 517, 517, 517, 517, 5, 70, 8113, 12, 600, 10, 1443, 7296), + (1453, -1, -1, 1453, 1453, 5, 66, -1, 0, 0, 10, -1, 1454), + (1454, -1, -1, 1453, 1453, 5, 67, -1, 0, 0, 10, 1453, 1455), + (1455, -1, -1, 1453, 1453, 5, 68, -1, 0, 0, 10, 1454, 1456), + (1456, -1, -1, 1453, 1453, 5, 69, -1, 0, 0, 10, 1455, 1457), + (1457, -1, -1, 1453, 1453, 5, 70, -1, 0, 0, 10, 1456, -1), + (1458, 1458, 1458, 1458, 1458, 12, 70, 8124, 6, 4320, 10, -1, -1), + (1459, 1459, 1459, 1459, 1459, 7, 70, 8125, 11, 1800, 10, -1, 1460), + (1460, 1459, 1459, 1459, 1459, 7, 70, 8126, 11, 1800, 10, 1459, 1461), + (1461, 1459, 1459, 1459, 1459, 7, 70, 8127, 11, 1800, 10, 1460, 5080), + (1462, 1462, 1462, 1462, 1462, 3, 59, 8133, 5, 300, 3, -1, 1463), + (1463, 1462, 1462, 1462, 1462, 6, 59, 8134, 5, 300, 3, 1462, 1464), + (1464, 1462, 1462, 1462, 1462, 9, 59, 8135, 5, 300, 3, 1463, 1465), + (1465, 1462, 1462, 1462, 1462, 9, 65, 8137, 5, 300, 4, 1464, 1466), + (1466, 1462, 1462, 1462, 1462, 9, 70, 8138, 5, 300, 10, 1465, 4900), + (1467, -1, -1, 729, 729, 3, 70, -1, 0, 0, 10, 733, 1468), + (1468, -1, -1, 729, 729, 6, 70, -1, 0, 0, 10, 1467, 1469), + (1469, -1, -1, 729, 729, 9, 70, -1, 0, 0, 10, 1468, 4960), + (1471, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, -1, 1472), + (1472, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1471, 1473), + (1473, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1472, 1474), + (1474, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1473, 1475), + (1475, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1474, 6442), + (1477, 1477, 1477, 1477, 1477, 9, 70, 8149, 3, 4320, 10, -1, -1), + (1478, 1478, -1, 1478, 1478, 3, 66, 8406, 0, 1, 10, -1, 1479), + (1479, 1478, -1, 1478, 1478, 6, 68, 8407, 0, 1, 10, 1478, 1480), + (1480, 1478, -1, 1478, 1478, 9, 70, 8408, 0, 1, 10, 1479, 6161), + (1483, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1212, 1484), + (1484, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1483, 1485), + (1485, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1484, 4752), + (1486, -1, -1, 1486, 1486, 5, 66, -1, 0, 0, 10, -1, 1487), + (1487, -1, -1, 1486, 1486, 5, 67, -1, 0, 0, 10, 1486, 1488), + (1488, -1, -1, 1486, 1486, 5, 68, -1, 0, 0, 10, 1487, 1489), + (1489, -1, -1, 1486, 1486, 5, 69, -1, 0, 0, 10, 1488, 1490), + (1490, -1, -1, 1486, 1486, 5, 70, -1, 0, 0, 10, 1489, 5529), + (1491, 746, 746, 746, 746, 3, 70, 8156, 10, 2160, 10, 748, 1492), + (1492, 746, 746, 746, 746, 6, 70, 8157, 10, 2160, 10, 1491, 1493), + (1493, 746, 746, 746, 746, 9, 70, 8158, 10, 2160, 10, 1492, 5800), + (1494, 1494, 1494, 1494, 1494, 12, 70, 8170, 2, 7, 10, -1, -1), + (1495, 1495, 1495, 1495, 1495, 3, 70, 8190, 30, 900, 10, -1, 1496), + (1496, 1495, 1495, 1495, 1495, 6, 70, 8191, 30, 900, 10, 1495, 1497), + (1497, 1495, 1495, 1495, 1495, 9, 70, 8192, 30, 900, 10, 1496, 5311), + (1498, 1498, 1498, 1498, 1498, 3, 70, 8193, 12, 1320, 10, -1, 1499), + (1499, 1498, 1498, 1498, 1498, 6, 70, 8194, 12, 1320, 10, 1498, 1500), + (1500, 1498, 1498, 1498, 1498, 9, 70, 8195, 12, 1320, 10, 1499, 5058), + (1501, 1501, 1501, 1501, 1501, 3, 70, 8196, 10, 4320, 10, -1, 1502), + (1502, 1501, 1501, 1501, 1501, 6, 70, 8197, 10, 4320, 10, 1501, 1503), + (1503, 1501, 1501, 1501, 1501, 9, 70, 8198, 10, 4320, 10, 1502, 1558), + (1504, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, -1, 1505), + (1505, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, 1504, 1506), + (1506, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, 1505, 5880), + (1507, 520, 520, 520, 520, 3, 70, 8201, 6, 540, 10, 522, 1508), + (1508, 520, 520, 520, 520, 6, 70, 8202, 6, 540, 10, 1507, 1509), + (1509, 520, 520, 520, 520, 9, 70, 8203, 6, 540, 10, 1508, 5883), + (1510, 1510, -1, 1510, 1510, 12, 70, 8205, 13, 2160, 10, -1, 7202), + (1511, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, -1, 1512), + (1512, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, 1511, 1513), + (1513, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, 1512, 5950), + (1514, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, -1, 1515), + (1515, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, 1514, 1516), + (1516, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, 1515, 13404), + (1519, 153, 153, 153, 153, 9, 70, 8216, 3, 2160, 10, 153, 5068), + (1520, 1520, 1520, 1520, 1520, 3, 70, 8218, 11, 900, 10, -1, 1521), + (1521, 1520, 1520, 1520, 1520, 6, 70, 8219, 11, 900, 10, 1520, 1522), + (1522, 1520, 1520, 1520, 1520, 9, 70, 8220, 11, 900, 10, 1521, 6449), + (1523, 1523, 1523, 1523, 1523, 12, 70, 8221, 7, 7, 10, -1, -1), + (1524, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 192, 1526), + (1525, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 1526, 5038), + (1526, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 1524, 1525), + (1527, 1527, 1527, 1527, 1527, 12, 70, 8223, 3, 7, 10, -1, -1), + (1528, -1, -1, 1528, 4819, 5, 66, -1, 0, 0, 10, -1, 1529), + (1529, -1, -1, 1528, 4819, 5, 67, -1, 0, 0, 10, 1528, 1530), + (1530, -1, -1, 1528, 4819, 5, 68, -1, 0, 0, 10, 1529, 1531), + (1531, -1, -1, 1528, 4819, 5, 69, -1, 0, 0, 10, 1530, 1532), + (1532, -1, -1, 1528, 4819, 5, 70, -1, 0, 0, 10, 1531, 4819), + (1533, -1, -1, 602, 602, 3, 70, -1, 0, 0, 10, 604, 1534), + (1534, -1, -1, 602, 602, 6, 70, -1, 0, 0, 10, 1533, 1535), + (1535, -1, -1, 602, 602, 9, 70, -1, 0, 0, 10, 1534, 4758), + (1536, -1, -1, 599, 599, 3, 70, -1, 0, 0, 10, 601, 1537), + (1537, -1, -1, 599, 599, 6, 70, -1, 0, 0, 10, 1536, 1538), + (1538, -1, -1, 599, 599, 9, 70, -1, 0, 0, 10, 1537, 5534), + (1539, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 880, 1540), + (1540, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 1539, 1541), + (1541, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 1540, 4957), + (1542, 1542, -1, 1542, 1542, 3, 60, 8240, 0, 1, 10, -1, -1), + (1543, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, -1, 1544), + (1544, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, 1543, 1545), + (1545, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, 1544, 4951), + (1546, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, -1, 1547), + (1547, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, 1546, 1548), + (1548, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, 1547, 4829), + (1549, -1, -1, 1549, 1549, 3, 66, -1, 0, 0, 10, -1, 1550), + (1550, -1, -1, 1549, 1549, 6, 68, -1, 0, 0, 10, 1549, 1551), + (1551, -1, -1, 1549, 1549, 9, 70, -1, 0, 0, 10, 1550, -1), + (1552, -1, -1, 1552, 1552, 3, 66, -1, 0, 0, 10, -1, 1553), + (1553, -1, -1, 1552, 1552, 6, 68, -1, 0, 0, 10, 1552, 1554), + (1554, -1, -1, 1552, 1552, 9, 70, -1, 0, 0, 10, 1553, -1), + (1555, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, -1, 1556), + (1556, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, 1555, 1557), + (1557, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, 1556, 12727), + (1558, 1501, 1501, 1501, 1501, 6, 75, 16444, 10, 4320, 15, 1503, 1559), + (1559, 1501, 1501, 1501, 1501, 6, 80, 16445, 10, 4320, 15, 1558, 1560), + (1560, 1501, 1501, 1501, 1501, 6, 85, 16446, 10, 4320, 15, 1559, 13244), + (1563, -1, -1, 556, 556, 5, 66, -1, 0, 0, 10, 560, 1564), + (1564, -1, -1, 556, 556, 5, 67, -1, 0, 0, 10, 1563, 1565), + (1565, -1, -1, 556, 556, 5, 68, -1, 0, 0, 10, 1564, 1566), + (1566, -1, -1, 556, 556, 5, 69, -1, 0, 0, 10, 1565, 1567), + (1567, -1, -1, 556, 556, 5, 70, -1, 0, 0, 10, 1566, 17004), + (1569, 1569, 1569, 1569, 1569, 3, 70, 8256, 5, 1800, 10, -1, 1570), + (1570, 1569, 1569, 1569, 1569, 6, 70, 8257, 5, 1800, 10, 1569, 1571), + (1571, 1569, 1569, 1569, 1569, 9, 70, 8258, 5, 1800, 10, 1570, 5713), + (1572, -1, -1, 1572, 1572, 5, 66, -1, 0, 0, 10, -1, 1573), + (1573, -1, -1, 1572, 1572, 5, 67, -1, 0, 0, 10, 1572, 1574), + (1574, -1, -1, 1572, 1572, 5, 68, -1, 0, 0, 10, 1573, 1575), + (1575, -1, -1, 1572, 1572, 5, 69, -1, 0, 0, 10, 1574, 1576), + (1576, -1, -1, 1572, 1572, 5, 70, -1, 0, 0, 10, 1575, 10554), + (1577, -1, -1, 1577, 1577, 3, 66, -1, 0, 0, 10, -1, 1578), + (1578, -1, -1, 1577, 1577, 6, 68, -1, 0, 0, 10, 1577, 1579), + (1579, -1, -1, 1577, 1577, 9, 70, -1, 0, 0, 10, 1578, 5886), + (1583, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, -1, 1584), + (1584, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1583, 1585), + (1585, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1584, 1586), + (1586, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1585, 1587), + (1587, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1586, -1), + (1588, -1, -1, 1587, 1587, 3, 66, -1, 0, 0, 10, -1, 1589), + (1589, -1, -1, 1587, 1587, 6, 68, -1, 0, 0, 10, 1588, 1590), + (1590, -1, -1, 1587, 1587, 9, 70, -1, 0, 0, 10, 1589, -1), + (1591, -1, -1, 1586, 1586, 12, 70, -1, 0, 0, 10, -1, -1), + (1592, -1, -1, 1592, 1592, 5, 66, -1, 0, 0, 10, -1, 1593), + (1593, -1, -1, 1592, 1592, 5, 67, -1, 0, 0, 10, 1592, 1594), + (1594, -1, -1, 1592, 1592, 5, 68, -1, 0, 0, 10, 1593, 1595), + (1595, -1, -1, 1592, 1592, 5, 69, -1, 0, 0, 10, 1594, 1596), + (1596, -1, -1, 1592, 1592, 5, 70, -1, 0, 0, 10, 1595, 4725), + (1597, 1597, 1597, 1597, 1597, 9, 70, 8271, 6, 10, 10, -1, 6606), + (1598, 1598, -1, 1598, 1598, 3, 70, 8272, 6, 900, 10, -1, 1599), + (1599, 1598, -1, 1598, 1598, 6, 70, 8273, 6, 900, 10, 1598, 1600), + (1600, 1598, -1, 1598, 1598, 9, 70, 8274, 6, 900, 10, 1599, 4972), + (1601, -1, -1, 644, 644, 5, 61, -1, 0, 0, 10, 644, 1602), + (1602, -1, -1, 644, 644, 5, 63, -1, 0, 0, 10, 1601, 1603), + (1603, -1, -1, 644, 644, 5, 65, -1, 0, 0, 10, 1602, 4986), + (1604, -1, -1, 1604, 1604, 5, 60, -1, 0, 0, 10, -1, 1605), + (1605, -1, -1, 1604, 1604, 5, 61, -1, 0, 0, 10, 1604, 1606), + (1606, -1, -1, 1604, 1604, 5, 62, -1, 0, 0, 10, 1605, 5290), + (1607, 289, 289, 289, 289, 9, 70, 8278, 3, 300, 10, 289, 5742), + (1608, -1, -1, 1608, 1608, 3, 66, -1, 0, 0, 10, -1, 1609), + (1609, -1, -1, 1608, 1608, 6, 68, -1, 0, 0, 10, 1608, 1610), + (1610, -1, -1, 1608, 1608, 9, 70, -1, 0, 0, 10, 1609, 4989), + (1611, -1, -1, 1417, 1417, 3, 66, -1, 0, 0, 10, -1, 1612), + (1612, -1, -1, 1417, 1417, 3, 67, -1, 0, 0, 10, 1611, 1613), + (1613, -1, -1, 1417, 1417, 3, 68, -1, 0, 0, 10, 1612, 1614), + (1614, -1, -1, 1417, 1417, 3, 69, -1, 0, 0, 10, 1613, 1615), + (1615, -1, -1, 1417, 1417, 3, 70, -1, 0, 0, 10, 1614, -1), + (1616, -1, -1, 1616, 1616, 5, 66, -1, 0, 0, 10, -1, 1617), + (1617, -1, -1, 1616, 1616, 5, 67, -1, 0, 0, 10, 1616, 1618), + (1618, -1, -1, 1616, 1616, 5, 68, -1, 0, 0, 10, 1617, 1619), + (1619, -1, -1, 1616, 1616, 5, 69, -1, 0, 0, 10, 1618, 1620), + (1620, -1, -1, 1616, 1616, 5, 70, -1, 0, 0, 10, 1619, 4992), + (1621, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 566, 1622), + (1622, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 1621, 1623), + (1623, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 1622, -1), + (1624, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 563, 1625), + (1625, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 1624, 1626), + (1626, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 1625, -1), + (1627, -1, -1, 1627, 1627, 3, 66, -1, 0, 0, 10, -1, 1628), + (1628, -1, -1, 1627, 1627, 6, 68, -1, 0, 0, 10, 1627, 1629), + (1629, -1, -1, 1627, 1627, 9, 70, -1, 0, 0, 10, 1628, -1), + (1630, 1474, 1474, 1474, 1474, 3, 70, 8146, 14, 300, 10, -1, 1631), + (1631, 1474, 1474, 1474, 1474, 6, 70, 8147, 14, 300, 10, 1630, 1632), + (1632, 1474, 1474, 1474, 1474, 9, 70, 8148, 14, 300, 10, 1631, -1), + (1633, -1, -1, 551, 551, 5, 66, -1, 0, 0, 10, 555, 1634), + (1634, -1, -1, 551, 551, 5, 67, -1, 0, 0, 10, 1633, 1635), + (1635, -1, -1, 551, 551, 5, 68, -1, 0, 0, 10, 1634, 1636), + (1636, -1, -1, 551, 551, 5, 69, -1, 0, 0, 10, 1635, 1637), + (1637, -1, -1, 551, 551, 5, 70, -1, 0, 0, 10, 1636, 6905), + (1638, 1638, 1638, 1638, 1638, 5, 59, 8450, 7, 4320, 3, -1, -1), + (1639, 1639, 1639, 1639, 1639, 9, 65, 8451, 7, 4320, 4, -1, -1), + (1640, 1640, 1640, 1640, 1640, 12, 70, 8452, 7, 4320, 10, -1, -1), + (1641, -1, -1, 1641, 1641, 15, 70, -1, 0, 0, 3, -1, -1), + (1642, -1, -1, 1642, 1642, 15, 70, -1, 0, 0, 3, -1, -1), + (1643, 1643, 1643, 1643, 1643, 0, 59, 8975, 0, 1, 11, -1, -1), + (1644, 1644, 1644, 1644, 1644, 0, 59, 8900, 0, 1, 11, -1, -1), + (1645, 1645, 1645, 1645, 1645, 9, 70, 8977, 0, 1, 3, -1, -1), + (1646, 1646, 1646, 1646, 1646, 9, 70, 8978, 0, 1, 3, -1, -1), + (1647, 1647, 1647, 1647, 1647, 0, 68, 8771, 21, 900, 3, -1, -1), + (1648, -1, -1, 1435, 4773, 9, 71, -1, 0, 0, 16, 1221, 1649), + (1649, -1, -1, 1435, 4773, 9, 76, -1, 0, 0, 16, 1648, 1650), + (1650, -1, -1, 1435, 4773, 9, 81, -1, 0, 0, 16, 1649, 13091), + (1651, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 8214, 1652), + (1652, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1651, 1653), + (1653, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1652, 1654), + (1654, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1653, 1655), + (1655, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1654, 13149), + (1656, -1, -1, 8204, 8204, 4, 85, -1, 0, 0, 16, 8206, 1657), + (1657, -1, -1, 8204, 8204, 4, 85, -1, 0, 0, 16, 1656, -1), + (1659, -1, -1, 8207, 8207, 4, 85, -1, 0, 0, 16, 8209, 1660), + (1660, -1, -1, 8207, 8207, 4, 85, -1, 0, 0, 16, 1659, -1), + (1662, -1, -1, 1662, 1662, 3, 65, -1, 0, 0, 17, -1, 1663), + (1663, -1, -1, 1662, 1662, 3, 66, -1, 0, 0, 17, 1662, 1664), + (1664, -1, -1, 1662, 1662, 3, 67, -1, 0, 0, 17, 1663, 1665), + (1665, -1, -1, 1662, 1662, 3, 68, -1, 0, 0, 17, 1664, 1666), + (1666, -1, -1, 1662, 1662, 3, 69, -1, 0, 0, 17, 1665, -1), + (1667, 1667, 1667, 1667, 1667, 9, 85, 23602, 0, 1, 16, -1, -1), + (2400, -1, -1, 2400, 2400, 9, 81, 0, 0, 0, 17, -1, 2401), + (2401, -1, -1, 2400, 2400, 12, 83, 0, 0, 0, 17, 2400, 2402), + (2402, -1, -1, 2400, 2400, 15, 85, 0, 0, 0, 17, 2401, 15344), + (3676, 3676, 3676, 3676, 3676, 9, 85, 23606, 67, 30, 16, -1, -1), + (4665, 4665, 4665, 4665, 4665, 0, 1, 9177, 19, 4320, 0, -1, -1), + (4666, -1, -1, 4844, 4844, 5, 81, -1, 0, 0, 16, -1, 4667), + (4667, -1, -1, 4844, 4844, 5, 82, -1, 0, 0, 16, 4666, 4668), + (4668, -1, -1, 4844, 4844, 5, 83, -1, 0, 0, 16, 4667, 4669), + (4669, -1, -1, 4844, 4844, 5, 84, -1, 0, 0, 16, 4668, 4670), + (4670, -1, -1, 4844, 4844, 5, 85, -1, 0, 0, 16, 4669, -1), + (4672, -1, -1, 4672, 4672, 3, 59, -1, 0, 0, 8, -1, 4673), + (4673, -1, -1, 4672, 4672, 6, 59, -1, 0, 0, 8, 4672, 4674), + (4674, -1, -1, 4672, 4672, 9, 59, -1, 0, 0, 8, 4673, -1), + (4675, -1, -1, 4675, 4675, 3, 59, -1, 0, 0, 3, -1, 4676), + (4676, -1, -1, 4675, 4675, 6, 59, -1, 0, 0, 3, 4675, 4677), + (4677, -1, -1, 4675, 4675, 9, 59, -1, 0, 0, 3, 4676, -1), + (4678, -1, -1, 418, 418, 5, 71, -1, 0, 0, 12, 1005, 4679), + (4679, -1, -1, 418, 418, 5, 72, -1, 0, 0, 12, 4678, 4680), + (4680, -1, -1, 418, 418, 5, 73, -1, 0, 0, 12, 4679, 4681), + (4681, -1, -1, 418, 418, 5, 74, -1, 0, 0, 12, 4680, 4682), + (4682, -1, -1, 418, 418, 5, 75, -1, 0, 0, 12, 4681, 7547), + (4683, -1, -1, 1026, 1026, 5, 71, -1, 0, 0, 12, 1393, 4684), + (4684, -1, -1, 1026, 1026, 5, 72, -1, 0, 0, 12, 4683, 4685), + (4685, -1, -1, 1026, 1026, 5, 73, -1, 0, 0, 12, 4684, 4686), + (4686, -1, -1, 1026, 1026, 5, 74, -1, 0, 0, 12, 4685, 4687), + (4687, -1, -1, 1026, 1026, 5, 75, -1, 0, 0, 12, 4686, 6523), + (4688, -1, -1, 4688, 4688, 3, 71, -1, 0, 0, 12, -1, 4689), + (4689, -1, -1, 4688, 4688, 3, 72, -1, 0, 0, 12, 4688, 4690), + (4690, -1, -1, 4688, 4688, 3, 73, -1, 0, 0, 12, 4689, 4691), + (4691, -1, -1, 4688, 4688, 3, 74, -1, 0, 0, 12, 4690, 4692), + (4692, -1, -1, 4688, 4688, 3, 75, -1, 0, 0, 12, 4691, -1), + (4693, -1, -1, 65, 661, 3, 71, -1, 0, 0, 12, 1035, 4694), + (4694, -1, -1, 65, 661, 3, 72, -1, 0, 0, 12, 4693, 4695), + (4695, -1, -1, 65, 661, 3, 73, -1, 0, 0, 12, 4694, 4696), + (4696, -1, -1, 65, 661, 3, 74, -1, 0, 0, 12, 4695, 4697), + (4697, -1, -1, 65, 661, 3, 75, -1, 0, 0, 12, 4696, 6390), + (4698, -1, -1, 4698, 4698, 5, 51, -1, 0, 0, 12, -1, 6545), + (4699, -1, -1, 4699, 4699, 5, 51, -1, 0, 0, 12, -1, 6540), + (4700, 1037, 1037, 1037, 1037, 0, 1, 7619, 33, 72000, 0, -1, -1), + (4702, 4702, 4702, 4702, 4702, 3, 71, 9475, 31, 600, 12, -1, -1), + (4704, 4704, 4704, 4704, 4704, 4, 71, 9477, 31, 600, 12, -1, -1), + (4705, 4705, 4705, 4705, 4705, 3, 71, 9478, 31, 600, 12, -1, -1), + (4706, 4706, 4706, 4706, 4706, 3, 71, 9479, 31, 600, 12, -1, -1), + (4707, -1, -1, 1041, 1041, 6, 71, -1, 0, 0, 12, 1043, 4708), + (4708, -1, -1, 1041, 1041, 6, 73, -1, 0, 0, 12, 4707, 4709), + (4709, -1, -1, 1041, 1041, 6, 75, -1, 0, 0, 12, 4708, 5542), + (4710, -1, -1, 1044, 1044, 6, 71, -1, 0, 0, 12, 1046, 4711), + (4711, -1, -1, 1044, 1044, 6, 73, -1, 0, 0, 12, 4710, 4712), + (4712, -1, -1, 1044, 1044, 6, 75, -1, 0, 0, 12, 4711, 5545), + (4713, -1, -1, 1047, 1047, 6, 71, -1, 0, 0, 12, 1049, 4714), + (4714, -1, -1, 1047, 1047, 6, 73, -1, 0, 0, 12, 4713, 4715), + (4715, -1, -1, 1047, 1047, 6, 75, -1, 0, 0, 12, 4714, 5548), + (4716, -1, -1, 1050, 1050, 6, 71, -1, 0, 0, 12, 1052, 4717), + (4717, -1, -1, 1050, 1050, 6, 73, -1, 0, 0, 12, 4716, 4718), + (4718, -1, -1, 1050, 1050, 6, 75, -1, 0, 0, 12, 4717, 5551), + (4722, -1, -1, 119, 119, 3, 71, -1, 0, 0, 12, 1055, 4723), + (4723, -1, -1, 119, 119, 3, 73, -1, 0, 0, 12, 4722, 4724), + (4724, -1, -1, 119, 119, 3, 75, -1, 0, 0, 12, 4723, 5554), + (4725, -1, -1, 1592, 1592, 5, 71, -1, 0, 0, 12, 1596, 4726), + (4726, -1, -1, 1592, 1592, 5, 72, -1, 0, 0, 12, 4725, 4727), + (4727, -1, -1, 1592, 1592, 5, 73, -1, 0, 0, 12, 4726, 4728), + (4728, -1, -1, 1592, 1592, 5, 74, -1, 0, 0, 12, 4727, 4729), + (4729, -1, -1, 1592, 1592, 5, 75, -1, 0, 0, 12, 4728, 5557), + (4733, -1, -1, 625, 625, 3, 71, -1, 0, 0, 12, 627, 4734), + (4734, -1, -1, 625, 625, 3, 73, -1, 0, 0, 12, 4733, 4735), + (4735, -1, -1, 625, 625, 3, 75, -1, 0, 0, 12, 4734, 7641), + (4739, -1, -1, 4739, 4739, 3, 71, -1, 0, 0, 12, -1, 4740), + (4740, -1, -1, 4739, 4739, 6, 73, -1, 0, 0, 12, 4739, 4741), + (4741, -1, -1, 4739, 4739, 9, 75, -1, 0, 0, 12, 4740, 5562), + (4742, 4742, 4742, 4742, 4742, 9, 71, 11024, 12, 600, 12, -1, 5565), + (4744, -1, -1, 1072, 1072, 5, 71, -1, 0, 0, 12, 1076, 4745), + (4745, -1, -1, 1072, 1072, 5, 72, -1, 0, 0, 12, 4744, 4746), + (4746, -1, -1, 1072, 1072, 5, 73, -1, 0, 0, 12, 4745, 4747), + (4747, -1, -1, 1072, 1072, 5, 74, -1, 0, 0, 12, 4746, 4748), + (4748, -1, -1, 1072, 1072, 5, 75, -1, 0, 0, 12, 4747, 5566), + (4749, -1, -1, 637, 637, 6, 71, -1, 0, 0, 12, 772, 4750), + (4750, -1, -1, 637, 637, 6, 73, -1, 0, 0, 12, 4749, 4751), + (4751, -1, -1, 637, 637, 6, 75, -1, 0, 0, 12, 4750, 5571), + (4752, -1, -1, 1210, 1210, 7, 71, -1, 0, 0, 12, 1485, 4753), + (4753, -1, -1, 1210, 1210, 7, 73, -1, 0, 0, 12, 4752, 4754), + (4754, -1, -1, 1210, 1210, 7, 75, -1, 0, 0, 12, 4753, 5574), + (4755, -1, -1, 1210, 1213, 6, 71, -1, 0, 0, 12, 1215, 4756), + (4756, -1, -1, 1210, 1213, 6, 73, -1, 0, 0, 12, 4755, 4757), + (4757, -1, -1, 1210, 1213, 6, 75, -1, 0, 0, 12, 4756, 5577), + (4758, -1, -1, 602, 602, 6, 71, -1, 0, 0, 12, 1535, 4759), + (4759, -1, -1, 602, 602, 6, 73, -1, 0, 0, 12, 4758, 4760), + (4760, -1, -1, 602, 602, 6, 75, -1, 0, 0, 12, 4759, 5580), + (4761, -1, -1, 4761, 4761, 7, 71, -1, 0, 0, 12, -1, 4762), + (4762, -1, -1, 4761, 4761, 7, 73, -1, 0, 0, 12, 4761, 4763), + (4763, -1, -1, 4761, 4761, 7, 75, -1, 0, 0, 12, 4762, 6500), + (4764, -1, -1, 1071, 1071, 6, 75, -1, 0, 0, 14, 1071, 7553), + (4767, -1, -1, 98, 98, 4, 71, -1, 0, 0, 12, 100, 4768), + (4768, -1, -1, 98, 98, 4, 73, -1, 0, 0, 12, 4767, 4769), + (4769, -1, -1, 98, 98, 4, 75, -1, 0, 0, 12, 4768, 5586), + (4773, -1, -1, 1435, 4773, 9, 71, -1, 0, 0, 12, 1437, 6517), + (4776, -1, -1, 1186, 1186, 6, 71, -1, 0, 0, 12, 1188, 4777), + (4777, -1, -1, 1186, 1186, 6, 73, -1, 0, 0, 12, 4776, 4778), + (4778, -1, -1, 1186, 1186, 6, 75, -1, 0, 0, 12, 4777, 5589), + (4779, -1, -1, 80, 80, 6, 71, -1, 0, 0, 12, 1088, 4780), + (4780, -1, -1, 80, 80, 6, 73, -1, 0, 0, 12, 4779, 4781), + (4781, -1, -1, 80, 80, 6, 75, -1, 0, 0, 12, 4780, 5592), + (4790, -1, -1, 1134, 1134, 5, 71, -1, 0, 0, 12, 1162, 4791), + (4791, -1, -1, 1134, 1134, 5, 72, -1, 0, 0, 12, 4790, 4792), + (4792, -1, -1, 1134, 1134, 5, 73, -1, 0, 0, 12, 4791, 4793), + (4793, -1, -1, 1134, 1134, 5, 74, -1, 0, 0, 12, 4792, 4794), + (4794, -1, -1, 1134, 1134, 5, 75, -1, 0, 0, 12, 4793, 4804), + (4795, -1, -1, 255, 255, 5, 71, -1, 0, 0, 12, 1165, 4796), + (4796, -1, -1, 255, 255, 5, 73, -1, 0, 0, 12, 4795, 4797), + (4797, -1, -1, 255, 255, 5, 75, -1, 0, 0, 12, 4796, 5595), + (4798, -1, -1, 631, 631, 5, 71, -1, 0, 0, 12, 1174, 4799), + (4799, -1, -1, 631, 631, 5, 73, -1, 0, 0, 12, 4798, 4800), + (4800, -1, -1, 631, 631, 5, 75, -1, 0, 0, 12, 4799, -1), + (4801, -1, -1, 4801, 4801, 6, 74, -1, 0, 0, 14, -1, 4802), + (4802, -1, -1, 4801, 4801, 6, 76, -1, 0, 0, 14, 4801, 4803), + (4803, -1, -1, 4801, 4801, 6, 78, -1, 0, 0, 14, 4802, 7160), + (4804, -1, -1, 1134, 1134, 5, 76, -1, 0, 0, 15, 4794, 4805), + (4805, -1, -1, 1134, 1134, 5, 77, -1, 0, 0, 15, 4804, 4806), + (4806, -1, -1, 1134, 1134, 5, 78, -1, 0, 0, 15, 4805, 4807), + (4807, -1, -1, 1134, 1134, 5, 79, -1, 0, 0, 15, 4806, 4808), + (4808, -1, -1, 1134, 1134, 5, 80, -1, 0, 0, 15, 4807, 10311), + (4809, -1, -1, 4809, 4809, 5, 81, -1, 0, 0, 15, -1, 4810), + (4810, -1, -1, 4809, 4809, 5, 83, -1, 0, 0, 15, 4809, 4811), + (4811, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 15, 4810, 10316), + (4813, -1, -1, 820, 820, 5, 71, -1, 0, 0, 12, 1267, 4814), + (4814, -1, -1, 820, 820, 5, 73, -1, 0, 0, 12, 4813, 4815), + (4815, -1, -1, 820, 820, 5, 75, -1, 0, 0, 12, 4814, 5917), + (4819, -1, -1, 1528, 4819, 5, 71, -1, 0, 0, 12, 1532, 4820), + (4820, -1, -1, 1528, 4819, 5, 72, -1, 0, 0, 12, 4819, 4821), + (4821, -1, -1, 1528, 4819, 5, 73, -1, 0, 0, 12, 4820, 4822), + (4822, -1, -1, 1528, 4819, 5, 74, -1, 0, 0, 12, 4821, 4823), + (4823, -1, -1, 1528, 4819, 5, 75, -1, 0, 0, 12, 4822, 15188), + (4824, -1, -1, 810, 810, 5, 71, -1, 0, 0, 12, 814, 4825), + (4825, -1, -1, 810, 810, 5, 72, -1, 0, 0, 12, 4824, 4826), + (4826, -1, -1, 810, 810, 5, 73, -1, 0, 0, 12, 4825, 4827), + (4827, -1, -1, 810, 810, 5, 74, -1, 0, 0, 12, 4826, 4828), + (4828, -1, -1, 810, 810, 5, 75, -1, 0, 0, 12, 4827, 15426), + (4829, -1, -1, 1546, 1546, 5, 71, -1, 0, 0, 12, 1548, 4830), + (4830, -1, -1, 1546, 1546, 5, 72, -1, 0, 0, 12, 4829, 4831), + (4831, -1, -1, 1546, 1546, 5, 73, -1, 0, 0, 12, 4830, 6441), + (4836, 4836, 4836, 4836, 4836, 5, 71, 11033, 5, 30, 12, -1, -1), + (4844, -1, -1, 4844, 4844, 5, 71, -1, 0, 0, 12, -1, 4845), + (4845, -1, -1, 4844, 4844, 5, 72, -1, 0, 0, 12, 4844, 4846), + (4846, -1, -1, 4844, 4844, 5, 73, -1, 0, 0, 12, 4845, 4847), + (4847, -1, -1, 4844, 4844, 5, 74, -1, 0, 0, 12, 4846, 4848), + (4848, -1, -1, 4844, 4844, 5, 75, -1, 0, 0, 12, 4847, 7122), + (4849, 4849, 4849, 4849, 4849, 9, 71, 11041, 7, 1800, 12, -1, 6134), + (4854, 4854, 4854, 4854, 4854, 3, 71, 11046, 8, 600, 12, -1, 4855), + (4855, 4854, 4854, 4854, 4854, 6, 73, 11047, 8, 600, 12, 4854, 4856), + (4856, 4854, 4854, 4854, 4854, 9, 75, 11048, 8, 600, 12, 4855, 5764), + (4857, 4857, 4857, 4857, 4857, 3, 71, 11049, 7, 600, 12, -1, 4858), + (4858, 4857, 4857, 4857, 4857, 6, 73, 11050, 7, 600, 12, 4857, 4859), + (4859, 4857, 4857, 4857, 4857, 9, 75, 11051, 7, 600, 12, 4858, 5767), + (4860, 4860, 4860, 4860, 4860, 9, 75, 11052, 13, 60, 12, -1, 5606), + (4861, -1, -1, 4861, 4861, 6, 71, -1, 0, 0, 12, -1, 4862), + (4862, -1, -1, 4861, 4861, 6, 73, -1, 0, 0, 12, 4861, 4863), + (4863, -1, -1, 4861, 4861, 6, 75, -1, 0, 0, 12, 4862, 5954), + (4864, 1274, 1274, 1274, 1274, 6, 73, 11053, 9, 540, 12, 1276, 4865), + (4865, 1274, 1274, 1274, 1274, 6, 74, 11054, 9, 540, 12, 4864, 4866), + (4866, 1274, 1274, 1274, 1274, 6, 75, 11055, 9, 540, 12, 4865, 5947), + (4887, -1, -1, 4887, 4887, 6, 71, -1, 0, 0, 12, -1, 4888), + (4888, -1, -1, 4887, 4887, 6, 73, -1, 0, 0, 12, 4887, 4889), + (4889, -1, -1, 4887, 4887, 6, 75, -1, 0, 0, 12, 4888, -1), + (4890, 4890, -1, 4890, 4890, 9, 75, 11056, 3, 8640, 12, -1, 5869), + (4894, 4894, 4894, 4894, 4894, 6, 73, 11057, 7, 2160, 12, -1, 4895), + (4895, 4894, 4894, 4894, 4894, 6, 74, 11058, 7, 2160, 12, 4894, 4896), + (4896, 4894, 4894, 4894, 4894, 6, 75, 11059, 7, 2160, 12, 4895, 6352), + (4897, -1, -1, 795, 795, 6, 71, -1, 0, 0, 12, 1432, 4898), + (4898, -1, -1, 795, 795, 6, 73, -1, 0, 0, 12, 4897, 4899), + (4899, -1, -1, 795, 795, 6, 75, -1, 0, 0, 12, 4898, 5889), + (4900, 1462, 1462, 1462, 1462, 6, 71, 11061, 5, 300, 12, 1466, 4901), + (4901, 1462, 1462, 1462, 1462, 6, 73, 11062, 5, 300, 12, 4900, 4902), + (4902, 1462, 1462, 1462, 1462, 6, 75, 11063, 5, 300, 12, 4901, 14739), + (4903, 4903, 4903, 4903, 4903, 9, 71, 11064, 9, 1320, 12, -1, 5892), + (4906, 4906, 4906, 4906, 4906, 9, 71, 11065, 9, 1320, 12, -1, 5893), + (4909, 4909, 4909, 4909, 4909, 9, 71, 11066, 16, 1320, 12, -1, 5894), + (4912, 4912, 4912, 4912, 4912, 9, 71, 11067, 16, 1320, 12, -1, 5895), + (4915, 4915, 4915, 4915, 4915, 9, 71, 11068, 7, 4320, 12, -1, 4916), + (4916, 4915, 4915, 4915, 4915, 9, 73, 11069, 7, 4320, 12, 4915, 4917), + (4917, 4915, 4915, 4915, 4915, 9, 75, 11070, 7, 4320, 12, 4916, 5607), + (4921, -1, -1, 480, 480, 2, 71, -1, 0, 0, 12, 482, 4922), + (4922, -1, -1, 480, 480, 2, 73, -1, 0, 0, 12, 4921, 4923), + (4923, -1, -1, 480, 480, 2, 75, -1, 0, 0, 12, 4922, -1), + (4924, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, -1, 4925), + (4925, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, 4924, 4926), + (4926, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, 4925, 5944), + (4927, 4927, 4927, 4927, 4927, 9, 71, 11076, 14, 600, 12, -1, 7209), + (4931, 4931, 4931, 4931, 4931, 6, 71, 11083, 4, 600, 12, -1, 4932), + (4932, 4931, 4931, 4931, 4931, 6, 73, 11084, 4, 600, 12, 4931, 4933), + (4933, 4931, 4931, 4931, 4931, 6, 75, 11085, 4, 600, 12, 4932, 6054), + (4934, 4934, 4934, 4934, 4934, 7, 71, 11086, 13, 300, 12, -1, 7295), + (4935, 4935, 4935, 4935, 4935, 7, 71, 11087, 14, 300, 12, -1, 7294), + (4938, 4938, 4938, 4938, 4938, 9, 75, 11092, 35, 1800, 12, -1, 5610), + (4943, 4943, 4943, 4943, 4943, 7, 75, 11098, 17, 1800, 12, -1, -1), + (4944, 4944, -1, 4944, 4944, 3, 71, 11103, 0, 1, 12, -1, 4945), + (4945, 4944, -1, 4944, 4944, 6, 73, 11104, 0, 1, 12, 4944, 4946), + (4946, 4944, -1, 4944, 4944, 9, 75, 11105, 0, 1, 12, 4945, 6155), + (4948, -1, -1, 846, 846, 3, 71, -1, 0, 0, 12, 1303, 4949), + (4949, -1, -1, 846, 846, 6, 73, -1, 0, 0, 12, 4948, 4950), + (4950, -1, -1, 846, 846, 9, 75, -1, 0, 0, 12, 4949, 6035), + (4951, -1, -1, 1543, 1543, 5, 71, -1, 0, 0, 12, 1545, 4952), + (4952, -1, -1, 1543, 1543, 5, 73, -1, 0, 0, 12, 4951, 4953), + (4953, -1, -1, 1543, 1543, 5, 75, -1, 0, 0, 12, 4952, 6042), + (4957, -1, -1, 878, 878, 7, 71, -1, 0, 0, 12, 1541, 4958), + (4958, -1, -1, 878, 878, 7, 73, -1, 0, 0, 12, 4957, 4959), + (4959, -1, -1, 878, 878, 7, 75, -1, 0, 0, 12, 4958, 6331), + (4960, -1, -1, 729, 729, 6, 71, -1, 0, 0, 12, 1469, 4961), + (4961, -1, -1, 729, 729, 6, 73, -1, 0, 0, 12, 4960, 4962), + (4962, -1, -1, 729, 729, 6, 75, -1, 0, 0, 12, 4961, 5738), + (4963, 723, 723, 723, 723, 9, 71, 11205, 6, 30, 12, 723, 5737), + (4964, 1119, 1119, 1119, 1119, 6, 73, 11206, 8, 900, 12, 1121, 4965), + (4965, 1119, 1119, 1119, 1119, 6, 74, 11207, 8, 900, 12, 4964, 4966), + (4966, 1119, 1119, 1119, 1119, 6, 75, 11208, 8, 900, 12, 4965, 5734), + (4969, 291, 291, 291, 291, 5, 71, 11212, 5, 900, 12, 1125, 4970), + (4970, 291, 291, 291, 291, 5, 73, 11213, 5, 900, 12, 4969, 4971), + (4971, 291, 291, 291, 291, 5, 75, 11214, 5, 900, 12, 4970, 5743), + (4972, 1598, -1, 1598, 1598, 6, 71, 11215, 6, 900, 12, 1600, 4973), + (4973, 1598, -1, 1598, 1598, 6, 73, 11216, 6, 900, 12, 4972, 4974), + (4974, 1598, -1, 1598, 1598, 6, 75, 11217, 6, 900, 12, 4973, 5710), + (4975, 592, 592, 592, 592, 3, 71, 11218, 2, 18, 12, 1106, 4976), + (4976, 592, 592, 592, 592, 3, 72, 11219, 2, 18, 12, 4975, 4977), + (4977, 592, 592, 592, 592, 3, 73, 11220, 2, 18, 12, 4976, 4978), + (4978, 592, 592, 592, 592, 3, 74, 11221, 2, 18, 12, 4977, 4979), + (4979, 592, 592, 592, 592, 3, 75, 11222, 2, 18, 12, 4978, 5702), + (4980, 1116, 1116, 1116, 1116, 6, 73, 11223, 4, 2160, 12, 1118, 4981), + (4981, 1116, 1116, 1116, 1116, 6, 74, 11224, 4, 2160, 12, 4980, 4982), + (4982, 1116, 1116, 1116, 1116, 6, 75, 11225, 4, 2160, 12, 4981, 5699), + (4983, -1, -1, 864, 864, 6, 71, -1, 0, 0, 12, 1292, 4984), + (4984, -1, -1, 864, 864, 6, 73, -1, 0, 0, 12, 4983, 4985), + (4985, -1, -1, 864, 864, 6, 75, -1, 0, 0, 12, 4984, 6011), + (4986, -1, -1, 644, 644, 5, 67, -1, 0, 0, 12, 1603, 4987), + (4987, -1, -1, 644, 644, 5, 69, -1, 0, 0, 12, 4986, 4988), + (4988, -1, -1, 644, 644, 5, 71, -1, 0, 0, 12, 4987, 6017), + (4989, -1, -1, 1608, 1608, 6, 71, -1, 0, 0, 12, 1610, 4990), + (4990, -1, -1, 1608, 1608, 6, 73, -1, 0, 0, 12, 4989, 4991), + (4991, -1, -1, 1608, 1608, 6, 75, -1, 0, 0, 12, 4990, 7378), + (4992, -1, -1, 1616, 1616, 5, 71, -1, 0, 0, 12, 1620, 4993), + (4993, -1, -1, 1616, 1616, 5, 72, -1, 0, 0, 12, 4992, 4994), + (4994, -1, -1, 1616, 1616, 5, 73, -1, 0, 0, 12, 4993, 4995), + (4995, -1, -1, 1616, 1616, 5, 74, -1, 0, 0, 12, 4994, 4996), + (4996, -1, -1, 1616, 1616, 5, 75, -1, 0, 0, 12, 4995, 6003), + (4997, 545, 545, 545, 545, 6, 73, 11226, 3, 900, 12, 1295, 4998), + (4998, 545, 545, 545, 545, 6, 74, 11227, 3, 900, 12, 4997, 4999), + (4999, 545, 545, 545, 545, 6, 75, 11228, 3, 900, 12, 4998, 6000), + (5000, -1, -1, 1230, 1230, 2, 71, -1, 0, 0, 12, 1232, 5001), + (5001, -1, -1, 1230, 1230, 2, 73, -1, 0, 0, 12, 5000, 5002), + (5002, -1, -1, 1230, 1230, 2, 75, -1, 0, 0, 12, 5001, -1), + (5003, 1345, 1345, 1345, 1345, 5, 73, 11229, 6, 900, 12, 1347, 5004), + (5004, 1345, 1345, 1345, 1345, 5, 74, 11230, 6, 900, 12, 5003, 5005), + (5005, 1345, 1345, 1345, 1345, 5, 75, 11231, 6, 900, 12, 5004, 6008), + (5006, 5006, 5006, 5006, 5006, 0, 0, 27673, 96, 72000, 0, -1, -1), + (5007, 5007, 5007, 5007, 5007, 3, 71, 11233, 8, 2160, 12, -1, 5008), + (5008, 5007, 5007, 5007, 5007, 6, 73, 11234, 8, 2160, 12, 5007, 5009), + (5009, 5007, 5007, 5007, 5007, 9, 75, 11235, 8, 2160, 12, 5008, 6425), + (5010, -1, -1, 1007, 1007, 8, 81, -1, 0, 0, 16, -1, 5011), + (5011, -1, -1, 1007, 1007, 10, 83, -1, 0, 0, 16, 5010, 5012), + (5012, -1, -1, 1007, 1007, 12, 85, -1, 0, 0, 16, 5011, 15317), + (5013, -1, -1, 1284, 1284, 6, 83, -1, 0, 0, 16, 5037, 5014), + (5014, -1, -1, 1284, 1284, 6, 85, -1, 0, 0, 16, 5013, -1), + (5015, 5015, 5015, 5015, 5015, 5, 75, 11241, 9, 900, 12, -1, 5741), + (5017, 5017, 5017, 5017, 5017, 3, 71, 11243, 8, 600, 12, -1, 5018), + (5018, 5017, 5017, 5017, 5017, 6, 73, 11244, 8, 600, 12, 5017, 5019), + (5019, 5017, 5017, 5017, 5017, 9, 75, 11245, 8, 600, 12, 5018, 7454), + (5020, 5020, 5020, 5020, 5020, 9, 75, 11246, 9, 300, 12, -1, 5716), + (5021, 5021, 5021, 5021, 5021, 9, 71, 11341, 7, 60, 12, -1, 10868), + (5022, 5022, 5022, 5022, 5022, 3, 71, 11247, 5, 600, 12, -1, 5023), + (5023, 5022, 5022, 5022, 5022, 6, 73, 23986, 5, 600, 12, 5022, 5024), + (5024, 5022, 5022, 5022, 5022, 9, 75, 23987, 5, 600, 12, 5023, 6038), + (5025, 5025, 5025, 5025, 5025, 3, 71, 11251, 6, 180, 12, -1, 5026), + (5026, 5025, 5025, 5025, 5025, 6, 73, 11252, 6, 180, 12, 5025, 5027), + (5027, 5025, 5025, 5025, 5025, 9, 75, 11253, 6, 180, 12, 5026, -1), + (5028, 5028, -1, 5028, 5028, 9, 75, 11254, 4, 900, 12, -1, 6041), + (5029, -1, -1, 1313, 1313, 6, 71, -1, 0, 0, 8, 1315, 5030), + (5030, -1, -1, 1313, 1313, 6, 73, -1, 0, 0, 8, 5029, 5031), + (5031, -1, -1, 1313, 1313, 6, 75, -1, 0, 0, 8, 5030, 6066), + (5032, -1, -1, 634, 634, 5, 72, -1, 0, 0, 12, 1321, 5033), + (5033, -1, -1, 634, 634, 5, 73, -1, 0, 0, 12, 5032, 5034), + (5034, -1, -1, 634, 634, 5, 74, -1, 0, 0, 12, 5033, 5611), + (5035, -1, -1, 1284, 1284, 6, 71, -1, 0, 0, 12, 1286, 5036), + (5036, -1, -1, 1284, 1284, 6, 73, -1, 0, 0, 12, 5035, 5037), + (5037, -1, -1, 1284, 1284, 6, 75, -1, 0, 0, 12, 5036, 5013), + (5038, -1, -1, 190, 190, 7, 71, -1, 0, 0, 12, 1525, 5039), + (5039, -1, -1, 190, 190, 7, 73, -1, 0, 0, 12, 5038, 5040), + (5040, -1, -1, 190, 190, 7, 75, -1, 0, 0, 12, 5039, 15141), + (5041, 534, 534, 534, 534, 5, 72, 11255, 4, 2160, 12, 1280, 5042), + (5042, 534, 534, 534, 534, 5, 73, 11256, 4, 2160, 12, 5041, 5043), + (5043, 534, 534, 534, 534, 5, 74, 11257, 4, 2160, 12, 5042, 5969), + (5044, 188, 188, 188, 188, 9, 73, 11258, 2, 30, 12, 1277, 7339), + (5045, -1, -1, 1057, 1057, 9, 85, -1, 0, 0, 16, -1, -1), + (5051, 757, -1, 757, 757, 5, 71, 11262, 6, 1800, 12, 1224, 5052), + (5052, 757, -1, 757, 757, 5, 73, 11263, 6, 1800, 12, 5051, 5053), + (5053, 757, -1, 757, 757, 5, 75, 11264, 6, 1800, 12, 5052, 5822), + (5054, 548, 548, 548, 548, 5, 72, 11265, 5, 900, 12, 1227, 5055), + (5055, 548, 548, 548, 548, 5, 73, 11266, 5, 900, 12, 5054, 5056), + (5056, 548, 548, 548, 548, 5, 74, 11267, 5, 900, 12, 5055, 5829), + (5058, 1498, 1498, 1498, 1498, 6, 71, 11269, 12, 1320, 12, 1500, 5059), + (5059, 1498, 1498, 1498, 1498, 6, 73, 11270, 12, 1320, 12, 5058, 5060), + (5060, 1498, 1498, 1498, 1498, 6, 75, 11271, 12, 1320, 12, 5059, 5819), + (5061, -1, -1, 567, 567, 5, 72, -1, 0, 0, 12, 567, 5825), + (5062, 459, 459, 459, 459, 6, 71, 11272, 8, 180, 12, 1191, 5063), + (5063, 459, 459, 459, 459, 6, 73, 11273, 8, 180, 12, 5062, 5064), + (5064, 459, 459, 459, 459, 6, 75, 11274, 8, 180, 12, 5063, -1), + (5068, 153, 153, 153, 153, 9, 75, 11279, 3, 2160, 12, 1519, 6101), + (5069, 146, 146, 146, 146, 5, 72, 11281, 2, 180, 12, 146, 6102), + (5070, 131, 131, 131, 131, 5, 72, 11282, 4, 900, 12, 1205, 5071), + (5071, 131, 131, 131, 131, 5, 73, 11283, 4, 900, 12, 5070, 5072), + (5072, 131, 131, 131, 131, 5, 74, 11284, 4, 900, 12, 5071, 5791), + (5076, 1192, 1192, 1192, 1192, 5, 72, 11288, 12, 1320, 12, 1194, 5077), + (5077, 1192, 1192, 1192, 1192, 5, 73, 11289, 12, 1320, 12, 5076, 5078), + (5078, 1192, 1192, 1192, 1192, 5, 74, 11290, 12, 1320, 12, 5077, 5794), + (5079, 1195, 1195, 1195, 1195, 9, 75, 11291, 13, 2160, 12, 1195, 5790), + (5080, 1459, 1459, 1459, 1459, 5, 71, 11293, 11, 1800, 12, 1461, 5081), + (5081, 1459, 1459, 1459, 1459, 5, 73, 11294, 11, 1800, 12, 5080, 5082), + (5082, 1459, 1459, 1459, 1459, 5, 75, 11295, 11, 1800, 12, 5081, 5803), + (5084, 1383, 1383, 1383, 1383, 12, 75, 11296, 6, 300, 12, 1387, 5789), + (5085, -1, -1, 5085, 5085, 3, 71, -1, 0, 0, 12, -1, 5086), + (5086, -1, -1, 5085, 5085, 6, 73, -1, 0, 0, 12, 5085, 5087), + (5087, -1, -1, 5085, 5085, 9, 75, -1, 0, 0, 12, 5086, 6406), + (5095, 5095, 5095, 5095, 5095, 3, 71, 11307, 10, 900, 12, -1, 5096), + (5096, 5095, 5095, 5095, 5095, 6, 73, 11308, 10, 900, 12, 5095, 5097), + (5097, 5095, 5095, 5095, 5095, 9, 75, 11309, 10, 900, 12, 5096, 5975), + (5098, 5098, 5098, 5098, 5098, 9, 75, 11310, 2, 30, 12, -1, -1), + (5105, 5105, 5105, 5105, 5105, 9, 75, 11317, 11, 600, 12, -1, 5832), + (5109, 5109, 5109, 5109, 5109, 9, 75, 11321, 0, 1, 12, -1, 6448), + (5118, -1, -1, 5083, 5083, 3, 71, -1, 0, 0, 12, -1, 5119), + (5119, -1, -1, 5083, 5083, 3, 73, -1, 0, 0, 12, 5118, 5120), + (5120, -1, -1, 5083, 5083, 3, 75, -1, 0, 0, 12, 5119, 5797), + (5127, -1, -1, 5127, 5127, 3, 71, -1, 0, 0, 12, -1, 5128), + (5128, -1, -1, 5127, 5127, 3, 73, -1, 0, 0, 12, 5127, 5129), + (5129, -1, -1, 5127, 5127, 3, 75, -1, 0, 0, 12, 5128, -1), + (5130, 860, 860, 860, 860, 6, 71, 5860, 5, 180, 12, 862, 5131), + (5131, 860, 860, 860, 860, 6, 73, 5861, 5, 180, 12, 5130, 5132), + (5132, 860, 860, 860, 860, 6, 75, 5862, 5, 180, 12, 5131, -1), + (5133, -1, -1, 267, 267, 6, 71, -1, 0, 0, 12, 925, 5134), + (5134, -1, -1, 267, 267, 6, 73, -1, 0, 0, 12, 5133, 5135), + (5135, -1, -1, 267, 267, 6, 75, -1, 0, 0, 12, 5134, 5617), + (5136, -1, -1, 4688, 4688, 3, 71, -1, 0, 0, 12, -1, 5137), + (5137, -1, -1, 4688, 4688, 3, 72, -1, 0, 0, 12, 5136, 5138), + (5138, -1, -1, 4688, 4688, 3, 73, -1, 0, 0, 12, 5137, 5139), + (5139, -1, -1, 4688, 4688, 3, 74, -1, 0, 0, 12, 5138, 5140), + (5140, -1, -1, 4688, 4688, 3, 75, -1, 0, 0, 12, 5139, -1), + (5141, -1, -1, 815, 815, 5, 71, -1, 0, 0, 12, 819, 5142), + (5142, -1, -1, 815, 815, 5, 72, -1, 0, 0, 12, 5141, 5143), + (5143, -1, -1, 815, 815, 5, 73, -1, 0, 0, 12, 5142, 5144), + (5144, -1, -1, 815, 815, 5, 74, -1, 0, 0, 12, 5143, 5145), + (5145, -1, -1, 815, 815, 5, 75, -1, 0, 0, 12, 5144, 5909), + (5150, 5150, 5150, 5150, 5150, 0, 1, 11112, 22, 300, 3, -1, 5151), + (5165, 5165, 5165, 5165, 5165, 0, 1, 11127, 22, 300, 3, -1, 5166), + (5180, 5180, 5180, 5180, 5180, 0, 1, 11142, 22, 300, 3, -1, 5181), + (5195, 5195, 5195, 5195, 5195, 0, 1, 11157, 22, 300, 3, -1, 5196), + (5210, 5210, 5210, 5210, 5210, 0, 1, 11172, 22, 300, 3, -1, 5211), + (5225, 5225, 5225, 5225, 5225, 0, 1, 11187, 22, 300, 3, -1, 5226), + (5240, 1355, 1355, 1355, 1355, 6, 71, 11611, 3, 60, 12, 1357, 5241), + (5241, 1355, 1355, 1355, 1355, 6, 73, 11612, 3, 60, 12, 5240, 5242), + (5242, 1355, 1355, 1355, 1355, 6, 75, 11613, 3, 60, 12, 5241, 5914), + (5243, -1, -1, 907, 907, 7, 71, -1, 0, 0, 12, 911, 5244), + (5244, -1, -1, 907, 907, 7, 72, -1, 0, 0, 12, 5243, 5245), + (5245, -1, -1, 907, 907, 7, 73, -1, 0, 0, 12, 5244, 5246), + (5246, -1, -1, 907, 907, 7, 74, -1, 0, 0, 12, 5245, 5247), + (5247, -1, -1, 907, 907, 7, 75, -1, 0, 0, 12, 5246, -1), + (5248, -1, -1, 5248, 5248, 3, 71, -1, 0, 0, 12, -1, 5249), + (5249, -1, -1, 5248, 5248, 6, 73, -1, 0, 0, 12, 5248, 5250), + (5250, -1, -1, 5248, 5248, 9, 75, -1, 0, 0, 12, 5249, 6014), + (5251, 5251, 5251, 5251, 5251, 5, 71, 11615, 13, 900, 12, -1, 5252), + (5252, 5251, 5251, 5251, 5251, 5, 73, 11616, 13, 900, 12, 5251, 5253), + (5253, 5251, 5251, 5251, 5251, 5, 75, 11617, 13, 900, 12, 5252, 6092), + (5254, -1, -1, 724, 724, 3, 71, -1, 0, 0, 12, 728, 5255), + (5255, -1, -1, 724, 724, 3, 72, -1, 0, 0, 12, 5254, 5256), + (5256, -1, -1, 724, 724, 3, 73, -1, 0, 0, 12, 5255, 5257), + (5257, -1, -1, 724, 724, 3, 74, -1, 0, 0, 12, 5256, 5258), + (5258, -1, -1, 724, 724, 3, 75, -1, 0, 0, 12, 5257, 5729), + (5259, -1, -1, 790, 790, 3, 71, -1, 0, 0, 12, 794, 5260), + (5260, -1, -1, 790, 790, 3, 72, -1, 0, 0, 12, 5259, 5261), + (5261, -1, -1, 790, 790, 3, 73, -1, 0, 0, 12, 5260, 5262), + (5262, -1, -1, 790, 790, 3, 74, -1, 0, 0, 12, 5261, 5263), + (5263, -1, -1, 790, 790, 3, 75, -1, 0, 0, 12, 5262, 5320), + (5264, -1, -1, 5264, 5264, 3, 71, -1, 0, 0, 12, -1, 5265), + (5265, -1, -1, 5264, 5264, 3, 72, -1, 0, 0, 12, 5264, 5266), + (5266, -1, -1, 5264, 5264, 3, 73, -1, 0, 0, 12, 5265, 5267), + (5267, -1, -1, 5264, 5264, 3, 74, -1, 0, 0, 12, 5266, 5268), + (5268, -1, -1, 5264, 5264, 3, 75, -1, 0, 0, 12, 5267, 5939), + (5269, -1, -1, 5269, 5269, 3, 71, -1, 0, 0, 12, -1, -1), + (5270, -1, -1, 589, 589, 7, 71, -1, 0, 0, 12, 894, 5271), + (5271, -1, -1, 589, 589, 7, 73, -1, 0, 0, 12, 5270, 5272), + (5272, -1, -1, 589, 589, 7, 75, -1, 0, 0, 12, 5271, 6063), + (5276, -1, -1, 5276, 5276, 3, 71, -1, 0, 0, 12, -1, 5277), + (5277, -1, -1, 5276, 5276, 6, 73, -1, 0, 0, 12, 5276, 5278), + (5278, -1, -1, 5276, 5276, 9, 75, -1, 0, 0, 12, 5277, 15238), + (5279, 155, 155, 155, 155, 12, 75, 11624, 8, 60, 12, 1344, 5289), + (5280, 921, 921, 921, 921, 9, 74, 11625, 8, 60, 12, 1340, 6149), + (5281, 922, 922, 922, 922, 9, 73, 11626, 8, 60, 12, 1341, 6150), + (5282, 923, 923, 923, 923, 9, 72, 11627, 8, 60, 12, 1342, 6151), + (5283, -1, -1, 5263, 5263, 3, 71, -1, 0, 0, 12, -1, 5284), + (5284, -1, -1, 5263, 5263, 6, 73, -1, 0, 0, 12, 5283, 5285), + (5285, -1, -1, 5263, 5263, 9, 75, -1, 0, 0, 12, 5284, 5620), + (5286, -1, -1, 1107, 1107, 6, 71, -1, 0, 0, 12, 1109, 5287), + (5287, -1, -1, 1107, 1107, 6, 73, -1, 0, 0, 12, 5286, 5288), + (5288, -1, -1, 1107, 1107, 6, 75, -1, 0, 0, 12, 5287, 6403), + (5289, 155, 155, 155, 155, 12, 77, 13227, 8, 60, 14, 5279, 7238), + (5290, -1, -1, 1604, 1604, 5, 63, -1, 0, 0, 12, 1606, 5291), + (5291, -1, -1, 1604, 1604, 5, 64, -1, 0, 0, 12, 5290, 5292), + (5292, -1, -1, 1604, 1604, 5, 65, -1, 0, 0, 12, 5291, 5293), + (5293, -1, -1, 1604, 1604, 5, 66, -1, 0, 0, 12, 5292, 5294), + (5294, -1, -1, 1604, 1604, 5, 67, -1, 0, 0, 12, 5293, 6032), + (5295, -1, -1, 5295, 5295, 3, 71, -1, 0, 0, 12, -1, 5296), + (5296, -1, -1, 5295, 5295, 6, 73, -1, 0, 0, 12, 5295, 5297), + (5297, -1, -1, 5295, 5295, 9, 75, -1, 0, 0, 12, 5296, 6531), + (5298, 5298, 5298, 5298, 5298, 3, 71, 11630, 32, 1800, 12, -1, 5299), + (5299, 5298, 5298, 5298, 5298, 6, 73, 11631, 32, 1800, 12, 5298, 5300), + (5300, 5298, 5298, 5298, 5298, 9, 75, 11632, 32, 1800, 12, 5299, 5707), + (5301, -1, -1, 683, 683, 5, 71, -1, 0, 0, 12, 1038, 5302), + (5302, -1, -1, 683, 683, 5, 72, -1, 0, 0, 12, 5301, 5303), + (5303, -1, -1, 683, 683, 5, 73, -1, 0, 0, 12, 5302, 5304), + (5304, -1, -1, 683, 683, 5, 74, -1, 0, 0, 12, 5303, 5305), + (5305, -1, -1, 683, 683, 5, 75, -1, 0, 0, 12, 5304, 6080), + (5306, -1, -1, 658, 658, 5, 71, -1, 0, 0, 12, 660, 5307), + (5307, -1, -1, 658, 658, 5, 72, -1, 0, 0, 12, 5306, 5308), + (5308, -1, -1, 658, 658, 5, 73, -1, 0, 0, 12, 5307, 5309), + (5309, -1, -1, 658, 658, 5, 74, -1, 0, 0, 12, 5308, 5310), + (5310, -1, -1, 658, 658, 5, 75, -1, 0, 0, 12, 5309, 5623), + (5311, 1495, 1495, 1495, 1495, 5, 71, 11639, 30, 900, 12, 1497, 5312), + (5312, 1495, 1495, 1495, 1495, 5, 73, 11640, 30, 900, 12, 5311, 5313), + (5313, 1495, 1495, 1495, 1495, 5, 75, 11641, 30, 900, 12, 5312, 5826), + (5314, 1327, 1327, 1327, 1327, 5, 71, 11642, 10, 900, 12, 1329, 5315), + (5315, 1327, 1327, 1327, 1327, 5, 73, 11643, 10, 900, 12, 5314, 5316), + (5316, 1327, 1327, 1327, 1327, 5, 75, 11644, 10, 900, 12, 5315, 6098), + (5317, -1, -1, 98, 738, 4, 71, -1, 0, 0, 12, 740, 5318), + (5318, -1, -1, 98, 738, 4, 73, -1, 0, 0, 12, 5317, 5319), + (5319, -1, -1, 98, 738, 4, 75, -1, 0, 0, 12, 5318, 5628), + (5320, -1, -1, 790, 790, 6, 76, -1, 0, 0, 14, 5263, 5321), + (5321, -1, -1, 790, 790, 6, 77, -1, 0, 0, 14, 5320, 5322), + (5322, -1, -1, 790, 790, 6, 78, -1, 0, 0, 14, 5321, 5323), + (5323, -1, -1, 790, 790, 6, 79, -1, 0, 0, 14, 5322, 5324), + (5324, -1, -1, 790, 790, 6, 80, -1, 0, 0, 14, 5323, 7270), + (5325, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 843, 5326), + (5326, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5325, 5327), + (5327, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5326, 5328), + (5328, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5327, 5329), + (5329, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5328, 7210), + (5330, 1327, 1327, 1327, 1327, 12, 91, 30870, 10, 900, 18, 10189, 5331), + (5333, 1520, 1520, 1520, 1520, 9, 91, 30873, 11, 900, 18, 12999, 5334), + (5336, 12989, 12989, 12989, 12989, 11, 91, 30876, 73, 1800, 18, 12991, 5337), + (5339, -1, -1, 6383, 6383, 11, 91, -1, 0, 0, 18, 12803, 5340), + (5342, 6692, 6692, 6692, 6692, 9, 91, 30879, 42, 600, 18, 6696, 5343), + (5347, -1, -1, 6375, 6375, 12, 91, -1, 0, 0, 18, 10086, 5348), + (5348, -1, -1, 6375, 6375, 15, 93, -1, 0, 0, 18, 5347, 5349), + (5350, 12992, 12992, 12992, 12992, 12, 91, 30884, 0, 1, 18, 12994, 5351), + (5353, 6706, 6706, 6706, 6706, 9, 91, 30887, 44, 600, 18, 10181, 5354), + (5356, 5109, 5109, 5109, 5109, 12, 92, 30890, 0, 1, 18, 13016, 17323), + (5357, 528, 528, 528, 528, 12, 91, 30891, 5, 720, 18, 13163, 5358), + (5360, -1, -1, 9503, 9503, 11, 91, -1, 0, 0, 18, 12794, 5361), + (5363, 5251, 5251, 5251, 5251, 15, 91, 30894, 13, 900, 18, 10199, 5364), + (5366, -1, -1, 5002, 5002, 12, 91, -1, 34, 0, 18, -1, 5367), + (5369, 5001, 5001, 5001, 5001, 12, 91, 30900, 32, 600, 18, -1, 5370), + (5500, -1, -1, 852, 852, 9, 78, -1, 0, 0, 14, 854, 5501), + (5501, -1, -1, 852, 852, 10, 79, -1, 0, 0, 14, 5500, 5502), + (5502, -1, -1, 852, 852, 12, 80, -1, 0, 0, 14, 5501, 7678), + (5513, 1126, 1126, 1126, 1126, 8, 77, 12668, 2, 2160, 14, 1128, 5514), + (5514, 1126, 1126, 1126, 1126, 9, 78, 12669, 2, 2160, 14, 5513, 5515), + (5515, 1126, 1126, 1126, 1126, 10, 79, 12670, 2, 2160, 14, 5514, 13253), + (5516, -1, -1, 1287, 1287, 8, 77, -1, 0, 0, 14, 1289, 5517), + (5517, -1, -1, 1287, 1287, 9, 78, -1, 0, 0, 14, 5516, 5518), + (5518, -1, -1, 1287, 1287, 10, 79, -1, 0, 0, 14, 5517, 12469), + (5519, -1, -1, 125, 125, 6, 76, -1, 0, 0, 14, 1398, 5520), + (5520, -1, -1, 125, 125, 7, 77, -1, 0, 0, 14, 5519, 5521), + (5521, -1, -1, 125, 125, 8, 78, -1, 0, 0, 14, 5520, 5522), + (5522, -1, -1, 125, 125, 9, 79, -1, 0, 0, 14, 5521, 5523), + (5523, -1, -1, 125, 125, 10, 80, -1, 0, 0, 14, 5522, 7501), + (5524, -1, -1, 122, 122, 6, 76, -1, 0, 0, 14, 1403, 5525), + (5525, -1, -1, 122, 122, 7, 77, -1, 0, 0, 14, 5524, 5526), + (5526, -1, -1, 122, 122, 8, 78, -1, 0, 0, 14, 5525, 5527), + (5527, -1, -1, 122, 122, 9, 79, -1, 0, 0, 14, 5526, 5528), + (5528, -1, -1, 122, 122, 10, 80, -1, 0, 0, 14, 5527, 7506), + (5529, -1, -1, 1486, 1486, 7, 76, -1, 0, 0, 14, 1490, 5530), + (5530, -1, -1, 1486, 1486, 8, 77, -1, 0, 0, 14, 5529, 5531), + (5531, -1, -1, 1486, 1486, 9, 78, -1, 0, 0, 14, 5530, 5532), + (5532, -1, -1, 1486, 1486, 10, 79, -1, 0, 0, 14, 5531, 5533), + (5533, -1, -1, 1486, 1486, 12, 80, -1, 0, 0, 14, 5532, 7554), + (5534, -1, -1, 599, 599, 9, 78, -1, 0, 0, 14, 1538, 5535), + (5535, -1, -1, 599, 599, 10, 79, -1, 0, 0, 14, 5534, 5536), + (5536, -1, -1, 599, 599, 12, 80, -1, 0, 0, 14, 5535, 7559), + (5542, -1, -1, 1041, 1041, 7, 76, -1, 0, 0, 14, 4709, 5543), + (5543, -1, -1, 1041, 1041, 9, 78, -1, 0, 0, 14, 5542, 5544), + (5544, -1, -1, 1041, 1041, 12, 80, -1, 0, 0, 14, 5543, 7562), + (5545, -1, -1, 1044, 1044, 7, 76, -1, 0, 0, 14, 4712, 5546), + (5546, -1, -1, 1044, 1044, 9, 78, -1, 0, 0, 14, 5545, 5547), + (5547, -1, -1, 1044, 1044, 12, 80, -1, 0, 0, 14, 5546, 7650), + (5548, -1, -1, 1047, 1047, 7, 76, -1, 0, 0, 14, 4715, 5549), + (5549, -1, -1, 1047, 1047, 9, 78, -1, 0, 0, 14, 5548, 5550), + (5550, -1, -1, 1047, 1047, 12, 80, -1, 0, 0, 14, 5549, 7653), + (5551, -1, -1, 1050, 1050, 7, 76, -1, 0, 0, 14, 4718, 5552), + (5552, -1, -1, 1050, 1050, 9, 78, -1, 0, 0, 14, 5551, 5553), + (5553, -1, -1, 1050, 1050, 12, 80, -1, 0, 0, 14, 5552, 7656), + (5554, -1, -1, 119, 119, 7, 76, -1, 0, 0, 14, 4724, 5555), + (5555, -1, -1, 119, 119, 9, 78, -1, 0, 0, 14, 5554, 5556), + (5556, -1, -1, 119, 119, 12, 80, -1, 0, 0, 14, 5555, 7565), + (5557, -1, -1, 1592, 1592, 7, 76, -1, 0, 0, 14, 4729, 5558), + (5558, -1, -1, 1592, 1592, 8, 77, -1, 0, 0, 14, 5557, 5559), + (5559, -1, -1, 1592, 1592, 9, 78, -1, 0, 0, 14, 5558, 5560), + (5560, -1, -1, 1592, 1592, 10, 79, -1, 0, 0, 14, 5559, 5561), + (5561, -1, -1, 1592, 1592, 12, 80, -1, 0, 0, 14, 5560, 7568), + (5562, -1, -1, 4739, 4739, 7, 76, -1, 0, 0, 14, 4741, 5563), + (5563, -1, -1, 4739, 4739, 9, 78, -1, 0, 0, 14, 5562, 5564), + (5564, -1, -1, 4739, 4739, 12, 80, -1, 0, 0, 14, 5563, 7573), + (5565, 4742, 4742, 4742, 4742, 7, 76, 12671, 12, 600, 14, 4742, -1), + (5566, -1, -1, 1072, 1072, 7, 76, -1, 0, 0, 14, 4748, 5567), + (5567, -1, -1, 1072, 1072, 8, 77, -1, 0, 0, 14, 5566, 5568), + (5568, -1, -1, 1072, 1072, 9, 78, -1, 0, 0, 14, 5567, 5569), + (5569, -1, -1, 1072, 1072, 10, 79, -1, 0, 0, 14, 5568, 5570), + (5570, -1, -1, 1072, 1072, 12, 80, -1, 0, 0, 14, 5569, 7576), + (5571, -1, -1, 637, 637, 7, 76, -1, 0, 0, 14, 4751, 5572), + (5572, -1, -1, 637, 637, 9, 78, -1, 0, 0, 14, 5571, 5573), + (5573, -1, -1, 637, 637, 12, 80, -1, 0, 0, 14, 5572, 12435), + (5574, -1, -1, 1210, 1210, 7, 76, -1, 0, 0, 14, 4754, 5575), + (5575, -1, -1, 1210, 1210, 9, 78, -1, 0, 0, 14, 5574, 5576), + (5576, -1, -1, 1210, 1210, 12, 80, -1, 0, 0, 14, 5575, 7232), + (5577, -1, -1, 1210, 1213, 7, 76, -1, 0, 0, 14, 4757, 5578), + (5578, -1, -1, 1210, 1213, 9, 78, -1, 0, 0, 14, 5577, 5579), + (5579, -1, -1, 1210, 1213, 12, 80, -1, 0, 0, 14, 5578, 7581), + (5580, -1, -1, 602, 602, 7, 76, -1, 0, 0, 14, 4760, 5581), + (5581, -1, -1, 602, 602, 9, 78, -1, 0, 0, 14, 5580, 5582), + (5582, -1, -1, 602, 602, 12, 80, -1, 0, 0, 14, 5581, 10685), + (5586, -1, -1, 98, 98, 7, 76, -1, 0, 0, 14, 4769, 5587), + (5587, -1, -1, 98, 98, 9, 78, -1, 0, 0, 14, 5586, 5588), + (5588, -1, -1, 98, 98, 12, 80, -1, 0, 0, 14, 5587, 7584), + (5589, -1, -1, 1186, 1186, 7, 76, -1, 0, 0, 14, 4778, 5590), + (5590, -1, -1, 1186, 1186, 9, 78, -1, 0, 0, 14, 5589, 5591), + (5591, -1, -1, 1186, 1186, 12, 80, -1, 0, 0, 14, 5590, 7587), + (5592, -1, -1, 80, 80, 7, 76, -1, 0, 0, 14, 4781, 5593), + (5593, -1, -1, 80, 80, 9, 78, -1, 0, 0, 14, 5592, 5594), + (5594, -1, -1, 80, 80, 12, 80, -1, 0, 0, 14, 5593, 7590), + (5595, -1, -1, 255, 255, 7, 76, -1, 0, 0, 14, 4797, 5596), + (5596, -1, -1, 255, 255, 9, 78, -1, 0, 0, 14, 5595, 5597), + (5597, -1, -1, 255, 255, 12, 80, -1, 0, 0, 14, 5596, 7631), + (5606, 4860, 4860, 4860, 4860, 12, 80, 11688, 13, 60, 14, 4860, 7127), + (5607, 4915, 4915, 4915, 4915, 7, 76, 12673, 7, 4320, 14, 4917, 5608), + (5608, 4915, 4915, 4915, 4915, 9, 78, 12674, 7, 4320, 14, 5607, 5609), + (5609, 4915, 4915, 4915, 4915, 12, 80, 12675, 7, 4320, 14, 5608, 7246), + (5610, 4938, 4938, 4938, 4938, 12, 80, 12676, 35, 1800, 14, 4938, 5614), + (5611, -1, -1, 634, 634, 7, 76, -1, 0, 0, 14, 5034, 5612), + (5612, -1, -1, 634, 634, 9, 78, -1, 0, 0, 14, 5611, 5613), + (5613, -1, -1, 634, 634, 12, 80, -1, 0, 0, 14, 5612, 7713), + (5614, 4938, 4938, 4938, 4938, 9, 85, 16852, 35, 1800, 16, 5610, 12875), + (5617, -1, -1, 267, 267, 7, 76, -1, 0, 0, 14, 5135, 5618), + (5618, -1, -1, 267, 267, 9, 78, -1, 0, 0, 14, 5617, 5619), + (5619, -1, -1, 267, 267, 12, 80, -1, 0, 0, 14, 5618, 12860), + (5620, -1, -1, 5263, 5263, 7, 76, -1, 0, 0, 14, 5285, 5621), + (5621, -1, -1, 5263, 5263, 9, 78, -1, 0, 0, 14, 5620, 5622), + (5622, -1, -1, 5263, 5263, 12, 80, -1, 0, 0, 14, 5621, 12466), + (5623, -1, -1, 658, 658, 5, 76, -1, 0, 0, 14, 5310, 5624), + (5624, -1, -1, 658, 658, 5, 77, -1, 0, 0, 14, 5623, 5625), + (5625, -1, -1, 658, 658, 5, 78, -1, 0, 0, 14, 5624, 5626), + (5626, -1, -1, 658, 658, 5, 79, -1, 0, 0, 14, 5625, 5627), + (5627, -1, -1, 658, 658, 5, 80, -1, 0, 0, 14, 5626, 7593), + (5628, -1, -1, 98, 738, 7, 76, -1, 0, 0, 14, 5319, 5629), + (5629, -1, -1, 98, 738, 9, 78, -1, 0, 0, 14, 5628, 5630), + (5630, -1, -1, 98, 738, 12, 80, -1, 0, 0, 14, 5629, 7598), + (5699, 1116, 1116, 1116, 1116, 7, 76, 12500, 4, 2160, 14, 4982, 5700), + (5700, 1116, 1116, 1116, 1116, 9, 78, 12501, 4, 2160, 14, 5699, 5701), + (5701, 1116, 1116, 1116, 1116, 12, 80, 12502, 4, 2160, 14, 5700, 7430), + (5702, 592, 592, 592, 592, 4, 76, 12503, 2, 18, 14, 4979, 5703), + (5703, 592, 592, 592, 592, 4, 77, 12504, 2, 18, 14, 5702, 5704), + (5704, 592, 592, 592, 592, 4, 78, 12505, 2, 18, 14, 5703, 5705), + (5705, 592, 592, 592, 592, 4, 79, 12506, 2, 18, 14, 5704, 5706), + (5706, 592, 592, 592, 592, 4, 80, 12507, 2, 18, 14, 5705, 7433), + (5707, 5298, 5298, 5298, 5298, 9, 78, 12508, 32, 1800, 14, 5300, 5708), + (5708, 5298, 5298, 5298, 5298, 10, 79, 12509, 32, 1800, 14, 5707, 5709), + (5709, 5298, 5298, 5298, 5298, 12, 80, 12510, 32, 1800, 14, 5708, 7438), + (5710, 1598, -1, 1598, 1598, 7, 76, 12511, 6, 900, 14, 4974, 5711), + (5711, 1598, -1, 1598, 1598, 9, 78, 12512, 6, 900, 14, 5710, 5712), + (5712, 1598, -1, 1598, 1598, 12, 80, 12513, 6, 900, 14, 5711, 7441), + (5713, 1569, 1569, 1569, 1569, 7, 76, 12514, 5, 1800, 14, 1571, 5714), + (5714, 1569, 1569, 1569, 1569, 9, 78, 12515, 5, 1800, 14, 5713, 5715), + (5715, 1569, 1569, 1569, 1569, 12, 80, 12516, 5, 1800, 14, 5714, 7457), + (5716, 5020, 5020, 5020, 5020, 9, 77, 12517, 9, 300, 14, 5020, 7444), + (5717, 5717, 5717, 5717, 5717, 10, 76, 12519, 17, 600, 14, -1, -1), + (5729, -1, -1, 724, 724, 7, 76, -1, 0, 0, 14, 5258, 5730), + (5730, -1, -1, 724, 724, 8, 77, -1, 0, 0, 14, 5729, 5731), + (5731, -1, -1, 724, 724, 9, 78, -1, 0, 0, 14, 5730, 5732), + (5732, -1, -1, 724, 724, 10, 79, -1, 0, 0, 14, 5731, 5733), + (5733, -1, -1, 724, 724, 12, 80, -1, 0, 0, 14, 5732, 7489), + (5734, 1119, 1119, 1119, 1119, 7, 78, 12520, 8, 900, 14, 4966, 5735), + (5735, 1119, 1119, 1119, 1119, 8, 79, 12521, 8, 900, 14, 5734, 5736), + (5736, 1119, 1119, 1119, 1119, 9, 80, 12522, 8, 900, 14, 5735, 7479), + (5737, 723, 723, 723, 723, 7, 76, 12523, 6, 30, 14, 4963, 7482), + (5738, -1, -1, 729, 729, 7, 76, -1, 0, 0, 14, 4962, 5739), + (5739, -1, -1, 729, 729, 8, 77, -1, 0, 0, 14, 5738, 5740), + (5740, -1, -1, 729, 729, 9, 78, -1, 0, 0, 14, 5739, 7494), + (5741, 5015, 5015, 5015, 5015, 12, 80, 12524, 9, 900, 14, 5015, 7483), + (5742, 289, 289, 289, 289, 12, 80, 12525, 3, 300, 14, 1607, 7484), + (5743, 291, 291, 291, 291, 9, 78, 12526, 5, 900, 14, 4971, 5744), + (5744, 291, 291, 291, 291, 10, 79, 12527, 5, 900, 14, 5743, 5745), + (5745, 291, 291, 291, 291, 12, 80, 12528, 5, 900, 14, 5744, 7485), + (5759, 1425, 1425, 1425, 1425, 7, 78, 13565, 2, 2160, 14, 1429, 5760), + (5760, 1425, 1425, 1425, 1425, 8, 78, 13570, 2, 2160, 14, 5759, 5761), + (5761, 1425, 1425, 1425, 1425, 9, 79, 13575, 2, 2160, 14, 5760, 5762), + (5762, 1425, 1425, 1425, 1425, 10, 79, 13580, 2, 2160, 14, 5761, 5763), + (5763, 1425, 1425, 1425, 1425, 11, 80, 13585, 2, 2160, 14, 5762, -1), + (5764, 4854, 4854, 4854, 4854, 7, 76, 12534, 8, 600, 14, 4856, 5765), + (5765, 4854, 4854, 4854, 4854, 9, 78, 12535, 8, 600, 14, 5764, 5766), + (5766, 4854, 4854, 4854, 4854, 12, 80, 12536, 8, 600, 14, 5765, 7178), + (5767, 4857, 4857, 4857, 4857, 7, 76, 12537, 7, 600, 14, 4859, 5768), + (5768, 4857, 4857, 4857, 4857, 9, 78, 12538, 7, 600, 14, 5767, 5769), + (5769, 4857, 4857, 4857, 4857, 12, 80, 12539, 7, 600, 14, 5768, 17030), + (5770, 1348, 1348, 1348, 1348, 9, 78, 12540, 0, 3600, 14, 1350, 5771), + (5771, 1348, 1348, 1348, 1348, 10, 79, 12541, 0, 3600, 14, 5770, 5772), + (5772, 1348, 1348, 1348, 1348, 12, 80, 12542, 0, 3600, 14, 5771, 7184), + (5776, -1, -1, 5776, 5776, 7, 76, -1, 0, 0, 14, -1, 5777), + (5777, -1, -1, 5776, 5776, 9, 78, -1, 0, 0, 14, 5776, 5778), + (5778, -1, -1, 5776, 5776, 12, 80, -1, 0, 0, 14, 5777, 7196), + (5779, 1178, 1178, 1178, 1178, 7, 76, 12546, 4, 900, 14, 1180, 5780), + (5780, 1178, 1178, 1178, 1178, 8, 77, 12547, 4, 900, 14, 5779, 5781), + (5781, 1178, 1178, 1178, 1178, 9, 78, 12548, 4, 900, 14, 5780, 7187), + (5789, 1383, 1383, 1383, 1383, 12, 80, 12549, 6, 300, 14, 5084, 7299), + (5790, 1195, 1195, 1195, 1195, 9, 80, 12550, 13, 2160, 14, 5079, 7300), + (5791, 131, 131, 131, 131, 8, 77, 12551, 4, 900, 14, 5072, 5792), + (5792, 131, 131, 131, 131, 9, 78, 12552, 4, 900, 14, 5791, 5793), + (5793, 131, 131, 131, 131, 10, 79, 12553, 4, 900, 14, 5792, 7301), + (5794, 1192, 1192, 1192, 1192, 8, 77, 12554, 12, 1320, 14, 5078, 5795), + (5795, 1192, 1192, 1192, 1192, 9, 78, 12555, 12, 1320, 14, 5794, 5796), + (5796, 1192, 1192, 1192, 1192, 10, 79, 12556, 12, 1320, 14, 5795, 7304), + (5797, -1, -1, 5083, 5083, 7, 76, -1, 0, 0, 14, 5120, 5798), + (5798, -1, -1, 5083, 5083, 9, 78, -1, 0, 0, 14, 5797, 5799), + (5799, -1, -1, 5083, 5083, 12, 80, -1, 0, 0, 14, 5798, -1), + (5800, 746, 746, 746, 746, 9, 78, 12557, 10, 2160, 14, 1493, 5801), + (5801, 746, 746, 746, 746, 10, 79, 12558, 10, 2160, 14, 5800, 5802), + (5802, 746, 746, 746, 746, 12, 80, 12559, 10, 2160, 14, 5801, 7307), + (5803, 1459, 1459, 1459, 1459, 7, 76, 12560, 11, 1800, 14, 5082, 5804), + (5804, 1459, 1459, 1459, 1459, 9, 78, 12561, 11, 1800, 14, 5803, 5805), + (5805, 1459, 1459, 1459, 1459, 12, 80, 12562, 11, 1800, 14, 5804, 7310), + (5806, -1, -1, 255, 255, 7, 59, -1, 0, 0, 16, -1, 5807), + (5807, -1, -1, 255, 255, 9, 59, -1, 0, 0, 16, 5806, 5808), + (5808, -1, -1, 255, 255, 12, 59, -1, 0, 0, 16, 5807, 10623), + (5809, 5833, 5833, 5833, 5833, 9, 85, 20184, 72, 900, 16, -1, -1), + (5819, 1498, 1498, 1498, 1498, 7, 76, 12563, 12, 1320, 14, 5060, 5820), + (5820, 1498, 1498, 1498, 1498, 9, 78, 12564, 12, 1320, 14, 5819, 5821), + (5821, 1498, 1498, 1498, 1498, 12, 80, 12565, 12, 1320, 14, 5820, 7408), + (5822, 757, -1, 757, 757, 7, 76, 12566, 6, 1800, 14, 5053, 5823), + (5823, 757, -1, 757, 757, 9, 78, 12567, 6, 1800, 14, 5822, 5824), + (5824, 757, -1, 757, 757, 12, 80, 12568, 6, 1800, 14, 5823, 7411), + (5825, -1, -1, 567, 567, 7, 76, -1, 0, 0, 14, 5061, -1), + (5826, 1495, 1495, 1495, 1495, 7, 76, 12569, 30, 900, 14, 5313, 5827), + (5827, 1495, 1495, 1495, 1495, 9, 78, 12570, 30, 900, 14, 5826, 5828), + (5828, 1495, 1495, 1495, 1495, 12, 80, 12571, 30, 900, 14, 5827, 7414), + (5829, 548, 548, 548, 548, 8, 77, 12572, 5, 900, 14, 5056, 5830), + (5830, 548, 548, 548, 548, 9, 78, 12573, 5, 900, 14, 5829, 5831), + (5831, 548, 548, 548, 548, 10, 79, 12574, 5, 900, 14, 5830, 7417), + (5832, 5105, 5105, 5105, 5105, 12, 80, 12575, 11, 600, 14, 5105, 7420), + (5849, 54009, 54009, 54009, 54009, 7, 73, 12576, 22, 12, 14, -1, 12923), + (5850, -1, -1, 781, 781, 8, 77, -1, 0, 0, 14, 781, 7284), + (5854, 773, -1, 773, 773, 7, 76, 12580, 5, 1800, 14, 775, 5855), + (5855, 773, -1, 773, 773, 9, 78, 12581, 5, 1800, 14, 5854, 5856), + (5856, 773, -1, 773, 773, 12, 80, 12582, 5, 1800, 14, 5855, 7276), + (5857, 1242, 1242, 1242, 1242, 7, 76, 12577, 9, 1320, 14, 1244, 5858), + (5858, 1242, 1242, 1242, 1242, 9, 78, 12578, 9, 1320, 14, 5857, 5859), + (5859, 1242, 1242, 1242, 1242, 12, 80, 12579, 9, 1320, 14, 5858, 7285), + (5860, -1, -1, 649, 649, 7, 76, -1, 0, 0, 14, 651, 5861), + (5861, -1, -1, 649, 649, 9, 78, -1, 0, 0, 14, 5860, 5862), + (5862, -1, -1, 649, 649, 12, 80, -1, 0, 0, 14, 5861, -1), + (5868, 1239, 1239, 1239, 1239, 12, 80, 13224, 6, 600, 14, 1239, 7275), + (5869, 4890, -1, 4890, 4890, 9, 77, 12587, 3, 8640, 14, 4890, 5871), + (5870, 54010, 54010, 54010, 54010, 7, 73, 12828, 22, 6, 14, -1, -1), + (5871, 4890, -1, 4890, 4890, 9, 79, 16440, 3, 8640, 15, 5869, 5872), + (5872, 4890, -1, 4890, 4890, 9, 81, 21745, 3, 8640, 16, 5871, 14280), + (5879, 167, 167, 167, 167, 10, 79, 12588, 14, 900, 14, 167, 7249), + (5880, -1, -1, 1504, 1504, 5, 76, -1, 0, 0, 14, 1506, 5881), + (5881, -1, -1, 1504, 1504, 5, 78, -1, 0, 0, 14, 5880, 5882), + (5882, -1, -1, 1504, 1504, 5, 80, -1, 0, 0, 14, 5881, 7260), + (5883, 520, 520, 520, 520, 12, 76, 12589, 6, 540, 14, 1509, 5884), + (5884, 520, 520, 520, 520, 12, 78, 12590, 6, 540, 14, 5883, 5885), + (5885, 520, 520, 520, 520, 12, 80, 12591, 6, 540, 14, 5884, 7250), + (5886, -1, -1, 1577, 1577, 7, 76, -1, 0, 0, 14, 1579, 5887), + (5887, -1, -1, 1577, 1577, 9, 78, -1, 0, 0, 14, 5886, 5888), + (5888, -1, -1, 1577, 1577, 12, 80, -1, 0, 0, 14, 5887, 7263), + (5889, -1, -1, 795, 795, 7, 76, -1, 0, 0, 14, 4899, 5890), + (5890, -1, -1, 795, 795, 9, 78, -1, 0, 0, 14, 5889, 5891), + (5891, -1, -1, 795, 795, 12, 80, -1, 0, 0, 14, 5890, 7267), + (5892, 4903, 4903, 4903, 4903, 9, 76, 12592, 9, 1320, 14, 4903, 7253), + (5893, 4906, 4906, 4906, 4906, 9, 76, 12593, 9, 1320, 14, 4906, 7254), + (5894, 4909, 4909, 4909, 4909, 9, 76, 12594, 16, 1320, 14, 4909, 7255), + (5895, 4912, 4912, 4912, 4912, 9, 76, 12595, 16, 1320, 14, 4912, 7256), + (5909, -1, -1, 815, 815, 7, 76, -1, 0, 0, 14, 5145, 5910), + (5910, -1, -1, 815, 815, 8, 77, -1, 0, 0, 14, 5909, 5911), + (5911, -1, -1, 815, 815, 9, 78, -1, 0, 0, 14, 5910, 5912), + (5912, -1, -1, 815, 815, 10, 79, -1, 0, 0, 14, 5911, 5913), + (5913, -1, -1, 815, 815, 12, 80, -1, 0, 0, 14, 5912, 7634), + (5914, 1355, 1355, 1355, 1355, 6, 76, 12596, 3, 60, 14, 5242, 5915), + (5915, 1355, 1355, 1355, 1355, 6, 78, 12597, 3, 60, 14, 5914, 5916), + (5916, 1355, 1355, 1355, 1355, 6, 80, 12598, 3, 60, 14, 5915, 7172), + (5917, -1, -1, 820, 820, 5, 76, -1, 0, 0, 14, 4815, 5918), + (5918, -1, -1, 820, 820, 5, 78, -1, 0, 0, 14, 5917, 5919), + (5919, -1, -1, 820, 820, 5, 80, -1, 0, 0, 14, 5918, 7163), + (5922, -1, -1, 807, 807, 5, 76, -1, 0, 0, 14, 1270, 5923), + (5923, -1, -1, 807, 807, 5, 78, -1, 0, 0, 14, 5922, 5924), + (5924, -1, -1, 807, 807, 5, 80, -1, 0, 0, 14, 5923, 7628), + (5939, -1, -1, 5264, 5264, 7, 76, -1, 0, 0, 14, 5268, 5940), + (5940, -1, -1, 5264, 5264, 8, 77, -1, 0, 0, 14, 5939, 5941), + (5941, -1, -1, 5264, 5264, 9, 78, -1, 0, 0, 14, 5940, 5942), + (5942, -1, -1, 5264, 5264, 10, 79, -1, 0, 0, 14, 5941, 5943), + (5943, -1, -1, 5264, 5264, 12, 80, -1, 0, 0, 14, 5942, 7204), + (5944, -1, -1, 4924, 4924, 9, 78, -1, 0, 0, 14, 4926, 5945), + (5945, -1, -1, 4924, 4924, 10, 79, -1, 0, 0, 14, 5944, 5946), + (5946, -1, -1, 4924, 4924, 12, 80, -1, 0, 0, 14, 5945, -1), + (5947, 1274, 1274, 1274, 1274, 9, 78, 12599, 9, 540, 14, 4866, 5948), + (5948, 1274, 1274, 1274, 1274, 10, 79, 12600, 9, 540, 14, 5947, 5949), + (5949, 1274, 1274, 1274, 1274, 12, 80, 12601, 9, 540, 14, 5948, 7199), + (5950, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 1513, 5951), + (5951, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 5950, 5952), + (5952, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 5951, -1), + (5953, 184, 184, 184, 184, 10, 79, 12602, 5, 4320, 14, 184, 7203), + (5954, -1, -1, 4861, 4861, 7, 76, -1, 0, 0, 14, 4863, 5955), + (5955, -1, -1, 4861, 4861, 9, 78, -1, 0, 0, 14, 5954, 5956), + (5956, -1, -1, 4861, 4861, 12, 80, -1, 0, 0, 14, 5955, 7215), + (5969, 534, 534, 534, 534, 7, 76, 12603, 4, 2160, 14, 5043, 5970), + (5970, 534, 534, 534, 534, 9, 78, 12604, 4, 2160, 14, 5969, 5971), + (5971, 534, 534, 534, 534, 12, 80, 12605, 4, 2160, 14, 5970, 7329), + (5972, -1, -1, 593, 593, 7, 76, -1, 0, 0, 14, 595, -1), + (5973, -1, -1, 596, 596, 7, 76, -1, 0, 0, 14, 598, -1), + (5975, 5095, 5095, 5095, 5095, 7, 76, 12606, 10, 900, 14, 5097, 5976), + (5976, 5095, 5095, 5095, 5095, 9, 78, 12607, 10, 900, 14, 5975, 5977), + (5977, 5095, 5095, 5095, 5095, 12, 80, 12608, 10, 900, 14, 5976, 7332), + (5984, 5984, 5984, 5984, 5984, 12, 80, 12609, 2, 30, 14, -1, 7335), + (5999, 645, -1, 645, 645, 10, 79, 12610, 4, 5, 14, 645, 10739), + (6000, 545, 545, 545, 545, 7, 76, 12611, 3, 900, 14, 4999, 6001), + (6001, 545, 545, 545, 545, 9, 78, 12612, 3, 900, 14, 6000, 6002), + (6002, 545, 545, 545, 545, 12, 80, 12613, 3, 900, 14, 6001, 7344), + (6003, -1, -1, 1616, 1616, 7, 76, -1, 0, 0, 14, 4996, 6004), + (6004, -1, -1, 1616, 1616, 8, 77, -1, 0, 0, 14, 6003, 6005), + (6005, -1, -1, 1616, 1616, 9, 78, -1, 0, 0, 14, 6004, 6006), + (6006, -1, -1, 1616, 1616, 10, 79, -1, 0, 0, 14, 6005, 6007), + (6007, -1, -1, 1616, 1616, 12, 80, -1, 0, 0, 14, 6006, 7637), + (6008, 1345, 1345, 1345, 1345, 8, 77, 12614, 6, 900, 14, 5005, 6009), + (6009, 1345, 1345, 1345, 1345, 9, 78, 12615, 6, 900, 14, 6008, 6010), + (6010, 1345, 1345, 1345, 1345, 10, 79, 12616, 6, 900, 14, 6009, 7347), + (6011, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 4985, 6012), + (6012, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 6011, 6013), + (6013, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 6012, 7353), + (6014, -1, -1, 5248, 5248, 7, 76, -1, 0, 0, 14, 5250, 6015), + (6015, -1, -1, 5248, 5248, 9, 78, -1, 0, 0, 14, 6014, 6016), + (6016, -1, -1, 5248, 5248, 12, 80, -1, 0, 0, 14, 6015, 7356), + (6017, -1, -1, 644, 644, 7, 73, -1, 0, 0, 14, 4988, 6018), + (6018, -1, -1, 644, 644, 9, 75, -1, 0, 0, 14, 6017, 6019), + (6019, -1, -1, 644, 644, 12, 77, -1, 0, 0, 14, 6018, 7359), + (6020, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, -1, 6021), + (6021, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, 6020, 6022), + (6022, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, 6021, 6045), + (6023, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 7567, 6024), + (6024, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 6023, 6025), + (6025, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 6024, 12548), + (6026, -1, -1, 1004, 1004, 7, 81, -1, 0, 0, 16, -1, 6027), + (6027, -1, -1, 1004, 1004, 9, 81, -1, 0, 0, 16, 6026, 6028), + (6028, -1, -1, 1004, 1004, 12, 81, -1, 0, 0, 16, 6027, -1), + (6029, -1, -1, 1304, 1304, 7, 76, -1, 0, 0, 14, 1306, 6030), + (6030, -1, -1, 1304, 1304, 9, 78, -1, 0, 0, 14, 6029, 6031), + (6031, -1, -1, 1304, 1304, 12, 80, -1, 0, 0, 14, 6030, 7148), + (6032, -1, -1, 1604, 1604, 7, 69, -1, 0, 0, 14, 5294, 6033), + (6033, -1, -1, 1604, 1604, 9, 71, -1, 0, 0, 14, 6032, 6034), + (6034, -1, -1, 1604, 1604, 12, 73, -1, 0, 0, 14, 6033, 7131), + (6035, -1, -1, 846, 846, 7, 76, -1, 0, 0, 14, 4950, 6036), + (6036, -1, -1, 846, 846, 9, 78, -1, 0, 0, 14, 6035, 6037), + (6037, -1, -1, 846, 846, 12, 80, -1, 0, 0, 14, 6036, 7151), + (6038, 5022, 5022, 5022, 5022, 7, 76, 23988, 5, 600, 14, 5024, 6039), + (6039, 5022, 5022, 5022, 5022, 9, 78, 23989, 5, 600, 14, 6038, 6040), + (6040, 5022, 5022, 5022, 5022, 12, 80, 23990, 5, 600, 14, 6039, 15628), + (6041, 5028, -1, 5028, 5028, 9, 78, 12621, 4, 900, 14, 5028, -1), + (6042, -1, -1, 1543, 1543, 7, 76, -1, 0, 0, 14, 4953, 6043), + (6043, -1, -1, 1543, 1543, 9, 78, -1, 0, 0, 14, 6042, 6044), + (6044, -1, -1, 1543, 1543, 12, 80, -1, 0, 0, 14, 6043, 7134), + (6045, -1, -1, 6020, 6020, 2, 66, -1, 0, 0, 14, 6022, 6046), + (6046, -1, -1, 6020, 6020, 2, 68, -1, 0, 0, 14, 6045, 6047), + (6047, -1, -1, 6020, 6020, 2, 70, -1, 0, 0, 14, 6046, 6048), + (6048, -1, -1, 6020, 6020, 2, 71, -1, 0, 0, 14, 6047, 6049), + (6049, -1, -1, 6020, 6020, 2, 73, -1, 0, 0, 14, 6048, 6050), + (6050, -1, -1, 6020, 6020, 2, 75, -1, 0, 0, 14, 6049, 6057), + (6051, -1, -1, 6051, 6051, 3, 76, -1, 0, 0, 14, -1, 6052), + (6052, -1, -1, 6051, 6051, 3, 78, -1, 0, 0, 14, 6051, 6053), + (6053, -1, -1, 6051, 6051, 3, 80, -1, 0, 0, 14, 6052, 7601), + (6054, 4931, 4931, 4931, 4931, 7, 76, 12756, 4, 600, 14, 4933, 6055), + (6055, 4931, 4931, 4931, 4931, 7, 78, 12757, 4, 600, 14, 6054, 6056), + (6056, 4931, 4931, 4931, 4931, 7, 80, 12758, 4, 600, 14, 6055, 7291), + (6057, -1, -1, 6020, 6020, 2, 76, -1, 0, 0, 14, 6050, 6058), + (6058, -1, -1, 6020, 6020, 2, 78, -1, 0, 0, 14, 6057, 6059), + (6059, -1, -1, 6020, 6020, 2, 80, -1, 0, 0, 14, 6058, 7169), + (6060, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, -1, 6061), + (6061, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, 6060, 6470), + (6063, -1, -1, 589, 589, 7, 76, -1, 0, 0, 14, 5272, 6064), + (6064, -1, -1, 589, 589, 9, 78, -1, 0, 0, 14, 6063, 6065), + (6065, -1, -1, 589, 589, 12, 80, -1, 0, 0, 14, 6064, 7390), + (6066, -1, -1, 1313, 1313, 7, 76, -1, 0, 0, 14, 5031, 6067), + (6067, -1, -1, 1313, 1313, 7, 76, -1, 0, 0, 14, 6066, 6068), + (6068, -1, -1, 1313, 1313, 8, 77, -1, 0, 0, 14, 6067, 6069), + (6069, -1, -1, 1313, 1313, 9, 78, -1, 0, 0, 14, 6068, 6070), + (6070, -1, -1, 1313, 1313, 10, 79, -1, 0, 0, 14, 6069, 6071), + (6071, -1, -1, 1313, 1313, 12, 80, -1, 0, 0, 14, 6070, 7393), + (6072, -1, -1, 210, 210, 8, 77, -1, 0, 0, 14, 1318, 6073), + (6073, -1, -1, 210, 210, 9, 78, -1, 0, 0, 14, 6072, 6074), + (6074, -1, -1, 210, 210, 10, 79, -1, 0, 0, 14, 6073, 7399), + (6075, -1, -1, 895, 895, 7, 76, -1, 0, 0, 14, 899, 6076), + (6076, -1, -1, 895, 895, 8, 77, -1, 0, 0, 14, 6075, 6077), + (6077, -1, -1, 895, 895, 9, 78, -1, 0, 0, 14, 6076, 6078), + (6078, -1, -1, 895, 895, 10, 79, -1, 0, 0, 14, 6077, 6079), + (6079, -1, -1, 895, 895, 12, 80, -1, 0, 0, 14, 6078, 7402), + (6080, -1, -1, 683, 683, 5, 75, -1, 0, 0, 14, 5305, 6081), + (6081, -1, -1, 683, 683, 5, 75, -1, 0, 0, 14, 6080, 7604), + (6082, -1, -1, 6084, 6084, 5, 85, 0, 0, 0, 17, -1, 6083), + (6083, -1, -1, 6084, 6084, 5, 87, 0, 0, 0, 17, 6082, 6084), + (6084, -1, -1, 6084, 6084, 5, 89, 0, 0, 0, 17, 6083, 13366), + (6085, -1, -1, 6761, 6761, 10, 81, -1, 0, 0, 16, 6763, 6086), + (6086, -1, -1, 6761, 6761, 11, 83, -1, 0, 0, 16, 6085, 6087), + (6087, -1, -1, 6761, 6761, 12, 85, -1, 0, 0, 16, 6086, 10763), + (6088, -1, -1, 6088, 6088, 9, 85, 0, 0, 0, 17, -1, 6089), + (6089, -1, -1, 6088, 6088, 12, 87, 0, 0, 0, 17, 6088, 6090), + (6090, -1, -1, 6088, 6088, 15, 89, 0, 0, 0, 17, 6089, -1), + (6092, 5251, 5251, 5251, 5251, 7, 76, 12635, 13, 900, 14, 5253, 6093), + (6093, 5251, 5251, 5251, 5251, 9, 78, 12636, 13, 900, 14, 6092, 6094), + (6094, 5251, 5251, 5251, 5251, 12, 80, 12637, 13, 900, 14, 6093, 7472), + (6095, 513, 513, 513, 513, 7, 76, 12638, 4, 120, 14, 515, 6096), + (6096, 513, 513, 513, 513, 9, 78, 12639, 4, 120, 14, 6095, 6097), + (6097, 513, 513, 513, 513, 12, 80, 12640, 4, 120, 14, 6096, 7475), + (6098, 1327, 1327, 1327, 1327, 7, 76, 12641, 10, 900, 14, 5316, 6099), + (6099, 1327, 1327, 1327, 1327, 9, 78, 12642, 10, 900, 14, 6098, 6100), + (6100, 1327, 1327, 1327, 1327, 12, 80, 12643, 10, 900, 14, 6099, 7460), + (6101, 153, 153, 153, 153, 12, 80, 12644, 3, 2160, 14, 5068, 7468), + (6102, 146, 146, 146, 146, 8, 77, 12645, 2, 180, 14, 5069, 7466), + (6103, 528, 528, 528, 528, 7, 76, 12646, 5, 720, 14, 901, 6104), + (6104, 528, 528, 528, 528, 9, 78, 12647, 5, 720, 14, 6103, 6105), + (6105, 528, 528, 528, 528, 12, 80, 12648, 5, 720, 14, 6104, 7469), + (6106, 6106, 6106, 6106, 6106, 4, 67, 21965, 13, 4320, 16, -1, 6107), + (6107, 6106, 6106, 6106, 6106, 5, 68, 21966, 13, 4320, 16, 6106, 6108), + (6108, 6106, 6106, 6106, 6106, 6, 69, 21967, 13, 4320, 16, 6107, 6109), + (6109, 6106, 6106, 6106, 6106, 7, 77, 21968, 13, 4320, 16, 6108, 6110), + (6110, 6106, 6106, 6106, 6106, 8, 78, 21969, 13, 4320, 16, 6109, 6111), + (6111, 6106, 6106, 6106, 6106, 9, 79, 21970, 13, 4320, 16, 6110, -1), + (6112, -1, -1, 6112, 6112, 5, 85, -1, 0, 0, 17, -1, 12966), + (6113, -1, -1, 6113, 6113, 9, 85, 0, 0, 0, 17, -1, 6114), + (6114, -1, -1, 6113, 6113, 12, 87, 0, 0, 0, 17, 6113, 6115), + (6115, -1, -1, 6113, 6113, 15, 89, 0, 0, 0, 17, 6114, -1), + (6119, -1, -1, 6119, 6119, 6, 76, -1, 0, 0, 14, -1, 6120), + (6120, -1, -1, 6119, 6119, 6, 77, -1, 0, 0, 14, 6119, 6121), + (6121, -1, -1, 6119, 6119, 6, 78, -1, 0, 0, 14, 6120, 6122), + (6122, -1, -1, 6119, 6119, 6, 79, -1, 0, 0, 14, 6121, 6123), + (6123, -1, -1, 6119, 6119, 6, 80, -1, 0, 0, 14, 6122, 7526), + (6124, -1, -1, 5263, 5263, 3, 71, -1, 0, 0, 12, -1, 6125), + (6125, -1, -1, 5263, 5263, 6, 73, -1, 0, 0, 12, 6124, 6126), + (6126, -1, -1, 5263, 5263, 9, 75, -1, 0, 0, 12, 6125, 6127), + (6127, -1, -1, 5263, 5263, 10, 76, -1, 0, 0, 14, 6126, 6128), + (6128, -1, -1, 5263, 5263, 11, 78, -1, 0, 0, 14, 6127, 6129), + (6129, -1, -1, 5263, 5263, 12, 80, -1, 0, 0, 14, 6128, 12463), + (6130, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 588, 6131), + (6131, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 6130, 6132), + (6132, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 6131, -1), + (6133, 1351, 1351, 1351, 1351, 8, 77, 12649, 5, 30, 14, 1351, 7109), + (6134, 4849, 4849, 4849, 4849, 7, 76, 12650, 7, 1800, 14, 4849, 7110), + (6135, 54006, 54006, 54006, 54006, 7, 76, 12651, 18, 180, 14, -1, 7111), + (6136, -1, -1, 6136, 6136, 7, 76, -1, 0, 0, 10, -1, 6137), + (6149, 921, 921, 921, 921, 9, 79, 12652, 8, 60, 14, 5280, 7245), + (6150, 922, 922, 922, 922, 9, 78, 12653, 8, 60, 14, 5281, 7236), + (6151, 923, 923, 923, 923, 9, 77, 12654, 8, 60, 14, 5282, 7235), + (6152, 1334, 1334, 1334, 1334, 9, 78, 12655, 11, 4320, 14, 1336, 6153), + (6153, 1334, 1334, 1334, 1334, 10, 79, 12656, 11, 4320, 14, 6152, 6154), + (6154, 1334, 1334, 1334, 1334, 12, 80, 12657, 11, 4320, 14, 6153, 7239), + (6155, 4944, -1, 4944, 4944, 7, 76, 12658, 0, 1, 14, 4946, 6156), + (6156, 4944, -1, 4944, 4944, 9, 78, 12659, 0, 1, 14, 6155, 6157), + (6157, 4944, -1, 4944, 4944, 12, 80, 12660, 0, 1, 14, 6156, 7229), + (6158, 1337, 1337, 1337, 1337, 8, 77, 12661, 13, 4320, 14, 1339, 6159), + (6159, 1337, 1337, 1337, 1337, 9, 78, 12662, 13, 4320, 14, 6158, 6160), + (6160, 1337, 1337, 1337, 1337, 10, 79, 12663, 13, 4320, 14, 6159, 14338), + (6161, 1478, -1, 1478, 1478, 9, 78, 12664, 0, 1, 14, 1480, 6162), + (6162, 1478, -1, 1478, 1478, 10, 79, 12665, 0, 1, 14, 6161, 6163), + (6163, 1478, -1, 1478, 1478, 12, 80, 12666, 0, 1, 14, 6162, 7242), + (6200, 6533, 6533, 6533, 6533, 10, 79, 12768, 15, 600, 14, -1, 7428), + (6201, 6534, 6534, 6534, 6534, 9, 78, 12769, 16, 900, 14, -1, 7429), + (6202, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, -1, 6203), + (6203, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, 6202, 6204), + (6204, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, 6203, -1), + (6205, 6536, 6536, 6536, 6536, 7, 76, 12712, 39, 5, 14, -1, -1), + (6206, 6537, 6537, 6537, 6537, 7, 76, 12770, 30, 900, 14, -1, 6207), + (6207, 6537, 6537, 6537, 6537, 8, 77, 12771, 30, 900, 14, 6206, 6208), + (6208, 6537, 6537, 6537, 6537, 9, 78, 12772, 30, 900, 14, 6207, 7606), + (6209, -1, -1, 6538, 6538, 7, 76, -1, 0, 0, 14, -1, 6210), + (6210, -1, -1, 6538, 6538, 9, 78, -1, 0, 0, 14, 6209, 6211), + (6211, -1, -1, 6538, 6538, 12, 80, -1, 0, 0, 14, 6210, 7478), + (6212, 6539, 6539, 6539, 6539, 6, 71, 12776, 18, 1800, 14, -1, 6213), + (6213, 6539, 6539, 6539, 6539, 6, 74, 12777, 18, 1800, 14, 6212, 6214), + (6214, 6539, 6539, 6539, 6539, 6, 77, 12778, 18, 1800, 14, 6213, 7609), + (6215, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6216), + (6216, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6215, 6217), + (6217, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6216, 6300), + (6218, 6218, 6218, 6218, 6218, 7, 76, 12782, 0, 1, 14, -1, 7488), + (6219, 6542, 6542, 6542, 6542, 7, 76, 12783, 18, 1800, 14, -1, 6220), + (6220, 6542, 6542, 6542, 6542, 9, 78, 12784, 18, 1800, 14, 6219, 6221), + (6221, 6542, 6542, 6542, 6542, 12, 80, 12785, 18, 1800, 14, 6220, -1), + (6222, 6543, 6543, 6543, 6543, 9, 72, 13143, 18, 25, 14, -1, -1), + (6223, -1, -1, 962, 962, 5, 76, -1, 0, 0, 14, 966, 6224), + (6224, -1, -1, 962, 962, 5, 77, -1, 0, 0, 14, 6223, 6225), + (6225, -1, -1, 962, 962, 5, 78, -1, 0, 0, 14, 6224, 6226), + (6226, -1, -1, 962, 962, 5, 79, -1, 0, 0, 14, 6225, 6227), + (6227, -1, -1, 962, 962, 5, 80, -1, 0, 0, 14, 6226, 10361), + (6228, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, -1, 6229), + (6229, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6228, 6230), + (6230, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6229, 6231), + (6231, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6230, -1), + (6232, 6232, 6232, 6232, 6232, 12, 80, 14413, 18, 900, 14, -1, 7421), + (6233, -1, -1, 477, 477, 2, 70, -1, 0, 0, 14, 479, 6234), + (6234, -1, -1, 477, 477, 2, 71, -1, 0, 0, 14, 6233, 6235), + (6235, -1, -1, 477, 477, 2, 72, -1, 0, 0, 14, 6234, 16094), + (6236, -1, -1, 6548, 6548, 6, 73, -1, 0, 0, 14, -1, 6237), + (6237, -1, -1, 6548, 6548, 6, 75, -1, 0, 0, 14, 6236, 6238), + (6238, -1, -1, 6548, 6548, 8, 77, -1, 0, 0, 14, 6237, 12929), + (6240, -1, -1, 767, 767, 3, 65, -1, 0, 0, 14, -1, 6241), + (6241, -1, -1, 767, 767, 6, 65, -1, 0, 0, 14, 6240, 6242), + (6242, -1, -1, 767, 767, 9, 65, -1, 0, 0, 14, 6241, 6243), + (6243, -1, -1, 767, 767, 3, 67, -1, 0, 0, 14, 6242, 6244), + (6244, -1, -1, 767, 767, 6, 68, -1, 0, 0, 14, 6243, 6245), + (6245, -1, -1, 767, 767, 9, 69, -1, 0, 0, 14, 6244, 12426), + (6249, 6552, 6552, 6552, 6552, 5, 70, -1, 0, 0, 14, -1, 6250), + (6250, 6552, 6552, 6552, 6552, 6, 72, -1, 0, 0, 14, 6249, 6251), + (6251, 6552, 6552, 6552, 6552, 6, 74, -1, 0, 0, 14, 6250, 6252), + (6252, 6552, 6552, 6552, 6552, 7, 76, -1, 0, 0, 14, 6251, 6253), + (6253, 6552, 6552, 6552, 6552, 9, 78, -1, 0, 0, 14, 6252, 7279), + (6254, 616, 616, 616, 616, 6, 73, 12765, 7, 900, 14, 1250, 6255), + (6255, 616, 616, 616, 616, 7, 76, 12766, 7, 900, 14, 6254, 6256), + (6256, 616, 616, 616, 616, 10, 79, 12767, 7, 900, 14, 6255, 7257), + (6257, -1, -1, 86, 86, 2, 55, -1, 0, 0, 14, -1, 6258), + (6258, -1, -1, 86, 86, 4, 55, -1, 0, 0, 14, 6257, 6259), + (6259, -1, -1, 86, 86, 6, 55, -1, 0, 0, 14, 6258, 8223), + (6260, -1, -1, 495, 495, 6, 73, -1, 0, 0, 14, 497, 6261), + (6261, -1, -1, 495, 495, 7, 76, -1, 0, 0, 14, 6260, 6262), + (6262, -1, -1, 495, 495, 10, 79, -1, 0, 0, 14, 6261, 10666), + (6266, -1, -1, 6557, 6557, 6, 73, -1, 0, 0, 14, -1, 6267), + (6267, -1, -1, 6557, 6557, 7, 76, -1, 0, 0, 14, 6266, 6268), + (6268, -1, -1, 6557, 6557, 10, 79, -1, 0, 0, 14, 6267, -1), + (6269, -1, -1, 6558, 6558, 6, 73, -1, 0, 0, 14, -1, 6270), + (6270, -1, -1, 6558, 6558, 7, 76, -1, 0, 0, 14, 6269, 6271), + (6271, -1, -1, 6558, 6558, 10, 79, -1, 0, 0, 14, 6270, -1), + (6272, -1, -1, 6559, 6559, 6, 73, -1, 0, 0, 14, -1, 6273), + (6273, -1, -1, 6559, 6559, 7, 75, -1, 0, 0, 14, 6272, 6274), + (6274, -1, -1, 6559, 6559, 10, 77, -1, 0, 0, 14, 6273, 7137), + (6275, -1, -1, 6560, 6560, 6, 73, -1, 0, 0, 14, -1, 6276), + (6276, -1, -1, 6560, 6560, 7, 76, -1, 0, 0, 14, 6275, 6277), + (6277, -1, -1, 6560, 6560, 10, 79, -1, 0, 0, 14, 6276, 16266), + (6278, 6561, 6561, 6561, 6561, 7, 76, 12795, 32, 30, 14, -1, 6279), + (6279, 6561, 6561, 6561, 6561, 7, 76, 12796, 32, 30, 14, 6278, 6280), + (6280, 6561, 6561, 6561, 6561, 7, 76, 12797, 32, 30, 14, 6279, 7422), + (6281, 6563, 6563, 6563, 6563, 9, 78, 13144, 36, 8, 14, -1, 12995), + (6282, 6562, 6562, 6562, 6562, 6, 72, 12798, 39, 1, 14, -1, -1), + (6283, -1, -1, 6564, 6564, 6, 73, -1, 0, 0, 14, -1, 6284), + (6284, -1, -1, 6564, 6564, 7, 76, -1, 0, 0, 14, 6283, 6285), + (6285, -1, -1, 6564, 6564, 10, 79, -1, 0, 0, 14, 6284, 7112), + (6286, 6565, 6565, 6565, 6565, 7, 76, 12802, 17, 45, 14, -1, 7115), + (6287, -1, -1, 6566, 6566, 6, 73, -1, 0, 0, 14, -1, 6288), + (6288, -1, -1, 6566, 6566, 7, 76, -1, 0, 0, 14, 6287, 6289), + (6289, -1, -1, 6566, 6566, 10, 79, -1, 0, 0, 14, 6288, -1), + (6290, 6290, 6290, 6290, 6290, 6, 71, 12803, 0, 1, 14, -1, 6291), + (6291, 6290, 6290, 6290, 6290, 6, 73, 12804, 0, 1, 14, 6290, 6292), + (6292, 6290, 6290, 6290, 6290, 6, 75, 12805, 0, 1, 14, 6291, 6293), + (6293, 6290, 6290, 6290, 6290, 7, 76, 12806, 0, 1, 14, 6292, 6294), + (6294, 6290, 6290, 6290, 6290, 9, 78, 12807, 0, 1, 14, 6293, 6295), + (6295, 6290, 6290, 6290, 6290, 12, 80, 12808, 0, 1, 14, 6294, 7223), + (6296, 619, 619, 619, 619, 6, 73, 12759, 6, 900, 14, 722, 6297), + (6297, 619, 619, 619, 619, 6, 73, 12760, 6, 900, 14, 6296, 6298), + (6298, 619, 619, 619, 619, 6, 73, 12761, 6, 900, 14, 6297, 7226), + (6299, 6299, 6299, 6299, 6299, 9, 65, 12786, 18, 12, 14, -1, -1), + (6300, -1, -1, 6540, 6540, 8, 74, -1, 0, 0, 14, 6217, 6301), + (6301, -1, -1, 6540, 6540, 8, 75, -1, 0, 0, 14, 6300, 6472), + (6302, -1, -1, 6302, 6302, 5, 81, 0, 0, 0, 16, -1, 6303), + (6303, -1, -1, 6302, 6302, 5, 83, 0, 0, 0, 16, 6302, 6304), + (6304, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 6303, 11011), + (6307, 1358, 1358, 1358, 1358, 6, 71, 13168, 3, 60, 14, 1360, 6308), + (6308, 1358, 1358, 1358, 1358, 6, 73, 13169, 3, 60, 14, 6307, 6309), + (6309, 1358, 1358, 1358, 1358, 6, 75, 13170, 3, 60, 14, 6308, 6310), + (6310, 1358, 1358, 1358, 1358, 6, 76, 13171, 3, 60, 14, 6309, 6311), + (6311, 1358, 1358, 1358, 1358, 6, 78, 13172, 3, 60, 14, 6310, 6312), + (6312, 1358, 1358, 1358, 1358, 6, 80, 13173, 3, 60, 14, 6311, 7157), + (6313, 1352, 1352, 1352, 1352, 6, 71, 13174, 3, 60, 14, 1354, 6314), + (6314, 1352, 1352, 1352, 1352, 6, 73, 13175, 3, 60, 14, 6313, 6315), + (6315, 1352, 1352, 1352, 1352, 6, 75, 13177, 3, 60, 14, 6314, 6316), + (6316, 1352, 1352, 1352, 1352, 6, 76, 13178, 3, 60, 14, 6315, 6317), + (6317, 1352, 1352, 1352, 1352, 6, 78, 13179, 3, 60, 14, 6316, 6318), + (6318, 1352, 1352, 1352, 1352, 6, 80, 13180, 3, 60, 14, 6317, 7154), + (6319, -1, -1, 501, 501, 6, 73, -1, 0, 0, 14, 503, 6320), + (6320, -1, -1, 501, 501, 6, 75, -1, 0, 0, 14, 6319, 6321), + (6321, -1, -1, 501, 501, 6, 77, -1, 0, 0, 14, 6320, 6528), + (6322, -1, -1, 6322, 6322, 6, 73, -1, 0, 0, 14, -1, 6323), + (6323, -1, -1, 6322, 6322, 6, 75, -1, 0, 0, 14, 6322, 6324), + (6324, -1, -1, 6322, 6322, 6, 77, -1, 0, 0, 14, 6323, -1), + (6325, 6325, 6325, 6325, 6325, 7, 73, 13213, 18, 600, 14, -1, 6326), + (6326, 6325, 6325, 6325, 6325, 7, 75, 13214, 18, 600, 14, 6325, 6327), + (6327, 6325, 6325, 6325, 6325, 7, 77, 13215, 18, 600, 14, 6326, 6361), + (6328, 6328, 6328, 6328, 6328, 7, 74, 13204, 10, 600, 14, -1, 6329), + (6329, 6328, 6328, 6328, 6328, 7, 76, 13205, 10, 600, 14, 6328, 6330), + (6330, 6328, 6328, 6328, 6328, 7, 78, 13212, 10, 600, 14, 6329, 7143), + (6331, -1, -1, 878, 878, 7, 76, -1, 0, 0, 14, 4959, 6332), + (6332, -1, -1, 878, 878, 7, 78, -1, 0, 0, 14, 6331, 7146), + (6333, 6333, 6333, 6333, 6333, 9, 59, 13167, 3, 600, 14, -1, 7266), + (6334, -1, -1, 6334, 6334, 6, 73, -1, 0, 0, 14, -1, 6335), + (6335, -1, -1, 6334, 6334, 6, 75, -1, 0, 0, 14, 6334, 6336), + (6336, -1, -1, 6334, 6334, 6, 77, -1, 0, 0, 14, 6335, -1), + (6337, -1, -1, 6337, 6337, 6, 74, -1, 0, 0, 14, -1, 6338), + (6338, -1, -1, 6337, 6337, 6, 76, -1, 0, 0, 14, 6337, 6339), + (6339, -1, -1, 6337, 6337, 6, 78, -1, 0, 0, 14, 6338, 7448), + (6340, -1, -1, 6340, 6340, 6, 74, -1, 0, 0, 14, -1, 6341), + (6341, -1, -1, 6340, 6340, 6, 76, -1, 0, 0, 14, 6340, 6342), + (6342, -1, -1, 6340, 6340, 6, 78, -1, 0, 0, 14, 6341, 7451), + (6343, -1, -1, 6343, 6343, 6, 74, -1, 0, 0, 14, -1, 6344), + (6344, -1, -1, 6343, 6343, 6, 76, -1, 0, 0, 14, 6343, 6345), + (6345, -1, -1, 6343, 6343, 6, 78, -1, 0, 0, 14, 6344, 7166), + (6346, -1, -1, 6346, 6346, 6, 74, -1, 0, 0, 14, -1, 6347), + (6347, -1, -1, 6346, 6346, 6, 76, -1, 0, 0, 14, 6346, 6348), + (6348, -1, -1, 6346, 6346, 6, 78, -1, 0, 0, 14, 6347, 7615), + (6349, -1, -1, 6349, 6349, 6, 74, -1, 0, 0, 14, -1, 6350), + (6350, -1, -1, 6349, 6349, 6, 76, -1, 0, 0, 14, 6349, 6351), + (6351, -1, -1, 6349, 6349, 6, 78, -1, 0, 0, 14, 6350, 7618), + (6352, 4894, 4894, 4894, 4894, 6, 76, 13181, 7, 2160, 14, 4896, 6353), + (6353, 4894, 4894, 4894, 4894, 6, 77, 13182, 7, 2160, 14, 6352, 6354), + (6354, 4894, 4894, 4894, 4894, 6, 78, 13183, 7, 2160, 14, 6353, 7288), + (6355, -1, -1, 6355, 6355, 6, 73, -1, 0, 0, 14, -1, 6356), + (6356, -1, -1, 6355, 6355, 6, 74, -1, 0, 0, 14, 6355, 6357), + (6357, -1, -1, 6355, 6355, 6, 75, -1, 0, 0, 14, 6356, 6358), + (6358, -1, -1, 6355, 6355, 6, 76, -1, 0, 0, 14, 6357, 6359), + (6359, -1, -1, 6355, 6355, 6, 77, -1, 0, 0, 14, 6358, 6360), + (6360, -1, -1, 6355, 6355, 6, 80, -1, 0, 0, 16, 6359, 14101), + (6361, 6325, 6325, 6325, 6325, 7, 81, 16861, 18, 600, 16, 6327, 12633), + (6362, -1, -1, 6362, 6362, 5, 77, 0, 0, 0, 16, -1, 6363), + (6363, -1, -1, 6362, 6362, 5, 79, 0, 0, 0, 16, 6362, 6364), + (6364, -1, -1, 6362, 6362, 5, 81, 0, 0, 0, 16, 6363, 6365), + (6365, -1, -1, 6362, 6362, 5, 83, 0, 0, 0, 16, 6364, 6366), + (6366, -1, -1, 6362, 6362, 5, 85, 0, 0, 0, 16, 6365, 16327), + (6370, 6370, 6370, 6370, 6370, 6, 76, 13188, 7, 600, 14, -1, 6371), + (6371, 6370, 6370, 6370, 6370, 6, 77, 13189, 7, 600, 14, 6370, 6372), + (6372, 6370, 6370, 6370, 6370, 6, 78, 13190, 7, 600, 14, 6371, 7350), + (6375, -1, -1, 6375, 6375, 6, 76, -1, 0, 0, 14, -1, 6376), + (6376, -1, -1, 6375, 6375, 6, 77, -1, 0, 0, 14, 6375, 6377), + (6377, -1, -1, 6375, 6375, 6, 78, -1, 0, 0, 14, 6376, 7644), + (6378, 209, 209, 209, 1272, 6, 76, 13501, 12, 5, 14, 1272, -1), + (6379, 6379, 6379, 6379, 6379, 6, 60, 13500, 37, 5, 14, -1, -1), + (6380, 6380, 6380, 6380, 6380, 6, 78, 13209, 39, 120, 14, -1, 6381), + (6381, 6380, 6380, 6380, 6380, 6, 79, 13210, 39, 120, 14, 6380, 6382), + (6382, 6380, 6380, 6380, 6380, 6, 80, 13211, 39, 120, 14, 6381, 7497), + (6383, -1, -1, 6383, 6383, 3, 70, -1, 0, 0, 14, -1, 6384), + (6384, -1, -1, 6383, 6383, 6, 70, -1, 0, 0, 14, 6383, 6385), + (6385, -1, -1, 6383, 6383, 9, 70, -1, 0, 0, 14, 6384, 10607), + (6386, -1, -1, 6386, 6386, 7, 72, -1, 0, 0, 14, -1, 6387), + (6387, -1, -1, 6386, 6386, 7, 74, -1, 0, 0, 14, 6386, 6388), + (6388, -1, -1, 6386, 6386, 7, 76, -1, 0, 0, 14, 6387, 6389), + (6389, -1, -1, 6386, 6386, 7, 78, -1, 0, 0, 14, 6388, 13521), + (6390, -1, -1, 65, 661, 3, 76, -1, 0, 0, 14, 4697, 6391), + (6391, -1, -1, 65, 661, 3, 77, -1, 0, 0, 14, 6390, 6392), + (6392, -1, -1, 65, 661, 3, 78, -1, 0, 0, 14, 6391, 6393), + (6393, -1, -1, 65, 661, 3, 79, -1, 0, 0, 14, 6392, 6394), + (6394, -1, -1, 65, 661, 3, 80, -1, 0, 0, 14, 6393, 7534), + (6395, -1, -1, 6395, 6395, 7, 76, -1, 0, 0, 14, -1, 6396), + (6396, -1, -1, 6395, 6395, 7, 77, -1, 0, 0, 14, 6395, 6397), + (6397, -1, -1, 6395, 6395, 7, 78, -1, 0, 0, 14, 6396, 7336), + (6398, 516, 516, 516, 516, 6, 72, 13198, 5, 480, 14, 516, 7237), + (6400, 1110, 1110, 1110, 1110, 6, 73, 13192, 3, 2160, 14, 1112, 6401), + (6401, 1110, 1110, 1110, 1110, 6, 75, 13193, 3, 2160, 14, 6400, 6402), + (6402, 1110, 1110, 1110, 1110, 6, 76, 13194, 3, 2160, 14, 6401, 7445), + (6403, -1, -1, 1107, 1107, 7, 76, -1, 0, 0, 14, 5288, 6404), + (6404, -1, -1, 1107, 1107, 9, 78, -1, 0, 0, 14, 6403, 6405), + (6405, -1, -1, 1107, 1107, 12, 80, -1, 0, 0, 14, 6404, 12432), + (6406, -1, -1, 5085, 5085, 6, 76, -1, 0, 0, 14, 5087, 6407), + (6407, -1, -1, 5085, 5085, 6, 78, -1, 0, 0, 14, 6406, 6408), + (6408, -1, -1, 5085, 5085, 6, 80, -1, 0, 0, 14, 6407, 7384), + (6409, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6410), + (6410, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6409, 6411), + (6411, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6410, 6412), + (6412, -1, -1, 6540, 6540, 8, 74, -1, 0, 0, 14, 6411, 6413), + (6413, -1, -1, 6540, 6540, 8, 75, -1, 0, 0, 14, 6412, 6414), + (6414, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, 6413, 6415), + (6415, -1, -1, 6540, 6540, 8, 77, -1, 0, 0, 14, 6414, 6416), + (6416, -1, -1, 6540, 6540, 8, 78, -1, 0, 0, 14, 6415, 6417), + (6417, -1, -1, 6540, 6540, 8, 79, -1, 0, 0, 14, 6416, 6418), + (6418, -1, -1, 6540, 6540, 8, 80, -1, 0, 0, 14, 6417, 6474), + (6419, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6420), + (6420, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6419, 6421), + (6421, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6420, 6476), + (6422, -1, -1, 6422, 6422, 3, 61, -1, 0, 0, 14, -1, 6423), + (6423, -1, -1, 6422, 6422, 3, 63, -1, 0, 0, 14, 6422, 6424), + (6424, -1, -1, 6422, 6422, 3, 65, -1, 0, 0, 14, 6423, -1), + (6425, 5007, 5007, 5007, 5007, 9, 76, 13509, 8, 2160, 14, 5009, 6426), + (6426, 5007, 5007, 5007, 5007, 9, 78, 13510, 8, 2160, 14, 6425, 6427), + (6427, 5007, 5007, 5007, 5007, 9, 80, 13511, 8, 2160, 14, 6426, 7341), + (6428, -1, -1, 1287, 1287, 3, 67, -1, 0, 0, 14, -1, 6429), + (6429, -1, -1, 1287, 1287, 6, 68, -1, 0, 0, 14, 6428, 6430), + (6430, -1, -1, 1287, 1287, 9, 69, -1, 0, 0, 14, 6429, 12472), + (6431, -1, -1, 1056, 1056, 5, 76, -1, 0, 0, 14, 1060, 6432), + (6432, -1, -1, 1056, 1056, 5, 77, -1, 0, 0, 14, 6431, 6433), + (6433, -1, -1, 1056, 1056, 5, 78, -1, 0, 0, 14, 6432, 6434), + (6434, -1, -1, 1056, 1056, 5, 79, -1, 0, 0, 14, 6433, 6435), + (6435, -1, -1, 1056, 1056, 5, 80, -1, 0, 0, 14, 6434, 7521), + (6436, -1, -1, 6436, 6436, 6, 73, -1, 0, 0, 14, -1, 6437), + (6437, -1, -1, 6436, 6436, 6, 75, -1, 0, 0, 14, 6436, 6438), + (6438, -1, -1, 6436, 6436, 8, 77, -1, 0, 0, 14, 6437, 7313), + (6439, -1, -1, 468, 468, 2, 67, -1, 0, 0, 14, 470, 6440), + (6440, -1, -1, 468, 468, 2, 69, -1, 0, 0, 14, 6439, 7316), + (6441, -1, -1, 1546, 1546, 5, 76, -1, 0, 0, 14, 4831, 12673), + (6442, -1, -1, 1471, 1471, 6, 76, -1, 0, 0, 14, 1475, 6443), + (6443, -1, -1, 1471, 1471, 6, 77, -1, 0, 0, 14, 6442, -1), + (6445, -1, -1, 6445, 6445, 2, 62, -1, 0, 0, 14, -1, 6446), + (6446, -1, -1, 6445, 6445, 2, 64, -1, 0, 0, 14, 6445, 6447), + (6447, -1, -1, 6445, 6445, 2, 66, -1, 0, 0, 14, 6446, -1), + (6448, 5109, 5109, 5109, 5109, 9, 77, 13515, 0, 1, 14, 5109, 7467), + (6449, 1520, 1520, 1520, 1520, 9, 70, 13516, 11, 900, 14, 1522, 6450), + (6450, 1520, 1520, 1520, 1520, 9, 70, 13517, 11, 900, 14, 6449, 6451), + (6451, 1520, 1520, 1520, 1520, 9, 70, 13518, 11, 900, 14, 6450, 7463), + (6452, -1, -1, 6452, 6452, 2, 71, -1, 0, 0, 14, -1, 6453), + (6453, -1, -1, 6452, 6452, 2, 72, -1, 0, 0, 14, 6452, 6454), + (6454, -1, -1, 6452, 6452, 2, 73, -1, 0, 0, 14, 6453, -1), + (6455, 6455, 6455, 6455, 6455, 2, 72, 14750, 36, 30, 14, -1, 6456), + (6456, 6455, 6455, 6455, 6455, 2, 74, 14751, 36, 30, 14, 6455, 6457), + (6457, 6455, 6455, 6455, 6455, 2, 76, 14752, 36, 30, 14, 6456, -1), + (6458, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, -1, 6459), + (6459, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, 6458, 6460), + (6460, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, 6459, -1), + (6461, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, -1, 6462), + (6462, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, 6461, 6463), + (6463, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, 6462, -1), + (6464, 967, 967, 967, 967, 6, 76, 13897, 10, 1800, 14, 969, 6465), + (6465, 967, 967, 967, 967, 6, 77, 13898, 10, 1800, 14, 6464, 6466), + (6466, 967, 967, 967, 967, 6, 78, 13899, 10, 1800, 14, 6465, 7217), + (6467, -1, -1, 6467, 6467, 3, 61, -1, 0, 0, 15, -1, 6468), + (6468, -1, -1, 6467, 6467, 3, 63, -1, 0, 0, 15, 6467, 6469), + (6469, -1, -1, 6467, 6467, 3, 65, -1, 0, 0, 15, 6468, -1), + (6470, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 15, 6061, 6471), + (6471, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6470, 12487), + (6472, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6301, 6473), + (6473, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6472, 12481), + (6474, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6418, 6475), + (6475, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6474, 12483), + (6476, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6421, 6477), + (6477, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6476, 12485), + (6478, 0, 0, 6478, 6478, 3, 81, -1, 0, 0, 16, -1, 6479), + (6479, 0, 0, 6478, 6478, 5, 83, -1, 0, 0, 16, 6478, 6480), + (6480, 0, 0, 6478, 6478, 7, 85, -1, 0, 0, 16, 6479, -1), + (6481, 0, 0, 6481, 6481, 5, 85, -1, 0, 0, 16, -1, 6482), + (6482, 0, 0, 6481, 6481, 7, 85, -1, 0, 0, 16, 6481, 6483), + (6483, 0, 0, 6481, 6481, 9, 85, -1, 0, 0, 16, 6482, 15314), + (6484, -1, -1, 7940, 7940, 5, 85, -1, 0, 0, 16, 10032, 6485), + (6485, -1, -1, 7940, 7940, 7, 85, -1, 0, 0, 16, 6484, 6486), + (6486, -1, -1, 7940, 7940, 9, 85, -1, 0, 0, 16, 6485, 15320), + (6487, 1383, 1383, 1383, 1383, 12, 85, 21812, 6, 300, 16, 10014, 14221), + (6488, 6488, 6488, 6488, 6488, 12, 85, 21806, 32, 900, 16, -1, 13383), + (6489, -1, -1, 6489, 6489, 5, 81, -1, 0, 0, 16, -1, 6490), + (6490, -1, -1, 6489, 6489, 7, 83, -1, 0, 0, 16, 6489, 6491), + (6491, -1, -1, 6489, 6489, 9, 85, -1, 0, 0, 16, 6490, 17239), + (6492, 6492, 6492, 6492, 6492, 7, 75, 21692, 52, 720, 16, -1, 6493), + (6493, 6492, 6492, 6492, 6492, 7, 77, 21693, 52, 720, 16, 6492, 6494), + (6494, 6492, 6492, 6492, 6492, 7, 79, 21694, 52, 720, 16, 6493, 6495), + (6495, 6492, 6492, 6492, 6492, 7, 81, 21695, 52, 720, 16, 6494, 6496), + (6496, 6492, 6492, 6492, 6492, 7, 83, 21696, 52, 720, 16, 6495, 6497), + (6497, 6492, 6492, 6492, 6492, 7, 85, 21697, 52, 720, 16, 6496, 10679), + (6499, 6499, 6499, 6499, 6499, 3, 75, 13512, 13, 60, 14, -1, -1), + (6500, -1, -1, 4761, 4761, 7, 76, -1, 0, 0, 14, 4763, 6501), + (6501, -1, -1, 4761, 4761, 7, 78, -1, 0, 0, 14, 6500, 6502), + (6502, -1, -1, 4761, 4761, 7, 80, -1, 0, 0, 14, 6501, -1), + (6503, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, -1, 6504), + (6504, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6503, 6505), + (6505, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6504, 6506), + (6506, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6505, -1), + (6508, 6508, 6508, 6508, 6508, 7, 74, 13195, 38, 600, 14, -1, 6509), + (6509, 6508, 6508, 6508, 6508, 7, 76, 13196, 38, 600, 14, 6508, 6510), + (6510, 6508, 6508, 6508, 6508, 7, 78, 13197, 38, 600, 14, 6509, 7387), + (6511, -1, -1, 6511, 6511, 6, 73, -1, 0, 0, 14, -1, 6512), + (6512, -1, -1, 6511, 6511, 6, 75, -1, 0, 0, 14, 6511, 6513), + (6513, -1, -1, 6511, 6511, 6, 77, -1, 0, 0, 14, 6512, -1), + (6514, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, -1, 6515), + (6515, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, 6514, 6516), + (6516, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, 6515, -1), + (6517, -1, -1, 1435, 4773, 9, 76, -1, 0, 0, 14, 4773, 7621), + (6518, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 682, 6519), + (6519, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 6518, 6520), + (6520, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 6519, 7544), + (6521, -1, -1, 1021, 1021, 5, 75, -1, 0, 0, 14, 1025, 6522), + (6522, -1, -1, 1021, 1021, 5, 80, -1, 0, 0, 14, 6521, 7539), + (6523, -1, -1, 1026, 1026, 5, 76, -1, 0, 0, 14, 4687, 6524), + (6524, -1, -1, 1026, 1026, 5, 77, -1, 0, 0, 14, 6523, 6525), + (6525, -1, -1, 1026, 1026, 5, 78, -1, 0, 0, 14, 6524, 6526), + (6526, -1, -1, 1026, 1026, 5, 79, -1, 0, 0, 14, 6525, 6527), + (6527, -1, -1, 1026, 1026, 5, 80, -1, 0, 0, 14, 6526, 7511), + (6528, -1, -1, 501, 501, 5, 96, -1, 0, 0, 19, 6321, 6529), + (6531, -1, -1, 5295, 5295, 6, 76, -1, 0, 0, 14, 5297, 6532), + (6532, -1, -1, 5295, 5295, 6, 78, -1, 0, 0, 14, 6531, 6533), + (6533, -1, -1, 5295, 5295, 6, 80, -1, 0, 0, 14, 6532, 7220), + (6534, 8000, 8000, 8000, 8000, 12, 90, 23607, 73, 600, 17, -1, 14216), + (6540, -1, -1, 4699, 4699, 5, 56, -1, 0, 0, 14, 4699, 7500), + (6545, -1, -1, 4698, 4698, 5, 56, -1, 0, 0, 14, 4698, -1), + (6546, -1, -1, 6546, 6546, 0, 55, -1, 0, 0, 3, -1, 6547), + (6547, -1, -1, 6546, 6546, 0, 56, -1, 0, 0, 3, 6546, 6548), + (6548, -1, -1, 6546, 6546, 0, 57, -1, 0, 0, 3, 6547, 6549), + (6549, -1, -1, 6546, 6546, 0, 58, -1, 0, 0, 3, 6548, 6550), + (6550, -1, -1, 6546, 6546, 0, 59, -1, 0, 0, 3, 6549, 6551), + (6551, -1, -1, 6546, 6546, 0, 60, -1, 0, 0, 3, 6550, 6552), + (6552, -1, -1, 6546, 6546, 0, 61, -1, 0, 0, 3, 6551, 6553), + (6553, -1, -1, 6546, 6546, 0, 62, -1, 0, 0, 3, 6552, 6554), + (6554, -1, -1, 6546, 6546, 0, 63, -1, 0, 0, 3, 6553, 6555), + (6555, -1, -1, 6546, 6546, 0, 64, -1, 0, 0, 3, 6554, 6556), + (6556, -1, -1, 6546, 6546, 0, 65, -1, 0, 0, 3, 6555, 6557), + (6557, -1, -1, 6546, 6546, 0, 66, -1, 0, 0, 3, 6556, 6558), + (6558, -1, -1, 6546, 6546, 0, 67, -1, 0, 0, 3, 6557, 6559), + (6559, -1, -1, 6546, 6546, 0, 68, -1, 0, 0, 3, 6558, 6560), + (6560, -1, -1, 6546, 6546, 0, 69, -1, 0, 0, 3, 6559, 6561), + (6561, -1, -1, 6546, 6546, 0, 70, -1, 0, 0, 3, 6560, 6562), + (6562, -1, -1, 6546, 6546, 0, 71, -1, 0, 0, 3, 6561, 6563), + (6563, -1, -1, 6546, 6546, 0, 72, -1, 0, 0, 3, 6562, 6564), + (6564, -1, -1, 6546, 6546, 0, 73, -1, 0, 0, 3, 6563, 6565), + (6565, -1, -1, 6546, 6546, 0, 74, -1, 0, 0, 3, 6564, 6566), + (6566, -1, -1, 6546, 6546, 0, 75, -1, 0, 0, 3, 6565, 6567), + (6567, -1, -1, 6546, 6546, 0, 76, -1, 0, 0, 3, 6566, 6568), + (6568, -1, -1, 6546, 6546, 0, 77, -1, 0, 0, 3, 6567, 6569), + (6569, -1, -1, 6546, 6546, 0, 78, -1, 0, 0, 3, 6568, 6570), + (6570, -1, -1, 6546, 6546, 0, 79, -1, 0, 0, 3, 6569, 6571), + (6571, -1, -1, 6546, 6546, 0, 80, -1, 0, 0, 3, 6570, 7373), + (6601, -1, -1, 6601, 6601, 6, 72, -1, 0, 0, 14, -1, 6602), + (6602, -1, -1, 6601, 6601, 6, 73, -1, 0, 0, 14, 6601, 6603), + (6603, -1, -1, 6601, 6601, 6, 74, -1, 0, 0, 14, 6602, 6604), + (6604, -1, -1, 6601, 6601, 6, 75, -1, 0, 0, 14, 6603, 6605), + (6605, -1, -1, 6601, 6601, 6, 76, -1, 0, 0, 14, 6604, 7318), + (6606, 1597, 1597, 1597, 1597, 9, 75, 16095, 6, 10, 15, 1597, 10571), + (6607, 6607, 6607, 6607, 6607, 9, 75, 16092, 61, 600, 15, -1, 6608), + (6608, 6607, 6607, 6607, 6607, 9, 80, 16093, 61, 600, 15, 6607, 6609), + (6609, 6607, 6607, 6607, 6607, 9, 85, 16094, 61, 600, 15, 6608, 16324), + (6610, 6610, 6610, 6610, 6610, 2, 55, 16096, 41, 30, 15, -1, 10003), + (6611, -1, -1, 6611, 6611, 2, 60, -1, 0, 0, 15, -1, 6612), + (6612, -1, -1, 6611, 6611, 4, 63, -1, 0, 0, 15, 6611, 6613), + (6613, -1, -1, 6611, 6611, 6, 66, -1, 0, 0, 15, 6612, 6618), + (6614, -1, -1, 6614, 6614, 2, 60, -1, 0, 0, 15, -1, 6615), + (6615, -1, -1, 6614, 6614, 4, 63, -1, 0, 0, 15, 6614, 6616), + (6616, -1, -1, 6614, 6614, 6, 66, -1, 0, 0, 15, 6615, 10004), + (6617, 6617, 6617, 6617, 6617, 6, 83, 16097, 42, 3600, 15, -1, 10572), + (6618, -1, -1, 6611, 6611, 6, 69, -1, 0, 0, 15, 6613, 6619), + (6619, -1, -1, 6611, 6611, 6, 72, -1, 0, 0, 15, 6618, 10574), + (6630, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, -1, 6631), + (6631, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6630, 6632), + (6632, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6631, 6633), + (6633, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6632, 6634), + (6634, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6633, 10070), + (6635, 6635, 6635, 6635, 6635, 7, 70, 16098, 41, 600, 15, -1, -1), + (6636, -1, -1, 6636, 6636, 3, 70, -1, 0, 0, 15, -1, 6637), + (6637, -1, -1, 6636, 6636, 6, 70, -1, 0, 0, 15, 6636, 6638), + (6638, -1, -1, 6636, 6636, 9, 70, -1, 0, 0, 15, 6637, 10041), + (6639, 6639, 6639, 6639, 6639, 7, 70, 16099, 42, 300, 15, -1, 15173), + (6640, 6640, 6640, 6640, 6640, 7, 81, 16100, 43, 60, 15, -1, 12585), + (6641, -1, -1, 6641, 6641, 7, 81, -1, 0, 0, 15, -1, 6642), + (6642, -1, -1, 6641, 6641, 8, 83, -1, 0, 0, 15, 6641, 6643), + (6643, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 15, 6642, 10075), + (6644, 6644, 6644, 6644, 6644, 2, 70, 16104, 44, 20, 15, -1, 12586), + (6645, 6645, 6645, 6645, 6645, 6, 80, 16105, 45, 60, 15, -1, 13107), + (6646, 6646, 6646, 6646, 6646, 6, 70, 16106, 46, 6, 15, -1, -1), + (6660, -1, -1, 1307, 1307, 5, 73, -1, 0, 0, 15, 1311, 6661), + (6661, -1, -1, 1307, 1307, 5, 74, -1, 0, 0, 15, 6660, 6662), + (6662, -1, -1, 1307, 1307, 5, 75, -1, 0, 0, 15, 6661, 13210), + (6663, 6663, 6663, 6663, 6663, 7, 73, 16107, 59, 600, 15, -1, 6664), + (6664, 6663, 6663, 6663, 6663, 7, 75, 16108, 59, 600, 15, 6663, 6665), + (6665, 6663, 6663, 6663, 6663, 7, 77, 16109, 59, 600, 15, 6664, 10162), + (6666, -1, -1, 6666, 6666, 8, 81, -1, 0, 0, 15, -1, 6667), + (6667, -1, -1, 6666, 6666, 8, 83, -1, 0, 0, 15, 6666, -1), + (6668, -1, -1, 6668, 6668, 3, 76, -1, 0, 0, 15, -1, 6669), + (6669, -1, -1, 6668, 6668, 3, 77, -1, 0, 0, 15, 6668, 6670), + (6670, -1, -1, 6668, 6668, 3, 78, -1, 0, 0, 15, 6669, -1), + (6671, 6671, 6671, 6671, 6671, 4, 65, 16148, 60, 60, 15, -1, -1), + (6672, 6672, 6672, 6672, 6672, 4, 67, 16149, 60, 60, 15, -1, -1), + (6673, 6673, 6673, 6673, 6673, 4, 69, 16150, 60, 60, 15, -1, -1), + (6674, 6674, 6674, 6674, 6674, 4, 71, 16151, 60, 60, 15, -1, -1), + (6675, 6675, 6675, 6675, 6675, 4, 73, 16152, 60, 60, 15, -1, -1), + (6676, 6676, 6676, 6676, 6676, 4, 75, 16153, 60, 60, 15, -1, -1), + (6691, 6691, 6691, 6691, 6691, 9, 81, 16114, 41, 30, 15, -1, -1), + (6692, 6692, 6692, 6692, 6692, 7, 65, 16115, 42, 600, 15, -1, 6693), + (6693, 6692, 6692, 6692, 6692, 7, 70, 16116, 42, 600, 15, 6692, 6694), + (6694, 6692, 6692, 6692, 6692, 7, 75, 16117, 42, 600, 15, 6693, 6695), + (6695, 6692, 6692, 6692, 6692, 7, 80, 16118, 42, 600, 15, 6694, 6696), + (6696, 6692, 6692, 6692, 6692, 7, 85, 16119, 42, 600, 15, 6695, 5342), + (6697, -1, -1, 6697, 6697, 7, 65, -1, 0, 0, 15, -1, 6698), + (6698, -1, -1, 6697, 6697, 7, 70, -1, 0, 0, 15, 6697, 6699), + (6699, -1, -1, 6697, 6697, 7, 75, -1, 0, 0, 15, 6698, 6700), + (6700, -1, -1, 6697, 6697, 7, 80, -1, 0, 0, 15, 6699, 6701), + (6701, -1, -1, 6697, 6697, 7, 85, -1, 0, 0, 15, 6700, -1), + (6702, 6702, 6702, 6702, 6702, 9, 75, 16120, 43, 120, 15, -1, -1), + (6703, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, -1, 6704), + (6704, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, 6703, 6705), + (6705, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, 6704, 10176), + (6706, 6706, 6706, 6706, 6706, 7, 75, 16121, 44, 600, 15, -1, 6707), + (6707, 6706, 6706, 6706, 6706, 7, 80, 16122, 44, 600, 15, 6706, 6708), + (6708, 6706, 6706, 6706, 6706, 7, 85, 16123, 44, 600, 15, 6707, 10179), + (6709, -1, -1, 6709, 6709, 3, 60, -1, 0, 0, 15, -1, 6710), + (6710, -1, -1, 6709, 6709, 3, 61, -1, 0, 0, 15, 6709, 6711), + (6711, -1, -1, 6709, 6709, 3, 62, -1, 0, 0, 15, 6710, -1), + (6712, -1, -1, 6712, 6712, 7, 65, -1, 0, 0, 15, -1, 6713), + (6713, -1, -1, 6712, 6712, 7, 70, -1, 0, 0, 15, 6712, 6714), + (6714, -1, -1, 6712, 6712, 7, 75, -1, 0, 0, 15, 6713, 6715), + (6715, -1, -1, 6712, 6712, 7, 80, -1, 0, 0, 15, 6714, 6716), + (6716, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 15, 6715, 10182), + (6750, 6750, 6750, 6750, 6750, 9, 85, 16127, 60, 120, 15, -1, 13899), + (6751, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, -1, 6752), + (6752, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6751, 6753), + (6753, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6752, 6768), + (6754, 6754, 6754, 6754, 6754, 7, 70, 16130, 41, 1200, 15, -1, 10053), + (6755, 6755, 6755, 6755, 6755, 7, 81, 16131, 42, 900, 15, -1, 6756), + (6756, 6755, 6755, 6755, 6755, 9, 83, 16132, 42, 900, 15, 6755, 6757), + (6757, 6755, 6755, 6755, 6755, 12, 85, 16133, 42, 900, 15, 6756, 13542), + (6758, 6758, 6758, 6758, 6758, 3, 81, 16134, 43, 900, 15, -1, 6759), + (6759, 6758, 6758, 6758, 6758, 6, 83, 16135, 43, 900, 15, 6758, 6760), + (6760, 6758, 6758, 6758, 6758, 9, 85, 16136, 43, 900, 15, 6759, 10054), + (6761, -1, -1, 6761, 6761, 3, 65, -1, 0, 0, 15, -1, 6762), + (6762, -1, -1, 6761, 6761, 6, 65, -1, 0, 0, 15, 6761, 6763), + (6763, -1, -1, 6761, 6761, 9, 65, -1, 0, 0, 15, 6762, 6085), + (6764, 6764, 6764, 6764, 6764, 7, 75, 16137, 52, 600, 15, -1, 10057), + (6765, -1, -1, 6765, 6765, 3, 70, -1, 0, 0, 15, -1, 6766), + (6766, -1, -1, 6765, 6765, 6, 75, -1, 0, 0, 15, 6765, 6767), + (6767, -1, -1, 6765, 6765, 9, 80, -1, 0, 0, 15, 6766, 10058), + (6768, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6753, 6769), + (6769, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6768, 10769), + (6791, -1, -1, 6791, 6791, 6, 75, -1, 0, 0, 15, -1, 6792), + (6792, -1, -1, 6791, 6791, 6, 80, -1, 0, 0, 15, 6791, 6793), + (6793, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 15, 6792, 10044), + (6794, 6794, 6794, 6794, 6794, 6, 75, 16142, 41, 60, 15, -1, -1), + (6815, 6815, 6815, 6815, 6815, 8, 75, 16144, 60, 600, 15, -1, 6816), + (6816, 6815, 6815, 6815, 6815, 8, 80, 16145, 60, 600, 15, 6815, 6817), + (6817, 6815, 6815, 6815, 6815, 8, 85, 16146, 60, 600, 15, 6816, 10200), + (6818, 6818, 6818, 6818, 6818, 6, 70, 16147, 44, 20, 15, -1, -1), + (6819, -1, -1, 6819, 6819, 6, 72, -1, 0, 0, 15, -1, 6820), + (6820, -1, -1, 6819, 6819, 6, 74, -1, 0, 0, 15, 6819, 6821), + (6821, -1, -1, 6819, 6819, 6, 76, -1, 0, 0, 15, 6820, 10203), + (6822, 6822, 6822, 6822, 6822, 12, 80, 16154, 42, 120, 15, -1, 13683), + (6823, -1, -1, 6823, 6823, 4, 65, -1, 0, 0, 15, -1, 6824), + (6824, -1, -1, 6823, 6823, 4, 67, -1, 0, 0, 15, 6823, 6825), + (6825, -1, -1, 6823, 6823, 4, 69, -1, 0, 0, 15, 6824, 6826), + (6826, -1, -1, 6823, 6823, 4, 71, -1, 0, 0, 15, 6825, 6827), + (6827, -1, -1, 6823, 6823, 4, 73, -1, 0, 0, 15, 6826, 10206), + (6828, 6828, 6828, 6828, 6828, 12, 80, 16155, 43, 60, 15, -1, 10208), + (6870, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, -1, 6871), + (6871, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, 6870, 6872), + (6872, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, 6871, 10130), + (6873, -1, -1, 255, 255, 3, 76, -1, 0, 0, 15, -1, 6874), + (6874, -1, -1, 255, 255, 6, 76, -1, 0, 0, 15, 6873, 6875), + (6875, -1, -1, 255, 255, 9, 76, -1, 0, 0, 15, 6874, 10133), + (6876, -1, -1, 6375, 6375, 6, 76, -1, 0, 0, 15, -1, 6877), + (6877, -1, -1, 6375, 6375, 6, 77, -1, 0, 0, 15, 6876, 6878), + (6878, -1, -1, 6375, 6375, 6, 78, -1, 0, 0, 15, 6877, 10136), + (6879, -1, -1, 649, 649, 2, 66, -1, 0, 0, 15, -1, 6880), + (6880, -1, -1, 649, 649, 4, 68, -1, 0, 0, 15, 6879, 6881), + (6881, -1, -1, 649, 649, 6, 70, -1, 0, 0, 15, 6880, -1), + (6882, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, -1, 6883), + (6883, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, 6882, 6884), + (6884, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, 6883, -1), + (6900, -1, -1, 6935, 6935, 6, 81, -1, 0, 0, 16, 6937, 6901), + (6901, -1, -1, 6935, 6935, 6, 82, -1, 0, 0, 16, 6900, 6902), + (6902, -1, -1, 6935, 6935, 6, 83, -1, 0, 0, 16, 6901, 6903), + (6903, -1, -1, 6935, 6935, 6, 84, -1, 0, 0, 16, 6902, 6904), + (6904, -1, -1, 6935, 6935, 6, 85, -1, 0, 0, 16, 6903, 14196), + (6905, -1, -1, 551, 551, 5, 81, -1, 0, 0, 16, 1637, 6906), + (6906, -1, -1, 551, 551, 5, 83, -1, 0, 0, 16, 6905, 6907), + (6907, -1, -1, 551, 551, 5, 85, -1, 0, 0, 16, 6906, 12843), + (6908, -1, -1, 6908, 6908, 6, 81, -1, 0, 0, 16, -1, 6909), + (6909, -1, -1, 6908, 6908, 6, 83, -1, 0, 0, 16, 6908, 6910), + (6910, -1, -1, 6908, 6908, 6, 85, -1, 0, 0, 16, 6909, 14199), + (6911, -1, -1, 1143, 1143, 5, 65, -1, 0, 0, 16, 1168, 6912), + (6912, -1, -1, 1143, 1143, 7, 65, -1, 0, 0, 16, 6911, 6913), + (6913, -1, -1, 1143, 1143, 9, 65, -1, 0, 0, 16, 6912, -1), + (6930, 6930, 6930, 6930, 6930, 12, 80, 16156, 13, 60, 15, -1, -1), + (6931, 6931, 6931, 6931, 6931, 12, 85, 16157, 41, 600, 15, -1, 10319), + (6932, 6932, 6932, 6932, 6932, 7, 81, 16158, 42, 1200, 15, -1, 6933), + (6933, 6932, 6932, 6932, 6932, 7, 83, 16159, 42, 1200, 15, 6932, 6934), + (6934, 6932, 6932, 6932, 6932, 7, 85, 16160, 42, 1200, 15, 6933, 10320), + (6935, -1, -1, 6935, 6935, 6, 75, -1, 0, 0, 15, -1, 6936), + (6936, -1, -1, 6935, 6935, 6, 77, -1, 0, 0, 15, 6935, 6937), + (6937, -1, -1, 6935, 6935, 6, 79, -1, 0, 0, 15, 6936, 6900), + (6938, -1, -1, 6938, 6938, 7, 81, -1, 0, 0, 15, -1, 6939), + (6939, -1, -1, 6938, 6938, 7, 83, -1, 0, 0, 15, 6938, 6940), + (6940, -1, -1, 6938, 6938, 7, 85, -1, 0, 0, 15, 6939, -1), + (6941, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, -1, 6942), + (6942, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6941, 6943), + (6943, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6942, 6944), + (6944, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6943, 6945), + (6945, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6944, -1), + (6970, 6970, 6970, 6970, 6970, 6, 70, 16167, 61, 6, 15, -1, -1), + (6971, 6971, 6971, 6971, 6971, 7, 78, 16168, 41, 600, 15, -1, 6972), + (6972, 6971, 6971, 6971, 6971, 7, 80, 16169, 41, 600, 15, 6971, 6973), + (6973, 6971, 6971, 6971, 6971, 7, 82, 16170, 41, 600, 15, 6972, 10288), + (6974, -1, -1, 6974, 6974, 5, 81, -1, 0, 0, 15, -1, 6975), + (6975, -1, -1, 6974, 6974, 5, 83, -1, 0, 0, 15, 6974, 6976), + (6976, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 15, 6975, 10291), + (6977, -1, -1, 6977, 6977, 5, 81, -1, 0, 0, 15, -1, 6978), + (6978, -1, -1, 6977, 6977, 5, 83, -1, 0, 0, 15, 6977, 6979), + (6979, -1, -1, 6977, 6977, 5, 85, -1, 0, 0, 15, 6978, 12840), + (6980, -1, -1, 6980, 6980, 5, 81, -1, 0, 0, 15, -1, 6981), + (6981, -1, -1, 6980, 6980, 5, 83, -1, 0, 0, 15, 6980, 6982), + (6982, -1, -1, 6980, 6980, 5, 85, -1, 0, 0, 15, 6981, 12834), + (6983, 6983, 6983, 6983, 6983, 7, 83, 16439, 66, 720, 15, -1, 16246), + (6984, 6984, 6984, 6984, 6984, 6, 73, 16172, 60, 60, 15, -1, 10294), + (6985, 6985, 6985, 6985, 6985, 6, 73, 16173, 60, 60, 15, -1, 10295), + (6986, 6986, 6986, 6986, 6986, 6, 73, 16174, 60, 60, 15, -1, 10296), + (6987, -1, -1, 6987, 6987, 12, 81, -1, 0, 0, 15, -1, -1), + (6988, -1, -1, 6988, 6988, 5, 83, 0, 0, 0, 16, -1, 6989), + (6989, -1, -1, 6988, 6988, 5, 84, 0, 0, 0, 16, 6988, 6990), + (6990, -1, -1, 6988, 6988, 5, 83, 0, 0, 0, 16, 6989, 14278), + (7000, 7000, 7000, 7000, 7000, 4, 65, 12748, 31, 600, 3, -1, -1), + (7002, 7002, 7002, 7002, 7002, 4, 65, 12750, 31, 600, 3, -1, -1), + (7003, 7003, 7003, 7003, 7003, 4, 65, 12751, 31, 600, 3, -1, -1), + (7004, 7004, 7004, 7004, 7004, 4, 65, 12752, 31, 300, 3, -1, -1), + (7005, -1, -1, 7005, 7005, 2, 73, -1, 0, 0, 15, -1, 7006), + (7006, -1, -1, 7005, 7005, 2, 74, -1, 0, 0, 15, 7005, 7007), + (7007, -1, -1, 7005, 7005, 2, 75, -1, 0, 0, 15, 7006, 15632), + (7008, -1, -1, 1604, 1604, 9, 81, -1, 0, 0, 16, 7133, 7009), + (7009, -1, -1, 1604, 1604, 12, 83, -1, 0, 0, 16, 7008, 12612), + (7010, -1, -1, 7010, 7010, 6, 81, -1, 0, 0, 16, -1, 7011), + (7011, -1, -1, 7010, 7010, 6, 83, -1, 0, 0, 16, 7010, 7012), + (7012, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7011, 7013), + (7013, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7012, 7014), + (7014, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7013, 7015), + (7015, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7014, 13533), + (7016, 7016, 7016, 7016, 7016, 5, 85, 21658, 31, 600, 3, -1, -1), + (7017, 7017, 7017, 7017, 7017, 5, 85, 21659, 31, 600, 3, -1, -1), + (7018, 7018, 7018, 7018, 7018, 5, 85, 21660, 31, 600, 3, -1, -1), + (7019, 7019, 7019, 7019, 7019, 5, 85, 21661, 31, 600, 3, -1, -1), + (7020, 7020, 7020, 7020, 7020, 0, 85, 21658, 31, 600, 3, -1, -1), + (7021, 7021, 7021, 7021, 7021, 0, 85, 21659, 31, 600, 3, -1, -1), + (7022, 7022, 7022, 7022, 7022, 0, 85, 21660, 31, 600, 3, -1, -1), + (7023, 7023, 7023, 7023, 7023, 0, 85, 21661, 31, 600, 3, -1, -1), + (7024, 7024, 7024, 7024, 7024, 0, 0, 9475, 31, 600, 12, -1, -1), + (7025, 7025, 7025, 7025, 7025, 0, 0, 9477, 31, 600, 12, -1, -1), + (7026, 7026, 7026, 7026, 7026, 0, 0, 9478, 31, 600, 12, -1, -1), + (7027, 7027, 7027, 7027, 7027, 0, 0, 9479, 31, 600, 12, -1, -1), + (7028, 7028, 7028, 7028, 7028, 0, 0, 12748, 31, 600, 3, -1, -1), + (7030, 7030, 7030, 7030, 7030, 0, 0, 12750, 31, 600, 3, -1, -1), + (7031, 7031, 7031, 7031, 7031, 0, 0, 12751, 31, 600, 3, -1, -1), + (7032, 7032, 7032, 7032, 7032, 0, 0, 12752, 31, 300, 3, -1, -1), + (7033, -1, -1, 7033, 7033, 6, 85, 0, 0, 0, 16, -1, 7034), + (7034, -1, -1, 7033, 7033, 9, 85, 0, 0, 0, 16, 7033, 7035), + (7035, -1, -1, 7033, 7033, 12, 85, 0, 0, 0, 16, 7034, 15746), + (7036, -1, -1, 7036, 7036, 7, 81, -1, 0, 0, 16, -1, 7037), + (7037, -1, -1, 7036, 7036, 9, 81, -1, 0, 0, 16, 7036, 7038), + (7038, -1, -1, 7036, 7036, 12, 81, -1, 0, 0, 16, 7037, 10579), + (7050, -1, -1, 446, 735, 5, 67, -1, 0, 0, 8, 448, 7051), + (7051, -1, -1, 446, 735, 5, 68, -1, 0, 0, 8, 7050, 7052), + (7052, -1, -1, 446, 735, 5, 69, -1, 0, 0, 8, 7051, 7053), + (7053, -1, -1, 446, 735, 7, 72, -1, 0, 0, 12, 7052, 7054), + (7054, -1, -1, 446, 735, 7, 73, -1, 0, 0, 12, 7053, 7055), + (7055, -1, -1, 446, 735, 7, 74, -1, 0, 0, 12, 7054, 7063), + (7056, -1, -1, 735, 735, 5, 67, -1, 0, 0, 8, 737, 7057), + (7057, -1, -1, 735, 735, 5, 68, -1, 0, 0, 8, 7056, 7058), + (7058, -1, -1, 735, 735, 5, 69, -1, 0, 0, 8, 7057, 7059), + (7059, -1, -1, 735, 735, 7, 72, -1, 0, 0, 12, 7058, 7060), + (7060, -1, -1, 735, 735, 7, 73, -1, 0, 0, 12, 7059, 7061), + (7061, -1, -1, 735, 735, 7, 74, -1, 0, 0, 12, 7060, 7066), + (7062, -1, -1, 7062, 7062, 3, 51, -1, 0, 0, 0, -1, -1), + (7063, -1, -1, 446, 735, 8, 76, -1, 0, 0, 14, 7055, 7064), + (7064, -1, -1, 446, 735, 8, 77, -1, 0, 0, 14, 7063, 7065), + (7065, -1, -1, 446, 735, 8, 78, -1, 0, 0, 14, 7064, 7622), + (7066, -1, -1, 735, 735, 8, 76, -1, 0, 0, 14, 7061, 7067), + (7067, -1, -1, 735, 735, 8, 77, -1, 0, 0, 14, 7066, 7068), + (7068, -1, -1, 735, 735, 8, 78, -1, 0, 0, 14, 7067, 7625), + (7069, 7069, 7069, 7069, 7069, 3, 71, 13219, 39, 7, 14, -1, -1), + (7100, -1, -1, 7100, 7100, 6, 76, -1, 0, 0, 14, -1, 7101), + (7101, -1, -1, 7100, 7100, 6, 77, -1, 0, 0, 14, 7100, 7102), + (7102, -1, -1, 7100, 7100, 6, 78, -1, 0, 0, 14, 7101, 7323), + (7103, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, -1, 7104), + (7104, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, 7103, 7105), + (7105, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, 7104, 7326), + (7106, -1, -1, 7106, 7106, 6, 73, -1, 0, 0, 14, -1, 7107), + (7107, -1, -1, 7106, 7106, 7, 76, -1, 0, 0, 14, 7106, 7108), + (7108, -1, -1, 7106, 7106, 10, 79, -1, 0, 0, 14, 7107, -1), + (7109, 1351, 1351, 1351, 1351, 8, 82, 13499, 5, 30, 15, 6133, 13109), + (7110, 4849, 4849, 4849, 4849, 7, 81, 13593, 7, 1800, 15, 6134, 13914), + (7111, 54006, 54006, 54006, 54006, 7, 81, 13594, 18, 180, 15, 6135, 10006), + (7112, -1, -1, 6564, 6564, 6, 78, -1, 0, 0, 15, 6285, 7113), + (7113, -1, -1, 6564, 6564, 7, 81, -1, 0, 0, 15, 7112, 7114), + (7114, -1, -1, 6564, 6564, 10, 84, -1, 0, 0, 15, 7113, 10007), + (7115, 6565, 6565, 6565, 6565, 7, 81, 13595, 17, 45, 15, 6286, 10010), + (7116, -1, -1, 489, 489, 3, 68, -1, 0, 0, 15, 491, 7117), + (7117, -1, -1, 489, 489, 3, 69, -1, 0, 0, 15, 7116, 7118), + (7118, -1, -1, 489, 489, 3, 70, -1, 0, 0, 15, 7117, -1), + (7119, 912, 912, 912, 912, 3, 71, 13496, 4, 3600, 15, 1332, 7120), + (7120, 912, 912, 912, 912, 6, 73, 13497, 4, 3600, 15, 7119, 7121), + (7121, 912, 912, 912, 912, 9, 75, 13498, 4, 3600, 15, 7120, 10011), + (7122, -1, -1, 4844, 4844, 5, 76, -1, 0, 0, 15, 4848, 7123), + (7123, -1, -1, 4844, 4844, 5, 77, -1, 0, 0, 15, 7122, 7124), + (7124, -1, -1, 4844, 4844, 5, 78, -1, 0, 0, 15, 7123, 7125), + (7125, -1, -1, 4844, 4844, 5, 79, -1, 0, 0, 15, 7124, 7126), + (7126, -1, -1, 4844, 4844, 5, 80, -1, 0, 0, 15, 7125, 7686), + (7127, 4860, 4860, 4860, 4860, 12, 85, 13599, 13, 60, 15, 5606, -1), + (7128, -1, -1, 492, 492, 2, 68, -1, 0, 0, 15, 494, 7129), + (7129, -1, -1, 492, 492, 2, 69, -1, 0, 0, 15, 7128, 7130), + (7130, -1, -1, 492, 492, 2, 70, -1, 0, 0, 15, 7129, 10576), + (7131, -1, -1, 1604, 1604, 7, 75, -1, 0, 0, 15, 6034, 7132), + (7132, -1, -1, 1604, 1604, 9, 77, -1, 0, 0, 15, 7131, 7133), + (7133, -1, -1, 1604, 1604, 12, 79, -1, 0, 0, 15, 7132, 7008), + (7134, -1, -1, 1543, 1543, 7, 81, -1, 0, 0, 15, 6044, 7135), + (7135, -1, -1, 1543, 1543, 9, 83, -1, 0, 0, 15, 7134, 7136), + (7136, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 15, 7135, 10165), + (7137, -1, -1, 6559, 6559, 6, 79, -1, 0, 0, 15, 6274, 7138), + (7138, -1, -1, 6559, 6559, 7, 81, -1, 0, 0, 15, 7137, 7139), + (7139, -1, -1, 6559, 6559, 10, 83, -1, 0, 0, 15, 7138, -1), + (7143, 6328, 6328, 6328, 6328, 7, 79, 13601, 10, 600, 15, 6330, 7144), + (7144, 6328, 6328, 6328, 6328, 7, 81, 13602, 10, 600, 15, 7143, 7145), + (7145, 6328, 6328, 6328, 6328, 7, 83, 13603, 10, 600, 15, 7144, 10168), + (7146, -1, -1, 878, 878, 7, 81, -1, 0, 0, 15, 6332, 7147), + (7147, -1, -1, 878, 878, 7, 83, -1, 0, 0, 15, 7146, 10171), + (7148, -1, -1, 1304, 1304, 7, 81, -1, 0, 0, 15, 6031, 7149), + (7149, -1, -1, 1304, 1304, 9, 83, -1, 0, 0, 15, 7148, 7150), + (7150, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 15, 7149, 10865), + (7151, -1, -1, 846, 846, 7, 81, -1, 0, 0, 15, 6037, 7152), + (7152, -1, -1, 846, 846, 9, 83, -1, 0, 0, 15, 7151, 7153), + (7153, -1, -1, 846, 846, 12, 85, -1, 0, 0, 15, 7152, 10173), + (7154, 1352, 1352, 1352, 1352, 6, 81, 13613, 3, 60, 15, 6318, 7155), + (7155, 1352, 1352, 1352, 1352, 6, 83, 13614, 3, 60, 15, 7154, 7156), + (7156, 1352, 1352, 1352, 1352, 6, 85, 13615, 3, 60, 15, 7155, 10113), + (7157, 1358, 1358, 1358, 1358, 6, 81, 13610, 3, 60, 15, 6312, 7158), + (7158, 1358, 1358, 1358, 1358, 6, 83, 13611, 3, 60, 15, 7157, 7159), + (7159, 1358, 1358, 1358, 1358, 6, 85, 13612, 3, 60, 15, 7158, 10116), + (7160, -1, -1, 4801, 4801, 6, 79, -1, 0, 0, 15, 4803, 7161), + (7161, -1, -1, 4801, 4801, 6, 81, -1, 0, 0, 15, 7160, 7162), + (7162, -1, -1, 4801, 4801, 6, 83, -1, 0, 0, 15, 7161, 10122), + (7163, -1, -1, 820, 820, 5, 81, -1, 0, 0, 15, 5919, 7164), + (7164, -1, -1, 820, 820, 5, 83, -1, 0, 0, 15, 7163, 7165), + (7165, -1, -1, 820, 820, 5, 85, -1, 0, 0, 15, 7164, 10660), + (7166, -1, -1, 6343, 6343, 6, 79, -1, 0, 0, 15, 6345, 7167), + (7167, -1, -1, 6343, 6343, 6, 81, -1, 0, 0, 15, 7166, 7168), + (7168, -1, -1, 6343, 6343, 6, 83, -1, 0, 0, 15, 7167, -1), + (7169, -1, -1, 6020, 6020, 2, 81, -1, 0, 0, 15, 6059, 7170), + (7170, -1, -1, 6020, 6020, 2, 83, -1, 0, 0, 15, 7169, 7171), + (7171, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 15, 7170, 10663), + (7172, 1355, 1355, 1355, 1355, 6, 81, 13607, 3, 60, 15, 5916, 7173), + (7173, 1355, 1355, 1355, 1355, 6, 83, 13608, 3, 60, 15, 7172, 7174), + (7174, 1355, 1355, 1355, 1355, 6, 85, 13609, 3, 60, 15, 7173, 10119), + (7175, -1, -1, 611, 611, 2, 68, -1, 0, 0, 15, 615, 7176), + (7176, -1, -1, 611, 611, 2, 69, -1, 0, 0, 15, 7175, 7177), + (7177, -1, -1, 611, 611, 2, 70, -1, 0, 0, 15, 7176, 10124), + (7178, 4854, 4854, 4854, 4854, 7, 81, 13616, 8, 600, 15, 5766, 7179), + (7179, 4854, 4854, 4854, 4854, 9, 83, 13617, 8, 600, 15, 7178, 7180), + (7180, 4854, 4854, 4854, 4854, 12, 85, 13618, 8, 600, 15, 7179, 10323), + (7184, 1348, 1348, 1348, 1348, 12, 91, 13622, 0, 3600, 18, 5772, 7185), + (7187, 1178, 1178, 1178, 1178, 7, 81, 13625, 4, 900, 15, 5781, 7188), + (7188, 1178, 1178, 1178, 1178, 8, 82, 13626, 4, 900, 15, 7187, 7189), + (7189, 1178, 1178, 1178, 1178, 9, 83, 13627, 4, 900, 15, 7188, 10326), + (7196, -1, -1, 5776, 5776, 7, 81, -1, 0, 0, 16, 5778, 7197), + (7197, -1, -1, 5776, 5776, 9, 83, -1, 0, 0, 16, 7196, 7198), + (7198, -1, -1, 5776, 5776, 12, 85, -1, 0, 0, 16, 7197, 13043), + (7199, 1274, 1274, 1274, 1274, 9, 83, 13657, 9, 540, 15, 5949, 7200), + (7200, 1274, 1274, 1274, 1274, 10, 84, 13658, 9, 540, 15, 7199, 7201), + (7201, 1274, 1274, 1274, 1274, 12, 85, 13659, 9, 540, 15, 7200, 10209), + (7202, 1510, -1, 1510, 1510, 12, 75, 13664, 13, 2160, 15, 1510, 10212), + (7203, 184, 184, 184, 184, 10, 84, 13660, 5, 4320, 15, 5953, -1), + (7204, -1, -1, 5264, 5264, 7, 81, -1, 0, 0, 15, 5943, 7205), + (7205, -1, -1, 5264, 5264, 8, 82, -1, 0, 0, 15, 7204, 7206), + (7206, -1, -1, 5264, 5264, 9, 83, -1, 0, 0, 15, 7205, 7207), + (7207, -1, -1, 5264, 5264, 10, 84, -1, 0, 0, 15, 7206, 7208), + (7208, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 15, 7207, 10213), + (7209, 4927, 4927, 4927, 4927, 9, 76, 13656, 14, 600, 15, 4927, 10218), + (7210, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 5329, 7211), + (7211, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7210, 7212), + (7212, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7211, 7213), + (7213, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7212, 7214), + (7214, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7213, 10219), + (7215, -1, -1, 4861, 4861, 9, 83, -1, 0, 0, 15, 5956, 7216), + (7216, -1, -1, 4861, 4861, 12, 85, -1, 0, 0, 15, 7215, 7682), + (7217, 967, 967, 967, 967, 6, 81, 13661, 10, 1800, 15, 6466, 7218), + (7218, 967, 967, 967, 967, 6, 82, 13662, 10, 1800, 15, 7217, 7219), + (7219, 967, 967, 967, 967, 6, 83, 13663, 10, 1800, 15, 7218, 10224), + (7220, -1, -1, 5295, 5295, 6, 81, -1, 0, 0, 15, 6533, 7221), + (7221, -1, -1, 5295, 5295, 6, 83, -1, 0, 0, 15, 7220, 7222), + (7222, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 15, 7221, 10227), + (7223, 6290, 6290, 6290, 6290, 7, 81, 13689, 0, 1, 15, 6295, 7224), + (7224, 6290, 6290, 6290, 6290, 9, 83, 13690, 0, 1, 15, 7223, 7225), + (7225, 6290, 6290, 6290, 6290, 12, 85, 13691, 0, 1, 15, 7224, 11064), + (7226, 619, 619, 619, 619, 6, 78, 13686, 6, 900, 15, 6298, 7227), + (7227, 619, 619, 619, 619, 6, 78, 13687, 6, 900, 15, 7226, 7228), + (7228, 619, 619, 619, 619, 6, 78, 13688, 6, 900, 15, 7227, 10230), + (7229, 4944, -1, 4944, 4944, 7, 81, 13677, 0, 1, 15, 6157, 7230), + (7230, 4944, -1, 4944, 4944, 9, 83, 13678, 0, 1, 15, 7229, 7231), + (7231, 4944, -1, 4944, 4944, 12, 85, 13679, 0, 1, 15, 7230, 11067), + (7232, -1, -1, 1210, 1210, 7, 81, -1, 0, 0, 15, 5576, 7233), + (7233, -1, -1, 1210, 1210, 9, 83, -1, 0, 0, 15, 7232, 7234), + (7234, -1, -1, 1210, 1210, 12, 85, -1, 0, 0, 15, 7233, 12523), + (7235, 923, 923, 923, 923, 9, 82, 13673, 8, 60, 15, 6151, -1), + (7236, 922, 922, 922, 922, 9, 83, 13672, 8, 60, 15, 6150, -1), + (7237, 516, 516, 516, 516, 6, 77, 13692, 5, 480, 15, 6398, 10233), + (7238, 155, 155, 155, 155, 12, 82, 13693, 8, 60, 15, 5289, 14324), + (7239, 1334, 1334, 1334, 1334, 9, 83, 13674, 11, 4320, 15, 6154, 7240), + (7240, 1334, 1334, 1334, 1334, 10, 84, 13675, 11, 4320, 15, 7239, 7241), + (7241, 1334, 1334, 1334, 1334, 12, 85, 13676, 11, 4320, 15, 7240, 10234), + (7242, 1478, -1, 1478, 1478, 9, 83, 13680, 0, 1, 15, 6163, 7243), + (7243, 1478, -1, 1478, 1478, 10, 84, 13681, 0, 1, 15, 7242, 7244), + (7244, 1478, -1, 1478, 1478, 12, 85, 13682, 0, 1, 15, 7243, 11070), + (7245, 921, 921, 921, 921, 9, 84, 13671, 8, 60, 15, 6149, -1), + (7246, 4915, 4915, 4915, 4915, 7, 81, 13683, 7, 4320, 15, 5609, 7247), + (7247, 4915, 4915, 4915, 4915, 9, 83, 13684, 7, 4320, 15, 7246, 7248), + (7248, 4915, 4915, 4915, 4915, 12, 85, 13685, 7, 4320, 15, 7247, -1), + (7249, 167, 167, 167, 167, 10, 84, 13703, 14, 900, 15, 5879, 8343), + (7250, 520, 520, 520, 520, 12, 81, 13704, 6, 540, 15, 5885, 7251), + (7251, 520, 520, 520, 520, 12, 83, 13705, 6, 540, 15, 7250, 7252), + (7252, 520, 520, 520, 520, 12, 85, 13706, 6, 540, 15, 7251, 10252), + (7253, 4903, 4903, 4903, 4903, 9, 81, 13707, 9, 1320, 15, 5892, 10255), + (7254, 4906, 4906, 4906, 4906, 9, 81, 13708, 9, 1320, 15, 5893, 10256), + (7255, 4909, 4909, 4909, 4909, 9, 81, 13709, 16, 1320, 15, 5894, 10257), + (7256, 4912, 4912, 4912, 4912, 9, 81, 13710, 16, 1320, 15, 5895, 10258), + (7257, 616, 616, 616, 616, 6, 78, 13711, 7, 900, 15, 6256, 7258), + (7258, 616, 616, 616, 616, 7, 81, 13712, 7, 900, 15, 7257, 7259), + (7259, 616, 616, 616, 616, 10, 84, 13713, 7, 900, 15, 7258, 10259), + (7260, -1, -1, 1504, 1504, 5, 81, -1, 0, 0, 15, 5882, 7261), + (7261, -1, -1, 1504, 1504, 5, 83, -1, 0, 0, 15, 7260, 7262), + (7262, -1, -1, 1504, 1504, 5, 85, -1, 0, 0, 15, 7261, -1), + (7263, -1, -1, 1577, 1577, 7, 81, -1, 0, 0, 15, 5888, 7264), + (7264, -1, -1, 1577, 1577, 9, 83, -1, 0, 0, 15, 7263, 7265), + (7265, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 15, 7264, 10262), + (7266, 6333, 6333, 6333, 6333, 6, 64, 13714, 3, 600, 15, 6333, 13920), + (7267, -1, -1, 795, 795, 7, 81, -1, 0, 0, 15, 5891, 7268), + (7268, -1, -1, 795, 795, 9, 83, -1, 0, 0, 15, 7267, 7269), + (7269, -1, -1, 795, 795, 12, 85, -1, 0, 0, 15, 7268, 10265), + (7270, -1, -1, 790, 790, 6, 81, -1, 0, 0, 15, 5324, 7271), + (7271, -1, -1, 790, 790, 6, 82, -1, 0, 0, 15, 7270, 7272), + (7272, -1, -1, 790, 790, 6, 83, -1, 0, 0, 15, 7271, 7273), + (7273, -1, -1, 790, 790, 6, 84, -1, 0, 0, 15, 7272, 7274), + (7274, -1, -1, 790, 790, 6, 85, -1, 0, 0, 15, 7273, 12950), + (7275, 1239, 1239, 1239, 1239, 12, 85, 13735, 6, 600, 15, 5868, 13251), + (7276, 773, -1, 773, 773, 7, 81, 13726, 5, 1800, 15, 5856, 7277), + (7277, 773, -1, 773, 773, 9, 83, 13727, 5, 1800, 15, 7276, 7278), + (7278, 773, -1, 773, 773, 12, 85, 13728, 5, 1800, 15, 7277, 10564), + (7279, 6552, 6552, 6552, 6552, 5, 75, -1, 0, 0, 15, 6253, 7280), + (7280, 6552, 6552, 6552, 6552, 6, 77, -1, 0, 0, 15, 7279, 7281), + (7281, 6552, 6552, 6552, 6552, 6, 79, -1, 0, 0, 15, 7280, 7282), + (7282, 6552, 6552, 6552, 6552, 7, 81, -1, 0, 0, 15, 7281, 7283), + (7283, 6552, 6552, 6552, 6552, 9, 83, -1, 0, 0, 15, 7282, -1), + (7284, -1, -1, 781, 781, 8, 82, -1, 0, 0, 15, 5850, 13763), + (7285, 1242, 1242, 1242, 1242, 7, 81, 13723, 9, 1320, 15, 5859, 7286), + (7286, 1242, 1242, 1242, 1242, 9, 83, 13724, 9, 1320, 15, 7285, 7287), + (7287, 1242, 1242, 1242, 1242, 12, 85, 13725, 9, 1320, 15, 7286, 10271), + (7288, 4894, 4894, 4894, 4894, 6, 81, 13732, 7, 2160, 15, 6354, 7289), + (7289, 4894, 4894, 4894, 4894, 6, 82, 13733, 7, 2160, 15, 7288, 7290), + (7290, 4894, 4894, 4894, 4894, 6, 83, 13734, 7, 2160, 15, 7289, 13247), + (7291, 4931, 4931, 4931, 4931, 7, 81, 13729, 4, 600, 15, 6056, 7292), + (7292, 4931, 4931, 4931, 4931, 7, 83, 13730, 4, 600, 15, 7291, 7293), + (7293, 4931, 4931, 4931, 4931, 7, 85, 13731, 4, 600, 15, 7292, 10274), + (7294, 4935, 4935, 4935, 4935, 7, 76, 13722, 14, 300, 15, 4935, 10277), + (7295, 4934, 4934, 4934, 4934, 7, 76, 13721, 13, 300, 15, 4934, 10278), + (7296, 517, 517, 517, 517, 5, 73, 13718, 12, 600, 15, 1444, 7297), + (7297, 517, 517, 517, 517, 5, 74, 13719, 12, 600, 15, 7296, 7298), + (7298, 517, 517, 517, 517, 5, 75, 13720, 12, 600, 15, 7297, 10279), + (7299, 1383, 1383, 1383, 1383, 12, 85, 16000, 6, 300, 15, 5789, 10014), + (7300, 1195, 1195, 1195, 1195, 9, 85, 16001, 13, 2160, 15, 5790, 10015), + (7301, 131, 131, 131, 131, 8, 82, 16002, 4, 900, 15, 5793, 7302), + (7302, 131, 131, 131, 131, 9, 83, 16003, 4, 900, 15, 7301, 7303), + (7303, 131, 131, 131, 131, 10, 84, 16004, 4, 900, 15, 7302, 10016), + (7304, 1192, 1192, 1192, 1192, 8, 82, 16005, 12, 1320, 15, 5796, 7305), + (7305, 1192, 1192, 1192, 1192, 9, 83, 16006, 12, 1320, 15, 7304, 7306), + (7306, 1192, 1192, 1192, 1192, 10, 84, 16007, 12, 1320, 15, 7305, 10019), + (7307, 746, 746, 746, 746, 9, 83, 16008, 10, 2160, 15, 5802, 7308), + (7308, 746, 746, 746, 746, 10, 84, 16009, 10, 2160, 15, 7307, 7309), + (7309, 746, 746, 746, 746, 12, 85, 16010, 10, 2160, 15, 7308, 10022), + (7310, 1459, 1459, 1459, 1459, 7, 81, 16011, 11, 1800, 15, 5805, 7311), + (7311, 1459, 1459, 1459, 1459, 9, 83, 16012, 11, 1800, 15, 7310, 7312), + (7312, 1459, 1459, 1459, 1459, 12, 85, 16013, 11, 1800, 15, 7311, -1), + (7313, -1, -1, 6436, 6436, 6, 78, -1, 0, 0, 15, 6438, 7314), + (7314, -1, -1, 6436, 6436, 6, 80, -1, 0, 0, 15, 7313, 7315), + (7315, -1, -1, 6436, 6436, 8, 82, -1, 0, 0, 15, 7314, -1), + (7316, -1, -1, 468, 468, 2, 72, -1, 0, 0, 15, 6440, 7317), + (7317, -1, -1, 468, 468, 2, 74, -1, 0, 0, 15, 7316, 17288), + (7318, -1, -1, 6601, 6601, 6, 77, -1, 0, 0, 15, 6605, 7319), + (7319, -1, -1, 6601, 6601, 6, 78, -1, 0, 0, 15, 7318, 7320), + (7320, -1, -1, 6601, 6601, 6, 79, -1, 0, 0, 15, 7319, 7321), + (7321, -1, -1, 6601, 6601, 6, 80, -1, 0, 0, 15, 7320, 7322), + (7322, -1, -1, 6601, 6601, 6, 81, -1, 0, 0, 15, 7321, 10025), + (7323, -1, -1, 7100, 7100, 6, 81, -1, 0, 0, 15, 7102, 7324), + (7324, -1, -1, 7100, 7100, 6, 82, -1, 0, 0, 15, 7323, 7325), + (7325, -1, -1, 7100, 7100, 6, 83, -1, 0, 0, 15, 7324, 8427), + (7326, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7105, 7327), + (7327, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7326, 7328), + (7328, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7327, 10750), + (7329, 534, 534, 534, 534, 7, 81, 16021, 4, 2160, 15, 5971, 7330), + (7330, 534, 534, 534, 534, 9, 83, 16022, 4, 2160, 15, 7329, 7331), + (7331, 534, 534, 534, 534, 12, 85, 16023, 4, 2160, 15, 7330, 10047), + (7332, 5095, 5095, 5095, 5095, 7, 81, 16024, 10, 900, 15, 5977, 7333), + (7333, 5095, 5095, 5095, 5095, 9, 83, 16025, 10, 900, 15, 7332, 7334), + (7334, 5095, 5095, 5095, 5095, 12, 85, 16026, 10, 900, 15, 7333, 10640), + (7335, 5984, 5984, 5984, 5984, 12, 85, 16027, 2, 30, 15, 5984, 7710), + (7336, -1, -1, 6395, 6395, 7, 81, -1, 0, 0, 15, 6397, 7337), + (7337, -1, -1, 6395, 6395, 7, 82, -1, 0, 0, 15, 7336, 7338), + (7338, -1, -1, 6395, 6395, 7, 83, -1, 0, 0, 15, 7337, 10050), + (7339, 188, 188, 188, 188, 9, 78, 16020, 2, 30, 14, 5044, 7662), + (7340, 7850, 7850, 7850, 7850, 8, 81, 16028, 39, 4320, 0, 7865, 10618), + (7341, 5007, 5007, 5007, 5007, 9, 81, 16047, 8, 2160, 15, 6427, 7342), + (7342, 5007, 5007, 5007, 5007, 9, 83, 16048, 8, 2160, 15, 7341, 7343), + (7343, 5007, 5007, 5007, 5007, 9, 85, 16049, 8, 2160, 15, 7342, 10061), + (7344, 545, 545, 545, 545, 7, 81, 16038, 3, 900, 15, 6002, 7345), + (7345, 545, 545, 545, 545, 9, 83, 16039, 3, 900, 15, 7344, 7346), + (7346, 545, 545, 545, 545, 12, 85, 16040, 3, 900, 15, 7345, 10758), + (7347, 1345, 1345, 1345, 1345, 8, 82, 16041, 6, 900, 15, 6010, 7348), + (7348, 1345, 1345, 1345, 1345, 9, 83, 16042, 6, 900, 15, 7347, 7349), + (7349, 1345, 1345, 1345, 1345, 10, 84, 16043, 6, 900, 15, 7348, 10740), + (7350, 6370, 6370, 6370, 6370, 6, 81, 16044, 7, 600, 15, 6372, 7351), + (7351, 6370, 6370, 6370, 6370, 6, 82, 16045, 7, 600, 15, 7350, 7352), + (7352, 6370, 6370, 6370, 6370, 6, 83, 16046, 7, 600, 15, 7351, 14112), + (7353, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 6013, 7354), + (7354, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 7353, 7355), + (7355, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 7354, -1), + (7356, -1, -1, 5248, 5248, 7, 81, -1, 0, 0, 15, 6016, 7357), + (7357, -1, -1, 5248, 5248, 9, 83, -1, 0, 0, 15, 7356, 7358), + (7358, -1, -1, 5248, 5248, 12, 85, -1, 0, 0, 15, 7357, 16170), + (7359, -1, -1, 644, 644, 7, 79, -1, 0, 0, 15, 6019, 7360), + (7360, -1, -1, 644, 644, 9, 81, -1, 0, 0, 15, 7359, 7361), + (7361, -1, -1, 644, 644, 12, 83, -1, 0, 0, 15, 7360, 13092), + (7362, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 871, 7363), + (7363, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7362, 7364), + (7364, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7363, 7365), + (7365, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7364, 7366), + (7366, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7365, 10748), + (7367, 872, 872, 872, 872, 3, 70, 16032, 5, 180, 15, 874, 7368), + (7368, 872, 872, 872, 872, 6, 70, 16033, 5, 180, 15, 7367, 7369), + (7369, 872, 872, 872, 872, 9, 70, 16034, 5, 180, 15, 7368, 10772), + (7370, 875, 875, 875, 875, 3, 70, 16035, 5, 180, 15, 877, 7371), + (7371, 875, 875, 875, 875, 6, 73, 16036, 5, 180, 15, 7370, 7372), + (7372, 875, 875, 875, 875, 9, 75, 16037, 5, 180, 15, 7371, 10775), + (7373, -1, -1, 6546, 6546, 0, 81, -1, 0, 0, 15, 6571, 7374), + (7374, -1, -1, 6546, 6546, 0, 82, -1, 0, 0, 15, 7373, 7375), + (7375, -1, -1, 6546, 6546, 0, 83, -1, 0, 0, 15, 7374, 7376), + (7376, -1, -1, 6546, 6546, 0, 84, -1, 0, 0, 15, 7375, 7377), + (7377, -1, -1, 6546, 6546, 0, 85, -1, 0, 0, 15, 7376, 13122), + (7378, -1, -1, 1608, 1608, 3, 71, -1, 0, 0, 15, 4991, 7379), + (7379, -1, -1, 1608, 1608, 6, 73, -1, 0, 0, 15, 7378, 7380), + (7380, -1, -1, 1608, 1608, 9, 75, -1, 0, 0, 15, 7379, 7381), + (7381, -1, -1, 1608, 1608, 6, 76, -1, 0, 0, 15, 7380, 7382), + (7382, -1, -1, 1608, 1608, 6, 78, -1, 0, 0, 15, 7381, 7383), + (7383, -1, -1, 1608, 1608, 6, 80, -1, 0, 0, 15, 7382, 10064), + (7384, -1, -1, 5085, 5085, 6, 81, -1, 0, 0, 15, 6408, 7385), + (7385, -1, -1, 5085, 5085, 6, 83, -1, 0, 0, 15, 7384, 7386), + (7386, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 15, 7385, 10383), + (7387, 6508, 6508, 6508, 6508, 7, 79, 16059, 38, 600, 15, 6510, 7388), + (7388, 6508, 6508, 6508, 6508, 7, 81, 16060, 38, 600, 15, 7387, 7389), + (7389, 6508, 6508, 6508, 6508, 7, 83, 16061, 38, 600, 15, 7388, 10078), + (7390, -1, -1, 589, 589, 7, 81, -1, 0, 0, 15, 6065, 7391), + (7391, -1, -1, 589, 589, 7, 83, -1, 0, 0, 15, 7390, 7392), + (7392, -1, -1, 589, 589, 7, 85, -1, 0, 0, 15, 7391, 7707), + (7393, -1, -1, 1313, 1313, 7, 81, -1, 0, 0, 15, 6071, 7394), + (7394, -1, -1, 1313, 1313, 7, 81, -1, 0, 0, 15, 7393, 7395), + (7395, -1, -1, 1313, 1313, 8, 82, -1, 0, 0, 15, 7394, 7396), + (7396, -1, -1, 1313, 1313, 9, 83, -1, 0, 0, 15, 7395, 7397), + (7397, -1, -1, 1313, 1313, 10, 84, -1, 0, 0, 15, 7396, 7398), + (7398, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 15, 7397, 10081), + (7399, -1, -1, 210, 210, 8, 82, -1, 0, 0, 15, 6074, 7400), + (7400, -1, -1, 210, 210, 9, 83, -1, 0, 0, 15, 7399, 7401), + (7401, -1, -1, 210, 210, 10, 84, -1, 0, 0, 15, 7400, 15172), + (7402, -1, -1, 895, 895, 7, 81, -1, 0, 0, 15, 6079, 7403), + (7403, -1, -1, 895, 895, 8, 82, -1, 0, 0, 15, 7402, 7404), + (7404, -1, -1, 895, 895, 9, 83, -1, 0, 0, 15, 7403, 7405), + (7405, -1, -1, 895, 895, 10, 84, -1, 0, 0, 15, 7404, 7406), + (7406, -1, -1, 895, 895, 12, 85, -1, 0, 0, 15, 7405, 10906), + (7407, -1, -1, 7407, 7407, 12, 85, 0, 0, 0, 16, -1, -1), + (7408, 1498, 1498, 1498, 1498, 7, 81, 16075, 12, 1320, 15, 5821, 7409), + (7409, 1498, 1498, 1498, 1498, 9, 83, 16076, 12, 1320, 15, 7408, 7410), + (7410, 1498, 1498, 1498, 1498, 12, 85, 16077, 12, 1320, 15, 7409, 10090), + (7411, 757, -1, 757, 757, 7, 81, 16078, 6, 1800, 15, 5824, 7412), + (7412, 757, -1, 757, 757, 9, 83, 16079, 6, 1800, 15, 7411, 7413), + (7413, 757, -1, 757, 757, 12, 85, 16080, 6, 1800, 15, 7412, 12658), + (7414, 1495, 1495, 1495, 1495, 7, 81, 16081, 30, 900, 15, 5828, 7415), + (7415, 1495, 1495, 1495, 1495, 9, 83, 16082, 30, 900, 15, 7414, 7416), + (7416, 1495, 1495, 1495, 1495, 12, 85, 16083, 30, 900, 15, 7415, 10093), + (7417, 548, 548, 548, 548, 8, 82, 16084, 5, 900, 15, 5831, 7418), + (7418, 548, 548, 548, 548, 9, 83, 16085, 5, 900, 15, 7417, 7419), + (7419, 548, 548, 548, 548, 10, 84, 16086, 5, 900, 15, 7418, 10096), + (7420, 5105, 5105, 5105, 5105, 12, 85, 16087, 11, 600, 15, 5832, 10509), + (7421, 6232, 6232, 6232, 6232, 12, 85, 16091, 18, 900, 15, 6232, -1), + (7422, 6561, 6561, 6561, 6561, 7, 81, 16088, 32, 30, 15, 6280, 7423), + (7423, 6561, 6561, 6561, 6561, 7, 81, 16089, 32, 30, 15, 7422, 7424), + (7424, 6561, 6561, 6561, 6561, 7, 81, 16090, 32, 30, 15, 7423, 10099), + (7425, 510, 510, 510, 510, 3, 66, 16072, 37, 240, 15, 512, 7426), + (7426, 510, 510, 510, 510, 3, 68, 16073, 37, 240, 15, 7425, 7427), + (7427, 510, 510, 510, 510, 3, 70, 16074, 37, 240, 15, 7426, 10102), + (7428, 6533, 6533, 6533, 6533, 10, 84, 13785, 15, 600, 15, 6200, 10139), + (7429, 6534, 6534, 6534, 6534, 9, 83, 13777, 16, 900, 15, 6201, 13524), + (7430, 1116, 1116, 1116, 1116, 7, 81, 13762, 4, 2160, 15, 5701, 7431), + (7431, 1116, 1116, 1116, 1116, 9, 83, 13763, 4, 2160, 15, 7430, 7432), + (7432, 1116, 1116, 1116, 1116, 12, 85, 13764, 4, 2160, 15, 7431, 10140), + (7433, 592, 592, 592, 592, 5, 81, 13765, 2, 18, 15, 5706, 7434), + (7434, 592, 592, 592, 592, 5, 82, 13766, 2, 18, 15, 7433, 7435), + (7435, 592, 592, 592, 592, 5, 83, 13767, 2, 18, 15, 7434, 7436), + (7436, 592, 592, 592, 592, 5, 84, 13768, 2, 18, 15, 7435, 7437), + (7437, 592, 592, 592, 592, 5, 85, 13769, 2, 18, 15, 7436, 12749), + (7438, 5298, 5298, 5298, 5298, 9, 83, 13770, 32, 1800, 15, 5709, 7439), + (7439, 5298, 5298, 5298, 5298, 10, 84, 13771, 32, 1800, 15, 7438, 7440), + (7440, 5298, 5298, 5298, 5298, 12, 85, 13772, 32, 1800, 15, 7439, 10143), + (7441, 1598, -1, 1598, 1598, 7, 81, 13773, 6, 900, 15, 5712, 7442), + (7442, 1598, -1, 1598, 1598, 9, 83, 13774, 6, 900, 15, 7441, 7443), + (7443, 1598, -1, 1598, 1598, 12, 85, 13775, 6, 900, 15, 7442, 10146), + (7444, 5020, 5020, 5020, 5020, 9, 82, 13776, 9, 300, 15, 5716, 10149), + (7445, 1110, 1110, 1110, 1110, 6, 78, 13778, 3, 2160, 15, 6402, 7446), + (7446, 1110, 1110, 1110, 1110, 6, 80, 13779, 3, 2160, 15, 7445, 7447), + (7447, 1110, 1110, 1110, 1110, 6, 81, 13780, 3, 2160, 15, 7446, 10150), + (7448, -1, -1, 6337, 6337, 6, 79, -1, 0, 0, 15, 6339, 7449), + (7449, -1, -1, 6337, 6337, 6, 81, -1, 0, 0, 15, 7448, 7450), + (7450, -1, -1, 6337, 6337, 6, 83, -1, 0, 0, 15, 7449, 10153), + (7451, -1, -1, 6340, 6340, 6, 79, -1, 0, 0, 15, 6342, 7452), + (7452, -1, -1, 6340, 6340, 6, 81, -1, 0, 0, 15, 7451, 7453), + (7453, -1, -1, 6340, 6340, 6, 83, -1, 0, 0, 15, 7452, 16306), + (7454, 5017, 5017, 5017, 5017, 3, 76, 13759, 8, 600, 15, 5019, 7455), + (7455, 5017, 5017, 5017, 5017, 6, 78, 13760, 8, 600, 15, 7454, 7456), + (7456, 5017, 5017, 5017, 5017, 9, 80, 13761, 8, 600, 15, 7455, 10156), + (7457, 1569, 1569, 1569, 1569, 7, 82, 13756, 5, 1800, 15, 5715, 7458), + (7458, 1569, 1569, 1569, 1569, 7, 83, 13757, 5, 1800, 15, 7457, 7459), + (7459, 1569, 1569, 1569, 1569, 7, 85, 13758, 5, 1800, 15, 7458, 10159), + (7460, 1327, 1327, 1327, 1327, 7, 81, 13792, 10, 900, 15, 6100, 7461), + (7461, 1327, 1327, 1327, 1327, 9, 83, 13793, 10, 900, 15, 7460, 7462), + (7462, 1327, 1327, 1327, 1327, 12, 85, 13794, 10, 900, 15, 7461, 10187), + (7463, 1520, 1520, 1520, 1520, 9, 75, 13801, 11, 900, 15, 6451, 7464), + (7464, 1520, 1520, 1520, 1520, 9, 75, 13802, 11, 900, 15, 7463, 7465), + (7465, 1520, 1520, 1520, 1520, 9, 75, 13803, 11, 900, 15, 7464, 10190), + (7466, 146, 146, 146, 146, 8, 82, 13796, 2, 180, 15, 6102, 7691), + (7467, 5109, 5109, 5109, 5109, 9, 82, 13800, 0, 1, 15, 6448, 13016), + (7468, 153, 153, 153, 153, 12, 85, 13795, 3, 2160, 15, 6101, 10193), + (7469, 528, 528, 528, 528, 7, 81, 13797, 5, 720, 15, 6105, 7470), + (7470, 528, 528, 528, 528, 9, 83, 13798, 5, 720, 15, 7469, 7471), + (7471, 528, 528, 528, 528, 12, 85, 13799, 5, 720, 15, 7470, 10194), + (7472, 5251, 5251, 5251, 5251, 7, 81, 13786, 13, 900, 15, 6094, 7473), + (7473, 5251, 5251, 5251, 5251, 9, 83, 13787, 13, 900, 15, 7472, 7474), + (7474, 5251, 5251, 5251, 5251, 12, 85, 13788, 13, 900, 15, 7473, 10197), + (7475, 513, 513, 513, 513, 7, 81, 13789, 4, 120, 15, 6097, 7476), + (7476, 513, 513, 513, 513, 9, 83, 13790, 4, 120, 15, 7475, 7477), + (7477, 513, 513, 513, 513, 12, 85, 13791, 4, 120, 15, 7476, -1), + (7478, -1, -1, 6538, 6538, 12, 85, -1, 0, 0, 15, 6211, 15421), + (7479, 1119, 1119, 1119, 1119, 7, 83, 13805, 8, 900, 15, 5736, 7480), + (7480, 1119, 1119, 1119, 1119, 8, 84, 13806, 8, 900, 15, 7479, 7481), + (7481, 1119, 1119, 1119, 1119, 9, 85, 13807, 8, 900, 15, 7480, 10297), + (7482, 723, 723, 723, 723, 7, 81, 13808, 6, 30, 15, 5737, 10300), + (7483, 5015, 5015, 5015, 5015, 12, 85, 13809, 9, 900, 15, 5741, 10301), + (7484, 289, 289, 289, 289, 12, 85, 13810, 3, 300, 15, 5742, -1), + (7485, 291, 291, 291, 291, 9, 83, 13811, 5, 900, 15, 5745, 7486), + (7486, 291, 291, 291, 291, 10, 84, 13812, 5, 900, 15, 7485, 7487), + (7487, 291, 291, 291, 291, 12, 85, 13813, 5, 900, 15, 7486, 10302), + (7488, 6218, 6218, 6218, 6218, 7, 81, 13814, 0, 1, 15, 6218, 14272), + (7489, -1, -1, 724, 724, 7, 81, -1, 0, 0, 15, 5733, 7490), + (7490, -1, -1, 724, 724, 8, 82, -1, 0, 0, 15, 7489, 7491), + (7491, -1, -1, 724, 724, 9, 83, -1, 0, 0, 15, 7490, 7492), + (7492, -1, -1, 724, 724, 10, 84, -1, 0, 0, 15, 7491, 7493), + (7493, -1, -1, 724, 724, 12, 85, -1, 0, 0, 15, 7492, 16890), + (7494, -1, -1, 729, 729, 7, 81, -1, 0, 0, 15, 5740, 7495), + (7495, -1, -1, 729, 729, 8, 82, -1, 0, 0, 15, 7494, 7496), + (7496, -1, -1, 729, 729, 9, 83, -1, 0, 0, 15, 7495, 10305), + (7497, 6380, 6380, 6380, 6380, 6, 83, 13815, 39, 120, 15, 6382, 7498), + (7498, 6380, 6380, 6380, 6380, 6, 84, 13816, 39, 120, 15, 7497, 7499), + (7499, 6380, 6380, 6380, 6380, 6, 85, 13817, 39, 120, 15, 7498, 10308), + (7500, -1, -1, 4699, 4699, 5, 61, -1, 0, 0, 15, 6540, 10788), + (7501, -1, -1, 125, 125, 6, 81, -1, 0, 0, 15, 5523, 7502), + (7502, -1, -1, 125, 125, 7, 82, -1, 0, 0, 15, 7501, 7503), + (7503, -1, -1, 125, 125, 8, 83, -1, 0, 0, 15, 7502, 7504), + (7504, -1, -1, 125, 125, 9, 84, -1, 0, 0, 15, 7503, 7505), + (7505, -1, -1, 125, 125, 10, 85, -1, 0, 0, 15, 7504, 12396), + (7506, -1, -1, 122, 122, 6, 81, -1, 0, 0, 15, 5528, 7507), + (7507, -1, -1, 122, 122, 7, 82, -1, 0, 0, 15, 7506, 7508), + (7508, -1, -1, 122, 122, 8, 83, -1, 0, 0, 15, 7507, 7509), + (7509, -1, -1, 122, 122, 9, 84, -1, 0, 0, 15, 7508, 7510), + (7510, -1, -1, 122, 122, 10, 85, -1, 0, 0, 15, 7509, 12401), + (7511, -1, -1, 1026, 1026, 5, 81, -1, 0, 0, 15, 6527, 7512), + (7512, -1, -1, 1026, 1026, 5, 82, -1, 0, 0, 15, 7511, 7513), + (7513, -1, -1, 1026, 1026, 5, 83, -1, 0, 0, 15, 7512, 7514), + (7514, -1, -1, 1026, 1026, 5, 84, -1, 0, 0, 15, 7513, 7515), + (7515, -1, -1, 1026, 1026, 5, 85, -1, 0, 0, 15, 7514, 7886), + (7516, -1, -1, 1006, 1006, 5, 71, -1, 0, 0, 15, 1010, 7517), + (7517, -1, -1, 1006, 1006, 5, 72, -1, 0, 0, 15, 7516, 7518), + (7518, -1, -1, 1006, 1006, 5, 73, -1, 0, 0, 15, 7517, 7519), + (7519, -1, -1, 1006, 1006, 5, 74, -1, 0, 0, 15, 7518, 7520), + (7520, -1, -1, 1006, 1006, 5, 75, -1, 0, 0, 15, 7519, 7837), + (7521, -1, -1, 1056, 1056, 5, 81, -1, 0, 0, 15, 6435, 7522), + (7522, -1, -1, 1056, 1056, 5, 82, -1, 0, 0, 15, 7521, 7523), + (7523, -1, -1, 1056, 1056, 5, 83, -1, 0, 0, 15, 7522, 7524), + (7524, -1, -1, 1056, 1056, 5, 84, -1, 0, 0, 15, 7523, 7525), + (7525, -1, -1, 1056, 1056, 5, 85, -1, 0, 0, 15, 7524, 16414), + (7526, -1, -1, 6119, 6119, 6, 81, -1, 0, 0, 15, 6123, 7527), + (7527, -1, -1, 6119, 6119, 6, 82, -1, 0, 0, 15, 7526, 7528), + (7528, -1, -1, 6119, 6119, 6, 83, -1, 0, 0, 15, 7527, 7529), + (7529, -1, -1, 6119, 6119, 6, 84, -1, 0, 0, 15, 7528, 7530), + (7530, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 15, 7529, 12406), + (7534, -1, -1, 65, 661, 3, 81, -1, 0, 0, 15, 6394, 7535), + (7535, -1, -1, 65, 661, 3, 82, -1, 0, 0, 15, 7534, 7536), + (7536, -1, -1, 65, 661, 3, 83, -1, 0, 0, 15, 7535, 7537), + (7537, -1, -1, 65, 661, 3, 84, -1, 0, 0, 15, 7536, 7538), + (7538, -1, -1, 65, 661, 3, 85, -1, 0, 0, 15, 7537, 7904), + (7539, -1, -1, 1021, 1021, 5, 80, -1, 0, 0, 16, 6522, 7540), + (7540, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7539, 7683), + (7541, -1, -1, 107, 107, 2, 60, -1, 0, 0, 15, 109, 7542), + (7542, -1, -1, 107, 107, 4, 60, -1, 0, 0, 15, 7541, 7543), + (7543, -1, -1, 107, 107, 6, 60, -1, 0, 0, 15, 7542, -1), + (7544, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 6520, 7545), + (7545, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 7544, 7546), + (7546, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 7545, -1), + (7547, -1, -1, 418, 418, 5, 76, -1, 0, 0, 15, 4682, 7548), + (7548, -1, -1, 418, 418, 5, 77, -1, 0, 0, 15, 7547, 7549), + (7549, -1, -1, 418, 418, 5, 78, -1, 0, 0, 15, 7548, 7550), + (7550, -1, -1, 418, 418, 5, 79, -1, 0, 0, 15, 7549, 7551), + (7551, -1, -1, 418, 418, 5, 80, -1, 0, 0, 15, 7550, -1), + (7553, -1, -1, 1071, 1071, 6, 80, -1, 0, 0, 16, 4764, 7681), + (7554, -1, -1, 1486, 1486, 7, 81, -1, 0, 0, 15, 5533, 7555), + (7555, -1, -1, 1486, 1486, 8, 82, -1, 0, 0, 15, 7554, 7556), + (7556, -1, -1, 1486, 1486, 9, 83, -1, 0, 0, 15, 7555, 7557), + (7557, -1, -1, 1486, 1486, 10, 84, -1, 0, 0, 15, 7556, 7558), + (7558, -1, -1, 1486, 1486, 12, 85, -1, 0, 0, 15, 7557, 7722), + (7559, -1, -1, 599, 599, 9, 83, -1, 0, 0, 15, 5536, 7560), + (7560, -1, -1, 599, 599, 10, 84, -1, 0, 0, 15, 7559, 7561), + (7561, -1, -1, 599, 599, 12, 85, -1, 0, 0, 15, 7560, 13026), + (7562, -1, -1, 1041, 1041, 7, 81, -1, 0, 0, 15, 5544, 7563), + (7563, -1, -1, 1041, 1041, 9, 83, -1, 0, 0, 15, 7562, 7564), + (7564, -1, -1, 1041, 1041, 12, 85, -1, 0, 0, 15, 7563, 12697), + (7565, -1, -1, 119, 119, 7, 81, -1, 0, 0, 15, 5556, 7566), + (7566, -1, -1, 119, 119, 9, 83, -1, 0, 0, 15, 7565, 7567), + (7567, -1, -1, 119, 119, 12, 85, -1, 0, 0, 15, 7566, 6023), + (7568, -1, -1, 1592, 1592, 7, 81, -1, 0, 0, 15, 5561, 7569), + (7569, -1, -1, 1592, 1592, 8, 82, -1, 0, 0, 15, 7568, 7570), + (7570, -1, -1, 1592, 1592, 9, 83, -1, 0, 0, 15, 7569, 7571), + (7571, -1, -1, 1592, 1592, 10, 84, -1, 0, 0, 15, 7570, 7572), + (7572, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 15, 7571, 12439), + (7573, -1, -1, 4739, 4739, 7, 81, -1, 0, 0, 15, 5564, 7574), + (7574, -1, -1, 4739, 4739, 9, 83, -1, 0, 0, 15, 7573, 7575), + (7575, -1, -1, 4739, 4739, 12, 85, -1, 0, 0, 15, 7574, -1), + (7576, -1, -1, 1072, 1072, 7, 81, -1, 0, 0, 15, 5570, 7577), + (7577, -1, -1, 1072, 1072, 8, 82, -1, 0, 0, 15, 7576, 7578), + (7578, -1, -1, 1072, 1072, 9, 83, -1, 0, 0, 15, 7577, 7579), + (7579, -1, -1, 1072, 1072, 10, 84, -1, 0, 0, 15, 7578, 7580), + (7580, -1, -1, 1072, 1072, 12, 85, -1, 0, 0, 15, 7579, 12444), + (7581, -1, -1, 1210, 1213, 7, 81, -1, 0, 0, 15, 5579, 7582), + (7582, -1, -1, 1210, 1213, 9, 83, -1, 0, 0, 15, 7581, 7583), + (7583, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 15, 7582, 8344), + (7584, -1, -1, 98, 98, 7, 81, -1, 0, 0, 15, 5588, 7585), + (7585, -1, -1, 98, 98, 9, 83, -1, 0, 0, 15, 7584, 7586), + (7586, -1, -1, 98, 98, 12, 85, -1, 0, 0, 15, 7585, 11061), + (7587, -1, -1, 1186, 1186, 7, 81, -1, 0, 0, 15, 5591, 7588), + (7588, -1, -1, 1186, 1186, 9, 83, -1, 0, 0, 15, 7587, 7589), + (7589, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 15, 7588, 7692), + (7590, -1, -1, 80, 80, 7, 81, -1, 0, 0, 15, 5594, 7591), + (7591, -1, -1, 80, 80, 9, 83, -1, 0, 0, 15, 7590, 7592), + (7592, -1, -1, 80, 80, 12, 85, -1, 0, 0, 15, 7591, 12452), + (7593, -1, -1, 658, 658, 5, 81, -1, 0, 0, 15, 5627, 7594), + (7594, -1, -1, 658, 658, 5, 82, -1, 0, 0, 15, 7593, 7595), + (7595, -1, -1, 658, 658, 5, 83, -1, 0, 0, 15, 7594, 7596), + (7596, -1, -1, 658, 658, 5, 84, -1, 0, 0, 15, 7595, 7597), + (7597, -1, -1, 658, 658, 5, 85, -1, 0, 0, 15, 7596, 12455), + (7598, -1, -1, 98, 738, 7, 81, -1, 0, 0, 15, 5630, 7599), + (7599, -1, -1, 98, 738, 9, 83, -1, 0, 0, 15, 7598, 7600), + (7600, -1, -1, 98, 738, 12, 85, -1, 0, 0, 15, 7599, 13924), + (7601, -1, -1, 6051, 6051, 3, 81, -1, 0, 0, 15, 6053, 7602), + (7602, -1, -1, 6051, 6051, 3, 83, -1, 0, 0, 15, 7601, 7603), + (7603, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 15, 7602, 10604), + (7604, -1, -1, 683, 683, 5, 80, -1, 0, 0, 15, 6081, 7605), + (7605, -1, -1, 683, 683, 5, 80, -1, 0, 0, 15, 7604, 12694), + (7606, 6537, 6537, 6537, 6537, 7, 81, 13821, 30, 900, 15, 6208, 7607), + (7607, 6537, 6537, 6537, 6537, 8, 82, 13822, 30, 900, 15, 7606, 7608), + (7608, 6537, 6537, 6537, 6537, 9, 83, 13823, 30, 900, 15, 7607, 12460), + (7609, 6539, 6539, 6539, 6539, 6, 76, 13824, 18, 1800, 15, 6214, 7610), + (7610, 6539, 6539, 6539, 6539, 6, 79, 13825, 18, 1800, 15, 7609, 7611), + (7611, 6539, 6539, 6539, 6539, 6, 82, 13826, 18, 1800, 15, 7610, 12942), + (7612, -1, -1, 270, 665, 2, 66, -1, 0, 0, 15, 670, 7613), + (7613, -1, -1, 270, 665, 2, 67, -1, 0, 0, 15, 7612, 7614), + (7614, -1, -1, 270, 665, 2, 68, -1, 0, 0, 15, 7613, -1), + (7615, -1, -1, 6346, 6346, 6, 79, -1, 0, 0, 15, 6348, 7616), + (7616, -1, -1, 6346, 6346, 6, 81, -1, 0, 0, 15, 7615, 7617), + (7617, -1, -1, 6346, 6346, 6, 83, -1, 0, 0, 15, 7616, 15397), + (7618, -1, -1, 6349, 6349, 6, 79, -1, 0, 0, 15, 6351, 7619), + (7619, -1, -1, 6349, 6349, 6, 81, -1, 0, 0, 15, 7618, 7620), + (7620, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 15, 7619, 11053), + (7621, -1, -1, 1435, 4773, 9, 81, -1, 0, 0, 15, 6517, 13090), + (7622, -1, -1, 446, 735, 8, 81, -1, 0, 0, 15, 7065, 7623), + (7623, -1, -1, 446, 735, 8, 82, -1, 0, 0, 15, 7622, 7624), + (7624, -1, -1, 446, 735, 8, 83, -1, 0, 0, 15, 7623, 10473), + (7625, -1, -1, 735, 735, 8, 81, -1, 0, 0, 15, 7068, 7626), + (7626, -1, -1, 735, 735, 8, 82, -1, 0, 0, 15, 7625, 7627), + (7627, -1, -1, 735, 735, 8, 83, -1, 0, 0, 15, 7626, 10632), + (7628, -1, -1, 807, 807, 5, 81, -1, 0, 0, 15, 5924, 7629), + (7629, -1, -1, 807, 807, 5, 83, -1, 0, 0, 15, 7628, 7630), + (7630, -1, -1, 807, 807, 5, 85, -1, 0, 0, 15, 7629, 12685), + (7631, -1, -1, 255, 255, 7, 81, -1, 0, 0, 15, 5597, 7632), + (7632, -1, -1, 255, 255, 9, 83, -1, 0, 0, 15, 7631, 7633), + (7633, -1, -1, 255, 255, 12, 85, -1, 0, 0, 15, 7632, 17441), + (7634, -1, -1, 815, 815, 9, 83, -1, 0, 0, 15, 5913, 7635), + (7635, -1, -1, 815, 815, 10, 84, -1, 0, 0, 15, 7634, 7636), + (7636, -1, -1, 815, 815, 12, 85, -1, 0, 0, 15, 7635, 15441), + (7637, -1, -1, 1616, 1616, 5, 83, -1, 0, 0, 15, 6007, 7638), + (7638, -1, -1, 1616, 1616, 5, 84, -1, 0, 0, 15, 7637, 7639), + (7639, -1, -1, 1616, 1616, 5, 85, -1, 0, 0, 15, 7638, -1), + (7640, -1, -1, 686, 686, 5, 60, -1, 0, 0, 15, 690, 12438), + (7641, -1, -1, 625, 625, 3, 76, -1, 0, 0, 15, 4735, 7642), + (7642, -1, -1, 625, 625, 3, 78, -1, 0, 0, 15, 7641, 7643), + (7643, -1, -1, 625, 625, 3, 80, -1, 0, 0, 15, 7642, -1), + (7644, -1, -1, 6375, 6375, 6, 81, -1, 0, 0, 15, 6377, 7645), + (7645, -1, -1, 6375, 6375, 6, 82, -1, 0, 0, 15, 7644, 7646), + (7646, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 15, 7645, 7663), + (7647, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 694, 7648), + (7648, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 7647, 7649), + (7649, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 7648, 7670), + (7650, -1, -1, 1044, 1044, 7, 81, -1, 0, 0, 15, 5547, 7651), + (7651, -1, -1, 1044, 1044, 9, 83, -1, 0, 0, 15, 7650, 7652), + (7652, -1, -1, 1044, 1044, 12, 85, -1, 0, 0, 15, 7651, 13074), + (7653, -1, -1, 1047, 1047, 7, 81, -1, 0, 0, 15, 5550, 7654), + (7654, -1, -1, 1047, 1047, 9, 83, -1, 0, 0, 15, 7653, 7655), + (7655, -1, -1, 1047, 1047, 12, 85, -1, 0, 0, 15, 7654, 13077), + (7656, -1, -1, 1050, 1050, 7, 81, -1, 0, 0, 15, 5553, 7657), + (7657, -1, -1, 1050, 1050, 9, 83, -1, 0, 0, 15, 7656, 7658), + (7658, -1, -1, 1050, 1050, 12, 85, -1, 0, 0, 15, 7657, 13023), + (7659, -1, -1, 754, 754, 3, 70, -1, 0, 0, 15, 756, 7660), + (7660, -1, -1, 754, 754, 6, 70, -1, 0, 0, 15, 7659, 7661), + (7661, -1, -1, 754, 754, 9, 70, -1, 0, 0, 15, 7660, -1), + (7662, 188, 188, 188, 188, 9, 83, 16431, 2, 30, 15, 7339, 10647), + (7663, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 15, 7646, 10084), + (7664, -1, -1, 7664, 7664, 2, 73, -1, 0, 0, 15, -1, 7665), + (7665, -1, -1, 7664, 7664, 2, 74, -1, 0, 0, 15, 7664, 7666), + (7666, -1, -1, 7664, 7664, 2, 75, -1, 0, 0, 15, 7665, 7667), + (7667, -1, -1, 7664, 7664, 2, 76, -1, 0, 0, 15, 7666, 7668), + (7668, -1, -1, 7664, 7664, 2, 77, -1, 0, 0, 15, 7667, 10105), + (7669, 7669, 7669, 7669, 7669, 3, 81, 13838, 35, 5, 15, -1, -1), + (7670, -1, -1, 692, 692, 7, 75, -1, 0, 0, 16, 7649, 7671), + (7671, -1, -1, 692, 692, 9, 80, -1, 0, 0, 16, 7670, 7672), + (7672, -1, -1, 692, 692, 12, 85, -1, 0, 0, 16, 7671, 12767), + (7673, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 859, 7674), + (7674, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7673, 7675), + (7675, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7674, 7676), + (7676, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7675, 7677), + (7677, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7676, 10688), + (7678, -1, -1, 852, 852, 9, 81, -1, 0, 0, 16, 5502, 7679), + (7679, -1, -1, 852, 852, 10, 83, -1, 0, 0, 16, 7678, 7680), + (7680, -1, -1, 852, 852, 12, 85, -1, 0, 0, 16, 7679, 12576), + (7681, -1, -1, 1071, 1071, 6, 80, -1, 0, 0, 16, 7553, -1), + (7682, -1, -1, 4861, 4861, 12, 85, -1, 0, 0, 16, 7216, 12757), + (7683, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7540, 7684), + (7684, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7683, 7685), + (7685, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7684, 13894), + (7686, -1, -1, 4844, 4844, 5, 81, -1, 0, 0, 16, 7126, 7687), + (7687, -1, -1, 4844, 4844, 5, 83, -1, 0, 0, 16, 7686, 7688), + (7688, -1, -1, 4844, 4844, 5, 85, -1, 0, 0, 16, 7687, -1), + (7689, 7689, 7689, 7689, 7689, 12, 85, 21820, 94, 180, 16, -1, -1), + (7690, -1, -1, 7690, 7690, 12, 85, -1, 0, 0, 16, -1, -1), + (7691, 146, 146, 146, 146, 8, 85, 16862, 2, 180, 16, 7466, 13256), + (7692, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7589, 7693), + (7693, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7692, 7694), + (7694, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7693, 12564), + (7695, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, -1, 7696), + (7696, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, 7695, 7697), + (7697, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, 7696, -1), + (7698, 7698, 7698, 7698, 7698, 6, 85, 21763, 17, 6, 16, -1, -1), + (7699, -1, -1, 7699, 7699, 12, 85, 0, 0, 0, 16, -1, -1), + (7700, -1, -1, 255, 255, 7, 81, -1, 0, 0, 16, -1, 7701), + (7701, -1, -1, 255, 255, 9, 83, -1, 0, 0, 16, 7700, 7702), + (7702, -1, -1, 255, 255, 12, 85, -1, 0, 0, 16, 7701, 12610), + (7703, 7703, 7703, 7703, 7703, 12, 85, 21754, 16, 600, 16, -1, -1), + (7704, -1, -1, 8195, 8195, 5, 81, -1, 0, 0, 16, 8197, 7705), + (7705, -1, -1, 8195, 8195, 5, 83, -1, 0, 0, 16, 7704, 7706), + (7706, -1, -1, 8195, 8195, 5, 85, -1, 0, 0, 16, 7705, -1), + (7707, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7392, 7708), + (7708, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7707, 7709), + (7709, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7708, 13104), + (7710, 5984, 5984, 5984, 5984, 12, 85, 21679, 2, 30, 16, 7335, 7711), + (7711, 5984, 5984, 5984, 5984, 12, 85, 21680, 2, 30, 16, 7710, 10626), + (7712, 7712, 7712, 7712, 7712, 12, 85, 21682, 2, 30, 16, -1, 10646), + (7713, -1, -1, 634, 634, 12, 81, -1, 0, 0, 16, 5613, 7714), + (7714, -1, -1, 634, 634, 12, 83, -1, 0, 0, 16, 7713, 10778), + (7715, -1, -1, 7715, 7715, 5, 77, 0, 0, 0, 16, -1, 7716), + (7716, -1, -1, 7715, 7715, 5, 79, 0, 0, 0, 16, 7715, 7717), + (7717, -1, -1, 7715, 7715, 5, 81, 0, 0, 0, 16, 7716, 14314), + (7718, -1, -1, 574, 574, 3, 81, -1, 0, 0, 16, 576, -1), + (7722, -1, -1, 1486, 1486, 7, 86, -1, 0, 0, 17, 7558, 7723), + (7723, -1, -1, 1486, 1486, 8, 87, -1, 0, 0, 17, 7722, 7724), + (7724, -1, -1, 1486, 1486, 9, 88, -1, 0, 0, 17, 7723, 7725), + (7725, -1, -1, 1486, 1486, 10, 89, -1, 0, 0, 17, 7724, 7726), + (7726, -1, -1, 1486, 1486, 12, 90, -1, 0, 0, 17, 7725, 7842), + (7732, 7732, 7732, 7732, 7732, 0, 60, 7732, 34, 3600, 14, -1, -1), + (7733, -1, -1, 288, 288, 6, 65, -1, 0, 0, 14, -1, -1), + (7734, 7734, 7734, 7734, 7734, 0, 61, 7734, 34, 28800, 14, -1, -1), + (7735, 7735, 7735, 7735, 7735, 0, 51, 7731, 32, 3600, 9, -1, -1), + (7736, 7736, 7736, 7736, 7736, 0, 52, 7865, 32, 10800, 9, -1, -1), + (7737, 7737, 7737, 7737, 7737, 0, 53, 7733, 32, 10800, 9, -1, -1), + (7738, 7738, 7738, 7738, 7738, 0, 54, 7990, 32, 21600, 9, -1, -1), + (7739, 7739, 7739, 7739, 7739, 0, 65, 13064, 36, 3600, 0, -1, -1), + (7740, 7740, 7740, 7740, 7740, 0, 66, 13065, 36, 28800, 0, -1, -1), + (7741, 7741, 7741, 7741, 7741, 0, 70, 21854, 50, 3600, 0, -1, -1), + (7742, 7742, 7742, 7742, 7742, 0, 71, 21855, 50, 28800, 0, -1, -1), + (7743, -1, -1, 7743, 7743, 5, 61, -1, 0, 0, 16, -1, 7744), + (7744, -1, -1, 7743, 7743, 7, 61, -1, 0, 0, 16, 7743, 7745), + (7745, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 16, 7744, 10717), + (7746, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, -1, 7763), + (7747, 7747, 7747, 7747, 7747, 9, 85, 21790, 32, 180, 16, -1, -1), + (7748, -1, -1, 7748, 7748, 3, 81, -1, 0, 0, 16, -1, 7749), + (7749, -1, -1, 7748, 7748, 6, 83, -1, 0, 0, 16, 7748, 7750), + (7750, -1, -1, 7748, 7748, 9, 85, -1, 0, 0, 16, 7749, -1), + (7751, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, -1, 7752), + (7752, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, 7751, 7753), + (7753, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, 7752, 14132), + (7754, 7754, 7754, 7754, 7754, 9, 85, 21803, 0, 1, 16, -1, -1), + (7755, 7755, 7755, 7755, 7755, 9, 81, 21804, 53, 900, 16, -1, 15782), + (7756, 7756, 7756, 7756, 7756, 12, 85, 21805, 54, 120, 16, -1, -1), + (7757, -1, -1, 7757, 7757, 5, 85, -1, 0, 0, 16, -1, 7758), + (7758, -1, -1, 7757, 7757, 7, 85, -1, 0, 0, 16, 7757, 7759), + (7759, -1, -1, 7757, 7757, 9, 85, -1, 0, 0, 16, 7758, 12587), + (7760, -1, -1, 7760, 7760, 5, 85, -1, 0, 0, 16, -1, 7761), + (7761, -1, -1, 7760, 7760, 7, 85, -1, 0, 0, 16, 7760, 7762), + (7762, -1, -1, 7760, 7760, 9, 85, -1, 0, 0, 16, 7761, -1), + (7763, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, 7746, 7764), + (7764, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, 7763, -1), + (7765, -1, -1, 7765, 7765, 5, 86, 0, 0, 0, 17, -1, 7766), + (7766, -1, -1, 7765, 7765, 7, 87, 0, 0, 0, 17, 7765, 7767), + (7767, -1, -1, 7765, 7765, 9, 88, 0, 0, 0, 17, 7766, 7768), + (7768, -1, -1, 7765, 7765, 12, 89, 0, 0, 0, 17, 7767, 7769), + (7770, 131, 131, 131, 131, 9, 86, 27655, 4, 900, 17, 10018, 7771), + (7771, 131, 131, 131, 131, 12, 88, 27656, 4, 900, 17, 7770, 7772), + (7772, 131, 131, 131, 131, 15, 90, 27657, 4, 900, 17, 7771, 13374), + (7773, 7951, 7951, 7951, 7951, 9, 86, 27658, 61, 900, 17, 10040, 7774), + (7774, 7951, 7951, 7951, 7951, 9, 88, 27659, 61, 900, 17, 7773, 7775), + (7775, 7951, 7951, 7951, 7951, 9, 90, 27660, 61, 900, 17, 7774, 13377), + (7800, 7800, 7800, 7800, 7800, 0, 1, 13531, 39, 4320, 0, -1, 7801), + (7801, 7800, 7800, 7800, 7800, 0, 6, 13532, 39, 4320, 0, 7800, 7802), + (7802, 7800, 7800, 7800, 7800, 0, 11, 13533, 39, 4320, 0, 7801, 7803), + (7803, 7800, 7800, 7800, 7800, 0, 16, 13534, 39, 4320, 0, 7802, 7804), + (7804, 7800, 7800, 7800, 7800, 0, 21, 13535, 39, 4320, 0, 7803, 7805), + (7805, 7800, 7800, 7800, 7800, 0, 26, 13536, 39, 4320, 0, 7804, 7806), + (7806, 7800, 7800, 7800, 7800, 0, 31, 13537, 39, 4320, 0, 7805, 7807), + (7807, 7800, 7800, 7800, 7800, 0, 36, 13538, 39, 4320, 0, 7806, 7808), + (7808, 7800, 7800, 7800, 7800, 0, 41, 13539, 39, 4320, 0, 7807, 7809), + (7809, 7800, 7800, 7800, 7800, 0, 46, 13540, 39, 4320, 0, 7808, 7810), + (7810, 7800, 7800, 7800, 7800, 3, 51, 13541, 39, 4320, 0, 7809, 7811), + (7811, 7800, 7800, 7800, 7800, 4, 56, 13542, 39, 4320, 0, 7810, 7812), + (7812, 7800, 7800, 7800, 7800, 5, 61, 13543, 39, 4320, 0, 7811, 7813), + (7813, 7800, 7800, 7800, 7800, 6, 66, 13544, 39, 4320, 0, 7812, 7814), + (7814, 7800, 7800, 7800, 7800, 7, 71, 13545, 39, 4320, 0, 7813, 7815), + (7815, 7800, 7800, 7800, 7800, 8, 76, 13562, 39, 4320, 0, 7814, 7816), + (7816, 7800, 7800, 7800, 7800, 8, 81, 16062, 39, 4320, 0, 7815, 7817), + (7817, 7800, 7800, 7800, 7800, 9, 83, 16855, 39, 4320, 0, 7816, 10786), + (7818, -1, -1, 7818, 7818, 12, 85, 21750, 0, 0, 16, -1, 13029), + (7819, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 9514, 7820), + (7820, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7819, 7821), + (7821, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7820, 7881), + (7822, -1, -1, 7822, 7822, 5, 77, 0, 0, 0, 16, -1, 7823), + (7823, -1, -1, 7822, 7822, 5, 79, 0, 0, 0, 16, 7822, 7824), + (7824, -1, -1, 7822, 7822, 5, 81, 0, 0, 0, 16, 7823, 7825), + (7825, -1, -1, 7822, 7822, 5, 83, 0, 0, 0, 16, 7824, 7826), + (7826, -1, -1, 7822, 7822, 5, 85, 0, 0, 0, 16, 7825, 14328), + (7827, -1, -1, 7827, 7827, 5, 81, 0, 0, 0, 16, -1, -1), + (7828, -1, -1, 7828, 7828, 5, 79, 0, 0, 0, 16, -1, 7829), + (7829, -1, -1, 7828, 7828, 5, 81, 0, 0, 0, 16, 7828, 7830), + (7830, -1, -1, 7828, 7828, 5, 83, 0, 0, 0, 16, 7829, -1), + (7832, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, -1, 7833), + (7833, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7832, 7834), + (7834, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7833, 7835), + (7835, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7834, 7836), + (7836, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7835, -1), + (7837, -1, -1, 1006, 1006, 5, 76, -1, 0, 0, 17, 7520, 7838), + (7838, -1, -1, 1006, 1006, 5, 77, -1, 0, 0, 17, 7837, 7839), + (7839, -1, -1, 1006, 1006, 5, 78, -1, 0, 0, 17, 7838, 7840), + (7840, -1, -1, 1006, 1006, 5, 79, -1, 0, 0, 17, 7839, 7841), + (7841, -1, -1, 1006, 1006, 5, 80, -1, 0, 0, 17, 7840, 8470), + (7842, -1, -1, 1486, 1486, 12, 91, -1, 0, 0, 18, 7726, 7843), + (7843, -1, -1, 1486, 1486, 12, 92, -1, 0, 0, 18, 7842, 7844), + (7844, -1, -1, 1486, 1486, 12, 93, -1, 0, 0, 18, 7843, 7845), + (7850, 7850, 7850, 7850, 7850, 0, 1, 13546, 39, 4320, 0, -1, 7851), + (7851, 7850, 7850, 7850, 7850, 0, 6, 13547, 39, 4320, 0, 7850, 7852), + (7852, 7850, 7850, 7850, 7850, 0, 11, 13548, 39, 4320, 0, 7851, 7853), + (7853, 7850, 7850, 7850, 7850, 0, 16, 13549, 39, 4320, 0, 7852, 7854), + (7854, 7850, 7850, 7850, 7850, 0, 21, 13550, 39, 4320, 0, 7853, 7855), + (7855, 7850, 7850, 7850, 7850, 0, 26, 13551, 39, 4320, 0, 7854, 7856), + (7856, 7850, 7850, 7850, 7850, 0, 31, 13552, 39, 4320, 0, 7855, 7857), + (7857, 7850, 7850, 7850, 7850, 0, 36, 13553, 39, 4320, 0, 7856, 7858), + (7858, 7850, 7850, 7850, 7850, 0, 41, 13554, 39, 4320, 0, 7857, 7859), + (7859, 7850, 7850, 7850, 7850, 0, 46, 13555, 39, 4320, 0, 7858, 7860), + (7860, 7850, 7850, 7850, 7850, 3, 51, 13556, 39, 4320, 0, 7859, 7861), + (7861, 7850, 7850, 7850, 7850, 4, 56, 13557, 39, 4320, 0, 7860, 7862), + (7862, 7850, 7850, 7850, 7850, 5, 61, 13558, 39, 4320, 0, 7861, 7863), + (7863, 7850, 7850, 7850, 7850, 6, 66, 13559, 39, 4320, 0, 7862, 7864), + (7864, 7850, 7850, 7850, 7850, 7, 71, 13560, 39, 4320, 0, 7863, 7865), + (7865, 7850, 7850, 7850, 7850, 8, 76, 13561, 39, 4320, 0, 7864, 7340), + (7869, 7869, 7869, 7869, 7869, 6, 73, 16175, 60, 30, 15, -1, 7870), + (7870, 7869, 7869, 7869, 7869, 6, 77, 16176, 60, 30, 15, 7869, 7871), + (7871, 7869, 7869, 7869, 7869, 6, 81, 16177, 60, 30, 15, 7870, -1), + (7872, 7872, 7872, 7872, 7872, 6, 76, 16178, 41, 600, 15, -1, 7873), + (7873, 7872, 7872, 7872, 7872, 6, 81, 16179, 41, 600, 15, 7872, 7874), + (7874, 7872, 7872, 7872, 7872, 6, 85, 16180, 41, 600, 15, 7873, 10127), + (7875, 7875, 7875, 7875, 7875, 6, 76, 16181, 42, 600, 15, -1, 7876), + (7876, 7875, 7875, 7875, 7875, 6, 81, 16182, 42, 600, 15, 7875, 7877), + (7877, 7875, 7875, 7875, 7875, 6, 85, 16183, 42, 600, 15, 7876, 7878), + (7878, 7875, 7875, 7875, 7875, 6, 85, 16859, 42, 600, 16, 7877, 7879), + (7879, 7875, 7875, 7875, 7875, 6, 85, 21823, 42, 600, 16, 7878, 7880), + (7880, 7875, 7875, 7875, 7875, 6, 85, 21824, 42, 600, 16, 7879, 13816), + (7881, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7821, 7882), + (7882, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7881, 7883), + (7883, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7882, 13187), + (7884, -1, -1, 7884, 7884, 9, 85, -1, 0, 0, 16, -1, 12689), + (7885, -1, -1, 7885, 7885, 9, 85, -1, 0, 0, 16, -1, 12690), + (7886, -1, -1, 1026, 1026, 5, 85, -1, 0, 0, 17, 7515, 7887), + (7887, -1, -1, 1026, 1026, 5, 86, -1, 0, 0, 17, 7886, 7888), + (7888, -1, -1, 1026, 1026, 5, 87, -1, 0, 0, 17, 7887, 7889), + (7889, -1, -1, 1026, 1026, 5, 88, -1, 0, 0, 17, 7888, 7890), + (7890, -1, -1, 1026, 1026, 5, 89, -1, 0, 0, 17, 7889, 8430), + (7900, -1, -1, 7900, 7900, 4, 60, -1, 0, 0, 15, -1, 7901), + (7901, -1, -1, 7900, 7900, 4, 65, -1, 0, 0, 15, 7900, 7902), + (7902, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 15, 7901, 10268), + (7903, 7903, 7903, 7903, 7903, 6, 75, 16188, 60, 30, 15, -1, 12976), + (7904, -1, -1, 65, 661, 3, 85, -1, 0, 0, 17, 7538, 7905), + (7905, -1, -1, 65, 661, 3, 86, -1, 0, 0, 17, 7904, 7906), + (7906, -1, -1, 65, 661, 3, 87, -1, 0, 0, 17, 7905, 7907), + (7907, -1, -1, 65, 661, 3, 88, -1, 0, 0, 17, 7906, 7908), + (7908, -1, -1, 65, 661, 3, 89, -1, 0, 0, 17, 7907, 8435), + (7940, -1, -1, 7940, 7940, 6, 60, -1, 0, 0, 15, -1, 7941), + (7941, -1, -1, 7940, 7940, 6, 65, -1, 0, 0, 15, 7940, 7942), + (7942, -1, -1, 7940, 7940, 6, 70, -1, 0, 0, 15, 7941, 10030), + (7943, 7943, 7943, 7943, 7943, 6, 79, 16192, 60, 8640, 15, -1, 7993), + (7944, 7944, 7944, 7944, 7944, 7, 79, 16193, 34, 1800, 15, -1, -1), + (7945, -1, -1, 7945, 7945, 6, 81, -1, 0, 0, 15, -1, 7946), + (7946, -1, -1, 7945, 7945, 6, 82, -1, 0, 0, 15, 7945, 7947), + (7947, -1, -1, 7945, 7945, 6, 83, -1, 0, 0, 15, 7946, 10033), + (7948, -1, -1, 7948, 7948, 6, 75, -1, 0, 0, 15, -1, 7949), + (7949, -1, -1, 7948, 7948, 6, 80, -1, 0, 0, 15, 7948, 7950), + (7950, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 15, 7949, 10035), + (7951, 7951, 7951, 7951, 7951, 6, 82, 16200, 61, 900, 15, -1, 7952), + (7952, 7951, 7951, 7951, 7951, 6, 83, 16201, 61, 900, 15, 7951, 7953), + (7953, 7951, 7951, 7951, 7951, 6, 84, 16202, 61, 900, 15, 7952, 10038), + (7980, -1, -1, 7980, 7980, 6, 70, -1, 0, 0, 15, -1, 7981), + (7981, -1, -1, 7980, 7980, 6, 73, -1, 0, 0, 15, 7980, 7982), + (7982, -1, -1, 7980, 7980, 6, 76, -1, 0, 0, 15, 7981, -1), + (7983, -1, -1, 7983, 7983, 6, 70, -1, 0, 0, 15, -1, 7984), + (7984, -1, -1, 7983, 7983, 6, 73, -1, 0, 0, 15, 7983, 7985), + (7985, -1, -1, 7983, 7983, 6, 76, -1, 0, 0, 15, 7984, 10110), + (7986, 7986, 7986, 7986, 7986, 9, 75, 16203, 11, 600, 15, -1, 7987), + (7987, 7986, 7986, 7986, 7986, 12, 80, 16204, 11, 600, 15, 7986, 7988), + (7988, 7986, 7986, 7986, 7986, 12, 85, 16205, 11, 600, 15, 7987, 10510), + (7989, -1, -1, 7989, 7989, 6, 75, -1, 0, 0, 15, -1, 7990), + (7990, -1, -1, 7989, 7989, 6, 80, -1, 0, 0, 15, 7989, 7991), + (7991, -1, -1, 7989, 7989, 6, 85, -1, 0, 0, 15, 7990, 7992), + (7992, -1, -1, 7989, 7989, 6, 85, -1, 0, 0, 15, 7991, 13415), + (7993, 7943, 7943, 7943, 7943, 6, 85, 23601, 60, 8640, 17, 7943, -1), + (7994, -1, -1, 462, 462, 2, 81, -1, 0, 0, 17, 464, 7995), + (7995, -1, -1, 462, 462, 2, 85, -1, 0, 0, 17, 7994, -1), + (8000, -1, -1, 8001, 8001, 0, 50, -1, 0, 0, 8, -1, -1), + (8030, 8030, 8030, 8030, 8030, 6, 70, 16206, 60, 900, 15, -1, -1), + (8031, -1, -1, 8031, 8031, 6, 75, -1, 0, 0, 15, -1, 8032), + (8032, -1, -1, 8031, 8031, 6, 77, -1, 0, 0, 15, 8031, 8033), + (8033, -1, -1, 8031, 8031, 6, 79, -1, 0, 0, 15, 8032, 10282), + (8034, 8034, 8034, 8034, 8034, 6, 81, 16207, 59, 600, 15, -1, -1), + (8035, -1, -1, 8035, 8035, 6, 73, -1, 0, 0, 15, -1, 8036), + (8036, -1, -1, 8035, 8035, 6, 75, -1, 0, 0, 15, 8035, 8037), + (8037, -1, -1, 8035, 8035, 6, 77, -1, 0, 0, 15, 8036, 10285), + (8038, 8038, 8038, 8038, 8038, 6, 81, 16210, 56, 12, 15, -1, 17541), + (8039, 8039, 8039, 8039, 8039, 6, 83, 16211, 58, 7, 15, -1, 15462), + (8040, -1, -1, 8040, 8040, 4, 65, -1, 0, 0, 15, -1, 8041), + (8041, -1, -1, 8040, 8040, 4, 70, -1, 0, 0, 15, 8040, 8042), + (8042, -1, -1, 8040, 8040, 4, 75, -1, 0, 0, 15, 8041, 8043), + (8043, -1, -1, 8040, 8040, 4, 78, -1, 0, 0, 15, 8042, 8313), + (8059, -1, -1, 8232, 8232, 4, 78, -1, 0, 0, 15, 8234, 8261), + (8060, 8060, 8060, 8060, 8060, 7, 75, 16238, 41, 1800, 15, -1, 8061), + (8061, 8060, 8060, 8060, 8060, 7, 78, 16239, 41, 1800, 15, 8060, 8062), + (8062, 8060, 8060, 8060, 8060, 7, 81, 16240, 41, 1800, 15, 8061, 10237), + (8063, 8063, 8063, 8063, 8063, 7, 75, 16241, 41, 1800, 15, -1, 8064), + (8064, 8063, 8063, 8063, 8063, 7, 78, 16242, 41, 1800, 15, 8063, 8065), + (8065, 8063, 8063, 8063, 8063, 7, 81, 16243, 41, 1800, 15, 8064, 10240), + (8066, 8066, 8066, 8066, 8066, 7, 75, 16244, 41, 1800, 15, -1, 8067), + (8067, 8066, 8066, 8066, 8066, 7, 78, 16245, 41, 1800, 15, 8066, 8068), + (8068, 8066, 8066, 8066, 8066, 7, 81, 16246, 41, 1800, 15, 8067, 10243), + (8069, -1, -1, 8069, 8069, 5, 71, -1, 0, 0, 15, -1, 8070), + (8070, -1, -1, 8069, 8069, 5, 72, -1, 0, 0, 15, 8069, 8071), + (8071, -1, -1, 8069, 8069, 5, 73, -1, 0, 0, 15, 8070, 15606), + (8072, 8072, 8072, 8072, 8072, 7, 75, 16221, 37, 20, 15, -1, 8073), + (8073, 8072, 8072, 8072, 8072, 7, 75, 16222, 37, 20, 15, 8072, 8074), + (8074, 8072, 8072, 8072, 8072, 7, 75, 16223, 37, 20, 15, 8073, 10246), + (8075, 8075, 8075, 8075, 8075, 7, 81, 16224, 42, 6, 15, -1, -1), + (8076, -1, -1, 8076, 8076, 5, 77, -1, 0, 0, 15, -1, 8077), + (8077, -1, -1, 8076, 8076, 5, 78, -1, 0, 0, 15, 8076, 8078), + (8078, -1, -1, 8076, 8076, 5, 79, -1, 0, 0, 15, 8077, 8079), + (8079, -1, -1, 8076, 8076, 5, 80, -1, 0, 0, 15, 8078, 8080), + (8080, -1, -1, 8076, 8076, 5, 81, -1, 0, 0, 15, 8079, 8081), + (8081, -1, -1, 8076, 8076, 5, 82, -1, 0, 0, 15, 8080, -1), + (8082, -1, -1, 8082, 8082, 3, 65, -1, 0, 0, 15, -1, 8083), + (8083, -1, -1, 8082, 8082, 3, 67, -1, 0, 0, 15, 8082, 8084), + (8084, -1, -1, 8082, 8082, 3, 69, -1, 0, 0, 15, 8083, 10249), + (8190, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, -1, 8191), + (8191, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, 8190, 8192), + (8192, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, 8191, -1), + (8193, -1, -1, 8193, 8193, 7, 75, -1, 0, 0, 15, -1, -1), + (8194, 8194, 8194, 8194, 8194, 7, 75, 16226, 47, 12, 15, -1, -1), + (8195, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, -1, 8196), + (8196, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, 8195, 8197), + (8197, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, 8196, 7704), + (8198, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, -1, 8199), + (8199, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, 8198, 8200), + (8200, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, 8199, -1), + (8201, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, -1, 8202), + (8202, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, 8201, 8203), + (8203, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, 8202, 16475), + (8204, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, -1, 8205), + (8205, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, 8204, 8206), + (8206, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, 8205, 1656), + (8207, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, -1, 8208), + (8208, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, 8207, 8209), + (8209, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, 8208, 1659), + (8210, -1, -1, 8210, 8210, 5, 65, -1, 0, 0, 15, -1, 8211), + (8211, -1, -1, 8210, 8210, 5, 70, -1, 0, 0, 15, 8210, 8212), + (8212, -1, -1, 8210, 8210, 5, 75, -1, 0, 0, 15, 8211, 8213), + (8213, -1, -1, 8210, 8210, 5, 80, -1, 0, 0, 15, 8212, 8214), + (8214, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 15, 8213, 1651), + (8215, -1, -1, 8215, 8215, 5, 65, -1, 0, 0, 15, -1, 8216), + (8216, -1, -1, 8215, 8215, 5, 70, -1, 0, 0, 15, 8215, 8217), + (8217, -1, -1, 8215, 8215, 5, 75, -1, 0, 0, 15, 8216, 8218), + (8218, -1, -1, 8215, 8215, 5, 80, -1, 0, 0, 15, 8217, 8219), + (8219, -1, -1, 8215, 8215, 5, 85, -1, 0, 0, 15, 8218, 12559), + (8220, 8220, 8220, 8220, 8220, 5, 76, 16227, 39, 15, 15, -1, -1), + (8221, 8221, 8221, 8221, 8221, 9, 81, 16228, 45, 600, 15, -1, -1), + (8222, 8222, 8222, 8222, 8222, 7, 75, 16229, 70, 10, 15, -1, -1), + (8223, -1, -1, 86, 86, 8, 59, -1, 0, 0, 15, 6259, 8262), + (8224, -1, -1, 8224, 8224, 5, 75, -1, 0, 0, 15, -1, 8225), + (8225, -1, -1, 8224, 8224, 5, 80, -1, 0, 0, 15, 8224, 8226), + (8226, -1, -1, 8224, 8224, 5, 85, -1, 0, 0, 15, 8225, 8421), + (8227, 8227, 8227, 8227, 8227, 3, 55, 16233, 71, 10, 15, -1, 12810), + (8228, -1, -1, 8228, 8228, 5, 75, -1, 0, 0, 15, -1, 8229), + (8229, -1, -1, 8228, 8228, 5, 80, -1, 0, 0, 15, 8228, 8230), + (8230, -1, -1, 8228, 8228, 5, 85, -1, 0, 0, 15, 8229, -1), + (8231, 8231, -1, 8231, 8231, 3, 55, 16234, 38, 60, 15, -1, -1), + (8232, -1, -1, 8232, 8232, 4, 65, -1, 0, 0, 15, -1, 8233), + (8233, -1, -1, 8232, 8232, 4, 70, -1, 0, 0, 15, 8232, 8234), + (8234, -1, -1, 8232, 8232, 4, 75, -1, 0, 0, 15, 8233, 8059), + (8235, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, -1, 8236), + (8236, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8235, 8237), + (8237, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8236, 8238), + (8238, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8237, 8239), + (8239, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8238, 8304), + (8240, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, -1, 8241), + (8241, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8240, 8242), + (8242, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8241, 8243), + (8243, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8242, 8244), + (8244, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8243, 10781), + (8245, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, -1, 8246), + (8246, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8245, 8247), + (8247, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8246, 8248), + (8248, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8247, 8249), + (8249, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8248, 8422), + (8250, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, -1, 8251), + (8251, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8250, 8252), + (8252, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8251, 8253), + (8253, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8252, 8254), + (8254, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8253, 13046), + (8255, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, -1, 8256), + (8256, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8255, 8257), + (8257, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8256, 8258), + (8258, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8257, 8259), + (8259, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8258, 12411), + (8260, 8005, 8005, 8005, 8005, 9, 85, 20185, 45, 600, 16, -1, -1), + (8261, -1, -1, 8232, 8232, 4, 80, -1, 0, 0, 16, 8059, 15772), + (8262, -1, -1, 86, 86, 8, 65, -1, 0, 0, 16, 8223, -1), + (8263, -1, -1, 8263, 8263, 5, 81, -1, 0, 0, 16, -1, 8264), + (8264, -1, -1, 8263, 8263, 5, 82, -1, 0, 0, 16, 8263, 8265), + (8265, -1, -1, 8263, 8263, 5, 83, -1, 0, 0, 16, 8264, 8266), + (8266, -1, -1, 8263, 8263, 5, 84, -1, 0, 0, 16, 8265, 8267), + (8267, -1, -1, 8263, 8263, 5, 85, -1, 0, 0, 16, 8266, 8351), + (8268, -1, -1, 8268, 8268, 5, 81, -1, 0, 0, 16, -1, 8269), + (8269, -1, -1, 8268, 8268, 5, 82, -1, 0, 0, 16, 8268, 8270), + (8270, -1, -1, 8268, 8268, 5, 83, -1, 0, 0, 16, 8269, 8271), + (8271, -1, -1, 8268, 8268, 5, 84, -1, 0, 0, 16, 8270, 8272), + (8272, -1, -1, 8268, 8268, 5, 85, -1, 0, 0, 16, 8271, 8361), + (8273, -1, -1, 8273, 8273, 5, 81, -1, 0, 0, 16, -1, 8274), + (8274, -1, -1, 8273, 8273, 5, 82, -1, 0, 0, 16, 8273, 8275), + (8275, -1, -1, 8273, 8273, 5, 83, -1, 0, 0, 16, 8274, 8276), + (8276, -1, -1, 8273, 8273, 5, 84, -1, 0, 0, 16, 8275, 8277), + (8277, -1, -1, 8273, 8273, 5, 85, -1, 0, 0, 16, 8276, 8371), + (8278, -1, -1, 8278, 8278, 5, 81, -1, 0, 0, 16, -1, 8279), + (8279, -1, -1, 8278, 8278, 5, 82, -1, 0, 0, 16, 8278, 8280), + (8280, -1, -1, 8278, 8278, 5, 83, -1, 0, 0, 16, 8279, 8281), + (8281, -1, -1, 8278, 8278, 5, 84, -1, 0, 0, 16, 8280, 8282), + (8282, -1, -1, 8278, 8278, 5, 85, -1, 0, 0, 16, 8281, 8381), + (8283, -1, -1, 8283, 8283, 5, 81, -1, 0, 0, 16, -1, 8284), + (8284, -1, -1, 8283, 8283, 5, 82, -1, 0, 0, 16, 8283, 8285), + (8285, -1, -1, 8283, 8283, 5, 83, -1, 0, 0, 16, 8284, 8286), + (8286, -1, -1, 8283, 8283, 5, 84, -1, 0, 0, 16, 8285, 8287), + (8287, -1, -1, 8283, 8283, 5, 85, -1, 0, 0, 16, 8286, 8391), + (8288, -1, -1, 8288, 8288, 5, 81, -1, 0, 0, 16, -1, 8289), + (8289, -1, -1, 8288, 8288, 5, 82, -1, 0, 0, 16, 8288, 8290), + (8290, -1, -1, 8288, 8288, 5, 83, -1, 0, 0, 16, 8289, 8291), + (8291, -1, -1, 8288, 8288, 5, 84, -1, 0, 0, 16, 8290, 8292), + (8292, -1, -1, 8288, 8288, 5, 85, -1, 0, 0, 16, 8291, 8401), + (8293, -1, -1, 8293, 8293, 5, 81, -1, 0, 0, 16, -1, 8294), + (8294, -1, -1, 8293, 8293, 5, 82, -1, 0, 0, 16, 8293, 8295), + (8295, -1, -1, 8293, 8293, 5, 83, -1, 0, 0, 16, 8294, 8296), + (8296, -1, -1, 8293, 8293, 5, 84, -1, 0, 0, 16, 8295, 8297), + (8297, -1, -1, 8293, 8293, 5, 85, -1, 0, 0, 16, 8296, 8411), + (8300, 8300, 8300, 8300, 8300, 5, 81, 21778, 8, 900, 16, -1, 8301), + (8301, 8300, 8300, 8300, 8300, 7, 83, 21779, 8, 900, 16, 8300, 8302), + (8302, 8300, 8300, 8300, 8300, 9, 85, 21780, 8, 900, 16, 8301, 15111), + (8303, 8303, 8303, 8303, 8303, 12, 85, 21773, 9, 1800, 16, -1, -1), + (8304, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8239, 8305), + (8305, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8304, 8306), + (8306, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8305, 8307), + (8307, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8306, 8308), + (8308, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8307, 13353), + (8309, 260, -1, 260, 260, 5, 81, 21687, 3, 2160, 16, 262, 8310), + (8310, 260, -1, 260, 260, 7, 83, 21688, 3, 2160, 16, 8309, 8311), + (8311, 260, -1, 260, 260, 9, 85, 21689, 3, 2160, 16, 8310, -1), + (8312, 8312, 8312, 8312, 8312, 12, 85, 21690, 2, 900, 16, -1, -1), + (8313, -1, -1, 8040, 8040, 4, 80, -1, 0, 0, 16, 8043, 15773), + (8314, -1, -1, 8314, 8314, 7, 85, -1, 0, 0, 16, -1, 8315), + (8315, -1, -1, 8314, 8314, 9, 85, -1, 0, 0, 16, 8314, 8316), + (8316, -1, -1, 8314, 8314, 12, 85, -1, 0, 0, 16, 8315, 13508), + (8317, -1, -1, 8317, 8317, 5, 85, -1, 0, 0, 16, -1, 8318), + (8318, -1, -1, 8317, 8317, 5, 85, -1, 0, 0, 16, 8317, -1), + (8319, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, -1, 8320), + (8320, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, 8319, 8321), + (8321, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, 8320, -1), + (8322, -1, -1, 8322, 8322, 5, 81, 0, 0, 0, 16, -1, 8323), + (8323, -1, -1, 8322, 8322, 7, 83, 0, 0, 0, 16, 8322, 8324), + (8324, -1, -1, 8322, 8322, 9, 85, 0, 0, 0, 16, 8323, 13199), + (8325, -1, -1, 8325, 8325, 7, 81, 0, 0, 0, 16, -1, 8326), + (8326, -1, -1, 8325, 8325, 9, 81, 0, 0, 0, 16, 8325, 8327), + (8327, -1, -1, 8325, 8325, 11, 81, 0, 0, 0, 16, 8326, 13219), + (8328, -1, -1, 244, 244, 12, 59, -1, 0, 0, 3, 246, -1), + (8329, -1, -1, 622, 622, 3, 71, -1, 0, 0, 16, 624, -1), + (8331, -1, -1, 8331, 8331, 9, 85, 0, 0, 0, 16, -1, -1), + (8332, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, -1, 8333), + (8333, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, 8332, 8334), + (8334, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, 8333, -1), + (8335, -1, -1, 8335, 8335, 5, 81, 0, 0, 0, 16, -1, 8336), + (8336, -1, -1, 8335, 8335, 5, 82, 0, 0, 0, 16, 8335, 8337), + (8337, -1, -1, 8335, 8335, 5, 83, 0, 0, 0, 16, 8336, 8338), + (8338, -1, -1, 8335, 8335, 5, 84, 0, 0, 0, 16, 8337, 8339), + (8339, -1, -1, 8335, 8335, 5, 85, 0, 0, 0, 16, 8338, -1), + (8341, 8341, 8341, 8341, 8341, 12, 85, 21829, 53, 450, 16, -1, -1), + (8342, 8342, 8342, 8342, 8342, 12, 85, 21843, 54, 240, 16, -1, 14729), + (8343, 167, 167, 167, 167, 10, 85, 21837, 14, 900, 16, 7249, 12955), + (8344, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 7583, 8345), + (8345, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 8344, 8346), + (8346, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 8345, 12526), + (8347, -1, -1, 8347, 8347, 7, 81, 0, 0, 0, 16, -1, 8348), + (8348, -1, -1, 8347, 8347, 9, 83, 0, 0, 0, 16, 8347, 8349), + (8349, -1, -1, 8347, 8347, 11, 85, 0, 0, 0, 16, 8348, -1), + (8350, -1, -1, 8350, 8350, 12, 85, 0, 0, 0, 16, -1, -1), + (8351, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8267, 8352), + (8352, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8351, 8353), + (8353, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8352, 8354), + (8354, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8353, 8355), + (8355, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8354, 8356), + (8356, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8355, 8357), + (8357, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8356, 8358), + (8358, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8357, 8359), + (8359, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8358, 8360), + (8360, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8359, 13933), + (8361, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8272, 8362), + (8362, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8361, 8363), + (8363, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8362, 8364), + (8364, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8363, 8365), + (8365, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8364, 8366), + (8366, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8365, 8367), + (8367, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8366, 8368), + (8368, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8367, 8369), + (8369, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8368, 8370), + (8370, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8369, 13943), + (8371, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8277, 8372), + (8372, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8371, 8373), + (8373, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8372, 8374), + (8374, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8373, 8375), + (8375, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8374, 8376), + (8376, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8375, 8377), + (8377, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8376, 8378), + (8378, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8377, 8379), + (8379, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8378, 8380), + (8380, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8379, 13953), + (8381, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8282, 8382), + (8382, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8381, 8383), + (8383, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8382, 8384), + (8384, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8383, 8385), + (8385, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8384, 8386), + (8386, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8385, 8387), + (8387, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8386, 8388), + (8388, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8387, 8389), + (8389, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8388, 8390), + (8390, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8389, 13963), + (8391, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8287, 8392), + (8392, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8391, 8393), + (8393, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8392, 8394), + (8394, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8393, 8395), + (8395, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8394, 8396), + (8396, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8395, 8397), + (8397, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8396, 8398), + (8398, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8397, 8399), + (8399, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8398, 8400), + (8400, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8399, 13973), + (8401, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8292, 8402), + (8402, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8401, 8403), + (8403, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8402, 8404), + (8404, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8403, 8405), + (8405, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8404, 8406), + (8406, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8405, 8407), + (8407, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8406, 8408), + (8408, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8407, 8409), + (8409, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8408, 8410), + (8410, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8409, 13983), + (8411, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8297, 8412), + (8412, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8411, 8413), + (8413, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8412, 8414), + (8414, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8413, 8415), + (8415, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8414, 8416), + (8416, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8415, 8417), + (8417, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8416, 8418), + (8418, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8417, 8419), + (8419, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8418, 8420), + (8420, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8419, 13993), + (8421, -1, -1, 8224, 8224, 5, 90, -1, 0, 0, 17, 8226, -1), + (8422, -1, -1, 8245, 8245, 6, 86, -1, 0, 0, 17, 8249, 8423), + (8423, -1, -1, 8245, 8245, 6, 87, -1, 0, 0, 17, 8422, 8424), + (8424, -1, -1, 8245, 8245, 6, 88, -1, 0, 0, 17, 8423, 8425), + (8425, -1, -1, 8245, 8245, 6, 89, -1, 0, 0, 17, 8424, 8426), + (8426, -1, -1, 8245, 8245, 6, 90, -1, 0, 0, 17, 8425, 13338), + (8427, -1, -1, 7100, 7100, 6, 85, -1, 0, 0, 17, 7325, 8428), + (8428, -1, -1, 7100, 7100, 6, 87, -1, 0, 0, 17, 8427, 8429), + (8429, -1, -1, 7100, 7100, 6, 89, -1, 0, 0, 17, 8428, -1), + (8430, -1, -1, 1026, 1026, 10, 91, -1, 0, 0, 18, 7890, 8431), + (8435, -1, -1, 65, 661, 8, 91, -1, 0, 0, 18, 7908, 8436), + (8440, -1, -1, 122, 122, 13, 91, -1, 0, 0, 18, 13089, 8441), + (8445, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 12637, 8446), + (8446, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8445, 8447), + (8447, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8446, 16419), + (8448, -1, -1, 6119, 6119, 8, 91, -1, 0, 0, 18, 12496, 8449), + (8463, -1, -1, 125, 125, 10, 91, -1, 0, 0, 18, 13084, 8464), + (8464, -1, -1, 125, 125, 11, 91, -1, 0, 0, 18, 8463, 8465), + (8470, -1, -1, 1006, 1006, 10, 91, -1, 0, 0, 18, 7841, 8471), + (9000, 9000, 9000, 9000, 9000, 0, 1, 16995, 49, 72000, 0, -1, -1), + (9001, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, -1, 9002), + (9002, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9001, 9003), + (9003, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9002, 9004), + (9004, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9003, 9005), + (9005, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9004, 9006), + (9006, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9005, 9007), + (9007, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9006, 9008), + (9008, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9007, 9009), + (9009, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9008, 9010), + (9010, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9009, -1), + (9011, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, -1, 9012), + (9012, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9011, 9013), + (9013, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9012, 9014), + (9014, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9013, 9015), + (9015, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9014, 9016), + (9016, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9015, 9017), + (9017, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9016, 9018), + (9018, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9017, 9019), + (9019, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9018, 9020), + (9020, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9019, -1), + (9021, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, -1, 9022), + (9022, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9021, 9023), + (9023, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9022, 9024), + (9024, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9023, 9025), + (9025, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9024, 9026), + (9026, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9025, 9027), + (9027, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9026, 9028), + (9028, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9027, 9029), + (9029, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9028, 9030), + (9030, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9029, -1), + (9031, 9031, 9031, 9031, 9031, 0, 1, 16601, 65, 72000, 0, -1, -1), + (9032, 9032, 9032, 9032, 9032, 0, 0, 21815, 51, 72000, 0, -1, -1), + (9033, -1, -1, 9033, 9033, 0, 1, -1, 0, 0, 0, -1, -1), + (9100, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, -1, 9101), + (9101, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9100, 9102), + (9102, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9101, 9103), + (9103, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9102, 9104), + (9104, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9103, 9105), + (9105, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9104, 9106), + (9106, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9105, 9107), + (9107, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9106, 9108), + (9108, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9107, -1), + (9109, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, -1, 9110), + (9110, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9109, 9111), + (9111, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9110, 9112), + (9112, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9111, 9113), + (9113, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9112, 9114), + (9114, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9113, 9115), + (9115, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9114, 9116), + (9116, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9115, 9117), + (9117, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9116, -1), + (9118, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, -1, 9119), + (9119, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9118, 9120), + (9120, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9119, 9121), + (9121, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9120, 9122), + (9122, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9121, 9123), + (9123, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9122, 9124), + (9124, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9123, 9125), + (9125, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9124, 9126), + (9126, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9125, -1), + (9127, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, -1, 9128), + (9128, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9127, 9129), + (9129, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9128, 9130), + (9130, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9129, 9131), + (9131, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9130, 9132), + (9132, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9131, 9133), + (9133, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9132, 9134), + (9134, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9133, 9135), + (9135, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9134, -1), + (9136, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, -1, 9137), + (9137, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9136, 9138), + (9138, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9137, 9139), + (9139, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9138, 9140), + (9140, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9139, 9141), + (9141, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9140, 9142), + (9142, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9141, 9143), + (9143, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9142, 9144), + (9144, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9143, -1), + (9145, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, -1, 9146), + (9146, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9145, 9147), + (9147, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9146, 9148), + (9148, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9147, 9149), + (9149, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9148, 9150), + (9150, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9149, 9151), + (9151, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9150, 9152), + (9152, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9151, 9153), + (9153, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9152, -1), + (9154, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, -1, 9155), + (9155, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9154, 9156), + (9156, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9155, 9157), + (9157, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9156, 9158), + (9158, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9157, 9159), + (9159, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9158, 9160), + (9160, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9159, 9161), + (9161, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9160, 9162), + (9162, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9161, -1), + (9163, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, -1, 9164), + (9164, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9163, 9165), + (9165, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9164, 9166), + (9166, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9165, 9167), + (9167, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9166, 9168), + (9168, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9167, 9169), + (9169, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9168, 9170), + (9170, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9169, 9171), + (9171, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9170, -1), + (9172, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, -1, 9173), + (9173, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9172, 9174), + (9174, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9173, 9175), + (9175, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9174, 9176), + (9176, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9175, 9177), + (9177, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9176, 9178), + (9178, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9177, 9179), + (9179, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9178, 9180), + (9180, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9179, -1), + (9181, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, -1, 9182), + (9182, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9181, 9183), + (9183, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9182, 9184), + (9184, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9183, 9185), + (9185, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9184, 9186), + (9186, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9185, 9187), + (9187, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9186, 9188), + (9188, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9187, 9189), + (9189, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9188, -1), + (9190, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, -1, 9191), + (9191, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9190, 9192), + (9192, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9191, 9193), + (9193, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9192, 9194), + (9194, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9193, 9195), + (9195, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9194, 9196), + (9196, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9195, 9197), + (9197, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9196, 9198), + (9198, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9197, -1), + (9199, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, -1, 9200), + (9200, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9199, 9201), + (9201, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9200, 9202), + (9202, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9201, 9203), + (9203, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9202, 9204), + (9204, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9203, 9205), + (9205, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9204, 9206), + (9206, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9205, 9207), + (9207, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9206, -1), + (9208, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, -1, 9209), + (9209, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9208, 9210), + (9210, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9209, 9211), + (9211, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9210, 9212), + (9212, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9211, 9213), + (9213, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9212, 9214), + (9214, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9213, 9215), + (9215, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9214, 9216), + (9216, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9215, -1), + (9217, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, -1, 9218), + (9218, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9217, 9219), + (9219, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9218, 9220), + (9220, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9219, 9221), + (9221, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9220, 9222), + (9222, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9221, 9223), + (9223, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9222, 9224), + (9224, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9223, 9225), + (9225, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9224, -1), + (9226, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, -1, 9227), + (9227, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9226, 9228), + (9228, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9227, 9229), + (9229, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9228, 9230), + (9230, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9229, 9231), + (9231, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9230, 9232), + (9232, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9231, 9233), + (9233, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9232, 9234), + (9234, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9233, -1), + (9235, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, -1, 9236), + (9236, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9235, 9237), + (9237, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9236, 9238), + (9238, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9237, 9239), + (9239, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9238, 9240), + (9240, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9239, 9241), + (9241, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9240, 9242), + (9242, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9241, 9243), + (9243, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9242, -1), + (9300, 9300, 9300, 9300, 9300, 5, 85, 16212, 40, 600, 15, -1, 9301), + (9301, 9300, 9300, 9300, 9300, 5, 85, 16213, 40, 600, 15, 9300, 9302), + (9302, 9300, 9300, 9300, 9300, 5, 85, 16214, 40, 600, 15, 9301, -1), + (9303, 9303, 9303, 9303, 9303, 5, 85, 16215, 40, 600, 15, -1, 9304), + (9304, 9303, 9303, 9303, 9303, 5, 85, 16216, 40, 600, 15, 9303, 9305), + (9305, 9303, 9303, 9303, 9303, 5, 85, 16217, 40, 600, 15, 9304, -1), + (9306, 9306, 9306, 9306, 9306, 5, 85, 16218, 40, 600, 15, -1, 9307), + (9307, 9306, 9306, 9306, 9306, 5, 85, 16219, 40, 600, 15, 9306, 9308), + (9308, 9306, 9306, 9306, 9306, 5, 85, 16220, 40, 600, 15, 9307, -1), + (9309, 9309, 9309, 9309, 9309, 5, 85, 16249, 40, 600, 15, -1, 9310), + (9310, 9309, 9309, 9309, 9309, 5, 85, 16250, 40, 600, 15, 9309, 9311), + (9311, 9309, 9309, 9309, 9309, 5, 85, 16251, 40, 600, 15, 9310, -1), + (9312, 9312, 9312, 9312, 9312, 5, 85, 16252, 40, 600, 15, -1, 9313), + (9313, 9312, 9312, 9312, 9312, 5, 85, 16253, 40, 600, 15, 9312, 9314), + (9314, 9312, 9312, 9312, 9312, 5, 85, 16254, 40, 600, 15, 9313, -1), + (9315, 9315, 9315, 9315, 9315, 5, 85, 16255, 40, 600, 15, -1, 9316), + (9316, 9315, 9315, 9315, 9315, 5, 85, 16256, 40, 600, 15, 9315, 9317), + (9317, 9315, 9315, 9315, 9315, 5, 85, 16257, 40, 600, 15, 9316, -1), + (9318, 9318, 9318, 9318, 9318, 5, 85, 16261, 40, 600, 15, -1, 9319), + (9319, 9318, 9318, 9318, 9318, 5, 85, 16262, 40, 600, 15, 9318, 9320), + (9320, 9318, 9318, 9318, 9318, 5, 85, 16263, 40, 600, 15, 9319, -1), + (9321, 9321, 9321, 9321, 9321, 5, 85, 16264, 40, 600, 15, -1, 9322), + (9322, 9321, 9321, 9321, 9321, 5, 85, 16265, 40, 600, 15, 9321, 9323), + (9323, 9321, 9321, 9321, 9321, 5, 85, 16266, 40, 600, 15, 9322, -1), + (9324, 9324, 9324, 9324, 9324, 5, 85, 16267, 40, 600, 15, -1, 9325), + (9325, 9324, 9324, 9324, 9324, 5, 85, 16268, 40, 600, 15, 9324, 9326), + (9326, 9324, 9324, 9324, 9324, 5, 85, 16269, 40, 600, 15, 9325, -1), + (9327, 9327, 9327, 9327, 9327, 5, 85, 16270, 40, 600, 15, -1, 9328), + (9328, 9327, 9327, 9327, 9327, 5, 85, 16271, 40, 600, 15, 9327, 9329), + (9329, 9327, 9327, 9327, 9327, 5, 85, 16272, 40, 600, 15, 9328, -1), + (9330, 9330, 9330, 9330, 9330, 5, 85, 16273, 40, 600, 15, -1, 9331), + (9331, 9330, 9330, 9330, 9330, 5, 85, 16274, 40, 600, 15, 9330, 9332), + (9332, 9330, 9330, 9330, 9330, 5, 85, 16275, 40, 600, 15, 9331, -1), + (9333, 9333, 9333, 9333, 9333, 5, 85, 16276, 40, 600, 15, -1, 9334), + (9334, 9333, 9333, 9333, 9333, 5, 85, 16277, 40, 600, 15, 9333, 9335), + (9335, 9333, 9333, 9333, 9333, 5, 85, 16278, 40, 600, 15, 9334, -1), + (9336, 9336, 9336, 9336, 9336, 5, 85, 16284, 40, 600, 15, -1, 9337), + (9337, 9336, 9336, 9336, 9336, 5, 85, 16285, 40, 600, 15, 9336, 9338), + (9338, 9336, 9336, 9336, 9336, 5, 85, 16286, 40, 600, 15, 9337, -1), + (9339, 9339, 9339, 9339, 9339, 5, 85, 16287, 40, 600, 15, -1, 9340), + (9340, 9339, 9339, 9339, 9339, 5, 85, 16288, 40, 600, 15, 9339, 9341), + (9341, 9339, 9339, 9339, 9339, 5, 85, 16289, 40, 600, 15, 9340, -1), + (9342, 9342, 9342, 9342, 9342, 5, 85, 16290, 40, 600, 15, -1, 9343), + (9343, 9342, 9342, 9342, 9342, 5, 85, 16291, 40, 600, 15, 9342, 9344), + (9344, 9342, 9342, 9342, 9342, 5, 85, 16292, 40, 600, 15, 9343, -1), + (9345, 9345, 9345, 9345, 9345, 5, 85, 16293, 40, 600, 15, -1, 9346), + (9346, 9345, 9345, 9345, 9345, 5, 85, 16294, 40, 600, 15, 9345, 9347), + (9347, 9345, 9345, 9345, 9345, 5, 85, 16295, 40, 600, 15, 9346, -1), + (9348, 9348, 9348, 9348, 9348, 5, 85, 16296, 40, 600, 15, -1, 9349), + (9349, 9348, 9348, 9348, 9348, 5, 85, 16297, 40, 600, 15, 9348, 9350), + (9350, 9348, 9348, 9348, 9348, 5, 85, 16298, 40, 600, 15, 9349, -1), + (9351, 9351, 9351, 9351, 9351, 5, 85, 16299, 40, 600, 15, -1, 9352), + (9352, 9351, 9351, 9351, 9351, 5, 85, 16300, 40, 600, 15, 9351, 9353), + (9353, 9351, 9351, 9351, 9351, 5, 85, 16301, 40, 600, 15, 9352, -1), + (9354, 9354, 9354, 9354, 9354, 5, 85, 16305, 40, 600, 15, -1, 9355), + (9355, 9354, 9354, 9354, 9354, 5, 85, 16306, 40, 600, 15, 9354, 9356), + (9356, 9354, 9354, 9354, 9354, 5, 85, 16307, 40, 600, 15, 9355, 12626), + (9357, 9357, 9357, 9357, 9357, 5, 85, 16308, 40, 600, 15, -1, 9358), + (9358, 9357, 9357, 9357, 9357, 5, 85, 16309, 40, 600, 15, 9357, 9359), + (9359, 9357, 9357, 9357, 9357, 5, 85, 16310, 40, 600, 15, 9358, 12629), + (9360, 9360, 9360, 9360, 9360, 5, 85, 16311, 40, 600, 15, -1, 9361), + (9361, 9360, 9360, 9360, 9360, 5, 85, 16312, 40, 600, 15, 9360, 9362), + (9362, 9360, 9360, 9360, 9360, 5, 85, 16313, 40, 600, 15, 9361, 12632), + (9363, 9363, 9363, 9363, 9363, 5, 85, 16317, 40, 600, 15, -1, 9364), + (9364, 9363, 9363, 9363, 9363, 5, 85, 16318, 40, 600, 15, 9363, 9365), + (9365, 9363, 9363, 9363, 9363, 5, 85, 16319, 40, 600, 15, 9364, -1), + (9366, 9366, 9366, 9366, 9366, 5, 85, 16320, 40, 600, 15, -1, 9367), + (9367, 9366, 9366, 9366, 9366, 5, 85, 16321, 40, 600, 15, 9366, 9368), + (9368, 9366, 9366, 9366, 9366, 5, 85, 16322, 40, 600, 15, 9367, -1), + (9369, 9369, 9369, 9369, 9369, 5, 85, 16323, 40, 600, 15, -1, 9370), + (9370, 9369, 9369, 9369, 9369, 5, 85, 16324, 40, 600, 15, 9369, 9371), + (9371, 9369, 9369, 9369, 9369, 5, 85, 16325, 40, 600, 15, 9370, -1), + (9372, 9372, 9372, 9372, 9372, 5, 85, 16326, 40, 600, 15, -1, 9373), + (9373, 9372, 9372, 9372, 9372, 5, 85, 16327, 40, 600, 15, 9372, 9374), + (9374, 9372, 9372, 9372, 9372, 5, 85, 16328, 40, 600, 15, 9373, -1), + (9375, 9375, 9375, 9375, 9375, 5, 85, 16329, 40, 600, 15, -1, 9376), + (9376, 9375, 9375, 9375, 9375, 5, 85, 16330, 40, 600, 15, 9375, 9377), + (9377, 9375, 9375, 9375, 9375, 5, 85, 16331, 40, 600, 15, 9376, -1), + (9378, 9378, 9378, 9378, 9378, 5, 85, 16332, 40, 600, 15, -1, 9379), + (9379, 9378, 9378, 9378, 9378, 5, 85, 16333, 40, 600, 15, 9378, 9380), + (9380, 9378, 9378, 9378, 9378, 5, 85, 16334, 40, 600, 15, 9379, -1), + (9381, 9381, 9381, 9381, 9381, 5, 85, 16335, 40, 600, 15, -1, 9382), + (9382, 9381, 9381, 9381, 9381, 5, 85, 16336, 40, 600, 15, 9381, 9383), + (9383, 9381, 9381, 9381, 9381, 5, 85, 16337, 40, 600, 15, 9382, -1), + (9384, 9384, 9384, 9384, 9384, 5, 85, 16338, 40, 600, 15, -1, 9385), + (9385, 9384, 9384, 9384, 9384, 5, 85, 16339, 40, 600, 15, 9384, 9386), + (9386, 9384, 9384, 9384, 9384, 5, 85, 16340, 40, 600, 15, 9385, -1), + (9387, 9387, 9387, 9387, 9387, 5, 85, 16341, 40, 600, 15, -1, 9388), + (9388, 9387, 9387, 9387, 9387, 5, 85, 16342, 40, 600, 15, 9387, 9389), + (9389, 9387, 9387, 9387, 9387, 5, 85, 16343, 40, 600, 15, 9388, -1), + (9390, 9390, 9390, 9390, 9390, 5, 85, 16344, 40, 600, 15, -1, 9391), + (9391, 9390, 9390, 9390, 9390, 5, 85, 16345, 40, 600, 15, 9390, 9392), + (9392, 9390, 9390, 9390, 9390, 5, 85, 16346, 40, 600, 15, 9391, -1), + (9393, 9393, 9393, 9393, 9393, 5, 85, 16347, 40, 600, 15, -1, 9394), + (9394, 9393, 9393, 9393, 9393, 5, 85, 16348, 40, 600, 15, 9393, 9395), + (9395, 9393, 9393, 9393, 9393, 5, 85, 16349, 40, 600, 15, 9394, -1), + (9396, 9396, 9396, 9396, 9396, 5, 85, 16350, 40, 600, 15, -1, 9397), + (9397, 9396, 9396, 9396, 9396, 5, 85, 16351, 40, 600, 15, 9396, 9398), + (9398, 9396, 9396, 9396, 9396, 5, 85, 16352, 40, 600, 15, 9397, -1), + (9399, 9399, 9399, 9399, 9399, 5, 85, 16359, 40, 600, 15, -1, 9400), + (9400, 9399, 9399, 9399, 9399, 5, 85, 16360, 40, 600, 15, 9399, 9401), + (9401, 9399, 9399, 9399, 9399, 5, 85, 16361, 40, 600, 15, 9400, -1), + (9402, 9402, 9402, 9402, 9402, 5, 85, 16362, 40, 600, 15, -1, 9403), + (9403, 9402, 9402, 9402, 9402, 5, 85, 16363, 40, 600, 15, 9402, 9404), + (9404, 9402, 9402, 9402, 9402, 5, 85, 16364, 40, 600, 15, 9403, -1), + (9405, 9405, 9405, 9405, 9405, 5, 85, 16365, 40, 600, 15, -1, 9406), + (9406, 9405, 9405, 9405, 9405, 5, 85, 16366, 40, 600, 15, 9405, 9407), + (9407, 9405, 9405, 9405, 9405, 5, 85, 16367, 40, 600, 15, 9406, -1), + (9408, 9408, 9408, 9408, 9408, 5, 85, 16368, 40, 600, 15, -1, 9409), + (9409, 9408, 9408, 9408, 9408, 5, 85, 16369, 40, 600, 15, 9408, 9410), + (9410, 9408, 9408, 9408, 9408, 5, 85, 16370, 40, 600, 15, 9409, -1), + (9411, 9411, 9411, 9411, 9411, 5, 85, 16371, 40, 600, 15, -1, 9412), + (9412, 9411, 9411, 9411, 9411, 5, 85, 16372, 40, 600, 15, 9411, 9413), + (9413, 9411, 9411, 9411, 9411, 5, 85, 16373, 40, 600, 15, 9412, -1), + (9414, 9414, 9414, 9414, 9414, 5, 85, 16374, 40, 600, 15, -1, 9415), + (9415, 9414, 9414, 9414, 9414, 5, 85, 16375, 40, 600, 15, 9414, 9416), + (9416, 9414, 9414, 9414, 9414, 5, 85, 16376, 40, 600, 15, 9415, -1), + (9417, 9417, 9417, 9417, 9417, 5, 85, 16377, 40, 600, 15, -1, 9418), + (9418, 9417, 9417, 9417, 9417, 5, 85, 16378, 40, 600, 15, 9417, 9419), + (9419, 9417, 9417, 9417, 9417, 5, 85, 16379, 40, 600, 15, 9418, -1), + (9420, 9420, 9420, 9420, 9420, 5, 85, 16380, 40, 600, 15, -1, 9421), + (9421, 9420, 9420, 9420, 9420, 5, 85, 16381, 40, 600, 15, 9420, 9422), + (9422, 9420, 9420, 9420, 9420, 5, 85, 16382, 40, 600, 15, 9421, -1), + (9423, 9423, 9423, 9423, 9423, 5, 85, 16386, 40, 600, 15, -1, 9424), + (9424, 9423, 9423, 9423, 9423, 5, 85, 16387, 40, 600, 15, 9423, 9425), + (9425, 9423, 9423, 9423, 9423, 5, 85, 16388, 40, 600, 15, 9424, -1), + (9426, 9426, 9426, 9426, 9426, 5, 85, 16389, 40, 600, 15, -1, 9427), + (9427, 9426, 9426, 9426, 9426, 5, 85, 16390, 40, 600, 15, 9426, 9428), + (9428, 9426, 9426, 9426, 9426, 5, 85, 16391, 40, 600, 15, 9427, -1), + (9429, 9429, 9429, 9429, 9429, 5, 85, 16392, 40, 600, 15, -1, 9430), + (9430, 9429, 9429, 9429, 9429, 5, 85, 16393, 40, 600, 15, 9429, 9431), + (9431, 9429, 9429, 9429, 9429, 5, 85, 16394, 40, 600, 15, 9430, -1), + (9432, 9432, 9432, 9432, 9432, 5, 85, 16395, 40, 600, 15, -1, 9433), + (9433, 9432, 9432, 9432, 9432, 5, 85, 16396, 40, 600, 15, 9432, 9434), + (9434, 9432, 9432, 9432, 9432, 5, 85, 16397, 40, 600, 15, 9433, -1), + (9435, 9435, 9435, 9435, 9435, 5, 85, 16398, 40, 600, 15, -1, 9436), + (9436, 9435, 9435, 9435, 9435, 5, 85, 16399, 40, 600, 15, 9435, 9437), + (9437, 9435, 9435, 9435, 9435, 5, 85, 16400, 40, 600, 15, 9436, -1), + (9438, 9438, 9438, 9438, 9438, 5, 85, 16401, 40, 600, 15, -1, 9439), + (9439, 9438, 9438, 9438, 9438, 5, 85, 16402, 40, 600, 15, 9438, 9440), + (9440, 9438, 9438, 9438, 9438, 5, 85, 16403, 40, 600, 15, 9439, -1), + (9441, 9441, 9441, 9441, 9441, 5, 85, 16404, 40, 600, 15, -1, 9442), + (9442, 9441, 9441, 9441, 9441, 5, 85, 16405, 40, 600, 15, 9441, 9443), + (9443, 9441, 9441, 9441, 9441, 5, 85, 16406, 40, 600, 15, 9442, -1), + (9500, 9500, 9500, 9500, 9500, 3, 76, 16247, 47, 60, 15, -1, -1), + (9501, 9501, 9501, 9501, 9501, 9, 85, 16247, 47, 600, 15, -1, -1), + (9502, 9502, 9502, 9502, 9502, 7, 81, 16248, 48, 3600, 15, -1, -1), + (9503, -1, -1, 9503, 9503, 7, 83, -1, 0, 0, 15, -1, 9504), + (9504, -1, -1, 9503, 9503, 7, 84, -1, 0, 0, 15, 9503, 9505), + (9505, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 15, 9504, 10087), + (9506, -1, -1, 9506, 9506, 7, 81, -1, 0, 0, 15, -1, 9507), + (9507, -1, -1, 9506, 9506, 7, 83, -1, 0, 0, 15, 9506, 9508), + (9508, -1, -1, 9506, 9506, 7, 85, -1, 0, 0, 15, 9507, 13630), + (9509, -1, -1, 9509, 9509, 7, 81, -1, 0, 0, 15, -1, 9510), + (9510, -1, -1, 9509, 9509, 7, 82, -1, 0, 0, 15, 9509, 9511), + (9511, -1, -1, 9509, 9509, 7, 83, -1, 0, 0, 15, 9510, 9515), + (9512, -1, -1, 9512, 9512, 7, 81, -1, 0, 0, 15, -1, 9513), + (9513, -1, -1, 9512, 9512, 7, 82, -1, 0, 0, 15, 9512, 9514), + (9514, -1, -1, 9512, 9512, 7, 83, -1, 0, 0, 15, 9513, 7819), + (9515, -1, -1, 9509, 9509, 7, 86, -1, 0, 0, 17, 9511, 16361), + (10003, 6610, 6610, 6610, 6610, 5, 60, 16494, 41, 30, 16, 6610, 10573), + (10004, -1, -1, 6614, 6614, 6, 70, -1, 0, 0, 16, 6616, 10005), + (10005, -1, -1, 6614, 6614, 9, 70, -1, 0, 0, 16, 10004, 10575), + (10006, 54006, 54006, 54006, 54006, 7, 85, 16495, 18, 180, 16, 7111, 13425), + (10007, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 7114, 10008), + (10008, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 10007, 10009), + (10009, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 10008, 10568), + (10010, 6565, 6565, 6565, 6565, 7, 85, 16496, 17, 45, 16, 7115, 10517), + (10011, 912, 912, 912, 912, 9, 80, 16497, 4, 3600, 16, 7121, 10012), + (10012, 912, 912, 912, 912, 9, 80, 16498, 4, 3600, 16, 10011, 10013), + (10013, 912, 912, 912, 912, 9, 80, 16499, 4, 3600, 16, 10012, 10585), + (10014, 1383, 1383, 1383, 1383, 12, 85, 21766, 6, 300, 16, 7299, 6487), + (10015, 1195, 1195, 1195, 1195, 9, 85, 16504, 13, 2160, 16, 7300, 13259), + (10016, 131, 131, 131, 131, 10, 85, 16505, 4, 900, 16, 7303, 10017), + (10017, 131, 131, 131, 131, 10, 85, 16506, 4, 900, 16, 10016, 10018), + (10018, 131, 131, 131, 131, 10, 85, 16507, 4, 900, 16, 10017, 7770), + (10019, 1192, 1192, 1192, 1192, 10, 85, 20177, 12, 1320, 16, 7306, 10020), + (10020, 1192, 1192, 1192, 1192, 10, 85, 21652, 12, 1320, 16, 10019, 10021), + (10021, 1192, 1192, 1192, 1192, 10, 85, 21704, 12, 1320, 16, 10020, 13363), + (10022, 746, 746, 746, 746, 12, 85, 16511, 10, 2160, 16, 7309, 10023), + (10023, 746, 746, 746, 746, 12, 85, 16512, 10, 2160, 16, 10022, 10024), + (10024, 746, 746, 746, 746, 12, 85, 16513, 10, 2160, 16, 10023, 15321), + (10025, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 7322, 10026), + (10026, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10025, 10027), + (10027, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10026, 10028), + (10028, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10027, 10029), + (10029, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10028, 10437), + (10030, -1, -1, 7940, 7940, 5, 75, -1, 0, 0, 16, 7942, 10031), + (10031, -1, -1, 7940, 7940, 7, 75, -1, 0, 0, 16, 10030, 10032), + (10032, -1, -1, 7940, 7940, 9, 75, -1, 0, 0, 16, 10031, 6484), + (10033, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 7947, 10034), + (10034, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 10033, 10347), + (10035, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 7950, 10036), + (10036, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 10035, 10037), + (10037, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 10036, 15328), + (10038, 7951, 7951, 7951, 7951, 6, 85, 16514, 61, 900, 16, 7953, 10039), + (10039, 7951, 7951, 7951, 7951, 6, 85, 16515, 61, 900, 16, 10038, 10040), + (10040, 7951, 7951, 7951, 7951, 6, 85, 16516, 61, 900, 16, 10039, 7773), + (10041, -1, -1, 6636, 6636, 9, 75, -1, 0, 0, 16, 6638, 10042), + (10042, -1, -1, 6636, 6636, 10, 75, -1, 0, 0, 16, 10041, 10043), + (10043, -1, -1, 6636, 6636, 11, 75, -1, 0, 0, 16, 10042, 12529), + (10044, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 6793, 10045), + (10045, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 10044, 10046), + (10046, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 10045, 10676), + (10047, 534, 534, 534, 534, 12, 85, 16561, 4, 2160, 16, 7331, 10048), + (10048, 534, 534, 534, 534, 12, 85, 16562, 4, 2160, 16, 10047, 10049), + (10049, 534, 534, 534, 534, 12, 85, 16563, 4, 2160, 16, 10048, 10708), + (10050, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 7338, 10051), + (10051, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 10050, 10052), + (10052, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 10051, 10705), + (10053, 6754, 6754, 6754, 6754, 9, 75, 16570, 41, 1200, 16, 6754, 14111), + (10054, 6758, 6758, 6758, 6758, 10, 85, 16571, 43, 900, 16, 6760, 10055), + (10055, 6758, 6758, 6758, 6758, 11, 85, 16572, 43, 900, 16, 10054, 10056), + (10056, 6758, 6758, 6758, 6758, 12, 85, 16573, 43, 900, 16, 10055, 13546), + (10057, 6764, 6764, 6764, 6764, 9, 80, 16574, 52, 600, 16, 6764, 16716), + (10058, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 6767, 10059), + (10059, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 10058, 10060), + (10060, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 10059, 10766), + (10061, 5007, 5007, 5007, 5007, 9, 85, 16575, 8, 2160, 16, 7343, 10062), + (10062, 5007, 5007, 5007, 5007, 9, 85, 16576, 8, 2160, 16, 10061, 10063), + (10063, 5007, 5007, 5007, 5007, 9, 85, 16577, 8, 2160, 16, 10062, 13119), + (10064, -1, -1, 1608, 1608, 6, 85, -1, 0, 0, 16, 7383, 10065), + (10065, -1, -1, 1608, 1608, 7, 85, -1, 0, 0, 16, 10064, 10066), + (10066, -1, -1, 1608, 1608, 8, 85, -1, 0, 0, 16, 10065, 10067), + (10067, -1, -1, 1608, 1608, 9, 85, -1, 0, 0, 16, 10066, 10068), + (10068, -1, -1, 1608, 1608, 10, 85, -1, 0, 0, 16, 10067, 10069), + (10069, -1, -1, 1608, 1608, 11, 85, -1, 0, 0, 16, 10068, 16730), + (10070, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 6634, 10071), + (10071, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10070, 10072), + (10072, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10071, 10073), + (10073, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10072, 10074), + (10074, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10073, 13621), + (10075, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 6643, 10076), + (10076, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 10075, 10077), + (10077, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 10076, 16192), + (10078, 6508, 6508, 6508, 6508, 7, 85, 16578, 38, 600, 16, 7389, 10079), + (10079, 6508, 6508, 6508, 6508, 7, 85, 16579, 38, 600, 16, 10078, 10080), + (10080, 6508, 6508, 6508, 6508, 7, 85, 16580, 38, 600, 16, 10079, 15775), + (10081, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 7398, 10082), + (10082, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 10081, 10083), + (10083, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 10082, 12579), + (10084, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 7663, 10085), + (10085, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 10084, 10086), + (10086, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 10085, 5347), + (10087, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 9505, 10088), + (10088, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 10087, 10089), + (10089, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 10088, 12792), + (10090, 1498, 1498, 1498, 1498, 12, 85, 16590, 12, 1320, 16, 7410, 10091), + (10091, 1498, 1498, 1498, 1498, 12, 85, 16591, 12, 1320, 16, 10090, 10092), + (10092, 1498, 1498, 1498, 1498, 12, 85, 16602, 12, 1320, 16, 10091, 13401), + (10093, 1495, 1495, 1495, 1495, 9, 86, 16603, 30, 900, 17, 7416, 10094), + (10096, 548, 548, 548, 548, 10, 85, 16606, 5, 900, 16, 7419, 10097), + (10097, 548, 548, 548, 548, 10, 85, 16607, 5, 900, 16, 10096, 10098), + (10098, 548, 548, 548, 548, 10, 85, 16608, 5, 900, 16, 10097, 13158), + (10099, 6561, 6561, 6561, 6561, 7, 85, 16609, 32, 30, 16, 7424, 10100), + (10100, 6561, 6561, 6561, 6561, 7, 85, 16610, 32, 30, 16, 10099, 10101), + (10101, 6561, 6561, 6561, 6561, 7, 85, 16611, 32, 30, 16, 10100, 10418), + (10102, 510, 510, 510, 510, 3, 75, 16587, 37, 240, 16, 7427, 10103), + (10103, 510, 510, 510, 510, 3, 75, 16588, 37, 240, 16, 10102, 10104), + (10104, 510, 510, 510, 510, 3, 75, 16589, 37, 240, 16, 10103, 10824), + (10105, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 7668, 10106), + (10106, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10105, 10107), + (10107, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10106, 10108), + (10108, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10107, 10109), + (10109, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10108, 17350), + (10110, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 7985, 10111), + (10111, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 10110, 10112), + (10112, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 10111, -1), + (10113, 1352, 1352, 1352, 1352, 6, 85, 16618, 3, 60, 16, 7156, 10114), + (10114, 1352, 1352, 1352, 1352, 6, 85, 16619, 3, 60, 16, 10113, 10115), + (10115, 1352, 1352, 1352, 1352, 6, 85, 16620, 3, 60, 16, 10114, 13807), + (10116, 1358, 1358, 1358, 1358, 6, 85, 16615, 3, 60, 16, 7159, 10117), + (10117, 1358, 1358, 1358, 1358, 6, 85, 16616, 3, 60, 16, 10116, 10118), + (10118, 1358, 1358, 1358, 1358, 6, 85, 16617, 3, 60, 16, 10117, 13810), + (10119, 1355, 1355, 1355, 1355, 6, 85, 16612, 3, 60, 16, 7174, 10120), + (10120, 1355, 1355, 1355, 1355, 6, 85, 16613, 3, 60, 16, 10119, 10121), + (10121, 1355, 1355, 1355, 1355, 6, 85, 16614, 3, 60, 16, 10120, 12700), + (10122, -1, -1, 4801, 4801, 6, 85, -1, 0, 0, 16, 7162, 10123), + (10123, -1, -1, 4801, 4801, 6, 85, -1, 0, 0, 16, 10122, 12674), + (10124, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 7177, 10125), + (10125, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 10124, 10126), + (10126, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 10125, 12703), + (10127, 7872, 7872, 7872, 7872, 6, 85, 16621, 41, 600, 16, 7874, 10128), + (10128, 7872, 7872, 7872, 7872, 6, 85, 16622, 41, 600, 16, 10127, 10129), + (10129, 7872, 7872, 7872, 7872, 6, 85, 16623, 41, 600, 16, 10128, 12682), + (10130, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 6872, 10131), + (10131, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 10130, 10132), + (10132, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 10131, -1), + (10133, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 6875, 10134), + (10134, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 10133, 10135), + (10135, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 10134, 13196), + (10136, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 6878, 10137), + (10137, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 10136, 10138), + (10138, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 10137, 12734), + (10139, 6533, 6533, 6533, 6533, 10, 85, 16631, 15, 600, 16, 7428, 12740), + (10140, 1116, 1116, 1116, 1116, 12, 85, 16647, 4, 2160, 16, 7432, 10141), + (10141, 1116, 1116, 1116, 1116, 12, 85, 16648, 4, 2160, 16, 10140, 10142), + (10142, 1116, 1116, 1116, 1116, 12, 85, 16649, 4, 2160, 16, 10141, 12743), + (10143, 5298, 5298, 5298, 5298, 12, 85, 16632, 32, 1800, 16, 7440, 10144), + (10144, 5298, 5298, 5298, 5298, 12, 85, 16633, 32, 1800, 16, 10143, 10145), + (10145, 5298, 5298, 5298, 5298, 12, 85, 16634, 32, 1800, 16, 10144, 12746), + (10146, 1598, -1, 1598, 1598, 12, 85, 16638, 6, 900, 16, 7443, 10147), + (10147, 1598, -1, 1598, 1598, 12, 85, 16639, 6, 900, 16, 10146, 10148), + (10148, 1598, -1, 1598, 1598, 12, 85, 16640, 6, 900, 16, 10147, 13193), + (10149, 5020, 5020, 5020, 5020, 9, 85, 16630, 9, 300, 16, 7444, 13490), + (10150, 1110, 1110, 1110, 1110, 6, 85, 16641, 3, 2160, 16, 7447, 10151), + (10151, 1110, 1110, 1110, 1110, 6, 85, 16642, 3, 2160, 16, 10150, 10152), + (10152, 1110, 1110, 1110, 1110, 6, 85, 16643, 3, 2160, 16, 10151, 13190), + (10153, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 7450, 10154), + (10154, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 10153, 10155), + (10155, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 10154, 16297), + (10156, 5017, 5017, 5017, 5017, 9, 85, 16627, 8, 600, 16, 7456, 10157), + (10157, 5017, 5017, 5017, 5017, 9, 85, 16628, 8, 600, 16, 10156, 10158), + (10158, 5017, 5017, 5017, 5017, 9, 85, 16629, 8, 600, 16, 10157, 14189), + (10159, 1569, 1569, 1569, 1569, 7, 85, 16624, 5, 1800, 16, 7459, 10160), + (10160, 1569, 1569, 1569, 1569, 7, 85, 16625, 5, 1800, 16, 10159, 10161), + (10161, 1569, 1569, 1569, 1569, 7, 85, 16626, 5, 1800, 16, 10160, 17276), + (10162, 6663, 6663, 6663, 6663, 7, 82, 16653, 59, 600, 16, 6665, 10163), + (10163, 6663, 6663, 6663, 6663, 7, 82, 16654, 59, 600, 16, 10162, 10164), + (10164, 6663, 6663, 6663, 6663, 7, 82, 16655, 59, 600, 16, 10163, -1), + (10165, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 7136, 10166), + (10166, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 10165, 10167), + (10167, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 10166, 13213), + (10168, 6328, 6328, 6328, 6328, 7, 85, 16650, 10, 600, 16, 7145, 10169), + (10169, 6328, 6328, 6328, 6328, 7, 85, 16651, 10, 600, 16, 10168, 10170), + (10170, 6328, 6328, 6328, 6328, 7, 85, 16652, 10, 600, 16, 10169, 13770), + (10171, -1, -1, 878, 878, 7, 85, -1, 0, 0, 16, 7147, 10172), + (10172, -1, -1, 878, 878, 7, 85, -1, 0, 0, 16, 10171, -1), + (10173, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 7153, 10174), + (10174, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 10173, 10175), + (10175, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 10174, 13795), + (10176, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 6705, 10177), + (10177, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 10176, 10178), + (10178, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 10177, 13005), + (10179, 6706, 6706, 6706, 6706, 7, 85, 16675, 44, 600, 16, 6708, 10180), + (10180, 6706, 6706, 6706, 6706, 7, 85, 16676, 44, 600, 16, 10179, 10181), + (10181, 6706, 6706, 6706, 6706, 7, 85, 16677, 44, 600, 16, 10180, 5353), + (10182, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 6716, 10183), + (10183, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10182, 10184), + (10184, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10183, 10185), + (10185, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10184, 10186), + (10186, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10185, -1), + (10187, 1327, 1327, 1327, 1327, 12, 85, 16665, 10, 900, 16, 7462, 10188), + (10188, 1327, 1327, 1327, 1327, 12, 85, 16666, 10, 900, 16, 10187, 10189), + (10189, 1327, 1327, 1327, 1327, 12, 85, 16667, 10, 900, 16, 10188, 5330), + (10190, 1520, 1520, 1520, 1520, 9, 80, 16672, 11, 900, 16, 7465, 10191), + (10191, 1520, 1520, 1520, 1520, 9, 80, 16673, 11, 900, 16, 10190, 10192), + (10192, 1520, 1520, 1520, 1520, 9, 80, 16674, 11, 900, 16, 10191, 12997), + (10193, 153, 153, 153, 153, 12, 85, 16668, 3, 2160, 16, 7468, 11081), + (10194, 528, 528, 528, 528, 12, 85, 16669, 5, 720, 16, 7471, 10195), + (10195, 528, 528, 528, 528, 12, 85, 16670, 5, 720, 16, 10194, 10196), + (10196, 528, 528, 528, 528, 12, 85, 16671, 5, 720, 16, 10195, 13161), + (10197, 5251, 5251, 5251, 5251, 12, 85, 16662, 13, 900, 16, 7474, 10198), + (10198, 5251, 5251, 5251, 5251, 12, 85, 16663, 13, 900, 16, 10197, 10199), + (10199, 5251, 5251, 5251, 5251, 12, 85, 16664, 13, 900, 16, 10198, 5363), + (10200, 6815, 6815, 6815, 6815, 8, 85, 16691, 60, 600, 16, 6817, 10201), + (10201, 6815, 6815, 6815, 6815, 8, 85, 16692, 60, 600, 16, 10200, 10202), + (10202, 6815, 6815, 6815, 6815, 8, 85, 16693, 60, 600, 16, 10201, 12786), + (10203, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 6821, 10204), + (10204, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 10203, 10205), + (10205, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 10204, -1), + (10206, -1, -1, 6823, 6823, 4, 75, -1, 0, 0, 16, 6827, 10207), + (10207, -1, -1, 6823, 6823, 4, 77, -1, 0, 0, 16, 10206, -1), + (10208, 6828, 6828, 6828, 6828, 12, 85, 16686, 43, 60, 16, 6828, 17534), + (10209, 1274, 1274, 1274, 1274, 12, 85, 16683, 9, 540, 16, 7201, 10210), + (10210, 1274, 1274, 1274, 1274, 12, 85, 16684, 9, 540, 16, 10209, 10211), + (10211, 1274, 1274, 1274, 1274, 12, 85, 16685, 9, 540, 16, 10210, 12760), + (10212, 1510, -1, 1510, 1510, 12, 80, 16690, 13, 2160, 16, 7202, -1), + (10213, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 7208, 10214), + (10214, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10213, 10215), + (10215, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10214, 10216), + (10216, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10215, 10217), + (10217, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10216, 12798), + (10218, 4927, 4927, 4927, 4927, 9, 85, 16682, 14, 600, 16, 7209, -1), + (10219, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 7214, 10220), + (10220, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10219, 10221), + (10221, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10220, 10222), + (10222, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10221, 10223), + (10223, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10222, -1), + (10224, 967, 967, 967, 967, 6, 85, 16687, 10, 1800, 16, 7219, 10225), + (10225, 967, 967, 967, 967, 6, 85, 16688, 10, 1800, 16, 10224, 10226), + (10226, 967, 967, 967, 967, 6, 85, 16689, 10, 1800, 16, 10225, 12789), + (10227, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 7222, 10228), + (10228, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 10227, 10229), + (10229, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 10228, 13226), + (10230, 619, 619, 619, 619, 6, 83, 16704, 6, 900, 16, 7228, 10231), + (10231, 619, 619, 619, 619, 6, 83, 16705, 6, 900, 16, 10230, 10232), + (10232, 619, 619, 619, 619, 6, 83, 16706, 6, 900, 16, 10231, -1), + (10233, 516, 516, 516, 516, 6, 82, 16707, 5, 480, 16, 7237, 12879), + (10234, 1334, 1334, 1334, 1334, 12, 85, 16701, 11, 4320, 16, 7241, 10235), + (10235, 1334, 1334, 1334, 1334, 12, 85, 16702, 11, 4320, 16, 10234, 10236), + (10236, 1334, 1334, 1334, 1334, 12, 85, 16703, 11, 4320, 16, 10235, 12868), + (10237, 8060, 8060, 8060, 8060, 7, 85, 16711, 41, 1800, 16, 8062, 10238), + (10238, 8060, 8060, 8060, 8060, 7, 85, 16712, 41, 1800, 16, 10237, 10239), + (10239, 8060, 8060, 8060, 8060, 7, 85, 16713, 41, 1800, 16, 10238, 13650), + (10240, 8063, 8063, 8063, 8063, 7, 85, 16714, 41, 1800, 16, 8065, 10241), + (10241, 8063, 8063, 8063, 8063, 7, 85, 16715, 41, 1800, 16, 10240, 10242), + (10242, 8063, 8063, 8063, 8063, 7, 85, 16716, 41, 1800, 16, 10241, 13653), + (10243, 8066, 8066, 8066, 8066, 7, 85, 16717, 41, 1800, 16, 8068, 10244), + (10244, 8066, 8066, 8066, 8066, 7, 85, 16718, 41, 1800, 16, 10243, 10245), + (10245, 8066, 8066, 8066, 8066, 7, 85, 16719, 41, 1800, 16, 10244, 13656), + (10246, 8072, 8072, 8072, 8072, 7, 80, 16708, 37, 20, 16, 8074, 10247), + (10247, 8072, 8072, 8072, 8072, 7, 80, 16709, 37, 20, 16, 10246, 10248), + (10248, 8072, 8072, 8072, 8072, 7, 80, 16710, 37, 20, 16, 10247, 12857), + (10249, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 8084, 10250), + (10250, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 10249, 10251), + (10251, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 10250, -1), + (10252, 520, 520, 520, 520, 12, 85, 16723, 6, 540, 16, 7252, 10253), + (10253, 520, 520, 520, 520, 12, 85, 16724, 6, 540, 16, 10252, 10254), + (10254, 520, 520, 520, 520, 12, 85, 16725, 6, 540, 16, 10253, 12985), + (10255, 4903, 4903, 4903, 4903, 9, 81, 16726, 9, 1320, 16, 7253, 12956), + (10256, 4906, 4906, 4906, 4906, 9, 81, 16727, 9, 1320, 16, 7254, 12959), + (10257, 4909, 4909, 4909, 4909, 9, 81, 16728, 16, 1320, 16, 7255, 12957), + (10258, 4912, 4912, 4912, 4912, 9, 81, 16729, 16, 1320, 16, 7256, 12958), + (10259, 616, 616, 616, 616, 10, 85, 16733, 7, 900, 16, 7259, 10260), + (10260, 616, 616, 616, 616, 10, 85, 16734, 7, 900, 16, 10259, 10261), + (10261, 616, 616, 616, 616, 10, 85, 16735, 7, 900, 16, 10260, 14730), + (10262, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 7265, 10263), + (10263, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 10262, 10264), + (10264, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 10263, 13707), + (10265, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 7269, 10266), + (10266, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 10265, 10267), + (10267, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 10266, 12945), + (10268, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 7902, 10269), + (10269, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 10268, 10270), + (10270, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 10269, -1), + (10271, 1242, 1242, 1242, 1242, 12, 85, 16744, 9, 1320, 16, 7287, 10272), + (10272, 1242, 1242, 1242, 1242, 12, 85, 16745, 9, 1320, 16, 10271, 10273), + (10273, 1242, 1242, 1242, 1242, 12, 85, 16746, 9, 1320, 16, 10272, 12934), + (10274, 4931, 4931, 4931, 4931, 7, 85, 16747, 4, 600, 16, 7293, 10275), + (10275, 4931, 4931, 4931, 4931, 7, 85, 16748, 4, 600, 16, 10274, 10276), + (10276, 4931, 4931, 4931, 4931, 7, 85, 16749, 4, 600, 16, 10275, 10428), + (10277, 4935, 4935, 4935, 4935, 7, 81, 16743, 14, 300, 16, 7294, 17540), + (10278, 4934, 4934, 4934, 4934, 7, 81, 16742, 13, 300, 16, 7295, 17539), + (10279, 517, 517, 517, 517, 5, 80, 16739, 12, 600, 16, 7298, 10280), + (10280, 517, 517, 517, 517, 5, 80, 16740, 12, 600, 16, 10279, 10281), + (10281, 517, 517, 517, 517, 5, 80, 16741, 12, 600, 16, 10280, 12917), + (10282, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 8033, 10283), + (10283, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 10282, 10284), + (10284, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 10283, 10431), + (10285, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 8037, 10286), + (10286, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 10285, 10287), + (10287, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 10286, 15472), + (10288, 6971, 6971, 6971, 6971, 7, 85, 16761, 41, 600, 16, 6973, 10289), + (10289, 6971, 6971, 6971, 6971, 7, 85, 16762, 41, 600, 16, 10288, 10290), + (10290, 6971, 6971, 6971, 6971, 7, 85, 16763, 41, 600, 16, 10289, 14274), + (10291, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 6976, 10292), + (10292, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 10291, 10293), + (10293, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 10292, -1), + (10294, 6984, 6984, 6984, 6984, 6, 78, 16765, 60, 60, 16, 6984, 13177), + (10295, 6985, 6985, 6985, 6985, 6, 78, 16766, 60, 60, 16, 6985, 13179), + (10296, 6986, 6986, 6986, 6986, 6, 78, 16767, 60, 60, 16, 6986, 13178), + (10297, 1119, 1119, 1119, 1119, 9, 85, 16750, 8, 900, 16, 7481, 10298), + (10298, 1119, 1119, 1119, 1119, 9, 85, 16751, 8, 900, 16, 10297, 10299), + (10299, 1119, 1119, 1119, 1119, 9, 85, 16752, 8, 900, 16, 10298, 16883), + (10300, 723, 723, 723, 723, 7, 85, 16753, 6, 30, 16, 7482, 14273), + (10301, 5015, 5015, 5015, 5015, 12, 85, 16754, 9, 900, 16, 7483, 17382), + (10302, 291, 291, 291, 291, 12, 85, 16755, 5, 900, 16, 7487, 10303), + (10303, 291, 291, 291, 291, 12, 85, 16756, 5, 900, 16, 10302, 10304), + (10304, 291, 291, 291, 291, 12, 85, 16757, 5, 900, 16, 10303, 12828), + (10305, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 7496, 10306), + (10306, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 10305, 10307), + (10307, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 10306, 16887), + (10308, 6380, 6380, 6380, 6380, 6, 85, 16758, 39, 120, 16, 7499, 10309), + (10309, 6380, 6380, 6380, 6380, 6, 85, 16759, 39, 120, 16, 10308, 10310), + (10310, 6380, 6380, 6380, 6380, 6, 85, 16760, 39, 120, 16, 10309, 13170), + (10311, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 4808, 10312), + (10312, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10311, 10313), + (10313, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10312, 10314), + (10314, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10313, 10315), + (10315, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10314, 13035), + (10316, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 4811, 10317), + (10317, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 10316, 10318), + (10318, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 10317, 13040), + (10319, 6931, 6931, 6931, 6931, 12, 85, 16774, 41, 600, 16, 6931, 13058), + (10320, 6932, 6932, 6932, 6932, 7, 85, 16775, 42, 1200, 16, 6934, 10321), + (10321, 6932, 6932, 6932, 6932, 7, 85, 16776, 42, 1200, 16, 10320, 10322), + (10322, 6932, 6932, 6932, 6932, 7, 85, 16777, 42, 1200, 16, 10321, 13062), + (10323, 4854, 4854, 4854, 4854, 12, 85, 16768, 8, 600, 16, 7180, 10324), + (10324, 4854, 4854, 4854, 4854, 12, 85, 16769, 8, 600, 16, 10323, 10325), + (10325, 4854, 4854, 4854, 4854, 12, 85, 16770, 8, 600, 16, 10324, 13059), + (10326, 1178, 1178, 1178, 1178, 9, 85, 16771, 4, 900, 16, 7189, 10327), + (10327, 1178, 1178, 1178, 1178, 9, 85, 16772, 4, 900, 16, 10326, 10328), + (10328, 1178, 1178, 1178, 1178, 9, 85, 16773, 4, 900, 16, 10327, 13845), + (10329, -1, -1, 10329, 10329, 5, 85, 0, 0, 0, 16, -1, 10398), + (10330, 10330, 10330, 10330, 10330, 7, 85, 16785, 35, 30, 16, -1, 13203), + (10331, 10331, 10331, 10331, 10331, 6, 85, 16787, 44, 20, 16, -1, -1), + (10332, -1, -1, 10332, 10332, 3, 85, -1, 0, 0, 16, -1, 12733), + (10333, 10333, 10333, 10333, 10333, 5, 85, 16788, 55, 120, 16, -1, 10334), + (10334, 10333, 10333, 10333, 10333, 7, 85, 16789, 55, 120, 16, 10333, 10335), + (10335, 10333, 10333, 10333, 10333, 9, 85, 16790, 55, 120, 16, 10334, 12724), + (10336, 10336, 10336, 10336, 10336, 5, 85, 16791, 58, 8, 16, -1, 10337), + (10337, 10336, 10336, 10336, 10336, 7, 85, 16792, 58, 8, 16, 10336, 10338), + (10338, 10336, 10336, 10336, 10336, 9, 85, 16793, 58, 8, 16, 10337, 12730), + (10339, 10339, 10339, 10339, 10339, 12, 85, 16786, 48, 1800, 16, -1, -1), + (10340, -1, -1, 10340, 10340, 3, 80, -1, 0, 0, 16, -1, 10341), + (10341, -1, -1, 10340, 10340, 6, 83, -1, 0, 0, 16, 10340, 10342), + (10342, -1, -1, 10340, 10340, 9, 85, -1, 0, 0, 16, 10341, 13184), + (10343, -1, -1, 10343, 10343, 5, 85, 0, 0, 0, 16, -1, 10344), + (10344, -1, -1, 10343, 10343, 7, 85, 0, 0, 0, 16, 10343, 10345), + (10345, -1, -1, 10343, 10343, 9, 85, 0, 0, 0, 16, 10344, 13841), + (10346, 10346, 10346, 10346, 10346, 9, 85, 21783, 46, 600, 16, -1, 13183), + (10347, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 10034, 17310), + (10348, 0, 0, 10348, 10348, 5, 80, -1, 0, 0, 16, -1, 10349), + (10349, 0, 0, 10348, 10348, 7, 83, -1, 0, 0, 16, 10348, 10350), + (10350, 0, 0, 10348, 10348, 9, 85, -1, 0, 0, 16, 10349, 13578), + (10351, 10351, 10351, 10351, 10351, 12, 85, 21785, 34, 600, 16, -1, 10682), + (10352, 10352, 10352, 10352, 10352, 12, 85, 21786, 34, 600, 16, -1, 10683), + (10353, 10353, 10353, 10353, 10353, 12, 85, 21787, 34, 600, 16, -1, 10684), + (10354, 10354, 10354, 10354, 10354, 8, 85, 21653, 39, 4320, 16, -1, 14016), + (10355, -1, -1, 10355, 10355, 6, 83, -1, 0, 0, 16, -1, 10356), + (10356, -1, -1, 10355, 10355, 8, 84, -1, 0, 0, 16, 10355, 10357), + (10357, -1, -1, 10355, 10355, 10, 85, -1, 0, 0, 16, 10356, 10643), + (10358, -1, -1, 10358, 10358, 7, 80, -1, 0, 0, 16, -1, 10359), + (10359, -1, -1, 10358, 10358, 9, 83, -1, 0, 0, 16, 10358, 10360), + (10360, -1, -1, 10358, 10358, 12, 85, -1, 0, 0, 16, 10359, 14210), + (10361, -1, -1, 962, 962, 5, 83, -1, 0, 0, 16, 6227, 10362), + (10362, -1, -1, 962, 962, 5, 84, -1, 0, 0, 16, 10361, 10363), + (10363, -1, -1, 962, 962, 5, 85, -1, 0, 0, 16, 10362, 14218), + (10364, -1, -1, 10364, 10364, 5, 85, -1, 0, 0, 16, -1, 10365), + (10365, -1, -1, 10364, 10364, 7, 85, -1, 0, 0, 16, 10364, 10366), + (10366, -1, -1, 10364, 10364, 9, 85, -1, 0, 0, 16, 10365, 10442), + (10367, 10367, 10367, 10367, 10367, 12, 85, 21751, 30, 360, 16, -1, 10630), + (10368, 10368, 10368, 10368, 10368, 6, 85, 21654, 46, 900, 16, -1, 10369), + (10369, 10368, 10368, 10368, 10368, 9, 85, 21655, 46, 900, 16, 10368, 10386), + (10370, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, -1, 10371), + (10371, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, 10370, 10372), + (10372, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, 10371, 13927), + (10373, 10373, 10373, 10373, 10373, 6, 75, 16806, 62, 6, 16, -1, -1), + (10374, 10374, 10374, 10374, 10374, 6, 85, 16800, 63, 900, 16, -1, 10375), + (10375, 10374, 10374, 10374, 10374, 6, 85, 16801, 63, 900, 16, 10374, 10376), + (10376, 10374, 10374, 10374, 10374, 6, 85, 16802, 63, 900, 16, 10375, 13174), + (10377, 10377, 10377, 10377, 10377, 6, 85, 16794, 64, 60, 16, -1, 10378), + (10378, 10377, 10377, 10377, 10377, 6, 85, 16795, 64, 60, 16, 10377, 10379), + (10379, 10377, 10377, 10377, 10377, 6, 85, 16796, 64, 60, 16, 10378, 13180), + (10380, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, -1, 10381), + (10381, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, 10380, 10382), + (10382, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, 10381, 13477), + (10383, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 7386, 10384), + (10384, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 10383, 10385), + (10385, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 10384, -1), + (10386, 10368, 10368, 10368, 10368, 12, 85, 21656, 46, 900, 16, 10369, -1), + (10387, 10387, 10387, 10387, 10387, 9, 85, 21835, 45, 1200, 16, -1, -1), + (10388, -1, -1, 10388, 10388, 12, 85, -1, 0, 0, 16, -1, 13545), + (10389, -1, -1, 10389, 10389, 9, 83, 0, 0, 0, 16, -1, 10390), + (10390, -1, -1, 10389, 10389, 11, 84, 0, 0, 0, 16, 10389, 10391), + (10391, -1, -1, 10389, 10389, 12, 85, 0, 0, 0, 16, 10390, -1), + (10392, 10392, 10392, 10392, 10392, 12, 85, 21751, 11, 480, 16, -1, 10631), + (10393, 10393, 10393, 10393, 10393, 9, 81, 3246, 42, 2, 16, -1, -1), + (10394, 10394, 10394, 10394, 10394, 12, 85, 21821, 30, 600, 16, -1, 10704), + (10395, 10395, 10395, 10395, 10395, 3, 80, 21748, 62, 5, 16, -1, 12590), + (10396, 10396, 10396, 10396, 10396, 12, 85, 16857, 14, 600, 16, -1, 10790), + (10397, 10397, 10397, 10397, 10397, 12, 85, 16858, 14, 600, 16, -1, 10791), + (10398, -1, -1, 10329, 10329, 7, 85, 0, 0, 0, 16, 10329, 10399), + (10399, -1, -1, 10329, 10329, 9, 85, 0, 0, 0, 16, 10398, -1), + (10400, 10400, 10400, 10400, 10400, 6, 85, 16807, 62, 900, 16, -1, 15558), + (10401, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, -1, 10402), + (10402, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, 10401, 10403), + (10403, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, 10402, 13052), + (10404, -1, -1, 10404, 10404, 6, 85, -1, 0, 0, 16, -1, 13051), + (10405, -1, -1, 10405, 10405, 7, 81, 0, 0, 0, 16, -1, 10406), + (10406, -1, -1, 10405, 10405, 7, 82, 0, 0, 0, 16, 10405, 10407), + (10407, -1, -1, 10405, 10405, 7, 83, 0, 0, 0, 16, 10406, 10408), + (10408, -1, -1, 10405, 10405, 7, 84, 0, 0, 0, 16, 10407, 10409), + (10409, -1, -1, 10405, 10405, 7, 85, 0, 0, 0, 16, 10408, 10671), + (10410, -1, -1, 10410, 10410, 8, 85, -1, 0, 0, 16, -1, 10411), + (10413, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, -1, 10414), + (10414, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10413, 10415), + (10415, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10414, 10416), + (10416, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10415, 10417), + (10417, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10416, -1), + (10418, 6561, 6561, 6561, 6561, 7, 85, 21808, 32, 30, 16, 10101, 10419), + (10419, 6561, 6561, 6561, 6561, 7, 85, 21810, 32, 30, 16, 10418, 10420), + (10420, 6561, 6561, 6561, 6561, 7, 85, 21811, 32, 30, 16, 10419, 14256), + (10421, 10506, 10506, 10506, 10506, 9, 85, 23521, 66, 120, 16, 10508, -1), + (10424, 10424, 10424, 10424, 10424, 7, 81, 21813, 41, 6, 16, -1, -1), + (10425, 10425, 10425, 10425, 10425, 7, 81, 21814, 39, 6, 16, -1, -1), + (10426, 10426, 10426, 10426, 10426, 10, 85, 21816, 5, 900, 16, -1, -1), + (10427, 10427, 10427, 10427, 10427, 12, 85, 21818, 30, 900, 16, -1, -1), + (10428, 4931, 4931, 4931, 4931, 7, 85, 21838, 4, 600, 16, 10276, 10429), + (10429, 4931, 4931, 4931, 4931, 7, 85, 21839, 4, 600, 16, 10428, 10430), + (10430, 4931, 4931, 4931, 4931, 7, 85, 21844, 4, 600, 16, 10429, 13241), + (10431, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10284, 10432), + (10432, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10431, 10433), + (10433, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10432, -1), + (10434, -1, -1, 10434, 10434, 7, 85, 0, 0, 0, 16, -1, 10435), + (10435, -1, -1, 10434, 10434, 9, 85, 0, 0, 0, 16, 10434, 10436), + (10436, -1, -1, 10434, 10434, 12, 85, 0, 0, 0, 16, 10435, -1), + (10437, -1, -1, 6601, 6601, 6, 86, -1, 0, 0, 17, 10029, 10438), + (10438, -1, -1, 6601, 6601, 6, 87, -1, 0, 0, 17, 10437, 10439), + (10439, -1, -1, 6601, 6601, 6, 88, -1, 0, 0, 17, 10438, 10440), + (10440, -1, -1, 6601, 6601, 6, 89, -1, 0, 0, 17, 10439, 10441), + (10442, -1, -1, 10364, 10364, 9, 86, -1, 0, 0, 17, 10366, 10443), + (10443, -1, -1, 10364, 10364, 9, 88, -1, 0, 0, 17, 10442, -1), + (10450, 10450, 10450, 10450, 10450, 7, 85, 16808, 63, 900, 16, -1, 10451), + (10451, 10450, 10450, 10450, 10450, 7, 85, 16809, 63, 900, 16, 10450, 10452), + (10452, 10450, 10450, 10450, 10450, 7, 85, 16810, 63, 900, 16, 10451, 10468), + (10453, -1, -1, 10453, 10453, 5, 85, -1, 0, 0, 16, -1, 10454), + (10454, -1, -1, 10453, 10453, 7, 85, -1, 0, 0, 16, 10453, 10455), + (10455, -1, -1, 10453, 10453, 9, 85, -1, 0, 0, 16, 10454, 13607), + (10456, -1, -1, 10456, 10456, 5, 85, -1, 0, 0, 16, -1, 10457), + (10457, -1, -1, 10456, 10456, 7, 85, -1, 0, 0, 16, 10456, 10458), + (10458, -1, -1, 10456, 10456, 9, 85, -1, 0, 0, 16, 10457, -1), + (10459, -1, -1, 10459, 10459, 5, 65, -1, 0, 0, 16, -1, 10460), + (10460, -1, -1, 10459, 10459, 7, 65, -1, 0, 0, 16, 10459, 10461), + (10461, -1, -1, 10459, 10459, 9, 65, -1, 0, 0, 16, 10460, -1), + (10462, 10462, 10462, 10462, 10462, 12, 85, 16811, 14, 4320, 16, -1, -1), + (10463, 10463, 10463, 10463, 10463, 12, 85, 16812, 16, 4320, 16, -1, -1), + (10464, -1, -1, 10464, 10464, 5, 80, -1, 0, 0, 16, -1, 10465), + (10465, -1, -1, 10464, 10464, 7, 80, -1, 0, 0, 16, 10464, 10466), + (10466, -1, -1, 10464, 10464, 9, 80, -1, 0, 0, 16, 10465, 13140), + (10467, -1, -1, 86, 86, 8, 85, -1, 0, 0, 17, 266, -1), + (10468, 10450, 10450, 10450, 10450, 7, 85, 23603, 63, 900, 17, 10452, 10469), + (10469, 10450, 10450, 10450, 10450, 7, 85, 23604, 63, 900, 17, 10468, 10670), + (10470, -1, -1, 10470, 10470, 9, 86, -1, 0, 0, 17, -1, 10471), + (10471, -1, -1, 10470, 10470, 12, 88, -1, 0, 0, 17, 10470, 10472), + (10472, -1, -1, 10470, 10470, 15, 90, -1, 0, 0, 17, 10471, 15828), + (10473, -1, -1, 446, 735, 10, 86, -1, 0, 0, 17, 7624, 10474), + (10474, -1, -1, 446, 735, 10, 87, -1, 0, 0, 17, 10473, 10475), + (10475, -1, -1, 446, 735, 10, 88, -1, 0, 0, 17, 10474, 10476), + (10476, -1, -1, 446, 735, 10, 89, -1, 0, 0, 17, 10475, 10477), + (10477, -1, -1, 446, 735, 10, 90, -1, 0, 0, 17, 10476, 13308), + (10478, -1, -1, 10478, 10478, 15, 101, -1, 0, 0, 21, -1, 10479), + (10481, 10481, 10481, 10481, 10481, 21, 105, 46249, 90, 600, 21, -1, -1), + (10500, 10500, 10500, 10500, 10500, 7, 85, 16813, 62, 12, 16, -1, -1), + (10501, 10501, 10501, 10501, 10501, 7, 85, 16814, 63, 1, 16, -1, -1), + (10502, 10502, -1, 10502, 10502, 7, 85, 1566, 64, 120, 16, -1, 12647), + (10503, 10503, 10503, 10503, 10503, 9, 85, 16816, 13, 600, 16, -1, 10504), + (10504, 10503, 10503, 10503, 10503, 9, 85, 16817, 13, 600, 16, 10503, 10505), + (10505, 10503, 10503, 10503, 10503, 9, 85, 16818, 13, 600, 16, 10504, 12648), + (10506, 10506, 10506, 10506, 10506, 9, 85, 16819, 66, 120, 16, -1, 10507), + (10507, 10506, 10506, 10506, 10506, 9, 85, 16820, 66, 120, 16, 10506, 10508), + (10508, 10506, 10506, 10506, 10506, 9, 85, 16821, 66, 120, 16, 10507, 10421), + (10509, 5105, 5105, 5105, 5105, 12, 85, 16822, 11, 600, 16, 7420, 13154), + (10510, 7986, 7986, 7986, 7986, 12, 85, 16823, 11, 600, 16, 7988, 13155), + (10511, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, -1, 10512), + (10512, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, 10511, 10513), + (10513, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, 10512, 12642), + (10514, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, -1, 10516), + (10515, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, 10516, 12639), + (10516, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, 10514, 10515), + (10517, 6565, 6565, 6565, 6565, 9, 88, 23608, 17, 45, 17, 10010, 10518), + (10519, -1, -1, 10519, 10519, 9, 86, 0, 0, 0, 17, -1, 10520), + (10522, -1, -1, 10522, 10522, 7, 86, 0, 0, 0, 17, -1, 10523), + (10527, -1, -1, 10527, 10527, 5, 86, 0, 0, 0, 17, -1, 10528), + (10532, -1, -1, 10532, 10532, 5, 86, 0, 0, 0, 17, -1, 10533), + (10537, -1, -1, 10537, 10537, 5, 86, 0, 0, 0, 17, -1, 10538), + (10545, 10545, 10545, 10545, 10545, 12, 85, 23531, 73, 600, 17, -1, -1), + (10546, 10546, 10546, 10546, 10546, 12, 85, 23528, 74, 600, 17, -1, -1), + (10548, -1, -1, 10548, 10548, 9, 86, -1, 0, 0, 17, -1, 10549), + (10550, 10550, 10550, 10550, 10550, 7, 85, 16824, 61, 120, 16, -1, 13250), + (10551, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, -1, 10552), + (10552, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, 10551, 10553), + (10553, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, 10552, 14764), + (10554, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 1576, 10555), + (10555, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 10554, 10556), + (10556, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 10555, 16062), + (10557, 12395, 12395, 12395, 12395, 9, 75, 16828, 11, 900, 16, -1, -1), + (10558, -1, -1, 10558, 10558, 6, 80, -1, 0, 0, 16, -1, 10559), + (10559, -1, -1, 10558, 10558, 6, 83, -1, 0, 0, 16, 10558, 10560), + (10560, -1, -1, 10558, 10558, 6, 85, -1, 0, 0, 16, 10559, 15469), + (10561, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, -1, 10562), + (10562, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, 10561, 10563), + (10563, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, 10562, 15466), + (10564, 773, -1, 773, 773, 12, 85, 16829, 5, 1800, 16, 7278, 10565), + (10565, 773, -1, 773, 773, 12, 85, 16830, 5, 1800, 16, 10564, 10566), + (10566, 773, -1, 773, 773, 12, 85, 16831, 5, 1800, 16, 10565, 13734), + (10568, -1, -1, 6564, 6564, 10, 86, -1, 0, 0, 17, 10009, 10569), + (10571, 1597, 1597, 1597, 1597, 9, 85, 23611, 6, 10, 17, 6606, -1), + (10572, 6617, 6617, 6617, 6617, 12, 86, 23612, 42, 3600, 17, 6617, 14036), + (10573, 6610, 6610, 6610, 6610, 9, 86, 23613, 41, 30, 17, 10003, 13422), + (10574, -1, -1, 6611, 6611, 6, 85, -1, 0, 0, 17, 6619, 16121), + (10575, -1, -1, 6614, 6614, 9, 85, -1, 0, 0, 17, 10005, -1), + (10576, -1, -1, 492, 492, 2, 87, -1, 0, 0, 17, 7130, -1), + (10578, 258, -1, 258, 258, 9, 86, 27520, 1, 600, 17, 258, 16003), + (10579, -1, -1, 7036, 10579, 9, 85, 0, 0, 0, 17, 7038, 10580), + (10580, -1, -1, 7036, 10579, 12, 87, 0, 0, 0, 17, 10579, 10581), + (10585, 912, 912, 912, 912, 9, 86, 23617, 4, 3600, 17, 10013, 10586), + (10588, -1, -1, 10588, 10588, 5, 86, 0, 0, 0, 17, -1, 10589), + (10589, -1, -1, 10588, 10588, 5, 87, 0, 0, 0, 17, 10588, 10590), + (10590, -1, -1, 10588, 10588, 5, 88, 0, 0, 0, 17, 10589, 10591), + (10591, -1, -1, 10588, 10588, 5, 89, 0, 0, 0, 17, 10590, 10592), + (10592, -1, -1, 10588, 10588, 5, 90, 0, 0, 0, 17, 10591, 17206), + (10600, 10600, 10600, 10600, 10600, 7, 85, 16832, 73, 20, 16, -1, 10601), + (10601, 10600, 10600, 10600, 10600, 7, 85, 16833, 73, 20, 16, 10600, 10602), + (10602, 10600, 10600, 10600, 10600, 7, 85, 16834, 73, 20, 16, 10601, 12982), + (10603, 10601, 10601, 10601, 10601, 3, 85, 16835, 62, 6, 16, -1, -1), + (10604, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 7603, 10605), + (10605, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 10604, 10606), + (10606, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 10605, 12795), + (10607, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 6385, 10608), + (10608, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 10607, 10609), + (10609, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 10608, 12801), + (10610, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, -1, 10611), + (10611, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, 10610, 10612), + (10612, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, 10611, -1), + (10618, 7850, 7850, 7850, 7850, 9, 86, 23532, 39, 4320, 17, 7340, 10619), + (10619, 7850, 7850, 7850, 7850, 12, 88, 23533, 39, 4320, 17, 10618, 10620), + (10620, 7850, 7850, 7850, 7850, 15, 90, 23534, 39, 4320, 17, 10619, 13604), + (10621, -1, -1, 849, 849, 9, 85, -1, 0, 0, 17, 851, 10622), + (10622, -1, -1, 849, 849, 9, 87, -1, 0, 0, 17, 10621, 16604), + (10623, -1, -1, 255, 255, 9, 85, -1, 0, 0, 17, 5808, 10624), + (10624, -1, -1, 255, 255, 12, 87, -1, 0, 0, 17, 10623, 10625), + (10625, -1, -1, 255, 255, 15, 89, -1, 0, 0, 17, 10624, 13589), + (10626, 5984, 5984, 5984, 5984, 12, 90, 23535, 2, 30, 17, 7711, 13592), + (10627, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, -1, 10628), + (10628, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, 10627, 10629), + (10629, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, 10628, -1), + (10630, 10367, 10367, 10367, 10367, 12, 90, 27642, 30, 360, 17, 10367, 13434), + (10631, 10392, 10392, 10392, 10392, 12, 90, 27642, 11, 480, 17, 10392, -1), + (10632, -1, -1, 735, 735, 10, 86, -1, 0, 0, 17, 7627, 10633), + (10633, -1, -1, 735, 735, 10, 87, -1, 0, 0, 17, 10632, 10634), + (10634, -1, -1, 735, 735, 10, 88, -1, 0, 0, 17, 10633, 10635), + (10635, -1, -1, 735, 735, 10, 89, -1, 0, 0, 17, 10634, 10636), + (10636, -1, -1, 735, 735, 10, 90, -1, 0, 0, 17, 10635, 13884), + (10637, -1, -1, 1287, 1287, 9, 86, -1, 0, 0, 17, 12471, 10638), + (10638, -1, -1, 1287, 1287, 12, 88, -1, 0, 0, 17, 10637, 10639), + (10639, -1, -1, 1287, 1287, 15, 90, -1, 0, 0, 17, 10638, 13323), + (10640, 5095, 5095, 5095, 5095, 9, 85, 23620, 10, 900, 17, 7334, 10641), + (10641, 5095, 5095, 5095, 5095, 12, 87, 23621, 10, 900, 17, 10640, 10642), + (10642, 5095, 5095, 5095, 5095, 15, 89, 23622, 10, 900, 17, 10641, 13575), + (10643, -1, -1, 10355, 10355, 10, 86, -1, 0, 0, 17, 10357, 10644), + (10644, -1, -1, 10355, 10355, 10, 88, -1, 0, 0, 17, 10643, 10645), + (10645, -1, -1, 10355, 10355, 10, 90, -1, 0, 0, 17, 10644, 14094), + (10646, 7712, 7712, 7712, 7712, 15, 90, 23536, 2, 30, 17, 7712, 13585), + (10647, 188, 188, 188, 188, 9, 88, 23537, 2, 30, 17, 7662, 13586), + (10650, -1, -1, 10650, 10650, 7, 85, -1, 0, 0, 16, -1, 10651), + (10651, -1, -1, 10650, 10650, 9, 85, -1, 0, 0, 16, 10650, 10652), + (10652, -1, -1, 10650, 10650, 12, 85, -1, 0, 0, 16, 10651, 13804), + (10653, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, -1, 10654), + (10654, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, 10653, 10655), + (10655, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, 10654, 17406), + (10656, -1, -1, 10656, 10656, 7, 85, -1, 0, 0, 16, -1, 12678), + (10657, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, -1, 10658), + (10658, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, 10657, 10659), + (10659, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, 10658, 12679), + (10660, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 7165, 10661), + (10661, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 10660, 10662), + (10662, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 10661, 12667), + (10663, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 7171, 10664), + (10664, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 10663, 10665), + (10665, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 10664, 12670), + (10666, -1, -1, 495, 495, 6, 85, -1, 0, 0, 16, 6262, 10667), + (10667, -1, -1, 495, 495, 5, 85, -1, 0, 0, 16, 10666, 10668), + (10668, -1, -1, 495, 495, 7, 85, -1, 0, 0, 16, 10667, 17391), + (10670, 10450, 10450, 10450, 10450, 7, 85, 23605, 63, 900, 17, 10469, 15839), + (10671, -1, -1, 10405, 10405, 9, 86, 0, 0, 0, 17, 10409, 10672), + (10672, -1, -1, 10405, 10405, 9, 87, 0, 0, 0, 17, 10671, 10673), + (10673, -1, -1, 10405, 10405, 9, 88, 0, 0, 0, 17, 10672, 10674), + (10674, -1, -1, 10405, 10405, 9, 89, 0, 0, 0, 17, 10673, 10675), + (10675, -1, -1, 10405, 10405, 9, 90, 0, 0, 0, 17, 10674, -1), + (10676, -1, -1, 6791, 6791, 6, 86, -1, 0, 0, 17, 10046, 10677), + (10677, -1, -1, 6791, 6791, 6, 88, -1, 0, 0, 17, 10676, 10678), + (10678, -1, -1, 6791, 6791, 6, 90, -1, 0, 0, 17, 10677, 13598), + (10679, 6492, 6492, 6492, 6492, 9, 85, 23626, 52, 720, 17, 6497, 10680), + (10680, 6492, 6492, 6492, 6492, 9, 87, 23627, 52, 720, 17, 10679, 10681), + (10681, 6492, 6492, 6492, 6492, 9, 89, 23628, 52, 720, 17, 10680, 14003), + (10682, 10351, 10351, 10351, 10351, 15, 90, 23538, 34, 600, 17, 10351, -1), + (10683, 10352, 10352, 10352, 10352, 15, 90, 23539, 34, 600, 17, 10352, -1), + (10684, 10353, 10353, 10353, 10353, 15, 90, 23540, 34, 600, 17, 10353, -1), + (10685, -1, -1, 602, 602, 9, 86, -1, 0, 0, 17, 5582, 10686), + (10686, -1, -1, 602, 602, 12, 88, -1, 0, 0, 17, 10685, 10687), + (10687, -1, -1, 602, 602, 15, 90, -1, 0, 0, 17, 10686, 13610), + (10688, -1, -1, 855, 855, 7, 86, -1, 0, 0, 17, 7677, 10689), + (10689, -1, -1, 855, 855, 7, 87, -1, 0, 0, 17, 10688, 10690), + (10690, -1, -1, 855, 855, 7, 88, -1, 0, 0, 17, 10689, 10691), + (10691, -1, -1, 855, 855, 7, 89, -1, 0, 0, 17, 10690, 10692), + (10692, -1, -1, 855, 855, 7, 90, -1, 0, 0, 17, 10691, 13613), + (10700, 10700, 10700, 10700, 10700, 7, 85, 16839, 61, 10, 16, -1, -1), + (10701, 10701, 10701, 10701, 10701, 7, 85, 21662, 32, 360, 16, -1, 10702), + (10702, 10701, 10701, 10701, 10701, 9, 85, 21663, 32, 360, 16, 10701, 10703), + (10703, 10701, 10701, 10701, 10701, 12, 85, 21664, 32, 360, 16, 10702, 12754), + (10704, 10394, 10394, 10394, 10394, 12, 85, 23541, 30, 300, 17, 10394, 13584), + (10705, -1, -1, 6395, 6395, 9, 86, -1, 0, 0, 17, 10052, 10706), + (10706, -1, -1, 6395, 6395, 9, 88, -1, 0, 0, 17, 10705, 10707), + (10707, -1, -1, 6395, 6395, 9, 90, -1, 0, 0, 17, 10706, 14097), + (10708, 534, 534, 534, 534, 12, 86, 23545, 4, 2160, 17, 10049, 10709), + (10709, 534, 534, 534, 534, 12, 88, 23546, 4, 2160, 17, 10708, 10710), + (10710, 534, 534, 534, 534, 12, 90, 23547, 4, 2160, 17, 10709, 13595), + (10711, 10711, 10711, 10711, 10711, 9, 86, 23548, 75, 1200, 17, -1, 10712), + (10712, 10711, 10711, 10711, 10711, 12, 88, 23549, 75, 1200, 17, 10711, 10713), + (10713, 10711, 10711, 10711, 10711, 15, 90, 23550, 75, 1200, 17, 10712, 14006), + (10714, -1, -1, 10714, 10714, 9, 86, 0, 0, 0, 17, -1, 10715), + (10715, -1, -1, 10714, 10714, 12, 88, 0, 0, 0, 17, 10714, 10716), + (10717, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 17, 7745, 10718), + (10718, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 17, 10717, 15258), + (10719, -1, -1, 10719, 10719, 9, 75, 0, 0, 0, 17, -1, 10720), + (10720, -1, -1, 10719, 10719, 12, 75, 0, 0, 0, 17, 10719, 10721), + (10721, -1, -1, 10719, 10719, 15, 75, 0, 0, 0, 17, 10720, 13562), + (10722, -1, -1, 10722, 10722, 5, 81, 0, 0, 0, 17, -1, 10723), + (10723, -1, -1, 10722, 10722, 5, 82, 0, 0, 0, 17, 10722, 10724), + (10724, -1, -1, 10722, 10722, 7, 83, 0, 0, 0, 17, 10723, 10725), + (10725, -1, -1, 10722, 10722, 9, 84, 0, 0, 0, 17, 10724, 10726), + (10726, -1, -1, 10722, 10722, 12, 85, 0, 0, 0, 17, 10725, 15280), + (10727, -1, -1, 10727, 10727, 7, 86, 0, 0, 0, 17, -1, 10728), + (10728, -1, -1, 10727, 10727, 9, 88, 0, 0, 0, 17, 10727, 10729), + (10730, -1, -1, 10730, 10730, 7, 86, 0, 0, 0, 17, -1, 10731), + (10731, -1, -1, 10730, 10730, 9, 88, 0, 0, 0, 17, 10730, 10732), + (10733, -1, -1, 10733, 10733, 7, 81, 0, 0, 0, 17, -1, 10734), + (10734, -1, -1, 10733, 10733, 9, 83, 0, 0, 0, 17, 10733, 10735), + (10735, -1, -1, 10733, 10733, 12, 85, 0, 0, 0, 17, 10734, -1), + (10736, 10736, 10736, 10736, 10736, 7, 86, 23632, 5, 180, 17, -1, 10737), + (10737, 10736, 10736, 10736, 10736, 9, 88, 23633, 5, 180, 17, 10736, 10738), + (10739, 645, -1, 645, 645, 12, 86, 23551, 4, 5, 17, 5999, 13410), + (10740, 1345, 1345, 1345, 1345, 9, 86, 23552, 6, 900, 17, 7349, 10741), + (10741, 1345, 1345, 1345, 1345, 12, 88, 23553, 6, 900, 17, 10740, 10742), + (10743, -1, -1, 1196, 1196, 5, 86, -1, 0, 0, 17, 1200, 10744), + (10744, -1, -1, 1196, 1196, 5, 87, -1, 0, 0, 17, 10743, 10745), + (10745, -1, -1, 1196, 1196, 5, 88, -1, 0, 0, 17, 10744, 10746), + (10748, -1, -1, 867, 867, 7, 86, -1, 0, 0, 17, 7366, 10749), + (10749, -1, -1, 867, 867, 7, 87, -1, 0, 0, 17, 10748, 10755), + (10750, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 16, 7328, 10751), + (10751, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 16, 10750, -1), + (10752, 10752, 10752, 10752, 10752, 6, 85, 16843, 72, 600, 16, -1, -1), + (10753, 10753, 10753, 10753, 10753, 12, 80, 16844, 6, 4320, 16, -1, -1), + (10754, 10754, 10754, 10754, 10754, 2, 70, 16845, 62, 5, 16, -1, -1), + (10755, -1, -1, 867, 867, 7, 88, -1, 0, 0, 17, 10749, 10756), + (10758, 545, 545, 545, 545, 12, 86, 23638, 3, 900, 17, 7346, 10759), + (10759, 545, 545, 545, 545, 12, 87, 23639, 3, 900, 17, 10758, 10760), + (10760, 545, 545, 545, 545, 12, 88, 23640, 3, 900, 17, 10759, 10761), + (10763, -1, -1, 6761, 6761, 12, 86, -1, 0, 0, 17, 6087, 10764), + (10764, -1, -1, 6761, 6761, 12, 88, -1, 0, 0, 17, 10763, 10765), + (10766, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 17, 10060, 10767), + (10767, -1, -1, 6765, 6765, 9, 87, -1, 0, 0, 17, 10766, 10768), + (10768, -1, -1, 6765, 6765, 9, 89, -1, 0, 0, 17, 10767, 13553), + (10769, -1, -1, 6751, 6751, 9, 86, -1, 0, 0, 17, 6769, 10770), + (10770, -1, -1, 6751, 6751, 9, 88, -1, 0, 0, 17, 10769, 10771), + (10772, 872, 872, 872, 872, 9, 85, 23555, 5, 180, 17, 7369, 10773), + (10773, 872, 872, 872, 872, 9, 87, 23556, 5, 180, 17, 10772, 10774), + (10774, 872, 872, 872, 872, 9, 89, 23557, 5, 180, 17, 10773, -1), + (10775, 875, 875, 875, 875, 9, 85, 23561, 5, 180, 17, 7372, 10776), + (10776, 875, 875, 875, 875, 9, 87, 23562, 5, 180, 17, 10775, 10777), + (10777, 875, 875, 875, 875, 9, 89, 23563, 5, 180, 17, 10776, 13536), + (10778, -1, -1, 634, 634, 12, 85, -1, 0, 0, 17, 7714, 10779), + (10779, -1, -1, 634, 634, 12, 87, -1, 0, 0, 17, 10778, 10780), + (10780, -1, -1, 634, 634, 12, 89, -1, 0, 0, 17, 10779, 15585), + (10781, -1, -1, 8240, 8240, 9, 85, -1, 0, 0, 17, 8244, 10782), + (10782, -1, -1, 8240, 8240, 9, 86, -1, 0, 0, 17, 10781, 10783), + (10783, -1, -1, 8240, 8240, 9, 87, -1, 0, 0, 17, 10782, 10784), + (10784, -1, -1, 8240, 8240, 9, 88, -1, 0, 0, 17, 10783, 10785), + (10785, -1, -1, 8240, 8240, 9, 89, -1, 0, 0, 17, 10784, 13343), + (10786, 7800, 7800, 7800, 7800, 12, 85, 23567, 39, 4320, 17, 7817, 10787), + (10787, 7800, 7800, 7800, 7800, 12, 87, 23568, 39, 4320, 17, 10786, 13619), + (10788, -1, -1, 4699, 4699, 7, 65, -1, 0, 0, 17, 7500, -1), + (10789, 10789, 10789, 10789, 10789, 15, 90, 23575, 41, 6, 17, -1, 14261), + (10790, 10396, 10396, 10396, 10396, 15, 90, 23576, 14, 600, 17, 10396, 14024), + (10791, 10397, 10397, 10397, 10397, 15, 90, 23577, 14, 600, 17, 10397, 14025), + (10792, -1, -1, 10792, 10792, 5, 86, 0, 0, 0, 17, -1, 10793), + (10793, -1, -1, 10792, 10792, 7, 87, 0, 0, 0, 17, 10792, 10794), + (10794, -1, -1, 10792, 10792, 9, 88, 0, 0, 0, 17, 10793, 10795), + (10795, -1, -1, 10792, 10792, 11, 89, 0, 0, 0, 17, 10794, 10796), + (10796, -1, -1, 10792, 10792, 13, 90, 0, 0, 0, 17, 10795, 17365), + (10800, -1, -1, 10800, 10800, 6, 70, -1, 0, 0, 16, -1, 10801), + (10801, -1, -1, 10800, 10800, 9, 70, -1, 0, 0, 16, 10800, 10802), + (10802, -1, -1, 10800, 10800, 12, 70, -1, 0, 0, 16, 10801, 17476), + (10803, -1, -1, 10803, 10803, 6, 76, -1, 0, 0, 16, -1, 10804), + (10804, -1, -1, 10803, 10803, 6, 78, -1, 0, 0, 16, 10803, 10805), + (10805, -1, -1, 10803, 10803, 6, 80, -1, 0, 0, 16, 10804, -1), + (10806, 10806, 10806, 10806, 10806, 10, 80, 16846, 71, 540, 16, -1, 10807), + (10807, 10806, 10806, 10806, 10806, 11, 80, 16847, 71, 540, 16, 10806, 10808), + (10808, 10806, 10806, 10806, 10806, 12, 80, 16848, 71, 540, 16, 10807, 15298), + (10809, 10809, 10809, 10809, 10809, 10, 80, 16849, 71, 540, 16, -1, 10810), + (10810, 10809, 10809, 10809, 10809, 11, 80, 16850, 71, 540, 16, 10809, 10811), + (10811, 10809, 10809, 10809, 10809, 12, 80, 16851, 71, 540, 16, 10810, 15301), + (10815, 10815, 10815, 10815, 10815, 6, 80, -1, 0, 0, 16, -1, 10816), + (10816, 10815, 10815, 10815, 10815, 9, 80, -1, 0, 0, 16, 10815, 10817), + (10817, 10815, 10815, 10815, 10815, 12, 80, -1, 0, 0, 16, 10816, 13110), + (10818, 10818, 10818, 10818, 10818, 6, 80, -1, 0, 0, 16, -1, 10819), + (10819, 10818, 10818, 10818, 10818, 9, 80, -1, 0, 0, 16, 10818, 10820), + (10820, 10818, 10818, 10818, 10818, 12, 80, -1, 0, 0, 16, 10819, 13113), + (10821, 10821, 10821, 10821, 10821, 6, 80, -1, 0, 0, 16, -1, 10822), + (10822, 10821, 10821, 10821, 10821, 9, 80, -1, 0, 0, 16, 10821, 10823), + (10823, 10821, 10821, 10821, 10821, 12, 80, -1, 0, 0, 16, 10822, 13116), + (10824, 510, 510, 510, 510, 6, 86, 23578, 37, 240, 17, 10104, 10825), + (10850, -1, -1, 10850, 10850, 6, 85, 16864, 0, 0, 16, -1, 10851), + (10851, -1, -1, 10850, 10850, 6, 85, 16865, 0, 0, 16, 10850, 10852), + (10852, -1, -1, 10850, 10850, 6, 85, 16866, 0, 0, 16, 10851, 13207), + (10853, -1, -1, 10853, 10853, 3, 65, -1, 0, 0, 16, -1, 10854), + (10854, -1, -1, 10853, 10853, 6, 65, -1, 0, 0, 16, 10853, 10855), + (10855, -1, -1, 10853, 10853, 9, 65, -1, 0, 0, 16, 10854, 10856), + (10856, -1, -1, 10853, 10853, 5, 66, -1, 0, 0, 16, 10855, 10857), + (10857, -1, -1, 10853, 10853, 5, 68, -1, 0, 0, 16, 10856, 10858), + (10858, -1, -1, 10853, 10853, 5, 70, -1, 0, 0, 16, 10857, 10859), + (10859, -1, -1, 10853, 10853, 5, 76, -1, 0, 0, 16, 10858, 10860), + (10860, -1, -1, 10853, 10853, 5, 78, -1, 0, 0, 16, 10859, 10861), + (10861, -1, -1, 10853, 10853, 5, 80, -1, 0, 0, 16, 10860, 10862), + (10862, -1, -1, 10853, 10853, 5, 81, -1, 0, 0, 16, 10861, 10863), + (10863, -1, -1, 10853, 10853, 5, 83, -1, 0, 0, 16, 10862, 10864), + (10864, -1, -1, 10853, 10853, 5, 85, -1, 0, 0, 16, 10863, 15954), + (10865, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 7150, 10866), + (10866, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 10865, 10867), + (10867, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 10866, 13218), + (10868, 5021, 5021, 5021, 5021, 9, 76, 16867, 7, 60, 16, 5021, 10869), + (10869, 5021, 5021, 5021, 5021, 9, 81, 16868, 7, 60, 16, 10868, 10870), + (10870, 5021, 5021, 5021, 5021, 9, 85, 16869, 7, 60, 16, 10869, 12618), + (10900, 10900, 10900, 10900, 10900, 9, 85, 16870, 55, 120, 16, -1, 10901), + (10901, 10900, 10900, 10900, 10900, 9, 85, 16871, 55, 120, 16, 10900, 10902), + (10902, 10900, 10900, 10900, 10900, 9, 85, 16872, 55, 120, 16, 10901, 13624), + (10903, -1, -1, 10903, 10903, 6, 81, -1, 0, 0, 16, -1, 10904), + (10904, -1, -1, 10903, 10903, 6, 83, -1, 0, 0, 16, 10903, 10905), + (10905, -1, -1, 10903, 10903, 6, 85, -1, 0, 0, 16, 10904, -1), + (10906, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 7406, 10907), + (10907, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 10906, 10908), + (10908, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 10907, 13627), + (10909, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, -1, 10910), + (10910, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, 10909, 10911), + (10911, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, 10910, -1), + (10912, 10912, 10912, 10912, 10912, 6, 85, 16873, 69, 1800, 16, -1, 10913), + (10913, 10912, 10912, 10912, 10912, 6, 85, 16874, 69, 1800, 16, 10912, 10914), + (10914, 10912, 10912, 10912, 10912, 6, 85, 16875, 69, 1800, 16, 10913, 14053), + (10915, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, -1, 10916), + (10916, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, 10915, 10917), + (10917, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, 10916, 16189), + (10950, -1, -1, 10950, 10950, 6, 85, -1, 0, 0, 16, -1, -1), + (10951, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, -1, 10952), + (10952, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, 10951, 10953), + (10953, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, 10952, 15363), + (10954, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, -1, 10955), + (10955, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, 10954, 10956), + (10956, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, 10955, -1), + (10957, 10957, 10957, 10957, 10957, 6, 85, 16879, 61, 5, 16, -1, -1), + (10958, 10958, 10958, 10958, 10958, 12, 85, 16880, 62, 900, 16, -1, 13000), + (10959, 10959, 10959, 10959, 10959, 12, 85, 16881, 63, 600, 16, -1, 10961), + (10961, 10959, 10959, 10959, 10959, 12, 85, 21717, 63, 600, 16, 10959, 10962), + (10962, 10959, 10959, 10959, 10959, 12, 85, 21718, 63, 600, 16, 10961, 12988), + (11000, -1, -1, 11000, 11000, 6, 85, -1, 0, 0, 16, -1, 11001), + (11001, -1, -1, 11000, 11000, 9, 85, -1, 0, 0, 16, 11000, 11002), + (11002, -1, -1, 11000, 11000, 12, 85, -1, 0, 0, 16, 11001, -1), + (11003, -1, -1, 11003, 11003, 6, 85, -1, 0, 0, 16, -1, -1), + (11004, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, -1, 11005), + (11005, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, 11004, 11006), + (11006, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, 11005, -1), + (11011, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 6304, 11012), + (11012, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 11011, 11013), + (11013, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 11012, 15552), + (11014, -1, -1, 11007, 11007, 5, 80, -1, 0, 0, 16, -1, 11015), + (11015, -1, -1, 11007, 11007, 7, 82, -1, 0, 0, 16, 11014, 11016), + (11016, -1, -1, 11007, 11007, 9, 85, -1, 0, 0, 16, 11015, 11020), + (11020, -1, -1, 11007, 11007, 12, 86, -1, 0, 0, 17, 11016, -1), + (11050, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, -1, 11051), + (11051, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11050, 11052), + (11052, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11051, 11059), + (11053, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 16, 7620, 11054), + (11054, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 16, 11053, -1), + (11055, 11055, 11055, 11055, 11055, 3, 85, 16884, 63, 20, 16, -1, -1), + (11056, 11056, 11056, 11056, 11056, 6, 85, 16885, 64, 180, 16, -1, -1), + (11057, 11057, 11057, 11057, 11057, 2, 85, 1422, 65, 10, 16, -1, -1), + (11058, 11058, 11058, 11058, 11058, 2, 85, 3243, 66, 10, 16, -1, -1), + (11059, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11052, 11060), + (11060, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11059, 12871), + (11061, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 7586, 11062), + (11062, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 11061, 11063), + (11063, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 11062, 13921), + (11064, 6290, 6290, 6290, 6290, 7, 85, 23500, 0, 1, 16, 7225, 11065), + (11065, 6290, 6290, 6290, 6290, 9, 85, 23501, 0, 1, 16, 11064, 11066), + (11066, 6290, 6290, 6290, 6290, 12, 85, 23502, 0, 1, 16, 11065, 13229), + (11067, 4944, -1, 4944, 4944, 7, 85, 23506, 0, 1, 16, 7231, 11068), + (11068, 4944, -1, 4944, 4944, 9, 85, 23507, 0, 1, 16, 11067, 11069), + (11069, 4944, -1, 4944, 4944, 12, 85, 23508, 0, 1, 16, 11068, 13232), + (11070, 1478, -1, 1478, 1478, 9, 85, 23512, 0, 1, 16, 7244, 11071), + (11071, 1478, -1, 1478, 1478, 10, 85, 23513, 0, 1, 16, 11070, 11072), + (11072, 1478, -1, 1478, 1478, 12, 85, 23514, 0, 1, 16, 11071, 13235), + (11073, 11073, 11073, 11073, 11073, 12, 85, 23518, 53, 30, 16, -1, 13447), + (11074, -1, -1, 11074, 11074, 5, 81, 0, 0, 0, 16, -1, 11075), + (11075, -1, -1, 11074, 11074, 7, 83, 0, 0, 0, 16, 11074, 11076), + (11076, -1, -1, 11074, 11074, 9, 85, 0, 0, 0, 16, 11075, -1), + (11077, -1, -1, 11077, 11077, 5, 81, 0, 0, 0, 16, -1, 15895), + (11078, -1, -1, 11078, 11078, 5, 81, 0, 0, 0, 16, -1, 15891), + (11079, -1, -1, 11079, 11079, 5, 81, 0, 0, 0, 16, -1, 15893), + (11080, 11080, 11080, 11080, 11080, 7, 85, 23519, 10, 20, 16, -1, 13472), + (11081, 153, 153, 153, 153, 12, 85, 23599, 3, 2160, 16, 10193, 12996), + (11082, -1, -1, 1131, 1131, 6, 81, -1, 0, 0, 16, 1133, 11083), + (11083, -1, -1, 1131, 1131, 9, 83, -1, 0, 0, 16, 11082, 11084), + (11084, -1, -1, 1131, 1131, 12, 85, -1, 0, 0, 16, 11083, 13032), + (11085, -1, -1, 11085, 11085, 7, 85, 0, 0, 0, 16, -1, 11086), + (11086, -1, -1, 11085, 11085, 9, 85, 0, 0, 0, 16, 11085, 11087), + (11087, -1, -1, 11085, 11085, 12, 85, 0, 0, 0, 16, 11086, 13021), + (11088, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, -1, 11089), + (11089, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11088, 11090), + (11090, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11089, 11091), + (11091, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11090, -1), + (12396, -1, -1, 125, 125, 8, 85, -1, 0, 0, 16, 7505, 12397), + (12397, -1, -1, 125, 125, 9, 85, -1, 0, 0, 16, 12396, 12398), + (12398, -1, -1, 125, 125, 10, 85, -1, 0, 0, 16, 12397, 12399), + (12399, -1, -1, 125, 125, 11, 85, -1, 0, 0, 16, 12398, 12400), + (12400, -1, -1, 125, 125, 12, 85, -1, 0, 0, 16, 12399, 13080), + (12401, -1, -1, 122, 122, 8, 85, -1, 0, 0, 16, 7510, 12402), + (12402, -1, -1, 122, 122, 9, 85, -1, 0, 0, 16, 12401, 12403), + (12403, -1, -1, 122, 122, 10, 85, -1, 0, 0, 16, 12402, 12404), + (12404, -1, -1, 122, 122, 11, 85, -1, 0, 0, 16, 12403, 12405), + (12405, -1, -1, 122, 122, 12, 85, -1, 0, 0, 16, 12404, 13085), + (12406, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 7530, 12407), + (12407, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12406, 12408), + (12408, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12407, 12409), + (12409, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12408, 12410), + (12410, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12409, 12492), + (12411, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 8259, 12412), + (12412, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12411, 12413), + (12413, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12412, 12414), + (12414, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12413, 12415), + (12415, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12414, 13358), + (12416, -1, -1, 12416, 12416, 7, 83, -1, 0, 0, 16, -1, 12417), + (12417, -1, -1, 12416, 12416, 9, 84, -1, 0, 0, 16, 12416, 12418), + (12418, -1, -1, 12416, 12416, 12, 85, -1, 0, 0, 16, 12417, 13413), + (12419, -1, -1, 12419, 12419, 5, 83, -1, 0, 0, 16, -1, 12420), + (12420, -1, -1, 12419, 12419, 5, 84, -1, 0, 0, 16, 12419, 12421), + (12421, -1, -1, 12419, 12419, 5, 85, -1, 0, 0, 16, 12420, 12575), + (12422, 12422, 12422, 12422, 12422, 12, 85, 13994, 47, 12, 16, -1, -1), + (12423, -1, -1, 767, 767, 9, 81, -1, 0, 0, 16, 1101, 12424), + (12424, -1, -1, 767, 767, 10, 83, -1, 0, 0, 16, 12423, 12425), + (12425, -1, -1, 767, 767, 12, 85, -1, 0, 0, 16, 12424, -1), + (12426, -1, -1, 767, 767, 3, 81, -1, 0, 0, 16, 6245, 12427), + (12427, -1, -1, 767, 767, 6, 83, -1, 0, 0, 16, 12426, 12428), + (12428, -1, -1, 767, 767, 9, 85, -1, 0, 0, 16, 12427, -1), + (12432, -1, -1, 1107, 1107, 10, 81, -1, 0, 0, 16, 6405, 12433), + (12433, -1, -1, 1107, 1107, 11, 83, -1, 0, 0, 16, 12432, 12434), + (12434, -1, -1, 1107, 1107, 12, 85, -1, 0, 0, 16, 12433, 12556), + (12435, -1, -1, 637, 637, 8, 81, -1, 0, 0, 16, 5573, 12436), + (12436, -1, -1, 637, 637, 10, 83, -1, 0, 0, 16, 12435, 12437), + (12437, -1, -1, 637, 637, 12, 85, -1, 0, 0, 16, 12436, 12553), + (12438, -1, -1, 686, 686, 5, 85, -1, 0, 0, 16, 7640, -1), + (12439, -1, -1, 1592, 1592, 9, 85, -1, 0, 0, 16, 7572, 12440), + (12440, -1, -1, 1592, 1592, 10, 85, -1, 0, 0, 16, 12439, 12441), + (12441, -1, -1, 1592, 1592, 11, 85, -1, 0, 0, 16, 12440, 12442), + (12442, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 16, 12441, 12443), + (12443, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 16, 12442, 12532), + (12444, -1, -1, 1072, 1072, 8, 85, -1, 0, 0, 16, 7580, 12445), + (12445, -1, -1, 1072, 1072, 9, 85, -1, 0, 0, 16, 12444, 12446), + (12446, -1, -1, 1072, 1072, 10, 85, -1, 0, 0, 16, 12445, 12447), + (12447, -1, -1, 1072, 1072, 11, 85, -1, 0, 0, 16, 12446, 12448), + (12448, -1, -1, 1072, 1072, 12, 85, -1, 0, 0, 16, 12447, 12537), + (12449, -1, -1, 77, 77, 10, 81, -1, 0, 0, 16, 1085, 12450), + (12450, -1, -1, 77, 77, 11, 83, -1, 0, 0, 16, 12449, 12451), + (12451, -1, -1, 77, 77, 12, 85, -1, 0, 0, 16, 12450, 12497), + (12452, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 7592, 12453), + (12453, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 12452, 12454), + (12454, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 12453, 12567), + (12455, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 7597, 12456), + (12456, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12455, 12457), + (12457, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12456, 12458), + (12458, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12457, 12459), + (12459, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12458, 12570), + (12460, 6537, 6537, 6537, 6537, 7, 83, 20172, 30, 900, 16, 7608, 12461), + (12461, 6537, 6537, 6537, 6537, 8, 83, 20173, 30, 900, 16, 12460, 12462), + (12462, 6537, 6537, 6537, 6537, 9, 83, 20174, 30, 900, 16, 12461, 12520), + (12463, -1, -1, 5263, 5263, 7, 81, -1, 0, 0, 16, 6129, 12464), + (12464, -1, -1, 5263, 5263, 8, 81, -1, 0, 0, 16, 12463, 12465), + (12465, -1, -1, 5263, 5263, 9, 81, -1, 0, 0, 16, 12464, 16173), + (12466, -1, -1, 5263, 5263, 7, 81, -1, 0, 0, 16, 5622, 12467), + (12467, -1, -1, 5263, 5263, 9, 81, -1, 0, 0, 16, 12466, 12468), + (12468, -1, -1, 5263, 5263, 12, 81, -1, 0, 0, 16, 12467, 15714), + (12469, -1, -1, 1287, 1287, 7, 81, -1, 0, 0, 16, 5518, 12470), + (12470, -1, -1, 1287, 1287, 9, 81, -1, 0, 0, 16, 12469, 12471), + (12471, -1, -1, 1287, 1287, 12, 81, -1, 0, 0, 16, 12470, 10637), + (12472, -1, -1, 1287, 1287, 8, 81, -1, 0, 0, 16, 6430, 12473), + (12473, -1, -1, 1287, 1287, 9, 81, -1, 0, 0, 16, 12472, 12474), + (12474, -1, -1, 1287, 1287, 10, 81, -1, 0, 0, 16, 12473, 13238), + (12475, -1, -1, 12430, 12430, 5, 85, 0, 0, 0, 16, -1, 12476), + (12476, -1, -1, 12430, 12430, 7, 85, 0, 0, 0, 16, 12475, 12477), + (12477, -1, -1, 12430, 12430, 9, 85, 0, 0, 0, 16, 12476, 12876), + (12478, -1, -1, 12478, 12478, 5, 85, 0, 0, 0, 16, -1, 12479), + (12479, -1, -1, 12478, 12478, 7, 85, 0, 0, 0, 16, 12478, 12480), + (12480, -1, -1, 12478, 12478, 9, 85, 0, 0, 0, 16, 12479, -1), + (12481, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6473, 12482), + (12482, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12481, 12508), + (12483, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6475, 12484), + (12484, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12483, 12511), + (12485, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6477, 12486), + (12486, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12485, 12514), + (12487, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 16, 6471, 12488), + (12488, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12487, 12517), + (12492, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 17, 12410, 12493), + (12493, -1, -1, 6119, 6119, 6, 86, -1, 0, 0, 17, 12492, 12494), + (12494, -1, -1, 6119, 6119, 6, 87, -1, 0, 0, 17, 12493, 12495), + (12495, -1, -1, 6119, 6119, 6, 88, -1, 0, 0, 17, 12494, 12496), + (12496, -1, -1, 6119, 6119, 6, 89, -1, 0, 0, 17, 12495, 8448), + (12497, -1, -1, 77, 77, 12, 86, -1, 0, 0, 17, 12451, 12498), + (12498, -1, -1, 77, 77, 12, 88, -1, 0, 0, 17, 12497, 12499), + (12499, -1, -1, 77, 77, 12, 90, -1, 0, 0, 17, 12498, 13296), + (12500, -1, -1, 12500, 12500, 5, 81, -1, 0, 0, 16, -1, 12501), + (12501, -1, -1, 12500, 12500, 7, 81, -1, 0, 0, 16, 12500, 12502), + (12502, -1, -1, 12500, 12500, 9, 81, -1, 0, 0, 16, 12501, 12505), + (12505, -1, -1, 12500, 12500, 11, 83, -1, 0, 0, 16, 12502, 12506), + (12506, -1, -1, 12500, 12500, 12, 85, -1, 0, 0, 16, 12505, -1), + (12507, -1, -1, 199, 199, 12, 81, -1, 0, 0, 16, 201, -1), + (12508, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12482, 12509), + (12509, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12508, 12510), + (12510, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12509, 16440), + (12511, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12484, 12512), + (12512, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12511, 12513), + (12513, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12512, 12591), + (12514, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12486, 12515), + (12515, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12514, 12516), + (12516, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12515, 12594), + (12517, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12488, 12518), + (12518, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12517, 12519), + (12519, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12518, 12597), + (12520, 6537, 6537, 6537, 6537, 7, 86, 23974, 30, 900, 17, 12462, 12521), + (12521, 6537, 6537, 6537, 6537, 8, 88, 23975, 30, 900, 17, 12520, 12522), + (12522, 6537, 6537, 6537, 6537, 9, 90, 23976, 30, 900, 17, 12521, 13275), + (12523, -1, -1, 1210, 1210, 7, 86, -1, 0, 0, 17, 7234, 12524), + (12526, -1, -1, 1210, 1213, 12, 86, -1, 0, 0, 17, 8346, 12527), + (12527, -1, -1, 1210, 1213, 12, 88, -1, 0, 0, 17, 12526, 12528), + (12528, -1, -1, 1210, 1213, 12, 90, -1, 0, 0, 17, 12527, 14349), + (12529, -1, -1, 6636, 6636, 9, 86, -1, 0, 0, 17, 10043, 12530), + (12530, -1, -1, 6636, 6636, 10, 88, -1, 0, 0, 17, 12529, 12531), + (12531, -1, -1, 6636, 6636, 11, 90, -1, 0, 0, 17, 12530, 16164), + (12532, -1, -1, 1592, 1592, 9, 86, -1, 0, 0, 17, 12443, 12533), + (12533, -1, -1, 1592, 1592, 10, 87, -1, 0, 0, 17, 12532, 12534), + (12534, -1, -1, 1592, 1592, 11, 88, -1, 0, 0, 17, 12533, 12535), + (12535, -1, -1, 1592, 1592, 12, 89, -1, 0, 0, 17, 12534, 12536), + (12536, -1, -1, 1592, 1592, 12, 90, -1, 0, 0, 17, 12535, 13930), + (12537, -1, -1, 1072, 1072, 8, 86, -1, 0, 0, 17, 12448, 12538), + (12538, -1, -1, 1072, 1072, 9, 87, -1, 0, 0, 17, 12537, 12539), + (12539, -1, -1, 1072, 1072, 10, 88, -1, 0, 0, 17, 12538, 12540), + (12540, -1, -1, 1072, 1072, 11, 89, -1, 0, 0, 17, 12539, 12541), + (12541, -1, -1, 1072, 1072, 12, 90, -1, 0, 0, 17, 12540, 13281), + (12548, -1, -1, 119, 119, 12, 86, -1, 0, 0, 17, 6025, 12549), + (12549, -1, -1, 119, 119, 12, 87, -1, 0, 0, 17, 12548, 12550), + (12550, -1, -1, 119, 119, 12, 88, -1, 0, 0, 17, 12549, 12551), + (12551, -1, -1, 119, 119, 12, 89, -1, 0, 0, 17, 12550, 12552), + (12552, -1, -1, 119, 119, 12, 90, -1, 0, 0, 17, 12551, 13286), + (12553, -1, -1, 637, 637, 8, 86, -1, 0, 0, 17, 12437, 12554), + (12554, -1, -1, 637, 637, 10, 88, -1, 0, 0, 17, 12553, 12555), + (12555, -1, -1, 637, 637, 12, 90, -1, 0, 0, 17, 12554, 14361), + (12556, -1, -1, 1107, 1107, 10, 86, -1, 0, 0, 17, 12434, 12557), + (12557, -1, -1, 1107, 1107, 11, 88, -1, 0, 0, 17, 12556, 12558), + (12558, -1, -1, 1107, 1107, 12, 90, -1, 0, 0, 17, 12557, 16489), + (12559, -1, -1, 8215, 8215, 5, 86, -1, 0, 0, 17, 8219, 12560), + (12560, -1, -1, 8215, 8215, 5, 87, -1, 0, 0, 17, 12559, 12561), + (12561, -1, -1, 8215, 8215, 5, 88, -1, 0, 0, 17, 12560, 12562), + (12562, -1, -1, 8215, 8215, 5, 89, -1, 0, 0, 17, 12561, 12563), + (12563, -1, -1, 8215, 8215, 5, 90, -1, 0, 0, 17, 12562, 15694), + (12564, -1, -1, 1186, 1186, 12, 86, -1, 0, 0, 17, 7694, 12565), + (12565, -1, -1, 1186, 1186, 12, 88, -1, 0, 0, 17, 12564, 12566), + (12566, -1, -1, 1186, 1186, 12, 90, -1, 0, 0, 17, 12565, 13299), + (12567, -1, -1, 80, 80, 12, 86, -1, 0, 0, 17, 12454, 12568), + (12568, -1, -1, 80, 80, 12, 88, -1, 0, 0, 17, 12567, 12569), + (12569, -1, -1, 80, 80, 12, 90, -1, 0, 0, 17, 12568, 13302), + (12570, -1, -1, 658, 658, 5, 86, -1, 0, 0, 17, 12459, 12571), + (12571, -1, -1, 658, 658, 5, 87, -1, 0, 0, 17, 12570, 12572), + (12572, -1, -1, 658, 658, 5, 88, -1, 0, 0, 17, 12571, 12573), + (12573, -1, -1, 658, 658, 5, 89, -1, 0, 0, 17, 12572, 12574), + (12574, -1, -1, 658, 658, 5, 90, -1, 0, 0, 17, 12573, 13313), + (12575, -1, -1, 12419, 12419, 9, 90, -1, 0, 0, 17, 12421, 13520), + (12576, -1, -1, 852, 852, 12, 86, -1, 0, 0, 17, 7680, 12577), + (12577, -1, -1, 852, 852, 12, 88, -1, 0, 0, 17, 12576, 12578), + (12578, -1, -1, 852, 852, 12, 90, -1, 0, 0, 17, 12577, 13601), + (12579, -1, -1, 1313, 1313, 12, 86, -1, 0, 0, 17, 10083, 12580), + (12580, -1, -1, 1313, 1313, 12, 88, -1, 0, 0, 17, 12579, 12581), + (12581, -1, -1, 1313, 1313, 12, 90, -1, 0, 0, 17, 12580, 14043), + (12582, -1, -1, 12582, 12582, 7, 85, 0, 0, 0, 17, -1, 12583), + (12583, -1, -1, 12582, 12582, 9, 87, 0, 0, 0, 17, 12582, 12584), + (12584, -1, -1, 12582, 12582, 12, 89, 0, 0, 0, 17, 12583, 15174), + (12585, 6640, 6640, 6640, 6640, 9, 86, 23572, 43, 60, 17, 6640, -1), + (12586, 6644, 6644, 6644, 6644, 2, 86, 23573, 44, 20, 17, 6644, -1), + (12587, -1, -1, 7757, 7757, 9, 86, -1, 0, 0, 17, 7759, 12588), + (12588, -1, -1, 7757, 7757, 9, 88, -1, 0, 0, 17, 12587, 12589), + (12589, -1, -1, 7757, 7757, 9, 90, -1, 0, 0, 17, 12588, 15182), + (12590, 10395, 10395, 10395, 10395, 5, 85, 23574, 62, 5, 17, 10395, -1), + (12591, -1, -1, 6540, 6540, 15, 91, -1, 0, 0, 18, 12513, 12592), + (12594, -1, -1, 6540, 6540, 11, 91, -1, 0, 0, 18, 12516, 12595), + (12597, -1, -1, 6540, 6540, 9, 91, -1, 0, 0, 18, 12519, 12598), + (12598, -1, -1, 6540, 6540, 11, 93, -1, 0, 0, 18, 12597, 12599), + (12600, -1, -1, 12600, 12600, 7, 85, 0, 0, 0, 17, -1, 13072), + (12603, -1, -1, 12603, 12603, 10, 70, 0, 0, 0, 17, -1, -1), + (12606, -1, -1, 12606, 12606, 6, 85, 0, 0, 0, 17, -1, -1), + (12607, -1, -1, 12607, 12607, 6, 74, 0, 0, 0, 17, -1, 14140), + (12610, -1, -1, 255, 255, 9, 87, -1, 0, 0, 17, 7702, 13773), + (12612, -1, -1, 1604, 1604, 10, 85, -1, 0, 0, 17, 7009, 12613), + (12613, -1, -1, 1604, 1604, 12, 87, -1, 0, 0, 17, 12612, 13095), + (12615, -1, -1, 12615, 12615, 10, 85, 0, 0, 0, 17, -1, 12616), + (12616, -1, -1, 12615, 12615, 12, 87, 0, 0, 0, 17, 12615, 12617), + (12617, -1, -1, 12615, 12615, 14, 89, 0, 0, 0, 17, 12616, 14138), + (12618, 5021, 5021, 5021, 5021, 9, 86, 24009, 7, 60, 17, 10870, 12619), + (12619, 5021, 5021, 5021, 5021, 9, 87, 24010, 7, 60, 17, 12618, 12620), + (12620, 5021, 5021, 5021, 5021, 9, 88, 24011, 7, 60, 17, 12619, 12621), + (12621, 5021, 5021, 5021, 5021, 9, 89, 24012, 7, 60, 17, 12620, 13785), + (12626, 9354, 9354, 9354, 9354, 5, 86, 23996, 40, 600, 17, 9356, -1), + (12629, 9357, 9357, 9357, 9357, 5, 86, 24002, 40, 600, 17, 9359, -1), + (12632, 9360, 9360, 9360, 9360, 5, 86, 24005, 40, 600, 17, 9362, -1), + (12633, 6325, 6325, 6325, 6325, 7, 85, 24008, 18, 600, 17, 6361, 13792), + (12635, 12635, 12635, 12635, 12635, 12, 90, 23643, 12, 5, 17, -1, -1), + (12636, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, -1, 12637), + (12637, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 12636, 8445), + (12638, 12638, 12638, 12638, 12638, 9, 85, 23581, 68, 10, 17, -1, -1), + (12639, -1, -1, 10514, 10514, 6, 86, -1, 0, 0, 17, 10515, 12640), + (12642, -1, -1, 10511, 10511, 6, 86, -1, 0, 0, 17, 10513, 12643), + (12645, -1, -1, 12645, 12645, 9, 90, 0, 0, 0, 17, -1, 15386), + (12646, -1, -1, 12646, 12646, 9, 90, 0, 0, 0, 17, -1, 15388), + (12647, 10502, -1, 10502, 10502, 7, 90, 16815, 64, 120, 17, 10502, -1), + (12648, 10503, 10503, 10503, 10503, 9, 86, 23582, 13, 600, 17, 10505, 12649), + (12651, 12651, 12651, 12651, 12651, 15, 90, 23585, 69, 600, 17, -1, 17352), + (12652, -1, -1, 12652, 12652, 9, 86, 0, 0, 0, 17, -1, 12653), + (12653, -1, -1, 12652, 12652, 12, 88, 0, 0, 0, 17, 12652, 12654), + (12654, -1, -1, 12652, 12652, 15, 90, 0, 0, 0, 17, 12653, 13411), + (12655, 12655, 12655, 12655, 12655, 9, 86, 23586, 70, 1800, 17, -1, 12656), + (12658, 757, -1, 757, 757, 12, 86, 23589, 6, 1800, 17, 7413, 12659), + (12661, 12661, 12661, 12661, 12661, 9, 86, 23592, 73, 2700, 17, -1, 12662), + (12664, -1, -1, 12664, 12664, 7, 86, 0, 0, 0, 17, -1, 12665), + (12667, -1, -1, 820, 820, 5, 86, -1, 0, 0, 17, 10662, 12668), + (12668, -1, -1, 820, 820, 5, 88, -1, 0, 0, 17, 12667, 12669), + (12669, -1, -1, 820, 820, 5, 90, -1, 0, 0, 17, 12668, 13820), + (12670, -1, -1, 6020, 6020, 2, 86, -1, 0, 0, 17, 10665, 12671), + (12671, -1, -1, 6020, 6020, 2, 87, -1, 0, 0, 17, 12670, 12672), + (12672, -1, -1, 6020, 6020, 2, 88, -1, 0, 0, 17, 12671, 12692), + (12673, -1, -1, 1546, 1546, 5, 80, -1, 0, 0, 17, 6441, -1), + (12674, -1, -1, 4801, 4801, 6, 86, -1, 0, 0, 17, 10123, 12675), + (12675, -1, -1, 4801, 4801, 6, 88, -1, 0, 0, 17, 12674, 12676), + (12676, -1, -1, 4801, 4801, 6, 90, -1, 0, 0, 17, 12675, -1), + (12677, -1, -1, 230, 230, 6, 90, -1, 0, 0, 17, 541, 16249), + (12678, -1, -1, 10656, 10656, 12, 90, 0, 0, 0, 17, 10656, -1), + (12679, -1, -1, 10657, 10657, 7, 86, 0, 0, 0, 17, 10659, 12680), + (12680, -1, -1, 10657, 10657, 9, 88, 0, 0, 0, 17, 12679, 12681), + (12681, -1, -1, 10657, 10657, 12, 90, 0, 0, 0, 17, 12680, 14154), + (12682, 7872, 7872, 7872, 7872, 6, 86, 23595, 41, 600, 17, 10129, 12683), + (12683, 7872, 7872, 7872, 7872, 6, 88, 23596, 41, 600, 17, 12682, 12684), + (12684, 7872, 7872, 7872, 7872, 6, 90, 23597, 41, 600, 17, 12683, 13838), + (12685, -1, -1, 807, 807, 5, 86, -1, 0, 0, 17, 7630, 12686), + (12686, -1, -1, 807, 807, 5, 88, -1, 0, 0, 17, 12685, 12687), + (12687, -1, -1, 807, 807, 5, 90, -1, 0, 0, 17, 12686, -1), + (12688, -1, -1, 12688, 12688, 12, 90, 0, 0, 0, 17, -1, -1), + (12689, -1, -1, 7884, 7884, 12, 87, -1, 0, 0, 17, 7884, -1), + (12690, -1, -1, 7885, 7885, 12, 86, -1, 0, 0, 17, 7885, -1), + (12691, -1, -1, 12691, 12691, 12, 88, 0, 0, 0, 17, -1, -1), + (12692, -1, -1, 6020, 6020, 2, 89, -1, 0, 0, 17, 12672, 12693), + (12693, -1, -1, 6020, 6020, 2, 90, -1, 0, 0, 17, 12692, 13823), + (12694, -1, -1, 683, 683, 5, 86, -1, 0, 0, 17, 7605, 12695), + (12695, -1, -1, 683, 683, 5, 88, -1, 0, 0, 17, 12694, 12696), + (12696, -1, -1, 683, 683, 5, 90, -1, 0, 0, 17, 12695, 13305), + (12697, -1, -1, 1041, 1041, 12, 86, -1, 0, 0, 17, 7564, 12698), + (12698, -1, -1, 1041, 1041, 12, 88, -1, 0, 0, 17, 12697, 12699), + (12699, -1, -1, 1041, 1041, 12, 90, -1, 0, 0, 17, 12698, 13332), + (12700, 1355, 1355, 1355, 1355, 9, 86, 23644, 3, 60, 17, 10121, 12701), + (12701, 1355, 1355, 1355, 1355, 9, 88, 23645, 3, 60, 17, 12700, 12702), + (12702, 1355, 1355, 1355, 1355, 9, 90, 23646, 3, 60, 17, 12701, 13832), + (12703, -1, -1, 611, 611, 4, 86, -1, 0, 0, 17, 10126, 12704), + (12704, -1, -1, 611, 611, 4, 88, -1, 0, 0, 17, 12703, 12705), + (12705, -1, -1, 611, 611, 4, 90, -1, 0, 0, 17, 12704, 13835), + (12706, -1, -1, 12706, 12706, 7, 86, 0, 0, 0, 17, -1, 12707), + (12707, -1, -1, 12706, 12706, 9, 88, 0, 0, 0, 17, 12706, 12708), + (12708, -1, -1, 12706, 12706, 12, 90, 0, 0, 0, 17, 12707, 13813), + (12709, -1, -1, 12709, 12709, 9, 86, -1, 0, 0, 17, -1, -1), + (12710, -1, -1, 12710, 12710, 9, 86, 0, 0, 0, 17, -1, 12711), + (12711, -1, -1, 12710, 12710, 12, 88, 0, 0, 0, 17, 12710, 12712), + (12712, -1, -1, 12710, 12710, 15, 90, 0, 0, 0, 17, 12711, 14173), + (12713, -1, -1, 12713, 12713, 7, 86, 0, 0, 0, 17, -1, 12714), + (12714, -1, -1, 12713, 12713, 7, 88, 0, 0, 0, 17, 12713, 12715), + (12715, -1, -1, 12713, 12713, 7, 90, 0, 0, 0, 17, 12714, -1), + (12716, -1, -1, 12716, 12716, 7, 86, 0, 0, 0, 17, -1, 12717), + (12717, -1, -1, 12716, 12716, 7, 88, 0, 0, 0, 17, 12716, 12718), + (12718, -1, -1, 12716, 12716, 7, 90, 0, 0, 0, 17, 12717, 15526), + (12719, -1, -1, 12719, 12719, 9, 90, 0, 0, 0, 17, -1, -1), + (12720, -1, -1, 12720, 12720, 9, 86, 0, 0, 0, 17, -1, -1), + (12721, -1, -1, 12721, 12721, 7, 86, 0, 0, 0, 17, -1, 12722), + (12722, -1, -1, 12721, 12721, 9, 88, 0, 0, 0, 17, 12721, 12723), + (12723, -1, -1, 12721, 12721, 12, 90, 0, 0, 0, 17, 12722, 16303), + (12724, 10333, 10333, 10333, 10333, 9, 86, 23647, 55, 120, 17, 10335, 12725), + (12725, 10333, 10333, 10333, 10333, 9, 86, 23648, 55, 120, 17, 12724, 12726), + (12726, 10333, 10333, 10333, 10333, 9, 86, 23649, 55, 120, 17, 12725, 15988), + (12727, -1, -1, 1555, 1555, 7, 86, 0, 0, 0, 17, 1557, 12728), + (12728, -1, -1, 1555, 1555, 7, 88, 0, 0, 0, 17, 12727, 12729), + (12729, -1, -1, 1555, 1555, 7, 90, 0, 0, 0, 17, 12728, -1), + (12730, 10336, 10336, 10336, 10336, 9, 86, 23650, 58, 8, 17, 10338, 12731), + (12731, 10336, 10336, 10336, 10336, 12, 88, 23651, 58, 8, 17, 12730, 12732), + (12732, 10336, 10336, 10336, 10336, 15, 90, 23652, 58, 8, 17, 12731, 13517), + (12733, -1, -1, 10332, 10332, 7, 90, -1, 0, 0, 17, 10332, -1), + (12734, -1, -1, 6375, 6375, 9, 86, -1, 0, 0, 17, 10138, 12735), + (12735, -1, -1, 6375, 6375, 9, 88, -1, 0, 0, 17, 12734, 12736), + (12736, -1, -1, 6375, 6375, 9, 90, -1, 0, 0, 17, 12735, 13502), + (12737, -1, -1, 12737, 12737, 9, 86, 0, 0, 0, 17, -1, 12738), + (12738, -1, -1, 12737, 12737, 9, 88, 0, 0, 0, 17, 12737, 12739), + (12739, -1, -1, 12737, 12737, 9, 90, 0, 0, 0, 17, 12738, 15961), + (12740, 6533, 6533, 6533, 6533, 10, 86, 23653, 15, 600, 17, 10139, 12741), + (12741, 6533, 6533, 6533, 6533, 10, 88, 23654, 15, 600, 17, 12740, 12742), + (12742, 6533, 6533, 6533, 6533, 10, 90, 23655, 15, 600, 17, 12741, 13505), + (12743, 1116, 1116, 1116, 1116, 12, 86, 23656, 4, 2160, 17, 10142, 12744), + (12744, 1116, 1116, 1116, 1116, 12, 88, 23657, 4, 2160, 17, 12743, 12745), + (12745, 1116, 1116, 1116, 1116, 12, 90, 23658, 4, 2160, 17, 12744, 13530), + (12746, 5298, 5298, 5298, 5298, 12, 86, 23659, 32, 1800, 17, 10145, 12747), + (12747, 5298, 5298, 5298, 5298, 12, 88, 23660, 32, 1800, 17, 12746, 12748), + (12748, 5298, 5298, 5298, 5298, 12, 90, 23661, 32, 1800, 17, 12747, 13514), + (12749, 592, 592, 592, 592, 5, 86, 23665, 2, 18, 17, 7437, 12750), + (12750, 592, 592, 592, 592, 5, 88, 23666, 2, 18, 17, 12749, 12751), + (12751, 592, 592, 592, 592, 5, 90, 23667, 2, 18, 17, 12750, 13499), + (12754, 10701, 10701, 10701, 10701, 12, 86, 23668, 32, 360, 17, 10703, 12755), + (12755, 10701, 10701, 10701, 10701, 12, 88, 23669, 32, 360, 17, 12754, 12756), + (12756, 10701, 10701, 10701, 10701, 12, 90, 23670, 32, 360, 17, 12755, 15588), + (12757, -1, -1, 4861, 4861, 12, 86, -1, 0, 0, 17, 7682, 12758), + (12758, -1, -1, 4861, 4861, 12, 88, -1, 0, 0, 17, 12757, 12759), + (12759, -1, -1, 4861, 4861, 12, 90, -1, 0, 0, 17, 12758, -1), + (12760, 1274, 1274, 1274, 1274, 12, 86, 23674, 9, 540, 17, 10211, 12761), + (12761, 1274, 1274, 1274, 1274, 12, 88, 23675, 9, 540, 17, 12760, 12762), + (12762, 1274, 1274, 1274, 1274, 12, 90, 23676, 9, 540, 17, 12761, 14352), + (12766, 12766, 12766, 12766, 12766, 15, 90, 23677, 69, 3600, 17, -1, 13682), + (12767, -1, -1, 692, 692, 12, 86, -1, 0, 0, 17, 7672, 12768), + (12768, -1, -1, 692, 692, 12, 88, -1, 0, 0, 17, 12767, 12769), + (12769, -1, -1, 692, 692, 12, 90, -1, 0, 0, 17, 12768, 17295), + (12770, 12770, 12770, 12770, 12770, 9, 85, 23678, 52, 120, 17, -1, 12771), + (12771, 12770, 12770, 12770, 12770, 12, 87, 23679, 52, 120, 17, 12770, 12772), + (12772, 12770, 12770, 12770, 12770, 15, 89, 23680, 52, 120, 17, 12771, -1), + (12773, -1, -1, 12773, 12773, 7, 86, 0, 0, 0, 17, -1, 12774), + (12774, -1, -1, 12773, 12773, 7, 87, 0, 0, 0, 17, 12773, 12775), + (12775, -1, -1, 12773, 12773, 7, 88, 0, 0, 0, 17, 12774, 12776), + (12776, -1, -1, 12773, 12773, 7, 89, 0, 0, 0, 17, 12775, 12777), + (12777, -1, -1, 12773, 12773, 7, 90, 0, 0, 0, 17, 12776, -1), + (12778, 12778, 12778, 12778, 12778, 12, 90, 23681, 74, 1200, 17, -1, 13678), + (12779, -1, -1, 12779, 12779, 7, 85, 0, 0, 0, 17, -1, 12780), + (12780, -1, -1, 12779, 12779, 9, 87, 0, 0, 0, 17, 12779, 12781), + (12781, -1, -1, 12779, 12779, 12, 89, 0, 0, 0, 17, 12780, -1), + (12782, -1, -1, 12782, 12782, 7, 86, 0, 0, 0, 17, -1, 12783), + (12783, -1, -1, 12782, 12782, 9, 88, 0, 0, 0, 17, 12782, 12784), + (12784, -1, -1, 12782, 12782, 12, 90, 0, 0, 0, 17, 12783, -1), + (12785, 12785, 12785, 12785, 12785, 12, 90, 23683, 80, 30, 17, -1, 17131), + (12786, 6815, 6815, 6815, 6815, 8, 86, 23684, 60, 600, 17, 10202, 12787), + (12787, 6815, 6815, 6815, 6815, 8, 88, 23685, 60, 600, 17, 12786, 12788), + (12788, 6815, 6815, 6815, 6815, 8, 90, 23686, 60, 600, 17, 12787, 14355), + (12789, 967, 967, 967, 967, 7, 85, 23687, 10, 1800, 17, 10226, 12790), + (12790, 967, 967, 967, 967, 7, 87, 23688, 10, 1800, 17, 12789, 12791), + (12791, 967, 967, 967, 967, 7, 89, 23689, 10, 1800, 17, 12790, 17535), + (12792, -1, -1, 9503, 9503, 7, 86, -1, 0, 0, 17, 10089, 12793), + (12793, -1, -1, 9503, 9503, 7, 88, -1, 0, 0, 17, 12792, 12794), + (12794, -1, -1, 9503, 9503, 7, 90, -1, 0, 0, 17, 12793, 5360), + (12795, -1, -1, 6051, 6051, 5, 85, -1, 0, 0, 17, 10606, 12796), + (12796, -1, -1, 6051, 6051, 5, 87, -1, 0, 0, 17, 12795, 12797), + (12797, -1, -1, 6051, 6051, 5, 89, -1, 0, 0, 17, 12796, 13278), + (12798, -1, -1, 5264, 5264, 12, 86, -1, 0, 0, 17, 10217, 12799), + (12799, -1, -1, 5264, 5264, 12, 88, -1, 0, 0, 17, 12798, 12800), + (12800, -1, -1, 5264, 5264, 12, 90, -1, 0, 0, 17, 12799, 13675), + (12801, -1, -1, 6383, 6383, 9, 85, -1, 0, 0, 17, 10609, 12802), + (12802, -1, -1, 6383, 6383, 9, 87, -1, 0, 0, 17, 12801, 12803), + (12803, -1, -1, 6383, 6383, 9, 89, -1, 0, 0, 17, 12802, 5339), + (12804, 12804, 12804, 12804, 12804, 7, 86, 23693, 75, 900, 17, -1, 12805), + (12807, 12807, 12807, 12807, 12807, 7, 86, 23699, 73, 1200, 17, -1, 12808), + (12810, 8227, 8227, 8227, 12810, 5, 85, 27402, 71, 10, 17, 8227, 12811), + (12811, 8227, 8227, 8227, 12810, 7, 87, 27403, 71, 10, 17, 12810, 12812), + (12812, 8227, 8227, 8227, 12810, 9, 89, 27404, 71, 10, 17, 12811, -1), + (12813, -1, -1, 1287, 1287, 5, 75, -1, 0, 0, 17, -1, 12814), + (12814, -1, -1, 1287, 1287, 5, 77, -1, 0, 0, 17, 12813, 12815), + (12815, -1, -1, 1287, 1287, 5, 79, -1, 0, 0, 17, 12814, 14279), + (12816, -1, -1, 12816, 12816, 7, 86, 0, 0, 0, 17, -1, 12817), + (12819, -1, -1, 12819, 12819, 9, 85, 0, 0, 0, 17, -1, 12820), + (12820, -1, -1, 12819, 12819, 12, 87, 0, 0, 0, 17, 12819, 12821), + (12822, -1, -1, 12822, 12822, 9, 86, 0, 0, 0, 17, -1, 12823), + (12828, 291, 291, 291, 12828, 12, 86, 27409, 5, 900, 17, 10304, 12829), + (12831, -1, -1, 12831, 12831, 7, 86, 0, 0, 0, 17, -1, 12832), + (12834, -1, -1, 6980, 6980, 5, 85, -1, 0, 0, 17, 6982, 12835), + (12835, -1, -1, 6980, 6980, 5, 87, -1, 0, 0, 17, 12834, 12836), + (12837, 12837, 12837, 12837, 12837, 7, 86, 27412, 74, 420, 17, -1, 12838), + (12840, -1, -1, 6977, 6977, 5, 85, -1, 0, 0, 17, 6979, 12841), + (12841, -1, -1, 6977, 6977, 5, 87, -1, 0, 0, 17, 12840, 12842), + (12843, -1, -1, 551, 551, 5, 86, -1, 0, 0, 17, 6907, 12844), + (12846, -1, -1, 12846, 12846, 7, 86, 6499, 0, 0, 17, -1, 12847), + (12849, -1, -1, 12849, 12849, 7, 86, 0, 0, 0, 17, -1, 12850), + (12857, 8072, 8072, 8072, 8072, 7, 86, 27419, 37, 20, 17, 10248, 12858), + (12860, -1, -1, 267, 267, 12, 86, -1, 0, 0, 17, 5619, 12861), + (12863, -1, -1, 141, 12863, 12, 59, -1, 0, 0, 17, 143, 15396), + (12864, 12864, -1, 12864, 12864, 5, 59, 27422, 73, 10, 17, -1, 17486), + (12865, 12865, 12865, 12865, 12865, 12, 90, 27423, 42, 6, 17, -1, -1), + (12866, 12866, 12866, 12866, 12866, 12, 86, 27424, 74, 1800, 17, -1, 15605), + (12867, 12867, 12867, 12867, 12867, 12, 86, 27426, 13, 4320, 17, -1, -1), + (12868, 1334, 1334, 1334, 1334, 12, 86, 27427, 11, 4320, 17, 10236, 12869), + (12871, -1, -1, 11050, 11050, 9, 85, -1, 0, 0, 17, 11060, 12872), + (12872, -1, -1, 11050, 11050, 12, 87, -1, 0, 0, 17, 12871, 12873), + (12874, -1, -1, 1414, 1414, 5, 86, -1, 0, 0, 17, 1418, 17490), + (12875, 4938, 4938, 4938, 4938, 12, 90, 27430, 35, 1800, 17, 5614, 13727), + (12876, -1, -1, 12430, 12430, 7, 86, 0, 0, 0, 17, 12477, 12877), + (12877, -1, -1, 12430, 12430, 9, 88, 0, 0, 0, 17, 12876, 12878), + (12878, -1, -1, 12430, 12430, 12, 90, 0, 0, 0, 17, 12877, 15270), + (12879, 516, 516, 516, 516, 6, 86, 27431, 5, 480, 17, 10233, 13659), + (12880, 1404, 1404, 1404, 1404, 7, 85, 27432, 15, 2160, 17, 1408, -1), + (12881, -1, -1, 12881, 12881, 9, 86, 0, 0, 0, 17, -1, 12882), + (12885, 12885, 12885, 12885, 12885, 12, 86, 27435, 75, 90, 17, -1, 17491), + (12886, -1, -1, 12886, 12886, 2, 85, -1, 0, 0, 17, -1, -1), + (12887, -1, -1, 12887, 12887, 2, 87, -1, 0, 0, 17, -1, -1), + (12888, -1, -1, 12888, 12888, 2, 89, -1, 0, 0, 17, -1, -1), + (12889, -1, -1, 12889, 12889, 2, 85, -1, 0, 0, 17, -1, 12890), + (12890, -1, -1, 12889, 12889, 2, 87, -1, 0, 0, 17, 12889, 12891), + (12892, 12892, 12892, 12892, 12892, 3, 90, 27434, 8, 60, 17, -1, 13666), + (12893, 12893, 12893, 12893, 12893, 12, 90, 27436, 76, 1800, 17, -1, 13663), + (12894, -1, -1, 12894, 12894, 5, 86, 0, 0, 0, 17, -1, 12895), + (12899, -1, -1, 471, 471, 2, 85, -1, 0, 0, 17, 473, 12900), + (12900, -1, -1, 471, 471, 2, 87, -1, 0, 0, 17, 12899, 12901), + (12902, -1, -1, 12902, 12902, 5, 85, 0, 0, 0, 17, -1, 12903), + (12903, -1, -1, 12902, 12902, 5, 86, 0, 0, 0, 17, 12902, 12904), + (12907, -1, -1, 12907, 12907, 5, 85, 0, 0, 0, 17, -1, 12908), + (12908, -1, -1, 12907, 12907, 5, 86, 0, 0, 0, 17, 12907, 12909), + (12912, -1, -1, 12912, 12912, 5, 85, 0, 0, 0, 17, -1, 12913), + (12913, -1, -1, 12912, 12912, 5, 86, 0, 0, 0, 17, 12912, 12914), + (12917, 517, 517, 517, 517, 5, 85, 27437, 12, 600, 17, 10281, 12918), + (12918, 517, 517, 517, 517, 5, 87, 27438, 12, 600, 17, 12917, 12919), + (12920, -1, -1, 12920, 12920, 5, 86, 0, 0, 0, 17, -1, 12921), + (12923, 54009, 54009, 54009, 12923, 3, 85, 27440, 22, 12, 17, 5849, 12924), + (12924, 54009, 54009, 54009, 12923, 3, 87, 27441, 22, 12, 17, 12923, 12925), + (12929, -1, -1, 6548, 6548, 8, 85, -1, 0, 0, 17, 6238, 12930), + (12930, -1, -1, 6548, 6548, 8, 90, -1, 0, 0, 17, 12929, 15463), + (12931, 12931, 12931, 12931, 12931, 7, 86, 27443, 73, 3600, 17, -1, 12932), + (12934, 1242, 1242, 1242, 1242, 12, 86, 27446, 9, 1320, 17, 10273, 12935), + (12937, 12937, 12937, 12937, 12937, 12, 86, 27449, 16, 420, 17, -1, 13733), + (12938, 12938, 12938, 12938, 12938, 15, 88, 27450, 75, 2700, 17, -1, 13743), + (12939, 12939, 12939, 12939, 12939, 12, 90, 27451, 77, 1800, 17, -1, 14756), + (12941, 12941, 12941, 12941, 12941, 5, 85, 27453, 77, 1, 17, -1, -1), + (12942, 6539, 6539, 6539, 6539, 6, 86, 27454, 18, 1800, 17, 7611, 12943), + (12943, 6539, 6539, 6539, 6539, 6, 88, 27455, 18, 1800, 17, 12942, 12944), + (12944, 6539, 6539, 6539, 6539, 6, 90, 27456, 18, 1800, 17, 12943, 13291), + (12945, -1, -1, 795, 795, 12, 85, -1, 0, 0, 17, 10267, 12946), + (12946, -1, -1, 795, 795, 12, 86, -1, 0, 0, 17, 12945, 12947), + (12947, -1, -1, 795, 795, 12, 87, -1, 0, 0, 17, 12946, 12948), + (12948, -1, -1, 795, 795, 12, 88, -1, 0, 0, 17, 12947, 12949), + (12949, -1, -1, 795, 795, 12, 89, -1, 0, 0, 17, 12948, 13710), + (12950, -1, -1, 790, 790, 6, 86, -1, 0, 0, 17, 7274, 12951), + (12951, -1, -1, 790, 790, 6, 87, -1, 0, 0, 17, 12950, 12952), + (12952, -1, -1, 790, 790, 6, 88, -1, 0, 0, 17, 12951, 12953), + (12953, -1, -1, 790, 790, 6, 89, -1, 0, 0, 17, 12952, 12954), + (12954, -1, -1, 790, 790, 6, 90, -1, 0, 0, 17, 12953, 13713), + (12955, 167, 167, 167, 167, 10, 86, 27457, 14, 900, 17, 8343, 13718), + (12956, 4903, 4903, 4903, 4903, 9, 85, 27460, 9, 1320, 17, 10255, 13698), + (12957, 4909, 4909, 4909, 4909, 9, 85, 27461, 16, 1320, 17, 10257, 14733), + (12958, 4912, 4912, 4912, 4912, 9, 85, 27459, 16, 1320, 17, 10258, 13704), + (12959, 4906, 4906, 4906, 4906, 9, 85, 27458, 9, 1320, 17, 10256, 13701), + (12963, 12963, 12963, 12963, 12963, 7, 86, 27465, 81, 5, 17, -1, -1), + (12964, 12964, 12964, 12964, 12964, 7, 88, 27466, 81, 5, 17, -1, -1), + (12965, 12965, 12965, 12965, 12965, 7, 90, 27467, 81, 5, 17, -1, -1), + (12966, -1, -1, 6112, 6112, 5, 87, -1, 0, 0, 17, 6112, 12967), + (12967, -1, -1, 6112, 6112, 5, 89, -1, 0, 0, 17, 12966, 16402), + (12968, -1, -1, 12968, 12968, 7, 85, 0, 0, 0, 17, -1, 12969), + (12969, -1, -1, 12968, 12968, 7, 87, 0, 0, 0, 17, 12968, 12970), + (12970, -1, -1, 12968, 12968, 7, 89, 0, 0, 0, 17, 12969, 14238), + (12971, 12971, 12971, 12971, 12971, 5, 86, 27471, 79, 2160, 17, -1, 12972), + (12972, 12971, 12971, 12971, 12971, 7, 87, 27472, 79, 2160, 17, 12971, 12973), + (12973, 12971, 12971, 12971, 12971, 9, 88, 27473, 79, 2160, 17, 12972, 12974), + (12974, 12971, 12971, 12971, 12971, 12, 89, 27474, 79, 2160, 17, 12973, 12975), + (12975, 12971, 12971, 12971, 12971, 15, 90, 27475, 79, 2160, 17, 12974, -1), + (12976, 7903, 7903, 7903, 7903, 6, 85, 27476, 60, 30, 17, 7903, 14734), + (12977, -1, -1, 12977, 12977, 5, 85, 0, 0, 0, 17, -1, 12978), + (12978, -1, -1, 12977, 12977, 5, 86, 0, 0, 0, 17, 12977, 12979), + (12979, -1, -1, 12977, 12977, 5, 87, 0, 0, 0, 17, 12978, 12980), + (12980, -1, -1, 12977, 12977, 5, 88, 0, 0, 0, 17, 12979, 12981), + (12981, -1, -1, 12977, 12977, 5, 89, 0, 0, 0, 17, 12980, 17334), + (12982, 10600, 10600, 10600, 10600, 7, 86, 27477, 73, 20, 17, 10602, 12983), + (12983, 10600, 10600, 10600, 10600, 7, 88, 27478, 73, 20, 17, 12982, 12984), + (12984, 10600, 10600, 10600, 10600, 7, 90, 27479, 73, 20, 17, 12983, 13720), + (12985, 520, 520, 520, 520, 12, 86, 27480, 6, 540, 17, 10254, 12986), + (12986, 520, 520, 520, 520, 12, 88, 27481, 6, 540, 17, 12985, 12987), + (12987, 520, 520, 520, 520, 12, 90, 27482, 6, 540, 17, 12986, -1), + (12988, -1, -1, 10959, 12988, 12, 90, -1, 0, 0, 17, 10962, -1), + (12989, 12989, 12989, 12989, 12989, 7, 86, 27486, 73, 1800, 17, -1, 12990), + (12990, 12989, 12989, 12989, 12989, 9, 88, 27487, 73, 1800, 17, 12989, 12991), + (12991, 12989, 12989, 12989, 12989, 12, 90, 27488, 73, 1800, 17, 12990, 5336), + (12992, 12992, 12992, 12992, 12992, 9, 86, 27489, 0, 1, 17, -1, 12993), + (12993, 12992, 12992, 12992, 12992, 12, 88, 27490, 0, 1, 17, 12992, 12994), + (12994, 12992, 12992, 12992, 12992, 15, 90, 27491, 0, 1, 17, 12993, 5350), + (12995, 6563, 6563, 6563, 6563, 12, 86, 27492, 36, 8, 17, 6281, -1), + (12996, 153, 153, 153, 153, 12, 90, 27493, 3, 2160, 17, 11081, 17333), + (12997, 1520, 1520, 1520, 1520, 9, 85, 27494, 11, 900, 17, 10192, 12998), + (12998, 1520, 1520, 1520, 1520, 9, 87, 27495, 11, 900, 17, 12997, 12999), + (12999, 1520, 1520, 1520, 1520, 9, 89, 27496, 11, 900, 17, 12998, 5333), + (13000, 10958, 10958, 10958, 10958, 15, 90, 27497, 62, 900, 17, 10958, 16214), + (13001, -1, -1, 13001, 13001, 7, 86, -1, 0, 0, 17, -1, 13002), + (13002, -1, -1, 13001, 13001, 7, 88, -1, 0, 0, 17, 13001, 13003), + (13003, -1, -1, 13001, 13001, 7, 90, -1, 0, 0, 17, 13002, 15348), + (13004, 13004, 13004, 13004, 13004, 9, 86, 27499, 78, 300, 17, -1, 15855), + (13005, -1, -1, 6703, 6703, 3, 86, -1, 0, 0, 17, 10178, 13006), + (13006, -1, -1, 6703, 6703, 3, 88, -1, 0, 0, 17, 13005, 13007), + (13007, -1, -1, 6703, 6703, 3, 90, -1, 0, 0, 17, 13006, -1), + (13008, 13008, 13008, 13008, 13008, 9, 90, 27500, 86, 300, 17, -1, -1), + (13009, 13009, 13009, 13009, 13009, 6, 86, 27501, 39, 1, 17, -1, -1), + (13010, -1, -1, 13010, 13010, 6, 85, 0, 0, 0, 17, -1, 13011), + (13011, -1, -1, 13010, 13010, 6, 87, 0, 0, 0, 17, 13010, 13012), + (13012, -1, -1, 13010, 13010, 6, 89, 0, 0, 0, 17, 13011, 14223), + (13013, -1, -1, 13013, 13013, 6, 86, 0, 0, 0, 17, -1, 13014), + (13014, -1, -1, 13013, 13013, 6, 88, 0, 0, 0, 17, 13013, 13015), + (13015, -1, -1, 13013, 13013, 6, 90, 0, 0, 0, 17, 13014, -1), + (13016, 5109, 5109, 5109, 5109, 9, 86, 27502, 0, 1, 17, 7467, 5356), + (13017, -1, -1, 13017, 13017, 9, 86, -1, 0, 0, 17, -1, 13018), + (13018, -1, -1, 13017, 13017, 12, 88, -1, 0, 0, 17, 13017, 13019), + (13019, -1, -1, 13017, 13017, 15, 90, -1, 0, 0, 17, 13018, 13396), + (13020, 13020, 13020, 13020, 13020, 12, 86, 27503, 76, 420, 17, -1, -1), + (13021, -1, -1, 11085, 11085, 12, 86, 0, 0, 0, 17, 11087, 13022), + (13023, -1, -1, 1050, 1050, 12, 86, -1, 0, 0, 17, 7658, 13024), + (13026, -1, -1, 599, 599, 12, 86, -1, 0, 0, 17, 7561, 13027), + (13027, -1, -1, 599, 599, 12, 88, -1, 0, 0, 17, 13026, 13028), + (13028, -1, -1, 599, 599, 12, 90, -1, 0, 0, 17, 13027, 13438), + (13029, -1, -1, 7818, 7818, 9, 86, 31681, 0, 0, 17, 7818, 13030), + (13032, -1, -1, 1131, 1131, 9, 85, -1, 0, 0, 17, 11084, 13033), + (13033, -1, -1, 1131, 1131, 12, 87, -1, 0, 0, 17, 13032, 13034), + (13035, -1, -1, 1134, 1134, 3, 86, -1, 0, 0, 17, 10315, 13036), + (13040, -1, -1, 4809, 4809, 5, 86, -1, 0, 0, 17, 10318, 13041), + (13043, -1, -1, 5776, 5776, 9, 86, -1, 0, 0, 17, 7198, 13044), + (13046, -1, -1, 8250, 8250, 6, 85, -1, 0, 0, 17, 8254, 13047), + (13047, -1, -1, 8250, 8250, 6, 86, -1, 0, 0, 17, 13046, 13048), + (13048, -1, -1, 8250, 8250, 6, 87, -1, 0, 0, 17, 13047, 13049), + (13049, -1, -1, 8250, 8250, 6, 88, -1, 0, 0, 17, 13048, 13050), + (13050, -1, -1, 8250, 8250, 6, 89, -1, 0, 0, 17, 13049, 13348), + (13051, -1, -1, 10404, 10404, 6, 90, -1, 0, 0, 17, 10404, -1), + (13052, -1, -1, 10401, 10401, 6, 86, -1, 0, 0, 17, 10403, 13053), + (13055, -1, -1, 13055, 13055, 6, 86, 0, 0, 0, 17, -1, 13056), + (13058, 6931, 6931, 6931, 6931, 12, 90, 27504, 41, 600, 17, 10319, 13857), + (13059, 4854, 4854, 4854, 4854, 9, 86, 27505, 8, 600, 17, 10325, 13060), + (13062, 6932, 6932, 6932, 6932, 7, 86, 27508, 42, 1200, 17, 10322, 13063), + (13065, 13065, 13065, 13065, 13065, 12, 86, 27514, 70, 90, 17, -1, -1), + (13066, 13066, 13066, 13066, 13066, 9, 85, 27516, 71, 1800, 17, -1, -1), + (13067, -1, -1, 13067, 13067, 6, 86, 0, 0, 0, 17, -1, 13068), + (13072, -1, -1, 12600, 12600, 7, 87, 0, 0, 0, 17, 12600, 13073), + (13073, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13072, 13222), + (13074, -1, -1, 1044, 1044, 9, 86, -1, 0, 0, 17, 7652, 13075), + (13075, -1, -1, 1044, 1044, 12, 88, -1, 0, 0, 17, 13074, 13076), + (13076, -1, -1, 1044, 1044, 15, 90, -1, 0, 0, 17, 13075, 13326), + (13077, -1, -1, 1047, 1047, 9, 86, -1, 0, 0, 17, 7655, 13078), + (13078, -1, -1, 1047, 1047, 12, 88, -1, 0, 0, 17, 13077, 13079), + (13080, -1, -1, 125, 125, 9, 86, -1, 0, 0, 17, 12400, 13081), + (13081, -1, -1, 125, 125, 10, 87, -1, 0, 0, 17, 13080, 13082), + (13082, -1, -1, 125, 125, 11, 88, -1, 0, 0, 17, 13081, 13083), + (13083, -1, -1, 125, 125, 12, 89, -1, 0, 0, 17, 13082, 13084), + (13084, -1, -1, 125, 125, 13, 90, -1, 0, 0, 17, 13083, 8463), + (13085, -1, -1, 122, 122, 9, 86, -1, 0, 0, 17, 12405, 13086), + (13086, -1, -1, 122, 122, 10, 87, -1, 0, 0, 17, 13085, 13087), + (13087, -1, -1, 122, 122, 11, 88, -1, 0, 0, 17, 13086, 13088), + (13088, -1, -1, 122, 122, 12, 89, -1, 0, 0, 17, 13087, 13089), + (13089, -1, -1, 122, 122, 13, 90, -1, 0, 0, 17, 13088, 8440), + (13090, -1, -1, 1435, 4773, 9, 86, -1, 0, 0, 17, 7621, 13295), + (13091, -1, -1, 1435, 4773, 9, 86, -1, 0, 0, 17, 1650, 13294), + (13092, -1, -1, 644, 644, 9, 85, -1, 0, 0, 17, 7361, 13093), + (13093, -1, -1, 644, 644, 12, 87, -1, 0, 0, 17, 13092, 13094), + (13094, -1, -1, 644, 644, 15, 89, -1, 0, 0, 17, 13093, 13265), + (13095, -1, -1, 1604, 1604, 15, 89, -1, 0, 0, 17, 12613, 13767), + (13096, -1, -1, 13096, 13096, 12, 86, -1, 0, 0, 17, -1, 13097), + (13097, -1, -1, 13096, 13096, 12, 88, -1, 0, 0, 17, 13096, 13098), + (13098, -1, -1, 13096, 13096, 12, 90, -1, 0, 0, 17, 13097, 13127), + (13099, -1, -1, 83, 83, 9, 55, -1, 0, 0, 17, 85, -1), + (13100, 13100, 13100, 13100, 13100, 9, 86, 27534, 86, 300, 17, -1, 15140), + (13101, -1, -1, 13101, 13101, 7, 86, 0, 0, 0, 17, -1, 13102), + (13102, -1, -1, 13101, 13101, 9, 88, 0, 0, 0, 17, 13101, 13103), + (13103, -1, -1, 13101, 13101, 12, 90, 0, 0, 0, 17, 13102, 14082), + (13104, -1, -1, 589, 589, 9, 86, -1, 0, 0, 17, 7709, 13105), + (13105, -1, -1, 589, 589, 9, 88, -1, 0, 0, 17, 13104, 13106), + (13106, -1, -1, 589, 589, 9, 90, -1, 0, 0, 17, 13105, 15778), + (13107, 6645, 6645, 6645, 6645, 9, 90, 27541, 45, 60, 17, 6645, 13633), + (13108, 13108, 13108, 13108, 13108, 5, 90, 27542, 89, 30, 17, -1, -1), + (13109, 1351, 1351, 1351, 1351, 8, 90, 27543, 5, 30, 17, 7109, -1), + (13110, 10815, 10815, 10815, 10815, 9, 86, -1, 0, 0, 17, 10817, 13111), + (13111, 10815, 10815, 10815, 10815, 11, 88, -1, 0, 0, 17, 13110, 13112), + (13113, 10818, 10818, 10818, 10818, 9, 86, -1, 0, 0, 17, 10820, 13114), + (13114, 10818, 10818, 10818, 10818, 11, 88, -1, 0, 0, 17, 13113, 13115), + (13116, 10821, 10821, 10821, 10821, 9, 86, -1, 0, 0, 17, 10823, 13117), + (13117, 10821, 10821, 10821, 10821, 11, 88, -1, 0, 0, 17, 13116, 13118), + (13119, 5007, 5007, 5007, 5007, 9, 86, 27544, 8, 2160, 17, 10063, 13120), + (13120, 5007, 5007, 5007, 5007, 9, 88, 27545, 8, 2160, 17, 13119, 13121), + (13122, -1, -1, 6546, 6546, 0, 86, -1, 0, 0, 17, 7377, 13123), + (13123, -1, -1, 6546, 6546, 0, 87, -1, 0, 0, 17, 13122, 13124), + (13124, -1, -1, 6546, 6546, 0, 88, -1, 0, 0, 17, 13123, 13125), + (13127, -1, -1, 13096, 13096, 12, 91, -1, 0, 0, 18, 13098, 13128), + (13130, 13130, 13130, 13130, 13130, 15, 95, 32440, 48, 30, 18, -1, -1), + (13133, 7756, 7756, 7756, 7756, 12, 85, 21805, 85, 120, 17, -1, -1), + (13134, 13134, 13134, 13134, 13134, 7, 86, 27547, 74, 900, 17, -1, 13135), + (13135, 13134, 13134, 13134, 13134, 7, 88, 27548, 74, 900, 17, 13134, 13136), + (13136, 13134, 13134, 13134, 13134, 7, 90, 27549, 74, 900, 17, 13135, 13380), + (13140, -1, -1, 10464, 10464, 7, 86, -1, 0, 0, 17, 10466, 13141), + (13141, -1, -1, 10464, 10464, 9, 88, -1, 0, 0, 17, 13140, 13142), + (13142, -1, -1, 10464, 10464, 11, 90, -1, 0, 0, 17, 13141, -1), + (13143, -1, -1, 13143, 13143, 5, 86, 0, 0, 0, 17, -1, 13144), + (13144, -1, -1, 13143, 13143, 5, 88, 0, 0, 0, 17, 13143, 13145), + (13145, -1, -1, 13143, 13143, 5, 90, 0, 0, 0, 17, 13144, -1), + (13146, -1, -1, 13146, 13146, 5, 86, 0, 0, 0, 17, -1, 13147), + (13147, -1, -1, 13146, 13146, 5, 88, 0, 0, 0, 17, 13146, 13148), + (13148, -1, -1, 13146, 13146, 5, 90, 0, 0, 0, 17, 13147, -1), + (13149, -1, -1, 8210, 8210, 5, 86, -1, 0, 0, 17, 1655, 13150), + (13150, -1, -1, 8210, 8210, 5, 87, -1, 0, 0, 17, 13149, 13151), + (13151, -1, -1, 8210, 8210, 5, 88, -1, 0, 0, 17, 13150, 13152), + (13152, -1, -1, 8210, 8210, 5, 89, -1, 0, 0, 17, 13151, 13153), + (13153, -1, -1, 8210, 8210, 5, 90, -1, 0, 0, 17, 13152, 13318), + (13154, 5105, 5105, 5105, 5105, 12, 90, 27550, 11, 600, 17, 10509, 14023), + (13155, 7986, 7986, 7986, 7986, 12, 90, 27551, 11, 600, 17, 10510, 14022), + (13158, 548, 548, 548, 548, 10, 86, 27552, 5, 900, 17, 10098, 13159), + (13161, 528, 528, 528, 528, 12, 86, 27555, 5, 720, 17, 10196, 13162), + (13162, 528, 528, 528, 528, 12, 88, 27556, 5, 720, 17, 13161, 13163), + (13163, 528, 528, 528, 528, 12, 90, 27557, 5, 720, 17, 13162, 5357), + (13164, 13164, 13164, 13164, 13164, 9, 86, 27540, 99, 180, 17, -1, -1), + (13165, 13165, 13165, 13165, 13165, 9, 86, 27559, 56, 60, 17, -1, -1), + (13166, -1, -1, 13166, 13166, 7, 86, 0, 0, 0, 17, -1, 13167), + (13167, -1, -1, 13166, 13166, 7, 88, 0, 0, 0, 17, 13166, 13168), + (13168, -1, -1, 13166, 13166, 7, 90, 0, 0, 0, 17, 13167, -1), + (13169, 13169, 13169, 13169, 13169, 9, 90, 27560, 99, 180, 17, -1, 17221), + (13170, 6380, 6380, 6380, 6380, 6, 86, 27561, 39, 120, 17, 10310, 13171), + (13173, 290, 290, 290, 290, 8, 86, 27564, 4, 720, 17, 290, 13448), + (13174, 10374, 10374, 10374, 10374, 6, 85, 27565, 63, 900, 17, 10376, 13175), + (13175, 10374, 10374, 10374, 10374, 8, 87, 27566, 63, 900, 17, 13174, 13176), + (13177, 6984, 6984, 6984, 6984, 6, 83, 27568, 60, 60, 17, 10294, 13466), + (13178, 6986, 6986, 6986, 6986, 6, 83, 27570, 60, 60, 17, 10296, 13468), + (13179, 6985, 6985, 6985, 6985, 6, 83, 27569, 60, 60, 17, 10295, 13467), + (13180, 10377, 10377, 10377, 10377, 6, 86, 16796, 64, 60, 17, 10379, 13181), + (13183, 10346, 10346, 10346, 10346, 9, 90, 27574, 46, 600, 17, 10346, 13819), + (13184, -1, -1, 10340, 10340, 9, 86, -1, 0, 0, 17, 10342, 13185), + (13185, -1, -1, 10340, 10340, 9, 88, -1, 0, 0, 17, 13184, 13186), + (13186, -1, -1, 10340, 10340, 9, 90, -1, 0, 0, 17, 13185, 13829), + (13187, -1, -1, 9512, 9512, 7, 86, -1, 0, 0, 17, 7883, 13188), + (13188, -1, -1, 9512, 9512, 7, 88, -1, 0, 0, 17, 13187, 13189), + (13189, -1, -1, 9512, 9512, 7, 90, -1, 0, 0, 17, 13188, 13826), + (13190, 1110, 1110, 1110, 1110, 6, 86, 27576, 3, 2160, 17, 10152, 13191), + (13191, 1110, 1110, 1110, 1110, 6, 88, 27577, 3, 2160, 17, 13190, 13192), + (13192, 1110, 1110, 1110, 1110, 6, 90, 27578, 3, 2160, 17, 13191, 13496), + (13193, 1598, -1, 1598, 1598, 9, 86, 27582, 6, 900, 17, 10148, 13194), + (13194, 1598, -1, 1598, 1598, 11, 88, 27583, 6, 900, 17, 13193, 13195), + (13195, 1598, -1, 1598, 1598, 13, 90, 27584, 6, 900, 17, 13194, 13493), + (13196, -1, -1, 255, 255, 9, 86, -1, 0, 0, 17, 10135, 13197), + (13197, -1, -1, 255, 255, 9, 88, -1, 0, 0, 17, 13196, 13198), + (13198, -1, -1, 255, 255, 9, 90, -1, 0, 0, 17, 13197, 13511), + (13199, -1, -1, 8322, 8322, 9, 86, 0, 0, 0, 17, 8324, 13200), + (13200, -1, -1, 8322, 8322, 9, 88, 0, 0, 0, 17, 13199, 13201), + (13201, -1, -1, 8322, 8322, 9, 90, 0, 0, 0, 17, 13200, -1), + (13202, 13202, 13202, 13202, 13202, 2, 81, 27585, 98, 20, 17, -1, 14009), + (13203, 10330, 10330, 10330, 10330, 7, 90, 27586, 35, 30, 17, 10330, 13492), + (13204, -1, -1, 13204, 13204, 7, 86, -1, 0, 0, 17, -1, 13205), + (13205, -1, -1, 13204, 13204, 7, 88, -1, 0, 0, 17, 13204, 13206), + (13206, -1, -1, 13204, 13204, 7, 90, -1, 0, 0, 17, 13205, 14176), + (13207, -1, -1, 10850, 10850, 9, 86, 27587, 0, 0, 17, 10852, 13208), + (13208, -1, -1, 10850, 10850, 9, 88, 27588, 0, 0, 17, 13207, 13209), + (13209, -1, -1, 10850, 10850, 9, 90, 27589, 0, 0, 17, 13208, 13779), + (13210, -1, -1, 1307, 1307, 5, 81, -1, 0, 0, 17, 6662, 13211), + (13211, -1, -1, 1307, 1307, 5, 83, -1, 0, 0, 17, 13210, 13212), + (13212, -1, -1, 1307, 1307, 5, 85, -1, 0, 0, 17, 13211, -1), + (13213, -1, -1, 1543, 1543, 7, 86, -1, 0, 0, 17, 10167, 13214), + (13214, -1, -1, 1543, 1543, 7, 87, -1, 0, 0, 17, 13213, 13215), + (13215, -1, -1, 1543, 1543, 7, 88, -1, 0, 0, 17, 13214, 13216), + (13216, -1, -1, 1543, 1543, 7, 89, -1, 0, 0, 17, 13215, 13217), + (13217, -1, -1, 1543, 1543, 7, 90, -1, 0, 0, 17, 13216, 13782), + (13218, -1, -1, 1304, 1304, 12, 90, -1, 0, 0, 17, 10867, 13789), + (13219, -1, -1, 8325, 8325, 7, 85, 0, 0, 0, 17, 8327, 13220), + (13220, -1, -1, 8325, 8325, 9, 87, 0, 0, 0, 17, 13219, 13221), + (13221, -1, -1, 8325, 8325, 11, 89, 0, 0, 0, 17, 13220, 13798), + (13222, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13073, 13223), + (13223, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13222, -1), + (13224, 13224, -1, 13224, 13224, 3, 86, 27590, 98, 1, 17, -1, 15559), + (13225, 13225, 13225, 13225, 13225, 6, 86, 27592, 0, 4, 17, -1, 13688), + (13226, -1, -1, 5295, 5295, 6, 86, -1, 0, 0, 17, 10229, 13227), + (13229, 6290, 6290, 6290, 6290, 9, 86, 27596, 0, 1, 17, 11066, 13230), + (13232, 4944, -1, 4944, 4944, 9, 86, 27602, 0, 1, 17, 11069, 13233), + (13235, 1478, -1, 1478, 1478, 9, 86, 27608, 0, 1, 17, 11072, 13236), + (13238, -1, -1, 1287, 1287, 9, 86, -1, 0, 0, 17, 12474, 13239), + (13239, -1, -1, 1287, 1287, 10, 88, -1, 0, 0, 17, 13238, 13240), + (13240, -1, -1, 1287, 1287, 11, 90, -1, 0, 0, 17, 13239, 15719), + (13241, 4931, 4931, 4931, 4931, 7, 86, 27614, 4, 600, 17, 10430, 13242), + (13244, 1501, 1501, 1501, 1501, 6, 86, 27617, 10, 4320, 17, 1560, 13245), + (13247, 4894, 4894, 4894, 4894, 6, 86, 27620, 7, 2160, 17, 7290, 13248), + (13250, 10550, 10550, 10550, 10550, 7, 90, 27626, 61, 120, 17, 10550, 13728), + (13251, 1239, 1239, 1239, 1239, 9, 90, 27627, 6, 600, 17, 7275, 13732), + (13252, 13252, 13252, 13252, 13252, 9, 86, 27629, 95, 4, 17, -1, 16065), + (13253, 1126, 1126, 1126, 1126, 7, 85, 27630, 2, 2160, 17, 5515, 13254), + (13254, 1126, 1126, 1126, 1126, 7, 87, 27631, 2, 2160, 17, 13253, 13255), + (13255, 1126, 1126, 1126, 1126, 7, 89, 27632, 2, 2160, 17, 13254, 13723), + (13256, 146, 146, 146, 146, 8, 86, 27633, 2, 180, 17, 7691, 13257), + (13257, 146, 146, 146, 146, 8, 88, 27634, 2, 180, 17, 13256, 13258), + (13258, 146, 146, 146, 146, 8, 90, 27635, 2, 180, 17, 13257, 14222), + (13259, 1195, 1195, 1195, 1195, 9, 90, 27661, 13, 2160, 17, 10015, 15334), + (13260, 13260, 13260, 13260, 13260, 0, 80, 27664, 98, 3600, 17, -1, -1), + (13261, 13261, 13261, 13261, 13261, 0, 81, 27665, 98, 28800, 17, -1, -1), + (13262, -1, -1, 498, 498, 5, 70, -1, 0, 0, 16, 975, 13263), + (13263, -1, -1, 498, 498, 5, 75, -1, 0, 0, 16, 13262, 13264), + (13264, -1, -1, 498, 498, 5, 80, -1, 0, 0, 16, 13263, -1), + (13271, 13271, 13271, 13271, 13271, 0, 80, 27691, 97, 3600, 18, -1, -1), + (13272, 13272, 13272, 13272, 13272, 0, 81, 27692, 97, 28800, 18, -1, -1), + (13275, 6537, 6537, 6537, 6537, 10, 91, 30638, 30, 900, 18, 12522, 13276), + (13278, -1, -1, 6051, 6051, 10, 91, -1, 0, 0, 18, 12797, 13279), + (13281, -1, -1, 1072, 1072, 12, 91, -1, 0, 0, 18, 12541, 13282), + (13286, -1, -1, 119, 119, 12, 91, -1, 0, 0, 18, 12552, 13287), + (13291, 6539, 6539, 6539, 6539, 9, 91, 30641, 18, 1800, 18, 12944, 13292), + (13294, -1, -1, 1435, 4773, 12, 91, -1, 0, 0, 18, 13091, 14490), + (13295, -1, -1, 1435, 4773, 12, 91, -1, 0, 0, 18, 13090, 14491), + (13296, -1, -1, 77, 77, 12, 91, -1, 0, 0, 18, 12499, 13297), + (13297, -1, -1, 77, 77, 12, 93, -1, 0, 0, 18, 13296, 13298), + (13299, -1, -1, 1186, 1186, 12, 91, -1, 0, 0, 18, 12566, 13300), + (13302, -1, -1, 80, 80, 12, 91, -1, 0, 0, 18, 12569, 13303), + (13305, -1, -1, 683, 683, 10, 91, -1, 0, 0, 18, 12696, 13306), + (13308, -1, -1, 446, 735, 10, 91, -1, 0, 0, 18, 10477, 13309), + (13313, -1, -1, 658, 658, 8, 91, -1, 0, 0, 18, 12574, 13314), + (13318, -1, -1, 8210, 8210, 10, 91, -1, 0, 0, 18, 13153, 13319), + (13323, -1, -1, 1287, 1287, 12, 91, -1, 0, 0, 18, 10639, 13324), + (13326, -1, -1, 1044, 1044, 10, 91, -1, 0, 0, 18, 13076, 13327), + (13332, -1, -1, 1041, 1041, 11, 91, -1, 0, 0, 18, 12699, 13333), + (13338, -1, -1, 8245, 8245, 11, 91, -1, 0, 0, 18, 8426, 13339), + (13343, -1, -1, 8240, 8240, 11, 91, -1, 0, 0, 18, 10785, 13344), + (13348, -1, -1, 8250, 8250, 11, 91, -1, 0, 0, 18, 13050, 13349), + (13353, -1, -1, 8235, 8235, 11, 91, -1, 0, 0, 18, 8308, 13354), + (13358, -1, -1, 8255, 8255, 11, 91, -1, 0, 0, 18, 12415, 13359), + (13363, 1192, 1192, 1192, 1192, 9, 91, 30645, 12, 1320, 18, 10021, 13364), + (13383, 6488, 6488, 6488, 6488, 15, 91, 30657, 32, 900, 18, 6488, 13384), + (13385, 13385, 13385, 13385, 13385, 12, 91, 30659, 75, 600, 18, -1, 13386), + (13388, 13388, 13388, 13388, 13388, 12, 91, 30665, 79, 180, 18, -1, -1), + (13389, 13389, -1, 13389, 13389, 5, 91, 30666, 77, 12, 18, -1, 15832), + (13396, -1, -1, 13017, 13017, 15, 91, -1, 0, 0, 18, 13019, 13397), + (13401, 1498, 1498, 1498, 1498, 15, 91, 30679, 12, 1320, 18, 10092, 13402), + (13404, -1, -1, 1514, 1514, 11, 91, -1, 0, 0, 18, 1516, 13405), + (13410, 645, -1, 645, 645, 15, 95, 30682, 4, 5, 18, 10739, -1), + (13411, -1, -1, 12652, 12652, 15, 92, 0, 0, 0, 18, 12654, 13412), + (13413, -1, -1, 12416, 12416, 15, 91, -1, 0, 0, 18, 12418, 13414), + (13415, -1, -1, 7989, 7989, 9, 95, -1, 0, 0, 18, 7992, -1), + (13416, -1, -1, 13416, 13416, 9, 91, 0, 0, 0, 18, -1, 13417), + (13419, 13419, 13419, 13419, 13419, 12, 91, 30683, 99, 600, 18, -1, 13420), + (13425, 54006, 54006, 54006, 54006, 9, 91, 30692, 18, 180, 18, 10006, 13426), + (13438, -1, -1, 599, 599, 13, 91, -1, 0, 0, 18, 13028, 13439), + (13444, 13444, 13444, 13444, 13444, 9, 91, 30699, 75, 600, 18, -1, 13445), + (13447, 11073, 11073, 11073, 11073, 12, 95, 30705, 53, 30, 18, 11073, 15412), + (13449, -1, -1, 13449, 13449, 5, 91, -1, 0, 0, 18, -1, 13450), + (13454, 718, 718, 718, 718, 12, 91, 30711, 7, 4320, 18, 1019, 14855), + (13463, -1, -1, 13463, 13463, 7, 91, -1, 0, 0, 18, -1, 13464), + (13466, 6984, 6984, 6984, 6984, 9, 91, 30721, 60, 60, 18, 13177, 13469), + (13467, 6985, 6985, 6985, 6985, 9, 91, 30723, 60, 60, 18, 13179, 13470), + (13468, 6986, 6986, 6986, 6986, 12, 92, 30725, 60, 60, 18, 13178, 13471), + (13472, 11080, 11080, 11080, 11080, 11, 91, 30727, 10, 20, 18, 11080, 13473), + (13474, -1, -1, 13474, 13474, 9, 91, -1, 0, 0, 18, -1, 13475), + (13477, -1, -1, 10380, 10380, 11, 91, -1, 0, 0, 18, 10382, 13478), + (13483, 13483, 13483, 13483, 13483, 5, 91, 30735, 68, 20, 18, -1, -1), + (13484, 13484, -1, 13484, 13484, 12, 95, 30736, 76, 720, 18, -1, 15879), + (13485, -1, -1, 13485, 13485, 7, 91, -1, 0, 0, 18, -1, 13486), + (13490, 5020, 5020, 5020, 5020, 9, 91, 30742, 9, 300, 18, 10149, 13491), + (13492, 10330, 10330, 10330, 10330, 12, 95, 30744, 35, 30, 18, 13203, 14797), + (13493, 1598, -1, 1598, 1598, 11, 91, 30745, 6, 900, 18, 13195, 13494), + (13496, 1110, 1110, 1110, 1110, 9, 91, 30748, 3, 2160, 18, 13192, 13497), + (13499, 592, 592, 592, 592, 9, 91, 30754, 2, 18, 18, 12751, 13500), + (13502, -1, -1, 6375, 6375, 9, 91, -1, 0, 0, 18, 12736, 13503), + (13505, 6533, 6533, 6533, 6533, 11, 91, 30757, 15, 600, 18, 12742, 13506), + (13508, -1, -1, 8314, 8314, 9, 91, -1, 0, 0, 18, 8316, 13509), + (13511, -1, -1, 255, 255, 9, 91, -1, 0, 0, 18, 13198, 13512), + (13514, 5298, 5298, 5298, 5298, 12, 91, 30760, 32, 1800, 18, 12748, 13515), + (13517, 10336, 10336, 10336, 10336, 11, 91, 30766, 58, 8, 18, 12732, 13518), + (13520, -1, -1, 12419, 12419, 15, 95, -1, 0, 0, 18, 12575, 16886), + (13521, -1, -1, 6386, 6386, 9, 91, -1, 0, 0, 18, 6389, 13522), + (13524, 6534, 6534, 6534, 6534, 11, 91, 30769, 16, 900, 18, 7429, 13525), + (13527, 13527, 13527, 13527, 13527, 9, 91, 30772, 18, 9, 18, -1, 15964), + (13528, 13528, 13528, 13528, 13528, 10, 91, 30773, 42, 60, 18, -1, -1), + (13529, 13529, 13529, 13529, 13529, 15, 95, 30774, 41, 120, 18, -1, -1), + (13530, 1116, 1116, 1116, 1116, 12, 91, 30775, 4, 2160, 18, 12745, 13531), + (13533, -1, -1, 7010, 7010, 9, 91, -1, 0, 0, 18, 7015, 13534), + (13542, 6755, 6755, 6755, 6755, 12, 91, 30784, 42, 900, 18, 6757, 13543), + (13545, -1, -1, 10388, 10388, 12, 95, -1, 0, 0, 18, 10388, 15293), + (13546, 6758, 6758, 6758, 6758, 11, 91, 32360, 43, 900, 18, 10056, 13547), + (13549, 13549, 13549, 13549, 13549, 15, 95, 30788, 64, 180, 18, -1, -1), + (13556, 13556, 13556, 13556, 13556, 9, 91, 30792, 44, 600, 18, -1, 13557), + (13562, -1, -1, 10719, 10719, 15, 91, 0, 0, 0, 18, 10721, 13563), + (13565, -1, -1, 13565, 13565, 11, 91, 0, 0, 0, 18, -1, 13566), + (13568, -1, -1, 13568, 13568, 11, 91, 0, 0, 0, 18, -1, 13569), + (13571, 13571, 13571, 13571, 13571, 12, 91, 30795, 50, 60, 18, -1, -1), + (13575, 5095, 5095, 5095, 5095, 11, 91, 30796, 10, 900, 18, 10642, 13576), + (13578, 0, 0, 10348, 10348, 9, 91, -1, 0, 0, 18, 10350, 13579), + (13584, 10394, 10394, 10394, 10394, 15, 91, 30799, 30, 300, 18, 10704, 14981), + (13585, 7712, 7712, 7712, 7712, 15, 95, 30800, 2, 30, 18, 10646, 15095), + (13586, 188, 188, 188, 188, 12, 91, 30801, 2, 30, 18, 10647, 13587), + (13589, -1, -1, 255, 255, 13, 91, -1, 0, 0, 18, 10625, 13590), + (13590, -1, -1, 255, 255, 15, 93, -1, 0, 0, 18, 13589, 13591), + (13592, 5984, 5984, 5984, 5984, 12, 91, 30803, 2, 30, 18, 10626, 13593), + (13595, 534, 534, 534, 534, 12, 91, 30806, 4, 2160, 18, 10710, 13596), + (13598, -1, -1, 6791, 6791, 11, 91, -1, 0, 0, 18, 10678, 13599), + (13601, -1, -1, 852, 852, 11, 91, -1, 0, 0, 18, 12578, 13602), + (13604, 7850, 7850, 7850, 7850, 15, 91, 30812, 39, 4320, 18, 10620, 13605), + (13607, -1, -1, 10453, 10453, 11, 91, -1, 0, 0, 18, 10455, 13608), + (13610, -1, -1, 602, 602, 12, 91, -1, 0, 0, 18, 10687, 13611), + (13613, -1, -1, 855, 855, 11, 91, -1, 0, 0, 18, 10692, 13614), + (13616, -1, -1, 13616, 13616, 7, 91, -1, 0, 0, 18, -1, 13617), + (13617, -1, -1, 13616, 13616, 9, 93, -1, 0, 0, 18, 13616, 13618), + (13618, -1, -1, 13616, 13616, 12, 95, -1, 0, 0, 18, 13617, 14786), + (13619, 7800, 7800, 7800, 7800, 15, 91, 30815, 39, 4320, 18, 10787, 13620), + (13621, -1, -1, 6630, 6630, 9, 91, -1, 0, 0, 18, 10074, 13622), + (13624, 10900, 10900, 10900, 10900, 9, 91, 30817, 55, 120, 18, 10902, 13625), + (13627, -1, -1, 895, 895, 9, 91, -1, 0, 0, 18, 10908, 13628), + (13628, -1, -1, 895, 895, 12, 93, -1, 0, 0, 18, 13627, 13629), + (13630, -1, -1, 9506, 9506, 11, 91, -1, 0, 0, 18, 9508, 13631), + (13633, 6645, 6645, 6645, 6645, 15, 95, 30820, 45, 60, 18, 13107, 15178), + (13646, 13646, 13646, 13646, 13646, 15, 91, 30837, 45, 600, 18, -1, -1), + (13650, 8060, 8060, 8060, 8060, 9, 91, 31524, 41, 1800, 18, 10239, 13651), + (13653, 8063, 8063, 8063, 8063, 9, 91, 31527, 41, 1800, 18, 10242, 13654), + (13656, 8066, 8066, 8066, 8066, 11, 91, 31530, 41, 1800, 18, 10245, 13657), + (13663, 12893, 12893, 12893, 12893, 15, 91, 31534, 76, 1800, 18, 12893, 13664), + (13667, -1, -1, 13667, 13667, 11, 91, -1, 0, 0, 18, -1, 13668), + (13670, 13670, 13670, 13670, 13670, 12, 91, 31538, 43, 1800, 18, -1, 13671), + (13673, 13673, 13673, 13673, 13673, 18, 95, 32050, 0, 1, 18, -1, -1), + (13674, 13674, 13674, 13674, 13674, 18, 95, 32058, 0, 1, 18, -1, -1), + (13675, -1, -1, 5264, 5264, 12, 91, -1, 0, 0, 18, 12800, 13676), + (13678, 13678, 13678, 13678, 13678, 15, 95, 31543, 74, 1200, 18, 12778, -1), + (13682, 12766, 12766, 12766, 12766, 18, 95, 31545, 69, 3600, 18, 12766, -1), + (13683, 6822, 6822, 6822, 6822, 15, 91, 31546, 42, 120, 18, 6822, 14780), + (13684, -1, -1, 13684, 13684, 9, 91, -1, 0, 0, 18, -1, 13685), + (13685, -1, -1, 13684, 13684, 12, 93, -1, 0, 0, 18, 13684, 13686), + (13686, -1, -1, 13684, 13684, 15, 95, -1, 0, 0, 18, 13685, 16653), + (13687, 13687, 13687, 13687, 13687, 15, 91, 31547, 75, 300, 18, -1, 17521), + (13688, 13225, 13225, 13225, 13225, 12, 91, 31548, 0, 4, 18, 13225, 15620), + (13689, -1, -1, 13689, 13689, 9, 91, -1, 0, 0, 18, -1, 13690), + (13692, 12208, 12208, 12208, 12208, 6, 91, 31549, 17, 12, 18, -1, -1), + (13693, 13693, 13693, 13693, 13693, 18, 95, 31550, 76, 500, 18, -1, 17531), + (13695, 13695, 13695, 13695, 13695, 12, 91, 31577, 91, 1320, 18, -1, 13696), + (13698, 4903, 4903, 4903, 4903, 12, 91, 31580, 9, 1320, 18, 12956, 13699), + (13701, 4906, 4906, 4906, 4906, 12, 91, 31583, 9, 1320, 18, 12959, 13702), + (13704, 4912, 4912, 4912, 4912, 12, 91, 31586, 16, 1320, 18, 12958, 13705), + (13707, -1, -1, 1577, 1577, 12, 91, -1, 0, 0, 18, 10264, 13708), + (13710, -1, -1, 795, 795, 9, 91, -1, 0, 0, 18, 12949, 13711), + (13713, -1, -1, 790, 790, 6, 91, -1, 0, 0, 18, 12954, 13714), + (13718, 167, 167, 167, 167, 12, 91, 31589, 14, 900, 18, 12955, 13719), + (13720, 10600, 10600, 10600, 10600, 11, 91, 31591, 73, 20, 18, 12984, 13721), + (13723, 1126, 1126, 1126, 1126, 11, 91, 31594, 2, 2160, 18, 13255, 13724), + (13726, 1017, 1017, 1017, 1017, 12, 91, 31597, 75, 15, 18, 1017, -1), + (13727, 4938, 4938, 4938, 4938, 12, 95, 31598, 35, 1800, 18, 12875, 16031), + (13734, 773, -1, 773, 773, 9, 91, 31606, 5, 1800, 18, 10566, 13735), + (13753, -1, -1, 13753, 13753, 5, 91, -1, 0, 0, 18, -1, 13754), + (13758, -1, -1, 13758, 13758, 5, 91, -1, 0, 0, 18, -1, 13759), + (13763, -1, -1, 781, 781, 12, 95, -1, 0, 0, 18, 7284, -1), + (13764, -1, -1, 13764, 13764, 9, 91, -1, 0, 0, 18, -1, 13765), + (13767, -1, -1, 1604, 1604, 12, 91, -1, 0, 0, 18, 13095, 13768), + (13770, 6328, 6328, 6328, 6328, 9, 91, 31628, 10, 600, 18, 10170, 13771), + (13771, 6328, 6328, 6328, 6328, 12, 93, 31629, 10, 600, 18, 13770, 13772), + (13773, -1, -1, 255, 255, 11, 91, -1, 0, 0, 18, 12610, 13774), + (13774, -1, -1, 255, 255, 13, 92, -1, 0, 0, 18, 13773, 13775), + (13775, -1, -1, 255, 255, 15, 93, -1, 0, 0, 18, 13774, 14126), + (13779, -1, -1, 10850, 10850, 12, 91, 31637, 0, 0, 18, 13209, 13780), + (13782, -1, -1, 1543, 1543, 9, 91, -1, 0, 0, 18, 13217, 13783), + (13785, 5021, 5021, 5021, 5021, 11, 91, 31640, 7, 60, 18, 12621, 13786), + (13788, 13788, 13788, 13788, 13788, 25, 51, 31643, 31, 2, 3, -1, -1), + (13789, -1, -1, 1304, 1304, 11, 91, -1, 0, 0, 18, 13218, 13790), + (13790, -1, -1, 1304, 1304, 13, 93, -1, 0, 0, 18, 13789, 13791), + (13792, 13792, 13792, 13792, 13792, 9, 91, 31644, 18, 600, 18, 12633, 13793), + (13795, -1, -1, 846, 846, 12, 91, -1, 0, 0, 18, 10175, 13796), + (13798, -1, -1, 8325, 8325, 9, 91, -1, 0, 0, 18, 13221, 13799), + (13804, -1, -1, 10650, 10650, 9, 91, -1, 0, 0, 18, 10652, 13805), + (13807, 1352, 1352, 1352, 1352, 9, 91, 31647, 3, 60, 18, 10115, 13808), + (13810, 1358, 1358, 1358, 1358, 9, 91, 31650, 3, 60, 18, 10118, 13811), + (13813, -1, -1, 12706, 12706, 12, 91, 0, 0, 0, 18, 12708, 13814), + (13816, 7875, 7875, 7875, 7875, 9, 91, 31653, 42, 600, 18, 7880, 13817), + (13819, 10346, 10346, 10346, 10346, 12, 95, 31659, 46, 600, 18, 13183, 16924), + (13820, -1, -1, 820, 820, 9, 91, -1, 0, 0, 18, 12669, 13821), + (13823, -1, -1, 6020, 6020, 9, 91, -1, 0, 0, 18, 12693, 13824), + (13826, -1, -1, 9512, 9512, 9, 91, -1, 0, 0, 18, 13189, 13827), + (13829, -1, -1, 10340, 10340, 12, 91, -1, 0, 0, 18, 13186, 13830), + (13832, 1355, 1355, 1355, 1355, 11, 91, 31661, 3, 60, 18, 12702, 13833), + (13835, -1, -1, 611, 611, 9, 91, -1, 0, 0, 18, 12705, 13836), + (13838, 7872, 7872, 7872, 7872, 9, 91, 31664, 41, 600, 18, 12684, 13839), + (13841, -1, -1, 10343, 10343, 9, 91, 0, 0, 0, 18, 10345, 13842), + (13845, 1178, 1178, 1178, 1178, 9, 91, 31669, 4, 900, 18, 10328, 13846), + (13872, 13872, 13872, 13872, 13872, 15, 95, 31694, 63, 60, 18, -1, 16002), + (13873, -1, -1, 13873, 13873, 7, 91, 0, 0, 0, 18, -1, 13874), + (13878, -1, -1, 13878, 13878, 9, 91, 0, 0, 0, 18, -1, 13879), + (13881, -1, -1, 13881, 13881, 9, 91, 0, 0, 0, 18, -1, 13882), + (13884, -1, -1, 735, 735, 10, 91, -1, 0, 0, 18, 10636, 13885), + (13889, -1, -1, 13889, 13889, 5, 91, 0, 0, 0, 18, -1, 13890), + (13894, -1, -1, 1021, 1021, 6, 91, -1, 0, 0, 18, 7685, 13895), + (13899, 6750, 6750, 6750, 6750, 15, 95, 32100, 60, 120, 18, 6750, 15294), + (13905, -1, -1, 13905, 13905, 10, 91, -1, 0, 0, 18, -1, 13906), + (13908, -1, -1, 13908, 13908, 10, 91, -1, 0, 0, 18, -1, 13909), + (13911, -1, -1, 13911, 13911, 12, 91, -1, 0, 0, 18, -1, 13912), + (13914, 4849, 4849, 4849, 4849, 12, 91, 32103, 7, 1800, 18, 7110, 13915), + (13917, -1, -1, 13917, 13917, 9, 91, -1, 0, 0, 18, -1, 13918), + (13920, 6333, 6333, 6333, 6333, 15, 91, 32140, 3, 600, 18, 7266, 16032), + (13921, -1, -1, 98, 98, 12, 91, -1, 0, 0, 18, 11063, 13922), + (13924, -1, -1, 98, 738, 12, 91, -1, 0, 0, 18, 7600, 13925), + (13927, -1, -1, 10370, 10370, 10, 91, -1, 0, 0, 18, 10372, 13928), + (13930, -1, -1, 1592, 1592, 12, 91, -1, 0, 0, 18, 12536, 13931), + (13933, -1, -1, 8263, 8263, 5, 91, -1, 0, 0, 18, 8360, 13934), + (13943, -1, -1, 8268, 8268, 5, 91, -1, 0, 0, 18, 8370, 13944), + (13953, -1, -1, 8273, 8273, 5, 91, -1, 0, 0, 18, 8380, 13954), + (13963, -1, -1, 8278, 8278, 5, 91, -1, 0, 0, 18, 8390, 13964), + (13973, -1, -1, 8283, 8283, 5, 91, -1, 0, 0, 18, 8400, 13974), + (13983, -1, -1, 8288, 8288, 5, 91, -1, 0, 0, 18, 8410, 13984), + (13993, -1, -1, 8293, 8293, 5, 91, -1, 0, 0, 18, 8420, 13994), + (14003, 6492, 6492, 6492, 6492, 12, 91, 32151, 52, 720, 18, 10681, 14004), + (14006, 10711, 10711, 10711, 10711, 15, 91, 32157, 75, 1200, 18, 10713, 14007), + (14009, 13202, 13202, 13202, 13202, 6, 91, 32160, 98, 20, 18, 13202, -1), + (14010, 14010, 14010, 14010, 14010, 15, 95, 32161, 97, 20, 18, -1, -1), + (14011, -1, -1, 14011, 14011, 5, 91, -1, 0, 0, 18, -1, 14012), + (14016, 10354, 10354, 10354, 10354, 15, 95, 32162, 39, 4320, 18, 10354, 14647), + (14017, -1, -1, 14017, 14017, 0, 90, -1, 0, 0, 18, -1, -1), + (14018, -1, -1, 14018, 14018, 0, 91, -1, 0, 0, 18, -1, -1), + (14019, 14019, 14019, 14019, 14019, 12, 91, 32177, 14, 900, 18, -1, 14020), + (14026, -1, -1, 14026, 14026, 12, 91, -1, 0, 0, 18, -1, 14027), + (14029, -1, -1, 14029, 14029, 12, 91, -1, 0, 0, 18, -1, 14030), + (14032, -1, -1, 14032, 14032, 15, 95, -1, 0, 0, 18, -1, -1), + (14037, -1, -1, 14037, 14037, 9, 91, 0, 0, 0, 18, -1, 14038), + (14040, -1, -1, 14040, 14040, 9, 91, 0, 0, 0, 18, -1, 14041), + (14043, -1, -1, 1313, 1313, 12, 91, -1, 0, 0, 18, 12581, 14044), + (14046, -1, -1, 14046, 14046, 5, 91, -1, 0, 0, 18, -1, 14047), + (14051, 14051, 14051, 14051, 14051, 12, 95, 32300, 62, 8, 18, -1, 15774), + (14052, 14052, 14052, 14052, 14052, 21, 95, 32301, 13, 1440, 18, -1, 14793), + (14053, 10912, 10912, 10912, 10912, 9, 91, 32303, 69, 1800, 18, 10914, 14054), + (14054, 10912, 10912, 10912, 10912, 12, 93, 32304, 69, 1800, 18, 14053, 14055), + (14055, 10912, 10912, 10912, 10912, 15, 95, 32305, 69, 1800, 18, 14054, -1), + (14056, -1, -1, 14056, 14056, 9, 91, -1, 0, 0, 18, -1, 14057), + (14059, -1, -1, 14059, 14059, 9, 91, -1, 0, 0, 18, -1, 14060), + (14062, -1, -1, 14062, 14062, 9, 91, -1, 0, 0, 18, -1, 14063), + (14065, -1, -1, 14065, 14065, 9, 91, 0, 0, 0, 18, -1, 14066), + (14068, -1, -1, 14068, 14068, 9, 91, 0, 0, 0, 18, -1, 14069), + (14071, 14071, 14071, 14071, 14071, 9, 91, 32307, 12, 600, 18, -1, 14072), + (14076, -1, -1, 14076, 14076, 9, 91, -1, 0, 0, 18, -1, 14077), + (14080, 14080, 14080, 14080, 14080, 9, 95, 32312, 13, 900, 18, -1, -1), + (14081, 14081, 14081, 14081, 14081, 9, 95, 32313, 14, 120, 18, -1, 17240), + (14082, -1, -1, 13101, 13101, 9, 91, 0, 0, 0, 18, 13103, 14083), + (14085, -1, -1, 14085, 14085, 9, 91, -1, 0, 0, 18, -1, 14086), + (14088, -1, -1, 14088, 14088, 9, 91, -1, 0, 0, 18, -1, 14089), + (14091, -1, -1, 14091, 14091, 9, 91, -1, 0, 0, 18, -1, 14092), + (14094, -1, -1, 10355, 10355, 9, 91, -1, 0, 0, 18, 10645, 14095), + (14097, -1, -1, 6395, 6395, 12, 91, -1, 0, 0, 18, 10707, 14098), + (14100, -1, -1, 14100, 14100, 15, 95, -1, 0, 0, 18, -1, -1), + (14101, -1, -1, 6355, 6355, 9, 91, -1, 0, 0, 18, 6360, 14263), + (14111, 6754, 6754, 6754, 6754, 12, 95, 32326, 41, 1200, 18, 10053, 14839), + (14112, 6370, 6370, 6370, 6370, 9, 91, 32329, 7, 600, 18, 7352, 14113), + (14115, -1, -1, 14115, 14115, 12, 91, -1, 0, 0, 18, -1, 14116), + (14129, -1, -1, 14129, 14129, 12, 91, -1, 0, 0, 18, -1, 14130), + (14130, -1, -1, 14129, 14129, 15, 93, -1, 0, 0, 18, 14129, 14131), + (14132, -1, -1, 7751, 7751, 7, 91, -1, 0, 0, 18, 7753, 14133), + (14135, -1, -1, 14135, 14135, 12, 91, -1, 0, 0, 18, -1, 14136), + (14138, -1, -1, 12615, 12615, 18, 95, -1, 0, 0, 18, 12617, 15499), + (14139, 14139, 14139, 14139, 14139, 15, 95, 32328, 60, 60, 18, -1, -1), + (14140, -1, -1, 12607, 12607, 15, 95, 0, 0, 0, 18, 12607, 15631), + (14141, -1, -1, 14141, 14141, 9, 91, -1, 0, 0, 18, -1, 14142), + (14144, -1, -1, 14144, 14144, 7, 91, -1, 0, 0, 18, -1, 14145), + (14148, -1, -1, 14148, 14148, 9, 91, 0, 0, 0, 18, -1, 14149), + (14151, -1, -1, 14151, 14151, 9, 91, 0, 0, 0, 18, -1, 14152), + (14154, -1, -1, 10657, 10657, 12, 91, 0, 0, 0, 18, 12681, 14155), + (14157, -1, -1, 14157, 14157, 9, 91, 0, 0, 0, 18, -1, 14158), + (14160, -1, -1, 14160, 14160, 9, 91, 0, 0, 0, 18, -1, 14161), + (14163, -1, -1, 14163, 14163, 9, 91, 0, 0, 0, 18, -1, 14164), + (14166, -1, -1, 14166, 14166, 9, 91, 0, 0, 0, 18, -1, 14167), + (14169, -1, -1, 14169, 14169, 7, 91, -1, 0, 0, 18, -1, 14170), + (14173, -1, -1, 12710, 12710, 9, 91, -1, 0, 0, 18, 12712, 14174), + (14176, -1, -1, 13204, 13204, 9, 91, -1, 0, 0, 18, 13206, 14177), + (14179, -1, -1, 14179, 14179, 9, 95, -1, 0, 0, 18, -1, -1), + (14180, -1, -1, 14180, 14180, 9, 95, -1, 0, 0, 18, -1, -1), + (14181, -1, -1, 14181, 14181, 9, 91, -1, 0, 0, 18, -1, 14182), + (14186, -1, -1, 14186, 14186, 9, 91, -1, 0, 0, 18, -1, 14187), + (14189, 5017, 5017, 5017, 5017, 9, 91, 32332, 8, 600, 18, 10158, 14190), + (14192, 14192, 14192, 14192, 14192, 15, 95, 32335, 36, 12, 18, -1, 15525), + (14196, -1, -1, 6935, 6935, 9, 91, -1, 0, 0, 18, 6904, 14197), + (14199, -1, -1, 6908, 6908, 12, 95, -1, 0, 0, 18, 6910, 15560), + (14200, -1, -1, 14200, 14200, 9, 91, 32336, 0, 0, 18, -1, 14201), + (14203, -1, -1, 14203, 14203, 12, 91, -1, 0, 0, 18, -1, 14204), + (14206, 14206, 14206, 14206, 14206, 12, 95, 32339, 41, 600, 18, -1, 15324), + (14207, 14207, 14207, 14207, 14207, 12, 95, 32340, 39, 180, 18, -1, -1), + (14208, 14208, 14208, 14208, 14208, 12, 95, 32341, 17, 180, 18, -1, 14568), + (14209, 14209, 14209, 14209, 14209, 12, 95, 32342, 22, 3, 18, -1, -1), + (14210, -1, -1, 10358, 10358, 12, 91, -1, 0, 0, 18, 10360, 14211), + (14213, -1, -1, 14213, 14213, 11, 91, -1, 0, 0, 18, -1, 14214), + (14218, -1, -1, 962, 962, 9, 91, -1, 0, 0, 18, 10363, 14219), + (14221, 1383, 1383, 1383, 1383, 18, 95, 32345, 6, 300, 18, 6487, 14581), + (14222, 146, 146, 146, 146, 15, 95, 32346, 2, 180, 18, 13258, 14977), + (14223, -1, -1, 13010, 13010, 12, 95, 0, 0, 0, 18, 13012, 16205), + (14224, 14224, -1, 14224, 14224, 9, 91, 345, 61, 5, 18, -1, 15860), + (14225, -1, -1, 14225, 14225, 9, 91, -1, 0, 0, 18, -1, 14226), + (14229, 14229, 14229, 14229, 14229, 12, 100, 37168, 42, 600, 19, -1, -1), + (14231, 14231, 14231, 14231, 14231, 12, 95, 32347, 91, 6, 18, -1, 16207), + (14232, 14232, -1, 14232, 14232, 12, 95, 32348, 92, 6, 18, -1, 14674), + (14233, 14233, 14233, 14233, 14233, 15, 95, 32349, 93, 30, 18, -1, 15621), + (14234, 14234, 14234, 14234, 14234, 9, 91, 32350, 94, 1800, 18, -1, 14235), + (14237, 12638, 12638, 12638, 12638, 9, 91, 23581, 68, 10, 18, -1, -1), + (14238, -1, -1, 12968, 12968, 9, 91, 0, 0, 0, 18, 12970, 14239), + (14241, -1, -1, 14241, 14241, 9, 91, -1, 0, 0, 18, -1, 14242), + (14244, -1, -1, 14244, 14244, 9, 91, -1, 0, 0, 18, -1, 14245), + (14249, -1, -1, 14249, 14249, 9, 91, -1, 0, 0, 18, -1, 14250), + (14254, -1, -1, 14254, 14254, 11, 91, -1, 0, 0, 18, -1, 14255), + (14256, 6561, 6561, 6561, 6561, 9, 91, 32353, 32, 30, 18, 10420, 14257), + (14259, -1, -1, 14259, 14259, 11, 91, -1, 0, 0, 18, -1, 14260), + (14262, 14262, 14262, 14262, 14262, 15, 95, 32357, 95, 180, 18, -1, -1), + (14264, 14264, 14264, 14264, 14264, 12, 95, 32358, 97, 120, 18, -1, 14600), + (14265, 14265, 14265, 14265, 14265, 15, 95, 32359, 68, 30, 18, -1, -1), + (14272, 6218, 6218, 6218, 14272, 12, 95, 32369, 0, 1, 18, 7488, 17381), + (14273, 723, 723, 723, 723, 12, 95, 32370, 6, 30, 18, 10300, 14869), + (14274, 6971, 6971, 6971, 6971, 9, 91, 32371, 41, 600, 18, 10290, 17383), + (14275, -1, -1, 14275, 14275, 7, 91, -1, 0, 0, 18, -1, 14276), + (14278, -1, -1, 14278, 14278, 12, 95, 0, 0, 0, 18, 6990, 16248), + (14279, -1, -1, 1287, 1287, 11, 95, -1, 0, 0, 18, 12815, 16529), + (14280, 4890, -1, 4890, 4890, 12, 95, 32373, 3, 8640, 18, 5872, 14776), + (14281, 14281, 14281, 14281, 14281, 12, 95, 32375, 39, 15, 18, -1, -1), + (14282, 14282, 14282, 14282, 14282, 9, 91, 32374, 39, 7, 18, -1, -1), + (14283, -1, -1, 14283, 14283, 7, 91, -1, 0, 0, 18, -1, 14284), + (14286, -1, -1, 14286, 14286, 9, 91, -1, 0, 0, 18, -1, 14287), + (14289, -1, -1, 14289, 14289, 9, 91, -1, 0, 0, 18, -1, 14290), + (14292, -1, -1, 14292, 14292, 9, 91, -1, 0, 0, 18, -1, 14293), + (14295, -1, -1, 14295, 14295, 9, 95, -1, 0, 0, 18, -1, 14296), + (14301, -1, -1, 14301, 14301, 9, 91, -1, 0, 0, 18, -1, 14302), + (14304, -1, -1, 14304, 14304, 9, 91, -1, 0, 0, 18, -1, 14305), + (14307, 14307, 14307, 14307, 14307, 12, 95, 32376, 92, 1200, 18, -1, 14743), + (14308, -1, -1, 14308, 14308, 9, 91, -1, 0, 0, 18, -1, 14309), + (14311, -1, -1, 14311, 14311, 9, 91, -1, 0, 0, 18, -1, 14312), + (14314, -1, -1, 7715, 7715, 7, 91, -1, 0, 0, 18, 7717, 14315), + (14318, -1, -1, 14318, 14318, 9, 91, -1, 0, 0, 18, -1, 14319), + (14321, 14321, 14321, 14321, 14321, 12, 95, 32378, 92, 8, 18, -1, 14781), + (14322, 14322, 14322, 14322, 14322, 12, 95, 32379, 94, 2160, 18, -1, 14782), + (14323, 14323, 14323, 14323, 14323, 12, 95, 32380, 92, 150, 18, -1, -1), + (14324, 155, 155, 155, 155, 15, 95, 32381, 8, 60, 18, 7238, 15610), + (14328, -1, -1, 7822, 7822, 7, 91, -1, 0, 0, 18, 7826, 14329), + (14331, -1, -1, 14331, 14331, 9, 91, -1, 0, 0, 18, -1, 14332), + (14338, 1337, 1337, 1337, 1337, 12, 91, 32382, 13, 4320, 18, 6160, 14339), + (14341, -1, -1, 14341, 14341, 5, 91, -1, 0, 0, 18, -1, 14342), + (14346, 14346, 14346, 14346, 14346, 9, 91, 32385, 94, 12, 18, -1, 14347), + (14349, -1, -1, 1210, 1213, 12, 91, -1, 0, 0, 18, 12528, 14350), + (14352, 1274, 1274, 1274, 1274, 12, 91, 32391, 9, 540, 18, 12762, 14353), + (14355, 6815, 6815, 6815, 6815, 9, 91, 32394, 60, 600, 18, 12788, 14356), + (14358, 14358, -1, 14358, 14358, 15, 95, 32397, 98, 300, 18, -1, -1), + (14359, 14359, 14359, 14359, 14359, 15, 95, 32399, 93, 1200, 18, -1, -1), + (14360, 14360, 14360, 14360, 14360, 15, 95, 32400, 95, 1800, 18, -1, 16334), + (14361, -1, -1, 637, 637, 12, 91, -1, 0, 0, 18, 12555, 14362), + (14364, -1, -1, 14364, 14364, 9, 91, -1, 0, 0, 18, -1, 14365), + (14367, -1, -1, 14367, 14367, 0, 1, -1, 0, 0, 0, -1, 14368), + (14371, 14371, 14371, 14371, 14371, 0, 1, 32910, 0, 10, 0, -1, -1), + (14372, 13844, 13844, 13844, 13844, 6, 95, 31667, 47, 6, 18, -1, -1), + (14373, 14373, 14373, 14373, 14373, 0, 85, 33106, 87, 3600, 19, -1, -1), + (14374, 14374, 14374, 14374, 14374, 0, 86, 33107, 88, 28800, 19, -1, -1), + (14690, 14690, 14690, 14690, 14690, 15, 96, 37014, 45, 600, 19, -1, 17479), + (14729, 8342, 8342, 8342, 8342, 15, 100, 33909, 54, 240, 19, 8342, 17501), + (14730, 616, 616, 616, 616, 12, 96, 33910, 7, 900, 19, 10261, 14731), + (14733, 4909, 4909, 4909, 4909, 18, 100, 33913, 16, 1320, 19, 12957, 17147), + (14734, 7903, 7903, 7903, 7903, 12, 100, 33914, 60, 30, 19, 12976, 15853), + (14739, 1462, 1462, 1462, 1462, 18, 99, 33919, 5, 300, 19, 4902, 16054), + (14764, -1, -1, 10551, 10551, 12, 96, -1, 0, 0, 19, 10553, 14765), + (14991, 926, 926, 926, 926, 5, 85, 11071, 12, 1800, 17, 930, 14992), + (14992, 926, 926, 926, 926, 5, 86, 11072, 12, 1800, 17, 14991, 14993), + (15073, 15073, -1, 15073, 15073, 0, 1, 37668, 90, 60, 19, -1, -1), + (15074, -1, -1, 15074, 15074, 0, 1, -1, 0, 0, 19, -1, 15075), + (15096, 15096, 15096, 15096, 15096, 5, 96, 38151, 35, 30, 19, -1, 15097), + (15099, 15099, 15099, 15099, 15099, 12, 100, 37187, 15, 45, 19, -1, 16566), + (15100, -1, -1, 15100, 15100, 5, 96, -1, 0, 0, 19, -1, 15101), + (15105, -1, -1, 15105, 15105, 11, 96, -1, 0, 0, 19, -1, 15106), + (15108, -1, -1, 15108, 15108, 9, 98, -1, 0, 0, 19, -1, 15109), + (15111, 8300, 8300, 8300, 8300, 11, 97, 37189, 8, 900, 19, 8302, 15112), + (15113, -1, -1, 15113, 15113, 11, 96, -1, 0, 0, 19, -1, 15114), + (15119, 15119, 15119, 15119, 15119, 12, 100, 37194, 16, 1200, 19, -1, 15749), + (15120, -1, -1, 15120, 15120, 9, 96, -1, 0, 0, 19, -1, 15121), + (15123, -1, -1, 15123, 15123, 9, 96, -1, 0, 0, 19, -1, 15124), + (15126, -1, -1, 15126, 15126, 9, 96, -1, 0, 0, 19, -1, 15127), + (15129, 15129, 15129, 15129, 15129, 12, 100, 37196, 32, 180, 19, -1, 15736), + (15130, 15130, 15130, 15130, 15130, 12, 100, 37197, 32, 180, 19, -1, 15737), + (15131, 15131, 15131, 15131, 15131, 12, 100, 37198, 32, 180, 19, -1, 15738), + (15132, -1, -1, 15132, 15132, 9, 96, -1, 0, 0, 19, -1, 15133), + (15135, -1, -1, 15135, 15135, 9, 100, -1, 0, 0, 19, -1, -1), + (15136, 15136, 15136, 15136, 15136, 9, 96, 38001, 5, 120, 19, -1, 17241), + (15140, 13100, 13100, 13100, 13100, 11, 100, 38002, 86, 300, 19, 13100, -1), + (15141, -1, -1, 190, 190, 9, 96, -1, 0, 0, 19, 5040, 15142), + (15146, 15146, 15146, 15146, 15146, 13, 100, 38006, 95, 9, 19, -1, 15758), + (15147, 15147, 15147, 15147, 15147, 11, 96, 38007, 8, 1200, 19, -1, 15148), + (15150, -1, -1, 15150, 15150, 7, 96, -1, 0, 0, 19, -1, 15151), + (15153, -1, -1, 15153, 15153, 11, 100, -1, 0, 0, 19, -1, -1), + (15154, -1, -1, 15154, 15154, 9, 96, -1, 0, 0, 19, -1, -1), + (15155, -1, -1, 15155, 15155, 5, 96, -1, 0, 0, 19, -1, 15156), + (15158, -1, -1, 15158, 15158, 13, 100, -1, 0, 0, 19, -1, -1), + (15159, -1, -1, 15159, 15159, 7, 96, -1, 0, 0, 19, -1, 15160), + (15162, -1, -1, 15162, 15162, 7, 96, -1, 0, 0, 19, -1, 15163), + (15168, -1, -1, 15168, 15168, 9, 96, -1, 0, 0, 19, -1, 15169), + (15172, -1, -1, 210, 210, 12, 100, -1, 0, 0, 19, 7401, 16658), + (15173, 6639, 6639, 6639, 6639, 9, 100, 38012, 42, 300, 19, 6639, 15788), + (15174, -1, -1, 12582, 12582, 9, 96, -1, 0, 0, 19, 12584, 15175), + (15177, 15177, 15177, 15177, 15177, 9, 100, 38013, 94, 180, 19, -1, -1), + (15179, -1, -1, 15179, 15179, 7, 96, -1, 0, 0, 19, -1, 15180), + (15182, -1, -1, 7757, 7757, 5, 96, -1, 0, 0, 19, 12589, 15183), + (15188, -1, -1, 1528, 4819, 5, 96, -1, 0, 0, 19, 4823, 15189), + (15193, 15193, 15193, 15193, 15193, 15, 100, 38016, 92, 600, 19, -1, -1), + (15194, -1, -1, 15194, 15194, 9, 100, -1, 0, 0, 19, -1, -1), + (15200, 15200, 15200, 15200, 15200, 9, 96, 38304, 32, 1080, 19, -1, 15201), + (15203, 15203, 15203, 15203, 15203, 15, 100, 38307, 34, 480, 19, -1, -1), + (15204, -1, -1, 15204, 15204, 9, 96, -1, 0, 0, 19, -1, 15205), + (15207, -1, -1, 15207, 15207, 9, 96, -1, 0, 0, 19, -1, 15208), + (15210, 15210, 15210, 15210, 15210, 9, 96, 38308, 12, 120, 19, -1, 15211), + (15213, 15213, 15213, 15213, 15213, 15, 100, 38312, 42, 1080, 19, -1, 17509), + (15214, 15214, 15214, 15214, 15214, 9, 96, 38313, 43, 1800, 19, -1, 15215), + (15217, -1, -1, 15217, 15217, 11, 96, -1, 0, 0, 19, -1, 15218), + (15220, -1, -1, 15220, 15220, 9, 100, -1, 0, 0, 19, -1, 15221), + (15223, -1, -1, 15223, 15223, 9, 100, -1, 0, 0, 19, -1, 15224), + (15226, -1, -1, 15226, 15226, 9, 100, -1, 0, 0, 19, -1, 15227), + (15229, -1, -1, 15229, 15229, 9, 100, -1, 0, 0, 19, -1, 15230), + (15232, -1, -1, 15232, 15232, 9, 96, -1, 0, 0, 19, -1, 15233), + (15235, 785, 785, 785, 785, 9, 96, 38325, 8, 900, 19, 789, 15236), + (15238, -1, -1, 5276, 5276, 11, 96, -1, 0, 0, 19, 5278, 15239), + (15241, 168, 168, 168, 168, 11, 96, 38329, 4, 10, 19, 170, 15242), + (15244, 171, 171, 171, 171, 11, 96, 38333, 4, 10, 19, 173, 15245), + (15247, 174, 174, 174, 174, 11, 96, 38336, 4, 10, 19, 176, 15248), + (15250, 177, 177, 177, 177, 11, 96, 38340, 4, 10, 19, 179, 15251), + (15253, -1, -1, 15253, 15253, 4, 96, -1, 0, 0, 19, -1, 15254), + (15258, -1, -1, 7743, 7743, 11, 100, -1, 0, 0, 19, 10718, -1), + (15270, -1, -1, 12430, 12430, 15, 100, -1, 0, 0, 19, 12878, -1), + (15280, -1, -1, 10722, 10722, 9, 96, -1, 0, 0, 19, 10726, 15281), + (15283, -1, -1, 15283, 15283, 5, 96, -1, 0, 0, 19, -1, 15284), + (15288, -1, -1, 15288, 15288, 7, 96, -1, 0, 0, 19, -1, 15289), + (15295, -1, -1, 15295, 15295, 7, 96, -1, 0, 0, 19, -1, 15296), + (15298, 10806, 10806, 10806, 10806, 9, 96, 38025, 71, 540, 19, 10808, 15299), + (15301, 10809, 10809, 10809, 10809, 9, 96, 38028, 71, 540, 19, 10811, 15302), + (15304, 15304, 15304, 15304, 15304, 12, 100, 38031, 91, 360, 19, -1, -1), + (15314, 0, 0, 6481, 6481, 11, 96, -1, 0, 0, 19, 6483, 15315), + (15317, -1, -1, 15317, 15317, 9, 96, -1, 0, 0, 19, 5012, 15318), + (15320, -1, -1, 7940, 7940, 11, 100, -1, 0, 0, 19, 6486, -1), + (15321, 746, 746, 746, 746, 9, 96, 38033, 10, 2160, 19, 10024, 15322), + (15328, -1, -1, 7948, 7948, 9, 96, -1, 0, 0, 19, 10037, 15329), + (15338, 15338, 15338, 15338, 15338, 9, 96, 38054, 30, 600, 19, -1, 15339), + (15341, 136, -1, 136, 136, 7, 100, 38057, 7, 1800, 19, 136, -1), + (15342, -1, -1, 15341, 15341, 7, 100, -1, 0, 0, 19, -1, -1), + (15343, 15343, 15343, 15343, 15343, 12, 100, 38058, 21, 300, 19, -1, -1), + (15344, -1, -1, 2400, 2400, 12, 97, -1, 0, 0, 19, 2402, 15345), + (15348, -1, -1, 13001, 13001, 7, 96, -1, 0, 0, 19, 13003, 15349), + (15356, -1, -1, 15356, 15356, 15, 100, -1, 0, 0, 19, -1, 15851), + (15357, 15357, 15357, 15357, 15357, 9, 96, 38062, 95, 2, 19, -1, -1), + (15358, -1, -1, 15358, 15358, 12, 100, -1, 0, 0, 19, -1, -1), + (15359, -1, -1, 474, 474, 5, 96, -1, 0, 0, 19, 476, 15360), + (15362, 15362, 15362, 15362, 15362, 15, 100, 38063, 89, 20, 19, -1, -1), + (15363, -1, -1, 10951, 10951, 12, 97, -1, 0, 0, 19, 10953, 15364), + (15371, -1, -1, 15371, 15371, 7, 96, -1, 0, 0, 19, -1, 15372), + (15374, -1, -1, 15374, 15374, 9, 96, -1, 0, 0, 19, -1, 15375), + (15377, 15377, 15377, 15377, 15377, 15, 100, 38070, 75, 420, 19, -1, 15852), + (15383, -1, -1, 15383, 15383, 9, 96, -1, 0, 0, 19, -1, 15384), + (15389, -1, -1, 15389, 15389, 9, 96, -1, 0, 0, 19, -1, 15390), + (15396, -1, -1, 141, 12863, 12, 100, -1, 0, 0, 19, 12863, -1), + (15397, -1, -1, 6346, 6346, 9, 96, -1, 0, 0, 19, 7617, 15398), + (15403, -1, -1, 15403, 15403, 7, 96, -1, 0, 0, 19, -1, 15404), + (15406, -1, -1, 15406, 15406, 7, 96, -1, 0, 0, 19, -1, 15407), + (15414, -1, -1, 15414, 15414, 9, 100, -1, 0, 0, 19, -1, -1), + (15421, -1, -1, 6538, 6538, 12, 100, -1, 0, 0, 19, 7478, -1), + (15422, -1, -1, 83, 83, 12, 100, -1, 0, 0, 19, 1218, -1), + (15423, 15423, 15423, 15423, 15423, 15, 100, 38078, 52, 180, 19, -1, 15884), + (15424, 15424, 15424, 15424, 15424, 12, 100, 38079, 78, 1200, 19, -1, -1), + (15425, 15425, 15425, 15425, 15425, 15, 100, 38077, 79, 6, 19, -1, 15903), + (15426, -1, -1, 810, 810, 5, 96, -1, 0, 0, 19, 4828, 15427), + (15429, -1, -1, 15429, 15429, 7, 96, -1, 0, 0, 19, -1, 15430), + (15432, -1, -1, 15432, 15432, 7, 96, -1, 0, 0, 19, -1, 15433), + (15438, -1, -1, 15438, 15438, 9, 96, -1, 0, 0, 19, -1, 15439), + (15441, -1, -1, 815, 815, 10, 96, -1, 0, 0, 19, 7636, 15442), + (15444, -1, -1, 15444, 15444, 9, 96, 38080, 0, 0, 19, -1, 15445), + (15447, 15447, 15447, 15447, 15447, 9, 96, 38083, 78, 180, 19, -1, 15448), + (15450, -1, -1, 15450, 15450, 9, 96, -1, 0, 0, 19, -1, 15451), + (15453, -1, -1, 15453, 15453, 9, 96, -1, 0, 0, 19, -1, 15454), + (15456, -1, -1, 15456, 15456, 9, 96, -1, 0, 0, 19, -1, 15457), + (15459, 1245, 1245, 1245, 1245, 9, 96, 38404, 8, 2160, 19, 1247, 15460), + (15462, 8039, 8039, 8039, 38407, 15, 100, 38407, 58, 7, 19, 8039, 17167), + (15466, -1, -1, 10561, 10561, 9, 96, -1, 0, 0, 19, 10563, 15467), + (15469, -1, -1, 10558, 10558, 9, 96, -1, 0, 0, 19, 10560, 15470), + (15472, -1, -1, 8035, 8035, 9, 96, -1, 0, 0, 19, 10287, 15473), + (15475, 15475, 15475, 15475, 15475, 11, 96, 38408, 41, 600, 20, -1, 15476), + (15478, -1, -1, 15478, 15478, 9, 96, -1, 0, 0, 19, -1, 15479), + (15481, 15481, 15481, 15481, 15481, 18, 100, 38603, 53, 1080, 19, -1, -1), + (15482, 15482, 15482, 15482, 15482, 11, 96, 38414, 42, 1800, 19, -1, 15483), + (15485, -1, -1, 15485, 15485, 18, 100, -1, 0, 0, 19, -1, -1), + (15486, 15486, 15486, 15486, 15486, 12, 96, 38418, 43, 600, 19, -1, 15487), + (15489, 15489, 15489, 15489, 15489, 18, 100, 38421, 52, 10, 19, -1, -1), + (15490, 15490, 15490, 15490, 15490, 11, 96, 38422, 44, 10, 19, -1, 15491), + (15493, -1, -1, 15493, 15493, 9, 96, -1, 0, 0, 19, -1, 15494), + (15496, 15496, 15496, 15496, 15496, 11, 96, 38425, 46, 1800, 19, -1, 15497), + (15502, -1, -1, 15502, 15502, 9, 96, -1, 0, 0, 19, -1, 15503), + (15509, -1, -1, 15509, 15509, 9, 96, -1, 0, 0, 19, -1, 15510), + (15512, -1, -1, 15512, 15512, 9, 96, 38086, 0, 0, 19, -1, 15513), + (15515, 15515, 15515, 15515, 15515, 12, 100, 38089, 11, 90, 19, -1, 17417), + (15516, -1, -1, 15516, 15516, 9, 100, -1, 0, 0, 19, -1, 15960), + (15517, -1, -1, 15517, 15517, 7, 96, -1, 0, 0, 19, -1, 15518), + (15521, 15521, 15521, 15521, 15521, 12, 96, 38090, 42, 60, 19, -1, -1), + (15526, -1, -1, 12716, 12716, 7, 96, -1, 0, 0, 19, 12718, 15527), + (15529, -1, -1, 695, 695, 4, 96, -1, 0, 0, 19, 699, 15530), + (15540, -1, -1, 15540, 15540, 7, 96, -1, 0, 0, 19, -1, 15541), + (15543, -1, -1, 15543, 15543, 7, 96, -1, 0, 0, 19, -1, 15544), + (15546, -1, -1, 15546, 15546, 7, 96, -1, 0, 0, 19, -1, 15547), + (15549, -1, -1, 15549, 15549, 7, 96, -1, 0, 0, 19, -1, 15550), + (15552, -1, -1, 6302, 6302, 5, 96, -1, 0, 0, 19, 11013, 15553), + (15555, -1, -1, 15555, 15555, 11, 96, -1, 0, 0, 19, -1, 15556), + (15558, 10400, 10400, 10400, 10400, 9, 100, 38104, 62, 900, 19, 10400, -1), + (15564, -1, -1, 15564, 15564, 9, 96, -1, 0, 0, 19, -1, 15565), + (15567, 15567, 15567, 15567, 15567, 12, 96, 38106, 11, 1200, 19, -1, 15568), + (15569, 15569, 15569, 15569, 15569, 12, 96, 38108, 13, 60, 19, -1, 15991), + (15570, 15570, 15570, 15570, 15570, 15, 100, 38109, 64, 600, 19, -1, 15992), + (15571, -1, -1, 15571, 15571, 7, 96, -1, 0, 0, 19, -1, 15572), + (15574, 15574, 15574, 15574, 15574, 9, 80, 38110, 73, 4, 15, -1, 15575), + (15575, 15574, 15574, 15574, 15574, 9, 85, 38111, 73, 4, 16, 15574, 15576), + (15576, 15574, 15574, 15574, 15574, 9, 90, 38112, 73, 4, 17, 15575, 15577), + (15577, 15574, 15574, 15574, 15574, 9, 95, 38113, 73, 4, 18, 15576, 15578), + (15579, -1, -1, 15579, 15579, 7, 96, -1, 0, 0, 19, -1, 15580), + (15582, 15582, 15582, 15582, 15582, 9, 96, 38115, 34, 600, 19, -1, 15583), + (15585, -1, -1, 634, 634, 11, 96, -1, 0, 0, 19, 10780, 15586), + (15588, 10701, 10701, 10701, 10701, 12, 96, 38121, 32, 360, 19, 12756, 15589), + (15591, -1, -1, 15591, 15591, 5, 96, -1, 0, 0, 19, -1, 15592), + (15594, 15594, 15594, 15594, 15594, 9, 96, 38197, 39, 30, 19, -1, 15595), + (15598, -1, -1, 15598, 15598, 12, 96, -1, 0, 0, 19, -1, 15599), + (15601, 15601, 15601, 15601, 15601, 12, 96, 38131, 34, 6, 19, -1, 16077), + (15602, -1, -1, 15602, 15602, 9, 96, -1, 0, 0, 19, -1, 15603), + (15605, 12866, 12866, 12866, 12866, 15, 96, 38132, 74, 1800, 19, 12866, -1), + (15606, -1, -1, 8069, 8069, 5, 96, -1, 0, 0, 19, 8071, 15607), + (15609, -1, -1, 15609, 15609, 15, 100, -1, 0, 0, 19, -1, -1), + (15611, 15611, 15611, 15611, 15611, 18, 100, 38136, 32, 900, 19, -1, 16078), + (15612, 15612, 15612, 15612, 15612, 12, 96, 38137, 36, 20, 19, -1, 15613), + (15615, 15615, 15615, 15615, 15615, 12, 96, 38140, 44, 20, 19, -1, 15616), + (15619, 15619, 15619, 15619, 15619, 15, 100, 37188, 32, 600, 19, -1, -1), + (15622, -1, -1, 15622, 15622, 7, 96, -1, 0, 0, 19, -1, 15623), + (15625, -1, -1, 15625, 15625, 9, 96, -1, 0, 0, 19, -1, 15626), + (15628, 5022, 5022, 5022, 5022, 9, 96, 38176, 5, 600, 19, 6040, 15629), + (15632, -1, -1, 7005, 7005, 5, 96, -1, 0, 0, 19, 7007, 15633), + (15634, -1, -1, 15634, 15634, 3, 80, -1, 0, 0, 19, -1, 15635), + (15635, -1, -1, 15634, 15634, 5, 85, -1, 0, 0, 19, 15634, 15636), + (15639, 15639, 15639, 15639, 15639, 12, 96, 38183, 56, 60, 19, -1, -1), + (15640, 15640, 15640, 15640, 15640, 12, 100, 38184, 43, 60, 19, -1, -1), + (15642, 15642, 15642, 15642, 15642, 18, 100, 38187, 13, 1440, 19, -1, -1), + (15643, 15643, 15643, 15643, 15643, 9, 96, 38188, 75, 600, 19, -1, 15644), + (15646, 15646, 15646, 15646, 15646, 15, 100, 38194, 74, 60, 19, -1, 17255), + (15648, -1, -1, 15648, 15648, 9, 96, -1, 0, 0, 19, -1, 15649), + (15694, -1, -1, 8215, 8215, 5, 96, -1, 0, 0, 20, 12563, 15695), + (15714, -1, -1, 5263, 5263, 12, 96, -1, 0, 0, 20, 12468, 15715), + (15719, -1, -1, 1287, 1287, 11, 96, -1, 0, 0, 20, 13240, 15720), + (15746, -1, -1, 7033, 7033, 12, 96, 0, 0, 0, 20, 7035, 15747), + (15768, -1, -1, 15768, 15768, 7, 96, -1, 0, 0, 20, -1, 15769), + (15771, 15771, -1, 15771, 15771, 1, 55, 38274, 0, 3, 20, -1, -1), + (15772, -1, -1, 8232, 8232, 8, 100, -1, 0, 0, 20, 8261, -1), + (15773, -1, -1, 8040, 8040, 8, 100, -1, 0, 0, 20, 8313, -1), + (15775, 6508, 6508, 6508, 6508, 9, 96, 38276, 38, 600, 20, 10080, 15776), + (15778, -1, -1, 589, 589, 12, 96, -1, 0, 0, 20, 13106, 15779), + (15782, 7755, 7755, 7755, 7755, 12, 96, 38280, 53, 900, 20, 7755, 16187), + (15798, 15798, 15798, 15798, 15798, 9, 100, 38297, 34, 18, 20, -1, 15799), + (15819, 15819, 15819, 15819, 15819, 18, 100, 40807, 18, 900, 20, -1, -1), + (15833, -1, -1, 15833, 15833, 9, 96, 0, 0, 0, 20, -1, 15834), + (15836, -1, -1, 15836, 15836, 9, 100, 0, 0, 0, 20, -1, 15837), + (15839, 10450, 10450, 10450, 10450, 7, 96, 40817, 63, 900, 20, 10670, 15840), + (15855, 13004, 13004, 13004, 13004, 9, 96, 40832, 78, 300, 20, 13004, -1), + (15891, -1, -1, 11078, 11078, 9, 96, 0, 0, 0, 20, 11078, 15892), + (15893, -1, -1, 11079, 11079, 9, 96, 0, 0, 0, 20, 11079, 15894), + (15895, -1, -1, 11077, 11077, 9, 96, 0, 0, 0, 20, 11077, 15896), + (15904, 15904, 15904, 15904, 15904, 7, 66, 40874, 54, 600, 20, -1, -1), + (15908, -1, -1, 15908, 15908, 3, 80, -1, 0, 0, 20, -1, 15909), + (15909, -1, -1, 15908, 15908, 5, 85, -1, 0, 0, 20, 15908, 15910), + (15910, -1, -1, 15908, 15908, 7, 90, -1, 0, 0, 20, 15909, 15911), + (15954, -1, -1, 10853, 10853, 5, 90, -1, 0, 0, 20, 10864, 15955), + (15961, -1, -1, 12737, 12737, 9, 96, 0, 0, 0, 20, 12739, 15962), + (15988, 10333, 10333, 10333, 10333, 9, 96, 40894, 55, 120, 20, 12726, 15989), + (16016, 16016, 16016, 16016, 16016, 12, 100, 40919, 17, 12, 20, -1, -1), + (16062, -1, -1, 1572, 1572, 5, 96, -1, 0, 0, 20, 10556, 16063), + (16071, 16071, 16071, 16071, 16071, 15, 100, 40953, 46, 1800, 20, -1, 16072), + (16081, 16081, 16081, 16081, 16081, 15, 100, 40969, 55, 6, 20, -1, -1), + (16082, 16082, 16082, 16082, 16082, 3, 100, 40970, 53, 6, 20, -1, -1), + (16083, 16083, 16083, 16083, 16083, 3, 55, 40971, 46, 6, 20, -1, -1), + (16084, -1, -1, 16084, 16084, 9, 100, 0, 0, 0, 20, -1, 16085), + (16087, -1, -1, 16087, 16087, 5, 100, 0, 0, 6, 20, -1, 16088), + (16094, -1, -1, 477, 477, 2, 100, -1, 0, 0, 20, 6235, 16095), + (16096, 16096, 16096, 16096, 16096, 12, 100, 40972, 36, 6, 20, -1, -1), + (16097, 16097, 16097, 16097, 16097, 12, 100, 40973, 38, 600, 20, -1, 16098), + (16103, 16103, 16103, 16103, 16103, 0, 85, 41071, 35, 180, 16, -1, -1), + (16104, -1, -1, 16104, 16104, 5, 85, 0, 0, 0, 20, -1, -1), + (16105, 16105, 16105, 16105, 16105, 0, 85, 41086, 76, 30, 20, -1, -1), + (16106, 16106, 16106, 16106, 16106, 0, 85, 41087, 76, 30, 20, -1, -1), + (16107, 16107, 16107, 16107, 16107, 0, 85, 41088, 76, 30, 20, -1, -1), + (16108, 16108, 16108, 16108, 16108, 12, 100, 41090, 77, 120, 20, -1, -1), + (16109, -1, -1, 16109, 16109, 11, 96, -1, 0, 0, 20, -1, 16110), + (16113, 16113, 16113, 16113, 16113, 15, 100, 41096, 78, 60, 20, -1, -1), + (16114, -1, -1, 16114, 16114, 5, 96, -1, 0, 0, 20, -1, 16115), + (16117, -1, -1, 16117, 16117, 11, 96, -1, 0, 0, 20, -1, 16118), + (16120, -1, -1, 16120, 16120, 9, 105, -1, 0, 0, 21, -1, -1), + (16121, -1, -1, 6611, 6611, 6, 100, -1, 0, 0, 20, 10574, 16122), + (16124, -1, -1, 16124, 16124, 5, 96, -1, 0, 0, 20, -1, 16125), + (16128, -1, -1, 16128, 16128, 6, 96, -1, 0, 0, 20, -1, 16129), + (16131, -1, -1, 16131, 16131, 5, 96, -1, 0, 0, 20, -1, 16132), + (16137, -1, -1, 16137, 16137, 9, 100, -1, 0, 0, 20, -1, 16138), + (16140, -1, -1, 16140, 16140, 9, 100, -1, 0, 0, 20, -1, -1), + (16146, -1, -1, 16146, 16146, 11, 100, -1, 0, 0, 20, -1, 16147), + (16149, -1, -1, 16149, 16149, 9, 100, -1, 0, 0, 20, -1, 16150), + (16152, -1, -1, 16152, 16152, 11, 100, -1, 0, 0, 20, -1, 16153), + (16156, -1, -1, 16156, 16156, 12, 100, -1, 0, 0, 20, -1, 16157), + (16159, -1, -1, 16159, 16159, 15, 100, -1, 0, 0, 20, -1, -1), + (16160, 16160, 16160, 16160, 16160, 18, 100, 41110, 81, 900, 20, -1, -1), + (16162, 16162, 16162, 16162, 16162, 12, 100, 41112, 80, 180, 20, -1, -1), + (16163, 16163, 16163, 16163, 16163, 18, 100, 41113, 63, 180, 20, -1, 16695), + (16164, -1, -1, 6636, 6636, 9, 96, -1, 0, 0, 20, 12531, 16165), + (16170, -1, -1, 5248, 5248, 12, 96, -1, 0, 0, 20, 7358, 16171), + (16173, -1, -1, 5263, 5263, 9, 101, -1, 0, 0, 21, 12465, 16174), + (16176, -1, -1, 16176, 16176, 7, 100, -1, 0, 0, 20, -1, 16177), + (16179, -1, -1, 16179, 16179, 18, 100, 41122, 0, 0, 20, -1, -1), + (16180, -1, -1, 16180, 16180, 7, 96, -1, 0, 0, 20, -1, 16181), + (16185, 16185, 16185, 16185, 16185, 18, 100, 41124, 68, 600, 20, -1, 16729), + (16186, -1, -1, 16186, 16186, 12, 100, 41125, 0, 0, 20, -1, -1), + (16188, 16188, 16188, 16188, 16188, 12, 100, 41126, 58, 180, 20, -1, -1), + (16189, -1, -1, 10915, 10915, 9, 96, -1, 0, 0, 20, 10917, 16190), + (16192, -1, -1, 6641, 6641, 9, 96, -1, 0, 0, 20, 10077, 16193), + (16195, 16195, 16195, 16195, 16195, 15, 100, 41133, 59, 60, 20, -1, -1), + (16196, 16196, 16196, 16196, 16196, 15, 100, 41134, 60, 900, 20, -1, 16665), + (16197, 16197, 16197, 16197, 16197, 12, 96, 41136, 61, 900, 20, -1, 16198), + (16200, 16200, 16200, 16200, 16200, 9, 96, 41139, 63, 900, 20, -1, 16201), + (16203, 16203, 16203, 16203, 16203, 12, 96, 41143, 98, 120, 20, -1, 16204), + (16208, -1, -1, 16208, 16208, 5, 96, -1, 0, 0, 20, -1, 16209), + (16211, -1, -1, 16211, 16211, 7, 100, -1, 0, 0, 20, -1, 16212), + (16214, 10958, 10958, 10958, 16214, 18, 100, 41148, 62, 900, 20, 13000, -1), + (16215, 16215, 16215, 16215, 16215, 9, 96, 41150, 92, 300, 20, -1, 16216), + (16218, -1, -1, 16218, 16218, 7, 96, -1, 0, 0, 20, -1, 16219), + (16221, -1, -1, 16221, 16221, 9, 100, -1, 0, 0, 20, -1, 16223), + (16222, 16222, -1, 16222, 16222, 9, 100, 41153, 88, 30, 20, -1, -1), + (16225, -1, -1, 16225, 16225, 5, 96, -1, 0, 0, 20, -1, 16226), + (16230, -1, -1, 16230, 16230, 5, 96, -1, 0, 0, 20, -1, 16231), + (16235, -1, -1, 16235, 16235, 7, 96, -1, 0, 0, 20, -1, 16236), + (16238, -1, -1, 16238, 16238, 7, 96, -1, 0, 0, 20, -1, 16239), + (16246, 6983, 6983, 6983, 6983, 9, 96, 41157, 66, 720, 20, 6983, 16247), + (16249, -1, -1, 230, 230, 9, 100, -1, 0, 0, 20, 12677, -1), + (16250, 828, 828, 828, 828, 9, 96, 41159, 2, 3600, 20, 830, -1), + (16257, -1, -1, 16257, 16257, 11, 100, 0, 0, 0, 20, -1, 16258), + (16260, -1, -1, 16260, 16260, 11, 100, -1, 0, 0, 20, -1, 16261), + (16263, 16263, 16263, 16263, 16263, 11, 96, 41161, 95, 600, 20, -1, 16264), + (16266, -1, -1, 6560, 6560, 9, 96, -1, 0, 0, 20, 6277, -1), + (16267, -1, -1, 888, 888, 3, 96, -1, 0, 0, 20, 892, 16268), + (16272, -1, -1, 16272, 16272, 9, 96, -1, 0, 0, 20, -1, 16273), + (16276, -1, -1, 16276, 16276, 5, 96, -1, 0, 0, 20, -1, 16277), + (16287, -1, -1, 16287, 16287, 7, 96, -1, 0, 0, 20, -1, 16288), + (16296, 16296, 16296, 16296, 16296, 13, 100, 41168, 60, 30, 20, -1, -1), + (16297, -1, -1, 6337, 6337, 6, 96, -1, 0, 0, 20, 10155, 16298), + (16300, -1, -1, 16300, 16300, 9, 100, -1, 0, 0, 20, -1, 16301), + (16303, -1, -1, 12721, 12721, 9, 96, 0, 0, 0, 20, 12723, 16304), + (16306, -1, -1, 6340, 6340, 6, 96, -1, 0, 0, 20, 7453, -1), + (16310, 16310, 16310, 16310, 16310, 12, 100, 41169, 97, 600, 20, -1, -1), + (16317, -1, -1, 16317, 16317, 5, 100, -1, 0, 0, 20, -1, 16318), + (16324, 6607, 6607, 6607, 16324, 9, 96, 16491, 61, 600, 20, 6609, 16325), + (16327, -1, -1, 6362, 6362, 7, 96, 0, 0, 0, 20, 6366, 16328), + (16330, -1, -1, 16330, 16330, 9, 96, -1, 0, 0, 20, -1, 16331), + (16336, -1, -1, 16336, 16336, 7, 96, -1, 0, 0, 20, -1, 16337), + (16339, -1, -1, 16339, 16339, 7, 96, -1, 0, 0, 20, -1, 16340), + (16342, -1, -1, 16342, 16342, 7, 96, -1, 0, 0, 20, -1, 16343), + (16360, 16360, 16360, 16360, 16360, 9, 100, 41188, 91, 6, 20, -1, -1), + (16361, -1, -1, 9509, 9509, 7, 96, -1, 0, 0, 20, 9515, -1), + (16363, 16363, 16363, 16363, 16363, 12, 96, 41193, 89, 1800, 20, -1, 16364), + (16366, -1, -1, 16366, 16366, 12, 96, -1, 0, 0, 20, -1, 16367), + (16369, 16369, 16369, 16369, 16369, 15, 100, 41196, 98, 12, 20, -1, -1), + (16370, 16370, -1, 16370, 16370, 5, 100, 41197, 98, 12, 20, -1, -1), + (16371, -1, -1, 16371, 16371, 3, 96, -1, 0, 0, 20, -1, 16372), + (16380, -1, -1, 16380, 16380, 5, 96, -1, 0, 0, 20, -1, 16381), + (16386, -1, -1, 16386, 16386, 7, 96, -1, 0, 0, 20, -1, 16387), + (16392, -1, -1, 16392, 16392, 5, 96, -1, 0, 0, 20, -1, 16393), + (16395, 16395, 16395, 16395, 16395, 7, 100, 41305, 93, 10, 20, -1, -1), + (16396, -1, -1, 16396, 16396, 7, 96, -1, 0, 0, 20, -1, 16397), + (16402, -1, -1, 6112, 6112, 5, 96, -1, 0, 0, 20, 12967, 16403), + (16414, -1, -1, 1056, 1056, 5, 101, -1, 0, 0, 21, 7525, 16415), + (16419, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8447, 16420), + (16420, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 16419, 16421), + (16421, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 16420, -1), + (16440, -1, -1, 6540, 6540, 10, 101, -1, 0, 0, 21, 12510, 16441), + (16475, -1, -1, 8201, 8201, 9, 101, -1, 0, 0, 21, 8203, 16476), + (16489, -1, -1, 1107, 1107, 9, 101, -1, 0, 0, 21, 12558, 16490), + (16536, -1, -1, 16536, 16536, 5, 101, -1, 0, 0, 21, -1, 16537), + (16604, -1, -1, 849, 849, 11, 105, -1, 0, 0, 21, 10622, -1), + (16644, -1, -1, 16644, 16644, 11, 101, -1, 0, 0, 21, -1, 16645), + (16666, -1, -1, 16666, 16666, 9, 101, -1, 0, 0, 21, -1, 16667), + (16716, 6764, 6764, 6764, 6764, 12, 105, 41308, 52, 600, 21, 10057, -1), + (16730, -1, -1, 1608, 1608, 13, 101, -1, 0, 0, 21, 10069, 16731), + (16745, -1, -1, 16745, 16745, 9, 101, -1, 0, 0, 21, -1, 16746), + (16883, 1119, 1119, 1119, 1119, 12, 101, 41594, 8, 900, 21, 10299, 16884), + (16887, -1, -1, 729, 729, 11, 101, -1, 0, 0, 21, 10307, 16888), + (16890, -1, -1, 724, 724, 15, 101, -1, 0, 0, 21, 7493, 16891), + (17004, -1, -1, 556, 556, 7, 101, -1, 0, 0, 21, 1567, 17005), + (17030, 4857, 4857, 4857, 4857, 15, 101, 41660, 7, 600, 21, 5769, 17031), + (17131, 12785, 12785, 12785, 12785, 15, 105, 41736, 80, 30, 21, 12785, -1), + (17199, 17199, 17199, 17199, 17199, 100, 51, 41819, 31, 2, 21, -1, -1), + (17206, -1, -1, 10588, 10588, 7, 101, 0, 0, 0, 21, 10592, 17207), + (17209, -1, -1, 17209, 17209, 9, 101, -1, 0, 0, 21, -1, 17210), + (17212, -1, -1, 17212, 17212, 12, 101, -1, 0, 0, 21, -1, 17213), + (17215, -1, -1, 17215, 17215, 12, 101, -1, 0, 0, 21, -1, 17216), + (17218, -1, -1, 17218, 17218, 9, 101, -1, 0, 0, 21, -1, 17219), + (17229, -1, -1, 17229, 17229, 9, 101, -1, 0, 0, 21, -1, 17230), + (17235, -1, -1, 17235, 17235, 15, 101, -1, 0, 0, 21, -1, 17236), + (17238, 17238, 17238, 17238, 17238, 24, 105, 41808, 10, 900, 21, -1, -1), + (17239, -1, -1, 6489, 6489, 12, 101, -1, 0, 0, 21, 6491, -1), + (17242, -1, -1, 17242, 17242, 12, 101, -1, 0, 0, 21, -1, 17243), + (17245, -1, -1, 17245, 17245, 12, 101, -1, 0, 0, 21, -1, 17246), + (17248, 17248, 17248, 17248, 17248, 24, 105, 41811, 93, 1080, 21, -1, -1), + (17249, -1, -1, 17249, 17249, 12, 101, -1, 0, 0, 21, -1, 17250), + (17252, -1, -1, 17252, 17252, 9, 101, -1, 0, 0, 21, -1, 17253), + (17256, 17256, 17256, 17256, 17256, 21, 105, 41815, 93, 360, 21, -1, -1), + (17257, 17257, 17257, 17257, 17257, 21, 105, 41816, 98, 300, 21, -1, -1), + (17258, -1, -1, 17258, 17258, 15, 101, 0, 0, 0, 21, -1, 17259), + (17267, -1, -1, 17267, 17267, 9, 101, -1, 0, 0, 21, -1, 17268), + (17273, 17273, 17273, 17273, 17273, 15, 101, 41830, 98, 720, 21, -1, -1), + (17276, 1569, 1569, 1569, 1569, 9, 101, 41831, 5, 1800, 21, 10161, 17277), + (17280, 17280, 17280, 17280, 17280, 21, 105, 41834, 97, 720, 21, -1, -1), + (17281, -1, -1, 17281, 17281, 15, 105, -1, 0, 0, 21, -1, -1), + (17288, -1, -1, 17288, 17288, 9, 105, -1, 0, 0, 21, 7317, -1), + (17289, -1, -1, 17289, 17289, 7, 101, -1, 0, 0, 21, -1, 17290), + (17295, -1, -1, 692, 692, 12, 101, -1, 0, 0, 21, 12769, 17296), + (17298, 749, 749, 749, 749, 15, 105, 41837, 11, 1800, 21, 1208, -1), + (17307, -1, -1, 17307, 17307, 9, 101, -1, 0, 0, 21, -1, 17308), + (17310, -1, -1, 7945, 7945, 9, 105, -1, 0, 0, 21, 10347, -1), + (17311, 970, 970, 970, 970, 9, 101, 41845, 6, 1800, 21, 1326, 17312), + (17317, -1, -1, 17317, 17317, 9, 101, -1, 0, 0, 21, -1, 17318), + (17328, 17328, 17328, 17328, 17328, 21, 105, 41854, 87, 600, 21, -1, -1), + (17329, 17329, 17329, 17329, 17329, 12, 101, 41855, 88, 20, 21, -1, -1), + (17333, 153, 153, 153, 153, 18, 105, 41856, 3, 2160, 21, 12996, -1), + (17334, -1, -1, 12977, 12977, 12, 102, 0, 0, 0, 21, 12981, 17335), + (17336, -1, -1, 17336, 17336, 9, 101, -1, 0, 0, 21, -1, 17337), + (17339, -1, -1, 17339, 17339, 9, 101, -1, 0, 0, 21, -1, 17340), + (17342, 17342, 17342, 17342, 17342, 15, 105, 41857, 85, 60, 21, -1, -1), + (17344, 17344, 17344, 17344, 17344, 15, 101, 41858, 94, 780, 21, -1, 17345), + (17347, 17347, 17347, 17347, 17347, 12, 101, 41861, 32, 30, 21, -1, 17348), + (17350, -1, -1, 7664, 7664, 5, 102, -1, 0, 0, 21, 10109, 17351), + (17357, -1, -1, 17357, 17357, 9, 96, -1, 0, 0, 19, -1, 17358), + (17361, -1, -1, 17361, 17361, 5, 100, -1, 0, 0, 21, -1, 17362), + (17364, 17364, 17364, 17364, 17364, 15, 105, 46160, 87, 120, 21, -1, -1), + (17365, -1, -1, 10792, 10792, 15, 101, 0, 0, 0, 21, 10796, 17366), + (17370, -1, -1, 17370, 17370, 15, 102, 0, 0, 0, 21, -1, 17371), + (17372, 17372, 17372, 17372, 17372, 18, 104, 46161, 85, 300, 21, -1, -1), + (17373, 17373, -1, 17373, 17373, 15, 105, 46162, 98, 900, 21, -1, -1), + (17375, -1, -1, 17375, 17375, 12, 101, -1, 0, 0, 21, -1, 17376), + (17378, 17378, 17378, 17378, 17378, 10, 101, 46164, 97, 3, 21, -1, -1), + (17379, 17378, 17378, 17378, 17378, 10, 101, 46165, 86, 3, 21, -1, -1), + (17380, 17378, 17378, 17378, 17378, 10, 101, 46166, 97, 3, 21, -1, -1), + (17382, 5015, 5015, 5015, 5015, 15, 103, 46168, 9, 900, 21, 10301, -1), + (17384, 17384, 17384, 17384, 17384, 18, 101, 46171, 10, 20, 21, -1, -1), + (17391, -1, -1, 495, 495, 12, 105, -1, 0, 0, 21, 10668, -1), + (17406, -1, -1, 10653, 10653, 12, 103, -1, 0, 0, 21, 10655, -1), + (17409, -1, -1, 17409, 17409, 15, 105, -1, 0, 0, 21, -1, -1), + (17414, -1, -1, 17414, 17414, 9, 101, -1, 0, 0, 21, -1, 17415), + (17418, -1, -1, 17418, 17418, 7, 101, -1, 0, 0, 21, -1, 17419), + (17428, 17428, 17428, 17428, 17428, 15, 101, 46178, 0, 0, 21, -1, 17429), + (17436, -1, -1, 17436, 17436, 7, 101, -1, 0, 0, 21, -1, 17437), + (17439, -1, -1, 17439, 17439, 9, 102, -1, 0, 0, 21, -1, 17440), + (17441, -1, -1, 255, 255, 15, 102, -1, 0, 0, 21, 7633, -1), + (17445, -1, -1, 17445, 17445, 15, 101, 0, 0, 0, 21, -1, 17446), + (17448, -1, -1, 17448, 17448, 15, 102, 0, 0, 0, 21, -1, 17449), + (17476, -1, -1, 10800, 10800, 15, 101, -1, 0, 0, 21, 10802, 17477), + (17486, 12864, -1, 12864, 12864, 12, 105, 46195, 73, 10, 21, 12864, -1), + (17492, -1, -1, 17492, 17492, 9, 101, -1, 0, 0, 21, -1, 17493), + (17495, -1, -1, 17495, 17495, 9, 101, -1, 0, 0, 21, -1, 17496), + (17515, -1, -1, 17515, 17515, 7, 102, -1, 0, 0, 21, -1, 17516), + (17517, -1, -1, 17517, 17517, 9, 101, -1, 0, 0, 21, -1, 17518), + (17522, -1, -1, 17522, 17522, 9, 101, -1, 0, 0, 21, -1, 17523), + (17533, -1, -1, 17533, 17533, 15, 105, -1, 0, 0, 21, -1, -1), + (17534, 6828, 6828, 6828, 6828, 15, 105, 46207, 43, 60, 21, 10208, -1), + (17535, 967, 967, 967, 967, 9, 101, 46208, 10, 1800, 21, 12791, 17536), + (17538, 17538, 17538, 17538, 17538, 21, 105, 46212, 91, 1800, 21, -1, -1), + (17539, 4934, 4934, 4934, 4934, 12, 105, 46214, 13, 300, 21, 10278, -1), + (17540, 4935, 4935, 4935, 4935, 12, 105, 46215, 14, 300, 21, 10277, -1), + (17541, 8038, 8038, 8038, 8038, 12, 105, 46217, 56, 12, 21, 8038, -1), + (17547, -1, -1, 17547, 17547, 12, 102, -1, 0, 0, 21, -1, 17548), + (17549, -1, -1, 17549, 17549, 9, 101, -1, 0, 0, 21, -1, 17550), + (17553, -1, -1, 17553, 17553, 18, 105, -1, 0, 0, 21, -1, -1), + (17554, -1, -1, 17554, 17554, 15, 105, -1, 0, 0, 21, -1, -1), + (17555, -1, -1, 17555, 17555, 5, 101, -1, 0, 0, 21, -1, 17556), + (17558, -1, -1, 17558, 17558, 5, 101, -1, 0, 0, 21, -1, 17559), + (17561, -1, -1, 17561, 17561, 5, 101, -1, 0, 0, 21, -1, 17562), + (17564, -1, -1, 17564, 17564, 5, 101, -1, 0, 0, 21, -1, 17565), + (17567, -1, -1, 17567, 17567, 5, 101, -1, 0, 0, 21, -1, 17568), + (17570, -1, -1, 17570, 17570, 5, 101, -1, 0, 0, 21, -1, 17571), + (17573, -1, -1, 17573, 17573, 5, 101, -1, 0, 0, 21, -1, 17574), + (17576, -1, -1, 17576, 17576, 5, 101, -1, 0, 0, 21, -1, 17577), + (17579, -1, -1, 17579, 17579, 5, 101, -1, 0, 0, 21, -1, 17580), + (17582, -1, -1, 17582, 17582, 5, 101, -1, 0, 0, 21, -1, 17583), + (17585, -1, -1, 17585, 17585, 5, 101, -1, 0, 0, 21, -1, 17586), + (17588, -1, -1, 17588, 17588, 5, 101, -1, 0, 0, 21, -1, 17589), + (17591, -1, -1, 17591, 17591, 5, 101, -1, 0, 0, 21, -1, 17592), + (17594, -1, -1, 17594, 17594, 5, 101, -1, 0, 0, 21, -1, 17595), + (17597, -1, -1, 17597, 17597, 5, 101, -1, 0, 0, 21, -1, 17598), + (17600, -1, -1, 17600, 17600, 5, 101, -1, 0, 0, 21, -1, 17601), + (17603, -1, -1, 17603, 17603, 5, 101, -1, 0, 0, 21, -1, 17604), + (17606, -1, -1, 17606, 17606, 5, 101, -1, 0, 0, 21, -1, 17607), + (17609, -1, -1, 17609, 17609, 5, 101, -1, 0, 0, 21, -1, 17610), + (17612, -1, -1, 17612, 17612, 5, 101, -1, 0, 0, 21, -1, 17613), + (17615, -1, -1, 17615, 17615, 5, 101, -1, 0, 0, 21, -1, 17616), + (17618, -1, -1, 17618, 17618, 5, 101, -1, 0, 0, 21, -1, 17619), + (17621, -1, -1, 17621, 17621, 5, 101, -1, 0, 0, 21, -1, 17622), + (17624, -1, -1, 17624, 17624, 5, 101, -1, 0, 0, 21, -1, 17625), + (17627, -1, -1, 17627, 17627, 5, 101, -1, 0, 0, 21, -1, 17628), + (17630, -1, -1, 17630, 17630, 5, 101, -1, 0, 0, 21, -1, 17631), + (17633, -1, -1, 17633, 17633, 5, 101, -1, 0, 0, 21, -1, 17634), + (17639, -1, -1, 17639, 17639, 9, 91, 0, 0, 0, 18, -1, 17640), + (18972, -1, -1, 279, 279, 15, 105, -1, 0, 0, 21, 279, -1), + (30050, -1, -1, 30050, 30050, 0, 1, -1, 0, 0, 0, -1, 30051), + (30100, -1, -1, 30100, 30100, 0, 1, -1, 0, 0, 0, -1, 30101), + (30150, -1, -1, 30150, 30150, 0, 1, -1, 0, 0, 0, -1, 30151), + (30175, -1, -1, 30175, 30175, 0, 1, -1, 0, 0, 0, -1, 30176), + (30180, -1, -1, 30180, 30180, 0, 1, -1, 0, 0, 0, -1, 30181), + (30185, -1, -1, 30185, 30185, 0, 1, -1, 0, 0, 0, -1, 30186), + (30190, -1, -1, 30190, 30190, 0, 1, -1, 0, 0, 0, -1, 30191), + (30195, -1, -1, 30195, 30195, 0, 1, -1, 0, 0, 0, -1, 30196), + (49999, -1, -1, -1, -1, 0, 71, 0, 0, 0, 0, -1, 1); + +-- Dumping structure for table eqdb.aa_rank_effects +DROP TABLE IF EXISTS `aa_rank_effects`; +CREATE TABLE IF NOT EXISTS `aa_rank_effects` ( + `rank_id` int(10) unsigned NOT NULL, + `slot` int(10) unsigned NOT NULL DEFAULT '1', + `effect_id` int(10) NOT NULL DEFAULT '0', + `base1` int(10) NOT NULL DEFAULT '0', + `base2` int(10) NOT NULL DEFAULT '0', + PRIMARY KEY (`rank_id`,`slot`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `aa_rank_effects` (`rank_id`, `slot`, `effect_id`, `base1`, `base2`) VALUES + (2, 1, 4, 2, 0), + (3, 1, 4, 4, 0), + (4, 1, 4, 6, 0), + (5, 1, 4, 8, 0), + (6, 1, 4, 10, 0), + (7, 1, 7, 2, 0), + (8, 1, 7, 4, 0), + (9, 1, 7, 6, 0), + (10, 1, 7, 8, 0), + (11, 1, 7, 10, 0), + (12, 1, 6, 2, 0), + (13, 1, 6, 4, 0), + (14, 1, 6, 6, 0), + (15, 1, 6, 8, 0), + (16, 1, 6, 10, 0), + (17, 1, 5, 2, 0), + (18, 1, 5, 4, 0), + (19, 1, 5, 6, 0), + (20, 1, 5, 8, 0), + (21, 1, 5, 10, 0), + (22, 1, 8, 2, 0), + (23, 1, 8, 4, 0), + (24, 1, 8, 6, 0), + (25, 1, 8, 8, 0), + (26, 1, 8, 10, 0), + (27, 1, 9, 2, 0), + (28, 1, 9, 4, 0), + (29, 1, 9, 6, 0), + (30, 1, 9, 8, 0), + (31, 1, 9, 10, 0), + (32, 1, 10, 2, 0), + (33, 1, 10, 4, 0), + (34, 1, 10, 6, 0), + (35, 1, 10, 8, 0), + (36, 1, 10, 10, 0), + (37, 1, 46, 2, 0), + (38, 1, 46, 4, 0), + (39, 1, 46, 6, 0), + (40, 1, 46, 8, 0), + (41, 1, 46, 10, 0), + (42, 1, 47, 2, 0), + (43, 1, 47, 4, 0), + (44, 1, 47, 6, 0), + (45, 1, 47, 8, 0), + (46, 1, 47, 10, 0), + (47, 1, 50, 2, 0), + (48, 1, 50, 4, 0), + (49, 1, 50, 6, 0), + (50, 1, 50, 8, 0), + (51, 1, 50, 10, 0), + (52, 1, 48, 2, 0), + (53, 1, 48, 4, 0), + (54, 1, 48, 6, 0), + (55, 1, 48, 8, 0), + (56, 1, 48, 10, 0), + (57, 1, 49, 2, 0), + (58, 1, 49, 4, 0), + (59, 1, 49, 6, 0), + (60, 1, 49, 8, 0), + (61, 1, 49, 10, 0), + (62, 1, 271, 8, 0), + (63, 1, 271, 14, 0), + (64, 1, 271, 21, 0), + (68, 1, 233, 110, 0), + (69, 1, 233, 125, 0), + (70, 1, 233, 150, 0), + (71, 1, 246, 110, 0), + (72, 1, 246, 125, 0), + (73, 1, 246, 150, 0), + (74, 1, 269, 10, 0), + (75, 1, 269, 20, 0), + (76, 1, 269, 30, 0), + (77, 1, 125, 2, 2), + (77, 2, 137, 0, 0), + (77, 3, 141, 1, 0), + (77, 4, 139, -6233, 0), + (77, 5, 139, -6265, 0), + (77, 6, 125, 2, 2), + (77, 7, 137, 147, 0), + (77, 8, 141, 1, 0), + (78, 1, 125, 5, 5), + (78, 2, 137, 0, 0), + (78, 3, 141, 1, 0), + (78, 4, 139, -6233, 0), + (78, 5, 139, -6265, 0), + (78, 6, 125, 5, 5), + (78, 7, 137, 147, 0), + (78, 8, 141, 1, 0), + (79, 1, 125, 10, 10), + (79, 2, 137, 0, 0), + (79, 3, 141, 1, 0), + (79, 4, 139, -6233, 0), + (79, 5, 139, -6265, 0), + (79, 6, 125, 10, 10), + (79, 7, 137, 147, 0), + (79, 8, 141, 1, 0), + (80, 1, 274, 3, 0), + (81, 1, 274, 6, 0), + (82, 1, 274, 10, 0), + (83, 1, 132, 2, 2), + (84, 1, 132, 5, 5), + (85, 1, 132, 10, 10), + (86, 1, 128, 5, 5), + (86, 2, 138, 1, 0), + (86, 3, 140, 1, 0), + (86, 4, 139, -2741, 0), + (86, 5, 139, -16843, 0), + (86, 6, 385, -16192, 0), + (86, 7, 385, -10547, 0), + (86, 8, 385, -13543, 0), + (87, 1, 128, 15, 15), + (87, 2, 138, 1, 0), + (87, 3, 140, 1, 0), + (87, 4, 139, -2741, 0), + (87, 5, 139, -16843, 0), + (87, 6, 385, -16192, 0), + (87, 7, 385, -10547, 0), + (87, 8, 385, -13543, 0), + (88, 1, 128, 30, 30), + (88, 2, 138, 1, 0), + (88, 3, 140, 1, 0), + (88, 4, 139, -2741, 0), + (88, 5, 139, -16843, 0), + (88, 6, 385, -16192, 0), + (88, 7, 385, -10547, 0), + (88, 8, 385, -13543, 0), + (92, 1, 294, 2, 100), + (93, 1, 294, 4, 100), + (94, 1, 294, 7, 100), + (98, 1, 114, -5, 0), + (99, 1, 114, -10, 0), + (100, 1, 114, -20, 0), + (101, 1, 265, 20, 0), + (102, 1, 265, 40, 0), + (103, 1, 265, 52, 0), + (104, 1, 127, 10, 10), + (104, 2, 138, 1, 0), + (104, 3, 140, 1, 0), + (104, 4, 143, 3000, 0), + (105, 1, 127, 25, 25), + (105, 2, 138, 1, 0), + (105, 3, 140, 1, 0), + (105, 4, 143, 3000, 0), + (106, 1, 127, 50, 50), + (106, 2, 138, 1, 0), + (106, 3, 140, 1, 0), + (106, 4, 143, 3000, 0), + (107, 1, 214, 200, 0), + (108, 1, 214, 500, 0), + (109, 1, 214, 1000, 0), + (110, 1, 0, 1, 0), + (111, 1, 0, 2, 0), + (112, 1, 0, 3, 0), + (113, 1, 169, 15, -1), + (114, 1, 169, 40, -1), + (115, 1, 169, 75, -1), + (116, 1, 181, 5, 0), + (117, 1, 181, 10, 0), + (118, 1, 181, 25, 0), + (119, 1, 278, 500, 16000), + (119, 2, 440, 50, 100), + (120, 1, 278, 510, 17102), + (120, 2, 440, 52, 100), + (121, 1, 278, 520, 19635), + (121, 2, 440, 54, 100), + (122, 1, 259, 2, 0), + (123, 1, 259, 5, 0), + (124, 1, 259, 10, 0), + (125, 1, 172, 2, 0), + (126, 1, 172, 5, 0), + (127, 1, 172, 10, 0), + (137, 1, 127, 10, 10), + (137, 2, 137, 88, 0), + (138, 1, 127, 25, 25), + (138, 2, 137, 88, 0), + (139, 1, 127, 50, 50), + (139, 2, 137, 88, 0), + (141, 1, 127, 2, 2), + (141, 2, 137, 0, 0), + (141, 3, 138, 0, 0), + (141, 4, 141, 1, 0), + (141, 5, 143, 3000, 0), + (141, 6, 127, 2, 2), + (141, 7, 385, 16555, 0), + (141, 8, 385, 16655, 0), + (142, 1, 127, 5, 5), + (142, 2, 137, 0, 0), + (142, 3, 138, 0, 0), + (142, 4, 141, 1, 0), + (142, 5, 143, 3000, 0), + (142, 6, 127, 5, 5), + (142, 7, 385, 16555, 0), + (142, 8, 385, 16655, 0), + (143, 1, 127, 10, 10), + (143, 2, 137, 0, 0), + (143, 3, 138, 0, 0), + (143, 4, 141, 1, 0), + (143, 5, 143, 3000, 0), + (143, 6, 127, 10, 10), + (143, 7, 385, 16555, 0), + (143, 8, 385, 16655, 0), + (144, 1, 244, 50, 0), + (147, 1, 127, 10, 10), + (147, 2, 138, 1, 0), + (147, 3, 140, 1, 0), + (147, 4, 143, 3000, 0), + (148, 1, 127, 25, 25), + (148, 2, 138, 1, 0), + (148, 3, 140, 1, 0), + (148, 4, 143, 3000, 0), + (149, 1, 127, 50, 50), + (149, 2, 138, 1, 0), + (149, 3, 140, 1, 0), + (149, 4, 143, 3000, 0), + (150, 1, 268, 10, 59), + (151, 1, 268, 25, 59), + (152, 1, 268, 50, 59), + (158, 1, 238, 1, 0), + (159, 1, 268, 10, 68), + (160, 1, 268, 25, 68), + (161, 1, 268, 50, 68), + (182, 1, 131, 100, 0), + (182, 2, 137, 33, 0), + (190, 1, 219, 225, 680), + (191, 1, 219, 235, 1190), + (192, 1, 219, 240, 1700), + (195, 1, 181, 100, 0), + (196, 1, 226, 1, 0), + (198, 1, 276, 32, 0), + (199, 1, 301, 30, 0), + (200, 1, 301, 60, 0), + (201, 1, 301, 100, 0), + (205, 1, 251, 100, 0), + (210, 1, 302, 50, 50), + (210, 2, 385, 99, 0), + (211, 1, 302, 100, 100), + (211, 2, 385, 99, 0), + (212, 1, 302, 200, 200), + (212, 2, 385, 99, 0), + (213, 1, 260, 2, 23), + (213, 2, 260, 2, 24), + (213, 3, 260, 2, 25), + (213, 4, 260, 2, 26), + (214, 1, 260, 4, 23), + (214, 2, 260, 4, 24), + (214, 3, 260, 4, 25), + (214, 4, 260, 4, 26), + (215, 1, 260, 6, 23), + (215, 2, 260, 6, 24), + (215, 3, 260, 6, 25), + (215, 4, 260, 6, 26), + (225, 1, 272, 1, 0), + (226, 1, 272, 3, 0), + (227, 1, 272, 5, 0), + (230, 1, 275, 10, 0), + (231, 1, 275, 20, 0), + (232, 1, 275, 30, 0), + (237, 1, 227, 1, 25), + (238, 1, 227, 3, 25), + (239, 1, 227, 5, 25), + (240, 1, 224, 20, 26), + (240, 2, 173, 1, 0), + (241, 1, 224, 35, 26), + (241, 2, 173, 2, 0), + (242, 1, 224, 50, 26), + (242, 2, 173, 3, 0), + (244, 1, 268, 10, 56), + (244, 2, 234, 7500, 0), + (245, 1, 268, 25, 56), + (245, 2, 234, 5000, 0), + (246, 1, 268, 50, 56), + (246, 2, 234, 2500, 0), + (247, 1, 224, 15, 0), + (248, 1, 224, 30, 0), + (249, 1, 224, 50, 0), + (255, 1, 279, 7, 0), + (256, 1, 279, 11, 0), + (257, 1, 279, 15, 0), + (263, 1, 282, 10, 0), + (264, 1, 282, 25, 0), + (265, 1, 282, 50, 0), + (266, 1, 128, 50, 50), + (266, 2, 138, 1, 0), + (266, 3, 140, 1, 0), + (266, 4, 139, -2741, 0), + (266, 5, 139, -16843, 0), + (266, 6, 385, -16192, 0), + (266, 7, 385, -10547, 0), + (266, 8, 385, -13543, 0), + (267, 1, 294, 2, 100), + (268, 1, 294, 4, 100), + (269, 1, 294, 6, 100), + (273, 1, 288, 1000, 21), + (275, 1, 260, 2, 50), + (276, 1, 260, 4, 50), + (277, 1, 260, 6, 50), + (278, 1, 0, 1, 0), + (278, 2, 15, 1, 0), + (279, 1, 214, 200, 0), + (279, 2, 259, 2, 0), + (279, 3, 172, 2, 0), + (280, 1, 227, 1, 62), + (280, 2, 227, 1, 17), + (281, 1, 227, 3, 62), + (281, 2, 227, 3, 17), + (282, 1, 227, 5, 62), + (282, 2, 227, 5, 17), + (283, 1, 228, 10, 0), + (284, 1, 228, 20, 0), + (285, 1, 228, 30, 0), + (286, 1, 10, 0, 0), + (287, 1, 253, 1, 0), + (288, 1, 257, 1, 0), + (288, 2, 267, 1, 31), + (288, 3, 267, 1, 32), + (288, 4, 267, 1, 33), + (288, 5, 267, 1, 15), + (288, 6, 267, 1, 16), + (288, 7, 267, 1, 17), + (288, 8, 267, 1, 18), + (288, 9, 267, 1, 19), + (288, 10, 267, 1, 20), + (292, 1, 4, 12, 0), + (293, 1, 4, 14, 0), + (294, 1, 4, 16, 0), + (295, 1, 4, 18, 0), + (296, 1, 4, 20, 0), + (297, 1, 4, 22, 0), + (298, 1, 4, 24, 0), + (299, 1, 4, 26, 0), + (300, 1, 4, 28, 0), + (301, 1, 4, 30, 0), + (302, 1, 7, 12, 0), + (303, 1, 7, 14, 0), + (304, 1, 7, 16, 0), + (305, 1, 7, 18, 0), + (306, 1, 7, 20, 0), + (307, 1, 7, 22, 0), + (308, 1, 7, 24, 0), + (309, 1, 7, 26, 0), + (310, 1, 7, 28, 0), + (311, 1, 7, 30, 0), + (312, 1, 6, 12, 0), + (313, 1, 6, 14, 0), + (314, 1, 6, 16, 0), + (315, 1, 6, 18, 0), + (316, 1, 6, 20, 0), + (317, 1, 6, 22, 0), + (318, 1, 6, 24, 0), + (319, 1, 6, 26, 0), + (320, 1, 6, 28, 0), + (321, 1, 6, 30, 0), + (322, 1, 5, 12, 0), + (323, 1, 5, 14, 0), + (324, 1, 5, 16, 0), + (325, 1, 5, 18, 0), + (326, 1, 5, 20, 0), + (327, 1, 5, 22, 0), + (328, 1, 5, 24, 0), + (329, 1, 5, 26, 0), + (330, 1, 5, 28, 0), + (331, 1, 5, 30, 0), + (332, 1, 8, 12, 0), + (333, 1, 8, 14, 0), + (334, 1, 8, 16, 0), + (335, 1, 8, 18, 0), + (336, 1, 8, 20, 0), + (337, 1, 8, 22, 0), + (338, 1, 8, 24, 0), + (339, 1, 8, 26, 0), + (340, 1, 8, 28, 0), + (341, 1, 8, 30, 0), + (342, 1, 9, 12, 0), + (343, 1, 9, 14, 0), + (344, 1, 9, 16, 0), + (345, 1, 9, 18, 0), + (346, 1, 9, 20, 0), + (347, 1, 9, 22, 0), + (348, 1, 9, 24, 0), + (349, 1, 9, 26, 0), + (350, 1, 9, 28, 0), + (351, 1, 9, 30, 0), + (352, 1, 10, 12, 0), + (353, 1, 10, 14, 0), + (354, 1, 10, 16, 0), + (355, 1, 10, 18, 0), + (356, 1, 10, 20, 0), + (357, 1, 10, 22, 0), + (358, 1, 10, 24, 0), + (359, 1, 10, 26, 0), + (360, 1, 10, 28, 0), + (361, 1, 10, 30, 0), + (362, 1, 46, 12, 0), + (363, 1, 46, 14, 0), + (364, 1, 46, 16, 0), + (365, 1, 46, 18, 0), + (366, 1, 46, 20, 0), + (367, 1, 46, 22, 0), + (368, 1, 46, 24, 0), + (369, 1, 46, 26, 0), + (370, 1, 46, 28, 0), + (371, 1, 46, 30, 0), + (372, 1, 47, 12, 0), + (373, 1, 47, 14, 0), + (374, 1, 47, 16, 0), + (375, 1, 47, 18, 0), + (376, 1, 47, 20, 0), + (377, 1, 47, 22, 0), + (378, 1, 47, 24, 0), + (379, 1, 47, 26, 0), + (380, 1, 47, 28, 0), + (381, 1, 47, 30, 0), + (382, 1, 50, 12, 0), + (383, 1, 50, 14, 0), + (384, 1, 50, 16, 0), + (385, 1, 50, 18, 0), + (386, 1, 50, 20, 0), + (387, 1, 50, 22, 0), + (388, 1, 50, 24, 0), + (389, 1, 50, 26, 0), + (390, 1, 50, 28, 0), + (391, 1, 50, 30, 0), + (392, 1, 48, 12, 0), + (393, 1, 48, 14, 0), + (394, 1, 48, 16, 0), + (395, 1, 48, 18, 0), + (396, 1, 48, 20, 0), + (397, 1, 48, 22, 0), + (398, 1, 48, 24, 0), + (399, 1, 48, 26, 0), + (400, 1, 48, 28, 0), + (401, 1, 48, 30, 0), + (402, 1, 49, 12, 0), + (403, 1, 49, 14, 0), + (404, 1, 49, 16, 0), + (405, 1, 49, 18, 0), + (406, 1, 49, 20, 0), + (407, 1, 49, 22, 0), + (408, 1, 49, 24, 0), + (409, 1, 49, 26, 0), + (410, 1, 49, 28, 0), + (411, 1, 49, 30, 0), + (412, 1, 263, 1, 0), + (413, 1, 263, 2, 0), + (414, 1, 263, 3, 0), + (415, 1, 263, 4, 0), + (416, 1, 263, 5, 0), + (417, 1, 263, 6, 0), + (418, 1, 262, 5, 0), + (418, 2, 262, 5, 1), + (418, 3, 262, 5, 2), + (418, 4, 262, 5, 3), + (418, 5, 262, 5, 4), + (418, 6, 262, 5, 5), + (418, 7, 262, 5, 6), + (419, 1, 262, 10, 0), + (419, 2, 262, 10, 1), + (419, 3, 262, 10, 2), + (419, 4, 262, 10, 3), + (419, 5, 262, 10, 4), + (419, 6, 262, 10, 5), + (419, 7, 262, 10, 6), + (420, 1, 262, 15, 0), + (420, 2, 262, 15, 1), + (420, 3, 262, 15, 2), + (420, 4, 262, 15, 3), + (420, 5, 262, 15, 4), + (420, 6, 262, 15, 5), + (420, 7, 262, 15, 6), + (421, 1, 262, 20, 0), + (421, 2, 262, 20, 1), + (421, 3, 262, 20, 2), + (421, 4, 262, 20, 3), + (421, 5, 262, 20, 4), + (421, 6, 262, 20, 5), + (421, 7, 262, 20, 6), + (422, 1, 262, 25, 0), + (422, 2, 262, 25, 1), + (422, 3, 262, 25, 2), + (422, 4, 262, 25, 3), + (422, 5, 262, 25, 4), + (422, 6, 262, 25, 5), + (422, 7, 262, 25, 6), + (423, 1, 214, 150, 0), + (424, 1, 214, 300, 0), + (425, 1, 214, 450, 0), + (426, 1, 262, 10, 5), + (426, 2, 262, 10, 4), + (427, 1, 262, 20, 5), + (427, 2, 262, 20, 4), + (428, 1, 262, 30, 5), + (428, 2, 262, 30, 4), + (429, 1, 262, 40, 5), + (429, 2, 262, 40, 4), + (430, 1, 262, 50, 5), + (430, 2, 262, 50, 4), + (434, 1, 125, 13, 13), + (434, 2, 137, 0, 0), + (434, 3, 141, 1, 0), + (434, 4, 139, -6233, 0), + (434, 5, 139, -6265, 0), + (434, 6, 125, 13, 13), + (434, 7, 137, 147, 0), + (434, 8, 141, 1, 0), + (435, 1, 125, 16, 16), + (435, 2, 137, 0, 0), + (435, 3, 141, 1, 0), + (435, 4, 139, -6233, 0), + (435, 5, 139, -6265, 0), + (435, 6, 125, 16, 16), + (435, 7, 137, 147, 0), + (435, 8, 141, 1, 0), + (436, 1, 125, 19, 19), + (436, 2, 137, 0, 0), + (436, 3, 141, 1, 0), + (436, 4, 139, -6233, 0), + (436, 5, 139, -6265, 0), + (436, 6, 125, 19, 19), + (436, 7, 137, 147, 0), + (436, 8, 141, 1, 0), + (437, 1, 274, 12, 0), + (438, 1, 274, 14, 0), + (439, 1, 274, 16, 0), + (440, 1, 278, 530, 21210), + (440, 2, 440, 56, 100), + (441, 1, 278, 540, 23160), + (441, 2, 440, 58, 100), + (442, 1, 278, 550, 25230), + (442, 2, 440, 60, 100), + (443, 1, 169, 100, -1), + (444, 1, 169, 125, -1), + (445, 1, 169, 150, -1), + (446, 1, 265, 54, 0), + (447, 1, 265, 56, 0), + (448, 1, 265, 58, 0), + (449, 1, 172, 13, 0), + (450, 1, 172, 16, 0), + (451, 1, 172, 19, 0), + (452, 1, 172, 22, 0), + (453, 1, 172, 25, 0), + (454, 1, 259, 13, 0), + (455, 1, 259, 16, 0), + (456, 1, 259, 19, 0), + (457, 1, 259, 22, 0), + (458, 1, 259, 25, 0), + (462, 1, 264, 60, 39), + (462, 2, 264, 864, 1061), + (463, 1, 264, 120, 39), + (463, 2, 264, 1728, 1061), + (464, 1, 264, 180, 39), + (464, 2, 264, 2592, 1061), + (468, 1, 264, 180, 41), + (469, 1, 264, 360, 41), + (470, 1, 264, 540, 41), + (471, 1, 264, 864, 57), + (471, 2, 264, 864, 616), + (472, 1, 264, 1728, 57), + (472, 2, 264, 1728, 616), + (473, 1, 264, 2592, 57), + (473, 2, 264, 2592, 616), + (474, 1, 264, 240, 50), + (475, 1, 264, 480, 50), + (476, 1, 264, 720, 50), + (477, 1, 264, 432, 43), + (478, 1, 264, 864, 43), + (479, 1, 264, 1296, 43), + (480, 1, 264, 432, 117), + (481, 1, 264, 864, 117), + (482, 1, 264, 1296, 117), + (483, 1, 264, 540, 58), + (483, 2, 264, 540, 418), + (484, 1, 264, 1080, 58), + (484, 2, 264, 1080, 418), + (485, 1, 264, 1620, 58), + (485, 2, 264, 1620, 418), + (489, 1, 264, 90, 110), + (490, 1, 264, 180, 110), + (491, 1, 264, 270, 110), + (492, 1, 264, 60, 109), + (493, 1, 264, 120, 109), + (494, 1, 264, 180, 109), + (495, 1, 264, 180, 98), + (496, 1, 264, 360, 98), + (497, 1, 264, 540, 98), + (498, 1, 264, 144, 102), + (499, 1, 264, 288, 102), + (500, 1, 264, 432, 102), + (501, 1, 264, 432, 107), + (502, 1, 264, 864, 107), + (503, 1, 264, 1296, 107), + (504, 1, 224, 110, 0), + (505, 1, 224, 120, 0), + (506, 1, 224, 130, 0), + (537, 1, 282, 60, 0), + (538, 1, 282, 75, 0), + (539, 1, 275, 68, 0), + (540, 1, 275, 76, 0), + (541, 1, 275, 84, 0), + (542, 1, 279, 17, 0), + (543, 1, 279, 19, 0), + (544, 1, 279, 21, 0), + (551, 1, 225, 3, 0), + (552, 1, 225, 6, 0), + (553, 1, 225, 9, 0), + (554, 1, 225, 12, 0), + (555, 1, 225, 15, 0), + (556, 1, 225, 3, 0), + (557, 1, 225, 6, 0), + (558, 1, 225, 9, 0), + (559, 1, 225, 12, 0), + (560, 1, 225, 15, 0), + (561, 1, 177, 3, -1), + (562, 1, 177, 6, -1), + (563, 1, 177, 9, -1), + (564, 1, 177, 3, -1), + (565, 1, 177, 6, -1), + (566, 1, 177, 9, -1), + (567, 1, 244, -12, 0), + (574, 1, 281, 25, 0), + (575, 1, 281, 50, 0), + (576, 1, 281, 75, 0), + (577, 1, 277, 20, 0), + (578, 1, 277, 40, 0), + (579, 1, 277, 60, 0), + (580, 1, 267, 1, 4), + (580, 2, 267, 1, 5), + (580, 3, 267, 1, 29), + (581, 1, 267, 1, 2), + (581, 2, 267, 1, 3), + (581, 3, 267, 1, 4), + (581, 4, 267, 1, 5), + (581, 5, 267, 1, 29), + (582, 1, 267, 1, 0), + (582, 2, 267, 1, 1), + (582, 3, 267, 1, 2), + (582, 4, 267, 1, 3), + (582, 5, 267, 1, 4), + (582, 6, 267, 1, 4), + (582, 7, 267, 1, 5), + (582, 8, 267, 1, 6), + (582, 9, 267, 1, 7), + (582, 10, 267, 1, 8), + (582, 11, 267, 1, 9), + (582, 12, 267, 1, 10), + (582, 13, 267, 1, 11), + (582, 14, 267, 1, 12), + (582, 15, 267, 1, 13), + (582, 16, 267, 1, 14), + (582, 17, 267, 1, 28), + (582, 18, 267, 1, 29), + (582, 19, 267, 1, 30), + (583, 1, 264, 7, 73), + (583, 2, 264, 7, 702), + (583, 3, 264, 7, 3826), + (583, 4, 264, 7, 7712), + (584, 1, 264, 14, 73), + (584, 2, 264, 14, 702), + (584, 3, 264, 14, 3826), + (584, 4, 264, 14, 7712), + (585, 1, 264, 21, 73), + (585, 2, 264, 21, 702), + (585, 3, 264, 21, 3826), + (585, 4, 264, 21, 7712), + (586, 1, 255, 12, 0), + (587, 1, 255, 24, 0), + (588, 1, 255, 36, 0), + (589, 1, 303, 500, 500), + (589, 2, 139, 2766, 0), + (590, 1, 303, 1000, 1000), + (590, 2, 139, 2766, 0), + (591, 1, 303, 1500, 1500), + (591, 2, 139, 2766, 0), + (593, 1, 264, 720, 6001), + (593, 2, 264, 720, 3676), + (594, 1, 264, 1440, 6001), + (594, 2, 264, 1440, 3676), + (595, 1, 264, 2160, 6001), + (595, 2, 264, 2160, 3676), + (596, 1, 264, 720, 6000), + (596, 2, 264, 720, 87), + (597, 1, 264, 1440, 6000), + (597, 2, 264, 1440, 87), + (598, 1, 264, 2160, 6000), + (598, 2, 264, 2160, 87), + (599, 1, 266, 2, 0), + (600, 1, 266, 5, 0), + (601, 1, 266, 8, 0), + (602, 1, 266, 2, 0), + (603, 1, 266, 5, 0), + (604, 1, 266, 8, 0), + (605, 1, 256, 1, 0), + (606, 1, 285, 20, 0), + (607, 1, 285, 40, 0), + (608, 1, 285, 60, 0), + (609, 1, 285, 80, 0), + (610, 1, 285, 100, 0), + (611, 1, 283, 20, 0), + (612, 1, 283, 40, 0), + (613, 1, 283, 60, 0), + (614, 1, 283, 80, 0), + (615, 1, 283, 100, 0), + (622, 1, 227, 1, 29), + (622, 2, 227, 1, 42), + (623, 1, 227, 2, 29), + (623, 2, 227, 2, 42), + (624, 1, 227, 3, 29), + (624, 2, 227, 3, 42), + (625, 1, 294, 3, 100), + (626, 1, 294, 6, 100), + (627, 1, 294, 9, 100), + (628, 1, 290, 5, 0), + (629, 1, 290, 10, 0), + (631, 1, 292, 15, 0), + (632, 1, 292, 30, 0), + (633, 1, 292, 45, 0), + (634, 1, 274, 3, 0), + (635, 1, 274, 6, 0), + (636, 1, 274, 10, 0), + (637, 1, 294, 2, 100), + (638, 1, 294, 4, 100), + (639, 1, 294, 6, 100), + (640, 1, 294, 7, 100), + (641, 1, 294, 8, 100), + (642, 1, 294, 9, 100), + (644, 1, 217, 0, 32000), + (644, 2, 346, 59, 0), + (649, 1, 243, 15, 0), + (650, 1, 243, 25, 0), + (651, 1, 243, 35, 0), + (652, 1, 293, 25, 0), + (653, 1, 293, 50, 0), + (654, 1, 293, 75, 0), + (655, 1, 127, 10, 10), + (655, 2, 137, 32, 0), + (655, 3, 127, 10, 10), + (655, 4, 137, 33, 0), + (655, 5, 127, 10, 10), + (655, 6, 137, 82, 0), + (655, 7, 127, 2, 2), + (655, 8, 137, 152, 0), + (655, 9, 143, 3000, 0), + (656, 1, 127, 25, 25), + (656, 2, 137, 32, 0), + (656, 3, 127, 25, 25), + (656, 4, 137, 33, 0), + (656, 5, 127, 25, 25), + (656, 6, 137, 82, 0), + (656, 7, 127, 5, 5), + (656, 8, 137, 152, 0), + (656, 9, 143, 3000, 0), + (657, 1, 127, 50, 50), + (657, 2, 137, 32, 0), + (657, 3, 127, 50, 50), + (657, 4, 137, 33, 0), + (657, 5, 127, 50, 50), + (657, 6, 137, 82, 0), + (657, 7, 127, 10, 10), + (657, 8, 137, 152, 0), + (657, 9, 143, 3000, 0), + (658, 1, 15, 1, 0), + (659, 1, 15, 2, 0), + (660, 1, 15, 3, 0), + (661, 1, 0, 1, 0), + (662, 1, 0, 2, 0), + (663, 1, 0, 3, 0), + (665, 1, 270, 10, 0), + (666, 1, 270, 15, 0), + (667, 1, 270, 25, 0), + (668, 1, 270, 55, 0), + (669, 1, 270, 60, 0), + (670, 1, 270, 65, 0), + (671, 1, 241, 95, 0), + (672, 1, 271, 28, 0), + (673, 1, 271, 35, 0), + (674, 1, 0, 4, 0), + (675, 1, 0, 5, 0), + (676, 1, 246, 325, 0), + (677, 1, 246, 350, 0), + (678, 1, 221, 3, 0), + (679, 1, 221, 6, 0), + (680, 1, 221, 9, 0), + (681, 1, 221, 12, 0), + (682, 1, 221, 15, 0), + (683, 1, 189, 1, 0), + (684, 1, 189, 2, 0), + (685, 1, 189, 3, 0), + (686, 1, 200, 10, 0), + (687, 1, 200, 20, 0), + (688, 1, 200, 30, 0), + (689, 1, 200, 40, 0), + (690, 1, 200, 50, 0), + (691, 1, 248, 100, 0), + (692, 1, 229, 5, 0), + (693, 1, 229, 10, 0), + (694, 1, 229, 15, 0), + (695, 1, 247, 10, 53), + (696, 1, 247, 20, 53), + (697, 1, 247, 30, 53), + (698, 1, 247, 40, 53), + (699, 1, 247, 50, 53), + (700, 1, 260, 8, 23), + (700, 2, 260, 8, 24), + (700, 3, 260, 8, 25), + (700, 4, 260, 8, 26), + (701, 1, 260, 8, 50), + (724, 1, 218, 1, 0), + (725, 1, 218, 2, 0), + (726, 1, 218, 3, 0), + (727, 1, 218, 4, 0), + (728, 1, 218, 5, 0), + (729, 1, 280, 4, 0), + (730, 1, 280, 8, 0), + (731, 1, 280, 12, 0), + (732, 1, 280, 16, 0), + (733, 1, 280, 20, 0), + (734, 1, 237, 1, 0), + (735, 1, 265, 54, 0), + (736, 1, 265, 56, 0), + (737, 1, 265, 58, 0), + (738, 1, 114, -5, 0), + (739, 1, 114, -10, 0), + (740, 1, 114, -20, 0), + (754, 1, 264, 18, 153), + (755, 1, 264, 36, 153), + (756, 1, 264, 54, 153), + (762, 1, 247, 10, 53), + (763, 1, 247, 20, 53), + (764, 1, 247, 30, 53), + (765, 1, 247, 40, 53), + (766, 1, 247, 50, 53), + (767, 1, 273, 3, 0), + (768, 1, 273, 6, 0), + (769, 1, 273, 9, 0), + (770, 1, 294, 7, 100), + (771, 1, 294, 8, 100), + (772, 1, 294, 9, 100), + (776, 1, 242, 10, 0), + (777, 1, 242, 20, 0), + (778, 1, 242, 30, 0), + (779, 1, 242, 40, 0), + (780, 1, 242, 50, 0), + (781, 1, 287, 1, 1), + (781, 2, 137, 31, 0), + (781, 3, 136, 5, 0), + (782, 1, 264, 432, 35), + (783, 1, 264, 864, 35), + (784, 1, 264, 1296, 35), + (790, 1, 218, 1, 0), + (791, 1, 218, 2, 0), + (792, 1, 218, 3, 0), + (793, 1, 218, 4, 0), + (794, 1, 218, 5, 0), + (795, 1, 280, 4, 0), + (796, 1, 280, 8, 0), + (797, 1, 280, 12, 0), + (798, 1, 280, 16, 0), + (799, 1, 280, 20, 0), + (800, 1, 215, 2, 0), + (801, 1, 215, 5, 0), + (802, 1, 215, 10, 0), + (803, 1, 213, 2, 0), + (804, 1, 213, 5, 0), + (805, 1, 213, 10, 0), + (806, 1, 249, 1, 0), + (807, 1, 292, 5, 0), + (808, 1, 292, 10, 0), + (809, 1, 292, 15, 0), + (810, 1, 239, 10, 0), + (811, 1, 239, 20, 0), + (812, 1, 239, 30, 0), + (813, 1, 239, 40, 0), + (814, 1, 239, 50, 0), + (815, 1, 279, 7, 0), + (816, 1, 279, 11, 0), + (817, 1, 279, 15, 0), + (818, 1, 279, 17, 0), + (819, 1, 279, 19, 0), + (820, 1, 220, 10, 26), + (820, 2, 220, 10, 30), + (820, 3, 220, 10, 38), + (821, 1, 220, 20, 26), + (821, 2, 220, 20, 30), + (821, 3, 220, 20, 38), + (822, 1, 220, 30, 26), + (822, 2, 220, 30, 30), + (822, 3, 220, 30, 38), + (823, 1, 222, 20, 0), + (824, 1, 222, 40, 0), + (825, 1, 222, 60, 0), + (826, 1, 222, 80, 0), + (827, 1, 222, 100, 0), + (834, 1, 218, 1, 0), + (835, 1, 218, 2, 0), + (836, 1, 218, 3, 0), + (837, 1, 218, 4, 0), + (838, 1, 218, 5, 0), + (839, 1, 280, 4, 0), + (840, 1, 280, 8, 0), + (841, 1, 280, 12, 0), + (842, 1, 280, 16, 0), + (843, 1, 280, 20, 0), + (844, 1, 274, 12, 0), + (845, 1, 274, 14, 0), + (846, 1, 258, 5, 0), + (847, 1, 258, 10, 0), + (848, 1, 258, 15, 0), + (849, 1, 264, 240, 180), + (850, 1, 264, 480, 180), + (851, 1, 264, 720, 180), + (852, 1, 231, 1, 0), + (853, 1, 231, 2, 0), + (854, 1, 231, 3, 0), + (855, 1, 220, 5, 10), + (856, 1, 220, 10, 10), + (857, 1, 220, 15, 10), + (858, 1, 220, 20, 10), + (859, 1, 220, 25, 10), + (864, 1, 216, 10, 0), + (864, 2, 216, 10, 1), + (864, 3, 216, 10, 2), + (864, 4, 216, 10, 3), + (864, 5, 216, 10, 10), + (864, 6, 216, 10, 28), + (864, 7, 216, 10, 30), + (864, 8, 216, 10, 36), + (864, 9, 216, 10, 77), + (865, 1, 216, 20, 0), + (865, 2, 216, 20, 1), + (865, 3, 216, 20, 2), + (865, 4, 216, 20, 3), + (865, 5, 216, 20, 10), + (865, 6, 216, 20, 28), + (865, 7, 216, 20, 30), + (865, 8, 216, 20, 36), + (865, 9, 216, 20, 77), + (866, 1, 216, 30, 0), + (866, 2, 216, 30, 1), + (866, 3, 216, 30, 2), + (866, 4, 216, 30, 3), + (866, 5, 216, 30, 10), + (866, 6, 216, 30, 28), + (866, 7, 216, 30, 30), + (866, 8, 216, 30, 36), + (866, 9, 216, 30, 77), + (867, 1, 59, -3, 0), + (868, 1, 59, -6, 0), + (869, 1, 59, -9, 0), + (870, 1, 59, -12, 0), + (871, 1, 59, -15, 0), + (878, 1, 252, 10, 0), + (879, 1, 252, 20, 0), + (880, 1, 252, 30, 0), + (881, 1, 245, 10, 0), + (882, 1, 245, 20, 0), + (883, 1, 245, 30, 0), + (884, 1, 245, 40, 0), + (885, 1, 245, 50, 0), + (886, 1, 264, 576, 102), + (887, 1, 264, 720, 102), + (888, 1, 250, 10, 0), + (889, 1, 250, 20, 0), + (890, 1, 250, 30, 0), + (891, 1, 250, 40, 0), + (892, 1, 250, 50, 0), + (893, 1, 303, 2000, 2000), + (893, 2, 139, 2766, 0), + (894, 1, 303, 2500, 2500), + (894, 2, 139, 2766, 0), + (895, 1, 59, -3, 0), + (896, 1, 59, -6, 0), + (897, 1, 59, -9, 0), + (898, 1, 59, -12, 0), + (899, 1, 59, -15, 0), + (907, 1, 69, 100, 0), + (908, 1, 69, 200, 0), + (909, 1, 69, 300, 0), + (910, 1, 69, 400, 0), + (911, 1, 69, 500, 0), + (915, 1, 220, 5, 10), + (915, 2, 220, 5, 30), + (916, 1, 220, 10, 10), + (916, 2, 220, 10, 30), + (917, 1, 220, 15, 10), + (917, 2, 220, 15, 30), + (918, 1, 230, 2, 0), + (919, 1, 230, 4, 0), + (920, 1, 230, 6, 0), + (924, 1, 294, 10, 100), + (925, 1, 294, 11, 100), + (934, 1, 169, 15, -1), + (935, 1, 169, 30, -1), + (936, 1, 169, 60, -1), + (937, 1, 169, 15, 0), + (937, 2, 169, 15, 1), + (937, 3, 169, 15, 2), + (937, 4, 169, 15, 3), + (937, 5, 169, 15, 7), + (937, 6, 169, 15, 8), + (937, 7, 169, 15, 10), + (937, 8, 169, 15, 28), + (937, 9, 169, 15, 30), + (937, 10, 169, 15, 36), + (937, 11, 169, 15, 51), + (938, 1, 169, 40, 0), + (938, 2, 169, 40, 1), + (938, 3, 169, 40, 2), + (938, 4, 169, 40, 3), + (938, 5, 169, 40, 7), + (938, 6, 169, 40, 8), + (938, 7, 169, 40, 10), + (938, 8, 169, 40, 28), + (938, 9, 169, 40, 30), + (938, 10, 169, 40, 36), + (938, 11, 169, 30, 51), + (939, 1, 169, 75, 0), + (939, 2, 169, 75, 1), + (939, 3, 169, 75, 2), + (939, 4, 169, 75, 3), + (939, 5, 169, 75, 7), + (939, 6, 169, 75, 8), + (939, 7, 169, 75, 10), + (939, 8, 169, 75, 28), + (939, 9, 169, 75, 30), + (939, 10, 169, 75, 36), + (939, 11, 169, 60, 51), + (940, 1, 169, 15, 0), + (940, 2, 169, 15, 1), + (940, 3, 169, 15, 2), + (940, 4, 169, 15, 3), + (940, 5, 169, 15, 7), + (940, 6, 169, 15, 8), + (940, 7, 169, 15, 10), + (940, 8, 169, 15, 28), + (940, 9, 169, 15, 30), + (940, 10, 169, 15, 36), + (940, 11, 169, 15, 51), + (940, 12, 169, 15, 77), + (941, 1, 169, 40, 0), + (941, 2, 169, 40, 1), + (941, 3, 169, 40, 2), + (941, 4, 169, 40, 3), + (941, 5, 169, 30, 7), + (941, 6, 169, 40, 8), + (941, 7, 169, 40, 10), + (941, 8, 169, 40, 28), + (941, 9, 169, 40, 30), + (941, 10, 169, 40, 36), + (941, 11, 169, 40, 51), + (941, 12, 169, 40, 77), + (942, 1, 169, 75, 0), + (942, 2, 169, 75, 1), + (942, 3, 169, 75, 2), + (942, 4, 169, 75, 3), + (942, 5, 169, 60, 7), + (942, 6, 169, 75, 8), + (942, 7, 169, 75, 10), + (942, 8, 169, 75, 28), + (942, 9, 169, 75, 30), + (942, 10, 169, 75, 36), + (942, 11, 169, 75, 51), + (942, 12, 169, 75, 77), + (943, 1, 169, 146, -1), + (944, 1, 169, 172, -1), + (945, 1, 169, 198, -1), + (946, 1, 169, 175, 0), + (946, 2, 169, 175, 1), + (946, 3, 169, 175, 2), + (946, 4, 169, 175, 3), + (946, 5, 169, 175, 7), + (946, 6, 169, 175, 8), + (946, 7, 169, 175, 10), + (946, 8, 169, 175, 28), + (946, 9, 169, 175, 30), + (946, 10, 169, 175, 36), + (946, 11, 169, 146, 51), + (947, 1, 169, 200, 0), + (947, 2, 169, 200, 1), + (947, 3, 169, 200, 2), + (947, 4, 169, 200, 3), + (947, 5, 169, 200, 7), + (947, 6, 169, 200, 8), + (947, 7, 169, 200, 10), + (947, 8, 169, 200, 28), + (947, 9, 169, 200, 30), + (947, 10, 169, 200, 36), + (947, 11, 169, 172, 51), + (948, 1, 169, 225, 0), + (948, 2, 169, 225, 1), + (948, 3, 169, 225, 2), + (948, 4, 169, 225, 3), + (948, 5, 169, 225, 7), + (948, 6, 169, 225, 8), + (948, 7, 169, 225, 10), + (948, 8, 169, 225, 28), + (948, 9, 169, 225, 30), + (948, 10, 169, 225, 36), + (948, 11, 169, 198, 51), + (949, 1, 169, 175, 0), + (949, 2, 169, 175, 1), + (949, 3, 169, 175, 2), + (949, 4, 169, 175, 3), + (949, 5, 169, 161, 7), + (949, 6, 169, 175, 8), + (949, 7, 169, 175, 10), + (949, 8, 169, 175, 28), + (949, 9, 169, 175, 30), + (949, 10, 169, 175, 36), + (949, 11, 169, 175, 51), + (949, 12, 169, 175, 77), + (950, 1, 169, 200, 0), + (950, 2, 169, 200, 1), + (950, 3, 169, 200, 2), + (950, 4, 169, 200, 3), + (950, 5, 169, 187, 7), + (950, 6, 169, 200, 8), + (950, 7, 169, 200, 10), + (950, 8, 169, 200, 28), + (950, 9, 169, 200, 30), + (950, 10, 169, 200, 36), + (950, 11, 169, 200, 51), + (950, 12, 169, 200, 77), + (951, 1, 169, 225, 0), + (951, 2, 169, 225, 1), + (951, 3, 169, 225, 2), + (951, 4, 169, 225, 3), + (951, 5, 169, 213, 7), + (951, 6, 169, 225, 8), + (951, 7, 169, 225, 10), + (951, 8, 169, 225, 28), + (951, 9, 169, 225, 30), + (951, 10, 169, 225, 36), + (951, 11, 169, 225, 51), + (951, 12, 169, 225, 77), + (952, 1, 214, 125, 0), + (953, 1, 214, 250, 0), + (954, 1, 214, 375, 0), + (955, 1, 262, 10, 4), + (955, 2, 262, 10, 5), + (956, 1, 262, 20, 4), + (956, 2, 262, 20, 5), + (957, 1, 262, 30, 4), + (957, 2, 262, 30, 5), + (958, 1, 262, 40, 4), + (958, 2, 262, 40, 5), + (959, 1, 262, 50, 4), + (959, 2, 262, 50, 5), + (962, 1, 232, 2, 4544), + (963, 1, 232, 4, 4544), + (964, 1, 232, 6, 4544), + (965, 1, 232, 8, 4544), + (966, 1, 232, 10, 4544), + (975, 1, 264, 864, 102), + (976, 1, 131, 100, 0), + (976, 2, 137, 33, 0), + (978, 1, 14, 1, 0), + (978, 2, 246, 350, 0), + (979, 1, 268, 10, 63), + (980, 1, 268, 25, 63), + (981, 1, 268, 50, 63), + (982, 1, 268, 10, 60), + (983, 1, 268, 25, 60), + (984, 1, 268, 50, 60), + (985, 1, 268, 10, 65), + (986, 1, 268, 25, 65), + (987, 1, 268, 50, 65), + (988, 1, 268, 10, 64), + (989, 1, 268, 25, 64), + (990, 1, 268, 50, 64), + (991, 1, 268, 10, 69), + (992, 1, 268, 25, 69), + (993, 1, 268, 50, 69), + (994, 1, 268, 10, 61), + (995, 1, 268, 25, 61), + (996, 1, 268, 50, 61), + (997, 1, 331, 5, 0), + (998, 1, 331, 15, 0), + (999, 1, 331, 25, 0), + (1001, 1, 262, 30, 0), + (1001, 2, 262, 30, 1), + (1001, 3, 262, 30, 2), + (1001, 4, 262, 30, 3), + (1001, 5, 262, 30, 4), + (1001, 6, 262, 30, 5), + (1001, 7, 262, 30, 6), + (1002, 1, 262, 35, 0), + (1002, 2, 262, 35, 1), + (1002, 3, 262, 35, 2), + (1002, 4, 262, 35, 3), + (1002, 5, 262, 35, 4), + (1002, 6, 262, 35, 5), + (1002, 7, 262, 35, 6), + (1003, 1, 262, 40, 0), + (1003, 2, 262, 40, 1), + (1003, 3, 262, 40, 2), + (1003, 4, 262, 40, 3), + (1003, 5, 262, 40, 4), + (1003, 6, 262, 40, 5), + (1003, 7, 262, 40, 6), + (1004, 1, 262, 45, 0), + (1004, 2, 262, 45, 1), + (1004, 3, 262, 45, 2), + (1004, 4, 262, 45, 3), + (1004, 5, 262, 45, 4), + (1004, 6, 262, 45, 5), + (1004, 7, 262, 45, 6), + (1005, 1, 262, 50, 0), + (1005, 2, 262, 50, 1), + (1005, 3, 262, 50, 2), + (1005, 4, 262, 50, 3), + (1005, 5, 262, 50, 4), + (1005, 6, 262, 50, 5), + (1005, 7, 262, 50, 6), + (1006, 1, 262, 5, 7), + (1006, 2, 262, 5, 8), + (1006, 3, 262, 5, 9), + (1006, 4, 262, 5, 10), + (1006, 5, 262, 5, 11), + (1007, 1, 262, 10, 7), + (1007, 2, 262, 10, 8), + (1007, 3, 262, 10, 9), + (1007, 4, 262, 10, 10), + (1007, 5, 262, 10, 11), + (1008, 1, 262, 15, 7), + (1008, 2, 262, 15, 8), + (1008, 3, 262, 15, 9), + (1008, 4, 262, 15, 10), + (1008, 5, 262, 15, 11), + (1009, 1, 262, 20, 7), + (1009, 2, 262, 20, 8), + (1009, 3, 262, 20, 9), + (1009, 4, 262, 20, 10), + (1009, 5, 262, 20, 11), + (1010, 1, 262, 25, 7), + (1010, 2, 262, 25, 8), + (1010, 3, 262, 25, 9), + (1010, 4, 262, 25, 10), + (1010, 5, 262, 25, 11), + (1011, 1, 262, 8, 7), + (1011, 2, 262, 8, 8), + (1011, 3, 262, 8, 9), + (1011, 4, 262, 8, 10), + (1011, 5, 262, 8, 11), + (1012, 1, 262, 16, 7), + (1012, 2, 262, 16, 8), + (1012, 3, 262, 16, 9), + (1012, 4, 262, 16, 10), + (1012, 5, 262, 16, 11), + (1013, 1, 262, 24, 7), + (1013, 2, 262, 24, 8), + (1013, 3, 262, 24, 9), + (1013, 4, 262, 24, 10), + (1013, 5, 262, 24, 11), + (1014, 1, 262, 32, 7), + (1014, 2, 262, 32, 8), + (1014, 3, 262, 32, 9), + (1014, 4, 262, 32, 10), + (1014, 5, 262, 32, 11), + (1016, 1, 262, 50, 7), + (1016, 2, 262, 50, 8), + (1016, 3, 262, 50, 9), + (1016, 4, 262, 50, 10), + (1016, 5, 262, 50, 11), + (1021, 1, 327, 1, 0), + (1022, 1, 327, 2, 0), + (1023, 1, 327, 3, 0), + (1024, 1, 327, 4, 0), + (1025, 1, 327, 5, 0), + (1026, 1, 328, 50, 0), + (1027, 1, 328, 100, 0), + (1028, 1, 328, 150, 0), + (1029, 1, 328, 200, 0), + (1030, 1, 328, 250, 0), + (1031, 1, 0, 6, 0), + (1032, 1, 0, 7, 0), + (1033, 1, 0, 8, 0), + (1034, 1, 0, 9, 0), + (1035, 1, 0, 10, 0), + (1036, 1, 189, 4, 0), + (1037, 1, 189, 5, 0), + (1038, 1, 189, 6, 0), + (1041, 1, 330, 25, 0), + (1041, 2, 330, 25, 1), + (1041, 3, 330, 25, 2), + (1041, 4, 330, 25, 3), + (1041, 5, 330, 25, 28), + (1041, 6, 330, 25, 36), + (1041, 7, 330, 25, 77), + (1042, 1, 330, 50, 0), + (1042, 2, 330, 50, 1), + (1042, 3, 330, 50, 2), + (1042, 4, 330, 50, 3), + (1042, 5, 330, 50, 28), + (1042, 6, 330, 50, 36), + (1042, 7, 330, 50, 77), + (1043, 1, 330, 75, 0), + (1043, 2, 330, 75, 1), + (1043, 3, 330, 75, 2), + (1043, 4, 330, 75, 3), + (1043, 5, 330, 75, 28), + (1043, 6, 330, 75, 36), + (1043, 7, 330, 75, 77), + (1044, 1, 330, 25, 0), + (1044, 2, 330, 25, 1), + (1044, 3, 330, 25, 2), + (1044, 4, 330, 25, 3), + (1044, 5, 330, 25, 28), + (1044, 6, 330, 25, 36), + (1045, 1, 330, 50, 0), + (1045, 2, 330, 50, 1), + (1045, 3, 330, 50, 2), + (1045, 4, 330, 50, 3), + (1045, 5, 330, 50, 28), + (1045, 6, 330, 50, 36), + (1046, 1, 330, 75, 0), + (1046, 2, 330, 75, 1), + (1046, 3, 330, 75, 2), + (1046, 4, 330, 75, 3), + (1046, 5, 330, 75, 28), + (1046, 6, 330, 75, 36), + (1047, 1, 330, 25, 0), + (1047, 2, 330, 25, 1), + (1047, 3, 330, 25, 2), + (1047, 4, 330, 25, 3), + (1047, 5, 330, 25, 28), + (1047, 6, 330, 25, 36), + (1047, 7, 330, 25, 77), + (1048, 1, 330, 50, 0), + (1048, 2, 330, 50, 1), + (1048, 3, 330, 50, 2), + (1048, 4, 330, 50, 3), + (1048, 5, 330, 50, 28), + (1048, 6, 330, 50, 36), + (1048, 7, 330, 50, 77), + (1049, 1, 330, 75, 0), + (1049, 2, 330, 75, 1), + (1049, 3, 330, 75, 2), + (1049, 4, 330, 75, 3), + (1049, 5, 330, 75, 28), + (1049, 6, 330, 75, 36), + (1049, 7, 330, 75, 77), + (1050, 1, 330, 15, 0), + (1050, 2, 330, 15, 1), + (1050, 3, 330, 15, 2), + (1050, 4, 330, 15, 3), + (1050, 5, 330, 15, 28), + (1050, 6, 330, 15, 36), + (1050, 7, 330, 15, 77), + (1051, 1, 330, 30, 0), + (1051, 2, 330, 30, 1), + (1051, 3, 330, 30, 2), + (1051, 4, 330, 30, 3), + (1051, 5, 330, 30, 28), + (1051, 6, 330, 30, 36), + (1051, 7, 330, 30, 77), + (1052, 1, 330, 50, 0), + (1052, 2, 330, 50, 1), + (1052, 3, 330, 50, 2), + (1052, 4, 330, 50, 3), + (1052, 5, 330, 50, 28), + (1052, 6, 330, 50, 36), + (1052, 7, 330, 50, 77), + (1053, 1, 278, 560, 27200), + (1053, 2, 440, 61, 100), + (1054, 1, 278, 580, 30135), + (1054, 2, 440, 63, 100), + (1055, 1, 278, 600, 32780), + (1055, 2, 440, 65, 100), + (1056, 1, 317, 1, 0), + (1057, 1, 317, 2, 0), + (1058, 1, 317, 3, 0), + (1059, 1, 317, 4, 0), + (1060, 1, 317, 5, 0), + (1061, 1, 172, 26, 0), + (1062, 1, 172, 27, 0), + (1063, 1, 172, 28, 0), + (1064, 1, 172, 30, 0), + (1065, 1, 172, 32, 0), + (1066, 1, 259, 27, 0), + (1067, 1, 259, 29, 0), + (1068, 1, 259, 31, 0), + (1069, 1, 259, 33, 0), + (1070, 1, 259, 35, 0), + (1071, 1, 326, 1, 0), + (1072, 1, 318, 1, 0), + (1073, 1, 318, 2, 0), + (1074, 1, 318, 3, 0), + (1075, 1, 318, 4, 0), + (1076, 1, 318, 5, 0), + (1083, 1, 125, 22, 22), + (1083, 2, 137, 0, 0), + (1083, 3, 141, 1, 0), + (1083, 4, 139, -6233, 0), + (1083, 5, 139, -6265, 0), + (1083, 6, 125, 22, 22), + (1083, 7, 137, 147, 0), + (1083, 8, 141, 1, 0), + (1084, 1, 125, 25, 25), + (1084, 2, 137, 0, 0), + (1084, 3, 141, 1, 0), + (1084, 4, 139, -6233, 0), + (1084, 5, 139, -6265, 0), + (1084, 6, 125, 25, 25), + (1084, 7, 137, 147, 0), + (1084, 8, 141, 1, 0), + (1085, 1, 125, 28, 28), + (1085, 2, 137, 0, 0), + (1085, 3, 141, 1, 0), + (1085, 4, 139, -6233, 0), + (1085, 5, 139, -6265, 0), + (1085, 6, 125, 28, 28), + (1085, 7, 137, 147, 0), + (1085, 8, 141, 1, 0), + (1086, 1, 274, 18, 0), + (1087, 1, 274, 20, 0), + (1088, 1, 274, 22, 0), + (1089, 1, 268, 10, 58), + (1090, 1, 268, 25, 58), + (1091, 1, 268, 50, 58), + (1092, 1, 238, 1, 0), + (1093, 1, 304, -20, 0), + (1094, 1, 304, -40, 0), + (1095, 1, 304, -60, 0), + (1096, 1, 304, -80, 0), + (1097, 1, 304, -100, 0), + (1099, 1, 273, 12, 0), + (1100, 1, 273, 15, 0), + (1101, 1, 273, 18, 0), + (1107, 1, 294, 2, 100), + (1108, 1, 294, 4, 100), + (1109, 1, 294, 6, 100), + (1113, 1, 331, 30, 0), + (1114, 1, 331, 35, 0), + (1115, 1, 331, 40, 0), + (1122, 1, 308, 1, 0), + (1129, 1, 267, 1, 24), + (1129, 2, 267, 1, 25), + (1129, 3, 267, 1, 26), + (1130, 1, 267, 1, 18), + (1130, 2, 267, 1, 19), + (1130, 3, 267, 1, 20), + (1130, 4, 267, 1, 21), + (1130, 5, 267, 1, 22), + (1130, 6, 267, 1, 23), + (1130, 7, 267, 1, 24), + (1130, 8, 267, 1, 25), + (1130, 9, 267, 1, 26), + (1131, 1, 185, 10, 51), + (1132, 1, 185, 20, 51), + (1133, 1, 185, 30, 51), + (1134, 1, 220, 32, 74), + (1135, 1, 220, 64, 74), + (1136, 1, 220, 96, 74), + (1137, 1, 310, 180000, 0), + (1137, 2, 139, 5027, 0), + (1137, 3, 310, 180000, 0), + (1137, 4, 139, 5028, 0), + (1137, 5, 310, 180000, 0), + (1137, 6, 139, 5029, 0), + (1137, 7, 310, 180000, 0), + (1137, 8, 139, 5030, 0), + (1137, 9, 310, 180000, 0), + (1137, 10, 139, 5031, 0), + (1137, 11, 310, 180000, 0), + (1137, 12, 139, 5032, 0), + (1137, 13, 310, 180000, 0), + (1137, 14, 139, 8476, 0), + (1138, 1, 310, 360000, 0), + (1138, 2, 139, 5027, 0), + (1138, 3, 310, 360000, 0), + (1138, 4, 139, 5028, 0), + (1138, 5, 310, 360000, 0), + (1138, 6, 139, 5029, 0), + (1138, 7, 310, 360000, 0), + (1138, 8, 139, 5030, 0), + (1138, 9, 310, 360000, 0), + (1138, 10, 139, 5031, 0), + (1138, 11, 310, 360000, 0), + (1138, 12, 139, 5032, 0), + (1138, 13, 310, 360000, 0), + (1138, 14, 139, 8476, 0), + (1139, 1, 310, 540000, 0), + (1139, 2, 139, 5027, 0), + (1139, 3, 310, 540000, 0), + (1139, 4, 139, 5028, 0), + (1139, 5, 310, 540000, 0), + (1139, 6, 139, 5029, 0), + (1139, 7, 310, 540000, 0), + (1139, 8, 139, 5030, 0), + (1139, 9, 310, 540000, 0), + (1139, 10, 139, 5031, 0), + (1139, 11, 310, 540000, 0), + (1139, 12, 139, 5032, 0), + (1139, 13, 310, 540000, 0), + (1139, 14, 139, 8476, 0), + (1140, 1, 216, 10, 51), + (1141, 1, 216, 20, 51), + (1142, 1, 216, 30, 51), + (1155, 1, 128, 25, 0), + (1155, 2, 139, 5027, 0), + (1155, 3, 128, 25, 0), + (1155, 4, 139, 5028, 0), + (1155, 5, 128, 25, 0), + (1155, 6, 139, 5029, 0), + (1155, 7, 128, 25, 0), + (1155, 8, 139, 5030, 0), + (1155, 9, 128, 25, 0), + (1155, 10, 139, 5031, 0), + (1155, 11, 128, 25, 0), + (1155, 12, 139, 5032, 0), + (1155, 13, 128, 25, 0), + (1155, 14, 139, 8476, 0), + (1156, 1, 128, 50, 0), + (1156, 2, 139, 5027, 0), + (1156, 3, 128, 50, 0), + (1156, 4, 139, 5028, 0), + (1156, 5, 128, 50, 0), + (1156, 6, 139, 5029, 0), + (1156, 7, 128, 50, 0), + (1156, 8, 139, 5030, 0), + (1156, 9, 128, 50, 0), + (1156, 10, 139, 5031, 0), + (1156, 11, 128, 50, 0), + (1156, 12, 139, 5032, 0), + (1156, 13, 128, 50, 0), + (1156, 14, 139, 8476, 0), + (1157, 1, 128, 100, 0), + (1157, 2, 139, 5027, 0), + (1157, 3, 128, 100, 0), + (1157, 4, 139, 5028, 0), + (1157, 5, 128, 100, 0), + (1157, 6, 139, 5029, 0), + (1157, 7, 128, 100, 0), + (1157, 8, 139, 5030, 0), + (1157, 9, 128, 100, 0), + (1157, 10, 139, 5031, 0), + (1157, 11, 128, 100, 0), + (1157, 12, 139, 5032, 0), + (1157, 13, 128, 100, 0), + (1157, 14, 139, 8476, 0), + (1158, 1, 220, 128, 74), + (1159, 1, 220, 160, 74), + (1160, 1, 220, 192, 74), + (1161, 1, 220, 224, 74), + (1162, 1, 220, 256, 74), + (1163, 1, 279, 23, 0), + (1164, 1, 279, 25, 0), + (1165, 1, 279, 27, 0), + (1166, 1, 224, 20, 74), + (1166, 2, 173, 1, 0), + (1167, 1, 224, 35, 74), + (1167, 2, 173, 1, 0), + (1168, 1, 224, 50, 74), + (1168, 2, 173, 2, 0), + (1172, 1, 292, 50, 0), + (1173, 1, 292, 55, 0), + (1174, 1, 292, 60, 0), + (1181, 1, 305, -20, 0), + (1182, 1, 305, -40, 0), + (1183, 1, 305, -60, 0), + (1184, 1, 305, -80, 0), + (1185, 1, 305, -100, 0), + (1186, 1, 319, 3, 0), + (1187, 1, 319, 6, 0), + (1188, 1, 319, 10, 0), + (1196, 1, 220, 20, 7), + (1197, 1, 220, 40, 7), + (1198, 1, 220, 60, 7), + (1199, 1, 220, 80, 7), + (1200, 1, 220, 100, 7), + (1210, 1, 294, 0, 107), + (1211, 1, 294, 0, 115), + (1212, 1, 294, 0, 125), + (1213, 1, 294, 0, 107), + (1214, 1, 294, 0, 115), + (1215, 1, 294, 0, 125), + (1216, 1, 132, 2, 2), + (1217, 1, 132, 5, 5), + (1218, 1, 132, 10, 10), + (1219, 1, 339, 3, 8105), + (1219, 2, 142, 65, 0), + (1219, 3, 311, 0, 0), + (1219, 4, 134, 70, 0), + (1219, 5, 348, 10, 0), + (1219, 6, 137, 0, 0), + (1219, 7, 339, 3, 8105), + (1219, 8, 142, 65, 0), + (1219, 9, 311, 0, 0), + (1219, 10, 134, 70, 0), + (1219, 11, 348, 10, 0), + (1219, 12, 137, 100, 0), + (1219, 13, 339, 3, 8105), + (1219, 14, 142, 65, 0), + (1219, 15, 311, 0, 0), + (1219, 16, 134, 70, 0), + (1219, 17, 348, 10, 0), + (1219, 18, 137, 79, 0), + (1219, 19, 339, 3, 8105), + (1219, 20, 142, 65, 0), + (1219, 21, 311, 0, 0), + (1219, 22, 134, 70, 0), + (1219, 23, 348, 10, 0), + (1219, 24, 137, 147, 0), + (1220, 1, 339, 6, 8105), + (1220, 2, 142, 65, 0), + (1220, 3, 311, 0, 0), + (1220, 4, 134, 70, 0), + (1220, 5, 348, 10, 0), + (1220, 6, 137, 0, 0), + (1220, 7, 339, 6, 8105), + (1220, 8, 142, 65, 0), + (1220, 9, 311, 0, 0), + (1220, 10, 134, 70, 0), + (1220, 11, 348, 10, 0), + (1220, 12, 137, 100, 0), + (1220, 13, 339, 6, 8105), + (1220, 14, 142, 65, 0), + (1220, 15, 311, 0, 0), + (1220, 16, 134, 70, 0), + (1220, 17, 348, 10, 0), + (1220, 18, 137, 79, 0), + (1220, 19, 339, 6, 8105), + (1220, 20, 142, 65, 0), + (1220, 21, 311, 0, 0), + (1220, 22, 134, 70, 0), + (1220, 23, 348, 10, 0), + (1220, 24, 137, 147, 0), + (1221, 1, 339, 10, 8105), + (1221, 2, 142, 65, 0), + (1221, 3, 311, 0, 0), + (1221, 4, 134, 70, 0), + (1221, 5, 348, 10, 0), + (1221, 6, 137, 0, 0), + (1221, 7, 339, 10, 8105), + (1221, 8, 142, 65, 0), + (1221, 9, 311, 0, 0), + (1221, 10, 134, 70, 0), + (1221, 11, 348, 10, 0), + (1221, 12, 137, 100, 0), + (1221, 13, 339, 10, 8105), + (1221, 14, 142, 65, 0), + (1221, 15, 311, 0, 0), + (1221, 16, 134, 70, 0), + (1221, 17, 348, 10, 0), + (1221, 18, 137, 79, 0), + (1221, 19, 339, 10, 8105), + (1221, 20, 142, 65, 0), + (1221, 21, 311, 0, 0), + (1221, 22, 134, 70, 0), + (1221, 23, 348, 10, 0), + (1221, 24, 137, 147, 0), + (1230, 1, 313, 25, 0), + (1231, 1, 313, 50, 0), + (1232, 1, 313, 75, 0), + (1265, 1, 220, 40, 26), + (1265, 2, 220, 40, 30), + (1265, 3, 220, 40, 38), + (1266, 1, 220, 50, 26), + (1266, 2, 220, 50, 30), + (1266, 3, 220, 50, 38), + (1267, 1, 220, 60, 26), + (1267, 2, 220, 60, 30), + (1267, 3, 220, 60, 38), + (1268, 1, 292, 20, 0), + (1269, 1, 292, 25, 0), + (1270, 1, 292, 30, 0), + (1284, 1, 293, 15, 0), + (1285, 1, 293, 30, 0), + (1286, 1, 293, 50, 0), + (1287, 1, 320, 1, 0), + (1288, 1, 320, 3, 0), + (1289, 1, 320, 5, 0), + (1290, 1, 216, 40, 0), + (1290, 2, 216, 40, 1), + (1290, 3, 216, 40, 2), + (1290, 4, 216, 40, 3), + (1290, 5, 216, 40, 10), + (1290, 6, 216, 40, 28), + (1290, 7, 216, 40, 30), + (1290, 8, 216, 40, 36), + (1290, 9, 216, 40, 77), + (1291, 1, 216, 50, 0), + (1291, 2, 216, 50, 1), + (1291, 3, 216, 50, 2), + (1291, 4, 216, 50, 3), + (1291, 5, 216, 50, 10), + (1291, 6, 216, 50, 28), + (1291, 7, 216, 50, 30), + (1291, 8, 216, 50, 36), + (1291, 9, 216, 50, 77), + (1292, 1, 216, 60, 0), + (1292, 2, 216, 60, 1), + (1292, 3, 216, 60, 2), + (1292, 4, 216, 60, 3), + (1292, 5, 216, 60, 10), + (1292, 6, 216, 60, 28), + (1292, 7, 216, 60, 30), + (1292, 8, 216, 60, 36), + (1292, 9, 216, 60, 77), + (1296, 1, 247, 20, 53), + (1297, 1, 247, 40, 53), + (1298, 1, 247, 60, 53), + (1299, 1, 247, 80, 53), + (1300, 1, 247, 100, 53), + (1301, 1, 258, 20, 0), + (1302, 1, 258, 25, 0), + (1303, 1, 258, 30, 0), + (1304, 1, 216, 50, 8), + (1305, 1, 216, 100, 8), + (1306, 1, 216, 150, 8), + (1307, 1, 325, 10, 0), + (1308, 1, 325, 20, 0), + (1309, 1, 325, 30, 0), + (1310, 1, 325, 40, 0), + (1311, 1, 325, 50, 0), + (1313, 1, 85, 6037, 0), + (1314, 1, 85, 6038, 0), + (1315, 1, 85, 6039, 0), + (1316, 1, 302, 216, 216), + (1316, 2, 385, 99, 0), + (1317, 1, 302, 233, 233), + (1317, 2, 385, 99, 0), + (1318, 1, 302, 250, 250), + (1318, 2, 385, 99, 0), + (1319, 1, 274, 16, 0), + (1320, 1, 274, 18, 0), + (1321, 1, 274, 20, 0), + (1361, 1, 159, 10, 0), + (1361, 2, 262, 10, 0), + (1361, 3, 262, 10, 1), + (1361, 4, 262, 10, 2), + (1361, 5, 262, 10, 3), + (1361, 6, 262, 10, 4), + (1361, 7, 262, 10, 5), + (1361, 8, 262, 10, 6), + (1362, 1, 214, 300, 0), + (1362, 2, 97, 200, 0), + (1362, 3, 190, 200, 0), + (1363, 1, 327, 1, 0), + (1364, 1, 273, 1, 0), + (1364, 2, 274, 1, 0), + (1364, 3, 294, 1, 100), + (1364, 4, 169, 40, 0), + (1364, 5, 169, 40, 1), + (1364, 6, 169, 40, 2), + (1364, 7, 169, 40, 3), + (1364, 8, 169, 40, 8), + (1364, 9, 169, 40, 10), + (1364, 10, 169, 40, 26), + (1364, 11, 169, 40, 28), + (1364, 12, 169, 40, 30), + (1364, 13, 169, 40, 36), + (1364, 14, 169, 40, 74), + (1365, 1, 180, 2, 0), + (1366, 1, 159, 10, 0), + (1366, 2, 262, 10, 0), + (1366, 3, 262, 10, 1), + (1366, 4, 262, 10, 2), + (1366, 5, 262, 10, 3), + (1366, 6, 262, 10, 4), + (1366, 7, 262, 10, 5), + (1366, 8, 262, 10, 6), + (1367, 1, 214, 300, 0), + (1367, 2, 97, 200, 0), + (1367, 3, 190, 200, 0), + (1368, 1, 327, 1, 0), + (1369, 1, 273, 1, 0), + (1369, 2, 274, 1, 0), + (1369, 3, 294, 1, 100), + (1369, 4, 169, 40, 0), + (1369, 5, 169, 40, 1), + (1369, 6, 169, 40, 2), + (1369, 7, 169, 40, 3), + (1369, 8, 169, 40, 8), + (1369, 9, 169, 40, 10), + (1369, 10, 169, 40, 26), + (1369, 11, 169, 40, 28), + (1369, 12, 169, 40, 30), + (1369, 13, 169, 40, 36), + (1369, 14, 169, 40, 74), + (1370, 1, 180, 2, 0), + (1378, 1, 10, 0, 0), + (1379, 1, 10, 0, 0), + (1380, 1, 10, 0, 0), + (1382, 1, 10, 0, 0), + (1388, 2, 13, 1, 0), + (1389, 1, 328, 300, 0), + (1390, 1, 328, 350, 0), + (1391, 1, 328, 400, 0), + (1392, 1, 328, 450, 0), + (1393, 1, 328, 500, 0), + (1394, 1, 172, 33, 0), + (1395, 1, 172, 34, 0), + (1396, 1, 172, 35, 0), + (1397, 1, 172, 37, 0), + (1398, 1, 172, 39, 0), + (1399, 1, 259, 37, 0), + (1400, 1, 259, 39, 0), + (1401, 1, 259, 41, 0), + (1402, 1, 259, 43, 0), + (1403, 1, 259, 45, 0), + (1414, 1, 264, 432, 451), + (1415, 1, 264, 864, 451), + (1416, 1, 264, 1296, 451), + (1417, 1, 264, 1728, 451), + (1418, 1, 264, 2160, 451), + (1420, 1, 282, 20, 0), + (1421, 1, 282, 40, 0), + (1422, 1, 282, 60, 0), + (1423, 1, 282, 80, 0), + (1424, 1, 282, 100, 0), + (1430, 1, 280, 27, 0), + (1431, 1, 280, 34, 0), + (1432, 1, 280, 41, 0), + (1435, 1, 339, 3, 8105), + (1435, 2, 142, 65, 0), + (1435, 3, 311, 0, 0), + (1435, 4, 134, 70, 0), + (1435, 5, 348, 10, 0), + (1435, 6, 137, 0, 0), + (1435, 7, 339, 3, 8105), + (1435, 8, 142, 65, 0), + (1435, 9, 311, 0, 0), + (1435, 10, 134, 70, 0), + (1435, 11, 348, 10, 0), + (1435, 12, 137, 100, 0), + (1435, 13, 339, 3, 8105), + (1435, 14, 142, 65, 0), + (1435, 15, 311, 0, 0), + (1435, 16, 134, 70, 0), + (1435, 17, 348, 10, 0), + (1435, 18, 137, 79, 0), + (1435, 19, 339, 3, 8105), + (1435, 20, 142, 65, 0), + (1435, 21, 311, 0, 0), + (1435, 22, 134, 70, 0), + (1435, 23, 348, 10, 0), + (1435, 24, 137, 147, 0), + (1436, 1, 339, 6, 8105), + (1436, 2, 142, 65, 0), + (1436, 3, 311, 0, 0), + (1436, 4, 134, 70, 0), + (1436, 5, 348, 10, 0), + (1436, 6, 137, 0, 0), + (1436, 7, 339, 6, 8105), + (1436, 8, 142, 65, 0), + (1436, 9, 311, 0, 0), + (1436, 10, 134, 70, 0), + (1436, 11, 348, 10, 0), + (1436, 12, 137, 100, 0), + (1436, 13, 339, 6, 8105), + (1436, 14, 142, 65, 0), + (1436, 15, 311, 0, 0), + (1436, 16, 134, 70, 0), + (1436, 17, 348, 10, 0), + (1436, 18, 137, 79, 0), + (1436, 19, 339, 6, 8105), + (1436, 20, 142, 65, 0), + (1436, 21, 311, 0, 0), + (1436, 22, 134, 70, 0), + (1436, 23, 348, 10, 0), + (1436, 24, 137, 147, 0), + (1437, 1, 339, 10, 8105), + (1437, 2, 142, 65, 0), + (1437, 3, 311, 0, 0), + (1437, 4, 134, 70, 0), + (1437, 5, 348, 10, 0), + (1437, 6, 137, 0, 0), + (1437, 7, 339, 10, 8105), + (1437, 8, 142, 65, 0), + (1437, 9, 311, 0, 0), + (1437, 10, 134, 70, 0), + (1437, 11, 348, 10, 0), + (1437, 12, 137, 100, 0), + (1437, 13, 339, 10, 8105), + (1437, 14, 142, 65, 0), + (1437, 15, 311, 0, 0), + (1437, 16, 134, 70, 0), + (1437, 17, 348, 10, 0), + (1437, 18, 137, 79, 0), + (1437, 19, 339, 10, 8105), + (1437, 20, 142, 65, 0), + (1437, 21, 311, 0, 0), + (1437, 22, 134, 70, 0), + (1437, 23, 348, 10, 0), + (1437, 24, 137, 147, 0), + (1453, 1, 131, 10, 10), + (1453, 2, 137, 32, 0), + (1453, 3, 311, 1, 0), + (1454, 1, 131, 20, 20), + (1454, 2, 137, 32, 0), + (1454, 3, 311, 1, 0), + (1455, 1, 131, 30, 30), + (1455, 2, 137, 32, 0), + (1455, 3, 311, 1, 0), + (1456, 1, 131, 40, 40), + (1456, 2, 137, 32, 0), + (1456, 3, 311, 1, 0), + (1457, 1, 131, 50, 50), + (1457, 2, 137, 32, 0), + (1457, 3, 311, 1, 0), + (1467, 1, 280, 27, 0), + (1468, 1, 280, 34, 0), + (1469, 1, 280, 41, 0), + (1471, 1, 264, 90, 362), + (1472, 1, 264, 180, 362), + (1473, 1, 264, 270, 362), + (1474, 1, 264, 360, 362), + (1475, 1, 264, 450, 362), + (1483, 1, 294, 0, 133), + (1484, 1, 294, 0, 141), + (1485, 1, 294, 0, 150), + (1486, 1, 339, 1, 8165), + (1486, 2, 138, 1, 0), + (1486, 3, 141, 1, 0), + (1486, 4, 142, 60, 0), + (1486, 5, 137, 0, 0), + (1486, 6, 311, 0, 0), + (1486, 7, 134, 75, 0), + (1486, 8, 139, -265, 0), + (1486, 9, 139, -754, 0), + (1486, 10, 139, -1332, 0), + (1486, 11, 139, -1572, 0), + (1486, 12, 139, -2749, 0), + (1486, 13, 139, -4979, 0), + (1486, 14, 139, -5418, 0), + (1486, 15, 139, -5403, 0), + (1486, 16, 348, 10, 0), + (1487, 1, 339, 3, 8166), + (1487, 2, 138, 1, 0), + (1487, 3, 141, 1, 0), + (1487, 4, 142, 60, 0), + (1487, 5, 137, 0, 0), + (1487, 6, 311, 0, 0), + (1487, 7, 134, 75, 0), + (1487, 8, 139, -265, 0), + (1487, 9, 139, -754, 0), + (1487, 10, 139, -1332, 0), + (1487, 11, 139, -1572, 0), + (1487, 12, 139, -2749, 0), + (1487, 13, 139, -4979, 0), + (1487, 14, 139, -5418, 0), + (1487, 15, 139, -5403, 0), + (1487, 16, 348, 10, 0), + (1488, 1, 339, 5, 8167), + (1488, 2, 138, 1, 0), + (1488, 3, 141, 1, 0), + (1488, 4, 142, 60, 0), + (1488, 5, 137, 0, 0), + (1488, 6, 311, 0, 0), + (1488, 7, 134, 75, 0), + (1488, 8, 139, -265, 0), + (1488, 9, 139, -754, 0), + (1488, 10, 139, -1332, 0), + (1488, 11, 139, -1572, 0), + (1488, 12, 139, -2749, 0), + (1488, 13, 139, -4979, 0), + (1488, 14, 139, -5418, 0), + (1488, 15, 139, -5403, 0), + (1488, 16, 348, 10, 0), + (1489, 1, 339, 7, 8168), + (1489, 2, 138, 1, 0), + (1489, 3, 141, 1, 0), + (1489, 4, 142, 60, 0), + (1489, 5, 137, 0, 0), + (1489, 6, 311, 0, 0), + (1489, 7, 134, 75, 0), + (1489, 8, 139, -265, 0), + (1489, 9, 139, -754, 0), + (1489, 10, 139, -1332, 0), + (1489, 11, 139, -1572, 0), + (1489, 12, 139, -2749, 0), + (1489, 13, 139, -4979, 0), + (1489, 14, 139, -5418, 0), + (1489, 15, 139, -5403, 0), + (1489, 16, 348, 10, 0), + (1490, 1, 339, 9, 8169), + (1490, 2, 138, 1, 0), + (1490, 3, 141, 1, 0), + (1490, 4, 142, 60, 0), + (1490, 5, 137, 0, 0), + (1490, 6, 311, 0, 0), + (1490, 7, 134, 75, 0), + (1490, 8, 139, -265, 0), + (1490, 9, 139, -754, 0), + (1490, 10, 139, -1332, 0), + (1490, 11, 139, -1572, 0), + (1490, 12, 139, -2749, 0), + (1490, 13, 139, -4979, 0), + (1490, 14, 139, -5418, 0), + (1490, 15, 139, -5403, 0), + (1490, 16, 348, 10, 0), + (1504, 1, 287, 2, 0), + (1504, 2, 385, 2754, 1), + (1505, 1, 287, 4, 0), + (1505, 2, 385, 2754, 1), + (1506, 1, 287, 6, 0), + (1506, 2, 385, 2754, 1), + (1511, 1, 264, 60, 175), + (1511, 2, 264, 60, 792), + (1512, 1, 264, 120, 175), + (1512, 2, 264, 120, 792), + (1513, 1, 264, 180, 175), + (1513, 2, 264, 180, 792), + (1514, 1, 273, 2, 0), + (1515, 1, 273, 4, 0), + (1516, 1, 273, 6, 0), + (1524, 1, 219, 260, 1800), + (1525, 1, 219, 300, 2000), + (1526, 1, 219, 280, 1900), + (1528, 1, 239, 30, 0), + (1529, 1, 239, 35, 0), + (1530, 1, 239, 40, 0), + (1531, 1, 239, 45, 0), + (1532, 1, 239, 50, 0), + (1533, 1, 266, 11, 0), + (1534, 1, 266, 14, 0), + (1535, 1, 266, 17, 0), + (1536, 1, 266, 11, 0), + (1537, 1, 266, 14, 0), + (1538, 1, 266, 17, 0), + (1539, 1, 252, 37, 0), + (1540, 1, 252, 44, 0), + (1541, 1, 252, 50, 0), + (1543, 1, 220, 10, 8), + (1544, 1, 220, 20, 8), + (1545, 1, 220, 30, 8), + (1546, 1, 264, 120, 420), + (1547, 1, 264, 240, 420), + (1548, 1, 264, 360, 420), + (1549, 1, 293, 25, 0), + (1550, 1, 293, 50, 0), + (1551, 1, 293, 75, 0), + (1552, 1, 271, 5, 0), + (1553, 1, 271, 10, 0), + (1554, 1, 271, 15, 0), + (1555, 1, 264, 240, 359), + (1556, 1, 264, 480, 359), + (1557, 1, 264, 720, 359), + (1563, 1, 225, 18, 0), + (1564, 1, 225, 21, 0), + (1565, 1, 225, 24, 0), + (1566, 1, 225, 27, 0), + (1567, 1, 225, 30, 0), + (1572, 1, 339, 2, 8261), + (1572, 2, 138, 0, 0), + (1572, 3, 137, 31, 0), + (1572, 4, 311, 0, 0), + (1573, 1, 339, 4, 8262), + (1573, 2, 138, 0, 0), + (1573, 3, 137, 31, 0), + (1573, 4, 311, 0, 0), + (1574, 1, 339, 6, 8263), + (1574, 2, 138, 0, 0), + (1574, 3, 137, 31, 0), + (1574, 4, 311, 0, 0), + (1575, 1, 339, 8, 8264), + (1575, 2, 138, 0, 0), + (1575, 3, 137, 31, 0), + (1575, 4, 311, 0, 0), + (1576, 1, 339, 10, 8265), + (1576, 2, 138, 0, 0), + (1576, 3, 137, 31, 0), + (1576, 4, 311, 0, 0), + (1577, 1, 274, 3, 0), + (1578, 1, 274, 6, 0), + (1579, 1, 274, 10, 0), + (1583, 1, 264, 360, 300), + (1584, 1, 264, 720, 300), + (1585, 1, 264, 1080, 300), + (1586, 1, 264, 1440, 300), + (1587, 1, 264, 1800, 300), + (1588, 1, 344, 50, 0), + (1589, 1, 344, 100, 0), + (1590, 1, 344, 150, 0), + (1591, 1, 293, 25, 0), + (1592, 1, 341, 10, 0), + (1593, 1, 341, 20, 0), + (1594, 1, 341, 30, 0), + (1595, 1, 341, 40, 0), + (1596, 1, 341, 50, 0), + (1601, 1, 217, 0, 35200), + (1601, 2, 346, 60, 0), + (1602, 1, 217, 0, 42440), + (1602, 2, 346, 62, 0), + (1603, 1, 217, 0, 46480), + (1603, 2, 346, 64, 0), + (1604, 1, 439, 0, 32000), + (1604, 2, 345, 59, 0), + (1605, 1, 439, 0, 35200), + (1605, 2, 345, 60, 0), + (1606, 1, 439, 0, 42440), + (1606, 2, 345, 61, 0), + (1608, 1, 347, 2, 0), + (1609, 1, 347, 4, 0), + (1610, 1, 347, 6, 0), + (1611, 1, 282, 20, 0), + (1612, 1, 282, 40, 0), + (1613, 1, 282, 60, 0), + (1614, 1, 282, 80, 0), + (1615, 1, 282, 100, 0), + (1616, 1, 279, 7, 0), + (1617, 1, 279, 11, 0), + (1618, 1, 279, 15, 0), + (1619, 1, 279, 17, 0), + (1620, 1, 279, 19, 0), + (1621, 1, 177, 20, -1), + (1622, 1, 177, 22, -1), + (1623, 1, 177, 24, -1), + (1624, 1, 177, 20, -1), + (1625, 1, 177, 22, -1), + (1626, 1, 177, 24, -1), + (1627, 1, 271, 5, 0), + (1628, 1, 271, 10, 0), + (1629, 1, 271, 15, 0), + (1633, 1, 225, 18, 0), + (1634, 1, 225, 21, 0), + (1635, 1, 225, 24, 0), + (1636, 1, 225, 27, 0), + (1637, 1, 225, 30, 0), + (1641, 1, 359, 100, 0), + (1642, 1, 359, 60, 0), + (1648, 1, 339, 10, 8105), + (1648, 2, 142, 65, 0), + (1648, 3, 311, 0, 0), + (1648, 4, 134, 70, 0), + (1648, 5, 348, 10, 0), + (1648, 6, 137, 0, 0), + (1648, 7, 339, 10, 8105), + (1648, 8, 142, 65, 0), + (1648, 9, 311, 0, 0), + (1648, 10, 134, 70, 0), + (1648, 11, 348, 10, 0), + (1648, 12, 137, 100, 0), + (1648, 13, 339, 10, 8105), + (1648, 14, 142, 65, 0), + (1648, 15, 311, 0, 0), + (1648, 16, 134, 70, 0), + (1648, 17, 348, 10, 0), + (1648, 18, 137, 79, 0), + (1648, 19, 339, 10, 8105), + (1648, 20, 142, 65, 0), + (1648, 21, 311, 0, 0), + (1648, 22, 134, 70, 0), + (1648, 23, 348, 10, 0), + (1648, 24, 137, 147, 0), + (1648, 25, 339, 10, 11404), + (1648, 26, 142, 71, 0), + (1648, 27, 311, 0, 0), + (1648, 28, 134, 75, 0), + (1648, 29, 348, 10, 0), + (1648, 30, 137, 0, 0), + (1648, 31, 339, 10, 11404), + (1648, 32, 142, 71, 0), + (1648, 33, 311, 0, 0), + (1648, 34, 134, 75, 0), + (1648, 35, 348, 10, 0), + (1648, 36, 137, 100, 0), + (1648, 37, 339, 10, 11404), + (1648, 38, 142, 71, 0), + (1648, 39, 311, 0, 0), + (1648, 40, 134, 75, 0), + (1648, 41, 348, 10, 0), + (1648, 42, 137, 79, 0), + (1648, 43, 339, 10, 11404), + (1648, 44, 142, 71, 0), + (1648, 45, 311, 0, 0), + (1648, 46, 134, 75, 0), + (1648, 47, 348, 10, 0), + (1648, 48, 137, 147, 0), + (1649, 1, 339, 10, 8105), + (1649, 2, 142, 65, 0), + (1649, 3, 311, 0, 0), + (1649, 4, 134, 70, 0), + (1649, 5, 348, 10, 0), + (1649, 6, 137, 0, 0), + (1649, 7, 339, 10, 8105), + (1649, 8, 142, 65, 0), + (1649, 9, 311, 0, 0), + (1649, 10, 134, 70, 0), + (1649, 11, 348, 10, 0), + (1649, 12, 137, 100, 0), + (1649, 13, 339, 10, 8105), + (1649, 14, 142, 65, 0), + (1649, 15, 311, 0, 0), + (1649, 16, 134, 70, 0), + (1649, 17, 348, 10, 0), + (1649, 18, 137, 79, 0), + (1649, 19, 339, 10, 8105), + (1649, 20, 142, 65, 0), + (1649, 21, 311, 0, 0), + (1649, 22, 134, 70, 0), + (1649, 23, 348, 10, 0), + (1649, 24, 137, 147, 0), + (1649, 25, 339, 10, 11404), + (1649, 26, 142, 71, 0), + (1649, 27, 311, 0, 0), + (1649, 28, 134, 75, 0), + (1649, 29, 348, 10, 0), + (1649, 30, 137, 0, 0), + (1649, 31, 339, 10, 11404), + (1649, 32, 142, 71, 0), + (1649, 33, 311, 0, 0), + (1649, 34, 134, 75, 0), + (1649, 35, 348, 10, 0), + (1649, 36, 137, 100, 0), + (1649, 37, 339, 10, 11404), + (1649, 38, 142, 71, 0), + (1649, 39, 311, 0, 0), + (1649, 40, 134, 75, 0), + (1649, 41, 348, 10, 0), + (1649, 42, 137, 79, 0), + (1649, 43, 339, 10, 11404), + (1649, 44, 142, 71, 0), + (1649, 45, 311, 0, 0), + (1649, 46, 134, 75, 0), + (1649, 47, 348, 10, 0), + (1649, 48, 137, 147, 0), + (1649, 49, 339, 10, 13199), + (1649, 50, 142, 76, 0), + (1649, 51, 311, 0, 0), + (1649, 52, 134, 80, 0), + (1649, 53, 348, 10, 0), + (1649, 54, 137, 0, 0), + (1649, 55, 339, 10, 13199), + (1649, 56, 142, 76, 0), + (1649, 57, 311, 0, 0), + (1649, 58, 134, 80, 0), + (1649, 59, 348, 10, 0), + (1649, 60, 137, 100, 0), + (1649, 61, 339, 10, 13199), + (1649, 62, 142, 76, 0), + (1649, 63, 311, 0, 0), + (1649, 64, 134, 80, 0), + (1649, 65, 348, 10, 0), + (1649, 66, 137, 79, 0), + (1649, 67, 339, 10, 13199), + (1649, 68, 142, 76, 0), + (1649, 69, 311, 0, 0), + (1649, 70, 134, 80, 0), + (1649, 71, 348, 10, 0), + (1649, 72, 137, 147, 0), + (1650, 1, 339, 10, 8105), + (1650, 2, 142, 65, 0), + (1650, 3, 311, 0, 0), + (1650, 4, 134, 70, 0), + (1650, 5, 348, 10, 0), + (1650, 6, 137, 0, 0), + (1650, 7, 339, 10, 8105), + (1650, 8, 142, 65, 0), + (1650, 9, 311, 0, 0), + (1650, 10, 134, 70, 0), + (1650, 11, 348, 10, 0), + (1650, 12, 137, 100, 0), + (1650, 13, 339, 10, 8105), + (1650, 14, 142, 65, 0), + (1650, 15, 311, 0, 0), + (1650, 16, 134, 70, 0), + (1650, 17, 348, 10, 0), + (1650, 18, 137, 79, 0), + (1650, 19, 339, 10, 8105), + (1650, 20, 142, 65, 0), + (1650, 21, 311, 0, 0), + (1650, 22, 134, 70, 0), + (1650, 23, 348, 10, 0), + (1650, 24, 137, 147, 0), + (1650, 25, 339, 10, 11404), + (1650, 26, 142, 71, 0), + (1650, 27, 311, 0, 0), + (1650, 28, 134, 75, 0), + (1650, 29, 348, 10, 0), + (1650, 30, 137, 0, 0), + (1650, 31, 339, 10, 11404), + (1650, 32, 142, 71, 0), + (1650, 33, 311, 0, 0), + (1650, 34, 134, 75, 0), + (1650, 35, 348, 10, 0), + (1650, 36, 137, 100, 0), + (1650, 37, 339, 10, 11404), + (1650, 38, 142, 71, 0), + (1650, 39, 311, 0, 0), + (1650, 40, 134, 75, 0), + (1650, 41, 348, 10, 0), + (1650, 42, 137, 79, 0), + (1650, 43, 339, 10, 11404), + (1650, 44, 142, 71, 0), + (1650, 45, 311, 0, 0), + (1650, 46, 134, 75, 0), + (1650, 47, 348, 10, 0), + (1650, 48, 137, 147, 0), + (1650, 49, 339, 10, 13199), + (1650, 50, 142, 76, 0), + (1650, 51, 311, 0, 0), + (1650, 52, 134, 80, 0), + (1650, 53, 348, 10, 0), + (1650, 54, 137, 0, 0), + (1650, 55, 339, 10, 13199), + (1650, 56, 142, 76, 0), + (1650, 57, 311, 0, 0), + (1650, 58, 134, 80, 0), + (1650, 59, 348, 10, 0), + (1650, 60, 137, 100, 0), + (1650, 61, 339, 10, 13199), + (1650, 62, 142, 76, 0), + (1650, 63, 311, 0, 0), + (1650, 64, 134, 80, 0), + (1650, 65, 348, 10, 0), + (1650, 66, 137, 79, 0), + (1650, 67, 339, 10, 13199), + (1650, 68, 142, 76, 0), + (1650, 69, 311, 0, 0), + (1650, 70, 134, 80, 0), + (1650, 71, 348, 10, 0), + (1650, 72, 137, 147, 0), + (1650, 73, 339, 10, 13830), + (1650, 74, 142, 81, 0), + (1650, 75, 311, 0, 0), + (1650, 76, 134, 85, 0), + (1650, 77, 348, 10, 0), + (1650, 78, 137, 0, 0), + (1650, 79, 339, 10, 13830), + (1650, 80, 142, 81, 0), + (1650, 81, 311, 0, 0), + (1650, 82, 134, 85, 0), + (1650, 83, 348, 10, 0), + (1650, 84, 137, 100, 0), + (1650, 85, 339, 10, 13830), + (1650, 86, 142, 81, 0), + (1650, 87, 311, 0, 0), + (1650, 88, 134, 85, 0), + (1650, 89, 348, 10, 0), + (1650, 90, 137, 79, 0), + (1650, 91, 339, 10, 13830), + (1650, 92, 142, 81, 0), + (1650, 93, 311, 0, 0), + (1650, 94, 134, 85, 0), + (1650, 95, 348, 10, 0), + (1650, 96, 137, 147, 0), + (1651, 1, 97, 300, 0), + (1652, 1, 97, 350, 0), + (1653, 1, 97, 400, 0), + (1654, 1, 97, 450, 0), + (1655, 1, 97, 500, 0), + (1656, 1, 127, 40, 0), + (1656, 2, 137, 154, 0), + (1656, 3, 403, 2, 0), + (1656, 4, 404, 10, 0), + (1657, 1, 127, 50, 0), + (1657, 2, 137, 154, 0), + (1657, 3, 403, 2, 0), + (1657, 4, 404, 10, 0), + (1659, 1, 127, 40, 0), + (1659, 2, 137, 154, 0), + (1659, 3, 403, 2, 0), + (1659, 4, 404, 10, 0), + (1660, 1, 127, 50, 0), + (1660, 2, 137, 154, 0), + (1660, 3, 403, 2, 0), + (1660, 4, 404, 10, 0), + (1662, 1, 370, 2, 0), + (1663, 1, 370, 4, 0), + (1664, 1, 370, 6, 0), + (1665, 1, 370, 8, 0), + (1666, 1, 370, 10, 0), + (2400, 1, 264, 90, 38), + (2401, 1, 264, 180, 38), + (2402, 1, 264, 270, 38), + (4666, 0, 366, 10, 50), + (4666, 1, 349, 5, 0), + (4667, 0, 366, 30, 50), + (4667, 1, 349, 10, 0), + (4668, 0, 366, 60, 50), + (4668, 1, 349, 15, 0), + (4669, 0, 366, 10, 500), + (4669, 1, 349, 20, 0), + (4670, 0, 366, 30, 500), + (4670, 1, 349, 25, 0), + (4672, 1, 268, 10, 57), + (4673, 1, 268, 25, 57), + (4674, 1, 268, 50, 57), + (4675, 1, 268, 10, 68), + (4676, 1, 268, 25, 68), + (4677, 1, 268, 50, 68), + (4678, 1, 262, 55, 0), + (4678, 2, 262, 55, 1), + (4678, 3, 262, 55, 2), + (4678, 4, 262, 55, 3), + (4678, 5, 262, 55, 4), + (4678, 6, 262, 55, 5), + (4678, 7, 262, 55, 6), + (4679, 1, 262, 60, 0), + (4679, 2, 262, 60, 1), + (4679, 3, 262, 60, 2), + (4679, 4, 262, 60, 3), + (4679, 5, 262, 60, 4), + (4679, 6, 262, 60, 5), + (4679, 7, 262, 60, 6), + (4680, 1, 262, 65, 0), + (4680, 2, 262, 65, 1), + (4680, 3, 262, 65, 2), + (4680, 4, 262, 65, 3), + (4680, 5, 262, 65, 4), + (4680, 6, 262, 65, 5), + (4680, 7, 262, 65, 6), + (4681, 1, 262, 70, 0), + (4681, 2, 262, 70, 1), + (4681, 3, 262, 70, 2), + (4681, 4, 262, 70, 3), + (4681, 5, 262, 70, 4), + (4681, 6, 262, 70, 5), + (4681, 7, 262, 70, 6), + (4682, 1, 262, 75, 0), + (4682, 2, 262, 75, 1), + (4682, 3, 262, 75, 2), + (4682, 4, 262, 75, 3), + (4682, 5, 262, 75, 4), + (4682, 6, 262, 75, 5), + (4682, 7, 262, 75, 6), + (4683, 1, 328, 550, 0), + (4684, 1, 328, 600, 0), + (4685, 1, 328, 650, 0), + (4686, 1, 328, 700, 0), + (4687, 1, 328, 750, 0), + (4688, 1, 282, 20, 0), + (4689, 1, 282, 40, 0), + (4690, 1, 282, 60, 0), + (4691, 1, 282, 80, 0), + (4692, 1, 282, 100, 0), + (4693, 1, 0, 11, 0), + (4694, 1, 0, 12, 0), + (4695, 1, 0, 13, 0), + (4696, 1, 0, 14, 0), + (4697, 1, 0, 15, 0), + (4698, 1, 362, 1, 0), + (4699, 1, 363, 1, 0), + (4707, 1, 330, 85, 0), + (4707, 2, 330, 85, 1), + (4707, 3, 330, 85, 2), + (4707, 4, 330, 85, 3), + (4707, 5, 330, 85, 28), + (4707, 6, 330, 85, 36), + (4707, 7, 330, 85, 77), + (4708, 1, 330, 95, 0), + (4708, 2, 330, 95, 1), + (4708, 3, 330, 95, 2), + (4708, 4, 330, 95, 3), + (4708, 5, 330, 95, 28), + (4708, 6, 330, 95, 36), + (4708, 7, 330, 95, 77), + (4709, 1, 330, 105, 0), + (4709, 2, 330, 105, 1), + (4709, 3, 330, 105, 2), + (4709, 4, 330, 105, 3), + (4709, 5, 330, 105, 28), + (4709, 6, 330, 105, 36), + (4709, 7, 330, 105, 77), + (4710, 1, 330, 85, 0), + (4710, 2, 330, 85, 1), + (4710, 3, 330, 85, 2), + (4710, 4, 330, 85, 3), + (4710, 5, 330, 85, 28), + (4710, 6, 330, 85, 36), + (4711, 1, 330, 95, 0), + (4711, 2, 330, 95, 1), + (4711, 3, 330, 95, 2), + (4711, 4, 330, 95, 3), + (4711, 5, 330, 95, 28), + (4711, 6, 330, 95, 36), + (4712, 1, 330, 105, 0), + (4712, 2, 330, 105, 1), + (4712, 3, 330, 105, 2), + (4712, 4, 330, 105, 3), + (4712, 5, 330, 105, 28), + (4712, 6, 330, 105, 36), + (4713, 1, 330, 85, 0), + (4713, 2, 330, 85, 1), + (4713, 3, 330, 85, 2), + (4713, 4, 330, 85, 3), + (4713, 5, 330, 85, 28), + (4713, 6, 330, 85, 36), + (4713, 7, 330, 85, 77), + (4714, 1, 330, 95, 0), + (4714, 2, 330, 95, 1), + (4714, 3, 330, 95, 2), + (4714, 4, 330, 95, 3), + (4714, 5, 330, 95, 28), + (4714, 6, 330, 95, 36), + (4714, 7, 330, 95, 77), + (4715, 1, 330, 105, 0), + (4715, 2, 330, 105, 1), + (4715, 3, 330, 105, 2), + (4715, 4, 330, 105, 3), + (4715, 5, 330, 105, 28), + (4715, 6, 330, 105, 36), + (4715, 7, 330, 105, 77), + (4716, 1, 330, 60, 0), + (4716, 2, 330, 60, 1), + (4716, 3, 330, 60, 2), + (4716, 4, 330, 60, 3), + (4716, 5, 330, 60, 28), + (4716, 6, 330, 60, 36), + (4716, 7, 330, 60, 77), + (4717, 1, 330, 70, 0), + (4717, 2, 330, 70, 1), + (4717, 3, 330, 70, 2), + (4717, 4, 330, 70, 3), + (4717, 5, 330, 70, 28), + (4717, 6, 330, 70, 36), + (4717, 7, 330, 70, 77), + (4718, 1, 330, 80, 0), + (4718, 2, 330, 80, 1), + (4718, 3, 330, 80, 2), + (4718, 4, 330, 80, 3), + (4718, 5, 330, 80, 28), + (4718, 6, 330, 80, 36), + (4718, 7, 330, 80, 77), + (4722, 1, 278, 620, 35216), + (4722, 2, 440, 66, 100), + (4723, 1, 278, 650, 38310), + (4723, 2, 440, 68, 100), + (4724, 1, 278, 670, 41300), + (4724, 2, 440, 70, 100), + (4725, 1, 341, 60, 0), + (4726, 1, 341, 70, 0), + (4727, 1, 341, 80, 0), + (4728, 1, 341, 90, 0), + (4729, 1, 341, 100, 0), + (4733, 1, 294, 11, 100), + (4734, 1, 294, 13, 100), + (4735, 1, 294, 15, 100), + (4739, 1, 360, 10, 11023), + (4740, 1, 360, 20, 11023), + (4741, 1, 360, 30, 11023), + (4744, 1, 318, 6, 0), + (4745, 1, 318, 7, 0), + (4746, 1, 318, 8, 0), + (4747, 1, 318, 9, 0), + (4748, 1, 318, 10, 0), + (4749, 1, 294, 11, 100), + (4750, 1, 294, 13, 100), + (4751, 1, 294, 15, 100), + (4752, 1, 294, 0, 155), + (4753, 1, 294, 0, 160), + (4754, 1, 294, 0, 165), + (4755, 1, 294, 0, 130), + (4756, 1, 294, 0, 135), + (4757, 1, 294, 0, 140), + (4758, 1, 266, 27, 0), + (4759, 1, 266, 28, 0), + (4760, 1, 266, 29, 0), + (4761, 1, 273, 2, 0), + (4762, 1, 273, 3, 0), + (4763, 1, 273, 4, 0), + (4764, 1, 326, 2, 0), + (4767, 1, 114, -43, 0), + (4768, 1, 114, -46, 0), + (4769, 1, 114, -50, 0), + (4773, 1, 339, 10, 8105), + (4773, 2, 142, 65, 0), + (4773, 3, 311, 0, 0), + (4773, 4, 134, 70, 0), + (4773, 5, 348, 10, 0), + (4773, 6, 137, 0, 0), + (4773, 7, 339, 10, 8105), + (4773, 8, 142, 65, 0), + (4773, 9, 311, 0, 0), + (4773, 10, 134, 70, 0), + (4773, 11, 348, 10, 0), + (4773, 12, 137, 100, 0), + (4773, 13, 339, 10, 8105), + (4773, 14, 142, 65, 0), + (4773, 15, 311, 0, 0), + (4773, 16, 134, 70, 0), + (4773, 17, 348, 10, 0), + (4773, 18, 137, 79, 0), + (4773, 19, 339, 10, 8105), + (4773, 20, 142, 65, 0), + (4773, 21, 311, 0, 0), + (4773, 22, 134, 70, 0), + (4773, 23, 348, 10, 0), + (4773, 24, 137, 147, 0), + (4773, 25, 339, 10, 11404), + (4773, 26, 142, 71, 0), + (4773, 27, 311, 0, 0), + (4773, 28, 134, 75, 0), + (4773, 29, 348, 10, 0), + (4773, 30, 137, 0, 0), + (4773, 31, 339, 10, 11404), + (4773, 32, 142, 71, 0), + (4773, 33, 311, 0, 0), + (4773, 34, 134, 75, 0), + (4773, 35, 348, 10, 0), + (4773, 36, 137, 100, 0), + (4773, 37, 339, 10, 11404), + (4773, 38, 142, 71, 0), + (4773, 39, 311, 0, 0), + (4773, 40, 134, 75, 0), + (4773, 41, 348, 10, 0), + (4773, 42, 137, 79, 0), + (4773, 43, 339, 10, 11404), + (4773, 44, 142, 71, 0), + (4773, 45, 311, 0, 0), + (4773, 46, 134, 75, 0), + (4773, 47, 348, 10, 0), + (4773, 48, 137, 147, 0), + (4776, 1, 319, 12, 0), + (4777, 1, 319, 14, 0), + (4778, 1, 319, 16, 0), + (4779, 1, 274, 24, 0), + (4780, 1, 274, 26, 0), + (4781, 1, 274, 28, 0), + (4790, 1, 220, 288, 74), + (4791, 1, 220, 320, 74), + (4792, 1, 220, 352, 74), + (4793, 1, 220, 384, 74), + (4794, 1, 220, 416, 74), + (4795, 1, 279, 28, 0), + (4796, 1, 279, 29, 0), + (4797, 1, 279, 30, 0), + (4798, 1, 292, 65, 0), + (4799, 1, 292, 70, 0), + (4800, 1, 292, 75, 0), + (4801, 1, 227, 30, 32), + (4802, 1, 227, 60, 32), + (4803, 1, 227, 90, 32), + (4804, 1, 220, 448, 74), + (4805, 1, 220, 480, 74), + (4806, 1, 220, 512, 74), + (4807, 1, 220, 544, 74), + (4808, 1, 220, 576, 74), + (4809, 1, 216, 40, 74), + (4810, 1, 216, 80, 74), + (4811, 1, 216, 120, 74), + (4813, 1, 220, 70, 26), + (4813, 2, 220, 70, 30), + (4813, 3, 220, 70, 38), + (4814, 1, 220, 80, 26), + (4814, 2, 220, 80, 30), + (4814, 3, 220, 80, 38), + (4815, 1, 220, 90, 26), + (4815, 2, 220, 90, 30), + (4815, 3, 220, 90, 38), + (4819, 1, 239, 52, 0), + (4820, 1, 239, 54, 0), + (4821, 1, 239, 56, 0), + (4822, 1, 239, 58, 0), + (4823, 1, 239, 60, 0), + (4824, 1, 239, 52, 0), + (4825, 1, 239, 54, 0), + (4826, 1, 239, 56, 0), + (4827, 1, 239, 58, 0), + (4828, 1, 239, 60, 0), + (4829, 1, 264, 480, 420), + (4830, 1, 264, 600, 420), + (4831, 1, 264, 720, 420), + (4844, 1, 349, 5, 0), + (4845, 1, 349, 10, 0), + (4846, 1, 349, 15, 0), + (4847, 1, 349, 20, 0), + (4848, 1, 349, 25, 0), + (4861, 1, 264, 600, 68), + (4862, 1, 264, 1200, 68), + (4863, 1, 264, 1800, 68), + (4887, 1, 264, 120, 413), + (4888, 1, 264, 240, 413), + (4889, 1, 264, 360, 413), + (4897, 1, 280, 44, 0), + (4898, 1, 280, 47, 0), + (4899, 1, 280, 50, 0), + (4921, 1, 264, 1896, 117), + (4921, 2, 244, 75, 0), + (4922, 1, 264, 2496, 117), + (4922, 2, 244, 60, 0), + (4923, 1, 264, 3096, 117), + (4923, 2, 244, 45, 0), + (4924, 1, 273, 1, 0), + (4925, 1, 273, 2, 0), + (4926, 1, 273, 3, 0), + (4948, 1, 258, 35, 0), + (4949, 1, 258, 40, 0), + (4950, 1, 258, 45, 0), + (4951, 1, 220, 40, 8), + (4952, 1, 220, 50, 8), + (4953, 1, 220, 60, 8), + (4957, 1, 252, 55, 0), + (4958, 1, 252, 60, 0), + (4959, 1, 252, 65, 0), + (4960, 1, 280, 46, 0), + (4961, 1, 280, 51, 0), + (4962, 1, 280, 56, 0), + (4983, 1, 216, 65, 0), + (4983, 2, 216, 65, 1), + (4983, 3, 216, 65, 2), + (4983, 4, 216, 65, 3), + (4983, 5, 216, 65, 10), + (4983, 6, 216, 65, 28), + (4983, 7, 216, 65, 30), + (4983, 8, 216, 65, 36), + (4983, 9, 216, 65, 77), + (4984, 1, 216, 70, 0), + (4984, 2, 216, 70, 1), + (4984, 3, 216, 70, 2), + (4984, 4, 216, 70, 3), + (4984, 5, 216, 70, 10), + (4984, 6, 216, 70, 28), + (4984, 7, 216, 70, 30), + (4984, 8, 216, 70, 36), + (4984, 9, 216, 70, 77), + (4985, 1, 216, 75, 0), + (4985, 2, 216, 75, 1), + (4985, 3, 216, 75, 2), + (4985, 4, 216, 75, 3), + (4985, 5, 216, 75, 10), + (4985, 6, 216, 75, 28), + (4985, 7, 216, 75, 30), + (4985, 8, 216, 75, 36), + (4985, 9, 216, 75, 77), + (4986, 1, 217, 0, 52960), + (4986, 2, 346, 66, 40), + (4987, 1, 217, 0, 55400), + (4987, 2, 346, 68, 40), + (4988, 1, 217, 0, 60280), + (4988, 2, 346, 70, 40), + (4989, 1, 347, 8, 0), + (4990, 1, 347, 10, 0), + (4991, 1, 347, 12, 0), + (4992, 1, 279, 21, 0), + (4993, 1, 279, 23, 0), + (4994, 1, 279, 25, 0), + (4995, 1, 279, 27, 0), + (4996, 1, 279, 28, 0), + (5000, 1, 313, 80, 0), + (5001, 1, 313, 90, 0), + (5002, 1, 313, 100, 0), + (5010, 1, 264, 432, 35), + (5011, 1, 264, 864, 35), + (5012, 1, 264, 1296, 35), + (5013, 1, 293, 90, 0), + (5014, 1, 293, 100, 0), + (5029, 1, 85, 11621, 0), + (5030, 1, 85, 11622, 0), + (5031, 1, 85, 11623, 0), + (5032, 1, 274, 22, 0), + (5033, 1, 274, 24, 0), + (5034, 1, 274, 26, 0), + (5035, 1, 293, 60, 0), + (5036, 1, 293, 70, 0), + (5037, 1, 293, 80, 0), + (5038, 1, 219, 330, 2100), + (5039, 1, 219, 360, 2200), + (5040, 1, 219, 390, 2300), + (5045, 1, 180, 5, 0), + (5061, 1, 244, -25, 0), + (5085, 1, 360, 25, 11297), + (5086, 1, 360, 25, 11298), + (5087, 1, 360, 25, 11299), + (5118, 1, 264, 720, 396), + (5118, 2, 264, 720, 8504), + (5118, 3, 264, 720, 8505), + (5119, 1, 264, 1440, 396), + (5119, 2, 264, 1440, 8504), + (5119, 3, 264, 1440, 8505), + (5120, 1, 264, 2160, 396), + (5120, 2, 264, 2160, 8504), + (5120, 3, 264, 2160, 8505), + (5127, 1, 264, 300, 261), + (5128, 1, 264, 600, 261), + (5129, 1, 264, 900, 261), + (5133, 1, 294, 13, 100), + (5134, 1, 294, 15, 100), + (5135, 1, 294, 17, 100), + (5136, 1, 282, 20, 0), + (5137, 1, 282, 40, 0), + (5138, 1, 282, 60, 0), + (5139, 1, 282, 80, 0), + (5140, 1, 282, 100, 0), + (5141, 1, 279, 21, 0), + (5142, 1, 279, 23, 0), + (5143, 1, 279, 25, 0), + (5144, 1, 279, 27, 0), + (5145, 1, 279, 28, 0), + (5243, 1, 69, 600, 0), + (5244, 1, 69, 700, 0), + (5245, 1, 69, 800, 0), + (5246, 1, 69, 900, 0), + (5247, 1, 69, 1000, 0), + (5248, 1, 360, 10, 11232), + (5249, 1, 360, 20, 11232), + (5250, 1, 360, 30, 11232), + (5254, 1, 218, 6, 0), + (5255, 1, 218, 7, 0), + (5256, 1, 218, 8, 0), + (5257, 1, 218, 9, 0), + (5258, 1, 218, 10, 0), + (5259, 1, 218, 6, 0), + (5260, 1, 218, 7, 0), + (5261, 1, 218, 8, 0), + (5262, 1, 218, 9, 0), + (5263, 1, 218, 10, 0), + (5264, 1, 218, 1, 0), + (5265, 1, 218, 2, 0), + (5266, 1, 218, 3, 0), + (5267, 1, 218, 4, 0), + (5268, 1, 218, 5, 0), + (5269, 1, 131, 50, 50), + (5269, 2, 137, 82, 0), + (5270, 1, 303, 3000, 3000), + (5270, 2, 139, 2766, 0), + (5271, 1, 303, 3500, 3500), + (5271, 2, 139, 2766, 0), + (5272, 1, 303, 4000, 4000), + (5272, 2, 139, 2766, 0), + (5276, 1, 264, 60, 621), + (5276, 2, 264, 60, 622), + (5276, 3, 264, 60, 623), + (5276, 4, 264, 60, 784), + (5276, 5, 264, 60, 785), + (5276, 6, 264, 60, 786), + (5276, 7, 264, 60, 787), + (5276, 8, 264, 60, 624), + (5277, 1, 264, 120, 621), + (5277, 2, 264, 120, 622), + (5277, 3, 264, 120, 623), + (5277, 4, 264, 120, 784), + (5277, 5, 264, 120, 785), + (5277, 6, 264, 120, 786), + (5277, 7, 264, 120, 787), + (5277, 8, 264, 120, 624), + (5278, 1, 264, 180, 621), + (5278, 2, 264, 180, 622), + (5278, 3, 264, 180, 623), + (5278, 4, 264, 180, 784), + (5278, 5, 264, 180, 785), + (5278, 6, 264, 180, 786), + (5278, 7, 264, 180, 787), + (5278, 8, 264, 180, 624), + (5283, 1, 320, 1, 0), + (5284, 1, 320, 3, 0), + (5285, 1, 320, 5, 0), + (5286, 1, 294, 7, 100), + (5287, 1, 294, 8, 100), + (5288, 1, 294, 9, 100), + (5290, 1, 439, 0, 46480), + (5290, 2, 345, 62, 0), + (5291, 1, 439, 0, 52960), + (5291, 2, 345, 63, 0), + (5292, 1, 439, 0, 55400), + (5292, 2, 345, 64, 0), + (5293, 1, 439, 0, 60280), + (5293, 2, 345, 65, 0), + (5294, 1, 439, 0, 65440), + (5294, 2, 345, 66, 50), + (5295, 1, 360, 10, 11629), + (5296, 1, 360, 20, 11629), + (5297, 1, 360, 30, 11629), + (5301, 1, 189, 7, 0), + (5302, 1, 189, 8, 0), + (5303, 1, 189, 9, 0), + (5304, 1, 189, 10, 0), + (5305, 1, 189, 11, 0), + (5306, 1, 15, 4, 0), + (5307, 1, 15, 5, 0), + (5308, 1, 15, 6, 0), + (5309, 1, 15, 7, 0), + (5310, 1, 15, 8, 0), + (5317, 1, 114, -43, 0), + (5318, 1, 114, -46, 0), + (5319, 1, 114, -50, 0), + (5320, 1, 218, 11, 0), + (5321, 1, 218, 12, 0), + (5322, 1, 218, 13, 0), + (5323, 1, 218, 14, 0), + (5324, 1, 218, 15, 0), + (5325, 1, 280, 27, 0), + (5326, 1, 280, 34, 0), + (5327, 1, 280, 41, 0), + (5328, 1, 280, 44, 0), + (5329, 1, 280, 47, 0), + (5339, 1, 215, 24, 0), + (5347, 1, 375, 225, 0), + (5348, 1, 375, 230, 0), + (5360, 1, 397, 1300, 0), + (5366, 1, 247, 75, 20), + (5500, 1, 231, 5, 0), + (5501, 1, 231, 7, 0), + (5502, 1, 231, 9, 0), + (5516, 1, 320, 6, 0), + (5517, 1, 320, 7, 0), + (5518, 1, 320, 8, 0), + (5519, 1, 172, 40, 0), + (5520, 1, 172, 41, 0), + (5521, 1, 172, 42, 0), + (5522, 1, 172, 43, 0), + (5523, 1, 172, 44, 0), + (5524, 1, 259, 46, 0), + (5525, 1, 259, 47, 0), + (5526, 1, 259, 48, 0), + (5527, 1, 259, 49, 0), + (5528, 1, 259, 50, 0), + (5529, 1, 339, 11, 12680), + (5529, 2, 138, 1, 0), + (5529, 3, 141, 1, 0), + (5529, 4, 142, 60, 0), + (5529, 5, 137, 0, 0), + (5529, 6, 311, 0, 0), + (5529, 7, 134, 80, 0), + (5529, 8, 139, -265, 0), + (5529, 9, 139, -754, 0), + (5529, 10, 139, -1332, 0), + (5529, 11, 139, -1572, 0), + (5529, 12, 139, -2749, 0), + (5529, 13, 139, -4979, 0), + (5529, 14, 139, -5418, 0), + (5529, 15, 139, -5403, 0), + (5529, 16, 348, 10, 0), + (5530, 1, 339, 13, 12681), + (5530, 2, 138, 1, 0), + (5530, 3, 141, 1, 0), + (5530, 4, 142, 60, 0), + (5530, 5, 137, 0, 0), + (5530, 6, 311, 0, 0), + (5530, 7, 134, 80, 0), + (5530, 8, 139, -265, 0), + (5530, 9, 139, -754, 0), + (5530, 10, 139, -1332, 0), + (5530, 11, 139, -1572, 0), + (5530, 12, 139, -2749, 0), + (5530, 13, 139, -4979, 0), + (5530, 14, 139, -5418, 0), + (5530, 15, 139, -5403, 0), + (5530, 16, 348, 10, 0), + (5531, 1, 339, 15, 12682), + (5531, 2, 138, 1, 0), + (5531, 3, 141, 1, 0), + (5531, 4, 142, 60, 0), + (5531, 5, 137, 0, 0), + (5531, 6, 311, 0, 0), + (5531, 7, 134, 80, 0), + (5531, 8, 139, -265, 0), + (5531, 9, 139, -754, 0), + (5531, 10, 139, -1332, 0), + (5531, 11, 139, -1572, 0), + (5531, 12, 139, -2749, 0), + (5531, 13, 139, -4979, 0), + (5531, 14, 139, -5418, 0), + (5531, 15, 139, -5403, 0), + (5531, 16, 348, 10, 0), + (5532, 1, 339, 17, 12683), + (5532, 2, 138, 1, 0), + (5532, 3, 141, 1, 0), + (5532, 4, 142, 60, 0), + (5532, 5, 137, 0, 0), + (5532, 6, 311, 0, 0), + (5532, 7, 134, 80, 0), + (5532, 8, 139, -265, 0), + (5532, 9, 139, -754, 0), + (5532, 10, 139, -1332, 0), + (5532, 11, 139, -1572, 0), + (5532, 12, 139, -2749, 0), + (5532, 13, 139, -4979, 0), + (5532, 14, 139, -5418, 0), + (5532, 15, 139, -5403, 0), + (5532, 16, 348, 10, 0), + (5533, 1, 339, 19, 12684), + (5533, 2, 138, 1, 0), + (5533, 3, 141, 1, 0), + (5533, 4, 142, 60, 0), + (5533, 5, 137, 0, 0), + (5533, 6, 311, 0, 0), + (5533, 7, 134, 80, 0), + (5533, 8, 139, -265, 0), + (5533, 9, 139, -754, 0), + (5533, 10, 139, -1332, 0), + (5533, 11, 139, -1572, 0), + (5533, 12, 139, -2749, 0), + (5533, 13, 139, -4979, 0), + (5533, 14, 139, -5418, 0), + (5533, 15, 139, -5403, 0), + (5533, 16, 348, 10, 0), + (5534, 1, 266, 18, 0), + (5535, 1, 266, 20, 0), + (5536, 1, 266, 22, 0), + (5542, 1, 330, 110, 0), + (5542, 2, 330, 110, 1), + (5542, 3, 330, 110, 2), + (5542, 4, 330, 110, 3), + (5542, 5, 330, 110, 28), + (5542, 6, 330, 110, 36), + (5542, 7, 330, 110, 77), + (5543, 1, 330, 115, 0), + (5543, 2, 330, 115, 1), + (5543, 3, 330, 115, 2), + (5543, 4, 330, 115, 3), + (5543, 5, 330, 115, 28), + (5543, 6, 330, 115, 36), + (5543, 7, 330, 115, 77), + (5544, 1, 330, 120, 0), + (5544, 2, 330, 120, 1), + (5544, 3, 330, 120, 2), + (5544, 4, 330, 120, 3), + (5544, 5, 330, 120, 28), + (5544, 6, 330, 120, 36), + (5544, 7, 330, 120, 77), + (5545, 1, 330, 110, 0), + (5545, 2, 330, 110, 1), + (5545, 3, 330, 110, 2), + (5545, 4, 330, 110, 3), + (5545, 5, 330, 110, 28), + (5545, 6, 330, 110, 36), + (5546, 1, 330, 115, 0), + (5546, 2, 330, 115, 1), + (5546, 3, 330, 115, 2), + (5546, 4, 330, 115, 3), + (5546, 5, 330, 115, 28), + (5546, 6, 330, 115, 36), + (5547, 1, 330, 120, 0), + (5547, 2, 330, 120, 1), + (5547, 3, 330, 120, 2), + (5547, 4, 330, 120, 3), + (5547, 5, 330, 120, 28), + (5547, 6, 330, 120, 36), + (5548, 1, 330, 110, 0), + (5548, 2, 330, 110, 1), + (5548, 3, 330, 110, 2), + (5548, 4, 330, 110, 3), + (5548, 5, 330, 110, 28), + (5548, 6, 330, 110, 36), + (5548, 7, 330, 110, 77), + (5549, 1, 330, 115, 0), + (5549, 2, 330, 115, 1), + (5549, 3, 330, 115, 2), + (5549, 4, 330, 115, 3), + (5549, 5, 330, 115, 28), + (5549, 6, 330, 115, 36), + (5549, 7, 330, 115, 77), + (5550, 1, 330, 120, 0), + (5550, 2, 330, 120, 1), + (5550, 3, 330, 120, 2), + (5550, 4, 330, 120, 3), + (5550, 5, 330, 120, 28), + (5550, 6, 330, 120, 36), + (5550, 7, 330, 120, 77), + (5551, 1, 330, 85, 0), + (5551, 2, 330, 85, 1), + (5551, 3, 330, 85, 2), + (5551, 4, 330, 85, 3), + (5551, 5, 330, 85, 28), + (5551, 6, 330, 85, 36), + (5551, 7, 330, 85, 77), + (5552, 1, 330, 90, 0), + (5552, 2, 330, 90, 1), + (5552, 3, 330, 90, 2), + (5552, 4, 330, 90, 3), + (5552, 5, 330, 90, 28), + (5552, 6, 330, 90, 36), + (5552, 7, 330, 90, 77), + (5553, 1, 330, 95, 0), + (5553, 2, 330, 95, 1), + (5553, 3, 330, 95, 2), + (5553, 4, 330, 95, 3), + (5553, 5, 330, 95, 28), + (5553, 6, 330, 95, 36), + (5553, 7, 330, 95, 77), + (5554, 1, 278, 700, 44340), + (5554, 2, 440, 71, 100), + (5555, 1, 278, 720, 47230), + (5555, 2, 440, 73, 100), + (5556, 1, 278, 750, 51057), + (5556, 2, 440, 75, 100), + (5557, 1, 341, 110, 0), + (5558, 1, 341, 120, 0), + (5559, 1, 341, 130, 0), + (5560, 1, 341, 140, 0), + (5561, 1, 341, 150, 0), + (5562, 1, 360, 40, 11023), + (5563, 1, 360, 50, 11023), + (5564, 1, 360, 60, 11023), + (5566, 1, 318, 11, 0), + (5567, 1, 318, 12, 0), + (5568, 1, 318, 13, 0), + (5569, 1, 318, 14, 0), + (5570, 1, 318, 15, 0), + (5571, 1, 294, 16, 100), + (5572, 1, 294, 17, 100), + (5573, 1, 294, 18, 100), + (5574, 1, 294, 0, 170), + (5575, 1, 294, 0, 175), + (5576, 1, 294, 0, 180), + (5577, 1, 294, 0, 145), + (5578, 1, 294, 0, 150), + (5579, 1, 294, 0, 155), + (5580, 1, 266, 30, 0), + (5581, 1, 266, 31, 0), + (5582, 1, 266, 32, 0), + (5586, 1, 114, -53, 0), + (5587, 1, 114, -56, 0), + (5588, 1, 114, -59, 0), + (5589, 1, 319, 17, 0), + (5590, 1, 319, 19, 0), + (5591, 1, 319, 21, 0), + (5592, 1, 274, 30, 0), + (5593, 1, 274, 32, 0), + (5594, 1, 274, 34, 0), + (5595, 1, 279, 31, 0), + (5596, 1, 279, 32, 0), + (5597, 1, 279, 33, 0), + (5611, 1, 274, 28, 0), + (5612, 1, 274, 30, 0), + (5613, 1, 274, 32, 0), + (5617, 1, 294, 18, 100), + (5618, 1, 294, 19, 100), + (5619, 1, 294, 20, 100), + (5620, 1, 320, 6, 0), + (5621, 1, 320, 7, 0), + (5622, 1, 320, 8, 0), + (5623, 1, 15, 9, 0), + (5624, 1, 15, 10, 0), + (5625, 1, 15, 11, 0), + (5626, 1, 15, 12, 0), + (5627, 1, 15, 13, 0), + (5628, 1, 114, -53, 0), + (5629, 1, 114, -56, 0), + (5630, 1, 114, -59, 0), + (5729, 1, 218, 11, 0), + (5730, 1, 218, 12, 0), + (5731, 1, 218, 13, 0), + (5732, 1, 218, 14, 0), + (5733, 1, 218, 15, 0), + (5738, 1, 280, 62, 0), + (5739, 1, 280, 63, 0), + (5740, 1, 280, 64, 0), + (5776, 1, 169, 5, -1), + (5777, 1, 169, 10, -1), + (5778, 1, 169, 15, -1), + (5797, 1, 264, 2520, 396), + (5797, 2, 264, 2520, 8504), + (5797, 3, 264, 2520, 8505), + (5798, 1, 264, 2880, 396), + (5798, 2, 264, 2880, 8504), + (5798, 3, 264, 2880, 8505), + (5799, 1, 264, 3240, 396), + (5799, 2, 264, 3240, 8504), + (5799, 3, 264, 3240, 8505), + (5806, 1, 279, 7, 0), + (5807, 1, 279, 11, 0), + (5808, 1, 279, 15, 0), + (5825, 1, 244, -40, 0), + (5850, 1, 287, 2, 1), + (5850, 2, 137, 31, 0), + (5850, 3, 136, 5, 0), + (5860, 1, 243, 40, 0), + (5861, 1, 243, 45, 0), + (5862, 1, 243, 50, 0), + (5880, 1, 287, 8, 0), + (5880, 2, 385, 2754, 1), + (5881, 1, 287, 10, 0), + (5881, 2, 385, 2754, 1), + (5882, 1, 287, 12, 0), + (5882, 2, 385, 2754, 1), + (5883, 2, 139, 2754, 1), + (5886, 1, 274, 12, 0), + (5887, 1, 274, 14, 0), + (5888, 1, 274, 16, 0), + (5889, 1, 280, 51, 0), + (5890, 1, 280, 52, 0), + (5891, 1, 280, 53, 0), + (5909, 1, 279, 29, 0), + (5910, 1, 279, 30, 0), + (5911, 1, 279, 31, 0), + (5912, 1, 279, 32, 0), + (5913, 1, 279, 33, 0), + (5917, 1, 220, 100, 26), + (5917, 2, 220, 100, 30), + (5917, 3, 220, 100, 38), + (5918, 1, 220, 110, 26), + (5918, 2, 220, 110, 30), + (5918, 3, 220, 110, 38), + (5919, 1, 220, 120, 26), + (5919, 2, 220, 120, 30), + (5919, 3, 220, 120, 38), + (5922, 1, 292, 35, 0), + (5923, 1, 292, 40, 0), + (5924, 1, 292, 45, 0), + (5939, 1, 218, 6, 0), + (5940, 1, 218, 7, 0), + (5941, 1, 218, 8, 0), + (5942, 1, 218, 9, 0), + (5943, 1, 218, 10, 0), + (5944, 1, 273, 4, 0), + (5945, 1, 273, 5, 0), + (5946, 1, 273, 6, 0), + (5950, 1, 264, 240, 175), + (5950, 2, 264, 240, 792), + (5951, 1, 264, 300, 175), + (5951, 2, 264, 300, 792), + (5952, 1, 264, 360, 175), + (5952, 2, 264, 360, 792), + (5954, 1, 264, 2400, 68), + (5955, 1, 264, 3000, 68), + (5956, 1, 264, 3600, 68), + (5972, 1, 264, 2880, 6001), + (5972, 2, 264, 2880, 3676), + (5973, 1, 264, 2880, 6000), + (5973, 2, 264, 2880, 87), + (6003, 1, 279, 29, 0), + (6004, 1, 279, 30, 0), + (6005, 1, 279, 31, 0), + (6006, 1, 279, 32, 0), + (6007, 1, 279, 33, 0), + (6011, 1, 216, 95, 0), + (6011, 2, 216, 95, 1), + (6011, 3, 216, 95, 2), + (6011, 4, 216, 95, 3), + (6011, 5, 216, 95, 10), + (6011, 6, 216, 95, 28), + (6011, 7, 216, 95, 30), + (6011, 8, 216, 95, 36), + (6011, 9, 216, 95, 77), + (6012, 1, 216, 100, 0), + (6012, 2, 216, 100, 1), + (6012, 3, 216, 100, 2), + (6012, 4, 216, 100, 3), + (6012, 5, 216, 100, 10), + (6012, 6, 216, 100, 28), + (6012, 7, 216, 100, 30), + (6012, 8, 216, 100, 36), + (6012, 9, 216, 100, 77), + (6013, 1, 216, 105, 0), + (6013, 2, 216, 105, 1), + (6013, 3, 216, 105, 2), + (6013, 4, 216, 105, 3), + (6013, 5, 216, 105, 10), + (6013, 6, 216, 105, 28), + (6013, 7, 216, 105, 30), + (6013, 8, 216, 105, 36), + (6013, 9, 216, 105, 77), + (6014, 1, 360, 40, 12617), + (6015, 1, 360, 50, 12617), + (6016, 1, 360, 60, 12617), + (6017, 1, 217, 0, 65440), + (6017, 2, 346, 72, 28), + (6018, 1, 217, 0, 70880), + (6018, 2, 346, 74, 28), + (6019, 1, 217, 0, 76600), + (6019, 2, 346, 76, 28), + (6020, 1, 220, 15, 21), + (6020, 2, 220, 15, 23), + (6020, 3, 220, 30, 52), + (6020, 4, 220, 15, 28), + (6021, 1, 220, 25, 21), + (6021, 2, 220, 25, 23), + (6021, 3, 220, 50, 52), + (6021, 4, 220, 25, 28), + (6022, 1, 220, 35, 21), + (6022, 2, 220, 35, 23), + (6022, 3, 220, 70, 52), + (6022, 4, 220, 35, 28), + (6023, 1, 278, 900, 66950), + (6023, 2, 440, 82, 100), + (6024, 1, 278, 900, 70230), + (6024, 2, 440, 84, 100), + (6025, 1, 278, 900, 74935), + (6025, 2, 440, 86, 100), + (6026, 1, 127, 10, 0), + (6026, 2, 139, 16106, 0), + (6027, 1, 127, 25, 0), + (6027, 2, 139, 16106, 0), + (6028, 1, 127, 50, 0), + (6028, 2, 139, 16106, 0), + (6029, 1, 216, 200, 8), + (6030, 1, 216, 250, 8), + (6031, 1, 216, 300, 8), + (6032, 1, 439, 0, 70880), + (6032, 2, 345, 68, 50), + (6033, 1, 439, 0, 76600), + (6033, 2, 345, 70, 50), + (6034, 1, 439, 0, 82600), + (6034, 2, 345, 72, 35), + (6035, 1, 258, 48, 0), + (6036, 1, 258, 51, 0), + (6037, 1, 258, 54, 0), + (6042, 1, 220, 70, 8), + (6043, 1, 220, 80, 8), + (6044, 1, 220, 100, 8), + (6045, 1, 220, 45, 21), + (6045, 2, 220, 45, 23), + (6045, 3, 220, 90, 52), + (6045, 4, 220, 45, 28), + (6046, 1, 220, 55, 21), + (6046, 2, 220, 55, 23), + (6046, 3, 220, 110, 52), + (6046, 4, 220, 55, 28), + (6047, 1, 220, 65, 21), + (6047, 2, 220, 65, 23), + (6047, 3, 220, 130, 52), + (6047, 4, 220, 65, 28), + (6048, 1, 220, 75, 21), + (6048, 2, 220, 75, 23), + (6048, 3, 220, 150, 52), + (6048, 4, 220, 75, 28), + (6049, 1, 220, 85, 21), + (6049, 2, 220, 85, 23), + (6049, 3, 220, 170, 52), + (6049, 4, 220, 85, 28), + (6050, 1, 220, 95, 21), + (6050, 2, 220, 95, 23), + (6050, 3, 220, 190, 52), + (6050, 4, 220, 95, 28), + (6051, 1, 213, 1, 0), + (6052, 1, 213, 3, 0), + (6053, 1, 213, 5, 0), + (6057, 1, 220, 105, 21), + (6057, 2, 220, 105, 23), + (6057, 3, 220, 210, 52), + (6057, 4, 220, 105, 28), + (6058, 1, 220, 115, 21), + (6058, 2, 220, 115, 23), + (6058, 3, 220, 230, 52), + (6058, 4, 220, 115, 28), + (6059, 1, 220, 125, 21), + (6059, 2, 220, 125, 23), + (6059, 3, 220, 250, 52), + (6059, 4, 220, 125, 28), + (6060, 1, 247, 5, 76), + (6061, 1, 247, 10, 76), + (6063, 1, 303, 4500, 4500), + (6063, 2, 139, 2766, 0), + (6064, 1, 303, 5000, 5000), + (6064, 2, 139, 2766, 0), + (6065, 1, 303, 5500, 5500), + (6065, 2, 139, 2766, 0), + (6066, 1, 85, 12629, 0), + (6067, 1, 85, 12630, 0), + (6068, 1, 85, 12631, 0), + (6069, 1, 85, 12632, 0), + (6070, 1, 85, 12633, 0), + (6071, 1, 85, 12634, 0), + (6072, 1, 302, 266, 266), + (6072, 2, 385, 99, 0), + (6073, 1, 302, 290, 290), + (6073, 2, 385, 99, 0), + (6074, 1, 302, 310, 310), + (6074, 2, 385, 99, 0), + (6075, 1, 59, -18, 0), + (6076, 1, 59, -21, 0), + (6077, 1, 59, -24, 0), + (6078, 1, 59, -27, 0), + (6079, 1, 59, -30, 0), + (6080, 1, 189, 12, 0), + (6081, 1, 189, 13, 0), + (6082, 1, 247, 50, 20), + (6083, 1, 247, 75, 20), + (6084, 1, 247, 100, 20), + (6085, 1, 292, 20, 0), + (6086, 1, 292, 30, 0), + (6087, 1, 292, 40, 0), + (6088, 1, 264, 180, 392), + (6089, 1, 264, 360, 392), + (6090, 1, 264, 540, 392), + (6112, 1, 131, 10, 10), + (6112, 2, 348, 10, 0), + (6112, 3, 137, -32, 0), + (6113, 1, 287, 2, 0), + (6113, 2, 137, 100, 0), + (6113, 3, 385, -4232, 0), + (6113, 4, 385, -4332, 0), + (6113, 5, 139, -2741, 0), + (6113, 6, 385, -16192, 0), + (6113, 7, 139, -16843, 0), + (6114, 1, 287, 3, 0), + (6114, 2, 137, 100, 0), + (6114, 3, 385, -4232, 0), + (6114, 4, 385, -4332, 0), + (6114, 5, 139, -2741, 0), + (6114, 6, 385, -16192, 0), + (6114, 7, 139, -16843, 0), + (6115, 1, 287, 4, 0), + (6115, 2, 137, 100, 0), + (6115, 3, 385, -4232, 0), + (6115, 4, 385, -4332, 0), + (6115, 5, 139, -2741, 0), + (6115, 6, 385, -16192, 0), + (6115, 7, 139, -16843, 0), + (6119, 1, 69, 100, 0), + (6120, 1, 69, 200, 0), + (6121, 1, 69, 300, 0), + (6122, 1, 69, 400, 0), + (6123, 1, 69, 500, 0), + (6124, 1, 320, 1, 0), + (6125, 1, 320, 3, 0), + (6126, 1, 320, 5, 0), + (6127, 1, 320, 6, 0), + (6128, 1, 320, 7, 0), + (6129, 1, 320, 8, 0), + (6130, 1, 255, 48, 0), + (6131, 1, 255, 60, 0), + (6132, 1, 255, 72, 0), + (6136, 1, 264, 360, 300), + (6202, 1, 247, 10, 35), + (6203, 1, 247, 20, 35), + (6204, 1, 247, 60, 35), + (6209, 1, 264, 720, 245), + (6210, 1, 264, 1440, 245), + (6211, 1, 264, 2160, 245), + (6215, 1, 247, 5, 76), + (6216, 1, 247, 10, 76), + (6217, 1, 247, 15, 76), + (6223, 1, 232, 11, 4544), + (6224, 1, 232, 12, 4544), + (6225, 1, 232, 13, 4544), + (6226, 1, 232, 14, 4544), + (6227, 1, 232, 15, 4544), + (6228, 1, 264, 120, 404), + (6229, 1, 264, 240, 404), + (6230, 1, 264, 360, 404), + (6231, 1, 264, 480, 404), + (6233, 1, 264, 1728, 43), + (6234, 1, 264, 2160, 43), + (6235, 1, 264, 2592, 43), + (6236, 1, 287, 1, 0), + (6236, 2, 137, 3, 0), + (6236, 3, 137, 99, 0), + (6236, 4, 138, 0, 0), + (6236, 5, 244, 50, 0), + (6237, 1, 287, 2, 0), + (6237, 2, 137, 3, 0), + (6237, 3, 137, 99, 0), + (6237, 4, 138, 0, 0), + (6237, 5, 244, 38, 0), + (6238, 1, 287, 3, 0), + (6238, 2, 137, 3, 0), + (6238, 3, 137, 99, 0), + (6238, 4, 138, 0, 0), + (6238, 5, 244, 25, 0), + (6240, 1, 273, 3, 0), + (6241, 1, 273, 6, 0), + (6242, 1, 273, 9, 0), + (6243, 1, 273, 12, 0), + (6244, 1, 273, 15, 0), + (6245, 1, 273, 18, 0), + (6249, 1, 310, 1000, 0), + (6249, 2, 139, 11903, 0), + (6249, 3, 310, 1000, 0), + (6249, 4, 139, 11904, 0), + (6249, 5, 310, 1000, 0), + (6249, 6, 139, 11905, 0), + (6249, 7, 310, 1000, 0), + (6249, 8, 139, 1362, 0), + (6249, 9, 310, 1000, 0), + (6249, 10, 139, 8032, 0), + (6249, 11, 310, 1000, 0), + (6249, 12, 385, 6131, 0), + (6249, 13, 385, 6231, 0), + (6249, 14, 385, 6331, 0), + (6249, 15, 385, 6431, 0), + (6249, 16, 385, 6531, 0), + (6249, 17, 385, 6631, 0), + (6250, 1, 310, 2000, 0), + (6250, 2, 139, 11903, 0), + (6250, 3, 310, 2000, 0), + (6250, 4, 139, 11904, 0), + (6250, 5, 310, 2000, 0), + (6250, 6, 139, 11905, 0), + (6250, 7, 310, 2000, 0), + (6250, 8, 139, 1362, 0), + (6250, 9, 310, 2000, 0), + (6250, 10, 139, 8032, 0), + (6250, 11, 310, 2000, 0), + (6250, 12, 385, 6131, 0), + (6250, 13, 385, 6231, 0), + (6250, 14, 385, 6331, 0), + (6250, 15, 385, 6431, 0), + (6250, 16, 385, 6531, 0), + (6250, 17, 385, 6631, 0), + (6251, 1, 310, 3000, 0), + (6251, 2, 139, 11903, 0), + (6251, 3, 310, 3000, 0), + (6251, 4, 139, 11904, 0), + (6251, 5, 310, 3000, 0), + (6251, 6, 139, 11905, 0), + (6251, 7, 310, 3000, 0), + (6251, 8, 139, 1362, 0), + (6251, 9, 310, 3000, 0), + (6251, 10, 139, 8032, 0), + (6251, 11, 310, 3000, 0), + (6251, 12, 385, 6131, 0), + (6251, 13, 385, 6231, 0), + (6251, 14, 385, 6331, 0), + (6251, 15, 385, 6431, 0), + (6251, 16, 385, 6531, 0), + (6251, 17, 385, 6631, 0), + (6252, 1, 310, 4000, 0), + (6252, 2, 139, 11903, 0), + (6252, 3, 310, 4000, 0), + (6252, 4, 139, 11904, 0), + (6252, 5, 310, 4000, 0), + (6252, 6, 139, 11905, 0), + (6252, 7, 310, 4000, 0), + (6252, 8, 139, 1362, 0), + (6252, 9, 310, 4000, 0), + (6252, 10, 139, 8032, 0), + (6252, 11, 310, 4000, 0), + (6252, 12, 385, 6131, 0), + (6252, 13, 385, 6231, 0), + (6252, 14, 385, 6331, 0), + (6252, 15, 385, 6431, 0), + (6252, 16, 385, 6531, 0), + (6252, 17, 385, 6631, 0), + (6253, 1, 310, 5000, 0), + (6253, 2, 139, 11903, 0), + (6253, 3, 310, 5000, 0), + (6253, 4, 139, 11904, 0), + (6253, 5, 310, 5000, 0), + (6253, 6, 139, 11905, 0), + (6253, 7, 310, 5000, 0), + (6253, 8, 139, 1362, 0), + (6253, 9, 310, 5000, 0), + (6253, 10, 139, 8032, 0), + (6253, 11, 310, 5000, 0), + (6253, 12, 385, 6131, 0), + (6253, 13, 385, 6231, 0), + (6253, 14, 385, 6331, 0), + (6253, 15, 385, 6431, 0), + (6253, 16, 385, 6531, 0), + (6253, 17, 385, 6631, 0), + (6257, 1, 128, 5, 5), + (6257, 2, 138, 1, 0), + (6257, 3, 140, 1, 0), + (6257, 4, 139, -2741, 0), + (6257, 5, 139, -16843, 0), + (6257, 6, 385, -16192, 0), + (6258, 1, 128, 15, 15), + (6258, 2, 138, 1, 0), + (6258, 3, 140, 1, 0), + (6258, 4, 139, -2741, 0), + (6258, 5, 139, -16843, 0), + (6258, 6, 385, -16192, 0), + (6259, 1, 128, 30, 30), + (6259, 2, 138, 1, 0), + (6259, 3, 140, 1, 0), + (6259, 4, 139, -2741, 0), + (6259, 5, 139, -16843, 0), + (6259, 6, 385, -16192, 0), + (6260, 1, 264, 720, 98), + (6261, 1, 264, 900, 98), + (6262, 1, 264, 1080, 98), + (6266, 1, 224, 20, 10), + (6266, 2, 173, 1, 0), + (6267, 1, 224, 35, 10), + (6267, 2, 173, 2, 0), + (6268, 1, 224, 50, 10), + (6268, 2, 173, 3, 0), + (6269, 1, 224, 20, 30), + (6269, 2, 173, 1, 0), + (6270, 1, 224, 35, 30), + (6270, 2, 173, 2, 0), + (6271, 1, 224, 50, 30), + (6271, 2, 173, 3, 0), + (6272, 1, 264, 15, 672), + (6273, 1, 264, 30, 672), + (6274, 1, 264, 45, 672), + (6275, 1, 224, 20, 8), + (6275, 2, 173, 1, 0), + (6276, 1, 224, 35, 8), + (6276, 2, 173, 2, 0), + (6277, 1, 224, 50, 8), + (6277, 2, 173, 3, 0), + (6283, 1, 85, 13200, 0), + (6284, 1, 85, 13200, 25), + (6285, 1, 85, 13200, 50), + (6287, 1, 224, 20, 30), + (6287, 2, 173, 1, 0), + (6288, 1, 224, 35, 30), + (6288, 2, 173, 3, 0), + (6289, 1, 224, 50, 30), + (6289, 2, 173, 3, 0), + (6300, 1, 247, 20, 76), + (6301, 1, 247, 25, 76), + (6302, 1, 264, 120, 3710), + (6303, 1, 264, 240, 3710), + (6304, 1, 264, 360, 3710), + (6319, 1, 264, 1728, 107), + (6320, 1, 264, 2160, 107), + (6321, 1, 264, 2592, 107), + (6322, 1, 216, 5, 51), + (6323, 1, 216, 15, 51), + (6324, 1, 216, 25, 51), + (6331, 1, 252, 70, 0), + (6332, 1, 252, 75, 0), + (6334, 1, 185, 5, 51), + (6335, 1, 185, 10, 51), + (6336, 1, 185, 15, 51), + (6337, 1, 264, 60, 553), + (6338, 1, 264, 120, 553), + (6339, 1, 264, 180, 553), + (6340, 1, 264, 180, 777), + (6341, 1, 264, 360, 777), + (6342, 1, 264, 540, 777), + (6343, 1, 264, 5, 468), + (6343, 2, 264, 5, 469), + (6343, 3, 264, 5, 470), + (6344, 1, 264, 10, 468), + (6344, 2, 264, 10, 469), + (6344, 3, 264, 10, 470), + (6345, 1, 264, 15, 468), + (6345, 2, 264, 15, 469), + (6345, 3, 264, 15, 470), + (6346, 1, 264, 180, 494), + (6347, 1, 264, 360, 494), + (6348, 1, 264, 540, 494), + (6349, 1, 264, 180, 500), + (6350, 1, 264, 360, 500), + (6351, 1, 264, 540, 500), + (6355, 1, 310, 360000, 0), + (6355, 2, 139, 4506, 0), + (6355, 3, 310, 360000, 0), + (6355, 4, 385, 11122, 0), + (6355, 5, 385, 11222, 0), + (6355, 6, 385, 11322, 0), + (6355, 7, 385, 11522, 0), + (6356, 1, 310, 720000, 0), + (6356, 2, 139, 4506, 0), + (6356, 3, 310, 720000, 0), + (6356, 4, 385, 11122, 0), + (6356, 5, 385, 11222, 0), + (6356, 6, 385, 11322, 0), + (6356, 7, 385, 11522, 0), + (6357, 1, 310, 1080000, 0), + (6357, 2, 139, 4506, 0), + (6357, 3, 310, 1080000, 0), + (6357, 4, 385, 11122, 0), + (6357, 5, 385, 11222, 0), + (6357, 6, 385, 11322, 0), + (6357, 7, 385, 11522, 0), + (6358, 1, 310, 1440000, 0), + (6358, 2, 139, 4506, 0), + (6358, 3, 310, 1440000, 0), + (6358, 4, 385, 11122, 0), + (6358, 5, 385, 11222, 0), + (6358, 6, 385, 11322, 0), + (6358, 7, 385, 11522, 0), + (6359, 1, 310, 1800000, 0), + (6359, 2, 139, 4506, 0), + (6359, 3, 310, 1800000, 0), + (6359, 4, 385, 11122, 0), + (6359, 5, 385, 11222, 0), + (6359, 6, 385, 11322, 0), + (6359, 7, 385, 11522, 0), + (6360, 1, 310, 2160000, 0), + (6360, 2, 139, 4506, 0), + (6360, 3, 310, 2160000, 0), + (6360, 4, 385, 11122, 0), + (6360, 5, 385, 11222, 0), + (6360, 6, 385, 11322, 0), + (6360, 7, 385, 11522, 0), + (6361, 1, 213, 3, 0), + (6362, 1, 310, 120000, 0), + (6362, 2, 139, 5040, 0), + (6363, 1, 310, 240000, 0), + (6363, 2, 139, 5040, 0), + (6364, 1, 310, 360000, 0), + (6364, 2, 139, 5040, 0), + (6365, 1, 310, 480000, 0), + (6365, 2, 139, 5040, 0), + (6366, 1, 310, 600000, 0), + (6366, 2, 139, 5040, 0), + (6375, 1, 375, 107, 0), + (6376, 1, 375, 115, 0), + (6377, 1, 375, 125, 0), + (6383, 1, 215, 5, 0), + (6384, 1, 215, 7, 0), + (6385, 1, 215, 10, 0), + (6386, 1, 293, 5, 0), + (6387, 1, 293, 10, 0), + (6388, 1, 293, 15, 0), + (6389, 1, 293, 20, 0), + (6390, 1, 0, 16, 0), + (6391, 1, 0, 17, 0), + (6392, 1, 0, 18, 0), + (6393, 1, 0, 19, 0), + (6394, 1, 0, 20, 0), + (6395, 1, 85, 13502, 0), + (6396, 1, 85, 13503, 0), + (6397, 1, 85, 13504, 0), + (6403, 1, 294, 11, 100), + (6404, 1, 294, 13, 100), + (6405, 1, 294, 15, 100), + (6406, 1, 360, 25, 13201), + (6407, 1, 360, 25, 13202), + (6408, 1, 360, 25, 13203), + (6409, 1, 247, 5, 76), + (6410, 1, 247, 10, 76), + (6411, 1, 247, 15, 76), + (6412, 1, 247, 20, 76), + (6413, 1, 247, 25, 76), + (6414, 1, 247, 30, 76), + (6415, 1, 247, 35, 76), + (6416, 1, 247, 40, 76), + (6417, 1, 247, 45, 76), + (6418, 1, 247, 50, 76), + (6419, 1, 247, 5, 76), + (6420, 1, 247, 10, 76), + (6421, 1, 247, 15, 76), + (6422, 1, 214, 100, 0), + (6423, 1, 214, 200, 0), + (6424, 1, 214, 300, 0), + (6428, 1, 320, 1, 0), + (6429, 1, 320, 3, 0), + (6430, 1, 320, 5, 0), + (6431, 1, 317, 6, 0), + (6432, 1, 317, 7, 0), + (6433, 1, 317, 8, 0), + (6434, 1, 317, 9, 0), + (6435, 1, 317, 10, 0), + (6436, 1, 244, 70, 0), + (6437, 1, 244, 60, 0), + (6438, 1, 244, 50, 0), + (6439, 1, 264, 720, 41), + (6440, 1, 264, 900, 41), + (6441, 1, 264, 840, 420), + (6442, 1, 264, 540, 362), + (6443, 1, 264, 630, 362), + (6445, 1, 127, 15, 0), + (6445, 2, 139, 3248, 0), + (6445, 3, 127, 15, 0), + (6445, 4, 139, 3249, 0), + (6446, 1, 127, 30, 0), + (6446, 2, 139, 3248, 0), + (6446, 3, 127, 30, 0), + (6446, 4, 139, 3249, 0), + (6447, 1, 127, 50, 0), + (6447, 2, 139, 3248, 0), + (6447, 3, 127, 50, 0), + (6447, 4, 139, 3249, 0), + (6452, 1, 310, 1000, 0), + (6452, 2, 403, 7, 0), + (6452, 3, 404, 35, 0), + (6452, 4, 144, 2000, 0), + (6452, 5, 310, 5000, 0), + (6452, 6, 403, 7, 0), + (6452, 7, 404, 35, 0), + (6452, 8, 144, 10000, 0), + (6453, 1, 310, 2000, 0), + (6453, 2, 403, 7, 0), + (6453, 3, 404, 35, 0), + (6453, 4, 144, 2000, 0), + (6453, 5, 310, 10000, 0), + (6453, 6, 403, 7, 0), + (6453, 7, 404, 35, 0), + (6453, 8, 144, 10000, 0), + (6454, 1, 310, 3000, 0), + (6454, 2, 403, 7, 0), + (6454, 3, 404, 35, 0), + (6454, 4, 144, 2000, 0), + (6454, 5, 310, 15000, 0), + (6454, 6, 403, 7, 0), + (6454, 7, 404, 35, 0), + (6454, 8, 144, 10000, 0), + (6458, 1, 310, 30000, 0), + (6458, 2, 385, 5137, 0), + (6458, 3, 385, 5237, 0), + (6458, 4, 385, 5337, 0), + (6458, 5, 385, 5437, 0), + (6458, 6, 385, 5537, 0), + (6458, 7, 385, 5637, 0), + (6458, 8, 127, 15, 15), + (6458, 9, 385, 5137, 0), + (6458, 10, 385, 5237, 0), + (6458, 11, 385, 5337, 0), + (6458, 12, 385, 5437, 0), + (6458, 13, 385, 5537, 0), + (6458, 14, 385, 5637, 0), + (6459, 1, 310, 60000, 0), + (6459, 2, 385, 5137, 0), + (6459, 3, 385, 5237, 0), + (6459, 4, 385, 5337, 0), + (6459, 5, 385, 5437, 0), + (6459, 6, 385, 5537, 0), + (6459, 7, 385, 5637, 0), + (6459, 8, 127, 30, 30), + (6459, 9, 385, 5137, 0), + (6459, 10, 385, 5237, 0), + (6459, 11, 385, 5337, 0), + (6459, 12, 385, 5437, 0), + (6459, 13, 385, 5537, 0), + (6459, 14, 385, 5637, 0), + (6460, 1, 310, 90000, 0), + (6460, 2, 385, 5137, 0), + (6460, 3, 385, 5237, 0), + (6460, 4, 385, 5337, 0), + (6460, 5, 385, 5437, 0), + (6460, 6, 385, 5537, 0), + (6460, 7, 385, 5637, 0), + (6460, 8, 127, 50, 50), + (6460, 9, 385, 5137, 0), + (6460, 10, 385, 5237, 0), + (6460, 11, 385, 5337, 0), + (6460, 12, 385, 5437, 0), + (6460, 13, 385, 5537, 0), + (6460, 14, 385, 5637, 0), + (6461, 1, 127, 15, 0), + (6461, 2, 385, 14130, 0), + (6461, 3, 385, 14230, 0), + (6461, 4, 385, 14330, 0), + (6461, 5, 385, 14430, 0), + (6461, 6, 385, 14530, 0), + (6461, 7, 385, 14630, 0), + (6461, 8, 310, 30000, 0), + (6461, 9, 385, 14130, 0), + (6461, 10, 385, 14230, 0), + (6461, 11, 385, 14330, 0), + (6461, 12, 385, 14430, 0), + (6461, 13, 385, 14530, 0), + (6461, 14, 385, 14630, 0), + (6462, 1, 127, 30, 0), + (6462, 2, 385, 14130, 0), + (6462, 3, 385, 14230, 0), + (6462, 4, 385, 14330, 0), + (6462, 5, 385, 14430, 0), + (6462, 6, 385, 14530, 0), + (6462, 7, 385, 14630, 0), + (6462, 8, 310, 60000, 0), + (6462, 9, 385, 14130, 0), + (6462, 10, 385, 14230, 0), + (6462, 11, 385, 14330, 0), + (6462, 12, 385, 14430, 0), + (6462, 13, 385, 14530, 0), + (6462, 14, 385, 14630, 0), + (6463, 1, 127, 50, 0), + (6463, 2, 385, 14130, 0), + (6463, 3, 385, 14230, 0), + (6463, 4, 385, 14330, 0), + (6463, 5, 385, 14430, 0), + (6463, 6, 385, 14530, 0), + (6463, 7, 385, 14630, 0), + (6463, 8, 310, 90000, 0), + (6463, 9, 385, 14130, 0), + (6463, 10, 385, 14230, 0), + (6463, 11, 385, 14330, 0), + (6463, 12, 385, 14430, 0), + (6463, 13, 385, 14530, 0), + (6463, 14, 385, 14630, 0), + (6467, 1, 214, 100, 0), + (6468, 1, 214, 200, 0), + (6469, 1, 214, 300, 0), + (6470, 1, 247, 15, 76), + (6471, 1, 247, 20, 76), + (6472, 1, 247, 30, 76), + (6473, 1, 247, 35, 76), + (6474, 1, 247, 55, 76), + (6475, 1, 247, 60, 76), + (6476, 1, 247, 20, 76), + (6477, 1, 247, 25, 76), + (6478, 1, 264, 1, 3800), + (6479, 1, 264, 2, 3800), + (6480, 1, 264, 3, 3800), + (6481, 1, 264, 6480, 36), + (6482, 1, 264, 12960, 36), + (6483, 1, 264, 19440, 36), + (6484, 1, 264, 105, 558), + (6485, 1, 264, 120, 558), + (6486, 1, 264, 135, 558), + (6489, 1, 310, 600000, 0), + (6489, 2, 139, 4500, 0), + (6489, 3, 411, 8, 0), + (6490, 1, 310, 1200000, 0), + (6490, 2, 139, 4500, 0), + (6490, 3, 411, 8, 0), + (6491, 1, 310, 1800000, 0), + (6491, 2, 139, 4500, 0), + (6491, 3, 411, 8, 0), + (6500, 1, 273, 5, 0), + (6501, 1, 273, 6, 0), + (6502, 1, 273, 7, 0), + (6503, 1, 127, 12, 0), + (6503, 2, 385, 3338, 0), + (6504, 1, 127, 24, 0), + (6504, 2, 385, 3338, 0), + (6505, 1, 127, 36, 0), + (6505, 2, 385, 3338, 0), + (6506, 1, 127, 50, 0), + (6506, 2, 385, 3338, 0), + (6511, 1, 216, 5, 7), + (6512, 1, 216, 15, 7), + (6513, 1, 216, 25, 7), + (6514, 1, 127, 15, 0), + (6514, 2, 139, 5880, 0), + (6515, 1, 127, 30, 0), + (6515, 2, 139, 5880, 0), + (6516, 1, 127, 50, 0), + (6516, 2, 139, 5880, 0), + (6517, 1, 339, 10, 8105), + (6517, 2, 142, 65, 0), + (6517, 3, 311, 0, 0), + (6517, 4, 134, 70, 0), + (6517, 5, 348, 10, 0), + (6517, 6, 137, 0, 0), + (6517, 7, 339, 10, 8105), + (6517, 8, 142, 65, 0), + (6517, 9, 311, 0, 0), + (6517, 10, 134, 70, 0), + (6517, 11, 348, 10, 0), + (6517, 12, 137, 100, 0), + (6517, 13, 339, 10, 8105), + (6517, 14, 142, 65, 0), + (6517, 15, 311, 0, 0), + (6517, 16, 134, 70, 0), + (6517, 17, 348, 10, 0), + (6517, 18, 137, 79, 0), + (6517, 19, 339, 10, 8105), + (6517, 20, 142, 65, 0), + (6517, 21, 311, 0, 0), + (6517, 22, 134, 70, 0), + (6517, 23, 348, 10, 0), + (6517, 24, 137, 147, 0), + (6517, 25, 339, 10, 11404), + (6517, 26, 142, 71, 0), + (6517, 27, 311, 0, 0), + (6517, 28, 134, 75, 0), + (6517, 29, 348, 10, 0), + (6517, 30, 137, 0, 0), + (6517, 31, 339, 10, 11404), + (6517, 32, 142, 71, 0), + (6517, 33, 311, 0, 0), + (6517, 34, 134, 75, 0), + (6517, 35, 348, 10, 0), + (6517, 36, 137, 100, 0), + (6517, 37, 339, 10, 11404), + (6517, 38, 142, 71, 0), + (6517, 39, 311, 0, 0), + (6517, 40, 134, 75, 0), + (6517, 41, 348, 10, 0), + (6517, 42, 137, 79, 0), + (6517, 43, 339, 10, 11404), + (6517, 44, 142, 71, 0), + (6517, 45, 311, 0, 0), + (6517, 46, 134, 75, 0), + (6517, 47, 348, 10, 0), + (6517, 48, 137, 147, 0), + (6517, 49, 339, 10, 13199), + (6517, 50, 142, 76, 0), + (6517, 51, 311, 0, 0), + (6517, 52, 134, 80, 0), + (6517, 53, 348, 10, 0), + (6517, 54, 137, 0, 0), + (6517, 55, 339, 10, 13199), + (6517, 56, 142, 76, 0), + (6517, 57, 311, 0, 0), + (6517, 58, 134, 80, 0), + (6517, 59, 348, 10, 0), + (6517, 60, 137, 100, 0), + (6517, 61, 339, 10, 13199), + (6517, 62, 142, 76, 0), + (6517, 63, 311, 0, 0), + (6517, 64, 134, 80, 0), + (6517, 65, 348, 10, 0), + (6517, 66, 137, 79, 0), + (6517, 67, 339, 10, 13199), + (6517, 68, 142, 76, 0), + (6517, 69, 311, 0, 0), + (6517, 70, 134, 80, 0), + (6517, 71, 348, 10, 0), + (6517, 72, 137, 147, 0), + (6518, 1, 221, 18, 0), + (6519, 1, 221, 21, 0), + (6520, 1, 221, 24, 0), + (6521, 1, 327, 6, 0), + (6522, 1, 327, 7, 0), + (6523, 1, 328, 800, 0), + (6524, 1, 328, 850, 0), + (6525, 1, 328, 900, 0), + (6526, 1, 328, 950, 0), + (6527, 1, 328, 1000, 0), + (6528, 1, 264, 3024, 107), + (6531, 1, 360, 40, 11629), + (6532, 1, 360, 50, 11629), + (6533, 1, 360, 60, 11629), + (6540, 1, 363, 2, 0), + (6545, 1, 362, 2, 0), + (6546, 1, 2, 4, 0), + (6547, 1, 2, 8, 0), + (6548, 1, 2, 12, 0), + (6549, 1, 2, 16, 0), + (6550, 1, 2, 20, 0), + (6551, 1, 2, 24, 0), + (6552, 1, 2, 28, 0), + (6553, 1, 2, 32, 0), + (6554, 1, 2, 36, 0), + (6555, 1, 2, 40, 0), + (6556, 1, 2, 44, 0), + (6557, 1, 2, 48, 0), + (6558, 1, 2, 52, 0), + (6559, 1, 2, 56, 0), + (6560, 1, 2, 60, 0), + (6561, 1, 2, 64, 0), + (6562, 1, 2, 68, 0), + (6563, 1, 2, 72, 0), + (6564, 1, 2, 76, 0), + (6565, 1, 2, 80, 0), + (6566, 1, 2, 84, 0), + (6567, 1, 2, 88, 0), + (6568, 1, 2, 92, 0), + (6569, 1, 2, 96, 0), + (6570, 1, 2, 100, 0), + (6571, 1, 2, 104, 0), + (6601, 1, 339, 5, 13519), + (6601, 2, 137, 21, 0), + (6602, 1, 339, 10, 13519), + (6602, 2, 137, 21, 0), + (6603, 1, 339, 15, 13519), + (6603, 2, 137, 21, 0), + (6604, 1, 339, 20, 13519), + (6604, 2, 137, 21, 0), + (6605, 1, 339, 25, 13519), + (6605, 2, 137, 21, 0), + (6611, 1, 310, 120000, 0), + (6611, 2, 139, 4670, 0), + (6612, 1, 310, 240000, 0), + (6612, 2, 139, 4670, 0), + (6613, 1, 310, 360000, 0), + (6613, 2, 139, 4670, 0), + (6614, 1, 310, 120000, 0), + (6614, 2, 139, 4674, 0), + (6615, 1, 310, 240000, 0), + (6615, 2, 139, 4674, 0), + (6616, 1, 310, 360000, 0), + (6616, 2, 139, 4674, 0), + (6618, 1, 310, 480000, 0), + (6618, 2, 139, 4670, 0), + (6619, 1, 310, 600000, 0), + (6619, 2, 139, 4670, 0), + (6630, 1, 218, 1, 0), + (6631, 1, 218, 2, 0), + (6632, 1, 218, 3, 0), + (6633, 1, 218, 4, 0), + (6634, 1, 218, 5, 0), + (6636, 1, 294, 0, 107), + (6637, 1, 294, 0, 115), + (6638, 1, 294, 0, 125), + (6641, 1, 339, 10, 16101), + (6641, 2, 138, 0, 0), + (6641, 3, 142, 70, 0), + (6641, 4, 403, 4, 0), + (6641, 5, 348, 1, 0), + (6641, 6, 404, 2, 0), + (6641, 7, 141, 1, 0), + (6642, 1, 339, 10, 16102), + (6642, 2, 138, 0, 0), + (6642, 3, 142, 70, 0), + (6642, 4, 403, 4, 0), + (6642, 5, 348, 1, 0), + (6642, 6, 404, 2, 0), + (6642, 7, 141, 1, 0), + (6643, 1, 339, 10, 16103), + (6643, 2, 138, 0, 0), + (6643, 3, 142, 70, 0), + (6643, 4, 403, 4, 0), + (6643, 5, 348, 1, 0), + (6643, 6, 404, 2, 0), + (6643, 7, 141, 1, 0), + (6660, 1, 325, 55, 0), + (6661, 1, 325, 60, 0), + (6662, 1, 325, 65, 0), + (6666, 1, 287, 2, 0), + (6666, 2, 139, 8001, 0), + (6666, 3, 385, 12529, 0), + (6667, 1, 287, 4, 0), + (6667, 2, 139, 8001, 0), + (6667, 3, 385, 12529, 0), + (6668, 1, 287, 2, 0), + (6668, 2, 139, 11251, 0), + (6668, 3, 139, 11252, 0), + (6668, 4, 139, 11253, 0), + (6669, 1, 287, 4, 0), + (6669, 2, 139, 11251, 0), + (6669, 3, 139, 11252, 0), + (6669, 4, 139, 11253, 0), + (6670, 1, 287, 6, 0), + (6670, 2, 139, 11251, 0), + (6670, 3, 139, 11252, 0), + (6670, 4, 139, 11253, 0), + (6697, 1, 264, 30, 857), + (6698, 1, 264, 60, 857), + (6699, 1, 264, 90, 857), + (6700, 1, 264, 120, 857), + (6701, 1, 264, 150, 857), + (6703, 1, 264, 10, 171), + (6704, 1, 264, 20, 171), + (6705, 1, 264, 30, 171), + (6709, 1, 127, 5, 0), + (6709, 2, 139, 3842, 0), + (6710, 1, 127, 10, 0), + (6710, 2, 139, 3842, 0), + (6711, 1, 127, 15, 0), + (6711, 2, 139, 3842, 0), + (6712, 1, 264, 30, 177), + (6713, 1, 264, 60, 177), + (6714, 1, 264, 90, 177), + (6715, 1, 264, 120, 177), + (6716, 1, 264, 150, 177), + (6751, 1, 310, 240000, 0), + (6751, 2, 139, 4519, 0), + (6752, 1, 310, 480000, 0), + (6752, 2, 139, 4519, 0), + (6753, 1, 310, 720000, 0), + (6753, 2, 139, 4519, 0), + (6761, 1, 292, 5, 0), + (6762, 1, 292, 10, 0), + (6763, 1, 292, 15, 0), + (6765, 1, 330, 15, 7), + (6766, 1, 330, 30, 7), + (6767, 1, 330, 50, 7), + (6768, 1, 310, 960000, 0), + (6768, 2, 139, 4519, 0), + (6769, 1, 310, 1200000, 0), + (6769, 2, 139, 4519, 0), + (6791, 1, 339, 20, 16139), + (6791, 2, 137, 21, 0), + (6791, 3, 385, -18000, 0), + (6791, 4, 339, 20, 16139), + (6791, 5, 137, 343, 0), + (6791, 6, 385, -18000, 0), + (6792, 1, 339, 20, 16140), + (6792, 2, 137, 21, 0), + (6792, 3, 385, -18000, 0), + (6792, 4, 339, 20, 16140), + (6792, 5, 137, 343, 0), + (6792, 6, 385, -18000, 0), + (6793, 1, 339, 20, 16141), + (6793, 2, 137, 21, 0), + (6793, 3, 385, -18000, 0), + (6793, 4, 339, 20, 16141), + (6793, 5, 137, 343, 0), + (6793, 6, 385, -18000, 0), + (6819, 1, 264, 180, 524), + (6820, 1, 264, 360, 524), + (6821, 1, 264, 540, 524), + (6823, 1, 264, 180, 320), + (6824, 1, 264, 360, 320), + (6825, 1, 264, 540, 320), + (6826, 1, 264, 720, 320), + (6827, 1, 264, 900, 320), + (6870, 1, 264, 180, 544), + (6871, 1, 264, 360, 544), + (6872, 1, 264, 540, 544), + (6873, 1, 279, 7, 0), + (6874, 1, 279, 11, 0), + (6875, 1, 279, 15, 0), + (6876, 1, 375, 107, 0), + (6877, 1, 375, 115, 0), + (6878, 1, 375, 125, 0), + (6879, 1, 243, 15, 0), + (6880, 1, 243, 25, 0), + (6881, 1, 243, 35, 0), + (6882, 1, 242, 5, 0), + (6883, 1, 242, 10, 0), + (6884, 1, 242, 15, 0), + (6900, 1, 264, 840, 465), + (6901, 1, 264, 1140, 465), + (6902, 1, 264, 1440, 465), + (6903, 1, 264, 1740, 465), + (6904, 1, 264, 2040, 465), + (6905, 1, 225, 33, 0), + (6906, 1, 225, 36, 0), + (6907, 1, 225, 39, 0), + (6908, 1, 264, 180, 499), + (6909, 1, 264, 360, 499), + (6910, 1, 264, 540, 499), + (6911, 1, 224, 60, 74), + (6911, 2, 173, 2, 0), + (6912, 1, 224, 70, 74), + (6912, 2, 173, 3, 0), + (6913, 1, 224, 80, 74), + (6913, 2, 173, 3, 0), + (6935, 1, 264, 180, 465), + (6936, 1, 264, 360, 465), + (6937, 1, 264, 540, 465), + (6938, 1, 361, 65, 16164), + (6939, 1, 361, 75, 16165), + (6940, 1, 361, 85, 16166), + (6941, 1, 264, 120, 962), + (6942, 1, 264, 240, 962), + (6943, 1, 264, 360, 962), + (6944, 1, 264, 480, 962), + (6945, 1, 264, 600, 962), + (6974, 1, 264, 3, 247), + (6974, 2, 264, 2, 986), + (6974, 3, 264, 2, 987), + (6974, 4, 264, 2, 988), + (6975, 1, 264, 6, 247), + (6975, 2, 264, 4, 986), + (6975, 3, 264, 4, 987), + (6975, 4, 264, 4, 988), + (6976, 1, 264, 12, 247), + (6976, 2, 264, 6, 986), + (6976, 3, 264, 6, 987), + (6976, 4, 264, 6, 988), + (6977, 1, 264, 6, 3817), + (6978, 1, 264, 12, 3817), + (6979, 1, 264, 18, 3817), + (6980, 1, 264, 45, 128), + (6981, 1, 264, 90, 128), + (6982, 1, 264, 135, 128), + (6987, 1, 353, 1, 0), + (6988, 1, 287, 1, 0), + (6988, 2, 385, 16439, 0), + (6988, 3, 411, 32768, 0), + (6989, 1, 287, 2, 0), + (6989, 2, 385, 16439, 0), + (6989, 3, 411, 32768, 0), + (6990, 1, 287, 3, 0), + (6990, 2, 385, 16439, 0), + (6990, 3, 411, 32768, 0), + (7005, 1, 264, 432, 789), + (7006, 1, 264, 864, 789), + (7007, 1, 264, 1296, 789), + (7008, 1, 439, 0, 109400), + (7008, 2, 345, 80, 35), + (7009, 1, 439, 0, 116800), + (7009, 2, 345, 82, 35), + (7010, 1, 378, 25, 96), + (7011, 1, 378, 30, 96), + (7012, 1, 378, 35, 96), + (7013, 1, 378, 40, 96), + (7014, 1, 378, 45, 96), + (7015, 1, 378, 50, 96), + (7033, 1, 421, 5, 0), + (7033, 2, 139, 16097, 0), + (7033, 3, 139, 23612, 0), + (7033, 4, 139, 32196, 0), + (7033, 5, 139, 32565, 0), + (7033, 6, 423, 6, 0), + (7033, 7, 422, 5, 0), + (7033, 8, 411, 2, 0), + (7034, 1, 421, 10, 0), + (7034, 2, 139, 16097, 0), + (7034, 3, 139, 23612, 0), + (7034, 4, 139, 32196, 0), + (7034, 5, 139, 32565, 0), + (7034, 6, 423, 6, 0), + (7034, 7, 422, 5, 0), + (7034, 8, 411, 2, 0), + (7035, 1, 421, 15, 0), + (7035, 2, 139, 16097, 0), + (7035, 3, 139, 23612, 0), + (7035, 4, 139, 32196, 0), + (7035, 5, 139, 32565, 0), + (7035, 6, 423, 6, 0), + (7035, 7, 422, 5, 0), + (7035, 8, 411, 2, 0), + (7036, 1, 264, 10, 3646), + (7037, 1, 264, 20, 3646), + (7038, 1, 264, 30, 3646), + (7050, 1, 265, 62, 0), + (7051, 1, 265, 64, 0), + (7052, 1, 265, 66, 0), + (7053, 1, 265, 67, 0), + (7054, 1, 265, 69, 0), + (7055, 1, 265, 71, 0), + (7056, 1, 265, 62, 0), + (7057, 1, 265, 64, 0), + (7058, 1, 265, 66, 0), + (7059, 1, 265, 67, 0), + (7060, 1, 265, 69, 0), + (7061, 1, 265, 71, 0), + (7062, 1, 372, 50, 0), + (7063, 1, 265, 72, 0), + (7064, 1, 265, 74, 0), + (7065, 1, 265, 76, 0), + (7066, 1, 265, 72, 0), + (7067, 1, 265, 74, 0), + (7068, 1, 265, 76, 0), + (7100, 1, 264, 180, 254), + (7101, 1, 264, 360, 254), + (7102, 1, 264, 540, 254), + (7103, 1, 264, 432, 286), + (7103, 2, 264, 432, 10753), + (7103, 3, 264, 432, 9101), + (7104, 1, 264, 864, 286), + (7104, 2, 264, 864, 10753), + (7104, 3, 264, 864, 9101), + (7105, 1, 264, 1296, 286), + (7105, 2, 264, 1296, 10753), + (7105, 3, 264, 1296, 9101), + (7106, 1, 224, 20, 30), + (7106, 2, 173, 1, 0), + (7107, 1, 224, 35, 30), + (7107, 2, 173, 2, 0), + (7108, 1, 224, 50, 30), + (7108, 2, 173, 3, 0), + (7112, 1, 85, 13596, 50), + (7113, 1, 85, 13597, 50), + (7114, 1, 85, 13598, 50), + (7116, 1, 264, 360, 110), + (7117, 1, 264, 450, 110), + (7118, 1, 264, 540, 110), + (7122, 1, 349, 30, 0), + (7123, 1, 349, 35, 0), + (7124, 1, 349, 40, 0), + (7125, 1, 349, 45, 0), + (7126, 1, 349, 50, 0), + (7128, 1, 264, 240, 109), + (7129, 1, 264, 300, 109), + (7130, 1, 264, 360, 109), + (7131, 1, 439, 0, 88880), + (7131, 2, 345, 74, 28), + (7132, 1, 439, 0, 95440), + (7132, 2, 345, 76, 28), + (7133, 1, 439, 0, 102280), + (7133, 2, 345, 78, 28), + (7134, 1, 220, 120, 8), + (7135, 1, 220, 140, 8), + (7136, 1, 220, 165, 8), + (7137, 1, 264, 60, 672), + (7138, 1, 264, 75, 672), + (7139, 1, 264, 90, 672), + (7146, 1, 252, 80, 0), + (7147, 1, 252, 85, 0), + (7148, 1, 216, 350, 8), + (7149, 1, 216, 400, 8), + (7150, 1, 216, 450, 8), + (7151, 1, 258, 59, 0), + (7152, 1, 258, 64, 0), + (7153, 1, 258, 69, 0), + (7160, 1, 227, 120, 32), + (7161, 1, 227, 150, 32), + (7162, 1, 227, 180, 32), + (7163, 1, 220, 130, 26), + (7163, 2, 220, 130, 30), + (7163, 3, 220, 130, 38), + (7164, 1, 220, 140, 26), + (7164, 2, 220, 140, 30), + (7164, 3, 220, 140, 38), + (7165, 1, 220, 150, 26), + (7165, 2, 220, 150, 30), + (7165, 3, 220, 150, 38), + (7166, 1, 264, 20, 468), + (7166, 2, 264, 20, 469), + (7166, 3, 264, 20, 470), + (7167, 1, 264, 25, 468), + (7167, 2, 264, 25, 469), + (7167, 3, 264, 25, 470), + (7168, 1, 264, 30, 468), + (7168, 2, 264, 30, 469), + (7168, 3, 264, 30, 470), + (7169, 1, 220, 135, 21), + (7169, 2, 220, 135, 23), + (7169, 3, 220, 270, 52), + (7169, 4, 220, 135, 28), + (7170, 1, 220, 145, 21), + (7170, 2, 220, 145, 23), + (7170, 3, 220, 290, 52), + (7170, 4, 220, 145, 28), + (7171, 1, 220, 155, 21), + (7171, 2, 220, 155, 23), + (7171, 3, 220, 310, 52), + (7171, 4, 220, 155, 28), + (7175, 1, 283, 120, 0), + (7176, 1, 283, 140, 0), + (7177, 1, 283, 160, 0), + (7196, 1, 169, 20, -1), + (7197, 1, 169, 25, -1), + (7198, 1, 169, 30, -1), + (7204, 1, 218, 11, 0), + (7205, 1, 218, 12, 0), + (7206, 1, 218, 13, 0), + (7207, 1, 218, 14, 0), + (7208, 1, 218, 15, 0), + (7210, 1, 280, 50, 0), + (7211, 1, 280, 53, 0), + (7212, 1, 280, 56, 0), + (7213, 1, 280, 59, 0), + (7214, 1, 280, 62, 0), + (7215, 1, 264, 4200, 68), + (7216, 1, 264, 4800, 68), + (7220, 1, 360, 60, 12701), + (7221, 1, 360, 60, 12702), + (7222, 1, 360, 60, 12703), + (7232, 1, 294, 0, 185), + (7233, 1, 294, 0, 190), + (7234, 1, 294, 0, 195), + (7260, 1, 287, 14, 0), + (7260, 2, 385, 2754, 1), + (7261, 1, 287, 16, 0), + (7261, 2, 385, 2754, 1), + (7262, 1, 287, 18, 0), + (7262, 2, 385, 2754, 1), + (7263, 1, 274, 18, 0), + (7264, 1, 274, 20, 0), + (7265, 1, 274, 22, 0), + (7267, 1, 280, 54, 0), + (7268, 1, 280, 55, 0), + (7269, 1, 280, 56, 0), + (7270, 1, 218, 16, 0), + (7271, 1, 218, 17, 0), + (7272, 1, 218, 18, 0), + (7273, 1, 218, 19, 0), + (7274, 1, 218, 20, 0), + (7279, 1, 310, 6000, 0), + (7279, 2, 139, 11903, 0), + (7279, 3, 310, 6000, 0), + (7279, 4, 139, 11904, 0), + (7279, 5, 310, 6000, 0), + (7279, 6, 139, 11905, 0), + (7279, 7, 310, 6000, 0), + (7279, 8, 139, 1362, 0), + (7279, 9, 310, 6000, 0), + (7279, 10, 139, 8032, 0), + (7279, 11, 310, 6000, 0), + (7279, 12, 385, 6131, 0), + (7279, 13, 385, 6231, 0), + (7279, 14, 385, 6331, 0), + (7279, 15, 385, 6431, 0), + (7279, 16, 385, 6531, 0), + (7279, 17, 385, 6631, 0), + (7280, 1, 310, 7000, 0), + (7280, 2, 139, 11903, 0), + (7280, 3, 310, 7000, 0), + (7280, 4, 139, 11904, 0), + (7280, 5, 310, 7000, 0), + (7280, 6, 139, 11905, 0), + (7280, 7, 310, 7000, 0), + (7280, 8, 139, 1362, 0), + (7280, 9, 310, 7000, 0), + (7280, 10, 139, 8032, 0), + (7280, 11, 310, 7000, 0), + (7280, 12, 385, 6131, 0), + (7280, 13, 385, 6231, 0), + (7280, 14, 385, 6331, 0), + (7280, 15, 385, 6431, 0), + (7280, 16, 385, 6531, 0), + (7280, 17, 385, 6631, 0), + (7281, 1, 310, 8000, 0), + (7281, 2, 139, 11903, 0), + (7281, 3, 310, 8000, 0), + (7281, 4, 139, 11904, 0), + (7281, 5, 310, 8000, 0), + (7281, 6, 139, 11905, 0), + (7281, 7, 310, 8000, 0), + (7281, 8, 139, 1362, 0), + (7281, 9, 310, 8000, 0), + (7281, 10, 139, 8032, 0), + (7281, 11, 310, 8000, 0), + (7281, 12, 385, 6131, 0), + (7281, 13, 385, 6231, 0), + (7281, 14, 385, 6331, 0), + (7281, 15, 385, 6431, 0), + (7281, 16, 385, 6531, 0), + (7281, 17, 385, 6631, 0), + (7282, 1, 310, 9000, 0), + (7282, 2, 139, 11903, 0), + (7282, 3, 310, 9000, 0), + (7282, 4, 139, 11904, 0), + (7282, 5, 310, 9000, 0), + (7282, 6, 139, 11905, 0), + (7282, 7, 310, 9000, 0), + (7282, 8, 139, 1362, 0), + (7282, 9, 310, 9000, 0), + (7282, 10, 139, 8032, 0), + (7282, 11, 310, 9000, 0), + (7282, 12, 385, 6131, 0), + (7282, 13, 385, 6231, 0), + (7282, 14, 385, 6331, 0), + (7282, 15, 385, 6431, 0), + (7282, 16, 385, 6531, 0), + (7282, 17, 385, 6631, 0), + (7283, 1, 310, 10000, 0), + (7283, 2, 139, 11903, 0), + (7283, 3, 310, 10000, 0), + (7283, 4, 139, 11904, 0), + (7283, 5, 310, 10000, 0), + (7283, 6, 139, 11905, 0), + (7283, 7, 310, 10000, 0), + (7283, 8, 139, 1362, 0), + (7283, 9, 310, 10000, 0), + (7283, 10, 139, 8032, 0), + (7283, 11, 310, 10000, 0), + (7283, 12, 385, 6131, 0), + (7283, 13, 385, 6231, 0), + (7283, 14, 385, 6331, 0), + (7283, 15, 385, 6431, 0), + (7283, 16, 385, 6531, 0), + (7283, 17, 385, 6631, 0), + (7284, 1, 287, 3, 0), + (7284, 2, 137, 31, 0), + (7284, 3, 136, 5, 0), + (7313, 1, 244, 40, 0), + (7314, 1, 244, 30, 0), + (7315, 1, 244, 20, 0), + (7316, 1, 264, 1080, 41), + (7317, 1, 264, 1260, 41), + (7318, 1, 339, 25, 16015), + (7318, 2, 137, 21, 0), + (7319, 1, 339, 25, 16016), + (7319, 2, 137, 21, 0), + (7320, 1, 339, 25, 16017), + (7320, 2, 137, 21, 0), + (7321, 1, 339, 25, 16018), + (7321, 2, 137, 21, 0), + (7322, 1, 339, 25, 16019), + (7322, 2, 137, 21, 0), + (7323, 1, 264, 720, 254), + (7324, 1, 264, 900, 254), + (7325, 1, 264, 1080, 254), + (7326, 1, 264, 1728, 286), + (7326, 2, 264, 1728, 10753), + (7326, 3, 264, 1728, 9101), + (7327, 1, 264, 2160, 286), + (7327, 2, 264, 2160, 10753), + (7327, 3, 264, 2160, 9101), + (7328, 1, 264, 2592, 286), + (7328, 2, 264, 2592, 10753), + (7328, 3, 264, 2592, 9101), + (7336, 1, 85, 16029, 0), + (7337, 1, 85, 16030, 0), + (7338, 1, 85, 16031, 0), + (7353, 1, 216, 115, 0), + (7353, 2, 216, 115, 1), + (7353, 3, 216, 115, 2), + (7353, 4, 216, 115, 3), + (7353, 5, 216, 115, 10), + (7353, 6, 216, 115, 28), + (7353, 7, 216, 115, 30), + (7353, 8, 216, 115, 36), + (7353, 9, 216, 115, 77), + (7354, 1, 216, 120, 0), + (7354, 2, 216, 120, 1), + (7354, 3, 216, 120, 2), + (7354, 4, 216, 120, 3), + (7354, 5, 216, 120, 10), + (7354, 6, 216, 120, 28), + (7354, 7, 216, 120, 30), + (7354, 8, 216, 120, 36), + (7354, 9, 216, 120, 77), + (7355, 1, 216, 125, 0), + (7355, 2, 216, 125, 1), + (7355, 3, 216, 125, 2), + (7355, 4, 216, 125, 3), + (7355, 5, 216, 125, 10), + (7355, 6, 216, 125, 28), + (7355, 7, 216, 125, 30), + (7355, 8, 216, 125, 36), + (7355, 9, 216, 125, 77), + (7356, 1, 360, 60, 16056), + (7357, 1, 360, 60, 16057), + (7358, 1, 360, 60, 16058), + (7359, 1, 217, 0, 82600), + (7359, 2, 346, 78, 22), + (7360, 1, 217, 0, 88880), + (7360, 2, 346, 80, 22), + (7361, 1, 217, 0, 95440), + (7361, 2, 346, 82, 22), + (7362, 1, 59, -18, 0), + (7363, 1, 59, -21, 0), + (7364, 1, 59, -24, 0), + (7365, 1, 59, -27, 0), + (7366, 1, 59, -30, 0), + (7373, 1, 2, 108, 0), + (7374, 1, 2, 112, 0), + (7375, 1, 2, 116, 0), + (7376, 1, 2, 120, 0), + (7377, 1, 2, 124, 0), + (7378, 1, 347, 14, 0), + (7379, 1, 347, 16, 0), + (7380, 1, 347, 18, 0), + (7381, 1, 347, 20, 0), + (7382, 1, 347, 22, 0), + (7383, 1, 347, 24, 0), + (7384, 1, 360, 25, 16063), + (7385, 1, 360, 25, 16064), + (7386, 1, 360, 25, 16065), + (7390, 1, 303, 6000, 6000), + (7390, 2, 139, 2766, 0), + (7391, 1, 303, 6500, 6500), + (7391, 2, 139, 2766, 0), + (7392, 1, 303, 7500, 8500), + (7392, 2, 139, 2766, 0), + (7393, 1, 85, 16066, 0), + (7394, 1, 85, 16067, 0), + (7395, 1, 85, 16068, 0), + (7396, 1, 85, 16069, 0), + (7397, 1, 85, 16070, 0), + (7398, 1, 85, 16071, 0), + (7399, 1, 302, 350, 350), + (7399, 2, 385, 99, 0), + (7400, 1, 302, 370, 370), + (7400, 2, 385, 99, 0), + (7401, 1, 302, 400, 400), + (7401, 2, 385, 99, 0), + (7402, 1, 59, -33, 0), + (7403, 1, 59, -36, 0), + (7404, 1, 59, -39, 0), + (7405, 1, 59, -42, 0), + (7406, 1, 59, -45, 0), + (7407, 1, 181, 100, -1), + (7448, 1, 264, 240, 553), + (7449, 1, 264, 300, 553), + (7450, 1, 264, 360, 553), + (7451, 1, 264, 720, 777), + (7452, 1, 264, 900, 777), + (7453, 1, 264, 1080, 777), + (7478, 1, 264, 2880, 245), + (7489, 1, 218, 16, 0), + (7490, 1, 218, 17, 0), + (7491, 1, 218, 18, 0), + (7492, 1, 218, 19, 0), + (7493, 1, 218, 20, 0), + (7494, 1, 280, 65, 0), + (7495, 1, 280, 66, 0), + (7496, 1, 280, 67, 0), + (7500, 1, 363, 3, 0), + (7501, 1, 172, 45, 0), + (7502, 1, 172, 46, 0), + (7503, 1, 172, 47, 0), + (7504, 1, 172, 48, 0), + (7505, 1, 172, 49, 0), + (7506, 1, 259, 51, 0), + (7507, 1, 259, 52, 0), + (7508, 1, 259, 53, 0), + (7509, 1, 259, 54, 0), + (7510, 1, 259, 55, 0), + (7511, 1, 328, 1050, 0), + (7512, 1, 328, 1100, 0), + (7513, 1, 328, 1150, 0), + (7514, 1, 328, 1200, 0), + (7515, 1, 328, 1250, 0), + (7516, 1, 262, 30, 7), + (7516, 2, 262, 30, 8), + (7516, 3, 262, 30, 9), + (7516, 4, 262, 30, 10), + (7516, 5, 262, 30, 11), + (7517, 1, 262, 35, 7), + (7517, 2, 262, 35, 8), + (7517, 3, 262, 35, 9), + (7517, 4, 262, 35, 10), + (7517, 5, 262, 35, 11), + (7518, 1, 262, 40, 7), + (7518, 2, 262, 40, 8), + (7518, 3, 262, 40, 9), + (7518, 4, 262, 40, 10), + (7518, 5, 262, 40, 11), + (7519, 1, 262, 45, 7), + (7519, 2, 262, 45, 8), + (7519, 3, 262, 45, 9), + (7519, 4, 262, 45, 10), + (7519, 5, 262, 45, 11), + (7520, 1, 262, 50, 7), + (7520, 2, 262, 50, 8), + (7520, 3, 262, 50, 9), + (7520, 4, 262, 50, 10), + (7520, 5, 262, 50, 11), + (7521, 1, 317, 11, 0), + (7522, 1, 317, 12, 0), + (7523, 1, 317, 13, 0), + (7524, 1, 317, 14, 0), + (7525, 1, 317, 15, 0), + (7526, 1, 69, 600, 0), + (7527, 1, 69, 700, 0), + (7528, 1, 69, 800, 0), + (7529, 1, 69, 900, 0), + (7530, 1, 69, 1000, 0), + (7534, 1, 0, 21, 0), + (7535, 1, 0, 22, 0), + (7536, 1, 0, 23, 0), + (7537, 1, 0, 24, 0), + (7538, 1, 0, 25, 0), + (7539, 1, 327, 8, 0), + (7540, 1, 327, 9, 0), + (7541, 1, 214, 1100, 0), + (7542, 1, 214, 1200, 0), + (7543, 1, 214, 1300, 0), + (7544, 1, 221, 27, 0), + (7545, 1, 221, 30, 0), + (7546, 1, 221, 33, 0), + (7547, 1, 262, 80, 0), + (7547, 2, 262, 80, 1), + (7547, 3, 262, 80, 2), + (7547, 4, 262, 80, 3), + (7547, 5, 262, 80, 4), + (7547, 6, 262, 80, 5), + (7547, 7, 262, 80, 6), + (7548, 1, 262, 85, 0), + (7548, 2, 262, 85, 1), + (7548, 3, 262, 85, 2), + (7548, 4, 262, 85, 3), + (7548, 5, 262, 85, 4), + (7548, 6, 262, 85, 5), + (7548, 7, 262, 85, 6), + (7549, 1, 262, 90, 0), + (7549, 2, 262, 90, 1), + (7549, 3, 262, 90, 2), + (7549, 4, 262, 90, 3), + (7549, 5, 262, 90, 4), + (7549, 6, 262, 90, 5), + (7549, 7, 262, 90, 6), + (7550, 1, 262, 95, 0), + (7550, 2, 262, 95, 1), + (7550, 3, 262, 95, 2), + (7550, 4, 262, 95, 3), + (7550, 5, 262, 95, 4), + (7550, 6, 262, 95, 5), + (7550, 7, 262, 95, 6), + (7551, 1, 262, 100, 0), + (7551, 2, 262, 100, 1), + (7551, 3, 262, 100, 2), + (7551, 4, 262, 100, 3), + (7551, 5, 262, 100, 4), + (7551, 6, 262, 100, 5), + (7551, 7, 262, 100, 6), + (7553, 1, 326, 3, 0), + (7554, 1, 339, 20, 16194), + (7554, 2, 138, 1, 0), + (7554, 3, 141, 1, 0), + (7554, 4, 142, 65, 0), + (7554, 5, 137, 0, 0), + (7554, 6, 311, 0, 0), + (7554, 7, 134, 85, 0), + (7554, 8, 139, -265, 0), + (7554, 9, 139, -754, 0), + (7554, 10, 139, -1332, 0), + (7554, 11, 139, -1572, 0), + (7554, 12, 139, -2749, 0), + (7554, 13, 139, -4979, 0), + (7554, 14, 139, -5418, 0), + (7554, 15, 139, -5403, 0), + (7554, 16, 348, 10, 0), + (7555, 1, 339, 21, 16195), + (7555, 2, 138, 1, 0), + (7555, 3, 141, 1, 0), + (7555, 4, 142, 65, 0), + (7555, 5, 137, 0, 0), + (7555, 6, 311, 0, 0), + (7555, 7, 134, 85, 0), + (7555, 8, 139, -265, 0), + (7555, 9, 139, -754, 0), + (7555, 10, 139, -1332, 0), + (7555, 11, 139, -1572, 0), + (7555, 12, 139, -2749, 0), + (7555, 13, 139, -4979, 0), + (7555, 14, 139, -5418, 0), + (7555, 15, 139, -5403, 0), + (7555, 16, 348, 10, 0), + (7556, 1, 339, 22, 16196), + (7556, 2, 138, 1, 0), + (7556, 3, 141, 1, 0), + (7556, 4, 142, 65, 0), + (7556, 5, 137, 0, 0), + (7556, 6, 311, 0, 0), + (7556, 7, 134, 85, 0), + (7556, 8, 139, -265, 0), + (7556, 9, 139, -754, 0), + (7556, 10, 139, -1332, 0), + (7556, 11, 139, -1572, 0), + (7556, 12, 139, -2749, 0), + (7556, 13, 139, -4979, 0), + (7556, 14, 139, -5418, 0), + (7556, 15, 139, -5403, 0), + (7556, 16, 348, 10, 0), + (7557, 1, 339, 23, 16417), + (7557, 2, 138, 1, 0), + (7557, 3, 141, 1, 0), + (7557, 4, 142, 65, 0), + (7557, 5, 137, 0, 0), + (7557, 6, 311, 0, 0), + (7557, 7, 134, 85, 0), + (7557, 8, 139, -265, 0), + (7557, 9, 139, -754, 0), + (7557, 10, 139, -1332, 0), + (7557, 11, 139, -1572, 0), + (7557, 12, 139, -2749, 0), + (7557, 13, 139, -4979, 0), + (7557, 14, 139, -5418, 0), + (7557, 15, 139, -5403, 0), + (7557, 16, 348, 10, 0), + (7558, 1, 339, 24, 16418), + (7558, 2, 138, 1, 0), + (7558, 3, 141, 1, 0), + (7558, 4, 142, 65, 0), + (7558, 5, 137, 0, 0), + (7558, 6, 311, 0, 0), + (7558, 7, 134, 85, 0), + (7558, 8, 139, -265, 0), + (7558, 9, 139, -754, 0), + (7558, 10, 139, -1332, 0), + (7558, 11, 139, -1572, 0), + (7558, 12, 139, -2749, 0), + (7558, 13, 139, -4979, 0), + (7558, 14, 139, -5418, 0), + (7558, 15, 139, -5403, 0), + (7558, 16, 348, 10, 0), + (7559, 1, 266, 23, 0), + (7560, 1, 266, 24, 0), + (7561, 1, 266, 25, 0), + (7562, 1, 330, 125, 0), + (7562, 2, 330, 125, 1), + (7562, 3, 330, 125, 2), + (7562, 4, 330, 125, 3), + (7562, 5, 330, 125, 28), + (7562, 6, 330, 125, 36), + (7562, 7, 330, 125, 77), + (7563, 1, 330, 130, 0), + (7563, 2, 330, 130, 1), + (7563, 3, 330, 130, 2), + (7563, 4, 330, 130, 3), + (7563, 5, 330, 130, 28), + (7563, 6, 330, 130, 36), + (7563, 7, 330, 130, 77), + (7564, 1, 330, 135, 0), + (7564, 2, 330, 135, 1), + (7564, 3, 330, 135, 2), + (7564, 4, 330, 135, 3), + (7564, 5, 330, 135, 28), + (7564, 6, 330, 135, 36), + (7564, 7, 330, 135, 77), + (7565, 1, 278, 800, 54510), + (7565, 2, 440, 76, 100), + (7566, 1, 278, 850, 58400), + (7566, 2, 440, 78, 100), + (7567, 1, 278, 900, 62680), + (7567, 2, 440, 80, 100), + (7568, 1, 341, 160, 0), + (7569, 1, 341, 170, 0), + (7570, 1, 341, 180, 0), + (7571, 1, 341, 190, 0), + (7572, 1, 341, 200, 0), + (7573, 1, 360, 70, 11023), + (7574, 1, 360, 80, 11023), + (7575, 1, 360, 90, 11023), + (7576, 1, 318, 16, 0), + (7577, 1, 318, 17, 0), + (7578, 1, 318, 18, 0), + (7579, 1, 318, 19, 0), + (7580, 1, 318, 20, 0), + (7581, 1, 294, 0, 160), + (7582, 1, 294, 0, 165), + (7583, 1, 294, 0, 170), + (7584, 1, 114, -60, 0), + (7585, 1, 114, -61, 0), + (7586, 1, 114, -62, 0), + (7587, 1, 319, 22, 0), + (7588, 1, 319, 23, 0), + (7589, 1, 319, 24, 0), + (7590, 1, 274, 35, 0), + (7591, 1, 274, 36, 0), + (7592, 1, 274, 37, 0), + (7593, 1, 15, 14, 0), + (7594, 1, 15, 15, 0), + (7595, 1, 15, 16, 0), + (7596, 1, 15, 17, 0), + (7597, 1, 15, 18, 0), + (7598, 1, 114, -60, 0), + (7599, 1, 114, -61, 0), + (7600, 1, 114, -62, 0), + (7601, 1, 213, 7, 0), + (7602, 1, 213, 9, 0), + (7603, 1, 213, 11, 0), + (7604, 1, 189, 14, 0), + (7605, 1, 189, 15, 0), + (7612, 1, 270, 70, 0), + (7613, 1, 270, 75, 0), + (7614, 1, 270, 80, 0), + (7615, 1, 264, 720, 494), + (7616, 1, 264, 900, 494), + (7617, 1, 264, 1080, 494), + (7618, 1, 264, 720, 500), + (7619, 1, 264, 900, 500), + (7620, 1, 264, 1080, 500), + (7621, 1, 339, 10, 8105), + (7621, 2, 142, 65, 0), + (7621, 3, 311, 0, 0), + (7621, 4, 134, 70, 0), + (7621, 5, 348, 10, 0), + (7621, 6, 137, 0, 0), + (7621, 7, 339, 10, 8105), + (7621, 8, 142, 65, 0), + (7621, 9, 311, 0, 0), + (7621, 10, 134, 70, 0), + (7621, 11, 348, 10, 0), + (7621, 12, 137, 100, 0), + (7621, 13, 339, 10, 8105), + (7621, 14, 142, 65, 0), + (7621, 15, 311, 0, 0), + (7621, 16, 134, 70, 0), + (7621, 17, 348, 10, 0), + (7621, 18, 137, 79, 0), + (7621, 19, 339, 10, 8105), + (7621, 20, 142, 65, 0), + (7621, 21, 311, 0, 0), + (7621, 22, 134, 70, 0), + (7621, 23, 348, 10, 0), + (7621, 24, 137, 147, 0), + (7621, 25, 339, 10, 11404), + (7621, 26, 142, 71, 0), + (7621, 27, 311, 0, 0), + (7621, 28, 134, 75, 0), + (7621, 29, 348, 10, 0), + (7621, 30, 137, 0, 0), + (7621, 31, 339, 10, 11404), + (7621, 32, 142, 71, 0), + (7621, 33, 311, 0, 0), + (7621, 34, 134, 75, 0), + (7621, 35, 348, 10, 0), + (7621, 36, 137, 100, 0), + (7621, 37, 339, 10, 11404), + (7621, 38, 142, 71, 0), + (7621, 39, 311, 0, 0), + (7621, 40, 134, 75, 0), + (7621, 41, 348, 10, 0), + (7621, 42, 137, 79, 0), + (7621, 43, 339, 10, 11404), + (7621, 44, 142, 71, 0), + (7621, 45, 311, 0, 0), + (7621, 46, 134, 75, 0), + (7621, 47, 348, 10, 0), + (7621, 48, 137, 147, 0), + (7621, 49, 339, 10, 13199), + (7621, 50, 142, 76, 0), + (7621, 51, 311, 0, 0), + (7621, 52, 134, 80, 0), + (7621, 53, 348, 10, 0), + (7621, 54, 137, 0, 0), + (7621, 55, 339, 10, 13199), + (7621, 56, 142, 76, 0), + (7621, 57, 311, 0, 0), + (7621, 58, 134, 80, 0), + (7621, 59, 348, 10, 0), + (7621, 60, 137, 100, 0), + (7621, 61, 339, 10, 13199), + (7621, 62, 142, 76, 0), + (7621, 63, 311, 0, 0), + (7621, 64, 134, 80, 0), + (7621, 65, 348, 10, 0), + (7621, 66, 137, 79, 0), + (7621, 67, 339, 10, 13199), + (7621, 68, 142, 76, 0), + (7621, 69, 311, 0, 0), + (7621, 70, 134, 80, 0), + (7621, 71, 348, 10, 0), + (7621, 72, 137, 147, 0), + (7621, 73, 339, 10, 13830), + (7621, 74, 142, 81, 0), + (7621, 75, 311, 0, 0), + (7621, 76, 134, 85, 0), + (7621, 77, 348, 10, 0), + (7621, 78, 137, 0, 0), + (7621, 79, 339, 10, 13830), + (7621, 80, 142, 81, 0), + (7621, 81, 311, 0, 0), + (7621, 82, 134, 85, 0), + (7621, 83, 348, 10, 0), + (7621, 84, 137, 100, 0), + (7621, 85, 339, 10, 13830), + (7621, 86, 142, 81, 0), + (7621, 87, 311, 0, 0), + (7621, 88, 134, 85, 0), + (7621, 89, 348, 10, 0), + (7621, 90, 137, 79, 0), + (7621, 91, 339, 10, 13830), + (7621, 92, 142, 81, 0), + (7621, 93, 311, 0, 0), + (7621, 94, 134, 85, 0), + (7621, 95, 348, 10, 0), + (7621, 96, 137, 147, 0), + (7622, 1, 265, 79, 0), + (7623, 1, 265, 80, 0), + (7624, 1, 265, 81, 0), + (7625, 1, 265, 79, 0), + (7626, 1, 265, 80, 0), + (7627, 1, 265, 81, 0), + (7628, 1, 292, 46, 0), + (7629, 1, 292, 47, 0), + (7630, 1, 292, 48, 0), + (7631, 1, 279, 34, 0), + (7632, 1, 279, 35, 0), + (7633, 1, 279, 36, 0), + (7634, 1, 279, 34, 0), + (7635, 1, 279, 35, 0), + (7636, 1, 279, 36, 0), + (7637, 1, 279, 34, 0), + (7638, 1, 279, 35, 0), + (7639, 1, 279, 36, 0), + (7640, 1, 200, 60, 0), + (7641, 1, 294, 17, 100), + (7642, 1, 294, 19, 100), + (7643, 1, 294, 21, 100), + (7644, 1, 375, 130, 0), + (7645, 1, 375, 135, 0), + (7646, 1, 375, 140, 0), + (7647, 1, 229, 20, 0), + (7648, 1, 229, 25, 0), + (7649, 1, 229, 30, 0), + (7650, 1, 330, 125, 0), + (7650, 2, 330, 125, 1), + (7650, 3, 330, 125, 2), + (7650, 4, 330, 125, 3), + (7650, 5, 330, 125, 28), + (7650, 6, 330, 125, 36), + (7651, 1, 330, 130, 0), + (7651, 2, 330, 130, 1), + (7651, 3, 330, 130, 2), + (7651, 4, 330, 130, 3), + (7651, 5, 330, 130, 28), + (7651, 6, 330, 130, 36), + (7652, 1, 330, 135, 0), + (7652, 2, 330, 135, 1), + (7652, 3, 330, 135, 2), + (7652, 4, 330, 135, 3), + (7652, 5, 330, 135, 28), + (7652, 6, 330, 135, 36), + (7653, 1, 330, 125, 0), + (7653, 2, 330, 125, 1), + (7653, 3, 330, 125, 2), + (7653, 4, 330, 125, 3), + (7653, 5, 330, 125, 28), + (7653, 6, 330, 125, 36), + (7653, 7, 330, 125, 77), + (7654, 1, 330, 130, 0), + (7654, 2, 330, 130, 1), + (7654, 3, 330, 130, 2), + (7654, 4, 330, 130, 3), + (7654, 5, 330, 130, 28), + (7654, 6, 330, 130, 36), + (7654, 7, 330, 130, 77), + (7655, 1, 330, 135, 0), + (7655, 2, 330, 135, 1), + (7655, 3, 330, 135, 2), + (7655, 4, 330, 135, 3), + (7655, 5, 330, 135, 28), + (7655, 6, 330, 135, 36), + (7655, 7, 330, 135, 77), + (7656, 1, 330, 100, 0), + (7656, 2, 330, 100, 1), + (7656, 3, 330, 100, 2), + (7656, 4, 330, 100, 3), + (7656, 5, 330, 100, 28), + (7656, 6, 330, 100, 36), + (7656, 7, 330, 100, 77), + (7657, 1, 330, 105, 0), + (7657, 2, 330, 105, 1), + (7657, 3, 330, 105, 2), + (7657, 4, 330, 105, 3), + (7657, 5, 330, 105, 28), + (7657, 6, 330, 105, 36), + (7657, 7, 330, 105, 77), + (7658, 1, 330, 110, 0), + (7658, 2, 330, 110, 1), + (7658, 3, 330, 110, 2), + (7658, 4, 330, 110, 3), + (7658, 5, 330, 110, 28), + (7658, 6, 330, 110, 36), + (7658, 7, 330, 110, 77), + (7659, 1, 264, 72, 153), + (7660, 1, 264, 90, 153), + (7661, 1, 264, 108, 153), + (7663, 1, 375, 150, 0), + (7664, 1, 264, 10, 170), + (7665, 1, 264, 20, 170), + (7666, 1, 264, 30, 170), + (7667, 1, 264, 40, 170), + (7668, 1, 264, 50, 170), + (7670, 1, 229, 35, 0), + (7671, 1, 229, 40, 0), + (7672, 1, 229, 45, 0), + (7673, 1, 220, 50, 10), + (7674, 1, 220, 65, 10), + (7675, 1, 220, 80, 10), + (7676, 1, 220, 95, 10), + (7677, 1, 220, 110, 10), + (7678, 1, 231, 11, 0), + (7679, 1, 231, 13, 0), + (7680, 1, 231, 15, 0), + (7681, 1, 326, 4, 0), + (7682, 1, 264, 5400, 68), + (7683, 1, 327, 10, 0), + (7684, 1, 327, 11, 0), + (7685, 1, 327, 12, 0), + (7686, 1, 349, 55, 0), + (7687, 1, 349, 60, 0), + (7688, 1, 349, 65, 0), + (7690, 1, 353, 1, 0), + (7692, 1, 319, 25, 0), + (7693, 1, 319, 26, 0), + (7694, 1, 319, 27, 0), + (7695, 1, 127, 5, 0), + (7695, 2, 385, 14232, 0), + (7696, 1, 127, 10, 0), + (7696, 2, 385, 14232, 0), + (7697, 1, 127, 15, 0), + (7697, 2, 385, 14232, 0), + (7699, 1, 181, 100, 0), + (7700, 1, 279, 7, 0), + (7701, 1, 279, 11, 0), + (7702, 1, 279, 15, 0), + (7704, 1, 264, 540, 3707), + (7705, 1, 264, 720, 3707), + (7706, 1, 264, 900, 3707), + (7707, 1, 303, 8500, 9500), + (7707, 2, 139, 2766, 0), + (7708, 1, 303, 9500, 11000), + (7708, 2, 139, 2766, 0), + (7709, 1, 303, 11000, 14000), + (7709, 2, 139, 2766, 0), + (7713, 1, 274, 34, 0), + (7714, 1, 274, 36, 0), + (7715, 1, 264, 2, 901), + (7716, 1, 264, 4, 901), + (7717, 1, 264, 6, 901), + (7718, 1, 281, 90, 0), + (7722, 1, 339, 25, 23492), + (7722, 2, 138, 1, 0), + (7722, 3, 141, 1, 0), + (7722, 4, 142, 70, 0), + (7722, 5, 137, 0, 0), + (7722, 6, 311, 0, 0), + (7722, 7, 134, 90, 0), + (7722, 8, 139, -265, 0), + (7722, 9, 139, -754, 0), + (7722, 10, 139, -1332, 0), + (7722, 11, 139, -1572, 0), + (7722, 12, 139, -2749, 0), + (7722, 13, 139, -4979, 0), + (7722, 14, 139, -5418, 0), + (7722, 15, 139, -5403, 0), + (7722, 16, 348, 10, 0), + (7723, 1, 339, 26, 23493), + (7723, 2, 138, 1, 0), + (7723, 3, 141, 1, 0), + (7723, 4, 142, 70, 0), + (7723, 5, 137, 0, 0), + (7723, 6, 311, 0, 0), + (7723, 7, 134, 90, 0), + (7723, 8, 139, -265, 0), + (7723, 9, 139, -754, 0), + (7723, 10, 139, -1332, 0), + (7723, 11, 139, -1572, 0), + (7723, 12, 139, -2749, 0), + (7723, 13, 139, -4979, 0), + (7723, 14, 139, -5418, 0), + (7723, 15, 139, -5403, 0), + (7723, 16, 348, 10, 0), + (7724, 1, 339, 27, 23494), + (7724, 2, 138, 1, 0), + (7724, 3, 141, 1, 0), + (7724, 4, 142, 70, 0), + (7724, 5, 137, 0, 0), + (7724, 6, 311, 0, 0), + (7724, 7, 134, 90, 0), + (7724, 8, 139, -265, 0), + (7724, 9, 139, -754, 0), + (7724, 10, 139, -1332, 0), + (7724, 11, 139, -1572, 0), + (7724, 12, 139, -2749, 0), + (7724, 13, 139, -4979, 0), + (7724, 14, 139, -5418, 0), + (7724, 15, 139, -5403, 0), + (7724, 16, 348, 10, 0), + (7725, 1, 339, 28, 23495), + (7725, 2, 138, 1, 0), + (7725, 3, 141, 1, 0), + (7725, 4, 142, 70, 0), + (7725, 5, 137, 0, 0), + (7725, 6, 311, 0, 0), + (7725, 7, 134, 90, 0), + (7725, 8, 139, -265, 0), + (7725, 9, 139, -754, 0), + (7725, 10, 139, -1332, 0), + (7725, 11, 139, -1572, 0), + (7725, 12, 139, -2749, 0), + (7725, 13, 139, -4979, 0), + (7725, 14, 139, -5418, 0), + (7725, 15, 139, -5403, 0), + (7725, 16, 348, 10, 0), + (7726, 1, 339, 29, 23496), + (7726, 2, 138, 1, 0), + (7726, 3, 141, 1, 0), + (7726, 4, 142, 70, 0), + (7726, 5, 137, 0, 0), + (7726, 6, 311, 0, 0), + (7726, 7, 134, 90, 0), + (7726, 8, 139, -265, 0), + (7726, 9, 139, -754, 0), + (7726, 10, 139, -1332, 0), + (7726, 11, 139, -1572, 0), + (7726, 12, 139, -2749, 0), + (7726, 13, 139, -4979, 0), + (7726, 14, 139, -5418, 0), + (7726, 15, 139, -5403, 0), + (7726, 16, 348, 10, 0), + (7733, 1, 257, 1, 0), + (7733, 2, 267, 1, 31), + (7733, 3, 267, 1, 32), + (7733, 4, 267, 1, 33), + (7733, 5, 267, 1, 15), + (7733, 6, 267, 1, 16), + (7733, 7, 267, 1, 17), + (7733, 8, 267, 1, 18), + (7733, 9, 267, 1, 19), + (7733, 10, 267, 1, 20), + (7743, 1, 264, 90, 184), + (7744, 1, 264, 180, 184), + (7745, 1, 264, 270, 184), + (7746, 1, 310, 2000, 0), + (7746, 2, 385, 11233, 0), + (7746, 3, 385, 11333, 0), + (7746, 4, 411, 16, 0), + (7748, 1, 271, 5, 0), + (7749, 1, 271, 10, 0), + (7750, 1, 271, 15, 0), + (7751, 1, 264, 60, 2234), + (7752, 1, 264, 120, 2234), + (7753, 1, 264, 180, 2234), + (7757, 1, 264, 120, 9403), + (7758, 1, 264, 240, 9403), + (7759, 1, 264, 360, 9403), + (7760, 1, 264, 2, 824), + (7761, 1, 264, 4, 824), + (7762, 1, 264, 6, 824), + (7763, 1, 310, 4000, 0), + (7763, 2, 385, 11233, 0), + (7763, 3, 385, 11333, 0), + (7763, 4, 411, 16, 0), + (7764, 1, 310, 6000, 0), + (7764, 2, 385, 11233, 0), + (7764, 3, 385, 11333, 0), + (7764, 4, 411, 16, 0), + (7765, 1, 392, 1000, 0), + (7765, 2, 139, 21820, 0), + (7765, 3, 411, 4, 0), + (7766, 1, 392, 2000, 0), + (7766, 2, 139, 21820, 0), + (7766, 3, 411, 4, 0), + (7767, 1, 392, 3000, 0), + (7767, 2, 139, 21820, 0), + (7767, 3, 411, 4, 0), + (7768, 1, 392, 4000, 0), + (7768, 2, 139, 21820, 0), + (7768, 3, 411, 4, 0), + (7818, 1, 288, 200, 51), + (7818, 2, 288, 50, 51), + (7819, 1, 405, 7, 0), + (7820, 1, 405, 9, 0), + (7821, 1, 405, 11, 0), + (7822, 1, 264, 1, 1154), + (7823, 1, 264, 2, 1154), + (7824, 1, 264, 3, 1154), + (7825, 1, 264, 4, 1154), + (7826, 1, 264, 5, 1154), + (7827, 1, 398, 9000, 0), + (7827, 2, 385, 7225, 0), + (7827, 3, 385, 7325, 0), + (7827, 4, 385, 7425, 0), + (7828, 1, 310, 2000, 0), + (7828, 2, 385, 7225, 0), + (7828, 3, 385, 7325, 0), + (7828, 4, 385, 7425, 0), + (7828, 5, 385, 7525, 0), + (7828, 6, 385, 7625, 0), + (7829, 1, 310, 4000, 0), + (7829, 2, 385, 7225, 0), + (7829, 3, 385, 7325, 0), + (7829, 4, 385, 7425, 0), + (7829, 5, 385, 7525, 0), + (7829, 6, 385, 7625, 0), + (7830, 1, 310, 6000, 0), + (7830, 2, 385, 7225, 0), + (7830, 3, 385, 7325, 0), + (7830, 4, 385, 7425, 0), + (7830, 5, 385, 7525, 0), + (7830, 6, 385, 7625, 0), + (7832, 1, 264, 60, 60), + (7833, 2, 264, 120, 60), + (7834, 3, 264, 180, 60), + (7835, 4, 264, 240, 60), + (7836, 5, 264, 300, 60), + (7837, 1, 262, 55, 7), + (7837, 2, 262, 55, 8), + (7837, 3, 262, 55, 9), + (7837, 4, 262, 55, 10), + (7837, 5, 262, 55, 11), + (7838, 1, 262, 60, 7), + (7838, 2, 262, 60, 8), + (7838, 3, 262, 60, 9), + (7838, 4, 262, 60, 10), + (7838, 5, 262, 60, 11), + (7839, 1, 262, 65, 7), + (7839, 2, 262, 65, 8), + (7839, 3, 262, 65, 9), + (7839, 4, 262, 65, 10), + (7839, 5, 262, 65, 11), + (7840, 1, 262, 70, 7), + (7840, 2, 262, 70, 8), + (7840, 3, 262, 70, 9), + (7840, 4, 262, 70, 10), + (7840, 5, 262, 70, 11), + (7841, 1, 262, 75, 7), + (7841, 2, 262, 75, 8), + (7841, 3, 262, 75, 9), + (7841, 4, 262, 75, 10), + (7841, 5, 262, 75, 11), + (7842, 1, 339, 30, 27695), + (7842, 2, 138, 1, 0), + (7842, 3, 141, 1, 0), + (7842, 4, 142, 70, 0), + (7842, 5, 137, 0, 0), + (7842, 6, 311, 0, 0), + (7842, 7, 134, 100, 0), + (7842, 8, 139, -265, 0), + (7842, 9, 139, -754, 0), + (7842, 10, 139, -1332, 0), + (7842, 11, 139, -1572, 0), + (7842, 12, 139, -2749, 0), + (7842, 13, 139, -4979, 0), + (7842, 14, 139, -5418, 0), + (7842, 15, 139, -5403, 0), + (7842, 16, 348, 10, 0), + (7843, 1, 339, 31, 27696), + (7843, 2, 138, 1, 0), + (7843, 3, 141, 1, 0), + (7843, 4, 142, 70, 0), + (7843, 5, 137, 0, 0), + (7843, 6, 311, 0, 0), + (7843, 7, 134, 100, 0), + (7843, 8, 139, -265, 0), + (7843, 9, 139, -754, 0), + (7843, 10, 139, -1332, 0), + (7843, 11, 139, -1572, 0), + (7843, 12, 139, -2749, 0), + (7843, 13, 139, -4979, 0), + (7843, 14, 139, -5418, 0), + (7843, 15, 139, -5403, 0), + (7843, 16, 348, 10, 0), + (7844, 1, 339, 32, 27697), + (7844, 2, 138, 1, 0), + (7844, 3, 141, 1, 0), + (7844, 4, 142, 70, 0), + (7844, 5, 137, 0, 0), + (7844, 6, 311, 0, 0), + (7844, 7, 134, 100, 0), + (7844, 8, 139, -265, 0), + (7844, 9, 139, -754, 0), + (7844, 10, 139, -1332, 0), + (7844, 11, 139, -1572, 0), + (7844, 12, 139, -2749, 0), + (7844, 13, 139, -4979, 0), + (7844, 14, 139, -5418, 0), + (7844, 15, 139, -5403, 0), + (7844, 16, 348, 10, 0), + (7881, 1, 405, 13, 0), + (7882, 1, 405, 15, 0), + (7883, 1, 405, 17, 0), + (7884, 1, 287, 1, 0), + (7884, 2, 139, 4691, 0), + (7884, 3, 411, 128, 0), + (7885, 1, 287, 1, 0), + (7885, 2, 385, 8111, 0), + (7885, 3, 385, 15008, 0), + (7885, 4, 385, 8411, 0), + (7885, 5, 385, 8511, 0), + (7885, 6, 411, 128, 0), + (7886, 1, 328, 1300, 0), + (7887, 1, 328, 1350, 0), + (7888, 1, 328, 1400, 0), + (7889, 1, 328, 1450, 0), + (7890, 1, 328, 1500, 0), + (7900, 1, 339, 45, 16189), + (7900, 2, 136, 11, 0), + (7900, 3, 383, 45, 16189), + (7900, 4, 385, 11012, 0), + (7900, 5, 383, 45, 16189), + (7900, 6, 385, 5130, 0), + (7900, 7, 383, 45, 16189), + (7900, 8, 385, 5230, 0), + (7900, 9, 383, 45, 16189), + (7900, 10, 136, 22, 0), + (7900, 11, 383, 45, 16189), + (7900, 12, 385, 5330, 0), + (7900, 13, 385, 5430, 0), + (7900, 14, 385, 5530, 0), + (7901, 1, 339, 45, 16190), + (7901, 2, 136, 11, 0), + (7901, 3, 383, 45, 16190), + (7901, 4, 385, 11012, 0), + (7901, 5, 383, 45, 16190), + (7901, 6, 385, 5130, 0), + (7901, 7, 383, 45, 16190), + (7901, 8, 385, 5230, 0), + (7901, 9, 383, 45, 16190), + (7901, 10, 136, 22, 0), + (7901, 11, 383, 45, 16190), + (7901, 12, 385, 5330, 0), + (7901, 13, 385, 5430, 0), + (7901, 14, 385, 5530, 0), + (7902, 1, 339, 45, 16191), + (7902, 2, 136, 11, 0), + (7902, 3, 383, 45, 16191), + (7902, 4, 385, 11012, 0), + (7902, 5, 383, 45, 16191), + (7902, 6, 385, 5130, 0), + (7902, 7, 383, 45, 16191), + (7902, 8, 385, 5230, 0), + (7902, 9, 383, 45, 16191), + (7902, 10, 136, 22, 0), + (7902, 11, 383, 45, 16191), + (7902, 12, 385, 5330, 0), + (7902, 13, 385, 5430, 0), + (7902, 14, 385, 5530, 0), + (7904, 1, 0, 26, 0), + (7905, 1, 0, 27, 0), + (7906, 1, 0, 28, 0), + (7907, 1, 0, 29, 0), + (7908, 1, 0, 30, 0), + (7940, 1, 264, 15, 558), + (7941, 1, 264, 30, 558), + (7942, 1, 264, 45, 558), + (7945, 1, 310, 2000, 0), + (7945, 2, 139, 8007, 0), + (7945, 3, 310, 2000, 0), + (7945, 4, 385, 4140, 0), + (7945, 5, 385, 4240, 0), + (7945, 6, 385, 4340, 0), + (7945, 7, 385, 4440, 0), + (7945, 8, 385, 4540, 0), + (7945, 9, 385, 4640, 0), + (7946, 1, 310, 4000, 0), + (7946, 2, 139, 8007, 0), + (7946, 3, 310, 4000, 0), + (7946, 4, 385, 4140, 0), + (7946, 5, 385, 4240, 0), + (7946, 6, 385, 4340, 0), + (7946, 7, 385, 4440, 0), + (7946, 8, 385, 4540, 0), + (7946, 9, 385, 4640, 0), + (7947, 1, 310, 6000, 0), + (7947, 2, 139, 8007, 0), + (7947, 3, 310, 6000, 0), + (7947, 4, 385, 4140, 0), + (7947, 5, 385, 4240, 0), + (7947, 6, 385, 4340, 0), + (7947, 7, 385, 4440, 0), + (7947, 8, 385, 4540, 0), + (7947, 9, 385, 4640, 0), + (7948, 1, 339, 25, 16197), + (7948, 2, 138, 1, 0), + (7948, 3, 142, 60, 0), + (7948, 4, 137, 35, 0), + (7948, 5, 134, 75, 0), + (7948, 6, 339, 25, 16197), + (7948, 7, 138, 1, 0), + (7948, 8, 142, 60, 0), + (7948, 9, 137, 36, 0), + (7948, 10, 134, 75, 0), + (7948, 11, 339, 25, 16197), + (7948, 12, 138, 1, 0), + (7948, 13, 142, 60, 0), + (7948, 14, 137, 369, 0), + (7948, 15, 134, 75, 0), + (7948, 16, 339, 25, 16197), + (7948, 17, 138, 1, 0), + (7948, 18, 142, 60, 0), + (7948, 19, 137, 116, 0), + (7948, 20, 134, 75, 0), + (7949, 1, 339, 25, 16198), + (7949, 2, 138, 1, 0), + (7949, 3, 142, 60, 0), + (7949, 4, 137, 35, 0), + (7949, 5, 134, 80, 0), + (7949, 6, 339, 25, 16198), + (7949, 7, 138, 1, 0), + (7949, 8, 142, 60, 0), + (7949, 9, 137, 36, 0), + (7949, 10, 134, 80, 0), + (7949, 11, 339, 25, 16198), + (7949, 12, 138, 1, 0), + (7949, 13, 142, 60, 0), + (7949, 14, 137, 369, 0), + (7949, 15, 134, 80, 0), + (7949, 16, 339, 25, 16198), + (7949, 17, 138, 1, 0), + (7949, 18, 142, 60, 0), + (7949, 19, 137, 116, 0), + (7949, 20, 134, 80, 0), + (7950, 1, 339, 25, 16199), + (7950, 2, 138, 1, 0), + (7950, 3, 142, 60, 0), + (7950, 4, 137, 35, 0), + (7950, 5, 134, 85, 0), + (7950, 6, 339, 25, 16199), + (7950, 7, 138, 1, 0), + (7950, 8, 142, 60, 0), + (7950, 9, 137, 36, 0), + (7950, 10, 134, 85, 0), + (7950, 11, 339, 25, 16199), + (7950, 12, 138, 1, 0), + (7950, 13, 142, 60, 0), + (7950, 14, 137, 369, 0), + (7950, 15, 134, 85, 0), + (7950, 16, 339, 25, 16199), + (7950, 17, 138, 1, 0), + (7950, 18, 142, 60, 0), + (7950, 19, 137, 116, 0), + (7950, 20, 134, 85, 0), + (7980, 1, 243, 15, 0), + (7981, 1, 243, 25, 0), + (7982, 1, 243, 35, 0), + (7983, 1, 264, 120, 520), + (7984, 1, 264, 240, 520), + (7985, 1, 264, 360, 520), + (7989, 1, 264, 30, 705), + (7989, 2, 264, 30, 1092), + (7989, 3, 264, 30, 10396), + (7989, 4, 264, 30, 10397), + (7990, 1, 264, 60, 705), + (7990, 2, 264, 60, 1092), + (7990, 3, 264, 60, 10396), + (7990, 4, 264, 60, 10397), + (7991, 1, 264, 90, 705), + (7991, 2, 264, 90, 1092), + (7991, 3, 264, 90, 10396), + (7991, 4, 264, 90, 10397), + (7992, 1, 264, 120, 705), + (7992, 2, 264, 120, 1092), + (7992, 3, 264, 120, 10396), + (7992, 4, 264, 120, 10397), + (7994, 1, 264, 240, 39), + (7994, 2, 264, 3456, 1061), + (7995, 1, 264, 300, 39), + (7995, 2, 264, 4320, 1061), + (8000, 1, 69, 200, 0), + (8000, 2, 2, 75, 0), + (8000, 3, 97, 200, 0), + (8000, 4, 317, 8, 0), + (8031, 1, 264, 30, 791), + (8032, 1, 264, 60, 791), + (8033, 1, 264, 90, 791), + (8035, 1, 264, 180, 521), + (8036, 1, 264, 360, 521), + (8037, 1, 264, 540, 521), + (8040, 1, 128, 5, 5), + (8040, 2, 138, 1, 0), + (8040, 3, 140, 1, 0), + (8040, 4, 311, 0, 0), + (8040, 5, 411, 256, 0), + (8040, 6, 137, -40, 0), + (8040, 7, 391, 1, 0), + (8041, 1, 128, 15, 15), + (8041, 2, 138, 1, 0), + (8041, 3, 140, 1, 0), + (8041, 4, 311, 0, 0), + (8041, 5, 411, 256, 0), + (8041, 6, 137, -40, 0), + (8041, 7, 391, 1, 0), + (8042, 1, 128, 30, 30), + (8042, 2, 138, 1, 0), + (8042, 3, 140, 1, 0), + (8042, 4, 311, 0, 0), + (8042, 5, 411, 256, 0), + (8042, 6, 137, -40, 0), + (8042, 7, 391, 1, 0), + (8043, 1, 128, 50, 50), + (8043, 2, 138, 1, 0), + (8043, 3, 140, 1, 0), + (8043, 4, 311, 0, 0), + (8043, 5, 411, 256, 0), + (8043, 6, 137, -40, 0), + (8043, 7, 391, 1, 0), + (8059, 1, 128, 50, 50), + (8059, 2, 138, 1, 0), + (8059, 3, 140, 1, 0), + (8059, 4, 311, 0, 0), + (8059, 5, 411, 66434, 0), + (8059, 6, 137, -40, 0), + (8069, 1, 244, -10, 0), + (8070, 1, 244, -15, 0), + (8071, 1, 244, -20, 0), + (8076, 1, 264, 360, 565), + (8076, 2, 264, 360, 793), + (8076, 3, 264, 360, 794), + (8077, 1, 264, 720, 565), + (8077, 2, 264, 720, 793), + (8077, 3, 264, 720, 794), + (8078, 1, 264, 1080, 565), + (8078, 2, 264, 1080, 793), + (8078, 3, 264, 1080, 794), + (8079, 1, 264, 1440, 565), + (8079, 2, 264, 1440, 793), + (8079, 3, 264, 1440, 794), + (8080, 1, 264, 1800, 565), + (8080, 2, 264, 1800, 793), + (8080, 3, 264, 1800, 794), + (8081, 1, 264, 2160, 565), + (8081, 2, 264, 2160, 793), + (8081, 3, 264, 2160, 794), + (8082, 1, 264, 60, 208), + (8083, 1, 264, 120, 208), + (8084, 1, 264, 180, 208), + (8190, 1, 280, 2, 0), + (8191, 1, 280, 4, 0), + (8192, 1, 280, 6, 0), + (8193, 1, 339, 100, 16225), + (8193, 2, 139, 6838, 0), + (8195, 1, 264, 120, 3707), + (8196, 1, 264, 240, 3707), + (8197, 1, 264, 360, 3707), + (8198, 1, 294, 0, 110), + (8199, 1, 294, 0, 120), + (8200, 1, 294, 0, 130), + (8201, 1, 218, 1, 0), + (8202, 1, 218, 2, 0), + (8203, 1, 218, 3, 0), + (8204, 1, 127, 10, 0), + (8204, 2, 137, 154, 0), + (8204, 3, 403, 2, 0), + (8204, 4, 404, 10, 0), + (8205, 1, 127, 20, 0), + (8205, 2, 137, 154, 0), + (8205, 3, 403, 2, 0), + (8205, 4, 404, 10, 0), + (8206, 1, 127, 30, 0), + (8206, 2, 137, 154, 0), + (8206, 3, 403, 2, 0), + (8206, 4, 404, 10, 0), + (8207, 1, 127, 10, 0), + (8207, 2, 137, 154, 0), + (8207, 3, 403, 2, 0), + (8207, 4, 404, 10, 0), + (8208, 1, 127, 20, 0), + (8208, 2, 137, 154, 0), + (8208, 3, 403, 2, 0), + (8208, 4, 404, 10, 0), + (8209, 1, 127, 30, 0), + (8209, 2, 137, 154, 0), + (8209, 3, 403, 2, 0), + (8209, 4, 404, 10, 0), + (8210, 1, 97, 50, 0), + (8211, 1, 97, 100, 0), + (8212, 1, 97, 150, 0), + (8213, 1, 97, 200, 0), + (8214, 1, 97, 250, 0), + (8215, 1, 190, 50, 0), + (8216, 1, 190, 100, 0), + (8217, 1, 190, 150, 0), + (8218, 1, 190, 200, 0), + (8219, 1, 190, 250, 0), + (8223, 1, 128, 50, 50), + (8223, 2, 138, 1, 0), + (8223, 3, 140, 1, 0), + (8223, 4, 139, -2741, 0), + (8223, 5, 139, -16843, 0), + (8223, 6, 385, -16192, 0), + (8224, 1, 339, 10, 16230), + (8224, 2, 138, 1, 0), + (8224, 3, 141, 1, 0), + (8224, 4, 142, 60, 0), + (8224, 5, 137, 0, 0), + (8224, 6, 311, 0, 0), + (8224, 7, 134, 80, 0), + (8224, 8, 139, -265, 0), + (8224, 9, 139, -754, 0), + (8224, 10, 139, -1332, 0), + (8224, 11, 139, -1572, 0), + (8224, 12, 139, -2749, 0), + (8224, 13, 139, -4979, 0), + (8224, 14, 139, -5418, 0), + (8224, 15, 139, -5403, 0), + (8225, 1, 339, 10, 16231), + (8225, 2, 138, 1, 0), + (8225, 3, 141, 1, 0), + (8225, 4, 142, 65, 0), + (8225, 5, 137, 0, 0), + (8225, 6, 311, 0, 0), + (8225, 7, 134, 85, 0), + (8225, 8, 139, -265, 0), + (8225, 9, 139, -754, 0), + (8225, 10, 139, -1332, 0), + (8225, 11, 139, -1572, 0), + (8225, 12, 139, -2749, 0), + (8225, 13, 139, -4979, 0), + (8225, 14, 139, -5418, 0), + (8225, 15, 139, -5403, 0), + (8226, 1, 339, 10, 16232), + (8226, 2, 138, 1, 0), + (8226, 3, 141, 1, 0), + (8226, 4, 142, 70, 0), + (8226, 5, 137, 0, 0), + (8226, 6, 311, 0, 0), + (8226, 7, 134, 90, 0), + (8226, 8, 139, -265, 0), + (8226, 9, 139, -754, 0), + (8226, 10, 139, -1332, 0), + (8226, 11, 139, -1572, 0), + (8226, 12, 139, -2749, 0), + (8226, 13, 139, -4979, 0), + (8226, 14, 139, -5418, 0), + (8226, 15, 139, -5403, 0), + (8228, 1, 378, 5, 22), + (8229, 1, 378, 10, 22), + (8230, 1, 378, 15, 22), + (8232, 1, 128, 5, 5), + (8232, 2, 138, 1, 0), + (8232, 3, 140, 1, 0), + (8232, 4, 311, 0, 0), + (8232, 5, 411, 66434, 0), + (8232, 6, 137, -40, 0), + (8233, 1, 128, 15, 15), + (8233, 2, 138, 1, 0), + (8233, 3, 140, 1, 0), + (8233, 4, 311, 0, 0), + (8233, 5, 411, 66434, 0), + (8233, 6, 137, -40, 0), + (8234, 1, 128, 30, 30), + (8234, 2, 138, 1, 0), + (8234, 3, 140, 1, 0), + (8234, 4, 311, 0, 0), + (8234, 5, 411, 66434, 0), + (8234, 6, 137, -40, 0), + (8235, 1, 1, 29, 0), + (8236, 1, 1, 58, 0), + (8237, 1, 1, 87, 0), + (8238, 1, 1, 116, 0), + (8239, 1, 1, 145, 0), + (8240, 1, 1, 31, 0), + (8241, 1, 1, 62, 0), + (8242, 1, 1, 93, 0), + (8243, 1, 1, 124, 0), + (8244, 1, 1, 155, 0), + (8245, 1, 1, 33, 0), + (8246, 1, 1, 66, 0), + (8247, 1, 1, 99, 0), + (8248, 1, 1, 132, 0), + (8249, 1, 1, 165, 0), + (8250, 1, 1, 40, 0), + (8251, 1, 1, 80, 0), + (8252, 1, 1, 120, 0), + (8253, 1, 1, 160, 0), + (8254, 1, 1, 200, 0), + (8255, 1, 1, 50, 0), + (8256, 1, 1, 100, 0), + (8257, 1, 1, 150, 0), + (8258, 1, 1, 200, 0), + (8259, 1, 1, 250, 0), + (8261, 1, 128, 65, 65), + (8261, 2, 138, 1, 0), + (8261, 3, 140, 1, 0), + (8261, 4, 311, 0, 0), + (8261, 5, 411, 66434, 0), + (8261, 6, 137, -40, 0), + (8262, 1, 128, 70, 70), + (8262, 2, 138, 1, 0), + (8262, 3, 140, 1, 0), + (8262, 4, 139, -2741, 0), + (8262, 5, 139, -16843, 0), + (8262, 6, 385, -16192, 0), + (8263, 1, 262, 5, 0), + (8264, 1, 262, 10, 0), + (8265, 1, 262, 15, 0), + (8266, 1, 262, 20, 0), + (8267, 1, 262, 25, 0), + (8268, 1, 262, 5, 1), + (8269, 1, 262, 10, 1), + (8270, 1, 262, 15, 1), + (8271, 1, 262, 20, 1), + (8272, 1, 262, 25, 1), + (8273, 1, 262, 5, 2), + (8274, 1, 262, 10, 2), + (8275, 1, 262, 15, 2), + (8276, 1, 262, 20, 2), + (8277, 1, 262, 25, 2), + (8278, 1, 262, 5, 3), + (8279, 1, 262, 10, 3), + (8280, 1, 262, 15, 3), + (8281, 1, 262, 20, 3), + (8282, 1, 262, 25, 3), + (8283, 1, 262, 5, 4), + (8284, 1, 262, 10, 4), + (8285, 1, 262, 15, 4), + (8286, 1, 262, 20, 4), + (8287, 1, 262, 25, 4), + (8288, 1, 262, 5, 5), + (8289, 1, 262, 10, 5), + (8290, 1, 262, 15, 5), + (8291, 1, 262, 20, 5), + (8292, 1, 262, 25, 5), + (8293, 1, 262, 5, 6), + (8294, 1, 262, 10, 6), + (8295, 1, 262, 15, 6), + (8296, 1, 262, 20, 6), + (8297, 1, 262, 25, 6), + (8304, 1, 1, 174, 0), + (8305, 1, 1, 203, 0), + (8306, 1, 1, 232, 0), + (8307, 1, 1, 261, 0), + (8308, 1, 1, 290, 0), + (8313, 1, 128, 65, 65), + (8313, 2, 138, 1, 0), + (8313, 3, 140, 1, 0), + (8313, 4, 311, 0, 0), + (8313, 5, 411, 256, 0), + (8313, 6, 137, -40, 0), + (8313, 7, 391, 1, 0), + (8314, 1, 378, 2, 3), + (8315, 1, 378, 3, 3), + (8316, 1, 378, 4, 3), + (8317, 1, 264, 1, 8205), + (8318, 1, 264, 2, 8205), + (8319, 1, 264, 2, 199), + (8320, 1, 264, 4, 199), + (8321, 1, 264, 6, 199), + (8322, 1, 378, 15, 31), + (8323, 1, 378, 20, 31), + (8324, 1, 378, 25, 31), + (8325, 1, 114, -3, 0), + (8326, 1, 114, -6, 0), + (8327, 1, 114, -9, 0), + (8328, 1, 268, 75, 56), + (8328, 2, 234, 1000, 0), + (8329, 1, 227, 4, 29), + (8329, 2, 227, 4, 42), + (8331, 1, 413, 10, 0), + (8331, 2, 139, 8001, 0), + (8331, 3, 385, 12529, 0), + (8331, 4, 411, 512, 0), + (8332, 1, 287, 1, 0), + (8332, 2, 385, 116121, 0), + (8333, 1, 287, 2, 0), + (8333, 2, 385, 116121, 0), + (8334, 1, 287, 3, 0), + (8334, 2, 385, 116121, 0), + (8335, 1, 127, 10, 0), + (8335, 2, 385, 16188, 0), + (8336, 1, 127, 20, 0), + (8336, 2, 385, 16188, 0), + (8337, 1, 127, 30, 0), + (8337, 2, 385, 16188, 0), + (8338, 1, 127, 40, 0), + (8338, 2, 385, 16188, 0), + (8339, 1, 127, 50, 0), + (8339, 2, 385, 16188, 0), + (8344, 1, 294, 0, 175), + (8345, 1, 294, 0, 180), + (8346, 1, 294, 0, 185), + (8347, 1, 264, 600, 616), + (8348, 1, 264, 1200, 616), + (8349, 1, 264, 1800, 616), + (8350, 1, 310, 1200, 0), + (8350, 2, 385, 6212, 0), + (8350, 3, 310, 600, 0), + (8350, 4, 385, 6215, 0), + (8350, 5, 310, 150, 0), + (8350, 6, 385, 6218, 0), + (8350, 7, 310, 9000, 0), + (8350, 8, 385, 6232, 0), + (8350, 9, 310, 600, 0), + (8350, 10, 385, 6243, 0), + (8350, 11, 310, 150, 0), + (8350, 12, 385, 6245, 0), + (8350, 13, 310, 1200, 0), + (8350, 14, 385, 6412, 0), + (8350, 15, 310, 600, 0), + (8350, 16, 385, 6415, 0), + (8350, 17, 310, 150, 0), + (8350, 18, 385, 6418, 0), + (8350, 19, 310, 9000, 0), + (8350, 20, 385, 6432, 0), + (8350, 21, 310, 600, 0), + (8350, 22, 385, 6443, 0), + (8350, 23, 310, 150, 0), + (8350, 24, 385, 6445, 0), + (8351, 1, 262, 30, 0), + (8352, 1, 262, 35, 0), + (8353, 1, 262, 40, 0), + (8354, 1, 262, 45, 0), + (8355, 1, 262, 50, 0), + (8356, 1, 262, 55, 0), + (8357, 1, 262, 60, 0), + (8358, 1, 262, 65, 0), + (8359, 1, 262, 70, 0), + (8360, 1, 262, 75, 0), + (8361, 1, 262, 30, 1), + (8362, 1, 262, 35, 1), + (8363, 1, 262, 40, 1), + (8364, 1, 262, 45, 1), + (8365, 1, 262, 50, 1), + (8366, 1, 262, 55, 1), + (8367, 1, 262, 60, 1), + (8368, 1, 262, 65, 1), + (8369, 1, 262, 70, 1), + (8370, 1, 262, 75, 1), + (8371, 1, 262, 30, 2), + (8372, 1, 262, 35, 2), + (8373, 1, 262, 40, 2), + (8374, 1, 262, 45, 2), + (8375, 1, 262, 50, 2), + (8376, 1, 262, 55, 2), + (8377, 1, 262, 60, 2), + (8378, 1, 262, 65, 2), + (8379, 1, 262, 70, 2), + (8380, 1, 262, 75, 2), + (8381, 1, 262, 30, 3), + (8382, 1, 262, 35, 3), + (8383, 1, 262, 40, 3), + (8384, 1, 262, 45, 3), + (8385, 1, 262, 50, 3), + (8386, 1, 262, 55, 3), + (8387, 1, 262, 60, 3), + (8388, 1, 262, 65, 3), + (8389, 1, 262, 70, 3), + (8390, 1, 262, 75, 3), + (8391, 1, 262, 30, 4), + (8392, 1, 262, 35, 4), + (8393, 1, 262, 40, 4), + (8394, 1, 262, 45, 4), + (8395, 1, 262, 50, 4), + (8396, 1, 262, 55, 4), + (8397, 1, 262, 60, 4), + (8398, 1, 262, 65, 4), + (8399, 1, 262, 70, 4), + (8400, 1, 262, 75, 4), + (8401, 1, 262, 30, 5), + (8402, 1, 262, 35, 5), + (8403, 1, 262, 40, 5), + (8404, 1, 262, 45, 5), + (8405, 1, 262, 50, 5), + (8406, 1, 262, 55, 5), + (8407, 1, 262, 60, 5), + (8408, 1, 262, 65, 5), + (8409, 1, 262, 70, 5), + (8410, 1, 262, 75, 5), + (8411, 1, 262, 30, 6), + (8412, 1, 262, 35, 6), + (8413, 1, 262, 40, 6), + (8414, 1, 262, 45, 6), + (8415, 1, 262, 50, 6), + (8416, 1, 262, 55, 6), + (8417, 1, 262, 60, 6), + (8418, 1, 262, 65, 6), + (8419, 1, 262, 70, 6), + (8420, 1, 262, 75, 6), + (8421, 1, 339, 10, 27535), + (8421, 2, 138, 1, 0), + (8421, 3, 141, 1, 0), + (8421, 4, 142, 75, 0), + (8421, 5, 137, 0, 0), + (8421, 6, 311, 0, 0), + (8421, 7, 134, 95, 0), + (8421, 8, 139, -265, 0), + (8421, 9, 139, -754, 0), + (8421, 10, 139, -1332, 0), + (8421, 11, 139, -1572, 0), + (8421, 12, 139, -2749, 0), + (8421, 13, 139, -4979, 0), + (8421, 14, 139, -5418, 0), + (8421, 15, 139, -5403, 0), + (8422, 1, 1, 198, 0), + (8423, 1, 1, 231, 0), + (8424, 1, 1, 264, 0), + (8425, 1, 1, 297, 0), + (8426, 1, 1, 330, 0), + (8427, 1, 264, 1260, 254), + (8428, 1, 264, 1440, 254), + (8429, 1, 264, 1620, 254), + (8430, 1, 328, 1600, 0), + (8435, 1, 0, 35, 0), + (8440, 1, 259, 66, 0), + (8445, 1, 426, 3, 0), + (8446, 1, 426, 4, 0), + (8447, 1, 426, 5, 0), + (8448, 1, 69, 2200, 0), + (8463, 1, 172, 60, 0), + (8464, 1, 172, 61, 0), + (8470, 1, 262, 80, 7), + (8470, 2, 262, 80, 8), + (8470, 3, 262, 80, 9), + (8470, 4, 262, 80, 10), + (8470, 5, 262, 80, 11), + (9001, 1, 247, 10, 58), + (9002, 1, 247, 20, 58), + (9003, 1, 247, 30, 58), + (9004, 1, 247, 40, 58), + (9005, 1, 247, 50, 58), + (9006, 1, 247, 60, 58), + (9007, 1, 247, 70, 58), + (9008, 1, 247, 80, 58), + (9009, 1, 247, 90, 58), + (9010, 1, 247, 100, 58), + (9011, 1, 247, 10, 58), + (9012, 1, 247, 20, 58), + (9013, 1, 247, 30, 58), + (9014, 1, 247, 40, 58), + (9015, 1, 247, 50, 58), + (9016, 1, 247, 60, 58), + (9017, 1, 247, 70, 58), + (9018, 1, 247, 80, 58), + (9019, 1, 247, 90, 58), + (9020, 1, 247, 100, 58), + (9021, 1, 247, 10, 58), + (9022, 1, 247, 20, 58), + (9023, 1, 247, 30, 58), + (9024, 1, 247, 40, 58), + (9025, 1, 247, 50, 58), + (9026, 1, 247, 60, 58), + (9027, 1, 247, 70, 58), + (9028, 1, 247, 80, 58), + (9029, 1, 247, 90, 58), + (9030, 1, 247, 100, 58), + (9033, 1, 264, 18000, 481), + (9033, 2, 264, 18000, 482), + (9033, 3, 264, 18000, 483), + (9033, 4, 264, 147600, 484), + (9033, 5, 264, 18000, 485), + (9033, 6, 264, 61200, 486), + (9033, 7, 264, 3600, 487), + (9033, 8, 264, 1080, 511), + (9033, 9, 264, 18000, 182), + (9033, 10, 264, 18000, 8081), + (9033, 11, 264, 18000, 8130), + (9033, 12, 264, 18000, 453), + (9033, 13, 264, 18000, 2000), + (9100, 1, 97, 10, 0), + (9100, 2, 262, 1, 5), + (9101, 1, 97, 20, 0), + (9101, 2, 262, 2, 5), + (9102, 1, 97, 30, 0), + (9102, 2, 262, 3, 5), + (9103, 1, 97, 40, 0), + (9103, 2, 262, 4, 5), + (9104, 1, 97, 50, 0), + (9104, 2, 262, 5, 5), + (9105, 1, 97, 60, 0), + (9105, 2, 262, 6, 5), + (9106, 1, 97, 70, 0), + (9106, 2, 262, 7, 5), + (9107, 1, 97, 80, 0), + (9107, 2, 262, 8, 5), + (9108, 1, 97, 90, 0), + (9108, 2, 262, 9, 5), + (9109, 1, 69, 10, 0), + (9109, 2, 262, 1, 1), + (9110, 1, 69, 20, 0), + (9110, 2, 262, 2, 1), + (9111, 1, 69, 30, 0), + (9111, 2, 262, 3, 1), + (9112, 1, 69, 40, 0), + (9112, 2, 262, 4, 1), + (9113, 1, 69, 50, 0), + (9113, 2, 262, 5, 1), + (9114, 1, 69, 60, 0), + (9114, 2, 262, 6, 1), + (9115, 1, 69, 70, 0), + (9115, 2, 262, 7, 1), + (9116, 1, 69, 80, 0), + (9116, 2, 262, 8, 1), + (9117, 1, 69, 90, 0), + (9117, 2, 262, 9, 1), + (9118, 1, 97, 10, 0), + (9118, 2, 262, 1, 5), + (9119, 1, 97, 20, 0), + (9119, 2, 262, 2, 5), + (9120, 1, 97, 30, 0), + (9120, 2, 262, 3, 5), + (9121, 1, 97, 40, 0), + (9121, 2, 262, 4, 5), + (9122, 1, 97, 50, 0), + (9122, 2, 262, 5, 5), + (9123, 1, 97, 60, 0), + (9123, 2, 262, 6, 5), + (9124, 1, 97, 70, 0), + (9124, 2, 262, 7, 5), + (9125, 1, 97, 80, 0), + (9125, 2, 262, 8, 5), + (9126, 1, 97, 90, 0), + (9126, 2, 262, 9, 5), + (9127, 1, 69, 10, 0), + (9127, 2, 262, 1, 5), + (9128, 1, 69, 20, 0), + (9128, 2, 262, 2, 5), + (9129, 1, 69, 30, 0), + (9129, 2, 262, 3, 5), + (9130, 1, 69, 40, 0), + (9130, 2, 262, 4, 5), + (9131, 1, 69, 50, 0), + (9131, 2, 262, 5, 5), + (9132, 1, 69, 60, 0), + (9132, 2, 262, 6, 5), + (9133, 1, 69, 70, 0), + (9133, 2, 262, 7, 5), + (9134, 1, 69, 80, 0), + (9134, 2, 262, 8, 5), + (9135, 1, 69, 90, 0), + (9135, 2, 262, 9, 5), + (9136, 1, 97, 10, 0), + (9136, 2, 262, 1, 4), + (9137, 1, 97, 20, 0), + (9137, 2, 262, 2, 4), + (9138, 1, 97, 30, 0), + (9138, 2, 262, 3, 4), + (9139, 1, 97, 40, 0), + (9139, 2, 262, 4, 4), + (9140, 1, 97, 50, 0), + (9140, 2, 262, 5, 4), + (9141, 1, 97, 60, 0), + (9141, 2, 262, 6, 4), + (9142, 1, 97, 70, 0), + (9142, 2, 262, 7, 4), + (9143, 1, 97, 80, 0), + (9143, 2, 262, 8, 4), + (9144, 1, 97, 90, 0), + (9144, 2, 262, 9, 4), + (9145, 1, 97, 10, 0), + (9145, 2, 262, 1, 4), + (9146, 1, 97, 20, 0), + (9146, 2, 262, 2, 4), + (9147, 1, 97, 30, 0), + (9147, 2, 262, 3, 4), + (9148, 1, 97, 40, 0), + (9148, 2, 262, 4, 4), + (9149, 1, 97, 50, 0), + (9149, 2, 262, 5, 4), + (9150, 1, 97, 60, 0), + (9150, 2, 262, 6, 4), + (9151, 1, 97, 70, 0), + (9151, 2, 262, 7, 4), + (9152, 1, 97, 80, 0), + (9152, 2, 262, 8, 4), + (9153, 1, 97, 90, 0), + (9153, 2, 262, 9, 4), + (9154, 1, 69, 10, 0), + (9154, 2, 262, 1, 1), + (9155, 1, 69, 20, 0), + (9155, 2, 262, 2, 1), + (9156, 1, 69, 30, 0), + (9156, 2, 262, 3, 1), + (9157, 1, 69, 40, 0), + (9157, 2, 262, 4, 1), + (9158, 1, 69, 50, 0), + (9158, 2, 262, 5, 1), + (9159, 1, 69, 60, 0), + (9159, 2, 262, 6, 1), + (9160, 1, 69, 70, 0), + (9160, 2, 262, 7, 1), + (9161, 1, 69, 80, 0), + (9161, 2, 262, 8, 1), + (9162, 1, 69, 90, 0), + (9162, 2, 262, 9, 1), + (9163, 1, 69, 10, 0), + (9163, 2, 262, 1, 3), + (9164, 1, 69, 20, 0), + (9164, 2, 262, 2, 3), + (9165, 1, 69, 30, 0), + (9165, 2, 262, 3, 3), + (9166, 1, 69, 40, 0), + (9166, 2, 262, 4, 3), + (9167, 1, 69, 50, 0), + (9167, 2, 262, 5, 3), + (9168, 1, 69, 60, 0), + (9168, 2, 262, 6, 3), + (9169, 1, 69, 70, 0), + (9169, 2, 262, 7, 3), + (9170, 1, 69, 80, 0), + (9170, 2, 262, 8, 3), + (9171, 1, 69, 90, 0), + (9171, 2, 262, 9, 3), + (9172, 1, 69, 10, 0), + (9172, 2, 262, 1, 0), + (9173, 1, 69, 20, 0), + (9173, 2, 262, 2, 0), + (9174, 1, 69, 30, 0), + (9174, 2, 262, 3, 0), + (9175, 1, 69, 40, 0), + (9175, 2, 262, 4, 0), + (9176, 1, 69, 50, 0), + (9176, 2, 262, 5, 0), + (9177, 1, 69, 60, 0), + (9177, 2, 262, 6, 0), + (9178, 1, 69, 70, 0), + (9178, 2, 262, 7, 0), + (9179, 1, 69, 80, 0), + (9179, 2, 262, 8, 0), + (9180, 1, 69, 90, 0), + (9180, 2, 262, 9, 0), + (9181, 1, 69, 10, 0), + (9181, 2, 262, 1, 0), + (9182, 1, 69, 20, 0), + (9182, 2, 262, 2, 0), + (9183, 1, 69, 30, 0), + (9183, 2, 262, 3, 0), + (9184, 1, 69, 40, 0), + (9184, 2, 262, 4, 0), + (9185, 1, 69, 50, 0), + (9185, 2, 262, 5, 0), + (9186, 1, 69, 60, 0), + (9186, 2, 262, 6, 0), + (9187, 1, 69, 70, 0), + (9187, 2, 262, 7, 0), + (9188, 1, 69, 80, 0), + (9188, 2, 262, 8, 0), + (9189, 1, 69, 90, 0), + (9189, 2, 262, 9, 0), + (9190, 1, 69, 10, 0), + (9190, 2, 262, 1, 0), + (9191, 1, 69, 20, 0), + (9191, 2, 262, 2, 0), + (9192, 1, 69, 30, 0), + (9192, 2, 262, 3, 0), + (9193, 1, 69, 40, 0), + (9193, 2, 262, 4, 0), + (9194, 1, 69, 50, 0), + (9194, 2, 262, 5, 0), + (9195, 1, 69, 60, 0), + (9195, 2, 262, 6, 0), + (9196, 1, 69, 70, 0), + (9196, 2, 262, 7, 0), + (9197, 1, 69, 80, 0), + (9197, 2, 262, 8, 0), + (9198, 1, 69, 90, 0), + (9198, 2, 262, 9, 0), + (9199, 1, 97, 10, 0), + (9199, 2, 262, 1, 0), + (9200, 1, 97, 20, 0), + (9200, 2, 262, 2, 0), + (9201, 1, 97, 30, 0), + (9201, 2, 262, 3, 0), + (9202, 1, 97, 40, 0), + (9202, 2, 262, 4, 0), + (9203, 1, 97, 50, 0), + (9203, 2, 262, 5, 0), + (9204, 1, 97, 60, 0), + (9204, 2, 262, 6, 0), + (9205, 1, 97, 70, 0), + (9205, 2, 262, 7, 0), + (9206, 1, 97, 80, 0), + (9206, 2, 262, 8, 0), + (9207, 1, 97, 90, 0), + (9207, 2, 262, 9, 0), + (9208, 1, 69, 10, 0), + (9208, 2, 262, 1, 0), + (9209, 1, 69, 20, 0), + (9209, 2, 262, 2, 0), + (9210, 1, 69, 30, 0), + (9210, 2, 262, 3, 0), + (9211, 1, 69, 40, 0), + (9211, 2, 262, 4, 0), + (9212, 1, 69, 50, 0), + (9212, 2, 262, 5, 0), + (9213, 1, 69, 60, 0), + (9213, 2, 262, 6, 0), + (9214, 1, 69, 70, 0), + (9214, 2, 262, 7, 0), + (9215, 1, 69, 80, 0), + (9215, 2, 262, 8, 0), + (9216, 1, 69, 90, 0), + (9216, 2, 262, 9, 0), + (9217, 1, 190, 10, 0), + (9217, 2, 262, 1, 0), + (9218, 1, 190, 20, 0), + (9218, 2, 262, 2, 0), + (9219, 1, 190, 30, 0), + (9219, 2, 262, 3, 0), + (9220, 1, 190, 40, 0), + (9220, 2, 262, 4, 0), + (9221, 1, 190, 50, 0), + (9221, 2, 262, 5, 0), + (9222, 1, 190, 60, 0), + (9222, 2, 262, 6, 0), + (9223, 1, 190, 70, 0), + (9223, 2, 262, 7, 0), + (9224, 1, 190, 80, 0), + (9224, 2, 262, 8, 0), + (9225, 1, 190, 90, 0), + (9225, 2, 262, 9, 0), + (9226, 1, 69, 10, 0), + (9226, 2, 262, 1, 0), + (9227, 1, 69, 20, 0), + (9227, 2, 262, 2, 0), + (9228, 1, 69, 30, 0), + (9228, 2, 262, 3, 0), + (9229, 1, 69, 40, 0), + (9229, 2, 262, 4, 0), + (9230, 1, 69, 50, 0), + (9230, 2, 262, 5, 0), + (9231, 1, 69, 60, 0), + (9231, 2, 262, 6, 0), + (9232, 1, 69, 70, 0), + (9232, 2, 262, 7, 0), + (9233, 1, 69, 80, 0), + (9233, 2, 262, 8, 0), + (9234, 1, 69, 90, 0), + (9234, 2, 262, 9, 0), + (9235, 1, 190, 10, 0), + (9235, 2, 262, 1, 0), + (9236, 1, 190, 20, 0), + (9236, 2, 262, 2, 0), + (9237, 1, 190, 30, 0), + (9237, 2, 262, 3, 0), + (9238, 1, 190, 40, 0), + (9238, 2, 262, 4, 0), + (9239, 1, 190, 50, 0), + (9239, 2, 262, 5, 0), + (9240, 1, 190, 60, 0), + (9240, 2, 262, 6, 0), + (9241, 1, 190, 70, 0), + (9241, 2, 262, 7, 0), + (9242, 1, 190, 80, 0), + (9242, 2, 262, 8, 0), + (9243, 1, 190, 90, 0), + (9243, 2, 262, 9, 0), + (9503, 1, 397, 100, 0), + (9504, 1, 397, 200, 0), + (9505, 1, 397, 300, 0), + (9506, 1, 398, 1000, 0), + (9506, 2, 137, 152, 0), + (9507, 1, 398, 2000, 0), + (9507, 2, 137, 152, 0), + (9508, 1, 398, 3000, 0), + (9508, 2, 137, 152, 0), + (9509, 1, 399, 1, 0), + (9509, 2, 141, 1, 0), + (9509, 3, 138, 0, 0), + (9509, 4, 134, 254, 0), + (9509, 5, 348, 10, 0), + (9509, 6, 137, 0, 0), + (9509, 7, 311, 0, 0), + (9509, 8, 137, -152, 0), + (9509, 9, 137, -39, 0), + (9510, 1, 399, 2, 0), + (9510, 2, 141, 1, 0), + (9510, 3, 138, 0, 0), + (9510, 4, 134, 254, 0), + (9510, 5, 348, 10, 0), + (9510, 6, 137, 0, 0), + (9510, 7, 311, 0, 0), + (9510, 8, 137, -152, 0), + (9510, 9, 137, -39, 0), + (9511, 1, 399, 3, 0), + (9511, 2, 141, 1, 0), + (9511, 3, 138, 0, 0), + (9511, 4, 134, 254, 0), + (9511, 5, 348, 10, 0), + (9511, 6, 137, 0, 0), + (9511, 7, 311, 0, 0), + (9511, 8, 137, -152, 0), + (9511, 9, 137, -39, 0), + (9512, 1, 405, 1, 0), + (9513, 1, 405, 3, 0), + (9514, 1, 405, 5, 0), + (9515, 1, 399, 4, 0), + (9515, 2, 141, 1, 0), + (9515, 3, 138, 0, 0), + (9515, 4, 134, 254, 0), + (9515, 5, 348, 10, 0), + (9515, 6, 137, 0, 0), + (9515, 7, 311, 0, 0), + (9515, 8, 137, -152, 0), + (9515, 9, 137, -39, 0), + (10004, 1, 310, 480000, 0), + (10004, 2, 139, 4674, 0), + (10005, 1, 310, 600000, 0), + (10005, 2, 139, 4674, 0), + (10007, 1, 85, 16500, 50), + (10008, 1, 85, 16501, 50), + (10009, 1, 85, 16502, 50), + (10025, 1, 339, 25, 16517), + (10025, 2, 137, 21, 0), + (10026, 1, 339, 25, 16518), + (10026, 2, 137, 21, 0), + (10027, 1, 339, 25, 16519), + (10027, 2, 137, 21, 0), + (10028, 1, 339, 25, 16520), + (10028, 2, 137, 21, 0), + (10029, 1, 339, 25, 16555), + (10029, 2, 137, 21, 0), + (10030, 1, 264, 60, 558), + (10031, 1, 264, 75, 558), + (10032, 1, 264, 90, 558), + (10033, 1, 310, 8000, 0), + (10033, 2, 139, 8007, 0), + (10033, 3, 310, 8000, 0), + (10033, 4, 385, 4140, 0), + (10033, 5, 385, 4240, 0), + (10033, 6, 385, 4340, 0), + (10033, 7, 385, 4440, 0), + (10033, 8, 385, 4540, 0), + (10033, 9, 385, 4640, 0), + (10034, 1, 310, 10000, 0), + (10034, 2, 139, 8007, 0), + (10034, 3, 310, 10000, 0), + (10034, 4, 385, 4140, 0), + (10034, 5, 385, 4240, 0), + (10034, 6, 385, 4340, 0), + (10034, 7, 385, 4440, 0), + (10034, 8, 385, 4540, 0), + (10034, 9, 385, 4640, 0), + (10035, 1, 339, 25, 16556), + (10035, 2, 138, 1, 0), + (10035, 3, 142, 60, 0), + (10035, 4, 137, 35, 0), + (10035, 5, 134, 85, 0), + (10035, 6, 339, 25, 16556), + (10035, 7, 138, 1, 0), + (10035, 8, 142, 60, 0), + (10035, 9, 137, 36, 0), + (10035, 10, 134, 85, 0), + (10035, 11, 339, 25, 16556), + (10035, 12, 138, 1, 0), + (10035, 13, 142, 60, 0), + (10035, 14, 137, 369, 0), + (10035, 15, 134, 85, 0), + (10035, 16, 339, 25, 16556), + (10035, 17, 138, 1, 0), + (10035, 18, 142, 60, 0), + (10035, 19, 137, 116, 0), + (10035, 20, 134, 85, 0), + (10036, 1, 339, 25, 16557), + (10036, 2, 138, 1, 0), + (10036, 3, 142, 60, 0), + (10036, 4, 137, 35, 0), + (10036, 5, 134, 85, 0), + (10036, 6, 339, 25, 16557), + (10036, 7, 138, 1, 0), + (10036, 8, 142, 60, 0), + (10036, 9, 137, 36, 0), + (10036, 10, 134, 85, 0), + (10036, 11, 339, 25, 16557), + (10036, 12, 138, 1, 0), + (10036, 13, 142, 60, 0), + (10036, 14, 137, 369, 0), + (10036, 15, 134, 85, 0), + (10036, 16, 339, 25, 16557), + (10036, 17, 138, 1, 0), + (10036, 18, 142, 60, 0), + (10036, 19, 137, 116, 0), + (10036, 20, 134, 85, 0), + (10037, 1, 339, 25, 16558), + (10037, 2, 138, 1, 0), + (10037, 3, 142, 60, 0), + (10037, 4, 137, 35, 0), + (10037, 5, 134, 85, 0), + (10037, 6, 339, 25, 16558), + (10037, 7, 138, 1, 0), + (10037, 8, 142, 60, 0), + (10037, 9, 137, 36, 0), + (10037, 10, 134, 85, 0), + (10037, 11, 339, 25, 16558), + (10037, 12, 138, 1, 0), + (10037, 13, 142, 60, 0), + (10037, 14, 137, 369, 0), + (10037, 15, 134, 85, 0), + (10037, 16, 339, 25, 16558), + (10037, 17, 138, 1, 0), + (10037, 18, 142, 60, 0), + (10037, 19, 137, 116, 0), + (10037, 20, 134, 85, 0), + (10041, 1, 294, 0, 135), + (10042, 1, 294, 0, 145), + (10043, 1, 294, 0, 155), + (10044, 1, 339, 20, 16564), + (10044, 2, 137, 21, 0), + (10044, 3, 385, -18000, 0), + (10044, 4, 339, 20, 16564), + (10044, 5, 137, 343, 0), + (10044, 6, 385, -18000, 0), + (10045, 1, 339, 20, 16565), + (10045, 2, 137, 21, 0), + (10045, 3, 385, -18000, 0), + (10045, 4, 339, 20, 16565), + (10045, 5, 137, 343, 0), + (10045, 6, 385, -18000, 0), + (10046, 1, 339, 20, 16566), + (10046, 2, 137, 21, 0), + (10046, 3, 385, -18000, 0), + (10046, 4, 339, 20, 16566), + (10046, 5, 137, 343, 0), + (10046, 6, 385, -18000, 0), + (10050, 1, 85, 16567, 0), + (10051, 1, 85, 16568, 0), + (10052, 1, 85, 16569, 0), + (10058, 1, 330, 55, 7), + (10059, 1, 330, 60, 7), + (10060, 1, 330, 65, 7), + (10064, 1, 347, 25, 0), + (10065, 1, 347, 26, 0), + (10066, 1, 347, 27, 0), + (10067, 1, 347, 28, 0), + (10068, 1, 347, 29, 0), + (10069, 1, 347, 30, 0), + (10070, 1, 218, 6, 0), + (10071, 1, 218, 7, 0), + (10072, 1, 218, 8, 0), + (10073, 1, 218, 9, 0), + (10074, 1, 218, 10, 0), + (10075, 1, 339, 10, 16581), + (10075, 2, 138, 0, 0), + (10075, 3, 142, 70, 0), + (10075, 4, 403, 4, 0), + (10075, 5, 348, 1, 0), + (10075, 6, 404, 2, 0), + (10075, 7, 141, 1, 0), + (10076, 1, 339, 10, 16582), + (10076, 2, 138, 0, 0), + (10076, 3, 142, 70, 0), + (10076, 4, 403, 4, 0), + (10076, 5, 348, 1, 0), + (10076, 6, 404, 2, 0), + (10076, 7, 141, 1, 0), + (10077, 1, 339, 10, 16583), + (10077, 2, 138, 0, 0), + (10077, 3, 142, 70, 0), + (10077, 4, 403, 4, 0), + (10077, 5, 348, 1, 0), + (10077, 6, 404, 2, 0), + (10077, 7, 141, 1, 0), + (10081, 1, 85, 16584, 0), + (10082, 1, 85, 16585, 0), + (10083, 1, 85, 16586, 0), + (10084, 1, 375, 175, 0), + (10085, 1, 375, 200, 0), + (10086, 1, 375, 215, 0), + (10087, 1, 397, 400, 0), + (10088, 1, 397, 600, 0), + (10089, 1, 397, 800, 0), + (10105, 1, 264, 60, 170), + (10106, 1, 264, 70, 170), + (10107, 1, 264, 80, 170), + (10108, 1, 264, 90, 170), + (10109, 1, 264, 100, 170), + (10110, 1, 264, 480, 520), + (10111, 1, 264, 600, 520), + (10112, 1, 264, 720, 520), + (10122, 1, 227, 210, 32), + (10123, 1, 227, 240, 32), + (10124, 1, 283, 180, 0), + (10125, 1, 283, 200, 0), + (10126, 1, 283, 220, 0), + (10130, 1, 264, 720, 544), + (10131, 1, 264, 900, 544), + (10132, 1, 264, 1080, 544), + (10133, 1, 279, 19, 0), + (10134, 1, 279, 23, 0), + (10135, 1, 279, 27, 0), + (10136, 1, 375, 130, 0), + (10137, 1, 375, 135, 0), + (10138, 1, 375, 140, 0), + (10153, 1, 264, 420, 553), + (10154, 1, 264, 480, 553), + (10155, 1, 264, 540, 553), + (10165, 1, 220, 195, 8), + (10166, 1, 220, 225, 8), + (10167, 1, 220, 255, 8), + (10171, 1, 252, 90, 0), + (10172, 1, 252, 95, 0), + (10173, 1, 258, 70, 0), + (10174, 1, 258, 71, 0), + (10175, 1, 258, 72, 0), + (10176, 1, 264, 40, 171), + (10177, 1, 264, 50, 171), + (10178, 1, 264, 60, 171), + (10182, 1, 264, 180, 177), + (10183, 1, 264, 210, 177), + (10184, 1, 264, 240, 177), + (10185, 1, 264, 270, 177), + (10186, 1, 264, 300, 177), + (10203, 1, 264, 720, 524), + (10204, 1, 264, 900, 524), + (10205, 1, 264, 1080, 524), + (10206, 1, 264, 1080, 320), + (10207, 1, 264, 1260, 320), + (10213, 1, 218, 16, 0), + (10214, 1, 218, 17, 0), + (10215, 1, 218, 18, 0), + (10216, 1, 218, 19, 0), + (10217, 1, 218, 20, 0), + (10219, 1, 280, 63, 0), + (10220, 1, 280, 64, 0), + (10221, 1, 280, 65, 0), + (10222, 1, 280, 66, 0), + (10223, 1, 280, 67, 0), + (10227, 1, 360, 60, 16720), + (10228, 1, 360, 60, 16721), + (10229, 1, 360, 60, 16722), + (10249, 1, 264, 240, 208), + (10250, 1, 264, 300, 208), + (10251, 1, 264, 360, 208), + (10262, 1, 274, 23, 0), + (10263, 1, 274, 24, 0), + (10264, 1, 274, 25, 0), + (10265, 1, 280, 57, 0), + (10266, 1, 280, 58, 0), + (10267, 1, 280, 59, 0), + (10268, 1, 339, 45, 16736), + (10268, 2, 136, 11, 0), + (10268, 3, 383, 45, 16736), + (10268, 4, 385, 11012, 0), + (10268, 5, 383, 45, 16736), + (10268, 6, 385, 5130, 0), + (10268, 7, 383, 45, 16736), + (10268, 8, 385, 5230, 0), + (10268, 9, 383, 45, 16736), + (10268, 10, 136, 22, 0), + (10268, 11, 383, 45, 16736), + (10268, 12, 385, 5330, 0), + (10268, 13, 385, 5430, 0), + (10268, 14, 385, 5530, 0), + (10269, 1, 339, 45, 16737), + (10269, 2, 136, 11, 0), + (10269, 3, 383, 45, 16737), + (10269, 4, 385, 11012, 0), + (10269, 5, 383, 45, 16737), + (10269, 6, 385, 5130, 0), + (10269, 7, 383, 45, 16737), + (10269, 8, 385, 5230, 0), + (10269, 9, 383, 45, 16737), + (10269, 10, 136, 22, 0), + (10269, 11, 383, 45, 16737), + (10269, 12, 385, 5330, 0), + (10269, 13, 385, 5430, 0), + (10269, 14, 385, 5530, 0), + (10270, 1, 339, 45, 16738), + (10270, 2, 136, 11, 0), + (10270, 3, 383, 45, 16738), + (10270, 4, 385, 11012, 0), + (10270, 5, 383, 45, 16738), + (10270, 6, 385, 5130, 0), + (10270, 7, 383, 45, 16738), + (10270, 8, 385, 5230, 0), + (10270, 9, 383, 45, 16738), + (10270, 10, 136, 22, 0), + (10270, 11, 383, 45, 16738), + (10270, 12, 385, 5330, 0), + (10270, 13, 385, 5430, 0), + (10270, 14, 385, 5530, 0), + (10282, 1, 264, 120, 791), + (10283, 1, 264, 150, 791), + (10284, 1, 264, 180, 791), + (10285, 1, 264, 720, 521), + (10286, 1, 264, 900, 521), + (10287, 1, 264, 1080, 521), + (10291, 1, 264, 15, 247), + (10291, 2, 264, 8, 986), + (10291, 3, 264, 8, 987), + (10291, 4, 264, 8, 988), + (10292, 1, 264, 18, 247), + (10292, 2, 264, 10, 986), + (10292, 3, 264, 10, 987), + (10292, 4, 264, 10, 988), + (10293, 1, 264, 21, 247), + (10293, 2, 264, 12, 986), + (10293, 3, 264, 12, 987), + (10293, 4, 264, 12, 988), + (10305, 1, 280, 68, 0), + (10306, 1, 280, 69, 0), + (10307, 1, 280, 70, 0), + (10311, 1, 220, 608, 74), + (10312, 1, 220, 640, 74), + (10313, 1, 220, 672, 74), + (10314, 1, 220, 704, 74), + (10315, 1, 220, 736, 74), + (10316, 1, 216, 160, 74), + (10317, 1, 216, 200, 74), + (10318, 1, 216, 240, 74), + (10329, 1, 264, 60, 3701), + (10332, 1, 287, 1, 0), + (10332, 2, 137, 22, 0), + (10332, 3, 411, 256, 0), + (10340, 1, 220, 100, 26), + (10341, 1, 220, 160, 26), + (10342, 1, 220, 235, 26), + (10343, 1, 264, 5, 469), + (10344, 1, 264, 10, 469), + (10345, 1, 264, 15, 469), + (10347, 1, 310, 12000, 0), + (10347, 2, 139, 8007, 0), + (10347, 3, 310, 12000, 0), + (10347, 4, 385, 4140, 0), + (10347, 5, 385, 4240, 0), + (10347, 6, 385, 4340, 0), + (10347, 7, 385, 4440, 0), + (10347, 8, 385, 4540, 0), + (10347, 9, 385, 4640, 0), + (10348, 1, 244, 60, 0), + (10349, 1, 244, 50, 0), + (10350, 1, 244, 40, 0), + (10355, 1, 124, 50, 50), + (10355, 2, 385, 19, 0), + (10355, 3, 144, 0, 0), + (10355, 4, 403, 3, 0), + (10355, 5, 404, 48, 0), + (10355, 6, 385, -21768, 0), + (10356, 1, 124, 100, 100), + (10356, 2, 385, 19, 0), + (10356, 3, 144, 0, 0), + (10356, 4, 403, 3, 0), + (10356, 5, 404, 48, 0), + (10356, 6, 385, -21768, 0), + (10357, 1, 124, 150, 150), + (10357, 2, 385, 19, 0), + (10357, 3, 144, 0, 0), + (10357, 4, 403, 3, 0), + (10357, 5, 404, 48, 0), + (10357, 6, 385, -21768, 0), + (10358, 1, 310, 10000, 0), + (10358, 2, 139, 1546, 0), + (10358, 3, 310, 10000, 0), + (10358, 4, 385, 4357, 0), + (10358, 5, 385, 4457, 0), + (10358, 6, 385, 4557, 0), + (10358, 7, 385, 4657, 0), + (10358, 8, 411, 4, 0), + (10359, 1, 310, 20000, 0), + (10359, 2, 139, 1546, 0), + (10359, 3, 310, 20000, 0), + (10359, 4, 385, 4357, 0), + (10359, 5, 385, 4457, 0), + (10359, 6, 385, 4557, 0), + (10359, 7, 385, 4657, 0), + (10359, 8, 411, 4, 0), + (10360, 1, 310, 30000, 0), + (10360, 2, 139, 1546, 0), + (10360, 3, 310, 30000, 0), + (10360, 4, 385, 4357, 0), + (10360, 5, 385, 4457, 0), + (10360, 6, 385, 4557, 0), + (10360, 7, 385, 4657, 0), + (10360, 8, 411, 4, 0), + (10361, 1, 232, 17, 4544), + (10362, 1, 232, 19, 4544), + (10363, 1, 232, 21, 4544), + (10364, 1, 413, -5, 0), + (10364, 2, 139, 480, 0), + (10364, 3, 385, 4352, 0), + (10364, 4, 385, 4452, 0), + (10365, 1, 413, -10, 0), + (10365, 2, 139, 480, 0), + (10365, 3, 385, 4352, 0), + (10365, 4, 385, 4452, 0), + (10366, 1, 413, -15, 0), + (10366, 2, 139, 480, 0), + (10366, 3, 385, 4352, 0), + (10366, 4, 385, 4452, 0), + (10370, 1, 114, -5, 0), + (10371, 1, 114, -10, 0), + (10372, 1, 114, -20, 0), + (10380, 1, 126, 5, 0), + (10380, 2, 134, 85, 0), + (10380, 3, 135, 4, 0), + (10380, 4, 135, 5, 0), + (10381, 1, 126, 10, 0), + (10381, 2, 134, 85, 0), + (10381, 3, 135, 4, 0), + (10381, 4, 135, 5, 0), + (10382, 1, 126, 15, 0), + (10382, 2, 134, 85, 0), + (10382, 3, 135, 4, 0), + (10382, 4, 135, 5, 0), + (10383, 1, 360, 25, 21770), + (10384, 1, 360, 25, 21771), + (10385, 1, 360, 25, 21772), + (10388, 1, 323, 21850, 0), + (10389, 1, 287, 5, 0), + (10389, 2, 385, 16107, 0), + (10389, 3, 411, 512, 0), + (10390, 1, 287, 10, 0), + (10390, 2, 385, 16107, 0), + (10390, 3, 411, 512, 0), + (10391, 1, 287, 15, 0), + (10391, 2, 385, 16107, 0), + (10391, 3, 411, 512, 0), + (10398, 1, 264, 120, 3701), + (10399, 1, 264, 180, 3701), + (10401, 1, 310, 30000, 0), + (10401, 2, 385, 3107, 0), + (10401, 3, 385, 3207, 0), + (10401, 4, 385, 3307, 0), + (10401, 5, 385, 3407, 0), + (10401, 6, 385, 3507, 0), + (10401, 7, 385, 3607, 0), + (10402, 1, 310, 60000, 0), + (10402, 2, 385, 3107, 0), + (10402, 3, 385, 3207, 0), + (10402, 4, 385, 3307, 0), + (10402, 5, 385, 3407, 0), + (10402, 6, 385, 3507, 0), + (10402, 7, 385, 3607, 0), + (10403, 1, 310, 90000, 0), + (10403, 2, 385, 3107, 0), + (10403, 3, 385, 3207, 0), + (10403, 4, 385, 3307, 0), + (10403, 5, 385, 3407, 0), + (10403, 6, 385, 3507, 0), + (10403, 7, 385, 3607, 0), + (10404, 1, 287, 1, 0), + (10404, 2, 139, 8003, 0), + (10405, 1, 310, 120000, 0), + (10405, 2, 139, 4590, 0), + (10406, 1, 310, 240000, 0), + (10406, 2, 139, 4590, 0), + (10407, 1, 310, 360000, 0), + (10407, 2, 139, 4590, 0), + (10408, 1, 310, 480000, 0), + (10408, 2, 139, 4590, 0), + (10409, 1, 310, 600000, 0), + (10409, 2, 139, 4590, 0), + (10410, 1, 247, 130, 76), + (10413, 1, 264, 60, 207), + (10414, 2, 264, 120, 207), + (10415, 3, 264, 180, 207), + (10416, 4, 264, 240, 207), + (10417, 5, 264, 300, 207), + (10431, 1, 264, 210, 791), + (10432, 1, 264, 240, 791), + (10433, 1, 264, 270, 791), + (10434, 1, 127, 16, 0), + (10434, 2, 385, 5921, 0), + (10435, 1, 127, 33, 0), + (10435, 2, 385, 5921, 0), + (10436, 1, 127, 50, 0), + (10436, 2, 385, 5921, 0), + (10437, 1, 339, 25, 23523), + (10437, 2, 137, 21, 0), + (10438, 1, 339, 25, 23524), + (10438, 2, 137, 21, 0), + (10439, 1, 339, 25, 23525), + (10439, 2, 137, 21, 0), + (10440, 1, 339, 25, 23526), + (10440, 2, 137, 21, 0), + (10442, 1, 413, -20, 0), + (10442, 2, 139, 480, 0), + (10442, 3, 385, 4352, 0), + (10442, 4, 385, 4452, 0), + (10443, 1, 413, -25, 0), + (10443, 2, 139, 480, 0), + (10443, 3, 385, 4352, 0), + (10443, 4, 385, 4452, 0), + (10453, 1, 126, 1, 1), + (10453, 2, 137, 21, 0), + (10453, 3, 231, 1, 0), + (10454, 1, 126, 2, 2), + (10454, 2, 137, 21, 0), + (10454, 3, 231, 2, 0), + (10455, 1, 126, 3, 3), + (10455, 2, 137, 21, 0), + (10455, 3, 231, 3, 0), + (10456, 1, 127, 15, 15), + (10456, 2, 139, 12786, 0), + (10457, 1, 127, 30, 30), + (10457, 2, 139, 12786, 0), + (10458, 1, 127, 50, 50), + (10458, 2, 139, 12786, 0), + (10459, 1, 310, 3000, 0), + (10459, 2, 139, 480, 0), + (10459, 3, 310, 3000, 0), + (10459, 4, 385, 4352, 0), + (10459, 5, 385, 4452, 0), + (10459, 6, 385, 4552, 0), + (10460, 1, 310, 6000, 0), + (10460, 2, 139, 480, 0), + (10460, 3, 310, 6000, 0), + (10460, 4, 385, 4352, 0), + (10460, 5, 385, 4452, 0), + (10460, 6, 385, 4552, 0), + (10461, 1, 310, 10000, 0), + (10461, 2, 139, 480, 0), + (10461, 3, 310, 10000, 0), + (10461, 4, 385, 4352, 0), + (10461, 5, 385, 4452, 0), + (10461, 6, 385, 4552, 0), + (10464, 1, 264, 120, 391), + (10465, 1, 264, 240, 391), + (10466, 1, 264, 360, 391), + (10467, 1, 128, 70, 70), + (10467, 2, 138, 1, 0), + (10467, 3, 140, 1, 0), + (10467, 4, 139, -2741, 0), + (10467, 5, 139, -16843, 0), + (10467, 6, 385, -16192, 0), + (10467, 7, 385, -10547, 0), + (10467, 8, 385, -13543, 0), + (10470, 1, 127, 10, 0), + (10470, 2, 385, 8048, 0), + (10471, 1, 127, 20, 0), + (10471, 2, 385, 8048, 0), + (10472, 1, 127, 30, 0), + (10472, 2, 385, 8048, 0), + (10473, 1, 265, 82, 0), + (10474, 1, 265, 83, 0), + (10475, 1, 265, 84, 0), + (10476, 1, 265, 85, 0), + (10477, 1, 265, 86, 0), + (10478, 1, 360, 3, 46246), + (10511, 1, 264, 60, 185), + (10511, 2, 264, 60, 10426), + (10512, 1, 264, 120, 185), + (10512, 2, 264, 120, 10426), + (10513, 1, 264, 180, 185), + (10513, 2, 264, 180, 10426), + (10514, 1, 264, 60, 519), + (10514, 2, 264, 60, 10427), + (10515, 1, 264, 180, 519), + (10515, 2, 264, 180, 10427), + (10516, 1, 264, 120, 519), + (10516, 2, 264, 120, 10427), + (10519, 1, 264, 60, 3213), + (10522, 1, 264, 2, 3732), + (10527, 1, 264, 30, 1400), + (10532, 1, 264, 30, 1401), + (10537, 1, 264, 30, 1402), + (10548, 1, 349, 10, 0), + (10548, 2, 200, 10, 0), + (10548, 3, 419, 27672, 20), + (10551, 1, 339, 10, 16825), + (10551, 2, 137, 31, 0), + (10552, 1, 339, 10, 16826), + (10552, 2, 137, 31, 0), + (10553, 1, 339, 10, 16827), + (10553, 2, 137, 31, 0), + (10554, 1, 339, 12, 8265), + (10554, 2, 138, 0, 0), + (10554, 3, 137, 31, 0), + (10554, 4, 311, 0, 0), + (10555, 1, 339, 14, 8265), + (10555, 2, 138, 0, 0), + (10555, 3, 137, 31, 0), + (10555, 4, 311, 0, 0), + (10556, 1, 339, 16, 8265), + (10556, 2, 138, 0, 0), + (10556, 3, 137, 31, 0), + (10556, 4, 311, 0, 0), + (10558, 1, 264, 60, 1120), + (10559, 1, 264, 120, 1120), + (10560, 1, 264, 180, 1120), + (10561, 1, 126, 5, 5), + (10561, 2, 139, 12576, 0), + (10561, 3, 126, 5, 5), + (10561, 4, 139, 12828, 0), + (10562, 1, 126, 10, 10), + (10562, 2, 139, 12576, 0), + (10562, 3, 126, 10, 10), + (10562, 4, 139, 12828, 0), + (10563, 1, 126, 15, 15), + (10563, 2, 139, 12576, 0), + (10563, 3, 126, 15, 15), + (10563, 4, 139, 12828, 0), + (10568, 1, 85, 23614, 50), + (10574, 1, 310, 720000, 0), + (10574, 2, 139, 4670, 0), + (10575, 1, 310, 720000, 0), + (10575, 2, 139, 4674, 0), + (10576, 1, 264, 420, 109), + (10579, 1, 264, 40, 3646), + (10580, 1, 264, 50, 3646), + (10588, 1, 264, 2, 601), + (10589, 1, 264, 4, 601), + (10590, 1, 264, 6, 601), + (10591, 1, 264, 8, 601), + (10592, 1, 264, 10, 601), + (10604, 1, 213, 13, 0), + (10605, 1, 213, 15, 0), + (10606, 1, 213, 17, 0), + (10607, 1, 215, 12, 0), + (10608, 1, 215, 14, 0), + (10609, 1, 215, 16, 0), + (10610, 1, 129, 25, 25), + (10610, 2, 385, 100265, 0), + (10611, 1, 129, 25, 25), + (10611, 2, 385, 100265, 0), + (10612, 1, 129, 25, 25), + (10612, 2, 385, 100265, 0), + (10621, 1, 264, 960, 180), + (10622, 1, 264, 1200, 180), + (10623, 1, 279, 19, 0), + (10624, 1, 279, 24, 0), + (10625, 1, 279, 30, 0), + (10627, 1, 224, 20, 74), + (10627, 2, 173, 1, 0), + (10628, 1, 224, 35, 74), + (10628, 2, 173, 2, 0), + (10629, 1, 224, 50, 74), + (10629, 2, 173, 3, 0), + (10632, 1, 265, 82, 0), + (10633, 1, 265, 83, 0), + (10634, 1, 265, 84, 0), + (10635, 1, 265, 85, 0), + (10636, 1, 265, 86, 0), + (10637, 1, 320, 12, 0), + (10638, 1, 320, 13, 0), + (10639, 1, 320, 14, 0), + (10641, 2, 385, 11064, 0), + (10643, 1, 124, 200, 200), + (10643, 2, 385, 19, 0), + (10643, 3, 144, 0, 0), + (10643, 4, 403, 3, 0), + (10643, 5, 404, 48, 0), + (10643, 6, 385, -21768, 0), + (10644, 1, 124, 250, 250), + (10644, 2, 385, 19, 0), + (10644, 3, 144, 0, 0), + (10644, 4, 403, 3, 0), + (10644, 5, 404, 48, 0), + (10644, 6, 385, -21768, 0), + (10645, 1, 124, 300, 300), + (10645, 2, 385, 19, 0), + (10645, 3, 144, 0, 0), + (10645, 4, 403, 3, 0), + (10645, 5, 404, 48, 0), + (10645, 6, 385, -21768, 0), + (10650, 1, 378, 1, 3), + (10651, 1, 378, 2, 3), + (10652, 1, 378, 3, 3), + (10653, 1, 310, 120000, 0), + (10653, 2, 139, 4502, 0), + (10653, 3, 139, 4509, 0), + (10654, 1, 310, 240000, 0), + (10654, 2, 139, 4502, 0), + (10654, 3, 139, 4509, 0), + (10655, 1, 310, 360000, 0), + (10655, 2, 139, 4502, 0), + (10655, 3, 139, 4509, 0), + (10656, 1, 287, 1, 0), + (10656, 2, 385, 15002, 0), + (10656, 3, 385, 15003, 0), + (10656, 4, 411, 128, 0), + (10657, 1, 264, 300, 276), + (10658, 1, 264, 600, 276), + (10659, 1, 264, 900, 276), + (10660, 1, 220, 175, 26), + (10660, 2, 220, 175, 30), + (10660, 3, 220, 175, 38), + (10661, 1, 220, 200, 26), + (10661, 2, 220, 200, 30), + (10661, 3, 220, 200, 38), + (10662, 1, 220, 225, 26), + (10662, 2, 220, 225, 30), + (10662, 3, 220, 225, 38), + (10663, 1, 220, 165, 21), + (10663, 2, 220, 165, 23), + (10663, 3, 220, 330, 52), + (10663, 4, 220, 165, 28), + (10664, 1, 220, 175, 21), + (10664, 2, 220, 175, 23), + (10664, 3, 220, 350, 52), + (10664, 4, 220, 175, 28), + (10665, 1, 220, 185, 21), + (10665, 2, 220, 185, 23), + (10665, 3, 220, 370, 52), + (10665, 4, 220, 185, 28), + (10666, 1, 264, 1200, 98), + (10667, 1, 264, 1320, 98), + (10668, 1, 264, 1440, 98), + (10671, 1, 310, 720000, 0), + (10671, 2, 139, 4590, 0), + (10672, 1, 310, 840000, 0), + (10672, 2, 139, 4590, 0), + (10673, 1, 310, 960000, 0), + (10673, 2, 139, 4590, 0), + (10674, 1, 310, 1080000, 0), + (10674, 2, 139, 4590, 0), + (10675, 1, 310, 1200000, 0), + (10675, 2, 139, 4590, 0), + (10676, 1, 339, 20, 23623), + (10676, 2, 137, 21, 0), + (10676, 3, 385, -18000, 0), + (10676, 4, 339, 20, 23623), + (10676, 5, 137, 343, 0), + (10676, 6, 385, -18000, 0), + (10677, 1, 339, 20, 23624), + (10677, 2, 137, 21, 0), + (10677, 3, 385, -18000, 0), + (10677, 4, 339, 20, 23624), + (10677, 5, 137, 343, 0), + (10677, 6, 385, -18000, 0), + (10678, 1, 339, 20, 23625), + (10678, 2, 137, 21, 0), + (10678, 3, 385, -18000, 0), + (10678, 4, 339, 20, 23625), + (10678, 5, 137, 343, 0), + (10678, 6, 385, -18000, 0), + (10685, 1, 266, 34, 0), + (10686, 1, 266, 39, 0), + (10687, 1, 266, 45, 0), + (10688, 1, 220, 125, 10), + (10689, 1, 220, 145, 10), + (10690, 1, 220, 165, 10), + (10691, 1, 220, 190, 10), + (10692, 1, 220, 220, 10), + (10705, 1, 85, 23542, 0), + (10706, 1, 85, 23543, 0), + (10707, 1, 85, 23544, 0), + (10714, 1, 264, 90, 873), + (10715, 1, 264, 180, 873), + (10717, 1, 264, 360, 184), + (10718, 1, 264, 450, 184), + (10719, 1, 264, 120, 872), + (10720, 1, 264, 240, 872), + (10721, 1, 264, 360, 872), + (10722, 1, 264, 120, 778), + (10723, 1, 264, 240, 778), + (10724, 1, 264, 360, 778), + (10725, 1, 264, 480, 778), + (10726, 1, 264, 600, 778), + (10727, 1, 264, 120, 2235), + (10728, 1, 264, 240, 2235), + (10730, 1, 264, 10, 870), + (10731, 1, 264, 20, 870), + (10733, 1, 264, 1, 219), + (10734, 1, 264, 2, 219), + (10735, 1, 264, 3, 219), + (10743, 1, 220, 135, 7), + (10744, 1, 220, 170, 7), + (10745, 1, 220, 205, 7), + (10748, 1, 59, -35, 0), + (10749, 1, 59, -42, 0), + (10750, 1, 264, 3024, 286), + (10750, 2, 264, 3024, 10753), + (10750, 3, 264, 3024, 9101), + (10751, 1, 264, 3456, 286), + (10751, 2, 264, 3456, 10753), + (10751, 3, 264, 3456, 9101), + (10755, 1, 59, -50, 0), + (10763, 1, 292, 50, 0), + (10764, 1, 292, 60, 0), + (10766, 1, 330, 70, 7), + (10767, 1, 330, 75, 7), + (10768, 1, 330, 80, 7), + (10769, 1, 310, 1440000, 0), + (10769, 2, 139, 4519, 0), + (10770, 1, 310, 1680000, 0), + (10770, 2, 139, 4519, 0), + (10778, 1, 274, 38, 0), + (10779, 1, 274, 40, 0), + (10780, 1, 274, 42, 0), + (10781, 1, 1, 186, 0), + (10782, 1, 1, 217, 0), + (10783, 1, 1, 248, 0), + (10784, 1, 1, 279, 0), + (10785, 1, 1, 310, 0), + (10788, 1, 363, 4, 0), + (10792, 1, 287, 1, 0), + (10792, 2, 385, 5240, 0), + (10792, 3, 385, 5340, 0), + (10792, 4, 385, 5440, 0), + (10792, 5, 385, 5540, 0), + (10792, 6, 385, 5640, 0), + (10793, 1, 287, 2, 0), + (10793, 2, 385, 5240, 0), + (10793, 3, 385, 5340, 0), + (10793, 4, 385, 5440, 0), + (10793, 5, 385, 5540, 0), + (10793, 6, 385, 5640, 0), + (10794, 1, 287, 3, 0), + (10794, 2, 385, 5240, 0), + (10794, 3, 385, 5340, 0), + (10794, 4, 385, 5440, 0), + (10794, 5, 385, 5540, 0), + (10794, 6, 385, 5640, 0), + (10795, 1, 287, 4, 0), + (10795, 2, 385, 5240, 0), + (10795, 3, 385, 5340, 0), + (10795, 4, 385, 5440, 0), + (10795, 5, 385, 5540, 0), + (10795, 6, 385, 5640, 0), + (10796, 1, 287, 5, 0), + (10796, 2, 385, 5240, 0), + (10796, 3, 385, 5340, 0), + (10796, 4, 385, 5440, 0), + (10796, 5, 385, 5540, 0), + (10796, 6, 385, 5640, 0), + (10800, 1, 264, 60, 462), + (10801, 1, 264, 120, 462), + (10802, 1, 264, 180, 462), + (10803, 1, 293, 25, 0), + (10804, 1, 293, 50, 0), + (10805, 1, 293, 75, 0), + (10815, 1, 185, 2, 1), + (10815, 2, 185, 2, 3), + (10816, 1, 185, 4, 1), + (10816, 2, 185, 4, 3), + (10817, 1, 185, 6, 1), + (10817, 2, 185, 6, 3), + (10818, 1, 185, 1, 36), + (10819, 1, 185, 3, 36), + (10820, 1, 185, 5, 36), + (10821, 1, 185, 2, 0), + (10821, 2, 185, 2, 2), + (10822, 1, 185, 4, 0), + (10822, 2, 185, 4, 2), + (10823, 1, 185, 6, 0), + (10823, 2, 185, 6, 2), + (10850, 1, 288, 100, 8), + (10851, 1, 288, 100, 8), + (10852, 1, 288, 100, 8), + (10853, 1, 292, 5, 0), + (10854, 1, 292, 10, 0), + (10855, 1, 292, 15, 0), + (10856, 1, 292, 20, 0), + (10857, 1, 292, 25, 0), + (10858, 1, 292, 30, 0), + (10859, 1, 292, 35, 0), + (10860, 1, 292, 40, 0), + (10861, 1, 292, 45, 0), + (10862, 1, 292, 46, 0), + (10863, 1, 292, 47, 0), + (10864, 1, 292, 48, 0), + (10865, 1, 216, 500, 8), + (10866, 1, 216, 550, 8), + (10867, 1, 216, 650, 8), + (10903, 1, 281, 25, 0), + (10904, 1, 281, 50, 0), + (10905, 1, 281, 75, 0), + (10906, 1, 59, -48, 0), + (10907, 1, 59, -51, 0), + (10908, 1, 59, -54, 0), + (10909, 1, 264, 60, 7007), + (10910, 1, 264, 120, 7007), + (10911, 1, 264, 180, 7007), + (10915, 1, 339, 10, 16876), + (10915, 2, 138, 0, 0), + (10915, 3, 142, 70, 0), + (10915, 4, 411, 32, 0), + (10915, 5, 348, 1, 0), + (10915, 6, 141, 1, 0), + (10916, 1, 339, 10, 16877), + (10916, 2, 138, 0, 0), + (10916, 3, 142, 70, 0), + (10916, 4, 411, 32, 0), + (10916, 5, 348, 1, 0), + (10916, 6, 141, 1, 0), + (10917, 1, 339, 10, 16878), + (10917, 2, 138, 0, 0), + (10917, 3, 142, 70, 0), + (10917, 4, 411, 32, 0), + (10917, 5, 348, 1, 0), + (10917, 6, 141, 1, 0), + (10950, 1, 287, 1, 0), + (10950, 2, 403, 4, 0), + (10950, 3, 404, 38, 0), + (10950, 4, 348, 1, 0), + (10950, 5, 137, 11, 0), + (10950, 6, 140, 2, 0), + (10951, 1, 264, 60, 447), + (10952, 1, 264, 120, 447), + (10953, 1, 264, 180, 447), + (10954, 1, 264, 60, 662), + (10955, 1, 264, 120, 662), + (10956, 1, 264, 180, 662), + (11000, 1, 227, 1, 73), + (11001, 1, 227, 2, 73), + (11002, 1, 227, 3, 73), + (11003, 1, 287, 1, 0), + (11003, 2, 137, 158, 0), + (11003, 3, 411, 2, 0), + (11004, 1, 287, 1, 0), + (11004, 2, 139, 8000, 0), + (11005, 1, 287, 2, 0), + (11005, 2, 139, 8000, 0), + (11006, 1, 287, 3, 0), + (11006, 2, 139, 8000, 0), + (11011, 1, 264, 480, 3710), + (11012, 1, 264, 600, 3710), + (11013, 1, 264, 720, 3710), + (11014, 1, 264, 10, 3899), + (11014, 2, 264, 10, 611), + (11014, 3, 264, 10, 960), + (11014, 4, 264, 10, 1252), + (11015, 1, 264, 20, 3899), + (11015, 2, 264, 20, 611), + (11015, 3, 264, 20, 960), + (11015, 4, 264, 20, 1252), + (11016, 1, 264, 30, 3899), + (11016, 2, 264, 30, 611), + (11016, 3, 264, 30, 960), + (11016, 4, 264, 30, 1252), + (11020, 1, 264, 40, 3899), + (11020, 2, 264, 40, 611), + (11020, 3, 264, 40, 960), + (11020, 4, 264, 40, 1252), + (11050, 1, 264, 360, 452), + (11050, 2, 264, 360, 6106), + (11050, 3, 264, 360, 493), + (11051, 1, 264, 720, 452), + (11051, 2, 264, 720, 6106), + (11051, 3, 264, 720, 493), + (11052, 1, 264, 1080, 452), + (11052, 2, 264, 1080, 6106), + (11052, 3, 264, 1080, 493), + (11053, 1, 264, 1260, 500), + (11054, 1, 264, 1440, 500), + (11059, 1, 264, 1440, 452), + (11059, 2, 264, 1440, 6106), + (11059, 3, 264, 1440, 493), + (11060, 1, 264, 1800, 452), + (11060, 2, 264, 1800, 6106), + (11060, 3, 264, 1800, 493), + (11061, 1, 114, -63, 0), + (11062, 1, 114, -64, 0), + (11063, 1, 114, -65, 0), + (11074, 1, 247, 100, 39), + (11075, 1, 247, 150, 39), + (11076, 1, 247, 200, 39), + (11077, 1, 264, 10, 986), + (11078, 1, 264, 10, 988), + (11079, 1, 264, 10, 987), + (11082, 1, 185, 40, 51), + (11083, 1, 185, 50, 51), + (11084, 1, 185, 60, 51), + (11085, 1, 247, 20, 2), + (11085, 2, 247, 20, 3), + (11085, 3, 247, 20, 77), + (11085, 4, 220, 25, 77), + (11085, 5, 220, 25, 2), + (11085, 6, 220, 25, 3), + (11086, 1, 247, 40, 2), + (11086, 2, 247, 40, 3), + (11086, 3, 247, 40, 77), + (11086, 4, 220, 35, 77), + (11086, 5, 220, 35, 2), + (11086, 6, 220, 35, 3), + (11087, 1, 247, 60, 2), + (11087, 2, 247, 60, 3), + (11087, 3, 247, 60, 77), + (11087, 4, 220, 50, 77), + (11087, 5, 220, 50, 2), + (11087, 6, 220, 50, 3), + (11088, 1, 264, 180, 505), + (11089, 1, 264, 360, 505), + (11090, 1, 264, 540, 505), + (11091, 1, 264, 720, 505), + (12396, 1, 172, 50, 0), + (12397, 1, 172, 51, 0), + (12398, 1, 172, 52, 0), + (12399, 1, 172, 53, 0), + (12400, 1, 172, 54, 0), + (12401, 1, 259, 56, 0), + (12402, 1, 259, 57, 0), + (12403, 1, 259, 58, 0), + (12404, 1, 259, 59, 0), + (12405, 1, 259, 60, 0), + (12406, 1, 69, 1100, 0), + (12407, 1, 69, 1200, 0), + (12408, 1, 69, 1300, 0), + (12409, 1, 69, 1400, 0), + (12410, 1, 69, 1500, 0), + (12411, 1, 1, 300, 0), + (12412, 1, 1, 350, 0), + (12413, 1, 1, 400, 0), + (12414, 1, 1, 450, 0), + (12415, 1, 1, 500, 0), + (12416, 1, 399, 3, 0), + (12416, 2, 141, 1, 0), + (12416, 3, 138, 0, 0), + (12416, 4, 142, 255, 0), + (12416, 5, 391, 0, 0), + (12416, 6, 311, 0, 0), + (12416, 7, 137, -152, 0), + (12416, 8, 411, 100350, 0), + (12416, 9, 137, -39, 0), + (12417, 1, 399, 6, 0), + (12417, 2, 141, 1, 0), + (12417, 3, 138, 0, 0), + (12417, 4, 142, 255, 0), + (12417, 5, 391, 0, 0), + (12417, 6, 311, 0, 0), + (12417, 7, 137, -152, 0), + (12417, 8, 411, 100350, 0), + (12417, 9, 137, -39, 0), + (12418, 1, 399, 9, 0), + (12418, 2, 141, 1, 0), + (12418, 3, 138, 0, 0), + (12418, 4, 142, 255, 0), + (12418, 5, 391, 0, 0), + (12418, 6, 311, 0, 0), + (12418, 7, 137, -152, 0), + (12418, 8, 411, 100350, 0), + (12418, 9, 137, -39, 0), + (12419, 1, 292, 15, 0), + (12420, 1, 292, 30, 0), + (12421, 1, 292, 45, 0), + (12423, 1, 273, 21, 0), + (12424, 1, 273, 24, 0), + (12425, 1, 273, 27, 0), + (12426, 1, 273, 21, 0), + (12427, 1, 273, 24, 0), + (12428, 1, 273, 27, 0), + (12432, 1, 294, 17, 100), + (12433, 1, 294, 19, 100), + (12434, 1, 294, 21, 100), + (12435, 1, 294, 23, 100), + (12436, 1, 294, 25, 100), + (12437, 1, 294, 27, 100), + (12438, 1, 200, 70, 0), + (12439, 1, 341, 210, 0), + (12440, 1, 341, 220, 0), + (12441, 1, 341, 230, 0), + (12442, 1, 341, 240, 0), + (12443, 1, 341, 250, 0), + (12444, 1, 318, 21, 0), + (12445, 1, 318, 22, 0), + (12446, 1, 318, 23, 0), + (12447, 1, 318, 24, 0), + (12448, 1, 318, 25, 0), + (12449, 1, 125, 31, 31), + (12449, 2, 137, 0, 0), + (12449, 3, 141, 1, 0), + (12449, 4, 139, -6233, 0), + (12449, 5, 139, -6265, 0), + (12449, 6, 125, 31, 31), + (12449, 7, 137, 147, 0), + (12449, 8, 141, 1, 0), + (12450, 1, 125, 34, 34), + (12450, 2, 137, 0, 0), + (12450, 3, 141, 1, 0), + (12450, 4, 139, -6233, 0), + (12450, 5, 139, -6265, 0), + (12450, 6, 125, 34, 34), + (12450, 7, 137, 147, 0), + (12450, 8, 141, 1, 0), + (12451, 1, 125, 37, 37), + (12451, 2, 137, 0, 0), + (12451, 3, 141, 1, 0), + (12451, 4, 139, -6233, 0), + (12451, 5, 139, -6265, 0), + (12451, 6, 125, 37, 37), + (12451, 7, 137, 147, 0), + (12451, 8, 141, 1, 0), + (12452, 1, 274, 38, 0), + (12453, 1, 274, 39, 0), + (12454, 1, 274, 40, 0), + (12455, 1, 15, 19, 0), + (12456, 1, 15, 20, 0), + (12457, 1, 15, 21, 0), + (12458, 1, 15, 22, 0), + (12459, 1, 15, 23, 0), + (12463, 1, 320, 9, 0), + (12464, 1, 320, 10, 0), + (12465, 1, 320, 11, 0), + (12466, 1, 320, 9, 0), + (12467, 1, 320, 10, 0), + (12468, 1, 320, 11, 0), + (12469, 1, 320, 9, 0), + (12470, 1, 320, 10, 0), + (12471, 1, 320, 11, 0), + (12472, 1, 320, 6, 0), + (12473, 1, 320, 7, 0), + (12474, 1, 320, 8, 0), + (12475, 1, 264, 180, 7003), + (12476, 1, 264, 360, 7003), + (12477, 1, 264, 540, 7003), + (12478, 1, 264, 60, 3705), + (12479, 1, 264, 120, 3705), + (12480, 1, 264, 180, 3705), + (12481, 1, 247, 40, 76), + (12482, 1, 247, 45, 76), + (12483, 1, 247, 65, 76), + (12484, 1, 247, 70, 76), + (12485, 1, 247, 30, 76), + (12486, 1, 247, 35, 76), + (12487, 1, 247, 25, 76), + (12488, 1, 247, 30, 76), + (12492, 1, 69, 1600, 0), + (12493, 1, 69, 1700, 0), + (12494, 1, 69, 1800, 0), + (12495, 1, 69, 1900, 0), + (12496, 1, 69, 2000, 0), + (12497, 1, 125, 40, 40), + (12497, 2, 137, 0, 0), + (12497, 3, 141, 1, 0), + (12497, 4, 139, -6233, 0), + (12497, 5, 139, -6265, 0), + (12497, 6, 125, 40, 40), + (12497, 7, 137, 147, 0), + (12497, 8, 141, 1, 0), + (12498, 1, 125, 43, 43), + (12498, 2, 137, 0, 0), + (12498, 3, 141, 1, 0), + (12498, 4, 139, -6233, 0), + (12498, 5, 139, -6265, 0), + (12498, 6, 125, 43, 43), + (12498, 7, 137, 147, 0), + (12498, 8, 141, 1, 0), + (12499, 1, 125, 46, 46), + (12499, 2, 137, 0, 0), + (12499, 3, 141, 1, 0), + (12499, 4, 139, -6233, 0), + (12499, 5, 139, -6265, 0), + (12499, 6, 125, 46, 46), + (12499, 7, 137, 147, 0), + (12499, 8, 141, 1, 0), + (12500, 1, 310, 1000, 0), + (12500, 2, 385, 4004, 0), + (12500, 3, 385, 11202, 0), + (12500, 4, 385, 11302, 0), + (12500, 5, 385, 11402, 0), + (12500, 6, 385, 11502, 0), + (12500, 7, 385, 11602, 0), + (12501, 1, 310, 2000, 0), + (12501, 2, 385, 4004, 0), + (12501, 3, 385, 11202, 0), + (12501, 4, 385, 11302, 0), + (12501, 5, 385, 11402, 0), + (12501, 6, 385, 11502, 0), + (12501, 7, 385, 11602, 0), + (12502, 1, 310, 3000, 0), + (12502, 2, 385, 4004, 0), + (12502, 3, 385, 11202, 0), + (12502, 4, 385, 11302, 0), + (12502, 5, 385, 11402, 0), + (12502, 6, 385, 11502, 0), + (12502, 7, 385, 11602, 0), + (12505, 1, 310, 4000, 0), + (12505, 2, 385, 4004, 0), + (12505, 3, 385, 11202, 0), + (12505, 4, 385, 11302, 0), + (12505, 5, 385, 11402, 0), + (12505, 6, 385, 11502, 0), + (12505, 7, 385, 11602, 0), + (12506, 1, 310, 5000, 0), + (12506, 2, 385, 4004, 0), + (12506, 3, 385, 11202, 0), + (12506, 4, 385, 11302, 0), + (12506, 5, 385, 11402, 0), + (12506, 6, 385, 11502, 0), + (12506, 7, 385, 11602, 0), + (12507, 1, 301, 120, 0), + (12508, 1, 247, 50, 76), + (12509, 1, 247, 55, 76), + (12510, 1, 247, 60, 76), + (12511, 1, 247, 75, 76), + (12512, 1, 247, 80, 76), + (12513, 1, 247, 85, 76), + (12514, 1, 247, 40, 76), + (12515, 1, 247, 45, 76), + (12516, 1, 247, 50, 76), + (12517, 1, 247, 35, 76), + (12518, 1, 247, 40, 76), + (12519, 1, 247, 45, 76), + (12523, 1, 294, 0, 200), + (12526, 1, 294, 0, 190), + (12527, 1, 294, 0, 195), + (12528, 1, 294, 0, 200), + (12529, 1, 294, 0, 165), + (12530, 1, 294, 0, 175), + (12531, 1, 294, 0, 185), + (12532, 1, 341, 260, 0), + (12533, 1, 341, 270, 0), + (12534, 1, 341, 280, 0), + (12535, 1, 341, 290, 0), + (12536, 1, 341, 300, 0), + (12537, 1, 318, 26, 0), + (12538, 1, 318, 27, 0), + (12539, 1, 318, 28, 0), + (12540, 1, 318, 29, 0), + (12541, 1, 318, 30, 0), + (12548, 1, 278, 900, 79230), + (12548, 2, 440, 87, 100), + (12549, 1, 278, 900, 86260), + (12549, 2, 440, 88, 100), + (12550, 1, 278, 900, 88260), + (12550, 2, 440, 89, 100), + (12551, 1, 278, 900, 91510), + (12551, 2, 440, 90, 100), + (12552, 1, 278, 900, 96305), + (12552, 2, 440, 91, 100), + (12553, 1, 294, 29, 102), + (12554, 1, 294, 31, 104), + (12555, 1, 294, 33, 106), + (12556, 1, 294, 23, 100), + (12557, 1, 294, 25, 100), + (12558, 1, 294, 27, 100), + (12559, 1, 190, 300, 0), + (12560, 1, 190, 350, 0), + (12561, 1, 190, 400, 0), + (12562, 1, 190, 450, 0), + (12563, 1, 190, 500, 0), + (12564, 1, 319, 28, 0), + (12565, 1, 319, 29, 0), + (12566, 1, 319, 30, 0), + (12567, 1, 274, 41, 0), + (12568, 1, 274, 42, 0), + (12569, 1, 274, 43, 0), + (12570, 1, 15, 24, 0), + (12571, 1, 15, 25, 0), + (12572, 1, 15, 26, 0), + (12573, 1, 15, 27, 0), + (12574, 1, 15, 28, 0), + (12575, 1, 292, 60, 0), + (12576, 1, 231, 17, 0), + (12577, 1, 231, 19, 0), + (12578, 1, 231, 21, 0), + (12579, 1, 85, 23569, 0), + (12580, 1, 85, 23570, 0), + (12581, 1, 85, 23571, 0), + (12582, 1, 264, 10, 9400), + (12583, 1, 264, 20, 9400), + (12584, 1, 264, 30, 9400), + (12587, 1, 264, 480, 9403), + (12588, 1, 264, 600, 9403), + (12589, 1, 264, 720, 9403), + (12591, 1, 247, 90, 76), + (12594, 1, 247, 55, 76), + (12597, 1, 247, 50, 76), + (12598, 1, 247, 55, 76), + (12600, 1, 310, 60000, 0), + (12600, 2, 139, 6197, 0), + (12600, 3, 411, 512, 0), + (12603, 1, 287, 1, 0), + (12603, 2, 139, 6197, 0), + (12603, 3, 411, 512, 0), + (12606, 1, 271, 5, 0), + (12607, 1, 310, 12000, 0), + (12607, 2, 385, 13007, 0), + (12607, 3, 385, 12105, 0), + (12607, 4, 385, 12205, 0), + (12607, 5, 310, 36000, 0), + (12607, 6, 385, 12305, 0), + (12607, 7, 385, 12405, 0), + (12607, 8, 385, 12505, 0), + (12607, 9, 411, 512, 0), + (12610, 1, 279, 19, 0), + (12612, 1, 439, 0, 124480), + (12612, 2, 345, 84, 25), + (12613, 1, 439, 0, 132440), + (12613, 2, 345, 86, 25), + (12615, 1, 310, 120000, 0), + (12615, 2, 139, 4695, 0), + (12615, 3, 411, 512, 0), + (12616, 1, 310, 240000, 0), + (12616, 2, 139, 4695, 0), + (12616, 3, 411, 512, 0), + (12617, 1, 310, 360000, 0), + (12617, 2, 139, 4695, 0), + (12617, 3, 411, 512, 0), + (12636, 1, 426, 1, 0), + (12637, 1, 426, 2, 0), + (12639, 1, 264, 240, 519), + (12639, 2, 264, 240, 10427), + (12642, 1, 264, 240, 185), + (12642, 2, 264, 240, 10426), + (12645, 1, 287, 1, 0), + (12645, 2, 385, 8190, 0), + (12645, 3, 287, 1, 0), + (12645, 4, 385, 21818, 0), + (12645, 5, 411, 64, 0), + (12646, 1, 287, 1, 0), + (12646, 2, 385, 3277, 0), + (12646, 3, 287, 1, 0), + (12646, 4, 385, 21816, 0), + (12652, 1, 399, 1, 0), + (12652, 2, 138, 1, 0), + (12652, 3, 137, 0, 0), + (12652, 4, 348, 10, 0), + (12652, 5, 311, 0, 0), + (12652, 6, 141, 1, 0), + (12652, 7, 134, 254, 0), + (12652, 8, 137, -39, 0), + (12653, 1, 399, 2, 0), + (12653, 2, 138, 1, 0), + (12653, 3, 137, 0, 0), + (12653, 4, 348, 10, 0), + (12653, 5, 311, 0, 0), + (12653, 6, 141, 1, 0), + (12653, 7, 134, 254, 0), + (12653, 8, 137, -39, 0), + (12654, 1, 399, 3, 0), + (12654, 2, 138, 1, 0), + (12654, 3, 137, 0, 0), + (12654, 4, 348, 10, 0), + (12654, 5, 311, 0, 0), + (12654, 6, 141, 1, 0), + (12654, 7, 134, 254, 0), + (12654, 8, 137, -39, 0), + (12664, 1, 264, 2, 3728), + (12667, 1, 220, 250, 26), + (12667, 2, 220, 250, 30), + (12667, 3, 220, 250, 38), + (12668, 1, 220, 275, 26), + (12668, 2, 220, 275, 30), + (12668, 3, 220, 275, 38), + (12669, 1, 220, 300, 26), + (12669, 2, 220, 300, 30), + (12669, 3, 220, 300, 38), + (12670, 1, 220, 200, 21), + (12670, 2, 220, 200, 23), + (12670, 3, 220, 400, 52), + (12670, 4, 220, 200, 28), + (12671, 1, 220, 215, 21), + (12671, 2, 220, 215, 23), + (12671, 3, 220, 450, 52), + (12671, 4, 220, 215, 28), + (12672, 1, 220, 235, 21), + (12672, 2, 220, 235, 23), + (12672, 3, 220, 510, 52), + (12672, 4, 220, 235, 28), + (12673, 1, 264, 960, 420), + (12674, 1, 227, 270, 32), + (12675, 1, 227, 300, 32), + (12676, 1, 227, 330, 32), + (12677, 1, 275, 92, 0), + (12678, 1, 287, 2, 0), + (12678, 2, 385, 15002, 0), + (12678, 3, 385, 15003, 0), + (12678, 4, 411, 128, 0), + (12679, 1, 264, 1200, 276), + (12680, 1, 264, 1500, 276), + (12681, 1, 264, 1800, 276), + (12685, 1, 292, 49, 0), + (12686, 1, 292, 50, 0), + (12687, 1, 292, 51, 0), + (12688, 1, 287, 1, 0), + (12688, 2, 385, 8473, 0), + (12688, 3, 385, 8318, 0), + (12688, 4, 385, 8418, 0), + (12688, 5, 385, 8518, 0), + (12688, 6, 411, 128, 0), + (12689, 1, 287, 2, 0), + (12689, 2, 139, 4691, 0), + (12689, 3, 411, 128, 0), + (12690, 1, 287, 2, 0), + (12690, 2, 385, 8111, 0), + (12690, 3, 385, 15008, 0), + (12690, 4, 385, 8411, 0), + (12690, 5, 385, 8511, 0), + (12690, 6, 411, 128, 0), + (12691, 1, 287, 1, 0), + (12691, 2, 385, 15007, 0), + (12691, 3, 411, 128, 0), + (12691, 4, 385, 8316, 0), + (12692, 1, 220, 255, 21), + (12692, 2, 220, 255, 23), + (12692, 3, 220, 570, 52), + (12692, 4, 220, 255, 28), + (12693, 1, 220, 275, 21), + (12693, 2, 220, 275, 23), + (12693, 3, 220, 630, 52), + (12693, 4, 220, 275, 28), + (12694, 1, 189, 16, 0), + (12695, 1, 189, 17, 0), + (12696, 1, 189, 18, 0), + (12697, 1, 330, 140, 0), + (12697, 2, 330, 140, 1), + (12697, 3, 330, 140, 2), + (12697, 4, 330, 140, 3), + (12697, 5, 330, 140, 28), + (12697, 6, 330, 140, 36), + (12697, 7, 330, 140, 77), + (12698, 1, 330, 145, 0), + (12698, 2, 330, 145, 1), + (12698, 3, 330, 145, 2), + (12698, 4, 330, 145, 3), + (12698, 5, 330, 145, 28), + (12698, 6, 330, 145, 36), + (12698, 7, 330, 145, 77), + (12699, 1, 330, 150, 0), + (12699, 2, 330, 150, 1), + (12699, 3, 330, 150, 2), + (12699, 4, 330, 150, 3), + (12699, 5, 330, 150, 28), + (12699, 6, 330, 150, 36), + (12699, 7, 330, 150, 77), + (12703, 1, 283, 240, 0), + (12704, 1, 283, 260, 0), + (12705, 1, 283, 280, 0), + (12706, 1, 220, 60, 28), + (12706, 2, 220, 60, 0), + (12706, 3, 427, 23598, 3), + (12706, 4, 428, 28, 0), + (12706, 5, 428, 0, 0), + (12707, 1, 220, 85, 28), + (12707, 2, 220, 85, 0), + (12707, 3, 427, 23598, 5), + (12707, 4, 428, 28, 0), + (12707, 5, 428, 0, 0), + (12708, 1, 220, 115, 28), + (12708, 2, 220, 115, 0), + (12708, 3, 427, 23598, 7), + (12708, 4, 428, 28, 0), + (12708, 5, 428, 0, 0), + (12709, 1, 287, 1, 0), + (12709, 2, 139, 4516, 0), + (12709, 3, 411, 256, 0), + (12710, 1, 310, 360000, 0), + (12710, 2, 139, 4516, 0), + (12710, 3, 411, 256, 0), + (12711, 1, 310, 720000, 0), + (12711, 2, 139, 4516, 0), + (12711, 3, 411, 256, 0), + (12712, 1, 310, 1080000, 0), + (12712, 2, 139, 4516, 0), + (12712, 3, 411, 256, 0), + (12713, 1, 264, 2, 8202), + (12714, 1, 264, 4, 8202), + (12715, 1, 264, 6, 8202), + (12716, 1, 264, 30, 3702), + (12717, 1, 264, 60, 3702), + (12718, 1, 264, 90, 3702), + (12719, 1, 128, 10, 0), + (12719, 2, 385, 12769, 0), + (12719, 3, 411, 256, 0), + (12720, 1, 287, 1, 0), + (12720, 2, 139, 12519, 0), + (12720, 3, 411, 256, 0), + (12721, 1, 264, 60, 3506), + (12722, 1, 264, 120, 3506), + (12723, 1, 264, 180, 3506), + (12727, 1, 264, 960, 359), + (12728, 1, 264, 1200, 359), + (12729, 1, 264, 1440, 359), + (12733, 1, 287, 2, 0), + (12733, 2, 137, 22, 0), + (12733, 3, 411, 256, 0), + (12734, 1, 375, 145, 0), + (12735, 1, 375, 150, 0), + (12736, 1, 375, 155, 0), + (12737, 1, 129, 5, 0), + (12737, 2, 385, 12768, 0), + (12737, 3, 411, 256, 0), + (12738, 1, 129, 10, 0), + (12738, 2, 385, 12768, 0), + (12738, 3, 411, 256, 0), + (12739, 1, 129, 15, 0), + (12739, 2, 385, 12768, 0), + (12739, 3, 411, 256, 0), + (12757, 1, 264, 6000, 68), + (12758, 1, 264, 6600, 68), + (12759, 1, 264, 7200, 68), + (12767, 1, 229, 50, 0), + (12768, 1, 229, 55, 0), + (12769, 1, 229, 60, 0), + (12773, 1, 264, 60, 1580), + (12774, 1, 264, 120, 1580), + (12775, 1, 264, 180, 1580), + (12776, 1, 264, 240, 1580), + (12777, 1, 264, 300, 1580), + (12779, 1, 264, 0, 826), + (12780, 1, 264, 1, 826), + (12781, 1, 264, 1, 826), + (12782, 1, 129, 10, 0), + (12782, 2, 385, 16106, 0), + (12783, 1, 129, 20, 0), + (12783, 2, 385, 16106, 0), + (12784, 1, 129, 30, 0), + (12784, 2, 385, 16106, 0), + (12792, 1, 397, 1000, 0), + (12793, 1, 397, 1200, 0), + (12794, 1, 397, 1250, 0), + (12795, 1, 213, 19, 0), + (12796, 1, 213, 21, 0), + (12797, 1, 213, 23, 0), + (12798, 1, 218, 21, 0), + (12799, 1, 218, 22, 0), + (12800, 1, 218, 23, 0), + (12801, 1, 215, 18, 0), + (12802, 1, 215, 20, 0), + (12803, 1, 215, 22, 0), + (12813, 1, 320, 2, 0), + (12814, 1, 320, 4, 0), + (12815, 1, 320, 6, 0), + (12816, 1, 128, 1, 0), + (12816, 2, 385, 2223, 0), + (12816, 3, 385, 2323, 0), + (12816, 4, 385, 2240, 0), + (12816, 5, 385, 2340, 0), + (12816, 6, 385, 2440, 0), + (12816, 7, 385, 2540, 0), + (12816, 8, 398, 6000, 0), + (12816, 9, 385, 11872, 0), + (12816, 10, 385, 14154, 0), + (12816, 11, 385, 18166, 0), + (12816, 12, 385, 27225, 0), + (12816, 13, 385, 2419, 0), + (12816, 14, 385, 2427, 0), + (12816, 15, 385, 30374, 0), + (12816, 16, 385, 2527, 0), + (12816, 17, 385, 36431, 0), + (12819, 1, 310, 23400, 0), + (12819, 2, 139, 4671, 0), + (12819, 3, 411, 32768, 0), + (12820, 1, 310, 46800, 0), + (12820, 2, 139, 4671, 0), + (12820, 3, 411, 32768, 0), + (12822, 1, 310, 153000, 0), + (12822, 2, 139, 8233, 0), + (12822, 3, 310, 120000, 0), + (12822, 4, 385, 2439, 0), + (12822, 5, 385, 2539, 0), + (12822, 6, 411, 32768, 0), + (12831, 1, 127, 17, 0), + (12831, 2, 385, 3291, 0), + (12831, 3, 385, 3817, 0), + (12831, 4, 411, 32768, 0), + (12834, 1, 264, 180, 128), + (12835, 1, 264, 225, 128), + (12840, 1, 264, 24, 3817), + (12841, 1, 264, 30, 3817), + (12843, 1, 225, 42, 0), + (12846, 1, 288, 20, 28), + (12846, 2, 288, 20, 0), + (12849, 1, 127, 14, 0), + (12849, 2, 385, 16794, 0), + (12849, 3, 411, 32768, 0), + (12860, 1, 294, 21, 102), + (12863, 1, 127, 15, 15), + (12863, 2, 137, 0, 0), + (12863, 3, 138, 0, 0), + (12863, 4, 141, 1, 0), + (12863, 5, 143, 3000, 0), + (12863, 6, 127, 15, 15), + (12863, 7, 385, 16555, 0), + (12863, 8, 385, 16655, 0), + (12871, 1, 264, 2160, 452), + (12871, 2, 264, 2160, 6106), + (12871, 3, 264, 2160, 493), + (12872, 1, 264, 2520, 452), + (12872, 2, 264, 2520, 6106), + (12872, 3, 264, 2520, 493), + (12874, 1, 264, 2572, 451), + (12876, 1, 264, 900, 7003), + (12877, 1, 264, 1260, 7003), + (12878, 1, 264, 1620, 7003), + (12881, 1, 264, 45, 172), + (12886, 1, 10, 0, 0), + (12887, 1, 10, 0, 0), + (12888, 1, 10, 0, 0), + (12889, 1, 10, 0, 0), + (12890, 1, 10, 0, 0), + (12894, 1, 264, 30, 1122), + (12899, 1, 264, 3456, 57), + (12899, 2, 264, 3456, 616), + (12900, 1, 264, 4320, 57), + (12900, 2, 264, 4320, 616), + (12902, 1, 264, 30, 1380), + (12903, 1, 264, 60, 1380), + (12907, 1, 264, 30, 1381), + (12908, 1, 264, 60, 1381), + (12912, 1, 264, 30, 1382), + (12913, 1, 264, 60, 1382), + (12920, 1, 130, 10, 10), + (12920, 2, 139, 2569, 0), + (12920, 3, 130, -10, -10), + (12920, 4, 139, 2568, 0), + (12929, 1, 287, 4, 0), + (12929, 2, 137, 3, 0), + (12929, 3, 137, 99, 0), + (12929, 4, 138, 0, 0), + (12929, 5, 244, 20, 0), + (12930, 1, 287, 5, 0), + (12930, 2, 137, 3, 0), + (12930, 3, 137, 99, 0), + (12930, 4, 138, 0, 0), + (12930, 5, 244, 15, 0), + (12945, 1, 280, 60, 0), + (12946, 1, 280, 61, 0), + (12947, 1, 280, 62, 0), + (12948, 1, 280, 63, 0), + (12949, 1, 280, 64, 0), + (12950, 1, 218, 21, 0), + (12951, 1, 218, 22, 0), + (12952, 1, 218, 23, 0), + (12953, 1, 218, 24, 0), + (12954, 1, 218, 25, 0), + (12966, 1, 131, 25, 25), + (12966, 2, 348, 10, 0), + (12966, 3, 137, -32, 0), + (12967, 1, 131, 50, 50), + (12967, 2, 348, 10, 0), + (12967, 3, 137, -32, 0), + (12968, 1, 264, 3, 1041), + (12969, 1, 264, 6, 1041), + (12970, 1, 264, 9, 1041), + (12977, 1, 287, 2, 0), + (12977, 2, 385, 16188, 0), + (12978, 1, 287, 4, 0), + (12978, 2, 385, 16188, 0), + (12979, 1, 287, 6, 0), + (12979, 2, 385, 16188, 0), + (12980, 1, 287, 8, 0), + (12980, 2, 385, 16188, 0), + (12981, 1, 287, 10, 0), + (12981, 2, 385, 16188, 0), + (12988, 1, 287, 3, 0), + (12988, 2, 140, 3, 0), + (12988, 3, 348, 1, 0), + (12988, 4, 138, 0, 0), + (12988, 5, 137, 0, 0), + (13001, 1, 264, 60, 9504), + (13002, 1, 264, 120, 9504), + (13003, 1, 264, 180, 9504), + (13005, 1, 264, 70, 171), + (13006, 1, 264, 80, 171), + (13007, 1, 264, 90, 171), + (13010, 1, 264, 10, 47), + (13011, 1, 264, 20, 47), + (13012, 1, 264, 30, 47), + (13013, 1, 264, 120, 446), + (13014, 1, 264, 240, 446), + (13015, 1, 264, 360, 446), + (13017, 1, 375, 15, 0), + (13018, 1, 375, 25, 0), + (13019, 1, 375, 35, 0), + (13021, 1, 247, 80, 2), + (13021, 2, 247, 80, 3), + (13021, 3, 247, 80, 77), + (13021, 4, 220, 75, 77), + (13021, 5, 220, 75, 2), + (13021, 6, 220, 75, 3), + (13023, 1, 330, 115, 0), + (13023, 2, 330, 115, 1), + (13023, 3, 330, 115, 2), + (13023, 4, 330, 115, 3), + (13023, 5, 330, 115, 28), + (13023, 6, 330, 115, 36), + (13023, 7, 330, 115, 77), + (13026, 1, 266, 26, 0), + (13027, 1, 266, 27, 0), + (13028, 1, 266, 28, 0), + (13029, 1, 288, 250, 51), + (13029, 2, 288, 60, 51), + (13032, 1, 185, 70, 51), + (13033, 1, 185, 80, 51), + (13035, 1, 220, 768, 74), + (13040, 1, 216, 280, 74), + (13043, 1, 169, 35, -1), + (13046, 1, 1, 240, 0), + (13047, 1, 1, 280, 0), + (13048, 1, 1, 320, 0), + (13049, 1, 1, 360, 0), + (13050, 1, 1, 400, 0), + (13051, 1, 287, 2, 0), + (13051, 2, 139, 8003, 0), + (13052, 1, 310, 120000, 0), + (13052, 2, 385, 3107, 0), + (13052, 3, 385, 3207, 0), + (13052, 4, 385, 3307, 0), + (13052, 5, 385, 3407, 0), + (13052, 6, 385, 3507, 0), + (13052, 7, 385, 3607, 0), + (13055, 1, 264, 60, 8400), + (13067, 1, 264, 120, 643), + (13072, 1, 310, 120000, 0), + (13072, 2, 139, 6197, 0), + (13072, 3, 411, 512, 0), + (13073, 1, 310, 180000, 0), + (13073, 2, 139, 6197, 0), + (13073, 3, 411, 512, 0), + (13074, 1, 330, 140, 0), + (13074, 2, 330, 140, 1), + (13074, 3, 330, 140, 2), + (13074, 4, 330, 140, 3), + (13074, 5, 330, 140, 28), + (13074, 6, 330, 140, 36), + (13075, 1, 330, 145, 0), + (13075, 2, 330, 145, 1), + (13075, 3, 330, 145, 2), + (13075, 4, 330, 145, 3), + (13075, 5, 330, 145, 28), + (13075, 6, 330, 145, 36), + (13076, 1, 330, 150, 0), + (13076, 2, 330, 150, 1), + (13076, 3, 330, 150, 2), + (13076, 4, 330, 150, 3), + (13076, 5, 330, 150, 28), + (13076, 6, 330, 150, 36), + (13077, 1, 330, 140, 0), + (13077, 2, 330, 140, 1), + (13077, 3, 330, 140, 2), + (13077, 4, 330, 140, 3), + (13077, 5, 330, 140, 28), + (13077, 6, 330, 140, 36), + (13077, 7, 330, 140, 77), + (13078, 1, 330, 145, 0), + (13078, 2, 330, 145, 1), + (13078, 3, 330, 145, 2), + (13078, 4, 330, 145, 3), + (13078, 5, 330, 145, 28), + (13078, 6, 330, 145, 36), + (13078, 7, 330, 145, 77), + (13080, 1, 172, 55, 0), + (13081, 1, 172, 56, 0), + (13082, 1, 172, 57, 0), + (13083, 1, 172, 58, 0), + (13084, 1, 172, 59, 0), + (13085, 1, 259, 61, 0), + (13086, 1, 259, 62, 0), + (13087, 1, 259, 63, 0), + (13088, 1, 259, 64, 0), + (13089, 1, 259, 65, 0), + (13090, 1, 339, 10, 8105), + (13090, 2, 142, 65, 0), + (13090, 3, 311, 0, 0), + (13090, 4, 134, 70, 0), + (13090, 5, 348, 10, 0), + (13090, 6, 137, 0, 0), + (13090, 7, 339, 10, 8105), + (13090, 8, 142, 65, 0), + (13090, 9, 311, 0, 0), + (13090, 10, 134, 70, 0), + (13090, 11, 348, 10, 0), + (13090, 12, 137, 100, 0), + (13090, 13, 339, 10, 8105), + (13090, 14, 142, 65, 0), + (13090, 15, 311, 0, 0), + (13090, 16, 134, 70, 0), + (13090, 17, 348, 10, 0), + (13090, 18, 137, 79, 0), + (13090, 19, 339, 10, 8105), + (13090, 20, 142, 65, 0), + (13090, 21, 311, 0, 0), + (13090, 22, 134, 70, 0), + (13090, 23, 348, 10, 0), + (13090, 24, 137, 147, 0), + (13090, 25, 339, 10, 11404), + (13090, 26, 142, 71, 0), + (13090, 27, 311, 0, 0), + (13090, 28, 134, 75, 0), + (13090, 29, 348, 10, 0), + (13090, 30, 137, 0, 0), + (13090, 31, 339, 10, 11404), + (13090, 32, 142, 71, 0), + (13090, 33, 311, 0, 0), + (13090, 34, 134, 75, 0), + (13090, 35, 348, 10, 0), + (13090, 36, 137, 100, 0), + (13090, 37, 339, 10, 11404), + (13090, 38, 142, 71, 0), + (13090, 39, 311, 0, 0), + (13090, 40, 134, 75, 0), + (13090, 41, 348, 10, 0), + (13090, 42, 137, 79, 0), + (13090, 43, 339, 10, 11404), + (13090, 44, 142, 71, 0), + (13090, 45, 311, 0, 0), + (13090, 46, 134, 75, 0), + (13090, 47, 348, 10, 0), + (13090, 48, 137, 147, 0), + (13090, 49, 339, 10, 13199), + (13090, 50, 142, 76, 0), + (13090, 51, 311, 0, 0), + (13090, 52, 134, 80, 0), + (13090, 53, 348, 10, 0), + (13090, 54, 137, 0, 0), + (13090, 55, 339, 10, 13199), + (13090, 56, 142, 76, 0), + (13090, 57, 311, 0, 0), + (13090, 58, 134, 80, 0), + (13090, 59, 348, 10, 0), + (13090, 60, 137, 100, 0), + (13090, 61, 339, 10, 13199), + (13090, 62, 142, 76, 0), + (13090, 63, 311, 0, 0), + (13090, 64, 134, 80, 0), + (13090, 65, 348, 10, 0), + (13090, 66, 137, 79, 0), + (13090, 67, 339, 10, 13199), + (13090, 68, 142, 76, 0), + (13090, 69, 311, 0, 0), + (13090, 70, 134, 80, 0), + (13090, 71, 348, 10, 0), + (13090, 72, 137, 147, 0), + (13090, 73, 339, 10, 13830), + (13090, 74, 142, 81, 0), + (13090, 75, 311, 0, 0), + (13090, 76, 134, 85, 0), + (13090, 77, 348, 10, 0), + (13090, 78, 137, 0, 0), + (13090, 79, 339, 10, 13830), + (13090, 80, 142, 81, 0), + (13090, 81, 311, 0, 0), + (13090, 82, 134, 85, 0), + (13090, 83, 348, 10, 0), + (13090, 84, 137, 100, 0), + (13090, 85, 339, 10, 13830), + (13090, 86, 142, 81, 0), + (13090, 87, 311, 0, 0), + (13090, 88, 134, 85, 0), + (13090, 89, 348, 10, 0), + (13090, 90, 137, 79, 0), + (13090, 91, 339, 10, 13830), + (13090, 92, 142, 81, 0), + (13090, 93, 311, 0, 0), + (13090, 94, 134, 85, 0), + (13090, 95, 348, 10, 0), + (13090, 96, 137, 147, 0), + (13090, 97, 339, 10, 27527), + (13090, 98, 142, 86, 0), + (13090, 99, 311, 0, 0), + (13090, 100, 134, 90, 0), + (13090, 101, 348, 10, 0), + (13090, 102, 137, 0, 0), + (13090, 103, 339, 10, 27527), + (13090, 104, 142, 86, 0), + (13090, 105, 311, 0, 0), + (13090, 106, 134, 90, 0), + (13090, 107, 348, 10, 0), + (13090, 108, 137, 100, 0), + (13090, 109, 339, 10, 27527), + (13090, 110, 142, 86, 0), + (13090, 111, 311, 0, 0), + (13090, 112, 134, 90, 0), + (13090, 113, 348, 10, 0), + (13090, 114, 137, 79, 0), + (13090, 115, 339, 10, 27527), + (13090, 116, 142, 86, 0), + (13090, 117, 311, 0, 0), + (13090, 118, 134, 90, 0), + (13090, 119, 348, 10, 0), + (13090, 120, 137, 147, 0), + (13091, 1, 339, 10, 8105), + (13091, 2, 142, 65, 0), + (13091, 3, 311, 0, 0), + (13091, 4, 134, 70, 0), + (13091, 5, 348, 10, 0), + (13091, 6, 137, 0, 0), + (13091, 7, 339, 10, 8105), + (13091, 8, 142, 65, 0), + (13091, 9, 311, 0, 0), + (13091, 10, 134, 70, 0), + (13091, 11, 348, 10, 0), + (13091, 12, 137, 100, 0), + (13091, 13, 339, 10, 8105), + (13091, 14, 142, 65, 0), + (13091, 15, 311, 0, 0), + (13091, 16, 134, 70, 0), + (13091, 17, 348, 10, 0), + (13091, 18, 137, 79, 0), + (13091, 19, 339, 10, 8105), + (13091, 20, 142, 65, 0), + (13091, 21, 311, 0, 0), + (13091, 22, 134, 70, 0), + (13091, 23, 348, 10, 0), + (13091, 24, 137, 147, 0), + (13091, 25, 339, 10, 11404), + (13091, 26, 142, 71, 0), + (13091, 27, 311, 0, 0), + (13091, 28, 134, 75, 0), + (13091, 29, 348, 10, 0), + (13091, 30, 137, 0, 0), + (13091, 31, 339, 10, 11404), + (13091, 32, 142, 71, 0), + (13091, 33, 311, 0, 0), + (13091, 34, 134, 75, 0), + (13091, 35, 348, 10, 0), + (13091, 36, 137, 100, 0), + (13091, 37, 339, 10, 11404), + (13091, 38, 142, 71, 0), + (13091, 39, 311, 0, 0), + (13091, 40, 134, 75, 0), + (13091, 41, 348, 10, 0), + (13091, 42, 137, 79, 0), + (13091, 43, 339, 10, 11404), + (13091, 44, 142, 71, 0), + (13091, 45, 311, 0, 0), + (13091, 46, 134, 75, 0), + (13091, 47, 348, 10, 0), + (13091, 48, 137, 147, 0), + (13091, 49, 339, 10, 13199), + (13091, 50, 142, 76, 0), + (13091, 51, 311, 0, 0), + (13091, 52, 134, 80, 0), + (13091, 53, 348, 10, 0), + (13091, 54, 137, 0, 0), + (13091, 55, 339, 10, 13199), + (13091, 56, 142, 76, 0), + (13091, 57, 311, 0, 0), + (13091, 58, 134, 80, 0), + (13091, 59, 348, 10, 0), + (13091, 60, 137, 100, 0), + (13091, 61, 339, 10, 13199), + (13091, 62, 142, 76, 0), + (13091, 63, 311, 0, 0), + (13091, 64, 134, 80, 0), + (13091, 65, 348, 10, 0), + (13091, 66, 137, 79, 0), + (13091, 67, 339, 10, 13199), + (13091, 68, 142, 76, 0), + (13091, 69, 311, 0, 0), + (13091, 70, 134, 80, 0), + (13091, 71, 348, 10, 0), + (13091, 72, 137, 147, 0), + (13091, 73, 339, 10, 13830), + (13091, 74, 142, 81, 0), + (13091, 75, 311, 0, 0), + (13091, 76, 134, 85, 0), + (13091, 77, 348, 10, 0), + (13091, 78, 137, 0, 0), + (13091, 79, 339, 10, 13830), + (13091, 80, 142, 81, 0), + (13091, 81, 311, 0, 0), + (13091, 82, 134, 85, 0), + (13091, 83, 348, 10, 0), + (13091, 84, 137, 100, 0), + (13091, 85, 339, 10, 13830), + (13091, 86, 142, 81, 0), + (13091, 87, 311, 0, 0), + (13091, 88, 134, 85, 0), + (13091, 89, 348, 10, 0), + (13091, 90, 137, 79, 0), + (13091, 91, 339, 10, 13830), + (13091, 92, 142, 81, 0), + (13091, 93, 311, 0, 0), + (13091, 94, 134, 85, 0), + (13091, 95, 348, 10, 0), + (13091, 96, 137, 147, 0), + (13091, 97, 339, 10, 27527), + (13091, 98, 142, 86, 0), + (13091, 99, 311, 0, 0), + (13091, 100, 134, 90, 0), + (13091, 101, 348, 10, 0), + (13091, 102, 137, 0, 0), + (13091, 103, 339, 10, 27527), + (13091, 104, 142, 86, 0), + (13091, 105, 311, 0, 0), + (13091, 106, 134, 90, 0), + (13091, 107, 348, 10, 0), + (13091, 108, 137, 100, 0), + (13091, 109, 339, 10, 27527), + (13091, 110, 142, 86, 0), + (13091, 111, 311, 0, 0), + (13091, 112, 134, 90, 0), + (13091, 113, 348, 10, 0), + (13091, 114, 137, 79, 0), + (13091, 115, 339, 10, 27527), + (13091, 116, 142, 86, 0), + (13091, 117, 311, 0, 0), + (13091, 118, 134, 90, 0), + (13091, 119, 348, 10, 0), + (13091, 120, 137, 147, 0), + (13092, 1, 217, 0, 102280), + (13092, 2, 346, 84, 18), + (13093, 1, 217, 0, 109400), + (13093, 2, 346, 86, 18), + (13094, 1, 217, 0, 116800), + (13094, 2, 346, 88, 18), + (13095, 1, 439, 0, 140680), + (13095, 2, 345, 88, 25), + (13096, 1, 287, 1, 0), + (13096, 2, 140, 3, 0), + (13096, 3, 348, 1, 0), + (13096, 4, 138, 0, 0), + (13096, 5, 137, 0, 0), + (13097, 1, 287, 2, 0), + (13097, 2, 140, 3, 0), + (13097, 3, 348, 1, 0), + (13097, 4, 138, 0, 0), + (13097, 5, 137, 0, 0), + (13098, 1, 287, 3, 0), + (13098, 2, 140, 3, 0), + (13098, 3, 348, 1, 0), + (13098, 4, 138, 0, 0), + (13098, 5, 137, 0, 0), + (13099, 1, 132, 15, 15), + (13101, 1, 360, 25, 27537), + (13102, 1, 360, 25, 27538), + (13103, 1, 360, 25, 27539), + (13104, 1, 303, 14000, 18000), + (13104, 2, 139, 2766, 0), + (13105, 1, 303, 18000, 22500), + (13105, 2, 139, 2766, 0), + (13106, 1, 303, 22500, 27500), + (13106, 2, 139, 2766, 0), + (13110, 1, 185, 8, 1), + (13110, 2, 185, 8, 3), + (13111, 1, 185, 10, 1), + (13111, 2, 185, 10, 3), + (13113, 1, 185, 7, 36), + (13114, 1, 185, 9, 36), + (13116, 1, 185, 8, 0), + (13116, 2, 185, 8, 2), + (13117, 1, 185, 10, 0), + (13117, 2, 185, 10, 2), + (13122, 1, 2, 128, 0), + (13123, 1, 2, 132, 0), + (13124, 1, 2, 136, 0), + (13127, 1, 287, 4, 0), + (13127, 2, 140, 3, 0), + (13127, 3, 348, 1, 0), + (13127, 4, 138, 0, 0), + (13127, 5, 137, 0, 0), + (13130, 1, 264, 1440, 7003), + (13140, 1, 264, 480, 391), + (13141, 1, 264, 600, 391), + (13142, 1, 264, 720, 391), + (13143, 1, 127, 17, 0), + (13143, 2, 385, 8054, 0), + (13144, 1, 127, 34, 0), + (13144, 2, 385, 8054, 0), + (13145, 1, 127, 50, 0), + (13145, 2, 385, 8054, 0), + (13146, 1, 127, 17, 0), + (13146, 2, 385, 8054, 0), + (13147, 1, 127, 34, 0), + (13147, 2, 385, 8054, 0), + (13148, 1, 127, 50, 0), + (13148, 2, 385, 8054, 0), + (13149, 1, 97, 550, 0), + (13150, 1, 97, 600, 0), + (13151, 1, 97, 650, 0), + (13152, 1, 97, 700, 0), + (13153, 1, 97, 750, 0), + (13166, 1, 264, 5, 749), + (13166, 2, 264, 5, 822), + (13166, 3, 264, 5, 1274), + (13166, 4, 264, 5, 1275), + (13167, 1, 264, 10, 749), + (13167, 2, 264, 10, 822), + (13167, 3, 264, 10, 1274), + (13167, 4, 264, 10, 1275), + (13168, 1, 264, 15, 749), + (13168, 2, 264, 15, 822), + (13168, 3, 264, 15, 1274), + (13168, 4, 264, 15, 1275), + (13184, 1, 220, 315, 26), + (13185, 1, 220, 400, 26), + (13186, 1, 220, 500, 26), + (13187, 1, 405, 19, 0), + (13188, 1, 405, 21, 0), + (13189, 1, 405, 23, 0), + (13196, 1, 279, 31, 0), + (13197, 1, 279, 35, 0), + (13198, 1, 279, 39, 0), + (13199, 1, 378, 30, 31), + (13200, 1, 378, 35, 31), + (13201, 1, 378, 40, 31), + (13204, 1, 264, 180, 8261), + (13205, 1, 264, 360, 8261), + (13206, 1, 264, 540, 8261), + (13207, 1, 288, 100, 8), + (13208, 1, 288, 100, 8), + (13209, 1, 288, 100, 8), + (13210, 1, 325, 70, 0), + (13211, 1, 325, 75, 0), + (13212, 1, 325, 80, 0), + (13213, 1, 220, 285, 8), + (13214, 1, 220, 315, 8), + (13215, 1, 220, 350, 8), + (13216, 1, 220, 390, 8), + (13217, 1, 220, 440, 8), + (13218, 1, 216, 750, 8), + (13219, 1, 114, -12, 0), + (13220, 1, 114, -15, 0), + (13221, 1, 114, -18, 0), + (13222, 1, 310, 240000, 0), + (13222, 2, 139, 6197, 0), + (13222, 3, 411, 512, 0), + (13223, 1, 310, 300000, 0), + (13223, 2, 139, 6197, 0), + (13223, 3, 411, 512, 0), + (13226, 1, 360, 60, 27593), + (13238, 1, 320, 9, 0), + (13239, 1, 320, 10, 0), + (13240, 1, 320, 11, 0), + (13262, 1, 264, 1008, 102), + (13263, 1, 264, 1152, 102), + (13264, 1, 264, 1290, 102), + (13278, 1, 213, 25, 0), + (13281, 1, 318, 31, 0), + (13286, 1, 278, 900, 102200), + (13286, 2, 440, 92, 100), + (13294, 1, 339, 10, 8105), + (13294, 2, 142, 65, 0), + (13294, 3, 311, 0, 0), + (13294, 4, 134, 70, 0), + (13294, 5, 348, 10, 0), + (13294, 6, 137, 0, 0), + (13294, 7, 339, 10, 8105), + (13294, 8, 142, 65, 0), + (13294, 9, 311, 0, 0), + (13294, 10, 134, 70, 0), + (13294, 11, 348, 10, 0), + (13294, 12, 137, 100, 0), + (13294, 13, 339, 10, 8105), + (13294, 14, 142, 65, 0), + (13294, 15, 311, 0, 0), + (13294, 16, 134, 70, 0), + (13294, 17, 348, 10, 0), + (13294, 18, 137, 79, 0), + (13294, 19, 339, 10, 8105), + (13294, 20, 142, 65, 0), + (13294, 21, 311, 0, 0), + (13294, 22, 134, 70, 0), + (13294, 23, 348, 10, 0), + (13294, 24, 137, 147, 0), + (13294, 25, 339, 10, 11404), + (13294, 26, 142, 71, 0), + (13294, 27, 311, 0, 0), + (13294, 28, 134, 75, 0), + (13294, 29, 348, 10, 0), + (13294, 30, 137, 0, 0), + (13294, 31, 339, 10, 11404), + (13294, 32, 142, 71, 0), + (13294, 33, 311, 0, 0), + (13294, 34, 134, 75, 0), + (13294, 35, 348, 10, 0), + (13294, 36, 137, 100, 0), + (13294, 37, 339, 10, 11404), + (13294, 38, 142, 71, 0), + (13294, 39, 311, 0, 0), + (13294, 40, 134, 75, 0), + (13294, 41, 348, 10, 0), + (13294, 42, 137, 79, 0), + (13294, 43, 339, 10, 11404), + (13294, 44, 142, 71, 0), + (13294, 45, 311, 0, 0), + (13294, 46, 134, 75, 0), + (13294, 47, 348, 10, 0), + (13294, 48, 137, 147, 0), + (13294, 49, 339, 10, 13199), + (13294, 50, 142, 76, 0), + (13294, 51, 311, 0, 0), + (13294, 52, 134, 80, 0), + (13294, 53, 348, 10, 0), + (13294, 54, 137, 0, 0), + (13294, 55, 339, 10, 13199), + (13294, 56, 142, 76, 0), + (13294, 57, 311, 0, 0), + (13294, 58, 134, 80, 0), + (13294, 59, 348, 10, 0), + (13294, 60, 137, 100, 0), + (13294, 61, 339, 10, 13199), + (13294, 62, 142, 76, 0), + (13294, 63, 311, 0, 0), + (13294, 64, 134, 80, 0), + (13294, 65, 348, 10, 0), + (13294, 66, 137, 79, 0), + (13294, 67, 339, 10, 13199), + (13294, 68, 142, 76, 0), + (13294, 69, 311, 0, 0), + (13294, 70, 134, 80, 0), + (13294, 71, 348, 10, 0), + (13294, 72, 137, 147, 0), + (13294, 73, 339, 10, 13830), + (13294, 74, 142, 81, 0), + (13294, 75, 311, 0, 0), + (13294, 76, 134, 85, 0), + (13294, 77, 348, 10, 0), + (13294, 78, 137, 0, 0), + (13294, 79, 339, 10, 13830), + (13294, 80, 142, 81, 0), + (13294, 81, 311, 0, 0), + (13294, 82, 134, 85, 0), + (13294, 83, 348, 10, 0), + (13294, 84, 137, 100, 0), + (13294, 85, 339, 10, 13830), + (13294, 86, 142, 81, 0), + (13294, 87, 311, 0, 0), + (13294, 88, 134, 85, 0), + (13294, 89, 348, 10, 0), + (13294, 90, 137, 79, 0), + (13294, 91, 339, 10, 13830), + (13294, 92, 142, 81, 0), + (13294, 93, 311, 0, 0), + (13294, 94, 134, 85, 0), + (13294, 95, 348, 10, 0), + (13294, 96, 137, 147, 0), + (13294, 97, 339, 10, 27527), + (13294, 98, 142, 86, 0), + (13294, 99, 311, 0, 0), + (13294, 100, 134, 90, 0), + (13294, 101, 348, 10, 0), + (13294, 102, 137, 0, 0), + (13294, 103, 339, 10, 27527), + (13294, 104, 142, 86, 0), + (13294, 105, 311, 0, 0), + (13294, 106, 134, 90, 0), + (13294, 107, 348, 10, 0), + (13294, 108, 137, 100, 0), + (13294, 109, 339, 10, 27527), + (13294, 110, 142, 86, 0), + (13294, 111, 311, 0, 0), + (13294, 112, 134, 90, 0), + (13294, 113, 348, 10, 0), + (13294, 114, 137, 79, 0), + (13294, 115, 339, 10, 27527), + (13294, 116, 142, 86, 0), + (13294, 117, 311, 0, 0), + (13294, 118, 134, 90, 0), + (13294, 119, 348, 10, 0), + (13294, 120, 137, 147, 0), + (13294, 121, 339, 10, 30644), + (13294, 122, 142, 91, 0), + (13294, 123, 311, 0, 0), + (13294, 124, 134, 95, 0), + (13294, 125, 348, 10, 0), + (13294, 126, 137, 0, 0), + (13294, 127, 339, 10, 30644), + (13294, 128, 142, 91, 0), + (13294, 129, 311, 0, 0), + (13294, 130, 134, 95, 0), + (13294, 131, 348, 10, 0), + (13294, 132, 137, 100, 0), + (13294, 133, 339, 10, 30644), + (13294, 134, 142, 91, 0), + (13294, 135, 311, 0, 0), + (13294, 136, 134, 95, 0), + (13294, 137, 348, 10, 0), + (13294, 138, 137, 79, 0), + (13294, 139, 339, 10, 30644), + (13294, 140, 142, 91, 0), + (13294, 141, 311, 0, 0), + (13294, 142, 134, 95, 0), + (13294, 143, 348, 10, 0), + (13294, 144, 137, 147, 0), + (13295, 1, 339, 10, 8105), + (13295, 2, 142, 65, 0), + (13295, 3, 311, 0, 0), + (13295, 4, 134, 70, 0), + (13295, 5, 348, 10, 0), + (13295, 6, 137, 0, 0), + (13295, 7, 339, 10, 8105), + (13295, 8, 142, 65, 0), + (13295, 9, 311, 0, 0), + (13295, 10, 134, 70, 0), + (13295, 11, 348, 10, 0), + (13295, 12, 137, 100, 0), + (13295, 13, 339, 10, 8105), + (13295, 14, 142, 65, 0), + (13295, 15, 311, 0, 0), + (13295, 16, 134, 70, 0), + (13295, 17, 348, 10, 0), + (13295, 18, 137, 79, 0), + (13295, 19, 339, 10, 8105), + (13295, 20, 142, 65, 0), + (13295, 21, 311, 0, 0), + (13295, 22, 134, 70, 0), + (13295, 23, 348, 10, 0), + (13295, 24, 137, 147, 0), + (13295, 25, 339, 10, 11404), + (13295, 26, 142, 71, 0), + (13295, 27, 311, 0, 0), + (13295, 28, 134, 75, 0), + (13295, 29, 348, 10, 0), + (13295, 30, 137, 0, 0), + (13295, 31, 339, 10, 11404), + (13295, 32, 142, 71, 0), + (13295, 33, 311, 0, 0), + (13295, 34, 134, 75, 0), + (13295, 35, 348, 10, 0), + (13295, 36, 137, 100, 0), + (13295, 37, 339, 10, 11404), + (13295, 38, 142, 71, 0), + (13295, 39, 311, 0, 0), + (13295, 40, 134, 75, 0), + (13295, 41, 348, 10, 0), + (13295, 42, 137, 79, 0), + (13295, 43, 339, 10, 11404), + (13295, 44, 142, 71, 0), + (13295, 45, 311, 0, 0), + (13295, 46, 134, 75, 0), + (13295, 47, 348, 10, 0), + (13295, 48, 137, 147, 0), + (13295, 49, 339, 10, 13199), + (13295, 50, 142, 76, 0), + (13295, 51, 311, 0, 0), + (13295, 52, 134, 80, 0), + (13295, 53, 348, 10, 0), + (13295, 54, 137, 0, 0), + (13295, 55, 339, 10, 13199), + (13295, 56, 142, 76, 0), + (13295, 57, 311, 0, 0), + (13295, 58, 134, 80, 0), + (13295, 59, 348, 10, 0), + (13295, 60, 137, 100, 0), + (13295, 61, 339, 10, 13199), + (13295, 62, 142, 76, 0), + (13295, 63, 311, 0, 0), + (13295, 64, 134, 80, 0), + (13295, 65, 348, 10, 0), + (13295, 66, 137, 79, 0), + (13295, 67, 339, 10, 13199), + (13295, 68, 142, 76, 0), + (13295, 69, 311, 0, 0), + (13295, 70, 134, 80, 0), + (13295, 71, 348, 10, 0), + (13295, 72, 137, 147, 0), + (13295, 73, 339, 10, 13830), + (13295, 74, 142, 81, 0), + (13295, 75, 311, 0, 0), + (13295, 76, 134, 85, 0), + (13295, 77, 348, 10, 0), + (13295, 78, 137, 0, 0), + (13295, 79, 339, 10, 13830), + (13295, 80, 142, 81, 0), + (13295, 81, 311, 0, 0), + (13295, 82, 134, 85, 0), + (13295, 83, 348, 10, 0), + (13295, 84, 137, 100, 0), + (13295, 85, 339, 10, 13830), + (13295, 86, 142, 81, 0), + (13295, 87, 311, 0, 0), + (13295, 88, 134, 85, 0), + (13295, 89, 348, 10, 0), + (13295, 90, 137, 79, 0), + (13295, 91, 339, 10, 13830), + (13295, 92, 142, 81, 0), + (13295, 93, 311, 0, 0), + (13295, 94, 134, 85, 0), + (13295, 95, 348, 10, 0), + (13295, 96, 137, 147, 0), + (13295, 97, 339, 10, 27527), + (13295, 98, 142, 86, 0), + (13295, 99, 311, 0, 0), + (13295, 100, 134, 90, 0), + (13295, 101, 348, 10, 0), + (13295, 102, 137, 0, 0), + (13295, 103, 339, 10, 27527), + (13295, 104, 142, 86, 0), + (13295, 105, 311, 0, 0), + (13295, 106, 134, 90, 0), + (13295, 107, 348, 10, 0), + (13295, 108, 137, 100, 0), + (13295, 109, 339, 10, 27527), + (13295, 110, 142, 86, 0), + (13295, 111, 311, 0, 0), + (13295, 112, 134, 90, 0), + (13295, 113, 348, 10, 0), + (13295, 114, 137, 79, 0), + (13295, 115, 339, 10, 27527), + (13295, 116, 142, 86, 0), + (13295, 117, 311, 0, 0), + (13295, 118, 134, 90, 0), + (13295, 119, 348, 10, 0), + (13295, 120, 137, 147, 0), + (13295, 121, 339, 10, 30644), + (13295, 122, 142, 91, 0), + (13295, 123, 311, 0, 0), + (13295, 124, 134, 95, 0), + (13295, 125, 348, 10, 0), + (13295, 126, 137, 0, 0), + (13295, 127, 339, 10, 30644), + (13295, 128, 142, 91, 0), + (13295, 129, 311, 0, 0), + (13295, 130, 134, 95, 0), + (13295, 131, 348, 10, 0), + (13295, 132, 137, 100, 0), + (13295, 133, 339, 10, 30644), + (13295, 134, 142, 91, 0), + (13295, 135, 311, 0, 0), + (13295, 136, 134, 95, 0), + (13295, 137, 348, 10, 0), + (13295, 138, 137, 79, 0), + (13295, 139, 339, 10, 30644), + (13295, 140, 142, 91, 0), + (13295, 141, 311, 0, 0), + (13295, 142, 134, 95, 0), + (13295, 143, 348, 10, 0), + (13295, 144, 137, 147, 0), + (13296, 1, 125, 49, 49), + (13296, 2, 137, 0, 0), + (13296, 3, 141, 1, 0), + (13296, 4, 139, -6233, 0), + (13296, 5, 139, -6265, 0), + (13296, 6, 125, 49, 49), + (13296, 7, 137, 147, 0), + (13296, 8, 141, 1, 0), + (13297, 1, 125, 52, 52), + (13297, 2, 137, 0, 0), + (13297, 3, 141, 1, 0), + (13297, 4, 139, -6233, 0), + (13297, 5, 139, -6265, 0), + (13297, 6, 125, 52, 52), + (13297, 7, 137, 147, 0), + (13297, 8, 141, 1, 0), + (13299, 1, 319, 31, 0), + (13302, 1, 274, 44, 0), + (13305, 1, 189, 19, 0), + (13308, 1, 265, 87, 0), + (13313, 1, 15, 29, 0), + (13318, 1, 97, 850, 0), + (13323, 1, 320, 15, 0), + (13326, 1, 330, 155, 0), + (13326, 2, 330, 155, 1), + (13326, 3, 330, 155, 2), + (13326, 4, 330, 155, 3), + (13326, 5, 330, 155, 28), + (13326, 6, 330, 155, 36), + (13332, 1, 330, 155, 0), + (13332, 2, 330, 155, 1), + (13332, 3, 330, 155, 2), + (13332, 4, 330, 155, 3), + (13332, 5, 330, 155, 28), + (13332, 6, 330, 155, 36), + (13332, 7, 330, 155, 77), + (13338, 1, 1, 370, 0), + (13343, 1, 1, 340, 0), + (13348, 1, 1, 440, 0), + (13353, 1, 1, 330, 0), + (13358, 1, 1, 540, 0), + (13396, 1, 375, 40, 0), + (13404, 1, 273, 8, 0), + (13411, 1, 399, 4, 0), + (13411, 2, 138, 1, 0), + (13411, 3, 137, 0, 0), + (13411, 4, 348, 10, 0), + (13411, 5, 311, 0, 0), + (13411, 6, 141, 1, 0), + (13411, 7, 134, 254, 0), + (13411, 8, 137, -39, 0), + (13413, 1, 399, 12, 0), + (13413, 2, 141, 1, 0), + (13413, 3, 138, 0, 0), + (13413, 4, 142, 255, 0), + (13413, 5, 391, 0, 0), + (13413, 6, 311, 0, 0), + (13413, 7, 137, -152, 0), + (13413, 8, 411, 100350, 0), + (13413, 9, 137, -39, 0), + (13415, 1, 264, 150, 705), + (13415, 2, 264, 150, 1092), + (13415, 3, 264, 150, 10396), + (13415, 4, 264, 150, 10397), + (13416, 1, 264, 20, 626), + (13438, 1, 266, 29, 0), + (13449, 1, 264, 2, 11073), + (13463, 1, 264, 90, 458), + (13474, 1, 264, 120, 444), + (13477, 1, 126, 20, 0), + (13477, 2, 134, 95, 0), + (13477, 3, 135, 4, 0), + (13477, 4, 135, 5, 0), + (13485, 1, 279, 3, 0), + (13502, 1, 375, 160, 0), + (13508, 1, 378, 5, 3), + (13511, 1, 279, 43, 0), + (13520, 1, 292, 70, 0), + (13521, 1, 293, 25, 0), + (13533, 1, 378, 55, 96), + (13545, 1, 323, 30787, 0), + (13562, 1, 264, 480, 872), + (13565, 1, 264, 60, 3804), + (13568, 1, 264, 60, 876), + (13578, 1, 244, 30, 0), + (13589, 1, 279, 34, 0), + (13590, 1, 279, 38, 0), + (13598, 1, 339, 20, 30809), + (13598, 2, 137, 21, 0), + (13598, 3, 385, -18000, 0), + (13598, 4, 339, 20, 30809), + (13598, 5, 137, 343, 0), + (13598, 6, 385, -18000, 0), + (13601, 1, 231, 22, 0), + (13607, 1, 126, 4, 4), + (13607, 2, 137, 21, 0), + (13607, 3, 231, 4, 4), + (13610, 1, 266, 47, 0), + (13613, 1, 220, 260, 10), + (13616, 1, 220, 150, 2), + (13616, 2, 220, 150, 3), + (13616, 3, 220, 150, 77), + (13617, 1, 220, 375, 2), + (13617, 2, 220, 375, 3), + (13617, 3, 220, 375, 77), + (13618, 1, 220, 500, 2), + (13618, 2, 220, 500, 3), + (13618, 3, 220, 500, 77), + (13621, 1, 218, 11, 0), + (13627, 1, 59, -59, 0), + (13628, 1, 59, -64, 0), + (13630, 1, 398, 10000, 0), + (13630, 2, 137, 152, 0), + (13667, 1, 287, 1, 0), + (13667, 2, 385, 8054, 0), + (13675, 1, 218, 24, 0), + (13684, 1, 399, 2, 0), + (13684, 2, 140, 2, 0), + (13684, 3, 348, 10, 0), + (13684, 4, 138, 0, 0), + (13684, 5, 137, -152, 0), + (13684, 6, 137, -39, 0), + (13685, 1, 399, 3, 0), + (13685, 2, 140, 2, 0), + (13685, 3, 348, 10, 0), + (13685, 4, 138, 0, 0), + (13685, 5, 137, -152, 0), + (13685, 6, 137, -39, 0), + (13686, 1, 399, 4, 0), + (13686, 2, 140, 2, 0), + (13686, 3, 348, 10, 0), + (13686, 4, 138, 0, 0), + (13686, 5, 137, -152, 0), + (13686, 6, 137, -39, 0), + (13689, 1, 127, 10, 0), + (13689, 2, 139, 27592, 0), + (13689, 3, 139, 31548, 0), + (13707, 1, 274, 26, 0), + (13710, 1, 280, 65, 0), + (13713, 1, 218, 26, 0), + (13753, 1, 264, 360, 534), + (13758, 1, 264, 360, 602), + (13763, 1, 287, 4, 0), + (13763, 2, 137, 31, 0), + (13763, 3, 136, 5, 0), + (13764, 1, 264, 60, 535), + (13767, 1, 439, 0, 153514), + (13767, 2, 345, 90, 22), + (13773, 1, 279, 21, 0), + (13774, 1, 279, 23, 0), + (13775, 1, 279, 25, 0), + (13779, 1, 288, 100, 8), + (13782, 1, 220, 490, 8), + (13789, 1, 216, 850, 8), + (13790, 1, 216, 950, 8), + (13795, 1, 258, 73, 0), + (13798, 1, 114, -21, 0), + (13804, 1, 378, 4, 3), + (13813, 1, 220, 150, 28), + (13813, 2, 220, 150, 0), + (13813, 3, 427, 23598, 9), + (13813, 4, 428, 28, 0), + (13813, 5, 428, 0, 0), + (13820, 1, 220, 325, 26), + (13820, 2, 220, 325, 30), + (13820, 3, 220, 325, 38), + (13823, 1, 220, 295, 21), + (13823, 2, 220, 295, 23), + (13823, 3, 220, 670, 52), + (13823, 4, 220, 295, 28), + (13826, 1, 405, 25, 0), + (13829, 1, 220, 550, 26), + (13835, 1, 283, 300, 0), + (13841, 1, 264, 17, 469), + (13873, 1, 264, 30, 961), + (13878, 1, 264, 60, 609), + (13881, 1, 264, 60, 387), + (13884, 1, 265, 87, 0), + (13889, 1, 264, 60, 1012), + (13894, 1, 327, 13, 0), + (13905, 1, 310, 24000, 0), + (13905, 2, 385, 15319, 0), + (13908, 1, 310, 3000, 0), + (13908, 2, 385, 15307, 0), + (13908, 3, 385, 15407, 0), + (13908, 4, 385, 15507, 0), + (13908, 5, 385, 15607, 0), + (13911, 1, 310, 3000, 0), + (13911, 2, 385, 16005, 0), + (13911, 3, 310, 3000, 0), + (13911, 4, 385, 15405, 0), + (13911, 5, 385, 15505, 0), + (13911, 6, 385, 15605, 0), + (13911, 7, 411, 2, 0), + (13917, 1, 264, 120, 606), + (13921, 1, 114, -66, 0), + (13924, 1, 114, -64, 0), + (13927, 1, 114, -25, 0), + (13930, 1, 341, 310, 0), + (13933, 1, 262, 80, 0), + (13943, 1, 262, 80, 1), + (13953, 1, 262, 80, 2), + (13963, 1, 262, 80, 3), + (13973, 1, 262, 80, 4), + (13983, 1, 262, 80, 5), + (13993, 1, 262, 80, 6), + (14011, 1, 264, 30, 10394), + (14017, 1, 69, 10, 0), + (14018, 1, 69, 10, 0), + (14026, 1, 185, 3, 2), + (14026, 2, 185, 3, 3), + (14026, 3, 185, 3, 77), + (14026, 4, 220, 50, 2), + (14026, 5, 220, 50, 3), + (14026, 6, 220, 50, 77), + (14029, 1, 395, 5, 5), + (14029, 2, 385, 9758, 0), + (14029, 3, 385, 9858, 0), + (14029, 4, 385, 9958, 0), + (14032, 1, 181, 100, 0), + (14037, 1, 264, 180, 804), + (14040, 1, 264, 180, 300), + (14043, 1, 85, 32197, 0), + (14046, 1, 264, 90, 87), + (14056, 1, 310, 360000, 0), + (14056, 2, 139, 4504, 0), + (14059, 1, 310, -180000, 0), + (14059, 2, 139, 4520, 0), + (14062, 1, 264, 60, 821), + (14065, 1, 264, 60, 3215), + (14068, 1, 264, 60, 3216), + (14076, 1, 310, 480000, 0), + (14076, 2, 139, 4518, 0), + (14082, 1, 360, 26, 32314), + (14085, 1, 264, 2, 741), + (14088, 1, 264, 30, 769), + (14091, 1, 264, 120, 701), + (14094, 1, 124, 325, 350), + (14094, 2, 385, 19, 0), + (14094, 3, 144, 0, 0), + (14094, 4, 403, 3, 0), + (14094, 5, 404, 48, 0), + (14094, 6, 385, -21768, 0), + (14097, 1, 85, 32317, 5), + (14100, 1, 127, 50, 0), + (14100, 2, 137, 21, 0), + (14100, 3, 143, 1, 0), + (14100, 4, 134, 253, 0), + (14100, 5, 348, 1, 0), + (14101, 1, 310, 2520000, 0), + (14101, 2, 139, 4506, 0), + (14101, 3, 310, 2520000, 0), + (14101, 4, 385, 11122, 0), + (14101, 5, 385, 11222, 0), + (14101, 6, 385, 11322, 0), + (14101, 7, 385, 11522, 0), + (14115, 1, 287, 1, 0), + (14115, 2, 385, 16130, 0), + (14129, 1, 220, 60, 36), + (14129, 2, 427, 32327, 3), + (14129, 3, 428, 36, 0), + (14130, 1, 220, 90, 36), + (14130, 2, 427, 32327, 5), + (14130, 3, 428, 36, 0), + (14132, 1, 264, 240, 2234), + (14135, 1, 310, 132000, 0), + (14135, 2, 385, 13005, 0), + (14135, 3, 385, 12423, 0), + (14135, 4, 385, 12504, 0), + (14135, 5, 310, 132000, 0), + (14135, 6, 139, 4676, 0), + (14135, 7, 411, 512, 0), + (14138, 1, 310, 480000, 0), + (14138, 2, 139, 4695, 0), + (14138, 3, 411, 512, 0), + (14140, 1, 310, 24000, 0), + (14140, 2, 385, 13007, 0), + (14140, 3, 385, 12105, 0), + (14140, 4, 385, 12205, 0), + (14140, 5, 310, 72000, 0), + (14140, 6, 385, 12305, 0), + (14140, 7, 385, 12405, 0), + (14140, 8, 385, 12505, 0), + (14140, 9, 411, 512, 0), + (14141, 1, 185, 2, 36), + (14144, 1, 287, 1, 0), + (14144, 2, 385, 13204, 0), + (14144, 3, 411, 512, 0), + (14148, 1, 310, 90000, 0), + (14148, 2, 139, 4691, 0), + (14151, 1, 185, 2, 26), + (14151, 2, 220, 100, 26), + (14154, 1, 264, 2100, 276), + (14157, 1, 216, 150, 26), + (14160, 1, 264, 60, 7001), + (14163, 1, 287, 1, 0), + (14163, 2, 385, 16178, 0), + (14163, 3, 411, 128, 0), + (14166, 1, 264, 60, 945), + (14169, 1, 310, 202500, 0), + (14169, 2, 139, 8030, 0), + (14169, 3, 411, 256, 0), + (14173, 1, 310, 1440000, 0), + (14173, 2, 139, 4516, 0), + (14173, 3, 411, 256, 0), + (14176, 1, 264, 660, 8261), + (14179, 1, 287, 1, 0), + (14179, 2, 385, 5830, 0), + (14179, 3, 411, 256, 0), + (14180, 1, 287, 1, 0), + (14180, 2, 139, 8030, 0), + (14180, 3, 411, 256, 0), + (14181, 1, 247, 25, 20), + (14186, 1, 247, 25, 76), + (14196, 1, 264, 2340, 465), + (14199, 1, 264, 720, 499), + (14200, 1, 288, 15, 2), + (14200, 2, 288, 15, 3), + (14200, 3, 288, 15, 51), + (14200, 4, 288, 15, 77), + (14203, 1, 310, 150000, 0), + (14203, 2, 385, 3419, 0), + (14203, 3, 385, 14005, 0), + (14203, 4, 385, 3519, 0), + (14203, 5, 411, 65536, 0), + (14210, 1, 310, 40000, 0), + (14210, 2, 139, 1546, 0), + (14210, 3, 310, 40000, 0), + (14210, 4, 385, 4357, 0), + (14210, 5, 385, 4457, 0), + (14210, 6, 385, 4557, 0), + (14210, 7, 385, 4657, 0), + (14210, 8, 411, 4, 0), + (14213, 1, 264, 120, 1065), + (14218, 1, 232, 23, 4544), + (14223, 1, 264, 40, 47), + (14225, 1, 127, 16, 0), + (14225, 2, 385, 3283, 0), + (14225, 3, 411, 1024, 0), + (14238, 1, 264, 12, 1041), + (14241, 1, 264, 180, 386), + (14244, 1, 286, 100, 0), + (14244, 2, 138, 0, 0), + (14244, 3, 143, 1, 0), + (14244, 4, 348, 1, 0), + (14244, 5, 411, 64, 0), + (14249, 1, 392, 200, 0), + (14249, 2, 138, 1, 0), + (14249, 3, 348, 1, 0), + (14254, 1, 287, 1, 0), + (14254, 2, 385, 2025, 0), + (14254, 3, 385, 5121, 0), + (14254, 4, 385, 5221, 0), + (14254, 5, 385, 5562, 0), + (14259, 1, 287, 1, 0), + (14259, 2, 139, 23585, 0), + (14275, 1, 239, 20, 0), + (14278, 1, 287, 4, 0), + (14278, 2, 385, 16439, 0), + (14278, 3, 411, 32768, 0), + (14279, 1, 320, 8, 0), + (14283, 1, 127, 17, 0), + (14283, 2, 385, 3151, 0), + (14283, 3, 385, 5887, 0), + (14286, 1, 287, 1, 0), + (14286, 2, 385, 4877, 0), + (14289, 1, 127, 10, 0), + (14289, 2, 385, 2754, 0), + (14292, 1, 127, 10, 0), + (14292, 2, 385, 3286, 0), + (14295, 1, 264, 1, 3816), + (14301, 1, 405, 5, 0), + (14304, 1, 264, 45, 8341), + (14308, 1, 264, 20, 431), + (14311, 1, 264, 360, 430), + (14314, 1, 264, 8, 901), + (14318, 1, 127, 10, 0), + (14318, 2, 139, 21754, 0), + (14328, 1, 264, 6, 1154), + (14331, 1, 264, 120, 515), + (14341, 1, 264, 360, 748), + (14349, 1, 294, 0, 205), + (14361, 1, 294, 35, 109), + (14364, 1, 264, 90, 173), + (14367, 1, 445, 1, 0), + (14764, 1, 339, 10, 33950), + (14764, 2, 137, 31, 0), + (15074, 1, 264, 5, 15073), + (15100, 1, 264, 2, 467), + (15105, 1, 264, 120, 131), + (15108, 1, 310, 60000, 0), + (15108, 2, 385, 15521, 0), + (15108, 3, 411, 2, 0), + (15111, 1, 287, 1, 0), + (15111, 2, 385, 21778, 0), + (15113, 1, 287, 3, 0), + (15113, 2, 385, 21778, 0), + (15113, 3, 411, 2, 0), + (15120, 1, 264, 60, 800), + (15123, 1, 310, 120000, 0), + (15123, 2, 385, 15422, 0), + (15123, 3, 411, 2, 0), + (15126, 1, 310, 1000, 0), + (15126, 2, 385, 15212, 0), + (15126, 3, 411, 2, 0), + (15132, 1, 264, 10, 660), + (15135, 1, 287, 1, 0), + (15135, 2, 139, 32313, 0), + (15141, 1, 219, 420, 2400), + (15150, 1, 127, 10, 0), + (15150, 2, 385, 10505, 0), + (15150, 3, 385, 10105, 0), + (15150, 4, 385, 10205, 0), + (15150, 5, 385, 10305, 0), + (15150, 6, 385, 10405, 0), + (15150, 7, 385, 10605, 0), + (15153, 1, 287, 1, 0), + (15153, 2, 139, 4518, 0), + (15154, 1, 287, 1, 0), + (15154, 2, 139, 32312, 0), + (15155, 1, 287, 1, 0), + (15155, 2, 385, 10320, 0), + (15155, 3, 385, 10420, 0), + (15155, 4, 385, 10520, 0), + (15158, 1, 287, 1, 0), + (15158, 2, 385, 32307, 0), + (15159, 1, 287, 1, 0), + (15159, 2, 385, 27537, 0), + (15162, 1, 264, 120, 659), + (15168, 1, 264, 60, 657), + (15172, 1, 302, 430, 430), + (15172, 2, 385, 99, 0), + (15174, 1, 264, 40, 9400), + (15179, 1, 127, 10, 0), + (15179, 2, 139, 21804, 0), + (15179, 3, 139, 38280, 0), + (15182, 1, 264, 840, 9403), + (15188, 1, 239, 62, 0), + (15194, 1, 287, 1, 0), + (15194, 2, 385, 13407, 0), + (15194, 3, 385, 13507, 0), + (15204, 1, 264, 60, 390), + (15207, 1, 264, 60, 323), + (15217, 1, 339, 10, 38319), + (15217, 2, 385, 11006, 0), + (15217, 3, 385, 7108, 0), + (15217, 4, 385, 7208, 0), + (15217, 5, 385, 7308, 0), + (15217, 6, 385, 7408, 0), + (15217, 7, 385, 7508, 0), + (15217, 8, 385, 7608, 0), + (15220, 1, 287, 1, 0), + (15220, 2, 385, 11065, 0), + (15223, 1, 287, 1, 0), + (15223, 2, 385, 11067, 0), + (15226, 1, 287, 1, 0), + (15226, 2, 385, 11064, 0), + (15229, 1, 287, 1, 0), + (15229, 2, 385, 11066, 0), + (15232, 1, 339, 100, 38322), + (15232, 2, 385, 7518, 0), + (15238, 1, 264, 240, 621), + (15238, 2, 264, 240, 622), + (15238, 3, 264, 240, 623), + (15238, 4, 264, 240, 784), + (15238, 5, 264, 240, 785), + (15238, 6, 264, 240, 786), + (15238, 7, 264, 240, 787), + (15238, 8, 264, 240, 624), + (15253, 1, 127, 10, 0), + (15253, 2, 385, 32322, 0), + (15258, 1, 264, 540, 184), + (15270, 1, 264, 1980, 7003), + (15280, 1, 264, 720, 778), + (15283, 1, 310, 1000, 0), + (15283, 2, 385, 11402, 0), + (15283, 3, 385, 11502, 0), + (15283, 4, 385, 11441, 0), + (15283, 5, 385, 11541, 0), + (15283, 6, 385, 11641, 0), + (15288, 1, 220, 50, 0), + (15288, 2, 220, 50, 1), + (15288, 3, 220, 100, 2), + (15288, 4, 220, 100, 3), + (15288, 5, 220, 50, 36), + (15288, 6, 220, 100, 77), + (15295, 1, 127, 10, 0), + (15295, 2, 385, 21654, 0), + (15314, 1, 264, 25920, 36), + (15317, 1, 264, 1728, 35), + (15320, 1, 264, 150, 558), + (15328, 1, 339, 25, 38037), + (15328, 2, 138, 1, 0), + (15328, 3, 142, 65, 0), + (15328, 4, 137, 35, 0), + (15328, 5, 134, 90, 0), + (15328, 6, 339, 25, 38037), + (15328, 7, 138, 1, 0), + (15328, 8, 142, 65, 0), + (15328, 9, 137, 36, 0), + (15328, 10, 134, 90, 0), + (15328, 11, 339, 25, 38037), + (15328, 12, 138, 1, 0), + (15328, 13, 142, 65, 0), + (15328, 14, 137, 369, 0), + (15328, 15, 134, 90, 0), + (15328, 16, 339, 25, 38037), + (15328, 17, 138, 1, 0), + (15328, 18, 142, 65, 0), + (15328, 19, 137, 116, 0), + (15328, 20, 134, 90, 0), + (15342, 1, 287, 1, 0), + (15342, 2, 385, 23605, 0), + (15344, 1, 264, 360, 38), + (15348, 1, 264, 240, 9504), + (15356, 1, 232, 20, 4544), + (15358, 1, 287, 1, 0), + (15358, 2, 385, 32350, 0), + (15359, 1, 264, 960, 50), + (15363, 1, 264, 240, 447), + (15371, 1, 264, 1, 3729), + (15374, 1, 195, 20, 0), + (15383, 1, 310, 1000, 0), + (15383, 2, 385, 5132, 0), + (15383, 3, 385, 5232, 0), + (15383, 4, 385, 5332, 0), + (15383, 5, 385, 5432, 0), + (15383, 6, 385, 5532, 0), + (15383, 7, 385, 5032, 0), + (15383, 8, 385, 5632, 0), + (15389, 1, 127, 16, 0), + (15389, 2, 385, 23575, 0), + (15396, 1, 127, 20, 20), + (15396, 2, 137, 0, 0), + (15396, 3, 138, 0, 0), + (15396, 4, 141, 1, 0), + (15396, 5, 143, 3000, 0), + (15396, 6, 127, 20, 20), + (15396, 7, 385, 16555, 0), + (15396, 8, 385, 16655, 0), + (15397, 1, 264, 1260, 494), + (15403, 1, 264, 10, 8604), + (15406, 1, 127, 10, 10), + (15406, 2, 385, 37097, 0), + (15414, 1, 287, 1, 0), + (15414, 2, 139, 30736, 0), + (15421, 1, 264, 3600, 245), + (15422, 1, 132, 15, 15), + (15426, 1, 239, 62, 0), + (15429, 1, 220, 135, 2), + (15432, 1, 184, 5, -1), + (15438, 1, 310, 180000, 0), + (15438, 2, 385, 8316, 0), + (15438, 3, 411, 128, 0), + (15441, 1, 279, 38, 0), + (15444, 1, 288, 60, 26), + (15450, 1, 310, 3000, 0), + (15450, 2, 385, 8202, 0), + (15450, 3, 385, 8302, 0), + (15450, 4, 385, 8402, 0), + (15450, 5, 385, 8502, 0), + (15450, 6, 385, 8602, 0), + (15450, 7, 411, 128, 0), + (15453, 1, 310, 60000, 0), + (15453, 2, 385, 8421, 0), + (15453, 3, 411, 128, 0), + (15456, 1, 264, 5, 470), + (15466, 1, 126, 20, 20), + (15466, 2, 139, 12576, 0), + (15466, 3, 126, 20, 20), + (15466, 4, 139, 12828, 0), + (15469, 1, 264, 240, 1120), + (15472, 1, 264, 1260, 521), + (15478, 1, 264, 120, 578), + (15485, 1, 339, 10, 38417), + (15485, 2, 142, 96, 0), + (15485, 3, 311, 0, 0), + (15485, 4, 134, 105, 0), + (15485, 5, 348, 10, 0), + (15485, 6, 137, 0, 0), + (15485, 7, 339, 10, 38417), + (15485, 8, 142, 96, 0), + (15485, 9, 311, 0, 0), + (15485, 10, 134, 105, 0), + (15485, 11, 348, 10, 0), + (15485, 12, 137, 100, 0), + (15485, 13, 339, 10, 38417), + (15485, 14, 142, 96, 0), + (15485, 15, 311, 0, 0), + (15485, 16, 134, 105, 0), + (15485, 17, 348, 10, 0), + (15485, 18, 137, 79, 0), + (15485, 19, 339, 10, 38417), + (15485, 20, 142, 96, 0), + (15485, 21, 311, 0, 0), + (15485, 22, 134, 105, 0), + (15485, 23, 348, 10, 0), + (15485, 24, 137, 147, 0), + (15493, 1, 127, 10, 0), + (15493, 2, 137, 31, 0), + (15502, 1, 310, 240000, 0), + (15502, 2, 139, 4673, 0), + (15502, 3, 411, 512, 0), + (15509, 1, 310, 3000, 0), + (15509, 2, 385, 12315, 0), + (15509, 3, 385, 12415, 0), + (15509, 4, 385, 12515, 0), + (15509, 5, 385, 12615, 0), + (15509, 10, 411, 512, 0), + (15512, 1, 288, 50, 8), + (15516, 1, 126, 20, 0), + (15516, 2, 139, 3066, 0), + (15516, 3, 411, 256, 0), + (15517, 1, 127, 16, 0), + (15517, 2, 139, 3066, 0), + (15517, 3, 411, 256, 0), + (15526, 1, 264, 120, 3702), + (15529, 1, 247, 60, 53), + (15540, 1, 185, 5, 1), + (15543, 1, 185, 5, 0), + (15546, 1, 185, 5, 36), + (15549, 1, 264, 15, 244), + (15552, 1, 264, 840, 3710), + (15555, 1, 339, 5, 38103), + (15555, 2, 385, 3208, 0), + (15555, 3, 385, 3308, 0), + (15555, 4, 385, 3408, 0), + (15555, 5, 385, 3508, 0), + (15564, 1, 220, 68, 51), + (15571, 1, 264, 180, 351), + (15579, 1, 287, 2, 0), + (15579, 2, 139, 16106, 0), + (15585, 1, 274, 44, 0), + (15591, 1, 127, 10, 0), + (15591, 2, 139, 16839, 0), + (15598, 1, 264, 180, 759), + (15598, 2, 264, 180, 1150), + (15598, 3, 264, 180, 1151), + (15598, 4, 264, 180, 1152), + (15602, 1, 124, 1, 0), + (15602, 2, 138, 0, 0), + (15602, 3, 141, 1, 0), + (15602, 4, 348, 10, 0), + (15606, 1, 244, -25, 0), + (15609, 1, 383, 10, 38134), + (15609, 2, 141, 1, 0), + (15609, 3, 348, 10, 0), + (15609, 4, 142, 85, 0), + (15609, 5, 143, 3000, 0), + (15622, 1, 127, 5, 5), + (15622, 2, 137, 0, 0), + (15622, 3, 138, 0, 0), + (15622, 4, 141, 1, 0), + (15625, 1, 330, 10, 8), + (15632, 1, 264, 1728, 789), + (15634, 1, 310, 1500, 0), + (15634, 2, 385, 12110, 0), + (15634, 3, 385, 12210, 0), + (15634, 4, 385, 12310, 0), + (15634, 5, 385, 12410, 0), + (15634, 6, 385, 12510, 0), + (15635, 1, 310, 3000, 0), + (15635, 2, 385, 12110, 0), + (15635, 3, 385, 12210, 0), + (15635, 4, 385, 12310, 0), + (15635, 5, 385, 12410, 0), + (15635, 6, 385, 12510, 0), + (15648, 1, 185, 3, 74), + (15694, 1, 190, 550, 0), + (15714, 1, 320, 12, 0), + (15719, 1, 320, 12, 0), + (15746, 1, 421, 20, 0), + (15746, 2, 139, 16097, 0), + (15746, 3, 139, 23612, 0), + (15746, 4, 139, 32196, 0), + (15746, 5, 139, 32565, 0), + (15746, 6, 423, 6, 0), + (15746, 7, 422, 5, 0), + (15746, 8, 411, 2, 0), + (15768, 1, 125, 1, 2), + (15768, 2, 136, 46, 0), + (15772, 1, 128, 80, 80), + (15772, 2, 138, 1, 0), + (15772, 3, 140, 1, 0), + (15772, 4, 311, 0, 0), + (15772, 5, 411, 66434, 0), + (15772, 6, 137, -40, 0), + (15773, 1, 128, 80, 80), + (15773, 2, 138, 1, 0), + (15773, 3, 140, 1, 0), + (15773, 4, 311, 0, 0), + (15773, 5, 411, 256, 0), + (15773, 6, 137, -40, 0), + (15773, 7, 391, 1, 0), + (15778, 1, 303, 27500, 32500), + (15778, 2, 139, 2766, 0), + (15833, 1, 264, 60, 2045), + (15836, 1, 264, 60, 463), + (15891, 1, 264, 20, 988), + (15893, 1, 264, 20, 987), + (15895, 1, 264, 20, 986), + (15908, 1, 220, 125, 0), + (15908, 2, 220, 200, 2), + (15909, 1, 220, 155, 0), + (15909, 2, 220, 290, 2), + (15910, 1, 220, 185, 0), + (15910, 2, 220, 385, 2), + (15954, 1, 292, 49, 0), + (15961, 1, 129, 20, 0), + (15961, 2, 385, 12768, 0), + (15961, 3, 411, 256, 0), + (16062, 1, 339, 20, 40941), + (16062, 2, 138, 0, 0), + (16062, 3, 137, 31, 0), + (16062, 4, 311, 0, 0), + (16084, 1, 158, 1, 0), + (16087, 1, 264, 432, 53), + (16094, 1, 264, 3024, 43), + (16104, 1, 10, 0, 0), + (16109, 1, 69, 3000, 0), + (16114, 1, 114, 2, 0), + (16117, 1, 171, 2, 0), + (16120, 1, 226, 1, 0), + (16121, 1, 310, 840000, 0), + (16121, 2, 139, 4670, 0), + (16124, 1, 264, 2, 3711), + (16128, 1, 127, 8, 0), + (16128, 2, 139, 13143, 0), + (16131, 1, 130, 10, 0), + (16131, 2, 385, 18000, 0), + (16137, 1, 287, 1, 0), + (16137, 2, 385, 21821, 0), + (16140, 1, 287, 1, 0), + (16140, 2, 385, 30666, 0), + (16146, 1, 339, 2, 41107), + (16146, 2, 142, 95, 0), + (16146, 3, 138, 1, 0), + (16146, 4, 137, 0, 0), + (16146, 5, 348, 10, 0), + (16146, 6, 141, 1, 0), + (16149, 1, 129, 20, 0), + (16149, 2, 385, 4357, 0), + (16149, 3, 385, 4457, 0), + (16149, 4, 385, 4557, 0), + (16149, 5, 411, 4, 0), + (16152, 1, 339, 3, 41108), + (16152, 2, 142, 90, 0), + (16152, 3, 138, 0, 0), + (16152, 4, 137, 0, 0), + (16152, 5, 348, 10, 0), + (16152, 6, 141, 1, 0), + (16156, 1, 392, 1000, 0), + (16156, 2, 385, 32341, 0), + (16159, 1, 287, 1, 0), + (16159, 2, 385, 32307, 0), + (16164, 1, 294, 0, 195), + (16170, 1, 360, 70, 41119), + (16173, 1, 320, 12, 0), + (16176, 1, 264, 2, 337), + (16179, 1, 288, 8, 7), + (16180, 1, 264, 5, 584), + (16186, 1, 288, 100, 30), + (16189, 1, 339, 12, 41127), + (16189, 2, 138, 0, 0), + (16189, 3, 142, 70, 0), + (16189, 4, 411, 32, 0), + (16189, 5, 348, 1, 0), + (16189, 6, 141, 1, 0), + (16192, 1, 339, 12, 41130), + (16192, 2, 138, 0, 0), + (16192, 3, 142, 70, 0), + (16192, 4, 403, 4, 0), + (16192, 5, 348, 1, 0), + (16192, 6, 404, 2, 0), + (16192, 7, 141, 1, 0), + (16208, 1, 247, 5, 27), + (16211, 1, 287, 1, 0), + (16211, 2, 139, 23581, 0), + (16211, 3, 139, 32359, 0), + (16218, 1, 264, 10, 403), + (16221, 1, 287, 1, 0), + (16221, 2, 385, 23586, 0), + (16225, 1, 264, 1, 219), + (16230, 1, 310, 1000, 0), + (16230, 2, 385, 2431, 0), + (16230, 3, 385, 2531, 0), + (16230, 4, 385, 2545, 0), + (16230, 5, 385, 2631, 0), + (16235, 1, 126, 35, 0), + (16235, 2, 134, 100, 0), + (16235, 3, 135, 3, 0), + (16238, 1, 287, 2, 0), + (16238, 2, 385, 23693, 0), + (16238, 3, 460, 1, 0), + (16249, 1, 275, 100, 0), + (16257, 1, 429, 37114, 2), + (16257, 2, 428, 52, 0), + (16260, 1, 427, 41160, 3), + (16260, 2, 428, 23, 0), + (16266, 1, 224, 50, 8), + (16266, 2, 173, 4, 0), + (16267, 1, 250, 52, 0), + (16272, 1, 175, 2, 0), + (16276, 1, 247, 10, 36), + (16287, 1, 264, 20, 669), + (16297, 1, 264, 600, 553), + (16300, 1, 264, 60, 668), + (16303, 1, 264, 240, 3506), + (16306, 1, 264, 1260, 777), + (16317, 1, 220, 100, -1), + (16327, 1, 310, 720000, 0), + (16327, 2, 139, 5040, 0), + (16330, 1, 330, 105, 74), + (16336, 1, 264, 30, 1257), + (16339, 1, 264, 10, 773), + (16342, 1, 127, 10, 0), + (16342, 2, 385, 38115, 0), + (16361, 1, 399, 5, 0), + (16361, 2, 141, 1, 0), + (16361, 3, 138, 0, 0), + (16361, 4, 134, 254, 0), + (16361, 5, 348, 10, 0), + (16361, 6, 137, 0, 0), + (16361, 7, 311, 0, 0), + (16361, 8, 137, -152, 0), + (16361, 9, 137, -39, 0), + (16366, 1, 286, 200, 0), + (16366, 2, 138, 0, 0), + (16366, 3, 143, 1, 0), + (16366, 4, 348, 10, 0), + (16371, 1, 129, 20, 0), + (16371, 2, 385, 2754, 0), + (16380, 1, 264, 30, 2061), + (16386, 1, 264, 10, 2064), + (16392, 1, 264, 90, 2202), + (16396, 1, 127, 5, 5), + (16396, 2, 137, 0, 0), + (16396, 3, 138, 0, 0), + (16396, 4, 141, 1, 0), + (16402, 1, 131, 60, 60), + (16402, 2, 348, 10, 0), + (16402, 3, 137, -32, 0), + (16414, 1, 317, 16, 0), + (16419, 1, 426, 6, 0), + (16420, 1, 426, 7, 0), + (16421, 1, 426, 8, 0), + (16440, 1, 247, 65, 76), + (16475, 1, 218, 4, 0), + (16489, 1, 294, 29, 102), + (16536, 1, 405, 3, 0), + (16604, 1, 264, 1440, 180), + (16644, 1, 264, 60, 747), + (16666, 1, 264, 60, 742), + (16730, 1, 347, 31, 0), + (16745, 1, 264, 60, 706), + (16887, 1, 280, 75, 0), + (16890, 1, 218, 21, 0), + (17004, 1, 225, 35, 0), + (17206, 1, 264, 12, 601), + (17209, 1, 264, 180, 111), + (17212, 1, 264, 60, 10367), + (17215, 1, 378, 2, 22), + (17215, 2, 378, 2, 31), + (17215, 3, 378, 2, 3), + (17215, 4, 378, 2, 20), + (17218, 1, 127, 10, 0), + (17218, 2, 139, 27560, 0), + (17229, 1, 220, 900, 3), + (17229, 2, 220, 900, 2), + (17229, 3, 220, 900, 77), + (17235, 1, 127, 15, 0), + (17235, 2, 385, 12609, 0), + (17239, 1, 310, 2400000, 0), + (17239, 2, 139, 4500, 0), + (17239, 3, 411, 8, 0), + (17242, 1, 378, 1, 22), + (17242, 2, 378, 1, 31), + (17242, 3, 378, 1, 3), + (17242, 4, 378, 1, 20), + (17245, 1, 378, 1, 22), + (17245, 2, 378, 1, 31), + (17245, 3, 378, 1, 3), + (17245, 4, 378, 1, 20), + (17249, 1, 264, 120, 651), + (17252, 1, 310, 3000, 0), + (17252, 2, 385, 13438, 0), + (17252, 3, 385, 13538, 0), + (17252, 4, 385, 13638, 0), + (17258, 1, 399, 2, 0), + (17258, 2, 137, 457, 0), + (17258, 3, 399, 2, 0), + (17258, 4, 134, 253, 0), + (17258, 5, 142, 100, 0), + (17258, 6, 138, 0, 0), + (17258, 7, 136, 13, 0), + (17258, 8, 136, 20, 0), + (17258, 9, 137, -39, 0), + (17267, 1, 127, 10, 0), + (17267, 2, 385, 13507, 0), + (17267, 3, 385, 13107, 0), + (17267, 4, 385, 13207, 0), + (17267, 5, 385, 13307, 0), + (17267, 6, 385, 13407, 0), + (17267, 7, 385, 13607, 0), + (17281, 1, 287, 1, 0), + (17281, 2, 385, 16646, 0), + (17288, 1, 264, 1440, 41), + (17289, 1, 264, 180, 1062), + (17295, 1, 229, 62, 0), + (17307, 1, 127, 8, 0), + (17307, 2, 139, 38058, 0), + (17310, 1, 310, 14000, 0), + (17310, 2, 139, 8007, 0), + (17310, 3, 310, 14000, 0), + (17310, 4, 385, 4140, 0), + (17310, 5, 385, 4240, 0), + (17310, 6, 385, 4340, 0), + (17310, 7, 385, 4440, 0), + (17310, 8, 385, 4540, 0), + (17310, 9, 385, 4640, 0), + (17317, 1, 264, 60, 1270), + (17334, 1, 287, 12, 0), + (17334, 2, 385, 16188, 0), + (17336, 1, 287, 1, 0), + (17336, 2, 385, 32348, 0), + (17339, 1, 264, 12, 760), + (17350, 1, 264, 110, 170), + (17357, 1, 287, 1, 0), + (17357, 2, 137, 100, 0), + (17357, 3, 138, 1, 0), + (17361, 1, 264, 60, 405), + (17361, 2, 264, 60, 426), + (17365, 1, 287, 6, 0), + (17365, 2, 385, 5240, 0), + (17365, 3, 385, 5340, 0), + (17365, 4, 385, 5440, 0), + (17365, 5, 385, 5540, 0), + (17365, 6, 385, 5640, 0), + (17370, 1, 287, 1, 0), + (17370, 2, 138, 0, 0), + (17370, 3, 137, 0, 0), + (17370, 4, 137, 100, 0), + (17370, 5, 140, 1, 0), + (17370, 6, 348, 10, 0), + (17375, 1, 127, 10, 0), + (17375, 2, 385, 38078, 0), + (17391, 1, 264, 1560, 98), + (17406, 1, 310, 480000, 0), + (17406, 2, 139, 4502, 0), + (17406, 3, 139, 4509, 0), + (17409, 1, 214, 205, 0), + (17409, 2, 259, 4, 0), + (17409, 3, 172, 4, 0), + (17414, 1, 264, 120, 673), + (17418, 1, 247, 10, 74), + (17428, 1, 288, 5, 51), + (17436, 1, 264, 60, 372), + (17439, 1, 287, 1, 0), + (17439, 2, 385, 6040, 0), + (17441, 1, 279, 37, 0), + (17445, 1, 310, 60000, 0), + (17445, 2, 385, 3312, 0), + (17448, 1, 287, 1, 0), + (17448, 2, 385, 14005, 0), + (17448, 3, 385, 3519, 0), + (17476, 1, 264, 240, 462), + (17492, 1, 264, 120, 840), + (17495, 1, 264, 20, 9702), + (17515, 1, 127, 25, 0), + (17515, 2, 385, 7125, 0), + (17517, 1, 127, 17, 0), + (17517, 2, 385, 23683, 0), + (17517, 3, 460, 1, 0), + (17522, 1, 264, 30, 764), + (17533, 1, 287, 1, 0), + (17533, 2, 139, 32399, 0), + (17533, 3, 460, 1, 0), + (17547, 1, 287, 1, 0), + (17547, 2, 137, 0, 0), + (17547, 3, 137, 100, 0), + (17547, 4, 140, 2, 0), + (17547, 5, 138, 0, 0), + (17547, 6, 348, 10, 0), + (17549, 1, 264, 10, 8700), + (17553, 1, 339, 8, 41768), + (17553, 2, 138, 0, 0), + (17553, 3, 141, 1, 0), + (17553, 4, 134, 253, 0), + (17553, 5, 142, 85, 0), + (17553, 6, 143, 1, 0), + (17553, 7, 311, 0, 0), + (17553, 8, 348, 1, 0), + (17553, 9, 137, 0, 0), + (17554, 1, 227, 2, 74), + (17555, 1, 286, 126, 2), + (17555, 2, 385, 9606, 0), + (17555, 3, 303, 252, 0), + (17555, 4, 385, 9606, 0), + (17558, 1, 413, 2, 2), + (17558, 2, 385, 9603, 0), + (17558, 3, 411, 2048, 0), + (17561, 1, 413, 2, 2), + (17561, 2, 385, 9609, 0), + (17561, 3, 411, 2048, 0), + (17564, 1, 413, 2, 2), + (17564, 2, 385, 9619, 0), + (17564, 3, 411, 2048, 0), + (17567, 1, 413, 2, 2), + (17567, 2, 385, 9613, 0), + (17567, 3, 411, 2048, 0), + (17570, 1, 413, 2, 2), + (17570, 2, 385, 9604, 0), + (17570, 3, 411, 2048, 0), + (17573, 1, 413, 2, 2), + (17573, 2, 385, 9651, 0), + (17573, 3, 411, 2048, 0), + (17576, 1, 413, 2, 2), + (17576, 2, 385, 16652, 0), + (17576, 3, 411, 4096, 0), + (17579, 1, 413, 2, 2), + (17579, 2, 385, 16629, 0), + (17579, 3, 411, 4096, 0), + (17582, 1, 413, 2, 2), + (17582, 2, 385, 16650, 0), + (17582, 3, 411, 4096, 0), + (17585, 1, 413, 2, 2), + (17585, 2, 385, 16608, 0), + (17585, 3, 411, 4096, 0), + (17588, 1, 413, 2, 2), + (17588, 2, 385, 16615, 0), + (17588, 3, 411, 4096, 0), + (17591, 1, 413, 2, 2), + (17591, 2, 385, 16618, 0), + (17591, 3, 411, 4096, 0), + (17594, 1, 413, 2, 2), + (17594, 2, 385, 16625, 0), + (17594, 3, 411, 4096, 0), + (17597, 1, 286, 345, 0), + (17597, 2, 385, 7604, 0), + (17600, 1, 413, 2, 2), + (17600, 2, 385, 7608, 0), + (17600, 3, 411, 8192, 0), + (17603, 1, 413, 2, 2), + (17603, 2, 385, 7612, 0), + (17603, 3, 411, 8192, 0), + (17606, 1, 392, 419, 0), + (17606, 2, 385, 7613, 0), + (17606, 3, 396, 838, 0), + (17606, 4, 385, 7613, 0), + (17609, 1, 413, 2, 2), + (17609, 2, 385, 7636, 0), + (17609, 3, 411, 8192, 0), + (17612, 1, 413, 2, 2), + (17612, 2, 385, 7618, 0), + (17612, 3, 411, 8192, 0), + (17615, 1, 286, 539, 0), + (17615, 2, 385, 7638, 0), + (17618, 1, 413, 2, 2), + (17618, 2, 385, 6664, 0), + (17618, 3, 411, 16384, 0), + (17621, 1, 413, 2, 2), + (17621, 2, 385, 6648, 0), + (17621, 3, 411, 16384, 0), + (17624, 1, 413, 2, 2), + (17624, 2, 385, 6649, 0), + (17624, 3, 411, 16384, 0), + (17627, 1, 413, 2, 2), + (17627, 2, 385, 6611, 0), + (17627, 3, 411, 16384, 0), + (17630, 1, 413, 2, 2), + (17630, 2, 385, 6652, 0), + (17630, 3, 411, 16384, 0), + (17633, 1, 413, 2, 2), + (17633, 2, 385, 6655, 0), + (17633, 3, 411, 16384, 0), + (17639, 1, 323, 37182, 100), + (18972, 1, 214, 210, 0), + (18972, 2, 259, 5, 0), + (18972, 3, 172, 5, 0), + (30050, 1, 69, 25, 0), + (30050, 2, 97, 25, 0), + (30050, 3, 190, 25, 0), + (30050, 4, 328, 25, 0), + (30100, 1, 1, 10, 0), + (30100, 2, 2, 10, 0), + (30100, 3, 341, 10, 0), + (30150, 1, 262, 5, 0), + (30150, 2, 262, 5, 1), + (30150, 3, 262, 5, 2), + (30150, 4, 262, 5, 3), + (30150, 5, 262, 5, 4), + (30150, 6, 262, 5, 5), + (30150, 7, 262, 5, 6), + (30150, 8, 159, 5, 0), + (30150, 9, 0, 2, 0), + (30150, 10, 15, 2, 0), + (30150, 11, 189, 2, 0), + (30150, 12, 317, 2, 0), + (30150, 13, 318, 2, 0), + (30175, 1, 271, 1, 0), + (30180, 1, 264, 1, 8202), + (30185, 1, 264, 1, 1011), + (30195, 1, 432, 1, 0), + (49999, 1, 10, 0, 0); + +DROP TABLE IF EXISTS `aa_rank_prereqs`; +CREATE TABLE IF NOT EXISTS `aa_rank_prereqs` ( + `rank_id` int(10) unsigned NOT NULL, + `aa_id` int(10) NOT NULL, + `points` int(10) NOT NULL, + PRIMARY KEY (`rank_id`,`aa_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `aa_rank_prereqs` (`rank_id`, `aa_id`, `points`) VALUES + (129, 19, 3), + (131, 19, 3), + (136, 19, 3), + (141, 23, 3), + (142, 23, 3), + (143, 23, 3), + (146, 224, 3), + (162, 224, 3), + (190, 30, 3), + (191, 30, 3), + (192, 30, 3), + (195, 31, 3), + (230, 17, 3), + (231, 17, 3), + (232, 17, 3), + (255, 309, 3), + (256, 309, 3), + (257, 309, 3), + (260, 31, 3), + (261, 31, 3), + (262, 31, 3), + (263, 17, 3), + (264, 17, 3), + (265, 17, 3), + (267, 23, 3), + (268, 23, 3), + (269, 23, 3), + (446, 26, 3), + (447, 26, 3), + (448, 26, 3), + (462, 39, 1), + (463, 39, 1), + (464, 39, 1), + (468, 41, 1), + (469, 41, 1), + (470, 41, 1), + (471, 57, 1), + (472, 57, 1), + (473, 57, 1), + (474, 50, 1), + (475, 50, 1), + (476, 50, 1), + (477, 43, 1), + (478, 43, 1), + (479, 43, 1), + (480, 117, 1), + (481, 117, 1), + (482, 117, 1), + (483, 58, 1), + (484, 58, 1), + (485, 58, 1), + (489, 110, 1), + (490, 110, 1), + (491, 110, 1), + (492, 109, 1), + (493, 109, 1), + (494, 109, 1), + (495, 98, 1), + (496, 98, 1), + (497, 98, 1), + (498, 102, 1), + (499, 102, 1), + (500, 102, 1), + (501, 107, 1), + (502, 107, 1), + (503, 107, 1), + (531, 19, 3), + (532, 19, 3), + (534, 6001, 11), + (535, 6001, 11), + (536, 6001, 11), + (537, 112, 3), + (538, 112, 3), + (539, 17, 3), + (540, 17, 3), + (541, 17, 3), + (542, 309, 3), + (543, 309, 3), + (544, 309, 3), + (567, 45, 1), + (574, 125, 1), + (575, 125, 1), + (576, 125, 1), + (583, 73, 1), + (584, 73, 1), + (585, 73, 1), + (586, 120, 1), + (587, 120, 1), + (588, 120, 1), + (589, 87, 1), + (590, 87, 1), + (591, 87, 1), + (592, 30, 1), + (593, 6001, 11), + (594, 6001, 11), + (595, 6001, 11), + (596, 6000, 11), + (597, 6000, 11), + (598, 6000, 11), + (637, 23, 3), + (638, 23, 3), + (639, 23, 3), + (640, 23, 3), + (641, 23, 3), + (642, 23, 3), + (643, 55, 1), + (644, 82, 1), + (702, 30, 1), + (703, 30, 1), + (704, 30, 1), + (705, 30, 1), + (706, 30, 1), + (715, 6001, 11), + (716, 6001, 11), + (717, 6001, 11), + (754, 153, 3), + (755, 153, 3), + (756, 153, 3), + (770, 23, 3), + (771, 23, 3), + (772, 23, 3), + (773, 217, 1), + (774, 217, 1), + (775, 217, 1), + (782, 35, 1), + (783, 35, 1), + (784, 35, 1), + (806, 81, 1), + (849, 180, 3), + (850, 180, 3), + (851, 180, 3), + (886, 102, 1), + (887, 102, 1), + (893, 87, 1), + (894, 87, 1), + (924, 23, 3), + (925, 23, 3), + (931, 23, 1), + (932, 23, 1), + (933, 23, 1), + (975, 102, 1), + (1018, 227, 3), + (1041, 30, 6), + (1042, 30, 6), + (1043, 30, 6), + (1044, 310, 6), + (1045, 310, 6), + (1046, 310, 6), + (1047, 311, 3), + (1048, 311, 3), + (1049, 311, 3), + (1050, 309, 6), + (1051, 309, 6), + (1052, 309, 6), + (1102, 30, 1), + (1103, 30, 1), + (1104, 30, 1), + (1105, 30, 1), + (1106, 30, 1), + (1107, 23, 3), + (1108, 23, 3), + (1109, 23, 3), + (1110, 187, 5), + (1111, 187, 5), + (1112, 187, 5), + (1122, 176, 2), + (1126, 58, 1), + (1127, 58, 1), + (1128, 58, 1), + (1129, 125, 1), + (1130, 125, 1), + (1150, 189, 3), + (1151, 189, 3), + (1152, 189, 3), + (1163, 309, 3), + (1164, 309, 3), + (1165, 309, 3), + (1203, 19, 3), + (1204, 19, 3), + (1205, 19, 3), + (1210, 114, 6), + (1211, 114, 6), + (1212, 114, 6), + (1213, 215, 6), + (1214, 215, 6), + (1215, 215, 6), + (1242, 173, 3), + (1243, 173, 3), + (1244, 173, 3), + (1251, 61, 1), + (1252, 64, 1), + (1253, 62, 1), + (1254, 63, 1), + (1274, 175, 3), + (1275, 175, 3), + (1276, 175, 3), + (1278, 6001, 11), + (1279, 6001, 11), + (1280, 6001, 11), + (1323, 47, 1), + (1337, 308, 3), + (1338, 308, 3), + (1339, 308, 3), + (1414, 451, 1), + (1415, 451, 1), + (1416, 451, 1), + (1417, 451, 1), + (1418, 451, 1), + (1420, 17, 3), + (1421, 17, 3), + (1422, 17, 3), + (1423, 17, 3), + (1424, 17, 3), + (1425, 374, 3), + (1426, 374, 3), + (1427, 374, 3), + (1428, 374, 3), + (1429, 374, 3), + (1435, 20, 3), + (1436, 20, 3), + (1437, 20, 3), + (1458, 375, 3), + (1459, 255, 5), + (1460, 255, 5), + (1461, 255, 5), + (1471, 362, 1), + (1472, 362, 1), + (1473, 362, 1), + (1474, 362, 1), + (1475, 362, 1), + (1483, 114, 6), + (1484, 114, 6), + (1485, 114, 6), + (1486, 19, 7), + (1487, 19, 7), + (1488, 19, 7), + (1489, 19, 7), + (1490, 19, 7), + (1494, 80, 1), + (1495, 185, 6), + (1496, 185, 6), + (1497, 185, 6), + (1501, 46, 1), + (1502, 46, 1), + (1503, 46, 1), + (1504, 60, 1), + (1505, 60, 1), + (1506, 60, 1), + (1511, 175, 3), + (1512, 175, 3), + (1513, 175, 3), + (1514, 259, 6), + (1515, 259, 6), + (1516, 259, 6), + (1524, 30, 3), + (1525, 30, 3), + (1526, 30, 3), + (1543, 439, 3), + (1544, 439, 3), + (1545, 439, 3), + (1546, 420, 1), + (1547, 420, 1), + (1548, 420, 1), + (1552, 13, 5), + (1553, 13, 5), + (1554, 13, 5), + (1555, 359, 3), + (1556, 359, 3), + (1557, 359, 3), + (1558, 46, 1), + (1559, 46, 1), + (1560, 46, 1), + (1572, 263, 1), + (1573, 263, 1), + (1574, 263, 1), + (1575, 263, 1), + (1576, 263, 1), + (1577, 58, 1), + (1578, 58, 1), + (1579, 58, 1), + (1583, 300, 6), + (1584, 300, 6), + (1585, 300, 6), + (1586, 300, 6), + (1587, 300, 6), + (1591, 222, 3), + (1601, 82, 1), + (1602, 82, 1), + (1603, 82, 1), + (1608, 82, 3), + (1609, 82, 3), + (1610, 82, 3), + (1611, 181, 2), + (1612, 181, 2), + (1613, 181, 2), + (1614, 181, 2), + (1615, 181, 2), + (1627, 13, 5), + (1628, 13, 5), + (1629, 13, 5), + (1638, 224, 3), + (1639, 565, 1), + (1640, 793, 1), + (1641, 121, 3), + (1642, 121, 3), + (1643, 77, 1), + (1644, 85, 1), + (1645, 77, 1), + (1646, 85, 1), + (1656, 153, 1), + (1657, 153, 1), + (1659, 285, 1), + (1660, 285, 1), + (1667, 570, 1), + (2400, 38, 1), + (2401, 38, 1), + (2402, 38, 1), + (3676, 35, 1), + (4666, 435, 3), + (4667, 435, 3), + (4668, 435, 3), + (4669, 435, 3), + (4670, 435, 3), + (4688, 497, 5), + (4689, 497, 5), + (4690, 497, 5), + (4691, 497, 5), + (4692, 497, 5), + (4707, 30, 6), + (4708, 30, 6), + (4709, 30, 6), + (4710, 310, 6), + (4711, 310, 6), + (4712, 310, 6), + (4713, 311, 3), + (4714, 311, 3), + (4715, 311, 3), + (4716, 309, 6), + (4717, 309, 6), + (4718, 309, 6), + (4749, 23, 3), + (4750, 23, 3), + (4751, 23, 3), + (4752, 114, 6), + (4753, 114, 6), + (4754, 114, 6), + (4755, 215, 6), + (4756, 215, 6), + (4757, 215, 6), + (4761, 526, 3), + (4762, 526, 3), + (4763, 526, 3), + (4773, 20, 3), + (4795, 309, 3), + (4796, 309, 3), + (4797, 309, 3), + (4829, 420, 1), + (4830, 420, 1), + (4831, 420, 1), + (4844, 435, 3), + (4845, 435, 3), + (4846, 435, 3), + (4847, 435, 3), + (4848, 435, 3), + (4861, 68, 1), + (4862, 68, 1), + (4863, 68, 1), + (4864, 175, 3), + (4865, 175, 3), + (4866, 175, 3), + (4887, 413, 3), + (4888, 413, 3), + (4889, 413, 3), + (4890, 57, 1), + (4894, 409, 3), + (4895, 409, 3), + (4896, 409, 3), + (4903, 784, 1), + (4906, 785, 1), + (4909, 786, 1), + (4912, 787, 1), + (4915, 794, 1), + (4916, 794, 1), + (4917, 794, 1), + (4921, 117, 1), + (4922, 117, 1), + (4923, 117, 1), + (4924, 740, 3), + (4925, 740, 3), + (4926, 740, 3), + (4931, 173, 8), + (4932, 173, 8), + (4933, 173, 8), + (4951, 439, 3), + (4952, 439, 3), + (4953, 439, 3), + (4975, 30, 1), + (4976, 30, 1), + (4977, 30, 1), + (4978, 30, 1), + (4979, 30, 1), + (4986, 82, 1), + (4987, 82, 1), + (4988, 82, 1), + (4989, 82, 3), + (4990, 82, 3), + (4991, 82, 3), + (5010, 35, 1), + (5011, 35, 1), + (5012, 35, 1), + (5038, 30, 3), + (5039, 30, 3), + (5040, 30, 3), + (5041, 6001, 11), + (5042, 6001, 11), + (5043, 6001, 11), + (5061, 45, 1), + (5069, 224, 3), + (5070, 19, 3), + (5071, 19, 3), + (5072, 19, 3), + (5080, 255, 5), + (5081, 255, 5), + (5082, 255, 5), + (5098, 73, 2), + (5118, 396, 1), + (5119, 396, 1), + (5120, 396, 1), + (5127, 261, 3), + (5128, 261, 3), + (5129, 261, 3), + (5133, 23, 3), + (5134, 23, 3), + (5135, 23, 3), + (5136, 496, 5), + (5137, 496, 5), + (5138, 496, 5), + (5139, 496, 5), + (5140, 496, 5), + (5251, 447, 3), + (5252, 447, 3), + (5253, 447, 3), + (5264, 278, 5), + (5265, 278, 5), + (5266, 278, 5), + (5267, 278, 5), + (5268, 278, 5), + (5270, 87, 1), + (5271, 87, 1), + (5272, 87, 1), + (5286, 23, 3), + (5287, 23, 3), + (5288, 23, 3), + (5311, 185, 6), + (5312, 185, 6), + (5313, 185, 6), + (5330, 1685, 1), + (5333, 1685, 1), + (5336, 1685, 1), + (5339, 1685, 1), + (5342, 1685, 1), + (5347, 1685, 1), + (5348, 1685, 1), + (5350, 707, 4), + (5350, 1685, 1), + (5353, 1685, 1), + (5356, 1685, 1), + (5357, 1685, 1), + (5360, 1685, 1), + (5363, 447, 3), + (5363, 1685, 1), + (5366, 1685, 1), + (5369, 1685, 1), + (5513, 58, 1), + (5514, 58, 1), + (5515, 58, 1), + (5529, 19, 7), + (5530, 19, 7), + (5531, 19, 7), + (5532, 19, 7), + (5533, 19, 7), + (5542, 30, 6), + (5543, 30, 6), + (5544, 30, 6), + (5545, 310, 6), + (5546, 310, 6), + (5547, 310, 6), + (5548, 311, 3), + (5549, 311, 3), + (5550, 311, 3), + (5551, 309, 6), + (5552, 309, 6), + (5553, 309, 6), + (5571, 23, 3), + (5572, 23, 3), + (5573, 23, 3), + (5574, 114, 6), + (5575, 114, 6), + (5576, 114, 6), + (5577, 215, 6), + (5578, 215, 6), + (5579, 215, 6), + (5595, 309, 3), + (5596, 309, 3), + (5597, 309, 3), + (5607, 794, 1), + (5608, 794, 1), + (5609, 794, 1), + (5617, 23, 3), + (5618, 23, 3), + (5619, 23, 3), + (5702, 30, 1), + (5703, 30, 1), + (5704, 30, 1), + (5705, 30, 1), + (5706, 30, 1), + (5759, 374, 3), + (5760, 374, 3), + (5761, 374, 3), + (5762, 374, 3), + (5763, 374, 3), + (5791, 19, 3), + (5792, 19, 3), + (5793, 19, 3), + (5797, 396, 1), + (5798, 396, 1), + (5799, 396, 1), + (5803, 255, 5), + (5804, 255, 5), + (5805, 255, 5), + (5806, 30, 3), + (5807, 30, 3), + (5808, 30, 3), + (5825, 45, 1), + (5826, 185, 6), + (5827, 185, 6), + (5828, 185, 6), + (5854, 217, 1), + (5855, 217, 1), + (5856, 217, 1), + (5857, 173, 3), + (5858, 173, 3), + (5859, 173, 3), + (5869, 57, 1), + (5871, 57, 1), + (5872, 57, 1), + (5880, 60, 1), + (5881, 60, 1), + (5882, 60, 1), + (5886, 58, 1), + (5887, 58, 1), + (5888, 58, 1), + (5892, 784, 1), + (5893, 785, 1), + (5894, 786, 1), + (5895, 787, 1), + (5939, 278, 5), + (5940, 278, 5), + (5941, 278, 5), + (5942, 278, 5), + (5943, 278, 5), + (5944, 740, 3), + (5945, 740, 3), + (5946, 740, 3), + (5947, 175, 3), + (5948, 175, 3), + (5949, 175, 3), + (5950, 175, 3), + (5951, 175, 3), + (5952, 175, 3), + (5954, 68, 1), + (5955, 68, 1), + (5956, 68, 1), + (5969, 6001, 11), + (5970, 6001, 11), + (5971, 6001, 11), + (5972, 6001, 11), + (5973, 6000, 11), + (5984, 702, 1), + (6017, 82, 1), + (6018, 82, 1), + (6019, 82, 1), + (6026, 826, 1), + (6027, 826, 1), + (6028, 826, 1), + (6042, 439, 3), + (6043, 439, 3), + (6044, 439, 3), + (6054, 173, 8), + (6055, 173, 8), + (6056, 173, 8), + (6063, 87, 1), + (6064, 87, 1), + (6065, 87, 1), + (6088, 392, 1), + (6089, 392, 1), + (6090, 392, 1), + (6092, 447, 3), + (6093, 447, 3), + (6094, 447, 3), + (6102, 224, 3), + (6106, 308, 3), + (6107, 308, 3), + (6108, 308, 3), + (6109, 308, 3), + (6110, 308, 3), + (6111, 308, 3), + (6130, 120, 1), + (6131, 120, 1), + (6132, 120, 1), + (6136, 300, 6), + (6158, 308, 3), + (6159, 308, 3), + (6160, 308, 3), + (6209, 245, 3), + (6210, 245, 3), + (6211, 245, 3), + (6228, 404, 1), + (6229, 404, 1), + (6230, 404, 1), + (6231, 404, 1), + (6233, 43, 1), + (6234, 43, 1), + (6235, 43, 1), + (6260, 98, 1), + (6261, 98, 1), + (6262, 98, 1), + (6272, 672, 1), + (6273, 672, 1), + (6274, 672, 1), + (6275, 790, 1), + (6276, 790, 1), + (6277, 790, 1), + (6302, 3710, 1), + (6303, 3710, 1), + (6304, 3710, 1), + (6319, 107, 1), + (6320, 107, 1), + (6321, 107, 1), + (6333, 125, 1), + (6337, 553, 1), + (6338, 553, 1), + (6339, 553, 1), + (6340, 777, 1), + (6341, 777, 1), + (6342, 777, 1), + (6346, 494, 3), + (6347, 494, 3), + (6348, 494, 3), + (6349, 500, 3), + (6350, 500, 3), + (6351, 500, 3), + (6352, 409, 3), + (6353, 409, 3), + (6354, 409, 3), + (6380, 128, 3), + (6381, 128, 3), + (6382, 128, 3), + (6400, 187, 5), + (6401, 187, 5), + (6402, 187, 5), + (6403, 23, 3), + (6404, 23, 3), + (6405, 23, 3), + (6439, 41, 1), + (6440, 41, 1), + (6441, 420, 1), + (6442, 362, 1), + (6443, 362, 1), + (6445, 176, 1), + (6446, 176, 1), + (6447, 176, 1), + (6478, 3800, 1), + (6479, 3800, 1), + (6480, 3800, 1), + (6481, 36, 1), + (6482, 36, 1), + (6483, 36, 1), + (6484, 558, 1), + (6485, 558, 1), + (6486, 558, 1), + (6499, 611, 1), + (6500, 526, 3), + (6501, 526, 3), + (6502, 526, 3), + (6503, 172, 1), + (6504, 172, 1), + (6505, 172, 1), + (6506, 172, 1), + (6514, 404, 1), + (6515, 404, 1), + (6516, 404, 1), + (6517, 20, 1), + (6528, 107, 1), + (6630, 278, 5), + (6631, 278, 5), + (6632, 278, 5), + (6633, 278, 5), + (6634, 278, 5), + (6636, 358, 3), + (6637, 358, 3), + (6638, 358, 3), + (6668, 672, 3), + (6669, 672, 3), + (6670, 672, 3), + (6697, 857, 1), + (6698, 857, 1), + (6699, 857, 1), + (6700, 857, 1), + (6701, 857, 1), + (6703, 171, 1), + (6704, 171, 1), + (6705, 171, 1), + (6712, 177, 1), + (6713, 177, 1), + (6714, 177, 1), + (6715, 177, 1), + (6716, 177, 1), + (6755, 184, 3), + (6756, 184, 3), + (6757, 184, 3), + (6819, 524, 1), + (6820, 524, 1), + (6821, 524, 1), + (6823, 320, 1), + (6824, 320, 1), + (6825, 320, 1), + (6826, 320, 1), + (6827, 320, 1), + (6870, 544, 1), + (6871, 544, 1), + (6872, 544, 1), + (6873, 3837, 3), + (6874, 3837, 3), + (6875, 3837, 3), + (6876, 259, 3), + (6877, 259, 3), + (6878, 259, 3), + (6900, 465, 3), + (6901, 465, 3), + (6902, 465, 3), + (6903, 465, 3), + (6904, 465, 3), + (6908, 499, 1), + (6909, 499, 1), + (6910, 499, 1), + (6930, 611, 1), + (6935, 465, 3), + (6936, 465, 3), + (6937, 465, 3), + (6941, 962, 1), + (6942, 962, 1), + (6943, 962, 1), + (6944, 962, 1), + (6945, 962, 1), + (6977, 3817, 1), + (6978, 3817, 1), + (6979, 3817, 1), + (6980, 128, 1), + (6981, 128, 1), + (6982, 128, 1), + (6983, 245, 3), + (6988, 985, 1), + (6989, 985, 1), + (6990, 985, 1), + (7005, 789, 1), + (7006, 789, 1), + (7007, 789, 1), + (7033, 804, 1), + (7034, 804, 1), + (7035, 804, 1), + (7036, 3646, 1), + (7037, 3646, 1), + (7038, 3646, 1), + (7050, 26, 3), + (7051, 26, 3), + (7052, 26, 3), + (7053, 26, 3), + (7054, 26, 3), + (7055, 26, 3), + (7063, 26, 3), + (7064, 26, 3), + (7065, 26, 3), + (7100, 254, 3), + (7101, 254, 3), + (7102, 254, 3), + (7103, 286, 1), + (7104, 286, 1), + (7105, 286, 1), + (7116, 110, 1), + (7117, 110, 1), + (7118, 110, 1), + (7122, 435, 3), + (7123, 435, 3), + (7124, 435, 3), + (7125, 435, 3), + (7126, 435, 3), + (7128, 109, 1), + (7129, 109, 1), + (7130, 109, 1), + (7134, 439, 3), + (7135, 439, 3), + (7136, 439, 3), + (7137, 672, 1), + (7138, 672, 1), + (7139, 672, 1), + (7184, 1685, 1), + (7199, 175, 3), + (7200, 175, 3), + (7201, 175, 3), + (7204, 278, 5), + (7205, 278, 5), + (7206, 278, 5), + (7207, 278, 5), + (7208, 278, 5), + (7215, 68, 1), + (7216, 68, 1), + (7232, 114, 6), + (7233, 114, 6), + (7234, 114, 6), + (7246, 794, 1), + (7247, 794, 1), + (7248, 794, 1), + (7253, 784, 1), + (7254, 785, 1), + (7255, 786, 1), + (7256, 787, 1), + (7260, 60, 1), + (7261, 60, 1), + (7262, 60, 1), + (7263, 58, 1), + (7264, 58, 1), + (7265, 58, 1), + (7266, 125, 1), + (7276, 217, 1), + (7277, 217, 1), + (7278, 217, 1), + (7285, 173, 3), + (7286, 173, 3), + (7287, 173, 3), + (7288, 409, 3), + (7289, 409, 3), + (7290, 409, 3), + (7291, 173, 8), + (7292, 173, 8), + (7293, 173, 8), + (7301, 19, 3), + (7302, 19, 3), + (7303, 19, 3), + (7310, 255, 5), + (7311, 255, 5), + (7312, 255, 5), + (7316, 41, 1), + (7317, 41, 1), + (7323, 254, 3), + (7324, 254, 3), + (7325, 254, 3), + (7326, 286, 1), + (7327, 286, 1), + (7328, 286, 1), + (7329, 6001, 11), + (7330, 6001, 11), + (7331, 6001, 11), + (7335, 702, 1), + (7359, 82, 1), + (7360, 82, 1), + (7361, 82, 1), + (7378, 82, 3), + (7379, 82, 3), + (7380, 82, 3), + (7381, 82, 3), + (7382, 82, 3), + (7383, 82, 3), + (7390, 87, 1), + (7391, 87, 1), + (7392, 87, 1), + (7407, 31, 3), + (7414, 185, 6), + (7415, 185, 6), + (7416, 185, 6), + (7433, 30, 1), + (7434, 30, 1), + (7435, 30, 1), + (7436, 30, 1), + (7437, 30, 1), + (7445, 187, 5), + (7446, 187, 5), + (7447, 187, 5), + (7448, 553, 1), + (7449, 553, 1), + (7450, 553, 1), + (7451, 777, 1), + (7452, 777, 1), + (7453, 777, 1), + (7466, 224, 3), + (7472, 447, 3), + (7473, 447, 3), + (7474, 447, 3), + (7478, 245, 3), + (7497, 128, 3), + (7498, 128, 3), + (7499, 128, 3), + (7554, 19, 7), + (7555, 19, 7), + (7556, 19, 7), + (7557, 19, 7), + (7558, 19, 7), + (7562, 30, 6), + (7563, 30, 6), + (7564, 30, 6), + (7581, 215, 6), + (7582, 215, 6), + (7583, 215, 6), + (7615, 494, 3), + (7616, 494, 3), + (7617, 494, 3), + (7618, 500, 3), + (7619, 500, 3), + (7620, 500, 3), + (7621, 20, 1), + (7622, 26, 3), + (7623, 26, 3), + (7624, 26, 3), + (7631, 309, 3), + (7632, 309, 3), + (7633, 309, 3), + (7650, 310, 6), + (7651, 310, 6), + (7652, 310, 6), + (7653, 311, 3), + (7654, 311, 3), + (7655, 311, 3), + (7656, 309, 6), + (7657, 309, 6), + (7658, 309, 6), + (7659, 153, 3), + (7660, 153, 3), + (7661, 153, 3), + (7664, 170, 3), + (7665, 170, 3), + (7666, 170, 3), + (7667, 170, 3), + (7668, 170, 3), + (7682, 68, 1), + (7686, 435, 3), + (7687, 435, 3), + (7688, 435, 3), + (7691, 224, 3), + (7695, 862, 3), + (7696, 862, 3), + (7697, 862, 3), + (7700, 310, 3), + (7701, 310, 3), + (7702, 310, 3), + (7704, 3707, 1), + (7705, 3707, 1), + (7706, 3707, 1), + (7707, 87, 1), + (7708, 87, 1), + (7709, 87, 1), + (7710, 702, 1), + (7711, 702, 1), + (7712, 3826, 1), + (7715, 901, 1), + (7716, 901, 1), + (7717, 901, 1), + (7718, 125, 1), + (7722, 19, 7), + (7723, 19, 7), + (7724, 19, 7), + (7725, 19, 7), + (7726, 19, 7), + (7733, 195, 3), + (7743, 184, 1), + (7744, 184, 1), + (7745, 184, 1), + (7748, 13, 5), + (7749, 13, 5), + (7750, 13, 5), + (7751, 2234, 1), + (7752, 2234, 1), + (7753, 2234, 1), + (7754, 85, 1), + (7757, 9403, 1), + (7758, 9403, 1), + (7759, 9403, 1), + (7760, 824, 1), + (7761, 824, 1), + (7762, 824, 1), + (7765, 7689, 1), + (7766, 7689, 1), + (7767, 7689, 1), + (7768, 7689, 1), + (7770, 19, 3), + (7771, 19, 3), + (7772, 19, 3), + (7773, 19, 3), + (7774, 19, 3), + (7775, 19, 3), + (7822, 1154, 1), + (7823, 1154, 1), + (7824, 1154, 1), + (7825, 1154, 1), + (7826, 1154, 1), + (7827, 1404, 3), + (7832, 60, 1), + (7833, 60, 1), + (7834, 60, 1), + (7835, 60, 1), + (7836, 60, 1), + (7842, 19, 7), + (7843, 19, 7), + (7844, 19, 7), + (7940, 558, 1), + (7941, 558, 1), + (7942, 558, 1), + (7943, 39, 1), + (7944, 41, 1), + (7951, 19, 3), + (7952, 19, 3), + (7953, 19, 3), + (7983, 520, 1), + (7984, 520, 1), + (7985, 520, 1), + (7986, 705, 1), + (7987, 705, 1), + (7988, 705, 1), + (7989, 1092, 1), + (7990, 1092, 1), + (7991, 1092, 1), + (7992, 1092, 1), + (7993, 39, 1), + (7994, 39, 1), + (7995, 39, 1), + (8031, 791, 1), + (8032, 791, 1), + (8033, 791, 1), + (8035, 521, 1), + (8036, 521, 1), + (8037, 521, 1), + (8069, 160, 4), + (8070, 160, 4), + (8071, 160, 4), + (8076, 565, 1), + (8077, 565, 1), + (8078, 565, 1), + (8079, 565, 1), + (8080, 565, 1), + (8081, 565, 1), + (8082, 208, 1), + (8083, 208, 1), + (8084, 208, 1), + (8195, 3707, 1), + (8196, 3707, 1), + (8197, 3707, 1), + (8198, 210, 1), + (8199, 210, 1), + (8200, 210, 1), + (8204, 153, 1), + (8205, 153, 1), + (8206, 153, 1), + (8207, 285, 1), + (8208, 285, 1), + (8209, 285, 1), + (8220, 3812, 1), + (8224, 516, 3), + (8225, 516, 3), + (8226, 516, 3), + (8260, 1211, 1), + (8263, 142, 20), + (8264, 142, 20), + (8265, 142, 20), + (8266, 142, 20), + (8267, 142, 20), + (8268, 142, 20), + (8269, 142, 20), + (8270, 142, 20), + (8271, 142, 20), + (8272, 142, 20), + (8273, 142, 20), + (8274, 142, 20), + (8275, 142, 20), + (8276, 142, 20), + (8277, 142, 20), + (8278, 142, 20), + (8279, 142, 20), + (8280, 142, 20), + (8281, 142, 20), + (8282, 142, 20), + (8283, 142, 20), + (8284, 142, 20), + (8285, 142, 20), + (8286, 142, 20), + (8287, 142, 20), + (8288, 142, 20), + (8289, 142, 20), + (8290, 142, 20), + (8291, 142, 20), + (8292, 142, 20), + (8293, 142, 20), + (8294, 142, 20), + (8295, 142, 20), + (8296, 142, 20), + (8297, 142, 20), + (8303, 309, 6), + (8309, 31, 3), + (8310, 31, 3), + (8311, 31, 3), + (8312, 110, 1), + (8317, 8205, 1), + (8318, 8205, 1), + (8319, 199, 1), + (8320, 199, 1), + (8321, 199, 1), + (8332, 861, 1), + (8333, 861, 1), + (8334, 861, 1), + (8335, 1041, 1), + (8336, 1041, 1), + (8337, 1041, 1), + (8338, 1041, 1), + (8339, 1041, 1), + (8344, 215, 6), + (8345, 215, 6), + (8346, 215, 6), + (8347, 616, 1), + (8348, 616, 1), + (8349, 616, 1), + (8351, 142, 20), + (8352, 142, 20), + (8353, 142, 20), + (8354, 142, 20), + (8355, 142, 20), + (8356, 142, 20), + (8357, 142, 20), + (8358, 142, 20), + (8359, 142, 20), + (8360, 142, 20), + (8361, 142, 20), + (8362, 142, 20), + (8363, 142, 20), + (8364, 142, 20), + (8365, 142, 20), + (8366, 142, 20), + (8367, 142, 20), + (8368, 142, 20), + (8369, 142, 20), + (8370, 142, 20), + (8371, 142, 20), + (8372, 142, 20), + (8373, 142, 20), + (8374, 142, 20), + (8375, 142, 20), + (8376, 142, 20), + (8377, 142, 20), + (8378, 142, 20), + (8379, 142, 20), + (8380, 142, 20), + (8381, 142, 20), + (8382, 142, 20), + (8383, 142, 20), + (8384, 142, 20), + (8385, 142, 20), + (8386, 142, 20), + (8387, 142, 20), + (8388, 142, 20), + (8389, 142, 20), + (8390, 142, 20), + (8391, 142, 20), + (8392, 142, 20), + (8393, 142, 20), + (8394, 142, 20), + (8395, 142, 20), + (8396, 142, 20), + (8397, 142, 20), + (8398, 142, 20), + (8399, 142, 20), + (8400, 142, 20), + (8401, 142, 20), + (8402, 142, 20), + (8403, 142, 20), + (8404, 142, 20), + (8405, 142, 20), + (8406, 142, 20), + (8407, 142, 20), + (8408, 142, 20), + (8409, 142, 20), + (8410, 142, 20), + (8411, 142, 20), + (8412, 142, 20), + (8413, 142, 20), + (8414, 142, 20), + (8415, 142, 20), + (8416, 142, 20), + (8417, 142, 20), + (8418, 142, 20), + (8419, 142, 20), + (8420, 142, 20), + (8421, 516, 3), + (8427, 254, 3), + (8428, 254, 3), + (8429, 254, 3), + (9103, 1350, 3), + (9104, 1350, 3), + (9105, 1350, 3), + (9106, 1351, 3), + (9107, 1351, 3), + (9108, 1351, 3), + (9112, 1390, 3), + (9113, 1390, 3), + (9114, 1390, 3), + (9115, 1391, 3), + (9116, 1391, 3), + (9117, 1391, 3), + (9121, 1370, 3), + (9122, 1370, 3), + (9123, 1370, 3), + (9124, 1371, 3), + (9125, 1371, 3), + (9126, 1371, 3), + (9130, 1380, 3), + (9131, 1380, 3), + (9132, 1380, 3), + (9133, 1381, 3), + (9134, 1381, 3), + (9135, 1381, 3), + (9139, 1470, 3), + (9140, 1470, 3), + (9141, 1470, 3), + (9142, 1471, 3), + (9143, 1471, 3), + (9144, 1471, 3), + (9148, 1480, 3), + (9149, 1480, 3), + (9150, 1480, 3), + (9151, 1481, 3), + (9152, 1481, 3), + (9153, 1481, 3), + (9157, 1490, 3), + (9158, 1490, 3), + (9159, 1490, 3), + (9160, 1491, 3), + (9161, 1491, 3), + (9162, 1491, 3), + (9166, 1460, 3), + (9167, 1460, 3), + (9168, 1460, 3), + (9169, 1461, 3), + (9170, 1461, 3), + (9171, 1461, 3), + (9175, 1450, 3), + (9176, 1450, 3), + (9177, 1450, 3), + (9178, 1451, 3), + (9179, 1451, 3), + (9180, 1451, 3), + (9184, 1440, 3), + (9185, 1440, 3), + (9186, 1440, 3), + (9187, 1441, 3), + (9188, 1441, 3), + (9189, 1441, 3), + (9193, 1420, 3), + (9194, 1420, 3), + (9195, 1420, 3), + (9196, 1421, 3), + (9197, 1421, 3), + (9198, 1421, 3), + (9202, 1430, 3), + (9203, 1430, 3), + (9204, 1430, 3), + (9205, 1431, 3), + (9206, 1431, 3), + (9207, 1431, 3), + (9211, 1400, 3), + (9212, 1400, 3), + (9213, 1400, 3), + (9214, 1401, 3), + (9215, 1401, 3), + (9216, 1401, 3), + (9220, 1360, 3), + (9221, 1360, 3), + (9222, 1360, 3), + (9223, 1361, 3), + (9224, 1361, 3), + (9225, 1361, 3), + (9229, 1500, 3), + (9230, 1500, 3), + (9231, 1500, 3), + (9232, 1501, 3), + (9233, 1501, 3), + (9234, 1501, 3), + (9238, 1410, 3), + (9239, 1410, 3), + (9240, 1410, 3), + (9241, 1411, 3), + (9242, 1411, 3), + (9243, 1411, 3), + (9300, 1300, 3), + (9301, 1300, 3), + (9302, 1300, 3), + (9303, 1300, 6), + (9304, 1300, 6), + (9305, 1300, 6), + (9306, 1300, 9), + (9307, 1300, 9), + (9308, 1300, 9), + (9309, 1313, 3), + (9310, 1313, 3), + (9311, 1313, 3), + (9312, 1313, 6), + (9313, 1313, 6), + (9314, 1313, 6), + (9315, 1313, 9), + (9316, 1313, 9), + (9317, 1313, 9), + (9318, 1302, 3), + (9319, 1302, 3), + (9320, 1302, 3), + (9321, 1302, 6), + (9322, 1302, 6), + (9323, 1302, 6), + (9324, 1302, 9), + (9325, 1302, 9), + (9326, 1302, 9), + (9327, 1303, 3), + (9328, 1303, 3), + (9329, 1303, 3), + (9330, 1303, 6), + (9331, 1303, 6), + (9332, 1303, 6), + (9333, 1303, 9), + (9334, 1303, 9), + (9335, 1303, 9), + (9336, 1301, 3), + (9337, 1301, 3), + (9338, 1301, 3), + (9339, 1301, 6), + (9340, 1301, 6), + (9341, 1301, 6), + (9342, 1301, 9), + (9343, 1301, 9), + (9344, 1301, 9), + (9345, 1312, 3), + (9346, 1312, 3), + (9347, 1312, 3), + (9348, 1312, 6), + (9349, 1312, 6), + (9350, 1312, 6), + (9351, 1312, 9), + (9352, 1312, 9), + (9353, 1312, 9), + (9354, 1315, 3), + (9355, 1315, 3), + (9356, 1315, 3), + (9357, 1315, 6), + (9358, 1315, 6), + (9359, 1315, 6), + (9360, 1315, 9), + (9361, 1315, 9), + (9362, 1315, 9), + (9363, 1310, 3), + (9364, 1310, 3), + (9365, 1310, 3), + (9366, 1310, 6), + (9367, 1310, 6), + (9368, 1310, 6), + (9369, 1310, 9), + (9370, 1310, 9), + (9371, 1310, 9), + (9372, 1311, 3), + (9373, 1311, 3), + (9374, 1311, 3), + (9375, 1311, 6), + (9376, 1311, 6), + (9377, 1311, 6), + (9378, 1311, 9), + (9379, 1311, 9), + (9380, 1311, 9), + (9381, 1309, 3), + (9382, 1309, 3), + (9383, 1309, 3), + (9384, 1309, 6), + (9385, 1309, 6), + (9386, 1309, 6), + (9387, 1309, 9), + (9388, 1309, 9), + (9389, 1309, 9), + (9390, 1308, 3), + (9391, 1308, 3), + (9392, 1308, 3), + (9393, 1308, 6), + (9394, 1308, 6), + (9395, 1308, 6), + (9396, 1308, 9), + (9397, 1308, 9), + (9398, 1308, 9), + (9399, 1307, 3), + (9400, 1307, 3), + (9401, 1307, 3), + (9402, 1307, 6), + (9403, 1307, 6), + (9404, 1307, 6), + (9405, 1307, 9), + (9406, 1307, 9), + (9407, 1307, 9), + (9408, 1304, 3), + (9409, 1304, 3), + (9410, 1304, 3), + (9411, 1304, 6), + (9412, 1304, 6), + (9413, 1304, 6), + (9414, 1304, 9), + (9415, 1304, 9), + (9416, 1304, 9), + (9417, 1305, 3), + (9418, 1305, 3), + (9419, 1305, 3), + (9420, 1305, 6), + (9421, 1305, 6), + (9422, 1305, 6), + (9423, 1305, 9), + (9424, 1305, 9), + (9425, 1305, 9), + (9426, 1306, 3), + (9427, 1306, 3), + (9428, 1306, 3), + (9429, 1306, 6), + (9430, 1306, 6), + (9431, 1306, 6), + (9432, 1306, 9), + (9433, 1306, 9), + (9434, 1306, 9), + (9435, 1314, 3), + (9436, 1314, 3), + (9437, 1314, 3), + (9438, 1314, 6), + (9439, 1314, 6), + (9440, 1314, 6), + (9441, 1314, 9), + (9442, 1314, 9), + (9443, 1314, 9), + (9500, 72, 1), + (10016, 19, 3), + (10017, 19, 3), + (10018, 19, 3), + (10030, 558, 1), + (10031, 558, 1), + (10032, 558, 1), + (10038, 19, 3), + (10039, 19, 3), + (10040, 19, 3), + (10041, 358, 3), + (10042, 358, 3), + (10043, 358, 3), + (10047, 6001, 11), + (10048, 6001, 11), + (10049, 6001, 11), + (10064, 82, 3), + (10065, 82, 3), + (10066, 82, 3), + (10067, 82, 3), + (10068, 82, 3), + (10069, 82, 3), + (10070, 278, 5), + (10071, 278, 5), + (10072, 278, 5), + (10073, 278, 5), + (10074, 278, 5), + (10093, 185, 6), + (10105, 170, 3), + (10106, 170, 3), + (10107, 170, 3), + (10108, 170, 3), + (10109, 170, 3), + (10110, 520, 1), + (10111, 520, 1), + (10112, 520, 1), + (10130, 544, 1), + (10131, 544, 1), + (10132, 544, 1), + (10133, 3837, 3), + (10134, 3837, 3), + (10135, 3837, 3), + (10136, 259, 3), + (10137, 259, 3), + (10138, 259, 3), + (10150, 187, 5), + (10151, 187, 5), + (10152, 187, 5), + (10153, 553, 1), + (10154, 553, 1), + (10155, 553, 1), + (10165, 439, 3), + (10166, 439, 3), + (10167, 439, 3), + (10176, 171, 1), + (10177, 171, 1), + (10178, 171, 1), + (10182, 177, 1), + (10183, 177, 1), + (10184, 177, 1), + (10185, 177, 1), + (10186, 177, 1), + (10197, 447, 3), + (10198, 447, 3), + (10199, 447, 3), + (10203, 524, 1), + (10204, 524, 1), + (10205, 524, 1), + (10206, 320, 1), + (10207, 320, 1), + (10209, 175, 3), + (10210, 175, 3), + (10211, 175, 3), + (10213, 278, 5), + (10214, 278, 5), + (10215, 278, 5), + (10216, 278, 5), + (10217, 278, 5), + (10249, 208, 1), + (10250, 208, 1), + (10251, 208, 1), + (10255, 784, 1), + (10256, 785, 1), + (10257, 786, 1), + (10258, 787, 1), + (10262, 58, 1), + (10263, 58, 1), + (10264, 58, 1), + (10271, 173, 3), + (10272, 173, 3), + (10273, 173, 3), + (10274, 173, 8), + (10275, 173, 8), + (10276, 173, 8), + (10282, 791, 1), + (10283, 791, 1), + (10284, 791, 1), + (10285, 521, 1), + (10286, 521, 1), + (10287, 521, 1), + (10308, 128, 3), + (10309, 128, 3), + (10310, 128, 3), + (10329, 3701, 1), + (10330, 199, 3), + (10332, 943, 3), + (10336, 941, 1), + (10337, 941, 1), + (10338, 941, 1), + (10354, 6001, 17), + (10389, 841, 1), + (10390, 841, 1), + (10391, 841, 1), + (10396, 705, 4), + (10397, 1092, 4), + (10398, 3701, 1), + (10399, 3701, 1), + (10413, 207, 1), + (10414, 207, 1), + (10415, 207, 1), + (10416, 207, 1), + (10417, 207, 1), + (10426, 185, 18), + (10427, 519, 15), + (10428, 173, 8), + (10429, 173, 8), + (10430, 173, 8), + (10431, 791, 1), + (10432, 791, 1), + (10433, 791, 1), + (10434, 792, 1), + (10435, 792, 1), + (10436, 792, 1), + (10450, 19, 9), + (10451, 19, 9), + (10452, 19, 9), + (10456, 3800, 1), + (10457, 3800, 1), + (10458, 3800, 1), + (10462, 396, 1), + (10463, 396, 1), + (10464, 391, 9), + (10465, 391, 9), + (10466, 391, 9), + (10468, 19, 9), + (10469, 19, 9), + (10470, 558, 1), + (10471, 558, 1), + (10472, 558, 1), + (10473, 26, 3), + (10474, 26, 3), + (10475, 26, 3), + (10476, 26, 3), + (10477, 26, 3), + (10510, 705, 1), + (10511, 185, 3), + (10512, 185, 3), + (10513, 185, 3), + (10514, 519, 3), + (10515, 519, 3), + (10516, 519, 3), + (10519, 3213, 1), + (10522, 3732, 1), + (10527, 1400, 1), + (10532, 1401, 1), + (10537, 1402, 1), + (10548, 605, 13), + (10554, 263, 1), + (10555, 263, 1), + (10556, 263, 1), + (10557, 1120, 1), + (10558, 1120, 1), + (10559, 1120, 1), + (10560, 1120, 1), + (10561, 3551, 1), + (10562, 3551, 1), + (10563, 3551, 1), + (10564, 217, 1), + (10565, 217, 1), + (10566, 217, 1), + (10576, 109, 1), + (10579, 3646, 1), + (10580, 3646, 1), + (10588, 601, 1), + (10589, 601, 1), + (10590, 601, 1), + (10591, 601, 1), + (10592, 601, 1), + (10610, 265, 5), + (10611, 265, 5), + (10612, 265, 5), + (10621, 180, 3), + (10622, 180, 3), + (10623, 30, 3), + (10624, 30, 3), + (10625, 30, 3), + (10626, 702, 1), + (10646, 3826, 1), + (10657, 276, 3), + (10658, 276, 3), + (10659, 276, 3), + (10666, 98, 1), + (10667, 98, 1), + (10668, 98, 1), + (10670, 19, 9), + (10708, 6001, 11), + (10709, 6001, 11), + (10710, 6001, 11), + (10711, 30, 6), + (10712, 30, 6), + (10713, 30, 6), + (10714, 873, 1), + (10715, 873, 1), + (10717, 184, 1), + (10718, 184, 1), + (10719, 872, 1), + (10720, 872, 1), + (10721, 872, 1), + (10722, 778, 1), + (10723, 778, 1), + (10724, 778, 1), + (10725, 778, 1), + (10726, 778, 1), + (10727, 2235, 1), + (10728, 2235, 1), + (10730, 870, 1), + (10731, 870, 1), + (10733, 219, 1), + (10734, 219, 1), + (10735, 219, 1), + (10750, 286, 1), + (10751, 286, 1), + (10752, 7108, 1), + (10753, 286, 1), + (10789, 10424, 1), + (10790, 705, 4), + (10791, 1092, 4), + (10800, 462, 3), + (10801, 462, 3), + (10802, 462, 3), + (10903, 125, 1), + (10904, 125, 1), + (10905, 125, 1), + (10909, 7007, 1), + (10910, 7007, 1), + (10911, 7007, 1), + (10915, 823, 3), + (10916, 823, 3), + (10917, 823, 3), + (10951, 447, 3), + (10952, 447, 3), + (10953, 447, 3), + (10954, 662, 3), + (10955, 662, 3), + (10956, 662, 3), + (11011, 3710, 1), + (11012, 3710, 1), + (11013, 3710, 1), + (11014, 3899, 1), + (11015, 3899, 1), + (11016, 3899, 1), + (11020, 3899, 1), + (11050, 452, 3), + (11051, 452, 3), + (11052, 452, 3), + (11053, 500, 3), + (11054, 500, 3), + (11059, 452, 3), + (11060, 452, 3), + (11077, 986, 1), + (11078, 988, 1), + (11079, 987, 1), + (11088, 505, 1), + (11089, 505, 1), + (11090, 505, 1), + (11091, 505, 1), + (12422, 1202, 1), + (12432, 23, 3), + (12433, 23, 3), + (12434, 23, 3), + (12435, 23, 3), + (12436, 23, 3), + (12437, 23, 3), + (12475, 7003, 1), + (12476, 7003, 1), + (12477, 7003, 1), + (12478, 3705, 9), + (12479, 3705, 9), + (12480, 3705, 9), + (12523, 114, 6), + (12526, 215, 6), + (12527, 215, 6), + (12528, 215, 6), + (12529, 358, 3), + (12530, 358, 3), + (12531, 358, 3), + (12553, 23, 3), + (12554, 23, 3), + (12555, 23, 3), + (12556, 23, 3), + (12557, 23, 3), + (12558, 23, 3), + (12582, 9400, 1), + (12583, 9400, 1), + (12584, 9400, 1), + (12587, 9403, 1), + (12588, 9403, 1), + (12589, 9403, 1), + (12600, 3514, 1), + (12606, 13, 5), + (12610, 310, 3), + (12626, 1410, 3), + (12629, 1411, 3), + (12632, 1412, 3), + (12635, 428, 2), + (12639, 519, 3), + (12642, 185, 3), + (12645, 519, 1), + (12646, 185, 1), + (12664, 3728, 1), + (12673, 420, 1), + (12677, 17, 3), + (12679, 276, 3), + (12680, 276, 3), + (12681, 276, 3), + (12697, 30, 6), + (12698, 30, 6), + (12699, 30, 6), + (12713, 8202, 1), + (12714, 8202, 1), + (12715, 8202, 1), + (12716, 3702, 1), + (12717, 3702, 1), + (12718, 3702, 1), + (12719, 3702, 1), + (12720, 3506, 1), + (12721, 3506, 1), + (12722, 3506, 1), + (12723, 3506, 1), + (12727, 359, 3), + (12728, 359, 3), + (12729, 359, 3), + (12730, 941, 1), + (12731, 941, 1), + (12732, 941, 1), + (12733, 943, 3), + (12734, 259, 3), + (12735, 259, 3), + (12736, 259, 3), + (12737, 3701, 1), + (12738, 3701, 1), + (12739, 3701, 1), + (12749, 30, 1), + (12750, 30, 1), + (12751, 30, 1), + (12757, 68, 1), + (12758, 68, 1), + (12759, 68, 1), + (12760, 175, 3), + (12761, 175, 3), + (12762, 175, 3), + (12773, 1580, 1), + (12774, 1580, 1), + (12775, 1580, 1), + (12776, 1580, 1), + (12777, 1580, 1), + (12779, 826, 1), + (12780, 826, 1), + (12781, 826, 1), + (12782, 826, 1), + (12783, 826, 1), + (12784, 826, 1), + (12798, 278, 5), + (12799, 278, 5), + (12800, 278, 5), + (12831, 128, 1), + (12834, 128, 1), + (12835, 128, 1), + (12840, 3817, 1), + (12841, 3817, 1), + (12849, 8303, 1), + (12860, 23, 3), + (12863, 23, 3), + (12865, 1155, 1), + (12866, 639, 1), + (12867, 6106, 6), + (12871, 452, 3), + (12872, 452, 3), + (12874, 451, 1), + (12876, 7003, 1), + (12877, 7003, 1), + (12878, 7003, 1), + (12881, 172, 1), + (12886, 304, 5), + (12887, 303, 5), + (12888, 305, 5), + (12889, 501, 1), + (12890, 507, 1), + (12892, 509, 3), + (12894, 1122, 1), + (12899, 57, 1), + (12900, 57, 1), + (12902, 1380, 1), + (12903, 1380, 1), + (12907, 1381, 1), + (12908, 1381, 1), + (12912, 1382, 1), + (12913, 1382, 1), + (12934, 173, 3), + (12956, 784, 1), + (12957, 786, 1), + (12958, 787, 1), + (12959, 785, 1), + (12964, 596, 1), + (12965, 597, 1), + (12968, 1041, 1), + (12969, 1041, 1), + (12970, 1041, 1), + (12977, 1041, 1), + (12978, 1041, 1), + (12979, 1041, 1), + (12980, 1041, 1), + (12981, 1041, 1), + (12992, 707, 4), + (12993, 707, 4), + (12994, 707, 4), + (13001, 9504, 1), + (13002, 9504, 1), + (13003, 9504, 1), + (13004, 153, 9), + (13005, 171, 1), + (13006, 171, 1), + (13007, 171, 1), + (13008, 859, 1), + (13009, 3730, 1), + (13010, 47, 1), + (13011, 47, 1), + (13012, 47, 1), + (13013, 446, 1), + (13014, 446, 1), + (13015, 446, 1), + (13017, 3815, 10), + (13018, 3815, 10), + (13019, 3815, 10), + (13023, 309, 6), + (13055, 8400, 1), + (13067, 643, 1), + (13072, 3514, 1), + (13073, 3514, 1), + (13074, 310, 6), + (13075, 310, 6), + (13076, 310, 6), + (13077, 311, 3), + (13078, 311, 3), + (13090, 20, 1), + (13092, 82, 1), + (13093, 82, 1), + (13094, 82, 1), + (13104, 87, 1), + (13105, 87, 1), + (13106, 87, 1), + (13130, 1685, 1), + (13140, 391, 9), + (13141, 391, 9), + (13142, 391, 9), + (13143, 500, 1), + (13144, 500, 1), + (13145, 500, 1), + (13146, 494, 1), + (13147, 494, 1), + (13148, 494, 1), + (13155, 705, 1), + (13166, 822, 1), + (13167, 822, 1), + (13168, 822, 1), + (13170, 128, 3), + (13190, 187, 5), + (13191, 187, 5), + (13192, 187, 5), + (13196, 3837, 3), + (13197, 3837, 3), + (13198, 3837, 3), + (13203, 199, 3), + (13204, 8261, 1), + (13205, 8261, 1), + (13206, 8261, 1), + (13213, 439, 3), + (13214, 439, 3), + (13215, 439, 3), + (13216, 439, 3), + (13217, 439, 3), + (13222, 3514, 1), + (13223, 3514, 1), + (13241, 173, 8), + (13244, 46, 1), + (13247, 409, 3), + (13253, 58, 1), + (13254, 58, 1), + (13255, 58, 1), + (13256, 224, 3), + (13257, 224, 3), + (13258, 224, 3), + (13262, 102, 1), + (13263, 102, 1), + (13264, 102, 1), + (13271, 1685, 1), + (13272, 1685, 1), + (13295, 20, 1), + (13308, 26, 3), + (13326, 310, 6), + (13326, 1685, 1), + (13332, 30, 6), + (13363, 1685, 1), + (13383, 1685, 1), + (13385, 1685, 1), + (13388, 1685, 1), + (13389, 1685, 1), + (13396, 1685, 1), + (13396, 3815, 10), + (13401, 1685, 1), + (13404, 259, 6), + (13404, 1685, 1), + (13410, 1685, 1), + (13413, 1685, 1), + (13415, 1092, 1), + (13415, 1685, 1), + (13416, 626, 1), + (13416, 1685, 1), + (13419, 1685, 1), + (13425, 1685, 1), + (13444, 1685, 1), + (13447, 1685, 1), + (13449, 1685, 1), + (13449, 11073, 1), + (13454, 1685, 1), + (13463, 458, 1), + (13463, 1685, 1), + (13466, 1685, 1), + (13467, 1685, 1), + (13468, 1685, 1), + (13472, 1685, 1), + (13474, 444, 1), + (13474, 1685, 1), + (13477, 1685, 1), + (13483, 1685, 1), + (13484, 1685, 1), + (13485, 1685, 1), + (13490, 1685, 1), + (13492, 199, 3), + (13492, 1685, 1), + (13493, 1685, 1), + (13496, 187, 5), + (13496, 1685, 1), + (13499, 30, 1), + (13499, 1685, 1), + (13502, 259, 3), + (13502, 1685, 1), + (13505, 1685, 1), + (13508, 1685, 1), + (13511, 1685, 1), + (13511, 3837, 3), + (13514, 1685, 1), + (13517, 941, 1), + (13517, 1685, 1), + (13520, 1685, 1), + (13521, 1685, 1), + (13524, 1685, 1), + (13527, 1685, 1), + (13528, 1685, 1), + (13529, 1685, 1), + (13530, 1685, 1), + (13533, 1685, 1), + (13542, 184, 3), + (13542, 1685, 1), + (13545, 1685, 1), + (13546, 1685, 1), + (13549, 1685, 1), + (13556, 1685, 1), + (13562, 872, 1), + (13562, 1685, 1), + (13565, 1685, 1), + (13565, 3804, 1), + (13568, 876, 1), + (13568, 1685, 1), + (13571, 1685, 1), + (13575, 1685, 1), + (13578, 1685, 1), + (13584, 1685, 1), + (13585, 1685, 1), + (13585, 3826, 1), + (13586, 1685, 1), + (13589, 30, 3), + (13589, 1685, 1), + (13590, 30, 3), + (13590, 1685, 1), + (13592, 702, 1), + (13592, 1685, 1), + (13595, 1685, 1), + (13595, 6001, 11), + (13598, 1685, 1), + (13601, 1685, 1), + (13604, 1685, 1), + (13607, 1685, 1), + (13610, 1685, 1), + (13613, 1685, 1), + (13616, 1685, 1), + (13617, 1685, 1), + (13618, 1685, 1), + (13619, 1685, 1), + (13621, 278, 5), + (13621, 1685, 1), + (13624, 1685, 1), + (13627, 1685, 1), + (13628, 1685, 1), + (13630, 1685, 1), + (13633, 1685, 1), + (13646, 1668, 1), + (13646, 1685, 1), + (13650, 1685, 1), + (13653, 1685, 1), + (13656, 1685, 1), + (13663, 1685, 1), + (13667, 500, 1), + (13667, 1685, 1), + (13670, 1685, 1), + (13673, 1158, 1), + (13674, 7754, 1), + (13675, 278, 5), + (13675, 1685, 1), + (13678, 1685, 1), + (13682, 1685, 1), + (13683, 1685, 1), + (13684, 1685, 1), + (13685, 1685, 1), + (13686, 1685, 1), + (13687, 1685, 1), + (13688, 1685, 1), + (13689, 751, 1), + (13689, 1685, 1), + (13692, 1685, 1), + (13693, 1685, 1), + (13695, 1685, 1), + (13698, 784, 1), + (13698, 1685, 1), + (13701, 785, 1), + (13701, 1685, 1), + (13704, 787, 1), + (13704, 1685, 1), + (13707, 58, 1), + (13707, 1685, 1), + (13710, 1685, 1), + (13713, 1685, 1), + (13718, 1685, 1), + (13720, 1685, 1), + (13723, 58, 1), + (13723, 1685, 1), + (13726, 1685, 1), + (13727, 25, 3), + (13727, 1685, 1), + (13734, 217, 1), + (13734, 1685, 1), + (13753, 534, 1), + (13753, 1685, 1), + (13758, 602, 1), + (13758, 1685, 1), + (13763, 1685, 1), + (13764, 535, 1), + (13764, 1685, 1), + (13767, 1685, 1), + (13770, 1685, 1), + (13771, 1685, 1), + (13773, 310, 3), + (13773, 1685, 1), + (13774, 310, 3), + (13774, 1685, 1), + (13775, 310, 3), + (13775, 1685, 1), + (13779, 1685, 1), + (13782, 439, 3), + (13782, 1685, 1), + (13785, 1685, 1), + (13789, 1685, 1), + (13790, 1685, 1), + (13792, 1685, 1), + (13795, 1685, 1), + (13798, 1685, 1), + (13804, 1685, 1), + (13807, 1685, 1), + (13810, 1685, 1), + (13813, 1685, 1), + (13816, 1685, 1), + (13819, 1685, 1), + (13820, 1685, 1), + (13823, 1685, 1), + (13826, 1685, 1), + (13829, 1685, 1), + (13832, 1685, 1), + (13835, 1685, 1), + (13838, 1685, 1), + (13841, 1685, 1), + (13845, 1685, 1), + (13872, 1685, 1), + (13873, 961, 1), + (13873, 1685, 1), + (13878, 609, 1), + (13878, 1685, 1), + (13881, 387, 1), + (13881, 1685, 1), + (13889, 1012, 1), + (13889, 1685, 1), + (13899, 1685, 1), + (13905, 1685, 1), + (13908, 1685, 1), + (13911, 1685, 1), + (13914, 1685, 1), + (13917, 606, 1), + (13917, 1685, 1), + (13920, 125, 1), + (13920, 1685, 1), + (13933, 142, 20), + (13943, 142, 20), + (13953, 142, 20), + (13963, 142, 20), + (13973, 142, 20), + (13983, 142, 20), + (13993, 142, 20), + (14003, 1685, 1), + (14006, 30, 6), + (14006, 1685, 1), + (14009, 1685, 1), + (14010, 1685, 1), + (14011, 1685, 1), + (14011, 10394, 1), + (14016, 1685, 1), + (14016, 6001, 17), + (14018, 1684, 1), + (14019, 1685, 1), + (14026, 1685, 1), + (14029, 1685, 1), + (14032, 1685, 1), + (14037, 804, 1), + (14037, 1685, 1), + (14040, 300, 1), + (14040, 1685, 1), + (14043, 1685, 1), + (14046, 87, 1), + (14046, 1685, 1), + (14051, 1685, 1), + (14052, 1685, 1), + (14053, 1685, 1), + (14054, 1685, 1), + (14055, 1685, 1), + (14056, 1685, 1), + (14059, 1685, 1), + (14062, 821, 1), + (14062, 1685, 1), + (14065, 1685, 1), + (14065, 3215, 1), + (14068, 1685, 1), + (14068, 3216, 1), + (14071, 1685, 1), + (14076, 1685, 1), + (14080, 1685, 1), + (14081, 1685, 1), + (14082, 1685, 1), + (14085, 741, 1), + (14085, 1685, 1), + (14088, 769, 1), + (14088, 1685, 1), + (14091, 701, 1), + (14091, 1685, 1), + (14094, 1685, 1), + (14097, 1685, 1), + (14100, 1685, 1), + (14101, 1685, 1), + (14111, 1685, 1), + (14112, 1685, 1), + (14115, 872, 1), + (14115, 1685, 1), + (14129, 1685, 1), + (14130, 1685, 1), + (14132, 1685, 1), + (14132, 2234, 1), + (14135, 1685, 1), + (14138, 1685, 1), + (14139, 1685, 1), + (14140, 1685, 1), + (14141, 1685, 1), + (14144, 1685, 1), + (14144, 3515, 1), + (14148, 1685, 1), + (14151, 1685, 1), + (14154, 276, 3), + (14154, 1685, 1), + (14157, 1685, 1), + (14160, 1685, 1), + (14160, 7001, 1), + (14163, 1685, 1), + (14163, 7001, 1), + (14166, 945, 1), + (14166, 1685, 1), + (14169, 1685, 1), + (14173, 1685, 1), + (14176, 1685, 1), + (14176, 8261, 1), + (14179, 359, 1), + (14179, 1685, 1), + (14180, 1685, 1), + (14181, 1685, 1), + (14181, 3837, 12), + (14186, 809, 5), + (14186, 1685, 1), + (14189, 1685, 1), + (14192, 1685, 1), + (14196, 465, 3), + (14196, 1685, 1), + (14199, 499, 1), + (14199, 1685, 1), + (14200, 1685, 1), + (14203, 1685, 1), + (14206, 1685, 1), + (14207, 1685, 1), + (14208, 1685, 1), + (14208, 7689, 1), + (14209, 1685, 1), + (14210, 1685, 1), + (14213, 1065, 1), + (14213, 1685, 1), + (14218, 1685, 1), + (14221, 1685, 1), + (14222, 224, 3), + (14222, 1685, 1), + (14223, 47, 1), + (14223, 1685, 1), + (14224, 1685, 1), + (14225, 177, 1), + (14225, 1685, 1), + (14229, 135, 1), + (14231, 1685, 1), + (14232, 1685, 1), + (14233, 1685, 1), + (14234, 1685, 1), + (14237, 1685, 1), + (14238, 1041, 1), + (14238, 1685, 1), + (14241, 386, 1), + (14241, 1685, 1), + (14244, 1685, 1), + (14249, 1685, 1), + (14254, 386, 1), + (14254, 1685, 1), + (14256, 1685, 1), + (14259, 384, 1), + (14259, 1685, 1), + (14265, 939, 1), + (14265, 1685, 1), + (14272, 1685, 1), + (14273, 1685, 1), + (14274, 1685, 1), + (14275, 1685, 1), + (14278, 985, 1), + (14278, 1685, 1), + (14280, 57, 1), + (14280, 1685, 1), + (14281, 291, 1), + (14281, 1685, 1), + (14282, 1685, 1), + (14282, 3812, 1), + (14283, 1685, 1), + (14286, 753, 1), + (14286, 1685, 1), + (14289, 1685, 1), + (14292, 207, 1), + (14292, 1685, 1), + (14295, 1685, 1), + (14295, 3816, 1), + (14304, 1685, 1), + (14304, 8341, 1), + (14307, 1685, 1), + (14308, 431, 1), + (14308, 1685, 1), + (14311, 430, 1), + (14311, 1685, 1), + (14314, 901, 1), + (14314, 1685, 1), + (14318, 1685, 1), + (14318, 7703, 1), + (14321, 1685, 1), + (14322, 1685, 1), + (14323, 1685, 1), + (14324, 1685, 1), + (14328, 1154, 1), + (14328, 1685, 1), + (14331, 515, 1), + (14331, 1685, 1), + (14338, 308, 3), + (14338, 1685, 1), + (14341, 748, 1), + (14341, 1685, 1), + (14346, 1685, 1), + (14349, 215, 6), + (14352, 175, 3), + (14352, 1685, 1), + (14355, 1685, 1), + (14358, 1685, 1), + (14359, 1685, 1), + (14360, 1685, 1), + (14361, 23, 3), + (14364, 173, 1), + (14364, 1685, 1), + (14372, 1685, 1), + (14690, 756, 1), + (14733, 786, 1), + (15100, 467, 1), + (15105, 131, 1), + (15113, 130, 1), + (15120, 800, 1), + (15132, 660, 1), + (15135, 660, 1), + (15141, 30, 3), + (15147, 701, 13), + (15154, 659, 1), + (15158, 657, 1), + (15159, 770, 1), + (15162, 659, 1), + (15168, 657, 1), + (15174, 9400, 1), + (15179, 7755, 1), + (15182, 9403, 1), + (15204, 390, 1), + (15207, 323, 1), + (15210, 1041, 1), + (15220, 622, 1), + (15223, 624, 1), + (15226, 621, 1), + (15229, 623, 1), + (15253, 462, 1), + (15258, 184, 1), + (15270, 7003, 1), + (15280, 778, 1), + (15295, 2234, 1), + (15314, 36, 1), + (15317, 35, 1), + (15320, 558, 1), + (15341, 19, 3), + (15342, 8500, 1), + (15344, 38, 1), + (15348, 9504, 1), + (15356, 149, 1), + (15358, 151, 1), + (15359, 50, 1), + (15363, 447, 3), + (15371, 3729, 1), + (15377, 638, 1), + (15389, 935, 1), + (15396, 23, 3), + (15397, 494, 3), + (15403, 8604, 1), + (15406, 3817, 1), + (15414, 241, 1), + (15421, 245, 3), + (15424, 247, 1), + (15424, 982, 6), + (15466, 3551, 1), + (15469, 1120, 1), + (15472, 521, 1), + (15478, 578, 1), + (15481, 398, 24), + (15482, 261, 1), + (15485, 495, 9), + (15486, 534, 3), + (15526, 3702, 1), + (15549, 244, 1), + (15552, 3710, 1), + (15571, 351, 1), + (15579, 826, 1), + (15591, 2899, 1), + (15598, 759, 1), + (15598, 1150, 1), + (15598, 1151, 1), + (15598, 1152, 1), + (15605, 639, 1), + (15606, 160, 4), + (15622, 23, 3), + (15632, 789, 1), + (15639, 749, 1), + (15640, 822, 2), + (15746, 804, 1), + (15778, 87, 1), + (15833, 2045, 1), + (15836, 463, 1), + (15839, 19, 9), + (15855, 153, 9), + (15891, 988, 1), + (15893, 987, 1), + (15895, 986, 1), + (15961, 3701, 1), + (16062, 263, 1), + (16071, 2209, 3), + (16087, 53, 1), + (16094, 43, 1), + (16103, 7703, 1), + (16105, 684, 1), + (16106, 684, 1), + (16107, 684, 1), + (16117, 309, 6), + (16124, 3711, 1), + (16128, 3711, 1), + (16131, 73, 1), + (16137, 10394, 1), + (16140, 489, 1), + (16156, 137, 1), + (16159, 2045, 1), + (16163, 260, 1), + (16163, 7747, 1), + (16164, 358, 3), + (16176, 337, 1), + (16180, 584, 1), + (16185, 9202, 1), + (16185, 9203, 1), + (16189, 823, 3), + (16203, 403, 1), + (16211, 152, 1), + (16218, 403, 1), + (16221, 393, 1), + (16225, 219, 1), + (16238, 443, 1), + (16246, 245, 3), + (16249, 17, 3), + (16257, 470, 20), + (16266, 790, 1), + (16287, 669, 1), + (16297, 553, 1), + (16300, 668, 1), + (16303, 3506, 1), + (16306, 777, 1), + (16336, 1257, 1), + (16339, 773, 1), + (16342, 1257, 1), + (16371, 60, 1), + (16380, 2061, 1), + (16386, 2064, 1), + (16392, 2202, 1), + (16489, 23, 3), + (16604, 180, 3), + (16644, 747, 1), + (16666, 742, 1), + (16730, 82, 3), + (16745, 706, 1), + (17206, 601, 1), + (17209, 111, 1), + (17212, 10367, 1), + (17218, 744, 1), + (17235, 3826, 1), + (17280, 8205, 1), + (17281, 359, 1), + (17288, 41, 1), + (17289, 1062, 1), + (17307, 2047, 1), + (17317, 1270, 1), + (17334, 1041, 1), + (17336, 148, 1), + (17339, 760, 1), + (17342, 148, 1), + (17350, 170, 3), + (17361, 405, 1), + (17361, 426, 1), + (17364, 935, 4), + (17375, 1239, 1), + (17391, 98, 1), + (17409, 120, 1), + (17414, 673, 1), + (17436, 372, 1), + (17439, 372, 1), + (17441, 309, 3), + (17476, 462, 3), + (17492, 840, 1), + (17495, 9702, 1), + (17515, 3841, 1), + (17517, 441, 1), + (17522, 764, 1), + (17533, 677, 1), + (17549, 8700, 1); + +DROP TABLE IF EXISTS `character_alternate_abilities`; +CREATE TABLE IF NOT EXISTS `character_alternate_abilities` ( + `id` int(11) unsigned NOT NULL DEFAULT '0', + `aa_id` smallint(11) unsigned NOT NULL DEFAULT '0', + `aa_value` smallint(11) unsigned NOT NULL DEFAULT '0', + `charges` smallint(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`,`aa_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; From 25c6ddd6318f77672341f5670e7896dea518ebd7 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 2 Jul 2015 20:07:09 -0700 Subject: [PATCH 230/846] Scary final SQL stuff for aa branch --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../sql/git/required/2015_07_02_aa_rework.sql | 20 +++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index 1813f77c3..00f74e801 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 9083 +#define CURRENT_BINARY_DATABASE_VERSION 9084 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index e7aa46221..1a67e2893 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -337,6 +337,7 @@ 9081|2015_05_23_dbstr_us.sql|SHOW TABLES LIKE 'db_str'|empty| 9082|2015_05_25_npc_types_texture_fields.sql|SHOW COLUMNS FROM `npc_types` LIKE 'armtexture'|empty| 9083|2015_06_07_aa_update.sql|SHOW COLUMNS FROM `character_alternate_abilities` LIKE 'charges'|empty| +9084|2015_07_92_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|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/2015_07_02_aa_rework.sql b/utils/sql/git/required/2015_07_02_aa_rework.sql index 41a67f7c0..8a585113c 100644 --- a/utils/sql/git/required/2015_07_02_aa_rework.sql +++ b/utils/sql/git/required/2015_07_02_aa_rework.sql @@ -20649,6 +20649,7 @@ INSERT INTO `aa_rank_prereqs` (`rank_id`, `aa_id`, `points`) VALUES (17533, 677, 1), (17549, 8700, 1); +RENAME TABLE `character_alternate_abilities` TO `character_alternate_abilities_old`; DROP TABLE IF EXISTS `character_alternate_abilities`; CREATE TABLE IF NOT EXISTS `character_alternate_abilities` ( `id` int(11) unsigned NOT NULL DEFAULT '0', @@ -20657,3 +20658,22 @@ CREATE TABLE IF NOT EXISTS `character_alternate_abilities` ( `charges` smallint(11) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`,`aa_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +ALTER TABLE `character_data` ADD COLUMN `aa_points_spent_old` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `aa_points_spent`; +ALTER TABLE `character_data` ADD COLUMN `aa_points_old` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `aa_points`; + +UPDATE `character_data` SET `aa_points_spent_old` = `aa_points_spent`, `aa_points_old` = `aa_points`; + + -- sanity checks since if someone never logged in after the db conversion there is junk data + -- I don't have a good way of addressing this so I keep the old data in aa_points_spent_old and aa_points_old and character_alternate_abilities_old + -- for anyone who wants to personally polish up their player data +UPDATE `character_data` SET `aa_points_spent` = 2700 WHERE `aa_points_spent` > 2700; +UPDATE `character_data` SET `aa_points` = 5000 WHERE `aa_points` > 5000; + + -- another sanity check, give people a few levels below 51 to keep their points +UPDATE `character_data` SET `aa_points_spent` = 0 WHERE `level` < 48; +UPDATE `character_data` SET `aa_points` = 0 WHERE `level` < 48; + + -- aa refund here +UPDATE `character_data` SET `aa_points` = `aa_points_spent` + `aa_points`; +UPDATE `character_data` SET `aa_points_spent` = 0; From 233b096c17aee4fe521a5898f407b8f2f2a7add2 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 2 Jul 2015 20:10:26 -0700 Subject: [PATCH 231/846] 0 != 9 and i suck at manifests cause of that fact --- utils/sql/db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 1a67e2893..08b3994fa 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -337,7 +337,7 @@ 9081|2015_05_23_dbstr_us.sql|SHOW TABLES LIKE 'db_str'|empty| 9082|2015_05_25_npc_types_texture_fields.sql|SHOW COLUMNS FROM `npc_types` LIKE 'armtexture'|empty| 9083|2015_06_07_aa_update.sql|SHOW COLUMNS FROM `character_alternate_abilities` LIKE 'charges'|empty| -9084|2015_07_92_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty| +9084|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 81e827481b2c3fc4d919fd8de488a76bcdf07ad0 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 2 Jul 2015 20:18:08 -0700 Subject: [PATCH 232/846] Final touch up on this, changelog + fix for sql classes default being left shifted 1. --- changelog.txt | 6 ++++++ utils/sql/git/required/2015_07_02_aa_rework.sql | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index eaaa6fb7a..3c31c83e5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 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. + == 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 Akkadius: Added a custom Health Update message that will display in the middle of the players screen, to enable this server wide you must enable rule 'Character:MarqueeHPUpdates' diff --git a/utils/sql/git/required/2015_07_02_aa_rework.sql b/utils/sql/git/required/2015_07_02_aa_rework.sql index 8a585113c..77dde6b86 100644 --- a/utils/sql/git/required/2015_07_02_aa_rework.sql +++ b/utils/sql/git/required/2015_07_02_aa_rework.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS `aa_ability` ( `id` int(10) unsigned NOT NULL, `name` text NOT NULL, `category` int(10) NOT NULL DEFAULT '-1', - `classes` int(10) NOT NULL DEFAULT '131070', + `classes` int(10) NOT NULL DEFAULT '65535', `races` int(10) NOT NULL DEFAULT '65535', `drakkin_heritage` int(10) NOT NULL DEFAULT '127', `deities` int(10) NOT NULL DEFAULT '131071', From 803fa48c053b6cb6b81c14b2b69eb735f1a63cf7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 3 Jul 2015 02:17:14 -0400 Subject: [PATCH 233/846] Fix AA class check --- zone/aa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index db765e813..9794aea77 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -839,7 +839,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { return; } - if(!(ability->classes & (1 << GetClass()))) { + if(!(ability->classes & (1 << (GetClass() - 1)))) { return; } @@ -1400,7 +1400,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { if(!ability) return false; - if(!ability->classes & (1 << GetClass())) { + if(!(ability->classes & (1 << (GetClass() - 1)))) { return false; } From 927a88cf96931a2d0d087ea1ad4a28d030ceaeb0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 3 Jul 2015 02:31:12 -0400 Subject: [PATCH 234/846] Really fix class AA check --- zone/aa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 9794aea77..d1dad4f40 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -839,7 +839,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { return; } - if(!(ability->classes & (1 << (GetClass() - 1)))) { + if(!(ability->classes & (1 << GetClass()))) { return; } @@ -1400,7 +1400,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { if(!ability) return false; - if(!(ability->classes & (1 << (GetClass() - 1)))) { + if(!(ability->classes & (1 << GetClass()))) { return false; } From 59e40b3fbe76f6ca1c8453eeb7e7a9d14ad08b96 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 3 Jul 2015 14:57:48 -0400 Subject: [PATCH 235/846] Files changed: command.cpp, questmgr.cpp - Added command aliases: #findzone -> #fz, #reloadquest -> #rq - Added instance ID to $client->GoToSafeCoords() in quest::safemove(); --- zone/command.cpp | 2 ++ zone/questmgr.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index 24c343dd0..ac419043f 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -218,6 +218,7 @@ int command_init(void) { command_add("flymode", "[0/1/2] - Set your or your player target's flymode to off/on/levitate", 50, command_flymode) || command_add("fov", "- Check wether you're behind or in your target's field of view", 80, command_fov) || command_add("freeze", "- Freeze your target", 80, command_freeze) || + command_add("fz", nullptr, 10, command_findzone) || command_add("gassign", "[id] - Assign targetted NPC to predefined wandering grid id", 100, command_gassign) || command_add("gender", "[0/1/2] - Change your or your target's gender to male/female/neuter", 50, command_gender) || command_add("getplayerburriedcorpsecount", "- Get the target's total number of burried player corpses.", 100, command_getplayerburriedcorpsecount) || @@ -336,6 +337,7 @@ int command_init(void) { command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", 200, command_resetaa) || command_add("resetaa_timer", "Command to reset AA cooldown timers.", 200, command_resetaa_timer) || command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) || + command_add("rq", nullptr, 150, command_reloadqst) || command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) || command_add("save", "- Force your player or player corpse target to be saved to the database", 50, command_save) || command_add("scribespell", "[spellid] - Scribe specified spell in your target's spell book.", 180, command_scribespell) || diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 67a1f06da..71f0de917 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -874,7 +874,7 @@ bool QuestManager::isdisctome(int item_id) { void QuestManager::safemove() { QuestManagerCurrentQuestVars(); if (initiator && initiator->IsClient()) - initiator->GoToSafeCoords(zone->GetZoneID(), 0); + initiator->GoToSafeCoords(zone->GetZoneID(), zone->GetInstanceID()); } void QuestManager::rain(int weather) { From 037265161301787f6e1a2d0bd88e7eef818080f5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 3 Jul 2015 17:42:31 -0400 Subject: [PATCH 236/846] Fix Bot::LoadAA --- zone/bot.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index 9dae2fc6a..912997a88 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1271,6 +1271,7 @@ void Bot::LoadAAs() { //skip expendables if(!ability->first || ability->charges > 0) { + ++iter; continue; } From 80c2d9d68db38192a75c311fe96e62c9d6145ee3 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Fri, 3 Jul 2015 15:44:31 -0700 Subject: [PATCH 237/846] Set a deity for bots so they can LoadAA --- zone/bot.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index 912997a88..5450d4f8a 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -694,6 +694,7 @@ void Bot::GenerateBaseStats() { this->pAggroRange = 0; this->pAssistRange = 0; this->raid_target = false; + this->deity = 396; } void Bot::GenerateAppearance() { From 49e9c9ee345556ca46b6fe429c2d9de5d49b7853 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 4 Jul 2015 02:13:26 -0400 Subject: [PATCH 238/846] Reworked activated avoidance skills based on dev quotes --- changelog.txt | 5 + zone/attack.cpp | 368 ++++++++++++++++++--------------------- zone/bot.cpp | 263 ++++++---------------------- zone/bot.h | 3 +- zone/mob.h | 2 +- zone/special_attacks.cpp | 58 +++--- 6 files changed, 258 insertions(+), 441 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3c31c83e5..f3fdc3ba0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 7/4/2015 == +mackal: Reworked the activated avoidace skills (riposte, dodge, etc) based on dev quotes + This also fixes the order things are checked (avoidance skills, THEN hit/miss) + 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. diff --git a/zone/attack.cpp b/zone/attack.cpp index c493b159f..8a120b896 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -341,7 +341,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c return(tohit_roll <= chancetohit); } -bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) +bool Mob::AvoidDamage(Mob *other, int32 &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. @@ -353,22 +353,32 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) * -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->aabonuses.MeleeSkillCheck + attacker->spellbonuses.MeleeSkillCheck + attacker->itembonuses.MeleeSkillCheck) > 500) - ghit = true; + /* Order according to current (SoF+?) dev quotes: + * https://forums.daybreakgames.com/eq/index.php?threads/test-update-06-10-15.223510/page-2#post-3261772 + * https://forums.daybreakgames.com/eq/index.php?threads/test-update-06-10-15.223510/page-2#post-3268227 + * Riposte 50, hDEX, must have weapon/fists, doesn't work on archery/throwing + * Block 25, hDEX, works on archery/throwing, behind block done here if back to attacker base1 is chance + * Parry 45, hDEX, doesn't work on throwing/archery, must be facing target + * Dodge 45, hAGI, works on archery/throwing, monks can dodge attacks from behind + * Shield Block, rand base1 + * Staff Block, rand base1 + * regular strike through + * avoiding the attack (CheckHitChance) + * As soon as one succeeds, none of the rest are checked + * + * Formula (all int math) + * (posted for parry, assume rest at the same) + * Chance = (((SKILL + 100) + [((SKILL+100) * SPA(175).Base1) / 100]) / 45) + [(hDex / 25) - min([hDex / 25], hStrikethrough)]. + * hStrikethrough is a mob stat that was added to counter the bonuses of heroic stats + * Number rolled against 100, if the chance is greater than 100 it happens 100% of time + * + * Things with 10k accuracy mods can be avoided with these skills qq + */ + Mob *attacker = other; + Mob *defender = this; - bool InFront = false; - - if (attacker->InFrontMob(this, attacker->GetX(), attacker->GetY())) - InFront = true; + bool InFront = attacker->InFrontMob(this, attacker->GetX(), attacker->GetY()); /* This special ability adds a negative modifer to the defenders riposte/block/parry/chance @@ -383,10 +393,9 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) int counter_parry = 0; int counter_dodge = 0; - if (attacker->GetSpecialAbility(COUNTER_AVOID_DAMAGE)){ - + if (attacker->GetSpecialAbility(COUNTER_AVOID_DAMAGE)) { counter_all = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 0); - counter_riposte = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE,1); + counter_riposte = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 1); counter_block = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 2); counter_parry = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 3); counter_dodge = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 4); @@ -400,31 +409,37 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); } - ///////////////////////////////////////////////////////// - // riposte - ///////////////////////////////////////////////////////// - float riposte_chance = 0.0f; - if (CanRiposte && damage > 0 && CanThisClassRiposte() && InFront) - { - riposte_chance = (100.0f + static_cast(aabonuses.RiposteChance + spellbonuses.RiposteChance + - itembonuses.RiposteChance - counter_riposte - counter_all)) / 100.0f; - skill = GetSkill(SkillRiposte); - if (IsClient()) { + // 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 (IsClient()) CastToClient()->CheckIncreaseSkill(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; } - - 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 + int chance = GetSkill(SkillRiposte) + 100; + chance += (chance * (aabonuses.RiposteChance + spellbonuses.RiposteChance + itembonuses.RiposteChance)) / 100; + chance /= 50; + chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter + if (counter_riposte || counter_all) { + float counter = (counter_riposte + counter_all) / 100.0f; + chance -= chance * counter; + } + // AA Slippery Attacks + if (hand == MainSecondary) { + 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; + return true; } } - /////////////////////////////////////////////////////// // block - /////////////////////////////////////////////////////// - bool bBlockFromRear = false; // a successful roll on this does not mean a successful block is forthcoming. only that a chance to block @@ -435,101 +450,100 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if (BlockBehindChance && zone->random.Roll(BlockBehindChance)) bBlockFromRear = true; - float block_chance = 0.0f; - if (damage > 0 && CanThisClassBlock() && (InFront || bBlockFromRear)) { - block_chance = (100.0f + static_cast(aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance + - itembonuses.IncreaseBlockChance - counter_block - counter_all)) / 100.0f; - skill = CastToClient()->GetSkill(SkillBlock); - if (IsClient()) { + if (CanThisClassBlock() && (InFront || bBlockFromRear)) { + 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]; - } - - //Try Shield Block OR TwoHandBluntBlockCheck - if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (InFront || bBlockFromRear)) - RollTable[1] += static_cast(aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock - counter_block - counter_all); - - else if(damage > 0 && HasTwoHandBluntEquiped() && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) && (InFront || bBlockFromRear)) - RollTable[1] += static_cast(aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock - counter_block - counter_all); - - ////////////////////////////////////////////////////// - // parry - ////////////////////////////////////////////////////// - float parry_chance = 0.0f; - if (damage > 0 && CanThisClassParry() && InFront){ - parry_chance = (100.0f + static_cast(aabonuses.ParryChance + itembonuses.ParryChance + - itembonuses.ParryChance - counter_parry - counter_all)) / 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() && InFront){ - - dodge_chance = (100.0f + static_cast(aabonuses.DodgeChance + spellbonuses.DodgeChance + - itembonuses.DodgeChance - counter_dodge - counter_all)) / 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 = zone->random.Real(0,100); - if(roll <= RollTable[0]){ - damage = -3; - } - else if(roll <= RollTable[1]){ + // check auto discs ... I guess aa/items too :P + if (spellbonuses.IncreaseBlockChance == 10000 || aabonuses.IncreaseBlockChance == 10000 || + itembonuses.IncreaseBlockChance == 10000) { damage = -1; + return true; } - else if(roll <= RollTable[2]){ - damage = -2; + int chance = GetSkill(SkillBlock) + 100; + chance += (chance * (aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance + itembonuses.IncreaseBlockChance)) / 100; + chance /= 25; + chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter + if (counter_block || counter_all) { + float counter = (counter_block + counter_all) / 100.0f; + chance -= chance * counter; } - else if(roll <= RollTable[3]){ - damage = -4; + if (zone->random.Roll(chance)) { + damage = -1; + return true; } } - Log.Out(Logs::Detail, Logs::Combat, "Final damage after all avoidances: %d", damage); + // parry + if (CanThisClassParry() && InFront && hand != MainRange) { + if (IsClient()) + CastToClient()->CheckIncreaseSkill(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; + chance += (chance * (aabonuses.ParryChance + spellbonuses.ParryChance + itembonuses.ParryChance)) / 100; + chance /= 45; + chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter + if (counter_parry || counter_all) { + float counter = (counter_parry + counter_all) / 100.0f; + chance -= chance * counter; + } + if (zone->random.Roll(chance)) { + damage = -2; + return true; + } + } + + // dodge + if (CanThisClassDodge() && (InFront || GetClass() == MONK) ) { + if (IsClient()) + CastToClient()->CheckIncreaseSkill(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; + chance += (chance * (aabonuses.DodgeChance + spellbonuses.DodgeChance + itembonuses.DodgeChance)) / 100; + chance /= 45; + chance += itembonuses.HeroicAGI / 25; // live has "heroic strickthrough" here to counter + if (counter_dodge || counter_all) { + float counter = (counter_dodge + counter_all) / 100.0f; + chance -= chance * counter; + } + if (zone->random.Roll(chance)) { + damage = -4; + return true; + } + } + + // Try Shield Block OR TwoHandBluntBlockCheck + if (HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (InFront || bBlockFromRear)) { + int chance = aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock; + if (counter_block || counter_all) { + float counter = (counter_block + counter_all) / 100.0f; + chance -= chance * counter; + } + if (zone->random.Roll(chance)) { + damage = -1; + return true; + } + } + + if (HasTwoHandBluntEquiped() && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) && (InFront || bBlockFromRear)) { + int chance = aabonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock; + if (counter_block || counter_all) { + float counter = (counter_block + counter_all) / 100.0f; + chance -= chance * counter; + } + if (zone->random.Roll(chance)) { + damage = -1; + return true; + } + } - if (damage < 0) - return true; return false; } @@ -1286,6 +1300,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b } } + // this effect is actually a min cap that happens after the final damage is calculated min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; if(max_hit < min_hit) @@ -1312,62 +1327,41 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b } //check to see if we hit.. - if(!other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) { - Log.Out(Logs::Detail, Logs::Combat, "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) - CommonOutgoingHitSuccess(other, damage, skillinuse); - - Log.Out(Logs::Detail, Logs::Combat, "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 == MainSecondary) {// 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. - int32 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; - OffhandRiposteFail *= -1; //Live uses a negative value for this. - - if (OffhandRiposteFail && - (OffhandRiposteFail > 99 || zone->random.Roll(OffhandRiposteFail))) { - damage = 0; // Counts as a miss - slippery_attack = true; - } else - DoRiposte(other); - if (IsDead()) return false; + 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; } - else + // I'm pretty sure you can riposte a riposte + if (damage == -3 && !bRiposte) { DoRiposte(other); - if (IsDead()) return false; + if (IsDead()) + return false; + } + } + Log.Out(Logs::Detail, Logs::Combat, "Avoided damage with code %d", damage); + } else { + if (other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) { + other->MeleeMitigation(this, damage, min_hit, opts); + if (damage > 0) + CommonOutgoingHitSuccess(other, damage, skillinuse); + 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; } } - - if (((damage < 0) || slippery_attack) && !bRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA - int32 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; - - if(bonusStrikeThrough && zone->random.Roll(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{ + } 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); + other->AddToHateList(this, hate); /////////////////////////////////////////////////////////// ////// Send Attack Damage @@ -1912,21 +1906,18 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool hit_chance_bonus += opts->hit_chance; } - if(!other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) { - damage = 0; //miss - } else { //hit, check for damage avoidance - other->AvoidDamage(this, damage); - other->MeleeMitigation(this, damage, min_dmg+eleBane, opts); - if(damage > 0) { + if (other->AvoidDamage(this, damage, Hand)) { + if (!bRiposte && damage == -3) + DoRiposte(other); + } else { + if (other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) { + other->MeleeMitigation(this, damage, min_dmg+eleBane, opts); CommonOutgoingHitSuccess(other, damage, skillinuse); + } else { + damage = 0; } - Log.Out(Logs::Detail, Logs::Combat, "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); } + other->AddToHateList(this, hate); } Log.Out(Logs::Detail, Logs::Combat, "Final damage against %s: %d", other->GetName(), damage); @@ -1939,12 +1930,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool else damage = -5; - //cant riposte a riposte - if (bRiposte && damage == -3) { - Log.Out(Logs::Detail, Logs::Combat, "Riposte of riposte canceled."); - return false; - } - if(GetHP() > 0 && !other->HasDied()) { other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, false); // Not avoidable client already had thier chance to Avoid } else @@ -1974,11 +1959,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool if(GetHP() > 0 && !other->HasDied()) TriggerDefensiveProcs(nullptr, other, Hand, damage); - // now check ripostes - if (damage == -3) { // riposting - DoRiposte(other); - } - if (damage > 0) return true; @@ -3581,7 +3561,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons //final damage has been determined. SetHP(GetHP() - damage); - + if (IsClient()) this->CastToClient()->SendHPUpdateMarquee(); diff --git a/zone/bot.cpp b/zone/bot.cpp index 5450d4f8a..4bc291e84 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2192,24 +2192,25 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = zone->random.Int(min_hit, max_hit); - if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) - damage = 0; - else { - other->AvoidDamage(this, damage, CanRiposte); - 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); + if (other->AvoidDamage(this, damage, CanRiposte ? MainRange : MainPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior + if (damage == -3) { + DoRiposte(other); + if (HasDied()) + return; + } + } else { + if (other->CheckHitChance(this, skillinuse, Hand, 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; } - } - - if (damage == -3) { - DoRiposte(other); - if (HasDied()) - return; } } else @@ -4813,70 +4814,38 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } //check to see if we hit.. - if(!other->CheckHitChance(other, skillinuse, Hand)) { - Log.Out(Logs::Detail, Logs::Combat, "Attack missed. Damage set to 0."); - damage = 0; - other->AddToHateList(this, 0); - } else { //we hit, try to avoid it - other->AvoidDamage(this, damage); - other->MeleeMitigation(this, damage, min_hit, opts); - if(damage > 0) { + 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, Hand)) { + 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); - Log.Out(Logs::Detail, Logs::Combat, "Generating hate %d towards %s", hate, GetCleanName()); - // now add done damage to the hate list - //other->AddToHateList(this, hate); - } - else - other->AddToHateList(this, 0); - Log.Out(Logs::Detail, Logs::Combat, "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 (FromRiposte) - return false; - else { - if (Hand == MainSecondary) {// 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. - int32 OffhandRiposteFail = (aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail); - OffhandRiposteFail *= -1; //Live uses a negative value for this. - - if (OffhandRiposteFail && - (OffhandRiposteFail > 99 || (zone->random.Int(0, 100) < OffhandRiposteFail))) { - damage = 0; // Counts as a miss - slippery_attack = true; - } else - DoRiposte(other); - if (GetHP() < 0) - return false; - } - else - DoRiposte(other); - if (GetHP() < 0) - return false; - } - } - - if (((damage < 0) || slippery_attack) && !FromRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA - int32 bonusStrikeThrough = (itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough); - if(bonusStrikeThrough && (zone->random.Int(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 = 0; } } + Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", damage); } 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 (!FromRiposte) - other->AddToHateList(this, hate); + other->AddToHateList(this, hate); /////////////////////////////////////////////////////////// ////// Send Attack Damage @@ -5771,132 +5740,6 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) { return ProcChance; } -bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) { - if(GetAppearance() == eaDead) - return false; - - float skill = 0; - float bonus = 0; - float RollTable[4] = {0,0,0,0}; - float roll = 0; - Mob *attacker = other; - Mob *defender = this; - - bool ghit = false; - if((attacker->GetSpellBonuses().MeleeSkillCheck + attacker->GetItemBonuses().MeleeSkillCheck) > 500) - ghit = true; - - if (IsEnraged() && !other->BehindMob(this, other->GetX(), other->GetY())) { - damage = -3; - Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); - } - - float riposte_chance = 0.0f; - if (CanRiposte && damage > 0 && CanThisClassRiposte() && !other->BehindMob(this, other->GetX(), other->GetY())) { - riposte_chance = ((100.0f + (float)defender->GetAABonuses().RiposteChance + (float)defender->GetSpellBonuses().RiposteChance + (float)defender->GetItemBonuses().RiposteChance) / 100.0f); - skill = GetSkill(SkillRiposte); - if (!ghit) { - bonus = (2.0 + skill / 60.0 + (GetDEX() / 200)); - bonus *= riposte_chance; - RollTable[0] = (bonus + (itembonuses.HeroicDEX / 25)); - } - } - - bool bBlockFromRear = false; - bool bShieldBlockFromRear = false; - if (this->IsBot()) { - int aaChance = 0; - int BlockBehindChance = (aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind); - if (BlockBehindChance && (BlockBehindChance > zone->random.Int(1, 100))){ - bBlockFromRear = true; - if (spellbonuses.BlockBehind || itembonuses.BlockBehind) - bShieldBlockFromRear = true; - } - } - - float block_chance = 0.0f; - if (damage > 0 && CanThisClassBlock() && (!other->BehindMob(this, other->GetX(), other->GetY()) || bBlockFromRear)) { - block_chance = ((100.0f + (float)spellbonuses.IncreaseBlockChance + (float)itembonuses.IncreaseBlockChance) / 100.0f); - skill = GetSkill(SkillBlock); - if (!ghit) { - bonus = (2.0 + skill / 35.0 + (GetDEX() / 200)); - RollTable[1] = (RollTable[0] + (bonus * block_chance) - riposte_chance); - block_chance *= bonus; - } - } else - RollTable[1] = RollTable[0]; - - if(damage > 0 && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) - && (!other->BehindMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { - bool equiped = GetBotItem(MainSecondary); - if(equiped) { - uint8 shield = GetBotItem(MainSecondary)->GetItem()->ItemType; - float bonusShieldBlock = 0.0f; - if(shield == ItemTypeShield) { - bonusShieldBlock = (aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock); - RollTable[1] = (RollTable[0] + bonusShieldBlock); - } - } - } - - if(damage > 0 && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) - && (!other->BehindMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { - bool equiped2 = GetBotItem(MainPrimary); - if(equiped2) { - uint8 TwoHandBlunt = GetBotItem(MainPrimary)->GetItem()->ItemType; - float bonusStaffBlock = 0.0f; - if(TwoHandBlunt == ItemType2HBlunt) { - bonusStaffBlock = (aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock); - RollTable[1] = (RollTable[0] + bonusStaffBlock); - } - } - } - - float parry_chance = 0.0f; - if (damage > 0 && CanThisClassParry() && !other->BehindMob(this, other->GetX(), other->GetY())) { - parry_chance = ((100.0f + (float)defender->GetSpellBonuses().ParryChance + (float)defender->GetItemBonuses().ParryChance) / 100.0f); - skill = GetSkill(SkillParry); - if (!ghit) { - bonus = (2.0 + skill / 60.0 + (GetDEX() / 200)); - bonus *= parry_chance; - RollTable[2] = (RollTable[1] + bonus - block_chance); - } - } else - RollTable[2] = (RollTable[1] - block_chance); - - float dodge_chance = 0.0f; - if (damage > 0 && CanThisClassDodge() && !other->BehindMob(this, other->GetX(), other->GetY())) { - dodge_chance = ((100.0f + (float)defender->GetSpellBonuses().DodgeChance + (float)defender->GetItemBonuses().DodgeChance) / 100.0f); - skill = GetSkill(SkillDodge); - if (!ghit) { - bonus = (2.0 + skill / 60.0 + (GetAGI() / 200)); - bonus *= dodge_chance; - RollTable[3] = (RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance); - } - } else { - RollTable[3] = (RollTable[2] - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance); - } - - if(damage > 0) { - roll = zone->random.Real(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; - } - - Log.Out(Logs::Detail, Logs::Combat, "Final damage after all avoidances: %d", damage); - - if (damage < 0) - return true; - - return false; -} - int Bot::GetMonkHandToHandDamage(void) { static int damage[66] = { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @@ -5986,26 +5829,25 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, } min_damage += (min_damage * GetMeleeMinDamageMod_SE(skill) / 100); - if(HitChance && !who->CheckHitChance(this, skill, MainPrimary)) - max_damage = 0; - else { - bool CanRiposte = true; - if(skill == SkillThrowing || skill == SkillArchery) - CanRiposte = false; - - who->AvoidDamage(this, max_damage, CanRiposte); - who->MeleeMitigation(this, max_damage, min_damage); - - if(max_damage > 0) { + int hand = MainPrimary; + if (skill == SkillThrowing || skill == SkillArchery) + hand = MainRange; + if (who->AvoidDamage(this, max_damage, hand)) { + if (max_damage == -3) + DoRiposte(who); + } else { + if (HitChance || who->CheckHitChance(this, skill, MainPrimary)) { + 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); + } else { + max_damage = 0; } } - if(max_damage >= 0) - who->AddToHateList(this, hate); + who->AddToHateList(this, hate); who->Damage(this, max_damage, SPELL_UNKNOWN, skill, false); @@ -6030,9 +5872,6 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if (max_damage > 0 && HasSkillProcSuccess()) TrySkillProc(who, skill, (ReuseTime * 1000), true); - - if(max_damage == -3 && !(who->GetHP() <= 0)) - DoRiposte(who); } void Bot::TryBackstab(Mob *other, int ReuseTime) { diff --git a/zone/bot.h b/zone/bot.h index 86a1ef895..7f2652498 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -169,7 +169,6 @@ public: uint16 BotGetSpellType(int spellslot) { return AIspells[spellslot].type; } uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; } virtual float GetProcChances(float ProcBonus, uint16 hand); - virtual bool AvoidDamage(Mob* other, int32 &damage, bool CanRiposte); virtual int GetMonkHandToHandDamage(void); virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse); virtual void DoRiposte(Mob* defender); @@ -314,7 +313,7 @@ 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, uint16 slot = USE_ITEM_SPELL_SLOT, 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); diff --git a/zone/mob.h b/zone/mob.h index 4cb4ef8dd..6a696256f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -149,7 +149,7 @@ public: 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); - virtual bool AvoidDamage(Mob* attacker, int32 &damage, bool CanRiposte = true); + 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); void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index bd8000e63..1bcccf272 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -130,22 +130,19 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100; - if(HitChance && !who->CheckHitChance(this, skill, MainPrimary)) - max_damage = 0; - - else{ - bool CanRiposte = true; - if(skill == SkillThrowing || skill == SkillArchery) // changed from '&&' - CanRiposte = false; - - if (CanAvoid) - who->AvoidDamage(this, max_damage, CanRiposte); - - who->MeleeMitigation(this, max_damage, min_damage); - - if(max_damage > 0) + int hand = MainPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most + if (skill == SkillThrowing || skill == SkillArchery) + hand = MainRange; + if (who->AvoidDamage(this, max_damage, hand)) { + if (max_damage == -3) + DoRiposte(who); + } else { + if (HitChance || who->CheckHitChance(this, skill, MainPrimary)) { + who->MeleeMitigation(this, max_damage, min_damage); CommonOutgoingHitSuccess(who, max_damage, skill); - + } else { + max_damage = 0; + } } who->AddToHateList(this, hate, 0, false); @@ -168,8 +165,6 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if (max_damage > 0 && HasSkillProcSuccess()) TrySkillProc(who, skill, ReuseTime*1000, true); - if(max_damage == -3 && !who->HasDied()) - DoRiposte(who); } @@ -972,7 +967,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } if (!HeadShot) - other->AvoidDamage(this, TotalDmg, false); + other->AvoidDamage(this, TotalDmg, MainRange); other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0){ @@ -1305,7 +1300,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha TotalDmg += TotalDmg * damage_mod / 100; - other->AvoidDamage(this, TotalDmg, false); + other->AvoidDamage(this, TotalDmg, MainRange); other->MeleeMitigation(this, TotalDmg, MinDmg); if (TotalDmg > 0) @@ -1539,7 +1534,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, false); //CanRiposte=false - Can not riposte throw attacks. + other->AvoidDamage(this, TotalDmg, MainRange); other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0) @@ -2411,27 +2406,26 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = zone->random.Int(min_hit, max_hit); - if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) { - damage = 0; + if (other->AvoidDamage(this, damage, CanRiposte ? MainRange : MainPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior + if (damage == -3) { + DoRiposte(other); + if (HasDied()) + return; + } } else { - other->AvoidDamage(this, damage, CanRiposte); - other->MeleeMitigation(this, damage, min_hit); - if(damage > 0) + if (other->CheckHitChance(this, skillinuse, Hand, chance_mod)) { + other->MeleeMitigation(this, damage, min_hit); CommonOutgoingHitSuccess(other, damage, skillinuse); + } else { + damage = 0; + } } - if (damage == -3) { - DoRiposte(other); - if (HasDied()) - return; - } } else damage = -5; - 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. From fe98b3363d49ff61fec5513f452fad40b80c64e9 Mon Sep 17 00:00:00 2001 From: JJ Date: Sat, 4 Jul 2015 12:10:58 -0400 Subject: [PATCH 239/846] Filename consistency. [skip ci] --- utils/sql/db_update_manifest.txt | 2 +- utils/sql/git/required/2015_7_1_Marquee_Rule.sql | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 utils/sql/git/required/2015_7_1_Marquee_Rule.sql diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 480aeb309..7394c7863 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -338,7 +338,7 @@ 9082|2015_05_25_npc_types_texture_fields.sql|SHOW COLUMNS FROM `npc_types` LIKE 'armtexture'|empty| 9083|2015_06_07_aa_update.sql|SHOW COLUMNS FROM `character_alternate_abilities` LIKE 'charges'|empty| 9084|2015_06_30_runspeed_adjustments.sql|SELECT `runspeed` FROM `npc_types` WHERE `runspeed` > 3|not_empty| -9085|2015_7_1_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty| +9085|2015_07_01_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty| 9086|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty| # Upgrade conditions: diff --git a/utils/sql/git/required/2015_7_1_Marquee_Rule.sql b/utils/sql/git/required/2015_7_1_Marquee_Rule.sql deleted file mode 100644 index 039a34412..000000000 --- a/utils/sql/git/required/2015_7_1_Marquee_Rule.sql +++ /dev/null @@ -1 +0,0 @@ -INSERT INTO `rule_values` (`rule_name`, `rule_value`, `notes`) VALUES ('Character:MarqueeHPUpdates', 'false', 'Will show Health % in center of screen < 100%'); \ No newline at end of file From 947145a6425a0bc95b9819e8b9f69b99444d50b0 Mon Sep 17 00:00:00 2001 From: JJ Date: Sat, 4 Jul 2015 12:12:18 -0400 Subject: [PATCH 240/846] Oops. [skip ci] --- utils/sql/git/required/2015_07_01_Marquee_Rule.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 utils/sql/git/required/2015_07_01_Marquee_Rule.sql diff --git a/utils/sql/git/required/2015_07_01_Marquee_Rule.sql b/utils/sql/git/required/2015_07_01_Marquee_Rule.sql new file mode 100644 index 000000000..039a34412 --- /dev/null +++ b/utils/sql/git/required/2015_07_01_Marquee_Rule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`rule_name`, `rule_value`, `notes`) VALUES ('Character:MarqueeHPUpdates', 'false', 'Will show Health % in center of screen < 100%'); \ No newline at end of file From 8d3d3d2af296350e3fd4e9ee23fa083ef486ef80 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 00:42:06 -0400 Subject: [PATCH 241/846] Add Dual Wield/Double Attack NPC skill overrides The vast majority of mobs on live follow this path. The exception appears most commonly with PC pets though. Eventually these should be changeable in the DB. --- zone/npc.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index ba6a2393b..8dbab7c64 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -278,6 +278,18 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if for(r = 0; r <= HIGHEST_SKILL; r++) { skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)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; + } else if (moblevel > 3) { + skills[SkillDoubleAttack] = moblevel * 5; + skills[SkillDualWield] = skills[SkillDoubleAttack]; + } else { + skills[SkillDoubleAttack] = moblevel * 5; + } if(d->trap_template > 0) { @@ -1928,14 +1940,14 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) 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 == "runspeed") { + else if(id == "runspeed") { runspeed = (float)atof(val.c_str()); base_runspeed = (int)((float)runspeed * 40.0f); base_walkspeed = base_runspeed * 100 / 265; walkspeed = ((float)base_walkspeed) * 0.025f; base_fearspeed = base_runspeed * 100 / 127; fearspeed = ((float)base_fearspeed) * 0.025f; - CalcBonuses(); return; + CalcBonuses(); return; } else if(id == "special_attacks") { NPCSpecialAttacks(val.c_str(), 0, 1); return; } else if(id == "special_abilities") { ProcessSpecialAbilities(val.c_str()); return; } From 99620f8535853636545e8a022089751df973d882 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 00:45:46 -0400 Subject: [PATCH 242/846] Add Mob/Client CheckDualWield functions --- zone/attack.cpp | 28 ++++++++++++++++++++++++++++ zone/client.h | 1 + zone/client_process.cpp | 10 +--------- zone/mob.h | 1 + 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 8a120b896..86f8b8d65 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5075,3 +5075,31 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) } } } + +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); + if (GetLevel() > 35) + chance += GetLevel(); + + chance += aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; + int per_inc = spellbonuses.DualWieldChance + aabonuses.DualWieldChance + itembonuses.DualWieldChance; + if (per_inc) + chance += chance * per_inc / 100; + + return zone->random.Int(1, 375) <= chance; +} + +bool Client::CheckDualWield() +{ + int chance = GetSkill(SkillDualWield) + GetLevel(); + + chance += aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; + int per_inc = spellbonuses.DualWieldChance + aabonuses.DualWieldChance + itembonuses.DualWieldChance; + if (per_inc) + chance += chance * per_inc / 100; + + return zone->random.Int(1, 375) <= chance; +} diff --git a/zone/client.h b/zone/client.h index 375006536..7558d9bb6 100644 --- a/zone/client.h +++ b/zone/client.h @@ -890,6 +890,7 @@ public: void Insight(uint32 t_id); bool CheckDoubleAttack(bool tripleAttack = false); bool CheckDoubleRangedAttack(); + bool CheckDualWield(); //remove charges/multiple objects from inventory: //bool DecreaseByType(uint32 type, uint8 amt); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 7cc3f9917..70899e2d6 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -428,16 +428,8 @@ bool Client::Process() { //you can't see your target } else if(auto_attack_target->GetHP() > -10) { - 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; - - float random = zone->random.Real(0, 1); CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10); - if (random < DualWieldProbability) { // Max 78% of DW + if (CheckDualWield()) { ItemInst *wpn = GetInv().GetItem(MainSecondary); TryWeaponProc(wpn, auto_attack_target, MainSecondary); diff --git a/zone/mob.h b/zone/mob.h index 6a696256f..e329128a9 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -166,6 +166,7 @@ public: void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse); void CommonBreakInvisible(); bool HasDied(); + virtual bool CheckDualWield(); //Appearance void SendLevelAppearance(); From 578bbf657a14d1b1ecf75d83239d521f2c20001c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 00:46:37 -0400 Subject: [PATCH 243/846] Make Client::AI_Process in line with uncharmed --- zone/mob_ai.cpp | 109 +++++++----------------------------------------- 1 file changed, 16 insertions(+), 93 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 045c724d6..f171d72e3 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -827,112 +827,35 @@ void Client::AI_Process() bool is_combat_range = CombatRange(GetTarget()); - if(is_combat_range) { - if(charm_class_attacks_timer.Check()) { + if (is_combat_range) { + if (charm_class_attacks_timer.Check()) { DoClassAttacks(GetTarget()); } if (AImovement_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(GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { - if(attack_timer.Check()) { - Attack(GetTarget(), MainPrimary); - if(GetTarget()) { - if(CheckDoubleAttack()) { - Attack(GetTarget(), MainPrimary); - 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(), MainPrimary, 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(zone->random.Roll(flurrychance)) - { - Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), MainPrimary, false); - Attack(GetTarget(), MainPrimary, false); - } - } - - int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; - - if (ExtraAttackChanceBonus && GetTarget()) { - ItemInst *wpn = GetInv().GetItem(MainPrimary); - if(wpn){ - if(wpn->GetItem()->ItemType == ItemType2HSlash || - wpn->GetItem()->ItemType == ItemType2HBlunt || - wpn->GetItem()->ItemType == ItemType2HPiercing ) - { - if(zone->random.Roll(ExtraAttackChanceBonus)) - { - Attack(GetTarget(), MainPrimary, 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 (GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { + if (attack_timer.Check()) { + // Should charmed clients not be procing? + DoAttackRounds(GetTarget(), MainPrimary); } } - 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(zone->random.Roll(DualWieldProbability)) - { - Attack(GetTarget(), MainSecondary); - if(CheckDoubleAttack()) - { - Attack(GetTarget(), MainSecondary); - } - + if (CanThisClassDualWield() && GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { + if (attack_dw_timer.Check()) { + if (CheckDualWield()) { + // Should charmed clients not be procing? + DoAttackRounds(GetTarget(), MainSecondary); } } } - } - else - { + } else { if(!IsRooted()) { if(AImovement_timer->Check()) @@ -1000,7 +923,7 @@ void Client::AI_Process() animation = nspeed; nspeed *= 2; SetCurrentSpeed(nspeed); - + CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed); } } @@ -1502,7 +1425,7 @@ void Mob::AI_Process() { int speed = GetWalkspeed(); if (dist >= 5625) speed = GetRunspeed(); - + CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); } else From 7c89ab3fec2a4824a489696419645e8fb545b62f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 01:15:46 -0400 Subject: [PATCH 244/846] Pull Mob mainhand/offhand attack rounds into their own functions --- zone/attack.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ zone/mob.h | 2 ++ zone/mob_ai.cpp | 56 ++--------------------------------------------- 3 files changed, 62 insertions(+), 54 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 86f8b8d65..a702f0efe 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5103,3 +5103,61 @@ bool Client::CheckDualWield() return zone->random.Int(1, 375) <= chance; } + +void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) +{ + if (IsNPC()) { + int16 n_atk = CastToNPC()->GetNumberOfAttacks(); + if (n_atk <= 1) { + Attack(target, MainPrimary, false, false, false, opts); + } else { + for (int i = 0; i < n_atk; ++i) { + Attack(target, MainPrimary, false, false, false, opts); + } + } + } else { + Attack(target, MainPrimary, false, false, false, opts); + } + + 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 = zone->random.Int(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, MainPrimary, 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, MainPrimary, false, false, false, opts); + // now lets check the quad attack + if (GetSpecialAbility(SPECATK_QUAD) && + RandRoll < (GetLevel() + NPCQuadAttackModifier)) { + Attack(target, MainPrimary, false, false, false, opts); + } + } + } + } +} + +void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) +{ + if (!target) + return; + // Mobs will only dual wield w/ the flag or have a secondary weapon + if (GetSpecialAbility(SPECATK_INNATE_DW) || GetEquipment(MaterialSecondary) != 0) { + if (CheckDualWield()) { + Attack(target, MainSecondary, false, false, false, opts); + if (CanThisClassDoubleAttack()) { + // This isn't correct yet + if (zone->random.Roll(GetLevel() + 20)) { + Attack(target, MainSecondary, false, false, false, opts); + } + } + } + } +} diff --git a/zone/mob.h b/zone/mob.h index e329128a9..84aa46595 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -167,6 +167,8 @@ public: void CommonBreakInvisible(); bool HasDied(); virtual bool CheckDualWield(); + void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); + void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); //Appearance void SendLevelAppearance(); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index f171d72e3..f4a511b7b 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1101,42 +1101,7 @@ void Mob::AI_Process() { //try main hand first if(attack_timer.Check()) { - if(IsNPC()) { - int16 n_atk = CastToNPC()->GetNumberOfAttacks(); - if(n_atk <= 1) { - Attack(target, MainPrimary); - } else { - for(int i = 0; i < n_atk; ++i) { - Attack(target, MainPrimary); - } - } - } else { - Attack(target, MainPrimary); - } - - 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 = zone->random.Int(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, MainPrimary); - // 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); - // now lets check the quad attack - if (GetSpecialAbility(SPECATK_QUAD) - && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, MainPrimary); - } - } - } - } + DoMainHandAttackRounds(target); if (GetSpecialAbility(SPECATK_FLURRY)) { int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0); @@ -1271,24 +1236,7 @@ void Mob::AI_Process() { //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(zone->random.Roll(DualWieldProbability)) - { - Attack(target, MainSecondary); - if (CanThisClassDoubleAttack()) - { - if (zone->random.Roll(GetLevel() + 20)) - { - Attack(target, MainSecondary); - } - } - } - } - } + DoOffHandAttackRounds(target); //now special attacks (kick, etc) if(IsNPC()) From 82fe15190b6be27554bd00de14765cbc73345f59 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 01:37:14 -0400 Subject: [PATCH 245/846] Add CheckDoubleAttack for mobs --- zone/attack.cpp | 23 ++++++++++++++++++----- zone/mob.h | 1 + 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index a702f0efe..1ca596016 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3452,6 +3452,21 @@ bool Client::CheckDoubleRangedAttack() { return false; } +bool Mob::CheckDoubleAttack(bool tripleAttack) +{ + // 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); + if (GetLevel() > 35) + chance += GetLevel(); + + int per_inc = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance; + if (per_inc) + chance += chance * per_inc / 100; + + 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) { // This method is called with skill_used=ABJURE for Damage Shield damage. bool FromDamageShield = (skill_used == SkillAbjuration); @@ -5029,8 +5044,7 @@ void NPC::SetAttackTimer() //special offhand stuff if (i == MainSecondary) { - //NPCs get it for free at 13 - if(GetLevel() < 13) { + if(!CanThisClassDualWield()) { attack_dw_timer.Disable(); continue; } @@ -5152,9 +5166,8 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) if (GetSpecialAbility(SPECATK_INNATE_DW) || GetEquipment(MaterialSecondary) != 0) { if (CheckDualWield()) { Attack(target, MainSecondary, false, false, false, opts); - if (CanThisClassDoubleAttack()) { - // This isn't correct yet - if (zone->random.Roll(GetLevel() + 20)) { + if (CanThisClassDoubleAttack() && GetLevel() > 35) { + if (CheckDoubleAttack()) { Attack(target, MainSecondary, false, false, false, opts); } } diff --git a/zone/mob.h b/zone/mob.h index 84aa46595..ec705faf7 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -169,6 +169,7 @@ public: virtual bool CheckDualWield(); void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); + virtual bool CheckDoubleAttack(bool tripleAttack = false); // mob version doesn't use this flag //Appearance void SendLevelAppearance(); From 22efe33f9b22aceaa8a2083adb80195ad51f86fd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 02:05:50 -0400 Subject: [PATCH 246/846] Correct the definition of "quading" If you would like your NPCs to use the old rules, turn Combat:UseLiveCombatRounds to false. --- common/ruletypes.h | 1 + zone/attack.cpp | 52 ++++++++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 6a52b1e78..8613eeebe 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -448,6 +448,7 @@ RULE_BOOL(Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per RULE_BOOL(Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly. RULE_BOOL(Combat, MeleePush, true) // enable melee push RULE_INT(Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad +RULE_BOOL(Combat, UseLiveCombatRounds, true) // turn this false if you don't want to worry about fixing up combat rounds for NPCs RULE_CATEGORY_END() RULE_CATEGORY(NPC) diff --git a/zone/attack.cpp b/zone/attack.cpp index 1ca596016..4f8ca4a53 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5120,6 +5120,18 @@ bool Client::CheckDualWield() void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) { + if (!target) + return; + + 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); + if (CanThisClassDoubleAttack() && CheckDoubleAttack()) + Attack(target, MainPrimary, false, false, false, opts); + return; + } + if (IsNPC()) { int16 n_atk = CastToNPC()->GetNumberOfAttacks(); if (n_atk <= 1) { @@ -5133,26 +5145,23 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) Attack(target, MainPrimary, false, false, false, opts); } - 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 = zone->random.Int(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)) { + // 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 = zone->random.Int(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, MainPrimary, 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, MainPrimary, 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)) { + // now lets check the quad attack + if (GetSpecialAbility(SPECATK_QUAD) && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { Attack(target, MainPrimary, false, false, false, opts); - // now lets check the quad attack - if (GetSpecialAbility(SPECATK_QUAD) && - RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, MainPrimary, false, false, false, opts); - } } } } @@ -5166,11 +5175,8 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) if (GetSpecialAbility(SPECATK_INNATE_DW) || GetEquipment(MaterialSecondary) != 0) { if (CheckDualWield()) { Attack(target, MainSecondary, false, false, false, opts); - if (CanThisClassDoubleAttack() && GetLevel() > 35) { - if (CheckDoubleAttack()) { - Attack(target, MainSecondary, false, false, false, opts); - } - } + if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()) + Attack(target, MainSecondary, false, false, false, opts); } } } From fe97af4d8990eb08d81cdc2bd4546d18dd1d34a7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 02:27:51 -0400 Subject: [PATCH 247/846] Fix some issues with Rampage/AE Ramp --- zone/hate_list.cpp | 37 ++++++++++--------------------------- zone/mob.h | 10 ++++++++++ zone/mob_ai.cpp | 17 ++++++++++------- 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index e68924844..86a75a545 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -535,37 +535,20 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption if (!target || !caster) return 0; - int ret = 0; - std::list id_list; - auto iterator = list.begin(); - while (iterator != list.end()) - { - struct_HateList *h = (*iterator); - ++iterator; - if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) - { - if (caster->CombatRange(h->entity_on_hatelist)) - { - id_list.push_back(h->entity_on_hatelist->GetID()); - ++ret; + int hit_count = 0; + auto it = list.begin(); + while (it != list.end() && hit_count < count) { + struct_HateList *h = (*it); + if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) { + if (caster->CombatRange(h->entity_on_hatelist)) { + ++hit_count; + caster->ProcessAttackRounds(h->entity_on_hatelist, opts); } } + ++it; } - std::list::iterator iter = id_list.begin(); - while (iter != id_list.end()) - { - Mob *cur = entity_list.GetMobID((*iter)); - if (cur) - { - for (int i = 0; i < count; ++i) { - caster->Attack(cur, MainPrimary, false, false, false, opts); - } - } - iter++; - } - - return ret; + return hit_count; } void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center) diff --git a/zone/mob.h b/zone/mob.h index ec705faf7..02d6d3e55 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -170,6 +170,16 @@ public: void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); virtual bool CheckDoubleAttack(bool tripleAttack = false); // mob version doesn't use this flag + // inline process for places where we need to do them outside of the AI_Process + void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr) + { + if (target) { + DoMainHandAttackRounds(target, opts); + if (CanThisClassDualWield()) + DoOffHandAttackRounds(target, opts); + } + return; + } //Appearance void SendLevelAppearance(); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index f4a511b7b..c8654849a 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1103,6 +1103,7 @@ void Mob::AI_Process() { if(attack_timer.Check()) { DoMainHandAttackRounds(target); + bool specialed = false; // NPCs can only do one of these a round if (GetSpecialAbility(SPECATK_FLURRY)) { int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0); flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance); @@ -1134,6 +1135,7 @@ void Mob::AI_Process() { opts.crit_flat = cur; Flurry(&opts); + specialed = true; } } @@ -1154,7 +1156,7 @@ void Mob::AI_Process() { } } - if (GetSpecialAbility(SPECATK_RAMPAGE)) + if (GetSpecialAbility(SPECATK_RAMPAGE) && !specialed) { int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0); rampage_chance = rampage_chance > 0 ? rampage_chance : 20; @@ -1190,10 +1192,11 @@ void Mob::AI_Process() { opts.crit_flat = cur; } Rampage(&opts); + specialed = true; } } - if (GetSpecialAbility(SPECATK_AREA_RAMPAGE)) + if (GetSpecialAbility(SPECATK_AREA_RAMPAGE) && !specialed) { int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0); rampage_chance = rampage_chance > 0 ? rampage_chance : 20; @@ -1230,6 +1233,7 @@ void Mob::AI_Process() { } AreaRampage(&opts); + specialed = true; } } } @@ -1974,14 +1978,14 @@ bool Mob::Rampage(ExtraAttackOptions *opts) if (m_target == GetTarget()) continue; if (CombatRange(m_target)) { - Attack(m_target, MainPrimary, false, false, false, opts); + ProcessAttackRounds(m_target, opts); index_hit++; } } } if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets) - Attack(GetTarget(), MainPrimary, false, false, false, opts); + ProcessAttackRounds(GetTarget(), opts); return true; } @@ -1999,9 +2003,8 @@ void Mob::AreaRampage(ExtraAttackOptions *opts) rampage_targets = rampage_targets > 0 ? rampage_targets : 1; index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); - if(index_hit == 0) { - Attack(GetTarget(), MainPrimary, false, false, false, opts); - } + if(index_hit == 0) + ProcessAttackRounds(GetTarget(), opts); } uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) { From d083262555c2ae6525ff2a76539fbf8f970d2125 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 02:43:33 -0400 Subject: [PATCH 248/846] Fix clients offhand double attack check --- zone/attack.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 4f8ca4a53..f953ce3db 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5061,7 +5061,13 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) Attack(target, hand, false, false, IsFromSpell); - if (CanThisClassDoubleAttack()) { + 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) + candouble = GetSkill(SkillDoubleAttack) > 149 || (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack) > 0; + + if (candouble) { CheckIncreaseSkill(SkillDoubleAttack, target, -10); if (CheckDoubleAttack()) Attack(target, hand, false, false, IsFromSpell); @@ -5073,9 +5079,9 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) if (hand == MainPrimary) { 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); - Attack(target, hand, false, false, IsFromSpell); - Attack(target, hand, false, false, IsFromSpell); } auto extraattackchance = aabonuses.ExtraAttackChance + spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance; From dcd1a0755316b34ab8a9394adb6c816892ad1c46 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 03:11:25 -0400 Subject: [PATCH 249/846] Fix issue with two hander for NPCs dual wielding Cleaned up some other 2hander logic as well --- zone/attack.cpp | 29 ++++------------------------- zone/bonuses.cpp | 6 +++++- zone/loottables.cpp | 4 +++- zone/mob.cpp | 1 + zone/mob.h | 3 +++ 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index f953ce3db..3714bb8e2 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4921,7 +4921,6 @@ void Client::SetAttackTimer() attack_timer.SetAtTrigger(4000, true); Timer *TimerToUse = nullptr; - const Item_Struct *PrimaryWeapon = nullptr; for (int i = MainRange; i <= MainSecondary; i++) { //pick a timer @@ -4943,19 +4942,8 @@ void Client::SetAttackTimer() //special offhand stuff if (i == MainSecondary) { - //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; - } - } - //if we cant dual wield, skip it - if (!CanThisClassDualWield()) { + if (!CanThisClassDualWield() || HasTwoHanderEquipped()) { attack_dw_timer.Disable(); continue; } @@ -5004,9 +4992,6 @@ void Client::SetAttackTimer() if (quiver_haste > 0) speed *= quiver_haste; TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true, true); - - if (i == MainPrimary) - PrimaryWeapon = ItemToUse; } } @@ -5044,7 +5029,7 @@ void NPC::SetAttackTimer() //special offhand stuff if (i == MainSecondary) { - if(!CanThisClassDualWield()) { + if(!CanThisClassDualWield() || HasTwoHanderEquipped()) { attack_dw_timer.Disable(); continue; } @@ -5085,14 +5070,8 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) } auto extraattackchance = aabonuses.ExtraAttackChance + spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance; - if (extraattackchance) { - auto wpn = GetInv().GetItem(MainPrimary); - if (wpn && (wpn->GetItem()->ItemType == ItemType2HBlunt || - wpn->GetItem()->ItemType == ItemType2HSlash || - wpn->GetItem()->ItemType == ItemType2HPiercing)) - if (zone->random.Roll(extraattackchance)) - Attack(target, hand, false, false, IsFromSpell); - } + if (extraattackchance && HasTwoHanderEquipped() && zone->random.Roll(extraattackchance)) + Attack(target, hand, false, false, IsFromSpell); } } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 1e719dceb..155dfc4ae 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -141,6 +141,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { ClearItemFactionBonuses(); SetShieldEquiped(false); SetTwoHandBluntEquiped(false); + SetTwoHanderEquipped(false); unsigned int i; //should not include 21 (SLOT_AMMO) @@ -154,8 +155,11 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { const Item_Struct *item = inst->GetItem(); if (i == MainSecondary && (item && item->ItemType == ItemTypeShield)) SetShieldEquiped(true); - else if (i == MainPrimary && (item && item->ItemType == ItemType2HBlunt)) + else if (i == MainPrimary && (item && item->ItemType == ItemType2HBlunt)) { SetTwoHandBluntEquiped(true); + SetTwoHanderEquipped(true); + } else if (i == MainPrimary && (item && (item->ItemType == ItemType2HSlash || item->ItemType == ItemType2HPiercing))) + SetTwoHanderEquipped(true); } //Power Source Slot diff --git a/zone/loottables.cpp b/zone/loottables.cpp index e3014b12e..12766b57f 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -334,9 +334,11 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge eslot = MaterialPrimary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); + if (item2->ItemType == ItemType2HBlunt || item2->ItemType == ItemType2HSlash || item2->ItemType == ItemType2HPiercing) + SetTwoHanderEquipped(true); } else if (foundslot == MainSecondary - && (GetOwner() != nullptr || (GetLevel() >= 13 && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && + && (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && (item2->ItemType == ItemType1HSlash || item2->ItemType == ItemType1HBlunt || item2->ItemType == ItemTypeShield || item2->ItemType == ItemType1HPiercing)) { diff --git a/zone/mob.cpp b/zone/mob.cpp index ad0a60899..ce0a97db9 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -211,6 +211,7 @@ Mob::Mob(const char* in_name, trackable = true; has_shieldequiped = false; has_twohandbluntequiped = false; + has_twohanderequipped = false; has_numhits = false; has_MGB = false; has_ProjectIllusion = false; diff --git a/zone/mob.h b/zone/mob.h index 02d6d3e55..0094b0fbc 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -336,6 +336,8 @@ public: inline void SetShieldEquiped(bool val) { has_shieldequiped = val; } bool HasTwoHandBluntEquiped() const { return has_twohandbluntequiped; } 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 uint32 GetEquipment(uint8 material_slot) const { return(0); } virtual int32 GetEquipmentMaterial(uint8 material_slot) const; @@ -1221,6 +1223,7 @@ protected: bool offhand; bool has_shieldequiped; bool has_twohandbluntequiped; + bool has_twohanderequipped; bool has_numhits; bool has_MGB; bool has_ProjectIllusion; From 70577584ab834e74e59e11a253a90bc620957d98 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 03:33:16 -0400 Subject: [PATCH 250/846] Make SPECATK_QUAD == SPECATK_INNATE_DW when Combat:UseLiveCombatRounds is true --- zone/attack.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 3714bb8e2..02b16c64e 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5157,7 +5157,10 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) if (!target) return; // Mobs will only dual wield w/ the flag or have a secondary weapon - if (GetSpecialAbility(SPECATK_INNATE_DW) || GetEquipment(MaterialSecondary) != 0) { + // 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) { if (CheckDualWield()) { Attack(target, MainSecondary, false, false, false, opts); if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()) From 1d29c873fbf2223819afe1c0f0bdf2128cffcc8a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Jul 2015 16:36:12 -0400 Subject: [PATCH 251/846] Rewrite NPC combat rounds logic See changelog.txt --- changelog.txt | 9 +++++++++ utils/sql/git/optional/2015_07_05_LiveCombatRounds.sql | 1 + 2 files changed, 10 insertions(+) create mode 100644 utils/sql/git/optional/2015_07_05_LiveCombatRounds.sql diff --git a/changelog.txt b/changelog.txt index f3fdc3ba0..27b3f9de4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,14 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/05/2015 == +mackal: Rewrite NPC combat attack round logic + An NPC "quading" is really just an NPC with innate dual wield that doubles on both hands + The old rules allowed NPCs to hit 6 times in one round + NPCs also seem to have their own skill progression for DW/DA + See: http://www.eqemulator.org/forums/showthread.php?t=38708 + You can set Combat:UseLiveCombatRounds to false to use the old rules + PC Double Attack rates kind of follow the same thing but still needs to be implemented + == 7/4/2015 == mackal: Reworked the activated avoidace skills (riposte, dodge, etc) based on dev quotes This also fixes the order things are checked (avoidance skills, THEN hit/miss) diff --git a/utils/sql/git/optional/2015_07_05_LiveCombatRounds.sql b/utils/sql/git/optional/2015_07_05_LiveCombatRounds.sql new file mode 100644 index 000000000..2a5377656 --- /dev/null +++ b/utils/sql/git/optional/2015_07_05_LiveCombatRounds.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:UseLiveCombatRounds', 'true', 'If true use live NPC combat rules, false will use old rules.'); From e2ac647e03c6ceac9131e89faa18d76f1e0fa637 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sun, 5 Jul 2015 22:32:59 -0400 Subject: [PATCH 252/846] Bot saylinks and command aliases. --- changelog.txt | 6 + common/ruletypes.h | 2 + zone/bot.cpp | 456 ++++++++++++++++------------------------- zone/bot.h | 2 + zone/client_packet.cpp | 2 +- zone/command.cpp | 19 +- zone/command.h | 4 +- zone/corpse.cpp | 2 +- zone/embparser_api.cpp | 20 +- zone/lua_general.cpp | 12 +- zone/questmgr.cpp | 4 +- zone/questmgr.h | 4 +- 12 files changed, 222 insertions(+), 311 deletions(-) diff --git a/changelog.txt b/changelog.txt index 27b3f9de4..227058eba 100644 --- a/changelog.txt +++ b/changelog.txt @@ -8,6 +8,12 @@ mackal: Rewrite NPC combat attack round logic See: http://www.eqemulator.org/forums/showthread.php?t=38708 You can set Combat:UseLiveCombatRounds to false to use the old rules PC Double Attack rates kind of follow the same thing but still needs to be implemented +Kinglykrab: WARNING: summonburriedplayercorpse is now summonburiedplayercorpse, getplayerburriedcorpsecount is now getplayerburiedcorpsecount, summon_burried_player_corpse is now summon_buried_player_corpse, and get_player_burried_corpse_count is now get_player_buried_corpse_count FIX THESE IN YOUR SCRIPTS OR THEY WILL NOT WORK!!!! + Added bot saylinks (thanks Uleat!) + Command aliases for #augmentitem (#aug), #findnpctype (#fn), #findspell (#fs) + Bot command changes: #bot sow -> #bot speed, #bot magepet -> #bot setpet, #bot resurrectme -> #bot resurrect + Changed all occurrences of burried to buried in the code. + client_packet.cpp was referencing old columns in character_corpses, not sure how we didn't already see this before. == 7/4/2015 == mackal: Reworked the activated avoidace skills (riposte, dodge, etc) based on dev quotes diff --git a/common/ruletypes.h b/common/ruletypes.h index 8613eeebe..e1a095724 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -506,6 +506,8 @@ RULE_INT(Bots, BotAAExpansion, 8) // Bots get AAs through this expansion 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. 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_CATEGORY_END() #endif diff --git a/zone/bot.cpp b/zone/bot.cpp index 4bc291e84..6e9a1f2fc 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8731,52 +8731,53 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 your bots all or 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 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 ai mez - If you're grouped with an Enchanter, he will mez your target."); + c->Message(0, "#bot ai 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 bindme - 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 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 pc group to safe location in the current zone. bots are lost"); - c->Message(0, "#bot resurrectme - Your bot Cleric will rez you."); - c->Message(0, "#bot corpse summon - Necromancers summon corpse."); + 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 sow - Bot sow on you (Druid has options)"); + 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 runeme - Enchanter Bot cast Rune spell on you"); + c->Message(0, "#bot runeme - 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 - you need a Druid or Wizard in your group)"); + 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 magepet [earth|water|air|fire|monster] - Select the pet type you want your Mage bot to use."); + 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 - Gives your targeted bot the item you have on your cursor."); - c->Message(0, "#bot augmentitem - Allows you to augment items for other classes. You must have the Augmentation Sealer window filled."); + c->Message(0, "#bot augmentitem - 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 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 [hair|haircolor|beard|beardcolor|face|eyes|heritage|tattoo|details ] - Change your BOTs appearance."); + 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] - Turns taunt on/off for targeted bot"); + 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 groupmessages [on|off] [bot name|all] - Turns group messages on/off for named bot/all bots."); - c->Message(0, "#bot defensive [bot name] - Causes warrior or knight bot to use defensive discipline / buff."); + 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 Pulling Target NPC's"); + c->Message(0, "#bot pull [] [target] - Bot Pulling Target NPCs"); c->Message(0, "#bot setinspectmessage - Copies your inspect message to a targeted bot that you own"); - c->Message(0, "#bot bardoutofcombat [on|off] - Determines wheter bard bots use out of combat songs."); + 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; } @@ -9083,6 +9084,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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()) { @@ -9588,7 +9596,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking mobs nearby", c->GetName()); entity_list.ShowSpawnWindow(c, RangeD, false); } else - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "You want to [track all], [track near], or [track rare]?", c->GetName()); + 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: @@ -9658,7 +9666,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 1)) { Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], [cure disease], [cure curse], or [cure blindness]?", c->GetName()); + 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: @@ -9678,7 +9686,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 2)) { Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); } else - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], [cure disease], or [cure blindness]?", c->GetName()); + 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: @@ -9696,7 +9704,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 5)) { Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]) ; } else - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], or [cure disease]?", c->GetName()); + 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."); @@ -9780,9 +9788,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } //Resurrect - if(!strcasecmp(sep->arg[1], "resurrectme")) { + if(!strcasecmp(sep->arg[1], "resurrect")) { Mob *target = c->GetTarget(); - if(target == nullptr || !target->IsCorpse()) { + if(target == nullptr || !target->IsPlayerCorpse()) { c->Message(15, "You must select a corpse!"); return; } @@ -9808,7 +9816,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - if(!strcasecmp(sep->arg[1], "magepet")) { + 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(); @@ -10144,7 +10152,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } // Sow - if ((!strcasecmp(sep->arg[1], "sow")) && (c->IsGrouped())) { + if ((!strcasecmp(sep->arg[1], "speed")) && (c->IsGrouped())) { Mob *Sower; uint32 SowerClass = 0; Group *g = c->GetGroup(); @@ -10182,37 +10190,37 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(SowerClass) { case DRUID: if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() >= 10)) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting sow..."); + 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 wolf..."); + 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->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->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 [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); + 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 [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); + 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 [sow regular] or [sow wolf]?"); + 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 [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); + 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)) { @@ -10258,7 +10266,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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"); + c->Message(15, "You must select a player or bot you own!"); else if(g) { for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ @@ -10305,6 +10313,25 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { // 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(); @@ -10328,212 +10355,36 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } switch(GaterClass) { - case DRUID: - if ((!strcasecmp(sep->arg[2], "karana")) && (c->GetLevel() >= 25) ) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Karana."); - Gater->CastSpell(550, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Commons."); - Gater->CastSpell(551, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Toxxulia."); - Gater->CastSpell(552, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "butcher")) && (c->GetLevel() >= 25)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Butcherblock."); - Gater->CastSpell(553, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "lava")) && (c->GetLevel() >= 30)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Lavastorm."); - Gater->CastSpell(554, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 32)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Ro."); - Gater->CastSpell(555, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "feerrott")) && (c->GetLevel() >= 32)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Feerrott."); - Gater->CastSpell(556, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "steamfont")) && (c->GetLevel() >= 31)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Steamfont."); - Gater->CastSpell(557, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "misty")) && (c->GetLevel() >= 36)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Misty."); - Gater->CastSpell(558, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 40)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Wakening Lands."); - Gater->CastSpell(1398, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 32)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Iceclad Ocean."); - Gater->CastSpell(1434, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Great Divide."); - Gater->CastSpell(1438, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 42)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Cobalt Scar."); - Gater->CastSpell(1440, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 33)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Combines."); - Gater->CastSpell(1517, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "surefall")) && (c->GetLevel() >= 26)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Surefall Glade."); - Gater->CastSpell(2020, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Grimling Forest."); - Gater->CastSpell(2419, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 33)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Twilight."); - Gater->CastSpell(2424, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 37)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Dawnshroud."); - Gater->CastSpell(2429, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 26)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Nexus."); - Gater->CastSpell(2432, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 38)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Knowledge."); - Gater->CastSpell(3184, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 28)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Stonebrunt Mountains."); - Gater->CastSpell(3792, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Bloodfields."); - Gater->CastSpell(6184, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 39)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the South."); - Gater->CastSpell(1737, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 44)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the North."); - Gater->CastSpell(1736, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "slaughter")) && (c->GetLevel() >= 64)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Slaughter."); - Gater->CastSpell(6179, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "karana") - || !strcasecmp(sep->arg[2], "tox") - || !strcasecmp(sep->arg[2], "butcher") && (c->GetLevel() <= 25)) - || !strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 27) - || (!strcasecmp(sep->arg[2], "ro") - || !strcasecmp(sep->arg[2], "feerrott") && (c->GetLevel() <= 32)) - || !strcasecmp(sep->arg[2], "steamfont") && (c->GetLevel() <= 31) - || !strcasecmp(sep->arg[2], "misty") && (c->GetLevel() <= 36) - || !strcasecmp(sep->arg[2], "lava") && (c->GetLevel() <= 30) - || !strcasecmp(sep->arg[2], "wakening") && (c->GetLevel() <= 40) - || !strcasecmp(sep->arg[2], "iceclad") && (c->GetLevel() <= 32) - || !strcasecmp(sep->arg[2], "divide") && (c->GetLevel() <= 38) - || !strcasecmp(sep->arg[2], "cobalt") && (c->GetLevel() <= 42) - || !strcasecmp(sep->arg[2], "combines") && (c->GetLevel() <= 33) - || !strcasecmp(sep->arg[2], "surefall") && (c->GetLevel() <= 26) - || !strcasecmp(sep->arg[2], "grimling") && (c->GetLevel() <= 29) - || !strcasecmp(sep->arg[2], "twilight") && (c->GetLevel() <= 33) - || !strcasecmp(sep->arg[2], "dawnshroud") && (c->GetLevel() <= 37) - || !strcasecmp(sep->arg[2], "nexus") && (c->GetLevel() <= 26) - || !strcasecmp(sep->arg[2], "pok") && (c->GetLevel() <= 38) - || !strcasecmp(sep->arg[2], "stonebrunt") && (c->GetLevel() <= 28) - || !strcasecmp(sep->arg[2], "bloodfields") && (c->GetLevel() <= 55) - || !strcasecmp(sep->arg[2], "emerald") && (c->GetLevel() <= 38) - || !strcasecmp(sep->arg[2], "skyfire") && (c->GetLevel() <= 43) - || !strcasecmp(sep->arg[2], "wos") && (c->GetLevel() <= 64)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet."); - } else - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [karana], [commons], [tox], [butcher], [lava], [ro], [feerrott], [steamfont], [misty], [wakening], [iceclad], [divide], [cobalt], [combines], [surefall], [grimling], [twilight], [dawnshroud], [nexus], [pok], [stonebrunt], [bloodfields], [emerald], [skyfire] or [wos]."); + 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: - if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 35) ) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Common Portal."); - Gater->CastSpell(566, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "fay")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal."); - Gater->CastSpell(563, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 37)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Ro Portal."); - Gater->CastSpell(567, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Toxxulia Portal."); - Gater->CastSpell(561, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "nk")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting North Karana Portal."); - Gater->CastSpell(562, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "nek")) && (c->GetLevel() >= 32)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nektulos Portal."); - Gater->CastSpell(564, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 43)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wakening Lands Portal."); - Gater->CastSpell(1399, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 33)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Iceclad Ocean Portal."); - Gater->CastSpell(1418, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Great Divide Portal."); - Gater->CastSpell(1423, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 43)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Cobalt Scar Portal."); - Gater->CastSpell(1425, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 34)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Combines Portal."); - Gater->CastSpell(1516, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "wk")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting West Karana Portal."); - Gater->CastSpell(568, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Twilight Portal."); - Gater->CastSpell(2425, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Dawnshroud Portal."); - Gater->CastSpell(2430, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 29)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nexus Portal."); - Gater->CastSpell(2944, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Plane of Knowledge Portal."); - Gater->CastSpell(3180, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "wos")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wall of Slaughter Portal."); - Gater->CastSpell(6178, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal."); - Gater->CastSpell(2420, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 37)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Emerald Jungle."); - Gater->CastSpell(1739, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "hateplane")) && (c->GetLevel() >= 39)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Hate Plane."); - Gater->CastSpell(666, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "airplane")) && (c->GetLevel() >= 39)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Airplane."); - Gater->CastSpell(674, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 36)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Skyfire."); - Gater->CastSpell(1738, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Bloodfields Portal."); - Gater->CastSpell(6183, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 27)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Stonebrunt Portal."); - Gater->CastSpell(3793, c->GetID(), 1, -1, -1); - } else if ((!strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 35)) - || !strcasecmp(sep->arg[2], "fay") && (c->GetLevel() <= 27) - || (!strcasecmp(sep->arg[2], "ro") && (c->GetLevel() <= 37)) - || !strcasecmp(sep->arg[2], "tox") && (c->GetLevel() <= 25) - || !strcasecmp(sep->arg[2], "nk") && (c->GetLevel() <= 25) - || !strcasecmp(sep->arg[2], "nek") && (c->GetLevel() <= 32) - || !strcasecmp(sep->arg[2], "wakening") && (c->GetLevel() <= 43) - || !strcasecmp(sep->arg[2], "iceclad") && (c->GetLevel() <= 33) - || !strcasecmp(sep->arg[2], "divide") && (c->GetLevel() <= 36) - || !strcasecmp(sep->arg[2], "cobalt") && (c->GetLevel() <= 43) - || !strcasecmp(sep->arg[2], "combines") && (c->GetLevel() <= 34) - || !strcasecmp(sep->arg[2], "wk") && (c->GetLevel() <= 37) - || !strcasecmp(sep->arg[2], "twilight") && (c->GetLevel() <= 33) - || !strcasecmp(sep->arg[2], "dawnshroud") && (c->GetLevel() <= 39) - || !strcasecmp(sep->arg[2], "nexus") && (c->GetLevel() <= 29) - || (!strcasecmp(sep->arg[2], "pok") - || !strcasecmp(sep->arg[2], "hateplane") - || !strcasecmp(sep->arg[2], "airplane") && (c->GetLevel() <= 38)) - || !strcasecmp(sep->arg[2], "grimling") && (c->GetLevel() <= 29) - || !strcasecmp(sep->arg[2], "bloodfields") && (c->GetLevel() <= 55) - || !strcasecmp(sep->arg[2], "stonebrunt") && (c->GetLevel() <= 27) - || !strcasecmp(sep->arg[2], "emerald") && (c->GetLevel() <= 36) - || !strcasecmp(sep->arg[2], "skyfire") && (c->GetLevel() <= 36) - || !strcasecmp(sep->arg[2], "wos") && (c->GetLevel() <= 64)) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet."); - } else - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [commons], [fay], [ro], [tox], [nk], [wakening], [iceclad], [divide], [cobalt], [combines], [wk], [grimling], [twilight], [dawnshroud], [nexus], [pok], [stonebrunt], [bloodfields], [emerald], [skyfire], [hateplane], [airplane] or [wos].", c->GetName()); + } + 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; @@ -10680,25 +10531,25 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 invis 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->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 invisible."); + 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 [invis undead], [invis live] or [invis see]?"); + 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")) @@ -10706,47 +10557,47 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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->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 invisible."); + 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 [invis live] or [invis see]?"); + 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 invis 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->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 invisible."); + 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 [invis undead], [invis live] or [invis see]?"); + 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 invis 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")) @@ -10756,7 +10607,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 [invis undead]"); + 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")) @@ -10767,7 +10618,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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->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())) @@ -10775,13 +10626,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 invisible."); + 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 [invis live] or [invis see]?"); + 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."); @@ -10908,19 +10759,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(ResisterClass) { case CLERIC: if(!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 6)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection."); + 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()->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()->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()->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()->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) @@ -10929,24 +10780,24 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 6)) { Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the required level yet."); } else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); + 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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis 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()->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()->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()->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()->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()->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) @@ -10955,24 +10806,24 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 20)) { Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the needed level yet."); } else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); + 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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis 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()->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()->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()->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()->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()->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) @@ -10980,7 +10831,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 19)) { Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the required level yet.") ; } else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); + 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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis magic", "Resist Magic").c_str()); break; default: c->Message(15, "You must have a Cleric, Shaman, or Druid in your group."); @@ -11053,7 +10904,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { botGroupLeader->BotGroupSay(botGroupLeader, "I am prepared to lead."); else botGroupLeader->BotGroupSay(botGroupLeader, "I cannot lead."); - } else + } + else c->Message(13, "You must target a spawned bot first."); return; @@ -11108,16 +10960,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 + } + 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 + } + else c->Message(13, "You must target a spawned bot first."); - } else + } + else botGroupLeader->BotGroupSay(botGroupMember, "I have no more openings in my group, %s.", c->GetName()); } else { Group* tempGroup = botGroupLeader->GetGroup(); @@ -11148,9 +11003,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { botGroupMember->BotGroupSay(botGroupMember, "I am no longer in a group."); else botGroupMember->BotGroupSay(botGroupMember, "I can not leave %s\'s group.", g->GetLeaderName()); - } else + } + else botGroupMember->BotGroupSay(botGroupMember, "I am not in a group."); - } else + } + else c->Message(13, "You must target a spawned bot first."); return; @@ -13350,4 +13207,45 @@ void Bot::BotHealRotationsClear(Client* c) { } } +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()); + } + } + } + safe_delete_array(escaped_string); + + sayid += 500000; + + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetProxyItemID(sayid); + linker.SetProxyText(name); + + auto say_link = linker.GenerateLink(); + return say_link; +} + #endif diff --git a/zone/bot.h b/zone/bot.h index 7f2652498..2c5e30644 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -549,6 +549,8 @@ public: void SetNumHealRotationMembers( uint8 numMembers ) { _numHealRotationMembers = numMembers; } void SetBardUseOutOfCombatSongs(bool useOutOfCombatSongs) { _bardUseOutOfCombatSongs = useOutOfCombatSongs;} void SetShowHelm(bool showhelm) { _showhelm = showhelm; } + + std::string CreateSayLink(Client* botOwner, const char* message, const char* name); // Class Destructors virtual ~Bot(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 0e2f0da08..ce63610da 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6008,7 +6008,7 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app) char *escSearchString = new char[129]; database.DoEscapeString(escSearchString, gmscs->Name, strlen(gmscs->Name)); - std::string query = StringFormat("SELECT charname, zoneid, x, y, z, time_of_death, rezzed, IsBurried " + std::string query = StringFormat("SELECT charname, zoneid, x, y, z, time_of_death, is_rezzed, is_buried " "FROM character_corpses WheRE charname LIKE '%%%s%%' ORDER BY charname LIMIT %i", escSearchString, maxResults); safe_delete_array(escSearchString); diff --git a/zone/command.cpp b/zone/command.cpp index ac419043f..7a846898b 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -170,6 +170,7 @@ int command_init(void) { command_add("appearance", "[type] [value] - Send an appearance packet for you or your target", 150, command_appearance) || command_add("attack", "[targetname] - Make your NPC target attack targetname", 150, command_attack) || command_add("augmentitem", "Force augments an item. Must have the augment item window open.", 250, command_augmentitem) || + command_add("aug", nullptr, 250, command_augmentitem) || command_add("ban", "[name] [reason]- Ban by character name", 150, command_ban) || command_add("beard", "- Change the beard of your target", 80, command_beard) || command_add("beardcolor", "- Change the beard color of your target", 80, command_beardcolor) || @@ -216,12 +217,14 @@ int command_init(void) { command_add("flagedit", "- Edit zone flags on your target", 100, command_flagedit) || command_add("flags", "- displays the flags of you or your target", 0, command_flags) || command_add("flymode", "[0/1/2] - Set your or your player target's flymode to off/on/levitate", 50, command_flymode) || + command_add("fn", nullptr, 100, command_findnpctype) || command_add("fov", "- Check wether you're behind or in your target's field of view", 80, command_fov) || command_add("freeze", "- Freeze your target", 80, command_freeze) || - command_add("fz", nullptr, 10, command_findzone) || + command_add("fs", nullptr, 50, command_findspell) || + command_add("fz", nullptr, 100, command_findzone) || command_add("gassign", "[id] - Assign targetted NPC to predefined wandering grid id", 100, command_gassign) || command_add("gender", "[0/1/2] - Change your or your target's gender to male/female/neuter", 50, command_gender) || - command_add("getplayerburriedcorpsecount", "- Get the target's total number of burried player corpses.", 100, command_getplayerburriedcorpsecount) || + command_add("getplayerburiedcorpsecount", "- Get the target's total number of buried player corpses.", 100, command_getplayerburiedcorpsecount) || command_add("getvariable", "[varname] - Get the value of a variable from the database", 200, command_getvariable) || command_add("gi", nullptr,200, command_giveitem) || command_add("ginfo", "- get group info on target.", 20, command_ginfo) || @@ -386,7 +389,7 @@ int command_init(void) { command_add("spon", "- Sends OP_MemorizeSpell", 80, command_spon) || command_add("stun", "[duration] - Stuns you or your target for duration", 100, command_stun) || command_add("summon", "[charname] - Summons your player/npc/corpse target, or charname if specified", 80, command_summon) || - command_add("summonburriedplayercorpse", "- Summons the target's oldest burried corpse, if any exist.", 100, command_summonburriedplayercorpse) || + command_add("summonburiedplayercorpse", "- Summons the target's oldest buried corpse, if any exist.", 100, command_summonburiedplayercorpse) || command_add("summonitem", "[itemid] [charges] - Summon an item onto your cursor. Charges are optional.", 200, command_summonitem) || command_add("suspend", "[name] [days] [reason] - Suspend by character name and for specificed number of days", 150, command_suspend) || command_add("task", "(subcommand) - Task system commands", 150, command_task) || @@ -7801,7 +7804,7 @@ void command_deletegraveyard(Client *c, const Seperator *sep) return; } -void command_summonburriedplayercorpse(Client *c, const Seperator *sep) +void command_summonburiedplayercorpse(Client *c, const Seperator *sep) { Client *t=c; @@ -7815,12 +7818,12 @@ void command_summonburriedplayercorpse(Client *c, const Seperator *sep) Corpse* PlayerCorpse = database.SummonBuriedCharacterCorpses(t->CharacterID(), t->GetZoneID(), zone->GetInstanceID(), t->GetPosition()); if(!PlayerCorpse) - c->Message(0, "Your target doesn't have any burried corpses."); + c->Message(0, "Your target doesn't have any buried corpses."); return; } -void command_getplayerburriedcorpsecount(Client *c, const Seperator *sep) +void command_getplayerburiedcorpsecount(Client *c, const Seperator *sep) { Client *t=c; @@ -7834,9 +7837,9 @@ void command_getplayerburriedcorpsecount(Client *c, const Seperator *sep) uint32 CorpseCount = database.GetCharacterBuriedCorpseCount(t->CharacterID()); if(CorpseCount > 0) - c->Message(0, "Your target has a total of %u burried corpses.", CorpseCount); + c->Message(0, "Your target has a total of %u buried corpses.", CorpseCount); else - c->Message(0, "Your target doesn't have any burried corpses."); + c->Message(0, "Your target doesn't have any buried corpses."); return; } diff --git a/zone/command.h b/zone/command.h index 795f75919..bf20d46d2 100644 --- a/zone/command.h +++ b/zone/command.h @@ -279,8 +279,8 @@ void command_refundaa(Client *c, const Seperator *sep); void command_traindisc(Client *c, const Seperator *sep); void command_deletegraveyard(Client *c, const Seperator *sep); void command_setgraveyard(Client *c, const Seperator *sep); -void command_getplayerburriedcorpsecount(Client *c, const Seperator *sep); -void command_summonburriedplayercorpse(Client *c, const Seperator *sep); +void command_getplayerburiedcorpsecount(Client *c, const Seperator *sep); +void command_summonburiedplayercorpse(Client *c, const Seperator *sep); void command_unscribespell(Client *c, const Seperator *sep); void command_scribespell(Client *c, const Seperator *sep); void command_refreshgroup(Client *c, const Seperator *sep); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index fad65aa3a..af937e41b 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -835,7 +835,7 @@ bool Corpse::Process() { Save(); player_corpse_depop = true; corpse_db_id = 0; - Log.Out(Logs::General, Logs::None, "Tagged %s player corpse has burried.", this->GetName()); + Log.Out(Logs::General, Logs::None, "Tagged %s player corpse has buried.", this->GetName()); } else { Log.Out(Logs::General, Logs::Error, "Unable to bury %s player corpse.", this->GetName()); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 6db7777ac..871d47074 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1748,18 +1748,18 @@ XS(XS__clear_zone_flag) XSRETURN_EMPTY; } -XS(XS__summonburriedplayercorpse); -XS(XS__summonburriedplayercorpse) +XS(XS__summonburiedplayercorpse); +XS(XS__summonburiedplayercorpse) { dXSARGS; if (items != 5) - Perl_croak(aTHX_ "Usage: summonburriedplayercorpse(char_id,dest_x,dest_y,dest_z,dest_heading)"); + Perl_croak(aTHX_ "Usage: summonburiedplayercorpse(char_id,dest_x,dest_y,dest_z,dest_heading)"); bool RETVAL; uint32 char_id = (int)SvIV(ST(0)); auto position = glm::vec4((float)SvIV(ST(1)), (float)SvIV(ST(2)), (float)SvIV(ST(3)),(float)SvIV(ST(4))); - RETVAL = quest_manager.summonburriedplayercorpse(char_id, position); + RETVAL = quest_manager.summonburiedplayercorpse(char_id, position); ST(0) = boolSV(RETVAL); sv_2mortal(ST(0)); @@ -1784,19 +1784,19 @@ XS(XS__summonallplayercorpses) XSRETURN(1); } -XS(XS__getplayerburriedcorpsecount); -XS(XS__getplayerburriedcorpsecount) +XS(XS__getplayerburiedcorpsecount); +XS(XS__getplayerburiedcorpsecount) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: getplayerburriedcorpsecount(char_id)"); + Perl_croak(aTHX_ "Usage: getplayerburiedcorpsecount(char_id)"); uint32 RETVAL; dXSTARG; uint32 char_id = (int)SvIV(ST(0)); - RETVAL = quest_manager.getplayerburriedcorpsecount(char_id); + RETVAL = quest_manager.getplayerburiedcorpsecount(char_id); XSprePUSH; PUSHu((IV)RETVAL); XSRETURN(1); @@ -3712,7 +3712,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "get_spawn_condition"), XS__get_spawn_condition, file); newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file); newXS(strcpy(buf, "getlevel"), XS__getlevel, file); - newXS(strcpy(buf, "getplayerburriedcorpsecount"), XS__getplayerburriedcorpsecount, file); + newXS(strcpy(buf, "getplayerburiedcorpsecount"), XS__getplayerburiedcorpsecount, file); newXS(strcpy(buf, "gettaskactivitydonecount"), XS__gettaskactivitydonecount, file); newXS(strcpy(buf, "givecash"), XS__givecash, file); newXS(strcpy(buf, "gmmove"), XS__gmmove, file); @@ -3802,7 +3802,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "stopalltimers"), XS__stopalltimers, file); newXS(strcpy(buf, "stoptimer"), XS__stoptimer, file); newXS(strcpy(buf, "summonallplayercorpses"), XS__summonallplayercorpses, file); - newXS(strcpy(buf, "summonburriedplayercorpse"), XS__summonburriedplayercorpse, file); + newXS(strcpy(buf, "summonburiedplayercorpse"), XS__summonburiedplayercorpse, file); newXS(strcpy(buf, "summonitem"), XS__summonitem, file); newXS(strcpy(buf, "surname"), XS__surname, file); newXS(strcpy(buf, "targlobal"), XS__targlobal, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index bf65fea7c..483426b2e 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -513,16 +513,16 @@ void lua_toggle_spawn_event(int event_id, bool enable, bool strict, bool reset) quest_manager.toggle_spawn_event(event_id, enable, strict, reset); } -void lua_summon_burried_player_corpse(uint32 char_id, float x, float y, float z, float h) { - quest_manager.summonburriedplayercorpse(char_id, glm::vec4(x, y, z, h)); +void lua_summon_buried_player_corpse(uint32 char_id, float x, float y, float z, float h) { + quest_manager.summonburiedplayercorpse(char_id, glm::vec4(x, y, z, h)); } void lua_summon_all_player_corpses(uint32 char_id, float x, float y, float z, float h) { quest_manager.summonallplayercorpses(char_id, glm::vec4(x, y, z, h)); } -int lua_get_player_burried_corpse_count(uint32 char_id) { - return quest_manager.getplayerburriedcorpsecount(char_id); +int lua_get_player_buried_corpse_count(uint32 char_id) { + return quest_manager.getplayerburiedcorpsecount(char_id); } bool lua_bury_player_corpse(uint32 char_id) { @@ -1524,9 +1524,9 @@ luabind::scope lua_register_general() { luabind::def("spawn_condition", &lua_spawn_condition), luabind::def("get_spawn_condition", &lua_get_spawn_condition), luabind::def("toggle_spawn_event", &lua_toggle_spawn_event), - luabind::def("summon_burried_player_corpse", &lua_summon_burried_player_corpse), + luabind::def("summon_buried_player_corpse", &lua_summon_buried_player_corpse), luabind::def("summon_all_player_corpses", &lua_summon_all_player_corpses), - luabind::def("get_player_burried_corpse_count", &lua_get_player_burried_corpse_count), + luabind::def("get_player_buried_corpse_count", &lua_get_player_buried_corpse_count), luabind::def("bury_player_corpse", &lua_bury_player_corpse), luabind::def("task_selector", &lua_task_selector), luabind::def("task_set_selector", &lua_task_set_selector), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 71f0de917..b6243091f 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1774,7 +1774,7 @@ void QuestManager::sethp(int hpperc) { owner->Damage(owner, newhp, SPELL_UNKNOWN, SkillHandtoHand, false, 0, false); } -bool QuestManager::summonburriedplayercorpse(uint32 char_id, const glm::vec4& position) { +bool QuestManager::summonburiedplayercorpse(uint32 char_id, const glm::vec4& position) { bool Result = false; if(char_id <= 0) @@ -1798,7 +1798,7 @@ bool QuestManager::summonallplayercorpses(uint32 char_id, const glm::vec4& posit return true; } -uint32 QuestManager::getplayerburriedcorpsecount(uint32 char_id) { +uint32 QuestManager::getplayerburiedcorpsecount(uint32 char_id) { uint32 Result = 0; if(char_id > 0) { diff --git a/zone/questmgr.h b/zone/questmgr.h index 879407dc6..960a8f1f4 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -159,9 +159,9 @@ public: void set_zone_flag(int zone_id); void clear_zone_flag(int zone_id); void sethp(int hpperc); - bool summonburriedplayercorpse(uint32 char_id, const glm::vec4& position); + bool summonburiedplayercorpse(uint32 char_id, const glm::vec4& position); bool summonallplayercorpses(uint32 char_id, const glm::vec4& position); - uint32 getplayerburriedcorpsecount(uint32 char_id); + uint32 getplayerburiedcorpsecount(uint32 char_id); bool buryplayercorpse(uint32 char_id); void forcedooropen(uint32 doorid, bool altmode); void forcedoorclose(uint32 doorid, bool altmode); From 61c9a0759698b0b52c5b9a345bc981d4c33ebc0b Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 6 Jul 2015 14:05:09 -0400 Subject: [PATCH 253/846] Fixed guild windows on bot-enabled servers. --- common/guild_base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 1416dedf1..bfd9f4126 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -867,7 +867,7 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) { //factored out so I dont have to copy this crap. #ifdef BOTS #define GuildMemberBaseQuery \ -"SELECT c.id,c.name,c.class,c.level,c.timelaston,c.zoneid," \ +"SELECT c.id,c.name,c.class,c.level,c.last_login,c.zone_id," \ " g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \ " g.banker,g.public_note,g.alt" \ " FROM vwBotCharacterMobs AS c LEFT JOIN vwGuildMembers AS g ON c.id=g.char_id AND c.mobtype = g.mobtype " From 1e75b4ba779635edb4a5162e61461e29eec89ade Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 6 Jul 2015 16:11:00 -0400 Subject: [PATCH 254/846] Implement Triple Attack as a skill See change log for more details Optional SQL will max toons triple attack skills --- changelog.txt | 7 + common/skills.h | 9 +- .../git/optional/2015_07_06_TripleAttack.sql | 27 ++++ zone/attack.cpp | 75 +++++----- zone/client.h | 3 +- zone/command.cpp | 128 +++++++++--------- zone/mob.cpp | 8 ++ zone/mob.h | 3 +- zone/special_attacks.cpp | 4 +- 9 files changed, 157 insertions(+), 107 deletions(-) create mode 100644 utils/sql/git/optional/2015_07_06_TripleAttack.sql diff --git a/changelog.txt b/changelog.txt index 227058eba..f5d1803d0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/06/2015 == +mackal: Implement Triple Attack Skill + Parses showed about rand(1000) for the chance, may need more investigating + Corrected Double Attack chances as well + Running optional 2015_07_06_TripleAttack.sql will set current toons to their max skill + This is optional because the admins might want to go a different route. + == 07/05/2015 == mackal: Rewrite NPC combat attack round logic An NPC "quading" is really just an NPC with innate dual wield that doubles on both hands diff --git a/common/skills.h b/common/skills.h index 1fad4de3e..c79a522ee 100644 --- a/common/skills.h +++ b/common/skills.h @@ -108,16 +108,17 @@ enum SkillUseTypes /*13869*/ SkillBerserking, /*13902*/ SkillTaunt, /*05837*/ SkillFrenzy, // This appears to be the only listed one not grouped with the others -/*00000*/ _EmuSkillCount // move to last position of active enumeration labels // SoF+ specific skills -// /*03670*/ SkillRemoveTraps, -// /*13049*/ SkillTripleAttack, +/*03670*/ SkillRemoveTraps, +/*13049*/ SkillTripleAttack, // RoF2+ specific skills // /*00789*/ Skill2HPiercing, // /*01216*/ SkillNone, // This needs to move down as new skills are added +/*00000*/ _EmuSkillCount // 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 @@ -170,7 +171,7 @@ enum SkillUseTypes }; // temporary until it can be sorted out... -#define HIGHEST_SKILL SkillFrenzy +#define HIGHEST_SKILL SkillTripleAttack // Spell Effects use this value to determine if an effect applies to all skills. #define ALL_SKILLS -1 diff --git a/utils/sql/git/optional/2015_07_06_TripleAttack.sql b/utils/sql/git/optional/2015_07_06_TripleAttack.sql new file mode 100644 index 000000000..e5061e108 --- /dev/null +++ b/utils/sql/git/optional/2015_07_06_TripleAttack.sql @@ -0,0 +1,27 @@ +DELIMITER $$ +DROP PROCEDURE IF EXISTS GrantTripleAttack$$ +CREATE PROCEDURE GrantTripleAttack() + BEGIN + DECLARE finished INT; + DECLARE char_id INT; + DECLARE skill_max INT; + DECLARE cur CURSOR FOR SELECT character_data.id, skill_caps.cap FROM `character_data` LEFT JOIN `skill_caps` ON character_data.`level` = skill_caps.`level` AND character_data.class = skill_caps.class AND skill_caps.skillID = 76; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1; + + OPEN cur; + + SET finished = 0; + REPEAT + FETCH cur INTO char_id, skill_max; + + IF skill_max IS NOT NULL AND skill_max > 0 THEN + REPLACE INTO `character_skills` (`id`, `skill_id`, `value`) VALUES(char_id, 76, skill_max); + END IF; + UNTIL finished END REPEAT; + + CLOSE cur; + END$$ +DELIMITER ; + +CALL GrantTripleAttack(); +DROP PROCEDURE GrantTripleAttack; diff --git a/zone/attack.cpp b/zone/attack.cpp index 02b16c64e..440e8c59a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3406,41 +3406,39 @@ bool Mob::HasRangedProcs() const return false; } -bool Client::CheckDoubleAttack(bool tripleAttack) { - +bool Client::CheckDoubleAttack() +{ + int chance = 0; + int skill = GetSkill(SkillDoubleAttack); //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(!HasSkill(SkillDoubleAttack) && !bonusGiveDA) + int bonusGiveDA = aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack; + if (skill > 0) + chance = skill + GetLevel(); + else if (!bonusGiveDA) return false; - float chance = 0.0f; + if (bonusGiveDA) + chance += bonusGiveDA / 100.0f * 500; // convert to skill value + int per_inc = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance; + if (per_inc) + chance += chance * per_inc / 100; - uint16 skill = GetSkill(SkillDoubleAttack); + return zone->random.Int(1, 500) <= chance; +} - int32 bonusDA = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance; +// Admittedly these parses were short, but this check worked for 3 toons across multiple levels +// with varying triple attack skill (1-3% error at least) +bool Client::CheckTripleAttack() +{ + int chance = GetSkill(SkillTripleAttack); + if (chance < 1) + return false; - //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; + int per_inc = aabonuses.TripleAttackChance + spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance; + if (per_inc) + chance += chance * per_inc / 100; - //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] - int32 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(zone->random.Roll(chance)) - return true; - - return false; + return zone->random.Int(1, 1000) <= chance; } bool Client::CheckDoubleRangedAttack() { @@ -3452,7 +3450,7 @@ bool Client::CheckDoubleRangedAttack() { return false; } -bool Mob::CheckDoubleAttack(bool tripleAttack) +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 @@ -5054,21 +5052,28 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) if (candouble) { CheckIncreaseSkill(SkillDoubleAttack, target, -10); - if (CheckDoubleAttack()) - Attack(target, hand, false, false, IsFromSpell); - if (hand == MainPrimary && GetLevel() >= 60 && - (GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER) && - CheckDoubleAttack(true)) + if (CheckDoubleAttack()) { Attack(target, hand, false, false, IsFromSpell); + // you can only triple from the main hand + if (hand == MainPrimary && CanThisClassTripleAttack()) { + CheckIncreaseSkill(SkillTripleAttack, target, -10); + if (CheckTripleAttack()) + Attack(target, hand, false, false, IsFromSpell); + } + } } + if (hand == MainPrimary) { + // 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/client.h b/zone/client.h index 7558d9bb6..03d09d50c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -888,7 +888,8 @@ public: bool CheckTradeLoreConflict(Client* other); void LinkDead(); void Insight(uint32 t_id); - bool CheckDoubleAttack(bool tripleAttack = false); + bool CheckDoubleAttack(); + bool CheckTripleAttack(); bool CheckDoubleRangedAttack(); bool CheckDualWield(); diff --git a/zone/command.cpp b/zone/command.cpp index 7a846898b..3b8fba3f6 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -146,7 +146,7 @@ Access Levels: */ int command_init(void) { - + if ( @@ -434,7 +434,7 @@ int command_init(void) { command_add("zsave", " - Saves zheader to the database", 80, command_zsave) || command_add("zsky", "[skytype] - Change zone sky type", 80, command_zsky) || command_add("zstats", "- Show info about zone header", 80, command_zstats) || - command_add("zunderworld", "[zcoord] - Sets the underworld using zcoord", 80, command_zunderworld) || + command_add("zunderworld", "[zcoord] - Sets the underworld using zcoord", 80, command_zunderworld) || command_add("zuwcoords", "[z coord] - Set underworld coord", 80, command_zuwcoords) ) { @@ -644,8 +644,8 @@ void command_logcommand(Client *c, const char *message) c->AccountName(), c->AccountID(), admin,c->GetName(), - c->GetTarget()?c->GetTarget()->GetName():"None", - "Command", + c->GetTarget()?c->GetTarget()->GetName():"None", + "Command", message, 1 ); @@ -731,7 +731,7 @@ void command_setfaction(Client *c, const Seperator *sep) auto npcTypeID = c->GetTarget()->CastToNPC()->GetNPCTypeID(); c->Message(15,"Setting NPC %u to faction %i", npcTypeID, atoi(sep->argplus[1])); - std::string query = StringFormat("UPDATE npc_types SET npc_faction_id = %i WHERE id = %i", + std::string query = StringFormat("UPDATE npc_types SET npc_faction_id = %i WHERE id = %i", atoi(sep->argplus[1]), npcTypeID); database.QueryDatabase(query); } @@ -2302,7 +2302,7 @@ void command_setskill(Client *c, const Seperator *sep) 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) + if(skill_num <= HIGHEST_SKILL) c->GetTarget()->CastToClient()->SetSkill((SkillUseTypes)skill_num, skill_value); } } @@ -2573,7 +2573,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", + c->Message((item_data == nullptr), "WornSlot: %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())); } @@ -2584,7 +2584,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", + 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())); } @@ -2596,7 +2596,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i", + 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) { @@ -2606,7 +2606,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", + 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())); } } @@ -2618,7 +2618,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message(1, "CursorSlot: %i, Item: %i (%s), Charges: %i", + c->Message(1, "CursorSlot: %i, Item: %i (%s), Charges: %i", MainCursor, 0, item_link.c_str(), 0); } else { @@ -2630,7 +2630,7 @@ 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", + 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())); for (uint8 indexSub = SUB_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { @@ -2640,7 +2640,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", + 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())); } } @@ -2655,7 +2655,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message((item_data == nullptr), "TributeSlot: %i, Item: %i (%s), Charges: %i", + c->Message((item_data == nullptr), "TributeSlot: %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())); } @@ -2667,7 +2667,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i", + 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) { @@ -2677,7 +2677,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", + 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())); } } @@ -2688,8 +2688,8 @@ void command_peekinv(Client *c, const Seperator *sep) linker.SetItemInst(inst_main); item_link = linker.GenerateLink(); - - c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", + + 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) { @@ -2699,7 +2699,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", + 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())); } } @@ -2712,7 +2712,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i", + 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) { @@ -2722,7 +2722,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", + 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())); } } @@ -2744,7 +2744,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i", + 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())); for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { @@ -2754,7 +2754,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); - c->Message((item_data == nullptr), " WorldBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + c->Message((item_data == nullptr), " WorldBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", INVALID_INDEX, indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -3752,7 +3752,7 @@ void command_spellinfo(Client *c, const Seperator *sep) c->Message(0, " zonetype: %d", s->zonetype); c->Message(0, " EnvironmentType: %d", s->EnvironmentType); c->Message(0, " TimeOfDay: %d", s->TimeOfDay); - c->Message(0, " classes[15]: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", + c->Message(0, " classes[15]: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", s->classes[0], s->classes[1], s->classes[2], s->classes[3], s->classes[4], s->classes[5], s->classes[6], s->classes[7], s->classes[8], s->classes[9], s->classes[10], s->classes[11], s->classes[12], s->classes[13], s->classes[14]); @@ -3882,7 +3882,7 @@ void command_repop(Client *c, const Seperator *sep) LinkedListIterator iterator(zone->spawn2_list); iterator.Reset(); while (iterator.MoreElements()) { - std::string query = StringFormat("DELETE FROM respawn_times WHERE id = %lu AND instance_id = %lu", + std::string query = StringFormat("DELETE FROM respawn_times WHERE id = %lu AND instance_id = %lu", (unsigned long)iterator.GetData()->GetID(), (unsigned long)zone->GetInstanceID()); auto results = database.QueryDatabase(query); @@ -4256,7 +4256,7 @@ void command_spawnfix(Client *c, const Seperator *sep) { return; } - std::string query = StringFormat("UPDATE spawn2 SET x = '%f', y = '%f', z = '%f', heading = '%f' WHERE id = '%i'", + std::string query = StringFormat("UPDATE spawn2 SET x = '%f', y = '%f', z = '%f', heading = '%f' WHERE id = '%i'", c->GetX(), c->GetY(), c->GetZ(), c->GetHeading(),s2->GetID()); auto results = database.QueryDatabase(query); if (!results.Success()) { @@ -4399,11 +4399,11 @@ void command_time(Client *c, const Seperator *sep) c->Message(13, "To set the Time: #time HH [MM]"); TimeOfDay_Struct eqTime; zone->zone_time.GetCurrentEQTimeOfDay( time(0), &eqTime); - sprintf(timeMessage,"%02d:%s%d %s (Timezone: %ih %im)", + sprintf(timeMessage,"%02d:%s%d %s (Timezone: %ih %im)", ((eqTime.hour - 1) % 12) == 0 ? 12 : ((eqTime.hour - 1) % 12), - (eqTime.minute < 10) ? "0" : "", + (eqTime.minute < 10) ? "0" : "", eqTime.minute, - (eqTime.hour >= 13) ? "pm" : "am", + (eqTime.hour >= 13) ? "pm" : "am", zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneMin() ); @@ -5734,7 +5734,7 @@ void command_suspend(Client *c, const Seperator *sep) } std::string query = StringFormat("UPDATE `account` SET `suspendeduntil` = DATE_ADD(NOW(), INTERVAL %i DAY), " - "suspend_reason = '%s' WHERE `id` = %i", + "suspend_reason = '%s' WHERE `id` = %i", duration, EscapeString(message).c_str(), accountID); auto results = database.QueryDatabase(query); @@ -6206,21 +6206,21 @@ void command_npcedit(Client *c, const Seperator *sep) database.QueryDatabase(query); return; } - + if (strcasecmp(sep->arg[1], "meleetype") == 0) { c->Message(15,"NPCID %u now has a primary melee type of %i and a secondary melee type of %i.", npcTypeID, atoi(sep->arg[2]), atoi(sep->arg[3])); std::string query = StringFormat("UPDATE npc_types SET prim_melee_type = %i, sec_melee_type = %i WHERE id = %i", atoi(sep->arg[2]), atoi(sep->arg[3]), npcTypeID); database.QueryDatabase(query); return; } - + if (strcasecmp(sep->arg[1], "rangedtype") == 0) { c->Message(15,"NPCID %u now has a ranged type of %i.", npcTypeID, atoi(sep->argplus[2])); std::string query = StringFormat("UPDATE npc_types SET rangedtype = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); return; } - + if (strcasecmp(sep->arg[1], "ammoidfile") == 0) { c->Message(15,"NPCID %u's ammo id file is now %i", npcTypeID, atoi(sep->argplus[2])); std::string query = StringFormat("UPDATE npc_types SET ammoidfile = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); @@ -6255,7 +6255,7 @@ void command_npcedit(Client *c, const Seperator *sep) database.QueryDatabase(query); return; } - + if (strcasecmp(sep->arg[1], "walkspeed") == 0) { c->Message(15,"NPCID %u now walks at %f", npcTypeID, atof(sep->argplus[2])); std::string query = StringFormat("UPDATE npc_types SET walkspeed = %f WHERE id = %i", atof(sep->argplus[2]), npcTypeID); @@ -6409,7 +6409,7 @@ void command_npcedit(Client *c, const Seperator *sep) database.QueryDatabase(query); return; } - + if (strcasecmp(sep->arg[1], "Avoidance") == 0) { c->Message(15,"NPCID %u now has %i Avoidance.", npcTypeID, atoi(sep->argplus[2])); std::string query = StringFormat("UPDATE npc_types SET avoidance = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); @@ -6465,7 +6465,7 @@ void command_npcedit(Client *c, const Seperator *sep) database.QueryDatabase(query); return; } - + if (strcasecmp(sep->arg[1], "Attackcount") == 0) { c->Message(15,"NPCID %u now has attack_count set to %i", npcTypeID,atoi(sep->arg[2])); std::string query = StringFormat("UPDATE npc_types SET attack_count = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); @@ -6502,7 +6502,7 @@ void command_npcedit(Client *c, const Seperator *sep) "luclin_hairstyle = %i, luclin_beard = %i, " "face = %i, drakkin_heritage = %i, " "drakkin_tattoo = %i, drakkin_details = %i " - "WHERE id = %i", + "WHERE id = %i", target->GetHairColor(), target->GetBeardColor(), target->GetHairStyle(), target->GetBeard(), target->GetLuclinFace(), target->GetDrakkinHeritage(), @@ -6588,7 +6588,7 @@ void command_npcedit(Client *c, const Seperator *sep) database.QueryDatabase(query); return; } - + if (strcasecmp(sep->arg[1], "slow_mitigation") == 0) { c->Message(15, "NPCID %u's slow mitigation limit is now %i.", npcTypeID, atoi(sep->arg[2])); std::string query = StringFormat("UPDATE npc_types SET slow_mitigation = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); @@ -6643,7 +6643,7 @@ void command_qglobal(Client *c, const Seperator *sep) { } if(!strcasecmp(sep->arg[1], "on")) { - std::string query = StringFormat("UPDATE npc_types SET qglobal = 1 WHERE id = '%i'", + std::string query = StringFormat("UPDATE npc_types SET qglobal = 1 WHERE id = '%i'", target->GetNPCTypeID()); auto results = database.QueryDatabase(query); if(!results.Success()) { @@ -6656,7 +6656,7 @@ void command_qglobal(Client *c, const Seperator *sep) { } if(!strcasecmp(sep->arg[1], "off")) { - std::string query = StringFormat("UPDATE npc_types SET qglobal = 0 WHERE id = '%i'", + std::string query = StringFormat("UPDATE npc_types SET qglobal = 0 WHERE id = '%i'", target->GetNPCTypeID()); auto results = database.QueryDatabase(query); if(!results.Success()) { @@ -7052,13 +7052,13 @@ void command_ginfo(Client *c, const Seperator *sep) if(g->membername[r][0] == '\0') continue; c->Message(0, "...Zoned Member: %s, Roles: %s %s %s", g->membername[r], - (g->MemberRoles[r] & RoleAssist) ? "Assist" : "", - (g->MemberRoles[r] & RoleTank) ? "Tank" : "", + (g->MemberRoles[r] & RoleAssist) ? "Assist" : "", + (g->MemberRoles[r] & RoleTank) ? "Tank" : "", (g->MemberRoles[r] & RolePuller) ? "Puller" : ""); } else { c->Message(0, "...In-Zone Member: %s (0x%x) Roles: %s %s %s", g->membername[r], g->members[r], - (g->MemberRoles[r] & RoleAssist) ? "Assist" : "", - (g->MemberRoles[r] & RoleTank) ? "Tank" : "", + (g->MemberRoles[r] & RoleAssist) ? "Assist" : "", + (g->MemberRoles[r] & RoleTank) ? "Tank" : "", (g->MemberRoles[r] & RolePuller) ? "Puller" : ""); } @@ -7221,7 +7221,7 @@ void command_flagedit(Client *c, const Seperator *sep) { flag_name[127] = '\0'; std::string query = StringFormat("UPDATE zone SET flag_needed = '%s' " - "WHERE zoneidnumber = %d AND version = %d", + "WHERE zoneidnumber = %d AND version = %d", flag_name, zoneid, zone->GetInstanceVersion()); auto results = database.QueryDatabase(query); if(!results.Success()) { @@ -7248,7 +7248,7 @@ void command_flagedit(Client *c, const Seperator *sep) { } std::string query = StringFormat("UPDATE zone SET flag_needed = '' " - "WHERE zoneidnumber = %d AND version = %d", + "WHERE zoneidnumber = %d AND version = %d", zoneid, zone->GetInstanceVersion()); auto results = database.QueryDatabase(query); if(!results.Success()) { @@ -7880,7 +7880,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) std::string query = StringFormat("INSERT INTO spawngroup " "(name, spawn_limit, dist, max_x, min_x, max_y, min_y, delay) " - "VALUES (\"%s\", %i, %f, %f, %f, %f, %f, %i)", + "VALUES (\"%s\", %i, %f, %f, %f, %f, %f, %i)", sep->arg[2], (sep->arg[3]? atoi(sep->arg[3]): 0), (sep->arg[4]? atof(sep->arg[4]): 0), @@ -7907,7 +7907,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) } std::string query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) " - "VALUES (%i, %i, %i)", + "VALUES (%i, %i, %i)", atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); auto results = database.QueryDatabase(query); if (!results.Success()) { @@ -7928,7 +7928,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) } std::string query = StringFormat("UPDATE spawngroup SET dist = '%f', max_x = '%f', min_x = '%f', " - "max_y = '%f', min_y = '%f', delay = '%i' WHERE id = '%i'", + "max_y = '%f', min_y = '%f', delay = '%i' WHERE id = '%i'", atof(sep->arg[3]), atof(sep->arg[4]), atof(sep->arg[5]), atof(sep->arg[6]), atof(sep->arg[7]), atoi(sep->arg[8]), atoi(sep->arg[2])); @@ -8013,7 +8013,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) } std::string query = StringFormat("UPDATE spawn2 SET x = '%f', y = '%f', z = '%f', heading = '%f' " - "WHERE id = '%i'", + "WHERE id = '%i'", c->GetX(), c->GetY(), c->GetZ(), c->GetHeading(),s2->GetID()); auto results = database.QueryDatabase(query); if (!results.Success()) { @@ -8084,7 +8084,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) int16 version = atoi(sep->arg[2]); std::string query = StringFormat("UPDATE spawn2 SET version = %i " - "WHERE spawngroupID = '%i'", + "WHERE spawngroupID = '%i'", version, c->GetTarget()->CastToNPC()->GetSp2()); auto results = database.QueryDatabase(query); if (!results.Success()) { @@ -10135,7 +10135,7 @@ void command_zopp(Client *c, const Seperator *sep) ItemInst* 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.", + 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, std::abs(charges == 1) ? "charge" : "charges", slotid); safe_delete(FakeItemInst); @@ -10354,7 +10354,7 @@ void command_tune(Client *c, const Seperator *sep) ac_override = 0; if (!info_level) info_level = 1; - + if(!strcasecmp(sep->arg[2], "A")) c->Tune_FindATKByPctMitigation(defender, attacker, pct_mitigation, interval, max_loop,ac_override,info_level); else if(!strcasecmp(sep->arg[2], "B")) @@ -10389,7 +10389,7 @@ void command_tune(Client *c, const Seperator *sep) atk_override = 0; if (!info_level) info_level = 1; - + if(!strcasecmp(sep->arg[2], "A")) c->Tune_FindACByPctMitigation(defender, attacker, pct_mitigation, interval, max_loop,atk_override,info_level); else if(!strcasecmp(sep->arg[2], "B")) @@ -10431,7 +10431,7 @@ void command_tune(Client *c, const Seperator *sep) c->Message(10, "#Tune - Error hit chance out of bounds. [Max %.2f Min .2f]", RuleR(Combat,MaxChancetoHit),RuleR(Combat,MinChancetoHit)); return; } - + if(!strcasecmp(sep->arg[2], "A")) c->Tune_FindAccuaryByHitChance(defender, attacker, hit_chance, interval, max_loop,avoid_override,info_level); else if(!strcasecmp(sep->arg[2], "B")) @@ -10473,7 +10473,7 @@ void command_tune(Client *c, const Seperator *sep) c->Message(10, "#Tune - Error hit chance out of bounds. [Max %.2f Min .2f]", RuleR(Combat,MaxChancetoHit),RuleR(Combat,MinChancetoHit)); return; } - + if(!strcasecmp(sep->arg[2], "A")) c->Tune_FindAvoidanceByHitChance(defender, attacker, hit_chance, interval, max_loop,acc_override, info_level); else if(!strcasecmp(sep->arg[2], "B")) @@ -10499,7 +10499,7 @@ void command_logtest(Client *c, const Seperator *sep){ for (i = 0; i < atoi(sep->arg[1]); i++){ Log.Out(Logs::General, Logs::Debug, "[%u] Test #2... Took %f seconds", i, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); } - + } } @@ -10555,7 +10555,7 @@ void command_logs(Client *c, const Seperator *sep){ c->Message(15, "Your Log Settings have been applied"); c->Message(15, "Output Method: %s :: Debug Level: %i - Category: %s", sep->arg[2], atoi(sep->arg[4]), Logs::LogCategoryName[atoi(sep->arg[3])]); } - /* We use a general 'is_category_enabled' now, let's update when we update any output settings + /* 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){ @@ -10583,9 +10583,9 @@ void command_mysqltest(Client *c, const Seperator *sep) for (i = 0; i < atoi(sep->arg[1]); i++){ std::string query = "SELECT * FROM `zone`"; auto results = database.QueryDatabase(query); - } + } } - Log.Out(Logs::General, Logs::Debug, "MySQL Test... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); + Log.Out(Logs::General, Logs::Debug, "MySQL Test... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); } void command_resetaa_timer(Client *c, const Seperator *sep) { @@ -10596,18 +10596,18 @@ void command_resetaa_timer(Client *c, const Seperator *sep) { target = c->GetTarget()->CastToClient(); } - if(sep->IsNumber(1)) + if(sep->IsNumber(1)) { int timer_id = atoi(sep->arg[1]); c->Message(0, "Reset of timer %i for %s", timer_id, c->GetName()); c->ResetAlternateAdvancementTimer(timer_id); } - else if(!strcasecmp(sep->arg[1], "all")) + else if(!strcasecmp(sep->arg[1], "all")) { c->Message(0, "Reset all timers for %s", c->GetName()); c->ResetAlternateAdvancementTimers(); - } - else + } + else { c->Message(0, "usage: #resetaa_timer [all | timer_id]"); } diff --git a/zone/mob.cpp b/zone/mob.cpp index ce0a97db9..938a9704b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2409,6 +2409,14 @@ bool Mob::CanThisClassDoubleAttack(void) const } } +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); +} + bool Mob::IsWarriorClass(void) const { switch(GetClass()) diff --git a/zone/mob.h b/zone/mob.h index 0094b0fbc..fcabf93fd 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -169,7 +169,7 @@ public: virtual bool CheckDualWield(); void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); - virtual bool CheckDoubleAttack(bool tripleAttack = false); // mob version doesn't use this flag + 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) { @@ -750,6 +750,7 @@ public: virtual int GetMonkHandToHandDamage(void); bool CanThisClassDoubleAttack(void) const; + bool CanThisClassTripleAttack() const; bool CanThisClassDualWield(void) const; bool CanThisClassRiposte(void) const; bool CanThisClassDodge(void) const; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 1bcccf272..1a134d167 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -536,7 +536,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { RogueBackstab(other,false,ReuseTime); if (level > 54) { - if(IsClient() && CastToClient()->CheckDoubleAttack(false)) + if(IsClient() && CastToClient()->CheckDoubleAttack()) { if(other->GetHP() > 0) RogueBackstab(other,false,ReuseTime); @@ -558,7 +558,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { if (level > 54) { // Check for double attack with main hand assuming maxed DA Skill (MS) - if(IsClient() && CastToClient()->CheckDoubleAttack(false)) + if(IsClient() && CastToClient()->CheckDoubleAttack()) if(other->GetHP() > 0) RogueBackstab(other,true, ReuseTime); From 2ca5a4ade6ed13e36ec5cdc99ca7f52d3296dc47 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 6 Jul 2015 15:44:02 -0400 Subject: [PATCH 255/846] Bot command changes. - #bot ai mez is now #bot mez - #bot bindme is now #bot bind - #bot runeme is now #bot rune - #bot augmentitem now has an alias of #bot ai - #bot giveitem now has an alias of #bot gi - Removed unused #bot groupmessages - Removed useless additional parameters (c->GetName()/sep->arg[2]) - Formatted loops and conditionals. --- zone/bot.cpp | 404 +++++++++++++++++++------------------------ zone/bot.h | 3 - zone/botspellsai.cpp | 6 +- 3 files changed, 182 insertions(+), 231 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 6e9a1f2fc..94b7d9e90 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -132,7 +132,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetHasBeenSummoned(false); LoadStance(); SetTaunting((GetClass() == WARRIOR || GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) && (GetBotStance() == BotStanceAggressive)); - SetGroupMessagesOn(GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN || GetClass() == ENCHANTER); SetInHealRotation(false); SetHealRotationActive(false); SetHasHealedThisCycle(false); @@ -1857,7 +1856,7 @@ void Bot::SavePetItems(uint32* petItems, uint32 botPetSaveId) { if(!petItems || botPetSaveId == 0) return; - for (int itemIndex = 0;itemIndex < EmuConstants::EQUIPMENT_SIZE; itemIndex++) { + for (int itemIndex = 0; itemIndex < EmuConstants::EQUIPMENT_SIZE; itemIndex++) { if(petItems[itemIndex] == 0) continue; @@ -6859,7 +6858,7 @@ bool Bot::SpellEffect(Mob* caster, uint16 spell_id, float partial) { if(g) { EQApplicationPacket hp_app; CreateHPPacket(&hp_app); - for(int i=0; imembers[i] && g->members[i]->IsClient()) g->members[i]->CastToClient()->QueuePacket(&hp_app); } @@ -7188,7 +7187,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, BotGroupBuffing)) { bool noGroupSpell = false; uint16 thespell = spell_id; - for(int i=0; i < AIspells.size(); i++) { + for(int i = 0; i < AIspells.size(); i++) { int j = BotGetSpells(i); int spelltype = BotGetSpellType(i); bool spellequal = (j == thespell); @@ -7213,7 +7212,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 if(!noGroupSpell) { Group *g = GetGroup(); if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS;i++) { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(g->members[i]) { if((g->members[i]->GetClass() == NECROMANCER) && (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune))) { } @@ -8090,7 +8089,7 @@ 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++) { + 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()) { @@ -8737,10 +8736,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 ai mez - If you're grouped with an Enchanter, he will mesmerize your target."); + 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 bindme - You must have a Cleric in your group to get Bind Affinity cast on you."); + 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)"); @@ -8751,7 +8750,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 runeme - Enchanter bot casts Rune spell on you"); + 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)"); @@ -8760,8 +8759,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 - Gives your targeted bot the item you have on your cursor."); - c->Message(0, "#bot augmentitem - Allows you to augment items for other classes. (You MUST have the Augmentation Sealer window filled)"); + 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."); @@ -8771,11 +8770,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 groupmessages [on|off] [bot name|all] - Turns group messages on/off for named bot/all bots."); 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 Pulling Target NPCs"); - c->Message(0, "#bot setinspectmessage - Copies your inspect message to a targeted bot that you own"); + 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; @@ -8797,10 +8795,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { haspuller = true; Mob *puller = g->members[i]; if (puller->CastToBot()->IsArcheryRange(target)) { - puller->CastToBot()->BotGroupSay(puller->CastToBot(), "Trying to Pull %s \n", target->GetCleanName()); + puller->CastToBot()->BotGroupSay(puller->CastToBot(), "Trying to pull %s.", target->GetCleanName()); puller->CastToBot()->BotRangedAttack(target); } else { - puller->CastToBot()->BotGroupSay(puller->CastToBot(), "Out of Range %s \n", target->GetCleanName()); + puller->CastToBot()->BotGroupSay(puller->CastToBot(), "%s is out of range.", target->GetCleanName()); } } } @@ -8880,7 +8878,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - if(!strcasecmp(sep->arg[1], "augmentitem")) { + 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; @@ -8888,15 +8886,14 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - if(!strcasecmp(sep->arg[1], "giveitem")) { + 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 { + else c->Message(15, "You must target a bot you own to do this."); - } return; } @@ -8909,7 +8906,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Bot* targetedBot = c->GetTarget()->CastToBot(); if(targetedBot) targetedBot->Camp(); - } else + } + else c->Message(15, "You must target a bot you own to do this."); } @@ -8918,16 +8916,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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)]"); + 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)]"); + 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)]"); + 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],"female")) { - c->Message(0, "Usage: #bot create [name] [class(1-16)] [race(1-12,128,130,330,522)] [gender (male/female)]"); + } 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; } @@ -8943,7 +8941,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } int gender = 0; - if(!strcasecmp(sep->arg[5], "female")) + if(!strcasecmp(sep->arg[5], "female") || !strcasecmp(sep->arg[5], "1")) gender = 1; if(!IsBotNameAvailable(sep->arg[2],&TempErrorMessage)) { @@ -8975,9 +8973,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else c->Message(0, "%s saved as bot %u.", NewBot->GetCleanName(), NewBot->GetBotID()); } - else { - // TODO: Log error message here - } + else + Log.Out(Logs::General, Logs::Error, "Error in #bot create, cannot find NewBot"); return; } @@ -8992,23 +8989,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(!strcasecmp(sep->arg[1], "delete") ) { - if((c->GetTarget() == nullptr) || !c->GetTarget()->IsBot()) - { + if((c->GetTarget() == nullptr) || !c->GetTarget()->IsBot()) { c->Message(15, "You must target a bot!"); return; - } - else if(c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID()) - { + } 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; @@ -9028,7 +9020,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { listAll = false; std::list AvailableBots = GetBotList(c->CharacterID(), &TempErrorMessage); - if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; @@ -9041,9 +9032,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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."); } + else + c->Message(0, "You have no bots created. Use the #bot create command to create a bot."); } if(!strcasecmp(sep->arg[1], "mana")) { @@ -9076,9 +9067,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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."); } + else + c->Message(0, "You have no spawned bots in this zone."); } return; } @@ -9092,7 +9083,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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; @@ -9110,18 +9100,17 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(c->IsGrouped()) { Group *g = entity_list.GetGroupByClient(c); - for (int i=0; imembers[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) { + + if(g && g->members[i] && g->members[i]->qglobal) return; - } } - } - else { + } else { if(c->GetAggroCount() > 0) { c->Message(0, "You can't spawn bots while you are engaged."); return; @@ -9129,7 +9118,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Mob* TempBotMob = entity_list.GetMobByBotID(botId); - if(TempBotMob) { c->Message(0, "This bot is already in the zone."); return; @@ -9144,7 +9132,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(RuleB(Bots, BotQuest) && !c->GetGM()) { const int allowedBots = AllowedBotSpawns(c->CharacterID(), &TempErrorMessage); - if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; @@ -9177,7 +9164,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(TempBot) { TempBot->Spawn(c, &TempErrorMessage); - if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); safe_delete(TempBot); @@ -9185,9 +9171,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } TempBot->BotGroupSay(TempBot, "I am ready for battle."); - } else { - c->Message(0, "BotID: %i not found", atoi(sep->arg[2])); } + else + c->Message(0, "BotID: %i not found", atoi(sep->arg[2])); return; } @@ -9199,7 +9185,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Bot* archerBot = c->GetTarget()->CastToBot(); - if(archerBot) { if(archerBot->IsBotArcher()) archerBot->SetBotArcher(false); @@ -9207,7 +9192,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { archerBot->SetBotArcher(true); archerBot->ChangeBotArcherWeapons(archerBot->IsBotArcher()); - if(archerBot->GetClass() == RANGER && archerBot->GetLevel() >= 61) archerBot->SetRangerAutoWeaponSelect(archerBot->IsBotArcher()); } @@ -9216,30 +9200,25 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } 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 { + 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()) - { + else if(c->GetTarget()->IsMob() && !c->GetTarget()->IsPet()) { Mob *b = c->GetTarget(); if(b) { - if(!b->IsBot()){ + if(!b->IsBot()) c->Message(15, "You must target a bot!"); - } else if((b->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID())) { + else if((b->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID())) b->CastToBot()->BotGroupSay(b->CastToBot(), "You can only summon your own bots."); - } else { + else { b->SetTarget(c->CastToMob()); b->Warp(glm::vec3(c->GetPosition())); } @@ -9254,7 +9233,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; @@ -9273,9 +9251,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { linker.SetLinkType(linker.linkItemInst); for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { - if((i == MainSecondary) && is2Hweapon) { + if((i == MainSecondary) && is2Hweapon) continue; - } inst = b->CastToBot()->GetBotItem(i == 22 ? 9999 : i); if (inst) @@ -9287,37 +9264,35 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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."); + 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()) - { + 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()) - { + } else if(c->GetTarget()->IsBot() && c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) { if(c->GetTradeskillObject() || (c->trade->state == Trading)) return; @@ -9326,6 +9301,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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" }; @@ -9358,9 +9334,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(itm) { c->PushItemOnCursor(*itminst, true); Bot *gearbot = c->GetTarget()->CastToBot(); - if((slotId == MainRange)||(slotId == MainAmmo)||(slotId == MainPrimary)||(slotId == MainSecondary)) { + if((slotId == MainRange)||(slotId == MainAmmo)||(slotId == MainPrimary)||(slotId == MainSecondary)) gearbot->SetBotArcher(false); - } + gearbot->RemoveBotItemBySlot(slotId, &TempErrorMessage); if(!TempErrorMessage.empty()) { @@ -9452,7 +9428,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(c->IsGrouped()) { Group *g = entity_list.GetGroupByClient(c); - for (int i=0; imembers[i] && g->members[i]->IsEngaged()) { c->Message(15, "You can't update bots while you are engaged."); return; @@ -9465,21 +9441,20 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { bot->SetPetChooser(false); bot->CalcBotStats(); } else { - if(c->GetFeigned()) { + 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 your bot first."); } - } else { - c->Message(15, "You must target a bot first"); } + else + c->Message(15, "You must target a bot first."); return; } //Bind - if(!strcasecmp(sep->arg[1], "bindme")) { + if(!strcasecmp(sep->arg[1], "bind")) { Mob *binder = nullptr; bool hasbinder = false; if(c->IsGrouped()) { @@ -9505,7 +9480,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } // Rune - if(!strcasecmp(sep->arg[1], "runeme")) { + if(!strcasecmp(sep->arg[1], "rune")) { Mob *runeer = nullptr; bool hasruneer = false; if(c->IsGrouped()) { @@ -9524,9 +9499,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(hasruneer) { - if (c->GetLevel() <= 12) { + 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)) { + 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)) { @@ -9587,13 +9562,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(TrackerClass) { case RANGER: if(!strcasecmp(sep->arg[2], "all")) { - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking everything", c->GetName()); + 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", c->GetName()); + 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", c->GetName()); + 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()); @@ -9601,12 +9576,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { break; case BARD: if(TrackerClass != RANGER) - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up", c->GetName()); + 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", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up."); entity_list.ShowSpawnWindow(c, RangeD, false); break; default: @@ -9664,7 +9639,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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 don't have the needed level yet", sep->arg[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, %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()); @@ -9677,14 +9652,14 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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", sep->arg[2]); + 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 don't have the needed level yet", sep->arg[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()); @@ -9697,12 +9672,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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", sep->arg[2]); + 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", sep->arg[2]); + 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 don't have the needed level yet", sep->arg[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 or %s?", Curer->CastToBot()->CreateSayLink(c, "#bot cure poison", "poison").c_str(), Curer->CastToBot()->CreateSayLink(c, "#bot cure disease", "disease").c_str()); break; @@ -9714,7 +9689,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } //Mez - if(!strcasecmp(sep->arg[1], "ai") && !strcasecmp(sep->arg[2], "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"); @@ -9932,7 +9907,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "I have successfully pacified %s.", target->GetCleanName()); return; - } else + } + else c->Message(0, "I failed to pacify %s.", target->GetCleanName()); } // seperated cleric and chanter so chanter is primary @@ -9945,7 +9921,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "I have successfully pacified %s.", target->GetCleanName()); return; - } else + } + else c->Message(0, "I failed to pacify %s.", target->GetCleanName()); } } @@ -9995,30 +9972,33 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(CharmerClass) { case ENCHANTER: if (c->GetLevel() >= 11) { - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName(), sep->arg[2]); - Charmer->CastToBot()->Bot_Command_CharmTarget (1,target); - } else if (c->GetLevel() <= 10){ - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); - } else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob level is too high or can't be charmed.", c->GetName()); + 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(), sep->arg[2]); - Charmer->CastToBot()->Bot_Command_CharmTarget (2,target); - } else if (c->GetLevel() <= 17){ - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); - } else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not undead.", c->GetName()); + 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(), sep->arg[2]); - Charmer->CastToBot()->Bot_Command_CharmTarget (3,target); - } else if (c->GetLevel() <= 12){ - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); - } else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not an animal.", c->GetName()); + 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."); @@ -10044,9 +10024,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->GetTarget()->CastToBot()->SetBotCharmer(true); c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "Available for Dire Charm command."); } - } else + } + else c->Message(15, "You must target your Enchanter, Necromancer, or Druid bot."); - } else + } + else c->Message(15, "You must target an Enchanter, Necromancer, or Druid bot."); return; @@ -10091,30 +10073,33 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(DirerClass) { case ENCHANTER: if (c->GetLevel() >= 55) { - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName(), sep->arg[2]); + 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 don't have the required level yet.", sep->arg[2]); - } else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob level is too high or can't be charmed.", c->GetName()); + } + 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(), sep->arg[2]); + 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 don't have the required level yet.", sep->arg[2]); - } else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not undead.", c->GetName()); + } + 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(), sep->arg[2]); + 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 don't have the required level yet.", sep->arg[2]); - } else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not an animal.", c->GetName()); + } + 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."); @@ -10145,8 +10130,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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.", c->GetName()); + } + else if((hasevac) && (c->GetLevel() <= 17)) + evac->CastToBot()->BotGroupSay(evac->CastToBot(), "I'm not level 18 yet."); return; } @@ -10778,7 +10764,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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 don't have the required level yet."); + 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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis magic", "Resist Magic").c_str()); @@ -10804,7 +10790,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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 don't have the needed level yet."); + 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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis magic", "Resist Magic").c_str()); @@ -10829,7 +10815,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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 don't have the required level yet.") ; + 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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis magic", "Resist Magic").c_str()); break; @@ -11032,7 +11018,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 + } + 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()); @@ -11060,7 +11047,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(g->IsLeader(botGroupLeader)) BotGroupSummon(g, c); } - } else if(c->HasGroup()) + } + else if(c->HasGroup()) BotGroupSummon(c->GetGroup(), c); return; @@ -11083,7 +11071,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(g->IsLeader(botGroupLeader)) BotGroupOrderFollow(g, c); } - } else if(c->HasGroup()) + } + else if(c->HasGroup()) BotGroupOrderFollow(c->GetGroup(), c); return; @@ -11106,13 +11095,14 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(g->IsLeader(botGroupLeader)) BotGroupOrderGuard(g, c); } - } else if(c->HasGroup()) + } + else if(c->HasGroup()) BotGroupOrderGuard(c->GetGroup(), c); return; } - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "attack") ) { + 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]); @@ -11131,13 +11121,17 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(g->IsLeader(botGroupLeader)) BotGroupOrderAttack(g, targetMob, c); } - } else if(c->HasGroup()) + } + else if(c->HasGroup()) BotGroupOrderAttack(c->GetGroup(), targetMob, c); - } else + } + else c->Message(13, "You must target a monster."); - } else + } + else c->Message(13, "You must target a monster."); - } else + } + else c->Message(13, "You must target a spawned bot group leader first."); } return; @@ -11153,7 +11147,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 + } + else c->Message(0, "You have no bot groups created. Use the #bot botgroup save command to save bot groups."); return; @@ -11326,11 +11321,14 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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 + } + else c->Message(0, "You must target a bot group leader only."); - } else + } + else c->Message(0, "You must target a bot that is in the same zone as you."); - } else + } + else c->Message(0, "The bot group name already exists. Please choose another name to save your bot group as."); } return; @@ -11413,11 +11411,14 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(13, "%s save failed!", target->GetCleanName()); c->Message(0, "Feature changed."); - } else + } + else c->Message(0, "You must own the bot to make changes."); - } else + } + else c->Message(0, "Requires a value."); - } else + } + else c->Message(0, "A bot needs to be targeted."); return; } @@ -11457,13 +11458,15 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } targetedBot->SetTaunting(taunt); - } else + } + 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(13, "You must target a spawned bot."); } - } else + } + else c->Message(0, "Usage #bot taunt [on|off]"); return; @@ -11538,66 +11541,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } c->Message(0, "Stance for %s: %s.", tempBot->GetCleanName(), stanceName.c_str()); - } else + } + else c->Message(13, "You must name a valid bot."); - } else + } + 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], "groupmessages")) { - bool groupMessages = false; - if(sep->arg[2] && sep->arg[3]){ - if(!strcasecmp(sep->arg[2], "on")) - groupMessages = true; - else if (!strcasecmp(sep->arg[2], "off")) - groupMessages = false; - else { - c->Message(0, "Usage #bot groupmessages [on|off] [bot name|all]"); - return; - } - - Bot* tempBot; - if(!strcasecmp(sep->arg[3], "all")) { - 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->SetGroupMessagesOn(groupMessages); - } - } - } else - c->Message(0, "You have no spawned bots in this zone."); - - c->Message(0, "Group messages now %s for all bots.", groupMessages?"on":"off"); - } else { - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - tempBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid bot."); - return; - } - - if(tempBot) { - if (tempBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - tempBot->SetGroupMessagesOn(groupMessages); - c->Message(0, "Group messages now %s.", groupMessages?"on":"off"); - } else { - c->Message(13, "You must name a valid bot."); - } - } - } else - c->Message(0, "Usage #bot groupmessages [on|off] [bot name|all]"); - - return; - } - if(!strcasecmp(sep->arg[1], "defensive")) { Bot* tempBot; std::string botName = std::string(sep->arg[2]); @@ -11660,7 +11613,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(defensiveSpellID > 0) tempBot->UseDiscipline(defensiveSpellID, tempBot->GetID()); - } else + } + else c->Message(13, "You must name a valid bot."); return; @@ -12669,7 +12623,7 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { if(this->HasGroup()) { g = this->GetGroup(); if(g) { - for( int i = 0; imembers[i] && !g->members[i]->qglobal) { if(g->members[i]->GetHPRatio() <= hpr) needHealed++; diff --git a/zone/bot.h b/zone/bot.h index 2c5e30644..9a2f2a308 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -450,7 +450,6 @@ public: int GetRawACNoShield(int &shield_ac); bool GetHasBeenSummoned() { return _hasBeenSummoned; } const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; } - bool GetGroupMessagesOn() { return _groupMessagesOn; } bool GetInHealRotation() { return _isInHealRotation; } bool GetHealRotationActive() { return (GetInHealRotation() && _isHealRotationActive); } bool GetHealRotationUseFastHeals() { return _healRotationUseFastHeals; } @@ -536,7 +535,6 @@ public: void SetDisciplineRecastTimer(int timer_index, int32 recast_delay); void SetHasBeenSummoned(bool s); void SetPreSummonLocation(const glm::vec3& location) { m_PreSummonLocation = location; } - void SetGroupMessagesOn(bool groupMessagesOn) { _groupMessagesOn = groupMessagesOn; } void SetInHealRotation( bool inRotation ) { _isInHealRotation = inRotation; } void SetHealRotationActive( bool isActive ) { _isHealRotationActive = isActive; } void SetHealRotationUseFastHeals( bool useFastHeals ) { _healRotationUseFastHeals = useFastHeals; } @@ -607,7 +605,6 @@ private: bool _hasBeenSummoned; glm::vec3 m_PreSummonLocation; uint8 _spellCastingChances[MaxStances][MaxSpellTypes]; - bool _groupMessagesOn; bool _isInHealRotation; bool _isHealRotationActive; bool _healRotationUseFastHeals; diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index fcbb052fe..cd8d28275 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -75,7 +75,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { MakeAnyLenString(&gmsg, "Attempting to mez %s.", addMob->GetCleanName()); - if(gmsg && GetGroupMessagesOn()) + if(gmsg) BotGroupSay(this, gmsg); } } @@ -262,7 +262,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { } } - if(gmsg && GetGroupMessagesOn()) + if(gmsg) BotGroupSay(this, gmsg); } } @@ -793,7 +793,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { MakeAnyLenString(&gmsg, "Attempting to slow %s.", tar->GetCleanName()); - if(gmsg && GetGroupMessagesOn()) + if(gmsg) BotGroupSay(this, gmsg); } } From 3455d70ca2e505a266533f5fc51b6f21a5e52d12 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 7 Jul 2015 17:20:37 -0400 Subject: [PATCH 256/846] Make SPECATK_QUAD uncheesable Live seems to have w kinds of "quads" one is an innate DW but people found out you could cheese them so luclin+ you can't anymore so INNATE_DW you can give the NPC a 2h and they will stop quadding QUAD they will accept the 2h but still quad --- zone/attack.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 440e8c59a..868c5ff03 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5027,7 +5027,8 @@ void NPC::SetAttackTimer() //special offhand stuff if (i == MainSecondary) { - if(!CanThisClassDualWield() || HasTwoHanderEquipped()) { + // SPECATK_QUAD is uncheesable + if(!CanThisClassDualWield() || (HasTwoHanderEquipped() && !GetSpecialAbility(SPECATK_QUAD))) { attack_dw_timer.Disable(); continue; } From 753f53be1bb9e92559aca1a39c64e442076c22f7 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 8 Jul 2015 17:10:33 -0700 Subject: [PATCH 257/846] Some small tweaks to reduce the amount of SendPosUpdates() are actually getting sent out on the wire. --- zone/mob.cpp | 14 +++++++++----- zone/waypoints.cpp | 28 +++++----------------------- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 938a9704b..0b46c8b12 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1395,19 +1395,23 @@ void Mob::SendPosUpdate(uint8 iSendToSelf) { MakeSpawnUpdate(spu); if (iSendToSelf == 2) { - if (this->IsClient()) - this->CastToClient()->FastQueuePacket(&app,false); + if (IsClient()) { + CastToClient()->FastQueuePacket(&app,false); + } } else { if(move_tic_count == RuleI(Zone, NPCPositonUpdateTicCount)) { - entity_list.QueueClients(this, app, (iSendToSelf==0), false); + entity_list.QueueClients(this, app, (iSendToSelf == 0), false); move_tic_count = 0; } - else + else if(move_tic_count % 2 == 0) { - entity_list.QueueCloseClients(this, app, (iSendToSelf==0), 800, nullptr, false); + entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), 700, nullptr, false); + move_tic_count++; + } + else { move_tic_count++; } } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 5bf506184..65da797de 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -443,31 +443,10 @@ void NPC::NextGuardPosition() { } } -/* -// we need this for charmed NPCs -void Mob::SaveSpawnSpot() { - spawn_x = x_pos; - spawn_y = y_pos; - spawn_z = z_pos; - spawn_heading = heading; -}*/ - - - - -/*float Mob::CalculateDistanceToNextWaypoint() { - return CalculateDistance(cur_wp_x, cur_wp_y, cur_wp_z); -}*/ - float Mob::CalculateDistance(float x, float y, float z) { return (float)sqrtf( ((m_Position.x-x)*(m_Position.x-x)) + ((m_Position.y-y)*(m_Position.y-y)) + ((m_Position.z-z)*(m_Position.z-z)) ); } -/* -uint8 NPC::CalculateHeadingToNextWaypoint() { - return CalculateHeadingToTarget(cur_wp_x, cur_wp_y); -} -*/ float Mob::CalculateHeadingToTarget(float in_x, float in_y) { float angle; @@ -656,6 +635,11 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo else { tar_vector/=16.0f; + float dur = Timer::SetCurrentTime() - pLastChange; + if(dur < 1.0f) { + dur = 1.0f; + } + tar_vector = (tar_vector * AImovement_duration) / 100.0f; float new_x = m_Position.x + m_TargetV.x*tar_vector; float new_y = m_Position.y + m_TargetV.y*tar_vector; @@ -717,8 +701,6 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo } else { - // force an update now - move_tic_count = RuleI(Zone, NPCPositonUpdateTicCount); SendPosUpdate(); SetAppearance(eaStanding, false); } From a69fbb9e0b17b5cebc8b776b427967469f1bc944 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 8 Jul 2015 18:10:04 -0700 Subject: [PATCH 258/846] Set -> Get Timer --- zone/waypoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 65da797de..e900c6838 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -635,7 +635,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo else { tar_vector/=16.0f; - float dur = Timer::SetCurrentTime() - pLastChange; + float dur = Timer::GetCurrentTime() - pLastChange; if(dur < 1.0f) { dur = 1.0f; } From 3c1b499485c373cad422a5015fb99b0b440e8d7f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 9 Jul 2015 02:37:43 -0400 Subject: [PATCH 259/846] Fix Expendable AAs Thanks to ASan --- zone/aa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index d1dad4f40..71274de61 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1234,13 +1234,13 @@ void Mob::ExpendAlternateAdvancementCharge(uint32 aa_id) { iter.second.second -= 1; if(iter.second.second == 0) { - aa_ranks.erase(iter.first); if(IsClient()) { AA::Rank *r = ability->GetRankByPointsSpent(iter.second.first); if(r) { CastToClient()->GetEPP().expended_aa += r->cost; } } + aa_ranks.erase(iter.first); } if(IsClient()) { From 790927052754ec368729212de5893c857fa9fb04 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 9 Jul 2015 02:44:55 -0400 Subject: [PATCH 260/846] Make sure we actually have the AA they're trying to cast --- zone/aa.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 71274de61..307eb3ba8 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1146,15 +1146,14 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { return; } - //if expendable make sure we have charges - if(ability->charges > 0) { - uint32 charges = 0; - GetAA(rank_id, &charges); + uint32 charges = 0; + // We don't have the AA + if (!GetAA(rank_id, &charges)) + return; - if(charges < 0) { - return; - } - } + //if expendable make sure we have charges + if(ability->charges > 0 && charges < 1) + return; //check cooldown if(!p_timers.Expired(&database, rank->spell_type + pTimerAAStart)) { From 8dd362a1014a47346bdacf71381b1fdc6711fb70 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 11 Jul 2015 13:28:09 -0700 Subject: [PATCH 261/846] Fix for launcher not actually sending static ports when set in the db --- common/servertalk.h | 1 + eqlaunch/eqlaunch.cpp | 2 - eqlaunch/worldserver.cpp | 3 +- eqlaunch/zone_launch.cpp | 15 ++++--- eqlaunch/zone_launch.h | 3 +- world/launcher_link.cpp | 51 ++++------------------- world/launcher_link.h | 1 + zone/net.cpp | 88 ++++++++++++++++++++++++++++------------ 8 files changed, 87 insertions(+), 77 deletions(-) diff --git a/common/servertalk.h b/common/servertalk.h index af39bfaa4..6693e86bc 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -760,6 +760,7 @@ typedef enum { struct LauncherZoneRequest { uint8 command; char short_name[33]; + uint16 port; }; struct LauncherZoneStatus { diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index 76c9b48d1..952b6198b 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -102,8 +102,6 @@ int main(int argc, char *argv[]) { Log.Out(Logs::Detail, Logs::Launcher, "Starting main loop..."); -// zones["test"] = new ZoneLaunch(&world, "./zone", "dynamic_1"); - ProcLauncher *launch = ProcLauncher::get(); RunLoops = true; while(RunLoops) { diff --git a/eqlaunch/worldserver.cpp b/eqlaunch/worldserver.cpp index a4b27a983..c1bc0fc42 100644 --- a/eqlaunch/worldserver.cpp +++ b/eqlaunch/worldserver.cpp @@ -86,14 +86,13 @@ void WorldServer::Process() { } const LauncherZoneRequest *lzr = (const LauncherZoneRequest *) pack->pBuffer; - switch(ZoneRequestCommands(lzr->command)) { case ZR_Start: { if(m_zones.find(lzr->short_name) != m_zones.end()) { 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, m_config); + ZoneLaunch *l = new ZoneLaunch(this, m_name, lzr->short_name, lzr->port, m_config); m_zones[lzr->short_name] = l; } break; diff --git a/eqlaunch/zone_launch.cpp b/eqlaunch/zone_launch.cpp index 8c1e62223..974cf5b3d 100644 --- a/eqlaunch/zone_launch.cpp +++ b/eqlaunch/zone_launch.cpp @@ -34,10 +34,11 @@ void ZoneLaunch::InitStartTimer() { } ZoneLaunch::ZoneLaunch(WorldServer *world, const char *launcher_name, -const char *zone_name, const EQEmuConfig *config) +const char *zone_name, uint16 port, const EQEmuConfig *config) : m_state(StateStartPending), m_world(world), m_zone(zone_name), + m_port(port), m_launcherName(launcher_name), m_config(config), m_timer(config->RestartWait), @@ -61,10 +62,14 @@ void ZoneLaunch::SendStatus() const { void ZoneLaunch::Start() { ProcLauncher::Spec *spec = new ProcLauncher::Spec(); spec->program = m_config->ZoneExe; -// if(m_zone.substr(0,7) == "dynamic") -// spec->args.push_back("."); -// else - spec->args.push_back(m_zone); + + if(m_port) { + std::string arg = m_zone + std::string(":") + std::to_string(m_port); + spec->args.push_back(arg); + } else { + spec->args.push_back(m_zone); + } + spec->args.push_back(m_launcherName); spec->handler = this; spec->logFile = m_config->LogPrefix + m_zone + m_config->LogSuffix; diff --git a/eqlaunch/zone_launch.h b/eqlaunch/zone_launch.h index 3dc0fd697..ac48be92c 100644 --- a/eqlaunch/zone_launch.h +++ b/eqlaunch/zone_launch.h @@ -28,7 +28,7 @@ class EQEmuConfig; class ZoneLaunch : protected ProcLauncher::EventHandler { public: ZoneLaunch(WorldServer *world, const char *launcher_name, - const char *zone_name, const EQEmuConfig *config); + const char *zone_name, uint16 port, const EQEmuConfig *config); virtual ~ZoneLaunch(); void Stop(bool graceful = true); @@ -63,6 +63,7 @@ protected: const std::string m_zone; const char *const m_launcherName; const EQEmuConfig *const m_config; + const uint16 m_port; Timer m_timer; ProcLauncher::ProcRef m_ref; diff --git a/world/launcher_link.cpp b/world/launcher_link.cpp index bd8bfdc4b..33adba6a8 100644 --- a/world/launcher_link.cpp +++ b/world/launcher_link.cpp @@ -60,7 +60,7 @@ bool LauncherLink::Process() { end = m_states.end(); for(; cur != end; ++cur) { if(!cur->second.up) { - StartZone(cur->first.c_str()); + StartZone(cur->first.c_str(), cur->second.port); } } m_bootTimer.Disable(); @@ -184,14 +184,6 @@ bool LauncherLink::Process() { bool LauncherLink::ContainsZone(const char *short_name) const { return(m_states.find(short_name) != m_states.end()); - - /* - * std::map::const_iterator cur, end; - cur = m_states.begin(); - end = m_states.end(); - for(; cur != end; cur++) { - if( - }*/ } void LauncherLink::BootZone(const char *short_name, uint16 port) { @@ -202,15 +194,20 @@ void LauncherLink::BootZone(const char *short_name, uint16 port) { Log.Out(Logs::Detail, Logs::World_Server, "%s: Loaded zone '%s' on port %d", m_name.c_str(), short_name, zs.port); m_states[short_name] = zs; - StartZone(short_name); + StartZone(short_name, port); } void LauncherLink::StartZone(const char *short_name) { + StartZone(short_name, 0); +} + +void LauncherLink::StartZone(const char *short_name, uint16 port) { auto pack = new ServerPacket(ServerOP_LauncherZoneRequest, sizeof(LauncherZoneRequest)); LauncherZoneRequest* s = (LauncherZoneRequest *) pack->pBuffer; strn0cpy(s->short_name, short_name, 32); s->command = ZR_Start; + s->port = port; SendPacket(pack); delete pack; @@ -222,6 +219,7 @@ void LauncherLink::RestartZone(const char *short_name) { strn0cpy(s->short_name, short_name, 32); s->command = ZR_Restart; + s->port = 0; SendPacket(pack); delete pack; @@ -233,6 +231,7 @@ void LauncherLink::StopZone(const char *short_name) { strn0cpy(s->short_name, short_name, 32); s->command = ZR_Stop; + s->port = 0; SendPacket(pack); delete pack; @@ -332,35 +331,3 @@ void LauncherLink::Shutdown() { SendPacket(pack); delete pack; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/world/launcher_link.h b/world/launcher_link.h index d1d8b6d61..35cbbcfea 100644 --- a/world/launcher_link.h +++ b/world/launcher_link.h @@ -50,6 +50,7 @@ public: void Shutdown(); void BootZone(const char *short_name, uint16 port); void StartZone(const char *short_name); + void StartZone(const char *short_name, uint16 port); void RestartZone(const char *short_name); void StopZone(const char *short_name); void BootDynamics(uint8 new_total); diff --git a/zone/net.cpp b/zone/net.cpp index 1bca0571b..ccd371858 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -28,7 +28,6 @@ #include "../common/eq_packet_structs.h" #include "../common/mutex.h" #include "../common/version.h" - #include "../common/packet_dump_file.h" #include "../common/opcodemgr.h" #include "../common/guilds.h" @@ -57,17 +56,14 @@ #include "titles.h" #include "guild_mgr.h" #include "tasks.h" - #include "quest_parser_collection.h" #include "embparser.h" #include "lua_parser.h" - #include "questmgr.h" #include #include #include - #include #include #include @@ -116,28 +112,77 @@ int main(int argc, char** argv) { RegisterExecutablePlatform(ExePlatformZone); Log.LoadLogSettingsDefaults(); set_exception_handler(); - const char *zone_name; QServ = new QueryServ; - if(argc == 3) { + Log.Out(Logs::General, Logs::Zone_Server, "Loading server configuration.."); + if(!ZoneConfig::LoadConfig()) { + Log.Out(Logs::General, Logs::Error, "Loading server configuration failed."); + return 1; + } + const ZoneConfig *Config = ZoneConfig::get(); + + const char *zone_name; + uint32 instance_id = 0; + std::string z_name; + if(argc == 4) { + instance_id = atoi(argv[3]); worldserver.SetLauncherName(argv[2]); - worldserver.SetLaunchedName(argv[1]); - if(strncmp(argv[1], "dynamic_", 8) == 0) { - //dynamic zone with a launcher name correlation + auto zone_port = SplitString(argv[1], ':'); + + if(zone_port.size() > 0) { + z_name = zone_port[0]; + } + + if(zone_port.size() > 1) { + std::string p_name = zone_port[1]; + Config->SetZonePort(atoi(p_name.c_str())); + } + + worldserver.SetLaunchedName(z_name.c_str()); + if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) { + zone_name = "."; + } + else { + zone_name = z_name.c_str(); + } + } else if(argc == 3) { + worldserver.SetLauncherName(argv[2]); + auto zone_port = SplitString(argv[1], ':'); + + if(zone_port.size() > 0) { + z_name = zone_port[0]; + } + + if(zone_port.size() > 1) { + std::string p_name = zone_port[1]; + Config->SetZonePort(atoi(p_name.c_str())); + } + + worldserver.SetLaunchedName(z_name.c_str()); + if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) { zone_name = "."; } else { - zone_name = argv[1]; - worldserver.SetLaunchedName(zone_name); + zone_name = z_name.c_str(); } } 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 + auto zone_port = SplitString(argv[1], ':'); + + if(zone_port.size() > 0) { + z_name = zone_port[0]; + } + + if(zone_port.size() > 1) { + std::string p_name = zone_port[1]; + Config->SetZonePort(atoi(p_name.c_str())); + } + + worldserver.SetLaunchedName(z_name.c_str()); + if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) { zone_name = "."; - } else { - zone_name = argv[1]; - worldserver.SetLaunchedName(zone_name); + } + else { + zone_name = z_name.c_str(); } } else { zone_name = "."; @@ -145,13 +190,6 @@ int main(int argc, char** argv) { worldserver.SetLauncherName("NONE"); } - Log.Out(Logs::General, Logs::Zone_Server, "Loading server configuration.."); - if (!ZoneConfig::LoadConfig()) { - Log.Out(Logs::General, Logs::Error, "Loading server configuration failed."); - return 1; - } - const ZoneConfig *Config = ZoneConfig::get(); - worldserver.SetPassword(Config->SharedKey.c_str()); Log.Out(Logs::General, Logs::Zone_Server, "Connecting to MySQL..."); @@ -312,7 +350,7 @@ int main(int argc, char** argv) { #endif if (!strlen(zone_name) || !strcmp(zone_name,".")) { Log.Out(Logs::General, Logs::Zone_Server, "Entering sleep mode"); - } else if (!Zone::Bootup(database.GetZoneID(zone_name), 0, true)) { //todo: go above and fix this to allow cmd line instance + } else if (!Zone::Bootup(database.GetZoneID(zone_name), instance_id, true)) { Log.Out(Logs::General, Logs::Error, "Zone Bootup failed :: Zone::Bootup"); zone = 0; } From 3cd474e960ed4166b8c47e73472afb574207b6b8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 12 Jul 2015 23:37:43 -0400 Subject: [PATCH 262/846] Updated SpecialAbility lua constants --- zone/lua_mob.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 9662d1931..431f18ffe 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -2234,7 +2234,14 @@ luabind::scope lua_register_special_abilities() { luabind::value("destructible_object", static_cast(DESTRUCTIBLE_OBJECT)), luabind::value("no_harm_from_client", static_cast(NO_HARM_FROM_CLIENT)), luabind::value("always_flee", static_cast(ALWAYS_FLEE)), - luabind::value("flee_percent", static_cast(FLEE_PERCENT)) + luabind::value("flee_percent", static_cast(FLEE_PERCENT)), + luabind::value("allow_beneficial", static_cast(ALLOW_BENEFICIAL)), + luabind::value("disable_melee", static_cast(DISABLE_MELEE)), + luabind::value("npc_chase_distance", static_cast(NPC_CHASE_DISTANCE)), + luabind::value("allow_to_tank", static_cast(ALLOW_TO_TANK)), + luabind::value("ignore_root_aggro_rules", static_cast(IGNORE_ROOT_AGGRO_RULES)), + luabind::value("casting_resist_diff", static_cast(CASTING_RESIST_DIFF)), + luabind::value("counter_avoid_damage", static_cast(COUNTER_AVOID_DAMAGE)) ]; } From b7cd0b223f9bd6834b3c988c47dae87cd1f2aa4a Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 16 Jul 2015 01:51:10 -0700 Subject: [PATCH 263/846] Added two other commands to let you do shared reloading on your own without the hotfix command. Also changed how world determines a zone's address --- common/servertalk.h | 1 + world/client.cpp | 33 +++++++++++++------------- world/zoneserver.cpp | 17 +++++++++++--- world/zoneserver.h | 2 ++ zone/command.cpp | 56 ++++++++++++++++++++++++++++++++++++++++---- zone/command.h | 2 ++ zone/net.cpp | 17 -------------- zone/net.h | 10 -------- zone/worldserver.cpp | 39 ++++++++---------------------- 9 files changed, 98 insertions(+), 79 deletions(-) diff --git a/common/servertalk.h b/common/servertalk.h index 562e542ac..0945d500d 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -546,6 +546,7 @@ struct ServerLSPeerConnect { struct ServerConnectInfo { char address[250]; + char local_address[250]; uint16 port; }; diff --git a/world/client.cpp b/world/client.cpp index 2c476902a..6d7233256 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1217,30 +1217,31 @@ void Client::Clearance(int8 response) return; } - // @bp This is the chat server - /* - char packetData[] = "64.37.148.34.9876,MyServer,Testchar,23cd2c95"; - outapp = new EQApplicationPacket(OP_0x0282, sizeof(packetData)); - strcpy((char*)outapp->pBuffer, packetData); - QueuePacket(outapp); - delete outapp; - */ - // Send zone server IP data outapp = new EQApplicationPacket(OP_ZoneServerInfo, sizeof(ZoneServerInfo_Struct)); ZoneServerInfo_Struct* zsi = (ZoneServerInfo_Struct*)outapp->pBuffer; - const char *zs_addr=zs->GetCAddress(); - if (!zs_addr[0]) { - if (cle->IsLocalClient()) { + + const char *zs_addr = nullptr; + if(cle && cle->IsLocalClient()) { + const char *local_addr = zs->GetCLocalAddress(); + if(local_addr[0]) { + zs_addr = local_addr; + } else { struct in_addr in; in.s_addr = zs->GetIP(); - zs_addr=inet_ntoa(in); - if (!strcmp(zs_addr,"127.0.0.1")) - zs_addr=WorldConfig::get()->LocalAddress.c_str(); + zs_addr = inet_ntoa(in); + } + } else { + const char *addr = zs->GetCAddress(); + if(addr[0]) { + zs_addr = addr; } else { - zs_addr=WorldConfig::get()->WorldAddress.c_str(); + struct in_addr in; + in.s_addr = zs->GetIP(); + zs_addr = inet_ntoa(in); } } + 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); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 943f99bfb..d36507f04 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -57,6 +57,7 @@ ZoneServer::ZoneServer(EmuTCPConnection* itcpc) instanceID = 0; memset(clientaddress, 0, sizeof(clientaddress)); + memset(clientlocaladdress, 0, sizeof(clientlocaladdress)); clientport = 0; BootingUp = false; authenticated = false; @@ -581,7 +582,7 @@ bool ZoneServer::Process() { ServerConnectInfo* sci = (ServerConnectInfo*) pack->pBuffer; if (!sci->port) { - clientport=zoneserver_list.GetAvailableZonePort(); + clientport = zoneserver_list.GetAvailableZonePort(); ServerPacket p(ServerOP_SetConnectInfo, sizeof(ServerConnectInfo)); memset(p.pBuffer,0,sizeof(ServerConnectInfo)); @@ -590,8 +591,18 @@ bool ZoneServer::Process() { SendPacket(&p); Log.Out(Logs::Detail, Logs::World_Server,"Auto zone port configuration. Telling zone to use port %d",clientport); } else { - clientport=sci->port; - Log.Out(Logs::Detail, Logs::World_Server,"Zone specified port %d, must be a previously allocated zone reconnecting.",clientport); + clientport = sci->port; + Log.Out(Logs::Detail, Logs::World_Server,"Zone specified port %d.",clientport); + } + + if(sci->address[0]) { + strn0cpy(clientaddress, sci->address, 250); + Log.Out(Logs::Detail, Logs::World_Server, "Zone specified address %s.", sci->address); + } + + if(sci->local_address[0]) { + strn0cpy(clientlocaladdress, sci->local_address, 250); + Log.Out(Logs::Detail, Logs::World_Server, "Zone specified local address %s.", sci->address); } } diff --git a/world/zoneserver.h b/world/zoneserver.h index 1babecc98..0c2cd6bec 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -56,6 +56,7 @@ public: inline uint32 GetIP() const { return tcpc->GetrIP(); } inline uint16 GetPort() const { return tcpc->GetrPort(); } inline const char* GetCAddress() const { return clientaddress; } + inline const char* GetCLocalAddress() const { return clientaddress; } inline uint16 GetCPort() const { return clientport; } inline uint32 GetID() const { return ID; } inline bool IsBootingUp() const { return BootingUp; } @@ -73,6 +74,7 @@ private: uint32 ID; char clientaddress[250]; + char clientlocaladdress[250]; uint16 clientport; bool BootingUp; bool staticzone; diff --git a/zone/command.cpp b/zone/command.cpp index 2dbb9297e..85437da47 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -169,6 +169,7 @@ int command_init(void) { command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", 100, command_aggrozone) || command_add("ai", "[factionid/spellslist/con/guard/roambox/stop/start] - Modify AI on NPC target", 100, command_ai) || command_add("appearance", "[type] [value] - Send an appearance packet for you or your target", 150, command_appearance) || + command_add("apply_shared_memory", "[shared_memory_name] - Tells every zone and world to apply a specific shared memory segment by name.", 250, command_apply_shared_memory) || command_add("attack", "[targetname] - Make your NPC target attack targetname", 150, command_attack) || command_add("augmentitem", "Force augments an item. Must have the augment item window open.", 250, command_augmentitem) || command_add("aug", nullptr, 250, command_augmentitem) || @@ -253,7 +254,7 @@ int command_init(void) { command_add("heromodel", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.", 200, command_heromodel) || command_add("hideme", "[on/off] - Hide yourself from spawn lists.", 80, command_hideme) || command_add("hm", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.)", 200, command_heromodel) || - command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix", 250, command_hotfix) || + command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix, equiv to load_shared_memory followed by apply_shared_memory", 250, command_hotfix) || command_add("hp", "- Refresh your HP bar from the server.", 0, command_hp) || command_add("incstat", "- Increases or Decreases a client's stats permanently.", 200, command_incstat) || command_add("instance", "- Modify Instances", 200, command_instance) || @@ -271,6 +272,7 @@ int command_init(void) { command_add("level", "[level] - Set your or your target's level", 10, command_level) || command_add("listnpcs", "[name/range] - Search NPCs", 20, command_listnpcs) || command_add("listpetition", "- List petitions", 50, command_listpetition) || + command_add("load_shared_memory", "[shared_memory_name] - Reloads shared memory and uses the input as output", 250, command_load_shared_memory) || command_add("loc", "- Print out your or your target's current location and heading", 0, command_loc) || command_add("lock", "- Lock the worldserver", 150, command_lock) || command_add("logs", "Manage anything to do with logs", 250, command_logs) || @@ -10634,10 +10636,7 @@ void command_hotfix(Client *c, const Seperator *sep) { hotfix_name = "hotfix_"; } - c->Message(0, "Creating and applying hotfix"); - //Not 100% certain on the thread safety of this. - //I think it's okay however std::thread t1([c,hotfix_name]() { #ifdef WIN32 if(hotfix_name.length() > 0) { @@ -10666,3 +10665,52 @@ void command_hotfix(Client *c, const Seperator *sep) { t1.detach(); } + +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_name; + if(strcasecmp(current_hotfix.c_str(), sep->arg[1]) == 0) { + c->Message(0, "Cannot attempt to load this shared memory segment as it is already loaded."); + return; + } + + hotfix_name = sep->arg[1]; + c->Message(0, "Loading shared memory segment %s", hotfix_name.c_str()); + std::thread t1([c,hotfix_name]() { +#ifdef WIN32 + if(hotfix_name.length() > 0) { + system(StringFormat("shared_memory -hotfix=%s", hotfix_name.c_str()).c_str()); + } else { + system(StringFormat("shared_memory").c_str()); + } +#else + if(hotfix_name.length() > 0) { + system(StringFormat("./shared_memory -hotfix=%s", hotfix_name.c_str()).c_str()); + } + else { + system(StringFormat("./shared_memory").c_str()); + } +#endif + c->Message(0, "Shared memory segment finished loading."); + }); + + t1.detach(); +} + +void command_apply_shared_memory(Client *c, const Seperator *sep) { + char hotfix[256] = { 0 }; + database.GetVariable("hotfix_name", hotfix, 256); + 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()); + + ServerPacket pack(ServerOP_ChangeSharedMem, hotfix_name.length() + 1); + if(hotfix_name.length() > 0) { + strcpy((char*)pack.pBuffer, hotfix_name.c_str()); + } + worldserver.SendPacket(&pack); +} \ No newline at end of file diff --git a/zone/command.h b/zone/command.h index cdf67639c..6ab9666d2 100644 --- a/zone/command.h +++ b/zone/command.h @@ -326,6 +326,8 @@ void command_logs(Client *c, const Seperator *sep); void command_resetaa_timer(Client *c, const Seperator *sep); void command_reloadaa(Client *c, const Seperator *sep); void command_hotfix(Client *c, const Seperator *sep); +void command_load_shared_memory(Client *c, const Seperator *sep); +void command_apply_shared_memory(Client *c, const Seperator *sep); #ifdef EQPROFILE void command_profiledump(Client *c, const Seperator *sep); diff --git a/zone/net.cpp b/zone/net.cpp index f561fbf3d..acf217b84 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -575,16 +575,6 @@ uint32 NetConnection::GetIP(char* name) } -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), @@ -594,9 +584,6 @@ NetConnection::NetConnection() raid_timer(1000), trap_timer(1000) { - ZonePort = 0; - ZoneAddress = 0; - WorldAddress = 0; group_timer.Disable(); raid_timer.Disable(); corpse_timer.Disable(); @@ -606,10 +593,6 @@ NetConnection::NetConnection() } NetConnection::~NetConnection() { - if (ZoneAddress != 0) - safe_delete_array(ZoneAddress); - if (WorldAddress != 0) - safe_delete_array(WorldAddress); } /* Update Window Title with relevant information */ diff --git a/zone/net.h b/zone/net.h index c49e1ec8e..8908a3740 100644 --- a/zone/net.h +++ b/zone/net.h @@ -39,20 +39,10 @@ public: uint32 GetIP(); uint32 GetIP(char* name); - void SaveInfo(char* address, uint32 port, char* waddress,char* filename); - char* GetWorldAddress() { return WorldAddress; } - char* GetZoneAddress() { return ZoneAddress; } - char* GetZoneFileName() { return ZoneFileName; } - uint32 GetZonePort() { return ZonePort; } Timer object_timer; Timer door_timer; Timer corpse_timer; Timer group_timer; Timer raid_timer; Timer trap_timer; -private: - uint16 ZonePort; - char* ZoneAddress; - char* WorldAddress; - char ZoneFileName[50]; }; diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index a2b85a6e3..59eca67ac 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -112,7 +112,16 @@ void WorldServer::OnConnected() { pack = new ServerPacket(ServerOP_SetConnectInfo, sizeof(ServerConnectInfo)); ServerConnectInfo* sci = (ServerConnectInfo*) pack->pBuffer; + auto config = ZoneConfig::get(); sci->port = ZoneConfig::get()->ZonePort; + if(config->WorldAddress.length() > 0) { + strn0cpy(sci->address, config->WorldAddress.c_str(), 250); + } + + if(config->LocalAddress.length() > 0) { + strn0cpy(sci->address, config->LocalAddress.c_str(), 250); + } + SendPacket(pack); safe_delete(pack); @@ -485,9 +494,7 @@ void WorldServer::Process() { if (zst->adminname[0] != 0) std::cout << "Zone bootup by " << zst->adminname << std::endl; - if (!(Zone::Bootup(zst->zoneid, zst->instanceid, zst->makestatic))) { - SendChannelMessage(0, 0, 10, 0, 0, "%s:%i Zone::Bootup failed: %s", net.GetZoneAddress(), net.GetZonePort(), database.GetZoneName(zst->zoneid)); - } + Zone::Bootup(zst->zoneid, zst->instanceid, zst->makestatic); break; } case ServerOP_ZoneIncClient: { @@ -508,8 +515,6 @@ void WorldServer::Process() { if ((Zone::Bootup(szic->zoneid, szic->instanceid))) { zone->AddAuth(szic); } - else - SendEmoteMessage(0, 0, 100, 0, "%s:%i Zone::Bootup failed: %s (%i)", net.GetZoneAddress(), net.GetZonePort(), database.GetZoneName(szic->zoneid, true), szic->zoneid); } break; } @@ -715,30 +720,6 @@ void WorldServer::Process() { case ServerOP_ZoneReboot: { std::cout << "Got Server Requested Zone reboot" << std::endl; ServerZoneReboot_Struct* zb = (ServerZoneReboot_Struct*) pack->pBuffer; - // printf("%i\n",zb->zoneid); - struct in_addr in; - in.s_addr = GetIP(); -#ifdef _WINDOWS - char buffer[200]; - snprintf(buffer,200,". %s %i %s",zb->ip2, zb->port, inet_ntoa(in)); - if(zb->zoneid != 0) { - snprintf(buffer,200,"%s %s %i %s",database.GetZoneName(zb->zoneid),zb->ip2, zb->port ,inet_ntoa(in)); - std::cout << "executing: " << buffer; - ShellExecute(0,"Open",net.GetZoneFileName(), buffer, 0, SW_SHOWDEFAULT); - } - else - { - std::cout << "executing: " << net.GetZoneFileName() << " " << buffer; - ShellExecute(0,"Open",net.GetZoneFileName(), buffer, 0, SW_SHOWDEFAULT); - } -#else - char buffer[5]; - snprintf(buffer,5,"%i",zb->port); //just to be sure that it will work on linux - if(zb->zoneid != 0) - execl(net.GetZoneFileName(),net.GetZoneFileName(),database.GetZoneName(zb->zoneid),zb->ip2, buffer,inet_ntoa(in), nullptr); - else - execl(net.GetZoneFileName(),net.GetZoneFileName(),".",zb->ip2, buffer,inet_ntoa(in), nullptr); -#endif break; } case ServerOP_SyncWorldTime: { From d64f79cb2a7de35dd04114fbe2ce5c31b34d1d6e Mon Sep 17 00:00:00 2001 From: hateborne Date: Wed, 15 Jul 2015 19:16:51 -0400 Subject: [PATCH 264/846] Add Optional Enforce Task Level Requirement Affected: quest::assigntask $client->AssignTask This is to allow those task level requirements in DB to be used, optionally. It defaults to do not enforce (translated: no change for current servers), but can be set with an additional flag to both commands (see below). The LUA bit was added thanks to help from demonstar55. quest::assigntask(703); # works quest::assigntask(703, 1); # denies user $client->AssignTask(701, $npc->GetID()); # works $client->AssignTask(701, $npc->GetID(), 1); # denies user --- zone/client.h | 2 +- zone/embparser_api.cpp | 14 +++++++++++--- zone/lua_client.cpp | 6 ++++++ zone/lua_client.h | 1 + zone/perl_client.cpp | 17 ++++++++++++----- zone/questmgr.cpp | 6 +++--- zone/questmgr.h | 2 +- zone/tasks.cpp | 32 +++++++++++++++++++++++++++++++- zone/tasks.h | 4 +++- 9 files changed, 69 insertions(+), 15 deletions(-) diff --git a/zone/client.h b/zone/client.h index 03d09d50c..bbe4ba575 100644 --- a/zone/client.h +++ b/zone/client.h @@ -997,7 +997,7 @@ public: inline void DisableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->DisableTask(CharacterID(), TaskCount, TaskList); } inline bool IsTaskEnabled(int TaskID) { return (taskstate ? taskstate->IsTaskEnabled(TaskID) : false); } inline void ProcessTaskProximities(float X, float Y, float Z) { if(taskstate) taskstate->ProcessTaskProximities(this, X, Y, Z); } - inline void AssignTask(int TaskID, int NPCID) { if(taskstate) taskstate->AcceptNewTask(this, TaskID, NPCID); } + inline void AssignTask(int TaskID, int NPCID, bool enforce_level_requirement = false) { if (taskstate) taskstate->AcceptNewTask(this, TaskID, NPCID, enforce_level_requirement); } inline int ActiveSpeakTask(int NPCID) { if(taskstate) return taskstate->ActiveSpeakTask(NPCID); else return 0; } inline int ActiveSpeakActivity(int NPCID, int TaskID) { if(taskstate) return taskstate->ActiveSpeakActivity(NPCID, TaskID); else return 0; } inline void FailTask(int TaskID) { if(taskstate) taskstate->FailTask(this, TaskID); } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 871d47074..f5de73698 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2383,11 +2383,19 @@ XS(XS__assigntask) { dXSARGS; unsigned int taskid; - if(items == 1) { + bool enforce_level_requirement = false; + if(items == 1 || items == 2) { taskid = (int)SvIV(ST(0)); - quest_manager.assigntask(taskid); + if (items == 2) + { + if ((int)SvIV(ST(1)) == 1) + { + enforce_level_requirement = true; + } + } + quest_manager.assigntask(taskid, enforce_level_requirement); } else { - Perl_croak(aTHX_ "Usage: assigntask(taskid)"); + Perl_croak(aTHX_ "Usage: assigntask(taskid, enforce_level_requirement)"); } XSRETURN_EMPTY; diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index d69924577..0e397b58e 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1077,6 +1077,11 @@ void Lua_Client::AssignTask(int task, int npc_id) { self->AssignTask(task, npc_id); } +void Lua_Client::AssignTask(int task, int npc_id, bool enforce_level_requirement) { + Lua_Safe_Call_Void(); + self->AssignTask(task, npc_id, enforce_level_requirement); +} + void Lua_Client::FailTask(int task) { Lua_Safe_Call_Void(); self->FailTask(task); @@ -1525,6 +1530,7 @@ luabind::scope lua_register_client() { .def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID) .def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity) .def("AssignTask", (void(Lua_Client::*)(int,int))&Lua_Client::AssignTask) + .def("AssignTask", (void(Lua_Client::*)(int,int,bool))&Lua_Client::AssignTask .def("FailTask", (void(Lua_Client::*)(int))&Lua_Client::FailTask) .def("IsTaskCompleted", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskCompleted) .def("IsTaskActive", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskActive) diff --git a/zone/lua_client.h b/zone/lua_client.h index dd1059a0a..f3f0e1897 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -242,6 +242,7 @@ public: int FindSpellBookSlotBySpellID(int spell_id); void UpdateTaskActivity(int task, int activity, int count); void AssignTask(int task, int npc_id); + void AssignTask(int task, int npc_id, bool enforce_level_requirement); void FailTask(int task); bool IsTaskCompleted(int task); bool IsTaskActive(int task); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index ee4ee943d..de9e8512a 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5126,13 +5126,20 @@ XS(XS_Client_AssignTask); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_AssignTask) { dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::AssignTask(THIS, TaskID, NPCID)"); + if (items != 3 && items != 4) + Perl_croak(aTHX_ "Usage: Client::AssignTask(THIS, TaskID, NPCID, enforce_level_requirement)"); { Client * THIS; int TaskID = (int)SvIV(ST(1)); int NPCID = (int)SvIV(ST(2)); - + bool enforce_level_requirement = false; + if (items == 4) + { + if ((int)SvIV(ST(3)) == 1) + { + enforce_level_requirement = true; + } + } if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); THIS = INT2PTR(Client *,tmp); @@ -5142,7 +5149,7 @@ XS(XS_Client_AssignTask) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - THIS->AssignTask(TaskID, NPCID); + THIS->AssignTask(TaskID, NPCID, enforce_level_requirement); } XSRETURN_EMPTY; } @@ -6477,7 +6484,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$"); newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$"); newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$;$"); - newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$"); + newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$;$"); newXSproto(strcpy(buf, "FailTask"), XS_Client_FailTask, file, "$$"); newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$"); newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index b6243091f..a15724325 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2200,11 +2200,11 @@ void QuestManager::taskexploredarea(int exploreid) { initiator->UpdateTasksOnExplore(exploreid); } -void QuestManager::assigntask(int taskid) { +void QuestManager::assigntask(int taskid, bool enforce_level_requirement) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner) - initiator->AssignTask(taskid, owner->GetID()); + if (RuleB(TaskSystem, EnableTaskSystem) && initiator && owner) + initiator->AssignTask(taskid, owner->GetID(), enforce_level_requirement); } void QuestManager::failtask(int taskid) { diff --git a/zone/questmgr.h b/zone/questmgr.h index 960a8f1f4..78f4b34ed 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -188,7 +188,7 @@ public: void updatetaskactivity(int task, int activity, int count, bool ignore_quest_update = false); void resettaskactivity(int task, int activity); void taskexploredarea(int exploreid); - void assigntask(int taskid); + void assigntask(int taskid, bool enforce_level_requirement = false); void failtask(int taskid); int tasktimeleft(int taskid); int istaskcompleted(int taskid); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 4f3fe8124..537cdefed 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -895,6 +895,30 @@ bool TaskManager::AppropriateLevel(int TaskID, int PlayerLevel) { } +int TaskManager::GetTaskMinLevel(int TaskID) +{ + if (Tasks[TaskID]->MinLevel) + { + return Tasks[TaskID]->MinLevel; + } + else + { + return -1; + } +} + +int TaskManager::GetTaskMaxLevel(int TaskID) +{ + if (Tasks[TaskID]->MaxLevel) + { + return Tasks[TaskID]->MaxLevel; + } + else + { + return -1; + } +} + void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID) { unsigned int EnabledTaskIndex = 0; @@ -2948,7 +2972,7 @@ void ClientTaskState::RemoveTask(Client *c, int sequenceNumber) { } -void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID) { +void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement) { if(!taskmanager || TaskID<0 || TaskID>=MAXTASKS) { c->Message(13, "Task system not functioning, or TaskID %i out of range.", TaskID); @@ -2973,6 +2997,12 @@ void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID) { } } + if (enforce_level_requirement && !taskmanager->AppropriateLevel(TaskID, c->GetLevel())) + { + c->Message(13, "You are outside the level range of this task."); + return; + } + if(!taskmanager->IsTaskRepeatable(TaskID) && IsTaskCompleted(TaskID)) return; // We do it this way, because when the Client cancels a task, it retains the sequence number of the remaining diff --git a/zone/tasks.h b/zone/tasks.h index c525bbcd8..459eacd08 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -168,7 +168,7 @@ public: int GetTaskActivityDoneCount(int index, int ActivityID); int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID); int GetTaskStartTime(int index); - void AcceptNewTask(Client *c, int TaskID, int NPCID); + void AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false); void FailTask(Client *c, int TaskID); int TaskTimeLeft(int TaskID); int IsTaskCompleted(int TaskID); @@ -230,6 +230,8 @@ public: void SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList); void SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList); bool AppropriateLevel(int TaskID, int PlayerLevel); + int GetTaskMinLevel(int TaskID); + int GetTaskMaxLevel(int TaskID); void TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID); void SendActiveTasksToClient(Client *c, bool TaskComplete=false); void SendSingleActiveTaskToClient(Client *c, int TaskIndex, bool TaskComplete, bool BringUpTaskJournal=false); From 1b8f613391da1ce92799538f265abcb03326d58a Mon Sep 17 00:00:00 2001 From: hateborne Date: Thu, 16 Jul 2015 13:46:29 -0400 Subject: [PATCH 265/846] Amend these to last commit Forgot to add changelog and adjustment to task.cpp getmin/getmax --- changelog.txt | 7 +++++++ zone/tasks.cpp | 12 ++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/changelog.txt b/changelog.txt index f5d1803d0..85428ca82 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/15/2015 == +Hateborne: Added optional ability to enforce task level requirements in perl and lua via an added, optional parameter to $client->AssignTask and quest::assigntask. + Use cases: + quest::assigntask(703); # this still assigns the task as normal, no functional change + quest::assigntask(703, 1); # this will assign the task, provided the character meets the db-stored level requirements + $client->AssignTask(703, $npc->GetID()); # still assigns the task as normal, no functional change + $client->AssignTask(703, $npc->GetID(), 1); # this will assign the task, provided the character meets the db-stored level requirements == 07/06/2015 == mackal: Implement Triple Attack Skill Parses showed about rand(1000) for the chance, may need more investigating diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 537cdefed..a5cdeb5a8 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -901,10 +901,8 @@ int TaskManager::GetTaskMinLevel(int TaskID) { return Tasks[TaskID]->MinLevel; } - else - { - return -1; - } + + return -1; } int TaskManager::GetTaskMaxLevel(int TaskID) @@ -913,10 +911,8 @@ int TaskManager::GetTaskMaxLevel(int TaskID) { return Tasks[TaskID]->MaxLevel; } - else - { - return -1; - } + + return -1; } void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID) { From cb874ad4e2aacdadbbd73c16b0981d1d99b3a8a3 Mon Sep 17 00:00:00 2001 From: hateborne Date: Thu, 16 Jul 2015 14:56:08 -0400 Subject: [PATCH 266/846] Me being a fool. Added missing closing paran --- zone/lua_client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 0e397b58e..7aa78d11d 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1530,7 +1530,7 @@ luabind::scope lua_register_client() { .def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID) .def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity) .def("AssignTask", (void(Lua_Client::*)(int,int))&Lua_Client::AssignTask) - .def("AssignTask", (void(Lua_Client::*)(int,int,bool))&Lua_Client::AssignTask + .def("AssignTask", (void(Lua_Client::*)(int,int,bool))&Lua_Client::AssignTask) .def("FailTask", (void(Lua_Client::*)(int))&Lua_Client::FailTask) .def("IsTaskCompleted", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskCompleted) .def("IsTaskActive", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskActive) From 87d42931aabe297696a6fb46f25d40d5fffaca50 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 16 Jul 2015 14:35:20 -0700 Subject: [PATCH 267/846] Fix for not having address/localaddress set from not localhost --- world/client.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index 6d7233256..f109a5cdf 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1224,21 +1224,34 @@ void Client::Clearance(int8 response) const char *zs_addr = nullptr; if(cle && cle->IsLocalClient()) { const char *local_addr = zs->GetCLocalAddress(); + if(local_addr[0]) { zs_addr = local_addr; } else { - struct in_addr in; - in.s_addr = zs->GetIP(); - zs_addr = inet_ntoa(in); + if(strcmp(local_addr, "127.0.0.1") == 0) + { + zs_addr = WorldConfig::get()->LocalAddress.c_str(); + } else { + struct in_addr in; + in.s_addr = zs->GetIP(); + zs_addr = inet_ntoa(in); + } } + } else { const char *addr = zs->GetCAddress(); if(addr[0]) { zs_addr = addr; } else { - struct in_addr in; - in.s_addr = zs->GetIP(); - zs_addr = inet_ntoa(in); + if(strcmp(addr, "127.0.0.1") == 0) + { + zs_addr = WorldConfig::get()->WorldAddress.c_str(); + } + else { + struct in_addr in; + in.s_addr = zs->GetIP(); + zs_addr = inet_ntoa(in); + } } } From 4d68ddc82f1606da3f8516ae04dd82db37eff334 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 16 Jul 2015 15:07:59 -0700 Subject: [PATCH 268/846] More NAT fixes, please work --- world/client.cpp | 21 ++++++++------------- world/zoneserver.h | 2 +- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index f109a5cdf..30128c076 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1228,13 +1228,16 @@ void Client::Clearance(int8 response) if(local_addr[0]) { zs_addr = local_addr; } else { - if(strcmp(local_addr, "127.0.0.1") == 0) + struct in_addr in; + in.s_addr = zs->GetIP(); + zs_addr = inet_ntoa(in); + + if(strcmp(zs_addr, "127.0.0.1") == 0) { + Log.Out(Logs::Detail, Logs::World_Server, "Local zone address was %s, setting local address to: %s", zs_addr, WorldConfig::get()->LocalAddress.c_str()); zs_addr = WorldConfig::get()->LocalAddress.c_str(); } else { - struct in_addr in; - in.s_addr = zs->GetIP(); - zs_addr = inet_ntoa(in); + Log.Out(Logs::Detail, Logs::World_Server, "Local zone address %s", zs_addr); } } @@ -1243,15 +1246,7 @@ void Client::Clearance(int8 response) if(addr[0]) { zs_addr = addr; } else { - if(strcmp(addr, "127.0.0.1") == 0) - { - zs_addr = WorldConfig::get()->WorldAddress.c_str(); - } - else { - struct in_addr in; - in.s_addr = zs->GetIP(); - zs_addr = inet_ntoa(in); - } + zs_addr = WorldConfig::get()->WorldAddress.c_str(); } } diff --git a/world/zoneserver.h b/world/zoneserver.h index 0c2cd6bec..125ac33f9 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -56,7 +56,7 @@ public: inline uint32 GetIP() const { return tcpc->GetrIP(); } inline uint16 GetPort() const { return tcpc->GetrPort(); } inline const char* GetCAddress() const { return clientaddress; } - inline const char* GetCLocalAddress() const { return clientaddress; } + inline const char* GetCLocalAddress() const { return clientlocaladdress; } inline uint16 GetCPort() const { return clientport; } inline uint32 GetID() const { return ID; } inline bool IsBootingUp() const { return BootingUp; } From eb5e0ee72c74fb8b3a56ada0da779ef86c0a6df1 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Thu, 16 Jul 2015 20:15:59 -0400 Subject: [PATCH 269/846] New commands. - #untraindisc [spellid] - Untrains specified discipline. - #untraindiscs - Untrains all disciplines. --- zone/command.cpp | 23 +++++++++++++++++++++++ zone/command.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/zone/command.cpp b/zone/command.cpp index 85437da47..75dec2b62 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -412,6 +412,8 @@ int command_init(void) { command_add("unlock", "- Unlock the worldserver", 150, command_unlock) || command_add("unscribespell", "[spellid] - Unscribe specified spell from your target's spell book.", 180, command_unscribespell) || command_add("unscribespells", "- Clear out your or your player target's spell book.", 180, command_unscribespells) || + command_add("untraindisc", "[spellid] - Untrain specified discipline from your target.", 180, command_untraindisc) || + command_add("untraindiscs", "- Untrains all disciplines from your target.", 180, command_untraindiscs) || command_add("uptime", "[zone server id] - Get uptime of worldserver, or zone server if argument provided", 10, command_uptime) || command_add("version", "- Display current version of EQEmu server", 0, command_version) || command_add("viewnpctype", "[npctype id] - Show info about an npctype", 100, command_viewnpctype) || @@ -5317,6 +5319,27 @@ void command_unscribespells(Client *c, const Seperator *sep) t->UnscribeSpellAll(); } +void command_untraindisc(Client *c, const Seperator *sep) { + Client *t = c; + if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) + t = c->GetTarget()->CastToClient(); + + for (int i = 0; i < MAX_PP_DISCIPLINES; i++) { + if (t->GetPP().disciplines.values[i] == atoi(sep->arg[1])) { + t->UntrainDisc(i, 1); + return; + } + } +} + +void command_untraindiscs(Client *c, const Seperator *sep) { + Client *t = c; + if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) + t = c->GetTarget()->CastToClient(); + + t->UntrainDiscAll(); +} + void command_wpinfo(Client *c, const Seperator *sep) { Mob *t=c->GetTarget(); diff --git a/zone/command.h b/zone/command.h index 6ab9666d2..67f813456 100644 --- a/zone/command.h +++ b/zone/command.h @@ -328,6 +328,8 @@ void command_reloadaa(Client *c, const Seperator *sep); void command_hotfix(Client *c, const Seperator *sep); void command_load_shared_memory(Client *c, const Seperator *sep); void command_apply_shared_memory(Client *c, const Seperator *sep); +void command_untraindisc(Client *c, const Seperator *sep); +void command_untraindiscs(Client *c, const Seperator *sep); #ifdef EQPROFILE void command_profiledump(Client *c, const Seperator *sep); From a52ab7ae48b46a2bbf74951024c162b7e2a93cb1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 16 Jul 2015 22:38:32 -0400 Subject: [PATCH 270/846] Rework spell aggro based on http://www.eqemulator.org/forums/showthread.php?t=39819 --- changelog.txt | 5 +- zone/aggro.cpp | 227 +++++++++++++++++++++++----------------------- zone/bot.cpp | 20 ++-- zone/bot.h | 4 +- zone/entity.cpp | 58 +++--------- zone/entity.h | 4 +- zone/lua_mob.cpp | 8 +- zone/mob.h | 4 +- zone/perl_mob.cpp | 6 +- zone/spells.cpp | 36 ++++---- 10 files changed, 169 insertions(+), 203 deletions(-) diff --git a/changelog.txt b/changelog.txt index 85428ca82..68ef9c2b1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/16/2013 == +mackal: Rework spell aggro based on http://www.eqemulator.org/forums/showthread.php?t=39819 + == 07/15/2015 == -Hateborne: Added optional ability to enforce task level requirements in perl and lua via an added, optional parameter to $client->AssignTask and quest::assigntask. +Hateborne: Added optional ability to enforce task level requirements in perl and lua via an added, optional parameter to $client->AssignTask and quest::assigntask. Use cases: quest::assigntask(703); # this still assigns the task as normal, no functional change quest::assigntask(703, 1); # this will assign the task, provided the character meets the db-stored level requirements diff --git a/zone/aggro.cpp b/zone/aggro.cpp index e983b8ea9..75e3434b0 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -44,12 +44,8 @@ void EntityList::CheckClientAggro(Client *around) if (mob->IsClient()) //also ensures that mob != around continue; - if (mob->CheckWillAggro(around)) { - if (mob->IsEngaged()) - mob->AddToHateList(around); - else - mob->AddToHateList(around, mob->GetLevel()); - } + if (mob->CheckWillAggro(around) && !mob->CheckAggro(around)) + mob->AddToHateList(around, 100); } } @@ -343,7 +339,7 @@ bool Mob::CheckWillAggro(Mob *mob) { { //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()); + Log.Out(Logs::Detail, Logs::Aggro, "Check aggro for %s target %s.", GetName(), mob->GetName()); return( mod_will_aggro(mob, this) ); } } @@ -468,8 +464,8 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) { if(mob->CheckLosFN(sender)) { #if (EQDEBUG>=5) Log.Out(Logs::General, Logs::None, "AIYellForHelp(\"%s\",\"%s\") %s attacking %s Dist %f Z %f", - sender->GetName(), attacker->GetName(), mob->GetName(), - attacker->GetName(), DistanceSquared(mob->GetPosition(), + sender->GetName(), attacker->GetName(), mob->GetName(), + attacker->GetName(), DistanceSquared(mob->GetPosition(), sender->GetPosition()), fabs(sender->GetZ()+mob->GetZ())); #endif mob->AddToHateList(attacker, 1, 0, false); @@ -880,11 +876,11 @@ bool Mob::CombatRange(Mob* other) float _DistNoRoot = DistanceSquared(m_Position, other->GetPosition()); if (GetSpecialAbility(NPC_CHASE_DISTANCE)){ - + bool DoLoSCheck = true; float max_dist = static_cast(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 0)); float min_dist = static_cast(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 1)); - + if (GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 2)) DoLoSCheck = false; //Ignore line of sight check @@ -897,10 +893,10 @@ bool Mob::CombatRange(Mob* other) min_dist = size_mod; //Default to melee range else min_dist = min_dist * min_dist; - + if ((DoLoSCheck && CheckLastLosState()) && (_DistNoRoot >= min_dist && _DistNoRoot <= max_dist)) - SetPseudoRoot(true); - else + SetPseudoRoot(true); + else SetPseudoRoot(false); } @@ -919,7 +915,7 @@ bool Mob::CheckLosFN(Mob* other) { Result = CheckLosFN(other->GetX(), other->GetY(), other->GetZ(), other->GetSize()); SetLastLosState(Result); - + return Result; } @@ -954,11 +950,24 @@ bool Mob::CheckLosFN(float posX, float posY, float posZ, float mobSize) { } //offensive spell aggro -int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc) +int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) { int32 AggroAmount = 0; int32 nonModifiedAggro = 0; uint16 slevel = GetLevel(); + bool add_default = false; + bool stun_proc = false; + bool dispel = false; + bool on_hatelist = target ? target->CheckAggro(this) : false; + + int32 target_hp = target ? target->GetMaxHP() : 18000; // default to max + int32 default_aggro = 0; + if (target_hp >= 18000) // max + default_aggro = 1200; + else if (target_hp < 390) // min, 390 is the first number with int division that is 26 + default_aggro = 25; + else + default_aggro = target_hp / 15; for (int o = 0; o < EFFECT_COUNT; o++) { switch (spells[spell_id].effectid[o]) { @@ -972,7 +981,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc) case SE_MovementSpeed: { int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); if (val < 0) - AggroAmount += (2 + ((slevel * slevel) / 8)); + add_default = true; break; } case SE_AttackSpeed: @@ -980,60 +989,35 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc) case SE_AttackSpeed3: { int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); if (val < 100) - AggroAmount += (5 + ((slevel * slevel) / 5)); + add_default = true; break; } - case SE_Stun: { - int val = (5 + ((slevel * slevel) / 6)); - if (isproc && RuleI(Aggro,MaxStunProcAggro) > -1 && (val > RuleI(Aggro,MaxStunProcAggro))) - val = RuleI(Aggro,MaxStunProcAggro); - AggroAmount += val; + case SE_Stun: + add_default = true; + stun_proc = isproc; break; - } - case SE_Blind: { - AggroAmount += (5 + ((slevel * slevel) / 6)); + case SE_Blind: + case SE_Mez: + case SE_Charm: + case SE_Fear: + add_default = true; break; - } - case SE_Mez: { - AggroAmount += (5 + ((slevel * slevel) / 5)); + case SE_Root: + AggroAmount += 10; break; - } - case SE_Charm: { - AggroAmount += (5 + ((slevel * slevel) / 5)); - break; - } - case SE_Root: { - AggroAmount += (2 + ((slevel * slevel) / 8)); - break; - } - case SE_Fear: { - AggroAmount += (5 + ((slevel * slevel) / 6)); - break; - } case SE_ATK: case SE_ACv2: case SE_ArmorClass: { int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); if (val < 0) - AggroAmount -= val * 2; + add_default = true; break; } case SE_ResistMagic: case SE_ResistFire: case SE_ResistCold: case SE_ResistPoison: - case SE_ResistDisease: { - int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); - if (val < 0) - AggroAmount -= val * 3; - break; - } - case SE_ResistAll: { - int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); - if (val < 0) - AggroAmount -= val * 6; - break; - } + case SE_ResistDisease: case SE_STR: case SE_STA: case SE_DEX: @@ -1043,32 +1027,31 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc) case SE_CHA: { int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); if (val < 0) - AggroAmount -= val * 2; + AggroAmount += 10; + break; + } + case SE_ResistAll: { + int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); + if (val < 0) + AggroAmount += 50; break; } case SE_AllStats: { int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); if (val < 0) - AggroAmount -= val * 6; + AggroAmount += 70; break; } - case SE_BardAEDot: { - AggroAmount += slevel * 2; + case SE_BardAEDot: + AggroAmount += 10; break; - } - case SE_SpinTarget: { - AggroAmount += (5 + ((slevel * slevel) / 5)); - break; - } + case SE_SpinTarget: case SE_Amnesia: - case SE_Silence: { - AggroAmount += slevel * 2; + case SE_Silence: + case SE_Destroy: + add_default = true; break; - } - case SE_Destroy: { - AggroAmount += slevel * 2; - break; - } + // unsure -- leave them this for now case SE_Harmony: case SE_CastingLevel: case SE_MeleeMitigation: @@ -1091,6 +1074,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc) AggroAmount += slevel * 2; break; } + // unsure -- leave them this for now case SE_CurrentMana: case SE_ManaRegen_v2: case SE_ManaPool: @@ -1101,94 +1085,105 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc) break; } case SE_CancelMagic: - case SE_DispelDetrimental: { - AggroAmount += slevel; + case SE_DispelDetrimental: + dispel = true; break; - } case SE_ReduceHate: - case SE_InstantHate: { + case SE_InstantHate: nonModifiedAggro = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); break; - } } } - if (IsAEDurationSpell(spell_id)) - AggroAmount /= 2; + if (add_default) { + if (stun_proc && RuleI(Aggro, MaxStunProcAggro) > -1 && (default_aggro > RuleI(Aggro, MaxStunProcAggro))) + AggroAmount += RuleI(Aggro, MaxStunProcAggro); + else if (IsBardSong(spell_id) && default_aggro > 40) + AggroAmount += 40; // bard songs seem to cap to 40 for most of their spells? + else + AggroAmount += default_aggro; + } - if (spells[spell_id].HateAdded > 0) + if (dispel && target && target->GetHateAmount(this) < 100) + AggroAmount += 50; + + if (spells[spell_id].HateAdded > 0) // overrides the hate (ex. tash) AggroAmount = spells[spell_id].HateAdded; - if (IsBardSong(spell_id)) - AggroAmount = AggroAmount * RuleI(Aggro, SongAggroMod) / 100; if (GetOwner() && IsPet()) AggroAmount = AggroAmount * RuleI(Aggro, PetSpellAggroMod) / 100; if (AggroAmount > 0) { - int HateMod = RuleI(Aggro, SpellAggroMod); - HateMod += GetFocusEffect(focusSpellHateMod, spell_id); AggroAmount = (AggroAmount * HateMod) / 100; - - //made up number probably scales a bit differently on live but it seems like it will be close enough - //every time you cast on live you get a certain amount of "this is a spell" aggro - //confirmed by EQ devs to be 100 exactly at level 85. From their wording it doesn't seem like it's affected - //by hate modifiers either. - //AggroAmount += (slevel*slevel/72); - // Saved so I can reimplement it; - // this should only be on the spell to aggro the npc not every spell - } + // initial aggro gets a bonus 100 + if (!dispel && spells[spell_id].HateAdded == 0 && !on_hatelist) + AggroAmount += 100; + return AggroAmount + spells[spell_id].bonushate + nonModifiedAggro; } //healing and buffing aggro -int32 Mob::CheckHealAggroAmount(uint16 spell_id, uint32 heal_possible) +int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible) { int32 AggroAmount = 0; + auto target_level = target ? target->GetLevel() : GetLevel(); + bool ignore_default_buff = false; // rune/hot don't use the default 9, HP buffs that heal (virtue) do use the default for (int o = 0; o < EFFECT_COUNT; o++) { switch (spells[spell_id].effectid[o]) { - case SE_CurrentHP: { - AggroAmount += IsBuffSpell(spell_id) ? spells[spell_id].mana / 4 : spells[spell_id].mana; + case SE_CurrentHP: { + if (heal_possible == 0) { + AggroAmount += 1; break; } - case SE_Rune: { - AggroAmount += CalcSpellEffectValue_formula(spells[spell_id].formula[0], spells[spell_id].base[0], spells[spell_id].max[o], GetLevel(), spell_id) * 2; - break; - } - case SE_HealOverTime: { - AggroAmount += CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], GetLevel(), spell_id); - break; - } - default: { - break; + // hate based on base healing power of the spell + int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], + spells[spell_id].base[o], spells[spell_id].max[o], GetLevel(), spell_id); + if (val > 0) { + if (heal_possible < val) + val = heal_possible; // capped to amount healed + val = 2 * val / 3; // 3:2 ratio + + if (target_level > 50 && val > 1500) + val = 1500; // target 51+ seems ~1500 + else if (target_level <= 50 && val > 800) + val = 800; // per live patch notes, capped to 800 } + AggroAmount += std::max(val, 1); + break; + } + case SE_Rune: + AggroAmount += CalcSpellEffectValue_formula(spells[spell_id].formula[0], + spells[spell_id].base[0], spells[spell_id].max[o], GetLevel(), spell_id) * 2; + ignore_default_buff = true; + break; + case SE_HealOverTime: + AggroAmount += 10; + ignore_default_buff = true; + break; + default: + break; } } - if (IsBardSong(spell_id)) - AggroAmount = AggroAmount * RuleI(Aggro, SongAggroMod) / 100; if (GetOwner() && IsPet()) AggroAmount = AggroAmount * RuleI(Aggro, PetSpellAggroMod) / 100; + if (!ignore_default_buff && IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) + AggroAmount = 9; + if (AggroAmount > 0) { int HateMod = RuleI(Aggro, SpellAggroMod); - HateMod += GetFocusEffect(focusSpellHateMod, spell_id); //Live AA - Spell casting subtlety HateMod += aabonuses.hatemod + spellbonuses.hatemod + itembonuses.hatemod; AggroAmount = (AggroAmount * HateMod) / 100; - - //made up number probably scales a bit differently on live but it seems like it will be close enough - //every time you cast on live you get a certain amount of "this is a spell" aggro - //confirmed by EQ devs to be 100 exactly at level 85. From their wording it doesn't seem like it's affected - //by hate modifiers either. - //AggroAmount += (slevel*slevel/72); // Moved Below } if (AggroAmount < 0) @@ -1249,7 +1244,7 @@ bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) { return true; float resist_check = 0; - + if(IsCharmSpell(spell_id)) { if (spells[spell_id].powerful_flag == -1) //If charm spell has this set(-1), it can not break till end of duration. @@ -1265,7 +1260,7 @@ bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) { resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, false,0, false, true); //2: The mob makes a resistance check against the charm - if (resist_check == 100) + if (resist_check == 100) return true; else diff --git a/zone/bot.cpp b/zone/bot.cpp index 94b7d9e90..479fd3030 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6220,14 +6220,14 @@ bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { } int32 Bot::CheckAggroAmount(uint16 spellid) { - int32 AggroAmount = Mob::CheckAggroAmount(spellid); + int32 AggroAmount = Mob::CheckAggroAmount(spellid, nullptr); int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid); AggroAmount = (AggroAmount * (100 + focusAggro) / 100); return AggroAmount; } -int32 Bot::CheckHealAggroAmount(uint16 spellid, uint32 heal_possible) { - int32 AggroAmount = Mob::CheckHealAggroAmount(spellid, heal_possible); +int32 Bot::CheckHealAggroAmount(uint16 spellid, Mob *target, uint32 heal_possible) { + int32 AggroAmount = Mob::CheckHealAggroAmount(spellid, target, heal_possible); int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid); AggroAmount = (AggroAmount * (100 + focusAggro) / 100); return AggroAmount; @@ -9081,7 +9081,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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."); @@ -9106,7 +9106,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "You can't summon bots while you are engaged."); return; } - + if(g && g->members[i] && g->members[i]->qglobal) return; } @@ -9264,12 +9264,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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; } @@ -9284,7 +9284,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } else c->Message(15, "You must target a bot first."); - + return; } @@ -9301,7 +9301,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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" }; @@ -9336,7 +9336,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Bot *gearbot = c->GetTarget()->CastToBot(); if((slotId == MainRange)||(slotId == MainAmmo)||(slotId == MainPrimary)||(slotId == MainSecondary)) gearbot->SetBotArcher(false); - + gearbot->RemoveBotItemBySlot(slotId, &TempErrorMessage); if(!TempErrorMessage.empty()) { diff --git a/zone/bot.h b/zone/bot.h index 9a2f2a308..c78abdd8f 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -200,7 +200,7 @@ public: virtual Mob* GetOwner(); virtual Mob* GetOwnerOrSelf(); inline virtual bool HasOwner() { return (GetBotOwner() ? true : false); } - virtual int32 CheckHealAggroAmount(uint16 spellid, uint32 heal_possible = 0); + virtual int32 CheckHealAggroAmount(uint16 spellid, Mob *target, uint32 heal_possible = 0); virtual int32 CalcMaxMana(); virtual void SetAttackTimer(); uint32 GetClassHPFactor(); @@ -547,7 +547,7 @@ public: void SetNumHealRotationMembers( uint8 numMembers ) { _numHealRotationMembers = numMembers; } void SetBardUseOutOfCombatSongs(bool useOutOfCombatSongs) { _bardUseOutOfCombatSongs = useOutOfCombatSongs;} void SetShowHelm(bool showhelm) { _showhelm = showhelm; } - + std::string CreateSayLink(Client* botOwner, const char* message, const char* name); // Class Destructors diff --git a/zone/entity.cpp b/zone/entity.cpp index 8749b102c..e9dd76c5e 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -3068,56 +3068,24 @@ bool EntityList::Fighting(Mob *targ) return false; } -void EntityList::AddHealAggro(Mob *target, Mob *caster, uint16 thedam) +void EntityList::AddHealAggro(Mob *target, Mob *caster, uint16 hate) { - NPC *cur = nullptr; - uint16 count = 0; - std::list npc_sub_list; - auto it = npc_list.begin(); - while (it != npc_list.end()) { - cur = it->second; + if (hate == 0) + return; - if (!cur->CheckAggro(target)) { - ++it; + for (auto &e : npc_list) { + auto &npc = e.second; + if (!npc->CheckAggro(target) || npc->IsFeared()) continue; - } - if (!cur->IsMezzed() && !cur->IsStunned() && !cur->IsFeared()) { - npc_sub_list.push_back(cur); - ++count; - } - ++it; - } + if (zone->random.Roll(15)) // witness check -- place holder + // This is either a level check (con color check?) or a stat roll + continue; - if (thedam > 1) { - if (count > 0) - thedam /= count; - - if (thedam < 1) - thedam = 1; - } - - cur = nullptr; - auto sit = npc_sub_list.begin(); - while (sit != npc_sub_list.end()) { - cur = *sit; - - if (cur->IsPet()) { - if (caster) { - if (cur->CheckAggro(caster)) { - cur->AddToHateList(caster, thedam); - } - } - } else { - if (caster) { - if (cur->CheckAggro(caster)) { - cur->AddToHateList(caster, thedam); - } else { - cur->AddToHateList(caster, thedam * 0.33); - } - } - } - ++sit; + if ((npc->IsMezzed() || npc->IsStunned()) && hate > 4) // patch notes say stunned/mezzed NPCs get a fraction of the hate + npc->AddToHateList(caster, hate / 4); // made up number + else + npc->AddToHateList(caster, hate); } } diff --git a/zone/entity.h b/zone/entity.h index 1adf23783..0b9521179 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -41,7 +41,7 @@ class EntityList; class Group; class Merc; class Mob; -class NPC; +class NPC; class Object; class Petition; class Raid; @@ -333,7 +333,7 @@ public: void SendAlarm(Trap* trap, Mob* currenttarget, uint8 kos); Trap* FindNearbyTrap(Mob* searcher, float max_dist); - void AddHealAggro(Mob* target, Mob* caster, uint16 thedam); + void AddHealAggro(Mob* target, Mob* caster, uint16 hate); Mob* FindDefenseNPC(uint32 npcid); void OpenDoorsNear(NPC* opener); void UpdateWho(bool iSendFullUpdate = false); diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 431f18ffe..2f0712ec0 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1172,22 +1172,22 @@ bool Lua_Mob::Charmed() { int Lua_Mob::CheckAggroAmount(int spell_id) { Lua_Safe_Call_Int(); - return self->CheckAggroAmount(spell_id); + return self->CheckAggroAmount(spell_id, nullptr); } int Lua_Mob::CheckAggroAmount(int spell_id, bool is_proc) { Lua_Safe_Call_Int(); - return self->CheckAggroAmount(spell_id, is_proc); + return self->CheckAggroAmount(spell_id, nullptr, is_proc); } int Lua_Mob::CheckHealAggroAmount(int spell_id) { Lua_Safe_Call_Int(); - return self->CheckHealAggroAmount(spell_id); + return self->CheckHealAggroAmount(spell_id, nullptr); } int Lua_Mob::CheckHealAggroAmount(int spell_id, uint32 heal_possible) { Lua_Safe_Call_Int(); - return self->CheckHealAggroAmount(spell_id, heal_possible); + return self->CheckHealAggroAmount(spell_id, nullptr, heal_possible); } int Lua_Mob::GetAA(int id) { diff --git a/zone/mob.h b/zone/mob.h index fcabf93fd..5cca7d526 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -879,8 +879,8 @@ public: 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 int32 CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc = false); + 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); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index dcd999a3e..323d22b36 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -6316,7 +6316,7 @@ XS(XS_Mob_CheckAggroAmount) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->CheckAggroAmount(spellid); + RETVAL = THIS->CheckAggroAmount(spellid, nullptr); XSprePUSH; PUSHu((UV)RETVAL); } XSRETURN(1); @@ -6349,7 +6349,7 @@ XS(XS_Mob_CheckHealAggroAmount) possible = (uint32)SvUV(ST(2)); } - RETVAL = THIS->CheckHealAggroAmount(spellid, possible); + RETVAL = THIS->CheckHealAggroAmount(spellid, nullptr, possible); XSprePUSH; PUSHu((UV)RETVAL); } XSRETURN(1); @@ -7405,7 +7405,7 @@ XS(XS_Mob_GetGlobal) RETVAL = ret_val.c_str(); sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; } - XSRETURN(1); + XSRETURN(1); } XS(XS_Mob_SetGlobal); diff --git a/zone/spells.cpp b/zone/spells.cpp index 0a4dc29b3..1eb84ad9a 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3704,7 +3704,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r } if (spelltar->IsAIControlled()) { - int32 aggro = CheckAggroAmount(spell_id); + int32 aggro = CheckAggroAmount(spell_id, spelltar); if (aggro > 0) { if (!IsHarmonySpell(spell_id)) spelltar->AddToHateList(this, aggro); @@ -3733,20 +3733,20 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r spelltar->DamageShield(this, true); if (spelltar->IsAIControlled() && IsDetrimentalSpell(spell_id) && !IsHarmonySpell(spell_id)) { - int32 aggro_amount = CheckAggroAmount(spell_id, isproc); - Log.Out(Logs::Detail, Logs::Spells, "Spell %d cast on %s generated %d hate", spell_id, spelltar->GetName(), aggro_amount); - if(aggro_amount > 0) - spelltar->AddToHateList(this, aggro_amount); else{ + int32 aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc); + Log.Out(Logs::Detail, Logs::Spells, "Spell %d cast on %s generated %d hate", spell_id, + spelltar->GetName(), aggro_amount); + if (aggro_amount > 0) { + spelltar->AddToHateList(this, aggro_amount); + } else { int32 newhate = spelltar->GetHateAmount(this) + aggro_amount; - if (newhate < 1) { - spelltar->SetHateAmountOnEnt(this,1); - } else { - spelltar->SetHateAmountOnEnt(this,newhate); - } + spelltar->SetHateAmountOnEnt(this, std::max(newhate, 1)); } + } else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) { + entity_list.AddHealAggro( + spelltar, this, + CheckHealAggroAmount(spell_id, spelltar, (spelltar->GetMaxHP() - spelltar->GetHP()))); } - else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) - entity_list.AddHealAggro(spelltar, this, CheckHealAggroAmount(spell_id, (spelltar->GetMaxHP() - spelltar->GetHP()))); // make sure spelltar is high enough level for the buff if(RuleB(Spells, BuffLevelRestrictions) && !spelltar->CheckSpellLevelRestriction(spell_id)) @@ -4059,7 +4059,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(GetSpecialAbility(UNMEZABLE)) { Log.Out(Logs::Detail, Logs::Spells, "We are immune to Mez spells."); caster->Message_StringID(MT_Shout, CANNOT_MEZ); - int32 aggro = caster->CheckAggroAmount(spell_id); + int32 aggro = caster->CheckAggroAmount(spell_id, this); if(aggro > 0) { AddToHateList(caster, aggro); } else { @@ -4086,7 +4086,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) { Log.Out(Logs::Detail, Logs::Spells, "We are immune to Slow spells."); caster->Message_StringID(MT_Shout, IMMUNE_ATKSPEED); - int32 aggro = caster->CheckAggroAmount(spell_id); + int32 aggro = caster->CheckAggroAmount(spell_id, this); if(aggro > 0) { AddToHateList(caster, aggro); } else { @@ -4102,7 +4102,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(GetSpecialAbility(UNFEARABLE)) { Log.Out(Logs::Detail, Logs::Spells, "We are immune to Fear spells."); caster->Message_StringID(MT_Shout, IMMUNE_FEAR); - int32 aggro = caster->CheckAggroAmount(spell_id); + int32 aggro = caster->CheckAggroAmount(spell_id, this); if(aggro > 0) { AddToHateList(caster, aggro); } else { @@ -4119,7 +4119,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) { Log.Out(Logs::Detail, Logs::Spells, "Level is %d, cannot be feared by this spell.", GetLevel()); caster->Message_StringID(MT_Shout, FEAR_TOO_HIGH); - int32 aggro = caster->CheckAggroAmount(spell_id); + int32 aggro = caster->CheckAggroAmount(spell_id, this); if (aggro > 0) { AddToHateList(caster, aggro); } else { @@ -4142,7 +4142,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) { Log.Out(Logs::Detail, Logs::Spells, "We are immune to Charm spells."); caster->Message_StringID(MT_Shout, CANNOT_CHARM); - int32 aggro = caster->CheckAggroAmount(spell_id); + int32 aggro = caster->CheckAggroAmount(spell_id, this); if(aggro > 0) { AddToHateList(caster, aggro); } else { @@ -4182,7 +4182,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(GetSpecialAbility(UNSNAREABLE)) { Log.Out(Logs::Detail, Logs::Spells, "We are immune to Snare spells."); caster->Message_StringID(MT_Shout, IMMUNE_MOVEMENT); - int32 aggro = caster->CheckAggroAmount(spell_id); + int32 aggro = caster->CheckAggroAmount(spell_id, this); if(aggro > 0) { AddToHateList(caster, aggro); } else { From 7cef9a05dd5c96fabb8017aa24e1b3e0bc30539c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Jul 2015 00:57:10 -0400 Subject: [PATCH 271/846] Bump witness fail chance to 50 --- zone/entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index e9dd76c5e..01f27700e 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -3078,7 +3078,7 @@ void EntityList::AddHealAggro(Mob *target, Mob *caster, uint16 hate) if (!npc->CheckAggro(target) || npc->IsFeared()) continue; - if (zone->random.Roll(15)) // witness check -- place holder + if (zone->random.Roll(50)) // witness check -- place holder // This is either a level check (con color check?) or a stat roll continue; From be16e558ff3550ec8a992dc1cf383bbb3dac6119 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Jul 2015 00:58:02 -0400 Subject: [PATCH 272/846] Fix Spell Casting Subtlety for offensive spells --- zone/aggro.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 75e3434b0..78b26795c 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1117,6 +1117,9 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) int HateMod = RuleI(Aggro, SpellAggroMod); HateMod += GetFocusEffect(focusSpellHateMod, spell_id); + //Live AA - Spell casting subtlety + HateMod += aabonuses.hatemod + spellbonuses.hatemod + itembonuses.hatemod; + AggroAmount = (AggroAmount * HateMod) / 100; } From c91374444bdee9934224158526d194c029315bf6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Jul 2015 01:01:27 -0400 Subject: [PATCH 273/846] Fix bard song hate --- zone/aggro.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 78b26795c..d64d6ac04 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1134,7 +1134,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible) { int32 AggroAmount = 0; - auto target_level = target ? target->GetLevel() : GetLevel(); + auto target_level = target ? target->GetLevel() : 1; bool ignore_default_buff = false; // rune/hot don't use the default 9, HP buffs that heal (virtue) do use the default for (int o = 0; o < EFFECT_COUNT; o++) { @@ -1177,7 +1177,7 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib AggroAmount = AggroAmount * RuleI(Aggro, PetSpellAggroMod) / 100; if (!ignore_default_buff && IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) - AggroAmount = 9; + AggroAmount = IsBardSong(spell_id) ? 2 : 9; if (AggroAmount > 0) { int HateMod = RuleI(Aggro, SpellAggroMod); From 663ff552710e460946ba6aed6b431602a8019a08 Mon Sep 17 00:00:00 2001 From: Kemmler Date: Sat, 18 Jul 2015 16:56:41 -0400 Subject: [PATCH 274/846] Very preliminary work with Visual Studio 2015 Community RC/RTM, resolve some version-specific build errors: 1. Standard library functions snprintf & vsnprintf are available thusly named (without the prepended underscores). Someone may want to check my conditionals against non-MSVC compilers, though. 2. zone/bonuses.cpp throws an internal compiler error with optimize enabled; #pragma disable optimization on VS2015 only. Doing further testing as to whether we have to disable optimization for the WHOLE file ... --- common/tcp_connection.h | 4 +++- common/types.h | 4 +++- zone/beacon.cpp | 6 ++++-- zone/bonuses.cpp | 14 ++++++++++++++ zone/corpse.cpp | 6 ++++-- zone/encounter.cpp | 10 ++++++---- 6 files changed, 34 insertions(+), 10 deletions(-) diff --git a/common/tcp_connection.h b/common/tcp_connection.h index ae02b9c56..c3fa5cd51 100644 --- a/common/tcp_connection.h +++ b/common/tcp_connection.h @@ -23,7 +23,9 @@ */ #ifdef _WINDOWS - #define snprintf _snprintf + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp diff --git a/common/types.h b/common/types.h index 2e1b5d3f3..b3be97d32 100644 --- a/common/types.h +++ b/common/types.h @@ -43,7 +43,9 @@ typedef unsigned char uchar; typedef const char Const_char; //for perl XS #ifdef _WINDOWS - #define snprintf _snprintf + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp typedef void ThreadReturnType; diff --git a/zone/beacon.cpp b/zone/beacon.cpp index 0df02b201..21943ecee 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -26,8 +26,10 @@ target to center around. class Zone; #ifdef _WINDOWS - #define snprintf _snprintf - #define vsnprintf _vsnprintf + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 155dfc4ae..ddabe89d5 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -38,6 +38,16 @@ #include "../common/unix.h" #endif +// Avoid an internal compiler error in VS 2015 +// Community RC (free) with the /O2 compiler +// option enabled on x64 build; definite fail on +// building Release-X64. Disabling optimizations +// for the entire file might be overkill and/or +// inapplicable to other builds, more testing needed. +// Bug has been reported to MS, fix ETA unknown. +#if (defined(_MSC_VER) && defined(_WIN64)&& _MSC_VER==1900) + #pragma optimize( "", off ) +#endif void Mob::CalcBonuses() { @@ -4669,3 +4679,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) } } +// See line 41 above, more or less +#if (defined(_MSC_VER) && defined(_WIN64)&& _MSC_VER==1900) + #pragma optimize( "", on ) +#endif diff --git a/zone/corpse.cpp b/zone/corpse.cpp index af937e41b..b0e9bef0d 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -22,8 +22,10 @@ Child of the Mob class. */ #ifdef _WINDOWS - #define snprintf _snprintf - #define vsnprintf _vsnprintf + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif diff --git a/zone/encounter.cpp b/zone/encounter.cpp index 1f77de43a..01d4ef670 100644 --- a/zone/encounter.cpp +++ b/zone/encounter.cpp @@ -17,10 +17,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef _WINDOWS -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #endif + #define strncasecmp _strnicmp + #define strcasecmp _stricmp #endif #include "../common/races.h" From 87b4640ff08b04e8afc0bb6141c4a67f5500c664 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 20 Jul 2015 00:25:18 -0700 Subject: [PATCH 275/846] Fix bots from loading AAs that are too high of a level for them. --- zone/bot.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index 479fd3030..052f84973 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1279,6 +1279,11 @@ void Bot::LoadAAs() { points = 0; AA::Rank *current = ability->first; + + if (current->level_req > GetLevel()) { + ++iter; + continue; + } while(current) { if(!CanUseAlternateAdvancementRank(current)) { From 5952610a7bafddf2de1009d1d13556911ecbc859 Mon Sep 17 00:00:00 2001 From: Kemmler Date: Sat, 18 Jul 2015 16:56:41 -0400 Subject: [PATCH 276/846] Very preliminary work with Visual Studio 2015 Community RC/RTM, resolve some version-specific build errors: 1. Standard library functions snprintf & vsnprintf are available thusly named (without the prepended underscores). Someone may want to check my conditionals against non-MSVC compilers, though. 2. zone/bonuses.cpp throws an internal compiler error with optimize enabled; #pragma disable optimization on VS2015 only on function Mob::NegateSpellBonuses works around it. --- common/tcp_connection.h | 4 +++- common/types.h | 4 +++- zone/beacon.cpp | 6 ++++-- zone/bonuses.cpp | 18 +++++++++++++++++- zone/corpse.cpp | 6 ++++-- zone/encounter.cpp | 10 ++++++---- 6 files changed, 37 insertions(+), 11 deletions(-) diff --git a/common/tcp_connection.h b/common/tcp_connection.h index ae02b9c56..c3fa5cd51 100644 --- a/common/tcp_connection.h +++ b/common/tcp_connection.h @@ -23,7 +23,9 @@ */ #ifdef _WINDOWS - #define snprintf _snprintf + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp diff --git a/common/types.h b/common/types.h index 2e1b5d3f3..b3be97d32 100644 --- a/common/types.h +++ b/common/types.h @@ -43,7 +43,9 @@ typedef unsigned char uchar; typedef const char Const_char; //for perl XS #ifdef _WINDOWS - #define snprintf _snprintf + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp typedef void ThreadReturnType; diff --git a/zone/beacon.cpp b/zone/beacon.cpp index 0df02b201..21943ecee 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -26,8 +26,10 @@ target to center around. class Zone; #ifdef _WINDOWS - #define snprintf _snprintf - #define vsnprintf _vsnprintf + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 155dfc4ae..3821592cb 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -38,7 +38,6 @@ #include "../common/unix.h" #endif - void Mob::CalcBonuses() { CalcSpellBonuses(&spellbonuses); @@ -3493,6 +3492,17 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff return 0; } +// Avoid an internal compiler error in VS 2015 +// Community RC (free) with the /O2 compiler +// option enabled on x64 build; definite fail on +// building Release-X64. Disabling optimizations +// for the entire file might be overkill and/or +// inapplicable to other builds, more testing needed. +// Bug has been reported to MS, fix ETA unknown. +#if (defined(_MSC_VER) && defined(_WIN64)&& _MSC_VER==1900) +#pragma optimize( "", off ) +#endif + void Mob::NegateSpellsBonuses(uint16 spell_id) { if(!IsValidSpell(spell_id)) @@ -4654,6 +4664,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.SkillProcSuccess[e] = effect_value; aabonuses.SkillProcSuccess[e] = effect_value; } + break; } case SE_SkillProc:{ @@ -4663,9 +4674,14 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.SkillProc[e] = effect_value; aabonuses.SkillProc[e] = effect_value; } + break; } } } } } +// See line 3495 above, more or less +#if (defined(_MSC_VER) && defined(_WIN64)&& _MSC_VER==1900) + #pragma optimize( "", on ) +#endif diff --git a/zone/corpse.cpp b/zone/corpse.cpp index af937e41b..b0e9bef0d 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -22,8 +22,10 @@ Child of the Mob class. */ #ifdef _WINDOWS - #define snprintf _snprintf - #define vsnprintf _vsnprintf + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif diff --git a/zone/encounter.cpp b/zone/encounter.cpp index 1f77de43a..01d4ef670 100644 --- a/zone/encounter.cpp +++ b/zone/encounter.cpp @@ -17,10 +17,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef _WINDOWS -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp + #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #endif + #define strncasecmp _strnicmp + #define strcasecmp _stricmp #endif #include "../common/races.h" From 8a5510628838ecc1f8a102babb0d9ee678ab1264 Mon Sep 17 00:00:00 2001 From: Kemmler Date: Tue, 21 Jul 2015 00:42:04 -0400 Subject: [PATCH 277/846] Visual Studio 2015 Community compiles bonuses.cpp correctly now. --- zone/bonuses.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index ad5a5770e..155dfc4ae 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -38,6 +38,7 @@ #include "../common/unix.h" #endif + void Mob::CalcBonuses() { CalcSpellBonuses(&spellbonuses); @@ -3492,17 +3493,6 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff return 0; } -// Avoid an internal compiler error in VS 2015 -// Community RC (free) with the /O2 compiler -// option enabled on x64 build; definite fail on -// building Release-X64. Disabling optimizations -// for the entire file might be overkill and/or -// inapplicable to other builds, more testing needed. -// Bug has been reported to MS, fix ETA unknown. -#if (defined(_MSC_VER) && defined(_WIN64)&& _MSC_VER==1900) -#pragma optimize( "", off ) -#endif - void Mob::NegateSpellsBonuses(uint16 spell_id) { if(!IsValidSpell(spell_id)) @@ -4664,7 +4654,6 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.SkillProcSuccess[e] = effect_value; aabonuses.SkillProcSuccess[e] = effect_value; } - break; } case SE_SkillProc:{ @@ -4674,15 +4663,9 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.SkillProc[e] = effect_value; aabonuses.SkillProc[e] = effect_value; } - break; } } } } } - -// See line 3495 above, more or less -#if (defined(_MSC_VER) && defined(_WIN64)&& _MSC_VER==1900) - #pragma optimize( "", on ) -#endif From 8f78a3fd356da5469ccc649a9d5b12d94ac75ae2 Mon Sep 17 00:00:00 2001 From: Drajor Date: Wed, 22 Jul 2015 15:50:19 +1000 Subject: [PATCH 278/846] Hand in stacked items Added support for handing in stacked items and getting task credit for those items. --- zone/client.h | 2 +- zone/tasks.cpp | 12 +++++------- zone/tasks.h | 4 +++- zone/trading.cpp | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/zone/client.h b/zone/client.h index bbe4ba575..22c81290c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -991,7 +991,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(uint32 *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); } diff --git a/zone/tasks.cpp b/zone/tasks.cpp index a5cdeb5a8..cc84cc9de 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1692,7 +1692,7 @@ void ClientTaskState::UpdateTasksOnExplore(Client *c, int ExploreID) { return; } -bool ClientTaskState::UpdateTasksOnDeliver(Client *c, uint32 *Items, int Cash, int NPCTypeID) { +bool ClientTaskState::UpdateTasksOnDeliver(Client *c, std::list& Items, int Cash, int NPCTypeID) { bool Ret = false; @@ -1731,17 +1731,15 @@ bool ClientTaskState::UpdateTasksOnDeliver(Client *c, uint32 *Items, int Cash, i Ret = true; } else { - for(int k=0; k<4; k++) { - if(Items[k]==0) continue; + for(auto& k : Items) { switch(Task->Activity[j].GoalMethod) { case METHODSINGLEID: - if(Task->Activity[j].GoalID != (int)Items[k]) continue; + if(Task->Activity[j].GoalID != k->GetID()) continue; break; case METHODLIST: - if(!taskmanager->GoalListManager.IsInList(Task->Activity[j].GoalID, - Items[k])) + if (!taskmanager->GoalListManager.IsInList(Task->Activity[j].GoalID, k->GetID())) continue; break; @@ -1751,7 +1749,7 @@ bool ClientTaskState::UpdateTasksOnDeliver(Client *c, uint32 *Items, int Cash, i } // We found an active task related to this item, so increment the done count Log.Out(Logs::General, Logs::Tasks, "[UPDATE] Increment on GiveItem"); - IncrementDoneCount(c, Task, i, j, 1); + IncrementDoneCount(c, Task, i, j, k->GetCharges()); Ret = true; } } diff --git a/zone/tasks.h b/zone/tasks.h index 459eacd08..9b5543b3d 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -22,6 +22,7 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) #include "../common/types.h" +#include #include #define MAXTASKS 10000 @@ -44,6 +45,7 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) class Client; class Mob; +class ItemInst; struct TaskGoalList_Struct { int ListID; @@ -185,7 +187,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, uint32 *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/trading.cpp b/zone/trading.cpp index df8d159b1..a12b426e4 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -874,11 +874,11 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } std::vector item_list; - uint32 items[4] = { 0 }; + std::list items; for(int i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_NPC_END; ++i) { ItemInst *inst = m_inv.GetItem(i); if(inst) { - items[i - EmuConstants::TRADE_BEGIN] = inst->GetItem()->ID; + items.push_back(inst); item_list.push_back(inst); } else { item_list.push_back((ItemInst*)nullptr); From 918bdd73f4b9314654e39a68c545cb193937034b Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Wed, 22 Jul 2015 09:23:49 -0400 Subject: [PATCH 279/846] Files changed: ruletypes.h, client.cpp Files added: 2015_07_22_CommonTongue.sql Adds new rules so you can change the start Common Tongue value for Iksars, Ogres, and Trolls. --- common/ruletypes.h | 3 +++ utils/sql/git/optional/2015_07_22_CommonTongue.sql | 4 ++++ world/client.cpp | 6 +++--- 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 utils/sql/git/optional/2015_07_22_CommonTongue.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index e1a095724..1356d63e7 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -116,6 +116,9 @@ RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lo RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster. RULE_BOOL(Character, SpamHPUpdates, false) // if your server has stupid amounts of HP that causes client display issues, turn this on! RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100% +RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?) +RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?) +RULE_INT(Character, TrollCommonTongue, 95) // 95 By default (live-like?) RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/utils/sql/git/optional/2015_07_22_CommonTongue.sql b/utils/sql/git/optional/2015_07_22_CommonTongue.sql new file mode 100644 index 000000000..7fe6d3c4f --- /dev/null +++ b/utils/sql/git/optional/2015_07_22_CommonTongue.sql @@ -0,0 +1,4 @@ +INSERT INTO `rule_values` VALUES +('1', 'Character:IksarCommonTongue', '95', ''), +('1', 'Character:OgreCommonTongue', '95', ''), +('1', 'Character:TrollCommonTongue', '95', ''); \ No newline at end of file diff --git a/world/client.cpp b/world/client.cpp index 30128c076..9a194e5ec 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1948,21 +1948,21 @@ void Client::SetRacialLanguages( PlayerProfile_Struct *pp ) } case IKSAR: { - pp->languages[LANG_COMMON_TONGUE] = 95; + pp->languages[LANG_COMMON_TONGUE] = RuleI(Character, IksarCommonTongue); pp->languages[LANG_DARK_SPEECH] = 100; pp->languages[LANG_LIZARDMAN] = 100; break; } case OGRE: { - pp->languages[LANG_COMMON_TONGUE] = 95; + pp->languages[LANG_COMMON_TONGUE] = RuleI(Character, OgreCommonTongue); pp->languages[LANG_DARK_SPEECH] = 100; pp->languages[LANG_OGRE] = 100; break; } case TROLL: { - pp->languages[LANG_COMMON_TONGUE] = 95; + pp->languages[LANG_COMMON_TONGUE] = RuleI(Character, TrollCommonTongue); pp->languages[LANG_DARK_SPEECH] = 100; pp->languages[LANG_TROLL] = 100; break; From fb4cc70999c76ce5a53bbb5a1180945fbbc3c32b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 22 Jul 2015 16:31:38 -0400 Subject: [PATCH 280/846] Correct some Aggro calcs See updated post: http://www.eqemulator.org/forums/showthread.php?t=39819 Aggro:MaxStunProcAggro renamed to Aggro:MaxScalingProcAggro --- changelog.txt | 7 ++++++- common/ruletypes.h | 2 +- zone/aggro.cpp | 51 +++++++++++++++++----------------------------- 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/changelog.txt b/changelog.txt index 68ef9c2b1..c403db8dd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 07/16/2013 == +== 07/22/2015 == +mackal: Corrected some hate value calcs based on updated http://www.eqemulator.org/forums/showthread.php?t=39819 + + Rule Aggro:MaxStunProcAggro to Aggro:MaxScalingProcAggro since the cap applies to more than stuns + +== 07/16/2015 == mackal: Rework spell aggro based on http://www.eqemulator.org/forums/showthread.php?t=39819 == 07/15/2015 == diff --git a/common/ruletypes.h b/common/ruletypes.h index e1a095724..fb0edeb54 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -480,7 +480,7 @@ RULE_INT(Aggro, SpellAggroMod, 100) RULE_INT(Aggro, SongAggroMod, 33) RULE_INT(Aggro, PetSpellAggroMod, 10) RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate generate this much hate on a Tunnel Vision mob -RULE_INT(Aggro, MaxStunProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add. +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_CATEGORY_END() diff --git a/zone/aggro.cpp b/zone/aggro.cpp index d64d6ac04..d1574dc50 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -955,18 +955,16 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) int32 AggroAmount = 0; int32 nonModifiedAggro = 0; uint16 slevel = GetLevel(); - bool add_default = false; - bool stun_proc = false; bool dispel = false; bool on_hatelist = target ? target->CheckAggro(this) : false; + int proc_cap = RuleI(Aggro, MaxScalingProcAggro); + int hate_cap = isproc && proc_cap != -1 ? proc_cap : 1200; int32 target_hp = target ? target->GetMaxHP() : 18000; // default to max - int32 default_aggro = 0; + int32 default_aggro = 25; if (target_hp >= 18000) // max - default_aggro = 1200; - else if (target_hp < 390) // min, 390 is the first number with int division that is 26 - default_aggro = 25; - else + default_aggro = hate_cap; + else if (target_hp >= 390) // min, 390 is the first number with int division that is 26 default_aggro = target_hp / 15; for (int o = 0; o < EFFECT_COUNT; o++) { @@ -981,7 +979,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) case SE_MovementSpeed: { int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); if (val < 0) - add_default = true; + AggroAmount += default_aggro; break; } case SE_AttackSpeed: @@ -989,30 +987,27 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) case SE_AttackSpeed3: { int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); if (val < 100) - add_default = true; + AggroAmount += default_aggro; break; } case SE_Stun: - add_default = true; - stun_proc = isproc; - break; case SE_Blind: case SE_Mez: case SE_Charm: case SE_Fear: - add_default = true; + AggroAmount += default_aggro; break; case SE_Root: AggroAmount += 10; break; - case SE_ATK: case SE_ACv2: case SE_ArmorClass: { int val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id); if (val < 0) - add_default = true; + AggroAmount += default_aggro; break; } + case SE_ATK: case SE_ResistMagic: case SE_ResistFire: case SE_ResistCold: @@ -1049,7 +1044,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) case SE_Amnesia: case SE_Silence: case SE_Destroy: - add_default = true; + AggroAmount += default_aggro; break; // unsure -- leave them this for now case SE_Harmony: @@ -1095,14 +1090,8 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) } } - if (add_default) { - if (stun_proc && RuleI(Aggro, MaxStunProcAggro) > -1 && (default_aggro > RuleI(Aggro, MaxStunProcAggro))) - AggroAmount += RuleI(Aggro, MaxStunProcAggro); - else if (IsBardSong(spell_id) && default_aggro > 40) - AggroAmount += 40; // bard songs seem to cap to 40 for most of their spells? - else - AggroAmount += default_aggro; - } + if (IsBardSong(spell_id) && AggroAmount > 40) + AggroAmount = 40; // bard songs seem to cap to 40 for most of their spells? if (dispel && target && target->GetHateAmount(this) < 100) AggroAmount += 50; @@ -1113,7 +1102,8 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) if (GetOwner() && IsPet()) AggroAmount = AggroAmount * RuleI(Aggro, PetSpellAggroMod) / 100; - if (AggroAmount > 0) { + // hate focus ignored on first action for some reason + if (!on_hatelist && AggroAmount > 0) { int HateMod = RuleI(Aggro, SpellAggroMod); HateMod += GetFocusEffect(focusSpellHateMod, spell_id); @@ -1123,7 +1113,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) AggroAmount = (AggroAmount * HateMod) / 100; } - // initial aggro gets a bonus 100 + // initial aggro gets a bonus 100 besides for dispel or hate override if (!dispel && spells[spell_id].HateAdded == 0 && !on_hatelist) AggroAmount += 100; @@ -1161,8 +1151,8 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib break; } case SE_Rune: - AggroAmount += CalcSpellEffectValue_formula(spells[spell_id].formula[0], - spells[spell_id].base[0], spells[spell_id].max[o], GetLevel(), spell_id) * 2; + AggroAmount += CalcSpellEffectValue_formula(spells[spell_id].formula[o], + spells[spell_id].base[o], spells[spell_id].max[o], GetLevel(), spell_id) * 2; ignore_default_buff = true; break; case SE_HealOverTime: @@ -1189,10 +1179,7 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib AggroAmount = (AggroAmount * HateMod) / 100; } - if (AggroAmount < 0) - return 0; - else - return AggroAmount; + return std::max(0, AggroAmount); } void Mob::AddFeignMemory(Client* attacker) { From 97e47dcbfbed1eba4b84b1648dde7284aba90f5e Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 22 Jul 2015 17:42:57 -0700 Subject: [PATCH 281/846] Fix for localaddress overwriting address --- zone/worldserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 59eca67ac..029975efe 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -119,7 +119,7 @@ void WorldServer::OnConnected() { } if(config->LocalAddress.length() > 0) { - strn0cpy(sci->address, config->LocalAddress.c_str(), 250); + strn0cpy(sci->local_address, config->LocalAddress.c_str(), 250); } SendPacket(pack); From 22a157787e01e456c81cb54e7d2f2ead61309e21 Mon Sep 17 00:00:00 2001 From: Drajor Date: Sat, 25 Jul 2015 16:14:33 +1000 Subject: [PATCH 282/846] Fix for ClientTaskState::UpdateTasksOnDeliver Fix for issue introduced in changes to allow stacked items to be handed in. Calling GetCharges on an item that can not be stacked will return 0 so this mean't that task credit was not awarded for single items. --- zone/tasks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/tasks.cpp b/zone/tasks.cpp index cc84cc9de..d52ae842b 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1749,7 +1749,7 @@ bool ClientTaskState::UpdateTasksOnDeliver(Client *c, std::list& Item } // We found an active task related to this item, so increment the done count Log.Out(Logs::General, Logs::Tasks, "[UPDATE] Increment on GiveItem"); - IncrementDoneCount(c, Task, i, j, k->GetCharges()); + IncrementDoneCount(c, Task, i, j, k->GetCharges() <= 0 ? 1 : k->GetCharges()); Ret = true; } } From 4258e5cebca21bd77310ce6e7567447b81673543 Mon Sep 17 00:00:00 2001 From: Drajor Date: Sat, 25 Jul 2015 17:13:18 +1000 Subject: [PATCH 283/846] Fixes #445 (Integer wrap in Inventory::HasItem) unit8 changed to uint32 will prevent wrapping, excepting maybe extreme cases. Fixes #445 --- common/item.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/item.cpp b/common/item.cpp index 7c871e630..8e8ec6f1a 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -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) { - uint8 quantity_found = 0; + uint32 quantity_found = 0; for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { auto inst = iter->second; @@ -1243,7 +1243,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) // to unintended results. Funtionality should be observed when referencing the return value // of this query - uint8 quantity_found = 0; + uint32 quantity_found = 0; for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { auto inst = *iter; @@ -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) { - uint8 quantity_found = 0; + uint32 quantity_found = 0; for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { auto inst = iter->second; @@ -1320,7 +1320,7 @@ int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, ui // Internal Method: Checks an inventory queue type bucket for a particular item int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) { - uint8 quantity_found = 0; + uint32 quantity_found = 0; for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { auto inst = *iter; From be459de555336fbfd2d2f075ab450aae1f83c9d6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 27 Jul 2015 01:19:45 -0400 Subject: [PATCH 284/846] Fix issue with adding spells via quest to an empty list --- zone/mob_ai.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index c8654849a..b9394f9a3 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2495,6 +2495,10 @@ void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, t.resist_adjust = iResistAdjust; AIspells.push_back(t); + + // If we're going from an empty list, we need to start the timer + if (AIspells.size() == 1) + AIautocastspell_timer->Start(RandomTimer(0, 15000), false); } void NPC::RemoveSpellFromNPCList(int16 spell_id) From 4c9a3b7c29cdaa961c3fa59a428344b2043c607d Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 27 Jul 2015 22:13:55 -0400 Subject: [PATCH 285/846] Fix for crash potential in Client::Handle_OP_ShopPlayerBuy --- changelog.txt | 3 +++ zone/client_packet.cpp | 25 +++++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/changelog.txt b/changelog.txt index c403db8dd..18b2e9a3f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/27/2015 == +Uleat: Reworked the QS Audit code in Handle_OP_ShopPlayerBuy (\zone\client_packet.cpp) to help eliminate potential for exception errors + == 07/22/2015 == mackal: Corrected some hate value calcs based on updated http://www.eqemulator.org/forums/showthread.php?t=39819 diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index ce63610da..f1ec8e8ec 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12232,20 +12232,29 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) qsaudit->items[0].item_id = item->ID; qsaudit->items[0].charges = mpo->quantity; - if (freeslotid == INVALID_INDEX) { + const ItemInst* audit_inst = m_inv[freeslotid]; + + if (audit_inst) { + qsaudit->items[0].aug_1 = audit_inst->GetAugmentItemID(0); + qsaudit->items[0].aug_2 = audit_inst->GetAugmentItemID(1); + qsaudit->items[0].aug_3 = audit_inst->GetAugmentItemID(2); + qsaudit->items[0].aug_4 = audit_inst->GetAugmentItemID(3); + qsaudit->items[0].aug_5 = audit_inst->GetAugmentItemID(4); + } + else { qsaudit->items[0].aug_1 = 0; qsaudit->items[0].aug_2 = 0; qsaudit->items[0].aug_3 = 0; qsaudit->items[0].aug_4 = 0; qsaudit->items[0].aug_5 = 0; + + if (freeslotid != INVALID_INDEX) { + Log.Out(Logs::General, Logs::Error, "Handle_OP_ShopPlayerBuy: QS Audit could not locate merchant (%u) purchased item in player (%u) inventory slot (%i)", + qsaudit->merchant_id, qsaudit->char_id, freeslotid); + } } - else { - qsaudit->items[0].aug_1 = m_inv[freeslotid]->GetAugmentItemID(0); - qsaudit->items[0].aug_2 = m_inv[freeslotid]->GetAugmentItemID(1); - qsaudit->items[0].aug_3 = m_inv[freeslotid]->GetAugmentItemID(2); - qsaudit->items[0].aug_4 = m_inv[freeslotid]->GetAugmentItemID(3); - qsaudit->items[0].aug_5 = m_inv[freeslotid]->GetAugmentItemID(4); - } + + audit_inst = nullptr; qspack->Deflate(); if (worldserver.Connected()) { worldserver.SendPacket(qspack); } From 0513f1ad5d6cff729f92ec6ad11ffe2a1df17daf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Jul 2015 21:26:51 -0400 Subject: [PATCH 286/846] Default area rampage to unlimited targets --- zone/hate_list.cpp | 2 +- zone/mob_ai.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 86a75a545..2268fd8f4 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -537,7 +537,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption int hit_count = 0; auto it = list.begin(); - while (it != list.end() && hit_count < count) { + while (it != list.end() && (hit_count == -1 || hit_count < count)) { struct_HateList *h = (*it); if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) { if (caster->CombatRange(h->entity_on_hatelist)) { diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b9394f9a3..9a483fddd 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2000,7 +2000,7 @@ void Mob::AreaRampage(ExtraAttackOptions *opts) } int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); - rampage_targets = rampage_targets > 0 ? rampage_targets : 1; + rampage_targets = rampage_targets > 0 ? rampage_targets : -1; index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); if(index_hit == 0) From f380519803f46e902fe11f51f3bd61d4ffbdd4cf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Jul 2015 21:42:55 -0400 Subject: [PATCH 287/846] Fix error with previous commit --- zone/hate_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 2268fd8f4..dfa6e30a8 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -537,7 +537,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption int hit_count = 0; auto it = list.begin(); - while (it != list.end() && (hit_count == -1 || hit_count < count)) { + while (it != list.end() && (count == -1 || hit_count < count)) { struct_HateList *h = (*it); if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) { if (caster->CombatRange(h->entity_on_hatelist)) { From b98bc207fbde71d7ff79907d6fc3caaa350d52d8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 31 Jul 2015 01:46:16 -0400 Subject: [PATCH 288/846] Move AE Ramp back to 1 target until iterator invalidation issue is resolved --- 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 9a483fddd..b9394f9a3 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2000,7 +2000,7 @@ void Mob::AreaRampage(ExtraAttackOptions *opts) } int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); - rampage_targets = rampage_targets > 0 ? rampage_targets : -1; + rampage_targets = rampage_targets > 0 ? rampage_targets : 1; index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); if(index_hit == 0) From 7fc8841a679a5055849b6b103a9daa17520ef4c0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 31 Jul 2015 02:00:09 -0400 Subject: [PATCH 289/846] Fix AE Ramp iterator issue --- zone/hate_list.cpp | 2 +- zone/mob_ai.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index dfa6e30a8..6d7d04496 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -539,13 +539,13 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption auto it = list.begin(); while (it != list.end() && (count == -1 || hit_count < count)) { struct_HateList *h = (*it); + ++it; // advancing the iterator here prevents the iterator being invalidated if they die if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) { if (caster->CombatRange(h->entity_on_hatelist)) { ++hit_count; caster->ProcessAttackRounds(h->entity_on_hatelist, opts); } } - ++it; } return hit_count; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b9394f9a3..9a483fddd 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2000,7 +2000,7 @@ void Mob::AreaRampage(ExtraAttackOptions *opts) } int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); - rampage_targets = rampage_targets > 0 ? rampage_targets : 1; + rampage_targets = rampage_targets > 0 ? rampage_targets : -1; index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); if(index_hit == 0) From 892fb58b181929fbad045cec8483fa35454d3f06 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sat, 1 Aug 2015 00:11:18 -0400 Subject: [PATCH 290/846] Added $client->GetMoney(type, subtype) to Perl/Lua. Types: - 0: Copper - 1: Silver - 2: Gold - 3: Platinum Sub Types (if applicable): - 0: On Character - 1: In Bank - 2: On Cursor - 3: Shared Bank (only applies to Type 3/Platinum) --- zone/client.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++ zone/client.h | 1 + zone/lua_client.cpp | 8 ++++- zone/lua_client.h | 1 + zone/perl_client.cpp | 31 ++++++++++++++++++ 5 files changed, 116 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 47b2eea68..f784e507e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8592,3 +8592,79 @@ void Client::SendHPUpdateMarquee(){ std::string health_update_notification = StringFormat("Health: %u%%", health_percentage); this->SendMarqueeMessage(15, 510, 0, 3000, 3000, health_update_notification); } + +uint32 Client::GetMoney(uint8 type, uint8 subtype) { + uint32 value = 0; + switch (type) { + case 0: { + switch (subtype) { + case 0: + value = static_cast(m_pp.copper); + break; + case 1: + value = static_cast(m_pp.copper_bank); + break; + case 2: + value = static_cast(m_pp.copper_cursor); + break; + default: + break; + } + break; + } + case 1: { + switch (subtype) { + case 0: + value = static_cast(m_pp.silver); + break; + case 1: + value = static_cast(m_pp.silver_bank); + break; + case 2: + value = static_cast(m_pp.silver_cursor); + break; + default: + break; + } + break; + } + case 2: { + switch (subtype) { + case 0: + value = static_cast(m_pp.gold); + break; + case 1: + value = static_cast(m_pp.gold_bank); + break; + case 2: + value = static_cast(m_pp.gold_cursor); + break; + default: + break; + } + break; + } + case 3: { + switch (subtype) { + case 0: + value = static_cast(m_pp.platinum); + break; + case 1: + value = static_cast(m_pp.platinum_bank); + break; + case 2: + value = static_cast(m_pp.platinum_cursor); + break; + case 3: + value = static_cast(m_pp.platinum_shared); + break; + default: + break; + } + break; + } + default: + break; + } + return value; +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index 22c81290c..64017fec3 100644 --- a/zone/client.h +++ b/zone/client.h @@ -663,6 +663,7 @@ public: bool HasMoney(uint64 copper); uint64 GetCarriedMoney(); uint64 GetAllMoney(); + uint32 GetMoney(uint8 type, uint8 subtype); bool IsDiscovered(uint32 itemid); void DiscoverItem(uint32 itemid); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 7aa78d11d..b7dad0ce3 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1315,6 +1315,11 @@ void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint3 self->QuestReward(target, copper, silver, gold, platinum, itemid, exp, faction); } +uint32 Lua_Client::GetMoney(uint8 type, uint8 subtype) { + Lua_Safe_Call_Int(); + return self->GetMoney(type, subtype); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -1576,7 +1581,8 @@ luabind::scope lua_register_client() { .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) - .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Lua_Client::QuestReward); + .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Lua_Client::QuestReward) + .def("GetMoney", (uint32(Lua_Client::*)(uint8, uint8))&Lua_Client::GetMoney); } luabind::scope lua_register_inventory_where() { diff --git a/zone/lua_client.h b/zone/lua_client.h index f3f0e1897..e50a16b98 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -256,6 +256,7 @@ public: int GetAggroCount(); uint64 GetCarriedMoney(); uint64 GetAllMoney(); + uint32 GetMoney(uint8 type, uint8 subtype); void OpenLFGuildWindow(); void Signal(uint32 id); void AddAlternateCurrencyValue(uint32 currency, int amount); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index de9e8512a..0eb3b918b 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6280,6 +6280,36 @@ XS(XS_Client_QuestReward) XSRETURN_EMPTY; } +XS(XS_Client_GetMoney); +XS(XS_Client_GetMoney) +{ + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: GetMoney(THIS, type, subtype)"); + { + Client* THIS; + uint32 RETVAL; + uint8 type = (uint8)SvUV(ST(1)); + uint8 subtype = (uint8)SvUV(ST(2)); + 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->GetMoney(type, subtype); + XSprePUSH; PUSHn((uint32)RETVAL); + } + XSRETURN(1); +} + + #ifdef __cplusplus extern "C" #endif @@ -6527,6 +6557,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetTargetRingZ"), XS_Client_GetTargetRingZ, file, "$$"); newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$"); newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$"); + newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$"); XSRETURN_YES; } From a04e78cfd1001e1e4e0f766c9d122fd954d35b4b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 2 Aug 2015 02:24:26 -0500 Subject: [PATCH 291/846] 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. --- changelog.txt | 4 ++++ zone/mob.h | 1 + zone/npc.cpp | 7 +++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 18b2e9a3f..d0d757df0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 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. + == 07/27/2015 == Uleat: Reworked the QS Audit code in Handle_OP_ShopPlayerBuy (\zone\client_packet.cpp) to help eliminate potential for exception errors diff --git a/zone/mob.h b/zone/mob.h index 5cca7d526..20df1ec41 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -431,6 +431,7 @@ public: ((static_cast(cur_mana) / max_mana) * 100); } virtual int32 CalcMaxMana(); uint32 GetNPCTypeID() const { return npctype_id; } + void SetNPCTypeID(uint32 npctypeid) { npctype_id = npctypeid; } inline const glm::vec4& GetPosition() const { return m_Position; } inline const float GetX() const { return m_Position.x; } inline const float GetY() const { return m_Position.y; } diff --git a/zone/npc.cpp b/zone/npc.cpp index 8dbab7c64..214161a3b 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1045,7 +1045,7 @@ uint32 ZoneDatabase::CreateNewNPCCommand(const char *zone, uint32 zone_version, query = StringFormat("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)", + "VALUES(%i, \"%s\" , %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %i, %i, %i)", npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), @@ -1059,7 +1059,7 @@ uint32 ZoneDatabase::CreateNewNPCCommand(const char *zone, uint32 zone_version, query = StringFormat("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)", + "VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %i, %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); @@ -1077,6 +1077,9 @@ uint32 ZoneDatabase::CreateNewNPCCommand(const char *zone, uint32 zone_version, } uint32 spawngroupid = results.LastInsertedID(); + spawn->SetSp2(spawngroupid); + spawn->SetNPCTypeID(npc_type_id); + query = StringFormat("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(), From 4e538d14c8f592dc572d6f51ef183c2a7664c8fa Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Tue, 4 Aug 2015 09:48:39 -0400 Subject: [PATCH 292/846] Fix snow so it ends correctly. Packet is different from the all zeros sent to end rain. End packets need to have the type that is ending. --- zone/zone.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zone/zone.cpp b/zone/zone.cpp index e5e30f01a..63730d0aa 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1346,7 +1346,6 @@ void Zone::ChangeWeather() weathertimer = (duration*60)*1000; Weather_Timer->Start(weathertimer); - zone->zone_weather = 0; zone->weather_intensity = 0; } else if(tmpOldWeather == 2) @@ -1358,7 +1357,6 @@ void Zone::ChangeWeather() weathertimer = (duration*60)*1000; Weather_Timer->Start(weathertimer); - zone->zone_weather = 0; zone->weather_intensity = 0; } } @@ -1377,6 +1375,10 @@ void Zone::ChangeWeather() { Log.Out(Logs::General, Logs::None, "The weather for zone: %s has changed. Old weather was = %i. New weather is = %i The next check will be in %i seconds. Rain chance: %i, Rain duration: %i, Snow chance %i, Snow duration: %i", zone->GetShortName(), tmpOldWeather, zone_weather,Weather_Timer->GetRemainingTime()/1000,rainchance,rainduration,snowchance,snowduration); this->weatherSend(); + if (zone->weather_intensity == 0) + { + zone->zone_weather = 0; + } } } From e0d65df4de9016a5c8ad11a9cbc113613f0635e9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 6 Aug 2015 20:29:55 -0400 Subject: [PATCH 293/846] Fix #myskills crash --- zone/client.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index f784e507e..acd0456ca 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4957,7 +4957,7 @@ void Client::ShowSkillsWindow() "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"}; + "Pottery","Percussion Instruments","Intimidation","Berserking","Taunt","Frenzy","Remove Traps","Triple Attack"}; for(int i = 0; i <= (int)HIGHEST_SKILL; i++) Skills[SkillName[i]] = (SkillUseTypes)i; @@ -4979,7 +4979,6 @@ void Client::ShowSkillsWindow() this->SendPopupToClient(WindowTitle, WindowText.c_str()); } - void Client::SetShadowStepExemption(bool v) { if(v == true) @@ -8654,7 +8653,7 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) { break; case 2: value = static_cast(m_pp.platinum_cursor); - break; + break; case 3: value = static_cast(m_pp.platinum_shared); break; @@ -8667,4 +8666,4 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) { break; } return value; -} \ No newline at end of file +} From ede969a6140a7e73a83b3fa1d52612095c068cac Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sat, 8 Aug 2015 17:09:57 -0400 Subject: [PATCH 294/846] Added GetAccountAge() functionality to Perl so people can grant veteran AAs based on account age. --- zone/client.cpp | 4 ++++ zone/client.h | 1 + zone/perl_client.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/zone/client.cpp b/zone/client.cpp index acd0456ca..f823c8b54 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8667,3 +8667,7 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) { } return value; } + +int Client::GetAccountAge() { + return (time(nullptr) - GetAccountCreation()); +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index 64017fec3..54452f373 100644 --- a/zone/client.h +++ b/zone/client.h @@ -664,6 +664,7 @@ public: uint64 GetCarriedMoney(); uint64 GetAllMoney(); uint32 GetMoney(uint8 type, uint8 subtype); + int GetAccountAge(); bool IsDiscovered(uint32 itemid); void DiscoverItem(uint32 itemid); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 0eb3b918b..3858eac0e 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6309,6 +6309,32 @@ XS(XS_Client_GetMoney) XSRETURN(1); } +XS(XS_Client_GetAccountAge); +XS(XS_Client_GetAccountAge) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: GetAccountAge(THIS)"); + { + Client* THIS; + int 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->GetAccountAge(); + XSprePUSH; PUSHn((int)RETVAL); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" @@ -6558,6 +6584,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$"); newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$"); newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$"); + newXSproto(strcpy(buf, "GetAccountAge"), XS_Client_GetAccountAge, file, "$"); XSRETURN_YES; } From 1fc23beb78ec0a793d69be9f0686ff9b8feecea8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 12 Aug 2015 23:36:59 -0400 Subject: [PATCH 295/846] Clear auto XTargets on WipeHateList --- zone/hate_list.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 6d7d04496..0247b376a 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -67,8 +67,10 @@ void HateList::WipeHateList() { parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0); - if (m->IsClient()) + if (m->IsClient()) { m->CastToClient()->DecrementAggroCount(); + m->CastToClient()->RemoveXTarget(hate_owner, true); + } } delete (*iterator); iterator = list.erase(iterator); From fe0758c9843d48c98a86cd7318bd3dff53969bb6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 13 Aug 2015 22:30:49 -0400 Subject: [PATCH 296/846] Add EVENT_TICK for NPCs This event fires at the start of the tick processing so we can script on the actual tick. --- zone/embparser.cpp | 47 +++++++++++++++--------------- zone/event_codes.h | 1 + zone/lua_general.cpp | 3 +- zone/lua_parser.cpp | 69 ++++++++++++++++++++++---------------------- zone/npc.cpp | 2 ++ 5 files changed, 64 insertions(+), 58 deletions(-) diff --git a/zone/embparser.cpp b/zone/embparser.cpp index d571dce24..389f93d1f 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -113,7 +113,8 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_LEAVE_AREA", "EVENT_RESPAWN", "EVENT_DEATH_COMPLETE", - "EVENT_UNHANDLED_OPCODE" + "EVENT_UNHANDLED_OPCODE", + "EVENT_TICK" }; PerlembParser::PerlembParser() : perl(nullptr) { @@ -154,7 +155,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, ItemInst* iteminst, Mob* mob, uint32 extradata, bool global, std::vector *extra_pointers) { if(!perl) @@ -186,7 +187,7 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da package_name, npcmob, mob, char_id); //ExportGenericVariables(); - ExportMobVariables(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, + ExportMobVariables(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, package_name, mob, npcmob); ExportZoneVariables(package_name); ExportItemVariables(package_name, mob); @@ -459,15 +460,15 @@ void PerlembParser::LoadItemScript(std::string filename, ItemInst *item) { std::stringstream package_name; package_name << "qst_item_" << item->GetID(); - + if(!perl) return; - + auto iter = item_quest_status_.find(item->GetID()); if(iter != item_quest_status_.end()) { return; } - + try { perl->eval_file(package_name.str().c_str(), filename.c_str()); } @@ -480,7 +481,7 @@ void PerlembParser::LoadItemScript(std::string filename, ItemInst *item) { item_quest_status_[item->GetID()] = questFailedToLoad; return; } - + item_quest_status_[item->GetID()] = questLoaded; } @@ -821,10 +822,10 @@ void PerlembParser::MapFunctions() { ); } -void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, +void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, bool &isSpellQuest, QuestEventID event, NPC* npcmob, ItemInst* iteminst, Mob* mob, bool global) { - if(event == EVENT_SPELL_EFFECT_CLIENT || + if(event == EVENT_SPELL_EFFECT_CLIENT || event == EVENT_SPELL_EFFECT_NPC || event == EVENT_SPELL_BUFF_TIC_CLIENT || event == EVENT_SPELL_BUFF_TIC_NPC || @@ -843,14 +844,14 @@ void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest isPlayerQuest = true; } } - else + else isItemQuest = true; } } } -void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, - bool &isSpellQuest, std::string &package_name, QuestEventID event, uint32 objid, const char * data, +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) { if(!isPlayerQuest && !isGlobalPlayerQuest && !isItemQuest && !isSpellQuest) { @@ -897,7 +898,7 @@ void PerlembParser::ExportCharID(const std::string &package_name, int &char_id, ExportVar(package_name.c_str(), "charid", char_id); } -void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, +void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, bool isSpellQuest, std::string &package_name, NPC *npcmob, Mob *mob, int char_id) { //NPC quest if(!isPlayerQuest && !isGlobalPlayerQuest && !isItemQuest && !isSpellQuest) @@ -953,7 +954,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(); while(iter != globalMap.end()) { @@ -1013,8 +1014,8 @@ void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, } } -void PerlembParser::ExportMobVariables(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, - bool isSpellQuest, std::string &package_name, Mob *mob, NPC *npcmob) +void PerlembParser::ExportMobVariables(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, + bool isSpellQuest, std::string &package_name, Mob *mob, NPC *npcmob) { uint8 fac = 0; if (mob && mob->IsClient()) { @@ -1027,7 +1028,7 @@ void PerlembParser::ExportMobVariables(bool isPlayerQuest, bool isGlobalPlayerQu if (mob && npcmob && mob->IsClient()) { Client* client = mob->CastToClient(); - fac = client->GetFactionLevel(client->CharacterID(), npcmob->GetID(), client->GetRace(), + fac = client->GetFactionLevel(client->CharacterID(), npcmob->GetID(), client->GetRace(), client->GetClass(), client->GetDeity(), npcmob->GetPrimaryFaction(), npcmob); } } @@ -1122,8 +1123,8 @@ void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) { #undef HASITEM_LAST #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) +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) { switch (event) { case EVENT_SAY: { @@ -1240,7 +1241,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID ExportVar(package_name.c_str(), "target_zone_id", data); break; } - + case EVENT_CAST_ON: case EVENT_CAST: case EVENT_CAST_BEGIN: { @@ -1278,7 +1279,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_PLAYER_PICKUP:{ ExportVar(package_name.c_str(), "picked_up_id", data); ExportVar(package_name.c_str(), "picked_up_entity_id", extradata); - break; + break; } case EVENT_AGGRO_SAY: { @@ -1359,12 +1360,12 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_FORAGE_SUCCESS: { ExportVar(package_name.c_str(), "foraged_item", extradata); - break; + break; } case EVENT_FISH_SUCCESS: { ExportVar(package_name.c_str(), "fished_item", extradata); - break; + break; } case EVENT_CLICK_OBJECT: { diff --git a/zone/event_codes.h b/zone/event_codes.h index f793efaf6..7850b0eb3 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -82,6 +82,7 @@ typedef enum { EVENT_RESPAWN, EVENT_DEATH_COMPLETE, EVENT_UNHANDLED_OPCODE, + EVENT_TICK, _LargestEventID } QuestEventID; diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 483426b2e..15a11604b 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1713,7 +1713,8 @@ luabind::scope lua_register_events() { luabind::value("enter_area", static_cast(EVENT_ENTER_AREA)), luabind::value("leave_area", static_cast(EVENT_LEAVE_AREA)), luabind::value("death_complete", static_cast(EVENT_DEATH_COMPLETE)), - luabind::value("unhandled_opcode", static_cast(EVENT_UNHANDLED_OPCODE)) + luabind::value("unhandled_opcode", static_cast(EVENT_UNHANDLED_OPCODE)), + luabind::value("tick", static_cast(EVENT_TICK)) ]; } diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 24f25948e..462752705 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -116,7 +116,8 @@ const char *LuaEvents[_LargestEventID] = { "event_leave_area", "event_respawn", "event_death_complete", - "event_unhandled_opcode" + "event_unhandled_opcode", + "event_tick" }; extern Zone *zone; @@ -281,7 +282,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M lua_getfield(L, -1, sub_name); npop = 2; } - + lua_createtable(L, 0, 0); //always push self Lua_NPC l_npc(npc); @@ -292,7 +293,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M auto arg_function = NPCArgumentDispatch[evt]; arg_function(this, L, npc, init, data, extra_data, extra_pointers); Client *c = (init && init->IsClient()) ? init->CastToClient() : nullptr; - + quest_manager.StartQuest(npc, c, nullptr); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -301,13 +302,13 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, npop); return ret; } - + lua_pop(L, npop); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -375,17 +376,17 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * lua_getfield(L, -1, sub_name); npop = 2; } - + lua_createtable(L, 0, 0); //push self Lua_Client l_client(client); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "self"); - + auto arg_function = PlayerArgumentDispatch[evt]; arg_function(this, L, client, data, extra_data, extra_pointers); - + quest_manager.StartQuest(client, client, nullptr); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -394,13 +395,13 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, npop); return ret; } - + lua_pop(L, npop); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -424,15 +425,15 @@ int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob * if(evt >= _LargestEventID) { return 0; } - + if(!item) { return 0; } - + if(!ItemHasQuestSub(item, evt)) { return 0; } - + std::string package_name = "item_"; package_name += std::to_string(item->GetID()); return _EventItem(package_name, evt, client, item, mob, data, extra_data, extra_pointers); @@ -452,7 +453,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str()); lua_getfield(L, -1, sub_name); } - + lua_createtable(L, 0, 0); //always push self Lua_ItemInst l_item(item); @@ -468,7 +469,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl //redo this arg function auto arg_function = ItemArgumentDispatch[evt]; arg_function(this, L, client, item, mob, data, extra_data, extra_pointers); - + quest_manager.StartQuest(client, client, item); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -477,13 +478,13 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, npop); return ret; } - + lua_pop(L, npop); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -520,7 +521,7 @@ int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spe int LuaParser::_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) { const char *sub_name = LuaEvents[evt]; - + int start = lua_gettop(L); try { @@ -532,7 +533,7 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, lua_getfield(L, -1, sub_name); npop = 2; } - + lua_createtable(L, 0, 0); //always push self even if invalid @@ -546,10 +547,10 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, l_spell_o.push(L); } lua_setfield(L, -2, "self"); - + auto arg_function = SpellArgumentDispatch[evt]; arg_function(this, L, npc, client, spell_id, extra_data, extra_pointers); - + quest_manager.StartQuest(npc, client, nullptr); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -558,13 +559,13 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, npop); return ret; } - + lua_pop(L, npop); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -593,20 +594,20 @@ int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, std: if(!EncounterHasQuestSub(encounter_name, evt)) { return 0; } - + return _EventEncounter(package_name, evt, encounter_name, data, extra_data, extra_pointers); } int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers) { const char *sub_name = LuaEvents[evt]; - + int start = lua_gettop(L); try { lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str()); lua_getfield(L, -1, sub_name); - + lua_createtable(L, 0, 0); lua_pushstring(L, encounter_name.c_str()); lua_setfield(L, -2, "name"); @@ -624,13 +625,13 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std:: return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, 2); return ret; } - + lua_pop(L, 2); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -864,13 +865,13 @@ void LuaParser::ReloadQuests() { FILE *f = fopen(path.c_str(), "r"); if(f) { fclose(f); - + if(luaL_dofile(L, path.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); } } - + //zone init - always loads after global if(zone) { std::string zone_script = "quests/"; @@ -881,7 +882,7 @@ void LuaParser::ReloadQuests() { f = fopen(zone_script.c_str(), "r"); if(f) { fclose(f); - + if(luaL_dofile(L, zone_script.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); @@ -910,7 +911,7 @@ void LuaParser::LoadScript(std::string filename, std::string package_name) { if(iter != loaded_.end()) { return; } - + if(luaL_loadfile(L, filename.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); @@ -1008,7 +1009,7 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_packet(), lua_register_packet_opcodes() ]; - + } catch(std::exception &ex) { std::string error = ex.what(); AddError(error); @@ -1122,7 +1123,7 @@ int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *ite if(iter == lua_encounter_events_registered.end()) { return ret; } - + auto riter = iter->second.begin(); while(riter != iter->second.end()) { if(riter->event_id == evt) { diff --git a/zone/npc.cpp b/zone/npc.cpp index 214161a3b..effd04a4a 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -37,6 +37,7 @@ #include "string_ids.h" #include "spawn2.h" #include "zone.h" +#include "quest_parser_collection.h" #include #include @@ -601,6 +602,7 @@ bool NPC::Process() if(tic_timer.Check()) { + parse->EventNPC(EVENT_TICK, this, nullptr, "", 0); BuffProcess(); if(curfp) From a4d0db8e0a30f733d0f8141d6022ab8afecd2826 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 15 Aug 2015 00:34:10 -0400 Subject: [PATCH 297/846] Implement the extra Wild Rampage/Rampage message (SoD+) --- common/eq_packet_structs.h | 2 +- common/patches/rof.cpp | 5 ++-- common/patches/rof2.cpp | 5 ++-- common/patches/rof2_structs.h | 3 ++- common/patches/rof_structs.h | 3 ++- common/patches/sod.cpp | 5 ++-- common/patches/sod_structs.h | 3 ++- common/patches/sof.cpp | 4 ++-- common/patches/sof_structs.h | 2 +- common/patches/titanium.cpp | 17 ++++++++++++++ common/patches/titanium_ops.h | 1 + common/patches/uf.cpp | 5 ++-- common/patches/uf_structs.h | 3 ++- zone/attack.cpp | 43 ++++++++++++++++++----------------- zone/beacon.h | 4 ++-- zone/bot.cpp | 6 ++--- zone/bot.h | 4 ++-- zone/client.h | 4 ++-- zone/corpse.h | 4 ++-- zone/encounter.h | 4 ++-- zone/hate_list.cpp | 2 +- zone/merc.cpp | 6 ++--- zone/merc.h | 6 ++--- zone/mob.h | 16 ++++++------- zone/mob_ai.cpp | 6 ++--- zone/npc.h | 4 ++-- 26 files changed, 97 insertions(+), 70 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 8c9dc0a4e..3f6476ba9 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1322,7 +1322,7 @@ struct CombatDamage_Struct /* 11 */ float force; /* 15 */ float meleepush_xy; // see above notes in Action_Struct /* 19 */ float meleepush_z; -/* 23 */ +/* 23 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage }; /* diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 783156a48..4ee6d4ec0 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -658,9 +658,10 @@ namespace RoF OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); + OUT(special); FINISH_ENCODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index dbf233f44..7319dc98b 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -729,9 +729,10 @@ namespace RoF2 OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); + OUT(special); FINISH_ENCODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index bc49fe88f..22748af8d 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1487,7 +1487,8 @@ struct CombatDamage_Struct /* 13 */ float force; // cd cc cc 3d /* 17 */ float meleepush_xy; // see above notes in Action_Struct /* 21 */ float meleepush_z; -/* 25 */ uint8 unknown25[5]; // was [9] +/* 25 */ uint8 unknown25; // was [9] +/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage /* 30 */ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index eb7c6edfb..adbfbb7fa 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1517,7 +1517,8 @@ struct CombatDamage_Struct /* 13 */ float force; // cd cc cc 3d /* 17 */ float meleepush_xy; // see above notes in Action_Struct /* 21 */ float meleepush_z; -/* 25 */ uint8 unknown25[5]; // was [9] +/* 25 */ uint8 unknown25; // was [9] +/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage /* 30 */ }; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 1910a96e4..bbd5acd45 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -446,9 +446,10 @@ namespace SoD OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); + OUT(special); FINISH_ENCODE(); } diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 816bff323..4e537221c 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1275,7 +1275,8 @@ struct CombatDamage_Struct /* 11 */ float force; // cd cc cc 3d /* 15 */ float meleepush_xy; // see above notes in Action_Struct /* 19 */ float meleepush_z; -/* 23 */ uint8 unknown23[5]; // was [9] +/* 23 */ uint8 unknown23; // was [9] +/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage /* 28 */ }; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 421903970..cb725f6a7 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -426,9 +426,9 @@ namespace SoF OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); FINISH_ENCODE(); } diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 49ad7ba3e..d15f20999 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1253,7 +1253,7 @@ struct CombatDamage_Struct /* 11 */ float force; // cd cc cc 3d /* 15 */ float meleepush_xy; // see above notes in Action_Struct /* 19 */ float meleepush_z; -/* 23 */ uint8 unknown23[5]; // was [9] +/* 23 */ uint8 unknown23[5]; // was [9] this appears unrelated to the stuff the other clients do here? /* 28 */ }; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index ec25aba61..42544f3b9 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -299,6 +299,23 @@ namespace Titanium dest->FastQueuePacket(&in, ack_req); } + ENCODE(OP_Damage) + { + ENCODE_LENGTH_EXACT(CombatDamage_Struct); + SETUP_DIRECT_ENCODE(CombatDamage_Struct, structs::CombatDamage_Struct); + + OUT(target); + OUT(source); + OUT(type); + OUT(spellid); + OUT(damage); + OUT(force); + OUT(meleepush_xy); + OUT(meleepush_z); + + FINISH_ENCODE(); + } + ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } ENCODE(OP_DeleteItem) diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 3d8dfbf79..477adf140 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -6,6 +6,7 @@ E(OP_BazaarSearch) E(OP_BecomeTrader) E(OP_ChannelMessage) E(OP_CharInventory) +E(OP_Damage) E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DeleteSpawn) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 1a786d94a..0e88a2a09 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -581,9 +581,10 @@ namespace UF OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); + OUT(special); FINISH_ENCODE(); } diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 882158492..046eb5138 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1333,7 +1333,8 @@ struct CombatDamage_Struct /* 11 */ float force; // cd cc cc 3d /* 15 */ float meleepush_xy; // see above notes in Action_Struct /* 19 */ float meleepush_z; -/* 23 */ uint8 unknown23[5]; // was [9] +/* 23 */ uint8 unknown23; // was [9] +/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage /* 28 */ }; diff --git a/zone/attack.cpp b/zone/attack.cpp index 868c5ff03..aa17c2355 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1168,7 +1168,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate //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) +bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { if (!other) { SetTarget(nullptr); @@ -1373,7 +1373,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b SpellFinished(aabonuses.SkillAttackProc[2], other, 10, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, special); if (IsDead()) return false; @@ -1401,7 +1401,7 @@ void Mob::Heal() SendHPUpdate(); } -void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) +void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(dead || IsCorpse()) return; @@ -1425,7 +1425,7 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes att damage = -5; //do a majority of the work... - CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); if (damage > 0) { @@ -1719,7 +1719,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att return true; } -bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) +bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { int damage = 0; @@ -1931,7 +1931,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, false); // Not avoidable client already had thier chance to Avoid + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, special); // Not avoidable client already had thier chance to Avoid } else return false; @@ -1966,7 +1966,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) { +void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(spell_id==0) spell_id = SPELL_UNKNOWN; @@ -2001,7 +2001,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack } //do a majority of the work... - CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); if(damage > 0) { //see if we are gunna start fleeing @@ -3465,7 +3465,7 @@ 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) { +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) { // This method is called with skill_used=ABJURE for Damage Shield damage. bool FromDamageShield = (skill_used == SkillAbjuration); @@ -3705,6 +3705,7 @@ 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; a->meleepush_xy = attacker->GetHeading() * 2.0f; if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() && (IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) { @@ -5109,7 +5110,7 @@ bool Client::CheckDualWield() return zone->random.Int(1, 375) <= chance; } -void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) +void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int special) { if (!target) return; @@ -5117,23 +5118,23 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) 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); + Attack(target, MainPrimary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && CheckDoubleAttack()) - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); return; } if (IsNPC()) { int16 n_atk = CastToNPC()->GetNumberOfAttacks(); if (n_atk <= 1) { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); } else { for (int i = 0; i < n_atk; ++i) { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); } } } else { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); } // we use this random value in three comparisons with different @@ -5144,21 +5145,21 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) // check double attack, this is NOT the same rules that clients use... && RandRoll < (GetLevel() + NPCDualAttackModifier)) { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, 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); + Attack(target, MainPrimary, 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); + Attack(target, MainPrimary, false, false, false, opts, special); } } } } -void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) +void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int special) { if (!target) return; @@ -5168,9 +5169,9 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) (RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) || GetEquipment(MaterialSecondary) != 0) { if (CheckDualWield()) { - Attack(target, MainSecondary, false, false, false, opts); + Attack(target, MainSecondary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()) - Attack(target, MainSecondary, false, false, false, opts); + Attack(target, MainSecondary, false, false, false, opts, special); } } } diff --git a/zone/beacon.h b/zone/beacon.h index f7845e91d..a35f6a1ed 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, 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) { return; } + 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, - ExtraAttackOptions *opts = nullptr) { return 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/bot.cpp b/zone/bot.cpp index 052f84973..5e9717c82 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -4632,7 +4632,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) { +void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(spell_id == 0) spell_id = SPELL_UNKNOWN; @@ -4651,7 +4651,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ entity_list.MessageClose(this, true, 300, MT_Spells, "%s beams a smile at %s", GetCleanName(), from->GetCleanName() ); } - CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); if(GetHP() < 0) { if(IsCasting()) InterruptSpell(); @@ -4678,7 +4678,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) { +bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { if (!other) { SetTarget(nullptr); Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Bot::Attack for evaluation!"); diff --git a/zone/bot.h b/zone/bot.h index c78abdd8f..aa77c5f59 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -137,9 +137,9 @@ 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); + 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, - ExtraAttackOptions *opts = nullptr); + ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); } diff --git a/zone/client.h b/zone/client.h index 54452f373..4b72ee94e 100644 --- a/zone/client.h +++ b/zone/client.h @@ -215,9 +215,9 @@ 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); + 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, - ExtraAttackOptions *opts = nullptr); + ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return entity_list.GetRaidByClient(this); } diff --git a/zone/corpse.h b/zone/corpse.h index 562173e80..a9916f4fd 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -48,8 +48,8 @@ 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) { return; } - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; } + 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 HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } diff --git a/zone/encounter.h b/zone/encounter.h index a2977d7e0..e341fc7ae 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, 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) { return; } + 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, - ExtraAttackOptions *opts = nullptr) { + ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 0247b376a..149d8c392 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -545,7 +545,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) { if (caster->CombatRange(h->entity_on_hatelist)) { ++hit_count; - caster->ProcessAttackRounds(h->entity_on_hatelist, opts); + caster->ProcessAttackRounds(h->entity_on_hatelist, opts, 1); } } } diff --git a/zone/merc.cpp b/zone/merc.cpp index 936dfcc68..68907fb5b 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4445,7 +4445,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) +bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { if (!other) { SetTarget(nullptr); @@ -4456,7 +4456,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) +void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(IsDead() || IsCorpse()) return; @@ -4464,7 +4464,7 @@ void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attac if(spell_id==0) spell_id = SPELL_UNKNOWN; - NPC::Damage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + NPC::Damage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); //Not needed since we're using NPC damage. //CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); diff --git a/zone/merc.h b/zone/merc.h index 9c683ed52..4f52d7367 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -61,9 +61,9 @@ 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); + 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, ExtraAttackOptions *opts = nullptr); + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return 0; } @@ -397,4 +397,4 @@ private: Timer check_target_timer; }; -#endif // MERC_H \ No newline at end of file +#endif // MERC_H diff --git a/zone/mob.h b/zone/mob.h index 20df1ec41..43745351f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -145,7 +145,7 @@ public: 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, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0; + 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); @@ -167,16 +167,16 @@ public: void CommonBreakInvisible(); bool HasDied(); virtual bool CheckDualWield(); - void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); - void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); + void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0); + void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0); 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) + void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0) { if (target) { - DoMainHandAttackRounds(target, opts); + DoMainHandAttackRounds(target, opts, special); if (CanThisClassDualWield()) - DoOffHandAttackRounds(target, opts); + DoOffHandAttackRounds(target, opts, special); } return; } @@ -348,7 +348,7 @@ public: 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; + 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); inline void SetOOCRegen(int32 newoocregen) {oocregen = newoocregen;} @@ -991,7 +991,7 @@ public: bool CheckAATimer(int timer); protected: - void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); + 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); float _GetMovementSpeed(int mod) const; int _GetWalkSpeed() const; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 9a483fddd..4be97897a 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1978,14 +1978,14 @@ bool Mob::Rampage(ExtraAttackOptions *opts) if (m_target == GetTarget()) continue; if (CombatRange(m_target)) { - ProcessAttackRounds(m_target, opts); + ProcessAttackRounds(m_target, opts, 2); index_hit++; } } } if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets) - ProcessAttackRounds(GetTarget(), opts); + ProcessAttackRounds(GetTarget(), opts, 2); return true; } @@ -2004,7 +2004,7 @@ void Mob::AreaRampage(ExtraAttackOptions *opts) index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); if(index_hit == 0) - ProcessAttackRounds(GetTarget(), opts); + ProcessAttackRounds(GetTarget(), opts, 1); } uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) { diff --git a/zone/npc.h b/zone/npc.h index 7274cccd1..32afd0afd 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -104,9 +104,9 @@ 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); + 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, ExtraAttackOptions *opts = nullptr); + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } From a2c5f359d85d9ad8a9ffe846382295f645b3bf3b Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 15 Aug 2015 20:14:15 -0400 Subject: [PATCH 298/846] Fix buffdurationpacket for seeinvis spells --- zone/spells.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 1eb84ad9a..690cbf71f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5302,6 +5302,14 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) int index = GetSpellEffectIndex(buff.spellid, SE_CurrentHP); sbf->effect = abs(spells[buff.spellid].base[index]); } + else if (IsEffectInSpell(buff.spellid, SE_SeeInvis)) + { + // Wish I knew what this sbf->effect field was trying to tell + // the client. 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 { // Default to what old code did until we find a better fix for From bc9f85843e8b458de623af481f89a187c87627b7 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 17 Aug 2015 23:23:24 -0400 Subject: [PATCH 299/846] Fix for SoF character select screen issue --- common/patches/sof.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index cb725f6a7..d8b7db541 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1665,6 +1665,8 @@ namespace SoF emu_ptr += sizeof(CharacterSelectEntry_Struct); eq_ptr += sizeof(structs::CharacterSelectEntry_Struct); } + + FINISH_ENCODE(); } //hack hack hack From 60c6583c54189725145f98746dfa703125bd2eee Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 19 Aug 2015 14:44:12 -0400 Subject: [PATCH 300/846] Fix readability [skip ci] --- zone/client_process.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 70899e2d6..f7fb46d12 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -137,8 +137,8 @@ bool Client::Process() { if(mana_timer.Check()) SendManaUpdatePacket(); - if(dead && dead_timer.Check()) { - database.MoveCharacterToZone(GetName(), database.GetZoneName(m_pp.binds[0].zoneId)); + if(dead && dead_timer.Check()) { + database.MoveCharacterToZone(GetName(), database.GetZoneName(m_pp.binds[0].zoneId)); m_pp.zone_id = m_pp.binds[0].zoneId; m_pp.zoneInstance = m_pp.binds[0].instance_id; From 1d6a185f0f9d82cf407e90883d9d65bfaa5c3f68 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 19 Aug 2015 22:21:17 -0400 Subject: [PATCH 301/846] Break "same spell line" optimizations for mana burns --- zone/spells.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 690cbf71f..63c91fc48 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2789,7 +2789,8 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, bool effect_match = true; // Figure out if we're identical in effects on all slots. if (spellid1 != spellid2) { for (i = 0; i < EFFECT_COUNT; i++) { - if (sp1.effectid[i] != sp2.effectid[i]) { + // we don't want this optimization for mana burns + if (sp1.effectid[i] != sp2.effectid[i] || sp1.effectid[i] == SE_ManaBurn) { effect_match = false; break; } From 39e35fa011ffb5080180d3b014933d9434aefba9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 21 Aug 2015 03:09:27 -0400 Subject: [PATCH 302/846] Temp solution for AE ramp crash --- zone/hate_list.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 149d8c392..962cfb010 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -538,15 +538,22 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption return 0; int hit_count = 0; - auto it = list.begin(); - while (it != list.end() && (count == -1 || hit_count < count)) { - struct_HateList *h = (*it); - ++it; // advancing the iterator here prevents the iterator being invalidated if they die - if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) { - if (caster->CombatRange(h->entity_on_hatelist)) { - ++hit_count; - caster->ProcessAttackRounds(h->entity_on_hatelist, opts, 1); - } + // This should prevent crashes if something dies (or mainly more than 1 thing goes away) + // This is a temp solution until the hate lists can be rewritten to not have that issue + std::vector id_list; + for (auto &h : list) { + if (h->entity_on_hatelist && h->entity_on_hatelist != caster && + caster->CombatRange(h->entity_on_hatelist)) + id_list.push_back(h->entity_on_hatelist->GetID()); + if (count != -1 && id_list.size() > count) + break; + } + + for (auto &id : id_list) { + auto mob = entity_list.GetMobID(id); + if (mob) { + ++hit_count; + caster->ProcessAttackRounds(mob, opts, 1); } } From 839b6e25d882f3e00d9153b59412f4b35718c90e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 24 Aug 2015 02:15:41 -0400 Subject: [PATCH 303/846] Fix "same spell line" optimization for same spell mana burns ... --- zone/spells.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 63c91fc48..340f8faf2 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2795,6 +2795,9 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, break; } } + } else if (IsEffectInSpell(spellid1, SE_ManaBurn)) { + Log.Out(Logs::Detail, Logs::Spells, "We have a Mana Burn spell that is the same, they won't stack"); + return -1; } // check for special stacking overwrite in spell2 against effects in spell1 From 43586a33cdf5d1d6f6a4f43dc20e0ba64bb34f8f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 26 Aug 2015 16:20:56 -0400 Subject: [PATCH 304/846] Port PROX_AGGRO from EQMacEmu If this ability is set, the NPCs will continuously add things to their hate list while their engaged. If it's not set (default) they won't, which is what the vast majority of NPCs do on live. --- zone/aggro.cpp | 8 ++++++++ zone/common.h | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index d1574dc50..78fab6758 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -285,6 +285,14 @@ bool Mob::CheckWillAggro(Mob *mob) { return(false); } + // Don't aggro new clients if we are already engaged unless PROX_AGGRO is set + if (IsEngaged() && (!GetSpecialAbility(PROX_AGGRO) || (GetSpecialAbility(PROX_AGGRO) && !CombatRange(mob)))) { + Log.Out(Logs::Moderate, Logs::Aggro, + "%s is in combat, and does not have prox_aggro, or does and is out of combat range with %s", + GetName(), mob->GetName()); + return false; + } + //im not sure I understand this.. //if I have an owner and it is not this mob, then I cannot //aggro this mob...??? diff --git a/zone/common.h b/zone/common.h index 0b875456b..7901d511e 100644 --- a/zone/common.h +++ b/zone/common.h @@ -138,7 +138,8 @@ enum { IGNORE_ROOT_AGGRO_RULES = 42, CASTING_RESIST_DIFF = 43, COUNTER_AVOID_DAMAGE = 44, - MAX_SPECIAL_ATTACK = 45 + PROX_AGGRO = 45, + MAX_SPECIAL_ATTACK = 46 }; typedef enum { //fear states From 53292a99a2214a5e423b5f8f4da780cab2fd106d Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 28 Aug 2015 15:15:19 -0400 Subject: [PATCH 305/846] Fixed #npcedit rangedtype. --- zone/command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index 75dec2b62..144fada08 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6243,7 +6243,7 @@ void command_npcedit(Client *c, const Seperator *sep) if (strcasecmp(sep->arg[1], "rangedtype") == 0) { c->Message(15,"NPCID %u now has a ranged type of %i.", npcTypeID, atoi(sep->argplus[2])); - std::string query = StringFormat("UPDATE npc_types SET rangedtype = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET ranged_type = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); return; } From b868cbbcfeddb9c1bdb7e67564af298ca01b978d Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 31 Aug 2015 14:41:58 -0400 Subject: [PATCH 306/846] Fixed #bot resist commands. --- zone/bot.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 5e9717c82..cbc951c34 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -10771,7 +10771,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis magic", "Resist Magic").c_str()); + 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: @@ -10797,7 +10797,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis magic", "Resist Magic").c_str()); + 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: @@ -10822,7 +10822,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !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 invis fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot invis magic", "Resist Magic").c_str()); + 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."); From 4ae02e5efe04aa665d833f041b6baaf7a9a72c7f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 3 Sep 2015 02:56:51 -0400 Subject: [PATCH 307/846] XTargets will move auto entries up on removal like live This also makes use of the bulk packet so not a crap ton of packets generated. --- zone/client.cpp | 96 ++++++++++++++++++++++++++++++++++++++----------- zone/client.h | 4 ++- zone/entity.cpp | 2 +- 3 files changed, 80 insertions(+), 22 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index f823c8b54..9968dcb4e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7041,7 +7041,7 @@ void Client::UpdateClientXTarget(Client *c) } } -void Client::AddAutoXTarget(Mob *m) +void Client::AddAutoXTarget(Mob *m, bool send) { if(!XTargettingAvailable() || !XTargetAutoAddHaters) return; @@ -7054,7 +7054,10 @@ void Client::AddAutoXTarget(Mob *m) if((XTargets[i].Type == Auto) && (XTargets[i].ID == 0)) { XTargets[i].ID = m->GetID(); - SendXTargetPacket(i, m); + if (send) // if we don't send we're bulk sending updates later on + SendXTargetPacket(i, m); + else + XTargets[i].dirty = true; break; } } @@ -7062,42 +7065,59 @@ void Client::AddAutoXTarget(Mob *m) void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots) { - if(!XTargettingAvailable()) + if (!XTargettingAvailable()) return; bool HadFreeAutoSlotsBefore = false; int FreedAutoSlots = 0; - if(m->GetID() == 0) + if (m->GetID() == 0) return; - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if(OnlyAutoSlots && (XTargets[i].Type !=Auto)) + 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) + if (XTargets[i].ID == m->GetID()) { + if (XTargets[i].Type == CurrentTargetNPC) XTargets[i].Type = Auto; - if(XTargets[i].Type == Auto) + if (XTargets[i].Type == Auto) ++FreedAutoSlots; XTargets[i].ID = 0; - - SendXTargetPacket(i, nullptr); - } - else - { - if((XTargets[i].Type == Auto) && (XTargets[i].ID == 0)) + XTargets[i].dirty = true; + } else { + if (XTargets[i].Type == Auto && XTargets[i].ID == 0) HadFreeAutoSlotsBefore = true; } } - // 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) + + // move shit up! + 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) @@ -7166,6 +7186,42 @@ void Client::SendXTargetPacket(uint32 Slot, Mob *m) FastQueuePacket(&outapp); } +// This is a bulk packet, we use it when we remove something since we need to reorder the xtargets and maybe +// add new mobs! Currently doesn't check if there is a dirty flag set, so it should only be called when there is +void Client::SendXTargetUpdates() +{ + if (!XTargettingAvailable()) + return; + + int count = 0; + // header is 4 bytes max xtargets, 4 bytes count + // entry is 4 bytes slot, 1 byte unknown, 4 bytes ID, 65 char name + auto outapp = new EQApplicationPacket(OP_XTargetResponse, 8 + 74 * GetMaxXTargets()); // fuck it max size + outapp->WriteUInt32(GetMaxXTargets()); + outapp->WriteUInt32(1); // we will correct this later + for (int i = 0; i < GetMaxXTargets(); ++i) { + if (XTargets[i].dirty) { + outapp->WriteUInt32(i); + outapp->WriteUInt8(0); // no idea what this is + outapp->WriteUInt32(XTargets[i].ID); + outapp->WriteString(XTargets[i].Name); + count++; + XTargets[i].dirty = false; + } + } + + assert(count > 0); // we don't have any logic to prevent this, assert for now + + auto newbuff = new uchar[outapp->GetWritePosition()]; + memcpy(newbuff, outapp->pBuffer, outapp->GetWritePosition()); + safe_delete_array(outapp->pBuffer); + outapp->pBuffer = newbuff; + outapp->size = outapp->GetWritePosition(); + outapp->SetWritePosition(4); + outapp->WriteUInt32(count); + FastQueuePacket(&outapp); +} + void Client::RemoveGroupXTargets() { if(!XTargettingAvailable()) @@ -8670,4 +8726,4 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) { int Client::GetAccountAge() { return (time(nullptr) - GetAccountCreation()); -} \ No newline at end of file +} diff --git a/zone/client.h b/zone/client.h index 4b72ee94e..9fa68350e 100644 --- a/zone/client.h +++ b/zone/client.h @@ -175,6 +175,7 @@ typedef enum struct XTarget_Struct { XTargetType Type; + bool dirty; uint16 ID; char Name[65]; }; @@ -1144,9 +1145,10 @@ public: bool IsClientXTarget(const Client *c) const; void UpdateClientXTarget(Client *c); void UpdateXTargetType(XTargetType Type, Mob *m, const char *Name = nullptr); - void AddAutoXTarget(Mob *m); + void AddAutoXTarget(Mob *m, bool send = true); void RemoveXTarget(Mob *m, bool OnlyAutoSlots); void SendXTargetPacket(uint32 Slot, Mob *m); + void SendXTargetUpdates(); void RemoveGroupXTargets(); void RemoveAutoXTargets(); void ShowXTargets(Client *c); diff --git a/zone/entity.cpp b/zone/entity.cpp index 01f27700e..69b13e6eb 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1373,7 +1373,7 @@ void EntityList::RefreshAutoXTargets(Client *c) continue; if (m->CheckAggro(c) && !c->IsXTarget(m)) { - c->AddAutoXTarget(m); + c->AddAutoXTarget(m, false); // we only call this before a bulk, so lets not send right away break; } From 64deca11b206e39fc637e1b8338574bf4e0c178c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 3 Sep 2015 03:05:50 -0400 Subject: [PATCH 308/846] Woops, gotta initialize the new flag --- zone/client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/client.cpp b/zone/client.cpp index 9968dcb4e..cabf30679 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -300,6 +300,7 @@ Client::Client(EQStreamInterface* ieqs) XTargets[i].Type = Auto; XTargets[i].ID = 0; XTargets[i].Name[0] = 0; + XTargets[i].dirty = false; } MaxXTargets = 5; XTargetAutoAddHaters = true; From 5126104fd68ce58058327b65f80141879dda24a5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 3 Sep 2015 20:42:35 -0400 Subject: [PATCH 309/846] Some crash fixes noticed on EQMacEmu --- zone/spells.cpp | 50 ++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 340f8faf2..44bd8e3de 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1408,47 +1408,47 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } //Must be out of combat. (If Beneficial checks casters combat state, Deterimental checks targets) - if (!spells[spell_id].InCombat && spells[spell_id].OutofCombat){ + if (!spells[spell_id].InCombat && spells[spell_id].OutofCombat) { if (IsDetrimentalSpell(spell_id)) { - if ( (spell_target->IsNPC() && spell_target->IsEngaged()) || - (spell_target->IsClient() && spell_target->CastToClient()->GetAggroCount())){ - Message_StringID(13,SPELL_NO_EFFECT); //Unsure correct string - return false; + if (spell_target && + ((spell_target->IsNPC() && spell_target->IsEngaged()) || + (spell_target->IsClient() && spell_target->CastToClient()->GetAggroCount()))) { + Message_StringID(13, SPELL_NO_EFFECT); // Unsure correct string + return false; } } else if (IsBeneficialSpell(spell_id)) { - if ( (IsNPC() && IsEngaged()) || - (IsClient() && CastToClient()->GetAggroCount())){ - if (IsDiscipline(spell_id)) - Message_StringID(13,NO_ABILITY_IN_COMBAT); - else - Message_StringID(13,NO_CAST_IN_COMBAT); + if ((IsNPC() && IsEngaged()) || (IsClient() && CastToClient()->GetAggroCount())) { + if (IsDiscipline(spell_id)) + Message_StringID(13, NO_ABILITY_IN_COMBAT); + else + Message_StringID(13, NO_CAST_IN_COMBAT); - return false; + return false; } } } - //Must be in combat. (If Beneficial checks casters combat state, Deterimental checks targets) - else if (spells[spell_id].InCombat && !spells[spell_id].OutofCombat){ + // Must be in combat. (If Beneficial checks casters combat state, Deterimental checks targets) + else if (spells[spell_id].InCombat && !spells[spell_id].OutofCombat) { if (IsDetrimentalSpell(spell_id)) { - if ( (spell_target->IsNPC() && !spell_target->IsEngaged()) || - (spell_target->IsClient() && !spell_target->CastToClient()->GetAggroCount())){ - Message_StringID(13,SPELL_NO_EFFECT); //Unsure correct string - return false; + if (spell_target && + ((spell_target->IsNPC() && !spell_target->IsEngaged()) || + (spell_target->IsClient() && !spell_target->CastToClient()->GetAggroCount()))) { + Message_StringID(13, SPELL_NO_EFFECT); // Unsure correct string + return false; } } else if (IsBeneficialSpell(spell_id)) { - if ( (IsNPC() && !IsEngaged()) || - (IsClient() && !CastToClient()->GetAggroCount())){ - if (IsDiscipline(spell_id)) - Message_StringID(13,NO_ABILITY_OUT_OF_COMBAT); - else - Message_StringID(13,NO_CAST_OUT_OF_COMBAT); + if ((IsNPC() && !IsEngaged()) || (IsClient() && !CastToClient()->GetAggroCount())) { + if (IsDiscipline(spell_id)) + Message_StringID(13, NO_ABILITY_OUT_OF_COMBAT); + else + Message_StringID(13, NO_CAST_OUT_OF_COMBAT); - return false; + return false; } } } From 0d3bd5988b03ccf263aa99d70a5b34848f79f43c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 4 Sep 2015 12:12:29 -0400 Subject: [PATCH 310/846] Fix issue when RemoveXTarget was called with a mob not on our XTargets This could be better, but works for now --- zone/client.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index cabf30679..cce3dbd29 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7095,7 +7095,8 @@ void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots) } } - // move shit up! + // 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) @@ -7211,7 +7212,11 @@ void Client::SendXTargetUpdates() } } - assert(count > 0); // we don't have any logic to prevent this, assert for now + // RemoveXTarget probably got called with a mob not on our xtargets + if (count == 0) { + safe_delete(outapp); + return; + } auto newbuff = new uchar[outapp->GetWritePosition()]; memcpy(newbuff, outapp->pBuffer, outapp->GetWritePosition()); From 548701cba6b68670bbebd57d3eb555375d935970 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 4 Sep 2015 14:07:01 -0400 Subject: [PATCH 311/846] Fix int underflow error in disc reuse timers focus --- zone/effects.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 85a858c94..a18e80428 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -623,11 +623,17 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { if(spell.recast_time > 0) { uint32 reduced_recast = spell.recast_time / 1000; - reduced_recast -= GetFocusEffect(focusReduceRecastTime, spell_id); - if(reduced_recast <= 0){ + auto focus = GetFocusEffect(focusReduceRecastTime, spell_id); + // do stupid stuff because custom servers. + // we really should be able to just do the -= focus but since custom servers could have shorter reuse timers + // we have to make sure we don't underflow the uint32 ... + // and yes, the focus effect can be used to increase the durations (spell 38944) + if (focus > reduced_recast) { reduced_recast = 0; if (GetPTimers().Enabled((uint32)DiscTimer)) GetPTimers().Clear(&database, (uint32)DiscTimer); + } else { + reduced_recast -= focus; } if (reduced_recast > 0) From b24f1914ab4786d000e443624bcbd500d26d4f62 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 16 Sep 2015 19:45:28 -0400 Subject: [PATCH 312/846] Minor fix for opcode_handlers.py (Underfoot to UF) --- utils/scripts/opcode_handlers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py index ce0e955a3..d428046ba 100644 --- a/utils/scripts/opcode_handlers.py +++ b/utils/scripts/opcode_handlers.py @@ -23,7 +23,7 @@ VERBOSE = False # messaging: {False - minimal, True - robust} base_path = os.getcwd()[:-14] # '/utils/scripts' base_path = base_path.replace('\\', '/') -client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF', 'RoF2'] +client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'UF', 'RoF', 'RoF2'] server_list = ['Login', 'World', 'Zone', 'UCS'] client_opcodes = {} # x[key='Client'][key='OP_CodeName'](value='0x####') @@ -248,7 +248,7 @@ def loadclientopcodes(): for client in client_list: try: - short_name = '/patch_{0}.conf'.format(client).lower() + short_name = '/patch_{0}.conf'.format(client) file_name = '{0}/utils/patches{1}'.format( base_path, From 211462456ccc3451a6942009f24226d04aa94003 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 17 Sep 2015 01:46:40 -0400 Subject: [PATCH 313/846] More hate fixes Refix double spell casting subtlety Fix double spell casting subtlety for beneficial spells Move 100 initial bonus to AddToHateList so melee get it as well Lower prox aggro since the 100 bonus is in AddToHateList now --- zone/aggro.cpp | 13 ++++--------- zone/attack.cpp | 20 +++++++++++++------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 78fab6758..06716b3df 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -45,7 +45,7 @@ void EntityList::CheckClientAggro(Client *around) continue; if (mob->CheckWillAggro(around) && !mob->CheckAggro(around)) - mob->AddToHateList(around, 100); + mob->AddToHateList(around, 25); } } @@ -1115,15 +1115,13 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) int HateMod = RuleI(Aggro, SpellAggroMod); HateMod += GetFocusEffect(focusSpellHateMod, spell_id); - //Live AA - Spell casting subtlety - HateMod += aabonuses.hatemod + spellbonuses.hatemod + itembonuses.hatemod; - AggroAmount = (AggroAmount * HateMod) / 100; } // initial aggro gets a bonus 100 besides for dispel or hate override - if (!dispel && spells[spell_id].HateAdded == 0 && !on_hatelist) - AggroAmount += 100; + // We add this 100 in AddToHateList so we need to account for the oddities here + if (dispel && spells[spell_id].HateAdded > 0 && !on_hatelist) + AggroAmount -= 100; return AggroAmount + spells[spell_id].bonushate + nonModifiedAggro; } @@ -1181,9 +1179,6 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib int HateMod = RuleI(Aggro, SpellAggroMod); HateMod += GetFocusEffect(focusSpellHateMod, spell_id); - //Live AA - Spell casting subtlety - HateMod += aabonuses.hatemod + spellbonuses.hatemod + itembonuses.hatemod; - AggroAmount = (AggroAmount * HateMod) / 100; } diff --git a/zone/attack.cpp b/zone/attack.cpp index aa17c2355..92b907250 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2429,17 +2429,23 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b Mob* targetmob = this->GetTarget(); if(other){ + bool on_hatelist = CheckAggro(other); AddRampage(other); - int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod; + if (on_hatelist) { // odd reason, if you're not on the hate list, subtlety etc don't apply! + // 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; + int32 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod; - if (shieldhatemod && other->HasShieldEquiped()) - hatemod += shieldhatemod; + if (shieldhatemod && other->HasShieldEquiped()) + hatemod += shieldhatemod; - if(hatemod < 1) - hatemod = 1; - hate = ((hate * (hatemod))/100); + if(hatemod < 1) + hatemod = 1; + hate = ((hate * (hatemod))/100); + } else { + hate += 100; // 100 bonus initial aggro + } } if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && !IsFocused()) { //ignore aggro if hold and !focus From 9408403a00c5f984a4cd1528dfd2a6afda09553d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 18 Sep 2015 19:50:48 -0400 Subject: [PATCH 314/846] Fix damage bonus calculations Based on dev quotes, nerfs Sinister Strikes --- zone/attack.cpp | 437 ++++-------------------------------------------- zone/mob.h | 2 +- 2 files changed, 37 insertions(+), 402 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 92b907250..171b8d2fe 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1292,7 +1292,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (Hand == MainSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr, true ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -2656,410 +2656,45 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { } } -uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) +uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand) { - // 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 == MainPrimary 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. + // 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 // - // 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. + // We assume that the level check is done before calling this function and sinister strikes is checked before + // calling for offhand DB + auto level = GetLevel(); + if (!weapon) + return 1 + ((level - 28) / 3); // how does weaponless scale? - // 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]; + auto delay = weapon->Delay; + if (weapon->ItemType == ItemType1HSlash || weapon->ItemType == ItemType1HBlunt || + weapon->ItemType == ItemTypeMartial || weapon->ItemType == ItemType1HPiercing) { + // we assume sinister strikes is checked before calling here + if (!offhand) { + if (delay <= 39) + return 1 + ((level - 28) / 3); + else if (delay < 43) + return 2 + ((level - 28) / 3) + ((delay - 40) / 3); + else if (delay < 45) + return 3 + ((level - 28) / 3) + ((delay - 40) / 3); + else if (delay >= 45) + return 4 + ((level - 28) / 3) + ((delay - 40) / 3); + } else { + return 1 + ((level - 28) / 3) * (delay / 30); } + } else { + // 2h damage bonus + if (delay <= 27) + return 1 + ((level - 28) / 3); + else if (delay < 40) + return 1 + ((level - 28) / 3) + ((level - 30) / 5); + else if (delay < 43) + return 2 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3); + else if (delay < 45) + return 3 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3); + else if (delay >= 45) + return 4 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3); } } diff --git a/zone/mob.h b/zone/mob.h index 43745351f..651065296 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -746,7 +746,7 @@ public: inline void SetExtraHaste(int Haste) { ExtraHaste = Haste; } virtual int GetHaste(); - uint8 GetWeaponDamageBonus(const Item_Struct* Weapon); + uint8 GetWeaponDamageBonus(const Item_Struct* weapon, bool offhand = false); uint16 GetDamageTable(SkillUseTypes skillinuse); virtual int GetMonkHandToHandDamage(void); From 72aaf56c79337e44b1ff5e5543b1a41a6d6446a4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 20 Sep 2015 03:58:21 -0400 Subject: [PATCH 315/846] Fix likely dev typo in sinister strikes calc --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 171b8d2fe..d8343cb8d 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2681,7 +2681,7 @@ uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand) else if (delay >= 45) return 4 + ((level - 28) / 3) + ((delay - 40) / 3); } else { - return 1 + ((level - 28) / 3) * (delay / 30); + return 1 + ((level - 28) / 3) + (delay / 30); } } else { // 2h damage bonus From 4c0a9562ee6d2e9157936a485140bcdde92a176b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 20 Sep 2015 15:12:00 -0500 Subject: [PATCH 316/846] Update db_dumper.pl (Database backup) script to only create backups with underscores as space delimiters (db 09-2-2015.sql) vs Now: (db_09_20_2015.sql) [skip ci] --- utils/scripts/db_dumper.pl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/scripts/db_dumper.pl b/utils/scripts/db_dumper.pl index 71e552ad3..dd0808bca 100644 --- a/utils/scripts/db_dumper.pl +++ b/utils/scripts/db_dumper.pl @@ -15,7 +15,7 @@ $localdrive = "C:"; #::: Where Windows and all Install Programs are... $linesep = "---------------------------------------"; use POSIX qw(strftime); -my $date = strftime "%m-%d-%Y", localtime; +my $date = strftime "%m_%d_%Y", localtime; print "\nTodays Date: " . $date . "\n"; use Config; @@ -105,7 +105,7 @@ else { if($t_tables ne ""){ $tables_f_l = substr($t_tables_l, 0, 20) . '...'; - $target_file = '' . $tables_f_l . ' ' . $date . ''; + $target_file = '' . $tables_f_l . '_' . $date . ''; print "Performing table based backup...\n"; #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; @@ -114,7 +114,7 @@ if($t_tables ne ""){ system($cmd); } else{ #::: Entire DB Backup - $target_file = '' . $db . ' ' . $date . ''; + $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"'; From 13ba99758938706bf9fbc1db7a18ff826773ae47 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 20 Sep 2015 15:21:38 -0500 Subject: [PATCH 317/846] Update eqemu_update.pl (v8) to use new AA data post AA rework for fresh AA table downloads [skip ci] --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 6 +- utils/sql/peq_aa_tables_post_rework.sql | 20650 ++++++++++++++++++++++ 3 files changed, 20654 insertions(+), 4 deletions(-) create mode 100644 utils/sql/peq_aa_tables_post_rework.sql diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index a96f51967..abd3fafb8 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -494,7 +494,7 @@ bool Database::CheckDatabaseConversions() { /* 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 7"); + system("perl eqemu_update.pl V 8"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 3b1a0272c..67e741030 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -22,7 +22,7 @@ if($Config{osname}=~/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 = 7; +$current_version = 8; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -377,9 +377,9 @@ sub AA_Fetch{ } print "Pulling down PEQ AA Tables...\n"; - GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/peq_aa_tables.sql", "db_update/peq_aa_tables.sql"); + GetRemoteFile("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 GetMySQLResultFromFile("db_update/peq_aa_tables.sql"); + print GetMySQLResultFromFile("db_update/peq_aa_tables_post_rework.sql"); print "\nDone...\n\n"; } diff --git a/utils/sql/peq_aa_tables_post_rework.sql b/utils/sql/peq_aa_tables_post_rework.sql new file mode 100644 index 000000000..53d465778 --- /dev/null +++ b/utils/sql/peq_aa_tables_post_rework.sql @@ -0,0 +1,20650 @@ +DROP TABLE IF EXISTS `aa_ability`; +CREATE TABLE IF NOT EXISTS `aa_ability` ( + `id` int(10) unsigned NOT NULL, + `name` text NOT NULL, + `category` int(10) NOT NULL DEFAULT '-1', + `classes` int(10) NOT NULL DEFAULT '65535', + `races` int(10) NOT NULL DEFAULT '65535', + `drakkin_heritage` int(10) NOT NULL DEFAULT '127', + `deities` int(10) NOT NULL DEFAULT '131071', + `status` int(10) NOT NULL DEFAULT '0', + `type` int(10) NOT NULL DEFAULT '0', + `charges` int(11) NOT NULL DEFAULT '0', + `grant_only` tinyint(4) NOT NULL DEFAULT '0', + `first_rank_id` int(10) NOT NULL DEFAULT '-1', + `enabled` tinyint(3) unsigned NOT NULL DEFAULT '1', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `aa_ability` (`id`, `name`, `category`, `classes`, `races`, `drakkin_heritage`, `deities`, `status`, `type`, `charges`, `grant_only`, `first_rank_id`, `enabled`) VALUES + (0, 'Unknown AA -1', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 49999, 1), + (1, 'Innate Strength', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 2, 1), + (2, 'Innate Stamina', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 7, 1), + (3, 'Innate Agility', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 12, 1), + (4, 'Innate Dexterity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 17, 1), + (5, 'Innate Intelligence', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 22, 1), + (6, 'Innate Wisdom', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 27, 1), + (7, 'Innate Charisma', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 32, 1), + (8, 'Innate Fire Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 37, 1), + (9, 'Innate Cold Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 42, 1), + (10, 'Innate Magic Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 47, 1), + (11, 'Innate Poison Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 52, 1), + (12, 'Innate Disease Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 57, 1), + (13, 'Innate Run Speed', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 62, 1), + (15, 'Innate Metabolism', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 68, 1), + (16, 'Innate Lung Capacity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 71, 1), + (17, 'First Aid', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 74, 1), + (18, 'Healing Adept', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 77, 1), + (19, 'Healing Gift', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 80, 1), + (20, 'Spell Casting Mastery', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 83, 1), + (21, 'Spell Casting Reinforcement', -1, 25150, 65535, 127, 131071, 0, 2, 0, 0, 86, 1), + (23, 'Spell Casting Fury', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 92, 1), + (25, 'Spell Casting Subtlety', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 98, 1), + (26, 'Spell Casting Expertise', -1, 15504, 65535, 127, 131071, 0, 2, 0, 0, 101, 1), + (27, 'Spell Casting Deftness', -1, 7184, 65535, 127, 131071, 0, 2, 0, 0, 104, 1), + (28, 'Natural Durability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 107, 1), + (29, 'Natural Healing', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 110, 1), + (30, 'Combat Fury', -1, 16596, 65535, 127, 131071, 0, 2, 0, 0, 113, 1), + (31, 'Fear Resistance', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 116, 1), + (32, 'Finishing Blow', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 119, 1), + (33, 'Combat Stability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 122, 1), + (34, 'Combat Agility', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 125, 1), + (35, 'Mass Group Buff', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 128, 1), + (36, 'Divine Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 129, 1), + (37, 'Innate Invis to Undead', -1, 1026, 65535, 127, 131071, 0, 3, 0, 0, 130, 1), + (38, 'Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 131, 1), + (39, 'Bestow Divine Aura', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 132, 1), + (41, 'Purify Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 136, 1), + (42, 'Quick Evacuation', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 137, 1), + (43, 'Exodus', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 140, 1), + (44, 'Quick Damage', -1, 6176, 65535, 127, 131071, 0, 3, 0, 0, 141, 1), + (45, 'Enhanced Root', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 144, 1), + (46, 'Dire Charm', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 145, 1), + (47, 'Cannibalization', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 146, 1), + (48, 'Quick Buff', -1, 25134, 65535, 127, 131071, 0, 2, 0, 0, 147, 1), + (49, 'Alchemy Mastery', 6, 512, 65535, 127, 131071, 0, 1, 0, 0, 150, 1), + (50, 'Rabid Bear', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 153, 1), + (52, 'Improved Familiar', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 155, 1), + (53, 'Nexus Gate', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 156, 1), + (55, 'Permanent Illusion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 158, 1), + (56, 'Jewel Craft Mastery', 6, 8192, 65535, 127, 131071, 0, 1, 0, 0, 159, 1), + (57, 'Gather Mana', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 162, 1), + (58, 'Mend Companion', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 163, 1), + (60, 'Frenzied Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 167, 1), + (61, 'Elemental Form: Fire', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 168, 1), + (62, 'Elemental Form: Water', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 171, 1), + (63, 'Elemental Form: Earth', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 174, 1), + (64, 'Elemental Form: Air', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 177, 1), + (67, 'Elemental Pact', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 182, 1), + (68, 'Life Burn', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 183, 1), + (69, 'Dead Mesmerization', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 184, 1), + (70, 'Fear Storm', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 185, 1), + (71, 'Flesh to Bone', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 186, 1), + (72, 'Call to Corpse', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 187, 1), + (73, 'Divine Stun', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 188, 1), + (75, 'Slay Undead', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 190, 1), + (76, 'Act of Valor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 193, 1), + (77, 'Holy Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 194, 1), + (78, 'Fearless', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 195, 1), + (79, '2 Hand Bash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 196, 1), + (80, 'Innate Camouflage', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 197, 1), + (81, 'Ambidexterity', -1, 16841, 65535, 127, 131071, 0, 3, 0, 0, 198, 1), + (82, 'Archery Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 199, 1), + (84, 'Endless Quiver', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 205, 1), + (85, 'Unholy Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 206, 1), + (87, 'Leech Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 208, 1), + (89, 'Soul Abrasion', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 210, 1), + (90, 'Instrument Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 213, 1), + (94, 'Jam Fest', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 225, 1), + (97, 'Critical Mend', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 230, 1), + (98, 'Purify Body', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 233, 1), + (100, 'Rapid Feign', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 237, 1), + (101, 'Return Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 240, 1), + (102, 'Escape', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 243, 1), + (103, 'Poison Mastery', 6, 256, 65535, 127, 131071, 0, 1, 0, 0, 244, 1), + (104, 'Double Riposte', -1, 49501, 65535, 127, 131071, 0, 2, 0, 0, 247, 1), + (107, 'Purge Poison', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 254, 1), + (108, 'Flurry', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 255, 1), + (109, 'Rampage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 258, 1), + (110, 'Area Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 259, 1), + (111, 'War Cry', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 260, 1), + (112, 'Bandage Wound', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 263, 1), + (114, 'Spell Casting Fury Mastery', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 267, 1), + (116, 'Dragon Punch', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 273, 1), + (117, 'Strong Root', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 274, 1), + (118, 'Singing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 275, 1), + (119, 'Body and Mind Rejuvenation', -1, 16540, 65535, 127, 131071, 0, 3, 0, 0, 278, 1), + (120, 'Physical Enhancement', -1, 49629, 65535, 127, 131071, 0, 3, 0, 0, 279, 1), + (121, 'Adv. Trap Negotiation', -1, 384, 65535, 127, 131071, 0, 3, 0, 0, 280, 1), + (122, 'Acrobatics', -1, 448, 65535, 127, 131071, 0, 3, 0, 0, 283, 1), + (123, 'Scribble Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 286, 1), + (124, 'Chaotic Stab', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 287, 1), + (125, 'Pet Discipline', -1, 22032, 65535, 127, 131071, 0, 3, 0, 0, 288, 1), + (126, 'Hobble of Spirits', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 289, 1), + (127, 'Frenzy of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 290, 1), + (128, 'Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 291, 1), + (129, 'Chains of Purity', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10348, 1), + (130, 'Resplendent Glory', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8300, 1), + (131, 'Rage of Rallos Zek', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8303, 1), + (132, 'Enhanced Area Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8312, 1), + (133, 'Decapitation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 14200, 1), + (134, 'Hastened Berserking Disciplines', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 14203, 1), + (135, 'Quiet Miracle', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14206, 1), + (136, 'Repel the Wicked', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14207, 1), + (137, 'Beacon of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14208, 1), + (138, 'Blessed Chains', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14209, 1), + (139, 'Hastened Focused Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14213, 1), + (140, 'Quickened Spirit Calling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14225, 1), + (141, 'New Tanaan Crafting Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 412, 1), + (142, 'Planar Power', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 418, 1), + (143, 'Planar Durability', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 423, 1), + (144, 'Innate Enlightenment', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 426, 1), + (146, 'Unknown AA 8001', 9, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8000, 0), + (147, 'Spiritual Rebuke', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14231, 1), + (148, 'Pathosis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14232, 1), + (149, 'Preincarnation', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 14233, 1), + (150, 'Mastery of the Past', -1, 15504, 65535, 127, 131071, 0, 2, 0, 0, 446, 1), + (151, 'Spiritual Blessing', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14234, 1), + (152, 'Communion of the Cheetah', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14237, 1), + (153, 'Radiant Cure', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 459, 1), + (154, 'Hastened Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 462, 1), + (156, 'Hastened Purification of the Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 468, 1), + (157, 'Hastened Gathering', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 471, 1), + (158, 'Hastened Rabidity', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 474, 1), + (159, 'Hastened Exodus', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 477, 1), + (160, 'Hastened Root', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 480, 1), + (161, 'Hastened Mending', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 483, 1), + (163, 'Hastened Instigation', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 489, 1), + (164, 'Hastened Rampage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 492, 1), + (165, 'Hastened Purification of the Body', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 495, 1), + (166, 'Hasty Exit', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 498, 1), + (167, 'Hastened Purification', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 501, 1), + (168, 'Hastened Nature\'s Fury', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14241, 1), + (169, 'Divine Arbitration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 507, 1), + (170, 'Wrath of the Wild', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 510, 1), + (171, 'Virulent Paralysis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 513, 1), + (172, 'Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 516, 1), + (173, 'Eldritch Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 517, 1), + (174, 'Servant of Ro', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 520, 1), + (175, 'Wake the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 523, 1), + (176, 'Suspended Minion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 526, 1), + (177, 'Spirit Call', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 528, 1), + (178, 'Wrath of the Forest Walker', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14244, 1), + (179, 'Gift of Sylvan Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14249, 1), + (180, 'Hand of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 534, 1), + (181, 'Mithaniel\'s Binding', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 537, 1), + (182, 'Summon Personal Tribute Master', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5006, 1), + (183, 'Extended Vinelash Cascade', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14254, 1), + (184, 'Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 545, 1), + (185, 'Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 548, 1), + (186, 'Bestial Frenzy', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 551, 1), + (187, 'Harmonious Attack', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 556, 1), + (188, 'Knight\'s Advantage', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 561, 1), + (189, 'Ferocity', -1, 33097, 65535, 127, 131071, 0, 2, 0, 0, 564, 1), + (190, 'Viscid Roots', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 567, 1), + (193, 'Feigned Minion', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 574, 1), + (194, 'Unfailing Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 577, 1), + (195, 'Animation Empathy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 580, 1), + (196, 'Rush to Judgment', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 583, 1), + (197, 'Living Shield', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 586, 1), + (198, 'Consumption of the Soul', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 589, 1), + (199, 'Boastful Bellow', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 592, 1), + (200, 'Fervent Blessing', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 593, 1), + (201, 'Touch of the Wicked', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 596, 1), + (202, 'Punishing Blade', -1, 32841, 65535, 127, 131071, 0, 2, 0, 0, 599, 1), + (203, 'Speed of the Knight', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 602, 1), + (204, 'Shroud of Stealth', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 605, 1), + (205, 'Nimble Evasion', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 606, 1), + (206, 'Technique of Master Wu', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 611, 1), + (207, 'Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 616, 1), + (208, 'Call of Xuzl', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 619, 1), + (209, 'Hastened Stealth', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 622, 1), + (210, 'Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 625, 1), + (211, 'Fleet of Foot', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 628, 1), + (212, 'Fading Memories', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 630, 1), + (213, 'Tactical Mastery', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 631, 1), + (214, 'Theft of Life', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 634, 1), + (215, 'Fury of Magic', -1, 13858, 65535, 127, 131071, 0, 2, 0, 0, 637, 1), + (216, 'Extended Spirit of the Bear', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14259, 1), + (217, 'Project Illusion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 643, 1), + (218, 'Headshot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 644, 1), + (219, 'Entrap', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 645, 1), + (220, 'Sonic Displacement', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13528, 1), + (221, 'Total Domination', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 649, 1), + (222, 'Stalwart Endurance', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 652, 1), + (223, 'Quick Summoning', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 655, 1), + (224, 'Mental Clarity', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 658, 1), + (225, 'Innate Regeneration', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 661, 1), + (227, 'Extended Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 665, 1), + (228, 'Hastened Warder\'s Gift', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13463, 1), + (229, 'Improved Reclaim Energy', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 671, 1), + (230, 'Hastened Possum', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13449, 1), + (231, 'Shauri\'s Sonorious Clouding', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13527, 1), + (232, 'Veil of the Underbrush', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14262, 1), + (233, 'Packrat', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 678, 1), + (234, 'Heightened Endurance ', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 683, 1), + (235, 'Weapon Affinity', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 686, 1), + (236, 'Secondary Forte', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 691, 1), + (237, 'Persistent Casting', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 692, 1), + (238, 'Tune of Pursuance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 695, 1), + (239, 'Hastened Companion\'s Sacrifice', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13474, 1), + (240, 'Cheetah\'s Pounce', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13483, 1), + (241, 'Bloodlust', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13484, 1), + (242, 'Primal Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13485, 1), + (244, 'Lure of the Siren\'s Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13529, 1), + (245, 'Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 718, 1), + (246, 'Hidden Communion of the Cheetah', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14265, 1), + (247, 'Feral Swipe', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 723, 1), + (248, 'Warder\'s Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 724, 1), + (249, 'Warder\'s Alacrity', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 729, 1), + (250, 'Pet Affinity', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 734, 1), + (251, 'Mastery of the Past', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 735, 1), + (252, 'Spell Casting Subtlety', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 738, 1), + (254, 'Divine Avatar', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 746, 1), + (255, 'Exquisite Benediction', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 749, 1), + (256, 'Hastened Curing', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 754, 1), + (257, 'Nature\'s Boon', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 757, 1), + (258, 'Advanced Tracking', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 762, 1), + (259, 'Critical Affliction', -1, 18104, 65535, 127, 131071, 0, 2, 0, 0, 767, 1), + (260, 'Glacial Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13549, 1), + (261, 'Doppelganger', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 773, 1), + (262, 'Enhanced Forgetfulness', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 776, 1), + (263, 'Mesmerization Mastery', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 781, 1), + (264, 'Quick Mass Group Buff', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 782, 1), + (265, 'Shared Health', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 785, 1), + (266, 'Elemental Fury', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 790, 1), + (267, 'Elemental Alacrity ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 795, 1), + (268, 'Elemental Agility', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 800, 1), + (269, 'Elemental Durability', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 803, 1), + (270, 'Sinister Strikes', -1, 16841, 65535, 127, 131071, 0, 3, 0, 0, 806, 1), + (271, 'Strikethrough', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 807, 1), + (272, 'Stonewall', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 810, 1), + (273, 'Rapid Strikes ', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 815, 1), + (274, 'Kick Mastery', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 820, 1), + (275, 'Heightened Awareness', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 823, 1), + (276, 'Destructive Force ', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 828, 1), + (278, 'Death\'s Fury ', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 834, 1), + (279, 'Quickening of Death ', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 839, 1), + (280, 'Group Perfected Invisibility to Undead', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 14281, 1), + (281, 'Triple Backstab', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 846, 1), + (282, 'Hastened Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 849, 1), + (283, 'Immobilizing Bash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 852, 1), + (284, 'Vicious Smash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 855, 1), + (285, 'Radiant Cure', -1, 4, 65535, 127, 131071, 0, 2, 0, 0, 860, 1), + (286, 'Purification ', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 863, 1), + (287, 'Precision of the Pathfinder', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 864, 1), + (288, 'Coat of Thistles', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 867, 1), + (289, 'Flaming Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 872, 1), + (290, 'Frost Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 875, 1), + (291, 'Perfected Invisibility to Undead', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 14282, 1), + (292, 'Trap Circumvention ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 881, 1), + (293, 'Quickened Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14283, 1), + (294, 'Virulent Venom ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 888, 1), + (295, 'Extended Dreary Deeds', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14286, 1), + (296, 'Intense Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 895, 1), + (297, 'Quickened Frenzied Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14289, 1), + (299, 'Sturdiness', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 907, 1), + (300, 'Warlord\'s Tenacity ', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 912, 1), + (301, 'Strengthened Strike', -1, 9, 65535, 127, 131071, 0, 3, 0, 0, 915, 1), + (302, 'Extended Shielding', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 918, 1), + (303, 'Ro\'s Flaming Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 921, 1), + (304, 'E\'ci\'s Icy Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 922, 1), + (305, 'Druzzil\'s Mystical Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 923, 1), + (306, 'Unknown AA 15819', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15819, 1), + (307, 'Ward of Destruction ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 926, 1), + (308, 'Frenzied Devastation', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 931, 1), + (309, 'Combat Fury', -1, 32769, 65535, 127, 131071, 0, 2, 0, 0, 934, 1), + (310, 'Combat Fury', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 937, 1), + (311, 'Combat Fury', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 940, 1), + (312, 'Quickened Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14292, 1), + (313, 'Hastened Companion\'s Relocation', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 14295, 1), + (314, 'Veteran\'s Wrath', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1047, 1), + (315, 'Planar Durability', -1, 32788, 65535, 127, 131071, 0, 3, 0, 0, 952, 1), + (316, 'Innate Enlightenment', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 955, 1), + (317, 'Dire Charm', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 960, 1), + (318, 'Dire Charm', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 961, 1), + (319, 'Touch of the Divine', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 962, 1), + (320, 'Swarm of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 967, 1), + (321, 'Call of the Ancients', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 970, 1), + (322, 'Innate See Invis', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1388, 1), + (323, 'Virulent Talon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14307, 1), + (324, 'Blacksmithing Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 979, 1), + (325, 'Baking Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 982, 1), + (326, 'Brewing Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 985, 1), + (327, 'Fletching Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 988, 1), + (328, 'Pottery Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 991, 1), + (329, 'Tailoring Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 994, 1), + (330, 'Salvage', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 997, 1), + (331, 'Origin', 9, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1000, 1), + (333, 'Discordant Defiance', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1006, 1), + (334, 'Mystical Attuning', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1021, 1), + (335, 'Delay Death', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1026, 1), + (336, 'Earthen Brawn', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8263, 1), + (337, 'Unknown AA 15798', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15798, 1), + (338, 'Veteran\'s Wrath', -1, 16596, 65535, 127, 131071, 0, 2, 0, 0, 1041, 1), + (339, 'Veteran\'s Wrath', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1044, 1), + (340, 'Unknown AA 15833', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15833, 1), + (341, 'Veteran\'s Wrath', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 1050, 1), + (342, 'Staff Block', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 14301, 1), + (343, 'Hastened Pestilent Paralysis', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14308, 1), + (344, 'Hastened Mercurial Torment', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14311, 1), + (345, 'Unknown AA 15768', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15768, 1), + (346, 'Unknown AA 15771', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 15771, 1), + (347, 'Mnemonic Retention', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 1071, 1), + (348, 'Expansive Mind', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 1072, 1), + (350, 'Death\'s Malaise', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14321, 1), + (351, 'Dying Grasp', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14322, 1), + (352, 'Arcane Tongues', 6, 15360, 65535, 127, 131071, 0, 2, 0, 0, 1089, 1), + (353, 'Master of Disguise', -1, 384, 65535, 127, 131071, 0, 3, 0, 0, 1092, 1), + (354, 'Slippery Attacks', -1, 16841, 65535, 127, 131071, 0, 2, 0, 0, 1093, 1), + (355, 'Unknown AA 15836', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15836, 1), + (357, 'Unknown AA 16176', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16176, 1), + (358, 'Fury of Magic', -1, 16540, 65535, 127, 131071, 0, 2, 0, 0, 1107, 1), + (359, 'Dance of Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1110, 1), + (360, 'Bloodthirsty Blade', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13616, 1), + (361, 'Shield of Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1116, 1), + (362, 'Roar of Thunder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 1119, 1), + (363, 'Unknown AA 16179', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16179, 1), + (364, 'Persistent Minion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 1122, 1), + (365, 'A Hole In Space', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 14323, 1), + (366, 'Advanced Pet Discipline', -1, 22032, 65535, 127, 131071, 0, 3, 0, 0, 1129, 1), + (367, 'Throwing Mastery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1131, 1), + (368, 'Blur of Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1134, 1), + (369, 'Hastened War Cry', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1137, 1), + (370, 'Dead Aim', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1140, 1), + (371, 'Frenzied Defense', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1166, 1), + (372, 'Tireless Sprint', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1146, 1), + (373, 'Desperation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1149, 1), + (374, 'Untamed Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1150, 1), + (375, 'Echoing Cries', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1155, 1), + (376, 'Distant Strike', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14372, 1), + (377, 'Earthen Stability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8268, 1), + (378, 'Earthen Alacrity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8273, 1), + (379, 'Earthen Artistry', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8278, 1), + (380, 'Earthen Sagacity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8283, 1), + (381, 'Earthen Brilliance', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8288, 1), + (382, 'Earthen Allure', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8293, 1), + (383, 'Extended Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12646, 1), + (384, 'Spirit of the Bear', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12651, 1), + (385, 'Twinheal', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 12652, 1), + (386, 'Nature\'s Fury', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12661, 1), + (387, 'Blood Pact', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1178, 1), + (388, 'Shielding Resistance', -1, 16841, 65535, 127, 131071, 0, 2, 0, 0, 1181, 1), + (389, 'Healing Boon', -1, 518, 65535, 127, 131071, 0, 2, 0, 0, 1186, 1), + (390, 'Elemental Union', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 13695, 1), + (391, 'Celestial Hammer', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1192, 1), + (392, 'Divine Retribution', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1195, 1), + (393, 'Nature\'s Blessing', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12655, 1), + (394, 'Extended Convergence of Spirit', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12645, 1), + (395, 'Hastened Storm Strike', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12664, 1), + (396, 'Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1209, 1), + (397, 'Destructive Fury', -1, 2048, 65535, 127, 131071, 0, 2, 0, 0, 1210, 1), + (398, 'Destructive Fury', -1, 13858, 65535, 127, 131071, 0, 2, 0, 0, 1213, 1), + (399, 'Unknown AA 16180', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16180, 1), + (400, 'Hastened Improved Twincast', -1, 14370, 65535, 127, 131071, 0, 3, 0, 0, 14331, 1), + (401, 'Extended Heel of Kanji', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12688, 1), + (402, 'Extended Scaledfist', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12691, 1), + (403, 'Paralytic Spores', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 14264, 1), + (404, 'Call of the Wild', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 1228, 1), + (405, 'Secondary Recall', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 1229, 1), + (406, 'Nature\'s Bounty', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 1230, 1), + (407, 'Extended Speed Focus', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7884, 1), + (408, 'Extended Crystalpalm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7885, 1), + (409, 'Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1233, 1), + (410, 'Fists of Steel', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12706, 1), + (411, 'Extended Deftdance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12709, 1), + (412, 'Color Shock', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1239, 1), + (413, 'Mind Over Matter', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1242, 1), + (414, 'Soothing Words', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1245, 1), + (415, 'Hastened Deftdance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12710, 1), + (416, 'Hastened Lyre Leap', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12713, 1), + (417, 'Hastened Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12716, 1), + (418, 'Replenish Companion', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 1126, 1), + (419, 'Extended Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12719, 1), + (420, 'Imitate Death', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1255, 1), + (424, 'Extended Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12720, 1), + (425, 'Hastened Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12721, 1), + (426, 'Unknown AA 15904', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 15904, 1), + (427, 'Resounding Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12737, 1), + (428, 'Death Peace', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1272, 1), + (429, 'Unknown AA 15908', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15908, 1), + (430, 'Mercurial Torment', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12766, 1), + (431, 'Pestilent Paralysis', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12770, 1), + (432, 'Hastened Divine Companion Aura', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 12773, 1), + (433, 'Embalmer\'s Carapace', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12778, 1), + (434, 'Steadfast Will', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 1284, 1), + (435, 'Shield Block', -1, 21, 65535, 127, 131071, 0, 2, 0, 0, 1287, 1), + (436, 'Hastened Encroaching Darkness', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12779, 1), + (437, 'Tracking Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1296, 1), + (438, 'Expanding Darkness', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12782, 1), + (439, 'Precision', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1304, 1), + (440, 'Nerves of Steel', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1307, 1), + (441, 'Aegis of Kildrukaun', -1, 5120, 65535, 127, 131071, 0, 3, 0, 0, 12785, 1), + (442, 'Touch of the Cursed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 1313, 1), + (443, 'Bestial Bloodrage', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12804, 1), + (444, 'Companion\'s Sacrifice', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12807, 1), + (445, 'Shield Block', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 12813, 1), + (446, 'Spiritual Channeling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1323, 1), + (447, 'Ancestral Aid', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1327, 1), + (448, 'Extended Feralgia', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12816, 1), + (450, 'Hastened Protective Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12819, 1), + (451, 'Mind Crash', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1334, 1), + (452, 'Prolonged Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1337, 1), + (453, 'Summon Permutation Peddler', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9032, 1), + (454, 'Hastened Empathic Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12822, 1), + (455, 'Convergence of Spirits', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13556, 1), + (456, 'Teleport Bind', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1343, 1), + (457, 'Quickened Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12831, 1), + (458, 'Warder\'s Gift', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12837, 1), + (459, 'Gelid Rending', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12846, 1), + (460, 'Quickened Nature\'s Salve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12849, 1), + (462, 'Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1345, 1), + (463, 'Divine Guardian', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13385, 1), + (464, 'Divine Peace', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13388, 1), + (465, 'Savage Spirit', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1348, 1), + (466, 'Trials of Mata Muram', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1011, 1), + (467, 'Press the Attack', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1351, 1), + (468, 'Crippling Strike', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1352, 1), + (469, 'Stunning Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1355, 1), + (470, 'Eye Gouge', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1358, 1), + (471, 'Gift of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1361, 1), + (472, 'Tenacity of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1362, 1), + (473, 'Embrace of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1363, 1), + (474, 'Power of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1364, 1), + (475, 'Fervor of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1365, 1), + (476, 'Gift of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1366, 1), + (477, 'Valor of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1367, 1), + (478, 'Embrace of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1368, 1), + (479, 'Power of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1369, 1), + (480, 'Sanctity of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1370, 1), + (481, 'Lesson of the Devoted', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1371, 1), + (482, 'Infusion of the Faithful', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1372, 1), + (483, 'Chaotic Jester', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1373, 1), + (484, 'Expedient Recovery', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1374, 1), + (485, 'Steadfast Servant', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1375, 1), + (486, 'Staunch Recovery', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1376, 1), + (487, 'Intensity of the Resolute', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1377, 1), + (488, 'Curse of Blood', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1378, 1), + (489, 'Yaulp', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 13389, 1), + (490, 'Abscond', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12864, 1), + (491, 'Atol\'s Unresistable Shackles', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12865, 1), + (492, 'Dimensional Shield', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 12866, 1), + (493, 'Improved Sustained Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12867, 1), + (494, 'Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 1409, 1), + (495, 'Gift of Mana', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 1435, 1), + (496, 'Field Dressing', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 1611, 1), + (497, 'Bandage Wounds', -1, 32766, 65535, 127, 131071, 0, 1, 0, 0, 1420, 1), + (498, 'Enhanced Aggression', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 1592, 1), + (499, 'Cascading Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1425, 1), + (500, 'Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 1404, 1), + (501, 'E\'ci\'s Icy Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12886, 1), + (503, 'Hastened Thunder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 1471, 1), + (504, 'Conservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1453, 1), + (505, 'Cry of Battle', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1458, 1), + (506, 'Ward of Purity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1459, 1), + (507, 'Ro\'s Fiery Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12887, 1), + (508, 'Druzzil\'s Mystical Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12888, 1), + (509, 'Kerafyrm\'s Favor', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12889, 1), + (510, 'Kerafyrm\'s Prismatic Familiar', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12892, 1), + (511, 'Throne of Heroes', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 4665, 1), + (512, 'Translocational Anchor', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1630, 1), + (513, 'Hastened Phantasmal Opponent', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12894, 1), + (514, 'Pyromancy', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1478, 1), + (515, 'Improved Twincast', -1, 14370, 65535, 127, 131071, 0, 3, 0, 0, 12893, 1), + (516, 'Abundant Healing', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 1486, 1), + (517, 'Hastened First Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12902, 1), + (518, 'Shared Camouflage', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 1494, 1), + (519, 'Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1495, 1), + (520, 'Nature\'s Guardian', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1498, 1), + (521, 'Edict of Command', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1501, 1), + (522, 'Extended Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1504, 1), + (523, 'Hastened Second Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12907, 1), + (524, 'Blood Magic', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1510, 1), + (525, 'Graverobbing', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1511, 1), + (526, 'Affliction Mastery', -1, 1568, 65535, 127, 131071, 0, 3, 0, 0, 1514, 1), + (527, 'Hastened Third Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12912, 1), + (528, 'Ancestral Guard', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1520, 1), + (529, 'Cloak of Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1523, 1), + (530, 'Profound Visage', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12920, 1), + (531, 'Cloak of Shadows', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1527, 1), + (532, 'Willful Death', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1528, 1), + (533, 'Unknown AA 16016', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16016, 1), + (534, 'Calculated Insanity', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12931, 1), + (535, 'Crippling Aurora', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12937, 1), + (536, 'Appraisal', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1542, 1), + (537, 'Precise Strikes', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1543, 1), + (538, 'Hastened Death', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1546, 1), + (539, 'Unflinching Resolve', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1549, 1), + (540, 'Weightless Steps', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1552, 1), + (541, 'Hastened Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1555, 1), + (542, 'Unknown AA 16071', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16071, 1), + (543, 'Diminutive Companion', -1, 20480, 65535, 127, 131071, 0, 3, 0, 0, 12941, 1), + (544, 'Song of Stone', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1569, 1), + (545, 'Deep Sleep', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1572, 1), + (546, 'Companion\'s Gift', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1577, 1), + (547, 'Unknown AA 16081', -1, 15360, 65535, 127, 131071, 0, 3, 0, 0, 16081, 1), + (548, 'Hastened Defiance', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1583, 1), + (549, 'Dauntless Perseverance', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1591, 1), + (550, 'Steadfast Resolve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 14275, 1), + (551, 'Hastened Mind Crash', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1414, 1), + (552, 'Call of Challenge', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1597, 1), + (553, 'Cacophony', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1598, 1), + (554, 'Hastened Nightmare Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14341, 1), + (555, 'Anatomy', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1604, 1), + (556, 'Scintillating Beam', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14346, 1), + (557, 'Trick Shot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1608, 1), + (558, 'Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1383, 1), + (559, 'Turn Summoned', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1462, 1), + (560, 'Selo\'s Enduring Cadence', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1627, 1), + (561, 'Hastened Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12881, 1), + (562, 'Lightning Strikes', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1616, 1), + (563, 'Concentration', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 1588, 1), + (565, 'Mana Burn', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1638, 1), + (567, 'Unknown AA 16146', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16146, 1), + (568, 'Thief\'s Intuition', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1641, 1), + (569, 'Thief\'s Intuition', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1642, 1), + (570, 'Valiant Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1645, 1), + (571, 'Abyssal Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 1646, 1), + (572, 'Holy Warhorse', -1, 4, 65535, 127, 131071, 0, 3, 0, 1, 1643, 1), + (573, 'Unholy Warhorse', -1, 16, 65535, 127, 131071, 0, 3, 0, 1, 1644, 1), + (574, 'Harmonic Dissonance', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1647, 1), + (575, 'Tinkering Mastery', 6, 15639, 65535, 127, 131071, 0, 1, 0, 1, 4672, 1), + (576, 'Jewel Craft Mastery ', 6, 57343, 65535, 127, 131071, 0, 1, 0, 0, 4675, 1), + (577, 'Concussive Intuition', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12885, 1), + (578, 'Glyph Spray', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12939, 1), + (579, 'Combat Medic ', -1, 32766, 65535, 127, 131071, 0, 1, 0, 0, 4688, 1), + (580, 'Hastened Outrider\'s Accuracy', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13565, 1), + (581, 'Quick Draw', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 4698, 1), + (582, 'Battle Ready', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 4699, 1), + (583, 'Hastened Outrider\'s Evasion', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13568, 1), + (584, 'Grasp of Sylvan Spirits', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13571, 1), + (585, 'Glyph of Dragon Scales', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4702, 1), + (586, 'Glyph of Indeterminable Reward', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 13788, 1), + (587, 'Glyph of Arcane Secrets', 7, 32318, 65535, 127, 131071, 0, 4, 1, 0, 4704, 1), + (588, 'Glyph of Draconic Potential', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4705, 1), + (589, 'Glyph of Destruction', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4706, 1), + (590, 'Breath of Atathus', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5150, 1), + (591, 'Breath of Draton\'ra', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5165, 1), + (592, 'Breath of Osh\'vir', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5180, 1), + (593, 'Breath of Venesh', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5195, 1), + (594, 'Breath of Mysaphar', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5210, 1), + (595, 'Breath of Keikolin', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5225, 1), + (596, 'Small Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12963, 1), + (597, 'Medium Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12964, 1), + (598, 'Large Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12965, 1), + (599, 'Hastened Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 12968, 1), + (600, 'Blessing of the Devoted', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9033, 1), + (601, 'Grappling Strike', -1, 65, 65535, 127, 131071, 0, 3, 0, 0, 4836, 1), + (602, 'Mental Contortion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12938, 1), + (603, 'Shield of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12971, 1), + (604, 'Extended Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 12977, 1), + (605, 'Shield Specialist', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 4844, 1), + (606, 'Mark of the Mage Hunter', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 4849, 1), + (609, 'Uncanny Resilience', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4854, 1), + (610, 'Blinding Fury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4857, 1), + (611, 'Battle Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 4860, 1), + (612, 'Soul Seeker', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4861, 1), + (613, 'Lingering Death', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13096, 1), + (614, 'Spirit Guardian', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5369, 1), + (615, 'Surreality', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4887, 1), + (616, 'Mana Draw', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4890, 1), + (617, 'Doppelganger\'s Beckon', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5127, 1), + (618, 'Armor of Ancestral Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 12989, 1), + (619, 'Group Pact of the Wolf', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 12992, 1), + (620, 'Hastened Inconspicuous Totem', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13001, 1), + (621, 'Fire Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4903, 1), + (622, 'Vapor Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4906, 1), + (623, 'Ice Core ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4909, 1), + (624, 'Stone Core ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4912, 1), + (625, 'Volatile Mana Blaze', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 4915, 1), + (626, 'Purified Spirits', -1, 546, 65535, 127, 131071, 0, 3, 0, 0, 13004, 1), + (627, 'Group Spirit Walk', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13008, 1), + (628, 'Greater Blood Tithe', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4924, 1), + (629, 'Gathering Dusk', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4927, 1), + (630, 'Group Silent Presence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13009, 1), + (631, 'Double Attack', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5366, 1), + (632, 'Sanguine Mind Crystal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4934, 1), + (633, 'Azure Mind Crystal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4935, 1), + (634, 'Hastened Cannibalization', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13010, 1), + (635, 'Hastened Spirit Channeling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13013, 1), + (636, 'Arcane Whisper', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 4938, 1), + (637, 'Vengeful Spirits', -1, 9776, 65535, 127, 131071, 0, 3, 0, 0, 13017, 1), + (638, 'Crippling Apparition', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13020, 1), + (639, 'Dimensional Instability', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 4943, 1), + (640, 'Cryomancy', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 4944, 1), + (641, 'Hastened Self Preservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13055, 1), + (642, 'Binding Axe', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13065, 1), + (643, 'Agony of Absolution', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13066, 1), + (644, 'Hastened Absolution', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13067, 1), + (645, 'Hastened Calculated Insanity', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13753, 1), + (646, 'Hastened Mental Contortion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13758, 1), + (647, 'Hastened Crippling Aurora', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13764, 1), + (649, 'Hastened Leech Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14046, 1), + (650, 'Bony Grasp of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14051, 1), + (651, 'Thought Leech', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14052, 1), + (652, 'Hastened Leechcurse Discipline', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14056, 1), + (653, 'Hastened Unholy Aura Discipline', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14059, 1), + (654, 'Hastened Harmshield', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 14062, 1), + (655, 'Hastened Projection of Doom', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14065, 1), + (656, 'Hastened Projection of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14068, 1), + (657, 'Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14071, 1), + (658, 'Hastened Sanctification Discipline', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14076, 1), + (659, 'Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14080, 1), + (660, 'Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14081, 1), + (661, 'Hunter\'s Fury', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 5248, 1), + (662, 'Union of Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5251, 1), + (663, 'Quickened Stuns', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14100, 1), + (664, 'Extended Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 14115, 1), + (665, 'Death\'s Wrath', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 5264, 1), + (666, 'Taste of Blood', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 5015, 1), + (667, 'Summoner\'s Beckon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 5269, 1), + (668, 'Hymn of the Last Stand', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5017, 1), + (669, 'Bladed Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5020, 1), + (670, 'Twisted Shank', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5021, 1), + (671, 'Dirty Fighting', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5022, 1), + (672, 'Ligament Slice', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5025, 1), + (673, 'Tumble', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5028, 1), + (674, 'Unknown AA 16149', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16149, 1), + (675, 'Shrink', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14224, 1), + (676, 'Convergence', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14358, 1), + (677, 'Gift of Deathly Resolve', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14359, 1), + (678, 'Unknown AA 16082', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 16082, 1), + (679, 'Unknown AA 16083', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 16083, 1), + (680, 'Unknown AA 16084', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16084, 1), + (681, 'Unknown AA 16087', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16087, 1), + (682, 'Unknown AA 16096', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16096, 1), + (683, 'Unknown AA 16097', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16097, 1), + (684, 'Unknown AA 16104', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16104, 1), + (685, 'Unknown AA 16105', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16105, 1), + (686, 'Unknown AA 16106', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16106, 1), + (687, 'Unknown AA 16107', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16107, 1), + (688, 'Unknown AA 16108', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16108, 1), + (689, 'Combat Medic ', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 5136, 1), + (690, 'Unknown AA 16109', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16109, 1), + (691, 'Unknown AA 16113', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16113, 1), + (692, 'Unknown AA 16114', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16114, 1), + (693, 'Unknown AA 16117', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16117, 1), + (694, 'Unknown AA 16120', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16120, 1), + (695, 'Unknown AA 16152', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16152, 1), + (696, 'Unknown AA 16156', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16156, 1), + (697, 'Mortal Coil', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 5085, 1), + (698, 'Hastened Purified Spirits', -1, 546, 65535, 127, 131071, 0, 3, 0, 0, 13416, 1), + (699, 'Swarm of Fireflies', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 13419, 1), + (700, 'Unknown AA 16159', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16159, 1), + (701, 'Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5095, 1), + (702, 'Hand of Disruption', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5098, 1), + (703, 'Quickened Death Bloom', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14318, 1), + (704, 'Hero\'s Barracks', 9, 65535, 65535, 127, 131071, 0, 4, 0, 1, 14367, 1), + (705, 'Spirit of the White Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 5105, 1), + (706, 'Unknown AA 16160', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16160, 1), + (707, 'Pact of the Wolf', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5109, 1), + (708, 'Enchant Alaran Metal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13271, 1), + (709, 'Mass Enchant Alaran Metal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13272, 1), + (710, 'Funeral Pyre', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14360, 1), + (711, 'Unknown AA 16162', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16162, 1), + (712, 'Hastened Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 5118, 1), + (713, 'Etherium Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14129, 1), + (714, 'Hastened Assassination Disciplines', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14135, 1), + (715, 'Cunning Disguise: Shissar', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14139, 1), + (716, 'Scout\'s Mastery of Piercing', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14141, 1), + (717, 'Extended Envenomed Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14144, 1), + (718, 'Heel of Brithrax', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14151, 1), + (719, 'Extended Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14163, 1), + (720, 'Hastened Marr\'s Salvation', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14088, 1), + (721, 'Hastened Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14091, 1), + (722, 'Hastened Drape of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14304, 1), + (723, 'Unknown AA 16185', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16185, 1), + (724, 'Hastened Eldritch Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14364, 1), + (725, 'Unknown AA 16124', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16124, 1), + (726, 'Unknown AA 16128', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16128, 1), + (727, 'Unknown AA 16131', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16131, 1), + (728, 'Unknown AA 16137', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16137, 1), + (729, 'Unknown AA 16140', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 16140, 1), + (730, 'Unknown AA 16186', -1, 9, 65535, 127, 131071, 0, 3, 0, 0, 16186, 1), + (731, 'Unknown AA 16188', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16188, 1), + (732, 'Unknown AA 16195', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16195, 1), + (733, 'Killing Spree', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 4739, 1), + (734, 'Hold the Line', -1, 32833, 65535, 127, 131071, 0, 3, 0, 0, 4742, 1), + (735, 'Battle Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13134, 1), + (737, 'Quickened Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 13143, 1), + (738, 'Quickened Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 13146, 1), + (739, 'Balefire Burst', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13164, 1), + (740, 'Blood Tithe', -1, 1568, 65535, 127, 131071, 0, 3, 0, 0, 4761, 1), + (741, 'Leap of Faith', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13202, 1), + (742, 'Unknown AA 16196', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16196, 1), + (743, 'Hastened Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13166, 1), + (744, 'Howl of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13169, 1), + (745, 'Hastened Tune In Your Head', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13204, 1), + (746, 'Unknown AA 16197', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16197, 1), + (747, 'Unknown AA 16200', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16200, 1), + (748, 'Nightmare Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4894, 1), + (749, 'Explosion of Spite', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13165, 1), + (751, 'Scent of Terris', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13225, 1), + (752, 'Bloodfury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13224, 1), + (753, 'Dreary Deeds', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13252, 1), + (754, 'Enchant Feymetal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13260, 1), + (755, 'Mass Enchant Feymetal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13261, 1), + (756, 'Enlightened Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 13646, 1), + (757, 'Shifting Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 5276, 1), + (758, 'Extended Silent Casting', -1, 15360, 65535, 127, 131071, 0, 3, 0, 0, 13667, 1), + (759, 'Fury of Kerafyrm', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 13670, 1), + (760, 'Unknown AA 16203', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 16203, 1), + (761, 'Unknown AA 16208', -1, 552, 65535, 127, 131071, 0, 3, 0, 0, 16208, 1), + (762, 'Shield Block', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 5283, 1), + (763, 'Mirrored Pestilence', -1, 1552, 65535, 127, 131071, 0, 3, 0, 0, 13684, 1), + (764, 'Embrace The Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13687, 1), + (765, 'Quickened Scent of Terris', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13689, 1), + (766, 'Frenzy of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13693, 1), + (767, 'Unknown AA 16211', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 16211, 1), + (768, 'Unknown AA 16215', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16215, 1), + (769, 'Marr\'s Salvation', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13100, 1), + (770, 'Blessing of the Faithful', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13101, 1), + (771, 'Unbridled Strike of Fear', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13108, 1), + (772, 'Noteworthy Disguise: Drake', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14192, 1), + (773, 'Death\'s Effigy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13133, 1), + (774, 'Empowered Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 14690, 1), + (775, 'Unknown AA 16342', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16342, 1), + (776, 'Arcane Overkill', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 5295, 1), + (777, 'Funeral Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5298, 1), + (778, 'Protection of the Spirit Wolf', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 5007, 1), + (779, 'Hastened Juggernaut Surge', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13873, 1), + (780, 'Hastened Resilience', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13878, 1), + (781, 'Hastened Blood Pact', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13881, 1), + (782, 'Unknown AA 16317', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16317, 1), + (783, 'Energetic Attunement', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1056, 1), + (784, 'Heart of Flames', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1251, 1), + (785, 'Heart of Vapor', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1252, 1), + (786, 'Heart of Ice', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1253, 1), + (787, 'Heart of Stone', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1254, 1), + (789, 'Stealthy Getaway', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1477, 1), + (790, 'Seized Opportunity', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 878, 1), + (791, 'Veil of Mindshadow', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4931, 1), + (792, 'Army of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1274, 1), + (793, 'Mana Blast', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1639, 1), + (794, 'Mana Blaze', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1640, 1), + (795, 'Innate Corruption Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1662, 1), + (796, 'Hastened Five Point Palm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 13889, 1), + (797, 'Moving Mountains', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 13130, 1), + (798, 'Veturika\'s Perseverance', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14229, 1), + (799, 'Unknown AA 16644', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16644, 1), + (800, 'Vehement Rage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6607, 1), + (801, 'Knee Strike', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6610, 1), + (802, 'Hastened Fortitude Discipline', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6611, 1), + (803, 'Hastened Furious Discipline', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6614, 1), + (804, 'Warlord\'s Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6617, 1), + (805, 'Hastened Speed Focus', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14148, 1), + (806, 'Hastened Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14160, 1), + (807, 'Pressure Points', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14157, 1), + (808, 'Hastened Thunder', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14166, 1), + (809, 'Allegretto of Battle', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14181, 1), + (810, 'Vivace of Conflict', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14186, 1), + (811, 'Unknown AA 16218', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 16218, 1), + (812, 'Unknown AA 16221', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16221, 1), + (813, 'Unknown AA 16222', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16222, 1), + (814, 'Unknown AA 16225', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16225, 1), + (815, 'Unknown AA 16230', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16230, 1), + (816, 'Unknown AA 16235', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16235, 1), + (817, 'Unknown AA 16238', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16238, 1), + (818, 'Unknown AA 16257', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 16257, 1), + (819, 'Unknown AA 16666', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16666, 1), + (820, 'Death\'s Revenge', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6630, 1), + (821, 'Harmshield', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 6635, 1), + (822, 'Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6640, 1), + (823, 'Cascading Theft of Defense', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6641, 1), + (824, 'Hate Step', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6644, 1), + (825, 'Vicious Bite of Chaos', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6645, 1), + (826, 'Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 6646, 1), + (827, 'Unknown AA 16745', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16745, 1), + (828, 'Unknown AA 16260', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 16260, 1), + (829, 'Unknown AA 16263', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16263, 1), + (830, 'Unknown AA 16272', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16272, 1), + (831, 'Unknown AA 16276', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16276, 1), + (832, 'Unknown AA 16287', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16287, 1), + (833, 'Unknown AA 17252', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17252, 1), + (834, 'Unknown AA 16296', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16296, 1), + (835, 'Unknown AA 16300', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16300, 1), + (836, 'Unknown AA 16310', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16310, 1), + (837, 'Unknown AA 16330', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16330, 1), + (838, 'Unknown AA 16163', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16163, 1), + (839, 'Unknown AA 16360', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 16360, 1), + (840, 'Unknown AA 16363', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16363, 1), + (841, 'Sleight of Hand', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6663, 1), + (842, 'Enduring Vision', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6666, 1), + (843, 'Expertise of Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6668, 1), + (844, 'Cunning Disguise: Human', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6671, 1), + (845, 'Cunning Disguise: Half-Elf', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6672, 1), + (846, 'Cunning Disguise: Barbarian', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6673, 1), + (847, 'Cunning Disguise: Erudite', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6674, 1), + (848, 'Cunning Disguise: Troll', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6675, 1), + (849, 'Cunning Disguise: Goblin', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6676, 1), + (850, 'Unknown AA 16366', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16366, 1), + (851, 'Unknown AA 16369', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16369, 1), + (852, 'Unknown AA 16370', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16370, 1), + (853, 'Unknown AA 16371', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16371, 1), + (854, 'Unknown AA 17256', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17256, 1), + (856, 'Tigir\'s Insect Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6691, 1), + (857, 'Dampen Resistance', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6692, 1), + (858, 'Hastened Dampen Resistance', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6697, 1), + (859, 'Spirit Walk', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6702, 1), + (860, 'Hastened Virulent Paralysis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6703, 1), + (861, 'Languid Bite', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6706, 1), + (862, 'Quickened Blood of Nadox', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6709, 1), + (863, 'Hastened Spirit Call', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6712, 1), + (864, 'Hastened Thousand Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14169, 1), + (865, 'Unknown AA 17257', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17257, 1), + (866, 'Extended Dance of Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14179, 1), + (867, 'Extended Thousand Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14180, 1), + (868, 'Unknown AA 16380', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16380, 1), + (869, 'Unknown AA 16386', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 16386, 1), + (870, 'Harmonious Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6750, 1), + (871, 'Hastened Weapon Shield', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6751, 1), + (872, 'Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6754, 1), + (873, 'Group Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6755, 1), + (874, 'Pack Hunt', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6758, 1), + (875, 'Keen Blade', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6761, 1), + (876, 'Outrider\'s Evasion', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6764, 1), + (877, 'Ranged Finesse', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6765, 1), + (878, 'Bow Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1196, 1), + (879, 'Unknown AA 17258', -1, 1040, 65535, 127, 131071, 0, 2, 0, 0, 17258, 1), + (880, 'Unknown AA 16392', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16392, 1), + (881, 'Unknown AA 16395', -1, 10248, 65535, 127, 131071, 0, 3, 0, 0, 16395, 1), + (882, 'Unknown AA 16396', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16396, 1), + (883, 'Unknown AA 16536', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 16536, 1), + (884, 'Unknown AA 17209', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17209, 1), + (885, 'Unknown AA 17212', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 17212, 1), + (886, 'Unknown AA 17218', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17218, 1), + (888, 'Unknown AA 17555', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17555, 1), + (889, 'Unknown AA 17229', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17229, 1), + (890, 'Unknown AA 17235', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17235, 1), + (891, 'Healing Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6791, 1), + (892, 'Halt the Dead', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6794, 1), + (894, 'Unknown AA 17242', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17242, 1), + (895, 'Unknown AA 17245', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17245, 1), + (896, 'Unknown AA 17249', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17249, 1), + (897, 'Unknown AA 17199', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 17199, 1), + (898, 'Unknown AA 17267', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17267, 1), + (899, 'Unknown AA 17273', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17273, 1), + (900, 'Rise of Bones', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6815, 1), + (901, 'Whisperwind', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6818, 1), + (902, 'Hastened Blood Magic', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6819, 1), + (903, 'Overpower Undead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6822, 1), + (904, 'Hastened Swarm of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6823, 1), + (905, 'Gift of the Grave', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6828, 1), + (906, 'Hastened Gut Punch', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10522, 1), + (907, 'Hastened First Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10527, 1), + (908, 'Hastened Second Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10532, 1), + (909, 'Hastened Third Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10537, 1), + (910, 'Unknown AA 17280', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17280, 1), + (911, 'Warlord\'s Resurgence', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10545, 1), + (912, 'Warlord\'s Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10546, 1), + (914, 'Improved Shield Specialist', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10548, 1), + (915, 'Unknown AA 17281', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17281, 1), + (917, 'Hastened Grappling Strike', -1, 65, 65535, 127, 131071, 0, 3, 0, 0, 10588, 1), + (918, 'Furious Refrain', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10627, 1), + (919, 'Unknown AA 17554', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17554, 1), + (920, 'Valorous Rage', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10711, 1), + (921, 'Hastened Group Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10714, 1), + (922, 'Hastened Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10719, 1), + (923, 'Hastened Protection of the Spirit Wolf', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10722, 1), + (924, 'Hastened Imbued Ferocity', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10727, 1), + (925, 'Hastened Harmonious Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10730, 1), + (926, 'Hastened Entrap', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10733, 1), + (927, 'Poison Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10736, 1), + (928, 'Merciless Blade', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14026, 1), + (929, 'Combatant\'s Pact', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14029, 1), + (930, 'Warlord\'s Resolve', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14032, 1), + (931, 'Hastened Hate\'s Attraction', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 12582, 1), + (932, 'Unknown AA 17289', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 17289, 1), + (933, 'Improved Death Peace', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 12635, 1), + (934, 'Unknown AA 17307', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 17307, 1), + (935, 'Blessing of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10789, 1), + (936, 'Extended Wild Growth', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 10792, 1), + (937, 'Unknown AA 17317', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17317, 1), + (938, 'Eyes Wide Open', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 12636, 1), + (939, 'Communion of the Cheetah', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12638, 1), + (940, 'Hastened Song of Stone', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6870, 1), + (941, 'Flurry', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6873, 1), + (942, 'Destructive Cascade', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6876, 1), + (943, 'Total Domination', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6879, 1), + (944, 'Enhanced Forgetfulness', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6882, 1), + (945, 'Infusion of Thunder', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10346, 1), + (946, 'Hastened Warlord\'s Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14037, 1), + (947, 'Hastened Warlord\'s Tenacity', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14040, 1), + (948, 'Unknown AA 17328', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17328, 1), + (949, 'Unknown AA 17329', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17329, 1), + (950, 'Unknown AA 17336', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17336, 1), + (951, 'Unknown AA 17339', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 17339, 1), + (952, 'Unknown AA 17342', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17342, 1), + (953, 'Unknown AA 17344', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17344, 1), + (954, 'Unknown AA 17347', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17347, 1), + (955, 'Unknown AA 17357', -1, 514, 65535, 127, 131071, 0, 2, 0, 0, 17357, 1), + (956, 'Unknown AA 17361', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 17361, 1), + (957, 'Unknown AA 17364', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17364, 1), + (958, 'Unknown AA 17370', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17370, 1), + (959, 'Unknown AA 17372', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17372, 1), + (960, 'Stomping Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6930, 1), + (961, 'Juggernaut Surge', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6931, 1), + (962, 'Distraction Attack', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6932, 1), + (963, 'Hastened Savage Spirit', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6935, 1), + (964, 'Dying Blow', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6938, 1), + (965, 'Hastened Projection of Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10519, 1), + (966, 'Unknown AA 17373', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17373, 1), + (967, 'Blade Guardian', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13444, 1), + (968, 'Unknown AA 17375', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17375, 1), + (969, 'Unknown AA 17378', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 17378, 1), + (970, 'Unknown AA 17378', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 17379, 1), + (971, 'Unknown AA 17378', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 17380, 1), + (972, 'Unknown AA 17384', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17384, 1), + (974, 'Unknown AA 17409', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 17409, 1), + (975, 'Unknown AA 17414', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 17414, 1), + (976, 'Unknown AA 17418', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17418, 1), + (977, 'Unknown AA 17558', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17558, 1), + (978, 'Unknown AA 17428', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17428, 1), + (979, 'Unknown AA 17436', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17436, 1), + (980, 'Natural Invisibility', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6970, 1), + (981, 'Attack of the Warders', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6971, 1), + (982, 'Hastened Feral Attacks', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6974, 1), + (983, 'Hastened Focused Paragon', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6977, 1), + (984, 'Hastened Paragon', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6980, 1), + (985, 'Group Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6983, 1), + (986, 'Bite of the Asp', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6984, 1), + (987, 'Raven\'s Claw', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6985, 1), + (988, 'Gorilla Smash', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6986, 1), + (989, 'Stonefoot', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10340, 1), + (990, 'Hastened Stunning Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10343, 1), + (991, 'Quickened Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10470, 1), + (992, 'Tranquil Blessings', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 3676, 1), + (993, 'Righteous Zeal', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6082, 1), + (994, 'Hastened Divine Retribution', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6088, 1), + (995, 'Intrinsic Efficiency', -1, 15386, 65535, 127, 131071, 0, 2, 0, 0, 6112, 1), + (996, 'Powerful Elixirs', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6113, 1), + (997, 'Celestial Rapidity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6534, 1), + (998, 'Hastened Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 2400, 1), + (999, 'Improved Burst of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7765, 1), + (1000, 'Unknown AA 17439', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17439, 1), + (1001, 'Unknown AA 17445', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17445, 1), + (1002, 'Unknown AA 17448', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17448, 1), + (1003, 'Unknown AA 10478', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10478, 1), + (1004, 'Unknown AA 17492', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 17492, 1), + (1005, 'Unknown AA 17495', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 17495, 1), + (1006, 'Unknown AA 17515', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 17515, 1), + (1007, 'Unknown AA 17517', -1, 5120, 65535, 127, 131071, 0, 3, 0, 0, 17517, 1), + (1008, 'Unknown AA 17522', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17522, 1), + (1009, 'Unknown AA 17533', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17533, 1), + (1011, 'Neshika\'s Blink', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7869, 1), + (1012, 'Five Point Palm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7875, 1), + (1013, 'War Cry of the Braxi', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13872, 1), + (1014, 'Unknown AA 17538', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17538, 1), + (1015, 'Unknown AA 17547', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17547, 1), + (1016, 'Unknown AA 17549', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17549, 1), + (1017, 'Unknown AA 17238', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17238, 1), + (1018, 'Unknown AA 17553', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17553, 1), + (1019, 'Unknown AA 17248', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17248, 1), + (1020, 'Hastened Companion\'s Blessing', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 12478, 1), + (1021, 'Unknown AA 17215', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17215, 1), + (1022, 'Destructive Fury', -1, 16540, 65535, 127, 131071, 0, 2, 0, 0, 6636, 1), + (1023, 'Restoration of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14010, 1), + (1024, 'Hastened Leap of Faith', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14085, 1), + (1025, 'Hastened Beacon of the Righteous', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14011, 1), + (1026, 'Unknown AA 17561', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17561, 1), + (1027, 'Unknown AA 17564', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17564, 1), + (1028, 'Unknown AA 17567', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17567, 1), + (1029, 'Unknown AA 17570', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17570, 1), + (1030, 'Unknown AA 17573', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17573, 1), + (1031, 'Unknown AA 17576', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17576, 1), + (1032, 'Unknown AA 17579', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17579, 1), + (1033, 'Unknown AA 17582', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17582, 1), + (1034, 'Unknown AA 17585', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17585, 1), + (1035, 'Unknown AA 17588', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17588, 1), + (1036, 'Unknown AA 17591', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17591, 1), + (1037, 'Unknown AA 17594', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17594, 1), + (1038, 'Unknown AA 17597', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17597, 1), + (1039, 'Unknown AA 17600', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17600, 1), + (1040, 'Theft of Essence', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7900, 1), + (1041, 'Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 7903, 1), + (1042, 'Unknown AA 17603', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17603, 1), + (1043, 'Unknown AA 17606', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17606, 1), + (1044, 'Unknown AA 17609', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17609, 1), + (1045, 'Unknown AA 17612', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17612, 1), + (1046, 'Unknown AA 17615', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17615, 1), + (1047, 'Unknown AA 17618', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17618, 1), + (1048, 'Unknown AA 17621', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17621, 1), + (1049, 'Unknown AA 17624', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17624, 1), + (1050, 'Unknown AA 17627', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17627, 1), + (1051, 'Unknown AA 17630', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17630, 1), + (1052, 'Unknown AA 17633', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17633, 1), + (1053, 'Unknown AA 10481', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10481, 1), + (1054, 'Unknown AA 17639', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17639, 1), + (1060, 'Hastened Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7940, 1), + (1061, 'Cascading Divine Aura', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7943, 1), + (1062, 'Group Purify Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7944, 1), + (1063, 'Hastened Renewal', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7945, 1), + (1064, 'Sanctified Blessing', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7948, 1), + (1065, 'Focused Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7951, 1), + (1090, 'Mastery of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7980, 1), + (1091, 'Hastened Nature\'s Guardian', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7983, 1), + (1092, 'Spirit of the Black Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7986, 1), + (1093, 'Hastened Lycan Soul', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7989, 1), + (1113, 'Hastened Mass Group Buff', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 5010, 1), + (1115, 'Mystical Shield', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 5045, 1), + (1120, 'Self Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8030, 1), + (1121, 'Hastened Veil of Mindshadow', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8031, 1), + (1122, 'Phantasmal Opponent', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8034, 1), + (1123, 'Hastened Edict of Command', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8035, 1), + (1124, 'Fog of Memories', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8038, 1), + (1125, 'Bite of Tashani', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8039, 1), + (1150, 'Fury of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8060, 1), + (1151, 'Fury of Eci', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8063, 1), + (1152, 'Fury of Ro', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8066, 1), + (1153, 'Fortified Entanglement', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8069, 1), + (1154, 'Force of Will', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8072, 1), + (1155, 'Atol\'s Shackles', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8075, 1), + (1156, 'Hastened Manaburn', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8076, 1), + (1157, 'Hastened Call of Xuzl', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8082, 1), + (1158, 'Divine Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1667, 1), + (1159, 'Hastened Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 11014, 1), + (1169, 'Unknown AA 16336', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16336, 1), + (1170, 'Unknown AA 16339', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16339, 1), + (1171, 'Hastened Counterattack Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15502, 1), + (1173, 'Hastened Onslaught', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15509, 1), + (1174, 'Mrylokar\'s Rigor', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15512, 1), + (1175, 'Absorbing Agent', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15515, 1), + (1176, 'Improved Requiem of Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15516, 1), + (1177, 'Quickened Requiem of Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15517, 1), + (1178, 'Silent Displacement', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15521, 1), + (1200, 'Companion\'s Alacrity', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8190, 1), + (1201, 'Improved Intimidation', -1, 41408, 65535, 127, 131071, 0, 2, 0, 1, 8193, 1), + (1202, 'Perfected Levitation', -1, 31272, 65535, 127, 131071, 0, 2, 0, 0, 8194, 1), + (1203, 'Hastened Fortify Companion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8195, 1), + (1204, 'Empowered Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8198, 1), + (1205, 'Companion\'s Fury', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8201, 1), + (1206, 'Quickened Radiant Cure', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 8204, 1), + (1207, 'Quickened Radiant Cure', -1, 4, 65535, 127, 131071, 0, 2, 0, 0, 8207, 1), + (1208, 'Mental Stamina', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 8210, 1), + (1209, 'Hardy Endurance', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8215, 1), + (1210, 'Group Perfected Invisibility', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 8220, 1), + (1211, 'Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 8221, 1), + (1212, 'Group Perfected Invisibility to Undead', -1, 1046, 65535, 127, 131071, 0, 2, 0, 0, 8222, 1), + (1214, 'Cascade of Life', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 8224, 1), + (1215, 'Summon Companion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8227, 1), + (1216, 'Mental Fortitude', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8228, 1), + (1217, 'Gate', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 8231, 1), + (1218, 'Extended Ingenuity', -1, 128, 65535, 127, 131071, 0, 2, 0, 0, 8040, 1), + (1219, 'Armor of Wisdom', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 8235, 1), + (1220, 'Armor of Wisdom', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 8240, 1), + (1221, 'Armor of Wisdom', -1, 202, 65535, 127, 131071, 0, 2, 0, 0, 8245, 1), + (1222, 'Armor of Wisdom', -1, 49920, 65535, 127, 131071, 0, 2, 0, 0, 8250, 1), + (1223, 'Armor of Wisdom', -1, 15392, 65535, 127, 131071, 0, 2, 0, 0, 8255, 1), + (1232, 'Way of the Katori', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15429, 1), + (1233, 'Harmony of Battle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15432, 1), + (1234, 'Hastened Ironfist', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15438, 1), + (1235, 'Two-Finger Wasp Touch', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15447, 1), + (1236, 'Thunderfoot', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15444, 1), + (1237, 'Extended Bloodlust', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15414, 1), + (1239, 'Consumption of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15423, 1), + (1240, 'Frenzied Swipes', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15424, 1), + (1242, 'Hastened Synergy', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15450, 1), + (1243, 'Hastened Crane Stance', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15453, 1), + (1244, 'Hastened Eye Gouge', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15456, 1), + (1245, 'Troubadour\'s Slashing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15540, 1), + (1246, 'Troubadour\'s Blunt Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15543, 1), + (1247, 'Troubadour\'s Piercing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15546, 1), + (1248, 'Hastened Lure of the Siren\'s Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15549, 1), + (1249, 'Frenzied Axe of Rallos', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15555, 1), + (1250, 'Juggernaut\'s Mastery of Throwing', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15564, 1), + (1251, 'Furious Rampage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15567, 1), + (1252, 'Battle Stomp', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15569, 1), + (1253, 'Communion of Blood', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15570, 1), + (1254, 'Hastened Dying Grasp', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15571, 1), + (1255, 'Rest the Dead', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 15574, 1), + (1256, 'Extended Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 15579, 1), + (1257, 'Hand of Death', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15582, 1), + (1258, 'Quickened Levant', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15591, 1), + (1259, 'Cascade of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15594, 1), + (1261, 'Hastened Fury of the Gods', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15598, 1), + (1262, 'Lower Element', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15601, 1), + (1263, 'Destructive Adept', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15602, 1), + (1264, 'Arcane Fusion', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15609, 1), + (1265, 'Arcane Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15611, 1), + (1266, 'Force of Flame', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15612, 1), + (1267, 'Force of Ice', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15615, 1), + (1269, 'Sha\'s Reprisal', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15425, 1), + (1270, 'Crippling Spirit', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15377, 1), + (1271, 'Quick Damage', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15622, 1), + (1272, 'Assassin\'s Wrath', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15625, 1), + (1273, 'Hastened Swiftblade', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15634, 1), + (1274, 'Improved Explosion of Spite', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15639, 1), + (1275, 'Improved Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15640, 1), + (1277, 'Soul Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15642, 1), + (1278, 'Soul Flay', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15643, 1), + (1279, 'Ragged Bite of Agony', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15646, 1), + (1281, 'Everburn', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15648, 1), + (1282, 'Marr\'s Gift', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15619, 1), + (1300, 'Fundament of Intellect', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9100, 1), + (1301, 'Fundament of Intellect', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9109, 1), + (1302, 'Fundament of Intellect', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9118, 1), + (1303, 'Fundament of Intellect', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9127, 1), + (1304, 'Fundament of Wisdom', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9136, 1), + (1305, 'Fundament of Wisdom', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9145, 1), + (1306, 'Fundament of Wisdom', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9154, 1), + (1307, 'Fundament of Power', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9163, 1), + (1308, 'Fundament of Power', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9172, 1), + (1309, 'Fundament of Power', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9181, 1), + (1310, 'Fundament of Power', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9190, 1), + (1311, 'Fundament of Power', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9199, 1), + (1312, 'Fundament of Combat', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9208, 1), + (1313, 'Fundament of Combat', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9217, 1), + (1314, 'Fundament of Combat', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9226, 1), + (1315, 'Fundament of Combat', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9235, 1), + (1350, 'Fundament: First Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9300, 1), + (1351, 'Fundament: Second Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9303, 1), + (1352, 'Fundament: Third Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9306, 1), + (1360, 'Fundament: First Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9309, 1), + (1361, 'Fundament: Second Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9312, 1), + (1362, 'Fundament: Third Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9315, 1), + (1370, 'Fundament: First Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9318, 1), + (1371, 'Fundament: Second Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9321, 1), + (1372, 'Fundament: Third Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9324, 1), + (1380, 'Fundament: First Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9327, 1), + (1381, 'Fundament: Second Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9330, 1), + (1382, 'Fundament: Third Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9333, 1), + (1390, 'Fundament: First Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9336, 1), + (1391, 'Fundament: Second Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9339, 1), + (1392, 'Fundament: Third Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9342, 1), + (1400, 'Fundament: First Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9345, 1), + (1401, 'Fundament: Second Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9348, 1), + (1402, 'Fundament: Third Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9351, 1), + (1403, 'Sturdy Companion', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 9503, 1), + (1404, 'Extended Swarm', -1, 32306, 65535, 127, 131071, 0, 3, 0, 0, 9506, 1), + (1405, 'Twincast', -1, 15906, 65535, 127, 131071, 0, 3, 0, 0, 9509, 1), + (1406, 'Staff Block', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9512, 1), + (1410, 'Fundament: First Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9354, 1), + (1411, 'Fundament: Second Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9357, 1), + (1412, 'Fundament: Third Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9360, 1), + (1420, 'Fundament: First Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9363, 1), + (1421, 'Fundament: Second Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9366, 1), + (1422, 'Fundament: Third Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9369, 1), + (1430, 'Fundament: First Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9372, 1), + (1431, 'Fundament: Second Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9375, 1), + (1432, 'Fundament: Third Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9378, 1), + (1433, 'Extended Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8232, 1), + (1440, 'Fundament: First Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9381, 1), + (1441, 'Fundament: Second Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9384, 1), + (1442, 'Fundament: Third Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9387, 1), + (1450, 'Fundament: First Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9390, 1), + (1451, 'Fundament: Second Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9393, 1), + (1452, 'Fundament: Third Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9396, 1), + (1460, 'Fundament: First Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9399, 1), + (1461, 'Fundament: Second Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9402, 1), + (1462, 'Fundament: Third Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9405, 1), + (1470, 'Fundament: First Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9408, 1), + (1471, 'Fundament: Second Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9411, 1), + (1472, 'Fundament: Third Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9414, 1), + (1480, 'Fundament: First Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9417, 1), + (1481, 'Fundament: Second Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9420, 1), + (1482, 'Fundament: Third Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9423, 1), + (1490, 'Fundament: First Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9426, 1), + (1491, 'Fundament: Second Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9429, 1), + (1492, 'Fundament: Third Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9432, 1), + (1500, 'Fundament: First Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9435, 1), + (1501, 'Fundament: Second Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9438, 1), + (1502, 'Fundament: Third Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9441, 1), + (1503, 'Hallowed Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13673, 1), + (1504, 'Wicked Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13674, 1), + (1505, 'Unknown AA 16103', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16103, 1), + (1580, 'Divine Companion Aura', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 5809, 1), + (1662, 'Spell Casting Mastery', -1, 16412, 65535, 127, 131071, 0, 2, 0, 0, 1216, 1), + (1663, 'Gift of Mana', -1, 16412, 65535, 127, 131071, 0, 2, 0, 0, 1219, 1), + (1664, 'Twinproc', -1, 50175, 65535, 127, 131071, 0, 3, 0, 0, 12416, 1), + (1665, 'Tactical Mastery', -1, 16596, 65535, 127, 131071, 0, 3, 0, 0, 12419, 1), + (1666, 'Group Perfected Levitation', -1, 31272, 65535, 127, 131071, 0, 2, 0, 0, 12422, 1), + (1667, 'Quickened Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 2, 0, 0, 6026, 1), + (1668, 'Acute Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 8260, 1), + (1669, 'Flurry', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 5806, 1), + (1680, 'Hastened Flash of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13905, 1), + (1681, 'Hastened Bazu Roar', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13908, 1), + (1682, 'Hastened Scowl', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13911, 1), + (1683, 'Hastened Mark of the Mage Hunter', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13917, 1), + (1684, 'Knowledge of Alaran Culture', 2, 65535, 65535, 127, 131071, 0, 4, 0, 0, 14017, 1), + (1685, 'Knowledge of Alaran Culture - Advanced', 2, 65535, 65535, 127, 131071, 0, 4, 0, 0, 14018, 1), + (1686, 'Brace For Impact', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14019, 1), + (1687, 'Summon Tome of the Hero\'s Journey', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 14371, 1), + (1800, 'Enchant Planar Alloy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 14373, 1), + (1801, 'Mass Enchant Planar Alloy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 14374, 1), + (2000, 'Armor of Experience', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 4700, 1), + (2001, 'Sneering Grin', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15096, 1), + (2002, 'Warlord\'s Grasp', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15099, 1), + (2003, 'Hastened Press the Attack', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15100, 1), + (2004, 'Hastened Rage of Rallos Zek', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15105, 1), + (2005, 'Hastened Unbroken Attention', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15108, 1), + (2006, 'Extended Resplendant Glory', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15113, 1), + (2007, 'Wars Sheol\'s Heroic Blade', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15119, 1), + (2008, 'Hastened Vehement Rage', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15120, 1), + (2009, 'Hastened Barbed Tongue', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15123, 1), + (2010, 'Hastened Shield Topple', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15126, 1), + (2011, 'Imperator\'s Command', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15129, 1), + (2012, 'Imperator\'s Charge', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15130, 1), + (2013, 'Imperator\'s Precision', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15131, 1), + (2014, 'Hastened Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15132, 1), + (2015, 'Extended Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15135, 1), + (2016, 'Heroic Leap', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15136, 1), + (2018, 'Helix of the Undying', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 15146, 1), + (2019, 'Group Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15147, 1), + (2020, 'Quickened Demand For Honor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15150, 1), + (2021, 'Extended Sanctification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15153, 1), + (2022, 'Extended Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15154, 1), + (2023, 'Extended Preservation of Marr', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15155, 1), + (2024, 'Extended Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15158, 1), + (2025, 'Extended Blessing of the Faithful', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15159, 1), + (2026, 'Hastened Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15162, 1), + (2028, 'Hastened Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15168, 1), + (2031, 'Purity of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15177, 1), + (2032, 'Quickened Scourge Skin', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15179, 1), + (2034, 'Gift of the Quick Spear', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15193, 1), + (2035, 'Extended Provocation for Power', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15194, 1), + (2036, 'Quickened Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15253, 1), + (2037, 'Chameleon\'s Gift', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15304, 1), + (2040, 'Hastened Enraging Kicks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15283, 1), + (2041, 'Close Combat Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15288, 1), + (2042, 'Quickened Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15295, 1), + (2045, 'Shield of Reverence', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15338, 1), + (2046, 'Extended Healing Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15342, 1), + (2047, 'Call of the Herald', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15343, 1), + (2048, 'Covenant of Spirit', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 15356, 1), + (2049, 'Talisman of Celerity', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15357, 1), + (2050, 'Extended Spiritual Blessing', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15358, 1), + (2051, 'Rejuvenation of Spirit', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 15362, 1), + (2053, 'Hastened Turgur\'s Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15371, 1), + (2054, 'Shielding of Spirits', -1, 16930, 65535, 127, 131071, 0, 2, 0, 0, 15374, 1), + (2055, 'Hastened Lunar Healing', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15383, 1), + (2056, 'Quickened Blessing of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15389, 1), + (2057, 'Hastened Wall of Wind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15403, 1), + (2059, 'Quickened Focused Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15406, 1), + (2060, 'Elemental Ward', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15200, 1), + (2061, 'Cloak of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15203, 1), + (2062, 'Hastened Elemental Union', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15204, 1), + (2063, 'Hastened Virulent Talon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15207, 1), + (2064, 'Wind of Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 15210, 1), + (2065, 'Mana Reserve', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15213, 1), + (2066, 'Second Wind Ward', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15214, 1), + (2076, 'Steel Vengeance', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15217, 1), + (2077, 'Extended Vapor Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15220, 1), + (2078, 'Extended Stone Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15223, 1), + (2079, 'Extended Fire Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15226, 1), + (2080, 'Extended Ice Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15229, 1), + (2081, 'Flames of Power', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15232, 1), + (2200, 'Rune of Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15475, 1), + (2201, 'Hastened Glyph Spray', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15478, 1), + (2202, 'Illusions of Grandeur', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15481, 1), + (2203, 'Illusory Ally', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15482, 1), + (2204, 'Gracious Gift of Mana', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15485, 1), + (2205, 'Chromatic Haze', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15486, 1), + (2206, 'Blanket of Forgetfulness', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15489, 1), + (2207, 'Ethereal Manipulation', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15490, 1), + (2208, 'Quick Mezz', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15493, 1), + (2209, 'Reactive Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15496, 1), + (2234, 'Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10368, 1), + (2235, 'Imbued Ferocity', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10387, 1), + (2709, 'Perfected Dead Man Floating', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13692, 1), + (2899, 'Levant', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10700, 1), + (3000, 'Auroria Mastery', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6987, 1), + (3202, 'Pet Discipline', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 7733, 1), + (3203, 'Enchant Palladium Trio', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7736, 1), + (3204, 'Mass Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7737, 1), + (3205, 'Greater Mass Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7738, 1), + (3206, 'Enchant Dwerium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7732, 1), + (3207, 'Mass Enchant Dwerium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7734, 1), + (3208, 'Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7735, 1), + (3209, 'Enchant Temporite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7739, 1), + (3210, 'Mass Enchant Temporite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7740, 1), + (3211, 'Nature\'s Reprieve', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10388, 1), + (3212, 'Hastened Divine Intervention', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10358, 1), + (3213, 'Projection of Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10351, 1), + (3214, 'Improved Atone', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10364, 1), + (3215, 'Projection of Doom', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10352, 1), + (3216, 'Projection of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10353, 1), + (3217, 'Hastened Jolting Kicks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 12500, 1), + (3218, 'Enchant Cosgrite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7741, 1), + (3219, 'Mass Enchant Cosgrite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7742, 1), + (3500, 'Blessing of Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10355, 1), + (3506, 'Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5717, 1), + (3511, 'Punch Mastery', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 6020, 1), + (3512, 'Companion\'s Durability', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6051, 1), + (3513, 'Rake\'s Deadly Aim', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6322, 1), + (3514, 'Rogue\'s Fury', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6325, 1), + (3515, 'Envenomed Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6328, 1), + (3516, 'Companion of Necessity', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 6333, 1), + (3517, 'Rake\'s Powerful Aim', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6334, 1), + (3518, 'Hastened Cacophony', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6337, 1), + (3519, 'Hastened Funeral Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6340, 1), + (3520, 'Master\'s Hastened Combination', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 6343, 1), + (3521, 'Hastened Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 6346, 1), + (3522, 'Hastened Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 6349, 1), + (3525, 'Precise Blow', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 5776, 1), + (3550, 'Beguiler\'s Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5849, 1), + (3551, 'Beguiler\'s Directed Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5870, 1), + (3600, 'Rapid Defiance', 1, 1, 65535, 127, 131071, 0, 3, 0, 1, 6136, 1), + (3646, 'Blast of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6135, 1), + (3676, 'Gift of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10354, 1), + (3701, 'Dirge of the Sleepwalker', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6200, 1), + (3702, 'Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6201, 1), + (3703, 'Steady Hands ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6202, 1), + (3704, 'Selo\'s Sonata', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6205, 1), + (3705, 'Companion\'s Blessing ', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6206, 1), + (3706, 'Hastened Bestial Alignment ', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6209, 1), + (3707, 'Fortify Companion ', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6212, 1), + (3708, 'Burst of Power ', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 6215, 1), + (3709, 'Pact of the Wurine', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6218, 1), + (3710, 'Reckless Abandon ', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6219, 1), + (3711, 'Gift of Resurrection', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6222, 1), + (3713, 'Hastened Call of the Wild ', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 6228, 1), + (3714, 'Protection of Direwood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6232, 1), + (3716, 'Clinging Root ', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6236, 1), + (3718, 'Critical Affliction', -1, 8194, 65535, 127, 131071, 0, 2, 0, 0, 6240, 1), + (3720, 'Mana Overburn ', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6249, 1), + (3724, 'Knight\'s Return Strike ', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 6266, 1), + (3725, 'Hunter\'s Return Kick ', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6269, 1), + (3726, 'Hastened Ligament Slice ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6272, 1), + (3727, 'Knave\'s Return Strike', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6275, 1), + (3728, 'Storm Strike', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6278, 1), + (3729, 'Turgur\'s Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6281, 1), + (3730, 'Silent Presence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6282, 1), + (3731, 'Infused by Rage ', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6283, 1), + (3732, 'Gut Punch', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6286, 1), + (3733, 'Warlord\'s Return Kick', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6287, 1), + (3734, 'Arcomancy ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6290, 1), + (3800, 'Blessing of Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6299, 1), + (3801, 'General Sturdiness', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 6119, 1), + (3802, 'Shield Block', -1, 392, 65535, 127, 131071, 0, 2, 0, 0, 6124, 1), + (3803, 'Hastened Trueshot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6355, 1), + (3804, 'Outrider\'s Accuracy', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6370, 1), + (3805, 'Hastened Mend', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 4801, 1), + (3812, 'Perfected Invisibility', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 7069, 1), + (3813, 'Spell Casting Reinforcement', -1, 7168, 65535, 127, 131071, 0, 2, 0, 0, 6257, 1), + (3815, 'Destructive Cascade', -1, 9776, 65535, 127, 131071, 0, 3, 0, 0, 6375, 1), + (3816, 'Companion\'s Relocation', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6379, 1), + (3817, 'Focused Paragon of Spirits', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6380, 1), + (3818, 'Companion\'s Agility', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6383, 1), + (3819, 'Maestro\'s Concentration', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6386, 1), + (3820, 'Blessing of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6395, 1), + (3821, 'Quickened Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6503, 1), + (3822, 'Chattering Bones', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6508, 1), + (3823, 'Warlord\'s Deadly Aim', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6511, 1), + (3824, 'Quickened Call of the Wild', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 6514, 1), + (3826, 'Force of Disruption', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5984, 1), + (3830, 'Hastened Divine Avatar', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7100, 1), + (3831, 'Hastened Purification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 7103, 1), + (3832, 'Beastlords Feral Kick', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 7106, 1), + (3833, 'Burst of Power ', -1, 32841, 65535, 127, 131071, 0, 2, 0, 0, 6409, 1), + (3834, 'Burst of Power ', -1, 256, 65535, 127, 131071, 0, 2, 0, 0, 6419, 1), + (3835, 'Shield Block', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 6428, 1), + (3836, 'Holy Root', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6436, 1), + (3837, 'Burst of Power ', -1, 16512, 65535, 127, 131071, 0, 2, 0, 0, 6060, 1), + (3838, 'Quickened Suspend Minion', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6445, 1), + (3839, 'Quickened Summon Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6452, 1), + (3840, 'Recourse of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6601, 1), + (3841, 'Call Hither', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 6455, 1), + (3842, 'Fortified Survival', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6458, 1), + (3843, 'Fortified Intervention', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6461, 1), + (3865, 'Planar Durability', -1, 72, 65535, 127, 131071, 0, 3, 0, 0, 6422, 1), + (3890, 'Hastened Force of Will', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 7822, 1), + (3891, 'Hastened Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7832, 1), + (3892, 'Hastened Rumbling Servant', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7828, 1), + (3893, 'Extended Rumbling Servant', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7827, 1), + (3899, 'Furious Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6499, 1), + (4001, 'Undaunted Fury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 7407, 1), + (4002, 'Frenzied Volley', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 7818, 1), + (4200, 'Hastened Forceful Rejuvenation', -1, 32318, 65535, 127, 131071, 0, 2, 0, 0, 12475, 1), + (4666, 'Shield Specialist', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 4666, 1), + (5000, 'Glyph of Courage', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7000, 1), + (5002, 'Glyph of Stored Life', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7002, 1), + (5003, 'Glyph of Frantic Infusion', 7, 30224, 65535, 127, 131071, 0, 4, 1, 0, 7003, 1), + (5004, 'Glyph of Angry Thoughts', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7004, 1), + (5005, 'Foraging', 8, 65535, 65535, 127, 131071, 0, 1, 0, 0, 7062, 1), + (6000, 'Harm Touch', 9, 16, 65535, 127, 131071, 0, 3, 0, 0, 7800, 1), + (6001, 'Lay on Hands', 9, 4, 65535, 127, 131071, 0, 3, 0, 0, 7850, 1), + (6002, 'Hunter\'s Attack Power', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6546, 1), + (6106, 'Sustained Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6106, 1), + (6302, 'Hastened Reckless Abandon', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6302, 1), + (6362, 'Hastened Recklessness', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6362, 1), + (6478, 'Hastened Blessing of Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6478, 1), + (6481, 'Hastened Divine Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6481, 1), + (6488, 'Flurry of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6488, 1), + (6489, 'Hastened Holyforge', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6489, 1), + (6492, 'Inquisitor\'s Judgement', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6492, 1), + (6988, 'Extended Group Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6988, 1), + (7000, 'Voice of Thule', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6639, 1), + (7001, 'Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7872, 1), + (7002, 'Summon Remains', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9500, 1), + (7003, 'Forceful Rejuvenation', -1, 32318, 65535, 127, 131071, 0, 2, 0, 0, 9502, 1), + (7007, 'Summon Remains', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9501, 1), + (7009, 'Teleport Bind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1419, 1), + (7016, 'Glyph of the Master', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7016, 1), + (7017, 'Glyph of Lost Secrets', 7, 32318, 65535, 127, 131071, 0, 4, 1, 0, 7017, 1), + (7018, 'Glyph of Genari Might', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7018, 1), + (7019, 'Glyph of the Cataclysm', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7019, 1), + (7025, 'Group Shrink', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 7669, 1), + (7033, 'Lasting Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 7033, 1), + (7036, 'Hastened Blast of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 7036, 1), + (7050, 'Call of the Hero', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1017, 1), + (7060, 'Precision of Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4809, 1), + (7070, 'Hastened Distraction Attack', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6941, 1), + (7105, 'Deathly Pact', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 976, 1), + (7106, 'Planar Durability', -1, 16768, 65535, 127, 131071, 0, 3, 0, 0, 6467, 1), + (7107, 'Hastened Getaway', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 7005, 1), + (7108, 'Divine Aura', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 977, 1), + (7109, 'Hastened Wrath of the Wild', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7664, 1), + (7689, 'Burst of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7689, 1), + (7690, 'Spirit Mastery', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7690, 1), + (7695, 'Quickened Blood of Avoling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 7695, 1), + (7698, 'Dead Man Floating', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7698, 1), + (7699, 'Dread Incarnate', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7699, 1), + (7700, 'Flurry', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 7700, 1), + (7703, 'Death Bloom', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7703, 1), + (7712, 'Disruptive Persecution', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 7712, 1), + (7715, 'Hastened Whisperwind', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7715, 1), + (7743, 'Hastened Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7743, 1), + (7746, 'Hastened Flusterbolt', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7746, 1), + (7747, 'Volatile Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7747, 1), + (7748, 'Pathfinder\'s Grace', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7748, 1), + (7751, 'Hastened Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7751, 1), + (7754, 'Steed of Souls', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7754, 1), + (7755, 'Scourge Skin', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7755, 1), + (7756, 'Death\'s Effigy', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7756, 1), + (7757, 'Hastened Visage of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7757, 1), + (7760, 'Hastened Hate Step', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7760, 1), + (7801, 'Songwriting', 6, 128, 65535, 127, 131071, 0, 3, 0, 0, 9001, 1), + (7809, 'Hybrid Research', 6, 16412, 65535, 127, 131071, 0, 2, 0, 0, 9011, 1), + (7819, 'Written Prayer', 6, 546, 65535, 127, 131071, 0, 2, 0, 0, 9021, 1), + (7925, 'Sionachie\'s Crescendo', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1018, 1), + (8081, 'Summon Resupply Agent', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9000, 1), + (8130, 'Summon Clockwork Banker', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9031, 1), + (8200, 'Hastened Dirge of the Sleepwalker', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10329, 1), + (8201, 'Vainglorious Shout ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10330, 1), + (8202, 'Lyre Leap ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10331, 1), + (8203, 'Domination Mastery ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10332, 1), + (8204, 'Lyrical Prankster', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10333, 1), + (8205, 'Selo\'s Kick ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10336, 1), + (8261, 'A Tune Stuck In Your Head', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10339, 1), + (8262, 'The Show Must Go On', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 7010, 1), + (8300, 'Spell Casting Subtlety', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 10370, 1), + (8301, 'Improved Natural Invisibility', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10373, 1), + (8302, 'Protection of the Warder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10374, 1), + (8303, 'Nature\'s Salve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10377, 1), + (8304, 'Focus of Animus', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10380, 1), + (8314, 'Fluid March', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8314, 1), + (8317, 'Hastened Selo\'s Kick', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8317, 1), + (8319, 'Hastened Bellow', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8319, 1), + (8322, 'Belltone Mind', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8322, 1), + (8325, 'Subtle Blows', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 8325, 1), + (8331, 'Enhanced Thief\'s Eyes', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 8331, 1), + (8332, 'Extended Languid Bite', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 8332, 1), + (8335, 'Quickened Malosinete', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 8335, 1), + (8341, 'Drape of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 8341, 1), + (8342, 'Host in the Shell', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 8342, 1), + (8347, 'Hastened Mana Draw', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8347, 1), + (8350, 'Hastened Mezmerization', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8350, 1), + (8400, 'Self Preservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10400, 1), + (8401, 'Hastened Frenzy', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10401, 1), + (8402, 'Extended Havoc', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10404, 1), + (8500, 'Healing Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10450, 1), + (8501, 'Overpowering Strikes', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 10453, 1), + (8502, 'Quickened Blessing of Ressurection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10456, 1), + (8503, 'Hastened Atonement', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10459, 1), + (8504, 'Improved Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10462, 1), + (8505, 'Blessing of Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10463, 1), + (8506, 'Hastened Celestial Hammer', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10464, 1), + (8600, 'Spirit of Eagle', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 10500, 1), + (8601, 'Flight of Eagles', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10501, 1), + (8602, 'Egress', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10502, 1), + (8603, 'Spirits of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10503, 1), + (8604, 'Wall of Wind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10506, 1), + (8605, 'Hastened Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10511, 1), + (8606, 'Hastened Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10514, 1), + (8700, 'Beam of Slumber', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10550, 1), + (8701, 'Phantasmic Reflex', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10551, 1), + (8702, 'Friendly Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10557, 1), + (8703, 'Hastened Self Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10558, 1), + (8704, 'Forceful Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10561, 1), + (8708, 'Hastened Cascading Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6908, 1), + (8800, 'Force of Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10600, 1), + (8801, 'Aspect of Zomm', -1, 6144, 65535, 127, 131071, 0, 3, 0, 0, 10603, 1), + (8802, 'Extended Shared Health', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10610, 1), + (8900, 'Agile Feet', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10650, 1), + (8901, 'Hastened Defensive Poses', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10653, 1), + (8902, 'Extended Impenetrable Discipline', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10656, 1), + (8903, 'Hastened Destructive Force', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10657, 1), + (9001, 'Reluctant Benevolence', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10701, 1), + (9100, 'Bestow Divine Aura', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10752, 1), + (9101, 'Blessing of Purification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10753, 1), + (9102, 'Sense the Dead', -1, 1030, 65535, 127, 131071, 0, 3, 0, 0, 10754, 1), + (9200, 'Hastened Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10800, 1), + (9201, 'Clenched Jaw', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10803, 1), + (9202, 'Scout\'s Mastery of Fire', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10806, 1), + (9203, 'Scout\'s Mastery of Ice', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10809, 1), + (9205, 'Scout\'s Mastery of Slashing', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10815, 1), + (9206, 'Scout\'s Mastery of Piercing', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10818, 1), + (9207, 'Scout\'s Mastery of Blunt Weapons', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10821, 1), + (9300, 'Massive Strike', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10850, 1), + (9301, 'Strikethrough', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10853, 1), + (9400, 'Hate\'s Attraction', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10900, 1), + (9401, 'Feigned Minion', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10903, 1), + (9402, 'Hastened Summon Remains', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10909, 1), + (9403, 'Visage of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10912, 1), + (9404, 'Cascading Theft of Life', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10915, 1), + (9500, 'Extended Sloth', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10950, 1), + (9501, 'Hastened Ancestral Aid', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10951, 1), + (9502, 'Hastened Union of Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10954, 1), + (9503, 'Group Shrink', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10957, 1), + (9504, 'Inconspicuous Totem', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10958, 1), + (9505, 'Extended Pestilence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10959, 1), + (9600, 'Hastened Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11000, 1), + (9601, 'Extended Shield Reflect', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11003, 1), + (9602, 'Extended Commanding Voice', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11004, 1), + (9700, 'Hastened Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11050, 1), + (9701, 'Netherstep', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11055, 1), + (9702, 'Beam of Displacement', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11056, 1), + (9703, 'Translocate', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11057, 1), + (9704, 'Teleport', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11058, 1), + (10367, 'Ageless Enmity', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 10367, 1), + (10389, 'Extended Trickery', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10389, 1), + (10392, 'Ageless Enmity', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 10392, 1), + (10393, 'Shackles of Tunare', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10393, 1), + (10394, 'Beacon of the Righteous', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10394, 1), + (10395, 'Bobbing Corpse', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10395, 1), + (10396, 'Group Spirit of the White Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10396, 1), + (10397, 'Group Spirit of the Black Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10397, 1), + (10405, 'Hastened Deflection Discipline', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 10405, 1), + (10410, 'Rogue Triple Attack Skillup Test', -1, 256, 65535, 127, 131071, 0, 3, 0, 1, 10410, 1), + (10413, 'Hastened Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10413, 1), + (10424, 'Hand of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10424, 1), + (10425, 'Fixation of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10425, 1), + (10426, 'Peaceful Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10426, 1), + (10427, 'Peaceful Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10427, 1), + (10434, 'Quickened Army of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10434, 1), + (11073, 'Playing Possum', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11073, 1), + (11074, 'Cat-like Reflexes', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11074, 1), + (11077, 'Hastened Bite of the Asp', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11077, 1), + (11078, 'Hastened Gorilla Smash', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11078, 1), + (11079, 'Hastened Raven\'s Claw', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11079, 1), + (11080, 'Chameleon Strike', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11080, 1), + (11085, 'Two Hands, No Mercy!', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 11085, 1), + (11088, 'Hastened Cry of Battle', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 11088, 1), + (12600, 'Hastened Frenzied Stabbing', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12600, 1), + (12603, 'Extended Frenzied Stabbing Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12603, 1), + (12606, 'Speed of the Scoundrel', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12606, 1), + (12607, 'Hastened Pinpoint', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12607, 1), + (12615, 'Hastened Twisted Chance Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12615, 1), + (15073, 'Banestrike', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 15073, 1), + (15074, 'Hastened Banestrike', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 15074, 1), + (30050, 'Unknown AA 30050', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30050, 1), + (30100, 'Unknown AA 30100', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30100, 1), + (30150, 'Unknown AA 30150', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30150, 1), + (30175, 'Unknown AA 30175', 2, 65335, 65535, 127, 131071, 0, 4, 0, 1, 30175, 1), + (30180, 'Unknown AA 30180', 2, 128, 65535, 127, 131071, 0, 4, 0, 1, 30180, 1), + (30185, 'Unknown AA 30185', 2, 64, 65535, 127, 131071, 0, 4, 0, 1, 30185, 1), + (30190, 'Unknown AA 30190', 2, 8, 65535, 127, 131071, 0, 4, 0, 1, 30190, 1), + (30195, 'Unknown AA 30195', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30195, 1); + +DROP TABLE IF EXISTS `aa_ranks`; +CREATE TABLE IF NOT EXISTS `aa_ranks` ( + `id` int(10) unsigned NOT NULL, + `upper_hotkey_sid` int(10) NOT NULL DEFAULT '-1', + `lower_hotkey_sid` int(10) NOT NULL DEFAULT '-1', + `title_sid` int(10) NOT NULL DEFAULT '-1', + `desc_sid` int(10) NOT NULL DEFAULT '-1', + `cost` int(10) NOT NULL DEFAULT '1', + `level_req` int(10) NOT NULL DEFAULT '51', + `spell` int(10) NOT NULL DEFAULT '-1', + `spell_type` int(10) NOT NULL DEFAULT '0', + `recast_time` int(10) NOT NULL DEFAULT '0', + `expansion` int(10) NOT NULL DEFAULT '0', + `prev_id` int(10) NOT NULL DEFAULT '-1', + `next_id` int(10) NOT NULL DEFAULT '-1', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `aa_ranks` (`id`, `upper_hotkey_sid`, `lower_hotkey_sid`, `title_sid`, `desc_sid`, `cost`, `level_req`, `spell`, `spell_type`, `recast_time`, `expansion`, `prev_id`, `next_id`) VALUES + (2, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, -1, 3), + (3, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 2, 4), + (4, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 3, 5), + (5, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 4, 6), + (6, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 5, 292), + (7, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, -1, 8), + (8, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 7, 9), + (9, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 8, 10), + (10, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 9, 11), + (11, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 10, 302), + (12, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, -1, 13), + (13, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 12, 14), + (14, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 13, 15), + (15, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 14, 16), + (16, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 15, 312), + (17, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, -1, 18), + (18, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 17, 19), + (19, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 18, 20), + (20, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 19, 21), + (21, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 20, 322), + (22, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, -1, 23), + (23, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 22, 24), + (24, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 23, 25), + (25, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 24, 26), + (26, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 25, 332), + (27, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, -1, 28), + (28, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 27, 29), + (29, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 28, 30), + (30, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 29, 31), + (31, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 30, 342), + (32, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, -1, 33), + (33, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 32, 34), + (34, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 33, 35), + (35, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 34, 36), + (36, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 35, 352), + (37, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, -1, 38), + (38, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 37, 39), + (39, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 38, 40), + (40, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 39, 41), + (41, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 40, 362), + (42, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, -1, 43), + (43, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 42, 44), + (44, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 43, 45), + (45, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 44, 46), + (46, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 45, 372), + (47, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, -1, 48), + (48, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 47, 49), + (49, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 48, 50), + (50, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 49, 51), + (51, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 50, 382), + (52, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, -1, 53), + (53, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 52, 54), + (54, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 53, 55), + (55, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 54, 56), + (56, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 55, 392), + (57, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, -1, 58), + (58, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 57, 59), + (59, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 58, 60), + (60, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 59, 61), + (61, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 60, 402), + (62, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, -1, 63), + (63, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, 62, 64), + (64, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, 63, 672), + (68, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, -1, 69), + (69, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, 68, 70), + (70, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, 69, -1), + (71, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, -1, 72), + (72, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, 71, 73), + (73, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, 72, 676), + (74, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, -1, 75), + (75, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, 74, 76), + (76, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, 75, -1), + (77, -1, -1, 77, 77, 2, 55, -1, 0, 0, 3, -1, 78), + (78, -1, -1, 77, 77, 4, 55, -1, 0, 0, 3, 77, 79), + (79, -1, -1, 77, 77, 6, 55, -1, 0, 0, 3, 78, 434), + (80, -1, -1, 80, 80, 2, 55, -1, 0, 0, 3, -1, 81), + (81, -1, -1, 80, 80, 4, 55, -1, 0, 0, 3, 80, 82), + (82, -1, -1, 80, 80, 6, 55, -1, 0, 0, 3, 81, 437), + (83, -1, -1, 83, 83, 2, 55, -1, 0, 0, 3, -1, 84), + (84, -1, -1, 83, 83, 4, 55, -1, 0, 0, 3, 83, 85), + (85, -1, -1, 83, 83, 6, 55, -1, 0, 0, 3, 84, 13099), + (86, -1, -1, 86, 86, 2, 55, -1, 0, 0, 3, -1, 87), + (87, -1, -1, 86, 86, 4, 55, -1, 0, 0, 3, 86, 88), + (88, -1, -1, 86, 86, 6, 55, -1, 0, 0, 3, 87, 266), + (92, -1, -1, 92, 92, 2, 55, -1, 0, 0, 3, -1, 93), + (93, -1, -1, 92, 92, 4, 55, -1, 0, 0, 3, 92, 94), + (94, -1, -1, 92, 92, 6, 55, -1, 0, 0, 3, 93, -1), + (98, -1, -1, 98, 98, 2, 55, -1, 0, 0, 3, -1, 99), + (99, -1, -1, 98, 98, 4, 55, -1, 0, 0, 3, 98, 100), + (100, -1, -1, 98, 98, 6, 55, -1, 0, 0, 3, 99, 4767), + (101, -1, -1, 101, 101, 2, 55, -1, 0, 0, 3, -1, 102), + (102, -1, -1, 101, 101, 4, 55, -1, 0, 0, 3, 101, 103), + (103, -1, -1, 101, 101, 6, 55, -1, 0, 0, 3, 102, -1), + (104, -1, -1, 104, 104, 2, 55, -1, 0, 0, 3, -1, 105), + (105, -1, -1, 104, 104, 4, 55, -1, 0, 0, 3, 104, 106), + (106, -1, -1, 104, 104, 6, 55, -1, 0, 0, 3, 105, -1), + (107, -1, -1, 107, 107, 2, 55, -1, 0, 0, 3, -1, 108), + (108, -1, -1, 107, 107, 4, 55, -1, 0, 0, 3, 107, 109), + (109, -1, -1, 107, 107, 6, 55, -1, 0, 0, 3, 108, 7541), + (110, -1, -1, 110, 110, 2, 55, -1, 0, 0, 3, -1, 111), + (111, -1, -1, 110, 110, 4, 55, -1, 0, 0, 3, 110, 112), + (112, -1, -1, 110, 110, 6, 55, -1, 0, 0, 3, 111, -1), + (113, -1, -1, 113, 113, 2, 55, -1, 0, 0, 3, -1, 114), + (114, -1, -1, 113, 113, 4, 55, -1, 0, 0, 3, 113, 115), + (115, -1, -1, 113, 113, 6, 55, -1, 0, 0, 3, 114, 443), + (116, -1, -1, 116, 116, 2, 55, -1, 0, 0, 3, -1, 117), + (117, -1, -1, 116, 116, 4, 55, -1, 0, 0, 3, 116, 118), + (118, -1, -1, 116, 116, 6, 55, -1, 0, 0, 3, 117, -1), + (119, -1, -1, 119, 119, 2, 55, -1, 0, 0, 3, -1, 120), + (120, -1, -1, 119, 119, 4, 55, -1, 0, 0, 3, 119, 121), + (121, -1, -1, 119, 119, 6, 55, -1, 0, 0, 3, 120, 440), + (122, -1, -1, 122, 122, 2, 55, -1, 0, 0, 3, -1, 123), + (123, -1, -1, 122, 122, 4, 55, -1, 0, 0, 3, 122, 124), + (124, -1, -1, 122, 122, 6, 55, -1, 0, 0, 3, 123, 454), + (125, -1, -1, 125, 125, 2, 55, -1, 0, 0, 3, -1, 126), + (126, -1, -1, 125, 125, 4, 55, -1, 0, 0, 3, 125, 127), + (127, -1, -1, 125, 125, 6, 55, -1, 0, 0, 3, 126, 449), + (128, 128, 128, 128, 128, 9, 59, 5228, 1, 4320, 3, -1, -1), + (129, 129, 129, 129, 129, 5, 59, 2738, 2, 64800, 3, -1, -1), + (130, 130, 130, 130, 130, 3, 59, 2739, 3, 7, 3, -1, -1), + (131, 131, 131, 131, 131, 5, 59, 2740, 4, 900, 3, -1, 531), + (132, 132, 132, 132, 132, 6, 59, 2741, 5, 600, 3, -1, -1), + (136, 136, -1, 136, 136, 5, 59, 2742, 7, 1800, 3, -1, 15341), + (137, -1, -1, 137, 137, 3, 59, -1, 0, 0, 3, -1, 138), + (138, -1, -1, 137, 137, 6, 59, -1, 0, 0, 3, 137, 139), + (139, -1, -1, 137, 137, 9, 59, -1, 0, 0, 3, 138, -1), + (140, 140, -1, 140, 140, 6, 59, 2771, 3, 4320, 3, -1, -1), + (141, -1, -1, 141, 12863, 3, 59, -1, 0, 0, 3, -1, 142), + (142, -1, -1, 141, 12863, 6, 59, -1, 0, 0, 3, 141, 143), + (143, -1, -1, 141, 12863, 9, 59, -1, 0, 0, 3, 142, 12863), + (144, -1, -1, 144, 144, 5, 59, -1, 0, 0, 3, -1, -1), + (145, 145, 145, 145, 145, 9, 59, 2761, 2, 4320, 3, -1, -1), + (146, 146, 146, 146, 146, 5, 59, 2749, 2, 180, 3, -1, 5069), + (147, -1, -1, 147, 147, 3, 59, -1, 0, 0, 3, -1, 148), + (148, -1, -1, 147, 147, 6, 59, -1, 0, 0, 3, 147, 149), + (149, -1, -1, 147, 147, 9, 59, -1, 0, 0, 3, 148, -1), + (150, -1, -1, 150, 150, 3, 59, -1, 0, 0, 3, -1, 151), + (151, -1, -1, 150, 150, 6, 59, -1, 0, 0, 3, 150, 152), + (152, -1, -1, 150, 150, 9, 59, -1, 0, 0, 3, 151, -1), + (153, 153, 153, 153, 153, 5, 59, 2750, 3, 2160, 3, -1, 1519), + (155, 155, 155, 155, 155, 9, 59, 2758, 8, 60, 3, -1, 533), + (156, 156, 156, 156, 156, 6, 59, 2734, 2, 4320, 3, -1, -1), + (158, -1, -1, 158, 158, 3, 59, -1, 0, 0, 3, -1, -1), + (159, -1, -1, 159, 159, 2, 59, -1, 0, 0, 3, -1, 160), + (160, -1, -1, 159, 159, 4, 59, -1, 0, 0, 3, 159, 161), + (161, -1, -1, 159, 159, 6, 59, -1, 0, 0, 3, 160, -1), + (162, 162, 162, 162, 162, 5, 59, 2753, 3, 8640, 3, -1, -1), + (163, 163, 163, 163, 163, 5, 59, 2752, 2, 2160, 3, -1, -1), + (167, 167, 167, 167, 167, 6, 59, 2754, 14, 900, 3, -1, 5879), + (168, 168, 168, 168, 168, 3, 59, 2795, 4, 10, 3, -1, 169), + (169, 168, 168, 168, 168, 6, 59, 2796, 4, 10, 3, 168, 170), + (170, 168, 168, 168, 168, 9, 59, 2797, 4, 10, 3, 169, 15241), + (171, 171, 171, 171, 171, 3, 59, 2798, 4, 10, 3, -1, 172), + (172, 171, 171, 171, 171, 6, 59, 2799, 4, 10, 3, 171, 173), + (173, 171, 171, 171, 171, 9, 59, 2800, 4, 10, 3, 172, 15244), + (174, 174, 174, 174, 174, 3, 59, 2792, 4, 10, 3, -1, 175), + (175, 174, 174, 174, 174, 6, 59, 2793, 4, 10, 3, 174, 176), + (176, 174, 174, 174, 174, 9, 59, 2794, 4, 10, 3, 175, 15247), + (177, 177, 177, 177, 177, 3, 59, 2789, 4, 10, 3, -1, 178), + (178, 177, 177, 177, 177, 6, 59, 2790, 4, 10, 3, 177, 179), + (179, 177, 177, 177, 177, 9, 59, 2791, 4, 10, 3, 178, 15250), + (182, -1, -1, 182, 182, 5, 59, -1, 0, 0, 3, -1, -1), + (183, 183, 183, 183, 183, 9, 59, 2755, 4, 8640, 3, -1, -1), + (184, 184, 184, 184, 184, 3, 59, 2756, 5, 4320, 3, -1, 5953), + (185, 185, 185, 185, 185, 5, 59, 2757, 6, 4320, 3, -1, -1), + (186, 186, 186, 186, 186, 3, 59, 2772, 7, 7, 3, -1, -1), + (187, 187, 187, 187, 187, 6, 59, 2764, 8, 4320, 3, -1, -1), + (188, 188, 188, 188, 188, 9, 59, 2190, 2, 30, 3, -1, 1277), + (190, -1, -1, 190, 190, 3, 59, -1, 0, 0, 3, -1, 191), + (191, -1, -1, 190, 190, 6, 59, -1, 0, 0, 3, 190, 192), + (192, -1, -1, 190, 190, 9, 59, -1, 0, 0, 3, 191, 1524), + (193, 193, 193, 193, 193, 3, 59, 2775, 3, 4320, 3, -1, -1), + (194, 194, 194, 194, 194, 5, 59, 2874, 0, 1, 3, -1, -1), + (195, -1, -1, 195, 195, 6, 59, -1, 0, 0, 3, -1, -1), + (196, -1, -1, 196, 196, 6, 59, -1, 0, 0, 3, -1, -1), + (197, 197, 197, 197, 197, 5, 59, 2765, 2, 7, 3, -1, -1), + (198, -1, -1, 198, 198, 9, 59, -1, 0, 0, 3, -1, -1), + (199, -1, -1, 199, 199, 3, 59, -1, 0, 0, 3, -1, 200), + (200, -1, -1, 199, 199, 6, 59, -1, 0, 0, 3, 199, 201), + (201, -1, -1, 199, 199, 9, 59, -1, 0, 0, 3, 200, 12507), + (205, -1, -1, 205, 205, 9, 59, -1, 0, 0, 3, -1, -1), + (206, 206, 206, 206, 206, 5, 59, 2875, 0, 1, 3, -1, -1), + (208, 208, 208, 208, 208, 6, 59, 2766, 2, 4320, 3, -1, -1), + (210, -1, -1, 210, 210, 3, 59, -1, 0, 0, 3, -1, 211), + (211, -1, -1, 210, 210, 6, 59, -1, 0, 0, 3, 210, 212), + (212, -1, -1, 210, 210, 9, 59, -1, 0, 0, 3, 211, 1316), + (213, -1, -1, 213, 213, 3, 59, -1, 0, 0, 3, -1, 214), + (214, -1, -1, 213, 213, 6, 59, -1, 0, 0, 3, 213, 215), + (215, -1, -1, 213, 213, 9, 59, -1, 0, 0, 3, 214, 700), + (225, -1, -1, 225, 225, 3, 59, -1, 0, 0, 3, -1, 226), + (226, -1, -1, 225, 225, 6, 59, -1, 0, 0, 3, 225, 227), + (227, -1, -1, 225, 225, 9, 59, -1, 0, 0, 3, 226, -1), + (230, -1, -1, 230, 230, 3, 59, -1, 0, 0, 3, -1, 231), + (231, -1, -1, 230, 230, 6, 59, -1, 0, 0, 3, 230, 232), + (232, -1, -1, 230, 230, 9, 59, -1, 0, 0, 3, 231, 539), + (233, 233, 233, 233, 233, 9, 59, 5248, 1, 1800, 3, -1, -1), + (237, -1, -1, 237, 237, 3, 59, -1, 0, 0, 3, -1, 238), + (238, -1, -1, 237, 237, 6, 59, -1, 0, 0, 3, 237, 239), + (239, -1, -1, 237, 237, 9, 59, -1, 0, 0, 3, 238, -1), + (240, -1, -1, 240, 240, 3, 59, -1, 0, 0, 3, -1, 241), + (241, -1, -1, 240, 240, 6, 59, -1, 0, 0, 3, 240, 242), + (242, -1, -1, 240, 240, 9, 59, -1, 0, 0, 3, 241, -1), + (243, 243, -1, 243, 243, 9, 59, 5244, 1, 1440, 3, -1, -1), + (244, -1, -1, 244, 244, 3, 59, -1, 0, 0, 3, -1, 245), + (245, -1, -1, 244, 244, 6, 59, -1, 0, 0, 3, 244, 246), + (246, -1, -1, 244, 244, 9, 59, -1, 0, 0, 3, 245, 8328), + (247, -1, -1, 247, 247, 3, 59, -1, 0, 0, 3, -1, 248), + (248, -1, -1, 247, 247, 6, 59, -1, 0, 0, 3, 247, 249), + (249, -1, -1, 247, 247, 9, 59, -1, 0, 0, 3, 248, 504), + (254, 254, 254, 254, 254, 5, 59, 5232, 12, 4320, 3, -1, -1), + (255, -1, -1, 255, 255, 3, 59, -1, 0, 0, 3, -1, 256), + (256, -1, -1, 255, 255, 6, 59, -1, 0, 0, 3, 255, 257), + (257, -1, -1, 255, 255, 9, 59, -1, 0, 0, 3, 256, 542), + (258, 258, -1, 258, 258, 5, 59, 5233, 1, 600, 3, -1, 10578), + (259, 259, 259, 259, 259, 5, 59, 5234, 2, 900, 3, -1, -1), + (260, 260, -1, 260, 260, 3, 59, 5229, 3, 2160, 3, -1, 261), + (261, 260, -1, 260, 260, 6, 59, 5230, 3, 2160, 3, 260, 262), + (262, 260, -1, 260, 260, 9, 59, 5231, 3, 2160, 3, 261, 8309), + (263, -1, -1, 263, 263, 3, 59, -1, 0, 0, 3, -1, 264), + (264, -1, -1, 263, 263, 6, 59, -1, 0, 0, 3, 263, 265), + (265, -1, -1, 263, 263, 9, 59, -1, 0, 0, 3, 264, -1), + (266, -1, -1, 86, 86, 8, 59, -1, 0, 0, 3, 88, 10467), + (267, -1, -1, 267, 267, 3, 59, -1, 0, 0, 3, -1, 268), + (268, -1, -1, 267, 267, 6, 59, -1, 0, 0, 3, 267, 269), + (269, -1, -1, 267, 267, 9, 59, -1, 0, 0, 3, 268, 640), + (273, -1, -1, 273, 273, 5, 59, 2767, 0, 0, 3, -1, -1), + (274, 274, 274, 274, 274, 5, 59, 2748, 4, 4320, 3, -1, -1), + (275, -1, -1, 275, 275, 3, 59, -1, 0, 0, 3, -1, 276), + (276, -1, -1, 275, 275, 6, 59, -1, 0, 0, 3, 275, 277), + (277, -1, -1, 275, 275, 9, 59, -1, 0, 0, 3, 276, 701), + (278, -1, -1, 278, 278, 5, 59, -1, 0, 0, 3, -1, -1), + (279, -1, -1, 279, 279, 5, 59, -1, 0, 0, 3, -1, 18972), + (280, -1, -1, 280, 280, 3, 59, -1, 0, 0, 3, -1, 281), + (281, -1, -1, 280, 280, 6, 59, -1, 0, 0, 3, 280, 282), + (282, -1, -1, 280, 280, 9, 59, -1, 0, 0, 3, 281, -1), + (283, -1, -1, 283, 283, 3, 59, -1, 0, 0, 3, -1, 284), + (284, -1, -1, 283, 283, 6, 59, -1, 0, 0, 3, 283, 285), + (285, -1, -1, 283, 283, 9, 59, -1, 0, 0, 3, 284, -1), + (286, -1, -1, 286, 286, 3, 59, -1, 0, 0, 3, -1, -1), + (287, -1, -1, 287, 287, 6, 59, -1, 0, 0, 3, -1, -1), + (288, -1, -1, 288, 288, 6, 59, -1, 0, 0, 3, -1, -1), + (289, 289, 289, 289, 289, 5, 59, 3290, 3, 300, 3, -1, 1607), + (290, 290, 290, 290, 290, 4, 59, 3289, 4, 720, 3, -1, 13173), + (291, 291, 291, 291, 291, 6, 59, 3291, 5, 900, 3, -1, 1123), + (292, -1, -1, 2, 2, 1, 61, -1, 0, 0, 4, 6, 293), + (293, -1, -1, 2, 2, 1, 61, -1, 0, 0, 4, 292, 294), + (294, -1, -1, 2, 2, 1, 62, -1, 0, 0, 4, 293, 295), + (295, -1, -1, 2, 2, 1, 62, -1, 0, 0, 4, 294, 296), + (296, -1, -1, 2, 2, 1, 63, -1, 0, 0, 4, 295, 297), + (297, -1, -1, 2, 2, 1, 63, -1, 0, 0, 4, 296, 298), + (298, -1, -1, 2, 2, 1, 64, -1, 0, 0, 4, 297, 299), + (299, -1, -1, 2, 2, 1, 64, -1, 0, 0, 4, 298, 300), + (300, -1, -1, 2, 2, 1, 65, -1, 0, 0, 4, 299, 301), + (301, -1, -1, 2, 2, 1, 65, -1, 0, 0, 4, 300, -1), + (302, -1, -1, 7, 7, 1, 61, -1, 0, 0, 4, 11, 303), + (303, -1, -1, 7, 7, 1, 61, -1, 0, 0, 4, 302, 304), + (304, -1, -1, 7, 7, 1, 62, -1, 0, 0, 4, 303, 305), + (305, -1, -1, 7, 7, 1, 62, -1, 0, 0, 4, 304, 306), + (306, -1, -1, 7, 7, 1, 63, -1, 0, 0, 4, 305, 307), + (307, -1, -1, 7, 7, 1, 63, -1, 0, 0, 4, 306, 308), + (308, -1, -1, 7, 7, 1, 64, -1, 0, 0, 4, 307, 309), + (309, -1, -1, 7, 7, 1, 64, -1, 0, 0, 4, 308, 310), + (310, -1, -1, 7, 7, 1, 65, -1, 0, 0, 4, 309, 311), + (311, -1, -1, 7, 7, 1, 65, -1, 0, 0, 4, 310, -1), + (312, -1, -1, 12, 12, 1, 61, -1, 0, 0, 4, 16, 313), + (313, -1, -1, 12, 12, 1, 61, -1, 0, 0, 4, 312, 314), + (314, -1, -1, 12, 12, 1, 62, -1, 0, 0, 4, 313, 315), + (315, -1, -1, 12, 12, 1, 62, -1, 0, 0, 4, 314, 316), + (316, -1, -1, 12, 12, 1, 63, -1, 0, 0, 4, 315, 317), + (317, -1, -1, 12, 12, 1, 63, -1, 0, 0, 4, 316, 318), + (318, -1, -1, 12, 12, 1, 64, -1, 0, 0, 4, 317, 319), + (319, -1, -1, 12, 12, 1, 64, -1, 0, 0, 4, 318, 320), + (320, -1, -1, 12, 12, 1, 65, -1, 0, 0, 4, 319, 321), + (321, -1, -1, 12, 12, 1, 65, -1, 0, 0, 4, 320, -1), + (322, -1, -1, 17, 17, 1, 61, -1, 0, 0, 4, 21, 323), + (323, -1, -1, 17, 17, 1, 61, -1, 0, 0, 4, 322, 324), + (324, -1, -1, 17, 17, 1, 62, -1, 0, 0, 4, 323, 325), + (325, -1, -1, 17, 17, 1, 62, -1, 0, 0, 4, 324, 326), + (326, -1, -1, 17, 17, 1, 63, -1, 0, 0, 4, 325, 327), + (327, -1, -1, 17, 17, 1, 63, -1, 0, 0, 4, 326, 328), + (328, -1, -1, 17, 17, 1, 64, -1, 0, 0, 4, 327, 329), + (329, -1, -1, 17, 17, 1, 64, -1, 0, 0, 4, 328, 330), + (330, -1, -1, 17, 17, 1, 65, -1, 0, 0, 4, 329, 331), + (331, -1, -1, 17, 17, 1, 65, -1, 0, 0, 4, 330, -1), + (332, -1, -1, 22, 22, 1, 61, -1, 0, 0, 4, 26, 333), + (333, -1, -1, 22, 22, 1, 61, -1, 0, 0, 4, 332, 334), + (334, -1, -1, 22, 22, 1, 62, -1, 0, 0, 4, 333, 335), + (335, -1, -1, 22, 22, 1, 62, -1, 0, 0, 4, 334, 336), + (336, -1, -1, 22, 22, 1, 63, -1, 0, 0, 4, 335, 337), + (337, -1, -1, 22, 22, 1, 63, -1, 0, 0, 4, 336, 338), + (338, -1, -1, 22, 22, 1, 64, -1, 0, 0, 4, 337, 339), + (339, -1, -1, 22, 22, 1, 64, -1, 0, 0, 4, 338, 340), + (340, -1, -1, 22, 22, 1, 65, -1, 0, 0, 4, 339, 341), + (341, -1, -1, 22, 22, 1, 65, -1, 0, 0, 4, 340, -1), + (342, -1, -1, 27, 27, 1, 61, -1, 0, 0, 4, 31, 343), + (343, -1, -1, 27, 27, 1, 61, -1, 0, 0, 4, 342, 344), + (344, -1, -1, 27, 27, 1, 62, -1, 0, 0, 4, 343, 345), + (345, -1, -1, 27, 27, 1, 62, -1, 0, 0, 4, 344, 346), + (346, -1, -1, 27, 27, 1, 63, -1, 0, 0, 4, 345, 347), + (347, -1, -1, 27, 27, 1, 63, -1, 0, 0, 4, 346, 348), + (348, -1, -1, 27, 27, 1, 64, -1, 0, 0, 4, 347, 349), + (349, -1, -1, 27, 27, 1, 64, -1, 0, 0, 4, 348, 350), + (350, -1, -1, 27, 27, 1, 65, -1, 0, 0, 4, 349, 351), + (351, -1, -1, 27, 27, 1, 65, -1, 0, 0, 4, 350, -1), + (352, -1, -1, 32, 32, 1, 61, -1, 0, 0, 4, 36, 353), + (353, -1, -1, 32, 32, 1, 61, -1, 0, 0, 4, 352, 354), + (354, -1, -1, 32, 32, 1, 62, -1, 0, 0, 4, 353, 355), + (355, -1, -1, 32, 32, 1, 62, -1, 0, 0, 4, 354, 356), + (356, -1, -1, 32, 32, 1, 63, -1, 0, 0, 4, 355, 357), + (357, -1, -1, 32, 32, 1, 63, -1, 0, 0, 4, 356, 358), + (358, -1, -1, 32, 32, 1, 64, -1, 0, 0, 4, 357, 359), + (359, -1, -1, 32, 32, 1, 64, -1, 0, 0, 4, 358, 360), + (360, -1, -1, 32, 32, 1, 65, -1, 0, 0, 4, 359, 361), + (361, -1, -1, 32, 32, 1, 65, -1, 0, 0, 4, 360, -1), + (362, -1, -1, 37, 37, 1, 61, -1, 0, 0, 4, 41, 363), + (363, -1, -1, 37, 37, 1, 61, -1, 0, 0, 4, 362, 364), + (364, -1, -1, 37, 37, 1, 62, -1, 0, 0, 4, 363, 365), + (365, -1, -1, 37, 37, 1, 62, -1, 0, 0, 4, 364, 366), + (366, -1, -1, 37, 37, 1, 63, -1, 0, 0, 4, 365, 367), + (367, -1, -1, 37, 37, 1, 63, -1, 0, 0, 4, 366, 368), + (368, -1, -1, 37, 37, 1, 64, -1, 0, 0, 4, 367, 369), + (369, -1, -1, 37, 37, 1, 64, -1, 0, 0, 4, 368, 370), + (370, -1, -1, 37, 37, 1, 65, -1, 0, 0, 4, 369, 371), + (371, -1, -1, 37, 37, 1, 65, -1, 0, 0, 4, 370, -1), + (372, -1, -1, 42, 42, 1, 61, -1, 0, 0, 4, 46, 373), + (373, -1, -1, 42, 42, 1, 61, -1, 0, 0, 4, 372, 374), + (374, -1, -1, 42, 42, 1, 62, -1, 0, 0, 4, 373, 375), + (375, -1, -1, 42, 42, 1, 62, -1, 0, 0, 4, 374, 376), + (376, -1, -1, 42, 42, 1, 63, -1, 0, 0, 4, 375, 377), + (377, -1, -1, 42, 42, 1, 63, -1, 0, 0, 4, 376, 378), + (378, -1, -1, 42, 42, 1, 64, -1, 0, 0, 4, 377, 379), + (379, -1, -1, 42, 42, 1, 64, -1, 0, 0, 4, 378, 380), + (380, -1, -1, 42, 42, 1, 65, -1, 0, 0, 4, 379, 381), + (381, -1, -1, 42, 42, 1, 65, -1, 0, 0, 4, 380, -1), + (382, -1, -1, 47, 47, 1, 61, -1, 0, 0, 4, 51, 383), + (383, -1, -1, 47, 47, 1, 61, -1, 0, 0, 4, 382, 384), + (384, -1, -1, 47, 47, 1, 62, -1, 0, 0, 4, 383, 385), + (385, -1, -1, 47, 47, 1, 62, -1, 0, 0, 4, 384, 386), + (386, -1, -1, 47, 47, 1, 63, -1, 0, 0, 4, 385, 387), + (387, -1, -1, 47, 47, 1, 63, -1, 0, 0, 4, 386, 388), + (388, -1, -1, 47, 47, 1, 64, -1, 0, 0, 4, 387, 389), + (389, -1, -1, 47, 47, 1, 64, -1, 0, 0, 4, 388, 390), + (390, -1, -1, 47, 47, 1, 65, -1, 0, 0, 4, 389, 391), + (391, -1, -1, 47, 47, 1, 65, -1, 0, 0, 4, 390, -1), + (392, -1, -1, 52, 52, 1, 61, -1, 0, 0, 4, 56, 393), + (393, -1, -1, 52, 52, 1, 61, -1, 0, 0, 4, 392, 394), + (394, -1, -1, 52, 52, 1, 62, -1, 0, 0, 4, 393, 395), + (395, -1, -1, 52, 52, 1, 62, -1, 0, 0, 4, 394, 396), + (396, -1, -1, 52, 52, 1, 63, -1, 0, 0, 4, 395, 397), + (397, -1, -1, 52, 52, 1, 63, -1, 0, 0, 4, 396, 398), + (398, -1, -1, 52, 52, 1, 64, -1, 0, 0, 4, 397, 399), + (399, -1, -1, 52, 52, 1, 64, -1, 0, 0, 4, 398, 400), + (400, -1, -1, 52, 52, 1, 65, -1, 0, 0, 4, 399, 401), + (401, -1, -1, 52, 52, 1, 65, -1, 0, 0, 4, 400, -1), + (402, -1, -1, 57, 57, 1, 61, -1, 0, 0, 4, 61, 403), + (403, -1, -1, 57, 57, 1, 61, -1, 0, 0, 4, 402, 404), + (404, -1, -1, 57, 57, 1, 62, -1, 0, 0, 4, 403, 405), + (405, -1, -1, 57, 57, 1, 62, -1, 0, 0, 4, 404, 406), + (406, -1, -1, 57, 57, 1, 63, -1, 0, 0, 4, 405, 407), + (407, -1, -1, 57, 57, 1, 63, -1, 0, 0, 4, 406, 408), + (408, -1, -1, 57, 57, 1, 64, -1, 0, 0, 4, 407, 409), + (409, -1, -1, 57, 57, 1, 64, -1, 0, 0, 4, 408, 410), + (410, -1, -1, 57, 57, 1, 65, -1, 0, 0, 4, 409, 411), + (411, -1, -1, 57, 57, 1, 65, -1, 0, 0, 4, 410, -1), + (412, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, -1, 413), + (413, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 412, 414), + (414, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 413, 415), + (415, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 414, 416), + (416, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 415, 417), + (417, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 416, -1), + (418, -1, -1, 418, 418, 2, 61, -1, 0, 0, 4, -1, 419), + (419, -1, -1, 418, 418, 2, 62, -1, 0, 0, 4, 418, 420), + (420, -1, -1, 418, 418, 2, 63, -1, 0, 0, 4, 419, 421), + (421, -1, -1, 418, 418, 2, 64, -1, 0, 0, 4, 420, 422), + (422, -1, -1, 418, 418, 2, 65, -1, 0, 0, 4, 421, 1001), + (423, -1, -1, 423, 423, 3, 61, -1, 0, 0, 4, -1, 424), + (424, -1, -1, 423, 423, 3, 63, -1, 0, 0, 4, 423, 425), + (425, -1, -1, 423, 423, 3, 65, -1, 0, 0, 4, 424, -1), + (426, -1, -1, 426, 426, 3, 61, -1, 0, 0, 4, -1, 427), + (427, -1, -1, 426, 426, 3, 62, -1, 0, 0, 4, 426, 428), + (428, -1, -1, 426, 426, 3, 63, -1, 0, 0, 4, 427, 429), + (429, -1, -1, 426, 426, 3, 64, -1, 0, 0, 4, 428, 430), + (430, -1, -1, 426, 426, 3, 65, -1, 0, 0, 4, 429, -1), + (434, -1, -1, 77, 77, 2, 62, -1, 0, 0, 4, 79, 435), + (435, -1, -1, 77, 77, 4, 63, -1, 0, 0, 4, 434, 436), + (436, -1, -1, 77, 77, 6, 64, -1, 0, 0, 4, 435, 1083), + (437, -1, -1, 80, 80, 2, 62, -1, 0, 0, 4, 82, 438), + (438, -1, -1, 80, 80, 3, 63, -1, 0, 0, 4, 437, 439), + (439, -1, -1, 80, 80, 4, 64, -1, 0, 0, 4, 438, 1086), + (440, -1, -1, 119, 119, 2, 62, -1, 0, 0, 4, 121, 441), + (441, -1, -1, 119, 119, 2, 63, -1, 0, 0, 4, 440, 442), + (442, -1, -1, 119, 119, 2, 64, -1, 0, 0, 4, 441, 1053), + (443, -1, -1, 113, 113, 3, 62, -1, 0, 0, 4, 115, 444), + (444, -1, -1, 113, 113, 3, 63, -1, 0, 0, 4, 443, 445), + (445, -1, -1, 113, 113, 3, 64, -1, 0, 0, 4, 444, -1), + (446, -1, -1, 446, 735, 3, 62, -1, 0, 0, 4, -1, 447), + (447, -1, -1, 446, 735, 3, 63, -1, 0, 0, 4, 446, 448), + (448, -1, -1, 446, 735, 3, 64, -1, 0, 0, 4, 447, 7050), + (449, -1, -1, 125, 125, 3, 61, -1, 0, 0, 4, 127, 450), + (450, -1, -1, 125, 125, 3, 62, -1, 0, 0, 4, 449, 451), + (451, -1, -1, 125, 125, 3, 63, -1, 0, 0, 4, 450, 452), + (452, -1, -1, 125, 125, 3, 64, -1, 0, 0, 4, 451, 453), + (453, -1, -1, 125, 125, 3, 65, -1, 0, 0, 4, 452, 1061), + (454, -1, -1, 122, 122, 3, 61, -1, 0, 0, 4, 124, 455), + (455, -1, -1, 122, 122, 3, 62, -1, 0, 0, 4, 454, 456), + (456, -1, -1, 122, 122, 3, 63, -1, 0, 0, 4, 455, 457), + (457, -1, -1, 122, 122, 3, 64, -1, 0, 0, 4, 456, 458), + (458, -1, -1, 122, 122, 3, 65, -1, 0, 0, 4, 457, 1066), + (459, 459, 459, 459, 459, 2, 61, 3297, 8, 180, 4, -1, 460), + (460, 459, 459, 459, 459, 4, 63, 3298, 8, 180, 4, 459, 461), + (461, 459, 459, 459, 459, 6, 65, 3299, 8, 180, 4, 460, 1189), + (462, -1, -1, 462, 462, 2, 63, -1, 0, 0, 4, -1, 463), + (463, -1, -1, 462, 462, 2, 64, -1, 0, 0, 4, 462, 464), + (464, -1, -1, 462, 462, 2, 65, -1, 0, 0, 4, 463, 7994), + (468, -1, -1, 468, 468, 2, 63, -1, 0, 0, 4, -1, 469), + (469, -1, -1, 468, 468, 2, 64, -1, 0, 0, 4, 468, 470), + (470, -1, -1, 468, 468, 2, 65, -1, 0, 0, 4, 469, 6439), + (471, -1, -1, 471, 471, 2, 63, -1, 0, 0, 4, -1, 472), + (472, -1, -1, 471, 471, 2, 64, -1, 0, 0, 4, 471, 473), + (473, -1, -1, 471, 471, 2, 65, -1, 0, 0, 4, 472, 12899), + (474, -1, -1, 474, 474, 2, 63, -1, 0, 0, 4, -1, 475), + (475, -1, -1, 474, 474, 2, 64, -1, 0, 0, 4, 474, 476), + (476, -1, -1, 474, 474, 2, 65, -1, 0, 0, 4, 475, 15359), + (477, -1, -1, 477, 477, 2, 63, -1, 0, 0, 4, -1, 478), + (478, -1, -1, 477, 477, 2, 64, -1, 0, 0, 4, 477, 479), + (479, -1, -1, 477, 477, 2, 65, -1, 0, 0, 4, 478, 6233), + (480, -1, -1, 480, 480, 2, 63, -1, 0, 0, 4, -1, 481), + (481, -1, -1, 480, 480, 2, 64, -1, 0, 0, 4, 480, 482), + (482, -1, -1, 480, 480, 2, 65, -1, 0, 0, 4, 481, 4921), + (483, -1, -1, 483, 483, 2, 63, -1, 0, 0, 4, -1, 484), + (484, -1, -1, 483, 483, 2, 64, -1, 0, 0, 4, 483, 485), + (485, -1, -1, 483, 483, 2, 65, -1, 0, 0, 4, 484, -1), + (489, -1, -1, 489, 489, 3, 63, -1, 0, 0, 4, -1, 490), + (490, -1, -1, 489, 489, 3, 64, -1, 0, 0, 4, 489, 491), + (491, -1, -1, 489, 489, 3, 65, -1, 0, 0, 4, 490, 7116), + (492, -1, -1, 492, 492, 2, 63, -1, 0, 0, 4, -1, 493), + (493, -1, -1, 492, 492, 2, 64, -1, 0, 0, 4, 492, 494), + (494, -1, -1, 492, 492, 2, 65, -1, 0, 0, 4, 493, 7128), + (495, -1, -1, 495, 495, 2, 63, -1, 0, 0, 4, -1, 496), + (496, -1, -1, 495, 495, 2, 64, -1, 0, 0, 4, 495, 497), + (497, -1, -1, 495, 495, 2, 65, -1, 0, 0, 4, 496, 6260), + (498, -1, -1, 498, 498, 2, 63, -1, 0, 0, 4, -1, 499), + (499, -1, -1, 498, 498, 2, 64, -1, 0, 0, 4, 498, 500), + (500, -1, -1, 498, 498, 2, 65, -1, 0, 0, 4, 499, 886), + (501, -1, -1, 501, 501, 2, 63, -1, 0, 0, 4, -1, 502), + (502, -1, -1, 501, 501, 2, 64, -1, 0, 0, 4, 501, 503), + (503, -1, -1, 501, 501, 2, 65, -1, 0, 0, 4, 502, 6319), + (504, -1, -1, 247, 247, 3, 62, -1, 0, 0, 4, 249, 505), + (505, -1, -1, 247, 247, 3, 63, -1, 0, 0, 4, 504, 506), + (506, -1, -1, 247, 247, 3, 64, -1, 0, 0, 4, 505, -1), + (507, 507, 507, 507, 507, 3, 61, 3252, 9, 180, 4, -1, 508), + (508, 507, 507, 507, 507, 3, 63, 3253, 9, 180, 4, 507, 509), + (509, 507, 507, 507, 507, 3, 65, 3254, 9, 180, 4, 508, -1), + (510, 510, 510, 510, 510, 3, 61, 3255, 37, 240, 4, -1, 511), + (511, 510, 510, 510, 510, 3, 63, 3256, 37, 240, 4, 510, 512), + (512, 510, 510, 510, 510, 3, 65, 3257, 37, 240, 4, 511, 7425), + (513, 513, 513, 513, 513, 3, 61, 3274, 4, 120, 4, -1, 514), + (514, 513, 513, 513, 513, 3, 63, 3275, 4, 120, 4, 513, 515), + (515, 513, 513, 513, 513, 3, 65, 3276, 4, 120, 4, 514, 6095), + (516, 516, 516, 516, 516, 2, 62, 3338, 5, 480, 4, -1, 6398), + (517, 517, 517, 517, 517, 3, 61, 3258, 12, 600, 4, -1, 518), + (518, 517, 517, 517, 517, 3, 63, 3259, 12, 600, 4, 517, 519), + (519, 517, 517, 517, 517, 3, 65, 3260, 12, 600, 4, 518, 1440), + (520, 520, 520, 520, 520, 3, 61, 3265, 6, 540, 4, -1, 521), + (521, 520, 520, 520, 520, 3, 63, 3266, 6, 540, 4, 520, 522), + (522, 520, 520, 520, 520, 3, 65, 3267, 6, 540, 4, 521, 1507), + (523, 523, 523, 523, 523, 5, 61, 3268, 9, 540, 4, -1, 524), + (524, 523, 523, 523, 523, 4, 63, 3269, 9, 540, 4, 523, 525), + (525, 523, 523, 523, 523, 3, 65, 3270, 9, 540, 4, 524, -1), + (526, 526, 526, 526, 526, 5, 62, 3248, 0, 1, 4, -1, 527), + (527, 526, 526, 526, 526, 3, 64, 3249, 0, 1, 4, 526, -1), + (528, 528, 528, 528, 528, 4, 61, 3283, 5, 720, 4, -1, 529), + (529, 528, 528, 528, 528, 3, 63, 3284, 5, 720, 4, 528, 530), + (530, 528, 528, 528, 528, 2, 65, 3285, 5, 720, 4, 529, 900), + (531, 131, 131, 131, 131, 3, 63, 3250, 4, 900, 4, 131, 532), + (532, 131, 131, 131, 131, 6, 64, 3251, 4, 900, 4, 531, 1203), + (533, 155, 155, 155, 155, 6, 64, 3264, 8, 60, 4, 155, 1344), + (534, 534, 534, 534, 534, 3, 61, 3261, 4, 2160, 4, -1, 535), + (535, 534, 534, 534, 534, 3, 63, 3262, 4, 2160, 4, 534, 536), + (536, 534, 534, 534, 534, 3, 65, 3263, 4, 2160, 4, 535, 715), + (537, -1, -1, 537, 537, 3, 63, -1, 0, 0, 4, -1, 538), + (538, -1, -1, 537, 537, 3, 64, -1, 0, 0, 4, 537, -1), + (539, -1, -1, 230, 230, 2, 63, -1, 0, 0, 4, 232, 540), + (540, -1, -1, 230, 230, 4, 64, -1, 0, 0, 4, 539, 541), + (541, -1, -1, 230, 230, 6, 65, -1, 0, 0, 4, 540, 12677), + (542, -1, -1, 255, 255, 2, 63, -1, 0, 0, 4, 257, 543), + (543, -1, -1, 255, 255, 4, 64, -1, 0, 0, 4, 542, 544), + (544, -1, -1, 255, 255, 6, 65, -1, 0, 0, 4, 543, 1163), + (545, 545, 545, 545, 545, 3, 61, 3271, 3, 900, 4, -1, 546), + (546, 545, 545, 545, 545, 3, 63, 3272, 3, 900, 4, 545, 547), + (547, 545, 545, 545, 545, 3, 65, 3273, 3, 900, 4, 546, 1293), + (548, 548, 548, 548, 548, 4, 61, 3277, 5, 900, 4, -1, 549), + (549, 548, 548, 548, 548, 3, 63, 3278, 5, 900, 4, 548, 550), + (550, 548, 548, 548, 548, 2, 65, 3279, 5, 900, 4, 549, 1225), + (551, -1, -1, 551, 551, 2, 61, -1, 0, 0, 4, -1, 552), + (552, -1, -1, 551, 551, 2, 62, -1, 0, 0, 4, 551, 553), + (553, -1, -1, 551, 551, 2, 63, -1, 0, 0, 4, 552, 554), + (554, -1, -1, 551, 551, 2, 64, -1, 0, 0, 4, 553, 555), + (555, -1, -1, 551, 551, 2, 65, -1, 0, 0, 4, 554, 1633), + (556, -1, -1, 556, 556, 2, 61, -1, 0, 0, 4, -1, 557), + (557, -1, -1, 556, 556, 2, 62, -1, 0, 0, 4, 556, 558), + (558, -1, -1, 556, 556, 2, 63, -1, 0, 0, 4, 557, 559), + (559, -1, -1, 556, 556, 2, 64, -1, 0, 0, 4, 558, 560), + (560, -1, -1, 556, 556, 2, 65, -1, 0, 0, 4, 559, 1563), + (561, -1, -1, 561, 561, 2, 61, -1, 0, 0, 4, -1, 562), + (562, -1, -1, 561, 561, 4, 63, -1, 0, 0, 4, 561, 563), + (563, -1, -1, 561, 561, 6, 65, -1, 0, 0, 4, 562, 1624), + (564, -1, -1, 564, 564, 3, 61, -1, 0, 0, 4, -1, 565), + (565, -1, -1, 564, 564, 3, 63, -1, 0, 0, 4, 564, 566), + (566, -1, -1, 564, 564, 3, 65, -1, 0, 0, 4, 565, 1621), + (567, -1, -1, 567, 567, 5, 63, -1, 0, 0, 4, -1, 5061), + (574, -1, -1, 574, 574, 3, 61, -1, 0, 0, 4, -1, 575), + (575, -1, -1, 574, 574, 3, 63, -1, 0, 0, 4, 574, 576), + (576, -1, -1, 574, 574, 3, 65, -1, 0, 0, 4, 575, 7718), + (577, -1, -1, 577, 577, 2, 61, -1, 0, 0, 4, -1, 578), + (578, -1, -1, 577, 577, 4, 63, -1, 0, 0, 4, 577, 579), + (579, -1, -1, 577, 577, 6, 65, -1, 0, 0, 4, 578, -1), + (580, -1, -1, 580, 580, 4, 61, -1, 0, 0, 4, -1, 581), + (581, -1, -1, 580, 580, 3, 63, -1, 0, 0, 4, 580, 582), + (582, -1, -1, 580, 580, 2, 65, -1, 0, 0, 4, 581, -1), + (583, -1, -1, 583, 583, 2, 63, -1, 0, 0, 4, -1, 584), + (584, -1, -1, 583, 583, 2, 64, -1, 0, 0, 4, 583, 585), + (585, -1, -1, 583, 583, 2, 65, -1, 0, 0, 4, 584, -1), + (586, -1, -1, 586, 586, 2, 61, -1, 0, 0, 4, -1, 587), + (587, -1, -1, 586, 586, 4, 63, -1, 0, 0, 4, 586, 588), + (588, -1, -1, 586, 586, 6, 65, -1, 0, 0, 4, 587, 6130), + (589, -1, -1, 589, 589, 3, 61, -1, 0, 0, 4, -1, 590), + (590, -1, -1, 589, 589, 3, 63, -1, 0, 0, 4, 589, 591), + (591, -1, -1, 589, 589, 3, 65, -1, 0, 0, 4, 590, 893), + (592, 592, 592, 592, 592, 6, 63, 3282, 2, 18, 4, -1, 702), + (593, -1, -1, 593, 593, 3, 61, -1, 0, 0, 4, -1, 594), + (594, -1, -1, 593, 593, 3, 63, -1, 0, 0, 4, 593, 595), + (595, -1, -1, 593, 593, 3, 65, -1, 0, 0, 4, 594, 5972), + (596, -1, -1, 596, 596, 2, 61, -1, 0, 0, 4, -1, 597), + (597, -1, -1, 596, 596, 4, 63, -1, 0, 0, 4, 596, 598), + (598, -1, -1, 596, 596, 6, 65, -1, 0, 0, 4, 597, 5973), + (599, -1, -1, 599, 599, 2, 61, -1, 0, 0, 4, -1, 600), + (600, -1, -1, 599, 599, 4, 63, -1, 0, 0, 4, 599, 601), + (601, -1, -1, 599, 599, 6, 65, -1, 0, 0, 4, 600, 1536), + (602, -1, -1, 602, 602, 3, 61, -1, 0, 0, 4, -1, 603), + (603, -1, -1, 602, 602, 3, 63, -1, 0, 0, 4, 602, 604), + (604, -1, -1, 602, 602, 3, 65, -1, 0, 0, 4, 603, 1533), + (605, -1, -1, 605, 605, 6, 63, -1, 0, 0, 4, -1, -1), + (606, -1, -1, 606, 606, 1, 61, -1, 0, 0, 4, -1, 607), + (607, -1, -1, 606, 606, 1, 62, -1, 0, 0, 4, 606, 608), + (608, -1, -1, 606, 606, 1, 63, -1, 0, 0, 4, 607, 609), + (609, -1, -1, 606, 606, 1, 64, -1, 0, 0, 4, 608, 610), + (610, -1, -1, 606, 606, 1, 65, -1, 0, 0, 4, 609, -1), + (611, -1, -1, 611, 611, 2, 61, -1, 0, 0, 4, -1, 612), + (612, -1, -1, 611, 611, 2, 62, -1, 0, 0, 4, 611, 613), + (613, -1, -1, 611, 611, 2, 63, -1, 0, 0, 4, 612, 614), + (614, -1, -1, 611, 611, 2, 64, -1, 0, 0, 4, 613, 615), + (615, -1, -1, 611, 611, 2, 65, -1, 0, 0, 4, 614, 7175), + (616, 616, 616, 616, 616, 5, 63, 3286, 7, 900, 4, -1, 617), + (617, 616, 616, 616, 616, 4, 64, 3287, 7, 900, 4, 616, 618), + (618, 616, 616, 616, 616, 3, 65, 3288, 7, 900, 4, 617, 1248), + (619, 619, 619, 619, 619, 3, 61, 3292, 6, 900, 4, -1, 620), + (620, 619, 619, 619, 619, 2, 63, 3293, 6, 900, 4, 619, 621), + (621, 619, 619, 619, 619, 1, 65, 3294, 6, 900, 4, 620, 721), + (622, -1, -1, 622, 622, 3, 61, -1, 0, 0, 4, -1, 623), + (623, -1, -1, 622, 622, 3, 62, -1, 0, 0, 4, 622, 624), + (624, -1, -1, 622, 622, 3, 63, -1, 0, 0, 4, 623, 8329), + (625, -1, -1, 625, 625, 1, 61, -1, 0, 0, 4, -1, 626), + (626, -1, -1, 625, 625, 2, 63, -1, 0, 0, 4, 625, 627), + (627, -1, -1, 625, 625, 3, 65, -1, 0, 0, 4, 626, 4733), + (628, -1, -1, 628, 628, 2, 62, -1, 0, 0, 4, -1, 629), + (629, -1, -1, 628, 628, 4, 64, -1, 0, 0, 4, 628, -1), + (630, 630, 630, 630, 630, 6, 63, 5243, 7, 1, 4, -1, -1), + (631, -1, -1, 631, 631, 2, 61, -1, 0, 0, 4, -1, 632), + (632, -1, -1, 631, 631, 3, 63, -1, 0, 0, 4, 631, 633), + (633, -1, -1, 631, 631, 4, 65, -1, 0, 0, 4, 632, 1172), + (634, -1, -1, 634, 634, 1, 61, -1, 0, 0, 4, -1, 635), + (635, -1, -1, 634, 634, 2, 63, -1, 0, 0, 4, 634, 636), + (636, -1, -1, 634, 634, 3, 65, -1, 0, 0, 4, 635, 844), + (637, -1, -1, 637, 637, 3, 61, -1, 0, 0, 4, -1, 638), + (638, -1, -1, 637, 637, 6, 63, -1, 0, 0, 4, 637, 639), + (639, -1, -1, 637, 637, 9, 65, -1, 0, 0, 4, 638, 770), + (640, -1, -1, 267, 267, 2, 61, -1, 0, 0, 4, 269, 641), + (641, -1, -1, 267, 267, 4, 63, -1, 0, 0, 4, 640, 642), + (642, -1, -1, 267, 267, 6, 65, -1, 0, 0, 4, 641, 924), + (643, 643, 643, 643, 643, 4, 62, 5227, 0, 1, 4, -1, -1), + (644, -1, -1, 644, 644, 4, 60, -1, 0, 0, 4, -1, 1601), + (645, 645, -1, 645, 645, 4, 64, 3614, 4, 5, 4, -1, 5999), + (649, -1, -1, 649, 649, 2, 61, -1, 0, 0, 4, -1, 650), + (650, -1, -1, 649, 649, 4, 63, -1, 0, 0, 4, 649, 651), + (651, -1, -1, 649, 649, 6, 65, -1, 0, 0, 4, 650, 5860), + (652, -1, -1, 652, 652, 2, 61, -1, 0, 0, 4, -1, 653), + (653, -1, -1, 652, 652, 4, 63, -1, 0, 0, 4, 652, 654), + (654, -1, -1, 652, 652, 6, 65, -1, 0, 0, 4, 653, -1), + (655, -1, -1, 655, 655, 3, 59, -1, 0, 0, 3, -1, 656), + (656, -1, -1, 655, 655, 6, 59, -1, 0, 0, 3, 655, 657), + (657, -1, -1, 655, 655, 9, 59, -1, 0, 0, 3, 656, -1), + (658, -1, -1, 658, 658, 2, 55, -1, 0, 0, 3, -1, 659), + (659, -1, -1, 658, 658, 4, 55, -1, 0, 0, 3, 658, 660), + (660, -1, -1, 658, 658, 6, 55, -1, 0, 0, 3, 659, 5306), + (661, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, -1, 662), + (662, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, 661, 663), + (663, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, 662, 674), + (665, -1, -1, 270, 665, 3, 59, -1, 0, 0, 3, -1, 666), + (666, -1, -1, 270, 665, 6, 59, -1, 0, 0, 3, 665, 667), + (667, -1, -1, 270, 665, 9, 59, -1, 0, 0, 3, 666, 668), + (668, -1, -1, 270, 665, 2, 63, -1, 0, 0, 4, 667, 669), + (669, -1, -1, 270, 665, 2, 64, -1, 0, 0, 4, 668, 670), + (670, -1, -1, 270, 665, 2, 65, -1, 0, 0, 4, 669, 7612), + (671, -1, -1, 671, 671, 3, 59, -1, 0, 0, 3, -1, -1), + (672, -1, -1, 62, 62, 5, 61, -1, 0, 0, 7, 64, 673), + (673, -1, -1, 62, 62, 5, 61, -1, 0, 0, 7, 672, -1), + (674, -1, -1, 65, 661, 3, 61, -1, 0, 0, 7, 663, 675), + (675, -1, -1, 65, 661, 3, 61, -1, 0, 0, 7, 674, 1031), + (676, -1, -1, 71, 71, 2, 61, -1, 0, 0, 7, 73, 677), + (677, -1, -1, 71, 71, 3, 61, -1, 0, 0, 7, 676, 978), + (678, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, -1, 679), + (679, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 678, 680), + (680, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 679, 681), + (681, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 680, 682), + (682, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 681, 6518), + (683, -1, -1, 683, 683, 3, 61, -1, 0, 0, 7, -1, 684), + (684, -1, -1, 683, 683, 6, 61, -1, 0, 0, 7, 683, 685), + (685, -1, -1, 683, 683, 9, 61, -1, 0, 0, 7, 684, 1036), + (686, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, -1, 687), + (687, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 686, 688), + (688, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 687, 689), + (689, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 688, 690), + (690, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 689, 7640), + (691, -1, -1, 691, 691, 9, 55, -1, 0, 0, 7, -1, -1), + (692, -1, -1, 692, 692, 3, 55, -1, 0, 0, 7, -1, 693), + (693, -1, -1, 692, 692, 6, 55, -1, 0, 0, 7, 692, 694), + (694, -1, -1, 692, 692, 9, 55, -1, 0, 0, 7, 693, 7647), + (695, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, -1, 696), + (696, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 695, 697), + (697, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 696, 698), + (698, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 697, 699), + (699, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 698, 15529), + (700, -1, -1, 213, 213, 9, 61, -1, 0, 0, 7, 215, -1), + (701, -1, -1, 275, 275, 9, 61, -1, 0, 0, 7, 277, -1), + (702, 592, 592, 592, 592, 3, 65, 4842, 2, 18, 7, 592, 703), + (703, 592, 592, 592, 592, 3, 65, 4843, 2, 18, 7, 702, 704), + (704, 592, 592, 592, 592, 3, 65, 4844, 2, 18, 7, 703, 705), + (705, 592, 592, 592, 592, 3, 65, 4845, 2, 18, 7, 704, 706), + (706, 592, 592, 592, 592, 3, 65, 4846, 2, 18, 7, 705, 1102), + (715, 534, 534, 534, 534, 3, 65, 5112, 4, 2160, 7, 536, 716), + (716, 534, 534, 534, 534, 6, 65, 5113, 4, 2160, 7, 715, 717), + (717, 534, 534, 534, 534, 9, 65, 5114, 4, 2160, 7, 716, 1278), + (718, 718, 718, 718, 718, 3, 65, 4521, 7, 4320, 7, -1, 719), + (719, 718, 718, 718, 718, 6, 65, 4522, 7, 4320, 7, 718, 720), + (720, 718, 718, 718, 718, 9, 65, 4523, 7, 4320, 7, 719, 1019), + (721, 619, 619, 619, 619, 5, 65, 5110, 6, 900, 7, 621, 722), + (722, 619, 619, 619, 619, 5, 65, 5111, 6, 900, 7, 721, 6296), + (723, 723, 723, 723, 723, 9, 65, 4788, 6, 30, 7, -1, 4963), + (724, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, -1, 725), + (725, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 724, 726), + (726, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 725, 727), + (727, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 726, 728), + (728, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 727, 5254), + (729, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, -1, 730), + (730, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 729, 731), + (731, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 730, 732), + (732, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 731, 733), + (733, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 732, 1467), + (734, -1, -1, 734, 734, 12, 65, -1, 0, 0, 7, -1, -1), + (735, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, -1, 736), + (736, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, 735, 737), + (737, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, 736, 7056), + (738, -1, -1, 98, 738, 3, 55, -1, 0, 0, 7, -1, 739), + (739, -1, -1, 98, 738, 6, 55, -1, 0, 0, 7, 738, 740), + (740, -1, -1, 98, 738, 9, 55, -1, 0, 0, 7, 739, 5317), + (746, 746, 746, 746, 746, 3, 65, 4549, 10, 2160, 7, -1, 747), + (747, 746, 746, 746, 746, 6, 65, 4550, 10, 2160, 7, 746, 748), + (748, 746, 746, 746, 746, 9, 65, 4551, 10, 2160, 7, 747, 1491), + (749, 749, 749, 749, 749, 5, 65, 4790, 11, 1800, 7, -1, 750), + (750, 749, 749, 749, 749, 5, 65, 4791, 11, 1800, 7, 749, 751), + (751, 749, 749, 749, 749, 5, 65, 4792, 11, 1800, 7, 750, 752), + (752, 749, 749, 749, 749, 5, 65, 4793, 11, 1800, 7, 751, 753), + (753, 749, 749, 749, 749, 5, 65, 4794, 11, 1800, 7, 752, 1206), + (754, -1, -1, 754, 754, 3, 65, -1, 0, 0, 7, -1, 755), + (755, -1, -1, 754, 754, 6, 65, -1, 0, 0, 7, 754, 756), + (756, -1, -1, 754, 754, 9, 65, -1, 0, 0, 7, 755, 7659), + (757, 757, -1, 757, 757, 5, 65, 4796, 6, 1800, 7, -1, 758), + (758, 757, -1, 757, 757, 5, 65, 4797, 6, 1800, 7, 757, 759), + (759, 757, -1, 757, 757, 5, 65, 4798, 6, 1800, 7, 758, 760), + (760, 757, -1, 757, 757, 5, 65, 4799, 6, 1800, 7, 759, 761), + (761, 757, -1, 757, 757, 5, 65, 4800, 6, 1800, 7, 760, 1222), + (762, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, -1, 763), + (763, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 762, 764), + (764, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 763, 765), + (765, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 764, 766), + (766, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 765, -1), + (767, -1, -1, 767, 767, 3, 65, -1, 0, 0, 7, -1, 768), + (768, -1, -1, 767, 767, 6, 65, -1, 0, 0, 7, 767, 769), + (769, -1, -1, 767, 767, 9, 65, -1, 0, 0, 7, 768, 1099), + (770, -1, -1, 637, 637, 3, 65, -1, 0, 0, 7, 639, 771), + (771, -1, -1, 637, 637, 6, 65, -1, 0, 0, 7, 770, 772), + (772, -1, -1, 637, 637, 9, 65, -1, 0, 0, 7, 771, 4749), + (773, 773, -1, 773, 773, 3, 65, 4552, 5, 1800, 7, -1, 774), + (774, 773, -1, 773, 773, 6, 65, 4553, 5, 1800, 7, 773, 775), + (775, 773, -1, 773, 773, 9, 65, 4554, 5, 1800, 7, 774, 5854), + (776, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, -1, 777), + (777, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 776, 778), + (778, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 777, 779), + (779, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 778, 780), + (780, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 779, -1), + (781, -1, -1, 781, 781, 12, 65, -1, 0, 0, 7, -1, 5850), + (782, -1, -1, 782, 782, 3, 65, -1, 0, 0, 7, -1, 783), + (783, -1, -1, 782, 782, 6, 65, -1, 0, 0, 7, 782, 784), + (784, -1, -1, 782, 782, 9, 65, -1, 0, 0, 7, 783, -1), + (785, 785, 785, 785, 785, 5, 65, 5235, 8, 900, 7, -1, 786), + (786, 785, 785, 785, 785, 5, 65, 5236, 8, 900, 7, 785, 787), + (787, 785, 785, 785, 785, 5, 65, 5237, 8, 900, 7, 786, 788), + (788, 785, 785, 785, 785, 5, 65, 5238, 8, 900, 7, 787, 789), + (789, 785, 785, 785, 785, 5, 65, 5239, 8, 900, 7, 788, 15235), + (790, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, -1, 791), + (791, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 790, 792), + (792, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 791, 793), + (793, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 792, 794), + (794, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 793, 5259), + (795, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, -1, 796), + (796, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 795, 797), + (797, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 796, 798), + (798, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 797, 799), + (799, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 798, 1430), + (800, -1, -1, 800, 800, 3, 65, -1, 0, 0, 7, -1, 801), + (801, -1, -1, 800, 800, 6, 65, -1, 0, 0, 7, 800, 802), + (802, -1, -1, 800, 800, 9, 65, -1, 0, 0, 7, 801, -1), + (803, -1, -1, 803, 803, 3, 65, -1, 0, 0, 7, -1, 804), + (804, -1, -1, 803, 803, 6, 65, -1, 0, 0, 7, 803, 805), + (805, -1, -1, 803, 803, 9, 65, -1, 0, 0, 7, 804, -1), + (806, -1, -1, 806, 806, 12, 65, -1, 0, 0, 7, -1, -1), + (807, -1, -1, 807, 807, 3, 65, -1, 0, 0, 7, -1, 808), + (808, -1, -1, 807, 807, 6, 65, -1, 0, 0, 7, 807, 809), + (809, -1, -1, 807, 807, 9, 65, -1, 0, 0, 7, 808, 1268), + (810, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, -1, 811), + (811, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 810, 812), + (812, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 811, 813), + (813, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 812, 814), + (814, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 813, 4824), + (815, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, -1, 816), + (816, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 815, 817), + (817, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 816, 818), + (818, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 817, 819), + (819, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 818, 5141), + (820, -1, -1, 820, 820, 3, 65, -1, 0, 0, 7, -1, 821), + (821, -1, -1, 820, 820, 6, 65, -1, 0, 0, 7, 820, 822), + (822, -1, -1, 820, 820, 9, 65, -1, 0, 0, 7, 821, 1265), + (823, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, -1, 824), + (824, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 823, 825), + (825, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 824, 826), + (826, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 825, 827), + (827, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 826, -1), + (828, 828, 828, 828, 828, 3, 65, 5240, 2, 3600, 7, -1, 829), + (829, 828, 828, 828, 828, 6, 65, 5241, 2, 3600, 7, 828, 830), + (830, 828, 828, 828, 828, 9, 65, 5242, 2, 3600, 7, 829, 16250), + (834, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, -1, 835), + (835, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 834, 836), + (836, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 835, 837), + (837, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 836, 838), + (838, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 837, -1), + (839, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, -1, 840), + (840, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 839, 841), + (841, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 840, 842), + (842, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 841, 843), + (843, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 842, 5325), + (844, -1, -1, 634, 634, 5, 65, -1, 0, 0, 7, 636, 845), + (845, -1, -1, 634, 634, 5, 65, -1, 0, 0, 7, 844, 1319), + (846, -1, -1, 846, 846, 3, 65, -1, 0, 0, 7, -1, 847), + (847, -1, -1, 846, 846, 6, 65, -1, 0, 0, 7, 846, 848), + (848, -1, -1, 846, 846, 9, 65, -1, 0, 0, 7, 847, 1301), + (849, -1, -1, 849, 849, 3, 65, -1, 0, 0, 7, -1, 850), + (850, -1, -1, 849, 849, 6, 65, -1, 0, 0, 7, 849, 851), + (851, -1, -1, 849, 849, 9, 65, -1, 0, 0, 7, 850, 10621), + (852, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, -1, 853), + (853, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, 852, 854), + (854, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, 853, 5500), + (855, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, -1, 856), + (856, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 855, 857), + (857, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 856, 858), + (858, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 857, 859), + (859, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 858, 7673), + (860, 860, 860, 860, 860, 3, 65, 3297, 5, 180, 7, -1, 861), + (861, 860, 860, 860, 860, 6, 65, 3298, 5, 180, 7, 860, 862), + (862, 860, 860, 860, 860, 9, 65, 3299, 5, 180, 7, 861, 5130), + (863, 863, -1, 863, 863, 12, 65, 5248, 6, 4320, 7, -1, -1), + (864, -1, -1, 864, 864, 3, 65, -1, 0, 0, 7, -1, 865), + (865, -1, -1, 864, 864, 6, 65, -1, 0, 0, 7, 864, 866), + (866, -1, -1, 864, 864, 9, 65, -1, 0, 0, 7, 865, 1290), + (867, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, -1, 868), + (868, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 867, 869), + (869, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 868, 870), + (870, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 869, 871), + (871, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 870, 7362), + (872, 872, 872, 872, 872, 3, 65, 4802, 5, 180, 7, -1, 873), + (873, 872, 872, 872, 872, 6, 65, 4803, 5, 180, 7, 872, 874), + (874, 872, 872, 872, 872, 9, 65, 4804, 5, 180, 7, 873, 7367), + (875, 875, 875, 875, 875, 3, 65, 4805, 5, 180, 7, -1, 876), + (876, 875, 875, 875, 875, 6, 65, 4806, 5, 180, 7, 875, 877), + (877, 875, 875, 875, 875, 9, 65, 4807, 5, 180, 7, 876, 7370), + (878, -1, -1, 878, 878, 3, 65, -1, 0, 0, 7, -1, 879), + (879, -1, -1, 878, 878, 6, 65, -1, 0, 0, 7, 878, 880), + (880, -1, -1, 878, 878, 9, 65, -1, 0, 0, 7, 879, 1539), + (881, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, -1, 882), + (882, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 881, 883), + (883, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 882, 884), + (884, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 883, 885), + (885, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 884, -1), + (886, -1, -1, 498, 498, 5, 65, -1, 0, 0, 7, 500, 887), + (887, -1, -1, 498, 498, 5, 65, -1, 0, 0, 7, 886, 975), + (888, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, -1, 889), + (889, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 888, 890), + (890, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 889, 891), + (891, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 890, 892), + (892, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 891, 16267), + (893, -1, -1, 589, 589, 5, 65, -1, 0, 0, 7, 591, 894), + (894, -1, -1, 589, 589, 5, 65, -1, 0, 0, 7, 893, 5270), + (895, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, -1, 896), + (896, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 895, 897), + (897, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 896, 898), + (898, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 897, 899), + (899, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 898, 6075), + (900, 528, 528, 528, 528, 5, 65, 4826, 5, 720, 7, 530, 901), + (901, 528, 528, 528, 528, 5, 65, 4827, 5, 720, 7, 900, 6103), + (907, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, -1, 908), + (908, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 907, 909), + (909, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 908, 910), + (910, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 909, 911), + (911, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 910, 5243), + (912, 912, 912, 912, 912, 3, 65, 4925, 4, 3600, 7, -1, 913), + (913, 912, 912, 912, 912, 6, 65, 4926, 4, 3600, 7, 912, 914), + (914, 912, 912, 912, 912, 9, 65, 4927, 4, 3600, 7, 913, 1330), + (915, -1, -1, 915, 915, 3, 65, -1, 0, 0, 7, -1, 916), + (916, -1, -1, 915, 915, 6, 65, -1, 0, 0, 7, 915, 917), + (917, -1, -1, 915, 915, 9, 65, -1, 0, 0, 7, 916, -1), + (918, -1, -1, 918, 918, 3, 65, -1, 0, 0, 7, -1, 919), + (919, -1, -1, 918, 918, 6, 65, -1, 0, 0, 7, 918, 920), + (920, -1, -1, 918, 918, 9, 65, -1, 0, 0, 7, 919, -1), + (921, 921, 921, 921, 921, 12, 65, 4833, 8, 60, 7, -1, 1340), + (922, 922, 922, 922, 922, 12, 65, 4834, 8, 60, 7, -1, 1341), + (923, 923, 923, 923, 923, 12, 65, 4835, 8, 60, 7, -1, 1342), + (924, -1, -1, 267, 267, 5, 65, -1, 0, 0, 7, 642, 925), + (925, -1, -1, 267, 267, 5, 65, -1, 0, 0, 7, 924, 5133), + (926, 926, 926, 926, 926, 3, 65, 4836, 12, 1800, 7, -1, 927), + (927, 926, 926, 926, 926, 3, 65, 4837, 12, 1800, 7, 926, 928), + (928, 926, 926, 926, 926, 3, 65, 4838, 12, 1800, 7, 927, 929), + (929, 926, 926, 926, 926, 3, 65, 4839, 12, 1800, 7, 928, 930), + (930, 926, 926, 926, 926, 3, 65, 4840, 12, 1800, 7, 929, 14991), + (931, 931, 931, 931, 931, 3, 65, 5245, 13, 4320, 7, -1, 932), + (932, 931, 931, 931, 931, 6, 65, 5246, 13, 4320, 7, 931, 933), + (933, 931, 931, 931, 931, 9, 65, 5247, 13, 4320, 7, 932, -1), + (934, -1, -1, 113, 934, 2, 55, -1, 0, 0, 3, -1, 935), + (935, -1, -1, 113, 934, 4, 55, -1, 0, 0, 3, 934, 936), + (936, -1, -1, 113, 934, 6, 55, -1, 0, 0, 3, 935, 943), + (937, -1, -1, 113, 937, 2, 55, -1, 0, 0, 3, -1, 938), + (938, -1, -1, 113, 937, 4, 55, -1, 0, 0, 3, 937, 939), + (939, -1, -1, 113, 937, 6, 55, -1, 0, 0, 3, 938, 946), + (940, -1, -1, 113, 940, 2, 55, -1, 0, 0, 3, -1, 941), + (941, -1, -1, 113, 940, 4, 55, -1, 0, 0, 3, 940, 942), + (942, -1, -1, 113, 940, 6, 55, -1, 0, 0, 3, 941, 949), + (943, -1, -1, 113, 934, 3, 62, -1, 0, 0, 4, 936, 944), + (944, -1, -1, 113, 934, 3, 63, -1, 0, 0, 4, 943, 945), + (945, -1, -1, 113, 934, 3, 64, -1, 0, 0, 4, 944, -1), + (946, -1, -1, 113, 937, 3, 62, -1, 0, 0, 4, 939, 947), + (947, -1, -1, 113, 937, 3, 63, -1, 0, 0, 4, 946, 948), + (948, -1, -1, 113, 937, 3, 64, -1, 0, 0, 4, 947, -1), + (949, -1, -1, 113, 940, 3, 62, -1, 0, 0, 4, 942, 950), + (950, -1, -1, 113, 940, 3, 63, -1, 0, 0, 4, 949, 951), + (951, -1, -1, 113, 940, 3, 64, -1, 0, 0, 4, 950, -1), + (952, -1, -1, 952, 952, 3, 61, -1, 0, 0, 4, -1, 953), + (953, -1, -1, 952, 952, 3, 63, -1, 0, 0, 4, 952, 954), + (954, -1, -1, 952, 952, 3, 65, -1, 0, 0, 4, 953, -1), + (955, -1, -1, 955, 955, 3, 61, -1, 0, 0, 4, -1, 956), + (956, -1, -1, 955, 955, 3, 62, -1, 0, 0, 4, 955, 957), + (957, -1, -1, 955, 955, 3, 63, -1, 0, 0, 4, 956, 958), + (958, -1, -1, 955, 955, 3, 64, -1, 0, 0, 4, 957, 959), + (959, -1, -1, 955, 955, 3, 65, -1, 0, 0, 4, 958, -1), + (960, 960, 960, 960, 960, 9, 59, 2760, 7, 4320, 3, -1, -1), + (961, 961, 961, 961, 961, 9, 59, 2759, 11, 4320, 3, -1, -1), + (962, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, -1, 963), + (963, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 962, 964), + (964, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 963, 965), + (965, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 964, 966), + (966, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 965, 6223), + (967, 967, 967, 967, 967, 3, 65, 4564, 10, 1800, 7, -1, 968), + (968, 967, 967, 967, 967, 6, 65, 4565, 10, 1800, 7, 967, 969), + (969, 967, 967, 967, 967, 9, 65, 4566, 10, 1800, 7, 968, 6464), + (970, 970, 970, 970, 970, 5, 65, 4828, 6, 1800, 7, -1, 971), + (971, 970, 970, 970, 970, 5, 65, 4829, 6, 1800, 7, 970, 972), + (972, 970, 970, 970, 970, 5, 65, 4830, 6, 1800, 7, 971, 973), + (973, 970, 970, 970, 970, 5, 65, 4831, 6, 1800, 7, 972, 974), + (974, 970, 970, 970, 970, 5, 65, 4832, 6, 1800, 7, 973, 1324), + (975, -1, -1, 498, 498, 5, 65, -1, 0, 0, 15, 887, 13262), + (976, -1, -1, 976, 976, 5, 59, -1, 0, 0, 15, -1, -1), + (977, 977, 977, 977, 977, 6, 64, 13835, 72, 600, 15, -1, -1), + (978, -1, -1, 71, 71, 5, 68, -1, 0, 0, 8, 677, -1), + (979, -1, -1, 979, 979, 3, 59, -1, 0, 0, 8, -1, 980), + (980, -1, -1, 979, 979, 6, 59, -1, 0, 0, 8, 979, 981), + (981, -1, -1, 979, 979, 9, 59, -1, 0, 0, 8, 980, -1), + (982, -1, -1, 982, 982, 3, 59, -1, 0, 0, 8, -1, 983), + (983, -1, -1, 982, 982, 6, 59, -1, 0, 0, 8, 982, 984), + (984, -1, -1, 982, 982, 9, 59, -1, 0, 0, 8, 983, -1), + (985, -1, -1, 985, 985, 3, 59, -1, 0, 0, 8, -1, 986), + (986, -1, -1, 985, 985, 6, 59, -1, 0, 0, 8, 985, 987), + (987, -1, -1, 985, 985, 9, 59, -1, 0, 0, 8, 986, -1), + (988, -1, -1, 988, 988, 3, 59, -1, 0, 0, 8, -1, 989), + (989, -1, -1, 988, 988, 6, 59, -1, 0, 0, 8, 988, 990), + (990, -1, -1, 988, 988, 9, 59, -1, 0, 0, 8, 989, -1), + (991, -1, -1, 991, 991, 3, 59, -1, 0, 0, 8, -1, 992), + (992, -1, -1, 991, 991, 6, 59, -1, 0, 0, 8, 991, 993), + (993, -1, -1, 991, 991, 9, 59, -1, 0, 0, 8, 992, -1), + (994, -1, -1, 994, 994, 3, 59, -1, 0, 0, 8, -1, 995), + (995, -1, -1, 994, 994, 6, 59, -1, 0, 0, 8, 994, 996), + (996, -1, -1, 994, 994, 9, 59, -1, 0, 0, 8, 995, -1), + (997, -1, -1, 997, 997, 5, 60, -1, 0, 0, 8, -1, 998), + (998, -1, -1, 997, 997, 5, 65, -1, 0, 0, 8, 997, 999), + (999, -1, -1, 997, 997, 5, 70, -1, 0, 0, 8, 998, 1113), + (1000, 1000, -1, 1000, 1000, 0, 5, 5824, 20, 1080, 0, -1, -1), + (1001, -1, -1, 418, 418, 5, 66, -1, 0, 0, 8, 422, 1002), + (1002, -1, -1, 418, 418, 5, 67, -1, 0, 0, 8, 1001, 1003), + (1003, -1, -1, 418, 418, 5, 68, -1, 0, 0, 8, 1002, 1004), + (1004, -1, -1, 418, 418, 5, 69, -1, 0, 0, 8, 1003, 1005), + (1005, -1, -1, 418, 418, 5, 70, -1, 0, 0, 8, 1004, 4678), + (1006, -1, -1, 1006, 1006, 5, 66, -1, 0, 0, 8, -1, 1007), + (1007, -1, -1, 1006, 1006, 5, 67, -1, 0, 0, 8, 1006, 1008), + (1008, -1, -1, 1006, 1006, 5, 68, -1, 0, 0, 8, 1007, 1009), + (1009, -1, -1, 1006, 1006, 5, 69, -1, 0, 0, 8, 1008, 1010), + (1010, -1, -1, 1006, 1006, 5, 70, -1, 0, 0, 8, 1009, 7516), + (1011, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, -1, 1012), + (1012, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1011, 1013), + (1013, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1012, 1014), + (1014, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1013, 1015), + (1016, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1015, -1), + (1017, 1017, 1017, 1017, 1017, 6, 59, 16531, 75, 15, 15, -1, 13726), + (1018, 1018, 1018, 1018, 1018, 2, 63, 16455, 69, 1, 15, -1, -1), + (1019, 718, 718, 718, 718, 12, 65, 21746, 7, 4320, 16, 720, 13454), + (1021, -1, -1, 1021, 1021, 5, 51, -1, 0, 0, 8, -1, 1022), + (1022, -1, -1, 1021, 1021, 5, 55, -1, 0, 0, 8, 1021, 1023), + (1023, -1, -1, 1021, 1021, 5, 60, -1, 0, 0, 8, 1022, 1024), + (1024, -1, -1, 1021, 1021, 5, 65, -1, 0, 0, 8, 1023, 1025), + (1025, -1, -1, 1021, 1021, 5, 70, -1, 0, 0, 8, 1024, 6521), + (1026, -1, -1, 1026, 1026, 3, 66, -1, 0, 0, 8, -1, 1027), + (1027, -1, -1, 1026, 1026, 3, 67, -1, 0, 0, 8, 1026, 1028), + (1028, -1, -1, 1026, 1026, 3, 68, -1, 0, 0, 8, 1027, 1029), + (1029, -1, -1, 1026, 1026, 3, 69, -1, 0, 0, 8, 1028, 1030), + (1030, -1, -1, 1026, 1026, 3, 70, -1, 0, 0, 8, 1029, 1389), + (1031, -1, -1, 65, 661, 3, 66, -1, 0, 0, 8, 675, 1032), + (1032, -1, -1, 65, 661, 3, 67, -1, 0, 0, 8, 1031, 1033), + (1033, -1, -1, 65, 661, 3, 68, -1, 0, 0, 8, 1032, 1034), + (1034, -1, -1, 65, 661, 3, 69, -1, 0, 0, 8, 1033, 1035), + (1035, -1, -1, 65, 661, 3, 70, -1, 0, 0, 8, 1034, 4693), + (1036, -1, -1, 683, 683, 5, 66, -1, 0, 0, 8, 685, 1037), + (1037, -1, -1, 683, 683, 5, 68, -1, 0, 0, 8, 1036, 1038), + (1038, -1, -1, 683, 683, 5, 70, -1, 0, 0, 8, 1037, 5301), + (1041, -1, -1, 1041, 1041, 3, 67, -1, 0, 0, 8, -1, 1042), + (1042, -1, -1, 1041, 1041, 6, 68, -1, 0, 0, 8, 1041, 1043), + (1043, -1, -1, 1041, 1041, 9, 69, -1, 0, 0, 8, 1042, 4707), + (1044, -1, -1, 1044, 1044, 3, 67, -1, 0, 0, 8, -1, 1045), + (1045, -1, -1, 1044, 1044, 6, 68, -1, 0, 0, 8, 1044, 1046), + (1046, -1, -1, 1044, 1044, 9, 69, -1, 0, 0, 8, 1045, 4710), + (1047, -1, -1, 1047, 1047, 3, 67, -1, 0, 0, 8, -1, 1048), + (1048, -1, -1, 1047, 1047, 6, 68, -1, 0, 0, 8, 1047, 1049), + (1049, -1, -1, 1047, 1047, 9, 69, -1, 0, 0, 8, 1048, 4713), + (1050, -1, -1, 1050, 1050, 3, 67, -1, 0, 0, 8, -1, 1051), + (1051, -1, -1, 1050, 1050, 6, 68, -1, 0, 0, 8, 1050, 1052), + (1052, -1, -1, 1050, 1050, 9, 69, -1, 0, 0, 8, 1051, 4716), + (1053, -1, -1, 119, 119, 3, 66, -1, 0, 0, 8, 442, 1054), + (1054, -1, -1, 119, 119, 3, 68, -1, 0, 0, 8, 1053, 1055), + (1055, -1, -1, 119, 119, 3, 70, -1, 0, 0, 8, 1054, 4722), + (1056, -1, -1, 1056, 1056, 5, 71, -1, 0, 0, 12, -1, 1057), + (1057, -1, -1, 1056, 1056, 5, 72, -1, 0, 0, 12, 1056, 1058), + (1058, -1, -1, 1056, 1056, 5, 73, -1, 0, 0, 12, 1057, 1059), + (1059, -1, -1, 1056, 1056, 5, 74, -1, 0, 0, 12, 1058, 1060), + (1060, -1, -1, 1056, 1056, 5, 75, -1, 0, 0, 12, 1059, 6431), + (1061, -1, -1, 125, 125, 5, 66, -1, 0, 0, 8, 453, 1062), + (1062, -1, -1, 125, 125, 5, 67, -1, 0, 0, 8, 1061, 1063), + (1063, -1, -1, 125, 125, 5, 68, -1, 0, 0, 8, 1062, 1064), + (1064, -1, -1, 125, 125, 5, 69, -1, 0, 0, 8, 1063, 1065), + (1065, -1, -1, 125, 125, 5, 70, -1, 0, 0, 8, 1064, 1394), + (1066, -1, -1, 122, 122, 5, 66, -1, 0, 0, 8, 458, 1067), + (1067, -1, -1, 122, 122, 5, 67, -1, 0, 0, 8, 1066, 1068), + (1068, -1, -1, 122, 122, 5, 68, -1, 0, 0, 8, 1067, 1069), + (1069, -1, -1, 122, 122, 5, 69, -1, 0, 0, 8, 1068, 1070), + (1070, -1, -1, 122, 122, 5, 70, -1, 0, 0, 8, 1069, 1399), + (1071, -1, -1, 1071, 1071, 3, 55, -1, 0, 0, 8, -1, 4764), + (1072, -1, -1, 1072, 1072, 5, 66, -1, 0, 0, 8, -1, 1073), + (1073, -1, -1, 1072, 1072, 5, 67, -1, 0, 0, 8, 1072, 1074), + (1074, -1, -1, 1072, 1072, 5, 68, -1, 0, 0, 8, 1073, 1075), + (1075, -1, -1, 1072, 1072, 5, 69, -1, 0, 0, 8, 1074, 1076), + (1076, -1, -1, 1072, 1072, 5, 70, -1, 0, 0, 8, 1075, 4744), + (1083, -1, -1, 77, 77, 3, 66, -1, 0, 0, 8, 436, 1084), + (1084, -1, -1, 77, 77, 6, 68, -1, 0, 0, 8, 1083, 1085), + (1085, -1, -1, 77, 77, 9, 70, -1, 0, 0, 8, 1084, 12449), + (1086, -1, -1, 80, 80, 3, 66, -1, 0, 0, 8, 439, 1087), + (1087, -1, -1, 80, 80, 6, 68, -1, 0, 0, 8, 1086, 1088), + (1088, -1, -1, 80, 80, 9, 70, -1, 0, 0, 8, 1087, 4779), + (1089, -1, -1, 1089, 1089, 3, 59, -1, 0, 0, 8, -1, 1090), + (1090, -1, -1, 1089, 1089, 6, 59, -1, 0, 0, 8, 1089, 1091), + (1091, -1, -1, 1089, 1089, 9, 59, -1, 0, 0, 8, 1090, -1), + (1092, -1, -1, 1092, 1092, 7, 67, -1, 0, 0, 8, -1, -1), + (1093, -1, -1, 1093, 1093, 3, 66, -1, 0, 0, 8, -1, 1094), + (1094, -1, -1, 1093, 1093, 3, 67, -1, 0, 0, 8, 1093, 1095), + (1095, -1, -1, 1093, 1093, 3, 68, -1, 0, 0, 8, 1094, 1096), + (1096, -1, -1, 1093, 1093, 3, 69, -1, 0, 0, 8, 1095, 1097), + (1097, -1, -1, 1093, 1093, 3, 70, -1, 0, 0, 8, 1096, -1), + (1099, -1, -1, 767, 767, 3, 67, -1, 0, 0, 8, 769, 1100), + (1100, -1, -1, 767, 767, 6, 68, -1, 0, 0, 8, 1099, 1101), + (1101, -1, -1, 767, 767, 9, 69, -1, 0, 0, 8, 1100, 12423), + (1102, 592, 592, 592, 592, 3, 66, 5825, 2, 18, 8, 706, 1103), + (1103, 592, 592, 592, 592, 3, 67, 5826, 2, 18, 8, 1102, 1104), + (1104, 592, 592, 592, 592, 3, 68, 5827, 2, 18, 8, 1103, 1105), + (1105, 592, 592, 592, 592, 3, 69, 5828, 2, 18, 8, 1104, 1106), + (1106, 592, 592, 592, 592, 3, 70, 5829, 2, 18, 8, 1105, 4975), + (1107, -1, -1, 1107, 1107, 3, 66, -1, 0, 0, 8, -1, 1108), + (1108, -1, -1, 1107, 1107, 6, 68, -1, 0, 0, 8, 1107, 1109), + (1109, -1, -1, 1107, 1107, 9, 70, -1, 0, 0, 8, 1108, 5286), + (1110, 1110, 1110, 1110, 1110, 3, 68, 5830, 3, 2160, 8, -1, 1111), + (1111, 1110, 1110, 1110, 1110, 6, 69, 5831, 3, 2160, 8, 1110, 1112), + (1112, 1110, 1110, 1110, 1110, 9, 70, 5832, 3, 2160, 8, 1111, 6400), + (1113, -1, -1, 997, 997, 5, 75, -1, 0, 0, 16, 999, 1114), + (1114, -1, -1, 997, 997, 5, 80, -1, 0, 0, 16, 1113, 1115), + (1115, -1, -1, 997, 997, 5, 85, -1, 0, 0, 16, 1114, -1), + (1116, 1116, 1116, 1116, 1116, 3, 68, 5837, 4, 2160, 8, -1, 1117), + (1117, 1116, 1116, 1116, 1116, 6, 69, 5838, 4, 2160, 8, 1116, 1118), + (1118, 1116, 1116, 1116, 1116, 9, 70, 5839, 4, 2160, 8, 1117, 4980), + (1119, 1119, 1119, 1119, 1119, 3, 68, 5841, 8, 900, 8, -1, 1120), + (1120, 1119, 1119, 1119, 1119, 6, 69, 5842, 8, 900, 8, 1119, 1121), + (1121, 1119, 1119, 1119, 1119, 9, 70, 5843, 8, 900, 8, 1120, 4964), + (1122, -1, -1, 1122, 1122, 7, 67, -1, 0, 0, 8, -1, -1), + (1123, 291, 291, 291, 291, 5, 66, 5854, 5, 900, 8, 291, 1124), + (1124, 291, 291, 291, 291, 5, 68, 5855, 5, 900, 8, 1123, 1125), + (1125, 291, 291, 291, 291, 5, 70, 5856, 5, 900, 8, 1124, 4969), + (1126, 1126, 1126, 1126, 1126, 3, 67, 5845, 2, 2160, 8, -1, 1127), + (1127, 1126, 1126, 1126, 1126, 6, 68, 5846, 2, 2160, 8, 1126, 1128), + (1128, 1126, 1126, 1126, 1126, 9, 69, 5847, 2, 2160, 8, 1127, 5513), + (1129, -1, -1, 1129, 1129, 5, 67, -1, 0, 0, 8, -1, 1130), + (1130, -1, -1, 1129, 1129, 3, 69, -1, 0, 0, 8, 1129, -1), + (1131, -1, -1, 1131, 1131, 3, 59, -1, 0, 0, 3, -1, 1132), + (1132, -1, -1, 1131, 1131, 6, 59, -1, 0, 0, 3, 1131, 1133), + (1133, -1, -1, 1131, 1131, 9, 59, -1, 0, 0, 3, 1132, 11082), + (1134, -1, -1, 1134, 1134, 3, 61, -1, 0, 0, 4, -1, 1135), + (1135, -1, -1, 1134, 1134, 4, 63, -1, 0, 0, 4, 1134, 1136), + (1136, -1, -1, 1134, 1134, 5, 65, -1, 0, 0, 4, 1135, 1158), + (1137, -1, -1, 1137, 1137, 3, 59, -1, 0, 0, 3, -1, 1138), + (1138, -1, -1, 1137, 1137, 6, 59, -1, 0, 0, 3, 1137, 1139), + (1139, -1, -1, 1137, 1137, 9, 59, -1, 0, 0, 3, 1138, -1), + (1140, -1, -1, 1140, 1140, 3, 61, -1, 0, 0, 4, -1, 1141), + (1141, -1, -1, 1140, 1140, 3, 63, -1, 0, 0, 4, 1140, 1142), + (1142, -1, -1, 1140, 1140, 3, 65, -1, 0, 0, 4, 1141, -1), + (1146, 1146, 1146, 1146, 1146, 3, 59, 6040, 3, 1500, 3, -1, 1147), + (1147, 1146, 1146, 1146, 1146, 6, 59, 6041, 3, 1200, 3, 1146, 1148), + (1148, 1146, 1146, 1146, 1146, 9, 59, 6042, 3, 900, 3, 1147, -1), + (1149, 1149, -1, 1149, 1149, 12, 65, 5853, 5, 1320, 7, -1, -1), + (1150, 1150, 1150, 1150, 1150, 3, 65, 5848, 2, 2160, 7, -1, 1151), + (1151, 1150, 1150, 1150, 1150, 6, 65, 5849, 2, 2160, 7, 1150, 1152), + (1152, 1150, 1150, 1150, 1150, 9, 65, 5850, 2, 2160, 7, 1151, -1), + (1155, -1, -1, 1155, 1155, 3, 65, -1, 0, 0, 7, -1, 1156), + (1156, -1, -1, 1155, 1155, 6, 65, -1, 0, 0, 7, 1155, 1157), + (1157, -1, -1, 1155, 1155, 9, 65, -1, 0, 0, 7, 1156, -1), + (1158, -1, -1, 1134, 1134, 4, 66, -1, 0, 0, 8, 1136, 1159), + (1159, -1, -1, 1134, 1134, 4, 67, -1, 0, 0, 8, 1158, 1160), + (1160, -1, -1, 1134, 1134, 4, 68, -1, 0, 0, 8, 1159, 1161), + (1161, -1, -1, 1134, 1134, 4, 69, -1, 0, 0, 8, 1160, 1162), + (1162, -1, -1, 1134, 1134, 4, 70, -1, 0, 0, 8, 1161, 4790), + (1163, -1, -1, 255, 255, 5, 67, -1, 0, 0, 8, 544, 1164), + (1164, -1, -1, 255, 255, 5, 68, -1, 0, 0, 8, 1163, 1165), + (1165, -1, -1, 255, 255, 5, 69, -1, 0, 0, 8, 1164, 4795), + (1166, -1, -1, 1143, 1143, 3, 65, -1, 0, 0, 15, -1, 1167), + (1167, -1, -1, 1143, 1143, 6, 65, -1, 0, 0, 15, 1166, 1168), + (1168, -1, -1, 1143, 1143, 9, 65, -1, 0, 0, 15, 1167, 6911), + (1172, -1, -1, 631, 631, 5, 67, -1, 0, 0, 8, 633, 1173), + (1173, -1, -1, 631, 631, 5, 68, -1, 0, 0, 8, 1172, 1174), + (1174, -1, -1, 631, 631, 5, 69, -1, 0, 0, 8, 1173, 4798), + (1178, 1178, 1178, 1178, 1178, 3, 68, 5857, 4, 900, 8, -1, 1179), + (1179, 1178, 1178, 1178, 1178, 6, 69, 5858, 4, 900, 8, 1178, 1180), + (1180, 1178, 1178, 1178, 1178, 9, 70, 5859, 4, 900, 8, 1179, 5779), + (1181, -1, -1, 1181, 1181, 3, 66, -1, 0, 0, 8, -1, 1182), + (1182, -1, -1, 1181, 1181, 3, 67, -1, 0, 0, 8, 1181, 1183), + (1183, -1, -1, 1181, 1181, 3, 68, -1, 0, 0, 8, 1182, 1184), + (1184, -1, -1, 1181, 1181, 3, 69, -1, 0, 0, 8, 1183, 1185), + (1185, -1, -1, 1181, 1181, 3, 70, -1, 0, 0, 8, 1184, -1), + (1186, -1, -1, 1186, 1186, 3, 66, -1, 0, 0, 8, -1, 1187), + (1187, -1, -1, 1186, 1186, 6, 68, -1, 0, 0, 8, 1186, 1188), + (1188, -1, -1, 1186, 1186, 9, 70, -1, 0, 0, 8, 1187, 4776), + (1189, 459, 459, 459, 459, 3, 66, 5860, 8, 180, 8, 461, 1190), + (1190, 459, 459, 459, 459, 6, 68, 5861, 8, 180, 8, 1189, 1191), + (1191, 459, 459, 459, 459, 9, 70, 5862, 8, 180, 8, 1190, 5062), + (1192, 1192, 1192, 1192, 1192, 5, 67, 5863, 12, 1320, 8, -1, 1193), + (1193, 1192, 1192, 1192, 1192, 5, 68, 5864, 12, 1320, 8, 1192, 1194), + (1194, 1192, 1192, 1192, 1192, 5, 69, 5865, 12, 1320, 8, 1193, 5076), + (1195, 1195, 1195, 1195, 1195, 12, 70, 5866, 13, 2160, 8, -1, 5079), + (1196, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, -1, 1197), + (1197, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1196, 1198), + (1198, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1197, 1199), + (1199, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1198, 1200), + (1200, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1199, 10743), + (1203, 131, 131, 131, 131, 5, 67, 5869, 4, 900, 8, 532, 1204), + (1204, 131, 131, 131, 131, 5, 68, 5870, 4, 900, 8, 1203, 1205), + (1205, 131, 131, 131, 131, 5, 69, 5988, 4, 900, 8, 1204, 5070), + (1206, 749, 749, 749, 749, 5, 66, 5871, 11, 1800, 8, 753, 1207), + (1207, 749, 749, 749, 749, 5, 68, 5872, 11, 1800, 8, 1206, 1208), + (1208, 749, 749, 749, 749, 5, 70, 5873, 11, 1800, 8, 1207, 17298), + (1209, 1209, -1, 1209, 1209, 12, 70, 5912, 14, 4320, 8, -1, -1), + (1210, -1, -1, 1210, 1210, 3, 66, -1, 0, 0, 8, -1, 1211), + (1211, -1, -1, 1210, 1210, 6, 68, -1, 0, 0, 8, 1210, 1212), + (1212, -1, -1, 1210, 1210, 9, 70, -1, 0, 0, 8, 1211, 1483), + (1213, -1, -1, 1210, 1213, 3, 66, -1, 0, 0, 8, -1, 1214), + (1214, -1, -1, 1210, 1213, 6, 68, -1, 0, 0, 8, 1213, 1215), + (1215, -1, -1, 1210, 1213, 9, 70, -1, 0, 0, 8, 1214, 4755), + (1216, -1, -1, 83, 83, 3, 81, -1, 0, 0, 16, -1, 1217), + (1217, -1, -1, 83, 83, 6, 81, -1, 0, 0, 16, 1216, 1218), + (1218, -1, -1, 83, 83, 9, 81, -1, 0, 0, 16, 1217, 15422), + (1219, -1, -1, 1435, 1435, 10, 71, -1, 0, 0, 16, -1, 1220), + (1220, -1, -1, 1435, 1435, 11, 71, -1, 0, 0, 16, 1219, 1221), + (1221, -1, -1, 1435, 1435, 12, 71, -1, 0, 0, 16, 1220, 1648), + (1222, 757, -1, 757, 1222, 5, 66, 5877, 6, 1800, 8, 761, 1223), + (1223, 757, -1, 757, 1222, 5, 68, 5878, 6, 1800, 8, 1222, 1224), + (1224, 757, -1, 757, 1222, 5, 70, 5879, 6, 1800, 8, 1223, 5051), + (1225, 548, 548, 548, 548, 5, 67, 5881, 5, 900, 8, 550, 1226), + (1226, 548, 548, 548, 548, 5, 68, 5882, 5, 900, 8, 1225, 1227), + (1227, 548, 548, 548, 548, 5, 69, 5883, 5, 900, 8, 1226, 5054), + (1228, 1228, 1228, 1228, 1228, 9, 70, 5880, 9, 600, 8, -1, -1), + (1229, 1229, 1229, 1229, 1229, 7, 66, 6094, 10, 600, 8, -1, -1), + (1230, -1, -1, 1230, 1230, 1, 51, -1, 0, 0, 8, -1, 1231), + (1231, -1, -1, 1230, 1230, 2, 53, -1, 0, 0, 8, 1230, 1232), + (1232, -1, -1, 1230, 1230, 3, 55, -1, 0, 0, 8, 1231, 5000), + (1233, 1233, -1, 1233, 1233, 3, 68, 5887, 7, 2160, 8, -1, 1234), + (1234, 1233, -1, 1233, 1233, 6, 69, 5888, 7, 2160, 8, 1233, 1235), + (1235, 1233, -1, 1233, 1233, 9, 70, 5889, 7, 2160, 8, 1234, -1), + (1239, 1239, 1239, 1239, 1239, 12, 70, 5903, 6, 600, 8, -1, 5868), + (1242, 1242, 1242, 1242, 1242, 3, 67, 5906, 9, 1320, 8, -1, 1243), + (1243, 1242, 1242, 1242, 1242, 6, 68, 5907, 9, 1320, 8, 1242, 1244), + (1244, 1242, 1242, 1242, 1242, 9, 69, 5908, 9, 1320, 8, 1243, 5857), + (1245, 1245, 1245, 1245, 1245, 3, 66, 5909, 8, 2160, 8, -1, 1246), + (1246, 1245, 1245, 1245, 1245, 6, 68, 5910, 8, 2160, 8, 1245, 1247), + (1247, 1245, 1245, 1245, 1245, 9, 70, 5911, 8, 2160, 8, 1246, 15459), + (1248, 616, 616, 616, 616, 3, 68, 6226, 7, 900, 8, 618, 1249), + (1249, 616, 616, 616, 616, 6, 69, 6227, 7, 900, 8, 1248, 1250), + (1250, 616, 616, 616, 616, 9, 70, 6228, 7, 900, 8, 1249, 6254), + (1251, 1251, 1251, 1251, 1251, 9, 70, 5915, 9, 1320, 8, -1, -1), + (1252, 1252, 1252, 1252, 1252, 9, 68, 5913, 9, 1320, 8, -1, -1), + (1253, 1253, 1253, 1253, 1253, 9, 67, 5916, 16, 1320, 8, -1, -1), + (1254, 1254, 1254, 1254, 1254, 9, 69, 5914, 16, 1320, 8, -1, -1), + (1255, 1255, 1255, 1255, 1255, 9, 70, 5918, 4, 1080, 8, -1, -1), + (1265, -1, -1, 820, 820, 5, 66, -1, 0, 0, 8, 822, 1266), + (1266, -1, -1, 820, 820, 5, 68, -1, 0, 0, 8, 1265, 1267), + (1267, -1, -1, 820, 820, 5, 70, -1, 0, 0, 8, 1266, 4813), + (1268, -1, -1, 807, 807, 5, 66, -1, 0, 0, 8, 809, 1269), + (1269, -1, -1, 807, 807, 5, 68, -1, 0, 0, 8, 1268, 1270), + (1270, -1, -1, 807, 807, 5, 70, -1, 0, 0, 8, 1269, 5922), + (1272, 209, 209, 209, 1272, 5, 66, 5919, 12, 5, 8, -1, 6378), + (1274, 1274, 1274, 1274, 1274, 3, 68, 5921, 9, 540, 8, -1, 1275), + (1275, 1274, 1274, 1274, 1274, 6, 69, 5922, 9, 540, 8, 1274, 1276), + (1276, 1274, 1274, 1274, 1274, 9, 70, 5923, 9, 540, 8, 1275, 4864), + (1277, 188, 188, 188, 188, 9, 68, 5924, 2, 30, 8, 188, 5044), + (1278, 534, 534, 534, 534, 5, 67, 5927, 4, 2160, 8, 717, 1279), + (1279, 534, 534, 534, 534, 5, 68, 5928, 4, 2160, 8, 1278, 1280), + (1280, 534, 534, 534, 534, 5, 69, 5929, 4, 2160, 8, 1279, 5041), + (1284, -1, -1, 1284, 1284, 3, 66, -1, 0, 0, 8, -1, 1285), + (1285, -1, -1, 1284, 1284, 6, 68, -1, 0, 0, 8, 1284, 1286), + (1286, -1, -1, 1284, 1284, 9, 70, -1, 0, 0, 8, 1285, 5035), + (1287, -1, -1, 1287, 1287, 3, 67, -1, 0, 0, 8, -1, 1288), + (1288, -1, -1, 1287, 1287, 6, 68, -1, 0, 0, 8, 1287, 1289), + (1289, -1, -1, 1287, 1287, 9, 69, -1, 0, 0, 8, 1288, 5516), + (1290, -1, -1, 864, 864, 3, 66, -1, 0, 0, 8, 866, 1291), + (1291, -1, -1, 864, 864, 6, 68, -1, 0, 0, 8, 1290, 1292), + (1292, -1, -1, 864, 864, 9, 70, -1, 0, 0, 8, 1291, 4983), + (1293, 545, 545, 545, 545, 3, 68, 6079, 3, 900, 8, 547, 1294), + (1294, 545, 545, 545, 545, 6, 69, 6080, 3, 900, 8, 1293, 1295), + (1295, 545, 545, 545, 545, 9, 70, 6081, 3, 900, 8, 1294, 4997), + (1296, -1, -1, 1296, 1296, 3, 66, -1, 0, 0, 8, -1, 1297), + (1297, -1, -1, 1296, 1296, 3, 67, -1, 0, 0, 8, 1296, 1298), + (1298, -1, -1, 1296, 1296, 3, 68, -1, 0, 0, 8, 1297, 1299), + (1299, -1, -1, 1296, 1296, 3, 69, -1, 0, 0, 8, 1298, 1300), + (1300, -1, -1, 1296, 1296, 3, 70, -1, 0, 0, 8, 1299, -1), + (1301, -1, -1, 846, 846, 3, 66, -1, 0, 0, 8, 848, 1302), + (1302, -1, -1, 846, 846, 6, 68, -1, 0, 0, 8, 1301, 1303), + (1303, -1, -1, 846, 846, 9, 70, -1, 0, 0, 8, 1302, 4948), + (1304, -1, -1, 1304, 1304, 3, 66, -1, 0, 0, 8, -1, 1305), + (1305, -1, -1, 1304, 1304, 6, 68, -1, 0, 0, 8, 1304, 1306), + (1306, -1, -1, 1304, 1304, 9, 70, -1, 0, 0, 8, 1305, 6029), + (1307, -1, -1, 1307, 1307, 5, 66, -1, 0, 0, 8, -1, 1308), + (1308, -1, -1, 1307, 1307, 5, 67, -1, 0, 0, 8, 1307, 1309), + (1309, -1, -1, 1307, 1307, 5, 68, -1, 0, 0, 8, 1308, 1310), + (1310, -1, -1, 1307, 1307, 5, 69, -1, 0, 0, 8, 1309, 1311), + (1311, -1, -1, 1307, 1307, 5, 70, -1, 0, 0, 8, 1310, 6660), + (1313, -1, -1, 1313, 1313, 3, 68, -1, 0, 0, 8, -1, 1314), + (1314, -1, -1, 1313, 1313, 6, 69, -1, 0, 0, 8, 1313, 1315), + (1315, -1, -1, 1313, 1313, 9, 70, -1, 0, 0, 8, 1314, 5029), + (1316, -1, -1, 210, 210, 5, 67, -1, 0, 0, 8, 212, 1317), + (1317, -1, -1, 210, 210, 5, 68, -1, 0, 0, 8, 1316, 1318), + (1318, -1, -1, 210, 210, 5, 69, -1, 0, 0, 8, 1317, 6072), + (1319, -1, -1, 634, 634, 5, 67, -1, 0, 0, 8, 845, 1320), + (1320, -1, -1, 634, 634, 5, 68, -1, 0, 0, 8, 1319, 1321), + (1321, -1, -1, 634, 634, 5, 69, -1, 0, 0, 8, 1320, 5032), + (1323, 1323, 1323, 1323, 1323, 12, 70, 5932, 7, 2160, 8, -1, -1), + (1324, 970, 970, 970, 970, 5, 66, 6030, 6, 1800, 8, 974, 1325), + (1325, 970, 970, 970, 970, 5, 68, 6031, 6, 1800, 8, 1324, 1326), + (1326, 970, 970, 970, 970, 5, 70, 6032, 6, 1800, 8, 1325, 17311), + (1327, 1327, 1327, 1327, 1327, 5, 67, 5933, 10, 900, 8, -1, 1328), + (1328, 1327, 1327, 1327, 1327, 5, 68, 5934, 10, 900, 8, 1327, 1329), + (1329, 1327, 1327, 1327, 1327, 5, 69, 5935, 10, 900, 8, 1328, 5314), + (1330, 912, 912, 912, 912, 3, 66, 5936, 4, 3600, 8, 914, 1331), + (1331, 912, 912, 912, 912, 6, 68, 5937, 4, 3600, 8, 1330, 1332), + (1332, 912, 912, 912, 912, 9, 70, 5938, 4, 3600, 8, 1331, 7119), + (1334, 1334, 1334, 1334, 1334, 3, 66, 5943, 11, 4320, 8, -1, 1335), + (1335, 1334, 1334, 1334, 1334, 6, 68, 5944, 11, 4320, 8, 1334, 1336), + (1336, 1334, 1334, 1334, 1334, 9, 70, 5945, 11, 4320, 8, 1335, 6152), + (1337, 1337, 1337, 1337, 1337, 5, 67, 5946, 13, 4320, 8, -1, 1338), + (1338, 1337, 1337, 1337, 1337, 5, 68, 5947, 13, 4320, 8, 1337, 1339), + (1339, 1337, 1337, 1337, 1337, 5, 69, 5948, 13, 4320, 8, 1338, 6158), + (1340, 921, 921, 921, 921, 12, 69, 5950, 8, 60, 8, 921, 5280), + (1341, 922, 922, 922, 922, 12, 68, 5951, 8, 60, 8, 922, 5281), + (1342, 923, 923, 923, 923, 12, 67, 5952, 8, 60, 8, 923, 5282), + (1343, 1343, 1343, 1343, 1343, 9, 69, 5953, 9, 300, 8, -1, -1), + (1344, 155, 155, 155, 155, 12, 70, 5949, 8, 60, 8, 533, 5279), + (1345, 1345, 1345, 1345, 1345, 5, 67, 6132, 6, 900, 8, -1, 1346), + (1346, 1345, 1345, 1345, 1345, 5, 68, 6133, 6, 900, 8, 1345, 1347), + (1347, 1345, 1345, 1345, 1345, 5, 69, 6134, 6, 900, 8, 1346, 5003), + (1348, 1348, 1348, 1348, 1348, 3, 68, 6090, 0, 3600, 8, -1, 1349), + (1349, 1348, 1348, 1348, 1348, 6, 69, 6091, 0, 3600, 8, 1348, 1350), + (1350, 1348, 1348, 1348, 1348, 9, 70, 6092, 0, 3600, 8, 1349, 5770), + (1351, 1351, 1351, 1351, 1351, 5, 67, 5939, 5, 30, 8, -1, 6133), + (1352, 1352, 1352, 1352, 1352, 3, 67, 6067, 3, 60, 8, -1, 1353), + (1353, 1352, 1352, 1352, 1352, 6, 68, 6068, 3, 60, 8, 1352, 1354), + (1354, 1352, 1352, 1352, 1352, 9, 69, 6069, 3, 60, 8, 1353, 6313), + (1355, 1355, 1355, 1355, 1355, 3, 68, 6070, 3, 60, 8, -1, 1356), + (1356, 1355, 1355, 1355, 1355, 6, 69, 6071, 3, 60, 8, 1355, 1357), + (1357, 1355, 1355, 1355, 1355, 9, 70, 6072, 3, 60, 8, 1356, 5240), + (1358, 1358, 1358, 1358, 1358, 3, 66, 6073, 3, 60, 8, -1, 1359), + (1359, 1358, 1358, 1358, 1358, 6, 67, 6074, 3, 60, 8, 1358, 1360), + (1360, 1358, 1358, 1358, 1358, 9, 68, 6075, 3, 60, 8, 1359, 6307), + (1361, -1, -1, 1361, 1361, 0, 65, -1, 0, 0, 3, -1, -1), + (1362, -1, -1, 1362, 1362, 0, 65, -1, 0, 0, 3, -1, -1), + (1363, -1, -1, 1363, 1363, 0, 68, -1, 0, 0, 3, -1, -1), + (1364, -1, -1, 1364, 1364, 0, 68, -1, 0, 0, 3, -1, -1), + (1365, -1, -1, 1365, 1365, 0, 68, -1, 0, 0, 3, -1, -1), + (1366, -1, -1, 1366, 1366, 0, 65, -1, 0, 0, 3, -1, -1), + (1367, -1, -1, 1367, 1367, 0, 65, -1, 0, 0, 3, -1, -1), + (1368, -1, -1, 1368, 1368, 0, 68, -1, 0, 0, 3, -1, -1), + (1369, -1, -1, 1369, 1369, 0, 68, -1, 0, 0, 3, -1, -1), + (1370, -1, -1, 1370, 1370, 0, 68, -1, 0, 0, 3, -1, -1), + (1371, 1371, 1371, 1371, 1371, 0, 1, 6880, 23, 72000, 0, -1, -1), + (1372, 1372, 1372, 1372, 1372, 0, 1, 6881, 24, 72000, 0, -1, -1), + (1373, 1373, 1373, 1373, 1373, 0, 1, 6882, 25, 72000, 0, -1, -1), + (1374, 1374, 1374, 1374, 1374, 0, 1, 6883, 26, 590400, 0, -1, -1), + (1375, 1375, 1375, 1375, 1375, 0, 1, 6884, 27, 72000, 0, -1, -1), + (1376, 1376, 1376, 1376, 1376, 0, 1, 6885, 28, 244800, 0, -1, -1), + (1377, 1377, 1377, 1377, 1377, 0, 1, 6886, 29, 14400, 0, -1, -1), + (1378, -1, -1, 1378, 1378, 0, 1, -1, 0, 0, 10, -1, 1379), + (1379, -1, -1, 1379, 1379, 0, 1, -1, 0, 0, 10, 1378, 1380), + (1380, -1, -1, 1380, 1380, 0, 1, -1, 0, 0, 10, 1379, 1381), + (1382, -1, -1, 1382, 1382, 0, 1, -1, 0, 0, 10, 1381, -1), + (1383, 1383, 1383, 1383, 1383, 3, 59, 8048, 6, 300, 3, -1, 1384), + (1384, 1383, 1383, 1383, 1383, 6, 59, 8049, 6, 300, 3, 1383, 1385), + (1385, 1383, 1383, 1383, 1383, 9, 59, 8050, 6, 300, 3, 1384, 1386), + (1386, 1383, 1383, 1383, 1383, 9, 65, 8052, 6, 300, 4, 1385, 1387), + (1387, 1383, 1383, 1383, 1383, 9, 70, 8053, 6, 300, 10, 1386, 5084), + (1388, -1, -1, 1388, 1388, 9, 70, -1, 0, 0, 10, -1, -1), + (1389, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1030, 1390), + (1390, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1389, 1391), + (1391, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1390, 1392), + (1392, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1391, 1393), + (1393, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1392, 4683), + (1394, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1065, 1395), + (1395, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1394, 1396), + (1396, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1395, 1397), + (1397, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1396, 1398), + (1398, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1397, 5519), + (1399, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1070, 1400), + (1400, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1399, 1401), + (1401, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1400, 1402), + (1402, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1401, 1403), + (1403, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1402, 5524), + (1404, 1404, 1404, 1404, 1404, 5, 66, 8054, 15, 2160, 10, -1, 1405), + (1405, 1404, 1404, 1404, 1404, 5, 67, 8055, 15, 2160, 10, 1404, 1406), + (1406, 1404, 1404, 1404, 1404, 5, 68, 8056, 15, 2160, 10, 1405, 1407), + (1407, 1404, 1404, 1404, 1404, 5, 69, 8057, 15, 2160, 10, 1406, 1408), + (1408, 1404, 1404, 1404, 1404, 5, 70, 8058, 15, 2160, 10, 1407, 12880), + (1409, 1409, 1409, 1409, 1409, 5, 66, 8054, 15, 2160, 10, -1, 1410), + (1410, 1409, 1409, 1409, 1409, 5, 67, 8055, 15, 2160, 10, 1409, 1411), + (1411, 1409, 1409, 1409, 1409, 5, 68, 8056, 15, 2160, 10, 1410, 1412), + (1412, 1409, 1409, 1409, 1409, 5, 69, 8057, 15, 2160, 10, 1411, 1413), + (1413, 1409, 1409, 1409, 1409, 5, 70, 8058, 15, 2160, 10, 1412, -1), + (1414, -1, -1, 1414, 1414, 5, 66, -1, 0, 0, 10, -1, 1415), + (1415, -1, -1, 1414, 1414, 5, 67, -1, 0, 0, 10, 1414, 1416), + (1416, -1, -1, 1414, 1414, 5, 68, -1, 0, 0, 10, 1415, 1417), + (1417, -1, -1, 1414, 1414, 5, 69, -1, 0, 0, 10, 1416, 1418), + (1418, -1, -1, 1414, 1414, 5, 70, -1, 0, 0, 10, 1417, 12874), + (1419, 1419, 1419, 1419, 1419, 9, 74, 16441, 52, 300, 15, -1, -1), + (1420, -1, -1, 1420, 1420, 3, 66, -1, 0, 0, 10, -1, 1421), + (1421, -1, -1, 1420, 1420, 3, 67, -1, 0, 0, 10, 1420, 1422), + (1422, -1, -1, 1420, 1420, 3, 68, -1, 0, 0, 10, 1421, 1423), + (1423, -1, -1, 1420, 1420, 3, 69, -1, 0, 0, 10, 1422, 1424), + (1424, -1, -1, 1420, 1420, 3, 70, -1, 0, 0, 10, 1423, -1), + (1425, 1425, 1425, 1425, 1425, 5, 70, 8060, 2, 2160, 10, -1, 1426), + (1426, 1425, 1425, 1425, 1425, 5, 70, 8061, 2, 2160, 10, 1425, 1427), + (1427, 1425, 1425, 1425, 1425, 5, 70, 8063, 2, 2160, 10, 1426, 1428), + (1428, 1425, 1425, 1425, 1425, 5, 70, 8066, 2, 2160, 10, 1427, 1429), + (1429, 1425, 1425, 1425, 1425, 5, 70, 8070, 2, 2160, 10, 1428, 5759), + (1430, -1, -1, 795, 795, 3, 70, -1, 0, 0, 10, 799, 1431), + (1431, -1, -1, 795, 795, 6, 70, -1, 0, 0, 10, 1430, 1432), + (1432, -1, -1, 795, 795, 9, 70, -1, 0, 0, 10, 1431, 4897), + (1435, -1, -1, 1435, 1435, 3, 66, -1, 0, 0, 10, -1, 1436), + (1436, -1, -1, 1435, 1435, 6, 68, -1, 0, 0, 10, 1435, 1437), + (1437, -1, -1, 1435, 1435, 9, 70, -1, 0, 0, 10, 1436, 4773), + (1440, 517, 517, 517, 517, 5, 66, 8109, 12, 600, 10, 519, 1441), + (1441, 517, 517, 517, 517, 5, 67, 8110, 12, 600, 10, 1440, 1442), + (1442, 517, 517, 517, 517, 5, 68, 8111, 12, 600, 10, 1441, 1443), + (1443, 517, 517, 517, 517, 5, 69, 8112, 12, 600, 10, 1442, 1444), + (1444, 517, 517, 517, 517, 5, 70, 8113, 12, 600, 10, 1443, 7296), + (1453, -1, -1, 1453, 1453, 5, 66, -1, 0, 0, 10, -1, 1454), + (1454, -1, -1, 1453, 1453, 5, 67, -1, 0, 0, 10, 1453, 1455), + (1455, -1, -1, 1453, 1453, 5, 68, -1, 0, 0, 10, 1454, 1456), + (1456, -1, -1, 1453, 1453, 5, 69, -1, 0, 0, 10, 1455, 1457), + (1457, -1, -1, 1453, 1453, 5, 70, -1, 0, 0, 10, 1456, -1), + (1458, 1458, 1458, 1458, 1458, 12, 70, 8124, 6, 4320, 10, -1, -1), + (1459, 1459, 1459, 1459, 1459, 7, 70, 8125, 11, 1800, 10, -1, 1460), + (1460, 1459, 1459, 1459, 1459, 7, 70, 8126, 11, 1800, 10, 1459, 1461), + (1461, 1459, 1459, 1459, 1459, 7, 70, 8127, 11, 1800, 10, 1460, 5080), + (1462, 1462, 1462, 1462, 1462, 3, 59, 8133, 5, 300, 3, -1, 1463), + (1463, 1462, 1462, 1462, 1462, 6, 59, 8134, 5, 300, 3, 1462, 1464), + (1464, 1462, 1462, 1462, 1462, 9, 59, 8135, 5, 300, 3, 1463, 1465), + (1465, 1462, 1462, 1462, 1462, 9, 65, 8137, 5, 300, 4, 1464, 1466), + (1466, 1462, 1462, 1462, 1462, 9, 70, 8138, 5, 300, 10, 1465, 4900), + (1467, -1, -1, 729, 729, 3, 70, -1, 0, 0, 10, 733, 1468), + (1468, -1, -1, 729, 729, 6, 70, -1, 0, 0, 10, 1467, 1469), + (1469, -1, -1, 729, 729, 9, 70, -1, 0, 0, 10, 1468, 4960), + (1471, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, -1, 1472), + (1472, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1471, 1473), + (1473, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1472, 1474), + (1474, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1473, 1475), + (1475, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1474, 6442), + (1477, 1477, 1477, 1477, 1477, 9, 70, 8149, 3, 4320, 10, -1, -1), + (1478, 1478, -1, 1478, 1478, 3, 66, 8406, 0, 1, 10, -1, 1479), + (1479, 1478, -1, 1478, 1478, 6, 68, 8407, 0, 1, 10, 1478, 1480), + (1480, 1478, -1, 1478, 1478, 9, 70, 8408, 0, 1, 10, 1479, 6161), + (1483, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1212, 1484), + (1484, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1483, 1485), + (1485, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1484, 4752), + (1486, -1, -1, 1486, 1486, 5, 66, -1, 0, 0, 10, -1, 1487), + (1487, -1, -1, 1486, 1486, 5, 67, -1, 0, 0, 10, 1486, 1488), + (1488, -1, -1, 1486, 1486, 5, 68, -1, 0, 0, 10, 1487, 1489), + (1489, -1, -1, 1486, 1486, 5, 69, -1, 0, 0, 10, 1488, 1490), + (1490, -1, -1, 1486, 1486, 5, 70, -1, 0, 0, 10, 1489, 5529), + (1491, 746, 746, 746, 746, 3, 70, 8156, 10, 2160, 10, 748, 1492), + (1492, 746, 746, 746, 746, 6, 70, 8157, 10, 2160, 10, 1491, 1493), + (1493, 746, 746, 746, 746, 9, 70, 8158, 10, 2160, 10, 1492, 5800), + (1494, 1494, 1494, 1494, 1494, 12, 70, 8170, 2, 7, 10, -1, -1), + (1495, 1495, 1495, 1495, 1495, 3, 70, 8190, 30, 900, 10, -1, 1496), + (1496, 1495, 1495, 1495, 1495, 6, 70, 8191, 30, 900, 10, 1495, 1497), + (1497, 1495, 1495, 1495, 1495, 9, 70, 8192, 30, 900, 10, 1496, 5311), + (1498, 1498, 1498, 1498, 1498, 3, 70, 8193, 12, 1320, 10, -1, 1499), + (1499, 1498, 1498, 1498, 1498, 6, 70, 8194, 12, 1320, 10, 1498, 1500), + (1500, 1498, 1498, 1498, 1498, 9, 70, 8195, 12, 1320, 10, 1499, 5058), + (1501, 1501, 1501, 1501, 1501, 3, 70, 8196, 10, 4320, 10, -1, 1502), + (1502, 1501, 1501, 1501, 1501, 6, 70, 8197, 10, 4320, 10, 1501, 1503), + (1503, 1501, 1501, 1501, 1501, 9, 70, 8198, 10, 4320, 10, 1502, 1558), + (1504, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, -1, 1505), + (1505, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, 1504, 1506), + (1506, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, 1505, 5880), + (1507, 520, 520, 520, 520, 3, 70, 8201, 6, 540, 10, 522, 1508), + (1508, 520, 520, 520, 520, 6, 70, 8202, 6, 540, 10, 1507, 1509), + (1509, 520, 520, 520, 520, 9, 70, 8203, 6, 540, 10, 1508, 5883), + (1510, 1510, -1, 1510, 1510, 12, 70, 8205, 13, 2160, 10, -1, 7202), + (1511, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, -1, 1512), + (1512, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, 1511, 1513), + (1513, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, 1512, 5950), + (1514, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, -1, 1515), + (1515, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, 1514, 1516), + (1516, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, 1515, 13404), + (1519, 153, 153, 153, 153, 9, 70, 8216, 3, 2160, 10, 153, 5068), + (1520, 1520, 1520, 1520, 1520, 3, 70, 8218, 11, 900, 10, -1, 1521), + (1521, 1520, 1520, 1520, 1520, 6, 70, 8219, 11, 900, 10, 1520, 1522), + (1522, 1520, 1520, 1520, 1520, 9, 70, 8220, 11, 900, 10, 1521, 6449), + (1523, 1523, 1523, 1523, 1523, 12, 70, 8221, 7, 7, 10, -1, -1), + (1524, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 192, 1526), + (1525, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 1526, 5038), + (1526, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 1524, 1525), + (1527, 1527, 1527, 1527, 1527, 12, 70, 8223, 3, 7, 10, -1, -1), + (1528, -1, -1, 1528, 4819, 5, 66, -1, 0, 0, 10, -1, 1529), + (1529, -1, -1, 1528, 4819, 5, 67, -1, 0, 0, 10, 1528, 1530), + (1530, -1, -1, 1528, 4819, 5, 68, -1, 0, 0, 10, 1529, 1531), + (1531, -1, -1, 1528, 4819, 5, 69, -1, 0, 0, 10, 1530, 1532), + (1532, -1, -1, 1528, 4819, 5, 70, -1, 0, 0, 10, 1531, 4819), + (1533, -1, -1, 602, 602, 3, 70, -1, 0, 0, 10, 604, 1534), + (1534, -1, -1, 602, 602, 6, 70, -1, 0, 0, 10, 1533, 1535), + (1535, -1, -1, 602, 602, 9, 70, -1, 0, 0, 10, 1534, 4758), + (1536, -1, -1, 599, 599, 3, 70, -1, 0, 0, 10, 601, 1537), + (1537, -1, -1, 599, 599, 6, 70, -1, 0, 0, 10, 1536, 1538), + (1538, -1, -1, 599, 599, 9, 70, -1, 0, 0, 10, 1537, 5534), + (1539, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 880, 1540), + (1540, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 1539, 1541), + (1541, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 1540, 4957), + (1542, 1542, -1, 1542, 1542, 3, 60, 8240, 0, 1, 10, -1, -1), + (1543, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, -1, 1544), + (1544, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, 1543, 1545), + (1545, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, 1544, 4951), + (1546, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, -1, 1547), + (1547, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, 1546, 1548), + (1548, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, 1547, 4829), + (1549, -1, -1, 1549, 1549, 3, 66, -1, 0, 0, 10, -1, 1550), + (1550, -1, -1, 1549, 1549, 6, 68, -1, 0, 0, 10, 1549, 1551), + (1551, -1, -1, 1549, 1549, 9, 70, -1, 0, 0, 10, 1550, -1), + (1552, -1, -1, 1552, 1552, 3, 66, -1, 0, 0, 10, -1, 1553), + (1553, -1, -1, 1552, 1552, 6, 68, -1, 0, 0, 10, 1552, 1554), + (1554, -1, -1, 1552, 1552, 9, 70, -1, 0, 0, 10, 1553, -1), + (1555, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, -1, 1556), + (1556, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, 1555, 1557), + (1557, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, 1556, 12727), + (1558, 1501, 1501, 1501, 1501, 6, 75, 16444, 10, 4320, 15, 1503, 1559), + (1559, 1501, 1501, 1501, 1501, 6, 80, 16445, 10, 4320, 15, 1558, 1560), + (1560, 1501, 1501, 1501, 1501, 6, 85, 16446, 10, 4320, 15, 1559, 13244), + (1563, -1, -1, 556, 556, 5, 66, -1, 0, 0, 10, 560, 1564), + (1564, -1, -1, 556, 556, 5, 67, -1, 0, 0, 10, 1563, 1565), + (1565, -1, -1, 556, 556, 5, 68, -1, 0, 0, 10, 1564, 1566), + (1566, -1, -1, 556, 556, 5, 69, -1, 0, 0, 10, 1565, 1567), + (1567, -1, -1, 556, 556, 5, 70, -1, 0, 0, 10, 1566, 17004), + (1569, 1569, 1569, 1569, 1569, 3, 70, 8256, 5, 1800, 10, -1, 1570), + (1570, 1569, 1569, 1569, 1569, 6, 70, 8257, 5, 1800, 10, 1569, 1571), + (1571, 1569, 1569, 1569, 1569, 9, 70, 8258, 5, 1800, 10, 1570, 5713), + (1572, -1, -1, 1572, 1572, 5, 66, -1, 0, 0, 10, -1, 1573), + (1573, -1, -1, 1572, 1572, 5, 67, -1, 0, 0, 10, 1572, 1574), + (1574, -1, -1, 1572, 1572, 5, 68, -1, 0, 0, 10, 1573, 1575), + (1575, -1, -1, 1572, 1572, 5, 69, -1, 0, 0, 10, 1574, 1576), + (1576, -1, -1, 1572, 1572, 5, 70, -1, 0, 0, 10, 1575, 10554), + (1577, -1, -1, 1577, 1577, 3, 66, -1, 0, 0, 10, -1, 1578), + (1578, -1, -1, 1577, 1577, 6, 68, -1, 0, 0, 10, 1577, 1579), + (1579, -1, -1, 1577, 1577, 9, 70, -1, 0, 0, 10, 1578, 5886), + (1583, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, -1, 1584), + (1584, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1583, 1585), + (1585, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1584, 1586), + (1586, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1585, 1587), + (1587, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1586, -1), + (1588, -1, -1, 1587, 1587, 3, 66, -1, 0, 0, 10, -1, 1589), + (1589, -1, -1, 1587, 1587, 6, 68, -1, 0, 0, 10, 1588, 1590), + (1590, -1, -1, 1587, 1587, 9, 70, -1, 0, 0, 10, 1589, -1), + (1591, -1, -1, 1586, 1586, 12, 70, -1, 0, 0, 10, -1, -1), + (1592, -1, -1, 1592, 1592, 5, 66, -1, 0, 0, 10, -1, 1593), + (1593, -1, -1, 1592, 1592, 5, 67, -1, 0, 0, 10, 1592, 1594), + (1594, -1, -1, 1592, 1592, 5, 68, -1, 0, 0, 10, 1593, 1595), + (1595, -1, -1, 1592, 1592, 5, 69, -1, 0, 0, 10, 1594, 1596), + (1596, -1, -1, 1592, 1592, 5, 70, -1, 0, 0, 10, 1595, 4725), + (1597, 1597, 1597, 1597, 1597, 9, 70, 8271, 6, 10, 10, -1, 6606), + (1598, 1598, -1, 1598, 1598, 3, 70, 8272, 6, 900, 10, -1, 1599), + (1599, 1598, -1, 1598, 1598, 6, 70, 8273, 6, 900, 10, 1598, 1600), + (1600, 1598, -1, 1598, 1598, 9, 70, 8274, 6, 900, 10, 1599, 4972), + (1601, -1, -1, 644, 644, 5, 61, -1, 0, 0, 10, 644, 1602), + (1602, -1, -1, 644, 644, 5, 63, -1, 0, 0, 10, 1601, 1603), + (1603, -1, -1, 644, 644, 5, 65, -1, 0, 0, 10, 1602, 4986), + (1604, -1, -1, 1604, 1604, 5, 60, -1, 0, 0, 10, -1, 1605), + (1605, -1, -1, 1604, 1604, 5, 61, -1, 0, 0, 10, 1604, 1606), + (1606, -1, -1, 1604, 1604, 5, 62, -1, 0, 0, 10, 1605, 5290), + (1607, 289, 289, 289, 289, 9, 70, 8278, 3, 300, 10, 289, 5742), + (1608, -1, -1, 1608, 1608, 3, 66, -1, 0, 0, 10, -1, 1609), + (1609, -1, -1, 1608, 1608, 6, 68, -1, 0, 0, 10, 1608, 1610), + (1610, -1, -1, 1608, 1608, 9, 70, -1, 0, 0, 10, 1609, 4989), + (1611, -1, -1, 1417, 1417, 3, 66, -1, 0, 0, 10, -1, 1612), + (1612, -1, -1, 1417, 1417, 3, 67, -1, 0, 0, 10, 1611, 1613), + (1613, -1, -1, 1417, 1417, 3, 68, -1, 0, 0, 10, 1612, 1614), + (1614, -1, -1, 1417, 1417, 3, 69, -1, 0, 0, 10, 1613, 1615), + (1615, -1, -1, 1417, 1417, 3, 70, -1, 0, 0, 10, 1614, -1), + (1616, -1, -1, 1616, 1616, 5, 66, -1, 0, 0, 10, -1, 1617), + (1617, -1, -1, 1616, 1616, 5, 67, -1, 0, 0, 10, 1616, 1618), + (1618, -1, -1, 1616, 1616, 5, 68, -1, 0, 0, 10, 1617, 1619), + (1619, -1, -1, 1616, 1616, 5, 69, -1, 0, 0, 10, 1618, 1620), + (1620, -1, -1, 1616, 1616, 5, 70, -1, 0, 0, 10, 1619, 4992), + (1621, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 566, 1622), + (1622, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 1621, 1623), + (1623, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 1622, -1), + (1624, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 563, 1625), + (1625, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 1624, 1626), + (1626, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 1625, -1), + (1627, -1, -1, 1627, 1627, 3, 66, -1, 0, 0, 10, -1, 1628), + (1628, -1, -1, 1627, 1627, 6, 68, -1, 0, 0, 10, 1627, 1629), + (1629, -1, -1, 1627, 1627, 9, 70, -1, 0, 0, 10, 1628, -1), + (1630, 1474, 1474, 1474, 1474, 3, 70, 8146, 14, 300, 10, -1, 1631), + (1631, 1474, 1474, 1474, 1474, 6, 70, 8147, 14, 300, 10, 1630, 1632), + (1632, 1474, 1474, 1474, 1474, 9, 70, 8148, 14, 300, 10, 1631, -1), + (1633, -1, -1, 551, 551, 5, 66, -1, 0, 0, 10, 555, 1634), + (1634, -1, -1, 551, 551, 5, 67, -1, 0, 0, 10, 1633, 1635), + (1635, -1, -1, 551, 551, 5, 68, -1, 0, 0, 10, 1634, 1636), + (1636, -1, -1, 551, 551, 5, 69, -1, 0, 0, 10, 1635, 1637), + (1637, -1, -1, 551, 551, 5, 70, -1, 0, 0, 10, 1636, 6905), + (1638, 1638, 1638, 1638, 1638, 5, 59, 8450, 7, 4320, 3, -1, -1), + (1639, 1639, 1639, 1639, 1639, 9, 65, 8451, 7, 4320, 4, -1, -1), + (1640, 1640, 1640, 1640, 1640, 12, 70, 8452, 7, 4320, 10, -1, -1), + (1641, -1, -1, 1641, 1641, 15, 70, -1, 0, 0, 3, -1, -1), + (1642, -1, -1, 1642, 1642, 15, 70, -1, 0, 0, 3, -1, -1), + (1643, 1643, 1643, 1643, 1643, 0, 59, 8975, 0, 1, 11, -1, -1), + (1644, 1644, 1644, 1644, 1644, 0, 59, 8900, 0, 1, 11, -1, -1), + (1645, 1645, 1645, 1645, 1645, 9, 70, 8977, 0, 1, 3, -1, -1), + (1646, 1646, 1646, 1646, 1646, 9, 70, 8978, 0, 1, 3, -1, -1), + (1647, 1647, 1647, 1647, 1647, 0, 68, 8771, 21, 900, 3, -1, -1), + (1648, -1, -1, 1435, 4773, 9, 71, -1, 0, 0, 16, 1221, 1649), + (1649, -1, -1, 1435, 4773, 9, 76, -1, 0, 0, 16, 1648, 1650), + (1650, -1, -1, 1435, 4773, 9, 81, -1, 0, 0, 16, 1649, 13091), + (1651, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 8214, 1652), + (1652, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1651, 1653), + (1653, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1652, 1654), + (1654, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1653, 1655), + (1655, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1654, 13149), + (1656, -1, -1, 8204, 8204, 4, 85, -1, 0, 0, 16, 8206, 1657), + (1657, -1, -1, 8204, 8204, 4, 85, -1, 0, 0, 16, 1656, -1), + (1659, -1, -1, 8207, 8207, 4, 85, -1, 0, 0, 16, 8209, 1660), + (1660, -1, -1, 8207, 8207, 4, 85, -1, 0, 0, 16, 1659, -1), + (1662, -1, -1, 1662, 1662, 3, 65, -1, 0, 0, 17, -1, 1663), + (1663, -1, -1, 1662, 1662, 3, 66, -1, 0, 0, 17, 1662, 1664), + (1664, -1, -1, 1662, 1662, 3, 67, -1, 0, 0, 17, 1663, 1665), + (1665, -1, -1, 1662, 1662, 3, 68, -1, 0, 0, 17, 1664, 1666), + (1666, -1, -1, 1662, 1662, 3, 69, -1, 0, 0, 17, 1665, -1), + (1667, 1667, 1667, 1667, 1667, 9, 85, 23602, 0, 1, 16, -1, -1), + (2400, -1, -1, 2400, 2400, 9, 81, 0, 0, 0, 17, -1, 2401), + (2401, -1, -1, 2400, 2400, 12, 83, 0, 0, 0, 17, 2400, 2402), + (2402, -1, -1, 2400, 2400, 15, 85, 0, 0, 0, 17, 2401, 15344), + (3676, 3676, 3676, 3676, 3676, 9, 85, 23606, 67, 30, 16, -1, -1), + (4665, 4665, 4665, 4665, 4665, 0, 1, 9177, 19, 4320, 0, -1, -1), + (4666, -1, -1, 4844, 4844, 5, 81, -1, 0, 0, 16, -1, 4667), + (4667, -1, -1, 4844, 4844, 5, 82, -1, 0, 0, 16, 4666, 4668), + (4668, -1, -1, 4844, 4844, 5, 83, -1, 0, 0, 16, 4667, 4669), + (4669, -1, -1, 4844, 4844, 5, 84, -1, 0, 0, 16, 4668, 4670), + (4670, -1, -1, 4844, 4844, 5, 85, -1, 0, 0, 16, 4669, -1), + (4672, -1, -1, 4672, 4672, 3, 59, -1, 0, 0, 8, -1, 4673), + (4673, -1, -1, 4672, 4672, 6, 59, -1, 0, 0, 8, 4672, 4674), + (4674, -1, -1, 4672, 4672, 9, 59, -1, 0, 0, 8, 4673, -1), + (4675, -1, -1, 4675, 4675, 3, 59, -1, 0, 0, 3, -1, 4676), + (4676, -1, -1, 4675, 4675, 6, 59, -1, 0, 0, 3, 4675, 4677), + (4677, -1, -1, 4675, 4675, 9, 59, -1, 0, 0, 3, 4676, -1), + (4678, -1, -1, 418, 418, 5, 71, -1, 0, 0, 12, 1005, 4679), + (4679, -1, -1, 418, 418, 5, 72, -1, 0, 0, 12, 4678, 4680), + (4680, -1, -1, 418, 418, 5, 73, -1, 0, 0, 12, 4679, 4681), + (4681, -1, -1, 418, 418, 5, 74, -1, 0, 0, 12, 4680, 4682), + (4682, -1, -1, 418, 418, 5, 75, -1, 0, 0, 12, 4681, 7547), + (4683, -1, -1, 1026, 1026, 5, 71, -1, 0, 0, 12, 1393, 4684), + (4684, -1, -1, 1026, 1026, 5, 72, -1, 0, 0, 12, 4683, 4685), + (4685, -1, -1, 1026, 1026, 5, 73, -1, 0, 0, 12, 4684, 4686), + (4686, -1, -1, 1026, 1026, 5, 74, -1, 0, 0, 12, 4685, 4687), + (4687, -1, -1, 1026, 1026, 5, 75, -1, 0, 0, 12, 4686, 6523), + (4688, -1, -1, 4688, 4688, 3, 71, -1, 0, 0, 12, -1, 4689), + (4689, -1, -1, 4688, 4688, 3, 72, -1, 0, 0, 12, 4688, 4690), + (4690, -1, -1, 4688, 4688, 3, 73, -1, 0, 0, 12, 4689, 4691), + (4691, -1, -1, 4688, 4688, 3, 74, -1, 0, 0, 12, 4690, 4692), + (4692, -1, -1, 4688, 4688, 3, 75, -1, 0, 0, 12, 4691, -1), + (4693, -1, -1, 65, 661, 3, 71, -1, 0, 0, 12, 1035, 4694), + (4694, -1, -1, 65, 661, 3, 72, -1, 0, 0, 12, 4693, 4695), + (4695, -1, -1, 65, 661, 3, 73, -1, 0, 0, 12, 4694, 4696), + (4696, -1, -1, 65, 661, 3, 74, -1, 0, 0, 12, 4695, 4697), + (4697, -1, -1, 65, 661, 3, 75, -1, 0, 0, 12, 4696, 6390), + (4698, -1, -1, 4698, 4698, 5, 51, -1, 0, 0, 12, -1, 6545), + (4699, -1, -1, 4699, 4699, 5, 51, -1, 0, 0, 12, -1, 6540), + (4700, 1037, 1037, 1037, 1037, 0, 1, 7619, 33, 72000, 0, -1, -1), + (4702, 4702, 4702, 4702, 4702, 3, 71, 9475, 31, 600, 12, -1, -1), + (4704, 4704, 4704, 4704, 4704, 4, 71, 9477, 31, 600, 12, -1, -1), + (4705, 4705, 4705, 4705, 4705, 3, 71, 9478, 31, 600, 12, -1, -1), + (4706, 4706, 4706, 4706, 4706, 3, 71, 9479, 31, 600, 12, -1, -1), + (4707, -1, -1, 1041, 1041, 6, 71, -1, 0, 0, 12, 1043, 4708), + (4708, -1, -1, 1041, 1041, 6, 73, -1, 0, 0, 12, 4707, 4709), + (4709, -1, -1, 1041, 1041, 6, 75, -1, 0, 0, 12, 4708, 5542), + (4710, -1, -1, 1044, 1044, 6, 71, -1, 0, 0, 12, 1046, 4711), + (4711, -1, -1, 1044, 1044, 6, 73, -1, 0, 0, 12, 4710, 4712), + (4712, -1, -1, 1044, 1044, 6, 75, -1, 0, 0, 12, 4711, 5545), + (4713, -1, -1, 1047, 1047, 6, 71, -1, 0, 0, 12, 1049, 4714), + (4714, -1, -1, 1047, 1047, 6, 73, -1, 0, 0, 12, 4713, 4715), + (4715, -1, -1, 1047, 1047, 6, 75, -1, 0, 0, 12, 4714, 5548), + (4716, -1, -1, 1050, 1050, 6, 71, -1, 0, 0, 12, 1052, 4717), + (4717, -1, -1, 1050, 1050, 6, 73, -1, 0, 0, 12, 4716, 4718), + (4718, -1, -1, 1050, 1050, 6, 75, -1, 0, 0, 12, 4717, 5551), + (4722, -1, -1, 119, 119, 3, 71, -1, 0, 0, 12, 1055, 4723), + (4723, -1, -1, 119, 119, 3, 73, -1, 0, 0, 12, 4722, 4724), + (4724, -1, -1, 119, 119, 3, 75, -1, 0, 0, 12, 4723, 5554), + (4725, -1, -1, 1592, 1592, 5, 71, -1, 0, 0, 12, 1596, 4726), + (4726, -1, -1, 1592, 1592, 5, 72, -1, 0, 0, 12, 4725, 4727), + (4727, -1, -1, 1592, 1592, 5, 73, -1, 0, 0, 12, 4726, 4728), + (4728, -1, -1, 1592, 1592, 5, 74, -1, 0, 0, 12, 4727, 4729), + (4729, -1, -1, 1592, 1592, 5, 75, -1, 0, 0, 12, 4728, 5557), + (4733, -1, -1, 625, 625, 3, 71, -1, 0, 0, 12, 627, 4734), + (4734, -1, -1, 625, 625, 3, 73, -1, 0, 0, 12, 4733, 4735), + (4735, -1, -1, 625, 625, 3, 75, -1, 0, 0, 12, 4734, 7641), + (4739, -1, -1, 4739, 4739, 3, 71, -1, 0, 0, 12, -1, 4740), + (4740, -1, -1, 4739, 4739, 6, 73, -1, 0, 0, 12, 4739, 4741), + (4741, -1, -1, 4739, 4739, 9, 75, -1, 0, 0, 12, 4740, 5562), + (4742, 4742, 4742, 4742, 4742, 9, 71, 11024, 12, 600, 12, -1, 5565), + (4744, -1, -1, 1072, 1072, 5, 71, -1, 0, 0, 12, 1076, 4745), + (4745, -1, -1, 1072, 1072, 5, 72, -1, 0, 0, 12, 4744, 4746), + (4746, -1, -1, 1072, 1072, 5, 73, -1, 0, 0, 12, 4745, 4747), + (4747, -1, -1, 1072, 1072, 5, 74, -1, 0, 0, 12, 4746, 4748), + (4748, -1, -1, 1072, 1072, 5, 75, -1, 0, 0, 12, 4747, 5566), + (4749, -1, -1, 637, 637, 6, 71, -1, 0, 0, 12, 772, 4750), + (4750, -1, -1, 637, 637, 6, 73, -1, 0, 0, 12, 4749, 4751), + (4751, -1, -1, 637, 637, 6, 75, -1, 0, 0, 12, 4750, 5571), + (4752, -1, -1, 1210, 1210, 7, 71, -1, 0, 0, 12, 1485, 4753), + (4753, -1, -1, 1210, 1210, 7, 73, -1, 0, 0, 12, 4752, 4754), + (4754, -1, -1, 1210, 1210, 7, 75, -1, 0, 0, 12, 4753, 5574), + (4755, -1, -1, 1210, 1213, 6, 71, -1, 0, 0, 12, 1215, 4756), + (4756, -1, -1, 1210, 1213, 6, 73, -1, 0, 0, 12, 4755, 4757), + (4757, -1, -1, 1210, 1213, 6, 75, -1, 0, 0, 12, 4756, 5577), + (4758, -1, -1, 602, 602, 6, 71, -1, 0, 0, 12, 1535, 4759), + (4759, -1, -1, 602, 602, 6, 73, -1, 0, 0, 12, 4758, 4760), + (4760, -1, -1, 602, 602, 6, 75, -1, 0, 0, 12, 4759, 5580), + (4761, -1, -1, 4761, 4761, 7, 71, -1, 0, 0, 12, -1, 4762), + (4762, -1, -1, 4761, 4761, 7, 73, -1, 0, 0, 12, 4761, 4763), + (4763, -1, -1, 4761, 4761, 7, 75, -1, 0, 0, 12, 4762, 6500), + (4764, -1, -1, 1071, 1071, 6, 75, -1, 0, 0, 14, 1071, 7553), + (4767, -1, -1, 98, 98, 4, 71, -1, 0, 0, 12, 100, 4768), + (4768, -1, -1, 98, 98, 4, 73, -1, 0, 0, 12, 4767, 4769), + (4769, -1, -1, 98, 98, 4, 75, -1, 0, 0, 12, 4768, 5586), + (4773, -1, -1, 1435, 4773, 9, 71, -1, 0, 0, 12, 1437, 6517), + (4776, -1, -1, 1186, 1186, 6, 71, -1, 0, 0, 12, 1188, 4777), + (4777, -1, -1, 1186, 1186, 6, 73, -1, 0, 0, 12, 4776, 4778), + (4778, -1, -1, 1186, 1186, 6, 75, -1, 0, 0, 12, 4777, 5589), + (4779, -1, -1, 80, 80, 6, 71, -1, 0, 0, 12, 1088, 4780), + (4780, -1, -1, 80, 80, 6, 73, -1, 0, 0, 12, 4779, 4781), + (4781, -1, -1, 80, 80, 6, 75, -1, 0, 0, 12, 4780, 5592), + (4790, -1, -1, 1134, 1134, 5, 71, -1, 0, 0, 12, 1162, 4791), + (4791, -1, -1, 1134, 1134, 5, 72, -1, 0, 0, 12, 4790, 4792), + (4792, -1, -1, 1134, 1134, 5, 73, -1, 0, 0, 12, 4791, 4793), + (4793, -1, -1, 1134, 1134, 5, 74, -1, 0, 0, 12, 4792, 4794), + (4794, -1, -1, 1134, 1134, 5, 75, -1, 0, 0, 12, 4793, 4804), + (4795, -1, -1, 255, 255, 5, 71, -1, 0, 0, 12, 1165, 4796), + (4796, -1, -1, 255, 255, 5, 73, -1, 0, 0, 12, 4795, 4797), + (4797, -1, -1, 255, 255, 5, 75, -1, 0, 0, 12, 4796, 5595), + (4798, -1, -1, 631, 631, 5, 71, -1, 0, 0, 12, 1174, 4799), + (4799, -1, -1, 631, 631, 5, 73, -1, 0, 0, 12, 4798, 4800), + (4800, -1, -1, 631, 631, 5, 75, -1, 0, 0, 12, 4799, -1), + (4801, -1, -1, 4801, 4801, 6, 74, -1, 0, 0, 14, -1, 4802), + (4802, -1, -1, 4801, 4801, 6, 76, -1, 0, 0, 14, 4801, 4803), + (4803, -1, -1, 4801, 4801, 6, 78, -1, 0, 0, 14, 4802, 7160), + (4804, -1, -1, 1134, 1134, 5, 76, -1, 0, 0, 15, 4794, 4805), + (4805, -1, -1, 1134, 1134, 5, 77, -1, 0, 0, 15, 4804, 4806), + (4806, -1, -1, 1134, 1134, 5, 78, -1, 0, 0, 15, 4805, 4807), + (4807, -1, -1, 1134, 1134, 5, 79, -1, 0, 0, 15, 4806, 4808), + (4808, -1, -1, 1134, 1134, 5, 80, -1, 0, 0, 15, 4807, 10311), + (4809, -1, -1, 4809, 4809, 5, 81, -1, 0, 0, 15, -1, 4810), + (4810, -1, -1, 4809, 4809, 5, 83, -1, 0, 0, 15, 4809, 4811), + (4811, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 15, 4810, 10316), + (4813, -1, -1, 820, 820, 5, 71, -1, 0, 0, 12, 1267, 4814), + (4814, -1, -1, 820, 820, 5, 73, -1, 0, 0, 12, 4813, 4815), + (4815, -1, -1, 820, 820, 5, 75, -1, 0, 0, 12, 4814, 5917), + (4819, -1, -1, 1528, 4819, 5, 71, -1, 0, 0, 12, 1532, 4820), + (4820, -1, -1, 1528, 4819, 5, 72, -1, 0, 0, 12, 4819, 4821), + (4821, -1, -1, 1528, 4819, 5, 73, -1, 0, 0, 12, 4820, 4822), + (4822, -1, -1, 1528, 4819, 5, 74, -1, 0, 0, 12, 4821, 4823), + (4823, -1, -1, 1528, 4819, 5, 75, -1, 0, 0, 12, 4822, 15188), + (4824, -1, -1, 810, 810, 5, 71, -1, 0, 0, 12, 814, 4825), + (4825, -1, -1, 810, 810, 5, 72, -1, 0, 0, 12, 4824, 4826), + (4826, -1, -1, 810, 810, 5, 73, -1, 0, 0, 12, 4825, 4827), + (4827, -1, -1, 810, 810, 5, 74, -1, 0, 0, 12, 4826, 4828), + (4828, -1, -1, 810, 810, 5, 75, -1, 0, 0, 12, 4827, 15426), + (4829, -1, -1, 1546, 1546, 5, 71, -1, 0, 0, 12, 1548, 4830), + (4830, -1, -1, 1546, 1546, 5, 72, -1, 0, 0, 12, 4829, 4831), + (4831, -1, -1, 1546, 1546, 5, 73, -1, 0, 0, 12, 4830, 6441), + (4836, 4836, 4836, 4836, 4836, 5, 71, 11033, 5, 30, 12, -1, -1), + (4844, -1, -1, 4844, 4844, 5, 71, -1, 0, 0, 12, -1, 4845), + (4845, -1, -1, 4844, 4844, 5, 72, -1, 0, 0, 12, 4844, 4846), + (4846, -1, -1, 4844, 4844, 5, 73, -1, 0, 0, 12, 4845, 4847), + (4847, -1, -1, 4844, 4844, 5, 74, -1, 0, 0, 12, 4846, 4848), + (4848, -1, -1, 4844, 4844, 5, 75, -1, 0, 0, 12, 4847, 7122), + (4849, 4849, 4849, 4849, 4849, 9, 71, 11041, 7, 1800, 12, -1, 6134), + (4854, 4854, 4854, 4854, 4854, 3, 71, 11046, 8, 600, 12, -1, 4855), + (4855, 4854, 4854, 4854, 4854, 6, 73, 11047, 8, 600, 12, 4854, 4856), + (4856, 4854, 4854, 4854, 4854, 9, 75, 11048, 8, 600, 12, 4855, 5764), + (4857, 4857, 4857, 4857, 4857, 3, 71, 11049, 7, 600, 12, -1, 4858), + (4858, 4857, 4857, 4857, 4857, 6, 73, 11050, 7, 600, 12, 4857, 4859), + (4859, 4857, 4857, 4857, 4857, 9, 75, 11051, 7, 600, 12, 4858, 5767), + (4860, 4860, 4860, 4860, 4860, 9, 75, 11052, 13, 60, 12, -1, 5606), + (4861, -1, -1, 4861, 4861, 6, 71, -1, 0, 0, 12, -1, 4862), + (4862, -1, -1, 4861, 4861, 6, 73, -1, 0, 0, 12, 4861, 4863), + (4863, -1, -1, 4861, 4861, 6, 75, -1, 0, 0, 12, 4862, 5954), + (4864, 1274, 1274, 1274, 1274, 6, 73, 11053, 9, 540, 12, 1276, 4865), + (4865, 1274, 1274, 1274, 1274, 6, 74, 11054, 9, 540, 12, 4864, 4866), + (4866, 1274, 1274, 1274, 1274, 6, 75, 11055, 9, 540, 12, 4865, 5947), + (4887, -1, -1, 4887, 4887, 6, 71, -1, 0, 0, 12, -1, 4888), + (4888, -1, -1, 4887, 4887, 6, 73, -1, 0, 0, 12, 4887, 4889), + (4889, -1, -1, 4887, 4887, 6, 75, -1, 0, 0, 12, 4888, -1), + (4890, 4890, -1, 4890, 4890, 9, 75, 11056, 3, 8640, 12, -1, 5869), + (4894, 4894, 4894, 4894, 4894, 6, 73, 11057, 7, 2160, 12, -1, 4895), + (4895, 4894, 4894, 4894, 4894, 6, 74, 11058, 7, 2160, 12, 4894, 4896), + (4896, 4894, 4894, 4894, 4894, 6, 75, 11059, 7, 2160, 12, 4895, 6352), + (4897, -1, -1, 795, 795, 6, 71, -1, 0, 0, 12, 1432, 4898), + (4898, -1, -1, 795, 795, 6, 73, -1, 0, 0, 12, 4897, 4899), + (4899, -1, -1, 795, 795, 6, 75, -1, 0, 0, 12, 4898, 5889), + (4900, 1462, 1462, 1462, 1462, 6, 71, 11061, 5, 300, 12, 1466, 4901), + (4901, 1462, 1462, 1462, 1462, 6, 73, 11062, 5, 300, 12, 4900, 4902), + (4902, 1462, 1462, 1462, 1462, 6, 75, 11063, 5, 300, 12, 4901, 14739), + (4903, 4903, 4903, 4903, 4903, 9, 71, 11064, 9, 1320, 12, -1, 5892), + (4906, 4906, 4906, 4906, 4906, 9, 71, 11065, 9, 1320, 12, -1, 5893), + (4909, 4909, 4909, 4909, 4909, 9, 71, 11066, 16, 1320, 12, -1, 5894), + (4912, 4912, 4912, 4912, 4912, 9, 71, 11067, 16, 1320, 12, -1, 5895), + (4915, 4915, 4915, 4915, 4915, 9, 71, 11068, 7, 4320, 12, -1, 4916), + (4916, 4915, 4915, 4915, 4915, 9, 73, 11069, 7, 4320, 12, 4915, 4917), + (4917, 4915, 4915, 4915, 4915, 9, 75, 11070, 7, 4320, 12, 4916, 5607), + (4921, -1, -1, 480, 480, 2, 71, -1, 0, 0, 12, 482, 4922), + (4922, -1, -1, 480, 480, 2, 73, -1, 0, 0, 12, 4921, 4923), + (4923, -1, -1, 480, 480, 2, 75, -1, 0, 0, 12, 4922, -1), + (4924, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, -1, 4925), + (4925, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, 4924, 4926), + (4926, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, 4925, 5944), + (4927, 4927, 4927, 4927, 4927, 9, 71, 11076, 14, 600, 12, -1, 7209), + (4931, 4931, 4931, 4931, 4931, 6, 71, 11083, 4, 600, 12, -1, 4932), + (4932, 4931, 4931, 4931, 4931, 6, 73, 11084, 4, 600, 12, 4931, 4933), + (4933, 4931, 4931, 4931, 4931, 6, 75, 11085, 4, 600, 12, 4932, 6054), + (4934, 4934, 4934, 4934, 4934, 7, 71, 11086, 13, 300, 12, -1, 7295), + (4935, 4935, 4935, 4935, 4935, 7, 71, 11087, 14, 300, 12, -1, 7294), + (4938, 4938, 4938, 4938, 4938, 9, 75, 11092, 35, 1800, 12, -1, 5610), + (4943, 4943, 4943, 4943, 4943, 7, 75, 11098, 17, 1800, 12, -1, -1), + (4944, 4944, -1, 4944, 4944, 3, 71, 11103, 0, 1, 12, -1, 4945), + (4945, 4944, -1, 4944, 4944, 6, 73, 11104, 0, 1, 12, 4944, 4946), + (4946, 4944, -1, 4944, 4944, 9, 75, 11105, 0, 1, 12, 4945, 6155), + (4948, -1, -1, 846, 846, 3, 71, -1, 0, 0, 12, 1303, 4949), + (4949, -1, -1, 846, 846, 6, 73, -1, 0, 0, 12, 4948, 4950), + (4950, -1, -1, 846, 846, 9, 75, -1, 0, 0, 12, 4949, 6035), + (4951, -1, -1, 1543, 1543, 5, 71, -1, 0, 0, 12, 1545, 4952), + (4952, -1, -1, 1543, 1543, 5, 73, -1, 0, 0, 12, 4951, 4953), + (4953, -1, -1, 1543, 1543, 5, 75, -1, 0, 0, 12, 4952, 6042), + (4957, -1, -1, 878, 878, 7, 71, -1, 0, 0, 12, 1541, 4958), + (4958, -1, -1, 878, 878, 7, 73, -1, 0, 0, 12, 4957, 4959), + (4959, -1, -1, 878, 878, 7, 75, -1, 0, 0, 12, 4958, 6331), + (4960, -1, -1, 729, 729, 6, 71, -1, 0, 0, 12, 1469, 4961), + (4961, -1, -1, 729, 729, 6, 73, -1, 0, 0, 12, 4960, 4962), + (4962, -1, -1, 729, 729, 6, 75, -1, 0, 0, 12, 4961, 5738), + (4963, 723, 723, 723, 723, 9, 71, 11205, 6, 30, 12, 723, 5737), + (4964, 1119, 1119, 1119, 1119, 6, 73, 11206, 8, 900, 12, 1121, 4965), + (4965, 1119, 1119, 1119, 1119, 6, 74, 11207, 8, 900, 12, 4964, 4966), + (4966, 1119, 1119, 1119, 1119, 6, 75, 11208, 8, 900, 12, 4965, 5734), + (4969, 291, 291, 291, 291, 5, 71, 11212, 5, 900, 12, 1125, 4970), + (4970, 291, 291, 291, 291, 5, 73, 11213, 5, 900, 12, 4969, 4971), + (4971, 291, 291, 291, 291, 5, 75, 11214, 5, 900, 12, 4970, 5743), + (4972, 1598, -1, 1598, 1598, 6, 71, 11215, 6, 900, 12, 1600, 4973), + (4973, 1598, -1, 1598, 1598, 6, 73, 11216, 6, 900, 12, 4972, 4974), + (4974, 1598, -1, 1598, 1598, 6, 75, 11217, 6, 900, 12, 4973, 5710), + (4975, 592, 592, 592, 592, 3, 71, 11218, 2, 18, 12, 1106, 4976), + (4976, 592, 592, 592, 592, 3, 72, 11219, 2, 18, 12, 4975, 4977), + (4977, 592, 592, 592, 592, 3, 73, 11220, 2, 18, 12, 4976, 4978), + (4978, 592, 592, 592, 592, 3, 74, 11221, 2, 18, 12, 4977, 4979), + (4979, 592, 592, 592, 592, 3, 75, 11222, 2, 18, 12, 4978, 5702), + (4980, 1116, 1116, 1116, 1116, 6, 73, 11223, 4, 2160, 12, 1118, 4981), + (4981, 1116, 1116, 1116, 1116, 6, 74, 11224, 4, 2160, 12, 4980, 4982), + (4982, 1116, 1116, 1116, 1116, 6, 75, 11225, 4, 2160, 12, 4981, 5699), + (4983, -1, -1, 864, 864, 6, 71, -1, 0, 0, 12, 1292, 4984), + (4984, -1, -1, 864, 864, 6, 73, -1, 0, 0, 12, 4983, 4985), + (4985, -1, -1, 864, 864, 6, 75, -1, 0, 0, 12, 4984, 6011), + (4986, -1, -1, 644, 644, 5, 67, -1, 0, 0, 12, 1603, 4987), + (4987, -1, -1, 644, 644, 5, 69, -1, 0, 0, 12, 4986, 4988), + (4988, -1, -1, 644, 644, 5, 71, -1, 0, 0, 12, 4987, 6017), + (4989, -1, -1, 1608, 1608, 6, 71, -1, 0, 0, 12, 1610, 4990), + (4990, -1, -1, 1608, 1608, 6, 73, -1, 0, 0, 12, 4989, 4991), + (4991, -1, -1, 1608, 1608, 6, 75, -1, 0, 0, 12, 4990, 7378), + (4992, -1, -1, 1616, 1616, 5, 71, -1, 0, 0, 12, 1620, 4993), + (4993, -1, -1, 1616, 1616, 5, 72, -1, 0, 0, 12, 4992, 4994), + (4994, -1, -1, 1616, 1616, 5, 73, -1, 0, 0, 12, 4993, 4995), + (4995, -1, -1, 1616, 1616, 5, 74, -1, 0, 0, 12, 4994, 4996), + (4996, -1, -1, 1616, 1616, 5, 75, -1, 0, 0, 12, 4995, 6003), + (4997, 545, 545, 545, 545, 6, 73, 11226, 3, 900, 12, 1295, 4998), + (4998, 545, 545, 545, 545, 6, 74, 11227, 3, 900, 12, 4997, 4999), + (4999, 545, 545, 545, 545, 6, 75, 11228, 3, 900, 12, 4998, 6000), + (5000, -1, -1, 1230, 1230, 2, 71, -1, 0, 0, 12, 1232, 5001), + (5001, -1, -1, 1230, 1230, 2, 73, -1, 0, 0, 12, 5000, 5002), + (5002, -1, -1, 1230, 1230, 2, 75, -1, 0, 0, 12, 5001, -1), + (5003, 1345, 1345, 1345, 1345, 5, 73, 11229, 6, 900, 12, 1347, 5004), + (5004, 1345, 1345, 1345, 1345, 5, 74, 11230, 6, 900, 12, 5003, 5005), + (5005, 1345, 1345, 1345, 1345, 5, 75, 11231, 6, 900, 12, 5004, 6008), + (5006, 5006, 5006, 5006, 5006, 0, 0, 27673, 96, 72000, 0, -1, -1), + (5007, 5007, 5007, 5007, 5007, 3, 71, 11233, 8, 2160, 12, -1, 5008), + (5008, 5007, 5007, 5007, 5007, 6, 73, 11234, 8, 2160, 12, 5007, 5009), + (5009, 5007, 5007, 5007, 5007, 9, 75, 11235, 8, 2160, 12, 5008, 6425), + (5010, -1, -1, 1007, 1007, 8, 81, -1, 0, 0, 16, -1, 5011), + (5011, -1, -1, 1007, 1007, 10, 83, -1, 0, 0, 16, 5010, 5012), + (5012, -1, -1, 1007, 1007, 12, 85, -1, 0, 0, 16, 5011, 15317), + (5013, -1, -1, 1284, 1284, 6, 83, -1, 0, 0, 16, 5037, 5014), + (5014, -1, -1, 1284, 1284, 6, 85, -1, 0, 0, 16, 5013, -1), + (5015, 5015, 5015, 5015, 5015, 5, 75, 11241, 9, 900, 12, -1, 5741), + (5017, 5017, 5017, 5017, 5017, 3, 71, 11243, 8, 600, 12, -1, 5018), + (5018, 5017, 5017, 5017, 5017, 6, 73, 11244, 8, 600, 12, 5017, 5019), + (5019, 5017, 5017, 5017, 5017, 9, 75, 11245, 8, 600, 12, 5018, 7454), + (5020, 5020, 5020, 5020, 5020, 9, 75, 11246, 9, 300, 12, -1, 5716), + (5021, 5021, 5021, 5021, 5021, 9, 71, 11341, 7, 60, 12, -1, 10868), + (5022, 5022, 5022, 5022, 5022, 3, 71, 11247, 5, 600, 12, -1, 5023), + (5023, 5022, 5022, 5022, 5022, 6, 73, 23986, 5, 600, 12, 5022, 5024), + (5024, 5022, 5022, 5022, 5022, 9, 75, 23987, 5, 600, 12, 5023, 6038), + (5025, 5025, 5025, 5025, 5025, 3, 71, 11251, 6, 180, 12, -1, 5026), + (5026, 5025, 5025, 5025, 5025, 6, 73, 11252, 6, 180, 12, 5025, 5027), + (5027, 5025, 5025, 5025, 5025, 9, 75, 11253, 6, 180, 12, 5026, -1), + (5028, 5028, -1, 5028, 5028, 9, 75, 11254, 4, 900, 12, -1, 6041), + (5029, -1, -1, 1313, 1313, 6, 71, -1, 0, 0, 8, 1315, 5030), + (5030, -1, -1, 1313, 1313, 6, 73, -1, 0, 0, 8, 5029, 5031), + (5031, -1, -1, 1313, 1313, 6, 75, -1, 0, 0, 8, 5030, 6066), + (5032, -1, -1, 634, 634, 5, 72, -1, 0, 0, 12, 1321, 5033), + (5033, -1, -1, 634, 634, 5, 73, -1, 0, 0, 12, 5032, 5034), + (5034, -1, -1, 634, 634, 5, 74, -1, 0, 0, 12, 5033, 5611), + (5035, -1, -1, 1284, 1284, 6, 71, -1, 0, 0, 12, 1286, 5036), + (5036, -1, -1, 1284, 1284, 6, 73, -1, 0, 0, 12, 5035, 5037), + (5037, -1, -1, 1284, 1284, 6, 75, -1, 0, 0, 12, 5036, 5013), + (5038, -1, -1, 190, 190, 7, 71, -1, 0, 0, 12, 1525, 5039), + (5039, -1, -1, 190, 190, 7, 73, -1, 0, 0, 12, 5038, 5040), + (5040, -1, -1, 190, 190, 7, 75, -1, 0, 0, 12, 5039, 15141), + (5041, 534, 534, 534, 534, 5, 72, 11255, 4, 2160, 12, 1280, 5042), + (5042, 534, 534, 534, 534, 5, 73, 11256, 4, 2160, 12, 5041, 5043), + (5043, 534, 534, 534, 534, 5, 74, 11257, 4, 2160, 12, 5042, 5969), + (5044, 188, 188, 188, 188, 9, 73, 11258, 2, 30, 12, 1277, 7339), + (5045, -1, -1, 1057, 1057, 9, 85, -1, 0, 0, 16, -1, -1), + (5051, 757, -1, 757, 757, 5, 71, 11262, 6, 1800, 12, 1224, 5052), + (5052, 757, -1, 757, 757, 5, 73, 11263, 6, 1800, 12, 5051, 5053), + (5053, 757, -1, 757, 757, 5, 75, 11264, 6, 1800, 12, 5052, 5822), + (5054, 548, 548, 548, 548, 5, 72, 11265, 5, 900, 12, 1227, 5055), + (5055, 548, 548, 548, 548, 5, 73, 11266, 5, 900, 12, 5054, 5056), + (5056, 548, 548, 548, 548, 5, 74, 11267, 5, 900, 12, 5055, 5829), + (5058, 1498, 1498, 1498, 1498, 6, 71, 11269, 12, 1320, 12, 1500, 5059), + (5059, 1498, 1498, 1498, 1498, 6, 73, 11270, 12, 1320, 12, 5058, 5060), + (5060, 1498, 1498, 1498, 1498, 6, 75, 11271, 12, 1320, 12, 5059, 5819), + (5061, -1, -1, 567, 567, 5, 72, -1, 0, 0, 12, 567, 5825), + (5062, 459, 459, 459, 459, 6, 71, 11272, 8, 180, 12, 1191, 5063), + (5063, 459, 459, 459, 459, 6, 73, 11273, 8, 180, 12, 5062, 5064), + (5064, 459, 459, 459, 459, 6, 75, 11274, 8, 180, 12, 5063, -1), + (5068, 153, 153, 153, 153, 9, 75, 11279, 3, 2160, 12, 1519, 6101), + (5069, 146, 146, 146, 146, 5, 72, 11281, 2, 180, 12, 146, 6102), + (5070, 131, 131, 131, 131, 5, 72, 11282, 4, 900, 12, 1205, 5071), + (5071, 131, 131, 131, 131, 5, 73, 11283, 4, 900, 12, 5070, 5072), + (5072, 131, 131, 131, 131, 5, 74, 11284, 4, 900, 12, 5071, 5791), + (5076, 1192, 1192, 1192, 1192, 5, 72, 11288, 12, 1320, 12, 1194, 5077), + (5077, 1192, 1192, 1192, 1192, 5, 73, 11289, 12, 1320, 12, 5076, 5078), + (5078, 1192, 1192, 1192, 1192, 5, 74, 11290, 12, 1320, 12, 5077, 5794), + (5079, 1195, 1195, 1195, 1195, 9, 75, 11291, 13, 2160, 12, 1195, 5790), + (5080, 1459, 1459, 1459, 1459, 5, 71, 11293, 11, 1800, 12, 1461, 5081), + (5081, 1459, 1459, 1459, 1459, 5, 73, 11294, 11, 1800, 12, 5080, 5082), + (5082, 1459, 1459, 1459, 1459, 5, 75, 11295, 11, 1800, 12, 5081, 5803), + (5084, 1383, 1383, 1383, 1383, 12, 75, 11296, 6, 300, 12, 1387, 5789), + (5085, -1, -1, 5085, 5085, 3, 71, -1, 0, 0, 12, -1, 5086), + (5086, -1, -1, 5085, 5085, 6, 73, -1, 0, 0, 12, 5085, 5087), + (5087, -1, -1, 5085, 5085, 9, 75, -1, 0, 0, 12, 5086, 6406), + (5095, 5095, 5095, 5095, 5095, 3, 71, 11307, 10, 900, 12, -1, 5096), + (5096, 5095, 5095, 5095, 5095, 6, 73, 11308, 10, 900, 12, 5095, 5097), + (5097, 5095, 5095, 5095, 5095, 9, 75, 11309, 10, 900, 12, 5096, 5975), + (5098, 5098, 5098, 5098, 5098, 9, 75, 11310, 2, 30, 12, -1, -1), + (5105, 5105, 5105, 5105, 5105, 9, 75, 11317, 11, 600, 12, -1, 5832), + (5109, 5109, 5109, 5109, 5109, 9, 75, 11321, 0, 1, 12, -1, 6448), + (5118, -1, -1, 5083, 5083, 3, 71, -1, 0, 0, 12, -1, 5119), + (5119, -1, -1, 5083, 5083, 3, 73, -1, 0, 0, 12, 5118, 5120), + (5120, -1, -1, 5083, 5083, 3, 75, -1, 0, 0, 12, 5119, 5797), + (5127, -1, -1, 5127, 5127, 3, 71, -1, 0, 0, 12, -1, 5128), + (5128, -1, -1, 5127, 5127, 3, 73, -1, 0, 0, 12, 5127, 5129), + (5129, -1, -1, 5127, 5127, 3, 75, -1, 0, 0, 12, 5128, -1), + (5130, 860, 860, 860, 860, 6, 71, 5860, 5, 180, 12, 862, 5131), + (5131, 860, 860, 860, 860, 6, 73, 5861, 5, 180, 12, 5130, 5132), + (5132, 860, 860, 860, 860, 6, 75, 5862, 5, 180, 12, 5131, -1), + (5133, -1, -1, 267, 267, 6, 71, -1, 0, 0, 12, 925, 5134), + (5134, -1, -1, 267, 267, 6, 73, -1, 0, 0, 12, 5133, 5135), + (5135, -1, -1, 267, 267, 6, 75, -1, 0, 0, 12, 5134, 5617), + (5136, -1, -1, 4688, 4688, 3, 71, -1, 0, 0, 12, -1, 5137), + (5137, -1, -1, 4688, 4688, 3, 72, -1, 0, 0, 12, 5136, 5138), + (5138, -1, -1, 4688, 4688, 3, 73, -1, 0, 0, 12, 5137, 5139), + (5139, -1, -1, 4688, 4688, 3, 74, -1, 0, 0, 12, 5138, 5140), + (5140, -1, -1, 4688, 4688, 3, 75, -1, 0, 0, 12, 5139, -1), + (5141, -1, -1, 815, 815, 5, 71, -1, 0, 0, 12, 819, 5142), + (5142, -1, -1, 815, 815, 5, 72, -1, 0, 0, 12, 5141, 5143), + (5143, -1, -1, 815, 815, 5, 73, -1, 0, 0, 12, 5142, 5144), + (5144, -1, -1, 815, 815, 5, 74, -1, 0, 0, 12, 5143, 5145), + (5145, -1, -1, 815, 815, 5, 75, -1, 0, 0, 12, 5144, 5909), + (5150, 5150, 5150, 5150, 5150, 0, 1, 11112, 22, 300, 3, -1, 5151), + (5165, 5165, 5165, 5165, 5165, 0, 1, 11127, 22, 300, 3, -1, 5166), + (5180, 5180, 5180, 5180, 5180, 0, 1, 11142, 22, 300, 3, -1, 5181), + (5195, 5195, 5195, 5195, 5195, 0, 1, 11157, 22, 300, 3, -1, 5196), + (5210, 5210, 5210, 5210, 5210, 0, 1, 11172, 22, 300, 3, -1, 5211), + (5225, 5225, 5225, 5225, 5225, 0, 1, 11187, 22, 300, 3, -1, 5226), + (5240, 1355, 1355, 1355, 1355, 6, 71, 11611, 3, 60, 12, 1357, 5241), + (5241, 1355, 1355, 1355, 1355, 6, 73, 11612, 3, 60, 12, 5240, 5242), + (5242, 1355, 1355, 1355, 1355, 6, 75, 11613, 3, 60, 12, 5241, 5914), + (5243, -1, -1, 907, 907, 7, 71, -1, 0, 0, 12, 911, 5244), + (5244, -1, -1, 907, 907, 7, 72, -1, 0, 0, 12, 5243, 5245), + (5245, -1, -1, 907, 907, 7, 73, -1, 0, 0, 12, 5244, 5246), + (5246, -1, -1, 907, 907, 7, 74, -1, 0, 0, 12, 5245, 5247), + (5247, -1, -1, 907, 907, 7, 75, -1, 0, 0, 12, 5246, -1), + (5248, -1, -1, 5248, 5248, 3, 71, -1, 0, 0, 12, -1, 5249), + (5249, -1, -1, 5248, 5248, 6, 73, -1, 0, 0, 12, 5248, 5250), + (5250, -1, -1, 5248, 5248, 9, 75, -1, 0, 0, 12, 5249, 6014), + (5251, 5251, 5251, 5251, 5251, 5, 71, 11615, 13, 900, 12, -1, 5252), + (5252, 5251, 5251, 5251, 5251, 5, 73, 11616, 13, 900, 12, 5251, 5253), + (5253, 5251, 5251, 5251, 5251, 5, 75, 11617, 13, 900, 12, 5252, 6092), + (5254, -1, -1, 724, 724, 3, 71, -1, 0, 0, 12, 728, 5255), + (5255, -1, -1, 724, 724, 3, 72, -1, 0, 0, 12, 5254, 5256), + (5256, -1, -1, 724, 724, 3, 73, -1, 0, 0, 12, 5255, 5257), + (5257, -1, -1, 724, 724, 3, 74, -1, 0, 0, 12, 5256, 5258), + (5258, -1, -1, 724, 724, 3, 75, -1, 0, 0, 12, 5257, 5729), + (5259, -1, -1, 790, 790, 3, 71, -1, 0, 0, 12, 794, 5260), + (5260, -1, -1, 790, 790, 3, 72, -1, 0, 0, 12, 5259, 5261), + (5261, -1, -1, 790, 790, 3, 73, -1, 0, 0, 12, 5260, 5262), + (5262, -1, -1, 790, 790, 3, 74, -1, 0, 0, 12, 5261, 5263), + (5263, -1, -1, 790, 790, 3, 75, -1, 0, 0, 12, 5262, 5320), + (5264, -1, -1, 5264, 5264, 3, 71, -1, 0, 0, 12, -1, 5265), + (5265, -1, -1, 5264, 5264, 3, 72, -1, 0, 0, 12, 5264, 5266), + (5266, -1, -1, 5264, 5264, 3, 73, -1, 0, 0, 12, 5265, 5267), + (5267, -1, -1, 5264, 5264, 3, 74, -1, 0, 0, 12, 5266, 5268), + (5268, -1, -1, 5264, 5264, 3, 75, -1, 0, 0, 12, 5267, 5939), + (5269, -1, -1, 5269, 5269, 3, 71, -1, 0, 0, 12, -1, -1), + (5270, -1, -1, 589, 589, 7, 71, -1, 0, 0, 12, 894, 5271), + (5271, -1, -1, 589, 589, 7, 73, -1, 0, 0, 12, 5270, 5272), + (5272, -1, -1, 589, 589, 7, 75, -1, 0, 0, 12, 5271, 6063), + (5276, -1, -1, 5276, 5276, 3, 71, -1, 0, 0, 12, -1, 5277), + (5277, -1, -1, 5276, 5276, 6, 73, -1, 0, 0, 12, 5276, 5278), + (5278, -1, -1, 5276, 5276, 9, 75, -1, 0, 0, 12, 5277, 15238), + (5279, 155, 155, 155, 155, 12, 75, 11624, 8, 60, 12, 1344, 5289), + (5280, 921, 921, 921, 921, 9, 74, 11625, 8, 60, 12, 1340, 6149), + (5281, 922, 922, 922, 922, 9, 73, 11626, 8, 60, 12, 1341, 6150), + (5282, 923, 923, 923, 923, 9, 72, 11627, 8, 60, 12, 1342, 6151), + (5283, -1, -1, 5263, 5263, 3, 71, -1, 0, 0, 12, -1, 5284), + (5284, -1, -1, 5263, 5263, 6, 73, -1, 0, 0, 12, 5283, 5285), + (5285, -1, -1, 5263, 5263, 9, 75, -1, 0, 0, 12, 5284, 5620), + (5286, -1, -1, 1107, 1107, 6, 71, -1, 0, 0, 12, 1109, 5287), + (5287, -1, -1, 1107, 1107, 6, 73, -1, 0, 0, 12, 5286, 5288), + (5288, -1, -1, 1107, 1107, 6, 75, -1, 0, 0, 12, 5287, 6403), + (5289, 155, 155, 155, 155, 12, 77, 13227, 8, 60, 14, 5279, 7238), + (5290, -1, -1, 1604, 1604, 5, 63, -1, 0, 0, 12, 1606, 5291), + (5291, -1, -1, 1604, 1604, 5, 64, -1, 0, 0, 12, 5290, 5292), + (5292, -1, -1, 1604, 1604, 5, 65, -1, 0, 0, 12, 5291, 5293), + (5293, -1, -1, 1604, 1604, 5, 66, -1, 0, 0, 12, 5292, 5294), + (5294, -1, -1, 1604, 1604, 5, 67, -1, 0, 0, 12, 5293, 6032), + (5295, -1, -1, 5295, 5295, 3, 71, -1, 0, 0, 12, -1, 5296), + (5296, -1, -1, 5295, 5295, 6, 73, -1, 0, 0, 12, 5295, 5297), + (5297, -1, -1, 5295, 5295, 9, 75, -1, 0, 0, 12, 5296, 6531), + (5298, 5298, 5298, 5298, 5298, 3, 71, 11630, 32, 1800, 12, -1, 5299), + (5299, 5298, 5298, 5298, 5298, 6, 73, 11631, 32, 1800, 12, 5298, 5300), + (5300, 5298, 5298, 5298, 5298, 9, 75, 11632, 32, 1800, 12, 5299, 5707), + (5301, -1, -1, 683, 683, 5, 71, -1, 0, 0, 12, 1038, 5302), + (5302, -1, -1, 683, 683, 5, 72, -1, 0, 0, 12, 5301, 5303), + (5303, -1, -1, 683, 683, 5, 73, -1, 0, 0, 12, 5302, 5304), + (5304, -1, -1, 683, 683, 5, 74, -1, 0, 0, 12, 5303, 5305), + (5305, -1, -1, 683, 683, 5, 75, -1, 0, 0, 12, 5304, 6080), + (5306, -1, -1, 658, 658, 5, 71, -1, 0, 0, 12, 660, 5307), + (5307, -1, -1, 658, 658, 5, 72, -1, 0, 0, 12, 5306, 5308), + (5308, -1, -1, 658, 658, 5, 73, -1, 0, 0, 12, 5307, 5309), + (5309, -1, -1, 658, 658, 5, 74, -1, 0, 0, 12, 5308, 5310), + (5310, -1, -1, 658, 658, 5, 75, -1, 0, 0, 12, 5309, 5623), + (5311, 1495, 1495, 1495, 1495, 5, 71, 11639, 30, 900, 12, 1497, 5312), + (5312, 1495, 1495, 1495, 1495, 5, 73, 11640, 30, 900, 12, 5311, 5313), + (5313, 1495, 1495, 1495, 1495, 5, 75, 11641, 30, 900, 12, 5312, 5826), + (5314, 1327, 1327, 1327, 1327, 5, 71, 11642, 10, 900, 12, 1329, 5315), + (5315, 1327, 1327, 1327, 1327, 5, 73, 11643, 10, 900, 12, 5314, 5316), + (5316, 1327, 1327, 1327, 1327, 5, 75, 11644, 10, 900, 12, 5315, 6098), + (5317, -1, -1, 98, 738, 4, 71, -1, 0, 0, 12, 740, 5318), + (5318, -1, -1, 98, 738, 4, 73, -1, 0, 0, 12, 5317, 5319), + (5319, -1, -1, 98, 738, 4, 75, -1, 0, 0, 12, 5318, 5628), + (5320, -1, -1, 790, 790, 6, 76, -1, 0, 0, 14, 5263, 5321), + (5321, -1, -1, 790, 790, 6, 77, -1, 0, 0, 14, 5320, 5322), + (5322, -1, -1, 790, 790, 6, 78, -1, 0, 0, 14, 5321, 5323), + (5323, -1, -1, 790, 790, 6, 79, -1, 0, 0, 14, 5322, 5324), + (5324, -1, -1, 790, 790, 6, 80, -1, 0, 0, 14, 5323, 7270), + (5325, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 843, 5326), + (5326, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5325, 5327), + (5327, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5326, 5328), + (5328, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5327, 5329), + (5329, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5328, 7210), + (5330, 1327, 1327, 1327, 1327, 12, 91, 30870, 10, 900, 18, 10189, 5331), + (5333, 1520, 1520, 1520, 1520, 9, 91, 30873, 11, 900, 18, 12999, 5334), + (5336, 12989, 12989, 12989, 12989, 11, 91, 30876, 73, 1800, 18, 12991, 5337), + (5339, -1, -1, 6383, 6383, 11, 91, -1, 0, 0, 18, 12803, 5340), + (5342, 6692, 6692, 6692, 6692, 9, 91, 30879, 42, 600, 18, 6696, 5343), + (5347, -1, -1, 6375, 6375, 12, 91, -1, 0, 0, 18, 10086, 5348), + (5348, -1, -1, 6375, 6375, 15, 93, -1, 0, 0, 18, 5347, 5349), + (5350, 12992, 12992, 12992, 12992, 12, 91, 30884, 0, 1, 18, 12994, 5351), + (5353, 6706, 6706, 6706, 6706, 9, 91, 30887, 44, 600, 18, 10181, 5354), + (5356, 5109, 5109, 5109, 5109, 12, 92, 30890, 0, 1, 18, 13016, 17323), + (5357, 528, 528, 528, 528, 12, 91, 30891, 5, 720, 18, 13163, 5358), + (5360, -1, -1, 9503, 9503, 11, 91, -1, 0, 0, 18, 12794, 5361), + (5363, 5251, 5251, 5251, 5251, 15, 91, 30894, 13, 900, 18, 10199, 5364), + (5366, -1, -1, 5002, 5002, 12, 91, -1, 34, 0, 18, -1, 5367), + (5369, 5001, 5001, 5001, 5001, 12, 91, 30900, 32, 600, 18, -1, 5370), + (5500, -1, -1, 852, 852, 9, 78, -1, 0, 0, 14, 854, 5501), + (5501, -1, -1, 852, 852, 10, 79, -1, 0, 0, 14, 5500, 5502), + (5502, -1, -1, 852, 852, 12, 80, -1, 0, 0, 14, 5501, 7678), + (5513, 1126, 1126, 1126, 1126, 8, 77, 12668, 2, 2160, 14, 1128, 5514), + (5514, 1126, 1126, 1126, 1126, 9, 78, 12669, 2, 2160, 14, 5513, 5515), + (5515, 1126, 1126, 1126, 1126, 10, 79, 12670, 2, 2160, 14, 5514, 13253), + (5516, -1, -1, 1287, 1287, 8, 77, -1, 0, 0, 14, 1289, 5517), + (5517, -1, -1, 1287, 1287, 9, 78, -1, 0, 0, 14, 5516, 5518), + (5518, -1, -1, 1287, 1287, 10, 79, -1, 0, 0, 14, 5517, 12469), + (5519, -1, -1, 125, 125, 6, 76, -1, 0, 0, 14, 1398, 5520), + (5520, -1, -1, 125, 125, 7, 77, -1, 0, 0, 14, 5519, 5521), + (5521, -1, -1, 125, 125, 8, 78, -1, 0, 0, 14, 5520, 5522), + (5522, -1, -1, 125, 125, 9, 79, -1, 0, 0, 14, 5521, 5523), + (5523, -1, -1, 125, 125, 10, 80, -1, 0, 0, 14, 5522, 7501), + (5524, -1, -1, 122, 122, 6, 76, -1, 0, 0, 14, 1403, 5525), + (5525, -1, -1, 122, 122, 7, 77, -1, 0, 0, 14, 5524, 5526), + (5526, -1, -1, 122, 122, 8, 78, -1, 0, 0, 14, 5525, 5527), + (5527, -1, -1, 122, 122, 9, 79, -1, 0, 0, 14, 5526, 5528), + (5528, -1, -1, 122, 122, 10, 80, -1, 0, 0, 14, 5527, 7506), + (5529, -1, -1, 1486, 1486, 7, 76, -1, 0, 0, 14, 1490, 5530), + (5530, -1, -1, 1486, 1486, 8, 77, -1, 0, 0, 14, 5529, 5531), + (5531, -1, -1, 1486, 1486, 9, 78, -1, 0, 0, 14, 5530, 5532), + (5532, -1, -1, 1486, 1486, 10, 79, -1, 0, 0, 14, 5531, 5533), + (5533, -1, -1, 1486, 1486, 12, 80, -1, 0, 0, 14, 5532, 7554), + (5534, -1, -1, 599, 599, 9, 78, -1, 0, 0, 14, 1538, 5535), + (5535, -1, -1, 599, 599, 10, 79, -1, 0, 0, 14, 5534, 5536), + (5536, -1, -1, 599, 599, 12, 80, -1, 0, 0, 14, 5535, 7559), + (5542, -1, -1, 1041, 1041, 7, 76, -1, 0, 0, 14, 4709, 5543), + (5543, -1, -1, 1041, 1041, 9, 78, -1, 0, 0, 14, 5542, 5544), + (5544, -1, -1, 1041, 1041, 12, 80, -1, 0, 0, 14, 5543, 7562), + (5545, -1, -1, 1044, 1044, 7, 76, -1, 0, 0, 14, 4712, 5546), + (5546, -1, -1, 1044, 1044, 9, 78, -1, 0, 0, 14, 5545, 5547), + (5547, -1, -1, 1044, 1044, 12, 80, -1, 0, 0, 14, 5546, 7650), + (5548, -1, -1, 1047, 1047, 7, 76, -1, 0, 0, 14, 4715, 5549), + (5549, -1, -1, 1047, 1047, 9, 78, -1, 0, 0, 14, 5548, 5550), + (5550, -1, -1, 1047, 1047, 12, 80, -1, 0, 0, 14, 5549, 7653), + (5551, -1, -1, 1050, 1050, 7, 76, -1, 0, 0, 14, 4718, 5552), + (5552, -1, -1, 1050, 1050, 9, 78, -1, 0, 0, 14, 5551, 5553), + (5553, -1, -1, 1050, 1050, 12, 80, -1, 0, 0, 14, 5552, 7656), + (5554, -1, -1, 119, 119, 7, 76, -1, 0, 0, 14, 4724, 5555), + (5555, -1, -1, 119, 119, 9, 78, -1, 0, 0, 14, 5554, 5556), + (5556, -1, -1, 119, 119, 12, 80, -1, 0, 0, 14, 5555, 7565), + (5557, -1, -1, 1592, 1592, 7, 76, -1, 0, 0, 14, 4729, 5558), + (5558, -1, -1, 1592, 1592, 8, 77, -1, 0, 0, 14, 5557, 5559), + (5559, -1, -1, 1592, 1592, 9, 78, -1, 0, 0, 14, 5558, 5560), + (5560, -1, -1, 1592, 1592, 10, 79, -1, 0, 0, 14, 5559, 5561), + (5561, -1, -1, 1592, 1592, 12, 80, -1, 0, 0, 14, 5560, 7568), + (5562, -1, -1, 4739, 4739, 7, 76, -1, 0, 0, 14, 4741, 5563), + (5563, -1, -1, 4739, 4739, 9, 78, -1, 0, 0, 14, 5562, 5564), + (5564, -1, -1, 4739, 4739, 12, 80, -1, 0, 0, 14, 5563, 7573), + (5565, 4742, 4742, 4742, 4742, 7, 76, 12671, 12, 600, 14, 4742, -1), + (5566, -1, -1, 1072, 1072, 7, 76, -1, 0, 0, 14, 4748, 5567), + (5567, -1, -1, 1072, 1072, 8, 77, -1, 0, 0, 14, 5566, 5568), + (5568, -1, -1, 1072, 1072, 9, 78, -1, 0, 0, 14, 5567, 5569), + (5569, -1, -1, 1072, 1072, 10, 79, -1, 0, 0, 14, 5568, 5570), + (5570, -1, -1, 1072, 1072, 12, 80, -1, 0, 0, 14, 5569, 7576), + (5571, -1, -1, 637, 637, 7, 76, -1, 0, 0, 14, 4751, 5572), + (5572, -1, -1, 637, 637, 9, 78, -1, 0, 0, 14, 5571, 5573), + (5573, -1, -1, 637, 637, 12, 80, -1, 0, 0, 14, 5572, 12435), + (5574, -1, -1, 1210, 1210, 7, 76, -1, 0, 0, 14, 4754, 5575), + (5575, -1, -1, 1210, 1210, 9, 78, -1, 0, 0, 14, 5574, 5576), + (5576, -1, -1, 1210, 1210, 12, 80, -1, 0, 0, 14, 5575, 7232), + (5577, -1, -1, 1210, 1213, 7, 76, -1, 0, 0, 14, 4757, 5578), + (5578, -1, -1, 1210, 1213, 9, 78, -1, 0, 0, 14, 5577, 5579), + (5579, -1, -1, 1210, 1213, 12, 80, -1, 0, 0, 14, 5578, 7581), + (5580, -1, -1, 602, 602, 7, 76, -1, 0, 0, 14, 4760, 5581), + (5581, -1, -1, 602, 602, 9, 78, -1, 0, 0, 14, 5580, 5582), + (5582, -1, -1, 602, 602, 12, 80, -1, 0, 0, 14, 5581, 10685), + (5586, -1, -1, 98, 98, 7, 76, -1, 0, 0, 14, 4769, 5587), + (5587, -1, -1, 98, 98, 9, 78, -1, 0, 0, 14, 5586, 5588), + (5588, -1, -1, 98, 98, 12, 80, -1, 0, 0, 14, 5587, 7584), + (5589, -1, -1, 1186, 1186, 7, 76, -1, 0, 0, 14, 4778, 5590), + (5590, -1, -1, 1186, 1186, 9, 78, -1, 0, 0, 14, 5589, 5591), + (5591, -1, -1, 1186, 1186, 12, 80, -1, 0, 0, 14, 5590, 7587), + (5592, -1, -1, 80, 80, 7, 76, -1, 0, 0, 14, 4781, 5593), + (5593, -1, -1, 80, 80, 9, 78, -1, 0, 0, 14, 5592, 5594), + (5594, -1, -1, 80, 80, 12, 80, -1, 0, 0, 14, 5593, 7590), + (5595, -1, -1, 255, 255, 7, 76, -1, 0, 0, 14, 4797, 5596), + (5596, -1, -1, 255, 255, 9, 78, -1, 0, 0, 14, 5595, 5597), + (5597, -1, -1, 255, 255, 12, 80, -1, 0, 0, 14, 5596, 7631), + (5606, 4860, 4860, 4860, 4860, 12, 80, 11688, 13, 60, 14, 4860, 7127), + (5607, 4915, 4915, 4915, 4915, 7, 76, 12673, 7, 4320, 14, 4917, 5608), + (5608, 4915, 4915, 4915, 4915, 9, 78, 12674, 7, 4320, 14, 5607, 5609), + (5609, 4915, 4915, 4915, 4915, 12, 80, 12675, 7, 4320, 14, 5608, 7246), + (5610, 4938, 4938, 4938, 4938, 12, 80, 12676, 35, 1800, 14, 4938, 5614), + (5611, -1, -1, 634, 634, 7, 76, -1, 0, 0, 14, 5034, 5612), + (5612, -1, -1, 634, 634, 9, 78, -1, 0, 0, 14, 5611, 5613), + (5613, -1, -1, 634, 634, 12, 80, -1, 0, 0, 14, 5612, 7713), + (5614, 4938, 4938, 4938, 4938, 9, 85, 16852, 35, 1800, 16, 5610, 12875), + (5617, -1, -1, 267, 267, 7, 76, -1, 0, 0, 14, 5135, 5618), + (5618, -1, -1, 267, 267, 9, 78, -1, 0, 0, 14, 5617, 5619), + (5619, -1, -1, 267, 267, 12, 80, -1, 0, 0, 14, 5618, 12860), + (5620, -1, -1, 5263, 5263, 7, 76, -1, 0, 0, 14, 5285, 5621), + (5621, -1, -1, 5263, 5263, 9, 78, -1, 0, 0, 14, 5620, 5622), + (5622, -1, -1, 5263, 5263, 12, 80, -1, 0, 0, 14, 5621, 12466), + (5623, -1, -1, 658, 658, 5, 76, -1, 0, 0, 14, 5310, 5624), + (5624, -1, -1, 658, 658, 5, 77, -1, 0, 0, 14, 5623, 5625), + (5625, -1, -1, 658, 658, 5, 78, -1, 0, 0, 14, 5624, 5626), + (5626, -1, -1, 658, 658, 5, 79, -1, 0, 0, 14, 5625, 5627), + (5627, -1, -1, 658, 658, 5, 80, -1, 0, 0, 14, 5626, 7593), + (5628, -1, -1, 98, 738, 7, 76, -1, 0, 0, 14, 5319, 5629), + (5629, -1, -1, 98, 738, 9, 78, -1, 0, 0, 14, 5628, 5630), + (5630, -1, -1, 98, 738, 12, 80, -1, 0, 0, 14, 5629, 7598), + (5699, 1116, 1116, 1116, 1116, 7, 76, 12500, 4, 2160, 14, 4982, 5700), + (5700, 1116, 1116, 1116, 1116, 9, 78, 12501, 4, 2160, 14, 5699, 5701), + (5701, 1116, 1116, 1116, 1116, 12, 80, 12502, 4, 2160, 14, 5700, 7430), + (5702, 592, 592, 592, 592, 4, 76, 12503, 2, 18, 14, 4979, 5703), + (5703, 592, 592, 592, 592, 4, 77, 12504, 2, 18, 14, 5702, 5704), + (5704, 592, 592, 592, 592, 4, 78, 12505, 2, 18, 14, 5703, 5705), + (5705, 592, 592, 592, 592, 4, 79, 12506, 2, 18, 14, 5704, 5706), + (5706, 592, 592, 592, 592, 4, 80, 12507, 2, 18, 14, 5705, 7433), + (5707, 5298, 5298, 5298, 5298, 9, 78, 12508, 32, 1800, 14, 5300, 5708), + (5708, 5298, 5298, 5298, 5298, 10, 79, 12509, 32, 1800, 14, 5707, 5709), + (5709, 5298, 5298, 5298, 5298, 12, 80, 12510, 32, 1800, 14, 5708, 7438), + (5710, 1598, -1, 1598, 1598, 7, 76, 12511, 6, 900, 14, 4974, 5711), + (5711, 1598, -1, 1598, 1598, 9, 78, 12512, 6, 900, 14, 5710, 5712), + (5712, 1598, -1, 1598, 1598, 12, 80, 12513, 6, 900, 14, 5711, 7441), + (5713, 1569, 1569, 1569, 1569, 7, 76, 12514, 5, 1800, 14, 1571, 5714), + (5714, 1569, 1569, 1569, 1569, 9, 78, 12515, 5, 1800, 14, 5713, 5715), + (5715, 1569, 1569, 1569, 1569, 12, 80, 12516, 5, 1800, 14, 5714, 7457), + (5716, 5020, 5020, 5020, 5020, 9, 77, 12517, 9, 300, 14, 5020, 7444), + (5717, 5717, 5717, 5717, 5717, 10, 76, 12519, 17, 600, 14, -1, -1), + (5729, -1, -1, 724, 724, 7, 76, -1, 0, 0, 14, 5258, 5730), + (5730, -1, -1, 724, 724, 8, 77, -1, 0, 0, 14, 5729, 5731), + (5731, -1, -1, 724, 724, 9, 78, -1, 0, 0, 14, 5730, 5732), + (5732, -1, -1, 724, 724, 10, 79, -1, 0, 0, 14, 5731, 5733), + (5733, -1, -1, 724, 724, 12, 80, -1, 0, 0, 14, 5732, 7489), + (5734, 1119, 1119, 1119, 1119, 7, 78, 12520, 8, 900, 14, 4966, 5735), + (5735, 1119, 1119, 1119, 1119, 8, 79, 12521, 8, 900, 14, 5734, 5736), + (5736, 1119, 1119, 1119, 1119, 9, 80, 12522, 8, 900, 14, 5735, 7479), + (5737, 723, 723, 723, 723, 7, 76, 12523, 6, 30, 14, 4963, 7482), + (5738, -1, -1, 729, 729, 7, 76, -1, 0, 0, 14, 4962, 5739), + (5739, -1, -1, 729, 729, 8, 77, -1, 0, 0, 14, 5738, 5740), + (5740, -1, -1, 729, 729, 9, 78, -1, 0, 0, 14, 5739, 7494), + (5741, 5015, 5015, 5015, 5015, 12, 80, 12524, 9, 900, 14, 5015, 7483), + (5742, 289, 289, 289, 289, 12, 80, 12525, 3, 300, 14, 1607, 7484), + (5743, 291, 291, 291, 291, 9, 78, 12526, 5, 900, 14, 4971, 5744), + (5744, 291, 291, 291, 291, 10, 79, 12527, 5, 900, 14, 5743, 5745), + (5745, 291, 291, 291, 291, 12, 80, 12528, 5, 900, 14, 5744, 7485), + (5759, 1425, 1425, 1425, 1425, 7, 78, 13565, 2, 2160, 14, 1429, 5760), + (5760, 1425, 1425, 1425, 1425, 8, 78, 13570, 2, 2160, 14, 5759, 5761), + (5761, 1425, 1425, 1425, 1425, 9, 79, 13575, 2, 2160, 14, 5760, 5762), + (5762, 1425, 1425, 1425, 1425, 10, 79, 13580, 2, 2160, 14, 5761, 5763), + (5763, 1425, 1425, 1425, 1425, 11, 80, 13585, 2, 2160, 14, 5762, -1), + (5764, 4854, 4854, 4854, 4854, 7, 76, 12534, 8, 600, 14, 4856, 5765), + (5765, 4854, 4854, 4854, 4854, 9, 78, 12535, 8, 600, 14, 5764, 5766), + (5766, 4854, 4854, 4854, 4854, 12, 80, 12536, 8, 600, 14, 5765, 7178), + (5767, 4857, 4857, 4857, 4857, 7, 76, 12537, 7, 600, 14, 4859, 5768), + (5768, 4857, 4857, 4857, 4857, 9, 78, 12538, 7, 600, 14, 5767, 5769), + (5769, 4857, 4857, 4857, 4857, 12, 80, 12539, 7, 600, 14, 5768, 17030), + (5770, 1348, 1348, 1348, 1348, 9, 78, 12540, 0, 3600, 14, 1350, 5771), + (5771, 1348, 1348, 1348, 1348, 10, 79, 12541, 0, 3600, 14, 5770, 5772), + (5772, 1348, 1348, 1348, 1348, 12, 80, 12542, 0, 3600, 14, 5771, 7184), + (5776, -1, -1, 5776, 5776, 7, 76, -1, 0, 0, 14, -1, 5777), + (5777, -1, -1, 5776, 5776, 9, 78, -1, 0, 0, 14, 5776, 5778), + (5778, -1, -1, 5776, 5776, 12, 80, -1, 0, 0, 14, 5777, 7196), + (5779, 1178, 1178, 1178, 1178, 7, 76, 12546, 4, 900, 14, 1180, 5780), + (5780, 1178, 1178, 1178, 1178, 8, 77, 12547, 4, 900, 14, 5779, 5781), + (5781, 1178, 1178, 1178, 1178, 9, 78, 12548, 4, 900, 14, 5780, 7187), + (5789, 1383, 1383, 1383, 1383, 12, 80, 12549, 6, 300, 14, 5084, 7299), + (5790, 1195, 1195, 1195, 1195, 9, 80, 12550, 13, 2160, 14, 5079, 7300), + (5791, 131, 131, 131, 131, 8, 77, 12551, 4, 900, 14, 5072, 5792), + (5792, 131, 131, 131, 131, 9, 78, 12552, 4, 900, 14, 5791, 5793), + (5793, 131, 131, 131, 131, 10, 79, 12553, 4, 900, 14, 5792, 7301), + (5794, 1192, 1192, 1192, 1192, 8, 77, 12554, 12, 1320, 14, 5078, 5795), + (5795, 1192, 1192, 1192, 1192, 9, 78, 12555, 12, 1320, 14, 5794, 5796), + (5796, 1192, 1192, 1192, 1192, 10, 79, 12556, 12, 1320, 14, 5795, 7304), + (5797, -1, -1, 5083, 5083, 7, 76, -1, 0, 0, 14, 5120, 5798), + (5798, -1, -1, 5083, 5083, 9, 78, -1, 0, 0, 14, 5797, 5799), + (5799, -1, -1, 5083, 5083, 12, 80, -1, 0, 0, 14, 5798, -1), + (5800, 746, 746, 746, 746, 9, 78, 12557, 10, 2160, 14, 1493, 5801), + (5801, 746, 746, 746, 746, 10, 79, 12558, 10, 2160, 14, 5800, 5802), + (5802, 746, 746, 746, 746, 12, 80, 12559, 10, 2160, 14, 5801, 7307), + (5803, 1459, 1459, 1459, 1459, 7, 76, 12560, 11, 1800, 14, 5082, 5804), + (5804, 1459, 1459, 1459, 1459, 9, 78, 12561, 11, 1800, 14, 5803, 5805), + (5805, 1459, 1459, 1459, 1459, 12, 80, 12562, 11, 1800, 14, 5804, 7310), + (5806, -1, -1, 255, 255, 7, 59, -1, 0, 0, 16, -1, 5807), + (5807, -1, -1, 255, 255, 9, 59, -1, 0, 0, 16, 5806, 5808), + (5808, -1, -1, 255, 255, 12, 59, -1, 0, 0, 16, 5807, 10623), + (5809, 5833, 5833, 5833, 5833, 9, 85, 20184, 72, 900, 16, -1, -1), + (5819, 1498, 1498, 1498, 1498, 7, 76, 12563, 12, 1320, 14, 5060, 5820), + (5820, 1498, 1498, 1498, 1498, 9, 78, 12564, 12, 1320, 14, 5819, 5821), + (5821, 1498, 1498, 1498, 1498, 12, 80, 12565, 12, 1320, 14, 5820, 7408), + (5822, 757, -1, 757, 757, 7, 76, 12566, 6, 1800, 14, 5053, 5823), + (5823, 757, -1, 757, 757, 9, 78, 12567, 6, 1800, 14, 5822, 5824), + (5824, 757, -1, 757, 757, 12, 80, 12568, 6, 1800, 14, 5823, 7411), + (5825, -1, -1, 567, 567, 7, 76, -1, 0, 0, 14, 5061, -1), + (5826, 1495, 1495, 1495, 1495, 7, 76, 12569, 30, 900, 14, 5313, 5827), + (5827, 1495, 1495, 1495, 1495, 9, 78, 12570, 30, 900, 14, 5826, 5828), + (5828, 1495, 1495, 1495, 1495, 12, 80, 12571, 30, 900, 14, 5827, 7414), + (5829, 548, 548, 548, 548, 8, 77, 12572, 5, 900, 14, 5056, 5830), + (5830, 548, 548, 548, 548, 9, 78, 12573, 5, 900, 14, 5829, 5831), + (5831, 548, 548, 548, 548, 10, 79, 12574, 5, 900, 14, 5830, 7417), + (5832, 5105, 5105, 5105, 5105, 12, 80, 12575, 11, 600, 14, 5105, 7420), + (5849, 54009, 54009, 54009, 54009, 7, 73, 12576, 22, 12, 14, -1, 12923), + (5850, -1, -1, 781, 781, 8, 77, -1, 0, 0, 14, 781, 7284), + (5854, 773, -1, 773, 773, 7, 76, 12580, 5, 1800, 14, 775, 5855), + (5855, 773, -1, 773, 773, 9, 78, 12581, 5, 1800, 14, 5854, 5856), + (5856, 773, -1, 773, 773, 12, 80, 12582, 5, 1800, 14, 5855, 7276), + (5857, 1242, 1242, 1242, 1242, 7, 76, 12577, 9, 1320, 14, 1244, 5858), + (5858, 1242, 1242, 1242, 1242, 9, 78, 12578, 9, 1320, 14, 5857, 5859), + (5859, 1242, 1242, 1242, 1242, 12, 80, 12579, 9, 1320, 14, 5858, 7285), + (5860, -1, -1, 649, 649, 7, 76, -1, 0, 0, 14, 651, 5861), + (5861, -1, -1, 649, 649, 9, 78, -1, 0, 0, 14, 5860, 5862), + (5862, -1, -1, 649, 649, 12, 80, -1, 0, 0, 14, 5861, -1), + (5868, 1239, 1239, 1239, 1239, 12, 80, 13224, 6, 600, 14, 1239, 7275), + (5869, 4890, -1, 4890, 4890, 9, 77, 12587, 3, 8640, 14, 4890, 5871), + (5870, 54010, 54010, 54010, 54010, 7, 73, 12828, 22, 6, 14, -1, -1), + (5871, 4890, -1, 4890, 4890, 9, 79, 16440, 3, 8640, 15, 5869, 5872), + (5872, 4890, -1, 4890, 4890, 9, 81, 21745, 3, 8640, 16, 5871, 14280), + (5879, 167, 167, 167, 167, 10, 79, 12588, 14, 900, 14, 167, 7249), + (5880, -1, -1, 1504, 1504, 5, 76, -1, 0, 0, 14, 1506, 5881), + (5881, -1, -1, 1504, 1504, 5, 78, -1, 0, 0, 14, 5880, 5882), + (5882, -1, -1, 1504, 1504, 5, 80, -1, 0, 0, 14, 5881, 7260), + (5883, 520, 520, 520, 520, 12, 76, 12589, 6, 540, 14, 1509, 5884), + (5884, 520, 520, 520, 520, 12, 78, 12590, 6, 540, 14, 5883, 5885), + (5885, 520, 520, 520, 520, 12, 80, 12591, 6, 540, 14, 5884, 7250), + (5886, -1, -1, 1577, 1577, 7, 76, -1, 0, 0, 14, 1579, 5887), + (5887, -1, -1, 1577, 1577, 9, 78, -1, 0, 0, 14, 5886, 5888), + (5888, -1, -1, 1577, 1577, 12, 80, -1, 0, 0, 14, 5887, 7263), + (5889, -1, -1, 795, 795, 7, 76, -1, 0, 0, 14, 4899, 5890), + (5890, -1, -1, 795, 795, 9, 78, -1, 0, 0, 14, 5889, 5891), + (5891, -1, -1, 795, 795, 12, 80, -1, 0, 0, 14, 5890, 7267), + (5892, 4903, 4903, 4903, 4903, 9, 76, 12592, 9, 1320, 14, 4903, 7253), + (5893, 4906, 4906, 4906, 4906, 9, 76, 12593, 9, 1320, 14, 4906, 7254), + (5894, 4909, 4909, 4909, 4909, 9, 76, 12594, 16, 1320, 14, 4909, 7255), + (5895, 4912, 4912, 4912, 4912, 9, 76, 12595, 16, 1320, 14, 4912, 7256), + (5909, -1, -1, 815, 815, 7, 76, -1, 0, 0, 14, 5145, 5910), + (5910, -1, -1, 815, 815, 8, 77, -1, 0, 0, 14, 5909, 5911), + (5911, -1, -1, 815, 815, 9, 78, -1, 0, 0, 14, 5910, 5912), + (5912, -1, -1, 815, 815, 10, 79, -1, 0, 0, 14, 5911, 5913), + (5913, -1, -1, 815, 815, 12, 80, -1, 0, 0, 14, 5912, 7634), + (5914, 1355, 1355, 1355, 1355, 6, 76, 12596, 3, 60, 14, 5242, 5915), + (5915, 1355, 1355, 1355, 1355, 6, 78, 12597, 3, 60, 14, 5914, 5916), + (5916, 1355, 1355, 1355, 1355, 6, 80, 12598, 3, 60, 14, 5915, 7172), + (5917, -1, -1, 820, 820, 5, 76, -1, 0, 0, 14, 4815, 5918), + (5918, -1, -1, 820, 820, 5, 78, -1, 0, 0, 14, 5917, 5919), + (5919, -1, -1, 820, 820, 5, 80, -1, 0, 0, 14, 5918, 7163), + (5922, -1, -1, 807, 807, 5, 76, -1, 0, 0, 14, 1270, 5923), + (5923, -1, -1, 807, 807, 5, 78, -1, 0, 0, 14, 5922, 5924), + (5924, -1, -1, 807, 807, 5, 80, -1, 0, 0, 14, 5923, 7628), + (5939, -1, -1, 5264, 5264, 7, 76, -1, 0, 0, 14, 5268, 5940), + (5940, -1, -1, 5264, 5264, 8, 77, -1, 0, 0, 14, 5939, 5941), + (5941, -1, -1, 5264, 5264, 9, 78, -1, 0, 0, 14, 5940, 5942), + (5942, -1, -1, 5264, 5264, 10, 79, -1, 0, 0, 14, 5941, 5943), + (5943, -1, -1, 5264, 5264, 12, 80, -1, 0, 0, 14, 5942, 7204), + (5944, -1, -1, 4924, 4924, 9, 78, -1, 0, 0, 14, 4926, 5945), + (5945, -1, -1, 4924, 4924, 10, 79, -1, 0, 0, 14, 5944, 5946), + (5946, -1, -1, 4924, 4924, 12, 80, -1, 0, 0, 14, 5945, -1), + (5947, 1274, 1274, 1274, 1274, 9, 78, 12599, 9, 540, 14, 4866, 5948), + (5948, 1274, 1274, 1274, 1274, 10, 79, 12600, 9, 540, 14, 5947, 5949), + (5949, 1274, 1274, 1274, 1274, 12, 80, 12601, 9, 540, 14, 5948, 7199), + (5950, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 1513, 5951), + (5951, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 5950, 5952), + (5952, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 5951, -1), + (5953, 184, 184, 184, 184, 10, 79, 12602, 5, 4320, 14, 184, 7203), + (5954, -1, -1, 4861, 4861, 7, 76, -1, 0, 0, 14, 4863, 5955), + (5955, -1, -1, 4861, 4861, 9, 78, -1, 0, 0, 14, 5954, 5956), + (5956, -1, -1, 4861, 4861, 12, 80, -1, 0, 0, 14, 5955, 7215), + (5969, 534, 534, 534, 534, 7, 76, 12603, 4, 2160, 14, 5043, 5970), + (5970, 534, 534, 534, 534, 9, 78, 12604, 4, 2160, 14, 5969, 5971), + (5971, 534, 534, 534, 534, 12, 80, 12605, 4, 2160, 14, 5970, 7329), + (5972, -1, -1, 593, 593, 7, 76, -1, 0, 0, 14, 595, -1), + (5973, -1, -1, 596, 596, 7, 76, -1, 0, 0, 14, 598, -1), + (5975, 5095, 5095, 5095, 5095, 7, 76, 12606, 10, 900, 14, 5097, 5976), + (5976, 5095, 5095, 5095, 5095, 9, 78, 12607, 10, 900, 14, 5975, 5977), + (5977, 5095, 5095, 5095, 5095, 12, 80, 12608, 10, 900, 14, 5976, 7332), + (5984, 5984, 5984, 5984, 5984, 12, 80, 12609, 2, 30, 14, -1, 7335), + (5999, 645, -1, 645, 645, 10, 79, 12610, 4, 5, 14, 645, 10739), + (6000, 545, 545, 545, 545, 7, 76, 12611, 3, 900, 14, 4999, 6001), + (6001, 545, 545, 545, 545, 9, 78, 12612, 3, 900, 14, 6000, 6002), + (6002, 545, 545, 545, 545, 12, 80, 12613, 3, 900, 14, 6001, 7344), + (6003, -1, -1, 1616, 1616, 7, 76, -1, 0, 0, 14, 4996, 6004), + (6004, -1, -1, 1616, 1616, 8, 77, -1, 0, 0, 14, 6003, 6005), + (6005, -1, -1, 1616, 1616, 9, 78, -1, 0, 0, 14, 6004, 6006), + (6006, -1, -1, 1616, 1616, 10, 79, -1, 0, 0, 14, 6005, 6007), + (6007, -1, -1, 1616, 1616, 12, 80, -1, 0, 0, 14, 6006, 7637), + (6008, 1345, 1345, 1345, 1345, 8, 77, 12614, 6, 900, 14, 5005, 6009), + (6009, 1345, 1345, 1345, 1345, 9, 78, 12615, 6, 900, 14, 6008, 6010), + (6010, 1345, 1345, 1345, 1345, 10, 79, 12616, 6, 900, 14, 6009, 7347), + (6011, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 4985, 6012), + (6012, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 6011, 6013), + (6013, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 6012, 7353), + (6014, -1, -1, 5248, 5248, 7, 76, -1, 0, 0, 14, 5250, 6015), + (6015, -1, -1, 5248, 5248, 9, 78, -1, 0, 0, 14, 6014, 6016), + (6016, -1, -1, 5248, 5248, 12, 80, -1, 0, 0, 14, 6015, 7356), + (6017, -1, -1, 644, 644, 7, 73, -1, 0, 0, 14, 4988, 6018), + (6018, -1, -1, 644, 644, 9, 75, -1, 0, 0, 14, 6017, 6019), + (6019, -1, -1, 644, 644, 12, 77, -1, 0, 0, 14, 6018, 7359), + (6020, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, -1, 6021), + (6021, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, 6020, 6022), + (6022, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, 6021, 6045), + (6023, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 7567, 6024), + (6024, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 6023, 6025), + (6025, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 6024, 12548), + (6026, -1, -1, 1004, 1004, 7, 81, -1, 0, 0, 16, -1, 6027), + (6027, -1, -1, 1004, 1004, 9, 81, -1, 0, 0, 16, 6026, 6028), + (6028, -1, -1, 1004, 1004, 12, 81, -1, 0, 0, 16, 6027, -1), + (6029, -1, -1, 1304, 1304, 7, 76, -1, 0, 0, 14, 1306, 6030), + (6030, -1, -1, 1304, 1304, 9, 78, -1, 0, 0, 14, 6029, 6031), + (6031, -1, -1, 1304, 1304, 12, 80, -1, 0, 0, 14, 6030, 7148), + (6032, -1, -1, 1604, 1604, 7, 69, -1, 0, 0, 14, 5294, 6033), + (6033, -1, -1, 1604, 1604, 9, 71, -1, 0, 0, 14, 6032, 6034), + (6034, -1, -1, 1604, 1604, 12, 73, -1, 0, 0, 14, 6033, 7131), + (6035, -1, -1, 846, 846, 7, 76, -1, 0, 0, 14, 4950, 6036), + (6036, -1, -1, 846, 846, 9, 78, -1, 0, 0, 14, 6035, 6037), + (6037, -1, -1, 846, 846, 12, 80, -1, 0, 0, 14, 6036, 7151), + (6038, 5022, 5022, 5022, 5022, 7, 76, 23988, 5, 600, 14, 5024, 6039), + (6039, 5022, 5022, 5022, 5022, 9, 78, 23989, 5, 600, 14, 6038, 6040), + (6040, 5022, 5022, 5022, 5022, 12, 80, 23990, 5, 600, 14, 6039, 15628), + (6041, 5028, -1, 5028, 5028, 9, 78, 12621, 4, 900, 14, 5028, -1), + (6042, -1, -1, 1543, 1543, 7, 76, -1, 0, 0, 14, 4953, 6043), + (6043, -1, -1, 1543, 1543, 9, 78, -1, 0, 0, 14, 6042, 6044), + (6044, -1, -1, 1543, 1543, 12, 80, -1, 0, 0, 14, 6043, 7134), + (6045, -1, -1, 6020, 6020, 2, 66, -1, 0, 0, 14, 6022, 6046), + (6046, -1, -1, 6020, 6020, 2, 68, -1, 0, 0, 14, 6045, 6047), + (6047, -1, -1, 6020, 6020, 2, 70, -1, 0, 0, 14, 6046, 6048), + (6048, -1, -1, 6020, 6020, 2, 71, -1, 0, 0, 14, 6047, 6049), + (6049, -1, -1, 6020, 6020, 2, 73, -1, 0, 0, 14, 6048, 6050), + (6050, -1, -1, 6020, 6020, 2, 75, -1, 0, 0, 14, 6049, 6057), + (6051, -1, -1, 6051, 6051, 3, 76, -1, 0, 0, 14, -1, 6052), + (6052, -1, -1, 6051, 6051, 3, 78, -1, 0, 0, 14, 6051, 6053), + (6053, -1, -1, 6051, 6051, 3, 80, -1, 0, 0, 14, 6052, 7601), + (6054, 4931, 4931, 4931, 4931, 7, 76, 12756, 4, 600, 14, 4933, 6055), + (6055, 4931, 4931, 4931, 4931, 7, 78, 12757, 4, 600, 14, 6054, 6056), + (6056, 4931, 4931, 4931, 4931, 7, 80, 12758, 4, 600, 14, 6055, 7291), + (6057, -1, -1, 6020, 6020, 2, 76, -1, 0, 0, 14, 6050, 6058), + (6058, -1, -1, 6020, 6020, 2, 78, -1, 0, 0, 14, 6057, 6059), + (6059, -1, -1, 6020, 6020, 2, 80, -1, 0, 0, 14, 6058, 7169), + (6060, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, -1, 6061), + (6061, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, 6060, 6470), + (6063, -1, -1, 589, 589, 7, 76, -1, 0, 0, 14, 5272, 6064), + (6064, -1, -1, 589, 589, 9, 78, -1, 0, 0, 14, 6063, 6065), + (6065, -1, -1, 589, 589, 12, 80, -1, 0, 0, 14, 6064, 7390), + (6066, -1, -1, 1313, 1313, 7, 76, -1, 0, 0, 14, 5031, 6067), + (6067, -1, -1, 1313, 1313, 7, 76, -1, 0, 0, 14, 6066, 6068), + (6068, -1, -1, 1313, 1313, 8, 77, -1, 0, 0, 14, 6067, 6069), + (6069, -1, -1, 1313, 1313, 9, 78, -1, 0, 0, 14, 6068, 6070), + (6070, -1, -1, 1313, 1313, 10, 79, -1, 0, 0, 14, 6069, 6071), + (6071, -1, -1, 1313, 1313, 12, 80, -1, 0, 0, 14, 6070, 7393), + (6072, -1, -1, 210, 210, 8, 77, -1, 0, 0, 14, 1318, 6073), + (6073, -1, -1, 210, 210, 9, 78, -1, 0, 0, 14, 6072, 6074), + (6074, -1, -1, 210, 210, 10, 79, -1, 0, 0, 14, 6073, 7399), + (6075, -1, -1, 895, 895, 7, 76, -1, 0, 0, 14, 899, 6076), + (6076, -1, -1, 895, 895, 8, 77, -1, 0, 0, 14, 6075, 6077), + (6077, -1, -1, 895, 895, 9, 78, -1, 0, 0, 14, 6076, 6078), + (6078, -1, -1, 895, 895, 10, 79, -1, 0, 0, 14, 6077, 6079), + (6079, -1, -1, 895, 895, 12, 80, -1, 0, 0, 14, 6078, 7402), + (6080, -1, -1, 683, 683, 5, 75, -1, 0, 0, 14, 5305, 6081), + (6081, -1, -1, 683, 683, 5, 75, -1, 0, 0, 14, 6080, 7604), + (6082, -1, -1, 6084, 6084, 5, 85, 0, 0, 0, 17, -1, 6083), + (6083, -1, -1, 6084, 6084, 5, 87, 0, 0, 0, 17, 6082, 6084), + (6084, -1, -1, 6084, 6084, 5, 89, 0, 0, 0, 17, 6083, 13366), + (6085, -1, -1, 6761, 6761, 10, 81, -1, 0, 0, 16, 6763, 6086), + (6086, -1, -1, 6761, 6761, 11, 83, -1, 0, 0, 16, 6085, 6087), + (6087, -1, -1, 6761, 6761, 12, 85, -1, 0, 0, 16, 6086, 10763), + (6088, -1, -1, 6088, 6088, 9, 85, 0, 0, 0, 17, -1, 6089), + (6089, -1, -1, 6088, 6088, 12, 87, 0, 0, 0, 17, 6088, 6090), + (6090, -1, -1, 6088, 6088, 15, 89, 0, 0, 0, 17, 6089, -1), + (6092, 5251, 5251, 5251, 5251, 7, 76, 12635, 13, 900, 14, 5253, 6093), + (6093, 5251, 5251, 5251, 5251, 9, 78, 12636, 13, 900, 14, 6092, 6094), + (6094, 5251, 5251, 5251, 5251, 12, 80, 12637, 13, 900, 14, 6093, 7472), + (6095, 513, 513, 513, 513, 7, 76, 12638, 4, 120, 14, 515, 6096), + (6096, 513, 513, 513, 513, 9, 78, 12639, 4, 120, 14, 6095, 6097), + (6097, 513, 513, 513, 513, 12, 80, 12640, 4, 120, 14, 6096, 7475), + (6098, 1327, 1327, 1327, 1327, 7, 76, 12641, 10, 900, 14, 5316, 6099), + (6099, 1327, 1327, 1327, 1327, 9, 78, 12642, 10, 900, 14, 6098, 6100), + (6100, 1327, 1327, 1327, 1327, 12, 80, 12643, 10, 900, 14, 6099, 7460), + (6101, 153, 153, 153, 153, 12, 80, 12644, 3, 2160, 14, 5068, 7468), + (6102, 146, 146, 146, 146, 8, 77, 12645, 2, 180, 14, 5069, 7466), + (6103, 528, 528, 528, 528, 7, 76, 12646, 5, 720, 14, 901, 6104), + (6104, 528, 528, 528, 528, 9, 78, 12647, 5, 720, 14, 6103, 6105), + (6105, 528, 528, 528, 528, 12, 80, 12648, 5, 720, 14, 6104, 7469), + (6106, 6106, 6106, 6106, 6106, 4, 67, 21965, 13, 4320, 16, -1, 6107), + (6107, 6106, 6106, 6106, 6106, 5, 68, 21966, 13, 4320, 16, 6106, 6108), + (6108, 6106, 6106, 6106, 6106, 6, 69, 21967, 13, 4320, 16, 6107, 6109), + (6109, 6106, 6106, 6106, 6106, 7, 77, 21968, 13, 4320, 16, 6108, 6110), + (6110, 6106, 6106, 6106, 6106, 8, 78, 21969, 13, 4320, 16, 6109, 6111), + (6111, 6106, 6106, 6106, 6106, 9, 79, 21970, 13, 4320, 16, 6110, -1), + (6112, -1, -1, 6112, 6112, 5, 85, -1, 0, 0, 17, -1, 12966), + (6113, -1, -1, 6113, 6113, 9, 85, 0, 0, 0, 17, -1, 6114), + (6114, -1, -1, 6113, 6113, 12, 87, 0, 0, 0, 17, 6113, 6115), + (6115, -1, -1, 6113, 6113, 15, 89, 0, 0, 0, 17, 6114, -1), + (6119, -1, -1, 6119, 6119, 6, 76, -1, 0, 0, 14, -1, 6120), + (6120, -1, -1, 6119, 6119, 6, 77, -1, 0, 0, 14, 6119, 6121), + (6121, -1, -1, 6119, 6119, 6, 78, -1, 0, 0, 14, 6120, 6122), + (6122, -1, -1, 6119, 6119, 6, 79, -1, 0, 0, 14, 6121, 6123), + (6123, -1, -1, 6119, 6119, 6, 80, -1, 0, 0, 14, 6122, 7526), + (6124, -1, -1, 5263, 5263, 3, 71, -1, 0, 0, 12, -1, 6125), + (6125, -1, -1, 5263, 5263, 6, 73, -1, 0, 0, 12, 6124, 6126), + (6126, -1, -1, 5263, 5263, 9, 75, -1, 0, 0, 12, 6125, 6127), + (6127, -1, -1, 5263, 5263, 10, 76, -1, 0, 0, 14, 6126, 6128), + (6128, -1, -1, 5263, 5263, 11, 78, -1, 0, 0, 14, 6127, 6129), + (6129, -1, -1, 5263, 5263, 12, 80, -1, 0, 0, 14, 6128, 12463), + (6130, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 588, 6131), + (6131, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 6130, 6132), + (6132, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 6131, -1), + (6133, 1351, 1351, 1351, 1351, 8, 77, 12649, 5, 30, 14, 1351, 7109), + (6134, 4849, 4849, 4849, 4849, 7, 76, 12650, 7, 1800, 14, 4849, 7110), + (6135, 54006, 54006, 54006, 54006, 7, 76, 12651, 18, 180, 14, -1, 7111), + (6136, -1, -1, 6136, 6136, 7, 76, -1, 0, 0, 10, -1, 6137), + (6149, 921, 921, 921, 921, 9, 79, 12652, 8, 60, 14, 5280, 7245), + (6150, 922, 922, 922, 922, 9, 78, 12653, 8, 60, 14, 5281, 7236), + (6151, 923, 923, 923, 923, 9, 77, 12654, 8, 60, 14, 5282, 7235), + (6152, 1334, 1334, 1334, 1334, 9, 78, 12655, 11, 4320, 14, 1336, 6153), + (6153, 1334, 1334, 1334, 1334, 10, 79, 12656, 11, 4320, 14, 6152, 6154), + (6154, 1334, 1334, 1334, 1334, 12, 80, 12657, 11, 4320, 14, 6153, 7239), + (6155, 4944, -1, 4944, 4944, 7, 76, 12658, 0, 1, 14, 4946, 6156), + (6156, 4944, -1, 4944, 4944, 9, 78, 12659, 0, 1, 14, 6155, 6157), + (6157, 4944, -1, 4944, 4944, 12, 80, 12660, 0, 1, 14, 6156, 7229), + (6158, 1337, 1337, 1337, 1337, 8, 77, 12661, 13, 4320, 14, 1339, 6159), + (6159, 1337, 1337, 1337, 1337, 9, 78, 12662, 13, 4320, 14, 6158, 6160), + (6160, 1337, 1337, 1337, 1337, 10, 79, 12663, 13, 4320, 14, 6159, 14338), + (6161, 1478, -1, 1478, 1478, 9, 78, 12664, 0, 1, 14, 1480, 6162), + (6162, 1478, -1, 1478, 1478, 10, 79, 12665, 0, 1, 14, 6161, 6163), + (6163, 1478, -1, 1478, 1478, 12, 80, 12666, 0, 1, 14, 6162, 7242), + (6200, 6533, 6533, 6533, 6533, 10, 79, 12768, 15, 600, 14, -1, 7428), + (6201, 6534, 6534, 6534, 6534, 9, 78, 12769, 16, 900, 14, -1, 7429), + (6202, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, -1, 6203), + (6203, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, 6202, 6204), + (6204, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, 6203, -1), + (6205, 6536, 6536, 6536, 6536, 7, 76, 12712, 39, 5, 14, -1, -1), + (6206, 6537, 6537, 6537, 6537, 7, 76, 12770, 30, 900, 14, -1, 6207), + (6207, 6537, 6537, 6537, 6537, 8, 77, 12771, 30, 900, 14, 6206, 6208), + (6208, 6537, 6537, 6537, 6537, 9, 78, 12772, 30, 900, 14, 6207, 7606), + (6209, -1, -1, 6538, 6538, 7, 76, -1, 0, 0, 14, -1, 6210), + (6210, -1, -1, 6538, 6538, 9, 78, -1, 0, 0, 14, 6209, 6211), + (6211, -1, -1, 6538, 6538, 12, 80, -1, 0, 0, 14, 6210, 7478), + (6212, 6539, 6539, 6539, 6539, 6, 71, 12776, 18, 1800, 14, -1, 6213), + (6213, 6539, 6539, 6539, 6539, 6, 74, 12777, 18, 1800, 14, 6212, 6214), + (6214, 6539, 6539, 6539, 6539, 6, 77, 12778, 18, 1800, 14, 6213, 7609), + (6215, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6216), + (6216, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6215, 6217), + (6217, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6216, 6300), + (6218, 6218, 6218, 6218, 6218, 7, 76, 12782, 0, 1, 14, -1, 7488), + (6219, 6542, 6542, 6542, 6542, 7, 76, 12783, 18, 1800, 14, -1, 6220), + (6220, 6542, 6542, 6542, 6542, 9, 78, 12784, 18, 1800, 14, 6219, 6221), + (6221, 6542, 6542, 6542, 6542, 12, 80, 12785, 18, 1800, 14, 6220, -1), + (6222, 6543, 6543, 6543, 6543, 9, 72, 13143, 18, 25, 14, -1, -1), + (6223, -1, -1, 962, 962, 5, 76, -1, 0, 0, 14, 966, 6224), + (6224, -1, -1, 962, 962, 5, 77, -1, 0, 0, 14, 6223, 6225), + (6225, -1, -1, 962, 962, 5, 78, -1, 0, 0, 14, 6224, 6226), + (6226, -1, -1, 962, 962, 5, 79, -1, 0, 0, 14, 6225, 6227), + (6227, -1, -1, 962, 962, 5, 80, -1, 0, 0, 14, 6226, 10361), + (6228, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, -1, 6229), + (6229, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6228, 6230), + (6230, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6229, 6231), + (6231, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6230, -1), + (6232, 6232, 6232, 6232, 6232, 12, 80, 14413, 18, 900, 14, -1, 7421), + (6233, -1, -1, 477, 477, 2, 70, -1, 0, 0, 14, 479, 6234), + (6234, -1, -1, 477, 477, 2, 71, -1, 0, 0, 14, 6233, 6235), + (6235, -1, -1, 477, 477, 2, 72, -1, 0, 0, 14, 6234, 16094), + (6236, -1, -1, 6548, 6548, 6, 73, -1, 0, 0, 14, -1, 6237), + (6237, -1, -1, 6548, 6548, 6, 75, -1, 0, 0, 14, 6236, 6238), + (6238, -1, -1, 6548, 6548, 8, 77, -1, 0, 0, 14, 6237, 12929), + (6240, -1, -1, 767, 767, 3, 65, -1, 0, 0, 14, -1, 6241), + (6241, -1, -1, 767, 767, 6, 65, -1, 0, 0, 14, 6240, 6242), + (6242, -1, -1, 767, 767, 9, 65, -1, 0, 0, 14, 6241, 6243), + (6243, -1, -1, 767, 767, 3, 67, -1, 0, 0, 14, 6242, 6244), + (6244, -1, -1, 767, 767, 6, 68, -1, 0, 0, 14, 6243, 6245), + (6245, -1, -1, 767, 767, 9, 69, -1, 0, 0, 14, 6244, 12426), + (6249, 6552, 6552, 6552, 6552, 5, 70, -1, 0, 0, 14, -1, 6250), + (6250, 6552, 6552, 6552, 6552, 6, 72, -1, 0, 0, 14, 6249, 6251), + (6251, 6552, 6552, 6552, 6552, 6, 74, -1, 0, 0, 14, 6250, 6252), + (6252, 6552, 6552, 6552, 6552, 7, 76, -1, 0, 0, 14, 6251, 6253), + (6253, 6552, 6552, 6552, 6552, 9, 78, -1, 0, 0, 14, 6252, 7279), + (6254, 616, 616, 616, 616, 6, 73, 12765, 7, 900, 14, 1250, 6255), + (6255, 616, 616, 616, 616, 7, 76, 12766, 7, 900, 14, 6254, 6256), + (6256, 616, 616, 616, 616, 10, 79, 12767, 7, 900, 14, 6255, 7257), + (6257, -1, -1, 86, 86, 2, 55, -1, 0, 0, 14, -1, 6258), + (6258, -1, -1, 86, 86, 4, 55, -1, 0, 0, 14, 6257, 6259), + (6259, -1, -1, 86, 86, 6, 55, -1, 0, 0, 14, 6258, 8223), + (6260, -1, -1, 495, 495, 6, 73, -1, 0, 0, 14, 497, 6261), + (6261, -1, -1, 495, 495, 7, 76, -1, 0, 0, 14, 6260, 6262), + (6262, -1, -1, 495, 495, 10, 79, -1, 0, 0, 14, 6261, 10666), + (6266, -1, -1, 6557, 6557, 6, 73, -1, 0, 0, 14, -1, 6267), + (6267, -1, -1, 6557, 6557, 7, 76, -1, 0, 0, 14, 6266, 6268), + (6268, -1, -1, 6557, 6557, 10, 79, -1, 0, 0, 14, 6267, -1), + (6269, -1, -1, 6558, 6558, 6, 73, -1, 0, 0, 14, -1, 6270), + (6270, -1, -1, 6558, 6558, 7, 76, -1, 0, 0, 14, 6269, 6271), + (6271, -1, -1, 6558, 6558, 10, 79, -1, 0, 0, 14, 6270, -1), + (6272, -1, -1, 6559, 6559, 6, 73, -1, 0, 0, 14, -1, 6273), + (6273, -1, -1, 6559, 6559, 7, 75, -1, 0, 0, 14, 6272, 6274), + (6274, -1, -1, 6559, 6559, 10, 77, -1, 0, 0, 14, 6273, 7137), + (6275, -1, -1, 6560, 6560, 6, 73, -1, 0, 0, 14, -1, 6276), + (6276, -1, -1, 6560, 6560, 7, 76, -1, 0, 0, 14, 6275, 6277), + (6277, -1, -1, 6560, 6560, 10, 79, -1, 0, 0, 14, 6276, 16266), + (6278, 6561, 6561, 6561, 6561, 7, 76, 12795, 32, 30, 14, -1, 6279), + (6279, 6561, 6561, 6561, 6561, 7, 76, 12796, 32, 30, 14, 6278, 6280), + (6280, 6561, 6561, 6561, 6561, 7, 76, 12797, 32, 30, 14, 6279, 7422), + (6281, 6563, 6563, 6563, 6563, 9, 78, 13144, 36, 8, 14, -1, 12995), + (6282, 6562, 6562, 6562, 6562, 6, 72, 12798, 39, 1, 14, -1, -1), + (6283, -1, -1, 6564, 6564, 6, 73, -1, 0, 0, 14, -1, 6284), + (6284, -1, -1, 6564, 6564, 7, 76, -1, 0, 0, 14, 6283, 6285), + (6285, -1, -1, 6564, 6564, 10, 79, -1, 0, 0, 14, 6284, 7112), + (6286, 6565, 6565, 6565, 6565, 7, 76, 12802, 17, 45, 14, -1, 7115), + (6287, -1, -1, 6566, 6566, 6, 73, -1, 0, 0, 14, -1, 6288), + (6288, -1, -1, 6566, 6566, 7, 76, -1, 0, 0, 14, 6287, 6289), + (6289, -1, -1, 6566, 6566, 10, 79, -1, 0, 0, 14, 6288, -1), + (6290, 6290, 6290, 6290, 6290, 6, 71, 12803, 0, 1, 14, -1, 6291), + (6291, 6290, 6290, 6290, 6290, 6, 73, 12804, 0, 1, 14, 6290, 6292), + (6292, 6290, 6290, 6290, 6290, 6, 75, 12805, 0, 1, 14, 6291, 6293), + (6293, 6290, 6290, 6290, 6290, 7, 76, 12806, 0, 1, 14, 6292, 6294), + (6294, 6290, 6290, 6290, 6290, 9, 78, 12807, 0, 1, 14, 6293, 6295), + (6295, 6290, 6290, 6290, 6290, 12, 80, 12808, 0, 1, 14, 6294, 7223), + (6296, 619, 619, 619, 619, 6, 73, 12759, 6, 900, 14, 722, 6297), + (6297, 619, 619, 619, 619, 6, 73, 12760, 6, 900, 14, 6296, 6298), + (6298, 619, 619, 619, 619, 6, 73, 12761, 6, 900, 14, 6297, 7226), + (6299, 6299, 6299, 6299, 6299, 9, 65, 12786, 18, 12, 14, -1, -1), + (6300, -1, -1, 6540, 6540, 8, 74, -1, 0, 0, 14, 6217, 6301), + (6301, -1, -1, 6540, 6540, 8, 75, -1, 0, 0, 14, 6300, 6472), + (6302, -1, -1, 6302, 6302, 5, 81, 0, 0, 0, 16, -1, 6303), + (6303, -1, -1, 6302, 6302, 5, 83, 0, 0, 0, 16, 6302, 6304), + (6304, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 6303, 11011), + (6307, 1358, 1358, 1358, 1358, 6, 71, 13168, 3, 60, 14, 1360, 6308), + (6308, 1358, 1358, 1358, 1358, 6, 73, 13169, 3, 60, 14, 6307, 6309), + (6309, 1358, 1358, 1358, 1358, 6, 75, 13170, 3, 60, 14, 6308, 6310), + (6310, 1358, 1358, 1358, 1358, 6, 76, 13171, 3, 60, 14, 6309, 6311), + (6311, 1358, 1358, 1358, 1358, 6, 78, 13172, 3, 60, 14, 6310, 6312), + (6312, 1358, 1358, 1358, 1358, 6, 80, 13173, 3, 60, 14, 6311, 7157), + (6313, 1352, 1352, 1352, 1352, 6, 71, 13174, 3, 60, 14, 1354, 6314), + (6314, 1352, 1352, 1352, 1352, 6, 73, 13175, 3, 60, 14, 6313, 6315), + (6315, 1352, 1352, 1352, 1352, 6, 75, 13177, 3, 60, 14, 6314, 6316), + (6316, 1352, 1352, 1352, 1352, 6, 76, 13178, 3, 60, 14, 6315, 6317), + (6317, 1352, 1352, 1352, 1352, 6, 78, 13179, 3, 60, 14, 6316, 6318), + (6318, 1352, 1352, 1352, 1352, 6, 80, 13180, 3, 60, 14, 6317, 7154), + (6319, -1, -1, 501, 501, 6, 73, -1, 0, 0, 14, 503, 6320), + (6320, -1, -1, 501, 501, 6, 75, -1, 0, 0, 14, 6319, 6321), + (6321, -1, -1, 501, 501, 6, 77, -1, 0, 0, 14, 6320, 6528), + (6322, -1, -1, 6322, 6322, 6, 73, -1, 0, 0, 14, -1, 6323), + (6323, -1, -1, 6322, 6322, 6, 75, -1, 0, 0, 14, 6322, 6324), + (6324, -1, -1, 6322, 6322, 6, 77, -1, 0, 0, 14, 6323, -1), + (6325, 6325, 6325, 6325, 6325, 7, 73, 13213, 18, 600, 14, -1, 6326), + (6326, 6325, 6325, 6325, 6325, 7, 75, 13214, 18, 600, 14, 6325, 6327), + (6327, 6325, 6325, 6325, 6325, 7, 77, 13215, 18, 600, 14, 6326, 6361), + (6328, 6328, 6328, 6328, 6328, 7, 74, 13204, 10, 600, 14, -1, 6329), + (6329, 6328, 6328, 6328, 6328, 7, 76, 13205, 10, 600, 14, 6328, 6330), + (6330, 6328, 6328, 6328, 6328, 7, 78, 13212, 10, 600, 14, 6329, 7143), + (6331, -1, -1, 878, 878, 7, 76, -1, 0, 0, 14, 4959, 6332), + (6332, -1, -1, 878, 878, 7, 78, -1, 0, 0, 14, 6331, 7146), + (6333, 6333, 6333, 6333, 6333, 9, 59, 13167, 3, 600, 14, -1, 7266), + (6334, -1, -1, 6334, 6334, 6, 73, -1, 0, 0, 14, -1, 6335), + (6335, -1, -1, 6334, 6334, 6, 75, -1, 0, 0, 14, 6334, 6336), + (6336, -1, -1, 6334, 6334, 6, 77, -1, 0, 0, 14, 6335, -1), + (6337, -1, -1, 6337, 6337, 6, 74, -1, 0, 0, 14, -1, 6338), + (6338, -1, -1, 6337, 6337, 6, 76, -1, 0, 0, 14, 6337, 6339), + (6339, -1, -1, 6337, 6337, 6, 78, -1, 0, 0, 14, 6338, 7448), + (6340, -1, -1, 6340, 6340, 6, 74, -1, 0, 0, 14, -1, 6341), + (6341, -1, -1, 6340, 6340, 6, 76, -1, 0, 0, 14, 6340, 6342), + (6342, -1, -1, 6340, 6340, 6, 78, -1, 0, 0, 14, 6341, 7451), + (6343, -1, -1, 6343, 6343, 6, 74, -1, 0, 0, 14, -1, 6344), + (6344, -1, -1, 6343, 6343, 6, 76, -1, 0, 0, 14, 6343, 6345), + (6345, -1, -1, 6343, 6343, 6, 78, -1, 0, 0, 14, 6344, 7166), + (6346, -1, -1, 6346, 6346, 6, 74, -1, 0, 0, 14, -1, 6347), + (6347, -1, -1, 6346, 6346, 6, 76, -1, 0, 0, 14, 6346, 6348), + (6348, -1, -1, 6346, 6346, 6, 78, -1, 0, 0, 14, 6347, 7615), + (6349, -1, -1, 6349, 6349, 6, 74, -1, 0, 0, 14, -1, 6350), + (6350, -1, -1, 6349, 6349, 6, 76, -1, 0, 0, 14, 6349, 6351), + (6351, -1, -1, 6349, 6349, 6, 78, -1, 0, 0, 14, 6350, 7618), + (6352, 4894, 4894, 4894, 4894, 6, 76, 13181, 7, 2160, 14, 4896, 6353), + (6353, 4894, 4894, 4894, 4894, 6, 77, 13182, 7, 2160, 14, 6352, 6354), + (6354, 4894, 4894, 4894, 4894, 6, 78, 13183, 7, 2160, 14, 6353, 7288), + (6355, -1, -1, 6355, 6355, 6, 73, -1, 0, 0, 14, -1, 6356), + (6356, -1, -1, 6355, 6355, 6, 74, -1, 0, 0, 14, 6355, 6357), + (6357, -1, -1, 6355, 6355, 6, 75, -1, 0, 0, 14, 6356, 6358), + (6358, -1, -1, 6355, 6355, 6, 76, -1, 0, 0, 14, 6357, 6359), + (6359, -1, -1, 6355, 6355, 6, 77, -1, 0, 0, 14, 6358, 6360), + (6360, -1, -1, 6355, 6355, 6, 80, -1, 0, 0, 16, 6359, 14101), + (6361, 6325, 6325, 6325, 6325, 7, 81, 16861, 18, 600, 16, 6327, 12633), + (6362, -1, -1, 6362, 6362, 5, 77, 0, 0, 0, 16, -1, 6363), + (6363, -1, -1, 6362, 6362, 5, 79, 0, 0, 0, 16, 6362, 6364), + (6364, -1, -1, 6362, 6362, 5, 81, 0, 0, 0, 16, 6363, 6365), + (6365, -1, -1, 6362, 6362, 5, 83, 0, 0, 0, 16, 6364, 6366), + (6366, -1, -1, 6362, 6362, 5, 85, 0, 0, 0, 16, 6365, 16327), + (6370, 6370, 6370, 6370, 6370, 6, 76, 13188, 7, 600, 14, -1, 6371), + (6371, 6370, 6370, 6370, 6370, 6, 77, 13189, 7, 600, 14, 6370, 6372), + (6372, 6370, 6370, 6370, 6370, 6, 78, 13190, 7, 600, 14, 6371, 7350), + (6375, -1, -1, 6375, 6375, 6, 76, -1, 0, 0, 14, -1, 6376), + (6376, -1, -1, 6375, 6375, 6, 77, -1, 0, 0, 14, 6375, 6377), + (6377, -1, -1, 6375, 6375, 6, 78, -1, 0, 0, 14, 6376, 7644), + (6378, 209, 209, 209, 1272, 6, 76, 13501, 12, 5, 14, 1272, -1), + (6379, 6379, 6379, 6379, 6379, 6, 60, 13500, 37, 5, 14, -1, -1), + (6380, 6380, 6380, 6380, 6380, 6, 78, 13209, 39, 120, 14, -1, 6381), + (6381, 6380, 6380, 6380, 6380, 6, 79, 13210, 39, 120, 14, 6380, 6382), + (6382, 6380, 6380, 6380, 6380, 6, 80, 13211, 39, 120, 14, 6381, 7497), + (6383, -1, -1, 6383, 6383, 3, 70, -1, 0, 0, 14, -1, 6384), + (6384, -1, -1, 6383, 6383, 6, 70, -1, 0, 0, 14, 6383, 6385), + (6385, -1, -1, 6383, 6383, 9, 70, -1, 0, 0, 14, 6384, 10607), + (6386, -1, -1, 6386, 6386, 7, 72, -1, 0, 0, 14, -1, 6387), + (6387, -1, -1, 6386, 6386, 7, 74, -1, 0, 0, 14, 6386, 6388), + (6388, -1, -1, 6386, 6386, 7, 76, -1, 0, 0, 14, 6387, 6389), + (6389, -1, -1, 6386, 6386, 7, 78, -1, 0, 0, 14, 6388, 13521), + (6390, -1, -1, 65, 661, 3, 76, -1, 0, 0, 14, 4697, 6391), + (6391, -1, -1, 65, 661, 3, 77, -1, 0, 0, 14, 6390, 6392), + (6392, -1, -1, 65, 661, 3, 78, -1, 0, 0, 14, 6391, 6393), + (6393, -1, -1, 65, 661, 3, 79, -1, 0, 0, 14, 6392, 6394), + (6394, -1, -1, 65, 661, 3, 80, -1, 0, 0, 14, 6393, 7534), + (6395, -1, -1, 6395, 6395, 7, 76, -1, 0, 0, 14, -1, 6396), + (6396, -1, -1, 6395, 6395, 7, 77, -1, 0, 0, 14, 6395, 6397), + (6397, -1, -1, 6395, 6395, 7, 78, -1, 0, 0, 14, 6396, 7336), + (6398, 516, 516, 516, 516, 6, 72, 13198, 5, 480, 14, 516, 7237), + (6400, 1110, 1110, 1110, 1110, 6, 73, 13192, 3, 2160, 14, 1112, 6401), + (6401, 1110, 1110, 1110, 1110, 6, 75, 13193, 3, 2160, 14, 6400, 6402), + (6402, 1110, 1110, 1110, 1110, 6, 76, 13194, 3, 2160, 14, 6401, 7445), + (6403, -1, -1, 1107, 1107, 7, 76, -1, 0, 0, 14, 5288, 6404), + (6404, -1, -1, 1107, 1107, 9, 78, -1, 0, 0, 14, 6403, 6405), + (6405, -1, -1, 1107, 1107, 12, 80, -1, 0, 0, 14, 6404, 12432), + (6406, -1, -1, 5085, 5085, 6, 76, -1, 0, 0, 14, 5087, 6407), + (6407, -1, -1, 5085, 5085, 6, 78, -1, 0, 0, 14, 6406, 6408), + (6408, -1, -1, 5085, 5085, 6, 80, -1, 0, 0, 14, 6407, 7384), + (6409, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6410), + (6410, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6409, 6411), + (6411, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6410, 6412), + (6412, -1, -1, 6540, 6540, 8, 74, -1, 0, 0, 14, 6411, 6413), + (6413, -1, -1, 6540, 6540, 8, 75, -1, 0, 0, 14, 6412, 6414), + (6414, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, 6413, 6415), + (6415, -1, -1, 6540, 6540, 8, 77, -1, 0, 0, 14, 6414, 6416), + (6416, -1, -1, 6540, 6540, 8, 78, -1, 0, 0, 14, 6415, 6417), + (6417, -1, -1, 6540, 6540, 8, 79, -1, 0, 0, 14, 6416, 6418), + (6418, -1, -1, 6540, 6540, 8, 80, -1, 0, 0, 14, 6417, 6474), + (6419, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6420), + (6420, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6419, 6421), + (6421, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6420, 6476), + (6422, -1, -1, 6422, 6422, 3, 61, -1, 0, 0, 14, -1, 6423), + (6423, -1, -1, 6422, 6422, 3, 63, -1, 0, 0, 14, 6422, 6424), + (6424, -1, -1, 6422, 6422, 3, 65, -1, 0, 0, 14, 6423, -1), + (6425, 5007, 5007, 5007, 5007, 9, 76, 13509, 8, 2160, 14, 5009, 6426), + (6426, 5007, 5007, 5007, 5007, 9, 78, 13510, 8, 2160, 14, 6425, 6427), + (6427, 5007, 5007, 5007, 5007, 9, 80, 13511, 8, 2160, 14, 6426, 7341), + (6428, -1, -1, 1287, 1287, 3, 67, -1, 0, 0, 14, -1, 6429), + (6429, -1, -1, 1287, 1287, 6, 68, -1, 0, 0, 14, 6428, 6430), + (6430, -1, -1, 1287, 1287, 9, 69, -1, 0, 0, 14, 6429, 12472), + (6431, -1, -1, 1056, 1056, 5, 76, -1, 0, 0, 14, 1060, 6432), + (6432, -1, -1, 1056, 1056, 5, 77, -1, 0, 0, 14, 6431, 6433), + (6433, -1, -1, 1056, 1056, 5, 78, -1, 0, 0, 14, 6432, 6434), + (6434, -1, -1, 1056, 1056, 5, 79, -1, 0, 0, 14, 6433, 6435), + (6435, -1, -1, 1056, 1056, 5, 80, -1, 0, 0, 14, 6434, 7521), + (6436, -1, -1, 6436, 6436, 6, 73, -1, 0, 0, 14, -1, 6437), + (6437, -1, -1, 6436, 6436, 6, 75, -1, 0, 0, 14, 6436, 6438), + (6438, -1, -1, 6436, 6436, 8, 77, -1, 0, 0, 14, 6437, 7313), + (6439, -1, -1, 468, 468, 2, 67, -1, 0, 0, 14, 470, 6440), + (6440, -1, -1, 468, 468, 2, 69, -1, 0, 0, 14, 6439, 7316), + (6441, -1, -1, 1546, 1546, 5, 76, -1, 0, 0, 14, 4831, 12673), + (6442, -1, -1, 1471, 1471, 6, 76, -1, 0, 0, 14, 1475, 6443), + (6443, -1, -1, 1471, 1471, 6, 77, -1, 0, 0, 14, 6442, -1), + (6445, -1, -1, 6445, 6445, 2, 62, -1, 0, 0, 14, -1, 6446), + (6446, -1, -1, 6445, 6445, 2, 64, -1, 0, 0, 14, 6445, 6447), + (6447, -1, -1, 6445, 6445, 2, 66, -1, 0, 0, 14, 6446, -1), + (6448, 5109, 5109, 5109, 5109, 9, 77, 13515, 0, 1, 14, 5109, 7467), + (6449, 1520, 1520, 1520, 1520, 9, 70, 13516, 11, 900, 14, 1522, 6450), + (6450, 1520, 1520, 1520, 1520, 9, 70, 13517, 11, 900, 14, 6449, 6451), + (6451, 1520, 1520, 1520, 1520, 9, 70, 13518, 11, 900, 14, 6450, 7463), + (6452, -1, -1, 6452, 6452, 2, 71, -1, 0, 0, 14, -1, 6453), + (6453, -1, -1, 6452, 6452, 2, 72, -1, 0, 0, 14, 6452, 6454), + (6454, -1, -1, 6452, 6452, 2, 73, -1, 0, 0, 14, 6453, -1), + (6455, 6455, 6455, 6455, 6455, 2, 72, 14750, 36, 30, 14, -1, 6456), + (6456, 6455, 6455, 6455, 6455, 2, 74, 14751, 36, 30, 14, 6455, 6457), + (6457, 6455, 6455, 6455, 6455, 2, 76, 14752, 36, 30, 14, 6456, -1), + (6458, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, -1, 6459), + (6459, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, 6458, 6460), + (6460, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, 6459, -1), + (6461, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, -1, 6462), + (6462, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, 6461, 6463), + (6463, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, 6462, -1), + (6464, 967, 967, 967, 967, 6, 76, 13897, 10, 1800, 14, 969, 6465), + (6465, 967, 967, 967, 967, 6, 77, 13898, 10, 1800, 14, 6464, 6466), + (6466, 967, 967, 967, 967, 6, 78, 13899, 10, 1800, 14, 6465, 7217), + (6467, -1, -1, 6467, 6467, 3, 61, -1, 0, 0, 15, -1, 6468), + (6468, -1, -1, 6467, 6467, 3, 63, -1, 0, 0, 15, 6467, 6469), + (6469, -1, -1, 6467, 6467, 3, 65, -1, 0, 0, 15, 6468, -1), + (6470, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 15, 6061, 6471), + (6471, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6470, 12487), + (6472, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6301, 6473), + (6473, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6472, 12481), + (6474, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6418, 6475), + (6475, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6474, 12483), + (6476, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6421, 6477), + (6477, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6476, 12485), + (6478, 0, 0, 6478, 6478, 3, 81, -1, 0, 0, 16, -1, 6479), + (6479, 0, 0, 6478, 6478, 5, 83, -1, 0, 0, 16, 6478, 6480), + (6480, 0, 0, 6478, 6478, 7, 85, -1, 0, 0, 16, 6479, -1), + (6481, 0, 0, 6481, 6481, 5, 85, -1, 0, 0, 16, -1, 6482), + (6482, 0, 0, 6481, 6481, 7, 85, -1, 0, 0, 16, 6481, 6483), + (6483, 0, 0, 6481, 6481, 9, 85, -1, 0, 0, 16, 6482, 15314), + (6484, -1, -1, 7940, 7940, 5, 85, -1, 0, 0, 16, 10032, 6485), + (6485, -1, -1, 7940, 7940, 7, 85, -1, 0, 0, 16, 6484, 6486), + (6486, -1, -1, 7940, 7940, 9, 85, -1, 0, 0, 16, 6485, 15320), + (6487, 1383, 1383, 1383, 1383, 12, 85, 21812, 6, 300, 16, 10014, 14221), + (6488, 6488, 6488, 6488, 6488, 12, 85, 21806, 32, 900, 16, -1, 13383), + (6489, -1, -1, 6489, 6489, 5, 81, -1, 0, 0, 16, -1, 6490), + (6490, -1, -1, 6489, 6489, 7, 83, -1, 0, 0, 16, 6489, 6491), + (6491, -1, -1, 6489, 6489, 9, 85, -1, 0, 0, 16, 6490, 17239), + (6492, 6492, 6492, 6492, 6492, 7, 75, 21692, 52, 720, 16, -1, 6493), + (6493, 6492, 6492, 6492, 6492, 7, 77, 21693, 52, 720, 16, 6492, 6494), + (6494, 6492, 6492, 6492, 6492, 7, 79, 21694, 52, 720, 16, 6493, 6495), + (6495, 6492, 6492, 6492, 6492, 7, 81, 21695, 52, 720, 16, 6494, 6496), + (6496, 6492, 6492, 6492, 6492, 7, 83, 21696, 52, 720, 16, 6495, 6497), + (6497, 6492, 6492, 6492, 6492, 7, 85, 21697, 52, 720, 16, 6496, 10679), + (6499, 6499, 6499, 6499, 6499, 3, 75, 13512, 13, 60, 14, -1, -1), + (6500, -1, -1, 4761, 4761, 7, 76, -1, 0, 0, 14, 4763, 6501), + (6501, -1, -1, 4761, 4761, 7, 78, -1, 0, 0, 14, 6500, 6502), + (6502, -1, -1, 4761, 4761, 7, 80, -1, 0, 0, 14, 6501, -1), + (6503, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, -1, 6504), + (6504, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6503, 6505), + (6505, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6504, 6506), + (6506, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6505, -1), + (6508, 6508, 6508, 6508, 6508, 7, 74, 13195, 38, 600, 14, -1, 6509), + (6509, 6508, 6508, 6508, 6508, 7, 76, 13196, 38, 600, 14, 6508, 6510), + (6510, 6508, 6508, 6508, 6508, 7, 78, 13197, 38, 600, 14, 6509, 7387), + (6511, -1, -1, 6511, 6511, 6, 73, -1, 0, 0, 14, -1, 6512), + (6512, -1, -1, 6511, 6511, 6, 75, -1, 0, 0, 14, 6511, 6513), + (6513, -1, -1, 6511, 6511, 6, 77, -1, 0, 0, 14, 6512, -1), + (6514, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, -1, 6515), + (6515, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, 6514, 6516), + (6516, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, 6515, -1), + (6517, -1, -1, 1435, 4773, 9, 76, -1, 0, 0, 14, 4773, 7621), + (6518, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 682, 6519), + (6519, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 6518, 6520), + (6520, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 6519, 7544), + (6521, -1, -1, 1021, 1021, 5, 75, -1, 0, 0, 14, 1025, 6522), + (6522, -1, -1, 1021, 1021, 5, 80, -1, 0, 0, 14, 6521, 7539), + (6523, -1, -1, 1026, 1026, 5, 76, -1, 0, 0, 14, 4687, 6524), + (6524, -1, -1, 1026, 1026, 5, 77, -1, 0, 0, 14, 6523, 6525), + (6525, -1, -1, 1026, 1026, 5, 78, -1, 0, 0, 14, 6524, 6526), + (6526, -1, -1, 1026, 1026, 5, 79, -1, 0, 0, 14, 6525, 6527), + (6527, -1, -1, 1026, 1026, 5, 80, -1, 0, 0, 14, 6526, 7511), + (6528, -1, -1, 501, 501, 5, 96, -1, 0, 0, 19, 6321, 6529), + (6531, -1, -1, 5295, 5295, 6, 76, -1, 0, 0, 14, 5297, 6532), + (6532, -1, -1, 5295, 5295, 6, 78, -1, 0, 0, 14, 6531, 6533), + (6533, -1, -1, 5295, 5295, 6, 80, -1, 0, 0, 14, 6532, 7220), + (6534, 8000, 8000, 8000, 8000, 12, 90, 23607, 73, 600, 17, -1, 14216), + (6540, -1, -1, 4699, 4699, 5, 56, -1, 0, 0, 14, 4699, 7500), + (6545, -1, -1, 4698, 4698, 5, 56, -1, 0, 0, 14, 4698, -1), + (6546, -1, -1, 6546, 6546, 0, 55, -1, 0, 0, 3, -1, 6547), + (6547, -1, -1, 6546, 6546, 0, 56, -1, 0, 0, 3, 6546, 6548), + (6548, -1, -1, 6546, 6546, 0, 57, -1, 0, 0, 3, 6547, 6549), + (6549, -1, -1, 6546, 6546, 0, 58, -1, 0, 0, 3, 6548, 6550), + (6550, -1, -1, 6546, 6546, 0, 59, -1, 0, 0, 3, 6549, 6551), + (6551, -1, -1, 6546, 6546, 0, 60, -1, 0, 0, 3, 6550, 6552), + (6552, -1, -1, 6546, 6546, 0, 61, -1, 0, 0, 3, 6551, 6553), + (6553, -1, -1, 6546, 6546, 0, 62, -1, 0, 0, 3, 6552, 6554), + (6554, -1, -1, 6546, 6546, 0, 63, -1, 0, 0, 3, 6553, 6555), + (6555, -1, -1, 6546, 6546, 0, 64, -1, 0, 0, 3, 6554, 6556), + (6556, -1, -1, 6546, 6546, 0, 65, -1, 0, 0, 3, 6555, 6557), + (6557, -1, -1, 6546, 6546, 0, 66, -1, 0, 0, 3, 6556, 6558), + (6558, -1, -1, 6546, 6546, 0, 67, -1, 0, 0, 3, 6557, 6559), + (6559, -1, -1, 6546, 6546, 0, 68, -1, 0, 0, 3, 6558, 6560), + (6560, -1, -1, 6546, 6546, 0, 69, -1, 0, 0, 3, 6559, 6561), + (6561, -1, -1, 6546, 6546, 0, 70, -1, 0, 0, 3, 6560, 6562), + (6562, -1, -1, 6546, 6546, 0, 71, -1, 0, 0, 3, 6561, 6563), + (6563, -1, -1, 6546, 6546, 0, 72, -1, 0, 0, 3, 6562, 6564), + (6564, -1, -1, 6546, 6546, 0, 73, -1, 0, 0, 3, 6563, 6565), + (6565, -1, -1, 6546, 6546, 0, 74, -1, 0, 0, 3, 6564, 6566), + (6566, -1, -1, 6546, 6546, 0, 75, -1, 0, 0, 3, 6565, 6567), + (6567, -1, -1, 6546, 6546, 0, 76, -1, 0, 0, 3, 6566, 6568), + (6568, -1, -1, 6546, 6546, 0, 77, -1, 0, 0, 3, 6567, 6569), + (6569, -1, -1, 6546, 6546, 0, 78, -1, 0, 0, 3, 6568, 6570), + (6570, -1, -1, 6546, 6546, 0, 79, -1, 0, 0, 3, 6569, 6571), + (6571, -1, -1, 6546, 6546, 0, 80, -1, 0, 0, 3, 6570, 7373), + (6601, -1, -1, 6601, 6601, 6, 72, -1, 0, 0, 14, -1, 6602), + (6602, -1, -1, 6601, 6601, 6, 73, -1, 0, 0, 14, 6601, 6603), + (6603, -1, -1, 6601, 6601, 6, 74, -1, 0, 0, 14, 6602, 6604), + (6604, -1, -1, 6601, 6601, 6, 75, -1, 0, 0, 14, 6603, 6605), + (6605, -1, -1, 6601, 6601, 6, 76, -1, 0, 0, 14, 6604, 7318), + (6606, 1597, 1597, 1597, 1597, 9, 75, 16095, 6, 10, 15, 1597, 10571), + (6607, 6607, 6607, 6607, 6607, 9, 75, 16092, 61, 600, 15, -1, 6608), + (6608, 6607, 6607, 6607, 6607, 9, 80, 16093, 61, 600, 15, 6607, 6609), + (6609, 6607, 6607, 6607, 6607, 9, 85, 16094, 61, 600, 15, 6608, 16324), + (6610, 6610, 6610, 6610, 6610, 2, 55, 16096, 41, 30, 15, -1, 10003), + (6611, -1, -1, 6611, 6611, 2, 60, -1, 0, 0, 15, -1, 6612), + (6612, -1, -1, 6611, 6611, 4, 63, -1, 0, 0, 15, 6611, 6613), + (6613, -1, -1, 6611, 6611, 6, 66, -1, 0, 0, 15, 6612, 6618), + (6614, -1, -1, 6614, 6614, 2, 60, -1, 0, 0, 15, -1, 6615), + (6615, -1, -1, 6614, 6614, 4, 63, -1, 0, 0, 15, 6614, 6616), + (6616, -1, -1, 6614, 6614, 6, 66, -1, 0, 0, 15, 6615, 10004), + (6617, 6617, 6617, 6617, 6617, 6, 83, 16097, 42, 3600, 15, -1, 10572), + (6618, -1, -1, 6611, 6611, 6, 69, -1, 0, 0, 15, 6613, 6619), + (6619, -1, -1, 6611, 6611, 6, 72, -1, 0, 0, 15, 6618, 10574), + (6630, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, -1, 6631), + (6631, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6630, 6632), + (6632, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6631, 6633), + (6633, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6632, 6634), + (6634, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6633, 10070), + (6635, 6635, 6635, 6635, 6635, 7, 70, 16098, 41, 600, 15, -1, -1), + (6636, -1, -1, 6636, 6636, 3, 70, -1, 0, 0, 15, -1, 6637), + (6637, -1, -1, 6636, 6636, 6, 70, -1, 0, 0, 15, 6636, 6638), + (6638, -1, -1, 6636, 6636, 9, 70, -1, 0, 0, 15, 6637, 10041), + (6639, 6639, 6639, 6639, 6639, 7, 70, 16099, 42, 300, 15, -1, 15173), + (6640, 6640, 6640, 6640, 6640, 7, 81, 16100, 43, 60, 15, -1, 12585), + (6641, -1, -1, 6641, 6641, 7, 81, -1, 0, 0, 15, -1, 6642), + (6642, -1, -1, 6641, 6641, 8, 83, -1, 0, 0, 15, 6641, 6643), + (6643, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 15, 6642, 10075), + (6644, 6644, 6644, 6644, 6644, 2, 70, 16104, 44, 20, 15, -1, 12586), + (6645, 6645, 6645, 6645, 6645, 6, 80, 16105, 45, 60, 15, -1, 13107), + (6646, 6646, 6646, 6646, 6646, 6, 70, 16106, 46, 6, 15, -1, -1), + (6660, -1, -1, 1307, 1307, 5, 73, -1, 0, 0, 15, 1311, 6661), + (6661, -1, -1, 1307, 1307, 5, 74, -1, 0, 0, 15, 6660, 6662), + (6662, -1, -1, 1307, 1307, 5, 75, -1, 0, 0, 15, 6661, 13210), + (6663, 6663, 6663, 6663, 6663, 7, 73, 16107, 59, 600, 15, -1, 6664), + (6664, 6663, 6663, 6663, 6663, 7, 75, 16108, 59, 600, 15, 6663, 6665), + (6665, 6663, 6663, 6663, 6663, 7, 77, 16109, 59, 600, 15, 6664, 10162), + (6666, -1, -1, 6666, 6666, 8, 81, -1, 0, 0, 15, -1, 6667), + (6667, -1, -1, 6666, 6666, 8, 83, -1, 0, 0, 15, 6666, -1), + (6668, -1, -1, 6668, 6668, 3, 76, -1, 0, 0, 15, -1, 6669), + (6669, -1, -1, 6668, 6668, 3, 77, -1, 0, 0, 15, 6668, 6670), + (6670, -1, -1, 6668, 6668, 3, 78, -1, 0, 0, 15, 6669, -1), + (6671, 6671, 6671, 6671, 6671, 4, 65, 16148, 60, 60, 15, -1, -1), + (6672, 6672, 6672, 6672, 6672, 4, 67, 16149, 60, 60, 15, -1, -1), + (6673, 6673, 6673, 6673, 6673, 4, 69, 16150, 60, 60, 15, -1, -1), + (6674, 6674, 6674, 6674, 6674, 4, 71, 16151, 60, 60, 15, -1, -1), + (6675, 6675, 6675, 6675, 6675, 4, 73, 16152, 60, 60, 15, -1, -1), + (6676, 6676, 6676, 6676, 6676, 4, 75, 16153, 60, 60, 15, -1, -1), + (6691, 6691, 6691, 6691, 6691, 9, 81, 16114, 41, 30, 15, -1, -1), + (6692, 6692, 6692, 6692, 6692, 7, 65, 16115, 42, 600, 15, -1, 6693), + (6693, 6692, 6692, 6692, 6692, 7, 70, 16116, 42, 600, 15, 6692, 6694), + (6694, 6692, 6692, 6692, 6692, 7, 75, 16117, 42, 600, 15, 6693, 6695), + (6695, 6692, 6692, 6692, 6692, 7, 80, 16118, 42, 600, 15, 6694, 6696), + (6696, 6692, 6692, 6692, 6692, 7, 85, 16119, 42, 600, 15, 6695, 5342), + (6697, -1, -1, 6697, 6697, 7, 65, -1, 0, 0, 15, -1, 6698), + (6698, -1, -1, 6697, 6697, 7, 70, -1, 0, 0, 15, 6697, 6699), + (6699, -1, -1, 6697, 6697, 7, 75, -1, 0, 0, 15, 6698, 6700), + (6700, -1, -1, 6697, 6697, 7, 80, -1, 0, 0, 15, 6699, 6701), + (6701, -1, -1, 6697, 6697, 7, 85, -1, 0, 0, 15, 6700, -1), + (6702, 6702, 6702, 6702, 6702, 9, 75, 16120, 43, 120, 15, -1, -1), + (6703, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, -1, 6704), + (6704, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, 6703, 6705), + (6705, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, 6704, 10176), + (6706, 6706, 6706, 6706, 6706, 7, 75, 16121, 44, 600, 15, -1, 6707), + (6707, 6706, 6706, 6706, 6706, 7, 80, 16122, 44, 600, 15, 6706, 6708), + (6708, 6706, 6706, 6706, 6706, 7, 85, 16123, 44, 600, 15, 6707, 10179), + (6709, -1, -1, 6709, 6709, 3, 60, -1, 0, 0, 15, -1, 6710), + (6710, -1, -1, 6709, 6709, 3, 61, -1, 0, 0, 15, 6709, 6711), + (6711, -1, -1, 6709, 6709, 3, 62, -1, 0, 0, 15, 6710, -1), + (6712, -1, -1, 6712, 6712, 7, 65, -1, 0, 0, 15, -1, 6713), + (6713, -1, -1, 6712, 6712, 7, 70, -1, 0, 0, 15, 6712, 6714), + (6714, -1, -1, 6712, 6712, 7, 75, -1, 0, 0, 15, 6713, 6715), + (6715, -1, -1, 6712, 6712, 7, 80, -1, 0, 0, 15, 6714, 6716), + (6716, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 15, 6715, 10182), + (6750, 6750, 6750, 6750, 6750, 9, 85, 16127, 60, 120, 15, -1, 13899), + (6751, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, -1, 6752), + (6752, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6751, 6753), + (6753, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6752, 6768), + (6754, 6754, 6754, 6754, 6754, 7, 70, 16130, 41, 1200, 15, -1, 10053), + (6755, 6755, 6755, 6755, 6755, 7, 81, 16131, 42, 900, 15, -1, 6756), + (6756, 6755, 6755, 6755, 6755, 9, 83, 16132, 42, 900, 15, 6755, 6757), + (6757, 6755, 6755, 6755, 6755, 12, 85, 16133, 42, 900, 15, 6756, 13542), + (6758, 6758, 6758, 6758, 6758, 3, 81, 16134, 43, 900, 15, -1, 6759), + (6759, 6758, 6758, 6758, 6758, 6, 83, 16135, 43, 900, 15, 6758, 6760), + (6760, 6758, 6758, 6758, 6758, 9, 85, 16136, 43, 900, 15, 6759, 10054), + (6761, -1, -1, 6761, 6761, 3, 65, -1, 0, 0, 15, -1, 6762), + (6762, -1, -1, 6761, 6761, 6, 65, -1, 0, 0, 15, 6761, 6763), + (6763, -1, -1, 6761, 6761, 9, 65, -1, 0, 0, 15, 6762, 6085), + (6764, 6764, 6764, 6764, 6764, 7, 75, 16137, 52, 600, 15, -1, 10057), + (6765, -1, -1, 6765, 6765, 3, 70, -1, 0, 0, 15, -1, 6766), + (6766, -1, -1, 6765, 6765, 6, 75, -1, 0, 0, 15, 6765, 6767), + (6767, -1, -1, 6765, 6765, 9, 80, -1, 0, 0, 15, 6766, 10058), + (6768, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6753, 6769), + (6769, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6768, 10769), + (6791, -1, -1, 6791, 6791, 6, 75, -1, 0, 0, 15, -1, 6792), + (6792, -1, -1, 6791, 6791, 6, 80, -1, 0, 0, 15, 6791, 6793), + (6793, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 15, 6792, 10044), + (6794, 6794, 6794, 6794, 6794, 6, 75, 16142, 41, 60, 15, -1, -1), + (6815, 6815, 6815, 6815, 6815, 8, 75, 16144, 60, 600, 15, -1, 6816), + (6816, 6815, 6815, 6815, 6815, 8, 80, 16145, 60, 600, 15, 6815, 6817), + (6817, 6815, 6815, 6815, 6815, 8, 85, 16146, 60, 600, 15, 6816, 10200), + (6818, 6818, 6818, 6818, 6818, 6, 70, 16147, 44, 20, 15, -1, -1), + (6819, -1, -1, 6819, 6819, 6, 72, -1, 0, 0, 15, -1, 6820), + (6820, -1, -1, 6819, 6819, 6, 74, -1, 0, 0, 15, 6819, 6821), + (6821, -1, -1, 6819, 6819, 6, 76, -1, 0, 0, 15, 6820, 10203), + (6822, 6822, 6822, 6822, 6822, 12, 80, 16154, 42, 120, 15, -1, 13683), + (6823, -1, -1, 6823, 6823, 4, 65, -1, 0, 0, 15, -1, 6824), + (6824, -1, -1, 6823, 6823, 4, 67, -1, 0, 0, 15, 6823, 6825), + (6825, -1, -1, 6823, 6823, 4, 69, -1, 0, 0, 15, 6824, 6826), + (6826, -1, -1, 6823, 6823, 4, 71, -1, 0, 0, 15, 6825, 6827), + (6827, -1, -1, 6823, 6823, 4, 73, -1, 0, 0, 15, 6826, 10206), + (6828, 6828, 6828, 6828, 6828, 12, 80, 16155, 43, 60, 15, -1, 10208), + (6870, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, -1, 6871), + (6871, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, 6870, 6872), + (6872, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, 6871, 10130), + (6873, -1, -1, 255, 255, 3, 76, -1, 0, 0, 15, -1, 6874), + (6874, -1, -1, 255, 255, 6, 76, -1, 0, 0, 15, 6873, 6875), + (6875, -1, -1, 255, 255, 9, 76, -1, 0, 0, 15, 6874, 10133), + (6876, -1, -1, 6375, 6375, 6, 76, -1, 0, 0, 15, -1, 6877), + (6877, -1, -1, 6375, 6375, 6, 77, -1, 0, 0, 15, 6876, 6878), + (6878, -1, -1, 6375, 6375, 6, 78, -1, 0, 0, 15, 6877, 10136), + (6879, -1, -1, 649, 649, 2, 66, -1, 0, 0, 15, -1, 6880), + (6880, -1, -1, 649, 649, 4, 68, -1, 0, 0, 15, 6879, 6881), + (6881, -1, -1, 649, 649, 6, 70, -1, 0, 0, 15, 6880, -1), + (6882, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, -1, 6883), + (6883, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, 6882, 6884), + (6884, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, 6883, -1), + (6900, -1, -1, 6935, 6935, 6, 81, -1, 0, 0, 16, 6937, 6901), + (6901, -1, -1, 6935, 6935, 6, 82, -1, 0, 0, 16, 6900, 6902), + (6902, -1, -1, 6935, 6935, 6, 83, -1, 0, 0, 16, 6901, 6903), + (6903, -1, -1, 6935, 6935, 6, 84, -1, 0, 0, 16, 6902, 6904), + (6904, -1, -1, 6935, 6935, 6, 85, -1, 0, 0, 16, 6903, 14196), + (6905, -1, -1, 551, 551, 5, 81, -1, 0, 0, 16, 1637, 6906), + (6906, -1, -1, 551, 551, 5, 83, -1, 0, 0, 16, 6905, 6907), + (6907, -1, -1, 551, 551, 5, 85, -1, 0, 0, 16, 6906, 12843), + (6908, -1, -1, 6908, 6908, 6, 81, -1, 0, 0, 16, -1, 6909), + (6909, -1, -1, 6908, 6908, 6, 83, -1, 0, 0, 16, 6908, 6910), + (6910, -1, -1, 6908, 6908, 6, 85, -1, 0, 0, 16, 6909, 14199), + (6911, -1, -1, 1143, 1143, 5, 65, -1, 0, 0, 16, 1168, 6912), + (6912, -1, -1, 1143, 1143, 7, 65, -1, 0, 0, 16, 6911, 6913), + (6913, -1, -1, 1143, 1143, 9, 65, -1, 0, 0, 16, 6912, -1), + (6930, 6930, 6930, 6930, 6930, 12, 80, 16156, 13, 60, 15, -1, -1), + (6931, 6931, 6931, 6931, 6931, 12, 85, 16157, 41, 600, 15, -1, 10319), + (6932, 6932, 6932, 6932, 6932, 7, 81, 16158, 42, 1200, 15, -1, 6933), + (6933, 6932, 6932, 6932, 6932, 7, 83, 16159, 42, 1200, 15, 6932, 6934), + (6934, 6932, 6932, 6932, 6932, 7, 85, 16160, 42, 1200, 15, 6933, 10320), + (6935, -1, -1, 6935, 6935, 6, 75, -1, 0, 0, 15, -1, 6936), + (6936, -1, -1, 6935, 6935, 6, 77, -1, 0, 0, 15, 6935, 6937), + (6937, -1, -1, 6935, 6935, 6, 79, -1, 0, 0, 15, 6936, 6900), + (6938, -1, -1, 6938, 6938, 7, 81, -1, 0, 0, 15, -1, 6939), + (6939, -1, -1, 6938, 6938, 7, 83, -1, 0, 0, 15, 6938, 6940), + (6940, -1, -1, 6938, 6938, 7, 85, -1, 0, 0, 15, 6939, -1), + (6941, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, -1, 6942), + (6942, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6941, 6943), + (6943, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6942, 6944), + (6944, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6943, 6945), + (6945, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6944, -1), + (6970, 6970, 6970, 6970, 6970, 6, 70, 16167, 61, 6, 15, -1, -1), + (6971, 6971, 6971, 6971, 6971, 7, 78, 16168, 41, 600, 15, -1, 6972), + (6972, 6971, 6971, 6971, 6971, 7, 80, 16169, 41, 600, 15, 6971, 6973), + (6973, 6971, 6971, 6971, 6971, 7, 82, 16170, 41, 600, 15, 6972, 10288), + (6974, -1, -1, 6974, 6974, 5, 81, -1, 0, 0, 15, -1, 6975), + (6975, -1, -1, 6974, 6974, 5, 83, -1, 0, 0, 15, 6974, 6976), + (6976, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 15, 6975, 10291), + (6977, -1, -1, 6977, 6977, 5, 81, -1, 0, 0, 15, -1, 6978), + (6978, -1, -1, 6977, 6977, 5, 83, -1, 0, 0, 15, 6977, 6979), + (6979, -1, -1, 6977, 6977, 5, 85, -1, 0, 0, 15, 6978, 12840), + (6980, -1, -1, 6980, 6980, 5, 81, -1, 0, 0, 15, -1, 6981), + (6981, -1, -1, 6980, 6980, 5, 83, -1, 0, 0, 15, 6980, 6982), + (6982, -1, -1, 6980, 6980, 5, 85, -1, 0, 0, 15, 6981, 12834), + (6983, 6983, 6983, 6983, 6983, 7, 83, 16439, 66, 720, 15, -1, 16246), + (6984, 6984, 6984, 6984, 6984, 6, 73, 16172, 60, 60, 15, -1, 10294), + (6985, 6985, 6985, 6985, 6985, 6, 73, 16173, 60, 60, 15, -1, 10295), + (6986, 6986, 6986, 6986, 6986, 6, 73, 16174, 60, 60, 15, -1, 10296), + (6987, -1, -1, 6987, 6987, 12, 81, -1, 0, 0, 15, -1, -1), + (6988, -1, -1, 6988, 6988, 5, 83, 0, 0, 0, 16, -1, 6989), + (6989, -1, -1, 6988, 6988, 5, 84, 0, 0, 0, 16, 6988, 6990), + (6990, -1, -1, 6988, 6988, 5, 83, 0, 0, 0, 16, 6989, 14278), + (7000, 7000, 7000, 7000, 7000, 4, 65, 12748, 31, 600, 3, -1, -1), + (7002, 7002, 7002, 7002, 7002, 4, 65, 12750, 31, 600, 3, -1, -1), + (7003, 7003, 7003, 7003, 7003, 4, 65, 12751, 31, 600, 3, -1, -1), + (7004, 7004, 7004, 7004, 7004, 4, 65, 12752, 31, 300, 3, -1, -1), + (7005, -1, -1, 7005, 7005, 2, 73, -1, 0, 0, 15, -1, 7006), + (7006, -1, -1, 7005, 7005, 2, 74, -1, 0, 0, 15, 7005, 7007), + (7007, -1, -1, 7005, 7005, 2, 75, -1, 0, 0, 15, 7006, 15632), + (7008, -1, -1, 1604, 1604, 9, 81, -1, 0, 0, 16, 7133, 7009), + (7009, -1, -1, 1604, 1604, 12, 83, -1, 0, 0, 16, 7008, 12612), + (7010, -1, -1, 7010, 7010, 6, 81, -1, 0, 0, 16, -1, 7011), + (7011, -1, -1, 7010, 7010, 6, 83, -1, 0, 0, 16, 7010, 7012), + (7012, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7011, 7013), + (7013, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7012, 7014), + (7014, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7013, 7015), + (7015, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7014, 13533), + (7016, 7016, 7016, 7016, 7016, 5, 85, 21658, 31, 600, 3, -1, -1), + (7017, 7017, 7017, 7017, 7017, 5, 85, 21659, 31, 600, 3, -1, -1), + (7018, 7018, 7018, 7018, 7018, 5, 85, 21660, 31, 600, 3, -1, -1), + (7019, 7019, 7019, 7019, 7019, 5, 85, 21661, 31, 600, 3, -1, -1), + (7020, 7020, 7020, 7020, 7020, 0, 85, 21658, 31, 600, 3, -1, -1), + (7021, 7021, 7021, 7021, 7021, 0, 85, 21659, 31, 600, 3, -1, -1), + (7022, 7022, 7022, 7022, 7022, 0, 85, 21660, 31, 600, 3, -1, -1), + (7023, 7023, 7023, 7023, 7023, 0, 85, 21661, 31, 600, 3, -1, -1), + (7024, 7024, 7024, 7024, 7024, 0, 0, 9475, 31, 600, 12, -1, -1), + (7025, 7025, 7025, 7025, 7025, 0, 0, 9477, 31, 600, 12, -1, -1), + (7026, 7026, 7026, 7026, 7026, 0, 0, 9478, 31, 600, 12, -1, -1), + (7027, 7027, 7027, 7027, 7027, 0, 0, 9479, 31, 600, 12, -1, -1), + (7028, 7028, 7028, 7028, 7028, 0, 0, 12748, 31, 600, 3, -1, -1), + (7030, 7030, 7030, 7030, 7030, 0, 0, 12750, 31, 600, 3, -1, -1), + (7031, 7031, 7031, 7031, 7031, 0, 0, 12751, 31, 600, 3, -1, -1), + (7032, 7032, 7032, 7032, 7032, 0, 0, 12752, 31, 300, 3, -1, -1), + (7033, -1, -1, 7033, 7033, 6, 85, 0, 0, 0, 16, -1, 7034), + (7034, -1, -1, 7033, 7033, 9, 85, 0, 0, 0, 16, 7033, 7035), + (7035, -1, -1, 7033, 7033, 12, 85, 0, 0, 0, 16, 7034, 15746), + (7036, -1, -1, 7036, 7036, 7, 81, -1, 0, 0, 16, -1, 7037), + (7037, -1, -1, 7036, 7036, 9, 81, -1, 0, 0, 16, 7036, 7038), + (7038, -1, -1, 7036, 7036, 12, 81, -1, 0, 0, 16, 7037, 10579), + (7050, -1, -1, 446, 735, 5, 67, -1, 0, 0, 8, 448, 7051), + (7051, -1, -1, 446, 735, 5, 68, -1, 0, 0, 8, 7050, 7052), + (7052, -1, -1, 446, 735, 5, 69, -1, 0, 0, 8, 7051, 7053), + (7053, -1, -1, 446, 735, 7, 72, -1, 0, 0, 12, 7052, 7054), + (7054, -1, -1, 446, 735, 7, 73, -1, 0, 0, 12, 7053, 7055), + (7055, -1, -1, 446, 735, 7, 74, -1, 0, 0, 12, 7054, 7063), + (7056, -1, -1, 735, 735, 5, 67, -1, 0, 0, 8, 737, 7057), + (7057, -1, -1, 735, 735, 5, 68, -1, 0, 0, 8, 7056, 7058), + (7058, -1, -1, 735, 735, 5, 69, -1, 0, 0, 8, 7057, 7059), + (7059, -1, -1, 735, 735, 7, 72, -1, 0, 0, 12, 7058, 7060), + (7060, -1, -1, 735, 735, 7, 73, -1, 0, 0, 12, 7059, 7061), + (7061, -1, -1, 735, 735, 7, 74, -1, 0, 0, 12, 7060, 7066), + (7062, -1, -1, 7062, 7062, 3, 51, -1, 0, 0, 0, -1, -1), + (7063, -1, -1, 446, 735, 8, 76, -1, 0, 0, 14, 7055, 7064), + (7064, -1, -1, 446, 735, 8, 77, -1, 0, 0, 14, 7063, 7065), + (7065, -1, -1, 446, 735, 8, 78, -1, 0, 0, 14, 7064, 7622), + (7066, -1, -1, 735, 735, 8, 76, -1, 0, 0, 14, 7061, 7067), + (7067, -1, -1, 735, 735, 8, 77, -1, 0, 0, 14, 7066, 7068), + (7068, -1, -1, 735, 735, 8, 78, -1, 0, 0, 14, 7067, 7625), + (7069, 7069, 7069, 7069, 7069, 3, 71, 13219, 39, 7, 14, -1, -1), + (7100, -1, -1, 7100, 7100, 6, 76, -1, 0, 0, 14, -1, 7101), + (7101, -1, -1, 7100, 7100, 6, 77, -1, 0, 0, 14, 7100, 7102), + (7102, -1, -1, 7100, 7100, 6, 78, -1, 0, 0, 14, 7101, 7323), + (7103, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, -1, 7104), + (7104, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, 7103, 7105), + (7105, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, 7104, 7326), + (7106, -1, -1, 7106, 7106, 6, 73, -1, 0, 0, 14, -1, 7107), + (7107, -1, -1, 7106, 7106, 7, 76, -1, 0, 0, 14, 7106, 7108), + (7108, -1, -1, 7106, 7106, 10, 79, -1, 0, 0, 14, 7107, -1), + (7109, 1351, 1351, 1351, 1351, 8, 82, 13499, 5, 30, 15, 6133, 13109), + (7110, 4849, 4849, 4849, 4849, 7, 81, 13593, 7, 1800, 15, 6134, 13914), + (7111, 54006, 54006, 54006, 54006, 7, 81, 13594, 18, 180, 15, 6135, 10006), + (7112, -1, -1, 6564, 6564, 6, 78, -1, 0, 0, 15, 6285, 7113), + (7113, -1, -1, 6564, 6564, 7, 81, -1, 0, 0, 15, 7112, 7114), + (7114, -1, -1, 6564, 6564, 10, 84, -1, 0, 0, 15, 7113, 10007), + (7115, 6565, 6565, 6565, 6565, 7, 81, 13595, 17, 45, 15, 6286, 10010), + (7116, -1, -1, 489, 489, 3, 68, -1, 0, 0, 15, 491, 7117), + (7117, -1, -1, 489, 489, 3, 69, -1, 0, 0, 15, 7116, 7118), + (7118, -1, -1, 489, 489, 3, 70, -1, 0, 0, 15, 7117, -1), + (7119, 912, 912, 912, 912, 3, 71, 13496, 4, 3600, 15, 1332, 7120), + (7120, 912, 912, 912, 912, 6, 73, 13497, 4, 3600, 15, 7119, 7121), + (7121, 912, 912, 912, 912, 9, 75, 13498, 4, 3600, 15, 7120, 10011), + (7122, -1, -1, 4844, 4844, 5, 76, -1, 0, 0, 15, 4848, 7123), + (7123, -1, -1, 4844, 4844, 5, 77, -1, 0, 0, 15, 7122, 7124), + (7124, -1, -1, 4844, 4844, 5, 78, -1, 0, 0, 15, 7123, 7125), + (7125, -1, -1, 4844, 4844, 5, 79, -1, 0, 0, 15, 7124, 7126), + (7126, -1, -1, 4844, 4844, 5, 80, -1, 0, 0, 15, 7125, 7686), + (7127, 4860, 4860, 4860, 4860, 12, 85, 13599, 13, 60, 15, 5606, -1), + (7128, -1, -1, 492, 492, 2, 68, -1, 0, 0, 15, 494, 7129), + (7129, -1, -1, 492, 492, 2, 69, -1, 0, 0, 15, 7128, 7130), + (7130, -1, -1, 492, 492, 2, 70, -1, 0, 0, 15, 7129, 10576), + (7131, -1, -1, 1604, 1604, 7, 75, -1, 0, 0, 15, 6034, 7132), + (7132, -1, -1, 1604, 1604, 9, 77, -1, 0, 0, 15, 7131, 7133), + (7133, -1, -1, 1604, 1604, 12, 79, -1, 0, 0, 15, 7132, 7008), + (7134, -1, -1, 1543, 1543, 7, 81, -1, 0, 0, 15, 6044, 7135), + (7135, -1, -1, 1543, 1543, 9, 83, -1, 0, 0, 15, 7134, 7136), + (7136, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 15, 7135, 10165), + (7137, -1, -1, 6559, 6559, 6, 79, -1, 0, 0, 15, 6274, 7138), + (7138, -1, -1, 6559, 6559, 7, 81, -1, 0, 0, 15, 7137, 7139), + (7139, -1, -1, 6559, 6559, 10, 83, -1, 0, 0, 15, 7138, -1), + (7143, 6328, 6328, 6328, 6328, 7, 79, 13601, 10, 600, 15, 6330, 7144), + (7144, 6328, 6328, 6328, 6328, 7, 81, 13602, 10, 600, 15, 7143, 7145), + (7145, 6328, 6328, 6328, 6328, 7, 83, 13603, 10, 600, 15, 7144, 10168), + (7146, -1, -1, 878, 878, 7, 81, -1, 0, 0, 15, 6332, 7147), + (7147, -1, -1, 878, 878, 7, 83, -1, 0, 0, 15, 7146, 10171), + (7148, -1, -1, 1304, 1304, 7, 81, -1, 0, 0, 15, 6031, 7149), + (7149, -1, -1, 1304, 1304, 9, 83, -1, 0, 0, 15, 7148, 7150), + (7150, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 15, 7149, 10865), + (7151, -1, -1, 846, 846, 7, 81, -1, 0, 0, 15, 6037, 7152), + (7152, -1, -1, 846, 846, 9, 83, -1, 0, 0, 15, 7151, 7153), + (7153, -1, -1, 846, 846, 12, 85, -1, 0, 0, 15, 7152, 10173), + (7154, 1352, 1352, 1352, 1352, 6, 81, 13613, 3, 60, 15, 6318, 7155), + (7155, 1352, 1352, 1352, 1352, 6, 83, 13614, 3, 60, 15, 7154, 7156), + (7156, 1352, 1352, 1352, 1352, 6, 85, 13615, 3, 60, 15, 7155, 10113), + (7157, 1358, 1358, 1358, 1358, 6, 81, 13610, 3, 60, 15, 6312, 7158), + (7158, 1358, 1358, 1358, 1358, 6, 83, 13611, 3, 60, 15, 7157, 7159), + (7159, 1358, 1358, 1358, 1358, 6, 85, 13612, 3, 60, 15, 7158, 10116), + (7160, -1, -1, 4801, 4801, 6, 79, -1, 0, 0, 15, 4803, 7161), + (7161, -1, -1, 4801, 4801, 6, 81, -1, 0, 0, 15, 7160, 7162), + (7162, -1, -1, 4801, 4801, 6, 83, -1, 0, 0, 15, 7161, 10122), + (7163, -1, -1, 820, 820, 5, 81, -1, 0, 0, 15, 5919, 7164), + (7164, -1, -1, 820, 820, 5, 83, -1, 0, 0, 15, 7163, 7165), + (7165, -1, -1, 820, 820, 5, 85, -1, 0, 0, 15, 7164, 10660), + (7166, -1, -1, 6343, 6343, 6, 79, -1, 0, 0, 15, 6345, 7167), + (7167, -1, -1, 6343, 6343, 6, 81, -1, 0, 0, 15, 7166, 7168), + (7168, -1, -1, 6343, 6343, 6, 83, -1, 0, 0, 15, 7167, -1), + (7169, -1, -1, 6020, 6020, 2, 81, -1, 0, 0, 15, 6059, 7170), + (7170, -1, -1, 6020, 6020, 2, 83, -1, 0, 0, 15, 7169, 7171), + (7171, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 15, 7170, 10663), + (7172, 1355, 1355, 1355, 1355, 6, 81, 13607, 3, 60, 15, 5916, 7173), + (7173, 1355, 1355, 1355, 1355, 6, 83, 13608, 3, 60, 15, 7172, 7174), + (7174, 1355, 1355, 1355, 1355, 6, 85, 13609, 3, 60, 15, 7173, 10119), + (7175, -1, -1, 611, 611, 2, 68, -1, 0, 0, 15, 615, 7176), + (7176, -1, -1, 611, 611, 2, 69, -1, 0, 0, 15, 7175, 7177), + (7177, -1, -1, 611, 611, 2, 70, -1, 0, 0, 15, 7176, 10124), + (7178, 4854, 4854, 4854, 4854, 7, 81, 13616, 8, 600, 15, 5766, 7179), + (7179, 4854, 4854, 4854, 4854, 9, 83, 13617, 8, 600, 15, 7178, 7180), + (7180, 4854, 4854, 4854, 4854, 12, 85, 13618, 8, 600, 15, 7179, 10323), + (7184, 1348, 1348, 1348, 1348, 12, 91, 13622, 0, 3600, 18, 5772, 7185), + (7187, 1178, 1178, 1178, 1178, 7, 81, 13625, 4, 900, 15, 5781, 7188), + (7188, 1178, 1178, 1178, 1178, 8, 82, 13626, 4, 900, 15, 7187, 7189), + (7189, 1178, 1178, 1178, 1178, 9, 83, 13627, 4, 900, 15, 7188, 10326), + (7196, -1, -1, 5776, 5776, 7, 81, -1, 0, 0, 16, 5778, 7197), + (7197, -1, -1, 5776, 5776, 9, 83, -1, 0, 0, 16, 7196, 7198), + (7198, -1, -1, 5776, 5776, 12, 85, -1, 0, 0, 16, 7197, 13043), + (7199, 1274, 1274, 1274, 1274, 9, 83, 13657, 9, 540, 15, 5949, 7200), + (7200, 1274, 1274, 1274, 1274, 10, 84, 13658, 9, 540, 15, 7199, 7201), + (7201, 1274, 1274, 1274, 1274, 12, 85, 13659, 9, 540, 15, 7200, 10209), + (7202, 1510, -1, 1510, 1510, 12, 75, 13664, 13, 2160, 15, 1510, 10212), + (7203, 184, 184, 184, 184, 10, 84, 13660, 5, 4320, 15, 5953, -1), + (7204, -1, -1, 5264, 5264, 7, 81, -1, 0, 0, 15, 5943, 7205), + (7205, -1, -1, 5264, 5264, 8, 82, -1, 0, 0, 15, 7204, 7206), + (7206, -1, -1, 5264, 5264, 9, 83, -1, 0, 0, 15, 7205, 7207), + (7207, -1, -1, 5264, 5264, 10, 84, -1, 0, 0, 15, 7206, 7208), + (7208, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 15, 7207, 10213), + (7209, 4927, 4927, 4927, 4927, 9, 76, 13656, 14, 600, 15, 4927, 10218), + (7210, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 5329, 7211), + (7211, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7210, 7212), + (7212, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7211, 7213), + (7213, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7212, 7214), + (7214, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7213, 10219), + (7215, -1, -1, 4861, 4861, 9, 83, -1, 0, 0, 15, 5956, 7216), + (7216, -1, -1, 4861, 4861, 12, 85, -1, 0, 0, 15, 7215, 7682), + (7217, 967, 967, 967, 967, 6, 81, 13661, 10, 1800, 15, 6466, 7218), + (7218, 967, 967, 967, 967, 6, 82, 13662, 10, 1800, 15, 7217, 7219), + (7219, 967, 967, 967, 967, 6, 83, 13663, 10, 1800, 15, 7218, 10224), + (7220, -1, -1, 5295, 5295, 6, 81, -1, 0, 0, 15, 6533, 7221), + (7221, -1, -1, 5295, 5295, 6, 83, -1, 0, 0, 15, 7220, 7222), + (7222, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 15, 7221, 10227), + (7223, 6290, 6290, 6290, 6290, 7, 81, 13689, 0, 1, 15, 6295, 7224), + (7224, 6290, 6290, 6290, 6290, 9, 83, 13690, 0, 1, 15, 7223, 7225), + (7225, 6290, 6290, 6290, 6290, 12, 85, 13691, 0, 1, 15, 7224, 11064), + (7226, 619, 619, 619, 619, 6, 78, 13686, 6, 900, 15, 6298, 7227), + (7227, 619, 619, 619, 619, 6, 78, 13687, 6, 900, 15, 7226, 7228), + (7228, 619, 619, 619, 619, 6, 78, 13688, 6, 900, 15, 7227, 10230), + (7229, 4944, -1, 4944, 4944, 7, 81, 13677, 0, 1, 15, 6157, 7230), + (7230, 4944, -1, 4944, 4944, 9, 83, 13678, 0, 1, 15, 7229, 7231), + (7231, 4944, -1, 4944, 4944, 12, 85, 13679, 0, 1, 15, 7230, 11067), + (7232, -1, -1, 1210, 1210, 7, 81, -1, 0, 0, 15, 5576, 7233), + (7233, -1, -1, 1210, 1210, 9, 83, -1, 0, 0, 15, 7232, 7234), + (7234, -1, -1, 1210, 1210, 12, 85, -1, 0, 0, 15, 7233, 12523), + (7235, 923, 923, 923, 923, 9, 82, 13673, 8, 60, 15, 6151, -1), + (7236, 922, 922, 922, 922, 9, 83, 13672, 8, 60, 15, 6150, -1), + (7237, 516, 516, 516, 516, 6, 77, 13692, 5, 480, 15, 6398, 10233), + (7238, 155, 155, 155, 155, 12, 82, 13693, 8, 60, 15, 5289, 14324), + (7239, 1334, 1334, 1334, 1334, 9, 83, 13674, 11, 4320, 15, 6154, 7240), + (7240, 1334, 1334, 1334, 1334, 10, 84, 13675, 11, 4320, 15, 7239, 7241), + (7241, 1334, 1334, 1334, 1334, 12, 85, 13676, 11, 4320, 15, 7240, 10234), + (7242, 1478, -1, 1478, 1478, 9, 83, 13680, 0, 1, 15, 6163, 7243), + (7243, 1478, -1, 1478, 1478, 10, 84, 13681, 0, 1, 15, 7242, 7244), + (7244, 1478, -1, 1478, 1478, 12, 85, 13682, 0, 1, 15, 7243, 11070), + (7245, 921, 921, 921, 921, 9, 84, 13671, 8, 60, 15, 6149, -1), + (7246, 4915, 4915, 4915, 4915, 7, 81, 13683, 7, 4320, 15, 5609, 7247), + (7247, 4915, 4915, 4915, 4915, 9, 83, 13684, 7, 4320, 15, 7246, 7248), + (7248, 4915, 4915, 4915, 4915, 12, 85, 13685, 7, 4320, 15, 7247, -1), + (7249, 167, 167, 167, 167, 10, 84, 13703, 14, 900, 15, 5879, 8343), + (7250, 520, 520, 520, 520, 12, 81, 13704, 6, 540, 15, 5885, 7251), + (7251, 520, 520, 520, 520, 12, 83, 13705, 6, 540, 15, 7250, 7252), + (7252, 520, 520, 520, 520, 12, 85, 13706, 6, 540, 15, 7251, 10252), + (7253, 4903, 4903, 4903, 4903, 9, 81, 13707, 9, 1320, 15, 5892, 10255), + (7254, 4906, 4906, 4906, 4906, 9, 81, 13708, 9, 1320, 15, 5893, 10256), + (7255, 4909, 4909, 4909, 4909, 9, 81, 13709, 16, 1320, 15, 5894, 10257), + (7256, 4912, 4912, 4912, 4912, 9, 81, 13710, 16, 1320, 15, 5895, 10258), + (7257, 616, 616, 616, 616, 6, 78, 13711, 7, 900, 15, 6256, 7258), + (7258, 616, 616, 616, 616, 7, 81, 13712, 7, 900, 15, 7257, 7259), + (7259, 616, 616, 616, 616, 10, 84, 13713, 7, 900, 15, 7258, 10259), + (7260, -1, -1, 1504, 1504, 5, 81, -1, 0, 0, 15, 5882, 7261), + (7261, -1, -1, 1504, 1504, 5, 83, -1, 0, 0, 15, 7260, 7262), + (7262, -1, -1, 1504, 1504, 5, 85, -1, 0, 0, 15, 7261, -1), + (7263, -1, -1, 1577, 1577, 7, 81, -1, 0, 0, 15, 5888, 7264), + (7264, -1, -1, 1577, 1577, 9, 83, -1, 0, 0, 15, 7263, 7265), + (7265, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 15, 7264, 10262), + (7266, 6333, 6333, 6333, 6333, 6, 64, 13714, 3, 600, 15, 6333, 13920), + (7267, -1, -1, 795, 795, 7, 81, -1, 0, 0, 15, 5891, 7268), + (7268, -1, -1, 795, 795, 9, 83, -1, 0, 0, 15, 7267, 7269), + (7269, -1, -1, 795, 795, 12, 85, -1, 0, 0, 15, 7268, 10265), + (7270, -1, -1, 790, 790, 6, 81, -1, 0, 0, 15, 5324, 7271), + (7271, -1, -1, 790, 790, 6, 82, -1, 0, 0, 15, 7270, 7272), + (7272, -1, -1, 790, 790, 6, 83, -1, 0, 0, 15, 7271, 7273), + (7273, -1, -1, 790, 790, 6, 84, -1, 0, 0, 15, 7272, 7274), + (7274, -1, -1, 790, 790, 6, 85, -1, 0, 0, 15, 7273, 12950), + (7275, 1239, 1239, 1239, 1239, 12, 85, 13735, 6, 600, 15, 5868, 13251), + (7276, 773, -1, 773, 773, 7, 81, 13726, 5, 1800, 15, 5856, 7277), + (7277, 773, -1, 773, 773, 9, 83, 13727, 5, 1800, 15, 7276, 7278), + (7278, 773, -1, 773, 773, 12, 85, 13728, 5, 1800, 15, 7277, 10564), + (7279, 6552, 6552, 6552, 6552, 5, 75, -1, 0, 0, 15, 6253, 7280), + (7280, 6552, 6552, 6552, 6552, 6, 77, -1, 0, 0, 15, 7279, 7281), + (7281, 6552, 6552, 6552, 6552, 6, 79, -1, 0, 0, 15, 7280, 7282), + (7282, 6552, 6552, 6552, 6552, 7, 81, -1, 0, 0, 15, 7281, 7283), + (7283, 6552, 6552, 6552, 6552, 9, 83, -1, 0, 0, 15, 7282, -1), + (7284, -1, -1, 781, 781, 8, 82, -1, 0, 0, 15, 5850, 13763), + (7285, 1242, 1242, 1242, 1242, 7, 81, 13723, 9, 1320, 15, 5859, 7286), + (7286, 1242, 1242, 1242, 1242, 9, 83, 13724, 9, 1320, 15, 7285, 7287), + (7287, 1242, 1242, 1242, 1242, 12, 85, 13725, 9, 1320, 15, 7286, 10271), + (7288, 4894, 4894, 4894, 4894, 6, 81, 13732, 7, 2160, 15, 6354, 7289), + (7289, 4894, 4894, 4894, 4894, 6, 82, 13733, 7, 2160, 15, 7288, 7290), + (7290, 4894, 4894, 4894, 4894, 6, 83, 13734, 7, 2160, 15, 7289, 13247), + (7291, 4931, 4931, 4931, 4931, 7, 81, 13729, 4, 600, 15, 6056, 7292), + (7292, 4931, 4931, 4931, 4931, 7, 83, 13730, 4, 600, 15, 7291, 7293), + (7293, 4931, 4931, 4931, 4931, 7, 85, 13731, 4, 600, 15, 7292, 10274), + (7294, 4935, 4935, 4935, 4935, 7, 76, 13722, 14, 300, 15, 4935, 10277), + (7295, 4934, 4934, 4934, 4934, 7, 76, 13721, 13, 300, 15, 4934, 10278), + (7296, 517, 517, 517, 517, 5, 73, 13718, 12, 600, 15, 1444, 7297), + (7297, 517, 517, 517, 517, 5, 74, 13719, 12, 600, 15, 7296, 7298), + (7298, 517, 517, 517, 517, 5, 75, 13720, 12, 600, 15, 7297, 10279), + (7299, 1383, 1383, 1383, 1383, 12, 85, 16000, 6, 300, 15, 5789, 10014), + (7300, 1195, 1195, 1195, 1195, 9, 85, 16001, 13, 2160, 15, 5790, 10015), + (7301, 131, 131, 131, 131, 8, 82, 16002, 4, 900, 15, 5793, 7302), + (7302, 131, 131, 131, 131, 9, 83, 16003, 4, 900, 15, 7301, 7303), + (7303, 131, 131, 131, 131, 10, 84, 16004, 4, 900, 15, 7302, 10016), + (7304, 1192, 1192, 1192, 1192, 8, 82, 16005, 12, 1320, 15, 5796, 7305), + (7305, 1192, 1192, 1192, 1192, 9, 83, 16006, 12, 1320, 15, 7304, 7306), + (7306, 1192, 1192, 1192, 1192, 10, 84, 16007, 12, 1320, 15, 7305, 10019), + (7307, 746, 746, 746, 746, 9, 83, 16008, 10, 2160, 15, 5802, 7308), + (7308, 746, 746, 746, 746, 10, 84, 16009, 10, 2160, 15, 7307, 7309), + (7309, 746, 746, 746, 746, 12, 85, 16010, 10, 2160, 15, 7308, 10022), + (7310, 1459, 1459, 1459, 1459, 7, 81, 16011, 11, 1800, 15, 5805, 7311), + (7311, 1459, 1459, 1459, 1459, 9, 83, 16012, 11, 1800, 15, 7310, 7312), + (7312, 1459, 1459, 1459, 1459, 12, 85, 16013, 11, 1800, 15, 7311, -1), + (7313, -1, -1, 6436, 6436, 6, 78, -1, 0, 0, 15, 6438, 7314), + (7314, -1, -1, 6436, 6436, 6, 80, -1, 0, 0, 15, 7313, 7315), + (7315, -1, -1, 6436, 6436, 8, 82, -1, 0, 0, 15, 7314, -1), + (7316, -1, -1, 468, 468, 2, 72, -1, 0, 0, 15, 6440, 7317), + (7317, -1, -1, 468, 468, 2, 74, -1, 0, 0, 15, 7316, 17288), + (7318, -1, -1, 6601, 6601, 6, 77, -1, 0, 0, 15, 6605, 7319), + (7319, -1, -1, 6601, 6601, 6, 78, -1, 0, 0, 15, 7318, 7320), + (7320, -1, -1, 6601, 6601, 6, 79, -1, 0, 0, 15, 7319, 7321), + (7321, -1, -1, 6601, 6601, 6, 80, -1, 0, 0, 15, 7320, 7322), + (7322, -1, -1, 6601, 6601, 6, 81, -1, 0, 0, 15, 7321, 10025), + (7323, -1, -1, 7100, 7100, 6, 81, -1, 0, 0, 15, 7102, 7324), + (7324, -1, -1, 7100, 7100, 6, 82, -1, 0, 0, 15, 7323, 7325), + (7325, -1, -1, 7100, 7100, 6, 83, -1, 0, 0, 15, 7324, 8427), + (7326, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7105, 7327), + (7327, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7326, 7328), + (7328, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7327, 10750), + (7329, 534, 534, 534, 534, 7, 81, 16021, 4, 2160, 15, 5971, 7330), + (7330, 534, 534, 534, 534, 9, 83, 16022, 4, 2160, 15, 7329, 7331), + (7331, 534, 534, 534, 534, 12, 85, 16023, 4, 2160, 15, 7330, 10047), + (7332, 5095, 5095, 5095, 5095, 7, 81, 16024, 10, 900, 15, 5977, 7333), + (7333, 5095, 5095, 5095, 5095, 9, 83, 16025, 10, 900, 15, 7332, 7334), + (7334, 5095, 5095, 5095, 5095, 12, 85, 16026, 10, 900, 15, 7333, 10640), + (7335, 5984, 5984, 5984, 5984, 12, 85, 16027, 2, 30, 15, 5984, 7710), + (7336, -1, -1, 6395, 6395, 7, 81, -1, 0, 0, 15, 6397, 7337), + (7337, -1, -1, 6395, 6395, 7, 82, -1, 0, 0, 15, 7336, 7338), + (7338, -1, -1, 6395, 6395, 7, 83, -1, 0, 0, 15, 7337, 10050), + (7339, 188, 188, 188, 188, 9, 78, 16020, 2, 30, 14, 5044, 7662), + (7340, 7850, 7850, 7850, 7850, 8, 81, 16028, 39, 4320, 0, 7865, 10618), + (7341, 5007, 5007, 5007, 5007, 9, 81, 16047, 8, 2160, 15, 6427, 7342), + (7342, 5007, 5007, 5007, 5007, 9, 83, 16048, 8, 2160, 15, 7341, 7343), + (7343, 5007, 5007, 5007, 5007, 9, 85, 16049, 8, 2160, 15, 7342, 10061), + (7344, 545, 545, 545, 545, 7, 81, 16038, 3, 900, 15, 6002, 7345), + (7345, 545, 545, 545, 545, 9, 83, 16039, 3, 900, 15, 7344, 7346), + (7346, 545, 545, 545, 545, 12, 85, 16040, 3, 900, 15, 7345, 10758), + (7347, 1345, 1345, 1345, 1345, 8, 82, 16041, 6, 900, 15, 6010, 7348), + (7348, 1345, 1345, 1345, 1345, 9, 83, 16042, 6, 900, 15, 7347, 7349), + (7349, 1345, 1345, 1345, 1345, 10, 84, 16043, 6, 900, 15, 7348, 10740), + (7350, 6370, 6370, 6370, 6370, 6, 81, 16044, 7, 600, 15, 6372, 7351), + (7351, 6370, 6370, 6370, 6370, 6, 82, 16045, 7, 600, 15, 7350, 7352), + (7352, 6370, 6370, 6370, 6370, 6, 83, 16046, 7, 600, 15, 7351, 14112), + (7353, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 6013, 7354), + (7354, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 7353, 7355), + (7355, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 7354, -1), + (7356, -1, -1, 5248, 5248, 7, 81, -1, 0, 0, 15, 6016, 7357), + (7357, -1, -1, 5248, 5248, 9, 83, -1, 0, 0, 15, 7356, 7358), + (7358, -1, -1, 5248, 5248, 12, 85, -1, 0, 0, 15, 7357, 16170), + (7359, -1, -1, 644, 644, 7, 79, -1, 0, 0, 15, 6019, 7360), + (7360, -1, -1, 644, 644, 9, 81, -1, 0, 0, 15, 7359, 7361), + (7361, -1, -1, 644, 644, 12, 83, -1, 0, 0, 15, 7360, 13092), + (7362, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 871, 7363), + (7363, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7362, 7364), + (7364, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7363, 7365), + (7365, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7364, 7366), + (7366, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7365, 10748), + (7367, 872, 872, 872, 872, 3, 70, 16032, 5, 180, 15, 874, 7368), + (7368, 872, 872, 872, 872, 6, 70, 16033, 5, 180, 15, 7367, 7369), + (7369, 872, 872, 872, 872, 9, 70, 16034, 5, 180, 15, 7368, 10772), + (7370, 875, 875, 875, 875, 3, 70, 16035, 5, 180, 15, 877, 7371), + (7371, 875, 875, 875, 875, 6, 73, 16036, 5, 180, 15, 7370, 7372), + (7372, 875, 875, 875, 875, 9, 75, 16037, 5, 180, 15, 7371, 10775), + (7373, -1, -1, 6546, 6546, 0, 81, -1, 0, 0, 15, 6571, 7374), + (7374, -1, -1, 6546, 6546, 0, 82, -1, 0, 0, 15, 7373, 7375), + (7375, -1, -1, 6546, 6546, 0, 83, -1, 0, 0, 15, 7374, 7376), + (7376, -1, -1, 6546, 6546, 0, 84, -1, 0, 0, 15, 7375, 7377), + (7377, -1, -1, 6546, 6546, 0, 85, -1, 0, 0, 15, 7376, 13122), + (7378, -1, -1, 1608, 1608, 3, 71, -1, 0, 0, 15, 4991, 7379), + (7379, -1, -1, 1608, 1608, 6, 73, -1, 0, 0, 15, 7378, 7380), + (7380, -1, -1, 1608, 1608, 9, 75, -1, 0, 0, 15, 7379, 7381), + (7381, -1, -1, 1608, 1608, 6, 76, -1, 0, 0, 15, 7380, 7382), + (7382, -1, -1, 1608, 1608, 6, 78, -1, 0, 0, 15, 7381, 7383), + (7383, -1, -1, 1608, 1608, 6, 80, -1, 0, 0, 15, 7382, 10064), + (7384, -1, -1, 5085, 5085, 6, 81, -1, 0, 0, 15, 6408, 7385), + (7385, -1, -1, 5085, 5085, 6, 83, -1, 0, 0, 15, 7384, 7386), + (7386, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 15, 7385, 10383), + (7387, 6508, 6508, 6508, 6508, 7, 79, 16059, 38, 600, 15, 6510, 7388), + (7388, 6508, 6508, 6508, 6508, 7, 81, 16060, 38, 600, 15, 7387, 7389), + (7389, 6508, 6508, 6508, 6508, 7, 83, 16061, 38, 600, 15, 7388, 10078), + (7390, -1, -1, 589, 589, 7, 81, -1, 0, 0, 15, 6065, 7391), + (7391, -1, -1, 589, 589, 7, 83, -1, 0, 0, 15, 7390, 7392), + (7392, -1, -1, 589, 589, 7, 85, -1, 0, 0, 15, 7391, 7707), + (7393, -1, -1, 1313, 1313, 7, 81, -1, 0, 0, 15, 6071, 7394), + (7394, -1, -1, 1313, 1313, 7, 81, -1, 0, 0, 15, 7393, 7395), + (7395, -1, -1, 1313, 1313, 8, 82, -1, 0, 0, 15, 7394, 7396), + (7396, -1, -1, 1313, 1313, 9, 83, -1, 0, 0, 15, 7395, 7397), + (7397, -1, -1, 1313, 1313, 10, 84, -1, 0, 0, 15, 7396, 7398), + (7398, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 15, 7397, 10081), + (7399, -1, -1, 210, 210, 8, 82, -1, 0, 0, 15, 6074, 7400), + (7400, -1, -1, 210, 210, 9, 83, -1, 0, 0, 15, 7399, 7401), + (7401, -1, -1, 210, 210, 10, 84, -1, 0, 0, 15, 7400, 15172), + (7402, -1, -1, 895, 895, 7, 81, -1, 0, 0, 15, 6079, 7403), + (7403, -1, -1, 895, 895, 8, 82, -1, 0, 0, 15, 7402, 7404), + (7404, -1, -1, 895, 895, 9, 83, -1, 0, 0, 15, 7403, 7405), + (7405, -1, -1, 895, 895, 10, 84, -1, 0, 0, 15, 7404, 7406), + (7406, -1, -1, 895, 895, 12, 85, -1, 0, 0, 15, 7405, 10906), + (7407, -1, -1, 7407, 7407, 12, 85, 0, 0, 0, 16, -1, -1), + (7408, 1498, 1498, 1498, 1498, 7, 81, 16075, 12, 1320, 15, 5821, 7409), + (7409, 1498, 1498, 1498, 1498, 9, 83, 16076, 12, 1320, 15, 7408, 7410), + (7410, 1498, 1498, 1498, 1498, 12, 85, 16077, 12, 1320, 15, 7409, 10090), + (7411, 757, -1, 757, 757, 7, 81, 16078, 6, 1800, 15, 5824, 7412), + (7412, 757, -1, 757, 757, 9, 83, 16079, 6, 1800, 15, 7411, 7413), + (7413, 757, -1, 757, 757, 12, 85, 16080, 6, 1800, 15, 7412, 12658), + (7414, 1495, 1495, 1495, 1495, 7, 81, 16081, 30, 900, 15, 5828, 7415), + (7415, 1495, 1495, 1495, 1495, 9, 83, 16082, 30, 900, 15, 7414, 7416), + (7416, 1495, 1495, 1495, 1495, 12, 85, 16083, 30, 900, 15, 7415, 10093), + (7417, 548, 548, 548, 548, 8, 82, 16084, 5, 900, 15, 5831, 7418), + (7418, 548, 548, 548, 548, 9, 83, 16085, 5, 900, 15, 7417, 7419), + (7419, 548, 548, 548, 548, 10, 84, 16086, 5, 900, 15, 7418, 10096), + (7420, 5105, 5105, 5105, 5105, 12, 85, 16087, 11, 600, 15, 5832, 10509), + (7421, 6232, 6232, 6232, 6232, 12, 85, 16091, 18, 900, 15, 6232, -1), + (7422, 6561, 6561, 6561, 6561, 7, 81, 16088, 32, 30, 15, 6280, 7423), + (7423, 6561, 6561, 6561, 6561, 7, 81, 16089, 32, 30, 15, 7422, 7424), + (7424, 6561, 6561, 6561, 6561, 7, 81, 16090, 32, 30, 15, 7423, 10099), + (7425, 510, 510, 510, 510, 3, 66, 16072, 37, 240, 15, 512, 7426), + (7426, 510, 510, 510, 510, 3, 68, 16073, 37, 240, 15, 7425, 7427), + (7427, 510, 510, 510, 510, 3, 70, 16074, 37, 240, 15, 7426, 10102), + (7428, 6533, 6533, 6533, 6533, 10, 84, 13785, 15, 600, 15, 6200, 10139), + (7429, 6534, 6534, 6534, 6534, 9, 83, 13777, 16, 900, 15, 6201, 13524), + (7430, 1116, 1116, 1116, 1116, 7, 81, 13762, 4, 2160, 15, 5701, 7431), + (7431, 1116, 1116, 1116, 1116, 9, 83, 13763, 4, 2160, 15, 7430, 7432), + (7432, 1116, 1116, 1116, 1116, 12, 85, 13764, 4, 2160, 15, 7431, 10140), + (7433, 592, 592, 592, 592, 5, 81, 13765, 2, 18, 15, 5706, 7434), + (7434, 592, 592, 592, 592, 5, 82, 13766, 2, 18, 15, 7433, 7435), + (7435, 592, 592, 592, 592, 5, 83, 13767, 2, 18, 15, 7434, 7436), + (7436, 592, 592, 592, 592, 5, 84, 13768, 2, 18, 15, 7435, 7437), + (7437, 592, 592, 592, 592, 5, 85, 13769, 2, 18, 15, 7436, 12749), + (7438, 5298, 5298, 5298, 5298, 9, 83, 13770, 32, 1800, 15, 5709, 7439), + (7439, 5298, 5298, 5298, 5298, 10, 84, 13771, 32, 1800, 15, 7438, 7440), + (7440, 5298, 5298, 5298, 5298, 12, 85, 13772, 32, 1800, 15, 7439, 10143), + (7441, 1598, -1, 1598, 1598, 7, 81, 13773, 6, 900, 15, 5712, 7442), + (7442, 1598, -1, 1598, 1598, 9, 83, 13774, 6, 900, 15, 7441, 7443), + (7443, 1598, -1, 1598, 1598, 12, 85, 13775, 6, 900, 15, 7442, 10146), + (7444, 5020, 5020, 5020, 5020, 9, 82, 13776, 9, 300, 15, 5716, 10149), + (7445, 1110, 1110, 1110, 1110, 6, 78, 13778, 3, 2160, 15, 6402, 7446), + (7446, 1110, 1110, 1110, 1110, 6, 80, 13779, 3, 2160, 15, 7445, 7447), + (7447, 1110, 1110, 1110, 1110, 6, 81, 13780, 3, 2160, 15, 7446, 10150), + (7448, -1, -1, 6337, 6337, 6, 79, -1, 0, 0, 15, 6339, 7449), + (7449, -1, -1, 6337, 6337, 6, 81, -1, 0, 0, 15, 7448, 7450), + (7450, -1, -1, 6337, 6337, 6, 83, -1, 0, 0, 15, 7449, 10153), + (7451, -1, -1, 6340, 6340, 6, 79, -1, 0, 0, 15, 6342, 7452), + (7452, -1, -1, 6340, 6340, 6, 81, -1, 0, 0, 15, 7451, 7453), + (7453, -1, -1, 6340, 6340, 6, 83, -1, 0, 0, 15, 7452, 16306), + (7454, 5017, 5017, 5017, 5017, 3, 76, 13759, 8, 600, 15, 5019, 7455), + (7455, 5017, 5017, 5017, 5017, 6, 78, 13760, 8, 600, 15, 7454, 7456), + (7456, 5017, 5017, 5017, 5017, 9, 80, 13761, 8, 600, 15, 7455, 10156), + (7457, 1569, 1569, 1569, 1569, 7, 82, 13756, 5, 1800, 15, 5715, 7458), + (7458, 1569, 1569, 1569, 1569, 7, 83, 13757, 5, 1800, 15, 7457, 7459), + (7459, 1569, 1569, 1569, 1569, 7, 85, 13758, 5, 1800, 15, 7458, 10159), + (7460, 1327, 1327, 1327, 1327, 7, 81, 13792, 10, 900, 15, 6100, 7461), + (7461, 1327, 1327, 1327, 1327, 9, 83, 13793, 10, 900, 15, 7460, 7462), + (7462, 1327, 1327, 1327, 1327, 12, 85, 13794, 10, 900, 15, 7461, 10187), + (7463, 1520, 1520, 1520, 1520, 9, 75, 13801, 11, 900, 15, 6451, 7464), + (7464, 1520, 1520, 1520, 1520, 9, 75, 13802, 11, 900, 15, 7463, 7465), + (7465, 1520, 1520, 1520, 1520, 9, 75, 13803, 11, 900, 15, 7464, 10190), + (7466, 146, 146, 146, 146, 8, 82, 13796, 2, 180, 15, 6102, 7691), + (7467, 5109, 5109, 5109, 5109, 9, 82, 13800, 0, 1, 15, 6448, 13016), + (7468, 153, 153, 153, 153, 12, 85, 13795, 3, 2160, 15, 6101, 10193), + (7469, 528, 528, 528, 528, 7, 81, 13797, 5, 720, 15, 6105, 7470), + (7470, 528, 528, 528, 528, 9, 83, 13798, 5, 720, 15, 7469, 7471), + (7471, 528, 528, 528, 528, 12, 85, 13799, 5, 720, 15, 7470, 10194), + (7472, 5251, 5251, 5251, 5251, 7, 81, 13786, 13, 900, 15, 6094, 7473), + (7473, 5251, 5251, 5251, 5251, 9, 83, 13787, 13, 900, 15, 7472, 7474), + (7474, 5251, 5251, 5251, 5251, 12, 85, 13788, 13, 900, 15, 7473, 10197), + (7475, 513, 513, 513, 513, 7, 81, 13789, 4, 120, 15, 6097, 7476), + (7476, 513, 513, 513, 513, 9, 83, 13790, 4, 120, 15, 7475, 7477), + (7477, 513, 513, 513, 513, 12, 85, 13791, 4, 120, 15, 7476, -1), + (7478, -1, -1, 6538, 6538, 12, 85, -1, 0, 0, 15, 6211, 15421), + (7479, 1119, 1119, 1119, 1119, 7, 83, 13805, 8, 900, 15, 5736, 7480), + (7480, 1119, 1119, 1119, 1119, 8, 84, 13806, 8, 900, 15, 7479, 7481), + (7481, 1119, 1119, 1119, 1119, 9, 85, 13807, 8, 900, 15, 7480, 10297), + (7482, 723, 723, 723, 723, 7, 81, 13808, 6, 30, 15, 5737, 10300), + (7483, 5015, 5015, 5015, 5015, 12, 85, 13809, 9, 900, 15, 5741, 10301), + (7484, 289, 289, 289, 289, 12, 85, 13810, 3, 300, 15, 5742, -1), + (7485, 291, 291, 291, 291, 9, 83, 13811, 5, 900, 15, 5745, 7486), + (7486, 291, 291, 291, 291, 10, 84, 13812, 5, 900, 15, 7485, 7487), + (7487, 291, 291, 291, 291, 12, 85, 13813, 5, 900, 15, 7486, 10302), + (7488, 6218, 6218, 6218, 6218, 7, 81, 13814, 0, 1, 15, 6218, 14272), + (7489, -1, -1, 724, 724, 7, 81, -1, 0, 0, 15, 5733, 7490), + (7490, -1, -1, 724, 724, 8, 82, -1, 0, 0, 15, 7489, 7491), + (7491, -1, -1, 724, 724, 9, 83, -1, 0, 0, 15, 7490, 7492), + (7492, -1, -1, 724, 724, 10, 84, -1, 0, 0, 15, 7491, 7493), + (7493, -1, -1, 724, 724, 12, 85, -1, 0, 0, 15, 7492, 16890), + (7494, -1, -1, 729, 729, 7, 81, -1, 0, 0, 15, 5740, 7495), + (7495, -1, -1, 729, 729, 8, 82, -1, 0, 0, 15, 7494, 7496), + (7496, -1, -1, 729, 729, 9, 83, -1, 0, 0, 15, 7495, 10305), + (7497, 6380, 6380, 6380, 6380, 6, 83, 13815, 39, 120, 15, 6382, 7498), + (7498, 6380, 6380, 6380, 6380, 6, 84, 13816, 39, 120, 15, 7497, 7499), + (7499, 6380, 6380, 6380, 6380, 6, 85, 13817, 39, 120, 15, 7498, 10308), + (7500, -1, -1, 4699, 4699, 5, 61, -1, 0, 0, 15, 6540, 10788), + (7501, -1, -1, 125, 125, 6, 81, -1, 0, 0, 15, 5523, 7502), + (7502, -1, -1, 125, 125, 7, 82, -1, 0, 0, 15, 7501, 7503), + (7503, -1, -1, 125, 125, 8, 83, -1, 0, 0, 15, 7502, 7504), + (7504, -1, -1, 125, 125, 9, 84, -1, 0, 0, 15, 7503, 7505), + (7505, -1, -1, 125, 125, 10, 85, -1, 0, 0, 15, 7504, 12396), + (7506, -1, -1, 122, 122, 6, 81, -1, 0, 0, 15, 5528, 7507), + (7507, -1, -1, 122, 122, 7, 82, -1, 0, 0, 15, 7506, 7508), + (7508, -1, -1, 122, 122, 8, 83, -1, 0, 0, 15, 7507, 7509), + (7509, -1, -1, 122, 122, 9, 84, -1, 0, 0, 15, 7508, 7510), + (7510, -1, -1, 122, 122, 10, 85, -1, 0, 0, 15, 7509, 12401), + (7511, -1, -1, 1026, 1026, 5, 81, -1, 0, 0, 15, 6527, 7512), + (7512, -1, -1, 1026, 1026, 5, 82, -1, 0, 0, 15, 7511, 7513), + (7513, -1, -1, 1026, 1026, 5, 83, -1, 0, 0, 15, 7512, 7514), + (7514, -1, -1, 1026, 1026, 5, 84, -1, 0, 0, 15, 7513, 7515), + (7515, -1, -1, 1026, 1026, 5, 85, -1, 0, 0, 15, 7514, 7886), + (7516, -1, -1, 1006, 1006, 5, 71, -1, 0, 0, 15, 1010, 7517), + (7517, -1, -1, 1006, 1006, 5, 72, -1, 0, 0, 15, 7516, 7518), + (7518, -1, -1, 1006, 1006, 5, 73, -1, 0, 0, 15, 7517, 7519), + (7519, -1, -1, 1006, 1006, 5, 74, -1, 0, 0, 15, 7518, 7520), + (7520, -1, -1, 1006, 1006, 5, 75, -1, 0, 0, 15, 7519, 7837), + (7521, -1, -1, 1056, 1056, 5, 81, -1, 0, 0, 15, 6435, 7522), + (7522, -1, -1, 1056, 1056, 5, 82, -1, 0, 0, 15, 7521, 7523), + (7523, -1, -1, 1056, 1056, 5, 83, -1, 0, 0, 15, 7522, 7524), + (7524, -1, -1, 1056, 1056, 5, 84, -1, 0, 0, 15, 7523, 7525), + (7525, -1, -1, 1056, 1056, 5, 85, -1, 0, 0, 15, 7524, 16414), + (7526, -1, -1, 6119, 6119, 6, 81, -1, 0, 0, 15, 6123, 7527), + (7527, -1, -1, 6119, 6119, 6, 82, -1, 0, 0, 15, 7526, 7528), + (7528, -1, -1, 6119, 6119, 6, 83, -1, 0, 0, 15, 7527, 7529), + (7529, -1, -1, 6119, 6119, 6, 84, -1, 0, 0, 15, 7528, 7530), + (7530, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 15, 7529, 12406), + (7534, -1, -1, 65, 661, 3, 81, -1, 0, 0, 15, 6394, 7535), + (7535, -1, -1, 65, 661, 3, 82, -1, 0, 0, 15, 7534, 7536), + (7536, -1, -1, 65, 661, 3, 83, -1, 0, 0, 15, 7535, 7537), + (7537, -1, -1, 65, 661, 3, 84, -1, 0, 0, 15, 7536, 7538), + (7538, -1, -1, 65, 661, 3, 85, -1, 0, 0, 15, 7537, 7904), + (7539, -1, -1, 1021, 1021, 5, 80, -1, 0, 0, 16, 6522, 7540), + (7540, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7539, 7683), + (7541, -1, -1, 107, 107, 2, 60, -1, 0, 0, 15, 109, 7542), + (7542, -1, -1, 107, 107, 4, 60, -1, 0, 0, 15, 7541, 7543), + (7543, -1, -1, 107, 107, 6, 60, -1, 0, 0, 15, 7542, -1), + (7544, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 6520, 7545), + (7545, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 7544, 7546), + (7546, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 7545, -1), + (7547, -1, -1, 418, 418, 5, 76, -1, 0, 0, 15, 4682, 7548), + (7548, -1, -1, 418, 418, 5, 77, -1, 0, 0, 15, 7547, 7549), + (7549, -1, -1, 418, 418, 5, 78, -1, 0, 0, 15, 7548, 7550), + (7550, -1, -1, 418, 418, 5, 79, -1, 0, 0, 15, 7549, 7551), + (7551, -1, -1, 418, 418, 5, 80, -1, 0, 0, 15, 7550, -1), + (7553, -1, -1, 1071, 1071, 6, 80, -1, 0, 0, 16, 4764, 7681), + (7554, -1, -1, 1486, 1486, 7, 81, -1, 0, 0, 15, 5533, 7555), + (7555, -1, -1, 1486, 1486, 8, 82, -1, 0, 0, 15, 7554, 7556), + (7556, -1, -1, 1486, 1486, 9, 83, -1, 0, 0, 15, 7555, 7557), + (7557, -1, -1, 1486, 1486, 10, 84, -1, 0, 0, 15, 7556, 7558), + (7558, -1, -1, 1486, 1486, 12, 85, -1, 0, 0, 15, 7557, 7722), + (7559, -1, -1, 599, 599, 9, 83, -1, 0, 0, 15, 5536, 7560), + (7560, -1, -1, 599, 599, 10, 84, -1, 0, 0, 15, 7559, 7561), + (7561, -1, -1, 599, 599, 12, 85, -1, 0, 0, 15, 7560, 13026), + (7562, -1, -1, 1041, 1041, 7, 81, -1, 0, 0, 15, 5544, 7563), + (7563, -1, -1, 1041, 1041, 9, 83, -1, 0, 0, 15, 7562, 7564), + (7564, -1, -1, 1041, 1041, 12, 85, -1, 0, 0, 15, 7563, 12697), + (7565, -1, -1, 119, 119, 7, 81, -1, 0, 0, 15, 5556, 7566), + (7566, -1, -1, 119, 119, 9, 83, -1, 0, 0, 15, 7565, 7567), + (7567, -1, -1, 119, 119, 12, 85, -1, 0, 0, 15, 7566, 6023), + (7568, -1, -1, 1592, 1592, 7, 81, -1, 0, 0, 15, 5561, 7569), + (7569, -1, -1, 1592, 1592, 8, 82, -1, 0, 0, 15, 7568, 7570), + (7570, -1, -1, 1592, 1592, 9, 83, -1, 0, 0, 15, 7569, 7571), + (7571, -1, -1, 1592, 1592, 10, 84, -1, 0, 0, 15, 7570, 7572), + (7572, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 15, 7571, 12439), + (7573, -1, -1, 4739, 4739, 7, 81, -1, 0, 0, 15, 5564, 7574), + (7574, -1, -1, 4739, 4739, 9, 83, -1, 0, 0, 15, 7573, 7575), + (7575, -1, -1, 4739, 4739, 12, 85, -1, 0, 0, 15, 7574, -1), + (7576, -1, -1, 1072, 1072, 7, 81, -1, 0, 0, 15, 5570, 7577), + (7577, -1, -1, 1072, 1072, 8, 82, -1, 0, 0, 15, 7576, 7578), + (7578, -1, -1, 1072, 1072, 9, 83, -1, 0, 0, 15, 7577, 7579), + (7579, -1, -1, 1072, 1072, 10, 84, -1, 0, 0, 15, 7578, 7580), + (7580, -1, -1, 1072, 1072, 12, 85, -1, 0, 0, 15, 7579, 12444), + (7581, -1, -1, 1210, 1213, 7, 81, -1, 0, 0, 15, 5579, 7582), + (7582, -1, -1, 1210, 1213, 9, 83, -1, 0, 0, 15, 7581, 7583), + (7583, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 15, 7582, 8344), + (7584, -1, -1, 98, 98, 7, 81, -1, 0, 0, 15, 5588, 7585), + (7585, -1, -1, 98, 98, 9, 83, -1, 0, 0, 15, 7584, 7586), + (7586, -1, -1, 98, 98, 12, 85, -1, 0, 0, 15, 7585, 11061), + (7587, -1, -1, 1186, 1186, 7, 81, -1, 0, 0, 15, 5591, 7588), + (7588, -1, -1, 1186, 1186, 9, 83, -1, 0, 0, 15, 7587, 7589), + (7589, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 15, 7588, 7692), + (7590, -1, -1, 80, 80, 7, 81, -1, 0, 0, 15, 5594, 7591), + (7591, -1, -1, 80, 80, 9, 83, -1, 0, 0, 15, 7590, 7592), + (7592, -1, -1, 80, 80, 12, 85, -1, 0, 0, 15, 7591, 12452), + (7593, -1, -1, 658, 658, 5, 81, -1, 0, 0, 15, 5627, 7594), + (7594, -1, -1, 658, 658, 5, 82, -1, 0, 0, 15, 7593, 7595), + (7595, -1, -1, 658, 658, 5, 83, -1, 0, 0, 15, 7594, 7596), + (7596, -1, -1, 658, 658, 5, 84, -1, 0, 0, 15, 7595, 7597), + (7597, -1, -1, 658, 658, 5, 85, -1, 0, 0, 15, 7596, 12455), + (7598, -1, -1, 98, 738, 7, 81, -1, 0, 0, 15, 5630, 7599), + (7599, -1, -1, 98, 738, 9, 83, -1, 0, 0, 15, 7598, 7600), + (7600, -1, -1, 98, 738, 12, 85, -1, 0, 0, 15, 7599, 13924), + (7601, -1, -1, 6051, 6051, 3, 81, -1, 0, 0, 15, 6053, 7602), + (7602, -1, -1, 6051, 6051, 3, 83, -1, 0, 0, 15, 7601, 7603), + (7603, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 15, 7602, 10604), + (7604, -1, -1, 683, 683, 5, 80, -1, 0, 0, 15, 6081, 7605), + (7605, -1, -1, 683, 683, 5, 80, -1, 0, 0, 15, 7604, 12694), + (7606, 6537, 6537, 6537, 6537, 7, 81, 13821, 30, 900, 15, 6208, 7607), + (7607, 6537, 6537, 6537, 6537, 8, 82, 13822, 30, 900, 15, 7606, 7608), + (7608, 6537, 6537, 6537, 6537, 9, 83, 13823, 30, 900, 15, 7607, 12460), + (7609, 6539, 6539, 6539, 6539, 6, 76, 13824, 18, 1800, 15, 6214, 7610), + (7610, 6539, 6539, 6539, 6539, 6, 79, 13825, 18, 1800, 15, 7609, 7611), + (7611, 6539, 6539, 6539, 6539, 6, 82, 13826, 18, 1800, 15, 7610, 12942), + (7612, -1, -1, 270, 665, 2, 66, -1, 0, 0, 15, 670, 7613), + (7613, -1, -1, 270, 665, 2, 67, -1, 0, 0, 15, 7612, 7614), + (7614, -1, -1, 270, 665, 2, 68, -1, 0, 0, 15, 7613, -1), + (7615, -1, -1, 6346, 6346, 6, 79, -1, 0, 0, 15, 6348, 7616), + (7616, -1, -1, 6346, 6346, 6, 81, -1, 0, 0, 15, 7615, 7617), + (7617, -1, -1, 6346, 6346, 6, 83, -1, 0, 0, 15, 7616, 15397), + (7618, -1, -1, 6349, 6349, 6, 79, -1, 0, 0, 15, 6351, 7619), + (7619, -1, -1, 6349, 6349, 6, 81, -1, 0, 0, 15, 7618, 7620), + (7620, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 15, 7619, 11053), + (7621, -1, -1, 1435, 4773, 9, 81, -1, 0, 0, 15, 6517, 13090), + (7622, -1, -1, 446, 735, 8, 81, -1, 0, 0, 15, 7065, 7623), + (7623, -1, -1, 446, 735, 8, 82, -1, 0, 0, 15, 7622, 7624), + (7624, -1, -1, 446, 735, 8, 83, -1, 0, 0, 15, 7623, 10473), + (7625, -1, -1, 735, 735, 8, 81, -1, 0, 0, 15, 7068, 7626), + (7626, -1, -1, 735, 735, 8, 82, -1, 0, 0, 15, 7625, 7627), + (7627, -1, -1, 735, 735, 8, 83, -1, 0, 0, 15, 7626, 10632), + (7628, -1, -1, 807, 807, 5, 81, -1, 0, 0, 15, 5924, 7629), + (7629, -1, -1, 807, 807, 5, 83, -1, 0, 0, 15, 7628, 7630), + (7630, -1, -1, 807, 807, 5, 85, -1, 0, 0, 15, 7629, 12685), + (7631, -1, -1, 255, 255, 7, 81, -1, 0, 0, 15, 5597, 7632), + (7632, -1, -1, 255, 255, 9, 83, -1, 0, 0, 15, 7631, 7633), + (7633, -1, -1, 255, 255, 12, 85, -1, 0, 0, 15, 7632, 17441), + (7634, -1, -1, 815, 815, 9, 83, -1, 0, 0, 15, 5913, 7635), + (7635, -1, -1, 815, 815, 10, 84, -1, 0, 0, 15, 7634, 7636), + (7636, -1, -1, 815, 815, 12, 85, -1, 0, 0, 15, 7635, 15441), + (7637, -1, -1, 1616, 1616, 5, 83, -1, 0, 0, 15, 6007, 7638), + (7638, -1, -1, 1616, 1616, 5, 84, -1, 0, 0, 15, 7637, 7639), + (7639, -1, -1, 1616, 1616, 5, 85, -1, 0, 0, 15, 7638, -1), + (7640, -1, -1, 686, 686, 5, 60, -1, 0, 0, 15, 690, 12438), + (7641, -1, -1, 625, 625, 3, 76, -1, 0, 0, 15, 4735, 7642), + (7642, -1, -1, 625, 625, 3, 78, -1, 0, 0, 15, 7641, 7643), + (7643, -1, -1, 625, 625, 3, 80, -1, 0, 0, 15, 7642, -1), + (7644, -1, -1, 6375, 6375, 6, 81, -1, 0, 0, 15, 6377, 7645), + (7645, -1, -1, 6375, 6375, 6, 82, -1, 0, 0, 15, 7644, 7646), + (7646, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 15, 7645, 7663), + (7647, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 694, 7648), + (7648, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 7647, 7649), + (7649, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 7648, 7670), + (7650, -1, -1, 1044, 1044, 7, 81, -1, 0, 0, 15, 5547, 7651), + (7651, -1, -1, 1044, 1044, 9, 83, -1, 0, 0, 15, 7650, 7652), + (7652, -1, -1, 1044, 1044, 12, 85, -1, 0, 0, 15, 7651, 13074), + (7653, -1, -1, 1047, 1047, 7, 81, -1, 0, 0, 15, 5550, 7654), + (7654, -1, -1, 1047, 1047, 9, 83, -1, 0, 0, 15, 7653, 7655), + (7655, -1, -1, 1047, 1047, 12, 85, -1, 0, 0, 15, 7654, 13077), + (7656, -1, -1, 1050, 1050, 7, 81, -1, 0, 0, 15, 5553, 7657), + (7657, -1, -1, 1050, 1050, 9, 83, -1, 0, 0, 15, 7656, 7658), + (7658, -1, -1, 1050, 1050, 12, 85, -1, 0, 0, 15, 7657, 13023), + (7659, -1, -1, 754, 754, 3, 70, -1, 0, 0, 15, 756, 7660), + (7660, -1, -1, 754, 754, 6, 70, -1, 0, 0, 15, 7659, 7661), + (7661, -1, -1, 754, 754, 9, 70, -1, 0, 0, 15, 7660, -1), + (7662, 188, 188, 188, 188, 9, 83, 16431, 2, 30, 15, 7339, 10647), + (7663, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 15, 7646, 10084), + (7664, -1, -1, 7664, 7664, 2, 73, -1, 0, 0, 15, -1, 7665), + (7665, -1, -1, 7664, 7664, 2, 74, -1, 0, 0, 15, 7664, 7666), + (7666, -1, -1, 7664, 7664, 2, 75, -1, 0, 0, 15, 7665, 7667), + (7667, -1, -1, 7664, 7664, 2, 76, -1, 0, 0, 15, 7666, 7668), + (7668, -1, -1, 7664, 7664, 2, 77, -1, 0, 0, 15, 7667, 10105), + (7669, 7669, 7669, 7669, 7669, 3, 81, 13838, 35, 5, 15, -1, -1), + (7670, -1, -1, 692, 692, 7, 75, -1, 0, 0, 16, 7649, 7671), + (7671, -1, -1, 692, 692, 9, 80, -1, 0, 0, 16, 7670, 7672), + (7672, -1, -1, 692, 692, 12, 85, -1, 0, 0, 16, 7671, 12767), + (7673, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 859, 7674), + (7674, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7673, 7675), + (7675, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7674, 7676), + (7676, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7675, 7677), + (7677, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7676, 10688), + (7678, -1, -1, 852, 852, 9, 81, -1, 0, 0, 16, 5502, 7679), + (7679, -1, -1, 852, 852, 10, 83, -1, 0, 0, 16, 7678, 7680), + (7680, -1, -1, 852, 852, 12, 85, -1, 0, 0, 16, 7679, 12576), + (7681, -1, -1, 1071, 1071, 6, 80, -1, 0, 0, 16, 7553, -1), + (7682, -1, -1, 4861, 4861, 12, 85, -1, 0, 0, 16, 7216, 12757), + (7683, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7540, 7684), + (7684, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7683, 7685), + (7685, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7684, 13894), + (7686, -1, -1, 4844, 4844, 5, 81, -1, 0, 0, 16, 7126, 7687), + (7687, -1, -1, 4844, 4844, 5, 83, -1, 0, 0, 16, 7686, 7688), + (7688, -1, -1, 4844, 4844, 5, 85, -1, 0, 0, 16, 7687, -1), + (7689, 7689, 7689, 7689, 7689, 12, 85, 21820, 94, 180, 16, -1, -1), + (7690, -1, -1, 7690, 7690, 12, 85, -1, 0, 0, 16, -1, -1), + (7691, 146, 146, 146, 146, 8, 85, 16862, 2, 180, 16, 7466, 13256), + (7692, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7589, 7693), + (7693, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7692, 7694), + (7694, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7693, 12564), + (7695, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, -1, 7696), + (7696, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, 7695, 7697), + (7697, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, 7696, -1), + (7698, 7698, 7698, 7698, 7698, 6, 85, 21763, 17, 6, 16, -1, -1), + (7699, -1, -1, 7699, 7699, 12, 85, 0, 0, 0, 16, -1, -1), + (7700, -1, -1, 255, 255, 7, 81, -1, 0, 0, 16, -1, 7701), + (7701, -1, -1, 255, 255, 9, 83, -1, 0, 0, 16, 7700, 7702), + (7702, -1, -1, 255, 255, 12, 85, -1, 0, 0, 16, 7701, 12610), + (7703, 7703, 7703, 7703, 7703, 12, 85, 21754, 16, 600, 16, -1, -1), + (7704, -1, -1, 8195, 8195, 5, 81, -1, 0, 0, 16, 8197, 7705), + (7705, -1, -1, 8195, 8195, 5, 83, -1, 0, 0, 16, 7704, 7706), + (7706, -1, -1, 8195, 8195, 5, 85, -1, 0, 0, 16, 7705, -1), + (7707, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7392, 7708), + (7708, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7707, 7709), + (7709, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7708, 13104), + (7710, 5984, 5984, 5984, 5984, 12, 85, 21679, 2, 30, 16, 7335, 7711), + (7711, 5984, 5984, 5984, 5984, 12, 85, 21680, 2, 30, 16, 7710, 10626), + (7712, 7712, 7712, 7712, 7712, 12, 85, 21682, 2, 30, 16, -1, 10646), + (7713, -1, -1, 634, 634, 12, 81, -1, 0, 0, 16, 5613, 7714), + (7714, -1, -1, 634, 634, 12, 83, -1, 0, 0, 16, 7713, 10778), + (7715, -1, -1, 7715, 7715, 5, 77, 0, 0, 0, 16, -1, 7716), + (7716, -1, -1, 7715, 7715, 5, 79, 0, 0, 0, 16, 7715, 7717), + (7717, -1, -1, 7715, 7715, 5, 81, 0, 0, 0, 16, 7716, 14314), + (7718, -1, -1, 574, 574, 3, 81, -1, 0, 0, 16, 576, -1), + (7722, -1, -1, 1486, 1486, 7, 86, -1, 0, 0, 17, 7558, 7723), + (7723, -1, -1, 1486, 1486, 8, 87, -1, 0, 0, 17, 7722, 7724), + (7724, -1, -1, 1486, 1486, 9, 88, -1, 0, 0, 17, 7723, 7725), + (7725, -1, -1, 1486, 1486, 10, 89, -1, 0, 0, 17, 7724, 7726), + (7726, -1, -1, 1486, 1486, 12, 90, -1, 0, 0, 17, 7725, 7842), + (7732, 7732, 7732, 7732, 7732, 0, 60, 7732, 34, 3600, 14, -1, -1), + (7733, -1, -1, 288, 288, 6, 65, -1, 0, 0, 14, -1, -1), + (7734, 7734, 7734, 7734, 7734, 0, 61, 7734, 34, 28800, 14, -1, -1), + (7735, 7735, 7735, 7735, 7735, 0, 51, 7731, 32, 3600, 9, -1, -1), + (7736, 7736, 7736, 7736, 7736, 0, 52, 7865, 32, 10800, 9, -1, -1), + (7737, 7737, 7737, 7737, 7737, 0, 53, 7733, 32, 10800, 9, -1, -1), + (7738, 7738, 7738, 7738, 7738, 0, 54, 7990, 32, 21600, 9, -1, -1), + (7739, 7739, 7739, 7739, 7739, 0, 65, 13064, 36, 3600, 0, -1, -1), + (7740, 7740, 7740, 7740, 7740, 0, 66, 13065, 36, 28800, 0, -1, -1), + (7741, 7741, 7741, 7741, 7741, 0, 70, 21854, 50, 3600, 0, -1, -1), + (7742, 7742, 7742, 7742, 7742, 0, 71, 21855, 50, 28800, 0, -1, -1), + (7743, -1, -1, 7743, 7743, 5, 61, -1, 0, 0, 16, -1, 7744), + (7744, -1, -1, 7743, 7743, 7, 61, -1, 0, 0, 16, 7743, 7745), + (7745, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 16, 7744, 10717), + (7746, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, -1, 7763), + (7747, 7747, 7747, 7747, 7747, 9, 85, 21790, 32, 180, 16, -1, -1), + (7748, -1, -1, 7748, 7748, 3, 81, -1, 0, 0, 16, -1, 7749), + (7749, -1, -1, 7748, 7748, 6, 83, -1, 0, 0, 16, 7748, 7750), + (7750, -1, -1, 7748, 7748, 9, 85, -1, 0, 0, 16, 7749, -1), + (7751, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, -1, 7752), + (7752, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, 7751, 7753), + (7753, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, 7752, 14132), + (7754, 7754, 7754, 7754, 7754, 9, 85, 21803, 0, 1, 16, -1, -1), + (7755, 7755, 7755, 7755, 7755, 9, 81, 21804, 53, 900, 16, -1, 15782), + (7756, 7756, 7756, 7756, 7756, 12, 85, 21805, 54, 120, 16, -1, -1), + (7757, -1, -1, 7757, 7757, 5, 85, -1, 0, 0, 16, -1, 7758), + (7758, -1, -1, 7757, 7757, 7, 85, -1, 0, 0, 16, 7757, 7759), + (7759, -1, -1, 7757, 7757, 9, 85, -1, 0, 0, 16, 7758, 12587), + (7760, -1, -1, 7760, 7760, 5, 85, -1, 0, 0, 16, -1, 7761), + (7761, -1, -1, 7760, 7760, 7, 85, -1, 0, 0, 16, 7760, 7762), + (7762, -1, -1, 7760, 7760, 9, 85, -1, 0, 0, 16, 7761, -1), + (7763, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, 7746, 7764), + (7764, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, 7763, -1), + (7765, -1, -1, 7765, 7765, 5, 86, 0, 0, 0, 17, -1, 7766), + (7766, -1, -1, 7765, 7765, 7, 87, 0, 0, 0, 17, 7765, 7767), + (7767, -1, -1, 7765, 7765, 9, 88, 0, 0, 0, 17, 7766, 7768), + (7768, -1, -1, 7765, 7765, 12, 89, 0, 0, 0, 17, 7767, 7769), + (7770, 131, 131, 131, 131, 9, 86, 27655, 4, 900, 17, 10018, 7771), + (7771, 131, 131, 131, 131, 12, 88, 27656, 4, 900, 17, 7770, 7772), + (7772, 131, 131, 131, 131, 15, 90, 27657, 4, 900, 17, 7771, 13374), + (7773, 7951, 7951, 7951, 7951, 9, 86, 27658, 61, 900, 17, 10040, 7774), + (7774, 7951, 7951, 7951, 7951, 9, 88, 27659, 61, 900, 17, 7773, 7775), + (7775, 7951, 7951, 7951, 7951, 9, 90, 27660, 61, 900, 17, 7774, 13377), + (7800, 7800, 7800, 7800, 7800, 0, 1, 13531, 39, 4320, 0, -1, 7801), + (7801, 7800, 7800, 7800, 7800, 0, 6, 13532, 39, 4320, 0, 7800, 7802), + (7802, 7800, 7800, 7800, 7800, 0, 11, 13533, 39, 4320, 0, 7801, 7803), + (7803, 7800, 7800, 7800, 7800, 0, 16, 13534, 39, 4320, 0, 7802, 7804), + (7804, 7800, 7800, 7800, 7800, 0, 21, 13535, 39, 4320, 0, 7803, 7805), + (7805, 7800, 7800, 7800, 7800, 0, 26, 13536, 39, 4320, 0, 7804, 7806), + (7806, 7800, 7800, 7800, 7800, 0, 31, 13537, 39, 4320, 0, 7805, 7807), + (7807, 7800, 7800, 7800, 7800, 0, 36, 13538, 39, 4320, 0, 7806, 7808), + (7808, 7800, 7800, 7800, 7800, 0, 41, 13539, 39, 4320, 0, 7807, 7809), + (7809, 7800, 7800, 7800, 7800, 0, 46, 13540, 39, 4320, 0, 7808, 7810), + (7810, 7800, 7800, 7800, 7800, 3, 51, 13541, 39, 4320, 0, 7809, 7811), + (7811, 7800, 7800, 7800, 7800, 4, 56, 13542, 39, 4320, 0, 7810, 7812), + (7812, 7800, 7800, 7800, 7800, 5, 61, 13543, 39, 4320, 0, 7811, 7813), + (7813, 7800, 7800, 7800, 7800, 6, 66, 13544, 39, 4320, 0, 7812, 7814), + (7814, 7800, 7800, 7800, 7800, 7, 71, 13545, 39, 4320, 0, 7813, 7815), + (7815, 7800, 7800, 7800, 7800, 8, 76, 13562, 39, 4320, 0, 7814, 7816), + (7816, 7800, 7800, 7800, 7800, 8, 81, 16062, 39, 4320, 0, 7815, 7817), + (7817, 7800, 7800, 7800, 7800, 9, 83, 16855, 39, 4320, 0, 7816, 10786), + (7818, -1, -1, 7818, 7818, 12, 85, 21750, 0, 0, 16, -1, 13029), + (7819, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 9514, 7820), + (7820, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7819, 7821), + (7821, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7820, 7881), + (7822, -1, -1, 7822, 7822, 5, 77, 0, 0, 0, 16, -1, 7823), + (7823, -1, -1, 7822, 7822, 5, 79, 0, 0, 0, 16, 7822, 7824), + (7824, -1, -1, 7822, 7822, 5, 81, 0, 0, 0, 16, 7823, 7825), + (7825, -1, -1, 7822, 7822, 5, 83, 0, 0, 0, 16, 7824, 7826), + (7826, -1, -1, 7822, 7822, 5, 85, 0, 0, 0, 16, 7825, 14328), + (7827, -1, -1, 7827, 7827, 5, 81, 0, 0, 0, 16, -1, -1), + (7828, -1, -1, 7828, 7828, 5, 79, 0, 0, 0, 16, -1, 7829), + (7829, -1, -1, 7828, 7828, 5, 81, 0, 0, 0, 16, 7828, 7830), + (7830, -1, -1, 7828, 7828, 5, 83, 0, 0, 0, 16, 7829, -1), + (7832, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, -1, 7833), + (7833, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7832, 7834), + (7834, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7833, 7835), + (7835, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7834, 7836), + (7836, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7835, -1), + (7837, -1, -1, 1006, 1006, 5, 76, -1, 0, 0, 17, 7520, 7838), + (7838, -1, -1, 1006, 1006, 5, 77, -1, 0, 0, 17, 7837, 7839), + (7839, -1, -1, 1006, 1006, 5, 78, -1, 0, 0, 17, 7838, 7840), + (7840, -1, -1, 1006, 1006, 5, 79, -1, 0, 0, 17, 7839, 7841), + (7841, -1, -1, 1006, 1006, 5, 80, -1, 0, 0, 17, 7840, 8470), + (7842, -1, -1, 1486, 1486, 12, 91, -1, 0, 0, 18, 7726, 7843), + (7843, -1, -1, 1486, 1486, 12, 92, -1, 0, 0, 18, 7842, 7844), + (7844, -1, -1, 1486, 1486, 12, 93, -1, 0, 0, 18, 7843, 7845), + (7850, 7850, 7850, 7850, 7850, 0, 1, 13546, 39, 4320, 0, -1, 7851), + (7851, 7850, 7850, 7850, 7850, 0, 6, 13547, 39, 4320, 0, 7850, 7852), + (7852, 7850, 7850, 7850, 7850, 0, 11, 13548, 39, 4320, 0, 7851, 7853), + (7853, 7850, 7850, 7850, 7850, 0, 16, 13549, 39, 4320, 0, 7852, 7854), + (7854, 7850, 7850, 7850, 7850, 0, 21, 13550, 39, 4320, 0, 7853, 7855), + (7855, 7850, 7850, 7850, 7850, 0, 26, 13551, 39, 4320, 0, 7854, 7856), + (7856, 7850, 7850, 7850, 7850, 0, 31, 13552, 39, 4320, 0, 7855, 7857), + (7857, 7850, 7850, 7850, 7850, 0, 36, 13553, 39, 4320, 0, 7856, 7858), + (7858, 7850, 7850, 7850, 7850, 0, 41, 13554, 39, 4320, 0, 7857, 7859), + (7859, 7850, 7850, 7850, 7850, 0, 46, 13555, 39, 4320, 0, 7858, 7860), + (7860, 7850, 7850, 7850, 7850, 3, 51, 13556, 39, 4320, 0, 7859, 7861), + (7861, 7850, 7850, 7850, 7850, 4, 56, 13557, 39, 4320, 0, 7860, 7862), + (7862, 7850, 7850, 7850, 7850, 5, 61, 13558, 39, 4320, 0, 7861, 7863), + (7863, 7850, 7850, 7850, 7850, 6, 66, 13559, 39, 4320, 0, 7862, 7864), + (7864, 7850, 7850, 7850, 7850, 7, 71, 13560, 39, 4320, 0, 7863, 7865), + (7865, 7850, 7850, 7850, 7850, 8, 76, 13561, 39, 4320, 0, 7864, 7340), + (7869, 7869, 7869, 7869, 7869, 6, 73, 16175, 60, 30, 15, -1, 7870), + (7870, 7869, 7869, 7869, 7869, 6, 77, 16176, 60, 30, 15, 7869, 7871), + (7871, 7869, 7869, 7869, 7869, 6, 81, 16177, 60, 30, 15, 7870, -1), + (7872, 7872, 7872, 7872, 7872, 6, 76, 16178, 41, 600, 15, -1, 7873), + (7873, 7872, 7872, 7872, 7872, 6, 81, 16179, 41, 600, 15, 7872, 7874), + (7874, 7872, 7872, 7872, 7872, 6, 85, 16180, 41, 600, 15, 7873, 10127), + (7875, 7875, 7875, 7875, 7875, 6, 76, 16181, 42, 600, 15, -1, 7876), + (7876, 7875, 7875, 7875, 7875, 6, 81, 16182, 42, 600, 15, 7875, 7877), + (7877, 7875, 7875, 7875, 7875, 6, 85, 16183, 42, 600, 15, 7876, 7878), + (7878, 7875, 7875, 7875, 7875, 6, 85, 16859, 42, 600, 16, 7877, 7879), + (7879, 7875, 7875, 7875, 7875, 6, 85, 21823, 42, 600, 16, 7878, 7880), + (7880, 7875, 7875, 7875, 7875, 6, 85, 21824, 42, 600, 16, 7879, 13816), + (7881, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7821, 7882), + (7882, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7881, 7883), + (7883, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7882, 13187), + (7884, -1, -1, 7884, 7884, 9, 85, -1, 0, 0, 16, -1, 12689), + (7885, -1, -1, 7885, 7885, 9, 85, -1, 0, 0, 16, -1, 12690), + (7886, -1, -1, 1026, 1026, 5, 85, -1, 0, 0, 17, 7515, 7887), + (7887, -1, -1, 1026, 1026, 5, 86, -1, 0, 0, 17, 7886, 7888), + (7888, -1, -1, 1026, 1026, 5, 87, -1, 0, 0, 17, 7887, 7889), + (7889, -1, -1, 1026, 1026, 5, 88, -1, 0, 0, 17, 7888, 7890), + (7890, -1, -1, 1026, 1026, 5, 89, -1, 0, 0, 17, 7889, 8430), + (7900, -1, -1, 7900, 7900, 4, 60, -1, 0, 0, 15, -1, 7901), + (7901, -1, -1, 7900, 7900, 4, 65, -1, 0, 0, 15, 7900, 7902), + (7902, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 15, 7901, 10268), + (7903, 7903, 7903, 7903, 7903, 6, 75, 16188, 60, 30, 15, -1, 12976), + (7904, -1, -1, 65, 661, 3, 85, -1, 0, 0, 17, 7538, 7905), + (7905, -1, -1, 65, 661, 3, 86, -1, 0, 0, 17, 7904, 7906), + (7906, -1, -1, 65, 661, 3, 87, -1, 0, 0, 17, 7905, 7907), + (7907, -1, -1, 65, 661, 3, 88, -1, 0, 0, 17, 7906, 7908), + (7908, -1, -1, 65, 661, 3, 89, -1, 0, 0, 17, 7907, 8435), + (7940, -1, -1, 7940, 7940, 6, 60, -1, 0, 0, 15, -1, 7941), + (7941, -1, -1, 7940, 7940, 6, 65, -1, 0, 0, 15, 7940, 7942), + (7942, -1, -1, 7940, 7940, 6, 70, -1, 0, 0, 15, 7941, 10030), + (7943, 7943, 7943, 7943, 7943, 6, 79, 16192, 60, 8640, 15, -1, 7993), + (7944, 7944, 7944, 7944, 7944, 7, 79, 16193, 34, 1800, 15, -1, -1), + (7945, -1, -1, 7945, 7945, 6, 81, -1, 0, 0, 15, -1, 7946), + (7946, -1, -1, 7945, 7945, 6, 82, -1, 0, 0, 15, 7945, 7947), + (7947, -1, -1, 7945, 7945, 6, 83, -1, 0, 0, 15, 7946, 10033), + (7948, -1, -1, 7948, 7948, 6, 75, -1, 0, 0, 15, -1, 7949), + (7949, -1, -1, 7948, 7948, 6, 80, -1, 0, 0, 15, 7948, 7950), + (7950, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 15, 7949, 10035), + (7951, 7951, 7951, 7951, 7951, 6, 82, 16200, 61, 900, 15, -1, 7952), + (7952, 7951, 7951, 7951, 7951, 6, 83, 16201, 61, 900, 15, 7951, 7953), + (7953, 7951, 7951, 7951, 7951, 6, 84, 16202, 61, 900, 15, 7952, 10038), + (7980, -1, -1, 7980, 7980, 6, 70, -1, 0, 0, 15, -1, 7981), + (7981, -1, -1, 7980, 7980, 6, 73, -1, 0, 0, 15, 7980, 7982), + (7982, -1, -1, 7980, 7980, 6, 76, -1, 0, 0, 15, 7981, -1), + (7983, -1, -1, 7983, 7983, 6, 70, -1, 0, 0, 15, -1, 7984), + (7984, -1, -1, 7983, 7983, 6, 73, -1, 0, 0, 15, 7983, 7985), + (7985, -1, -1, 7983, 7983, 6, 76, -1, 0, 0, 15, 7984, 10110), + (7986, 7986, 7986, 7986, 7986, 9, 75, 16203, 11, 600, 15, -1, 7987), + (7987, 7986, 7986, 7986, 7986, 12, 80, 16204, 11, 600, 15, 7986, 7988), + (7988, 7986, 7986, 7986, 7986, 12, 85, 16205, 11, 600, 15, 7987, 10510), + (7989, -1, -1, 7989, 7989, 6, 75, -1, 0, 0, 15, -1, 7990), + (7990, -1, -1, 7989, 7989, 6, 80, -1, 0, 0, 15, 7989, 7991), + (7991, -1, -1, 7989, 7989, 6, 85, -1, 0, 0, 15, 7990, 7992), + (7992, -1, -1, 7989, 7989, 6, 85, -1, 0, 0, 15, 7991, 13415), + (7993, 7943, 7943, 7943, 7943, 6, 85, 23601, 60, 8640, 17, 7943, -1), + (7994, -1, -1, 462, 462, 2, 81, -1, 0, 0, 17, 464, 7995), + (7995, -1, -1, 462, 462, 2, 85, -1, 0, 0, 17, 7994, -1), + (8000, -1, -1, 8001, 8001, 0, 50, -1, 0, 0, 8, -1, -1), + (8030, 8030, 8030, 8030, 8030, 6, 70, 16206, 60, 900, 15, -1, -1), + (8031, -1, -1, 8031, 8031, 6, 75, -1, 0, 0, 15, -1, 8032), + (8032, -1, -1, 8031, 8031, 6, 77, -1, 0, 0, 15, 8031, 8033), + (8033, -1, -1, 8031, 8031, 6, 79, -1, 0, 0, 15, 8032, 10282), + (8034, 8034, 8034, 8034, 8034, 6, 81, 16207, 59, 600, 15, -1, -1), + (8035, -1, -1, 8035, 8035, 6, 73, -1, 0, 0, 15, -1, 8036), + (8036, -1, -1, 8035, 8035, 6, 75, -1, 0, 0, 15, 8035, 8037), + (8037, -1, -1, 8035, 8035, 6, 77, -1, 0, 0, 15, 8036, 10285), + (8038, 8038, 8038, 8038, 8038, 6, 81, 16210, 56, 12, 15, -1, 17541), + (8039, 8039, 8039, 8039, 8039, 6, 83, 16211, 58, 7, 15, -1, 15462), + (8040, -1, -1, 8040, 8040, 4, 65, -1, 0, 0, 15, -1, 8041), + (8041, -1, -1, 8040, 8040, 4, 70, -1, 0, 0, 15, 8040, 8042), + (8042, -1, -1, 8040, 8040, 4, 75, -1, 0, 0, 15, 8041, 8043), + (8043, -1, -1, 8040, 8040, 4, 78, -1, 0, 0, 15, 8042, 8313), + (8059, -1, -1, 8232, 8232, 4, 78, -1, 0, 0, 15, 8234, 8261), + (8060, 8060, 8060, 8060, 8060, 7, 75, 16238, 41, 1800, 15, -1, 8061), + (8061, 8060, 8060, 8060, 8060, 7, 78, 16239, 41, 1800, 15, 8060, 8062), + (8062, 8060, 8060, 8060, 8060, 7, 81, 16240, 41, 1800, 15, 8061, 10237), + (8063, 8063, 8063, 8063, 8063, 7, 75, 16241, 41, 1800, 15, -1, 8064), + (8064, 8063, 8063, 8063, 8063, 7, 78, 16242, 41, 1800, 15, 8063, 8065), + (8065, 8063, 8063, 8063, 8063, 7, 81, 16243, 41, 1800, 15, 8064, 10240), + (8066, 8066, 8066, 8066, 8066, 7, 75, 16244, 41, 1800, 15, -1, 8067), + (8067, 8066, 8066, 8066, 8066, 7, 78, 16245, 41, 1800, 15, 8066, 8068), + (8068, 8066, 8066, 8066, 8066, 7, 81, 16246, 41, 1800, 15, 8067, 10243), + (8069, -1, -1, 8069, 8069, 5, 71, -1, 0, 0, 15, -1, 8070), + (8070, -1, -1, 8069, 8069, 5, 72, -1, 0, 0, 15, 8069, 8071), + (8071, -1, -1, 8069, 8069, 5, 73, -1, 0, 0, 15, 8070, 15606), + (8072, 8072, 8072, 8072, 8072, 7, 75, 16221, 37, 20, 15, -1, 8073), + (8073, 8072, 8072, 8072, 8072, 7, 75, 16222, 37, 20, 15, 8072, 8074), + (8074, 8072, 8072, 8072, 8072, 7, 75, 16223, 37, 20, 15, 8073, 10246), + (8075, 8075, 8075, 8075, 8075, 7, 81, 16224, 42, 6, 15, -1, -1), + (8076, -1, -1, 8076, 8076, 5, 77, -1, 0, 0, 15, -1, 8077), + (8077, -1, -1, 8076, 8076, 5, 78, -1, 0, 0, 15, 8076, 8078), + (8078, -1, -1, 8076, 8076, 5, 79, -1, 0, 0, 15, 8077, 8079), + (8079, -1, -1, 8076, 8076, 5, 80, -1, 0, 0, 15, 8078, 8080), + (8080, -1, -1, 8076, 8076, 5, 81, -1, 0, 0, 15, 8079, 8081), + (8081, -1, -1, 8076, 8076, 5, 82, -1, 0, 0, 15, 8080, -1), + (8082, -1, -1, 8082, 8082, 3, 65, -1, 0, 0, 15, -1, 8083), + (8083, -1, -1, 8082, 8082, 3, 67, -1, 0, 0, 15, 8082, 8084), + (8084, -1, -1, 8082, 8082, 3, 69, -1, 0, 0, 15, 8083, 10249), + (8190, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, -1, 8191), + (8191, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, 8190, 8192), + (8192, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, 8191, -1), + (8193, -1, -1, 8193, 8193, 7, 75, -1, 0, 0, 15, -1, -1), + (8194, 8194, 8194, 8194, 8194, 7, 75, 16226, 47, 12, 15, -1, -1), + (8195, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, -1, 8196), + (8196, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, 8195, 8197), + (8197, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, 8196, 7704), + (8198, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, -1, 8199), + (8199, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, 8198, 8200), + (8200, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, 8199, -1), + (8201, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, -1, 8202), + (8202, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, 8201, 8203), + (8203, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, 8202, 16475), + (8204, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, -1, 8205), + (8205, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, 8204, 8206), + (8206, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, 8205, 1656), + (8207, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, -1, 8208), + (8208, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, 8207, 8209), + (8209, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, 8208, 1659), + (8210, -1, -1, 8210, 8210, 5, 65, -1, 0, 0, 15, -1, 8211), + (8211, -1, -1, 8210, 8210, 5, 70, -1, 0, 0, 15, 8210, 8212), + (8212, -1, -1, 8210, 8210, 5, 75, -1, 0, 0, 15, 8211, 8213), + (8213, -1, -1, 8210, 8210, 5, 80, -1, 0, 0, 15, 8212, 8214), + (8214, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 15, 8213, 1651), + (8215, -1, -1, 8215, 8215, 5, 65, -1, 0, 0, 15, -1, 8216), + (8216, -1, -1, 8215, 8215, 5, 70, -1, 0, 0, 15, 8215, 8217), + (8217, -1, -1, 8215, 8215, 5, 75, -1, 0, 0, 15, 8216, 8218), + (8218, -1, -1, 8215, 8215, 5, 80, -1, 0, 0, 15, 8217, 8219), + (8219, -1, -1, 8215, 8215, 5, 85, -1, 0, 0, 15, 8218, 12559), + (8220, 8220, 8220, 8220, 8220, 5, 76, 16227, 39, 15, 15, -1, -1), + (8221, 8221, 8221, 8221, 8221, 9, 81, 16228, 45, 600, 15, -1, -1), + (8222, 8222, 8222, 8222, 8222, 7, 75, 16229, 70, 10, 15, -1, -1), + (8223, -1, -1, 86, 86, 8, 59, -1, 0, 0, 15, 6259, 8262), + (8224, -1, -1, 8224, 8224, 5, 75, -1, 0, 0, 15, -1, 8225), + (8225, -1, -1, 8224, 8224, 5, 80, -1, 0, 0, 15, 8224, 8226), + (8226, -1, -1, 8224, 8224, 5, 85, -1, 0, 0, 15, 8225, 8421), + (8227, 8227, 8227, 8227, 8227, 3, 55, 16233, 71, 10, 15, -1, 12810), + (8228, -1, -1, 8228, 8228, 5, 75, -1, 0, 0, 15, -1, 8229), + (8229, -1, -1, 8228, 8228, 5, 80, -1, 0, 0, 15, 8228, 8230), + (8230, -1, -1, 8228, 8228, 5, 85, -1, 0, 0, 15, 8229, -1), + (8231, 8231, -1, 8231, 8231, 3, 55, 16234, 38, 60, 15, -1, -1), + (8232, -1, -1, 8232, 8232, 4, 65, -1, 0, 0, 15, -1, 8233), + (8233, -1, -1, 8232, 8232, 4, 70, -1, 0, 0, 15, 8232, 8234), + (8234, -1, -1, 8232, 8232, 4, 75, -1, 0, 0, 15, 8233, 8059), + (8235, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, -1, 8236), + (8236, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8235, 8237), + (8237, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8236, 8238), + (8238, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8237, 8239), + (8239, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8238, 8304), + (8240, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, -1, 8241), + (8241, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8240, 8242), + (8242, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8241, 8243), + (8243, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8242, 8244), + (8244, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8243, 10781), + (8245, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, -1, 8246), + (8246, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8245, 8247), + (8247, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8246, 8248), + (8248, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8247, 8249), + (8249, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8248, 8422), + (8250, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, -1, 8251), + (8251, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8250, 8252), + (8252, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8251, 8253), + (8253, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8252, 8254), + (8254, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8253, 13046), + (8255, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, -1, 8256), + (8256, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8255, 8257), + (8257, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8256, 8258), + (8258, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8257, 8259), + (8259, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8258, 12411), + (8260, 8005, 8005, 8005, 8005, 9, 85, 20185, 45, 600, 16, -1, -1), + (8261, -1, -1, 8232, 8232, 4, 80, -1, 0, 0, 16, 8059, 15772), + (8262, -1, -1, 86, 86, 8, 65, -1, 0, 0, 16, 8223, -1), + (8263, -1, -1, 8263, 8263, 5, 81, -1, 0, 0, 16, -1, 8264), + (8264, -1, -1, 8263, 8263, 5, 82, -1, 0, 0, 16, 8263, 8265), + (8265, -1, -1, 8263, 8263, 5, 83, -1, 0, 0, 16, 8264, 8266), + (8266, -1, -1, 8263, 8263, 5, 84, -1, 0, 0, 16, 8265, 8267), + (8267, -1, -1, 8263, 8263, 5, 85, -1, 0, 0, 16, 8266, 8351), + (8268, -1, -1, 8268, 8268, 5, 81, -1, 0, 0, 16, -1, 8269), + (8269, -1, -1, 8268, 8268, 5, 82, -1, 0, 0, 16, 8268, 8270), + (8270, -1, -1, 8268, 8268, 5, 83, -1, 0, 0, 16, 8269, 8271), + (8271, -1, -1, 8268, 8268, 5, 84, -1, 0, 0, 16, 8270, 8272), + (8272, -1, -1, 8268, 8268, 5, 85, -1, 0, 0, 16, 8271, 8361), + (8273, -1, -1, 8273, 8273, 5, 81, -1, 0, 0, 16, -1, 8274), + (8274, -1, -1, 8273, 8273, 5, 82, -1, 0, 0, 16, 8273, 8275), + (8275, -1, -1, 8273, 8273, 5, 83, -1, 0, 0, 16, 8274, 8276), + (8276, -1, -1, 8273, 8273, 5, 84, -1, 0, 0, 16, 8275, 8277), + (8277, -1, -1, 8273, 8273, 5, 85, -1, 0, 0, 16, 8276, 8371), + (8278, -1, -1, 8278, 8278, 5, 81, -1, 0, 0, 16, -1, 8279), + (8279, -1, -1, 8278, 8278, 5, 82, -1, 0, 0, 16, 8278, 8280), + (8280, -1, -1, 8278, 8278, 5, 83, -1, 0, 0, 16, 8279, 8281), + (8281, -1, -1, 8278, 8278, 5, 84, -1, 0, 0, 16, 8280, 8282), + (8282, -1, -1, 8278, 8278, 5, 85, -1, 0, 0, 16, 8281, 8381), + (8283, -1, -1, 8283, 8283, 5, 81, -1, 0, 0, 16, -1, 8284), + (8284, -1, -1, 8283, 8283, 5, 82, -1, 0, 0, 16, 8283, 8285), + (8285, -1, -1, 8283, 8283, 5, 83, -1, 0, 0, 16, 8284, 8286), + (8286, -1, -1, 8283, 8283, 5, 84, -1, 0, 0, 16, 8285, 8287), + (8287, -1, -1, 8283, 8283, 5, 85, -1, 0, 0, 16, 8286, 8391), + (8288, -1, -1, 8288, 8288, 5, 81, -1, 0, 0, 16, -1, 8289), + (8289, -1, -1, 8288, 8288, 5, 82, -1, 0, 0, 16, 8288, 8290), + (8290, -1, -1, 8288, 8288, 5, 83, -1, 0, 0, 16, 8289, 8291), + (8291, -1, -1, 8288, 8288, 5, 84, -1, 0, 0, 16, 8290, 8292), + (8292, -1, -1, 8288, 8288, 5, 85, -1, 0, 0, 16, 8291, 8401), + (8293, -1, -1, 8293, 8293, 5, 81, -1, 0, 0, 16, -1, 8294), + (8294, -1, -1, 8293, 8293, 5, 82, -1, 0, 0, 16, 8293, 8295), + (8295, -1, -1, 8293, 8293, 5, 83, -1, 0, 0, 16, 8294, 8296), + (8296, -1, -1, 8293, 8293, 5, 84, -1, 0, 0, 16, 8295, 8297), + (8297, -1, -1, 8293, 8293, 5, 85, -1, 0, 0, 16, 8296, 8411), + (8300, 8300, 8300, 8300, 8300, 5, 81, 21778, 8, 900, 16, -1, 8301), + (8301, 8300, 8300, 8300, 8300, 7, 83, 21779, 8, 900, 16, 8300, 8302), + (8302, 8300, 8300, 8300, 8300, 9, 85, 21780, 8, 900, 16, 8301, 15111), + (8303, 8303, 8303, 8303, 8303, 12, 85, 21773, 9, 1800, 16, -1, -1), + (8304, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8239, 8305), + (8305, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8304, 8306), + (8306, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8305, 8307), + (8307, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8306, 8308), + (8308, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8307, 13353), + (8309, 260, -1, 260, 260, 5, 81, 21687, 3, 2160, 16, 262, 8310), + (8310, 260, -1, 260, 260, 7, 83, 21688, 3, 2160, 16, 8309, 8311), + (8311, 260, -1, 260, 260, 9, 85, 21689, 3, 2160, 16, 8310, -1), + (8312, 8312, 8312, 8312, 8312, 12, 85, 21690, 2, 900, 16, -1, -1), + (8313, -1, -1, 8040, 8040, 4, 80, -1, 0, 0, 16, 8043, 15773), + (8314, -1, -1, 8314, 8314, 7, 85, -1, 0, 0, 16, -1, 8315), + (8315, -1, -1, 8314, 8314, 9, 85, -1, 0, 0, 16, 8314, 8316), + (8316, -1, -1, 8314, 8314, 12, 85, -1, 0, 0, 16, 8315, 13508), + (8317, -1, -1, 8317, 8317, 5, 85, -1, 0, 0, 16, -1, 8318), + (8318, -1, -1, 8317, 8317, 5, 85, -1, 0, 0, 16, 8317, -1), + (8319, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, -1, 8320), + (8320, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, 8319, 8321), + (8321, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, 8320, -1), + (8322, -1, -1, 8322, 8322, 5, 81, 0, 0, 0, 16, -1, 8323), + (8323, -1, -1, 8322, 8322, 7, 83, 0, 0, 0, 16, 8322, 8324), + (8324, -1, -1, 8322, 8322, 9, 85, 0, 0, 0, 16, 8323, 13199), + (8325, -1, -1, 8325, 8325, 7, 81, 0, 0, 0, 16, -1, 8326), + (8326, -1, -1, 8325, 8325, 9, 81, 0, 0, 0, 16, 8325, 8327), + (8327, -1, -1, 8325, 8325, 11, 81, 0, 0, 0, 16, 8326, 13219), + (8328, -1, -1, 244, 244, 12, 59, -1, 0, 0, 3, 246, -1), + (8329, -1, -1, 622, 622, 3, 71, -1, 0, 0, 16, 624, -1), + (8331, -1, -1, 8331, 8331, 9, 85, 0, 0, 0, 16, -1, -1), + (8332, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, -1, 8333), + (8333, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, 8332, 8334), + (8334, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, 8333, -1), + (8335, -1, -1, 8335, 8335, 5, 81, 0, 0, 0, 16, -1, 8336), + (8336, -1, -1, 8335, 8335, 5, 82, 0, 0, 0, 16, 8335, 8337), + (8337, -1, -1, 8335, 8335, 5, 83, 0, 0, 0, 16, 8336, 8338), + (8338, -1, -1, 8335, 8335, 5, 84, 0, 0, 0, 16, 8337, 8339), + (8339, -1, -1, 8335, 8335, 5, 85, 0, 0, 0, 16, 8338, -1), + (8341, 8341, 8341, 8341, 8341, 12, 85, 21829, 53, 450, 16, -1, -1), + (8342, 8342, 8342, 8342, 8342, 12, 85, 21843, 54, 240, 16, -1, 14729), + (8343, 167, 167, 167, 167, 10, 85, 21837, 14, 900, 16, 7249, 12955), + (8344, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 7583, 8345), + (8345, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 8344, 8346), + (8346, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 8345, 12526), + (8347, -1, -1, 8347, 8347, 7, 81, 0, 0, 0, 16, -1, 8348), + (8348, -1, -1, 8347, 8347, 9, 83, 0, 0, 0, 16, 8347, 8349), + (8349, -1, -1, 8347, 8347, 11, 85, 0, 0, 0, 16, 8348, -1), + (8350, -1, -1, 8350, 8350, 12, 85, 0, 0, 0, 16, -1, -1), + (8351, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8267, 8352), + (8352, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8351, 8353), + (8353, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8352, 8354), + (8354, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8353, 8355), + (8355, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8354, 8356), + (8356, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8355, 8357), + (8357, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8356, 8358), + (8358, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8357, 8359), + (8359, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8358, 8360), + (8360, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8359, 13933), + (8361, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8272, 8362), + (8362, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8361, 8363), + (8363, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8362, 8364), + (8364, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8363, 8365), + (8365, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8364, 8366), + (8366, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8365, 8367), + (8367, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8366, 8368), + (8368, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8367, 8369), + (8369, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8368, 8370), + (8370, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8369, 13943), + (8371, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8277, 8372), + (8372, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8371, 8373), + (8373, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8372, 8374), + (8374, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8373, 8375), + (8375, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8374, 8376), + (8376, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8375, 8377), + (8377, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8376, 8378), + (8378, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8377, 8379), + (8379, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8378, 8380), + (8380, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8379, 13953), + (8381, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8282, 8382), + (8382, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8381, 8383), + (8383, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8382, 8384), + (8384, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8383, 8385), + (8385, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8384, 8386), + (8386, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8385, 8387), + (8387, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8386, 8388), + (8388, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8387, 8389), + (8389, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8388, 8390), + (8390, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8389, 13963), + (8391, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8287, 8392), + (8392, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8391, 8393), + (8393, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8392, 8394), + (8394, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8393, 8395), + (8395, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8394, 8396), + (8396, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8395, 8397), + (8397, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8396, 8398), + (8398, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8397, 8399), + (8399, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8398, 8400), + (8400, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8399, 13973), + (8401, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8292, 8402), + (8402, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8401, 8403), + (8403, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8402, 8404), + (8404, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8403, 8405), + (8405, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8404, 8406), + (8406, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8405, 8407), + (8407, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8406, 8408), + (8408, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8407, 8409), + (8409, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8408, 8410), + (8410, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8409, 13983), + (8411, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8297, 8412), + (8412, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8411, 8413), + (8413, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8412, 8414), + (8414, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8413, 8415), + (8415, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8414, 8416), + (8416, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8415, 8417), + (8417, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8416, 8418), + (8418, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8417, 8419), + (8419, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8418, 8420), + (8420, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8419, 13993), + (8421, -1, -1, 8224, 8224, 5, 90, -1, 0, 0, 17, 8226, -1), + (8422, -1, -1, 8245, 8245, 6, 86, -1, 0, 0, 17, 8249, 8423), + (8423, -1, -1, 8245, 8245, 6, 87, -1, 0, 0, 17, 8422, 8424), + (8424, -1, -1, 8245, 8245, 6, 88, -1, 0, 0, 17, 8423, 8425), + (8425, -1, -1, 8245, 8245, 6, 89, -1, 0, 0, 17, 8424, 8426), + (8426, -1, -1, 8245, 8245, 6, 90, -1, 0, 0, 17, 8425, 13338), + (8427, -1, -1, 7100, 7100, 6, 85, -1, 0, 0, 17, 7325, 8428), + (8428, -1, -1, 7100, 7100, 6, 87, -1, 0, 0, 17, 8427, 8429), + (8429, -1, -1, 7100, 7100, 6, 89, -1, 0, 0, 17, 8428, -1), + (8430, -1, -1, 1026, 1026, 10, 91, -1, 0, 0, 18, 7890, 8431), + (8435, -1, -1, 65, 661, 8, 91, -1, 0, 0, 18, 7908, 8436), + (8440, -1, -1, 122, 122, 13, 91, -1, 0, 0, 18, 13089, 8441), + (8445, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 12637, 8446), + (8446, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8445, 8447), + (8447, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8446, 16419), + (8448, -1, -1, 6119, 6119, 8, 91, -1, 0, 0, 18, 12496, 8449), + (8463, -1, -1, 125, 125, 10, 91, -1, 0, 0, 18, 13084, 8464), + (8464, -1, -1, 125, 125, 11, 91, -1, 0, 0, 18, 8463, 8465), + (8470, -1, -1, 1006, 1006, 10, 91, -1, 0, 0, 18, 7841, 8471), + (9000, 9000, 9000, 9000, 9000, 0, 1, 16995, 49, 72000, 0, -1, -1), + (9001, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, -1, 9002), + (9002, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9001, 9003), + (9003, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9002, 9004), + (9004, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9003, 9005), + (9005, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9004, 9006), + (9006, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9005, 9007), + (9007, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9006, 9008), + (9008, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9007, 9009), + (9009, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9008, 9010), + (9010, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9009, -1), + (9011, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, -1, 9012), + (9012, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9011, 9013), + (9013, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9012, 9014), + (9014, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9013, 9015), + (9015, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9014, 9016), + (9016, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9015, 9017), + (9017, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9016, 9018), + (9018, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9017, 9019), + (9019, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9018, 9020), + (9020, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9019, -1), + (9021, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, -1, 9022), + (9022, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9021, 9023), + (9023, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9022, 9024), + (9024, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9023, 9025), + (9025, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9024, 9026), + (9026, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9025, 9027), + (9027, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9026, 9028), + (9028, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9027, 9029), + (9029, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9028, 9030), + (9030, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9029, -1), + (9031, 9031, 9031, 9031, 9031, 0, 1, 16601, 65, 72000, 0, -1, -1), + (9032, 9032, 9032, 9032, 9032, 0, 0, 21815, 51, 72000, 0, -1, -1), + (9033, -1, -1, 9033, 9033, 0, 1, -1, 0, 0, 0, -1, -1), + (9100, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, -1, 9101), + (9101, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9100, 9102), + (9102, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9101, 9103), + (9103, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9102, 9104), + (9104, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9103, 9105), + (9105, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9104, 9106), + (9106, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9105, 9107), + (9107, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9106, 9108), + (9108, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9107, -1), + (9109, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, -1, 9110), + (9110, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9109, 9111), + (9111, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9110, 9112), + (9112, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9111, 9113), + (9113, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9112, 9114), + (9114, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9113, 9115), + (9115, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9114, 9116), + (9116, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9115, 9117), + (9117, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9116, -1), + (9118, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, -1, 9119), + (9119, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9118, 9120), + (9120, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9119, 9121), + (9121, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9120, 9122), + (9122, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9121, 9123), + (9123, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9122, 9124), + (9124, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9123, 9125), + (9125, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9124, 9126), + (9126, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9125, -1), + (9127, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, -1, 9128), + (9128, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9127, 9129), + (9129, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9128, 9130), + (9130, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9129, 9131), + (9131, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9130, 9132), + (9132, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9131, 9133), + (9133, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9132, 9134), + (9134, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9133, 9135), + (9135, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9134, -1), + (9136, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, -1, 9137), + (9137, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9136, 9138), + (9138, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9137, 9139), + (9139, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9138, 9140), + (9140, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9139, 9141), + (9141, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9140, 9142), + (9142, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9141, 9143), + (9143, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9142, 9144), + (9144, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9143, -1), + (9145, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, -1, 9146), + (9146, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9145, 9147), + (9147, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9146, 9148), + (9148, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9147, 9149), + (9149, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9148, 9150), + (9150, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9149, 9151), + (9151, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9150, 9152), + (9152, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9151, 9153), + (9153, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9152, -1), + (9154, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, -1, 9155), + (9155, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9154, 9156), + (9156, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9155, 9157), + (9157, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9156, 9158), + (9158, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9157, 9159), + (9159, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9158, 9160), + (9160, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9159, 9161), + (9161, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9160, 9162), + (9162, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9161, -1), + (9163, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, -1, 9164), + (9164, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9163, 9165), + (9165, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9164, 9166), + (9166, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9165, 9167), + (9167, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9166, 9168), + (9168, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9167, 9169), + (9169, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9168, 9170), + (9170, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9169, 9171), + (9171, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9170, -1), + (9172, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, -1, 9173), + (9173, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9172, 9174), + (9174, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9173, 9175), + (9175, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9174, 9176), + (9176, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9175, 9177), + (9177, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9176, 9178), + (9178, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9177, 9179), + (9179, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9178, 9180), + (9180, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9179, -1), + (9181, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, -1, 9182), + (9182, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9181, 9183), + (9183, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9182, 9184), + (9184, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9183, 9185), + (9185, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9184, 9186), + (9186, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9185, 9187), + (9187, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9186, 9188), + (9188, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9187, 9189), + (9189, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9188, -1), + (9190, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, -1, 9191), + (9191, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9190, 9192), + (9192, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9191, 9193), + (9193, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9192, 9194), + (9194, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9193, 9195), + (9195, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9194, 9196), + (9196, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9195, 9197), + (9197, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9196, 9198), + (9198, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9197, -1), + (9199, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, -1, 9200), + (9200, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9199, 9201), + (9201, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9200, 9202), + (9202, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9201, 9203), + (9203, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9202, 9204), + (9204, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9203, 9205), + (9205, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9204, 9206), + (9206, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9205, 9207), + (9207, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9206, -1), + (9208, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, -1, 9209), + (9209, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9208, 9210), + (9210, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9209, 9211), + (9211, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9210, 9212), + (9212, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9211, 9213), + (9213, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9212, 9214), + (9214, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9213, 9215), + (9215, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9214, 9216), + (9216, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9215, -1), + (9217, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, -1, 9218), + (9218, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9217, 9219), + (9219, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9218, 9220), + (9220, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9219, 9221), + (9221, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9220, 9222), + (9222, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9221, 9223), + (9223, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9222, 9224), + (9224, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9223, 9225), + (9225, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9224, -1), + (9226, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, -1, 9227), + (9227, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9226, 9228), + (9228, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9227, 9229), + (9229, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9228, 9230), + (9230, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9229, 9231), + (9231, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9230, 9232), + (9232, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9231, 9233), + (9233, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9232, 9234), + (9234, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9233, -1), + (9235, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, -1, 9236), + (9236, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9235, 9237), + (9237, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9236, 9238), + (9238, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9237, 9239), + (9239, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9238, 9240), + (9240, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9239, 9241), + (9241, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9240, 9242), + (9242, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9241, 9243), + (9243, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9242, -1), + (9300, 9300, 9300, 9300, 9300, 5, 85, 16212, 40, 600, 15, -1, 9301), + (9301, 9300, 9300, 9300, 9300, 5, 85, 16213, 40, 600, 15, 9300, 9302), + (9302, 9300, 9300, 9300, 9300, 5, 85, 16214, 40, 600, 15, 9301, -1), + (9303, 9303, 9303, 9303, 9303, 5, 85, 16215, 40, 600, 15, -1, 9304), + (9304, 9303, 9303, 9303, 9303, 5, 85, 16216, 40, 600, 15, 9303, 9305), + (9305, 9303, 9303, 9303, 9303, 5, 85, 16217, 40, 600, 15, 9304, -1), + (9306, 9306, 9306, 9306, 9306, 5, 85, 16218, 40, 600, 15, -1, 9307), + (9307, 9306, 9306, 9306, 9306, 5, 85, 16219, 40, 600, 15, 9306, 9308), + (9308, 9306, 9306, 9306, 9306, 5, 85, 16220, 40, 600, 15, 9307, -1), + (9309, 9309, 9309, 9309, 9309, 5, 85, 16249, 40, 600, 15, -1, 9310), + (9310, 9309, 9309, 9309, 9309, 5, 85, 16250, 40, 600, 15, 9309, 9311), + (9311, 9309, 9309, 9309, 9309, 5, 85, 16251, 40, 600, 15, 9310, -1), + (9312, 9312, 9312, 9312, 9312, 5, 85, 16252, 40, 600, 15, -1, 9313), + (9313, 9312, 9312, 9312, 9312, 5, 85, 16253, 40, 600, 15, 9312, 9314), + (9314, 9312, 9312, 9312, 9312, 5, 85, 16254, 40, 600, 15, 9313, -1), + (9315, 9315, 9315, 9315, 9315, 5, 85, 16255, 40, 600, 15, -1, 9316), + (9316, 9315, 9315, 9315, 9315, 5, 85, 16256, 40, 600, 15, 9315, 9317), + (9317, 9315, 9315, 9315, 9315, 5, 85, 16257, 40, 600, 15, 9316, -1), + (9318, 9318, 9318, 9318, 9318, 5, 85, 16261, 40, 600, 15, -1, 9319), + (9319, 9318, 9318, 9318, 9318, 5, 85, 16262, 40, 600, 15, 9318, 9320), + (9320, 9318, 9318, 9318, 9318, 5, 85, 16263, 40, 600, 15, 9319, -1), + (9321, 9321, 9321, 9321, 9321, 5, 85, 16264, 40, 600, 15, -1, 9322), + (9322, 9321, 9321, 9321, 9321, 5, 85, 16265, 40, 600, 15, 9321, 9323), + (9323, 9321, 9321, 9321, 9321, 5, 85, 16266, 40, 600, 15, 9322, -1), + (9324, 9324, 9324, 9324, 9324, 5, 85, 16267, 40, 600, 15, -1, 9325), + (9325, 9324, 9324, 9324, 9324, 5, 85, 16268, 40, 600, 15, 9324, 9326), + (9326, 9324, 9324, 9324, 9324, 5, 85, 16269, 40, 600, 15, 9325, -1), + (9327, 9327, 9327, 9327, 9327, 5, 85, 16270, 40, 600, 15, -1, 9328), + (9328, 9327, 9327, 9327, 9327, 5, 85, 16271, 40, 600, 15, 9327, 9329), + (9329, 9327, 9327, 9327, 9327, 5, 85, 16272, 40, 600, 15, 9328, -1), + (9330, 9330, 9330, 9330, 9330, 5, 85, 16273, 40, 600, 15, -1, 9331), + (9331, 9330, 9330, 9330, 9330, 5, 85, 16274, 40, 600, 15, 9330, 9332), + (9332, 9330, 9330, 9330, 9330, 5, 85, 16275, 40, 600, 15, 9331, -1), + (9333, 9333, 9333, 9333, 9333, 5, 85, 16276, 40, 600, 15, -1, 9334), + (9334, 9333, 9333, 9333, 9333, 5, 85, 16277, 40, 600, 15, 9333, 9335), + (9335, 9333, 9333, 9333, 9333, 5, 85, 16278, 40, 600, 15, 9334, -1), + (9336, 9336, 9336, 9336, 9336, 5, 85, 16284, 40, 600, 15, -1, 9337), + (9337, 9336, 9336, 9336, 9336, 5, 85, 16285, 40, 600, 15, 9336, 9338), + (9338, 9336, 9336, 9336, 9336, 5, 85, 16286, 40, 600, 15, 9337, -1), + (9339, 9339, 9339, 9339, 9339, 5, 85, 16287, 40, 600, 15, -1, 9340), + (9340, 9339, 9339, 9339, 9339, 5, 85, 16288, 40, 600, 15, 9339, 9341), + (9341, 9339, 9339, 9339, 9339, 5, 85, 16289, 40, 600, 15, 9340, -1), + (9342, 9342, 9342, 9342, 9342, 5, 85, 16290, 40, 600, 15, -1, 9343), + (9343, 9342, 9342, 9342, 9342, 5, 85, 16291, 40, 600, 15, 9342, 9344), + (9344, 9342, 9342, 9342, 9342, 5, 85, 16292, 40, 600, 15, 9343, -1), + (9345, 9345, 9345, 9345, 9345, 5, 85, 16293, 40, 600, 15, -1, 9346), + (9346, 9345, 9345, 9345, 9345, 5, 85, 16294, 40, 600, 15, 9345, 9347), + (9347, 9345, 9345, 9345, 9345, 5, 85, 16295, 40, 600, 15, 9346, -1), + (9348, 9348, 9348, 9348, 9348, 5, 85, 16296, 40, 600, 15, -1, 9349), + (9349, 9348, 9348, 9348, 9348, 5, 85, 16297, 40, 600, 15, 9348, 9350), + (9350, 9348, 9348, 9348, 9348, 5, 85, 16298, 40, 600, 15, 9349, -1), + (9351, 9351, 9351, 9351, 9351, 5, 85, 16299, 40, 600, 15, -1, 9352), + (9352, 9351, 9351, 9351, 9351, 5, 85, 16300, 40, 600, 15, 9351, 9353), + (9353, 9351, 9351, 9351, 9351, 5, 85, 16301, 40, 600, 15, 9352, -1), + (9354, 9354, 9354, 9354, 9354, 5, 85, 16305, 40, 600, 15, -1, 9355), + (9355, 9354, 9354, 9354, 9354, 5, 85, 16306, 40, 600, 15, 9354, 9356), + (9356, 9354, 9354, 9354, 9354, 5, 85, 16307, 40, 600, 15, 9355, 12626), + (9357, 9357, 9357, 9357, 9357, 5, 85, 16308, 40, 600, 15, -1, 9358), + (9358, 9357, 9357, 9357, 9357, 5, 85, 16309, 40, 600, 15, 9357, 9359), + (9359, 9357, 9357, 9357, 9357, 5, 85, 16310, 40, 600, 15, 9358, 12629), + (9360, 9360, 9360, 9360, 9360, 5, 85, 16311, 40, 600, 15, -1, 9361), + (9361, 9360, 9360, 9360, 9360, 5, 85, 16312, 40, 600, 15, 9360, 9362), + (9362, 9360, 9360, 9360, 9360, 5, 85, 16313, 40, 600, 15, 9361, 12632), + (9363, 9363, 9363, 9363, 9363, 5, 85, 16317, 40, 600, 15, -1, 9364), + (9364, 9363, 9363, 9363, 9363, 5, 85, 16318, 40, 600, 15, 9363, 9365), + (9365, 9363, 9363, 9363, 9363, 5, 85, 16319, 40, 600, 15, 9364, -1), + (9366, 9366, 9366, 9366, 9366, 5, 85, 16320, 40, 600, 15, -1, 9367), + (9367, 9366, 9366, 9366, 9366, 5, 85, 16321, 40, 600, 15, 9366, 9368), + (9368, 9366, 9366, 9366, 9366, 5, 85, 16322, 40, 600, 15, 9367, -1), + (9369, 9369, 9369, 9369, 9369, 5, 85, 16323, 40, 600, 15, -1, 9370), + (9370, 9369, 9369, 9369, 9369, 5, 85, 16324, 40, 600, 15, 9369, 9371), + (9371, 9369, 9369, 9369, 9369, 5, 85, 16325, 40, 600, 15, 9370, -1), + (9372, 9372, 9372, 9372, 9372, 5, 85, 16326, 40, 600, 15, -1, 9373), + (9373, 9372, 9372, 9372, 9372, 5, 85, 16327, 40, 600, 15, 9372, 9374), + (9374, 9372, 9372, 9372, 9372, 5, 85, 16328, 40, 600, 15, 9373, -1), + (9375, 9375, 9375, 9375, 9375, 5, 85, 16329, 40, 600, 15, -1, 9376), + (9376, 9375, 9375, 9375, 9375, 5, 85, 16330, 40, 600, 15, 9375, 9377), + (9377, 9375, 9375, 9375, 9375, 5, 85, 16331, 40, 600, 15, 9376, -1), + (9378, 9378, 9378, 9378, 9378, 5, 85, 16332, 40, 600, 15, -1, 9379), + (9379, 9378, 9378, 9378, 9378, 5, 85, 16333, 40, 600, 15, 9378, 9380), + (9380, 9378, 9378, 9378, 9378, 5, 85, 16334, 40, 600, 15, 9379, -1), + (9381, 9381, 9381, 9381, 9381, 5, 85, 16335, 40, 600, 15, -1, 9382), + (9382, 9381, 9381, 9381, 9381, 5, 85, 16336, 40, 600, 15, 9381, 9383), + (9383, 9381, 9381, 9381, 9381, 5, 85, 16337, 40, 600, 15, 9382, -1), + (9384, 9384, 9384, 9384, 9384, 5, 85, 16338, 40, 600, 15, -1, 9385), + (9385, 9384, 9384, 9384, 9384, 5, 85, 16339, 40, 600, 15, 9384, 9386), + (9386, 9384, 9384, 9384, 9384, 5, 85, 16340, 40, 600, 15, 9385, -1), + (9387, 9387, 9387, 9387, 9387, 5, 85, 16341, 40, 600, 15, -1, 9388), + (9388, 9387, 9387, 9387, 9387, 5, 85, 16342, 40, 600, 15, 9387, 9389), + (9389, 9387, 9387, 9387, 9387, 5, 85, 16343, 40, 600, 15, 9388, -1), + (9390, 9390, 9390, 9390, 9390, 5, 85, 16344, 40, 600, 15, -1, 9391), + (9391, 9390, 9390, 9390, 9390, 5, 85, 16345, 40, 600, 15, 9390, 9392), + (9392, 9390, 9390, 9390, 9390, 5, 85, 16346, 40, 600, 15, 9391, -1), + (9393, 9393, 9393, 9393, 9393, 5, 85, 16347, 40, 600, 15, -1, 9394), + (9394, 9393, 9393, 9393, 9393, 5, 85, 16348, 40, 600, 15, 9393, 9395), + (9395, 9393, 9393, 9393, 9393, 5, 85, 16349, 40, 600, 15, 9394, -1), + (9396, 9396, 9396, 9396, 9396, 5, 85, 16350, 40, 600, 15, -1, 9397), + (9397, 9396, 9396, 9396, 9396, 5, 85, 16351, 40, 600, 15, 9396, 9398), + (9398, 9396, 9396, 9396, 9396, 5, 85, 16352, 40, 600, 15, 9397, -1), + (9399, 9399, 9399, 9399, 9399, 5, 85, 16359, 40, 600, 15, -1, 9400), + (9400, 9399, 9399, 9399, 9399, 5, 85, 16360, 40, 600, 15, 9399, 9401), + (9401, 9399, 9399, 9399, 9399, 5, 85, 16361, 40, 600, 15, 9400, -1), + (9402, 9402, 9402, 9402, 9402, 5, 85, 16362, 40, 600, 15, -1, 9403), + (9403, 9402, 9402, 9402, 9402, 5, 85, 16363, 40, 600, 15, 9402, 9404), + (9404, 9402, 9402, 9402, 9402, 5, 85, 16364, 40, 600, 15, 9403, -1), + (9405, 9405, 9405, 9405, 9405, 5, 85, 16365, 40, 600, 15, -1, 9406), + (9406, 9405, 9405, 9405, 9405, 5, 85, 16366, 40, 600, 15, 9405, 9407), + (9407, 9405, 9405, 9405, 9405, 5, 85, 16367, 40, 600, 15, 9406, -1), + (9408, 9408, 9408, 9408, 9408, 5, 85, 16368, 40, 600, 15, -1, 9409), + (9409, 9408, 9408, 9408, 9408, 5, 85, 16369, 40, 600, 15, 9408, 9410), + (9410, 9408, 9408, 9408, 9408, 5, 85, 16370, 40, 600, 15, 9409, -1), + (9411, 9411, 9411, 9411, 9411, 5, 85, 16371, 40, 600, 15, -1, 9412), + (9412, 9411, 9411, 9411, 9411, 5, 85, 16372, 40, 600, 15, 9411, 9413), + (9413, 9411, 9411, 9411, 9411, 5, 85, 16373, 40, 600, 15, 9412, -1), + (9414, 9414, 9414, 9414, 9414, 5, 85, 16374, 40, 600, 15, -1, 9415), + (9415, 9414, 9414, 9414, 9414, 5, 85, 16375, 40, 600, 15, 9414, 9416), + (9416, 9414, 9414, 9414, 9414, 5, 85, 16376, 40, 600, 15, 9415, -1), + (9417, 9417, 9417, 9417, 9417, 5, 85, 16377, 40, 600, 15, -1, 9418), + (9418, 9417, 9417, 9417, 9417, 5, 85, 16378, 40, 600, 15, 9417, 9419), + (9419, 9417, 9417, 9417, 9417, 5, 85, 16379, 40, 600, 15, 9418, -1), + (9420, 9420, 9420, 9420, 9420, 5, 85, 16380, 40, 600, 15, -1, 9421), + (9421, 9420, 9420, 9420, 9420, 5, 85, 16381, 40, 600, 15, 9420, 9422), + (9422, 9420, 9420, 9420, 9420, 5, 85, 16382, 40, 600, 15, 9421, -1), + (9423, 9423, 9423, 9423, 9423, 5, 85, 16386, 40, 600, 15, -1, 9424), + (9424, 9423, 9423, 9423, 9423, 5, 85, 16387, 40, 600, 15, 9423, 9425), + (9425, 9423, 9423, 9423, 9423, 5, 85, 16388, 40, 600, 15, 9424, -1), + (9426, 9426, 9426, 9426, 9426, 5, 85, 16389, 40, 600, 15, -1, 9427), + (9427, 9426, 9426, 9426, 9426, 5, 85, 16390, 40, 600, 15, 9426, 9428), + (9428, 9426, 9426, 9426, 9426, 5, 85, 16391, 40, 600, 15, 9427, -1), + (9429, 9429, 9429, 9429, 9429, 5, 85, 16392, 40, 600, 15, -1, 9430), + (9430, 9429, 9429, 9429, 9429, 5, 85, 16393, 40, 600, 15, 9429, 9431), + (9431, 9429, 9429, 9429, 9429, 5, 85, 16394, 40, 600, 15, 9430, -1), + (9432, 9432, 9432, 9432, 9432, 5, 85, 16395, 40, 600, 15, -1, 9433), + (9433, 9432, 9432, 9432, 9432, 5, 85, 16396, 40, 600, 15, 9432, 9434), + (9434, 9432, 9432, 9432, 9432, 5, 85, 16397, 40, 600, 15, 9433, -1), + (9435, 9435, 9435, 9435, 9435, 5, 85, 16398, 40, 600, 15, -1, 9436), + (9436, 9435, 9435, 9435, 9435, 5, 85, 16399, 40, 600, 15, 9435, 9437), + (9437, 9435, 9435, 9435, 9435, 5, 85, 16400, 40, 600, 15, 9436, -1), + (9438, 9438, 9438, 9438, 9438, 5, 85, 16401, 40, 600, 15, -1, 9439), + (9439, 9438, 9438, 9438, 9438, 5, 85, 16402, 40, 600, 15, 9438, 9440), + (9440, 9438, 9438, 9438, 9438, 5, 85, 16403, 40, 600, 15, 9439, -1), + (9441, 9441, 9441, 9441, 9441, 5, 85, 16404, 40, 600, 15, -1, 9442), + (9442, 9441, 9441, 9441, 9441, 5, 85, 16405, 40, 600, 15, 9441, 9443), + (9443, 9441, 9441, 9441, 9441, 5, 85, 16406, 40, 600, 15, 9442, -1), + (9500, 9500, 9500, 9500, 9500, 3, 76, 16247, 47, 60, 15, -1, -1), + (9501, 9501, 9501, 9501, 9501, 9, 85, 16247, 47, 600, 15, -1, -1), + (9502, 9502, 9502, 9502, 9502, 7, 81, 16248, 48, 3600, 15, -1, -1), + (9503, -1, -1, 9503, 9503, 7, 83, -1, 0, 0, 15, -1, 9504), + (9504, -1, -1, 9503, 9503, 7, 84, -1, 0, 0, 15, 9503, 9505), + (9505, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 15, 9504, 10087), + (9506, -1, -1, 9506, 9506, 7, 81, -1, 0, 0, 15, -1, 9507), + (9507, -1, -1, 9506, 9506, 7, 83, -1, 0, 0, 15, 9506, 9508), + (9508, -1, -1, 9506, 9506, 7, 85, -1, 0, 0, 15, 9507, 13630), + (9509, -1, -1, 9509, 9509, 7, 81, -1, 0, 0, 15, -1, 9510), + (9510, -1, -1, 9509, 9509, 7, 82, -1, 0, 0, 15, 9509, 9511), + (9511, -1, -1, 9509, 9509, 7, 83, -1, 0, 0, 15, 9510, 9515), + (9512, -1, -1, 9512, 9512, 7, 81, -1, 0, 0, 15, -1, 9513), + (9513, -1, -1, 9512, 9512, 7, 82, -1, 0, 0, 15, 9512, 9514), + (9514, -1, -1, 9512, 9512, 7, 83, -1, 0, 0, 15, 9513, 7819), + (9515, -1, -1, 9509, 9509, 7, 86, -1, 0, 0, 17, 9511, 16361), + (10003, 6610, 6610, 6610, 6610, 5, 60, 16494, 41, 30, 16, 6610, 10573), + (10004, -1, -1, 6614, 6614, 6, 70, -1, 0, 0, 16, 6616, 10005), + (10005, -1, -1, 6614, 6614, 9, 70, -1, 0, 0, 16, 10004, 10575), + (10006, 54006, 54006, 54006, 54006, 7, 85, 16495, 18, 180, 16, 7111, 13425), + (10007, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 7114, 10008), + (10008, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 10007, 10009), + (10009, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 10008, 10568), + (10010, 6565, 6565, 6565, 6565, 7, 85, 16496, 17, 45, 16, 7115, 10517), + (10011, 912, 912, 912, 912, 9, 80, 16497, 4, 3600, 16, 7121, 10012), + (10012, 912, 912, 912, 912, 9, 80, 16498, 4, 3600, 16, 10011, 10013), + (10013, 912, 912, 912, 912, 9, 80, 16499, 4, 3600, 16, 10012, 10585), + (10014, 1383, 1383, 1383, 1383, 12, 85, 21766, 6, 300, 16, 7299, 6487), + (10015, 1195, 1195, 1195, 1195, 9, 85, 16504, 13, 2160, 16, 7300, 13259), + (10016, 131, 131, 131, 131, 10, 85, 16505, 4, 900, 16, 7303, 10017), + (10017, 131, 131, 131, 131, 10, 85, 16506, 4, 900, 16, 10016, 10018), + (10018, 131, 131, 131, 131, 10, 85, 16507, 4, 900, 16, 10017, 7770), + (10019, 1192, 1192, 1192, 1192, 10, 85, 20177, 12, 1320, 16, 7306, 10020), + (10020, 1192, 1192, 1192, 1192, 10, 85, 21652, 12, 1320, 16, 10019, 10021), + (10021, 1192, 1192, 1192, 1192, 10, 85, 21704, 12, 1320, 16, 10020, 13363), + (10022, 746, 746, 746, 746, 12, 85, 16511, 10, 2160, 16, 7309, 10023), + (10023, 746, 746, 746, 746, 12, 85, 16512, 10, 2160, 16, 10022, 10024), + (10024, 746, 746, 746, 746, 12, 85, 16513, 10, 2160, 16, 10023, 15321), + (10025, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 7322, 10026), + (10026, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10025, 10027), + (10027, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10026, 10028), + (10028, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10027, 10029), + (10029, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10028, 10437), + (10030, -1, -1, 7940, 7940, 5, 75, -1, 0, 0, 16, 7942, 10031), + (10031, -1, -1, 7940, 7940, 7, 75, -1, 0, 0, 16, 10030, 10032), + (10032, -1, -1, 7940, 7940, 9, 75, -1, 0, 0, 16, 10031, 6484), + (10033, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 7947, 10034), + (10034, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 10033, 10347), + (10035, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 7950, 10036), + (10036, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 10035, 10037), + (10037, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 10036, 15328), + (10038, 7951, 7951, 7951, 7951, 6, 85, 16514, 61, 900, 16, 7953, 10039), + (10039, 7951, 7951, 7951, 7951, 6, 85, 16515, 61, 900, 16, 10038, 10040), + (10040, 7951, 7951, 7951, 7951, 6, 85, 16516, 61, 900, 16, 10039, 7773), + (10041, -1, -1, 6636, 6636, 9, 75, -1, 0, 0, 16, 6638, 10042), + (10042, -1, -1, 6636, 6636, 10, 75, -1, 0, 0, 16, 10041, 10043), + (10043, -1, -1, 6636, 6636, 11, 75, -1, 0, 0, 16, 10042, 12529), + (10044, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 6793, 10045), + (10045, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 10044, 10046), + (10046, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 10045, 10676), + (10047, 534, 534, 534, 534, 12, 85, 16561, 4, 2160, 16, 7331, 10048), + (10048, 534, 534, 534, 534, 12, 85, 16562, 4, 2160, 16, 10047, 10049), + (10049, 534, 534, 534, 534, 12, 85, 16563, 4, 2160, 16, 10048, 10708), + (10050, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 7338, 10051), + (10051, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 10050, 10052), + (10052, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 10051, 10705), + (10053, 6754, 6754, 6754, 6754, 9, 75, 16570, 41, 1200, 16, 6754, 14111), + (10054, 6758, 6758, 6758, 6758, 10, 85, 16571, 43, 900, 16, 6760, 10055), + (10055, 6758, 6758, 6758, 6758, 11, 85, 16572, 43, 900, 16, 10054, 10056), + (10056, 6758, 6758, 6758, 6758, 12, 85, 16573, 43, 900, 16, 10055, 13546), + (10057, 6764, 6764, 6764, 6764, 9, 80, 16574, 52, 600, 16, 6764, 16716), + (10058, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 6767, 10059), + (10059, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 10058, 10060), + (10060, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 10059, 10766), + (10061, 5007, 5007, 5007, 5007, 9, 85, 16575, 8, 2160, 16, 7343, 10062), + (10062, 5007, 5007, 5007, 5007, 9, 85, 16576, 8, 2160, 16, 10061, 10063), + (10063, 5007, 5007, 5007, 5007, 9, 85, 16577, 8, 2160, 16, 10062, 13119), + (10064, -1, -1, 1608, 1608, 6, 85, -1, 0, 0, 16, 7383, 10065), + (10065, -1, -1, 1608, 1608, 7, 85, -1, 0, 0, 16, 10064, 10066), + (10066, -1, -1, 1608, 1608, 8, 85, -1, 0, 0, 16, 10065, 10067), + (10067, -1, -1, 1608, 1608, 9, 85, -1, 0, 0, 16, 10066, 10068), + (10068, -1, -1, 1608, 1608, 10, 85, -1, 0, 0, 16, 10067, 10069), + (10069, -1, -1, 1608, 1608, 11, 85, -1, 0, 0, 16, 10068, 16730), + (10070, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 6634, 10071), + (10071, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10070, 10072), + (10072, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10071, 10073), + (10073, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10072, 10074), + (10074, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10073, 13621), + (10075, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 6643, 10076), + (10076, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 10075, 10077), + (10077, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 10076, 16192), + (10078, 6508, 6508, 6508, 6508, 7, 85, 16578, 38, 600, 16, 7389, 10079), + (10079, 6508, 6508, 6508, 6508, 7, 85, 16579, 38, 600, 16, 10078, 10080), + (10080, 6508, 6508, 6508, 6508, 7, 85, 16580, 38, 600, 16, 10079, 15775), + (10081, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 7398, 10082), + (10082, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 10081, 10083), + (10083, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 10082, 12579), + (10084, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 7663, 10085), + (10085, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 10084, 10086), + (10086, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 10085, 5347), + (10087, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 9505, 10088), + (10088, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 10087, 10089), + (10089, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 10088, 12792), + (10090, 1498, 1498, 1498, 1498, 12, 85, 16590, 12, 1320, 16, 7410, 10091), + (10091, 1498, 1498, 1498, 1498, 12, 85, 16591, 12, 1320, 16, 10090, 10092), + (10092, 1498, 1498, 1498, 1498, 12, 85, 16602, 12, 1320, 16, 10091, 13401), + (10093, 1495, 1495, 1495, 1495, 9, 86, 16603, 30, 900, 17, 7416, 10094), + (10096, 548, 548, 548, 548, 10, 85, 16606, 5, 900, 16, 7419, 10097), + (10097, 548, 548, 548, 548, 10, 85, 16607, 5, 900, 16, 10096, 10098), + (10098, 548, 548, 548, 548, 10, 85, 16608, 5, 900, 16, 10097, 13158), + (10099, 6561, 6561, 6561, 6561, 7, 85, 16609, 32, 30, 16, 7424, 10100), + (10100, 6561, 6561, 6561, 6561, 7, 85, 16610, 32, 30, 16, 10099, 10101), + (10101, 6561, 6561, 6561, 6561, 7, 85, 16611, 32, 30, 16, 10100, 10418), + (10102, 510, 510, 510, 510, 3, 75, 16587, 37, 240, 16, 7427, 10103), + (10103, 510, 510, 510, 510, 3, 75, 16588, 37, 240, 16, 10102, 10104), + (10104, 510, 510, 510, 510, 3, 75, 16589, 37, 240, 16, 10103, 10824), + (10105, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 7668, 10106), + (10106, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10105, 10107), + (10107, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10106, 10108), + (10108, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10107, 10109), + (10109, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10108, 17350), + (10110, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 7985, 10111), + (10111, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 10110, 10112), + (10112, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 10111, -1), + (10113, 1352, 1352, 1352, 1352, 6, 85, 16618, 3, 60, 16, 7156, 10114), + (10114, 1352, 1352, 1352, 1352, 6, 85, 16619, 3, 60, 16, 10113, 10115), + (10115, 1352, 1352, 1352, 1352, 6, 85, 16620, 3, 60, 16, 10114, 13807), + (10116, 1358, 1358, 1358, 1358, 6, 85, 16615, 3, 60, 16, 7159, 10117), + (10117, 1358, 1358, 1358, 1358, 6, 85, 16616, 3, 60, 16, 10116, 10118), + (10118, 1358, 1358, 1358, 1358, 6, 85, 16617, 3, 60, 16, 10117, 13810), + (10119, 1355, 1355, 1355, 1355, 6, 85, 16612, 3, 60, 16, 7174, 10120), + (10120, 1355, 1355, 1355, 1355, 6, 85, 16613, 3, 60, 16, 10119, 10121), + (10121, 1355, 1355, 1355, 1355, 6, 85, 16614, 3, 60, 16, 10120, 12700), + (10122, -1, -1, 4801, 4801, 6, 85, -1, 0, 0, 16, 7162, 10123), + (10123, -1, -1, 4801, 4801, 6, 85, -1, 0, 0, 16, 10122, 12674), + (10124, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 7177, 10125), + (10125, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 10124, 10126), + (10126, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 10125, 12703), + (10127, 7872, 7872, 7872, 7872, 6, 85, 16621, 41, 600, 16, 7874, 10128), + (10128, 7872, 7872, 7872, 7872, 6, 85, 16622, 41, 600, 16, 10127, 10129), + (10129, 7872, 7872, 7872, 7872, 6, 85, 16623, 41, 600, 16, 10128, 12682), + (10130, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 6872, 10131), + (10131, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 10130, 10132), + (10132, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 10131, -1), + (10133, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 6875, 10134), + (10134, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 10133, 10135), + (10135, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 10134, 13196), + (10136, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 6878, 10137), + (10137, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 10136, 10138), + (10138, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 10137, 12734), + (10139, 6533, 6533, 6533, 6533, 10, 85, 16631, 15, 600, 16, 7428, 12740), + (10140, 1116, 1116, 1116, 1116, 12, 85, 16647, 4, 2160, 16, 7432, 10141), + (10141, 1116, 1116, 1116, 1116, 12, 85, 16648, 4, 2160, 16, 10140, 10142), + (10142, 1116, 1116, 1116, 1116, 12, 85, 16649, 4, 2160, 16, 10141, 12743), + (10143, 5298, 5298, 5298, 5298, 12, 85, 16632, 32, 1800, 16, 7440, 10144), + (10144, 5298, 5298, 5298, 5298, 12, 85, 16633, 32, 1800, 16, 10143, 10145), + (10145, 5298, 5298, 5298, 5298, 12, 85, 16634, 32, 1800, 16, 10144, 12746), + (10146, 1598, -1, 1598, 1598, 12, 85, 16638, 6, 900, 16, 7443, 10147), + (10147, 1598, -1, 1598, 1598, 12, 85, 16639, 6, 900, 16, 10146, 10148), + (10148, 1598, -1, 1598, 1598, 12, 85, 16640, 6, 900, 16, 10147, 13193), + (10149, 5020, 5020, 5020, 5020, 9, 85, 16630, 9, 300, 16, 7444, 13490), + (10150, 1110, 1110, 1110, 1110, 6, 85, 16641, 3, 2160, 16, 7447, 10151), + (10151, 1110, 1110, 1110, 1110, 6, 85, 16642, 3, 2160, 16, 10150, 10152), + (10152, 1110, 1110, 1110, 1110, 6, 85, 16643, 3, 2160, 16, 10151, 13190), + (10153, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 7450, 10154), + (10154, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 10153, 10155), + (10155, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 10154, 16297), + (10156, 5017, 5017, 5017, 5017, 9, 85, 16627, 8, 600, 16, 7456, 10157), + (10157, 5017, 5017, 5017, 5017, 9, 85, 16628, 8, 600, 16, 10156, 10158), + (10158, 5017, 5017, 5017, 5017, 9, 85, 16629, 8, 600, 16, 10157, 14189), + (10159, 1569, 1569, 1569, 1569, 7, 85, 16624, 5, 1800, 16, 7459, 10160), + (10160, 1569, 1569, 1569, 1569, 7, 85, 16625, 5, 1800, 16, 10159, 10161), + (10161, 1569, 1569, 1569, 1569, 7, 85, 16626, 5, 1800, 16, 10160, 17276), + (10162, 6663, 6663, 6663, 6663, 7, 82, 16653, 59, 600, 16, 6665, 10163), + (10163, 6663, 6663, 6663, 6663, 7, 82, 16654, 59, 600, 16, 10162, 10164), + (10164, 6663, 6663, 6663, 6663, 7, 82, 16655, 59, 600, 16, 10163, -1), + (10165, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 7136, 10166), + (10166, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 10165, 10167), + (10167, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 10166, 13213), + (10168, 6328, 6328, 6328, 6328, 7, 85, 16650, 10, 600, 16, 7145, 10169), + (10169, 6328, 6328, 6328, 6328, 7, 85, 16651, 10, 600, 16, 10168, 10170), + (10170, 6328, 6328, 6328, 6328, 7, 85, 16652, 10, 600, 16, 10169, 13770), + (10171, -1, -1, 878, 878, 7, 85, -1, 0, 0, 16, 7147, 10172), + (10172, -1, -1, 878, 878, 7, 85, -1, 0, 0, 16, 10171, -1), + (10173, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 7153, 10174), + (10174, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 10173, 10175), + (10175, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 10174, 13795), + (10176, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 6705, 10177), + (10177, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 10176, 10178), + (10178, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 10177, 13005), + (10179, 6706, 6706, 6706, 6706, 7, 85, 16675, 44, 600, 16, 6708, 10180), + (10180, 6706, 6706, 6706, 6706, 7, 85, 16676, 44, 600, 16, 10179, 10181), + (10181, 6706, 6706, 6706, 6706, 7, 85, 16677, 44, 600, 16, 10180, 5353), + (10182, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 6716, 10183), + (10183, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10182, 10184), + (10184, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10183, 10185), + (10185, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10184, 10186), + (10186, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10185, -1), + (10187, 1327, 1327, 1327, 1327, 12, 85, 16665, 10, 900, 16, 7462, 10188), + (10188, 1327, 1327, 1327, 1327, 12, 85, 16666, 10, 900, 16, 10187, 10189), + (10189, 1327, 1327, 1327, 1327, 12, 85, 16667, 10, 900, 16, 10188, 5330), + (10190, 1520, 1520, 1520, 1520, 9, 80, 16672, 11, 900, 16, 7465, 10191), + (10191, 1520, 1520, 1520, 1520, 9, 80, 16673, 11, 900, 16, 10190, 10192), + (10192, 1520, 1520, 1520, 1520, 9, 80, 16674, 11, 900, 16, 10191, 12997), + (10193, 153, 153, 153, 153, 12, 85, 16668, 3, 2160, 16, 7468, 11081), + (10194, 528, 528, 528, 528, 12, 85, 16669, 5, 720, 16, 7471, 10195), + (10195, 528, 528, 528, 528, 12, 85, 16670, 5, 720, 16, 10194, 10196), + (10196, 528, 528, 528, 528, 12, 85, 16671, 5, 720, 16, 10195, 13161), + (10197, 5251, 5251, 5251, 5251, 12, 85, 16662, 13, 900, 16, 7474, 10198), + (10198, 5251, 5251, 5251, 5251, 12, 85, 16663, 13, 900, 16, 10197, 10199), + (10199, 5251, 5251, 5251, 5251, 12, 85, 16664, 13, 900, 16, 10198, 5363), + (10200, 6815, 6815, 6815, 6815, 8, 85, 16691, 60, 600, 16, 6817, 10201), + (10201, 6815, 6815, 6815, 6815, 8, 85, 16692, 60, 600, 16, 10200, 10202), + (10202, 6815, 6815, 6815, 6815, 8, 85, 16693, 60, 600, 16, 10201, 12786), + (10203, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 6821, 10204), + (10204, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 10203, 10205), + (10205, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 10204, -1), + (10206, -1, -1, 6823, 6823, 4, 75, -1, 0, 0, 16, 6827, 10207), + (10207, -1, -1, 6823, 6823, 4, 77, -1, 0, 0, 16, 10206, -1), + (10208, 6828, 6828, 6828, 6828, 12, 85, 16686, 43, 60, 16, 6828, 17534), + (10209, 1274, 1274, 1274, 1274, 12, 85, 16683, 9, 540, 16, 7201, 10210), + (10210, 1274, 1274, 1274, 1274, 12, 85, 16684, 9, 540, 16, 10209, 10211), + (10211, 1274, 1274, 1274, 1274, 12, 85, 16685, 9, 540, 16, 10210, 12760), + (10212, 1510, -1, 1510, 1510, 12, 80, 16690, 13, 2160, 16, 7202, -1), + (10213, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 7208, 10214), + (10214, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10213, 10215), + (10215, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10214, 10216), + (10216, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10215, 10217), + (10217, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10216, 12798), + (10218, 4927, 4927, 4927, 4927, 9, 85, 16682, 14, 600, 16, 7209, -1), + (10219, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 7214, 10220), + (10220, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10219, 10221), + (10221, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10220, 10222), + (10222, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10221, 10223), + (10223, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10222, -1), + (10224, 967, 967, 967, 967, 6, 85, 16687, 10, 1800, 16, 7219, 10225), + (10225, 967, 967, 967, 967, 6, 85, 16688, 10, 1800, 16, 10224, 10226), + (10226, 967, 967, 967, 967, 6, 85, 16689, 10, 1800, 16, 10225, 12789), + (10227, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 7222, 10228), + (10228, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 10227, 10229), + (10229, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 10228, 13226), + (10230, 619, 619, 619, 619, 6, 83, 16704, 6, 900, 16, 7228, 10231), + (10231, 619, 619, 619, 619, 6, 83, 16705, 6, 900, 16, 10230, 10232), + (10232, 619, 619, 619, 619, 6, 83, 16706, 6, 900, 16, 10231, -1), + (10233, 516, 516, 516, 516, 6, 82, 16707, 5, 480, 16, 7237, 12879), + (10234, 1334, 1334, 1334, 1334, 12, 85, 16701, 11, 4320, 16, 7241, 10235), + (10235, 1334, 1334, 1334, 1334, 12, 85, 16702, 11, 4320, 16, 10234, 10236), + (10236, 1334, 1334, 1334, 1334, 12, 85, 16703, 11, 4320, 16, 10235, 12868), + (10237, 8060, 8060, 8060, 8060, 7, 85, 16711, 41, 1800, 16, 8062, 10238), + (10238, 8060, 8060, 8060, 8060, 7, 85, 16712, 41, 1800, 16, 10237, 10239), + (10239, 8060, 8060, 8060, 8060, 7, 85, 16713, 41, 1800, 16, 10238, 13650), + (10240, 8063, 8063, 8063, 8063, 7, 85, 16714, 41, 1800, 16, 8065, 10241), + (10241, 8063, 8063, 8063, 8063, 7, 85, 16715, 41, 1800, 16, 10240, 10242), + (10242, 8063, 8063, 8063, 8063, 7, 85, 16716, 41, 1800, 16, 10241, 13653), + (10243, 8066, 8066, 8066, 8066, 7, 85, 16717, 41, 1800, 16, 8068, 10244), + (10244, 8066, 8066, 8066, 8066, 7, 85, 16718, 41, 1800, 16, 10243, 10245), + (10245, 8066, 8066, 8066, 8066, 7, 85, 16719, 41, 1800, 16, 10244, 13656), + (10246, 8072, 8072, 8072, 8072, 7, 80, 16708, 37, 20, 16, 8074, 10247), + (10247, 8072, 8072, 8072, 8072, 7, 80, 16709, 37, 20, 16, 10246, 10248), + (10248, 8072, 8072, 8072, 8072, 7, 80, 16710, 37, 20, 16, 10247, 12857), + (10249, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 8084, 10250), + (10250, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 10249, 10251), + (10251, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 10250, -1), + (10252, 520, 520, 520, 520, 12, 85, 16723, 6, 540, 16, 7252, 10253), + (10253, 520, 520, 520, 520, 12, 85, 16724, 6, 540, 16, 10252, 10254), + (10254, 520, 520, 520, 520, 12, 85, 16725, 6, 540, 16, 10253, 12985), + (10255, 4903, 4903, 4903, 4903, 9, 81, 16726, 9, 1320, 16, 7253, 12956), + (10256, 4906, 4906, 4906, 4906, 9, 81, 16727, 9, 1320, 16, 7254, 12959), + (10257, 4909, 4909, 4909, 4909, 9, 81, 16728, 16, 1320, 16, 7255, 12957), + (10258, 4912, 4912, 4912, 4912, 9, 81, 16729, 16, 1320, 16, 7256, 12958), + (10259, 616, 616, 616, 616, 10, 85, 16733, 7, 900, 16, 7259, 10260), + (10260, 616, 616, 616, 616, 10, 85, 16734, 7, 900, 16, 10259, 10261), + (10261, 616, 616, 616, 616, 10, 85, 16735, 7, 900, 16, 10260, 14730), + (10262, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 7265, 10263), + (10263, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 10262, 10264), + (10264, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 10263, 13707), + (10265, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 7269, 10266), + (10266, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 10265, 10267), + (10267, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 10266, 12945), + (10268, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 7902, 10269), + (10269, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 10268, 10270), + (10270, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 10269, -1), + (10271, 1242, 1242, 1242, 1242, 12, 85, 16744, 9, 1320, 16, 7287, 10272), + (10272, 1242, 1242, 1242, 1242, 12, 85, 16745, 9, 1320, 16, 10271, 10273), + (10273, 1242, 1242, 1242, 1242, 12, 85, 16746, 9, 1320, 16, 10272, 12934), + (10274, 4931, 4931, 4931, 4931, 7, 85, 16747, 4, 600, 16, 7293, 10275), + (10275, 4931, 4931, 4931, 4931, 7, 85, 16748, 4, 600, 16, 10274, 10276), + (10276, 4931, 4931, 4931, 4931, 7, 85, 16749, 4, 600, 16, 10275, 10428), + (10277, 4935, 4935, 4935, 4935, 7, 81, 16743, 14, 300, 16, 7294, 17540), + (10278, 4934, 4934, 4934, 4934, 7, 81, 16742, 13, 300, 16, 7295, 17539), + (10279, 517, 517, 517, 517, 5, 80, 16739, 12, 600, 16, 7298, 10280), + (10280, 517, 517, 517, 517, 5, 80, 16740, 12, 600, 16, 10279, 10281), + (10281, 517, 517, 517, 517, 5, 80, 16741, 12, 600, 16, 10280, 12917), + (10282, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 8033, 10283), + (10283, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 10282, 10284), + (10284, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 10283, 10431), + (10285, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 8037, 10286), + (10286, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 10285, 10287), + (10287, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 10286, 15472), + (10288, 6971, 6971, 6971, 6971, 7, 85, 16761, 41, 600, 16, 6973, 10289), + (10289, 6971, 6971, 6971, 6971, 7, 85, 16762, 41, 600, 16, 10288, 10290), + (10290, 6971, 6971, 6971, 6971, 7, 85, 16763, 41, 600, 16, 10289, 14274), + (10291, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 6976, 10292), + (10292, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 10291, 10293), + (10293, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 10292, -1), + (10294, 6984, 6984, 6984, 6984, 6, 78, 16765, 60, 60, 16, 6984, 13177), + (10295, 6985, 6985, 6985, 6985, 6, 78, 16766, 60, 60, 16, 6985, 13179), + (10296, 6986, 6986, 6986, 6986, 6, 78, 16767, 60, 60, 16, 6986, 13178), + (10297, 1119, 1119, 1119, 1119, 9, 85, 16750, 8, 900, 16, 7481, 10298), + (10298, 1119, 1119, 1119, 1119, 9, 85, 16751, 8, 900, 16, 10297, 10299), + (10299, 1119, 1119, 1119, 1119, 9, 85, 16752, 8, 900, 16, 10298, 16883), + (10300, 723, 723, 723, 723, 7, 85, 16753, 6, 30, 16, 7482, 14273), + (10301, 5015, 5015, 5015, 5015, 12, 85, 16754, 9, 900, 16, 7483, 17382), + (10302, 291, 291, 291, 291, 12, 85, 16755, 5, 900, 16, 7487, 10303), + (10303, 291, 291, 291, 291, 12, 85, 16756, 5, 900, 16, 10302, 10304), + (10304, 291, 291, 291, 291, 12, 85, 16757, 5, 900, 16, 10303, 12828), + (10305, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 7496, 10306), + (10306, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 10305, 10307), + (10307, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 10306, 16887), + (10308, 6380, 6380, 6380, 6380, 6, 85, 16758, 39, 120, 16, 7499, 10309), + (10309, 6380, 6380, 6380, 6380, 6, 85, 16759, 39, 120, 16, 10308, 10310), + (10310, 6380, 6380, 6380, 6380, 6, 85, 16760, 39, 120, 16, 10309, 13170), + (10311, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 4808, 10312), + (10312, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10311, 10313), + (10313, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10312, 10314), + (10314, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10313, 10315), + (10315, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10314, 13035), + (10316, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 4811, 10317), + (10317, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 10316, 10318), + (10318, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 10317, 13040), + (10319, 6931, 6931, 6931, 6931, 12, 85, 16774, 41, 600, 16, 6931, 13058), + (10320, 6932, 6932, 6932, 6932, 7, 85, 16775, 42, 1200, 16, 6934, 10321), + (10321, 6932, 6932, 6932, 6932, 7, 85, 16776, 42, 1200, 16, 10320, 10322), + (10322, 6932, 6932, 6932, 6932, 7, 85, 16777, 42, 1200, 16, 10321, 13062), + (10323, 4854, 4854, 4854, 4854, 12, 85, 16768, 8, 600, 16, 7180, 10324), + (10324, 4854, 4854, 4854, 4854, 12, 85, 16769, 8, 600, 16, 10323, 10325), + (10325, 4854, 4854, 4854, 4854, 12, 85, 16770, 8, 600, 16, 10324, 13059), + (10326, 1178, 1178, 1178, 1178, 9, 85, 16771, 4, 900, 16, 7189, 10327), + (10327, 1178, 1178, 1178, 1178, 9, 85, 16772, 4, 900, 16, 10326, 10328), + (10328, 1178, 1178, 1178, 1178, 9, 85, 16773, 4, 900, 16, 10327, 13845), + (10329, -1, -1, 10329, 10329, 5, 85, 0, 0, 0, 16, -1, 10398), + (10330, 10330, 10330, 10330, 10330, 7, 85, 16785, 35, 30, 16, -1, 13203), + (10331, 10331, 10331, 10331, 10331, 6, 85, 16787, 44, 20, 16, -1, -1), + (10332, -1, -1, 10332, 10332, 3, 85, -1, 0, 0, 16, -1, 12733), + (10333, 10333, 10333, 10333, 10333, 5, 85, 16788, 55, 120, 16, -1, 10334), + (10334, 10333, 10333, 10333, 10333, 7, 85, 16789, 55, 120, 16, 10333, 10335), + (10335, 10333, 10333, 10333, 10333, 9, 85, 16790, 55, 120, 16, 10334, 12724), + (10336, 10336, 10336, 10336, 10336, 5, 85, 16791, 58, 8, 16, -1, 10337), + (10337, 10336, 10336, 10336, 10336, 7, 85, 16792, 58, 8, 16, 10336, 10338), + (10338, 10336, 10336, 10336, 10336, 9, 85, 16793, 58, 8, 16, 10337, 12730), + (10339, 10339, 10339, 10339, 10339, 12, 85, 16786, 48, 1800, 16, -1, -1), + (10340, -1, -1, 10340, 10340, 3, 80, -1, 0, 0, 16, -1, 10341), + (10341, -1, -1, 10340, 10340, 6, 83, -1, 0, 0, 16, 10340, 10342), + (10342, -1, -1, 10340, 10340, 9, 85, -1, 0, 0, 16, 10341, 13184), + (10343, -1, -1, 10343, 10343, 5, 85, 0, 0, 0, 16, -1, 10344), + (10344, -1, -1, 10343, 10343, 7, 85, 0, 0, 0, 16, 10343, 10345), + (10345, -1, -1, 10343, 10343, 9, 85, 0, 0, 0, 16, 10344, 13841), + (10346, 10346, 10346, 10346, 10346, 9, 85, 21783, 46, 600, 16, -1, 13183), + (10347, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 10034, 17310), + (10348, 0, 0, 10348, 10348, 5, 80, -1, 0, 0, 16, -1, 10349), + (10349, 0, 0, 10348, 10348, 7, 83, -1, 0, 0, 16, 10348, 10350), + (10350, 0, 0, 10348, 10348, 9, 85, -1, 0, 0, 16, 10349, 13578), + (10351, 10351, 10351, 10351, 10351, 12, 85, 21785, 34, 600, 16, -1, 10682), + (10352, 10352, 10352, 10352, 10352, 12, 85, 21786, 34, 600, 16, -1, 10683), + (10353, 10353, 10353, 10353, 10353, 12, 85, 21787, 34, 600, 16, -1, 10684), + (10354, 10354, 10354, 10354, 10354, 8, 85, 21653, 39, 4320, 16, -1, 14016), + (10355, -1, -1, 10355, 10355, 6, 83, -1, 0, 0, 16, -1, 10356), + (10356, -1, -1, 10355, 10355, 8, 84, -1, 0, 0, 16, 10355, 10357), + (10357, -1, -1, 10355, 10355, 10, 85, -1, 0, 0, 16, 10356, 10643), + (10358, -1, -1, 10358, 10358, 7, 80, -1, 0, 0, 16, -1, 10359), + (10359, -1, -1, 10358, 10358, 9, 83, -1, 0, 0, 16, 10358, 10360), + (10360, -1, -1, 10358, 10358, 12, 85, -1, 0, 0, 16, 10359, 14210), + (10361, -1, -1, 962, 962, 5, 83, -1, 0, 0, 16, 6227, 10362), + (10362, -1, -1, 962, 962, 5, 84, -1, 0, 0, 16, 10361, 10363), + (10363, -1, -1, 962, 962, 5, 85, -1, 0, 0, 16, 10362, 14218), + (10364, -1, -1, 10364, 10364, 5, 85, -1, 0, 0, 16, -1, 10365), + (10365, -1, -1, 10364, 10364, 7, 85, -1, 0, 0, 16, 10364, 10366), + (10366, -1, -1, 10364, 10364, 9, 85, -1, 0, 0, 16, 10365, 10442), + (10367, 10367, 10367, 10367, 10367, 12, 85, 21751, 30, 360, 16, -1, 10630), + (10368, 10368, 10368, 10368, 10368, 6, 85, 21654, 46, 900, 16, -1, 10369), + (10369, 10368, 10368, 10368, 10368, 9, 85, 21655, 46, 900, 16, 10368, 10386), + (10370, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, -1, 10371), + (10371, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, 10370, 10372), + (10372, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, 10371, 13927), + (10373, 10373, 10373, 10373, 10373, 6, 75, 16806, 62, 6, 16, -1, -1), + (10374, 10374, 10374, 10374, 10374, 6, 85, 16800, 63, 900, 16, -1, 10375), + (10375, 10374, 10374, 10374, 10374, 6, 85, 16801, 63, 900, 16, 10374, 10376), + (10376, 10374, 10374, 10374, 10374, 6, 85, 16802, 63, 900, 16, 10375, 13174), + (10377, 10377, 10377, 10377, 10377, 6, 85, 16794, 64, 60, 16, -1, 10378), + (10378, 10377, 10377, 10377, 10377, 6, 85, 16795, 64, 60, 16, 10377, 10379), + (10379, 10377, 10377, 10377, 10377, 6, 85, 16796, 64, 60, 16, 10378, 13180), + (10380, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, -1, 10381), + (10381, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, 10380, 10382), + (10382, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, 10381, 13477), + (10383, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 7386, 10384), + (10384, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 10383, 10385), + (10385, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 10384, -1), + (10386, 10368, 10368, 10368, 10368, 12, 85, 21656, 46, 900, 16, 10369, -1), + (10387, 10387, 10387, 10387, 10387, 9, 85, 21835, 45, 1200, 16, -1, -1), + (10388, -1, -1, 10388, 10388, 12, 85, -1, 0, 0, 16, -1, 13545), + (10389, -1, -1, 10389, 10389, 9, 83, 0, 0, 0, 16, -1, 10390), + (10390, -1, -1, 10389, 10389, 11, 84, 0, 0, 0, 16, 10389, 10391), + (10391, -1, -1, 10389, 10389, 12, 85, 0, 0, 0, 16, 10390, -1), + (10392, 10392, 10392, 10392, 10392, 12, 85, 21751, 11, 480, 16, -1, 10631), + (10393, 10393, 10393, 10393, 10393, 9, 81, 3246, 42, 2, 16, -1, -1), + (10394, 10394, 10394, 10394, 10394, 12, 85, 21821, 30, 600, 16, -1, 10704), + (10395, 10395, 10395, 10395, 10395, 3, 80, 21748, 62, 5, 16, -1, 12590), + (10396, 10396, 10396, 10396, 10396, 12, 85, 16857, 14, 600, 16, -1, 10790), + (10397, 10397, 10397, 10397, 10397, 12, 85, 16858, 14, 600, 16, -1, 10791), + (10398, -1, -1, 10329, 10329, 7, 85, 0, 0, 0, 16, 10329, 10399), + (10399, -1, -1, 10329, 10329, 9, 85, 0, 0, 0, 16, 10398, -1), + (10400, 10400, 10400, 10400, 10400, 6, 85, 16807, 62, 900, 16, -1, 15558), + (10401, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, -1, 10402), + (10402, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, 10401, 10403), + (10403, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, 10402, 13052), + (10404, -1, -1, 10404, 10404, 6, 85, -1, 0, 0, 16, -1, 13051), + (10405, -1, -1, 10405, 10405, 7, 81, 0, 0, 0, 16, -1, 10406), + (10406, -1, -1, 10405, 10405, 7, 82, 0, 0, 0, 16, 10405, 10407), + (10407, -1, -1, 10405, 10405, 7, 83, 0, 0, 0, 16, 10406, 10408), + (10408, -1, -1, 10405, 10405, 7, 84, 0, 0, 0, 16, 10407, 10409), + (10409, -1, -1, 10405, 10405, 7, 85, 0, 0, 0, 16, 10408, 10671), + (10410, -1, -1, 10410, 10410, 8, 85, -1, 0, 0, 16, -1, 10411), + (10413, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, -1, 10414), + (10414, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10413, 10415), + (10415, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10414, 10416), + (10416, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10415, 10417), + (10417, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10416, -1), + (10418, 6561, 6561, 6561, 6561, 7, 85, 21808, 32, 30, 16, 10101, 10419), + (10419, 6561, 6561, 6561, 6561, 7, 85, 21810, 32, 30, 16, 10418, 10420), + (10420, 6561, 6561, 6561, 6561, 7, 85, 21811, 32, 30, 16, 10419, 14256), + (10421, 10506, 10506, 10506, 10506, 9, 85, 23521, 66, 120, 16, 10508, -1), + (10424, 10424, 10424, 10424, 10424, 7, 81, 21813, 41, 6, 16, -1, -1), + (10425, 10425, 10425, 10425, 10425, 7, 81, 21814, 39, 6, 16, -1, -1), + (10426, 10426, 10426, 10426, 10426, 10, 85, 21816, 5, 900, 16, -1, -1), + (10427, 10427, 10427, 10427, 10427, 12, 85, 21818, 30, 900, 16, -1, -1), + (10428, 4931, 4931, 4931, 4931, 7, 85, 21838, 4, 600, 16, 10276, 10429), + (10429, 4931, 4931, 4931, 4931, 7, 85, 21839, 4, 600, 16, 10428, 10430), + (10430, 4931, 4931, 4931, 4931, 7, 85, 21844, 4, 600, 16, 10429, 13241), + (10431, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10284, 10432), + (10432, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10431, 10433), + (10433, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10432, -1), + (10434, -1, -1, 10434, 10434, 7, 85, 0, 0, 0, 16, -1, 10435), + (10435, -1, -1, 10434, 10434, 9, 85, 0, 0, 0, 16, 10434, 10436), + (10436, -1, -1, 10434, 10434, 12, 85, 0, 0, 0, 16, 10435, -1), + (10437, -1, -1, 6601, 6601, 6, 86, -1, 0, 0, 17, 10029, 10438), + (10438, -1, -1, 6601, 6601, 6, 87, -1, 0, 0, 17, 10437, 10439), + (10439, -1, -1, 6601, 6601, 6, 88, -1, 0, 0, 17, 10438, 10440), + (10440, -1, -1, 6601, 6601, 6, 89, -1, 0, 0, 17, 10439, 10441), + (10442, -1, -1, 10364, 10364, 9, 86, -1, 0, 0, 17, 10366, 10443), + (10443, -1, -1, 10364, 10364, 9, 88, -1, 0, 0, 17, 10442, -1), + (10450, 10450, 10450, 10450, 10450, 7, 85, 16808, 63, 900, 16, -1, 10451), + (10451, 10450, 10450, 10450, 10450, 7, 85, 16809, 63, 900, 16, 10450, 10452), + (10452, 10450, 10450, 10450, 10450, 7, 85, 16810, 63, 900, 16, 10451, 10468), + (10453, -1, -1, 10453, 10453, 5, 85, -1, 0, 0, 16, -1, 10454), + (10454, -1, -1, 10453, 10453, 7, 85, -1, 0, 0, 16, 10453, 10455), + (10455, -1, -1, 10453, 10453, 9, 85, -1, 0, 0, 16, 10454, 13607), + (10456, -1, -1, 10456, 10456, 5, 85, -1, 0, 0, 16, -1, 10457), + (10457, -1, -1, 10456, 10456, 7, 85, -1, 0, 0, 16, 10456, 10458), + (10458, -1, -1, 10456, 10456, 9, 85, -1, 0, 0, 16, 10457, -1), + (10459, -1, -1, 10459, 10459, 5, 65, -1, 0, 0, 16, -1, 10460), + (10460, -1, -1, 10459, 10459, 7, 65, -1, 0, 0, 16, 10459, 10461), + (10461, -1, -1, 10459, 10459, 9, 65, -1, 0, 0, 16, 10460, -1), + (10462, 10462, 10462, 10462, 10462, 12, 85, 16811, 14, 4320, 16, -1, -1), + (10463, 10463, 10463, 10463, 10463, 12, 85, 16812, 16, 4320, 16, -1, -1), + (10464, -1, -1, 10464, 10464, 5, 80, -1, 0, 0, 16, -1, 10465), + (10465, -1, -1, 10464, 10464, 7, 80, -1, 0, 0, 16, 10464, 10466), + (10466, -1, -1, 10464, 10464, 9, 80, -1, 0, 0, 16, 10465, 13140), + (10467, -1, -1, 86, 86, 8, 85, -1, 0, 0, 17, 266, -1), + (10468, 10450, 10450, 10450, 10450, 7, 85, 23603, 63, 900, 17, 10452, 10469), + (10469, 10450, 10450, 10450, 10450, 7, 85, 23604, 63, 900, 17, 10468, 10670), + (10470, -1, -1, 10470, 10470, 9, 86, -1, 0, 0, 17, -1, 10471), + (10471, -1, -1, 10470, 10470, 12, 88, -1, 0, 0, 17, 10470, 10472), + (10472, -1, -1, 10470, 10470, 15, 90, -1, 0, 0, 17, 10471, 15828), + (10473, -1, -1, 446, 735, 10, 86, -1, 0, 0, 17, 7624, 10474), + (10474, -1, -1, 446, 735, 10, 87, -1, 0, 0, 17, 10473, 10475), + (10475, -1, -1, 446, 735, 10, 88, -1, 0, 0, 17, 10474, 10476), + (10476, -1, -1, 446, 735, 10, 89, -1, 0, 0, 17, 10475, 10477), + (10477, -1, -1, 446, 735, 10, 90, -1, 0, 0, 17, 10476, 13308), + (10478, -1, -1, 10478, 10478, 15, 101, -1, 0, 0, 21, -1, 10479), + (10481, 10481, 10481, 10481, 10481, 21, 105, 46249, 90, 600, 21, -1, -1), + (10500, 10500, 10500, 10500, 10500, 7, 85, 16813, 62, 12, 16, -1, -1), + (10501, 10501, 10501, 10501, 10501, 7, 85, 16814, 63, 1, 16, -1, -1), + (10502, 10502, -1, 10502, 10502, 7, 85, 1566, 64, 120, 16, -1, 12647), + (10503, 10503, 10503, 10503, 10503, 9, 85, 16816, 13, 600, 16, -1, 10504), + (10504, 10503, 10503, 10503, 10503, 9, 85, 16817, 13, 600, 16, 10503, 10505), + (10505, 10503, 10503, 10503, 10503, 9, 85, 16818, 13, 600, 16, 10504, 12648), + (10506, 10506, 10506, 10506, 10506, 9, 85, 16819, 66, 120, 16, -1, 10507), + (10507, 10506, 10506, 10506, 10506, 9, 85, 16820, 66, 120, 16, 10506, 10508), + (10508, 10506, 10506, 10506, 10506, 9, 85, 16821, 66, 120, 16, 10507, 10421), + (10509, 5105, 5105, 5105, 5105, 12, 85, 16822, 11, 600, 16, 7420, 13154), + (10510, 7986, 7986, 7986, 7986, 12, 85, 16823, 11, 600, 16, 7988, 13155), + (10511, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, -1, 10512), + (10512, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, 10511, 10513), + (10513, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, 10512, 12642), + (10514, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, -1, 10516), + (10515, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, 10516, 12639), + (10516, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, 10514, 10515), + (10517, 6565, 6565, 6565, 6565, 9, 88, 23608, 17, 45, 17, 10010, 10518), + (10519, -1, -1, 10519, 10519, 9, 86, 0, 0, 0, 17, -1, 10520), + (10522, -1, -1, 10522, 10522, 7, 86, 0, 0, 0, 17, -1, 10523), + (10527, -1, -1, 10527, 10527, 5, 86, 0, 0, 0, 17, -1, 10528), + (10532, -1, -1, 10532, 10532, 5, 86, 0, 0, 0, 17, -1, 10533), + (10537, -1, -1, 10537, 10537, 5, 86, 0, 0, 0, 17, -1, 10538), + (10545, 10545, 10545, 10545, 10545, 12, 85, 23531, 73, 600, 17, -1, -1), + (10546, 10546, 10546, 10546, 10546, 12, 85, 23528, 74, 600, 17, -1, -1), + (10548, -1, -1, 10548, 10548, 9, 86, -1, 0, 0, 17, -1, 10549), + (10550, 10550, 10550, 10550, 10550, 7, 85, 16824, 61, 120, 16, -1, 13250), + (10551, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, -1, 10552), + (10552, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, 10551, 10553), + (10553, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, 10552, 14764), + (10554, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 1576, 10555), + (10555, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 10554, 10556), + (10556, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 10555, 16062), + (10557, 12395, 12395, 12395, 12395, 9, 75, 16828, 11, 900, 16, -1, -1), + (10558, -1, -1, 10558, 10558, 6, 80, -1, 0, 0, 16, -1, 10559), + (10559, -1, -1, 10558, 10558, 6, 83, -1, 0, 0, 16, 10558, 10560), + (10560, -1, -1, 10558, 10558, 6, 85, -1, 0, 0, 16, 10559, 15469), + (10561, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, -1, 10562), + (10562, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, 10561, 10563), + (10563, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, 10562, 15466), + (10564, 773, -1, 773, 773, 12, 85, 16829, 5, 1800, 16, 7278, 10565), + (10565, 773, -1, 773, 773, 12, 85, 16830, 5, 1800, 16, 10564, 10566), + (10566, 773, -1, 773, 773, 12, 85, 16831, 5, 1800, 16, 10565, 13734), + (10568, -1, -1, 6564, 6564, 10, 86, -1, 0, 0, 17, 10009, 10569), + (10571, 1597, 1597, 1597, 1597, 9, 85, 23611, 6, 10, 17, 6606, -1), + (10572, 6617, 6617, 6617, 6617, 12, 86, 23612, 42, 3600, 17, 6617, 14036), + (10573, 6610, 6610, 6610, 6610, 9, 86, 23613, 41, 30, 17, 10003, 13422), + (10574, -1, -1, 6611, 6611, 6, 85, -1, 0, 0, 17, 6619, 16121), + (10575, -1, -1, 6614, 6614, 9, 85, -1, 0, 0, 17, 10005, -1), + (10576, -1, -1, 492, 492, 2, 87, -1, 0, 0, 17, 7130, -1), + (10578, 258, -1, 258, 258, 9, 86, 27520, 1, 600, 17, 258, 16003), + (10579, -1, -1, 7036, 10579, 9, 85, 0, 0, 0, 17, 7038, 10580), + (10580, -1, -1, 7036, 10579, 12, 87, 0, 0, 0, 17, 10579, 10581), + (10585, 912, 912, 912, 912, 9, 86, 23617, 4, 3600, 17, 10013, 10586), + (10588, -1, -1, 10588, 10588, 5, 86, 0, 0, 0, 17, -1, 10589), + (10589, -1, -1, 10588, 10588, 5, 87, 0, 0, 0, 17, 10588, 10590), + (10590, -1, -1, 10588, 10588, 5, 88, 0, 0, 0, 17, 10589, 10591), + (10591, -1, -1, 10588, 10588, 5, 89, 0, 0, 0, 17, 10590, 10592), + (10592, -1, -1, 10588, 10588, 5, 90, 0, 0, 0, 17, 10591, 17206), + (10600, 10600, 10600, 10600, 10600, 7, 85, 16832, 73, 20, 16, -1, 10601), + (10601, 10600, 10600, 10600, 10600, 7, 85, 16833, 73, 20, 16, 10600, 10602), + (10602, 10600, 10600, 10600, 10600, 7, 85, 16834, 73, 20, 16, 10601, 12982), + (10603, 10601, 10601, 10601, 10601, 3, 85, 16835, 62, 6, 16, -1, -1), + (10604, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 7603, 10605), + (10605, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 10604, 10606), + (10606, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 10605, 12795), + (10607, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 6385, 10608), + (10608, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 10607, 10609), + (10609, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 10608, 12801), + (10610, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, -1, 10611), + (10611, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, 10610, 10612), + (10612, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, 10611, -1), + (10618, 7850, 7850, 7850, 7850, 9, 86, 23532, 39, 4320, 17, 7340, 10619), + (10619, 7850, 7850, 7850, 7850, 12, 88, 23533, 39, 4320, 17, 10618, 10620), + (10620, 7850, 7850, 7850, 7850, 15, 90, 23534, 39, 4320, 17, 10619, 13604), + (10621, -1, -1, 849, 849, 9, 85, -1, 0, 0, 17, 851, 10622), + (10622, -1, -1, 849, 849, 9, 87, -1, 0, 0, 17, 10621, 16604), + (10623, -1, -1, 255, 255, 9, 85, -1, 0, 0, 17, 5808, 10624), + (10624, -1, -1, 255, 255, 12, 87, -1, 0, 0, 17, 10623, 10625), + (10625, -1, -1, 255, 255, 15, 89, -1, 0, 0, 17, 10624, 13589), + (10626, 5984, 5984, 5984, 5984, 12, 90, 23535, 2, 30, 17, 7711, 13592), + (10627, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, -1, 10628), + (10628, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, 10627, 10629), + (10629, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, 10628, -1), + (10630, 10367, 10367, 10367, 10367, 12, 90, 27642, 30, 360, 17, 10367, 13434), + (10631, 10392, 10392, 10392, 10392, 12, 90, 27642, 11, 480, 17, 10392, -1), + (10632, -1, -1, 735, 735, 10, 86, -1, 0, 0, 17, 7627, 10633), + (10633, -1, -1, 735, 735, 10, 87, -1, 0, 0, 17, 10632, 10634), + (10634, -1, -1, 735, 735, 10, 88, -1, 0, 0, 17, 10633, 10635), + (10635, -1, -1, 735, 735, 10, 89, -1, 0, 0, 17, 10634, 10636), + (10636, -1, -1, 735, 735, 10, 90, -1, 0, 0, 17, 10635, 13884), + (10637, -1, -1, 1287, 1287, 9, 86, -1, 0, 0, 17, 12471, 10638), + (10638, -1, -1, 1287, 1287, 12, 88, -1, 0, 0, 17, 10637, 10639), + (10639, -1, -1, 1287, 1287, 15, 90, -1, 0, 0, 17, 10638, 13323), + (10640, 5095, 5095, 5095, 5095, 9, 85, 23620, 10, 900, 17, 7334, 10641), + (10641, 5095, 5095, 5095, 5095, 12, 87, 23621, 10, 900, 17, 10640, 10642), + (10642, 5095, 5095, 5095, 5095, 15, 89, 23622, 10, 900, 17, 10641, 13575), + (10643, -1, -1, 10355, 10355, 10, 86, -1, 0, 0, 17, 10357, 10644), + (10644, -1, -1, 10355, 10355, 10, 88, -1, 0, 0, 17, 10643, 10645), + (10645, -1, -1, 10355, 10355, 10, 90, -1, 0, 0, 17, 10644, 14094), + (10646, 7712, 7712, 7712, 7712, 15, 90, 23536, 2, 30, 17, 7712, 13585), + (10647, 188, 188, 188, 188, 9, 88, 23537, 2, 30, 17, 7662, 13586), + (10650, -1, -1, 10650, 10650, 7, 85, -1, 0, 0, 16, -1, 10651), + (10651, -1, -1, 10650, 10650, 9, 85, -1, 0, 0, 16, 10650, 10652), + (10652, -1, -1, 10650, 10650, 12, 85, -1, 0, 0, 16, 10651, 13804), + (10653, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, -1, 10654), + (10654, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, 10653, 10655), + (10655, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, 10654, 17406), + (10656, -1, -1, 10656, 10656, 7, 85, -1, 0, 0, 16, -1, 12678), + (10657, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, -1, 10658), + (10658, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, 10657, 10659), + (10659, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, 10658, 12679), + (10660, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 7165, 10661), + (10661, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 10660, 10662), + (10662, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 10661, 12667), + (10663, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 7171, 10664), + (10664, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 10663, 10665), + (10665, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 10664, 12670), + (10666, -1, -1, 495, 495, 6, 85, -1, 0, 0, 16, 6262, 10667), + (10667, -1, -1, 495, 495, 5, 85, -1, 0, 0, 16, 10666, 10668), + (10668, -1, -1, 495, 495, 7, 85, -1, 0, 0, 16, 10667, 17391), + (10670, 10450, 10450, 10450, 10450, 7, 85, 23605, 63, 900, 17, 10469, 15839), + (10671, -1, -1, 10405, 10405, 9, 86, 0, 0, 0, 17, 10409, 10672), + (10672, -1, -1, 10405, 10405, 9, 87, 0, 0, 0, 17, 10671, 10673), + (10673, -1, -1, 10405, 10405, 9, 88, 0, 0, 0, 17, 10672, 10674), + (10674, -1, -1, 10405, 10405, 9, 89, 0, 0, 0, 17, 10673, 10675), + (10675, -1, -1, 10405, 10405, 9, 90, 0, 0, 0, 17, 10674, -1), + (10676, -1, -1, 6791, 6791, 6, 86, -1, 0, 0, 17, 10046, 10677), + (10677, -1, -1, 6791, 6791, 6, 88, -1, 0, 0, 17, 10676, 10678), + (10678, -1, -1, 6791, 6791, 6, 90, -1, 0, 0, 17, 10677, 13598), + (10679, 6492, 6492, 6492, 6492, 9, 85, 23626, 52, 720, 17, 6497, 10680), + (10680, 6492, 6492, 6492, 6492, 9, 87, 23627, 52, 720, 17, 10679, 10681), + (10681, 6492, 6492, 6492, 6492, 9, 89, 23628, 52, 720, 17, 10680, 14003), + (10682, 10351, 10351, 10351, 10351, 15, 90, 23538, 34, 600, 17, 10351, -1), + (10683, 10352, 10352, 10352, 10352, 15, 90, 23539, 34, 600, 17, 10352, -1), + (10684, 10353, 10353, 10353, 10353, 15, 90, 23540, 34, 600, 17, 10353, -1), + (10685, -1, -1, 602, 602, 9, 86, -1, 0, 0, 17, 5582, 10686), + (10686, -1, -1, 602, 602, 12, 88, -1, 0, 0, 17, 10685, 10687), + (10687, -1, -1, 602, 602, 15, 90, -1, 0, 0, 17, 10686, 13610), + (10688, -1, -1, 855, 855, 7, 86, -1, 0, 0, 17, 7677, 10689), + (10689, -1, -1, 855, 855, 7, 87, -1, 0, 0, 17, 10688, 10690), + (10690, -1, -1, 855, 855, 7, 88, -1, 0, 0, 17, 10689, 10691), + (10691, -1, -1, 855, 855, 7, 89, -1, 0, 0, 17, 10690, 10692), + (10692, -1, -1, 855, 855, 7, 90, -1, 0, 0, 17, 10691, 13613), + (10700, 10700, 10700, 10700, 10700, 7, 85, 16839, 61, 10, 16, -1, -1), + (10701, 10701, 10701, 10701, 10701, 7, 85, 21662, 32, 360, 16, -1, 10702), + (10702, 10701, 10701, 10701, 10701, 9, 85, 21663, 32, 360, 16, 10701, 10703), + (10703, 10701, 10701, 10701, 10701, 12, 85, 21664, 32, 360, 16, 10702, 12754), + (10704, 10394, 10394, 10394, 10394, 12, 85, 23541, 30, 300, 17, 10394, 13584), + (10705, -1, -1, 6395, 6395, 9, 86, -1, 0, 0, 17, 10052, 10706), + (10706, -1, -1, 6395, 6395, 9, 88, -1, 0, 0, 17, 10705, 10707), + (10707, -1, -1, 6395, 6395, 9, 90, -1, 0, 0, 17, 10706, 14097), + (10708, 534, 534, 534, 534, 12, 86, 23545, 4, 2160, 17, 10049, 10709), + (10709, 534, 534, 534, 534, 12, 88, 23546, 4, 2160, 17, 10708, 10710), + (10710, 534, 534, 534, 534, 12, 90, 23547, 4, 2160, 17, 10709, 13595), + (10711, 10711, 10711, 10711, 10711, 9, 86, 23548, 75, 1200, 17, -1, 10712), + (10712, 10711, 10711, 10711, 10711, 12, 88, 23549, 75, 1200, 17, 10711, 10713), + (10713, 10711, 10711, 10711, 10711, 15, 90, 23550, 75, 1200, 17, 10712, 14006), + (10714, -1, -1, 10714, 10714, 9, 86, 0, 0, 0, 17, -1, 10715), + (10715, -1, -1, 10714, 10714, 12, 88, 0, 0, 0, 17, 10714, 10716), + (10717, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 17, 7745, 10718), + (10718, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 17, 10717, 15258), + (10719, -1, -1, 10719, 10719, 9, 75, 0, 0, 0, 17, -1, 10720), + (10720, -1, -1, 10719, 10719, 12, 75, 0, 0, 0, 17, 10719, 10721), + (10721, -1, -1, 10719, 10719, 15, 75, 0, 0, 0, 17, 10720, 13562), + (10722, -1, -1, 10722, 10722, 5, 81, 0, 0, 0, 17, -1, 10723), + (10723, -1, -1, 10722, 10722, 5, 82, 0, 0, 0, 17, 10722, 10724), + (10724, -1, -1, 10722, 10722, 7, 83, 0, 0, 0, 17, 10723, 10725), + (10725, -1, -1, 10722, 10722, 9, 84, 0, 0, 0, 17, 10724, 10726), + (10726, -1, -1, 10722, 10722, 12, 85, 0, 0, 0, 17, 10725, 15280), + (10727, -1, -1, 10727, 10727, 7, 86, 0, 0, 0, 17, -1, 10728), + (10728, -1, -1, 10727, 10727, 9, 88, 0, 0, 0, 17, 10727, 10729), + (10730, -1, -1, 10730, 10730, 7, 86, 0, 0, 0, 17, -1, 10731), + (10731, -1, -1, 10730, 10730, 9, 88, 0, 0, 0, 17, 10730, 10732), + (10733, -1, -1, 10733, 10733, 7, 81, 0, 0, 0, 17, -1, 10734), + (10734, -1, -1, 10733, 10733, 9, 83, 0, 0, 0, 17, 10733, 10735), + (10735, -1, -1, 10733, 10733, 12, 85, 0, 0, 0, 17, 10734, -1), + (10736, 10736, 10736, 10736, 10736, 7, 86, 23632, 5, 180, 17, -1, 10737), + (10737, 10736, 10736, 10736, 10736, 9, 88, 23633, 5, 180, 17, 10736, 10738), + (10739, 645, -1, 645, 645, 12, 86, 23551, 4, 5, 17, 5999, 13410), + (10740, 1345, 1345, 1345, 1345, 9, 86, 23552, 6, 900, 17, 7349, 10741), + (10741, 1345, 1345, 1345, 1345, 12, 88, 23553, 6, 900, 17, 10740, 10742), + (10743, -1, -1, 1196, 1196, 5, 86, -1, 0, 0, 17, 1200, 10744), + (10744, -1, -1, 1196, 1196, 5, 87, -1, 0, 0, 17, 10743, 10745), + (10745, -1, -1, 1196, 1196, 5, 88, -1, 0, 0, 17, 10744, 10746), + (10748, -1, -1, 867, 867, 7, 86, -1, 0, 0, 17, 7366, 10749), + (10749, -1, -1, 867, 867, 7, 87, -1, 0, 0, 17, 10748, 10755), + (10750, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 16, 7328, 10751), + (10751, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 16, 10750, -1), + (10752, 10752, 10752, 10752, 10752, 6, 85, 16843, 72, 600, 16, -1, -1), + (10753, 10753, 10753, 10753, 10753, 12, 80, 16844, 6, 4320, 16, -1, -1), + (10754, 10754, 10754, 10754, 10754, 2, 70, 16845, 62, 5, 16, -1, -1), + (10755, -1, -1, 867, 867, 7, 88, -1, 0, 0, 17, 10749, 10756), + (10758, 545, 545, 545, 545, 12, 86, 23638, 3, 900, 17, 7346, 10759), + (10759, 545, 545, 545, 545, 12, 87, 23639, 3, 900, 17, 10758, 10760), + (10760, 545, 545, 545, 545, 12, 88, 23640, 3, 900, 17, 10759, 10761), + (10763, -1, -1, 6761, 6761, 12, 86, -1, 0, 0, 17, 6087, 10764), + (10764, -1, -1, 6761, 6761, 12, 88, -1, 0, 0, 17, 10763, 10765), + (10766, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 17, 10060, 10767), + (10767, -1, -1, 6765, 6765, 9, 87, -1, 0, 0, 17, 10766, 10768), + (10768, -1, -1, 6765, 6765, 9, 89, -1, 0, 0, 17, 10767, 13553), + (10769, -1, -1, 6751, 6751, 9, 86, -1, 0, 0, 17, 6769, 10770), + (10770, -1, -1, 6751, 6751, 9, 88, -1, 0, 0, 17, 10769, 10771), + (10772, 872, 872, 872, 872, 9, 85, 23555, 5, 180, 17, 7369, 10773), + (10773, 872, 872, 872, 872, 9, 87, 23556, 5, 180, 17, 10772, 10774), + (10774, 872, 872, 872, 872, 9, 89, 23557, 5, 180, 17, 10773, -1), + (10775, 875, 875, 875, 875, 9, 85, 23561, 5, 180, 17, 7372, 10776), + (10776, 875, 875, 875, 875, 9, 87, 23562, 5, 180, 17, 10775, 10777), + (10777, 875, 875, 875, 875, 9, 89, 23563, 5, 180, 17, 10776, 13536), + (10778, -1, -1, 634, 634, 12, 85, -1, 0, 0, 17, 7714, 10779), + (10779, -1, -1, 634, 634, 12, 87, -1, 0, 0, 17, 10778, 10780), + (10780, -1, -1, 634, 634, 12, 89, -1, 0, 0, 17, 10779, 15585), + (10781, -1, -1, 8240, 8240, 9, 85, -1, 0, 0, 17, 8244, 10782), + (10782, -1, -1, 8240, 8240, 9, 86, -1, 0, 0, 17, 10781, 10783), + (10783, -1, -1, 8240, 8240, 9, 87, -1, 0, 0, 17, 10782, 10784), + (10784, -1, -1, 8240, 8240, 9, 88, -1, 0, 0, 17, 10783, 10785), + (10785, -1, -1, 8240, 8240, 9, 89, -1, 0, 0, 17, 10784, 13343), + (10786, 7800, 7800, 7800, 7800, 12, 85, 23567, 39, 4320, 17, 7817, 10787), + (10787, 7800, 7800, 7800, 7800, 12, 87, 23568, 39, 4320, 17, 10786, 13619), + (10788, -1, -1, 4699, 4699, 7, 65, -1, 0, 0, 17, 7500, -1), + (10789, 10789, 10789, 10789, 10789, 15, 90, 23575, 41, 6, 17, -1, 14261), + (10790, 10396, 10396, 10396, 10396, 15, 90, 23576, 14, 600, 17, 10396, 14024), + (10791, 10397, 10397, 10397, 10397, 15, 90, 23577, 14, 600, 17, 10397, 14025), + (10792, -1, -1, 10792, 10792, 5, 86, 0, 0, 0, 17, -1, 10793), + (10793, -1, -1, 10792, 10792, 7, 87, 0, 0, 0, 17, 10792, 10794), + (10794, -1, -1, 10792, 10792, 9, 88, 0, 0, 0, 17, 10793, 10795), + (10795, -1, -1, 10792, 10792, 11, 89, 0, 0, 0, 17, 10794, 10796), + (10796, -1, -1, 10792, 10792, 13, 90, 0, 0, 0, 17, 10795, 17365), + (10800, -1, -1, 10800, 10800, 6, 70, -1, 0, 0, 16, -1, 10801), + (10801, -1, -1, 10800, 10800, 9, 70, -1, 0, 0, 16, 10800, 10802), + (10802, -1, -1, 10800, 10800, 12, 70, -1, 0, 0, 16, 10801, 17476), + (10803, -1, -1, 10803, 10803, 6, 76, -1, 0, 0, 16, -1, 10804), + (10804, -1, -1, 10803, 10803, 6, 78, -1, 0, 0, 16, 10803, 10805), + (10805, -1, -1, 10803, 10803, 6, 80, -1, 0, 0, 16, 10804, -1), + (10806, 10806, 10806, 10806, 10806, 10, 80, 16846, 71, 540, 16, -1, 10807), + (10807, 10806, 10806, 10806, 10806, 11, 80, 16847, 71, 540, 16, 10806, 10808), + (10808, 10806, 10806, 10806, 10806, 12, 80, 16848, 71, 540, 16, 10807, 15298), + (10809, 10809, 10809, 10809, 10809, 10, 80, 16849, 71, 540, 16, -1, 10810), + (10810, 10809, 10809, 10809, 10809, 11, 80, 16850, 71, 540, 16, 10809, 10811), + (10811, 10809, 10809, 10809, 10809, 12, 80, 16851, 71, 540, 16, 10810, 15301), + (10815, 10815, 10815, 10815, 10815, 6, 80, -1, 0, 0, 16, -1, 10816), + (10816, 10815, 10815, 10815, 10815, 9, 80, -1, 0, 0, 16, 10815, 10817), + (10817, 10815, 10815, 10815, 10815, 12, 80, -1, 0, 0, 16, 10816, 13110), + (10818, 10818, 10818, 10818, 10818, 6, 80, -1, 0, 0, 16, -1, 10819), + (10819, 10818, 10818, 10818, 10818, 9, 80, -1, 0, 0, 16, 10818, 10820), + (10820, 10818, 10818, 10818, 10818, 12, 80, -1, 0, 0, 16, 10819, 13113), + (10821, 10821, 10821, 10821, 10821, 6, 80, -1, 0, 0, 16, -1, 10822), + (10822, 10821, 10821, 10821, 10821, 9, 80, -1, 0, 0, 16, 10821, 10823), + (10823, 10821, 10821, 10821, 10821, 12, 80, -1, 0, 0, 16, 10822, 13116), + (10824, 510, 510, 510, 510, 6, 86, 23578, 37, 240, 17, 10104, 10825), + (10850, -1, -1, 10850, 10850, 6, 85, 16864, 0, 0, 16, -1, 10851), + (10851, -1, -1, 10850, 10850, 6, 85, 16865, 0, 0, 16, 10850, 10852), + (10852, -1, -1, 10850, 10850, 6, 85, 16866, 0, 0, 16, 10851, 13207), + (10853, -1, -1, 10853, 10853, 3, 65, -1, 0, 0, 16, -1, 10854), + (10854, -1, -1, 10853, 10853, 6, 65, -1, 0, 0, 16, 10853, 10855), + (10855, -1, -1, 10853, 10853, 9, 65, -1, 0, 0, 16, 10854, 10856), + (10856, -1, -1, 10853, 10853, 5, 66, -1, 0, 0, 16, 10855, 10857), + (10857, -1, -1, 10853, 10853, 5, 68, -1, 0, 0, 16, 10856, 10858), + (10858, -1, -1, 10853, 10853, 5, 70, -1, 0, 0, 16, 10857, 10859), + (10859, -1, -1, 10853, 10853, 5, 76, -1, 0, 0, 16, 10858, 10860), + (10860, -1, -1, 10853, 10853, 5, 78, -1, 0, 0, 16, 10859, 10861), + (10861, -1, -1, 10853, 10853, 5, 80, -1, 0, 0, 16, 10860, 10862), + (10862, -1, -1, 10853, 10853, 5, 81, -1, 0, 0, 16, 10861, 10863), + (10863, -1, -1, 10853, 10853, 5, 83, -1, 0, 0, 16, 10862, 10864), + (10864, -1, -1, 10853, 10853, 5, 85, -1, 0, 0, 16, 10863, 15954), + (10865, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 7150, 10866), + (10866, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 10865, 10867), + (10867, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 10866, 13218), + (10868, 5021, 5021, 5021, 5021, 9, 76, 16867, 7, 60, 16, 5021, 10869), + (10869, 5021, 5021, 5021, 5021, 9, 81, 16868, 7, 60, 16, 10868, 10870), + (10870, 5021, 5021, 5021, 5021, 9, 85, 16869, 7, 60, 16, 10869, 12618), + (10900, 10900, 10900, 10900, 10900, 9, 85, 16870, 55, 120, 16, -1, 10901), + (10901, 10900, 10900, 10900, 10900, 9, 85, 16871, 55, 120, 16, 10900, 10902), + (10902, 10900, 10900, 10900, 10900, 9, 85, 16872, 55, 120, 16, 10901, 13624), + (10903, -1, -1, 10903, 10903, 6, 81, -1, 0, 0, 16, -1, 10904), + (10904, -1, -1, 10903, 10903, 6, 83, -1, 0, 0, 16, 10903, 10905), + (10905, -1, -1, 10903, 10903, 6, 85, -1, 0, 0, 16, 10904, -1), + (10906, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 7406, 10907), + (10907, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 10906, 10908), + (10908, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 10907, 13627), + (10909, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, -1, 10910), + (10910, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, 10909, 10911), + (10911, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, 10910, -1), + (10912, 10912, 10912, 10912, 10912, 6, 85, 16873, 69, 1800, 16, -1, 10913), + (10913, 10912, 10912, 10912, 10912, 6, 85, 16874, 69, 1800, 16, 10912, 10914), + (10914, 10912, 10912, 10912, 10912, 6, 85, 16875, 69, 1800, 16, 10913, 14053), + (10915, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, -1, 10916), + (10916, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, 10915, 10917), + (10917, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, 10916, 16189), + (10950, -1, -1, 10950, 10950, 6, 85, -1, 0, 0, 16, -1, -1), + (10951, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, -1, 10952), + (10952, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, 10951, 10953), + (10953, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, 10952, 15363), + (10954, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, -1, 10955), + (10955, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, 10954, 10956), + (10956, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, 10955, -1), + (10957, 10957, 10957, 10957, 10957, 6, 85, 16879, 61, 5, 16, -1, -1), + (10958, 10958, 10958, 10958, 10958, 12, 85, 16880, 62, 900, 16, -1, 13000), + (10959, 10959, 10959, 10959, 10959, 12, 85, 16881, 63, 600, 16, -1, 10961), + (10961, 10959, 10959, 10959, 10959, 12, 85, 21717, 63, 600, 16, 10959, 10962), + (10962, 10959, 10959, 10959, 10959, 12, 85, 21718, 63, 600, 16, 10961, 12988), + (11000, -1, -1, 11000, 11000, 6, 85, -1, 0, 0, 16, -1, 11001), + (11001, -1, -1, 11000, 11000, 9, 85, -1, 0, 0, 16, 11000, 11002), + (11002, -1, -1, 11000, 11000, 12, 85, -1, 0, 0, 16, 11001, -1), + (11003, -1, -1, 11003, 11003, 6, 85, -1, 0, 0, 16, -1, -1), + (11004, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, -1, 11005), + (11005, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, 11004, 11006), + (11006, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, 11005, -1), + (11011, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 6304, 11012), + (11012, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 11011, 11013), + (11013, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 11012, 15552), + (11014, -1, -1, 11007, 11007, 5, 80, -1, 0, 0, 16, -1, 11015), + (11015, -1, -1, 11007, 11007, 7, 82, -1, 0, 0, 16, 11014, 11016), + (11016, -1, -1, 11007, 11007, 9, 85, -1, 0, 0, 16, 11015, 11020), + (11020, -1, -1, 11007, 11007, 12, 86, -1, 0, 0, 17, 11016, -1), + (11050, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, -1, 11051), + (11051, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11050, 11052), + (11052, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11051, 11059), + (11053, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 16, 7620, 11054), + (11054, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 16, 11053, -1), + (11055, 11055, 11055, 11055, 11055, 3, 85, 16884, 63, 20, 16, -1, -1), + (11056, 11056, 11056, 11056, 11056, 6, 85, 16885, 64, 180, 16, -1, -1), + (11057, 11057, 11057, 11057, 11057, 2, 85, 1422, 65, 10, 16, -1, -1), + (11058, 11058, 11058, 11058, 11058, 2, 85, 3243, 66, 10, 16, -1, -1), + (11059, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11052, 11060), + (11060, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11059, 12871), + (11061, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 7586, 11062), + (11062, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 11061, 11063), + (11063, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 11062, 13921), + (11064, 6290, 6290, 6290, 6290, 7, 85, 23500, 0, 1, 16, 7225, 11065), + (11065, 6290, 6290, 6290, 6290, 9, 85, 23501, 0, 1, 16, 11064, 11066), + (11066, 6290, 6290, 6290, 6290, 12, 85, 23502, 0, 1, 16, 11065, 13229), + (11067, 4944, -1, 4944, 4944, 7, 85, 23506, 0, 1, 16, 7231, 11068), + (11068, 4944, -1, 4944, 4944, 9, 85, 23507, 0, 1, 16, 11067, 11069), + (11069, 4944, -1, 4944, 4944, 12, 85, 23508, 0, 1, 16, 11068, 13232), + (11070, 1478, -1, 1478, 1478, 9, 85, 23512, 0, 1, 16, 7244, 11071), + (11071, 1478, -1, 1478, 1478, 10, 85, 23513, 0, 1, 16, 11070, 11072), + (11072, 1478, -1, 1478, 1478, 12, 85, 23514, 0, 1, 16, 11071, 13235), + (11073, 11073, 11073, 11073, 11073, 12, 85, 23518, 53, 30, 16, -1, 13447), + (11074, -1, -1, 11074, 11074, 5, 81, 0, 0, 0, 16, -1, 11075), + (11075, -1, -1, 11074, 11074, 7, 83, 0, 0, 0, 16, 11074, 11076), + (11076, -1, -1, 11074, 11074, 9, 85, 0, 0, 0, 16, 11075, -1), + (11077, -1, -1, 11077, 11077, 5, 81, 0, 0, 0, 16, -1, 15895), + (11078, -1, -1, 11078, 11078, 5, 81, 0, 0, 0, 16, -1, 15891), + (11079, -1, -1, 11079, 11079, 5, 81, 0, 0, 0, 16, -1, 15893), + (11080, 11080, 11080, 11080, 11080, 7, 85, 23519, 10, 20, 16, -1, 13472), + (11081, 153, 153, 153, 153, 12, 85, 23599, 3, 2160, 16, 10193, 12996), + (11082, -1, -1, 1131, 1131, 6, 81, -1, 0, 0, 16, 1133, 11083), + (11083, -1, -1, 1131, 1131, 9, 83, -1, 0, 0, 16, 11082, 11084), + (11084, -1, -1, 1131, 1131, 12, 85, -1, 0, 0, 16, 11083, 13032), + (11085, -1, -1, 11085, 11085, 7, 85, 0, 0, 0, 16, -1, 11086), + (11086, -1, -1, 11085, 11085, 9, 85, 0, 0, 0, 16, 11085, 11087), + (11087, -1, -1, 11085, 11085, 12, 85, 0, 0, 0, 16, 11086, 13021), + (11088, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, -1, 11089), + (11089, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11088, 11090), + (11090, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11089, 11091), + (11091, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11090, -1), + (12396, -1, -1, 125, 125, 8, 85, -1, 0, 0, 16, 7505, 12397), + (12397, -1, -1, 125, 125, 9, 85, -1, 0, 0, 16, 12396, 12398), + (12398, -1, -1, 125, 125, 10, 85, -1, 0, 0, 16, 12397, 12399), + (12399, -1, -1, 125, 125, 11, 85, -1, 0, 0, 16, 12398, 12400), + (12400, -1, -1, 125, 125, 12, 85, -1, 0, 0, 16, 12399, 13080), + (12401, -1, -1, 122, 122, 8, 85, -1, 0, 0, 16, 7510, 12402), + (12402, -1, -1, 122, 122, 9, 85, -1, 0, 0, 16, 12401, 12403), + (12403, -1, -1, 122, 122, 10, 85, -1, 0, 0, 16, 12402, 12404), + (12404, -1, -1, 122, 122, 11, 85, -1, 0, 0, 16, 12403, 12405), + (12405, -1, -1, 122, 122, 12, 85, -1, 0, 0, 16, 12404, 13085), + (12406, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 7530, 12407), + (12407, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12406, 12408), + (12408, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12407, 12409), + (12409, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12408, 12410), + (12410, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12409, 12492), + (12411, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 8259, 12412), + (12412, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12411, 12413), + (12413, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12412, 12414), + (12414, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12413, 12415), + (12415, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12414, 13358), + (12416, -1, -1, 12416, 12416, 7, 83, -1, 0, 0, 16, -1, 12417), + (12417, -1, -1, 12416, 12416, 9, 84, -1, 0, 0, 16, 12416, 12418), + (12418, -1, -1, 12416, 12416, 12, 85, -1, 0, 0, 16, 12417, 13413), + (12419, -1, -1, 12419, 12419, 5, 83, -1, 0, 0, 16, -1, 12420), + (12420, -1, -1, 12419, 12419, 5, 84, -1, 0, 0, 16, 12419, 12421), + (12421, -1, -1, 12419, 12419, 5, 85, -1, 0, 0, 16, 12420, 12575), + (12422, 12422, 12422, 12422, 12422, 12, 85, 13994, 47, 12, 16, -1, -1), + (12423, -1, -1, 767, 767, 9, 81, -1, 0, 0, 16, 1101, 12424), + (12424, -1, -1, 767, 767, 10, 83, -1, 0, 0, 16, 12423, 12425), + (12425, -1, -1, 767, 767, 12, 85, -1, 0, 0, 16, 12424, -1), + (12426, -1, -1, 767, 767, 3, 81, -1, 0, 0, 16, 6245, 12427), + (12427, -1, -1, 767, 767, 6, 83, -1, 0, 0, 16, 12426, 12428), + (12428, -1, -1, 767, 767, 9, 85, -1, 0, 0, 16, 12427, -1), + (12432, -1, -1, 1107, 1107, 10, 81, -1, 0, 0, 16, 6405, 12433), + (12433, -1, -1, 1107, 1107, 11, 83, -1, 0, 0, 16, 12432, 12434), + (12434, -1, -1, 1107, 1107, 12, 85, -1, 0, 0, 16, 12433, 12556), + (12435, -1, -1, 637, 637, 8, 81, -1, 0, 0, 16, 5573, 12436), + (12436, -1, -1, 637, 637, 10, 83, -1, 0, 0, 16, 12435, 12437), + (12437, -1, -1, 637, 637, 12, 85, -1, 0, 0, 16, 12436, 12553), + (12438, -1, -1, 686, 686, 5, 85, -1, 0, 0, 16, 7640, -1), + (12439, -1, -1, 1592, 1592, 9, 85, -1, 0, 0, 16, 7572, 12440), + (12440, -1, -1, 1592, 1592, 10, 85, -1, 0, 0, 16, 12439, 12441), + (12441, -1, -1, 1592, 1592, 11, 85, -1, 0, 0, 16, 12440, 12442), + (12442, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 16, 12441, 12443), + (12443, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 16, 12442, 12532), + (12444, -1, -1, 1072, 1072, 8, 85, -1, 0, 0, 16, 7580, 12445), + (12445, -1, -1, 1072, 1072, 9, 85, -1, 0, 0, 16, 12444, 12446), + (12446, -1, -1, 1072, 1072, 10, 85, -1, 0, 0, 16, 12445, 12447), + (12447, -1, -1, 1072, 1072, 11, 85, -1, 0, 0, 16, 12446, 12448), + (12448, -1, -1, 1072, 1072, 12, 85, -1, 0, 0, 16, 12447, 12537), + (12449, -1, -1, 77, 77, 10, 81, -1, 0, 0, 16, 1085, 12450), + (12450, -1, -1, 77, 77, 11, 83, -1, 0, 0, 16, 12449, 12451), + (12451, -1, -1, 77, 77, 12, 85, -1, 0, 0, 16, 12450, 12497), + (12452, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 7592, 12453), + (12453, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 12452, 12454), + (12454, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 12453, 12567), + (12455, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 7597, 12456), + (12456, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12455, 12457), + (12457, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12456, 12458), + (12458, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12457, 12459), + (12459, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12458, 12570), + (12460, 6537, 6537, 6537, 6537, 7, 83, 20172, 30, 900, 16, 7608, 12461), + (12461, 6537, 6537, 6537, 6537, 8, 83, 20173, 30, 900, 16, 12460, 12462), + (12462, 6537, 6537, 6537, 6537, 9, 83, 20174, 30, 900, 16, 12461, 12520), + (12463, -1, -1, 5263, 5263, 7, 81, -1, 0, 0, 16, 6129, 12464), + (12464, -1, -1, 5263, 5263, 8, 81, -1, 0, 0, 16, 12463, 12465), + (12465, -1, -1, 5263, 5263, 9, 81, -1, 0, 0, 16, 12464, 16173), + (12466, -1, -1, 5263, 5263, 7, 81, -1, 0, 0, 16, 5622, 12467), + (12467, -1, -1, 5263, 5263, 9, 81, -1, 0, 0, 16, 12466, 12468), + (12468, -1, -1, 5263, 5263, 12, 81, -1, 0, 0, 16, 12467, 15714), + (12469, -1, -1, 1287, 1287, 7, 81, -1, 0, 0, 16, 5518, 12470), + (12470, -1, -1, 1287, 1287, 9, 81, -1, 0, 0, 16, 12469, 12471), + (12471, -1, -1, 1287, 1287, 12, 81, -1, 0, 0, 16, 12470, 10637), + (12472, -1, -1, 1287, 1287, 8, 81, -1, 0, 0, 16, 6430, 12473), + (12473, -1, -1, 1287, 1287, 9, 81, -1, 0, 0, 16, 12472, 12474), + (12474, -1, -1, 1287, 1287, 10, 81, -1, 0, 0, 16, 12473, 13238), + (12475, -1, -1, 12430, 12430, 5, 85, 0, 0, 0, 16, -1, 12476), + (12476, -1, -1, 12430, 12430, 7, 85, 0, 0, 0, 16, 12475, 12477), + (12477, -1, -1, 12430, 12430, 9, 85, 0, 0, 0, 16, 12476, 12876), + (12478, -1, -1, 12478, 12478, 5, 85, 0, 0, 0, 16, -1, 12479), + (12479, -1, -1, 12478, 12478, 7, 85, 0, 0, 0, 16, 12478, 12480), + (12480, -1, -1, 12478, 12478, 9, 85, 0, 0, 0, 16, 12479, -1), + (12481, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6473, 12482), + (12482, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12481, 12508), + (12483, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6475, 12484), + (12484, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12483, 12511), + (12485, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6477, 12486), + (12486, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12485, 12514), + (12487, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 16, 6471, 12488), + (12488, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12487, 12517), + (12492, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 17, 12410, 12493), + (12493, -1, -1, 6119, 6119, 6, 86, -1, 0, 0, 17, 12492, 12494), + (12494, -1, -1, 6119, 6119, 6, 87, -1, 0, 0, 17, 12493, 12495), + (12495, -1, -1, 6119, 6119, 6, 88, -1, 0, 0, 17, 12494, 12496), + (12496, -1, -1, 6119, 6119, 6, 89, -1, 0, 0, 17, 12495, 8448), + (12497, -1, -1, 77, 77, 12, 86, -1, 0, 0, 17, 12451, 12498), + (12498, -1, -1, 77, 77, 12, 88, -1, 0, 0, 17, 12497, 12499), + (12499, -1, -1, 77, 77, 12, 90, -1, 0, 0, 17, 12498, 13296), + (12500, -1, -1, 12500, 12500, 5, 81, -1, 0, 0, 16, -1, 12501), + (12501, -1, -1, 12500, 12500, 7, 81, -1, 0, 0, 16, 12500, 12502), + (12502, -1, -1, 12500, 12500, 9, 81, -1, 0, 0, 16, 12501, 12505), + (12505, -1, -1, 12500, 12500, 11, 83, -1, 0, 0, 16, 12502, 12506), + (12506, -1, -1, 12500, 12500, 12, 85, -1, 0, 0, 16, 12505, -1), + (12507, -1, -1, 199, 199, 12, 81, -1, 0, 0, 16, 201, -1), + (12508, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12482, 12509), + (12509, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12508, 12510), + (12510, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12509, 16440), + (12511, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12484, 12512), + (12512, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12511, 12513), + (12513, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12512, 12591), + (12514, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12486, 12515), + (12515, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12514, 12516), + (12516, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12515, 12594), + (12517, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12488, 12518), + (12518, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12517, 12519), + (12519, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12518, 12597), + (12520, 6537, 6537, 6537, 6537, 7, 86, 23974, 30, 900, 17, 12462, 12521), + (12521, 6537, 6537, 6537, 6537, 8, 88, 23975, 30, 900, 17, 12520, 12522), + (12522, 6537, 6537, 6537, 6537, 9, 90, 23976, 30, 900, 17, 12521, 13275), + (12523, -1, -1, 1210, 1210, 7, 86, -1, 0, 0, 17, 7234, 12524), + (12526, -1, -1, 1210, 1213, 12, 86, -1, 0, 0, 17, 8346, 12527), + (12527, -1, -1, 1210, 1213, 12, 88, -1, 0, 0, 17, 12526, 12528), + (12528, -1, -1, 1210, 1213, 12, 90, -1, 0, 0, 17, 12527, 14349), + (12529, -1, -1, 6636, 6636, 9, 86, -1, 0, 0, 17, 10043, 12530), + (12530, -1, -1, 6636, 6636, 10, 88, -1, 0, 0, 17, 12529, 12531), + (12531, -1, -1, 6636, 6636, 11, 90, -1, 0, 0, 17, 12530, 16164), + (12532, -1, -1, 1592, 1592, 9, 86, -1, 0, 0, 17, 12443, 12533), + (12533, -1, -1, 1592, 1592, 10, 87, -1, 0, 0, 17, 12532, 12534), + (12534, -1, -1, 1592, 1592, 11, 88, -1, 0, 0, 17, 12533, 12535), + (12535, -1, -1, 1592, 1592, 12, 89, -1, 0, 0, 17, 12534, 12536), + (12536, -1, -1, 1592, 1592, 12, 90, -1, 0, 0, 17, 12535, 13930), + (12537, -1, -1, 1072, 1072, 8, 86, -1, 0, 0, 17, 12448, 12538), + (12538, -1, -1, 1072, 1072, 9, 87, -1, 0, 0, 17, 12537, 12539), + (12539, -1, -1, 1072, 1072, 10, 88, -1, 0, 0, 17, 12538, 12540), + (12540, -1, -1, 1072, 1072, 11, 89, -1, 0, 0, 17, 12539, 12541), + (12541, -1, -1, 1072, 1072, 12, 90, -1, 0, 0, 17, 12540, 13281), + (12548, -1, -1, 119, 119, 12, 86, -1, 0, 0, 17, 6025, 12549), + (12549, -1, -1, 119, 119, 12, 87, -1, 0, 0, 17, 12548, 12550), + (12550, -1, -1, 119, 119, 12, 88, -1, 0, 0, 17, 12549, 12551), + (12551, -1, -1, 119, 119, 12, 89, -1, 0, 0, 17, 12550, 12552), + (12552, -1, -1, 119, 119, 12, 90, -1, 0, 0, 17, 12551, 13286), + (12553, -1, -1, 637, 637, 8, 86, -1, 0, 0, 17, 12437, 12554), + (12554, -1, -1, 637, 637, 10, 88, -1, 0, 0, 17, 12553, 12555), + (12555, -1, -1, 637, 637, 12, 90, -1, 0, 0, 17, 12554, 14361), + (12556, -1, -1, 1107, 1107, 10, 86, -1, 0, 0, 17, 12434, 12557), + (12557, -1, -1, 1107, 1107, 11, 88, -1, 0, 0, 17, 12556, 12558), + (12558, -1, -1, 1107, 1107, 12, 90, -1, 0, 0, 17, 12557, 16489), + (12559, -1, -1, 8215, 8215, 5, 86, -1, 0, 0, 17, 8219, 12560), + (12560, -1, -1, 8215, 8215, 5, 87, -1, 0, 0, 17, 12559, 12561), + (12561, -1, -1, 8215, 8215, 5, 88, -1, 0, 0, 17, 12560, 12562), + (12562, -1, -1, 8215, 8215, 5, 89, -1, 0, 0, 17, 12561, 12563), + (12563, -1, -1, 8215, 8215, 5, 90, -1, 0, 0, 17, 12562, 15694), + (12564, -1, -1, 1186, 1186, 12, 86, -1, 0, 0, 17, 7694, 12565), + (12565, -1, -1, 1186, 1186, 12, 88, -1, 0, 0, 17, 12564, 12566), + (12566, -1, -1, 1186, 1186, 12, 90, -1, 0, 0, 17, 12565, 13299), + (12567, -1, -1, 80, 80, 12, 86, -1, 0, 0, 17, 12454, 12568), + (12568, -1, -1, 80, 80, 12, 88, -1, 0, 0, 17, 12567, 12569), + (12569, -1, -1, 80, 80, 12, 90, -1, 0, 0, 17, 12568, 13302), + (12570, -1, -1, 658, 658, 5, 86, -1, 0, 0, 17, 12459, 12571), + (12571, -1, -1, 658, 658, 5, 87, -1, 0, 0, 17, 12570, 12572), + (12572, -1, -1, 658, 658, 5, 88, -1, 0, 0, 17, 12571, 12573), + (12573, -1, -1, 658, 658, 5, 89, -1, 0, 0, 17, 12572, 12574), + (12574, -1, -1, 658, 658, 5, 90, -1, 0, 0, 17, 12573, 13313), + (12575, -1, -1, 12419, 12419, 9, 90, -1, 0, 0, 17, 12421, 13520), + (12576, -1, -1, 852, 852, 12, 86, -1, 0, 0, 17, 7680, 12577), + (12577, -1, -1, 852, 852, 12, 88, -1, 0, 0, 17, 12576, 12578), + (12578, -1, -1, 852, 852, 12, 90, -1, 0, 0, 17, 12577, 13601), + (12579, -1, -1, 1313, 1313, 12, 86, -1, 0, 0, 17, 10083, 12580), + (12580, -1, -1, 1313, 1313, 12, 88, -1, 0, 0, 17, 12579, 12581), + (12581, -1, -1, 1313, 1313, 12, 90, -1, 0, 0, 17, 12580, 14043), + (12582, -1, -1, 12582, 12582, 7, 85, 0, 0, 0, 17, -1, 12583), + (12583, -1, -1, 12582, 12582, 9, 87, 0, 0, 0, 17, 12582, 12584), + (12584, -1, -1, 12582, 12582, 12, 89, 0, 0, 0, 17, 12583, 15174), + (12585, 6640, 6640, 6640, 6640, 9, 86, 23572, 43, 60, 17, 6640, -1), + (12586, 6644, 6644, 6644, 6644, 2, 86, 23573, 44, 20, 17, 6644, -1), + (12587, -1, -1, 7757, 7757, 9, 86, -1, 0, 0, 17, 7759, 12588), + (12588, -1, -1, 7757, 7757, 9, 88, -1, 0, 0, 17, 12587, 12589), + (12589, -1, -1, 7757, 7757, 9, 90, -1, 0, 0, 17, 12588, 15182), + (12590, 10395, 10395, 10395, 10395, 5, 85, 23574, 62, 5, 17, 10395, -1), + (12591, -1, -1, 6540, 6540, 15, 91, -1, 0, 0, 18, 12513, 12592), + (12594, -1, -1, 6540, 6540, 11, 91, -1, 0, 0, 18, 12516, 12595), + (12597, -1, -1, 6540, 6540, 9, 91, -1, 0, 0, 18, 12519, 12598), + (12598, -1, -1, 6540, 6540, 11, 93, -1, 0, 0, 18, 12597, 12599), + (12600, -1, -1, 12600, 12600, 7, 85, 0, 0, 0, 17, -1, 13072), + (12603, -1, -1, 12603, 12603, 10, 70, 0, 0, 0, 17, -1, -1), + (12606, -1, -1, 12606, 12606, 6, 85, 0, 0, 0, 17, -1, -1), + (12607, -1, -1, 12607, 12607, 6, 74, 0, 0, 0, 17, -1, 14140), + (12610, -1, -1, 255, 255, 9, 87, -1, 0, 0, 17, 7702, 13773), + (12612, -1, -1, 1604, 1604, 10, 85, -1, 0, 0, 17, 7009, 12613), + (12613, -1, -1, 1604, 1604, 12, 87, -1, 0, 0, 17, 12612, 13095), + (12615, -1, -1, 12615, 12615, 10, 85, 0, 0, 0, 17, -1, 12616), + (12616, -1, -1, 12615, 12615, 12, 87, 0, 0, 0, 17, 12615, 12617), + (12617, -1, -1, 12615, 12615, 14, 89, 0, 0, 0, 17, 12616, 14138), + (12618, 5021, 5021, 5021, 5021, 9, 86, 24009, 7, 60, 17, 10870, 12619), + (12619, 5021, 5021, 5021, 5021, 9, 87, 24010, 7, 60, 17, 12618, 12620), + (12620, 5021, 5021, 5021, 5021, 9, 88, 24011, 7, 60, 17, 12619, 12621), + (12621, 5021, 5021, 5021, 5021, 9, 89, 24012, 7, 60, 17, 12620, 13785), + (12626, 9354, 9354, 9354, 9354, 5, 86, 23996, 40, 600, 17, 9356, -1), + (12629, 9357, 9357, 9357, 9357, 5, 86, 24002, 40, 600, 17, 9359, -1), + (12632, 9360, 9360, 9360, 9360, 5, 86, 24005, 40, 600, 17, 9362, -1), + (12633, 6325, 6325, 6325, 6325, 7, 85, 24008, 18, 600, 17, 6361, 13792), + (12635, 12635, 12635, 12635, 12635, 12, 90, 23643, 12, 5, 17, -1, -1), + (12636, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, -1, 12637), + (12637, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 12636, 8445), + (12638, 12638, 12638, 12638, 12638, 9, 85, 23581, 68, 10, 17, -1, -1), + (12639, -1, -1, 10514, 10514, 6, 86, -1, 0, 0, 17, 10515, 12640), + (12642, -1, -1, 10511, 10511, 6, 86, -1, 0, 0, 17, 10513, 12643), + (12645, -1, -1, 12645, 12645, 9, 90, 0, 0, 0, 17, -1, 15386), + (12646, -1, -1, 12646, 12646, 9, 90, 0, 0, 0, 17, -1, 15388), + (12647, 10502, -1, 10502, 10502, 7, 90, 16815, 64, 120, 17, 10502, -1), + (12648, 10503, 10503, 10503, 10503, 9, 86, 23582, 13, 600, 17, 10505, 12649), + (12651, 12651, 12651, 12651, 12651, 15, 90, 23585, 69, 600, 17, -1, 17352), + (12652, -1, -1, 12652, 12652, 9, 86, 0, 0, 0, 17, -1, 12653), + (12653, -1, -1, 12652, 12652, 12, 88, 0, 0, 0, 17, 12652, 12654), + (12654, -1, -1, 12652, 12652, 15, 90, 0, 0, 0, 17, 12653, 13411), + (12655, 12655, 12655, 12655, 12655, 9, 86, 23586, 70, 1800, 17, -1, 12656), + (12658, 757, -1, 757, 757, 12, 86, 23589, 6, 1800, 17, 7413, 12659), + (12661, 12661, 12661, 12661, 12661, 9, 86, 23592, 73, 2700, 17, -1, 12662), + (12664, -1, -1, 12664, 12664, 7, 86, 0, 0, 0, 17, -1, 12665), + (12667, -1, -1, 820, 820, 5, 86, -1, 0, 0, 17, 10662, 12668), + (12668, -1, -1, 820, 820, 5, 88, -1, 0, 0, 17, 12667, 12669), + (12669, -1, -1, 820, 820, 5, 90, -1, 0, 0, 17, 12668, 13820), + (12670, -1, -1, 6020, 6020, 2, 86, -1, 0, 0, 17, 10665, 12671), + (12671, -1, -1, 6020, 6020, 2, 87, -1, 0, 0, 17, 12670, 12672), + (12672, -1, -1, 6020, 6020, 2, 88, -1, 0, 0, 17, 12671, 12692), + (12673, -1, -1, 1546, 1546, 5, 80, -1, 0, 0, 17, 6441, -1), + (12674, -1, -1, 4801, 4801, 6, 86, -1, 0, 0, 17, 10123, 12675), + (12675, -1, -1, 4801, 4801, 6, 88, -1, 0, 0, 17, 12674, 12676), + (12676, -1, -1, 4801, 4801, 6, 90, -1, 0, 0, 17, 12675, -1), + (12677, -1, -1, 230, 230, 6, 90, -1, 0, 0, 17, 541, 16249), + (12678, -1, -1, 10656, 10656, 12, 90, 0, 0, 0, 17, 10656, -1), + (12679, -1, -1, 10657, 10657, 7, 86, 0, 0, 0, 17, 10659, 12680), + (12680, -1, -1, 10657, 10657, 9, 88, 0, 0, 0, 17, 12679, 12681), + (12681, -1, -1, 10657, 10657, 12, 90, 0, 0, 0, 17, 12680, 14154), + (12682, 7872, 7872, 7872, 7872, 6, 86, 23595, 41, 600, 17, 10129, 12683), + (12683, 7872, 7872, 7872, 7872, 6, 88, 23596, 41, 600, 17, 12682, 12684), + (12684, 7872, 7872, 7872, 7872, 6, 90, 23597, 41, 600, 17, 12683, 13838), + (12685, -1, -1, 807, 807, 5, 86, -1, 0, 0, 17, 7630, 12686), + (12686, -1, -1, 807, 807, 5, 88, -1, 0, 0, 17, 12685, 12687), + (12687, -1, -1, 807, 807, 5, 90, -1, 0, 0, 17, 12686, -1), + (12688, -1, -1, 12688, 12688, 12, 90, 0, 0, 0, 17, -1, -1), + (12689, -1, -1, 7884, 7884, 12, 87, -1, 0, 0, 17, 7884, -1), + (12690, -1, -1, 7885, 7885, 12, 86, -1, 0, 0, 17, 7885, -1), + (12691, -1, -1, 12691, 12691, 12, 88, 0, 0, 0, 17, -1, -1), + (12692, -1, -1, 6020, 6020, 2, 89, -1, 0, 0, 17, 12672, 12693), + (12693, -1, -1, 6020, 6020, 2, 90, -1, 0, 0, 17, 12692, 13823), + (12694, -1, -1, 683, 683, 5, 86, -1, 0, 0, 17, 7605, 12695), + (12695, -1, -1, 683, 683, 5, 88, -1, 0, 0, 17, 12694, 12696), + (12696, -1, -1, 683, 683, 5, 90, -1, 0, 0, 17, 12695, 13305), + (12697, -1, -1, 1041, 1041, 12, 86, -1, 0, 0, 17, 7564, 12698), + (12698, -1, -1, 1041, 1041, 12, 88, -1, 0, 0, 17, 12697, 12699), + (12699, -1, -1, 1041, 1041, 12, 90, -1, 0, 0, 17, 12698, 13332), + (12700, 1355, 1355, 1355, 1355, 9, 86, 23644, 3, 60, 17, 10121, 12701), + (12701, 1355, 1355, 1355, 1355, 9, 88, 23645, 3, 60, 17, 12700, 12702), + (12702, 1355, 1355, 1355, 1355, 9, 90, 23646, 3, 60, 17, 12701, 13832), + (12703, -1, -1, 611, 611, 4, 86, -1, 0, 0, 17, 10126, 12704), + (12704, -1, -1, 611, 611, 4, 88, -1, 0, 0, 17, 12703, 12705), + (12705, -1, -1, 611, 611, 4, 90, -1, 0, 0, 17, 12704, 13835), + (12706, -1, -1, 12706, 12706, 7, 86, 0, 0, 0, 17, -1, 12707), + (12707, -1, -1, 12706, 12706, 9, 88, 0, 0, 0, 17, 12706, 12708), + (12708, -1, -1, 12706, 12706, 12, 90, 0, 0, 0, 17, 12707, 13813), + (12709, -1, -1, 12709, 12709, 9, 86, -1, 0, 0, 17, -1, -1), + (12710, -1, -1, 12710, 12710, 9, 86, 0, 0, 0, 17, -1, 12711), + (12711, -1, -1, 12710, 12710, 12, 88, 0, 0, 0, 17, 12710, 12712), + (12712, -1, -1, 12710, 12710, 15, 90, 0, 0, 0, 17, 12711, 14173), + (12713, -1, -1, 12713, 12713, 7, 86, 0, 0, 0, 17, -1, 12714), + (12714, -1, -1, 12713, 12713, 7, 88, 0, 0, 0, 17, 12713, 12715), + (12715, -1, -1, 12713, 12713, 7, 90, 0, 0, 0, 17, 12714, -1), + (12716, -1, -1, 12716, 12716, 7, 86, 0, 0, 0, 17, -1, 12717), + (12717, -1, -1, 12716, 12716, 7, 88, 0, 0, 0, 17, 12716, 12718), + (12718, -1, -1, 12716, 12716, 7, 90, 0, 0, 0, 17, 12717, 15526), + (12719, -1, -1, 12719, 12719, 9, 90, 0, 0, 0, 17, -1, -1), + (12720, -1, -1, 12720, 12720, 9, 86, 0, 0, 0, 17, -1, -1), + (12721, -1, -1, 12721, 12721, 7, 86, 0, 0, 0, 17, -1, 12722), + (12722, -1, -1, 12721, 12721, 9, 88, 0, 0, 0, 17, 12721, 12723), + (12723, -1, -1, 12721, 12721, 12, 90, 0, 0, 0, 17, 12722, 16303), + (12724, 10333, 10333, 10333, 10333, 9, 86, 23647, 55, 120, 17, 10335, 12725), + (12725, 10333, 10333, 10333, 10333, 9, 86, 23648, 55, 120, 17, 12724, 12726), + (12726, 10333, 10333, 10333, 10333, 9, 86, 23649, 55, 120, 17, 12725, 15988), + (12727, -1, -1, 1555, 1555, 7, 86, 0, 0, 0, 17, 1557, 12728), + (12728, -1, -1, 1555, 1555, 7, 88, 0, 0, 0, 17, 12727, 12729), + (12729, -1, -1, 1555, 1555, 7, 90, 0, 0, 0, 17, 12728, -1), + (12730, 10336, 10336, 10336, 10336, 9, 86, 23650, 58, 8, 17, 10338, 12731), + (12731, 10336, 10336, 10336, 10336, 12, 88, 23651, 58, 8, 17, 12730, 12732), + (12732, 10336, 10336, 10336, 10336, 15, 90, 23652, 58, 8, 17, 12731, 13517), + (12733, -1, -1, 10332, 10332, 7, 90, -1, 0, 0, 17, 10332, -1), + (12734, -1, -1, 6375, 6375, 9, 86, -1, 0, 0, 17, 10138, 12735), + (12735, -1, -1, 6375, 6375, 9, 88, -1, 0, 0, 17, 12734, 12736), + (12736, -1, -1, 6375, 6375, 9, 90, -1, 0, 0, 17, 12735, 13502), + (12737, -1, -1, 12737, 12737, 9, 86, 0, 0, 0, 17, -1, 12738), + (12738, -1, -1, 12737, 12737, 9, 88, 0, 0, 0, 17, 12737, 12739), + (12739, -1, -1, 12737, 12737, 9, 90, 0, 0, 0, 17, 12738, 15961), + (12740, 6533, 6533, 6533, 6533, 10, 86, 23653, 15, 600, 17, 10139, 12741), + (12741, 6533, 6533, 6533, 6533, 10, 88, 23654, 15, 600, 17, 12740, 12742), + (12742, 6533, 6533, 6533, 6533, 10, 90, 23655, 15, 600, 17, 12741, 13505), + (12743, 1116, 1116, 1116, 1116, 12, 86, 23656, 4, 2160, 17, 10142, 12744), + (12744, 1116, 1116, 1116, 1116, 12, 88, 23657, 4, 2160, 17, 12743, 12745), + (12745, 1116, 1116, 1116, 1116, 12, 90, 23658, 4, 2160, 17, 12744, 13530), + (12746, 5298, 5298, 5298, 5298, 12, 86, 23659, 32, 1800, 17, 10145, 12747), + (12747, 5298, 5298, 5298, 5298, 12, 88, 23660, 32, 1800, 17, 12746, 12748), + (12748, 5298, 5298, 5298, 5298, 12, 90, 23661, 32, 1800, 17, 12747, 13514), + (12749, 592, 592, 592, 592, 5, 86, 23665, 2, 18, 17, 7437, 12750), + (12750, 592, 592, 592, 592, 5, 88, 23666, 2, 18, 17, 12749, 12751), + (12751, 592, 592, 592, 592, 5, 90, 23667, 2, 18, 17, 12750, 13499), + (12754, 10701, 10701, 10701, 10701, 12, 86, 23668, 32, 360, 17, 10703, 12755), + (12755, 10701, 10701, 10701, 10701, 12, 88, 23669, 32, 360, 17, 12754, 12756), + (12756, 10701, 10701, 10701, 10701, 12, 90, 23670, 32, 360, 17, 12755, 15588), + (12757, -1, -1, 4861, 4861, 12, 86, -1, 0, 0, 17, 7682, 12758), + (12758, -1, -1, 4861, 4861, 12, 88, -1, 0, 0, 17, 12757, 12759), + (12759, -1, -1, 4861, 4861, 12, 90, -1, 0, 0, 17, 12758, -1), + (12760, 1274, 1274, 1274, 1274, 12, 86, 23674, 9, 540, 17, 10211, 12761), + (12761, 1274, 1274, 1274, 1274, 12, 88, 23675, 9, 540, 17, 12760, 12762), + (12762, 1274, 1274, 1274, 1274, 12, 90, 23676, 9, 540, 17, 12761, 14352), + (12766, 12766, 12766, 12766, 12766, 15, 90, 23677, 69, 3600, 17, -1, 13682), + (12767, -1, -1, 692, 692, 12, 86, -1, 0, 0, 17, 7672, 12768), + (12768, -1, -1, 692, 692, 12, 88, -1, 0, 0, 17, 12767, 12769), + (12769, -1, -1, 692, 692, 12, 90, -1, 0, 0, 17, 12768, 17295), + (12770, 12770, 12770, 12770, 12770, 9, 85, 23678, 52, 120, 17, -1, 12771), + (12771, 12770, 12770, 12770, 12770, 12, 87, 23679, 52, 120, 17, 12770, 12772), + (12772, 12770, 12770, 12770, 12770, 15, 89, 23680, 52, 120, 17, 12771, -1), + (12773, -1, -1, 12773, 12773, 7, 86, 0, 0, 0, 17, -1, 12774), + (12774, -1, -1, 12773, 12773, 7, 87, 0, 0, 0, 17, 12773, 12775), + (12775, -1, -1, 12773, 12773, 7, 88, 0, 0, 0, 17, 12774, 12776), + (12776, -1, -1, 12773, 12773, 7, 89, 0, 0, 0, 17, 12775, 12777), + (12777, -1, -1, 12773, 12773, 7, 90, 0, 0, 0, 17, 12776, -1), + (12778, 12778, 12778, 12778, 12778, 12, 90, 23681, 74, 1200, 17, -1, 13678), + (12779, -1, -1, 12779, 12779, 7, 85, 0, 0, 0, 17, -1, 12780), + (12780, -1, -1, 12779, 12779, 9, 87, 0, 0, 0, 17, 12779, 12781), + (12781, -1, -1, 12779, 12779, 12, 89, 0, 0, 0, 17, 12780, -1), + (12782, -1, -1, 12782, 12782, 7, 86, 0, 0, 0, 17, -1, 12783), + (12783, -1, -1, 12782, 12782, 9, 88, 0, 0, 0, 17, 12782, 12784), + (12784, -1, -1, 12782, 12782, 12, 90, 0, 0, 0, 17, 12783, -1), + (12785, 12785, 12785, 12785, 12785, 12, 90, 23683, 80, 30, 17, -1, 17131), + (12786, 6815, 6815, 6815, 6815, 8, 86, 23684, 60, 600, 17, 10202, 12787), + (12787, 6815, 6815, 6815, 6815, 8, 88, 23685, 60, 600, 17, 12786, 12788), + (12788, 6815, 6815, 6815, 6815, 8, 90, 23686, 60, 600, 17, 12787, 14355), + (12789, 967, 967, 967, 967, 7, 85, 23687, 10, 1800, 17, 10226, 12790), + (12790, 967, 967, 967, 967, 7, 87, 23688, 10, 1800, 17, 12789, 12791), + (12791, 967, 967, 967, 967, 7, 89, 23689, 10, 1800, 17, 12790, 17535), + (12792, -1, -1, 9503, 9503, 7, 86, -1, 0, 0, 17, 10089, 12793), + (12793, -1, -1, 9503, 9503, 7, 88, -1, 0, 0, 17, 12792, 12794), + (12794, -1, -1, 9503, 9503, 7, 90, -1, 0, 0, 17, 12793, 5360), + (12795, -1, -1, 6051, 6051, 5, 85, -1, 0, 0, 17, 10606, 12796), + (12796, -1, -1, 6051, 6051, 5, 87, -1, 0, 0, 17, 12795, 12797), + (12797, -1, -1, 6051, 6051, 5, 89, -1, 0, 0, 17, 12796, 13278), + (12798, -1, -1, 5264, 5264, 12, 86, -1, 0, 0, 17, 10217, 12799), + (12799, -1, -1, 5264, 5264, 12, 88, -1, 0, 0, 17, 12798, 12800), + (12800, -1, -1, 5264, 5264, 12, 90, -1, 0, 0, 17, 12799, 13675), + (12801, -1, -1, 6383, 6383, 9, 85, -1, 0, 0, 17, 10609, 12802), + (12802, -1, -1, 6383, 6383, 9, 87, -1, 0, 0, 17, 12801, 12803), + (12803, -1, -1, 6383, 6383, 9, 89, -1, 0, 0, 17, 12802, 5339), + (12804, 12804, 12804, 12804, 12804, 7, 86, 23693, 75, 900, 17, -1, 12805), + (12807, 12807, 12807, 12807, 12807, 7, 86, 23699, 73, 1200, 17, -1, 12808), + (12810, 8227, 8227, 8227, 12810, 5, 85, 27402, 71, 10, 17, 8227, 12811), + (12811, 8227, 8227, 8227, 12810, 7, 87, 27403, 71, 10, 17, 12810, 12812), + (12812, 8227, 8227, 8227, 12810, 9, 89, 27404, 71, 10, 17, 12811, -1), + (12813, -1, -1, 1287, 1287, 5, 75, -1, 0, 0, 17, -1, 12814), + (12814, -1, -1, 1287, 1287, 5, 77, -1, 0, 0, 17, 12813, 12815), + (12815, -1, -1, 1287, 1287, 5, 79, -1, 0, 0, 17, 12814, 14279), + (12816, -1, -1, 12816, 12816, 7, 86, 0, 0, 0, 17, -1, 12817), + (12819, -1, -1, 12819, 12819, 9, 85, 0, 0, 0, 17, -1, 12820), + (12820, -1, -1, 12819, 12819, 12, 87, 0, 0, 0, 17, 12819, 12821), + (12822, -1, -1, 12822, 12822, 9, 86, 0, 0, 0, 17, -1, 12823), + (12828, 291, 291, 291, 12828, 12, 86, 27409, 5, 900, 17, 10304, 12829), + (12831, -1, -1, 12831, 12831, 7, 86, 0, 0, 0, 17, -1, 12832), + (12834, -1, -1, 6980, 6980, 5, 85, -1, 0, 0, 17, 6982, 12835), + (12835, -1, -1, 6980, 6980, 5, 87, -1, 0, 0, 17, 12834, 12836), + (12837, 12837, 12837, 12837, 12837, 7, 86, 27412, 74, 420, 17, -1, 12838), + (12840, -1, -1, 6977, 6977, 5, 85, -1, 0, 0, 17, 6979, 12841), + (12841, -1, -1, 6977, 6977, 5, 87, -1, 0, 0, 17, 12840, 12842), + (12843, -1, -1, 551, 551, 5, 86, -1, 0, 0, 17, 6907, 12844), + (12846, -1, -1, 12846, 12846, 7, 86, 6499, 0, 0, 17, -1, 12847), + (12849, -1, -1, 12849, 12849, 7, 86, 0, 0, 0, 17, -1, 12850), + (12857, 8072, 8072, 8072, 8072, 7, 86, 27419, 37, 20, 17, 10248, 12858), + (12860, -1, -1, 267, 267, 12, 86, -1, 0, 0, 17, 5619, 12861), + (12863, -1, -1, 141, 12863, 12, 59, -1, 0, 0, 17, 143, 15396), + (12864, 12864, -1, 12864, 12864, 5, 59, 27422, 73, 10, 17, -1, 17486), + (12865, 12865, 12865, 12865, 12865, 12, 90, 27423, 42, 6, 17, -1, -1), + (12866, 12866, 12866, 12866, 12866, 12, 86, 27424, 74, 1800, 17, -1, 15605), + (12867, 12867, 12867, 12867, 12867, 12, 86, 27426, 13, 4320, 17, -1, -1), + (12868, 1334, 1334, 1334, 1334, 12, 86, 27427, 11, 4320, 17, 10236, 12869), + (12871, -1, -1, 11050, 11050, 9, 85, -1, 0, 0, 17, 11060, 12872), + (12872, -1, -1, 11050, 11050, 12, 87, -1, 0, 0, 17, 12871, 12873), + (12874, -1, -1, 1414, 1414, 5, 86, -1, 0, 0, 17, 1418, 17490), + (12875, 4938, 4938, 4938, 4938, 12, 90, 27430, 35, 1800, 17, 5614, 13727), + (12876, -1, -1, 12430, 12430, 7, 86, 0, 0, 0, 17, 12477, 12877), + (12877, -1, -1, 12430, 12430, 9, 88, 0, 0, 0, 17, 12876, 12878), + (12878, -1, -1, 12430, 12430, 12, 90, 0, 0, 0, 17, 12877, 15270), + (12879, 516, 516, 516, 516, 6, 86, 27431, 5, 480, 17, 10233, 13659), + (12880, 1404, 1404, 1404, 1404, 7, 85, 27432, 15, 2160, 17, 1408, -1), + (12881, -1, -1, 12881, 12881, 9, 86, 0, 0, 0, 17, -1, 12882), + (12885, 12885, 12885, 12885, 12885, 12, 86, 27435, 75, 90, 17, -1, 17491), + (12886, -1, -1, 12886, 12886, 2, 85, -1, 0, 0, 17, -1, -1), + (12887, -1, -1, 12887, 12887, 2, 87, -1, 0, 0, 17, -1, -1), + (12888, -1, -1, 12888, 12888, 2, 89, -1, 0, 0, 17, -1, -1), + (12889, -1, -1, 12889, 12889, 2, 85, -1, 0, 0, 17, -1, 12890), + (12890, -1, -1, 12889, 12889, 2, 87, -1, 0, 0, 17, 12889, 12891), + (12892, 12892, 12892, 12892, 12892, 3, 90, 27434, 8, 60, 17, -1, 13666), + (12893, 12893, 12893, 12893, 12893, 12, 90, 27436, 76, 1800, 17, -1, 13663), + (12894, -1, -1, 12894, 12894, 5, 86, 0, 0, 0, 17, -1, 12895), + (12899, -1, -1, 471, 471, 2, 85, -1, 0, 0, 17, 473, 12900), + (12900, -1, -1, 471, 471, 2, 87, -1, 0, 0, 17, 12899, 12901), + (12902, -1, -1, 12902, 12902, 5, 85, 0, 0, 0, 17, -1, 12903), + (12903, -1, -1, 12902, 12902, 5, 86, 0, 0, 0, 17, 12902, 12904), + (12907, -1, -1, 12907, 12907, 5, 85, 0, 0, 0, 17, -1, 12908), + (12908, -1, -1, 12907, 12907, 5, 86, 0, 0, 0, 17, 12907, 12909), + (12912, -1, -1, 12912, 12912, 5, 85, 0, 0, 0, 17, -1, 12913), + (12913, -1, -1, 12912, 12912, 5, 86, 0, 0, 0, 17, 12912, 12914), + (12917, 517, 517, 517, 517, 5, 85, 27437, 12, 600, 17, 10281, 12918), + (12918, 517, 517, 517, 517, 5, 87, 27438, 12, 600, 17, 12917, 12919), + (12920, -1, -1, 12920, 12920, 5, 86, 0, 0, 0, 17, -1, 12921), + (12923, 54009, 54009, 54009, 12923, 3, 85, 27440, 22, 12, 17, 5849, 12924), + (12924, 54009, 54009, 54009, 12923, 3, 87, 27441, 22, 12, 17, 12923, 12925), + (12929, -1, -1, 6548, 6548, 8, 85, -1, 0, 0, 17, 6238, 12930), + (12930, -1, -1, 6548, 6548, 8, 90, -1, 0, 0, 17, 12929, 15463), + (12931, 12931, 12931, 12931, 12931, 7, 86, 27443, 73, 3600, 17, -1, 12932), + (12934, 1242, 1242, 1242, 1242, 12, 86, 27446, 9, 1320, 17, 10273, 12935), + (12937, 12937, 12937, 12937, 12937, 12, 86, 27449, 16, 420, 17, -1, 13733), + (12938, 12938, 12938, 12938, 12938, 15, 88, 27450, 75, 2700, 17, -1, 13743), + (12939, 12939, 12939, 12939, 12939, 12, 90, 27451, 77, 1800, 17, -1, 14756), + (12941, 12941, 12941, 12941, 12941, 5, 85, 27453, 77, 1, 17, -1, -1), + (12942, 6539, 6539, 6539, 6539, 6, 86, 27454, 18, 1800, 17, 7611, 12943), + (12943, 6539, 6539, 6539, 6539, 6, 88, 27455, 18, 1800, 17, 12942, 12944), + (12944, 6539, 6539, 6539, 6539, 6, 90, 27456, 18, 1800, 17, 12943, 13291), + (12945, -1, -1, 795, 795, 12, 85, -1, 0, 0, 17, 10267, 12946), + (12946, -1, -1, 795, 795, 12, 86, -1, 0, 0, 17, 12945, 12947), + (12947, -1, -1, 795, 795, 12, 87, -1, 0, 0, 17, 12946, 12948), + (12948, -1, -1, 795, 795, 12, 88, -1, 0, 0, 17, 12947, 12949), + (12949, -1, -1, 795, 795, 12, 89, -1, 0, 0, 17, 12948, 13710), + (12950, -1, -1, 790, 790, 6, 86, -1, 0, 0, 17, 7274, 12951), + (12951, -1, -1, 790, 790, 6, 87, -1, 0, 0, 17, 12950, 12952), + (12952, -1, -1, 790, 790, 6, 88, -1, 0, 0, 17, 12951, 12953), + (12953, -1, -1, 790, 790, 6, 89, -1, 0, 0, 17, 12952, 12954), + (12954, -1, -1, 790, 790, 6, 90, -1, 0, 0, 17, 12953, 13713), + (12955, 167, 167, 167, 167, 10, 86, 27457, 14, 900, 17, 8343, 13718), + (12956, 4903, 4903, 4903, 4903, 9, 85, 27460, 9, 1320, 17, 10255, 13698), + (12957, 4909, 4909, 4909, 4909, 9, 85, 27461, 16, 1320, 17, 10257, 14733), + (12958, 4912, 4912, 4912, 4912, 9, 85, 27459, 16, 1320, 17, 10258, 13704), + (12959, 4906, 4906, 4906, 4906, 9, 85, 27458, 9, 1320, 17, 10256, 13701), + (12963, 12963, 12963, 12963, 12963, 7, 86, 27465, 81, 5, 17, -1, -1), + (12964, 12964, 12964, 12964, 12964, 7, 88, 27466, 81, 5, 17, -1, -1), + (12965, 12965, 12965, 12965, 12965, 7, 90, 27467, 81, 5, 17, -1, -1), + (12966, -1, -1, 6112, 6112, 5, 87, -1, 0, 0, 17, 6112, 12967), + (12967, -1, -1, 6112, 6112, 5, 89, -1, 0, 0, 17, 12966, 16402), + (12968, -1, -1, 12968, 12968, 7, 85, 0, 0, 0, 17, -1, 12969), + (12969, -1, -1, 12968, 12968, 7, 87, 0, 0, 0, 17, 12968, 12970), + (12970, -1, -1, 12968, 12968, 7, 89, 0, 0, 0, 17, 12969, 14238), + (12971, 12971, 12971, 12971, 12971, 5, 86, 27471, 79, 2160, 17, -1, 12972), + (12972, 12971, 12971, 12971, 12971, 7, 87, 27472, 79, 2160, 17, 12971, 12973), + (12973, 12971, 12971, 12971, 12971, 9, 88, 27473, 79, 2160, 17, 12972, 12974), + (12974, 12971, 12971, 12971, 12971, 12, 89, 27474, 79, 2160, 17, 12973, 12975), + (12975, 12971, 12971, 12971, 12971, 15, 90, 27475, 79, 2160, 17, 12974, -1), + (12976, 7903, 7903, 7903, 7903, 6, 85, 27476, 60, 30, 17, 7903, 14734), + (12977, -1, -1, 12977, 12977, 5, 85, 0, 0, 0, 17, -1, 12978), + (12978, -1, -1, 12977, 12977, 5, 86, 0, 0, 0, 17, 12977, 12979), + (12979, -1, -1, 12977, 12977, 5, 87, 0, 0, 0, 17, 12978, 12980), + (12980, -1, -1, 12977, 12977, 5, 88, 0, 0, 0, 17, 12979, 12981), + (12981, -1, -1, 12977, 12977, 5, 89, 0, 0, 0, 17, 12980, 17334), + (12982, 10600, 10600, 10600, 10600, 7, 86, 27477, 73, 20, 17, 10602, 12983), + (12983, 10600, 10600, 10600, 10600, 7, 88, 27478, 73, 20, 17, 12982, 12984), + (12984, 10600, 10600, 10600, 10600, 7, 90, 27479, 73, 20, 17, 12983, 13720), + (12985, 520, 520, 520, 520, 12, 86, 27480, 6, 540, 17, 10254, 12986), + (12986, 520, 520, 520, 520, 12, 88, 27481, 6, 540, 17, 12985, 12987), + (12987, 520, 520, 520, 520, 12, 90, 27482, 6, 540, 17, 12986, -1), + (12988, -1, -1, 10959, 12988, 12, 90, -1, 0, 0, 17, 10962, -1), + (12989, 12989, 12989, 12989, 12989, 7, 86, 27486, 73, 1800, 17, -1, 12990), + (12990, 12989, 12989, 12989, 12989, 9, 88, 27487, 73, 1800, 17, 12989, 12991), + (12991, 12989, 12989, 12989, 12989, 12, 90, 27488, 73, 1800, 17, 12990, 5336), + (12992, 12992, 12992, 12992, 12992, 9, 86, 27489, 0, 1, 17, -1, 12993), + (12993, 12992, 12992, 12992, 12992, 12, 88, 27490, 0, 1, 17, 12992, 12994), + (12994, 12992, 12992, 12992, 12992, 15, 90, 27491, 0, 1, 17, 12993, 5350), + (12995, 6563, 6563, 6563, 6563, 12, 86, 27492, 36, 8, 17, 6281, -1), + (12996, 153, 153, 153, 153, 12, 90, 27493, 3, 2160, 17, 11081, 17333), + (12997, 1520, 1520, 1520, 1520, 9, 85, 27494, 11, 900, 17, 10192, 12998), + (12998, 1520, 1520, 1520, 1520, 9, 87, 27495, 11, 900, 17, 12997, 12999), + (12999, 1520, 1520, 1520, 1520, 9, 89, 27496, 11, 900, 17, 12998, 5333), + (13000, 10958, 10958, 10958, 10958, 15, 90, 27497, 62, 900, 17, 10958, 16214), + (13001, -1, -1, 13001, 13001, 7, 86, -1, 0, 0, 17, -1, 13002), + (13002, -1, -1, 13001, 13001, 7, 88, -1, 0, 0, 17, 13001, 13003), + (13003, -1, -1, 13001, 13001, 7, 90, -1, 0, 0, 17, 13002, 15348), + (13004, 13004, 13004, 13004, 13004, 9, 86, 27499, 78, 300, 17, -1, 15855), + (13005, -1, -1, 6703, 6703, 3, 86, -1, 0, 0, 17, 10178, 13006), + (13006, -1, -1, 6703, 6703, 3, 88, -1, 0, 0, 17, 13005, 13007), + (13007, -1, -1, 6703, 6703, 3, 90, -1, 0, 0, 17, 13006, -1), + (13008, 13008, 13008, 13008, 13008, 9, 90, 27500, 86, 300, 17, -1, -1), + (13009, 13009, 13009, 13009, 13009, 6, 86, 27501, 39, 1, 17, -1, -1), + (13010, -1, -1, 13010, 13010, 6, 85, 0, 0, 0, 17, -1, 13011), + (13011, -1, -1, 13010, 13010, 6, 87, 0, 0, 0, 17, 13010, 13012), + (13012, -1, -1, 13010, 13010, 6, 89, 0, 0, 0, 17, 13011, 14223), + (13013, -1, -1, 13013, 13013, 6, 86, 0, 0, 0, 17, -1, 13014), + (13014, -1, -1, 13013, 13013, 6, 88, 0, 0, 0, 17, 13013, 13015), + (13015, -1, -1, 13013, 13013, 6, 90, 0, 0, 0, 17, 13014, -1), + (13016, 5109, 5109, 5109, 5109, 9, 86, 27502, 0, 1, 17, 7467, 5356), + (13017, -1, -1, 13017, 13017, 9, 86, -1, 0, 0, 17, -1, 13018), + (13018, -1, -1, 13017, 13017, 12, 88, -1, 0, 0, 17, 13017, 13019), + (13019, -1, -1, 13017, 13017, 15, 90, -1, 0, 0, 17, 13018, 13396), + (13020, 13020, 13020, 13020, 13020, 12, 86, 27503, 76, 420, 17, -1, -1), + (13021, -1, -1, 11085, 11085, 12, 86, 0, 0, 0, 17, 11087, 13022), + (13023, -1, -1, 1050, 1050, 12, 86, -1, 0, 0, 17, 7658, 13024), + (13026, -1, -1, 599, 599, 12, 86, -1, 0, 0, 17, 7561, 13027), + (13027, -1, -1, 599, 599, 12, 88, -1, 0, 0, 17, 13026, 13028), + (13028, -1, -1, 599, 599, 12, 90, -1, 0, 0, 17, 13027, 13438), + (13029, -1, -1, 7818, 7818, 9, 86, 31681, 0, 0, 17, 7818, 13030), + (13032, -1, -1, 1131, 1131, 9, 85, -1, 0, 0, 17, 11084, 13033), + (13033, -1, -1, 1131, 1131, 12, 87, -1, 0, 0, 17, 13032, 13034), + (13035, -1, -1, 1134, 1134, 3, 86, -1, 0, 0, 17, 10315, 13036), + (13040, -1, -1, 4809, 4809, 5, 86, -1, 0, 0, 17, 10318, 13041), + (13043, -1, -1, 5776, 5776, 9, 86, -1, 0, 0, 17, 7198, 13044), + (13046, -1, -1, 8250, 8250, 6, 85, -1, 0, 0, 17, 8254, 13047), + (13047, -1, -1, 8250, 8250, 6, 86, -1, 0, 0, 17, 13046, 13048), + (13048, -1, -1, 8250, 8250, 6, 87, -1, 0, 0, 17, 13047, 13049), + (13049, -1, -1, 8250, 8250, 6, 88, -1, 0, 0, 17, 13048, 13050), + (13050, -1, -1, 8250, 8250, 6, 89, -1, 0, 0, 17, 13049, 13348), + (13051, -1, -1, 10404, 10404, 6, 90, -1, 0, 0, 17, 10404, -1), + (13052, -1, -1, 10401, 10401, 6, 86, -1, 0, 0, 17, 10403, 13053), + (13055, -1, -1, 13055, 13055, 6, 86, 0, 0, 0, 17, -1, 13056), + (13058, 6931, 6931, 6931, 6931, 12, 90, 27504, 41, 600, 17, 10319, 13857), + (13059, 4854, 4854, 4854, 4854, 9, 86, 27505, 8, 600, 17, 10325, 13060), + (13062, 6932, 6932, 6932, 6932, 7, 86, 27508, 42, 1200, 17, 10322, 13063), + (13065, 13065, 13065, 13065, 13065, 12, 86, 27514, 70, 90, 17, -1, -1), + (13066, 13066, 13066, 13066, 13066, 9, 85, 27516, 71, 1800, 17, -1, -1), + (13067, -1, -1, 13067, 13067, 6, 86, 0, 0, 0, 17, -1, 13068), + (13072, -1, -1, 12600, 12600, 7, 87, 0, 0, 0, 17, 12600, 13073), + (13073, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13072, 13222), + (13074, -1, -1, 1044, 1044, 9, 86, -1, 0, 0, 17, 7652, 13075), + (13075, -1, -1, 1044, 1044, 12, 88, -1, 0, 0, 17, 13074, 13076), + (13076, -1, -1, 1044, 1044, 15, 90, -1, 0, 0, 17, 13075, 13326), + (13077, -1, -1, 1047, 1047, 9, 86, -1, 0, 0, 17, 7655, 13078), + (13078, -1, -1, 1047, 1047, 12, 88, -1, 0, 0, 17, 13077, 13079), + (13080, -1, -1, 125, 125, 9, 86, -1, 0, 0, 17, 12400, 13081), + (13081, -1, -1, 125, 125, 10, 87, -1, 0, 0, 17, 13080, 13082), + (13082, -1, -1, 125, 125, 11, 88, -1, 0, 0, 17, 13081, 13083), + (13083, -1, -1, 125, 125, 12, 89, -1, 0, 0, 17, 13082, 13084), + (13084, -1, -1, 125, 125, 13, 90, -1, 0, 0, 17, 13083, 8463), + (13085, -1, -1, 122, 122, 9, 86, -1, 0, 0, 17, 12405, 13086), + (13086, -1, -1, 122, 122, 10, 87, -1, 0, 0, 17, 13085, 13087), + (13087, -1, -1, 122, 122, 11, 88, -1, 0, 0, 17, 13086, 13088), + (13088, -1, -1, 122, 122, 12, 89, -1, 0, 0, 17, 13087, 13089), + (13089, -1, -1, 122, 122, 13, 90, -1, 0, 0, 17, 13088, 8440), + (13090, -1, -1, 1435, 4773, 9, 86, -1, 0, 0, 17, 7621, 13295), + (13091, -1, -1, 1435, 4773, 9, 86, -1, 0, 0, 17, 1650, 13294), + (13092, -1, -1, 644, 644, 9, 85, -1, 0, 0, 17, 7361, 13093), + (13093, -1, -1, 644, 644, 12, 87, -1, 0, 0, 17, 13092, 13094), + (13094, -1, -1, 644, 644, 15, 89, -1, 0, 0, 17, 13093, 13265), + (13095, -1, -1, 1604, 1604, 15, 89, -1, 0, 0, 17, 12613, 13767), + (13096, -1, -1, 13096, 13096, 12, 86, -1, 0, 0, 17, -1, 13097), + (13097, -1, -1, 13096, 13096, 12, 88, -1, 0, 0, 17, 13096, 13098), + (13098, -1, -1, 13096, 13096, 12, 90, -1, 0, 0, 17, 13097, 13127), + (13099, -1, -1, 83, 83, 9, 55, -1, 0, 0, 17, 85, -1), + (13100, 13100, 13100, 13100, 13100, 9, 86, 27534, 86, 300, 17, -1, 15140), + (13101, -1, -1, 13101, 13101, 7, 86, 0, 0, 0, 17, -1, 13102), + (13102, -1, -1, 13101, 13101, 9, 88, 0, 0, 0, 17, 13101, 13103), + (13103, -1, -1, 13101, 13101, 12, 90, 0, 0, 0, 17, 13102, 14082), + (13104, -1, -1, 589, 589, 9, 86, -1, 0, 0, 17, 7709, 13105), + (13105, -1, -1, 589, 589, 9, 88, -1, 0, 0, 17, 13104, 13106), + (13106, -1, -1, 589, 589, 9, 90, -1, 0, 0, 17, 13105, 15778), + (13107, 6645, 6645, 6645, 6645, 9, 90, 27541, 45, 60, 17, 6645, 13633), + (13108, 13108, 13108, 13108, 13108, 5, 90, 27542, 89, 30, 17, -1, -1), + (13109, 1351, 1351, 1351, 1351, 8, 90, 27543, 5, 30, 17, 7109, -1), + (13110, 10815, 10815, 10815, 10815, 9, 86, -1, 0, 0, 17, 10817, 13111), + (13111, 10815, 10815, 10815, 10815, 11, 88, -1, 0, 0, 17, 13110, 13112), + (13113, 10818, 10818, 10818, 10818, 9, 86, -1, 0, 0, 17, 10820, 13114), + (13114, 10818, 10818, 10818, 10818, 11, 88, -1, 0, 0, 17, 13113, 13115), + (13116, 10821, 10821, 10821, 10821, 9, 86, -1, 0, 0, 17, 10823, 13117), + (13117, 10821, 10821, 10821, 10821, 11, 88, -1, 0, 0, 17, 13116, 13118), + (13119, 5007, 5007, 5007, 5007, 9, 86, 27544, 8, 2160, 17, 10063, 13120), + (13120, 5007, 5007, 5007, 5007, 9, 88, 27545, 8, 2160, 17, 13119, 13121), + (13122, -1, -1, 6546, 6546, 0, 86, -1, 0, 0, 17, 7377, 13123), + (13123, -1, -1, 6546, 6546, 0, 87, -1, 0, 0, 17, 13122, 13124), + (13124, -1, -1, 6546, 6546, 0, 88, -1, 0, 0, 17, 13123, 13125), + (13127, -1, -1, 13096, 13096, 12, 91, -1, 0, 0, 18, 13098, 13128), + (13130, 13130, 13130, 13130, 13130, 15, 95, 32440, 48, 30, 18, -1, -1), + (13133, 7756, 7756, 7756, 7756, 12, 85, 21805, 85, 120, 17, -1, -1), + (13134, 13134, 13134, 13134, 13134, 7, 86, 27547, 74, 900, 17, -1, 13135), + (13135, 13134, 13134, 13134, 13134, 7, 88, 27548, 74, 900, 17, 13134, 13136), + (13136, 13134, 13134, 13134, 13134, 7, 90, 27549, 74, 900, 17, 13135, 13380), + (13140, -1, -1, 10464, 10464, 7, 86, -1, 0, 0, 17, 10466, 13141), + (13141, -1, -1, 10464, 10464, 9, 88, -1, 0, 0, 17, 13140, 13142), + (13142, -1, -1, 10464, 10464, 11, 90, -1, 0, 0, 17, 13141, -1), + (13143, -1, -1, 13143, 13143, 5, 86, 0, 0, 0, 17, -1, 13144), + (13144, -1, -1, 13143, 13143, 5, 88, 0, 0, 0, 17, 13143, 13145), + (13145, -1, -1, 13143, 13143, 5, 90, 0, 0, 0, 17, 13144, -1), + (13146, -1, -1, 13146, 13146, 5, 86, 0, 0, 0, 17, -1, 13147), + (13147, -1, -1, 13146, 13146, 5, 88, 0, 0, 0, 17, 13146, 13148), + (13148, -1, -1, 13146, 13146, 5, 90, 0, 0, 0, 17, 13147, -1), + (13149, -1, -1, 8210, 8210, 5, 86, -1, 0, 0, 17, 1655, 13150), + (13150, -1, -1, 8210, 8210, 5, 87, -1, 0, 0, 17, 13149, 13151), + (13151, -1, -1, 8210, 8210, 5, 88, -1, 0, 0, 17, 13150, 13152), + (13152, -1, -1, 8210, 8210, 5, 89, -1, 0, 0, 17, 13151, 13153), + (13153, -1, -1, 8210, 8210, 5, 90, -1, 0, 0, 17, 13152, 13318), + (13154, 5105, 5105, 5105, 5105, 12, 90, 27550, 11, 600, 17, 10509, 14023), + (13155, 7986, 7986, 7986, 7986, 12, 90, 27551, 11, 600, 17, 10510, 14022), + (13158, 548, 548, 548, 548, 10, 86, 27552, 5, 900, 17, 10098, 13159), + (13161, 528, 528, 528, 528, 12, 86, 27555, 5, 720, 17, 10196, 13162), + (13162, 528, 528, 528, 528, 12, 88, 27556, 5, 720, 17, 13161, 13163), + (13163, 528, 528, 528, 528, 12, 90, 27557, 5, 720, 17, 13162, 5357), + (13164, 13164, 13164, 13164, 13164, 9, 86, 27540, 99, 180, 17, -1, -1), + (13165, 13165, 13165, 13165, 13165, 9, 86, 27559, 56, 60, 17, -1, -1), + (13166, -1, -1, 13166, 13166, 7, 86, 0, 0, 0, 17, -1, 13167), + (13167, -1, -1, 13166, 13166, 7, 88, 0, 0, 0, 17, 13166, 13168), + (13168, -1, -1, 13166, 13166, 7, 90, 0, 0, 0, 17, 13167, -1), + (13169, 13169, 13169, 13169, 13169, 9, 90, 27560, 99, 180, 17, -1, 17221), + (13170, 6380, 6380, 6380, 6380, 6, 86, 27561, 39, 120, 17, 10310, 13171), + (13173, 290, 290, 290, 290, 8, 86, 27564, 4, 720, 17, 290, 13448), + (13174, 10374, 10374, 10374, 10374, 6, 85, 27565, 63, 900, 17, 10376, 13175), + (13175, 10374, 10374, 10374, 10374, 8, 87, 27566, 63, 900, 17, 13174, 13176), + (13177, 6984, 6984, 6984, 6984, 6, 83, 27568, 60, 60, 17, 10294, 13466), + (13178, 6986, 6986, 6986, 6986, 6, 83, 27570, 60, 60, 17, 10296, 13468), + (13179, 6985, 6985, 6985, 6985, 6, 83, 27569, 60, 60, 17, 10295, 13467), + (13180, 10377, 10377, 10377, 10377, 6, 86, 16796, 64, 60, 17, 10379, 13181), + (13183, 10346, 10346, 10346, 10346, 9, 90, 27574, 46, 600, 17, 10346, 13819), + (13184, -1, -1, 10340, 10340, 9, 86, -1, 0, 0, 17, 10342, 13185), + (13185, -1, -1, 10340, 10340, 9, 88, -1, 0, 0, 17, 13184, 13186), + (13186, -1, -1, 10340, 10340, 9, 90, -1, 0, 0, 17, 13185, 13829), + (13187, -1, -1, 9512, 9512, 7, 86, -1, 0, 0, 17, 7883, 13188), + (13188, -1, -1, 9512, 9512, 7, 88, -1, 0, 0, 17, 13187, 13189), + (13189, -1, -1, 9512, 9512, 7, 90, -1, 0, 0, 17, 13188, 13826), + (13190, 1110, 1110, 1110, 1110, 6, 86, 27576, 3, 2160, 17, 10152, 13191), + (13191, 1110, 1110, 1110, 1110, 6, 88, 27577, 3, 2160, 17, 13190, 13192), + (13192, 1110, 1110, 1110, 1110, 6, 90, 27578, 3, 2160, 17, 13191, 13496), + (13193, 1598, -1, 1598, 1598, 9, 86, 27582, 6, 900, 17, 10148, 13194), + (13194, 1598, -1, 1598, 1598, 11, 88, 27583, 6, 900, 17, 13193, 13195), + (13195, 1598, -1, 1598, 1598, 13, 90, 27584, 6, 900, 17, 13194, 13493), + (13196, -1, -1, 255, 255, 9, 86, -1, 0, 0, 17, 10135, 13197), + (13197, -1, -1, 255, 255, 9, 88, -1, 0, 0, 17, 13196, 13198), + (13198, -1, -1, 255, 255, 9, 90, -1, 0, 0, 17, 13197, 13511), + (13199, -1, -1, 8322, 8322, 9, 86, 0, 0, 0, 17, 8324, 13200), + (13200, -1, -1, 8322, 8322, 9, 88, 0, 0, 0, 17, 13199, 13201), + (13201, -1, -1, 8322, 8322, 9, 90, 0, 0, 0, 17, 13200, -1), + (13202, 13202, 13202, 13202, 13202, 2, 81, 27585, 98, 20, 17, -1, 14009), + (13203, 10330, 10330, 10330, 10330, 7, 90, 27586, 35, 30, 17, 10330, 13492), + (13204, -1, -1, 13204, 13204, 7, 86, -1, 0, 0, 17, -1, 13205), + (13205, -1, -1, 13204, 13204, 7, 88, -1, 0, 0, 17, 13204, 13206), + (13206, -1, -1, 13204, 13204, 7, 90, -1, 0, 0, 17, 13205, 14176), + (13207, -1, -1, 10850, 10850, 9, 86, 27587, 0, 0, 17, 10852, 13208), + (13208, -1, -1, 10850, 10850, 9, 88, 27588, 0, 0, 17, 13207, 13209), + (13209, -1, -1, 10850, 10850, 9, 90, 27589, 0, 0, 17, 13208, 13779), + (13210, -1, -1, 1307, 1307, 5, 81, -1, 0, 0, 17, 6662, 13211), + (13211, -1, -1, 1307, 1307, 5, 83, -1, 0, 0, 17, 13210, 13212), + (13212, -1, -1, 1307, 1307, 5, 85, -1, 0, 0, 17, 13211, -1), + (13213, -1, -1, 1543, 1543, 7, 86, -1, 0, 0, 17, 10167, 13214), + (13214, -1, -1, 1543, 1543, 7, 87, -1, 0, 0, 17, 13213, 13215), + (13215, -1, -1, 1543, 1543, 7, 88, -1, 0, 0, 17, 13214, 13216), + (13216, -1, -1, 1543, 1543, 7, 89, -1, 0, 0, 17, 13215, 13217), + (13217, -1, -1, 1543, 1543, 7, 90, -1, 0, 0, 17, 13216, 13782), + (13218, -1, -1, 1304, 1304, 12, 90, -1, 0, 0, 17, 10867, 13789), + (13219, -1, -1, 8325, 8325, 7, 85, 0, 0, 0, 17, 8327, 13220), + (13220, -1, -1, 8325, 8325, 9, 87, 0, 0, 0, 17, 13219, 13221), + (13221, -1, -1, 8325, 8325, 11, 89, 0, 0, 0, 17, 13220, 13798), + (13222, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13073, 13223), + (13223, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13222, -1), + (13224, 13224, -1, 13224, 13224, 3, 86, 27590, 98, 1, 17, -1, 15559), + (13225, 13225, 13225, 13225, 13225, 6, 86, 27592, 0, 4, 17, -1, 13688), + (13226, -1, -1, 5295, 5295, 6, 86, -1, 0, 0, 17, 10229, 13227), + (13229, 6290, 6290, 6290, 6290, 9, 86, 27596, 0, 1, 17, 11066, 13230), + (13232, 4944, -1, 4944, 4944, 9, 86, 27602, 0, 1, 17, 11069, 13233), + (13235, 1478, -1, 1478, 1478, 9, 86, 27608, 0, 1, 17, 11072, 13236), + (13238, -1, -1, 1287, 1287, 9, 86, -1, 0, 0, 17, 12474, 13239), + (13239, -1, -1, 1287, 1287, 10, 88, -1, 0, 0, 17, 13238, 13240), + (13240, -1, -1, 1287, 1287, 11, 90, -1, 0, 0, 17, 13239, 15719), + (13241, 4931, 4931, 4931, 4931, 7, 86, 27614, 4, 600, 17, 10430, 13242), + (13244, 1501, 1501, 1501, 1501, 6, 86, 27617, 10, 4320, 17, 1560, 13245), + (13247, 4894, 4894, 4894, 4894, 6, 86, 27620, 7, 2160, 17, 7290, 13248), + (13250, 10550, 10550, 10550, 10550, 7, 90, 27626, 61, 120, 17, 10550, 13728), + (13251, 1239, 1239, 1239, 1239, 9, 90, 27627, 6, 600, 17, 7275, 13732), + (13252, 13252, 13252, 13252, 13252, 9, 86, 27629, 95, 4, 17, -1, 16065), + (13253, 1126, 1126, 1126, 1126, 7, 85, 27630, 2, 2160, 17, 5515, 13254), + (13254, 1126, 1126, 1126, 1126, 7, 87, 27631, 2, 2160, 17, 13253, 13255), + (13255, 1126, 1126, 1126, 1126, 7, 89, 27632, 2, 2160, 17, 13254, 13723), + (13256, 146, 146, 146, 146, 8, 86, 27633, 2, 180, 17, 7691, 13257), + (13257, 146, 146, 146, 146, 8, 88, 27634, 2, 180, 17, 13256, 13258), + (13258, 146, 146, 146, 146, 8, 90, 27635, 2, 180, 17, 13257, 14222), + (13259, 1195, 1195, 1195, 1195, 9, 90, 27661, 13, 2160, 17, 10015, 15334), + (13260, 13260, 13260, 13260, 13260, 0, 80, 27664, 98, 3600, 17, -1, -1), + (13261, 13261, 13261, 13261, 13261, 0, 81, 27665, 98, 28800, 17, -1, -1), + (13262, -1, -1, 498, 498, 5, 70, -1, 0, 0, 16, 975, 13263), + (13263, -1, -1, 498, 498, 5, 75, -1, 0, 0, 16, 13262, 13264), + (13264, -1, -1, 498, 498, 5, 80, -1, 0, 0, 16, 13263, -1), + (13271, 13271, 13271, 13271, 13271, 0, 80, 27691, 97, 3600, 18, -1, -1), + (13272, 13272, 13272, 13272, 13272, 0, 81, 27692, 97, 28800, 18, -1, -1), + (13275, 6537, 6537, 6537, 6537, 10, 91, 30638, 30, 900, 18, 12522, 13276), + (13278, -1, -1, 6051, 6051, 10, 91, -1, 0, 0, 18, 12797, 13279), + (13281, -1, -1, 1072, 1072, 12, 91, -1, 0, 0, 18, 12541, 13282), + (13286, -1, -1, 119, 119, 12, 91, -1, 0, 0, 18, 12552, 13287), + (13291, 6539, 6539, 6539, 6539, 9, 91, 30641, 18, 1800, 18, 12944, 13292), + (13294, -1, -1, 1435, 4773, 12, 91, -1, 0, 0, 18, 13091, 14490), + (13295, -1, -1, 1435, 4773, 12, 91, -1, 0, 0, 18, 13090, 14491), + (13296, -1, -1, 77, 77, 12, 91, -1, 0, 0, 18, 12499, 13297), + (13297, -1, -1, 77, 77, 12, 93, -1, 0, 0, 18, 13296, 13298), + (13299, -1, -1, 1186, 1186, 12, 91, -1, 0, 0, 18, 12566, 13300), + (13302, -1, -1, 80, 80, 12, 91, -1, 0, 0, 18, 12569, 13303), + (13305, -1, -1, 683, 683, 10, 91, -1, 0, 0, 18, 12696, 13306), + (13308, -1, -1, 446, 735, 10, 91, -1, 0, 0, 18, 10477, 13309), + (13313, -1, -1, 658, 658, 8, 91, -1, 0, 0, 18, 12574, 13314), + (13318, -1, -1, 8210, 8210, 10, 91, -1, 0, 0, 18, 13153, 13319), + (13323, -1, -1, 1287, 1287, 12, 91, -1, 0, 0, 18, 10639, 13324), + (13326, -1, -1, 1044, 1044, 10, 91, -1, 0, 0, 18, 13076, 13327), + (13332, -1, -1, 1041, 1041, 11, 91, -1, 0, 0, 18, 12699, 13333), + (13338, -1, -1, 8245, 8245, 11, 91, -1, 0, 0, 18, 8426, 13339), + (13343, -1, -1, 8240, 8240, 11, 91, -1, 0, 0, 18, 10785, 13344), + (13348, -1, -1, 8250, 8250, 11, 91, -1, 0, 0, 18, 13050, 13349), + (13353, -1, -1, 8235, 8235, 11, 91, -1, 0, 0, 18, 8308, 13354), + (13358, -1, -1, 8255, 8255, 11, 91, -1, 0, 0, 18, 12415, 13359), + (13363, 1192, 1192, 1192, 1192, 9, 91, 30645, 12, 1320, 18, 10021, 13364), + (13383, 6488, 6488, 6488, 6488, 15, 91, 30657, 32, 900, 18, 6488, 13384), + (13385, 13385, 13385, 13385, 13385, 12, 91, 30659, 75, 600, 18, -1, 13386), + (13388, 13388, 13388, 13388, 13388, 12, 91, 30665, 79, 180, 18, -1, -1), + (13389, 13389, -1, 13389, 13389, 5, 91, 30666, 77, 12, 18, -1, 15832), + (13396, -1, -1, 13017, 13017, 15, 91, -1, 0, 0, 18, 13019, 13397), + (13401, 1498, 1498, 1498, 1498, 15, 91, 30679, 12, 1320, 18, 10092, 13402), + (13404, -1, -1, 1514, 1514, 11, 91, -1, 0, 0, 18, 1516, 13405), + (13410, 645, -1, 645, 645, 15, 95, 30682, 4, 5, 18, 10739, -1), + (13411, -1, -1, 12652, 12652, 15, 92, 0, 0, 0, 18, 12654, 13412), + (13413, -1, -1, 12416, 12416, 15, 91, -1, 0, 0, 18, 12418, 13414), + (13415, -1, -1, 7989, 7989, 9, 95, -1, 0, 0, 18, 7992, -1), + (13416, -1, -1, 13416, 13416, 9, 91, 0, 0, 0, 18, -1, 13417), + (13419, 13419, 13419, 13419, 13419, 12, 91, 30683, 99, 600, 18, -1, 13420), + (13425, 54006, 54006, 54006, 54006, 9, 91, 30692, 18, 180, 18, 10006, 13426), + (13438, -1, -1, 599, 599, 13, 91, -1, 0, 0, 18, 13028, 13439), + (13444, 13444, 13444, 13444, 13444, 9, 91, 30699, 75, 600, 18, -1, 13445), + (13447, 11073, 11073, 11073, 11073, 12, 95, 30705, 53, 30, 18, 11073, 15412), + (13449, -1, -1, 13449, 13449, 5, 91, -1, 0, 0, 18, -1, 13450), + (13454, 718, 718, 718, 718, 12, 91, 30711, 7, 4320, 18, 1019, 14855), + (13463, -1, -1, 13463, 13463, 7, 91, -1, 0, 0, 18, -1, 13464), + (13466, 6984, 6984, 6984, 6984, 9, 91, 30721, 60, 60, 18, 13177, 13469), + (13467, 6985, 6985, 6985, 6985, 9, 91, 30723, 60, 60, 18, 13179, 13470), + (13468, 6986, 6986, 6986, 6986, 12, 92, 30725, 60, 60, 18, 13178, 13471), + (13472, 11080, 11080, 11080, 11080, 11, 91, 30727, 10, 20, 18, 11080, 13473), + (13474, -1, -1, 13474, 13474, 9, 91, -1, 0, 0, 18, -1, 13475), + (13477, -1, -1, 10380, 10380, 11, 91, -1, 0, 0, 18, 10382, 13478), + (13483, 13483, 13483, 13483, 13483, 5, 91, 30735, 68, 20, 18, -1, -1), + (13484, 13484, -1, 13484, 13484, 12, 95, 30736, 76, 720, 18, -1, 15879), + (13485, -1, -1, 13485, 13485, 7, 91, -1, 0, 0, 18, -1, 13486), + (13490, 5020, 5020, 5020, 5020, 9, 91, 30742, 9, 300, 18, 10149, 13491), + (13492, 10330, 10330, 10330, 10330, 12, 95, 30744, 35, 30, 18, 13203, 14797), + (13493, 1598, -1, 1598, 1598, 11, 91, 30745, 6, 900, 18, 13195, 13494), + (13496, 1110, 1110, 1110, 1110, 9, 91, 30748, 3, 2160, 18, 13192, 13497), + (13499, 592, 592, 592, 592, 9, 91, 30754, 2, 18, 18, 12751, 13500), + (13502, -1, -1, 6375, 6375, 9, 91, -1, 0, 0, 18, 12736, 13503), + (13505, 6533, 6533, 6533, 6533, 11, 91, 30757, 15, 600, 18, 12742, 13506), + (13508, -1, -1, 8314, 8314, 9, 91, -1, 0, 0, 18, 8316, 13509), + (13511, -1, -1, 255, 255, 9, 91, -1, 0, 0, 18, 13198, 13512), + (13514, 5298, 5298, 5298, 5298, 12, 91, 30760, 32, 1800, 18, 12748, 13515), + (13517, 10336, 10336, 10336, 10336, 11, 91, 30766, 58, 8, 18, 12732, 13518), + (13520, -1, -1, 12419, 12419, 15, 95, -1, 0, 0, 18, 12575, 16886), + (13521, -1, -1, 6386, 6386, 9, 91, -1, 0, 0, 18, 6389, 13522), + (13524, 6534, 6534, 6534, 6534, 11, 91, 30769, 16, 900, 18, 7429, 13525), + (13527, 13527, 13527, 13527, 13527, 9, 91, 30772, 18, 9, 18, -1, 15964), + (13528, 13528, 13528, 13528, 13528, 10, 91, 30773, 42, 60, 18, -1, -1), + (13529, 13529, 13529, 13529, 13529, 15, 95, 30774, 41, 120, 18, -1, -1), + (13530, 1116, 1116, 1116, 1116, 12, 91, 30775, 4, 2160, 18, 12745, 13531), + (13533, -1, -1, 7010, 7010, 9, 91, -1, 0, 0, 18, 7015, 13534), + (13542, 6755, 6755, 6755, 6755, 12, 91, 30784, 42, 900, 18, 6757, 13543), + (13545, -1, -1, 10388, 10388, 12, 95, -1, 0, 0, 18, 10388, 15293), + (13546, 6758, 6758, 6758, 6758, 11, 91, 32360, 43, 900, 18, 10056, 13547), + (13549, 13549, 13549, 13549, 13549, 15, 95, 30788, 64, 180, 18, -1, -1), + (13556, 13556, 13556, 13556, 13556, 9, 91, 30792, 44, 600, 18, -1, 13557), + (13562, -1, -1, 10719, 10719, 15, 91, 0, 0, 0, 18, 10721, 13563), + (13565, -1, -1, 13565, 13565, 11, 91, 0, 0, 0, 18, -1, 13566), + (13568, -1, -1, 13568, 13568, 11, 91, 0, 0, 0, 18, -1, 13569), + (13571, 13571, 13571, 13571, 13571, 12, 91, 30795, 50, 60, 18, -1, -1), + (13575, 5095, 5095, 5095, 5095, 11, 91, 30796, 10, 900, 18, 10642, 13576), + (13578, 0, 0, 10348, 10348, 9, 91, -1, 0, 0, 18, 10350, 13579), + (13584, 10394, 10394, 10394, 10394, 15, 91, 30799, 30, 300, 18, 10704, 14981), + (13585, 7712, 7712, 7712, 7712, 15, 95, 30800, 2, 30, 18, 10646, 15095), + (13586, 188, 188, 188, 188, 12, 91, 30801, 2, 30, 18, 10647, 13587), + (13589, -1, -1, 255, 255, 13, 91, -1, 0, 0, 18, 10625, 13590), + (13590, -1, -1, 255, 255, 15, 93, -1, 0, 0, 18, 13589, 13591), + (13592, 5984, 5984, 5984, 5984, 12, 91, 30803, 2, 30, 18, 10626, 13593), + (13595, 534, 534, 534, 534, 12, 91, 30806, 4, 2160, 18, 10710, 13596), + (13598, -1, -1, 6791, 6791, 11, 91, -1, 0, 0, 18, 10678, 13599), + (13601, -1, -1, 852, 852, 11, 91, -1, 0, 0, 18, 12578, 13602), + (13604, 7850, 7850, 7850, 7850, 15, 91, 30812, 39, 4320, 18, 10620, 13605), + (13607, -1, -1, 10453, 10453, 11, 91, -1, 0, 0, 18, 10455, 13608), + (13610, -1, -1, 602, 602, 12, 91, -1, 0, 0, 18, 10687, 13611), + (13613, -1, -1, 855, 855, 11, 91, -1, 0, 0, 18, 10692, 13614), + (13616, -1, -1, 13616, 13616, 7, 91, -1, 0, 0, 18, -1, 13617), + (13617, -1, -1, 13616, 13616, 9, 93, -1, 0, 0, 18, 13616, 13618), + (13618, -1, -1, 13616, 13616, 12, 95, -1, 0, 0, 18, 13617, 14786), + (13619, 7800, 7800, 7800, 7800, 15, 91, 30815, 39, 4320, 18, 10787, 13620), + (13621, -1, -1, 6630, 6630, 9, 91, -1, 0, 0, 18, 10074, 13622), + (13624, 10900, 10900, 10900, 10900, 9, 91, 30817, 55, 120, 18, 10902, 13625), + (13627, -1, -1, 895, 895, 9, 91, -1, 0, 0, 18, 10908, 13628), + (13628, -1, -1, 895, 895, 12, 93, -1, 0, 0, 18, 13627, 13629), + (13630, -1, -1, 9506, 9506, 11, 91, -1, 0, 0, 18, 9508, 13631), + (13633, 6645, 6645, 6645, 6645, 15, 95, 30820, 45, 60, 18, 13107, 15178), + (13646, 13646, 13646, 13646, 13646, 15, 91, 30837, 45, 600, 18, -1, -1), + (13650, 8060, 8060, 8060, 8060, 9, 91, 31524, 41, 1800, 18, 10239, 13651), + (13653, 8063, 8063, 8063, 8063, 9, 91, 31527, 41, 1800, 18, 10242, 13654), + (13656, 8066, 8066, 8066, 8066, 11, 91, 31530, 41, 1800, 18, 10245, 13657), + (13663, 12893, 12893, 12893, 12893, 15, 91, 31534, 76, 1800, 18, 12893, 13664), + (13667, -1, -1, 13667, 13667, 11, 91, -1, 0, 0, 18, -1, 13668), + (13670, 13670, 13670, 13670, 13670, 12, 91, 31538, 43, 1800, 18, -1, 13671), + (13673, 13673, 13673, 13673, 13673, 18, 95, 32050, 0, 1, 18, -1, -1), + (13674, 13674, 13674, 13674, 13674, 18, 95, 32058, 0, 1, 18, -1, -1), + (13675, -1, -1, 5264, 5264, 12, 91, -1, 0, 0, 18, 12800, 13676), + (13678, 13678, 13678, 13678, 13678, 15, 95, 31543, 74, 1200, 18, 12778, -1), + (13682, 12766, 12766, 12766, 12766, 18, 95, 31545, 69, 3600, 18, 12766, -1), + (13683, 6822, 6822, 6822, 6822, 15, 91, 31546, 42, 120, 18, 6822, 14780), + (13684, -1, -1, 13684, 13684, 9, 91, -1, 0, 0, 18, -1, 13685), + (13685, -1, -1, 13684, 13684, 12, 93, -1, 0, 0, 18, 13684, 13686), + (13686, -1, -1, 13684, 13684, 15, 95, -1, 0, 0, 18, 13685, 16653), + (13687, 13687, 13687, 13687, 13687, 15, 91, 31547, 75, 300, 18, -1, 17521), + (13688, 13225, 13225, 13225, 13225, 12, 91, 31548, 0, 4, 18, 13225, 15620), + (13689, -1, -1, 13689, 13689, 9, 91, -1, 0, 0, 18, -1, 13690), + (13692, 12208, 12208, 12208, 12208, 6, 91, 31549, 17, 12, 18, -1, -1), + (13693, 13693, 13693, 13693, 13693, 18, 95, 31550, 76, 500, 18, -1, 17531), + (13695, 13695, 13695, 13695, 13695, 12, 91, 31577, 91, 1320, 18, -1, 13696), + (13698, 4903, 4903, 4903, 4903, 12, 91, 31580, 9, 1320, 18, 12956, 13699), + (13701, 4906, 4906, 4906, 4906, 12, 91, 31583, 9, 1320, 18, 12959, 13702), + (13704, 4912, 4912, 4912, 4912, 12, 91, 31586, 16, 1320, 18, 12958, 13705), + (13707, -1, -1, 1577, 1577, 12, 91, -1, 0, 0, 18, 10264, 13708), + (13710, -1, -1, 795, 795, 9, 91, -1, 0, 0, 18, 12949, 13711), + (13713, -1, -1, 790, 790, 6, 91, -1, 0, 0, 18, 12954, 13714), + (13718, 167, 167, 167, 167, 12, 91, 31589, 14, 900, 18, 12955, 13719), + (13720, 10600, 10600, 10600, 10600, 11, 91, 31591, 73, 20, 18, 12984, 13721), + (13723, 1126, 1126, 1126, 1126, 11, 91, 31594, 2, 2160, 18, 13255, 13724), + (13726, 1017, 1017, 1017, 1017, 12, 91, 31597, 75, 15, 18, 1017, -1), + (13727, 4938, 4938, 4938, 4938, 12, 95, 31598, 35, 1800, 18, 12875, 16031), + (13734, 773, -1, 773, 773, 9, 91, 31606, 5, 1800, 18, 10566, 13735), + (13753, -1, -1, 13753, 13753, 5, 91, -1, 0, 0, 18, -1, 13754), + (13758, -1, -1, 13758, 13758, 5, 91, -1, 0, 0, 18, -1, 13759), + (13763, -1, -1, 781, 781, 12, 95, -1, 0, 0, 18, 7284, -1), + (13764, -1, -1, 13764, 13764, 9, 91, -1, 0, 0, 18, -1, 13765), + (13767, -1, -1, 1604, 1604, 12, 91, -1, 0, 0, 18, 13095, 13768), + (13770, 6328, 6328, 6328, 6328, 9, 91, 31628, 10, 600, 18, 10170, 13771), + (13771, 6328, 6328, 6328, 6328, 12, 93, 31629, 10, 600, 18, 13770, 13772), + (13773, -1, -1, 255, 255, 11, 91, -1, 0, 0, 18, 12610, 13774), + (13774, -1, -1, 255, 255, 13, 92, -1, 0, 0, 18, 13773, 13775), + (13775, -1, -1, 255, 255, 15, 93, -1, 0, 0, 18, 13774, 14126), + (13779, -1, -1, 10850, 10850, 12, 91, 31637, 0, 0, 18, 13209, 13780), + (13782, -1, -1, 1543, 1543, 9, 91, -1, 0, 0, 18, 13217, 13783), + (13785, 5021, 5021, 5021, 5021, 11, 91, 31640, 7, 60, 18, 12621, 13786), + (13788, 13788, 13788, 13788, 13788, 25, 51, 31643, 31, 2, 3, -1, -1), + (13789, -1, -1, 1304, 1304, 11, 91, -1, 0, 0, 18, 13218, 13790), + (13790, -1, -1, 1304, 1304, 13, 93, -1, 0, 0, 18, 13789, 13791), + (13792, 13792, 13792, 13792, 13792, 9, 91, 31644, 18, 600, 18, 12633, 13793), + (13795, -1, -1, 846, 846, 12, 91, -1, 0, 0, 18, 10175, 13796), + (13798, -1, -1, 8325, 8325, 9, 91, -1, 0, 0, 18, 13221, 13799), + (13804, -1, -1, 10650, 10650, 9, 91, -1, 0, 0, 18, 10652, 13805), + (13807, 1352, 1352, 1352, 1352, 9, 91, 31647, 3, 60, 18, 10115, 13808), + (13810, 1358, 1358, 1358, 1358, 9, 91, 31650, 3, 60, 18, 10118, 13811), + (13813, -1, -1, 12706, 12706, 12, 91, 0, 0, 0, 18, 12708, 13814), + (13816, 7875, 7875, 7875, 7875, 9, 91, 31653, 42, 600, 18, 7880, 13817), + (13819, 10346, 10346, 10346, 10346, 12, 95, 31659, 46, 600, 18, 13183, 16924), + (13820, -1, -1, 820, 820, 9, 91, -1, 0, 0, 18, 12669, 13821), + (13823, -1, -1, 6020, 6020, 9, 91, -1, 0, 0, 18, 12693, 13824), + (13826, -1, -1, 9512, 9512, 9, 91, -1, 0, 0, 18, 13189, 13827), + (13829, -1, -1, 10340, 10340, 12, 91, -1, 0, 0, 18, 13186, 13830), + (13832, 1355, 1355, 1355, 1355, 11, 91, 31661, 3, 60, 18, 12702, 13833), + (13835, -1, -1, 611, 611, 9, 91, -1, 0, 0, 18, 12705, 13836), + (13838, 7872, 7872, 7872, 7872, 9, 91, 31664, 41, 600, 18, 12684, 13839), + (13841, -1, -1, 10343, 10343, 9, 91, 0, 0, 0, 18, 10345, 13842), + (13845, 1178, 1178, 1178, 1178, 9, 91, 31669, 4, 900, 18, 10328, 13846), + (13872, 13872, 13872, 13872, 13872, 15, 95, 31694, 63, 60, 18, -1, 16002), + (13873, -1, -1, 13873, 13873, 7, 91, 0, 0, 0, 18, -1, 13874), + (13878, -1, -1, 13878, 13878, 9, 91, 0, 0, 0, 18, -1, 13879), + (13881, -1, -1, 13881, 13881, 9, 91, 0, 0, 0, 18, -1, 13882), + (13884, -1, -1, 735, 735, 10, 91, -1, 0, 0, 18, 10636, 13885), + (13889, -1, -1, 13889, 13889, 5, 91, 0, 0, 0, 18, -1, 13890), + (13894, -1, -1, 1021, 1021, 6, 91, -1, 0, 0, 18, 7685, 13895), + (13899, 6750, 6750, 6750, 6750, 15, 95, 32100, 60, 120, 18, 6750, 15294), + (13905, -1, -1, 13905, 13905, 10, 91, -1, 0, 0, 18, -1, 13906), + (13908, -1, -1, 13908, 13908, 10, 91, -1, 0, 0, 18, -1, 13909), + (13911, -1, -1, 13911, 13911, 12, 91, -1, 0, 0, 18, -1, 13912), + (13914, 4849, 4849, 4849, 4849, 12, 91, 32103, 7, 1800, 18, 7110, 13915), + (13917, -1, -1, 13917, 13917, 9, 91, -1, 0, 0, 18, -1, 13918), + (13920, 6333, 6333, 6333, 6333, 15, 91, 32140, 3, 600, 18, 7266, 16032), + (13921, -1, -1, 98, 98, 12, 91, -1, 0, 0, 18, 11063, 13922), + (13924, -1, -1, 98, 738, 12, 91, -1, 0, 0, 18, 7600, 13925), + (13927, -1, -1, 10370, 10370, 10, 91, -1, 0, 0, 18, 10372, 13928), + (13930, -1, -1, 1592, 1592, 12, 91, -1, 0, 0, 18, 12536, 13931), + (13933, -1, -1, 8263, 8263, 5, 91, -1, 0, 0, 18, 8360, 13934), + (13943, -1, -1, 8268, 8268, 5, 91, -1, 0, 0, 18, 8370, 13944), + (13953, -1, -1, 8273, 8273, 5, 91, -1, 0, 0, 18, 8380, 13954), + (13963, -1, -1, 8278, 8278, 5, 91, -1, 0, 0, 18, 8390, 13964), + (13973, -1, -1, 8283, 8283, 5, 91, -1, 0, 0, 18, 8400, 13974), + (13983, -1, -1, 8288, 8288, 5, 91, -1, 0, 0, 18, 8410, 13984), + (13993, -1, -1, 8293, 8293, 5, 91, -1, 0, 0, 18, 8420, 13994), + (14003, 6492, 6492, 6492, 6492, 12, 91, 32151, 52, 720, 18, 10681, 14004), + (14006, 10711, 10711, 10711, 10711, 15, 91, 32157, 75, 1200, 18, 10713, 14007), + (14009, 13202, 13202, 13202, 13202, 6, 91, 32160, 98, 20, 18, 13202, -1), + (14010, 14010, 14010, 14010, 14010, 15, 95, 32161, 97, 20, 18, -1, -1), + (14011, -1, -1, 14011, 14011, 5, 91, -1, 0, 0, 18, -1, 14012), + (14016, 10354, 10354, 10354, 10354, 15, 95, 32162, 39, 4320, 18, 10354, 14647), + (14017, -1, -1, 14017, 14017, 0, 90, -1, 0, 0, 18, -1, -1), + (14018, -1, -1, 14018, 14018, 0, 91, -1, 0, 0, 18, -1, -1), + (14019, 14019, 14019, 14019, 14019, 12, 91, 32177, 14, 900, 18, -1, 14020), + (14026, -1, -1, 14026, 14026, 12, 91, -1, 0, 0, 18, -1, 14027), + (14029, -1, -1, 14029, 14029, 12, 91, -1, 0, 0, 18, -1, 14030), + (14032, -1, -1, 14032, 14032, 15, 95, -1, 0, 0, 18, -1, -1), + (14037, -1, -1, 14037, 14037, 9, 91, 0, 0, 0, 18, -1, 14038), + (14040, -1, -1, 14040, 14040, 9, 91, 0, 0, 0, 18, -1, 14041), + (14043, -1, -1, 1313, 1313, 12, 91, -1, 0, 0, 18, 12581, 14044), + (14046, -1, -1, 14046, 14046, 5, 91, -1, 0, 0, 18, -1, 14047), + (14051, 14051, 14051, 14051, 14051, 12, 95, 32300, 62, 8, 18, -1, 15774), + (14052, 14052, 14052, 14052, 14052, 21, 95, 32301, 13, 1440, 18, -1, 14793), + (14053, 10912, 10912, 10912, 10912, 9, 91, 32303, 69, 1800, 18, 10914, 14054), + (14054, 10912, 10912, 10912, 10912, 12, 93, 32304, 69, 1800, 18, 14053, 14055), + (14055, 10912, 10912, 10912, 10912, 15, 95, 32305, 69, 1800, 18, 14054, -1), + (14056, -1, -1, 14056, 14056, 9, 91, -1, 0, 0, 18, -1, 14057), + (14059, -1, -1, 14059, 14059, 9, 91, -1, 0, 0, 18, -1, 14060), + (14062, -1, -1, 14062, 14062, 9, 91, -1, 0, 0, 18, -1, 14063), + (14065, -1, -1, 14065, 14065, 9, 91, 0, 0, 0, 18, -1, 14066), + (14068, -1, -1, 14068, 14068, 9, 91, 0, 0, 0, 18, -1, 14069), + (14071, 14071, 14071, 14071, 14071, 9, 91, 32307, 12, 600, 18, -1, 14072), + (14076, -1, -1, 14076, 14076, 9, 91, -1, 0, 0, 18, -1, 14077), + (14080, 14080, 14080, 14080, 14080, 9, 95, 32312, 13, 900, 18, -1, -1), + (14081, 14081, 14081, 14081, 14081, 9, 95, 32313, 14, 120, 18, -1, 17240), + (14082, -1, -1, 13101, 13101, 9, 91, 0, 0, 0, 18, 13103, 14083), + (14085, -1, -1, 14085, 14085, 9, 91, -1, 0, 0, 18, -1, 14086), + (14088, -1, -1, 14088, 14088, 9, 91, -1, 0, 0, 18, -1, 14089), + (14091, -1, -1, 14091, 14091, 9, 91, -1, 0, 0, 18, -1, 14092), + (14094, -1, -1, 10355, 10355, 9, 91, -1, 0, 0, 18, 10645, 14095), + (14097, -1, -1, 6395, 6395, 12, 91, -1, 0, 0, 18, 10707, 14098), + (14100, -1, -1, 14100, 14100, 15, 95, -1, 0, 0, 18, -1, -1), + (14101, -1, -1, 6355, 6355, 9, 91, -1, 0, 0, 18, 6360, 14263), + (14111, 6754, 6754, 6754, 6754, 12, 95, 32326, 41, 1200, 18, 10053, 14839), + (14112, 6370, 6370, 6370, 6370, 9, 91, 32329, 7, 600, 18, 7352, 14113), + (14115, -1, -1, 14115, 14115, 12, 91, -1, 0, 0, 18, -1, 14116), + (14129, -1, -1, 14129, 14129, 12, 91, -1, 0, 0, 18, -1, 14130), + (14130, -1, -1, 14129, 14129, 15, 93, -1, 0, 0, 18, 14129, 14131), + (14132, -1, -1, 7751, 7751, 7, 91, -1, 0, 0, 18, 7753, 14133), + (14135, -1, -1, 14135, 14135, 12, 91, -1, 0, 0, 18, -1, 14136), + (14138, -1, -1, 12615, 12615, 18, 95, -1, 0, 0, 18, 12617, 15499), + (14139, 14139, 14139, 14139, 14139, 15, 95, 32328, 60, 60, 18, -1, -1), + (14140, -1, -1, 12607, 12607, 15, 95, 0, 0, 0, 18, 12607, 15631), + (14141, -1, -1, 14141, 14141, 9, 91, -1, 0, 0, 18, -1, 14142), + (14144, -1, -1, 14144, 14144, 7, 91, -1, 0, 0, 18, -1, 14145), + (14148, -1, -1, 14148, 14148, 9, 91, 0, 0, 0, 18, -1, 14149), + (14151, -1, -1, 14151, 14151, 9, 91, 0, 0, 0, 18, -1, 14152), + (14154, -1, -1, 10657, 10657, 12, 91, 0, 0, 0, 18, 12681, 14155), + (14157, -1, -1, 14157, 14157, 9, 91, 0, 0, 0, 18, -1, 14158), + (14160, -1, -1, 14160, 14160, 9, 91, 0, 0, 0, 18, -1, 14161), + (14163, -1, -1, 14163, 14163, 9, 91, 0, 0, 0, 18, -1, 14164), + (14166, -1, -1, 14166, 14166, 9, 91, 0, 0, 0, 18, -1, 14167), + (14169, -1, -1, 14169, 14169, 7, 91, -1, 0, 0, 18, -1, 14170), + (14173, -1, -1, 12710, 12710, 9, 91, -1, 0, 0, 18, 12712, 14174), + (14176, -1, -1, 13204, 13204, 9, 91, -1, 0, 0, 18, 13206, 14177), + (14179, -1, -1, 14179, 14179, 9, 95, -1, 0, 0, 18, -1, -1), + (14180, -1, -1, 14180, 14180, 9, 95, -1, 0, 0, 18, -1, -1), + (14181, -1, -1, 14181, 14181, 9, 91, -1, 0, 0, 18, -1, 14182), + (14186, -1, -1, 14186, 14186, 9, 91, -1, 0, 0, 18, -1, 14187), + (14189, 5017, 5017, 5017, 5017, 9, 91, 32332, 8, 600, 18, 10158, 14190), + (14192, 14192, 14192, 14192, 14192, 15, 95, 32335, 36, 12, 18, -1, 15525), + (14196, -1, -1, 6935, 6935, 9, 91, -1, 0, 0, 18, 6904, 14197), + (14199, -1, -1, 6908, 6908, 12, 95, -1, 0, 0, 18, 6910, 15560), + (14200, -1, -1, 14200, 14200, 9, 91, 32336, 0, 0, 18, -1, 14201), + (14203, -1, -1, 14203, 14203, 12, 91, -1, 0, 0, 18, -1, 14204), + (14206, 14206, 14206, 14206, 14206, 12, 95, 32339, 41, 600, 18, -1, 15324), + (14207, 14207, 14207, 14207, 14207, 12, 95, 32340, 39, 180, 18, -1, -1), + (14208, 14208, 14208, 14208, 14208, 12, 95, 32341, 17, 180, 18, -1, 14568), + (14209, 14209, 14209, 14209, 14209, 12, 95, 32342, 22, 3, 18, -1, -1), + (14210, -1, -1, 10358, 10358, 12, 91, -1, 0, 0, 18, 10360, 14211), + (14213, -1, -1, 14213, 14213, 11, 91, -1, 0, 0, 18, -1, 14214), + (14218, -1, -1, 962, 962, 9, 91, -1, 0, 0, 18, 10363, 14219), + (14221, 1383, 1383, 1383, 1383, 18, 95, 32345, 6, 300, 18, 6487, 14581), + (14222, 146, 146, 146, 146, 15, 95, 32346, 2, 180, 18, 13258, 14977), + (14223, -1, -1, 13010, 13010, 12, 95, 0, 0, 0, 18, 13012, 16205), + (14224, 14224, -1, 14224, 14224, 9, 91, 345, 61, 5, 18, -1, 15860), + (14225, -1, -1, 14225, 14225, 9, 91, -1, 0, 0, 18, -1, 14226), + (14229, 14229, 14229, 14229, 14229, 12, 100, 37168, 42, 600, 19, -1, -1), + (14231, 14231, 14231, 14231, 14231, 12, 95, 32347, 91, 6, 18, -1, 16207), + (14232, 14232, -1, 14232, 14232, 12, 95, 32348, 92, 6, 18, -1, 14674), + (14233, 14233, 14233, 14233, 14233, 15, 95, 32349, 93, 30, 18, -1, 15621), + (14234, 14234, 14234, 14234, 14234, 9, 91, 32350, 94, 1800, 18, -1, 14235), + (14237, 12638, 12638, 12638, 12638, 9, 91, 23581, 68, 10, 18, -1, -1), + (14238, -1, -1, 12968, 12968, 9, 91, 0, 0, 0, 18, 12970, 14239), + (14241, -1, -1, 14241, 14241, 9, 91, -1, 0, 0, 18, -1, 14242), + (14244, -1, -1, 14244, 14244, 9, 91, -1, 0, 0, 18, -1, 14245), + (14249, -1, -1, 14249, 14249, 9, 91, -1, 0, 0, 18, -1, 14250), + (14254, -1, -1, 14254, 14254, 11, 91, -1, 0, 0, 18, -1, 14255), + (14256, 6561, 6561, 6561, 6561, 9, 91, 32353, 32, 30, 18, 10420, 14257), + (14259, -1, -1, 14259, 14259, 11, 91, -1, 0, 0, 18, -1, 14260), + (14262, 14262, 14262, 14262, 14262, 15, 95, 32357, 95, 180, 18, -1, -1), + (14264, 14264, 14264, 14264, 14264, 12, 95, 32358, 97, 120, 18, -1, 14600), + (14265, 14265, 14265, 14265, 14265, 15, 95, 32359, 68, 30, 18, -1, -1), + (14272, 6218, 6218, 6218, 14272, 12, 95, 32369, 0, 1, 18, 7488, 17381), + (14273, 723, 723, 723, 723, 12, 95, 32370, 6, 30, 18, 10300, 14869), + (14274, 6971, 6971, 6971, 6971, 9, 91, 32371, 41, 600, 18, 10290, 17383), + (14275, -1, -1, 14275, 14275, 7, 91, -1, 0, 0, 18, -1, 14276), + (14278, -1, -1, 14278, 14278, 12, 95, 0, 0, 0, 18, 6990, 16248), + (14279, -1, -1, 1287, 1287, 11, 95, -1, 0, 0, 18, 12815, 16529), + (14280, 4890, -1, 4890, 4890, 12, 95, 32373, 3, 8640, 18, 5872, 14776), + (14281, 14281, 14281, 14281, 14281, 12, 95, 32375, 39, 15, 18, -1, -1), + (14282, 14282, 14282, 14282, 14282, 9, 91, 32374, 39, 7, 18, -1, -1), + (14283, -1, -1, 14283, 14283, 7, 91, -1, 0, 0, 18, -1, 14284), + (14286, -1, -1, 14286, 14286, 9, 91, -1, 0, 0, 18, -1, 14287), + (14289, -1, -1, 14289, 14289, 9, 91, -1, 0, 0, 18, -1, 14290), + (14292, -1, -1, 14292, 14292, 9, 91, -1, 0, 0, 18, -1, 14293), + (14295, -1, -1, 14295, 14295, 9, 95, -1, 0, 0, 18, -1, 14296), + (14301, -1, -1, 14301, 14301, 9, 91, -1, 0, 0, 18, -1, 14302), + (14304, -1, -1, 14304, 14304, 9, 91, -1, 0, 0, 18, -1, 14305), + (14307, 14307, 14307, 14307, 14307, 12, 95, 32376, 92, 1200, 18, -1, 14743), + (14308, -1, -1, 14308, 14308, 9, 91, -1, 0, 0, 18, -1, 14309), + (14311, -1, -1, 14311, 14311, 9, 91, -1, 0, 0, 18, -1, 14312), + (14314, -1, -1, 7715, 7715, 7, 91, -1, 0, 0, 18, 7717, 14315), + (14318, -1, -1, 14318, 14318, 9, 91, -1, 0, 0, 18, -1, 14319), + (14321, 14321, 14321, 14321, 14321, 12, 95, 32378, 92, 8, 18, -1, 14781), + (14322, 14322, 14322, 14322, 14322, 12, 95, 32379, 94, 2160, 18, -1, 14782), + (14323, 14323, 14323, 14323, 14323, 12, 95, 32380, 92, 150, 18, -1, -1), + (14324, 155, 155, 155, 155, 15, 95, 32381, 8, 60, 18, 7238, 15610), + (14328, -1, -1, 7822, 7822, 7, 91, -1, 0, 0, 18, 7826, 14329), + (14331, -1, -1, 14331, 14331, 9, 91, -1, 0, 0, 18, -1, 14332), + (14338, 1337, 1337, 1337, 1337, 12, 91, 32382, 13, 4320, 18, 6160, 14339), + (14341, -1, -1, 14341, 14341, 5, 91, -1, 0, 0, 18, -1, 14342), + (14346, 14346, 14346, 14346, 14346, 9, 91, 32385, 94, 12, 18, -1, 14347), + (14349, -1, -1, 1210, 1213, 12, 91, -1, 0, 0, 18, 12528, 14350), + (14352, 1274, 1274, 1274, 1274, 12, 91, 32391, 9, 540, 18, 12762, 14353), + (14355, 6815, 6815, 6815, 6815, 9, 91, 32394, 60, 600, 18, 12788, 14356), + (14358, 14358, -1, 14358, 14358, 15, 95, 32397, 98, 300, 18, -1, -1), + (14359, 14359, 14359, 14359, 14359, 15, 95, 32399, 93, 1200, 18, -1, -1), + (14360, 14360, 14360, 14360, 14360, 15, 95, 32400, 95, 1800, 18, -1, 16334), + (14361, -1, -1, 637, 637, 12, 91, -1, 0, 0, 18, 12555, 14362), + (14364, -1, -1, 14364, 14364, 9, 91, -1, 0, 0, 18, -1, 14365), + (14367, -1, -1, 14367, 14367, 0, 1, -1, 0, 0, 0, -1, 14368), + (14371, 14371, 14371, 14371, 14371, 0, 1, 32910, 0, 10, 0, -1, -1), + (14372, 13844, 13844, 13844, 13844, 6, 95, 31667, 47, 6, 18, -1, -1), + (14373, 14373, 14373, 14373, 14373, 0, 85, 33106, 87, 3600, 19, -1, -1), + (14374, 14374, 14374, 14374, 14374, 0, 86, 33107, 88, 28800, 19, -1, -1), + (14690, 14690, 14690, 14690, 14690, 15, 96, 37014, 45, 600, 19, -1, 17479), + (14729, 8342, 8342, 8342, 8342, 15, 100, 33909, 54, 240, 19, 8342, 17501), + (14730, 616, 616, 616, 616, 12, 96, 33910, 7, 900, 19, 10261, 14731), + (14733, 4909, 4909, 4909, 4909, 18, 100, 33913, 16, 1320, 19, 12957, 17147), + (14734, 7903, 7903, 7903, 7903, 12, 100, 33914, 60, 30, 19, 12976, 15853), + (14739, 1462, 1462, 1462, 1462, 18, 99, 33919, 5, 300, 19, 4902, 16054), + (14764, -1, -1, 10551, 10551, 12, 96, -1, 0, 0, 19, 10553, 14765), + (14991, 926, 926, 926, 926, 5, 85, 11071, 12, 1800, 17, 930, 14992), + (14992, 926, 926, 926, 926, 5, 86, 11072, 12, 1800, 17, 14991, 14993), + (15073, 15073, -1, 15073, 15073, 0, 1, 37668, 90, 60, 19, -1, -1), + (15074, -1, -1, 15074, 15074, 0, 1, -1, 0, 0, 19, -1, 15075), + (15096, 15096, 15096, 15096, 15096, 5, 96, 38151, 35, 30, 19, -1, 15097), + (15099, 15099, 15099, 15099, 15099, 12, 100, 37187, 15, 45, 19, -1, 16566), + (15100, -1, -1, 15100, 15100, 5, 96, -1, 0, 0, 19, -1, 15101), + (15105, -1, -1, 15105, 15105, 11, 96, -1, 0, 0, 19, -1, 15106), + (15108, -1, -1, 15108, 15108, 9, 98, -1, 0, 0, 19, -1, 15109), + (15111, 8300, 8300, 8300, 8300, 11, 97, 37189, 8, 900, 19, 8302, 15112), + (15113, -1, -1, 15113, 15113, 11, 96, -1, 0, 0, 19, -1, 15114), + (15119, 15119, 15119, 15119, 15119, 12, 100, 37194, 16, 1200, 19, -1, 15749), + (15120, -1, -1, 15120, 15120, 9, 96, -1, 0, 0, 19, -1, 15121), + (15123, -1, -1, 15123, 15123, 9, 96, -1, 0, 0, 19, -1, 15124), + (15126, -1, -1, 15126, 15126, 9, 96, -1, 0, 0, 19, -1, 15127), + (15129, 15129, 15129, 15129, 15129, 12, 100, 37196, 32, 180, 19, -1, 15736), + (15130, 15130, 15130, 15130, 15130, 12, 100, 37197, 32, 180, 19, -1, 15737), + (15131, 15131, 15131, 15131, 15131, 12, 100, 37198, 32, 180, 19, -1, 15738), + (15132, -1, -1, 15132, 15132, 9, 96, -1, 0, 0, 19, -1, 15133), + (15135, -1, -1, 15135, 15135, 9, 100, -1, 0, 0, 19, -1, -1), + (15136, 15136, 15136, 15136, 15136, 9, 96, 38001, 5, 120, 19, -1, 17241), + (15140, 13100, 13100, 13100, 13100, 11, 100, 38002, 86, 300, 19, 13100, -1), + (15141, -1, -1, 190, 190, 9, 96, -1, 0, 0, 19, 5040, 15142), + (15146, 15146, 15146, 15146, 15146, 13, 100, 38006, 95, 9, 19, -1, 15758), + (15147, 15147, 15147, 15147, 15147, 11, 96, 38007, 8, 1200, 19, -1, 15148), + (15150, -1, -1, 15150, 15150, 7, 96, -1, 0, 0, 19, -1, 15151), + (15153, -1, -1, 15153, 15153, 11, 100, -1, 0, 0, 19, -1, -1), + (15154, -1, -1, 15154, 15154, 9, 96, -1, 0, 0, 19, -1, -1), + (15155, -1, -1, 15155, 15155, 5, 96, -1, 0, 0, 19, -1, 15156), + (15158, -1, -1, 15158, 15158, 13, 100, -1, 0, 0, 19, -1, -1), + (15159, -1, -1, 15159, 15159, 7, 96, -1, 0, 0, 19, -1, 15160), + (15162, -1, -1, 15162, 15162, 7, 96, -1, 0, 0, 19, -1, 15163), + (15168, -1, -1, 15168, 15168, 9, 96, -1, 0, 0, 19, -1, 15169), + (15172, -1, -1, 210, 210, 12, 100, -1, 0, 0, 19, 7401, 16658), + (15173, 6639, 6639, 6639, 6639, 9, 100, 38012, 42, 300, 19, 6639, 15788), + (15174, -1, -1, 12582, 12582, 9, 96, -1, 0, 0, 19, 12584, 15175), + (15177, 15177, 15177, 15177, 15177, 9, 100, 38013, 94, 180, 19, -1, -1), + (15179, -1, -1, 15179, 15179, 7, 96, -1, 0, 0, 19, -1, 15180), + (15182, -1, -1, 7757, 7757, 5, 96, -1, 0, 0, 19, 12589, 15183), + (15188, -1, -1, 1528, 4819, 5, 96, -1, 0, 0, 19, 4823, 15189), + (15193, 15193, 15193, 15193, 15193, 15, 100, 38016, 92, 600, 19, -1, -1), + (15194, -1, -1, 15194, 15194, 9, 100, -1, 0, 0, 19, -1, -1), + (15200, 15200, 15200, 15200, 15200, 9, 96, 38304, 32, 1080, 19, -1, 15201), + (15203, 15203, 15203, 15203, 15203, 15, 100, 38307, 34, 480, 19, -1, -1), + (15204, -1, -1, 15204, 15204, 9, 96, -1, 0, 0, 19, -1, 15205), + (15207, -1, -1, 15207, 15207, 9, 96, -1, 0, 0, 19, -1, 15208), + (15210, 15210, 15210, 15210, 15210, 9, 96, 38308, 12, 120, 19, -1, 15211), + (15213, 15213, 15213, 15213, 15213, 15, 100, 38312, 42, 1080, 19, -1, 17509), + (15214, 15214, 15214, 15214, 15214, 9, 96, 38313, 43, 1800, 19, -1, 15215), + (15217, -1, -1, 15217, 15217, 11, 96, -1, 0, 0, 19, -1, 15218), + (15220, -1, -1, 15220, 15220, 9, 100, -1, 0, 0, 19, -1, 15221), + (15223, -1, -1, 15223, 15223, 9, 100, -1, 0, 0, 19, -1, 15224), + (15226, -1, -1, 15226, 15226, 9, 100, -1, 0, 0, 19, -1, 15227), + (15229, -1, -1, 15229, 15229, 9, 100, -1, 0, 0, 19, -1, 15230), + (15232, -1, -1, 15232, 15232, 9, 96, -1, 0, 0, 19, -1, 15233), + (15235, 785, 785, 785, 785, 9, 96, 38325, 8, 900, 19, 789, 15236), + (15238, -1, -1, 5276, 5276, 11, 96, -1, 0, 0, 19, 5278, 15239), + (15241, 168, 168, 168, 168, 11, 96, 38329, 4, 10, 19, 170, 15242), + (15244, 171, 171, 171, 171, 11, 96, 38333, 4, 10, 19, 173, 15245), + (15247, 174, 174, 174, 174, 11, 96, 38336, 4, 10, 19, 176, 15248), + (15250, 177, 177, 177, 177, 11, 96, 38340, 4, 10, 19, 179, 15251), + (15253, -1, -1, 15253, 15253, 4, 96, -1, 0, 0, 19, -1, 15254), + (15258, -1, -1, 7743, 7743, 11, 100, -1, 0, 0, 19, 10718, -1), + (15270, -1, -1, 12430, 12430, 15, 100, -1, 0, 0, 19, 12878, -1), + (15280, -1, -1, 10722, 10722, 9, 96, -1, 0, 0, 19, 10726, 15281), + (15283, -1, -1, 15283, 15283, 5, 96, -1, 0, 0, 19, -1, 15284), + (15288, -1, -1, 15288, 15288, 7, 96, -1, 0, 0, 19, -1, 15289), + (15295, -1, -1, 15295, 15295, 7, 96, -1, 0, 0, 19, -1, 15296), + (15298, 10806, 10806, 10806, 10806, 9, 96, 38025, 71, 540, 19, 10808, 15299), + (15301, 10809, 10809, 10809, 10809, 9, 96, 38028, 71, 540, 19, 10811, 15302), + (15304, 15304, 15304, 15304, 15304, 12, 100, 38031, 91, 360, 19, -1, -1), + (15314, 0, 0, 6481, 6481, 11, 96, -1, 0, 0, 19, 6483, 15315), + (15317, -1, -1, 15317, 15317, 9, 96, -1, 0, 0, 19, 5012, 15318), + (15320, -1, -1, 7940, 7940, 11, 100, -1, 0, 0, 19, 6486, -1), + (15321, 746, 746, 746, 746, 9, 96, 38033, 10, 2160, 19, 10024, 15322), + (15328, -1, -1, 7948, 7948, 9, 96, -1, 0, 0, 19, 10037, 15329), + (15338, 15338, 15338, 15338, 15338, 9, 96, 38054, 30, 600, 19, -1, 15339), + (15341, 136, -1, 136, 136, 7, 100, 38057, 7, 1800, 19, 136, -1), + (15342, -1, -1, 15341, 15341, 7, 100, -1, 0, 0, 19, -1, -1), + (15343, 15343, 15343, 15343, 15343, 12, 100, 38058, 21, 300, 19, -1, -1), + (15344, -1, -1, 2400, 2400, 12, 97, -1, 0, 0, 19, 2402, 15345), + (15348, -1, -1, 13001, 13001, 7, 96, -1, 0, 0, 19, 13003, 15349), + (15356, -1, -1, 15356, 15356, 15, 100, -1, 0, 0, 19, -1, 15851), + (15357, 15357, 15357, 15357, 15357, 9, 96, 38062, 95, 2, 19, -1, -1), + (15358, -1, -1, 15358, 15358, 12, 100, -1, 0, 0, 19, -1, -1), + (15359, -1, -1, 474, 474, 5, 96, -1, 0, 0, 19, 476, 15360), + (15362, 15362, 15362, 15362, 15362, 15, 100, 38063, 89, 20, 19, -1, -1), + (15363, -1, -1, 10951, 10951, 12, 97, -1, 0, 0, 19, 10953, 15364), + (15371, -1, -1, 15371, 15371, 7, 96, -1, 0, 0, 19, -1, 15372), + (15374, -1, -1, 15374, 15374, 9, 96, -1, 0, 0, 19, -1, 15375), + (15377, 15377, 15377, 15377, 15377, 15, 100, 38070, 75, 420, 19, -1, 15852), + (15383, -1, -1, 15383, 15383, 9, 96, -1, 0, 0, 19, -1, 15384), + (15389, -1, -1, 15389, 15389, 9, 96, -1, 0, 0, 19, -1, 15390), + (15396, -1, -1, 141, 12863, 12, 100, -1, 0, 0, 19, 12863, -1), + (15397, -1, -1, 6346, 6346, 9, 96, -1, 0, 0, 19, 7617, 15398), + (15403, -1, -1, 15403, 15403, 7, 96, -1, 0, 0, 19, -1, 15404), + (15406, -1, -1, 15406, 15406, 7, 96, -1, 0, 0, 19, -1, 15407), + (15414, -1, -1, 15414, 15414, 9, 100, -1, 0, 0, 19, -1, -1), + (15421, -1, -1, 6538, 6538, 12, 100, -1, 0, 0, 19, 7478, -1), + (15422, -1, -1, 83, 83, 12, 100, -1, 0, 0, 19, 1218, -1), + (15423, 15423, 15423, 15423, 15423, 15, 100, 38078, 52, 180, 19, -1, 15884), + (15424, 15424, 15424, 15424, 15424, 12, 100, 38079, 78, 1200, 19, -1, -1), + (15425, 15425, 15425, 15425, 15425, 15, 100, 38077, 79, 6, 19, -1, 15903), + (15426, -1, -1, 810, 810, 5, 96, -1, 0, 0, 19, 4828, 15427), + (15429, -1, -1, 15429, 15429, 7, 96, -1, 0, 0, 19, -1, 15430), + (15432, -1, -1, 15432, 15432, 7, 96, -1, 0, 0, 19, -1, 15433), + (15438, -1, -1, 15438, 15438, 9, 96, -1, 0, 0, 19, -1, 15439), + (15441, -1, -1, 815, 815, 10, 96, -1, 0, 0, 19, 7636, 15442), + (15444, -1, -1, 15444, 15444, 9, 96, 38080, 0, 0, 19, -1, 15445), + (15447, 15447, 15447, 15447, 15447, 9, 96, 38083, 78, 180, 19, -1, 15448), + (15450, -1, -1, 15450, 15450, 9, 96, -1, 0, 0, 19, -1, 15451), + (15453, -1, -1, 15453, 15453, 9, 96, -1, 0, 0, 19, -1, 15454), + (15456, -1, -1, 15456, 15456, 9, 96, -1, 0, 0, 19, -1, 15457), + (15459, 1245, 1245, 1245, 1245, 9, 96, 38404, 8, 2160, 19, 1247, 15460), + (15462, 8039, 8039, 8039, 38407, 15, 100, 38407, 58, 7, 19, 8039, 17167), + (15466, -1, -1, 10561, 10561, 9, 96, -1, 0, 0, 19, 10563, 15467), + (15469, -1, -1, 10558, 10558, 9, 96, -1, 0, 0, 19, 10560, 15470), + (15472, -1, -1, 8035, 8035, 9, 96, -1, 0, 0, 19, 10287, 15473), + (15475, 15475, 15475, 15475, 15475, 11, 96, 38408, 41, 600, 20, -1, 15476), + (15478, -1, -1, 15478, 15478, 9, 96, -1, 0, 0, 19, -1, 15479), + (15481, 15481, 15481, 15481, 15481, 18, 100, 38603, 53, 1080, 19, -1, -1), + (15482, 15482, 15482, 15482, 15482, 11, 96, 38414, 42, 1800, 19, -1, 15483), + (15485, -1, -1, 15485, 15485, 18, 100, -1, 0, 0, 19, -1, -1), + (15486, 15486, 15486, 15486, 15486, 12, 96, 38418, 43, 600, 19, -1, 15487), + (15489, 15489, 15489, 15489, 15489, 18, 100, 38421, 52, 10, 19, -1, -1), + (15490, 15490, 15490, 15490, 15490, 11, 96, 38422, 44, 10, 19, -1, 15491), + (15493, -1, -1, 15493, 15493, 9, 96, -1, 0, 0, 19, -1, 15494), + (15496, 15496, 15496, 15496, 15496, 11, 96, 38425, 46, 1800, 19, -1, 15497), + (15502, -1, -1, 15502, 15502, 9, 96, -1, 0, 0, 19, -1, 15503), + (15509, -1, -1, 15509, 15509, 9, 96, -1, 0, 0, 19, -1, 15510), + (15512, -1, -1, 15512, 15512, 9, 96, 38086, 0, 0, 19, -1, 15513), + (15515, 15515, 15515, 15515, 15515, 12, 100, 38089, 11, 90, 19, -1, 17417), + (15516, -1, -1, 15516, 15516, 9, 100, -1, 0, 0, 19, -1, 15960), + (15517, -1, -1, 15517, 15517, 7, 96, -1, 0, 0, 19, -1, 15518), + (15521, 15521, 15521, 15521, 15521, 12, 96, 38090, 42, 60, 19, -1, -1), + (15526, -1, -1, 12716, 12716, 7, 96, -1, 0, 0, 19, 12718, 15527), + (15529, -1, -1, 695, 695, 4, 96, -1, 0, 0, 19, 699, 15530), + (15540, -1, -1, 15540, 15540, 7, 96, -1, 0, 0, 19, -1, 15541), + (15543, -1, -1, 15543, 15543, 7, 96, -1, 0, 0, 19, -1, 15544), + (15546, -1, -1, 15546, 15546, 7, 96, -1, 0, 0, 19, -1, 15547), + (15549, -1, -1, 15549, 15549, 7, 96, -1, 0, 0, 19, -1, 15550), + (15552, -1, -1, 6302, 6302, 5, 96, -1, 0, 0, 19, 11013, 15553), + (15555, -1, -1, 15555, 15555, 11, 96, -1, 0, 0, 19, -1, 15556), + (15558, 10400, 10400, 10400, 10400, 9, 100, 38104, 62, 900, 19, 10400, -1), + (15564, -1, -1, 15564, 15564, 9, 96, -1, 0, 0, 19, -1, 15565), + (15567, 15567, 15567, 15567, 15567, 12, 96, 38106, 11, 1200, 19, -1, 15568), + (15569, 15569, 15569, 15569, 15569, 12, 96, 38108, 13, 60, 19, -1, 15991), + (15570, 15570, 15570, 15570, 15570, 15, 100, 38109, 64, 600, 19, -1, 15992), + (15571, -1, -1, 15571, 15571, 7, 96, -1, 0, 0, 19, -1, 15572), + (15574, 15574, 15574, 15574, 15574, 9, 80, 38110, 73, 4, 15, -1, 15575), + (15575, 15574, 15574, 15574, 15574, 9, 85, 38111, 73, 4, 16, 15574, 15576), + (15576, 15574, 15574, 15574, 15574, 9, 90, 38112, 73, 4, 17, 15575, 15577), + (15577, 15574, 15574, 15574, 15574, 9, 95, 38113, 73, 4, 18, 15576, 15578), + (15579, -1, -1, 15579, 15579, 7, 96, -1, 0, 0, 19, -1, 15580), + (15582, 15582, 15582, 15582, 15582, 9, 96, 38115, 34, 600, 19, -1, 15583), + (15585, -1, -1, 634, 634, 11, 96, -1, 0, 0, 19, 10780, 15586), + (15588, 10701, 10701, 10701, 10701, 12, 96, 38121, 32, 360, 19, 12756, 15589), + (15591, -1, -1, 15591, 15591, 5, 96, -1, 0, 0, 19, -1, 15592), + (15594, 15594, 15594, 15594, 15594, 9, 96, 38197, 39, 30, 19, -1, 15595), + (15598, -1, -1, 15598, 15598, 12, 96, -1, 0, 0, 19, -1, 15599), + (15601, 15601, 15601, 15601, 15601, 12, 96, 38131, 34, 6, 19, -1, 16077), + (15602, -1, -1, 15602, 15602, 9, 96, -1, 0, 0, 19, -1, 15603), + (15605, 12866, 12866, 12866, 12866, 15, 96, 38132, 74, 1800, 19, 12866, -1), + (15606, -1, -1, 8069, 8069, 5, 96, -1, 0, 0, 19, 8071, 15607), + (15609, -1, -1, 15609, 15609, 15, 100, -1, 0, 0, 19, -1, -1), + (15611, 15611, 15611, 15611, 15611, 18, 100, 38136, 32, 900, 19, -1, 16078), + (15612, 15612, 15612, 15612, 15612, 12, 96, 38137, 36, 20, 19, -1, 15613), + (15615, 15615, 15615, 15615, 15615, 12, 96, 38140, 44, 20, 19, -1, 15616), + (15619, 15619, 15619, 15619, 15619, 15, 100, 37188, 32, 600, 19, -1, -1), + (15622, -1, -1, 15622, 15622, 7, 96, -1, 0, 0, 19, -1, 15623), + (15625, -1, -1, 15625, 15625, 9, 96, -1, 0, 0, 19, -1, 15626), + (15628, 5022, 5022, 5022, 5022, 9, 96, 38176, 5, 600, 19, 6040, 15629), + (15632, -1, -1, 7005, 7005, 5, 96, -1, 0, 0, 19, 7007, 15633), + (15634, -1, -1, 15634, 15634, 3, 80, -1, 0, 0, 19, -1, 15635), + (15635, -1, -1, 15634, 15634, 5, 85, -1, 0, 0, 19, 15634, 15636), + (15639, 15639, 15639, 15639, 15639, 12, 96, 38183, 56, 60, 19, -1, -1), + (15640, 15640, 15640, 15640, 15640, 12, 100, 38184, 43, 60, 19, -1, -1), + (15642, 15642, 15642, 15642, 15642, 18, 100, 38187, 13, 1440, 19, -1, -1), + (15643, 15643, 15643, 15643, 15643, 9, 96, 38188, 75, 600, 19, -1, 15644), + (15646, 15646, 15646, 15646, 15646, 15, 100, 38194, 74, 60, 19, -1, 17255), + (15648, -1, -1, 15648, 15648, 9, 96, -1, 0, 0, 19, -1, 15649), + (15694, -1, -1, 8215, 8215, 5, 96, -1, 0, 0, 20, 12563, 15695), + (15714, -1, -1, 5263, 5263, 12, 96, -1, 0, 0, 20, 12468, 15715), + (15719, -1, -1, 1287, 1287, 11, 96, -1, 0, 0, 20, 13240, 15720), + (15746, -1, -1, 7033, 7033, 12, 96, 0, 0, 0, 20, 7035, 15747), + (15768, -1, -1, 15768, 15768, 7, 96, -1, 0, 0, 20, -1, 15769), + (15771, 15771, -1, 15771, 15771, 1, 55, 38274, 0, 3, 20, -1, -1), + (15772, -1, -1, 8232, 8232, 8, 100, -1, 0, 0, 20, 8261, -1), + (15773, -1, -1, 8040, 8040, 8, 100, -1, 0, 0, 20, 8313, -1), + (15775, 6508, 6508, 6508, 6508, 9, 96, 38276, 38, 600, 20, 10080, 15776), + (15778, -1, -1, 589, 589, 12, 96, -1, 0, 0, 20, 13106, 15779), + (15782, 7755, 7755, 7755, 7755, 12, 96, 38280, 53, 900, 20, 7755, 16187), + (15798, 15798, 15798, 15798, 15798, 9, 100, 38297, 34, 18, 20, -1, 15799), + (15819, 15819, 15819, 15819, 15819, 18, 100, 40807, 18, 900, 20, -1, -1), + (15833, -1, -1, 15833, 15833, 9, 96, 0, 0, 0, 20, -1, 15834), + (15836, -1, -1, 15836, 15836, 9, 100, 0, 0, 0, 20, -1, 15837), + (15839, 10450, 10450, 10450, 10450, 7, 96, 40817, 63, 900, 20, 10670, 15840), + (15855, 13004, 13004, 13004, 13004, 9, 96, 40832, 78, 300, 20, 13004, -1), + (15891, -1, -1, 11078, 11078, 9, 96, 0, 0, 0, 20, 11078, 15892), + (15893, -1, -1, 11079, 11079, 9, 96, 0, 0, 0, 20, 11079, 15894), + (15895, -1, -1, 11077, 11077, 9, 96, 0, 0, 0, 20, 11077, 15896), + (15904, 15904, 15904, 15904, 15904, 7, 66, 40874, 54, 600, 20, -1, -1), + (15908, -1, -1, 15908, 15908, 3, 80, -1, 0, 0, 20, -1, 15909), + (15909, -1, -1, 15908, 15908, 5, 85, -1, 0, 0, 20, 15908, 15910), + (15910, -1, -1, 15908, 15908, 7, 90, -1, 0, 0, 20, 15909, 15911), + (15954, -1, -1, 10853, 10853, 5, 90, -1, 0, 0, 20, 10864, 15955), + (15961, -1, -1, 12737, 12737, 9, 96, 0, 0, 0, 20, 12739, 15962), + (15988, 10333, 10333, 10333, 10333, 9, 96, 40894, 55, 120, 20, 12726, 15989), + (16016, 16016, 16016, 16016, 16016, 12, 100, 40919, 17, 12, 20, -1, -1), + (16062, -1, -1, 1572, 1572, 5, 96, -1, 0, 0, 20, 10556, 16063), + (16071, 16071, 16071, 16071, 16071, 15, 100, 40953, 46, 1800, 20, -1, 16072), + (16081, 16081, 16081, 16081, 16081, 15, 100, 40969, 55, 6, 20, -1, -1), + (16082, 16082, 16082, 16082, 16082, 3, 100, 40970, 53, 6, 20, -1, -1), + (16083, 16083, 16083, 16083, 16083, 3, 55, 40971, 46, 6, 20, -1, -1), + (16084, -1, -1, 16084, 16084, 9, 100, 0, 0, 0, 20, -1, 16085), + (16087, -1, -1, 16087, 16087, 5, 100, 0, 0, 6, 20, -1, 16088), + (16094, -1, -1, 477, 477, 2, 100, -1, 0, 0, 20, 6235, 16095), + (16096, 16096, 16096, 16096, 16096, 12, 100, 40972, 36, 6, 20, -1, -1), + (16097, 16097, 16097, 16097, 16097, 12, 100, 40973, 38, 600, 20, -1, 16098), + (16103, 16103, 16103, 16103, 16103, 0, 85, 41071, 35, 180, 16, -1, -1), + (16104, -1, -1, 16104, 16104, 5, 85, 0, 0, 0, 20, -1, -1), + (16105, 16105, 16105, 16105, 16105, 0, 85, 41086, 76, 30, 20, -1, -1), + (16106, 16106, 16106, 16106, 16106, 0, 85, 41087, 76, 30, 20, -1, -1), + (16107, 16107, 16107, 16107, 16107, 0, 85, 41088, 76, 30, 20, -1, -1), + (16108, 16108, 16108, 16108, 16108, 12, 100, 41090, 77, 120, 20, -1, -1), + (16109, -1, -1, 16109, 16109, 11, 96, -1, 0, 0, 20, -1, 16110), + (16113, 16113, 16113, 16113, 16113, 15, 100, 41096, 78, 60, 20, -1, -1), + (16114, -1, -1, 16114, 16114, 5, 96, -1, 0, 0, 20, -1, 16115), + (16117, -1, -1, 16117, 16117, 11, 96, -1, 0, 0, 20, -1, 16118), + (16120, -1, -1, 16120, 16120, 9, 105, -1, 0, 0, 21, -1, -1), + (16121, -1, -1, 6611, 6611, 6, 100, -1, 0, 0, 20, 10574, 16122), + (16124, -1, -1, 16124, 16124, 5, 96, -1, 0, 0, 20, -1, 16125), + (16128, -1, -1, 16128, 16128, 6, 96, -1, 0, 0, 20, -1, 16129), + (16131, -1, -1, 16131, 16131, 5, 96, -1, 0, 0, 20, -1, 16132), + (16137, -1, -1, 16137, 16137, 9, 100, -1, 0, 0, 20, -1, 16138), + (16140, -1, -1, 16140, 16140, 9, 100, -1, 0, 0, 20, -1, -1), + (16146, -1, -1, 16146, 16146, 11, 100, -1, 0, 0, 20, -1, 16147), + (16149, -1, -1, 16149, 16149, 9, 100, -1, 0, 0, 20, -1, 16150), + (16152, -1, -1, 16152, 16152, 11, 100, -1, 0, 0, 20, -1, 16153), + (16156, -1, -1, 16156, 16156, 12, 100, -1, 0, 0, 20, -1, 16157), + (16159, -1, -1, 16159, 16159, 15, 100, -1, 0, 0, 20, -1, -1), + (16160, 16160, 16160, 16160, 16160, 18, 100, 41110, 81, 900, 20, -1, -1), + (16162, 16162, 16162, 16162, 16162, 12, 100, 41112, 80, 180, 20, -1, -1), + (16163, 16163, 16163, 16163, 16163, 18, 100, 41113, 63, 180, 20, -1, 16695), + (16164, -1, -1, 6636, 6636, 9, 96, -1, 0, 0, 20, 12531, 16165), + (16170, -1, -1, 5248, 5248, 12, 96, -1, 0, 0, 20, 7358, 16171), + (16173, -1, -1, 5263, 5263, 9, 101, -1, 0, 0, 21, 12465, 16174), + (16176, -1, -1, 16176, 16176, 7, 100, -1, 0, 0, 20, -1, 16177), + (16179, -1, -1, 16179, 16179, 18, 100, 41122, 0, 0, 20, -1, -1), + (16180, -1, -1, 16180, 16180, 7, 96, -1, 0, 0, 20, -1, 16181), + (16185, 16185, 16185, 16185, 16185, 18, 100, 41124, 68, 600, 20, -1, 16729), + (16186, -1, -1, 16186, 16186, 12, 100, 41125, 0, 0, 20, -1, -1), + (16188, 16188, 16188, 16188, 16188, 12, 100, 41126, 58, 180, 20, -1, -1), + (16189, -1, -1, 10915, 10915, 9, 96, -1, 0, 0, 20, 10917, 16190), + (16192, -1, -1, 6641, 6641, 9, 96, -1, 0, 0, 20, 10077, 16193), + (16195, 16195, 16195, 16195, 16195, 15, 100, 41133, 59, 60, 20, -1, -1), + (16196, 16196, 16196, 16196, 16196, 15, 100, 41134, 60, 900, 20, -1, 16665), + (16197, 16197, 16197, 16197, 16197, 12, 96, 41136, 61, 900, 20, -1, 16198), + (16200, 16200, 16200, 16200, 16200, 9, 96, 41139, 63, 900, 20, -1, 16201), + (16203, 16203, 16203, 16203, 16203, 12, 96, 41143, 98, 120, 20, -1, 16204), + (16208, -1, -1, 16208, 16208, 5, 96, -1, 0, 0, 20, -1, 16209), + (16211, -1, -1, 16211, 16211, 7, 100, -1, 0, 0, 20, -1, 16212), + (16214, 10958, 10958, 10958, 16214, 18, 100, 41148, 62, 900, 20, 13000, -1), + (16215, 16215, 16215, 16215, 16215, 9, 96, 41150, 92, 300, 20, -1, 16216), + (16218, -1, -1, 16218, 16218, 7, 96, -1, 0, 0, 20, -1, 16219), + (16221, -1, -1, 16221, 16221, 9, 100, -1, 0, 0, 20, -1, 16223), + (16222, 16222, -1, 16222, 16222, 9, 100, 41153, 88, 30, 20, -1, -1), + (16225, -1, -1, 16225, 16225, 5, 96, -1, 0, 0, 20, -1, 16226), + (16230, -1, -1, 16230, 16230, 5, 96, -1, 0, 0, 20, -1, 16231), + (16235, -1, -1, 16235, 16235, 7, 96, -1, 0, 0, 20, -1, 16236), + (16238, -1, -1, 16238, 16238, 7, 96, -1, 0, 0, 20, -1, 16239), + (16246, 6983, 6983, 6983, 6983, 9, 96, 41157, 66, 720, 20, 6983, 16247), + (16249, -1, -1, 230, 230, 9, 100, -1, 0, 0, 20, 12677, -1), + (16250, 828, 828, 828, 828, 9, 96, 41159, 2, 3600, 20, 830, -1), + (16257, -1, -1, 16257, 16257, 11, 100, 0, 0, 0, 20, -1, 16258), + (16260, -1, -1, 16260, 16260, 11, 100, -1, 0, 0, 20, -1, 16261), + (16263, 16263, 16263, 16263, 16263, 11, 96, 41161, 95, 600, 20, -1, 16264), + (16266, -1, -1, 6560, 6560, 9, 96, -1, 0, 0, 20, 6277, -1), + (16267, -1, -1, 888, 888, 3, 96, -1, 0, 0, 20, 892, 16268), + (16272, -1, -1, 16272, 16272, 9, 96, -1, 0, 0, 20, -1, 16273), + (16276, -1, -1, 16276, 16276, 5, 96, -1, 0, 0, 20, -1, 16277), + (16287, -1, -1, 16287, 16287, 7, 96, -1, 0, 0, 20, -1, 16288), + (16296, 16296, 16296, 16296, 16296, 13, 100, 41168, 60, 30, 20, -1, -1), + (16297, -1, -1, 6337, 6337, 6, 96, -1, 0, 0, 20, 10155, 16298), + (16300, -1, -1, 16300, 16300, 9, 100, -1, 0, 0, 20, -1, 16301), + (16303, -1, -1, 12721, 12721, 9, 96, 0, 0, 0, 20, 12723, 16304), + (16306, -1, -1, 6340, 6340, 6, 96, -1, 0, 0, 20, 7453, -1), + (16310, 16310, 16310, 16310, 16310, 12, 100, 41169, 97, 600, 20, -1, -1), + (16317, -1, -1, 16317, 16317, 5, 100, -1, 0, 0, 20, -1, 16318), + (16324, 6607, 6607, 6607, 16324, 9, 96, 16491, 61, 600, 20, 6609, 16325), + (16327, -1, -1, 6362, 6362, 7, 96, 0, 0, 0, 20, 6366, 16328), + (16330, -1, -1, 16330, 16330, 9, 96, -1, 0, 0, 20, -1, 16331), + (16336, -1, -1, 16336, 16336, 7, 96, -1, 0, 0, 20, -1, 16337), + (16339, -1, -1, 16339, 16339, 7, 96, -1, 0, 0, 20, -1, 16340), + (16342, -1, -1, 16342, 16342, 7, 96, -1, 0, 0, 20, -1, 16343), + (16360, 16360, 16360, 16360, 16360, 9, 100, 41188, 91, 6, 20, -1, -1), + (16361, -1, -1, 9509, 9509, 7, 96, -1, 0, 0, 20, 9515, -1), + (16363, 16363, 16363, 16363, 16363, 12, 96, 41193, 89, 1800, 20, -1, 16364), + (16366, -1, -1, 16366, 16366, 12, 96, -1, 0, 0, 20, -1, 16367), + (16369, 16369, 16369, 16369, 16369, 15, 100, 41196, 98, 12, 20, -1, -1), + (16370, 16370, -1, 16370, 16370, 5, 100, 41197, 98, 12, 20, -1, -1), + (16371, -1, -1, 16371, 16371, 3, 96, -1, 0, 0, 20, -1, 16372), + (16380, -1, -1, 16380, 16380, 5, 96, -1, 0, 0, 20, -1, 16381), + (16386, -1, -1, 16386, 16386, 7, 96, -1, 0, 0, 20, -1, 16387), + (16392, -1, -1, 16392, 16392, 5, 96, -1, 0, 0, 20, -1, 16393), + (16395, 16395, 16395, 16395, 16395, 7, 100, 41305, 93, 10, 20, -1, -1), + (16396, -1, -1, 16396, 16396, 7, 96, -1, 0, 0, 20, -1, 16397), + (16402, -1, -1, 6112, 6112, 5, 96, -1, 0, 0, 20, 12967, 16403), + (16414, -1, -1, 1056, 1056, 5, 101, -1, 0, 0, 21, 7525, 16415), + (16419, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8447, 16420), + (16420, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 16419, 16421), + (16421, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 16420, -1), + (16440, -1, -1, 6540, 6540, 10, 101, -1, 0, 0, 21, 12510, 16441), + (16475, -1, -1, 8201, 8201, 9, 101, -1, 0, 0, 21, 8203, 16476), + (16489, -1, -1, 1107, 1107, 9, 101, -1, 0, 0, 21, 12558, 16490), + (16536, -1, -1, 16536, 16536, 5, 101, -1, 0, 0, 21, -1, 16537), + (16604, -1, -1, 849, 849, 11, 105, -1, 0, 0, 21, 10622, -1), + (16644, -1, -1, 16644, 16644, 11, 101, -1, 0, 0, 21, -1, 16645), + (16666, -1, -1, 16666, 16666, 9, 101, -1, 0, 0, 21, -1, 16667), + (16716, 6764, 6764, 6764, 6764, 12, 105, 41308, 52, 600, 21, 10057, -1), + (16730, -1, -1, 1608, 1608, 13, 101, -1, 0, 0, 21, 10069, 16731), + (16745, -1, -1, 16745, 16745, 9, 101, -1, 0, 0, 21, -1, 16746), + (16883, 1119, 1119, 1119, 1119, 12, 101, 41594, 8, 900, 21, 10299, 16884), + (16887, -1, -1, 729, 729, 11, 101, -1, 0, 0, 21, 10307, 16888), + (16890, -1, -1, 724, 724, 15, 101, -1, 0, 0, 21, 7493, 16891), + (17004, -1, -1, 556, 556, 7, 101, -1, 0, 0, 21, 1567, 17005), + (17030, 4857, 4857, 4857, 4857, 15, 101, 41660, 7, 600, 21, 5769, 17031), + (17131, 12785, 12785, 12785, 12785, 15, 105, 41736, 80, 30, 21, 12785, -1), + (17199, 17199, 17199, 17199, 17199, 100, 51, 41819, 31, 2, 21, -1, -1), + (17206, -1, -1, 10588, 10588, 7, 101, 0, 0, 0, 21, 10592, 17207), + (17209, -1, -1, 17209, 17209, 9, 101, -1, 0, 0, 21, -1, 17210), + (17212, -1, -1, 17212, 17212, 12, 101, -1, 0, 0, 21, -1, 17213), + (17215, -1, -1, 17215, 17215, 12, 101, -1, 0, 0, 21, -1, 17216), + (17218, -1, -1, 17218, 17218, 9, 101, -1, 0, 0, 21, -1, 17219), + (17229, -1, -1, 17229, 17229, 9, 101, -1, 0, 0, 21, -1, 17230), + (17235, -1, -1, 17235, 17235, 15, 101, -1, 0, 0, 21, -1, 17236), + (17238, 17238, 17238, 17238, 17238, 24, 105, 41808, 10, 900, 21, -1, -1), + (17239, -1, -1, 6489, 6489, 12, 101, -1, 0, 0, 21, 6491, -1), + (17242, -1, -1, 17242, 17242, 12, 101, -1, 0, 0, 21, -1, 17243), + (17245, -1, -1, 17245, 17245, 12, 101, -1, 0, 0, 21, -1, 17246), + (17248, 17248, 17248, 17248, 17248, 24, 105, 41811, 93, 1080, 21, -1, -1), + (17249, -1, -1, 17249, 17249, 12, 101, -1, 0, 0, 21, -1, 17250), + (17252, -1, -1, 17252, 17252, 9, 101, -1, 0, 0, 21, -1, 17253), + (17256, 17256, 17256, 17256, 17256, 21, 105, 41815, 93, 360, 21, -1, -1), + (17257, 17257, 17257, 17257, 17257, 21, 105, 41816, 98, 300, 21, -1, -1), + (17258, -1, -1, 17258, 17258, 15, 101, 0, 0, 0, 21, -1, 17259), + (17267, -1, -1, 17267, 17267, 9, 101, -1, 0, 0, 21, -1, 17268), + (17273, 17273, 17273, 17273, 17273, 15, 101, 41830, 98, 720, 21, -1, -1), + (17276, 1569, 1569, 1569, 1569, 9, 101, 41831, 5, 1800, 21, 10161, 17277), + (17280, 17280, 17280, 17280, 17280, 21, 105, 41834, 97, 720, 21, -1, -1), + (17281, -1, -1, 17281, 17281, 15, 105, -1, 0, 0, 21, -1, -1), + (17288, -1, -1, 17288, 17288, 9, 105, -1, 0, 0, 21, 7317, -1), + (17289, -1, -1, 17289, 17289, 7, 101, -1, 0, 0, 21, -1, 17290), + (17295, -1, -1, 692, 692, 12, 101, -1, 0, 0, 21, 12769, 17296), + (17298, 749, 749, 749, 749, 15, 105, 41837, 11, 1800, 21, 1208, -1), + (17307, -1, -1, 17307, 17307, 9, 101, -1, 0, 0, 21, -1, 17308), + (17310, -1, -1, 7945, 7945, 9, 105, -1, 0, 0, 21, 10347, -1), + (17311, 970, 970, 970, 970, 9, 101, 41845, 6, 1800, 21, 1326, 17312), + (17317, -1, -1, 17317, 17317, 9, 101, -1, 0, 0, 21, -1, 17318), + (17328, 17328, 17328, 17328, 17328, 21, 105, 41854, 87, 600, 21, -1, -1), + (17329, 17329, 17329, 17329, 17329, 12, 101, 41855, 88, 20, 21, -1, -1), + (17333, 153, 153, 153, 153, 18, 105, 41856, 3, 2160, 21, 12996, -1), + (17334, -1, -1, 12977, 12977, 12, 102, 0, 0, 0, 21, 12981, 17335), + (17336, -1, -1, 17336, 17336, 9, 101, -1, 0, 0, 21, -1, 17337), + (17339, -1, -1, 17339, 17339, 9, 101, -1, 0, 0, 21, -1, 17340), + (17342, 17342, 17342, 17342, 17342, 15, 105, 41857, 85, 60, 21, -1, -1), + (17344, 17344, 17344, 17344, 17344, 15, 101, 41858, 94, 780, 21, -1, 17345), + (17347, 17347, 17347, 17347, 17347, 12, 101, 41861, 32, 30, 21, -1, 17348), + (17350, -1, -1, 7664, 7664, 5, 102, -1, 0, 0, 21, 10109, 17351), + (17357, -1, -1, 17357, 17357, 9, 96, -1, 0, 0, 19, -1, 17358), + (17361, -1, -1, 17361, 17361, 5, 100, -1, 0, 0, 21, -1, 17362), + (17364, 17364, 17364, 17364, 17364, 15, 105, 46160, 87, 120, 21, -1, -1), + (17365, -1, -1, 10792, 10792, 15, 101, 0, 0, 0, 21, 10796, 17366), + (17370, -1, -1, 17370, 17370, 15, 102, 0, 0, 0, 21, -1, 17371), + (17372, 17372, 17372, 17372, 17372, 18, 104, 46161, 85, 300, 21, -1, -1), + (17373, 17373, -1, 17373, 17373, 15, 105, 46162, 98, 900, 21, -1, -1), + (17375, -1, -1, 17375, 17375, 12, 101, -1, 0, 0, 21, -1, 17376), + (17378, 17378, 17378, 17378, 17378, 10, 101, 46164, 97, 3, 21, -1, -1), + (17379, 17378, 17378, 17378, 17378, 10, 101, 46165, 86, 3, 21, -1, -1), + (17380, 17378, 17378, 17378, 17378, 10, 101, 46166, 97, 3, 21, -1, -1), + (17382, 5015, 5015, 5015, 5015, 15, 103, 46168, 9, 900, 21, 10301, -1), + (17384, 17384, 17384, 17384, 17384, 18, 101, 46171, 10, 20, 21, -1, -1), + (17391, -1, -1, 495, 495, 12, 105, -1, 0, 0, 21, 10668, -1), + (17406, -1, -1, 10653, 10653, 12, 103, -1, 0, 0, 21, 10655, -1), + (17409, -1, -1, 17409, 17409, 15, 105, -1, 0, 0, 21, -1, -1), + (17414, -1, -1, 17414, 17414, 9, 101, -1, 0, 0, 21, -1, 17415), + (17418, -1, -1, 17418, 17418, 7, 101, -1, 0, 0, 21, -1, 17419), + (17428, 17428, 17428, 17428, 17428, 15, 101, 46178, 0, 0, 21, -1, 17429), + (17436, -1, -1, 17436, 17436, 7, 101, -1, 0, 0, 21, -1, 17437), + (17439, -1, -1, 17439, 17439, 9, 102, -1, 0, 0, 21, -1, 17440), + (17441, -1, -1, 255, 255, 15, 102, -1, 0, 0, 21, 7633, -1), + (17445, -1, -1, 17445, 17445, 15, 101, 0, 0, 0, 21, -1, 17446), + (17448, -1, -1, 17448, 17448, 15, 102, 0, 0, 0, 21, -1, 17449), + (17476, -1, -1, 10800, 10800, 15, 101, -1, 0, 0, 21, 10802, 17477), + (17486, 12864, -1, 12864, 12864, 12, 105, 46195, 73, 10, 21, 12864, -1), + (17492, -1, -1, 17492, 17492, 9, 101, -1, 0, 0, 21, -1, 17493), + (17495, -1, -1, 17495, 17495, 9, 101, -1, 0, 0, 21, -1, 17496), + (17515, -1, -1, 17515, 17515, 7, 102, -1, 0, 0, 21, -1, 17516), + (17517, -1, -1, 17517, 17517, 9, 101, -1, 0, 0, 21, -1, 17518), + (17522, -1, -1, 17522, 17522, 9, 101, -1, 0, 0, 21, -1, 17523), + (17533, -1, -1, 17533, 17533, 15, 105, -1, 0, 0, 21, -1, -1), + (17534, 6828, 6828, 6828, 6828, 15, 105, 46207, 43, 60, 21, 10208, -1), + (17535, 967, 967, 967, 967, 9, 101, 46208, 10, 1800, 21, 12791, 17536), + (17538, 17538, 17538, 17538, 17538, 21, 105, 46212, 91, 1800, 21, -1, -1), + (17539, 4934, 4934, 4934, 4934, 12, 105, 46214, 13, 300, 21, 10278, -1), + (17540, 4935, 4935, 4935, 4935, 12, 105, 46215, 14, 300, 21, 10277, -1), + (17541, 8038, 8038, 8038, 8038, 12, 105, 46217, 56, 12, 21, 8038, -1), + (17547, -1, -1, 17547, 17547, 12, 102, -1, 0, 0, 21, -1, 17548), + (17549, -1, -1, 17549, 17549, 9, 101, -1, 0, 0, 21, -1, 17550), + (17553, -1, -1, 17553, 17553, 18, 105, -1, 0, 0, 21, -1, -1), + (17554, -1, -1, 17554, 17554, 15, 105, -1, 0, 0, 21, -1, -1), + (17555, -1, -1, 17555, 17555, 5, 101, -1, 0, 0, 21, -1, 17556), + (17558, -1, -1, 17558, 17558, 5, 101, -1, 0, 0, 21, -1, 17559), + (17561, -1, -1, 17561, 17561, 5, 101, -1, 0, 0, 21, -1, 17562), + (17564, -1, -1, 17564, 17564, 5, 101, -1, 0, 0, 21, -1, 17565), + (17567, -1, -1, 17567, 17567, 5, 101, -1, 0, 0, 21, -1, 17568), + (17570, -1, -1, 17570, 17570, 5, 101, -1, 0, 0, 21, -1, 17571), + (17573, -1, -1, 17573, 17573, 5, 101, -1, 0, 0, 21, -1, 17574), + (17576, -1, -1, 17576, 17576, 5, 101, -1, 0, 0, 21, -1, 17577), + (17579, -1, -1, 17579, 17579, 5, 101, -1, 0, 0, 21, -1, 17580), + (17582, -1, -1, 17582, 17582, 5, 101, -1, 0, 0, 21, -1, 17583), + (17585, -1, -1, 17585, 17585, 5, 101, -1, 0, 0, 21, -1, 17586), + (17588, -1, -1, 17588, 17588, 5, 101, -1, 0, 0, 21, -1, 17589), + (17591, -1, -1, 17591, 17591, 5, 101, -1, 0, 0, 21, -1, 17592), + (17594, -1, -1, 17594, 17594, 5, 101, -1, 0, 0, 21, -1, 17595), + (17597, -1, -1, 17597, 17597, 5, 101, -1, 0, 0, 21, -1, 17598), + (17600, -1, -1, 17600, 17600, 5, 101, -1, 0, 0, 21, -1, 17601), + (17603, -1, -1, 17603, 17603, 5, 101, -1, 0, 0, 21, -1, 17604), + (17606, -1, -1, 17606, 17606, 5, 101, -1, 0, 0, 21, -1, 17607), + (17609, -1, -1, 17609, 17609, 5, 101, -1, 0, 0, 21, -1, 17610), + (17612, -1, -1, 17612, 17612, 5, 101, -1, 0, 0, 21, -1, 17613), + (17615, -1, -1, 17615, 17615, 5, 101, -1, 0, 0, 21, -1, 17616), + (17618, -1, -1, 17618, 17618, 5, 101, -1, 0, 0, 21, -1, 17619), + (17621, -1, -1, 17621, 17621, 5, 101, -1, 0, 0, 21, -1, 17622), + (17624, -1, -1, 17624, 17624, 5, 101, -1, 0, 0, 21, -1, 17625), + (17627, -1, -1, 17627, 17627, 5, 101, -1, 0, 0, 21, -1, 17628), + (17630, -1, -1, 17630, 17630, 5, 101, -1, 0, 0, 21, -1, 17631), + (17633, -1, -1, 17633, 17633, 5, 101, -1, 0, 0, 21, -1, 17634), + (17639, -1, -1, 17639, 17639, 9, 91, 0, 0, 0, 18, -1, 17640), + (18972, -1, -1, 279, 279, 15, 105, -1, 0, 0, 21, 279, -1), + (30050, -1, -1, 30050, 30050, 0, 1, -1, 0, 0, 0, -1, 30051), + (30100, -1, -1, 30100, 30100, 0, 1, -1, 0, 0, 0, -1, 30101), + (30150, -1, -1, 30150, 30150, 0, 1, -1, 0, 0, 0, -1, 30151), + (30175, -1, -1, 30175, 30175, 0, 1, -1, 0, 0, 0, -1, 30176), + (30180, -1, -1, 30180, 30180, 0, 1, -1, 0, 0, 0, -1, 30181), + (30185, -1, -1, 30185, 30185, 0, 1, -1, 0, 0, 0, -1, 30186), + (30190, -1, -1, 30190, 30190, 0, 1, -1, 0, 0, 0, -1, 30191), + (30195, -1, -1, 30195, 30195, 0, 1, -1, 0, 0, 0, -1, 30196), + (49999, -1, -1, -1, -1, 0, 71, 0, 0, 0, 0, -1, 1); + +-- Dumping structure for table eqdb.aa_rank_effects +DROP TABLE IF EXISTS `aa_rank_effects`; +CREATE TABLE IF NOT EXISTS `aa_rank_effects` ( + `rank_id` int(10) unsigned NOT NULL, + `slot` int(10) unsigned NOT NULL DEFAULT '1', + `effect_id` int(10) NOT NULL DEFAULT '0', + `base1` int(10) NOT NULL DEFAULT '0', + `base2` int(10) NOT NULL DEFAULT '0', + PRIMARY KEY (`rank_id`,`slot`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `aa_rank_effects` (`rank_id`, `slot`, `effect_id`, `base1`, `base2`) VALUES + (2, 1, 4, 2, 0), + (3, 1, 4, 4, 0), + (4, 1, 4, 6, 0), + (5, 1, 4, 8, 0), + (6, 1, 4, 10, 0), + (7, 1, 7, 2, 0), + (8, 1, 7, 4, 0), + (9, 1, 7, 6, 0), + (10, 1, 7, 8, 0), + (11, 1, 7, 10, 0), + (12, 1, 6, 2, 0), + (13, 1, 6, 4, 0), + (14, 1, 6, 6, 0), + (15, 1, 6, 8, 0), + (16, 1, 6, 10, 0), + (17, 1, 5, 2, 0), + (18, 1, 5, 4, 0), + (19, 1, 5, 6, 0), + (20, 1, 5, 8, 0), + (21, 1, 5, 10, 0), + (22, 1, 8, 2, 0), + (23, 1, 8, 4, 0), + (24, 1, 8, 6, 0), + (25, 1, 8, 8, 0), + (26, 1, 8, 10, 0), + (27, 1, 9, 2, 0), + (28, 1, 9, 4, 0), + (29, 1, 9, 6, 0), + (30, 1, 9, 8, 0), + (31, 1, 9, 10, 0), + (32, 1, 10, 2, 0), + (33, 1, 10, 4, 0), + (34, 1, 10, 6, 0), + (35, 1, 10, 8, 0), + (36, 1, 10, 10, 0), + (37, 1, 46, 2, 0), + (38, 1, 46, 4, 0), + (39, 1, 46, 6, 0), + (40, 1, 46, 8, 0), + (41, 1, 46, 10, 0), + (42, 1, 47, 2, 0), + (43, 1, 47, 4, 0), + (44, 1, 47, 6, 0), + (45, 1, 47, 8, 0), + (46, 1, 47, 10, 0), + (47, 1, 50, 2, 0), + (48, 1, 50, 4, 0), + (49, 1, 50, 6, 0), + (50, 1, 50, 8, 0), + (51, 1, 50, 10, 0), + (52, 1, 48, 2, 0), + (53, 1, 48, 4, 0), + (54, 1, 48, 6, 0), + (55, 1, 48, 8, 0), + (56, 1, 48, 10, 0), + (57, 1, 49, 2, 0), + (58, 1, 49, 4, 0), + (59, 1, 49, 6, 0), + (60, 1, 49, 8, 0), + (61, 1, 49, 10, 0), + (62, 1, 271, 8, 0), + (63, 1, 271, 14, 0), + (64, 1, 271, 21, 0), + (68, 1, 233, 110, 0), + (69, 1, 233, 125, 0), + (70, 1, 233, 150, 0), + (71, 1, 246, 110, 0), + (72, 1, 246, 125, 0), + (73, 1, 246, 150, 0), + (74, 1, 269, 10, 0), + (75, 1, 269, 20, 0), + (76, 1, 269, 30, 0), + (77, 1, 125, 2, 2), + (77, 2, 137, 0, 0), + (77, 3, 141, 1, 0), + (77, 4, 139, -6233, 0), + (77, 5, 139, -6265, 0), + (77, 6, 125, 2, 2), + (77, 7, 137, 147, 0), + (77, 8, 141, 1, 0), + (78, 1, 125, 5, 5), + (78, 2, 137, 0, 0), + (78, 3, 141, 1, 0), + (78, 4, 139, -6233, 0), + (78, 5, 139, -6265, 0), + (78, 6, 125, 5, 5), + (78, 7, 137, 147, 0), + (78, 8, 141, 1, 0), + (79, 1, 125, 10, 10), + (79, 2, 137, 0, 0), + (79, 3, 141, 1, 0), + (79, 4, 139, -6233, 0), + (79, 5, 139, -6265, 0), + (79, 6, 125, 10, 10), + (79, 7, 137, 147, 0), + (79, 8, 141, 1, 0), + (80, 1, 274, 3, 0), + (81, 1, 274, 6, 0), + (82, 1, 274, 10, 0), + (83, 1, 132, 2, 2), + (84, 1, 132, 5, 5), + (85, 1, 132, 10, 10), + (86, 1, 128, 5, 5), + (86, 2, 138, 1, 0), + (86, 3, 140, 1, 0), + (86, 4, 139, -2741, 0), + (86, 5, 139, -16843, 0), + (86, 6, 385, -16192, 0), + (86, 7, 385, -10547, 0), + (86, 8, 385, -13543, 0), + (87, 1, 128, 15, 15), + (87, 2, 138, 1, 0), + (87, 3, 140, 1, 0), + (87, 4, 139, -2741, 0), + (87, 5, 139, -16843, 0), + (87, 6, 385, -16192, 0), + (87, 7, 385, -10547, 0), + (87, 8, 385, -13543, 0), + (88, 1, 128, 30, 30), + (88, 2, 138, 1, 0), + (88, 3, 140, 1, 0), + (88, 4, 139, -2741, 0), + (88, 5, 139, -16843, 0), + (88, 6, 385, -16192, 0), + (88, 7, 385, -10547, 0), + (88, 8, 385, -13543, 0), + (92, 1, 294, 2, 100), + (93, 1, 294, 4, 100), + (94, 1, 294, 7, 100), + (98, 1, 114, -5, 0), + (99, 1, 114, -10, 0), + (100, 1, 114, -20, 0), + (101, 1, 265, 20, 0), + (102, 1, 265, 40, 0), + (103, 1, 265, 52, 0), + (104, 1, 127, 10, 10), + (104, 2, 138, 1, 0), + (104, 3, 140, 1, 0), + (104, 4, 143, 3000, 0), + (105, 1, 127, 25, 25), + (105, 2, 138, 1, 0), + (105, 3, 140, 1, 0), + (105, 4, 143, 3000, 0), + (106, 1, 127, 50, 50), + (106, 2, 138, 1, 0), + (106, 3, 140, 1, 0), + (106, 4, 143, 3000, 0), + (107, 1, 214, 200, 0), + (108, 1, 214, 500, 0), + (109, 1, 214, 1000, 0), + (110, 1, 0, 1, 0), + (111, 1, 0, 2, 0), + (112, 1, 0, 3, 0), + (113, 1, 169, 15, -1), + (114, 1, 169, 40, -1), + (115, 1, 169, 75, -1), + (116, 1, 181, 5, 0), + (117, 1, 181, 10, 0), + (118, 1, 181, 25, 0), + (119, 1, 278, 500, 16000), + (119, 2, 440, 50, 100), + (120, 1, 278, 510, 17102), + (120, 2, 440, 52, 100), + (121, 1, 278, 520, 19635), + (121, 2, 440, 54, 100), + (122, 1, 259, 2, 0), + (123, 1, 259, 5, 0), + (124, 1, 259, 10, 0), + (125, 1, 172, 2, 0), + (126, 1, 172, 5, 0), + (127, 1, 172, 10, 0), + (137, 1, 127, 10, 10), + (137, 2, 137, 88, 0), + (138, 1, 127, 25, 25), + (138, 2, 137, 88, 0), + (139, 1, 127, 50, 50), + (139, 2, 137, 88, 0), + (141, 1, 127, 2, 2), + (141, 2, 137, 0, 0), + (141, 3, 138, 0, 0), + (141, 4, 141, 1, 0), + (141, 5, 143, 3000, 0), + (141, 6, 127, 2, 2), + (141, 7, 385, 16555, 0), + (141, 8, 385, 16655, 0), + (142, 1, 127, 5, 5), + (142, 2, 137, 0, 0), + (142, 3, 138, 0, 0), + (142, 4, 141, 1, 0), + (142, 5, 143, 3000, 0), + (142, 6, 127, 5, 5), + (142, 7, 385, 16555, 0), + (142, 8, 385, 16655, 0), + (143, 1, 127, 10, 10), + (143, 2, 137, 0, 0), + (143, 3, 138, 0, 0), + (143, 4, 141, 1, 0), + (143, 5, 143, 3000, 0), + (143, 6, 127, 10, 10), + (143, 7, 385, 16555, 0), + (143, 8, 385, 16655, 0), + (144, 1, 244, 50, 0), + (147, 1, 127, 10, 10), + (147, 2, 138, 1, 0), + (147, 3, 140, 1, 0), + (147, 4, 143, 3000, 0), + (148, 1, 127, 25, 25), + (148, 2, 138, 1, 0), + (148, 3, 140, 1, 0), + (148, 4, 143, 3000, 0), + (149, 1, 127, 50, 50), + (149, 2, 138, 1, 0), + (149, 3, 140, 1, 0), + (149, 4, 143, 3000, 0), + (150, 1, 268, 10, 59), + (151, 1, 268, 25, 59), + (152, 1, 268, 50, 59), + (158, 1, 238, 1, 0), + (159, 1, 268, 10, 68), + (160, 1, 268, 25, 68), + (161, 1, 268, 50, 68), + (182, 1, 131, 100, 0), + (182, 2, 137, 33, 0), + (190, 1, 219, 225, 680), + (191, 1, 219, 235, 1190), + (192, 1, 219, 240, 1700), + (195, 1, 181, 100, 0), + (196, 1, 226, 1, 0), + (198, 1, 276, 32, 0), + (199, 1, 301, 30, 0), + (200, 1, 301, 60, 0), + (201, 1, 301, 100, 0), + (205, 1, 251, 100, 0), + (210, 1, 302, 50, 50), + (210, 2, 385, 99, 0), + (211, 1, 302, 100, 100), + (211, 2, 385, 99, 0), + (212, 1, 302, 200, 200), + (212, 2, 385, 99, 0), + (213, 1, 260, 2, 23), + (213, 2, 260, 2, 24), + (213, 3, 260, 2, 25), + (213, 4, 260, 2, 26), + (214, 1, 260, 4, 23), + (214, 2, 260, 4, 24), + (214, 3, 260, 4, 25), + (214, 4, 260, 4, 26), + (215, 1, 260, 6, 23), + (215, 2, 260, 6, 24), + (215, 3, 260, 6, 25), + (215, 4, 260, 6, 26), + (225, 1, 272, 1, 0), + (226, 1, 272, 3, 0), + (227, 1, 272, 5, 0), + (230, 1, 275, 10, 0), + (231, 1, 275, 20, 0), + (232, 1, 275, 30, 0), + (237, 1, 227, 1, 25), + (238, 1, 227, 3, 25), + (239, 1, 227, 5, 25), + (240, 1, 224, 20, 26), + (240, 2, 173, 1, 0), + (241, 1, 224, 35, 26), + (241, 2, 173, 2, 0), + (242, 1, 224, 50, 26), + (242, 2, 173, 3, 0), + (244, 1, 268, 10, 56), + (244, 2, 234, 7500, 0), + (245, 1, 268, 25, 56), + (245, 2, 234, 5000, 0), + (246, 1, 268, 50, 56), + (246, 2, 234, 2500, 0), + (247, 1, 224, 15, 0), + (248, 1, 224, 30, 0), + (249, 1, 224, 50, 0), + (255, 1, 279, 7, 0), + (256, 1, 279, 11, 0), + (257, 1, 279, 15, 0), + (263, 1, 282, 10, 0), + (264, 1, 282, 25, 0), + (265, 1, 282, 50, 0), + (266, 1, 128, 50, 50), + (266, 2, 138, 1, 0), + (266, 3, 140, 1, 0), + (266, 4, 139, -2741, 0), + (266, 5, 139, -16843, 0), + (266, 6, 385, -16192, 0), + (266, 7, 385, -10547, 0), + (266, 8, 385, -13543, 0), + (267, 1, 294, 2, 100), + (268, 1, 294, 4, 100), + (269, 1, 294, 6, 100), + (273, 1, 288, 1000, 21), + (275, 1, 260, 2, 50), + (276, 1, 260, 4, 50), + (277, 1, 260, 6, 50), + (278, 1, 0, 1, 0), + (278, 2, 15, 1, 0), + (279, 1, 214, 200, 0), + (279, 2, 259, 2, 0), + (279, 3, 172, 2, 0), + (280, 1, 227, 1, 62), + (280, 2, 227, 1, 17), + (281, 1, 227, 3, 62), + (281, 2, 227, 3, 17), + (282, 1, 227, 5, 62), + (282, 2, 227, 5, 17), + (283, 1, 228, 10, 0), + (284, 1, 228, 20, 0), + (285, 1, 228, 30, 0), + (286, 1, 10, 0, 0), + (287, 1, 253, 1, 0), + (288, 1, 257, 1, 0), + (288, 2, 267, 1, 31), + (288, 3, 267, 1, 32), + (288, 4, 267, 1, 33), + (288, 5, 267, 1, 15), + (288, 6, 267, 1, 16), + (288, 7, 267, 1, 17), + (288, 8, 267, 1, 18), + (288, 9, 267, 1, 19), + (288, 10, 267, 1, 20), + (292, 1, 4, 12, 0), + (293, 1, 4, 14, 0), + (294, 1, 4, 16, 0), + (295, 1, 4, 18, 0), + (296, 1, 4, 20, 0), + (297, 1, 4, 22, 0), + (298, 1, 4, 24, 0), + (299, 1, 4, 26, 0), + (300, 1, 4, 28, 0), + (301, 1, 4, 30, 0), + (302, 1, 7, 12, 0), + (303, 1, 7, 14, 0), + (304, 1, 7, 16, 0), + (305, 1, 7, 18, 0), + (306, 1, 7, 20, 0), + (307, 1, 7, 22, 0), + (308, 1, 7, 24, 0), + (309, 1, 7, 26, 0), + (310, 1, 7, 28, 0), + (311, 1, 7, 30, 0), + (312, 1, 6, 12, 0), + (313, 1, 6, 14, 0), + (314, 1, 6, 16, 0), + (315, 1, 6, 18, 0), + (316, 1, 6, 20, 0), + (317, 1, 6, 22, 0), + (318, 1, 6, 24, 0), + (319, 1, 6, 26, 0), + (320, 1, 6, 28, 0), + (321, 1, 6, 30, 0), + (322, 1, 5, 12, 0), + (323, 1, 5, 14, 0), + (324, 1, 5, 16, 0), + (325, 1, 5, 18, 0), + (326, 1, 5, 20, 0), + (327, 1, 5, 22, 0), + (328, 1, 5, 24, 0), + (329, 1, 5, 26, 0), + (330, 1, 5, 28, 0), + (331, 1, 5, 30, 0), + (332, 1, 8, 12, 0), + (333, 1, 8, 14, 0), + (334, 1, 8, 16, 0), + (335, 1, 8, 18, 0), + (336, 1, 8, 20, 0), + (337, 1, 8, 22, 0), + (338, 1, 8, 24, 0), + (339, 1, 8, 26, 0), + (340, 1, 8, 28, 0), + (341, 1, 8, 30, 0), + (342, 1, 9, 12, 0), + (343, 1, 9, 14, 0), + (344, 1, 9, 16, 0), + (345, 1, 9, 18, 0), + (346, 1, 9, 20, 0), + (347, 1, 9, 22, 0), + (348, 1, 9, 24, 0), + (349, 1, 9, 26, 0), + (350, 1, 9, 28, 0), + (351, 1, 9, 30, 0), + (352, 1, 10, 12, 0), + (353, 1, 10, 14, 0), + (354, 1, 10, 16, 0), + (355, 1, 10, 18, 0), + (356, 1, 10, 20, 0), + (357, 1, 10, 22, 0), + (358, 1, 10, 24, 0), + (359, 1, 10, 26, 0), + (360, 1, 10, 28, 0), + (361, 1, 10, 30, 0), + (362, 1, 46, 12, 0), + (363, 1, 46, 14, 0), + (364, 1, 46, 16, 0), + (365, 1, 46, 18, 0), + (366, 1, 46, 20, 0), + (367, 1, 46, 22, 0), + (368, 1, 46, 24, 0), + (369, 1, 46, 26, 0), + (370, 1, 46, 28, 0), + (371, 1, 46, 30, 0), + (372, 1, 47, 12, 0), + (373, 1, 47, 14, 0), + (374, 1, 47, 16, 0), + (375, 1, 47, 18, 0), + (376, 1, 47, 20, 0), + (377, 1, 47, 22, 0), + (378, 1, 47, 24, 0), + (379, 1, 47, 26, 0), + (380, 1, 47, 28, 0), + (381, 1, 47, 30, 0), + (382, 1, 50, 12, 0), + (383, 1, 50, 14, 0), + (384, 1, 50, 16, 0), + (385, 1, 50, 18, 0), + (386, 1, 50, 20, 0), + (387, 1, 50, 22, 0), + (388, 1, 50, 24, 0), + (389, 1, 50, 26, 0), + (390, 1, 50, 28, 0), + (391, 1, 50, 30, 0), + (392, 1, 48, 12, 0), + (393, 1, 48, 14, 0), + (394, 1, 48, 16, 0), + (395, 1, 48, 18, 0), + (396, 1, 48, 20, 0), + (397, 1, 48, 22, 0), + (398, 1, 48, 24, 0), + (399, 1, 48, 26, 0), + (400, 1, 48, 28, 0), + (401, 1, 48, 30, 0), + (402, 1, 49, 12, 0), + (403, 1, 49, 14, 0), + (404, 1, 49, 16, 0), + (405, 1, 49, 18, 0), + (406, 1, 49, 20, 0), + (407, 1, 49, 22, 0), + (408, 1, 49, 24, 0), + (409, 1, 49, 26, 0), + (410, 1, 49, 28, 0), + (411, 1, 49, 30, 0), + (412, 1, 263, 1, 0), + (413, 1, 263, 2, 0), + (414, 1, 263, 3, 0), + (415, 1, 263, 4, 0), + (416, 1, 263, 5, 0), + (417, 1, 263, 6, 0), + (418, 1, 262, 5, 0), + (418, 2, 262, 5, 1), + (418, 3, 262, 5, 2), + (418, 4, 262, 5, 3), + (418, 5, 262, 5, 4), + (418, 6, 262, 5, 5), + (418, 7, 262, 5, 6), + (419, 1, 262, 10, 0), + (419, 2, 262, 10, 1), + (419, 3, 262, 10, 2), + (419, 4, 262, 10, 3), + (419, 5, 262, 10, 4), + (419, 6, 262, 10, 5), + (419, 7, 262, 10, 6), + (420, 1, 262, 15, 0), + (420, 2, 262, 15, 1), + (420, 3, 262, 15, 2), + (420, 4, 262, 15, 3), + (420, 5, 262, 15, 4), + (420, 6, 262, 15, 5), + (420, 7, 262, 15, 6), + (421, 1, 262, 20, 0), + (421, 2, 262, 20, 1), + (421, 3, 262, 20, 2), + (421, 4, 262, 20, 3), + (421, 5, 262, 20, 4), + (421, 6, 262, 20, 5), + (421, 7, 262, 20, 6), + (422, 1, 262, 25, 0), + (422, 2, 262, 25, 1), + (422, 3, 262, 25, 2), + (422, 4, 262, 25, 3), + (422, 5, 262, 25, 4), + (422, 6, 262, 25, 5), + (422, 7, 262, 25, 6), + (423, 1, 214, 150, 0), + (424, 1, 214, 300, 0), + (425, 1, 214, 450, 0), + (426, 1, 262, 10, 5), + (426, 2, 262, 10, 4), + (427, 1, 262, 20, 5), + (427, 2, 262, 20, 4), + (428, 1, 262, 30, 5), + (428, 2, 262, 30, 4), + (429, 1, 262, 40, 5), + (429, 2, 262, 40, 4), + (430, 1, 262, 50, 5), + (430, 2, 262, 50, 4), + (434, 1, 125, 13, 13), + (434, 2, 137, 0, 0), + (434, 3, 141, 1, 0), + (434, 4, 139, -6233, 0), + (434, 5, 139, -6265, 0), + (434, 6, 125, 13, 13), + (434, 7, 137, 147, 0), + (434, 8, 141, 1, 0), + (435, 1, 125, 16, 16), + (435, 2, 137, 0, 0), + (435, 3, 141, 1, 0), + (435, 4, 139, -6233, 0), + (435, 5, 139, -6265, 0), + (435, 6, 125, 16, 16), + (435, 7, 137, 147, 0), + (435, 8, 141, 1, 0), + (436, 1, 125, 19, 19), + (436, 2, 137, 0, 0), + (436, 3, 141, 1, 0), + (436, 4, 139, -6233, 0), + (436, 5, 139, -6265, 0), + (436, 6, 125, 19, 19), + (436, 7, 137, 147, 0), + (436, 8, 141, 1, 0), + (437, 1, 274, 12, 0), + (438, 1, 274, 14, 0), + (439, 1, 274, 16, 0), + (440, 1, 278, 530, 21210), + (440, 2, 440, 56, 100), + (441, 1, 278, 540, 23160), + (441, 2, 440, 58, 100), + (442, 1, 278, 550, 25230), + (442, 2, 440, 60, 100), + (443, 1, 169, 100, -1), + (444, 1, 169, 125, -1), + (445, 1, 169, 150, -1), + (446, 1, 265, 54, 0), + (447, 1, 265, 56, 0), + (448, 1, 265, 58, 0), + (449, 1, 172, 13, 0), + (450, 1, 172, 16, 0), + (451, 1, 172, 19, 0), + (452, 1, 172, 22, 0), + (453, 1, 172, 25, 0), + (454, 1, 259, 13, 0), + (455, 1, 259, 16, 0), + (456, 1, 259, 19, 0), + (457, 1, 259, 22, 0), + (458, 1, 259, 25, 0), + (462, 1, 264, 60, 39), + (462, 2, 264, 864, 1061), + (463, 1, 264, 120, 39), + (463, 2, 264, 1728, 1061), + (464, 1, 264, 180, 39), + (464, 2, 264, 2592, 1061), + (468, 1, 264, 180, 41), + (469, 1, 264, 360, 41), + (470, 1, 264, 540, 41), + (471, 1, 264, 864, 57), + (471, 2, 264, 864, 616), + (472, 1, 264, 1728, 57), + (472, 2, 264, 1728, 616), + (473, 1, 264, 2592, 57), + (473, 2, 264, 2592, 616), + (474, 1, 264, 240, 50), + (475, 1, 264, 480, 50), + (476, 1, 264, 720, 50), + (477, 1, 264, 432, 43), + (478, 1, 264, 864, 43), + (479, 1, 264, 1296, 43), + (480, 1, 264, 432, 117), + (481, 1, 264, 864, 117), + (482, 1, 264, 1296, 117), + (483, 1, 264, 540, 58), + (483, 2, 264, 540, 418), + (484, 1, 264, 1080, 58), + (484, 2, 264, 1080, 418), + (485, 1, 264, 1620, 58), + (485, 2, 264, 1620, 418), + (489, 1, 264, 90, 110), + (490, 1, 264, 180, 110), + (491, 1, 264, 270, 110), + (492, 1, 264, 60, 109), + (493, 1, 264, 120, 109), + (494, 1, 264, 180, 109), + (495, 1, 264, 180, 98), + (496, 1, 264, 360, 98), + (497, 1, 264, 540, 98), + (498, 1, 264, 144, 102), + (499, 1, 264, 288, 102), + (500, 1, 264, 432, 102), + (501, 1, 264, 432, 107), + (502, 1, 264, 864, 107), + (503, 1, 264, 1296, 107), + (504, 1, 224, 110, 0), + (505, 1, 224, 120, 0), + (506, 1, 224, 130, 0), + (537, 1, 282, 60, 0), + (538, 1, 282, 75, 0), + (539, 1, 275, 68, 0), + (540, 1, 275, 76, 0), + (541, 1, 275, 84, 0), + (542, 1, 279, 17, 0), + (543, 1, 279, 19, 0), + (544, 1, 279, 21, 0), + (551, 1, 225, 3, 0), + (552, 1, 225, 6, 0), + (553, 1, 225, 9, 0), + (554, 1, 225, 12, 0), + (555, 1, 225, 15, 0), + (556, 1, 225, 3, 0), + (557, 1, 225, 6, 0), + (558, 1, 225, 9, 0), + (559, 1, 225, 12, 0), + (560, 1, 225, 15, 0), + (561, 1, 177, 3, -1), + (562, 1, 177, 6, -1), + (563, 1, 177, 9, -1), + (564, 1, 177, 3, -1), + (565, 1, 177, 6, -1), + (566, 1, 177, 9, -1), + (567, 1, 244, -12, 0), + (574, 1, 281, 25, 0), + (575, 1, 281, 50, 0), + (576, 1, 281, 75, 0), + (577, 1, 277, 20, 0), + (578, 1, 277, 40, 0), + (579, 1, 277, 60, 0), + (580, 1, 267, 1, 4), + (580, 2, 267, 1, 5), + (580, 3, 267, 1, 29), + (581, 1, 267, 1, 2), + (581, 2, 267, 1, 3), + (581, 3, 267, 1, 4), + (581, 4, 267, 1, 5), + (581, 5, 267, 1, 29), + (582, 1, 267, 1, 0), + (582, 2, 267, 1, 1), + (582, 3, 267, 1, 2), + (582, 4, 267, 1, 3), + (582, 5, 267, 1, 4), + (582, 6, 267, 1, 4), + (582, 7, 267, 1, 5), + (582, 8, 267, 1, 6), + (582, 9, 267, 1, 7), + (582, 10, 267, 1, 8), + (582, 11, 267, 1, 9), + (582, 12, 267, 1, 10), + (582, 13, 267, 1, 11), + (582, 14, 267, 1, 12), + (582, 15, 267, 1, 13), + (582, 16, 267, 1, 14), + (582, 17, 267, 1, 28), + (582, 18, 267, 1, 29), + (582, 19, 267, 1, 30), + (583, 1, 264, 7, 73), + (583, 2, 264, 7, 702), + (583, 3, 264, 7, 3826), + (583, 4, 264, 7, 7712), + (584, 1, 264, 14, 73), + (584, 2, 264, 14, 702), + (584, 3, 264, 14, 3826), + (584, 4, 264, 14, 7712), + (585, 1, 264, 21, 73), + (585, 2, 264, 21, 702), + (585, 3, 264, 21, 3826), + (585, 4, 264, 21, 7712), + (586, 1, 255, 12, 0), + (587, 1, 255, 24, 0), + (588, 1, 255, 36, 0), + (589, 1, 303, 500, 500), + (589, 2, 139, 2766, 0), + (590, 1, 303, 1000, 1000), + (590, 2, 139, 2766, 0), + (591, 1, 303, 1500, 1500), + (591, 2, 139, 2766, 0), + (593, 1, 264, 720, 6001), + (593, 2, 264, 720, 3676), + (594, 1, 264, 1440, 6001), + (594, 2, 264, 1440, 3676), + (595, 1, 264, 2160, 6001), + (595, 2, 264, 2160, 3676), + (596, 1, 264, 720, 6000), + (596, 2, 264, 720, 87), + (597, 1, 264, 1440, 6000), + (597, 2, 264, 1440, 87), + (598, 1, 264, 2160, 6000), + (598, 2, 264, 2160, 87), + (599, 1, 266, 2, 0), + (600, 1, 266, 5, 0), + (601, 1, 266, 8, 0), + (602, 1, 266, 2, 0), + (603, 1, 266, 5, 0), + (604, 1, 266, 8, 0), + (605, 1, 256, 1, 0), + (606, 1, 285, 20, 0), + (607, 1, 285, 40, 0), + (608, 1, 285, 60, 0), + (609, 1, 285, 80, 0), + (610, 1, 285, 100, 0), + (611, 1, 283, 20, 0), + (612, 1, 283, 40, 0), + (613, 1, 283, 60, 0), + (614, 1, 283, 80, 0), + (615, 1, 283, 100, 0), + (622, 1, 227, 1, 29), + (622, 2, 227, 1, 42), + (623, 1, 227, 2, 29), + (623, 2, 227, 2, 42), + (624, 1, 227, 3, 29), + (624, 2, 227, 3, 42), + (625, 1, 294, 3, 100), + (626, 1, 294, 6, 100), + (627, 1, 294, 9, 100), + (628, 1, 290, 5, 0), + (629, 1, 290, 10, 0), + (631, 1, 292, 15, 0), + (632, 1, 292, 30, 0), + (633, 1, 292, 45, 0), + (634, 1, 274, 3, 0), + (635, 1, 274, 6, 0), + (636, 1, 274, 10, 0), + (637, 1, 294, 2, 100), + (638, 1, 294, 4, 100), + (639, 1, 294, 6, 100), + (640, 1, 294, 7, 100), + (641, 1, 294, 8, 100), + (642, 1, 294, 9, 100), + (644, 1, 217, 0, 32000), + (644, 2, 346, 59, 0), + (649, 1, 243, 15, 0), + (650, 1, 243, 25, 0), + (651, 1, 243, 35, 0), + (652, 1, 293, 25, 0), + (653, 1, 293, 50, 0), + (654, 1, 293, 75, 0), + (655, 1, 127, 10, 10), + (655, 2, 137, 32, 0), + (655, 3, 127, 10, 10), + (655, 4, 137, 33, 0), + (655, 5, 127, 10, 10), + (655, 6, 137, 82, 0), + (655, 7, 127, 2, 2), + (655, 8, 137, 152, 0), + (655, 9, 143, 3000, 0), + (656, 1, 127, 25, 25), + (656, 2, 137, 32, 0), + (656, 3, 127, 25, 25), + (656, 4, 137, 33, 0), + (656, 5, 127, 25, 25), + (656, 6, 137, 82, 0), + (656, 7, 127, 5, 5), + (656, 8, 137, 152, 0), + (656, 9, 143, 3000, 0), + (657, 1, 127, 50, 50), + (657, 2, 137, 32, 0), + (657, 3, 127, 50, 50), + (657, 4, 137, 33, 0), + (657, 5, 127, 50, 50), + (657, 6, 137, 82, 0), + (657, 7, 127, 10, 10), + (657, 8, 137, 152, 0), + (657, 9, 143, 3000, 0), + (658, 1, 15, 1, 0), + (659, 1, 15, 2, 0), + (660, 1, 15, 3, 0), + (661, 1, 0, 1, 0), + (662, 1, 0, 2, 0), + (663, 1, 0, 3, 0), + (665, 1, 270, 10, 0), + (666, 1, 270, 15, 0), + (667, 1, 270, 25, 0), + (668, 1, 270, 55, 0), + (669, 1, 270, 60, 0), + (670, 1, 270, 65, 0), + (671, 1, 241, 95, 0), + (672, 1, 271, 28, 0), + (673, 1, 271, 35, 0), + (674, 1, 0, 4, 0), + (675, 1, 0, 5, 0), + (676, 1, 246, 325, 0), + (677, 1, 246, 350, 0), + (678, 1, 221, 3, 0), + (679, 1, 221, 6, 0), + (680, 1, 221, 9, 0), + (681, 1, 221, 12, 0), + (682, 1, 221, 15, 0), + (683, 1, 189, 1, 0), + (684, 1, 189, 2, 0), + (685, 1, 189, 3, 0), + (686, 1, 200, 10, 0), + (687, 1, 200, 20, 0), + (688, 1, 200, 30, 0), + (689, 1, 200, 40, 0), + (690, 1, 200, 50, 0), + (691, 1, 248, 100, 0), + (692, 1, 229, 5, 0), + (693, 1, 229, 10, 0), + (694, 1, 229, 15, 0), + (695, 1, 247, 10, 53), + (696, 1, 247, 20, 53), + (697, 1, 247, 30, 53), + (698, 1, 247, 40, 53), + (699, 1, 247, 50, 53), + (700, 1, 260, 8, 23), + (700, 2, 260, 8, 24), + (700, 3, 260, 8, 25), + (700, 4, 260, 8, 26), + (701, 1, 260, 8, 50), + (724, 1, 218, 1, 0), + (725, 1, 218, 2, 0), + (726, 1, 218, 3, 0), + (727, 1, 218, 4, 0), + (728, 1, 218, 5, 0), + (729, 1, 280, 4, 0), + (730, 1, 280, 8, 0), + (731, 1, 280, 12, 0), + (732, 1, 280, 16, 0), + (733, 1, 280, 20, 0), + (734, 1, 237, 1, 0), + (735, 1, 265, 54, 0), + (736, 1, 265, 56, 0), + (737, 1, 265, 58, 0), + (738, 1, 114, -5, 0), + (739, 1, 114, -10, 0), + (740, 1, 114, -20, 0), + (754, 1, 264, 18, 153), + (755, 1, 264, 36, 153), + (756, 1, 264, 54, 153), + (762, 1, 247, 10, 53), + (763, 1, 247, 20, 53), + (764, 1, 247, 30, 53), + (765, 1, 247, 40, 53), + (766, 1, 247, 50, 53), + (767, 1, 273, 3, 0), + (768, 1, 273, 6, 0), + (769, 1, 273, 9, 0), + (770, 1, 294, 7, 100), + (771, 1, 294, 8, 100), + (772, 1, 294, 9, 100), + (776, 1, 242, 10, 0), + (777, 1, 242, 20, 0), + (778, 1, 242, 30, 0), + (779, 1, 242, 40, 0), + (780, 1, 242, 50, 0), + (781, 1, 287, 1, 1), + (781, 2, 137, 31, 0), + (781, 3, 136, 5, 0), + (782, 1, 264, 432, 35), + (783, 1, 264, 864, 35), + (784, 1, 264, 1296, 35), + (790, 1, 218, 1, 0), + (791, 1, 218, 2, 0), + (792, 1, 218, 3, 0), + (793, 1, 218, 4, 0), + (794, 1, 218, 5, 0), + (795, 1, 280, 4, 0), + (796, 1, 280, 8, 0), + (797, 1, 280, 12, 0), + (798, 1, 280, 16, 0), + (799, 1, 280, 20, 0), + (800, 1, 215, 2, 0), + (801, 1, 215, 5, 0), + (802, 1, 215, 10, 0), + (803, 1, 213, 2, 0), + (804, 1, 213, 5, 0), + (805, 1, 213, 10, 0), + (806, 1, 249, 1, 0), + (807, 1, 292, 5, 0), + (808, 1, 292, 10, 0), + (809, 1, 292, 15, 0), + (810, 1, 239, 10, 0), + (811, 1, 239, 20, 0), + (812, 1, 239, 30, 0), + (813, 1, 239, 40, 0), + (814, 1, 239, 50, 0), + (815, 1, 279, 7, 0), + (816, 1, 279, 11, 0), + (817, 1, 279, 15, 0), + (818, 1, 279, 17, 0), + (819, 1, 279, 19, 0), + (820, 1, 220, 10, 26), + (820, 2, 220, 10, 30), + (820, 3, 220, 10, 38), + (821, 1, 220, 20, 26), + (821, 2, 220, 20, 30), + (821, 3, 220, 20, 38), + (822, 1, 220, 30, 26), + (822, 2, 220, 30, 30), + (822, 3, 220, 30, 38), + (823, 1, 222, 20, 0), + (824, 1, 222, 40, 0), + (825, 1, 222, 60, 0), + (826, 1, 222, 80, 0), + (827, 1, 222, 100, 0), + (834, 1, 218, 1, 0), + (835, 1, 218, 2, 0), + (836, 1, 218, 3, 0), + (837, 1, 218, 4, 0), + (838, 1, 218, 5, 0), + (839, 1, 280, 4, 0), + (840, 1, 280, 8, 0), + (841, 1, 280, 12, 0), + (842, 1, 280, 16, 0), + (843, 1, 280, 20, 0), + (844, 1, 274, 12, 0), + (845, 1, 274, 14, 0), + (846, 1, 258, 5, 0), + (847, 1, 258, 10, 0), + (848, 1, 258, 15, 0), + (849, 1, 264, 240, 180), + (850, 1, 264, 480, 180), + (851, 1, 264, 720, 180), + (852, 1, 231, 1, 0), + (853, 1, 231, 2, 0), + (854, 1, 231, 3, 0), + (855, 1, 220, 5, 10), + (856, 1, 220, 10, 10), + (857, 1, 220, 15, 10), + (858, 1, 220, 20, 10), + (859, 1, 220, 25, 10), + (864, 1, 216, 10, 0), + (864, 2, 216, 10, 1), + (864, 3, 216, 10, 2), + (864, 4, 216, 10, 3), + (864, 5, 216, 10, 10), + (864, 6, 216, 10, 28), + (864, 7, 216, 10, 30), + (864, 8, 216, 10, 36), + (864, 9, 216, 10, 77), + (865, 1, 216, 20, 0), + (865, 2, 216, 20, 1), + (865, 3, 216, 20, 2), + (865, 4, 216, 20, 3), + (865, 5, 216, 20, 10), + (865, 6, 216, 20, 28), + (865, 7, 216, 20, 30), + (865, 8, 216, 20, 36), + (865, 9, 216, 20, 77), + (866, 1, 216, 30, 0), + (866, 2, 216, 30, 1), + (866, 3, 216, 30, 2), + (866, 4, 216, 30, 3), + (866, 5, 216, 30, 10), + (866, 6, 216, 30, 28), + (866, 7, 216, 30, 30), + (866, 8, 216, 30, 36), + (866, 9, 216, 30, 77), + (867, 1, 59, -3, 0), + (868, 1, 59, -6, 0), + (869, 1, 59, -9, 0), + (870, 1, 59, -12, 0), + (871, 1, 59, -15, 0), + (878, 1, 252, 10, 0), + (879, 1, 252, 20, 0), + (880, 1, 252, 30, 0), + (881, 1, 245, 10, 0), + (882, 1, 245, 20, 0), + (883, 1, 245, 30, 0), + (884, 1, 245, 40, 0), + (885, 1, 245, 50, 0), + (886, 1, 264, 576, 102), + (887, 1, 264, 720, 102), + (888, 1, 250, 10, 0), + (889, 1, 250, 20, 0), + (890, 1, 250, 30, 0), + (891, 1, 250, 40, 0), + (892, 1, 250, 50, 0), + (893, 1, 303, 2000, 2000), + (893, 2, 139, 2766, 0), + (894, 1, 303, 2500, 2500), + (894, 2, 139, 2766, 0), + (895, 1, 59, -3, 0), + (896, 1, 59, -6, 0), + (897, 1, 59, -9, 0), + (898, 1, 59, -12, 0), + (899, 1, 59, -15, 0), + (907, 1, 69, 100, 0), + (908, 1, 69, 200, 0), + (909, 1, 69, 300, 0), + (910, 1, 69, 400, 0), + (911, 1, 69, 500, 0), + (915, 1, 220, 5, 10), + (915, 2, 220, 5, 30), + (916, 1, 220, 10, 10), + (916, 2, 220, 10, 30), + (917, 1, 220, 15, 10), + (917, 2, 220, 15, 30), + (918, 1, 230, 2, 0), + (919, 1, 230, 4, 0), + (920, 1, 230, 6, 0), + (924, 1, 294, 10, 100), + (925, 1, 294, 11, 100), + (934, 1, 169, 15, -1), + (935, 1, 169, 30, -1), + (936, 1, 169, 60, -1), + (937, 1, 169, 15, 0), + (937, 2, 169, 15, 1), + (937, 3, 169, 15, 2), + (937, 4, 169, 15, 3), + (937, 5, 169, 15, 7), + (937, 6, 169, 15, 8), + (937, 7, 169, 15, 10), + (937, 8, 169, 15, 28), + (937, 9, 169, 15, 30), + (937, 10, 169, 15, 36), + (937, 11, 169, 15, 51), + (938, 1, 169, 40, 0), + (938, 2, 169, 40, 1), + (938, 3, 169, 40, 2), + (938, 4, 169, 40, 3), + (938, 5, 169, 40, 7), + (938, 6, 169, 40, 8), + (938, 7, 169, 40, 10), + (938, 8, 169, 40, 28), + (938, 9, 169, 40, 30), + (938, 10, 169, 40, 36), + (938, 11, 169, 30, 51), + (939, 1, 169, 75, 0), + (939, 2, 169, 75, 1), + (939, 3, 169, 75, 2), + (939, 4, 169, 75, 3), + (939, 5, 169, 75, 7), + (939, 6, 169, 75, 8), + (939, 7, 169, 75, 10), + (939, 8, 169, 75, 28), + (939, 9, 169, 75, 30), + (939, 10, 169, 75, 36), + (939, 11, 169, 60, 51), + (940, 1, 169, 15, 0), + (940, 2, 169, 15, 1), + (940, 3, 169, 15, 2), + (940, 4, 169, 15, 3), + (940, 5, 169, 15, 7), + (940, 6, 169, 15, 8), + (940, 7, 169, 15, 10), + (940, 8, 169, 15, 28), + (940, 9, 169, 15, 30), + (940, 10, 169, 15, 36), + (940, 11, 169, 15, 51), + (940, 12, 169, 15, 77), + (941, 1, 169, 40, 0), + (941, 2, 169, 40, 1), + (941, 3, 169, 40, 2), + (941, 4, 169, 40, 3), + (941, 5, 169, 30, 7), + (941, 6, 169, 40, 8), + (941, 7, 169, 40, 10), + (941, 8, 169, 40, 28), + (941, 9, 169, 40, 30), + (941, 10, 169, 40, 36), + (941, 11, 169, 40, 51), + (941, 12, 169, 40, 77), + (942, 1, 169, 75, 0), + (942, 2, 169, 75, 1), + (942, 3, 169, 75, 2), + (942, 4, 169, 75, 3), + (942, 5, 169, 60, 7), + (942, 6, 169, 75, 8), + (942, 7, 169, 75, 10), + (942, 8, 169, 75, 28), + (942, 9, 169, 75, 30), + (942, 10, 169, 75, 36), + (942, 11, 169, 75, 51), + (942, 12, 169, 75, 77), + (943, 1, 169, 146, -1), + (944, 1, 169, 172, -1), + (945, 1, 169, 198, -1), + (946, 1, 169, 175, 0), + (946, 2, 169, 175, 1), + (946, 3, 169, 175, 2), + (946, 4, 169, 175, 3), + (946, 5, 169, 175, 7), + (946, 6, 169, 175, 8), + (946, 7, 169, 175, 10), + (946, 8, 169, 175, 28), + (946, 9, 169, 175, 30), + (946, 10, 169, 175, 36), + (946, 11, 169, 146, 51), + (947, 1, 169, 200, 0), + (947, 2, 169, 200, 1), + (947, 3, 169, 200, 2), + (947, 4, 169, 200, 3), + (947, 5, 169, 200, 7), + (947, 6, 169, 200, 8), + (947, 7, 169, 200, 10), + (947, 8, 169, 200, 28), + (947, 9, 169, 200, 30), + (947, 10, 169, 200, 36), + (947, 11, 169, 172, 51), + (948, 1, 169, 225, 0), + (948, 2, 169, 225, 1), + (948, 3, 169, 225, 2), + (948, 4, 169, 225, 3), + (948, 5, 169, 225, 7), + (948, 6, 169, 225, 8), + (948, 7, 169, 225, 10), + (948, 8, 169, 225, 28), + (948, 9, 169, 225, 30), + (948, 10, 169, 225, 36), + (948, 11, 169, 198, 51), + (949, 1, 169, 175, 0), + (949, 2, 169, 175, 1), + (949, 3, 169, 175, 2), + (949, 4, 169, 175, 3), + (949, 5, 169, 161, 7), + (949, 6, 169, 175, 8), + (949, 7, 169, 175, 10), + (949, 8, 169, 175, 28), + (949, 9, 169, 175, 30), + (949, 10, 169, 175, 36), + (949, 11, 169, 175, 51), + (949, 12, 169, 175, 77), + (950, 1, 169, 200, 0), + (950, 2, 169, 200, 1), + (950, 3, 169, 200, 2), + (950, 4, 169, 200, 3), + (950, 5, 169, 187, 7), + (950, 6, 169, 200, 8), + (950, 7, 169, 200, 10), + (950, 8, 169, 200, 28), + (950, 9, 169, 200, 30), + (950, 10, 169, 200, 36), + (950, 11, 169, 200, 51), + (950, 12, 169, 200, 77), + (951, 1, 169, 225, 0), + (951, 2, 169, 225, 1), + (951, 3, 169, 225, 2), + (951, 4, 169, 225, 3), + (951, 5, 169, 213, 7), + (951, 6, 169, 225, 8), + (951, 7, 169, 225, 10), + (951, 8, 169, 225, 28), + (951, 9, 169, 225, 30), + (951, 10, 169, 225, 36), + (951, 11, 169, 225, 51), + (951, 12, 169, 225, 77), + (952, 1, 214, 125, 0), + (953, 1, 214, 250, 0), + (954, 1, 214, 375, 0), + (955, 1, 262, 10, 4), + (955, 2, 262, 10, 5), + (956, 1, 262, 20, 4), + (956, 2, 262, 20, 5), + (957, 1, 262, 30, 4), + (957, 2, 262, 30, 5), + (958, 1, 262, 40, 4), + (958, 2, 262, 40, 5), + (959, 1, 262, 50, 4), + (959, 2, 262, 50, 5), + (962, 1, 232, 2, 4544), + (963, 1, 232, 4, 4544), + (964, 1, 232, 6, 4544), + (965, 1, 232, 8, 4544), + (966, 1, 232, 10, 4544), + (975, 1, 264, 864, 102), + (976, 1, 131, 100, 0), + (976, 2, 137, 33, 0), + (978, 1, 14, 1, 0), + (978, 2, 246, 350, 0), + (979, 1, 268, 10, 63), + (980, 1, 268, 25, 63), + (981, 1, 268, 50, 63), + (982, 1, 268, 10, 60), + (983, 1, 268, 25, 60), + (984, 1, 268, 50, 60), + (985, 1, 268, 10, 65), + (986, 1, 268, 25, 65), + (987, 1, 268, 50, 65), + (988, 1, 268, 10, 64), + (989, 1, 268, 25, 64), + (990, 1, 268, 50, 64), + (991, 1, 268, 10, 69), + (992, 1, 268, 25, 69), + (993, 1, 268, 50, 69), + (994, 1, 268, 10, 61), + (995, 1, 268, 25, 61), + (996, 1, 268, 50, 61), + (997, 1, 331, 5, 0), + (998, 1, 331, 15, 0), + (999, 1, 331, 25, 0), + (1001, 1, 262, 30, 0), + (1001, 2, 262, 30, 1), + (1001, 3, 262, 30, 2), + (1001, 4, 262, 30, 3), + (1001, 5, 262, 30, 4), + (1001, 6, 262, 30, 5), + (1001, 7, 262, 30, 6), + (1002, 1, 262, 35, 0), + (1002, 2, 262, 35, 1), + (1002, 3, 262, 35, 2), + (1002, 4, 262, 35, 3), + (1002, 5, 262, 35, 4), + (1002, 6, 262, 35, 5), + (1002, 7, 262, 35, 6), + (1003, 1, 262, 40, 0), + (1003, 2, 262, 40, 1), + (1003, 3, 262, 40, 2), + (1003, 4, 262, 40, 3), + (1003, 5, 262, 40, 4), + (1003, 6, 262, 40, 5), + (1003, 7, 262, 40, 6), + (1004, 1, 262, 45, 0), + (1004, 2, 262, 45, 1), + (1004, 3, 262, 45, 2), + (1004, 4, 262, 45, 3), + (1004, 5, 262, 45, 4), + (1004, 6, 262, 45, 5), + (1004, 7, 262, 45, 6), + (1005, 1, 262, 50, 0), + (1005, 2, 262, 50, 1), + (1005, 3, 262, 50, 2), + (1005, 4, 262, 50, 3), + (1005, 5, 262, 50, 4), + (1005, 6, 262, 50, 5), + (1005, 7, 262, 50, 6), + (1006, 1, 262, 5, 7), + (1006, 2, 262, 5, 8), + (1006, 3, 262, 5, 9), + (1006, 4, 262, 5, 10), + (1006, 5, 262, 5, 11), + (1007, 1, 262, 10, 7), + (1007, 2, 262, 10, 8), + (1007, 3, 262, 10, 9), + (1007, 4, 262, 10, 10), + (1007, 5, 262, 10, 11), + (1008, 1, 262, 15, 7), + (1008, 2, 262, 15, 8), + (1008, 3, 262, 15, 9), + (1008, 4, 262, 15, 10), + (1008, 5, 262, 15, 11), + (1009, 1, 262, 20, 7), + (1009, 2, 262, 20, 8), + (1009, 3, 262, 20, 9), + (1009, 4, 262, 20, 10), + (1009, 5, 262, 20, 11), + (1010, 1, 262, 25, 7), + (1010, 2, 262, 25, 8), + (1010, 3, 262, 25, 9), + (1010, 4, 262, 25, 10), + (1010, 5, 262, 25, 11), + (1011, 1, 262, 8, 7), + (1011, 2, 262, 8, 8), + (1011, 3, 262, 8, 9), + (1011, 4, 262, 8, 10), + (1011, 5, 262, 8, 11), + (1012, 1, 262, 16, 7), + (1012, 2, 262, 16, 8), + (1012, 3, 262, 16, 9), + (1012, 4, 262, 16, 10), + (1012, 5, 262, 16, 11), + (1013, 1, 262, 24, 7), + (1013, 2, 262, 24, 8), + (1013, 3, 262, 24, 9), + (1013, 4, 262, 24, 10), + (1013, 5, 262, 24, 11), + (1014, 1, 262, 32, 7), + (1014, 2, 262, 32, 8), + (1014, 3, 262, 32, 9), + (1014, 4, 262, 32, 10), + (1014, 5, 262, 32, 11), + (1016, 1, 262, 50, 7), + (1016, 2, 262, 50, 8), + (1016, 3, 262, 50, 9), + (1016, 4, 262, 50, 10), + (1016, 5, 262, 50, 11), + (1021, 1, 327, 1, 0), + (1022, 1, 327, 2, 0), + (1023, 1, 327, 3, 0), + (1024, 1, 327, 4, 0), + (1025, 1, 327, 5, 0), + (1026, 1, 328, 50, 0), + (1027, 1, 328, 100, 0), + (1028, 1, 328, 150, 0), + (1029, 1, 328, 200, 0), + (1030, 1, 328, 250, 0), + (1031, 1, 0, 6, 0), + (1032, 1, 0, 7, 0), + (1033, 1, 0, 8, 0), + (1034, 1, 0, 9, 0), + (1035, 1, 0, 10, 0), + (1036, 1, 189, 4, 0), + (1037, 1, 189, 5, 0), + (1038, 1, 189, 6, 0), + (1041, 1, 330, 25, 0), + (1041, 2, 330, 25, 1), + (1041, 3, 330, 25, 2), + (1041, 4, 330, 25, 3), + (1041, 5, 330, 25, 28), + (1041, 6, 330, 25, 36), + (1041, 7, 330, 25, 77), + (1042, 1, 330, 50, 0), + (1042, 2, 330, 50, 1), + (1042, 3, 330, 50, 2), + (1042, 4, 330, 50, 3), + (1042, 5, 330, 50, 28), + (1042, 6, 330, 50, 36), + (1042, 7, 330, 50, 77), + (1043, 1, 330, 75, 0), + (1043, 2, 330, 75, 1), + (1043, 3, 330, 75, 2), + (1043, 4, 330, 75, 3), + (1043, 5, 330, 75, 28), + (1043, 6, 330, 75, 36), + (1043, 7, 330, 75, 77), + (1044, 1, 330, 25, 0), + (1044, 2, 330, 25, 1), + (1044, 3, 330, 25, 2), + (1044, 4, 330, 25, 3), + (1044, 5, 330, 25, 28), + (1044, 6, 330, 25, 36), + (1045, 1, 330, 50, 0), + (1045, 2, 330, 50, 1), + (1045, 3, 330, 50, 2), + (1045, 4, 330, 50, 3), + (1045, 5, 330, 50, 28), + (1045, 6, 330, 50, 36), + (1046, 1, 330, 75, 0), + (1046, 2, 330, 75, 1), + (1046, 3, 330, 75, 2), + (1046, 4, 330, 75, 3), + (1046, 5, 330, 75, 28), + (1046, 6, 330, 75, 36), + (1047, 1, 330, 25, 0), + (1047, 2, 330, 25, 1), + (1047, 3, 330, 25, 2), + (1047, 4, 330, 25, 3), + (1047, 5, 330, 25, 28), + (1047, 6, 330, 25, 36), + (1047, 7, 330, 25, 77), + (1048, 1, 330, 50, 0), + (1048, 2, 330, 50, 1), + (1048, 3, 330, 50, 2), + (1048, 4, 330, 50, 3), + (1048, 5, 330, 50, 28), + (1048, 6, 330, 50, 36), + (1048, 7, 330, 50, 77), + (1049, 1, 330, 75, 0), + (1049, 2, 330, 75, 1), + (1049, 3, 330, 75, 2), + (1049, 4, 330, 75, 3), + (1049, 5, 330, 75, 28), + (1049, 6, 330, 75, 36), + (1049, 7, 330, 75, 77), + (1050, 1, 330, 15, 0), + (1050, 2, 330, 15, 1), + (1050, 3, 330, 15, 2), + (1050, 4, 330, 15, 3), + (1050, 5, 330, 15, 28), + (1050, 6, 330, 15, 36), + (1050, 7, 330, 15, 77), + (1051, 1, 330, 30, 0), + (1051, 2, 330, 30, 1), + (1051, 3, 330, 30, 2), + (1051, 4, 330, 30, 3), + (1051, 5, 330, 30, 28), + (1051, 6, 330, 30, 36), + (1051, 7, 330, 30, 77), + (1052, 1, 330, 50, 0), + (1052, 2, 330, 50, 1), + (1052, 3, 330, 50, 2), + (1052, 4, 330, 50, 3), + (1052, 5, 330, 50, 28), + (1052, 6, 330, 50, 36), + (1052, 7, 330, 50, 77), + (1053, 1, 278, 560, 27200), + (1053, 2, 440, 61, 100), + (1054, 1, 278, 580, 30135), + (1054, 2, 440, 63, 100), + (1055, 1, 278, 600, 32780), + (1055, 2, 440, 65, 100), + (1056, 1, 317, 1, 0), + (1057, 1, 317, 2, 0), + (1058, 1, 317, 3, 0), + (1059, 1, 317, 4, 0), + (1060, 1, 317, 5, 0), + (1061, 1, 172, 26, 0), + (1062, 1, 172, 27, 0), + (1063, 1, 172, 28, 0), + (1064, 1, 172, 30, 0), + (1065, 1, 172, 32, 0), + (1066, 1, 259, 27, 0), + (1067, 1, 259, 29, 0), + (1068, 1, 259, 31, 0), + (1069, 1, 259, 33, 0), + (1070, 1, 259, 35, 0), + (1071, 1, 326, 1, 0), + (1072, 1, 318, 1, 0), + (1073, 1, 318, 2, 0), + (1074, 1, 318, 3, 0), + (1075, 1, 318, 4, 0), + (1076, 1, 318, 5, 0), + (1083, 1, 125, 22, 22), + (1083, 2, 137, 0, 0), + (1083, 3, 141, 1, 0), + (1083, 4, 139, -6233, 0), + (1083, 5, 139, -6265, 0), + (1083, 6, 125, 22, 22), + (1083, 7, 137, 147, 0), + (1083, 8, 141, 1, 0), + (1084, 1, 125, 25, 25), + (1084, 2, 137, 0, 0), + (1084, 3, 141, 1, 0), + (1084, 4, 139, -6233, 0), + (1084, 5, 139, -6265, 0), + (1084, 6, 125, 25, 25), + (1084, 7, 137, 147, 0), + (1084, 8, 141, 1, 0), + (1085, 1, 125, 28, 28), + (1085, 2, 137, 0, 0), + (1085, 3, 141, 1, 0), + (1085, 4, 139, -6233, 0), + (1085, 5, 139, -6265, 0), + (1085, 6, 125, 28, 28), + (1085, 7, 137, 147, 0), + (1085, 8, 141, 1, 0), + (1086, 1, 274, 18, 0), + (1087, 1, 274, 20, 0), + (1088, 1, 274, 22, 0), + (1089, 1, 268, 10, 58), + (1090, 1, 268, 25, 58), + (1091, 1, 268, 50, 58), + (1092, 1, 238, 1, 0), + (1093, 1, 304, -20, 0), + (1094, 1, 304, -40, 0), + (1095, 1, 304, -60, 0), + (1096, 1, 304, -80, 0), + (1097, 1, 304, -100, 0), + (1099, 1, 273, 12, 0), + (1100, 1, 273, 15, 0), + (1101, 1, 273, 18, 0), + (1107, 1, 294, 2, 100), + (1108, 1, 294, 4, 100), + (1109, 1, 294, 6, 100), + (1113, 1, 331, 30, 0), + (1114, 1, 331, 35, 0), + (1115, 1, 331, 40, 0), + (1122, 1, 308, 1, 0), + (1129, 1, 267, 1, 24), + (1129, 2, 267, 1, 25), + (1129, 3, 267, 1, 26), + (1130, 1, 267, 1, 18), + (1130, 2, 267, 1, 19), + (1130, 3, 267, 1, 20), + (1130, 4, 267, 1, 21), + (1130, 5, 267, 1, 22), + (1130, 6, 267, 1, 23), + (1130, 7, 267, 1, 24), + (1130, 8, 267, 1, 25), + (1130, 9, 267, 1, 26), + (1131, 1, 185, 10, 51), + (1132, 1, 185, 20, 51), + (1133, 1, 185, 30, 51), + (1134, 1, 220, 32, 74), + (1135, 1, 220, 64, 74), + (1136, 1, 220, 96, 74), + (1137, 1, 310, 180000, 0), + (1137, 2, 139, 5027, 0), + (1137, 3, 310, 180000, 0), + (1137, 4, 139, 5028, 0), + (1137, 5, 310, 180000, 0), + (1137, 6, 139, 5029, 0), + (1137, 7, 310, 180000, 0), + (1137, 8, 139, 5030, 0), + (1137, 9, 310, 180000, 0), + (1137, 10, 139, 5031, 0), + (1137, 11, 310, 180000, 0), + (1137, 12, 139, 5032, 0), + (1137, 13, 310, 180000, 0), + (1137, 14, 139, 8476, 0), + (1138, 1, 310, 360000, 0), + (1138, 2, 139, 5027, 0), + (1138, 3, 310, 360000, 0), + (1138, 4, 139, 5028, 0), + (1138, 5, 310, 360000, 0), + (1138, 6, 139, 5029, 0), + (1138, 7, 310, 360000, 0), + (1138, 8, 139, 5030, 0), + (1138, 9, 310, 360000, 0), + (1138, 10, 139, 5031, 0), + (1138, 11, 310, 360000, 0), + (1138, 12, 139, 5032, 0), + (1138, 13, 310, 360000, 0), + (1138, 14, 139, 8476, 0), + (1139, 1, 310, 540000, 0), + (1139, 2, 139, 5027, 0), + (1139, 3, 310, 540000, 0), + (1139, 4, 139, 5028, 0), + (1139, 5, 310, 540000, 0), + (1139, 6, 139, 5029, 0), + (1139, 7, 310, 540000, 0), + (1139, 8, 139, 5030, 0), + (1139, 9, 310, 540000, 0), + (1139, 10, 139, 5031, 0), + (1139, 11, 310, 540000, 0), + (1139, 12, 139, 5032, 0), + (1139, 13, 310, 540000, 0), + (1139, 14, 139, 8476, 0), + (1140, 1, 216, 10, 51), + (1141, 1, 216, 20, 51), + (1142, 1, 216, 30, 51), + (1155, 1, 128, 25, 0), + (1155, 2, 139, 5027, 0), + (1155, 3, 128, 25, 0), + (1155, 4, 139, 5028, 0), + (1155, 5, 128, 25, 0), + (1155, 6, 139, 5029, 0), + (1155, 7, 128, 25, 0), + (1155, 8, 139, 5030, 0), + (1155, 9, 128, 25, 0), + (1155, 10, 139, 5031, 0), + (1155, 11, 128, 25, 0), + (1155, 12, 139, 5032, 0), + (1155, 13, 128, 25, 0), + (1155, 14, 139, 8476, 0), + (1156, 1, 128, 50, 0), + (1156, 2, 139, 5027, 0), + (1156, 3, 128, 50, 0), + (1156, 4, 139, 5028, 0), + (1156, 5, 128, 50, 0), + (1156, 6, 139, 5029, 0), + (1156, 7, 128, 50, 0), + (1156, 8, 139, 5030, 0), + (1156, 9, 128, 50, 0), + (1156, 10, 139, 5031, 0), + (1156, 11, 128, 50, 0), + (1156, 12, 139, 5032, 0), + (1156, 13, 128, 50, 0), + (1156, 14, 139, 8476, 0), + (1157, 1, 128, 100, 0), + (1157, 2, 139, 5027, 0), + (1157, 3, 128, 100, 0), + (1157, 4, 139, 5028, 0), + (1157, 5, 128, 100, 0), + (1157, 6, 139, 5029, 0), + (1157, 7, 128, 100, 0), + (1157, 8, 139, 5030, 0), + (1157, 9, 128, 100, 0), + (1157, 10, 139, 5031, 0), + (1157, 11, 128, 100, 0), + (1157, 12, 139, 5032, 0), + (1157, 13, 128, 100, 0), + (1157, 14, 139, 8476, 0), + (1158, 1, 220, 128, 74), + (1159, 1, 220, 160, 74), + (1160, 1, 220, 192, 74), + (1161, 1, 220, 224, 74), + (1162, 1, 220, 256, 74), + (1163, 1, 279, 23, 0), + (1164, 1, 279, 25, 0), + (1165, 1, 279, 27, 0), + (1166, 1, 224, 20, 74), + (1166, 2, 173, 1, 0), + (1167, 1, 224, 35, 74), + (1167, 2, 173, 1, 0), + (1168, 1, 224, 50, 74), + (1168, 2, 173, 2, 0), + (1172, 1, 292, 50, 0), + (1173, 1, 292, 55, 0), + (1174, 1, 292, 60, 0), + (1181, 1, 305, -20, 0), + (1182, 1, 305, -40, 0), + (1183, 1, 305, -60, 0), + (1184, 1, 305, -80, 0), + (1185, 1, 305, -100, 0), + (1186, 1, 319, 3, 0), + (1187, 1, 319, 6, 0), + (1188, 1, 319, 10, 0), + (1196, 1, 220, 20, 7), + (1197, 1, 220, 40, 7), + (1198, 1, 220, 60, 7), + (1199, 1, 220, 80, 7), + (1200, 1, 220, 100, 7), + (1210, 1, 294, 0, 107), + (1211, 1, 294, 0, 115), + (1212, 1, 294, 0, 125), + (1213, 1, 294, 0, 107), + (1214, 1, 294, 0, 115), + (1215, 1, 294, 0, 125), + (1216, 1, 132, 2, 2), + (1217, 1, 132, 5, 5), + (1218, 1, 132, 10, 10), + (1219, 1, 339, 3, 8105), + (1219, 2, 142, 65, 0), + (1219, 3, 311, 0, 0), + (1219, 4, 134, 70, 0), + (1219, 5, 348, 10, 0), + (1219, 6, 137, 0, 0), + (1219, 7, 339, 3, 8105), + (1219, 8, 142, 65, 0), + (1219, 9, 311, 0, 0), + (1219, 10, 134, 70, 0), + (1219, 11, 348, 10, 0), + (1219, 12, 137, 100, 0), + (1219, 13, 339, 3, 8105), + (1219, 14, 142, 65, 0), + (1219, 15, 311, 0, 0), + (1219, 16, 134, 70, 0), + (1219, 17, 348, 10, 0), + (1219, 18, 137, 79, 0), + (1219, 19, 339, 3, 8105), + (1219, 20, 142, 65, 0), + (1219, 21, 311, 0, 0), + (1219, 22, 134, 70, 0), + (1219, 23, 348, 10, 0), + (1219, 24, 137, 147, 0), + (1220, 1, 339, 6, 8105), + (1220, 2, 142, 65, 0), + (1220, 3, 311, 0, 0), + (1220, 4, 134, 70, 0), + (1220, 5, 348, 10, 0), + (1220, 6, 137, 0, 0), + (1220, 7, 339, 6, 8105), + (1220, 8, 142, 65, 0), + (1220, 9, 311, 0, 0), + (1220, 10, 134, 70, 0), + (1220, 11, 348, 10, 0), + (1220, 12, 137, 100, 0), + (1220, 13, 339, 6, 8105), + (1220, 14, 142, 65, 0), + (1220, 15, 311, 0, 0), + (1220, 16, 134, 70, 0), + (1220, 17, 348, 10, 0), + (1220, 18, 137, 79, 0), + (1220, 19, 339, 6, 8105), + (1220, 20, 142, 65, 0), + (1220, 21, 311, 0, 0), + (1220, 22, 134, 70, 0), + (1220, 23, 348, 10, 0), + (1220, 24, 137, 147, 0), + (1221, 1, 339, 10, 8105), + (1221, 2, 142, 65, 0), + (1221, 3, 311, 0, 0), + (1221, 4, 134, 70, 0), + (1221, 5, 348, 10, 0), + (1221, 6, 137, 0, 0), + (1221, 7, 339, 10, 8105), + (1221, 8, 142, 65, 0), + (1221, 9, 311, 0, 0), + (1221, 10, 134, 70, 0), + (1221, 11, 348, 10, 0), + (1221, 12, 137, 100, 0), + (1221, 13, 339, 10, 8105), + (1221, 14, 142, 65, 0), + (1221, 15, 311, 0, 0), + (1221, 16, 134, 70, 0), + (1221, 17, 348, 10, 0), + (1221, 18, 137, 79, 0), + (1221, 19, 339, 10, 8105), + (1221, 20, 142, 65, 0), + (1221, 21, 311, 0, 0), + (1221, 22, 134, 70, 0), + (1221, 23, 348, 10, 0), + (1221, 24, 137, 147, 0), + (1230, 1, 313, 25, 0), + (1231, 1, 313, 50, 0), + (1232, 1, 313, 75, 0), + (1265, 1, 220, 40, 26), + (1265, 2, 220, 40, 30), + (1265, 3, 220, 40, 38), + (1266, 1, 220, 50, 26), + (1266, 2, 220, 50, 30), + (1266, 3, 220, 50, 38), + (1267, 1, 220, 60, 26), + (1267, 2, 220, 60, 30), + (1267, 3, 220, 60, 38), + (1268, 1, 292, 20, 0), + (1269, 1, 292, 25, 0), + (1270, 1, 292, 30, 0), + (1284, 1, 293, 15, 0), + (1285, 1, 293, 30, 0), + (1286, 1, 293, 50, 0), + (1287, 1, 320, 1, 0), + (1288, 1, 320, 3, 0), + (1289, 1, 320, 5, 0), + (1290, 1, 216, 40, 0), + (1290, 2, 216, 40, 1), + (1290, 3, 216, 40, 2), + (1290, 4, 216, 40, 3), + (1290, 5, 216, 40, 10), + (1290, 6, 216, 40, 28), + (1290, 7, 216, 40, 30), + (1290, 8, 216, 40, 36), + (1290, 9, 216, 40, 77), + (1291, 1, 216, 50, 0), + (1291, 2, 216, 50, 1), + (1291, 3, 216, 50, 2), + (1291, 4, 216, 50, 3), + (1291, 5, 216, 50, 10), + (1291, 6, 216, 50, 28), + (1291, 7, 216, 50, 30), + (1291, 8, 216, 50, 36), + (1291, 9, 216, 50, 77), + (1292, 1, 216, 60, 0), + (1292, 2, 216, 60, 1), + (1292, 3, 216, 60, 2), + (1292, 4, 216, 60, 3), + (1292, 5, 216, 60, 10), + (1292, 6, 216, 60, 28), + (1292, 7, 216, 60, 30), + (1292, 8, 216, 60, 36), + (1292, 9, 216, 60, 77), + (1296, 1, 247, 20, 53), + (1297, 1, 247, 40, 53), + (1298, 1, 247, 60, 53), + (1299, 1, 247, 80, 53), + (1300, 1, 247, 100, 53), + (1301, 1, 258, 20, 0), + (1302, 1, 258, 25, 0), + (1303, 1, 258, 30, 0), + (1304, 1, 216, 50, 8), + (1305, 1, 216, 100, 8), + (1306, 1, 216, 150, 8), + (1307, 1, 325, 10, 0), + (1308, 1, 325, 20, 0), + (1309, 1, 325, 30, 0), + (1310, 1, 325, 40, 0), + (1311, 1, 325, 50, 0), + (1313, 1, 85, 6037, 0), + (1314, 1, 85, 6038, 0), + (1315, 1, 85, 6039, 0), + (1316, 1, 302, 216, 216), + (1316, 2, 385, 99, 0), + (1317, 1, 302, 233, 233), + (1317, 2, 385, 99, 0), + (1318, 1, 302, 250, 250), + (1318, 2, 385, 99, 0), + (1319, 1, 274, 16, 0), + (1320, 1, 274, 18, 0), + (1321, 1, 274, 20, 0), + (1361, 1, 159, 10, 0), + (1361, 2, 262, 10, 0), + (1361, 3, 262, 10, 1), + (1361, 4, 262, 10, 2), + (1361, 5, 262, 10, 3), + (1361, 6, 262, 10, 4), + (1361, 7, 262, 10, 5), + (1361, 8, 262, 10, 6), + (1362, 1, 214, 300, 0), + (1362, 2, 97, 200, 0), + (1362, 3, 190, 200, 0), + (1363, 1, 327, 1, 0), + (1364, 1, 273, 1, 0), + (1364, 2, 274, 1, 0), + (1364, 3, 294, 1, 100), + (1364, 4, 169, 40, 0), + (1364, 5, 169, 40, 1), + (1364, 6, 169, 40, 2), + (1364, 7, 169, 40, 3), + (1364, 8, 169, 40, 8), + (1364, 9, 169, 40, 10), + (1364, 10, 169, 40, 26), + (1364, 11, 169, 40, 28), + (1364, 12, 169, 40, 30), + (1364, 13, 169, 40, 36), + (1364, 14, 169, 40, 74), + (1365, 1, 180, 2, 0), + (1366, 1, 159, 10, 0), + (1366, 2, 262, 10, 0), + (1366, 3, 262, 10, 1), + (1366, 4, 262, 10, 2), + (1366, 5, 262, 10, 3), + (1366, 6, 262, 10, 4), + (1366, 7, 262, 10, 5), + (1366, 8, 262, 10, 6), + (1367, 1, 214, 300, 0), + (1367, 2, 97, 200, 0), + (1367, 3, 190, 200, 0), + (1368, 1, 327, 1, 0), + (1369, 1, 273, 1, 0), + (1369, 2, 274, 1, 0), + (1369, 3, 294, 1, 100), + (1369, 4, 169, 40, 0), + (1369, 5, 169, 40, 1), + (1369, 6, 169, 40, 2), + (1369, 7, 169, 40, 3), + (1369, 8, 169, 40, 8), + (1369, 9, 169, 40, 10), + (1369, 10, 169, 40, 26), + (1369, 11, 169, 40, 28), + (1369, 12, 169, 40, 30), + (1369, 13, 169, 40, 36), + (1369, 14, 169, 40, 74), + (1370, 1, 180, 2, 0), + (1378, 1, 10, 0, 0), + (1379, 1, 10, 0, 0), + (1380, 1, 10, 0, 0), + (1382, 1, 10, 0, 0), + (1388, 2, 13, 1, 0), + (1389, 1, 328, 300, 0), + (1390, 1, 328, 350, 0), + (1391, 1, 328, 400, 0), + (1392, 1, 328, 450, 0), + (1393, 1, 328, 500, 0), + (1394, 1, 172, 33, 0), + (1395, 1, 172, 34, 0), + (1396, 1, 172, 35, 0), + (1397, 1, 172, 37, 0), + (1398, 1, 172, 39, 0), + (1399, 1, 259, 37, 0), + (1400, 1, 259, 39, 0), + (1401, 1, 259, 41, 0), + (1402, 1, 259, 43, 0), + (1403, 1, 259, 45, 0), + (1414, 1, 264, 432, 451), + (1415, 1, 264, 864, 451), + (1416, 1, 264, 1296, 451), + (1417, 1, 264, 1728, 451), + (1418, 1, 264, 2160, 451), + (1420, 1, 282, 20, 0), + (1421, 1, 282, 40, 0), + (1422, 1, 282, 60, 0), + (1423, 1, 282, 80, 0), + (1424, 1, 282, 100, 0), + (1430, 1, 280, 27, 0), + (1431, 1, 280, 34, 0), + (1432, 1, 280, 41, 0), + (1435, 1, 339, 3, 8105), + (1435, 2, 142, 65, 0), + (1435, 3, 311, 0, 0), + (1435, 4, 134, 70, 0), + (1435, 5, 348, 10, 0), + (1435, 6, 137, 0, 0), + (1435, 7, 339, 3, 8105), + (1435, 8, 142, 65, 0), + (1435, 9, 311, 0, 0), + (1435, 10, 134, 70, 0), + (1435, 11, 348, 10, 0), + (1435, 12, 137, 100, 0), + (1435, 13, 339, 3, 8105), + (1435, 14, 142, 65, 0), + (1435, 15, 311, 0, 0), + (1435, 16, 134, 70, 0), + (1435, 17, 348, 10, 0), + (1435, 18, 137, 79, 0), + (1435, 19, 339, 3, 8105), + (1435, 20, 142, 65, 0), + (1435, 21, 311, 0, 0), + (1435, 22, 134, 70, 0), + (1435, 23, 348, 10, 0), + (1435, 24, 137, 147, 0), + (1436, 1, 339, 6, 8105), + (1436, 2, 142, 65, 0), + (1436, 3, 311, 0, 0), + (1436, 4, 134, 70, 0), + (1436, 5, 348, 10, 0), + (1436, 6, 137, 0, 0), + (1436, 7, 339, 6, 8105), + (1436, 8, 142, 65, 0), + (1436, 9, 311, 0, 0), + (1436, 10, 134, 70, 0), + (1436, 11, 348, 10, 0), + (1436, 12, 137, 100, 0), + (1436, 13, 339, 6, 8105), + (1436, 14, 142, 65, 0), + (1436, 15, 311, 0, 0), + (1436, 16, 134, 70, 0), + (1436, 17, 348, 10, 0), + (1436, 18, 137, 79, 0), + (1436, 19, 339, 6, 8105), + (1436, 20, 142, 65, 0), + (1436, 21, 311, 0, 0), + (1436, 22, 134, 70, 0), + (1436, 23, 348, 10, 0), + (1436, 24, 137, 147, 0), + (1437, 1, 339, 10, 8105), + (1437, 2, 142, 65, 0), + (1437, 3, 311, 0, 0), + (1437, 4, 134, 70, 0), + (1437, 5, 348, 10, 0), + (1437, 6, 137, 0, 0), + (1437, 7, 339, 10, 8105), + (1437, 8, 142, 65, 0), + (1437, 9, 311, 0, 0), + (1437, 10, 134, 70, 0), + (1437, 11, 348, 10, 0), + (1437, 12, 137, 100, 0), + (1437, 13, 339, 10, 8105), + (1437, 14, 142, 65, 0), + (1437, 15, 311, 0, 0), + (1437, 16, 134, 70, 0), + (1437, 17, 348, 10, 0), + (1437, 18, 137, 79, 0), + (1437, 19, 339, 10, 8105), + (1437, 20, 142, 65, 0), + (1437, 21, 311, 0, 0), + (1437, 22, 134, 70, 0), + (1437, 23, 348, 10, 0), + (1437, 24, 137, 147, 0), + (1453, 1, 131, 10, 10), + (1453, 2, 137, 32, 0), + (1453, 3, 311, 1, 0), + (1454, 1, 131, 20, 20), + (1454, 2, 137, 32, 0), + (1454, 3, 311, 1, 0), + (1455, 1, 131, 30, 30), + (1455, 2, 137, 32, 0), + (1455, 3, 311, 1, 0), + (1456, 1, 131, 40, 40), + (1456, 2, 137, 32, 0), + (1456, 3, 311, 1, 0), + (1457, 1, 131, 50, 50), + (1457, 2, 137, 32, 0), + (1457, 3, 311, 1, 0), + (1467, 1, 280, 27, 0), + (1468, 1, 280, 34, 0), + (1469, 1, 280, 41, 0), + (1471, 1, 264, 90, 362), + (1472, 1, 264, 180, 362), + (1473, 1, 264, 270, 362), + (1474, 1, 264, 360, 362), + (1475, 1, 264, 450, 362), + (1483, 1, 294, 0, 133), + (1484, 1, 294, 0, 141), + (1485, 1, 294, 0, 150), + (1486, 1, 339, 1, 8165), + (1486, 2, 138, 1, 0), + (1486, 3, 141, 1, 0), + (1486, 4, 142, 60, 0), + (1486, 5, 137, 0, 0), + (1486, 6, 311, 0, 0), + (1486, 7, 134, 75, 0), + (1486, 8, 139, -265, 0), + (1486, 9, 139, -754, 0), + (1486, 10, 139, -1332, 0), + (1486, 11, 139, -1572, 0), + (1486, 12, 139, -2749, 0), + (1486, 13, 139, -4979, 0), + (1486, 14, 139, -5418, 0), + (1486, 15, 139, -5403, 0), + (1486, 16, 348, 10, 0), + (1487, 1, 339, 3, 8166), + (1487, 2, 138, 1, 0), + (1487, 3, 141, 1, 0), + (1487, 4, 142, 60, 0), + (1487, 5, 137, 0, 0), + (1487, 6, 311, 0, 0), + (1487, 7, 134, 75, 0), + (1487, 8, 139, -265, 0), + (1487, 9, 139, -754, 0), + (1487, 10, 139, -1332, 0), + (1487, 11, 139, -1572, 0), + (1487, 12, 139, -2749, 0), + (1487, 13, 139, -4979, 0), + (1487, 14, 139, -5418, 0), + (1487, 15, 139, -5403, 0), + (1487, 16, 348, 10, 0), + (1488, 1, 339, 5, 8167), + (1488, 2, 138, 1, 0), + (1488, 3, 141, 1, 0), + (1488, 4, 142, 60, 0), + (1488, 5, 137, 0, 0), + (1488, 6, 311, 0, 0), + (1488, 7, 134, 75, 0), + (1488, 8, 139, -265, 0), + (1488, 9, 139, -754, 0), + (1488, 10, 139, -1332, 0), + (1488, 11, 139, -1572, 0), + (1488, 12, 139, -2749, 0), + (1488, 13, 139, -4979, 0), + (1488, 14, 139, -5418, 0), + (1488, 15, 139, -5403, 0), + (1488, 16, 348, 10, 0), + (1489, 1, 339, 7, 8168), + (1489, 2, 138, 1, 0), + (1489, 3, 141, 1, 0), + (1489, 4, 142, 60, 0), + (1489, 5, 137, 0, 0), + (1489, 6, 311, 0, 0), + (1489, 7, 134, 75, 0), + (1489, 8, 139, -265, 0), + (1489, 9, 139, -754, 0), + (1489, 10, 139, -1332, 0), + (1489, 11, 139, -1572, 0), + (1489, 12, 139, -2749, 0), + (1489, 13, 139, -4979, 0), + (1489, 14, 139, -5418, 0), + (1489, 15, 139, -5403, 0), + (1489, 16, 348, 10, 0), + (1490, 1, 339, 9, 8169), + (1490, 2, 138, 1, 0), + (1490, 3, 141, 1, 0), + (1490, 4, 142, 60, 0), + (1490, 5, 137, 0, 0), + (1490, 6, 311, 0, 0), + (1490, 7, 134, 75, 0), + (1490, 8, 139, -265, 0), + (1490, 9, 139, -754, 0), + (1490, 10, 139, -1332, 0), + (1490, 11, 139, -1572, 0), + (1490, 12, 139, -2749, 0), + (1490, 13, 139, -4979, 0), + (1490, 14, 139, -5418, 0), + (1490, 15, 139, -5403, 0), + (1490, 16, 348, 10, 0), + (1504, 1, 287, 2, 0), + (1504, 2, 385, 2754, 1), + (1505, 1, 287, 4, 0), + (1505, 2, 385, 2754, 1), + (1506, 1, 287, 6, 0), + (1506, 2, 385, 2754, 1), + (1511, 1, 264, 60, 175), + (1511, 2, 264, 60, 792), + (1512, 1, 264, 120, 175), + (1512, 2, 264, 120, 792), + (1513, 1, 264, 180, 175), + (1513, 2, 264, 180, 792), + (1514, 1, 273, 2, 0), + (1515, 1, 273, 4, 0), + (1516, 1, 273, 6, 0), + (1524, 1, 219, 260, 1800), + (1525, 1, 219, 300, 2000), + (1526, 1, 219, 280, 1900), + (1528, 1, 239, 30, 0), + (1529, 1, 239, 35, 0), + (1530, 1, 239, 40, 0), + (1531, 1, 239, 45, 0), + (1532, 1, 239, 50, 0), + (1533, 1, 266, 11, 0), + (1534, 1, 266, 14, 0), + (1535, 1, 266, 17, 0), + (1536, 1, 266, 11, 0), + (1537, 1, 266, 14, 0), + (1538, 1, 266, 17, 0), + (1539, 1, 252, 37, 0), + (1540, 1, 252, 44, 0), + (1541, 1, 252, 50, 0), + (1543, 1, 220, 10, 8), + (1544, 1, 220, 20, 8), + (1545, 1, 220, 30, 8), + (1546, 1, 264, 120, 420), + (1547, 1, 264, 240, 420), + (1548, 1, 264, 360, 420), + (1549, 1, 293, 25, 0), + (1550, 1, 293, 50, 0), + (1551, 1, 293, 75, 0), + (1552, 1, 271, 5, 0), + (1553, 1, 271, 10, 0), + (1554, 1, 271, 15, 0), + (1555, 1, 264, 240, 359), + (1556, 1, 264, 480, 359), + (1557, 1, 264, 720, 359), + (1563, 1, 225, 18, 0), + (1564, 1, 225, 21, 0), + (1565, 1, 225, 24, 0), + (1566, 1, 225, 27, 0), + (1567, 1, 225, 30, 0), + (1572, 1, 339, 2, 8261), + (1572, 2, 138, 0, 0), + (1572, 3, 137, 31, 0), + (1572, 4, 311, 0, 0), + (1573, 1, 339, 4, 8262), + (1573, 2, 138, 0, 0), + (1573, 3, 137, 31, 0), + (1573, 4, 311, 0, 0), + (1574, 1, 339, 6, 8263), + (1574, 2, 138, 0, 0), + (1574, 3, 137, 31, 0), + (1574, 4, 311, 0, 0), + (1575, 1, 339, 8, 8264), + (1575, 2, 138, 0, 0), + (1575, 3, 137, 31, 0), + (1575, 4, 311, 0, 0), + (1576, 1, 339, 10, 8265), + (1576, 2, 138, 0, 0), + (1576, 3, 137, 31, 0), + (1576, 4, 311, 0, 0), + (1577, 1, 274, 3, 0), + (1578, 1, 274, 6, 0), + (1579, 1, 274, 10, 0), + (1583, 1, 264, 360, 300), + (1584, 1, 264, 720, 300), + (1585, 1, 264, 1080, 300), + (1586, 1, 264, 1440, 300), + (1587, 1, 264, 1800, 300), + (1588, 1, 344, 50, 0), + (1589, 1, 344, 100, 0), + (1590, 1, 344, 150, 0), + (1591, 1, 293, 25, 0), + (1592, 1, 341, 10, 0), + (1593, 1, 341, 20, 0), + (1594, 1, 341, 30, 0), + (1595, 1, 341, 40, 0), + (1596, 1, 341, 50, 0), + (1601, 1, 217, 0, 35200), + (1601, 2, 346, 60, 0), + (1602, 1, 217, 0, 42440), + (1602, 2, 346, 62, 0), + (1603, 1, 217, 0, 46480), + (1603, 2, 346, 64, 0), + (1604, 1, 439, 0, 32000), + (1604, 2, 345, 59, 0), + (1605, 1, 439, 0, 35200), + (1605, 2, 345, 60, 0), + (1606, 1, 439, 0, 42440), + (1606, 2, 345, 61, 0), + (1608, 1, 347, 2, 0), + (1609, 1, 347, 4, 0), + (1610, 1, 347, 6, 0), + (1611, 1, 282, 20, 0), + (1612, 1, 282, 40, 0), + (1613, 1, 282, 60, 0), + (1614, 1, 282, 80, 0), + (1615, 1, 282, 100, 0), + (1616, 1, 279, 7, 0), + (1617, 1, 279, 11, 0), + (1618, 1, 279, 15, 0), + (1619, 1, 279, 17, 0), + (1620, 1, 279, 19, 0), + (1621, 1, 177, 20, -1), + (1622, 1, 177, 22, -1), + (1623, 1, 177, 24, -1), + (1624, 1, 177, 20, -1), + (1625, 1, 177, 22, -1), + (1626, 1, 177, 24, -1), + (1627, 1, 271, 5, 0), + (1628, 1, 271, 10, 0), + (1629, 1, 271, 15, 0), + (1633, 1, 225, 18, 0), + (1634, 1, 225, 21, 0), + (1635, 1, 225, 24, 0), + (1636, 1, 225, 27, 0), + (1637, 1, 225, 30, 0), + (1641, 1, 359, 100, 0), + (1642, 1, 359, 60, 0), + (1648, 1, 339, 10, 8105), + (1648, 2, 142, 65, 0), + (1648, 3, 311, 0, 0), + (1648, 4, 134, 70, 0), + (1648, 5, 348, 10, 0), + (1648, 6, 137, 0, 0), + (1648, 7, 339, 10, 8105), + (1648, 8, 142, 65, 0), + (1648, 9, 311, 0, 0), + (1648, 10, 134, 70, 0), + (1648, 11, 348, 10, 0), + (1648, 12, 137, 100, 0), + (1648, 13, 339, 10, 8105), + (1648, 14, 142, 65, 0), + (1648, 15, 311, 0, 0), + (1648, 16, 134, 70, 0), + (1648, 17, 348, 10, 0), + (1648, 18, 137, 79, 0), + (1648, 19, 339, 10, 8105), + (1648, 20, 142, 65, 0), + (1648, 21, 311, 0, 0), + (1648, 22, 134, 70, 0), + (1648, 23, 348, 10, 0), + (1648, 24, 137, 147, 0), + (1648, 25, 339, 10, 11404), + (1648, 26, 142, 71, 0), + (1648, 27, 311, 0, 0), + (1648, 28, 134, 75, 0), + (1648, 29, 348, 10, 0), + (1648, 30, 137, 0, 0), + (1648, 31, 339, 10, 11404), + (1648, 32, 142, 71, 0), + (1648, 33, 311, 0, 0), + (1648, 34, 134, 75, 0), + (1648, 35, 348, 10, 0), + (1648, 36, 137, 100, 0), + (1648, 37, 339, 10, 11404), + (1648, 38, 142, 71, 0), + (1648, 39, 311, 0, 0), + (1648, 40, 134, 75, 0), + (1648, 41, 348, 10, 0), + (1648, 42, 137, 79, 0), + (1648, 43, 339, 10, 11404), + (1648, 44, 142, 71, 0), + (1648, 45, 311, 0, 0), + (1648, 46, 134, 75, 0), + (1648, 47, 348, 10, 0), + (1648, 48, 137, 147, 0), + (1649, 1, 339, 10, 8105), + (1649, 2, 142, 65, 0), + (1649, 3, 311, 0, 0), + (1649, 4, 134, 70, 0), + (1649, 5, 348, 10, 0), + (1649, 6, 137, 0, 0), + (1649, 7, 339, 10, 8105), + (1649, 8, 142, 65, 0), + (1649, 9, 311, 0, 0), + (1649, 10, 134, 70, 0), + (1649, 11, 348, 10, 0), + (1649, 12, 137, 100, 0), + (1649, 13, 339, 10, 8105), + (1649, 14, 142, 65, 0), + (1649, 15, 311, 0, 0), + (1649, 16, 134, 70, 0), + (1649, 17, 348, 10, 0), + (1649, 18, 137, 79, 0), + (1649, 19, 339, 10, 8105), + (1649, 20, 142, 65, 0), + (1649, 21, 311, 0, 0), + (1649, 22, 134, 70, 0), + (1649, 23, 348, 10, 0), + (1649, 24, 137, 147, 0), + (1649, 25, 339, 10, 11404), + (1649, 26, 142, 71, 0), + (1649, 27, 311, 0, 0), + (1649, 28, 134, 75, 0), + (1649, 29, 348, 10, 0), + (1649, 30, 137, 0, 0), + (1649, 31, 339, 10, 11404), + (1649, 32, 142, 71, 0), + (1649, 33, 311, 0, 0), + (1649, 34, 134, 75, 0), + (1649, 35, 348, 10, 0), + (1649, 36, 137, 100, 0), + (1649, 37, 339, 10, 11404), + (1649, 38, 142, 71, 0), + (1649, 39, 311, 0, 0), + (1649, 40, 134, 75, 0), + (1649, 41, 348, 10, 0), + (1649, 42, 137, 79, 0), + (1649, 43, 339, 10, 11404), + (1649, 44, 142, 71, 0), + (1649, 45, 311, 0, 0), + (1649, 46, 134, 75, 0), + (1649, 47, 348, 10, 0), + (1649, 48, 137, 147, 0), + (1649, 49, 339, 10, 13199), + (1649, 50, 142, 76, 0), + (1649, 51, 311, 0, 0), + (1649, 52, 134, 80, 0), + (1649, 53, 348, 10, 0), + (1649, 54, 137, 0, 0), + (1649, 55, 339, 10, 13199), + (1649, 56, 142, 76, 0), + (1649, 57, 311, 0, 0), + (1649, 58, 134, 80, 0), + (1649, 59, 348, 10, 0), + (1649, 60, 137, 100, 0), + (1649, 61, 339, 10, 13199), + (1649, 62, 142, 76, 0), + (1649, 63, 311, 0, 0), + (1649, 64, 134, 80, 0), + (1649, 65, 348, 10, 0), + (1649, 66, 137, 79, 0), + (1649, 67, 339, 10, 13199), + (1649, 68, 142, 76, 0), + (1649, 69, 311, 0, 0), + (1649, 70, 134, 80, 0), + (1649, 71, 348, 10, 0), + (1649, 72, 137, 147, 0), + (1650, 1, 339, 10, 8105), + (1650, 2, 142, 65, 0), + (1650, 3, 311, 0, 0), + (1650, 4, 134, 70, 0), + (1650, 5, 348, 10, 0), + (1650, 6, 137, 0, 0), + (1650, 7, 339, 10, 8105), + (1650, 8, 142, 65, 0), + (1650, 9, 311, 0, 0), + (1650, 10, 134, 70, 0), + (1650, 11, 348, 10, 0), + (1650, 12, 137, 100, 0), + (1650, 13, 339, 10, 8105), + (1650, 14, 142, 65, 0), + (1650, 15, 311, 0, 0), + (1650, 16, 134, 70, 0), + (1650, 17, 348, 10, 0), + (1650, 18, 137, 79, 0), + (1650, 19, 339, 10, 8105), + (1650, 20, 142, 65, 0), + (1650, 21, 311, 0, 0), + (1650, 22, 134, 70, 0), + (1650, 23, 348, 10, 0), + (1650, 24, 137, 147, 0), + (1650, 25, 339, 10, 11404), + (1650, 26, 142, 71, 0), + (1650, 27, 311, 0, 0), + (1650, 28, 134, 75, 0), + (1650, 29, 348, 10, 0), + (1650, 30, 137, 0, 0), + (1650, 31, 339, 10, 11404), + (1650, 32, 142, 71, 0), + (1650, 33, 311, 0, 0), + (1650, 34, 134, 75, 0), + (1650, 35, 348, 10, 0), + (1650, 36, 137, 100, 0), + (1650, 37, 339, 10, 11404), + (1650, 38, 142, 71, 0), + (1650, 39, 311, 0, 0), + (1650, 40, 134, 75, 0), + (1650, 41, 348, 10, 0), + (1650, 42, 137, 79, 0), + (1650, 43, 339, 10, 11404), + (1650, 44, 142, 71, 0), + (1650, 45, 311, 0, 0), + (1650, 46, 134, 75, 0), + (1650, 47, 348, 10, 0), + (1650, 48, 137, 147, 0), + (1650, 49, 339, 10, 13199), + (1650, 50, 142, 76, 0), + (1650, 51, 311, 0, 0), + (1650, 52, 134, 80, 0), + (1650, 53, 348, 10, 0), + (1650, 54, 137, 0, 0), + (1650, 55, 339, 10, 13199), + (1650, 56, 142, 76, 0), + (1650, 57, 311, 0, 0), + (1650, 58, 134, 80, 0), + (1650, 59, 348, 10, 0), + (1650, 60, 137, 100, 0), + (1650, 61, 339, 10, 13199), + (1650, 62, 142, 76, 0), + (1650, 63, 311, 0, 0), + (1650, 64, 134, 80, 0), + (1650, 65, 348, 10, 0), + (1650, 66, 137, 79, 0), + (1650, 67, 339, 10, 13199), + (1650, 68, 142, 76, 0), + (1650, 69, 311, 0, 0), + (1650, 70, 134, 80, 0), + (1650, 71, 348, 10, 0), + (1650, 72, 137, 147, 0), + (1650, 73, 339, 10, 13830), + (1650, 74, 142, 81, 0), + (1650, 75, 311, 0, 0), + (1650, 76, 134, 85, 0), + (1650, 77, 348, 10, 0), + (1650, 78, 137, 0, 0), + (1650, 79, 339, 10, 13830), + (1650, 80, 142, 81, 0), + (1650, 81, 311, 0, 0), + (1650, 82, 134, 85, 0), + (1650, 83, 348, 10, 0), + (1650, 84, 137, 100, 0), + (1650, 85, 339, 10, 13830), + (1650, 86, 142, 81, 0), + (1650, 87, 311, 0, 0), + (1650, 88, 134, 85, 0), + (1650, 89, 348, 10, 0), + (1650, 90, 137, 79, 0), + (1650, 91, 339, 10, 13830), + (1650, 92, 142, 81, 0), + (1650, 93, 311, 0, 0), + (1650, 94, 134, 85, 0), + (1650, 95, 348, 10, 0), + (1650, 96, 137, 147, 0), + (1651, 1, 97, 300, 0), + (1652, 1, 97, 350, 0), + (1653, 1, 97, 400, 0), + (1654, 1, 97, 450, 0), + (1655, 1, 97, 500, 0), + (1656, 1, 127, 40, 0), + (1656, 2, 137, 154, 0), + (1656, 3, 403, 2, 0), + (1656, 4, 404, 10, 0), + (1657, 1, 127, 50, 0), + (1657, 2, 137, 154, 0), + (1657, 3, 403, 2, 0), + (1657, 4, 404, 10, 0), + (1659, 1, 127, 40, 0), + (1659, 2, 137, 154, 0), + (1659, 3, 403, 2, 0), + (1659, 4, 404, 10, 0), + (1660, 1, 127, 50, 0), + (1660, 2, 137, 154, 0), + (1660, 3, 403, 2, 0), + (1660, 4, 404, 10, 0), + (1662, 1, 370, 2, 0), + (1663, 1, 370, 4, 0), + (1664, 1, 370, 6, 0), + (1665, 1, 370, 8, 0), + (1666, 1, 370, 10, 0), + (2400, 1, 264, 90, 38), + (2401, 1, 264, 180, 38), + (2402, 1, 264, 270, 38), + (4666, 0, 366, 10, 50), + (4666, 1, 349, 5, 0), + (4667, 0, 366, 30, 50), + (4667, 1, 349, 10, 0), + (4668, 0, 366, 60, 50), + (4668, 1, 349, 15, 0), + (4669, 0, 366, 10, 500), + (4669, 1, 349, 20, 0), + (4670, 0, 366, 30, 500), + (4670, 1, 349, 25, 0), + (4672, 1, 268, 10, 57), + (4673, 1, 268, 25, 57), + (4674, 1, 268, 50, 57), + (4675, 1, 268, 10, 68), + (4676, 1, 268, 25, 68), + (4677, 1, 268, 50, 68), + (4678, 1, 262, 55, 0), + (4678, 2, 262, 55, 1), + (4678, 3, 262, 55, 2), + (4678, 4, 262, 55, 3), + (4678, 5, 262, 55, 4), + (4678, 6, 262, 55, 5), + (4678, 7, 262, 55, 6), + (4679, 1, 262, 60, 0), + (4679, 2, 262, 60, 1), + (4679, 3, 262, 60, 2), + (4679, 4, 262, 60, 3), + (4679, 5, 262, 60, 4), + (4679, 6, 262, 60, 5), + (4679, 7, 262, 60, 6), + (4680, 1, 262, 65, 0), + (4680, 2, 262, 65, 1), + (4680, 3, 262, 65, 2), + (4680, 4, 262, 65, 3), + (4680, 5, 262, 65, 4), + (4680, 6, 262, 65, 5), + (4680, 7, 262, 65, 6), + (4681, 1, 262, 70, 0), + (4681, 2, 262, 70, 1), + (4681, 3, 262, 70, 2), + (4681, 4, 262, 70, 3), + (4681, 5, 262, 70, 4), + (4681, 6, 262, 70, 5), + (4681, 7, 262, 70, 6), + (4682, 1, 262, 75, 0), + (4682, 2, 262, 75, 1), + (4682, 3, 262, 75, 2), + (4682, 4, 262, 75, 3), + (4682, 5, 262, 75, 4), + (4682, 6, 262, 75, 5), + (4682, 7, 262, 75, 6), + (4683, 1, 328, 550, 0), + (4684, 1, 328, 600, 0), + (4685, 1, 328, 650, 0), + (4686, 1, 328, 700, 0), + (4687, 1, 328, 750, 0), + (4688, 1, 282, 20, 0), + (4689, 1, 282, 40, 0), + (4690, 1, 282, 60, 0), + (4691, 1, 282, 80, 0), + (4692, 1, 282, 100, 0), + (4693, 1, 0, 11, 0), + (4694, 1, 0, 12, 0), + (4695, 1, 0, 13, 0), + (4696, 1, 0, 14, 0), + (4697, 1, 0, 15, 0), + (4698, 1, 362, 1, 0), + (4699, 1, 363, 1, 0), + (4707, 1, 330, 85, 0), + (4707, 2, 330, 85, 1), + (4707, 3, 330, 85, 2), + (4707, 4, 330, 85, 3), + (4707, 5, 330, 85, 28), + (4707, 6, 330, 85, 36), + (4707, 7, 330, 85, 77), + (4708, 1, 330, 95, 0), + (4708, 2, 330, 95, 1), + (4708, 3, 330, 95, 2), + (4708, 4, 330, 95, 3), + (4708, 5, 330, 95, 28), + (4708, 6, 330, 95, 36), + (4708, 7, 330, 95, 77), + (4709, 1, 330, 105, 0), + (4709, 2, 330, 105, 1), + (4709, 3, 330, 105, 2), + (4709, 4, 330, 105, 3), + (4709, 5, 330, 105, 28), + (4709, 6, 330, 105, 36), + (4709, 7, 330, 105, 77), + (4710, 1, 330, 85, 0), + (4710, 2, 330, 85, 1), + (4710, 3, 330, 85, 2), + (4710, 4, 330, 85, 3), + (4710, 5, 330, 85, 28), + (4710, 6, 330, 85, 36), + (4711, 1, 330, 95, 0), + (4711, 2, 330, 95, 1), + (4711, 3, 330, 95, 2), + (4711, 4, 330, 95, 3), + (4711, 5, 330, 95, 28), + (4711, 6, 330, 95, 36), + (4712, 1, 330, 105, 0), + (4712, 2, 330, 105, 1), + (4712, 3, 330, 105, 2), + (4712, 4, 330, 105, 3), + (4712, 5, 330, 105, 28), + (4712, 6, 330, 105, 36), + (4713, 1, 330, 85, 0), + (4713, 2, 330, 85, 1), + (4713, 3, 330, 85, 2), + (4713, 4, 330, 85, 3), + (4713, 5, 330, 85, 28), + (4713, 6, 330, 85, 36), + (4713, 7, 330, 85, 77), + (4714, 1, 330, 95, 0), + (4714, 2, 330, 95, 1), + (4714, 3, 330, 95, 2), + (4714, 4, 330, 95, 3), + (4714, 5, 330, 95, 28), + (4714, 6, 330, 95, 36), + (4714, 7, 330, 95, 77), + (4715, 1, 330, 105, 0), + (4715, 2, 330, 105, 1), + (4715, 3, 330, 105, 2), + (4715, 4, 330, 105, 3), + (4715, 5, 330, 105, 28), + (4715, 6, 330, 105, 36), + (4715, 7, 330, 105, 77), + (4716, 1, 330, 60, 0), + (4716, 2, 330, 60, 1), + (4716, 3, 330, 60, 2), + (4716, 4, 330, 60, 3), + (4716, 5, 330, 60, 28), + (4716, 6, 330, 60, 36), + (4716, 7, 330, 60, 77), + (4717, 1, 330, 70, 0), + (4717, 2, 330, 70, 1), + (4717, 3, 330, 70, 2), + (4717, 4, 330, 70, 3), + (4717, 5, 330, 70, 28), + (4717, 6, 330, 70, 36), + (4717, 7, 330, 70, 77), + (4718, 1, 330, 80, 0), + (4718, 2, 330, 80, 1), + (4718, 3, 330, 80, 2), + (4718, 4, 330, 80, 3), + (4718, 5, 330, 80, 28), + (4718, 6, 330, 80, 36), + (4718, 7, 330, 80, 77), + (4722, 1, 278, 620, 35216), + (4722, 2, 440, 66, 100), + (4723, 1, 278, 650, 38310), + (4723, 2, 440, 68, 100), + (4724, 1, 278, 670, 41300), + (4724, 2, 440, 70, 100), + (4725, 1, 341, 60, 0), + (4726, 1, 341, 70, 0), + (4727, 1, 341, 80, 0), + (4728, 1, 341, 90, 0), + (4729, 1, 341, 100, 0), + (4733, 1, 294, 11, 100), + (4734, 1, 294, 13, 100), + (4735, 1, 294, 15, 100), + (4739, 1, 360, 10, 11023), + (4740, 1, 360, 20, 11023), + (4741, 1, 360, 30, 11023), + (4744, 1, 318, 6, 0), + (4745, 1, 318, 7, 0), + (4746, 1, 318, 8, 0), + (4747, 1, 318, 9, 0), + (4748, 1, 318, 10, 0), + (4749, 1, 294, 11, 100), + (4750, 1, 294, 13, 100), + (4751, 1, 294, 15, 100), + (4752, 1, 294, 0, 155), + (4753, 1, 294, 0, 160), + (4754, 1, 294, 0, 165), + (4755, 1, 294, 0, 130), + (4756, 1, 294, 0, 135), + (4757, 1, 294, 0, 140), + (4758, 1, 266, 27, 0), + (4759, 1, 266, 28, 0), + (4760, 1, 266, 29, 0), + (4761, 1, 273, 2, 0), + (4762, 1, 273, 3, 0), + (4763, 1, 273, 4, 0), + (4764, 1, 326, 2, 0), + (4767, 1, 114, -43, 0), + (4768, 1, 114, -46, 0), + (4769, 1, 114, -50, 0), + (4773, 1, 339, 10, 8105), + (4773, 2, 142, 65, 0), + (4773, 3, 311, 0, 0), + (4773, 4, 134, 70, 0), + (4773, 5, 348, 10, 0), + (4773, 6, 137, 0, 0), + (4773, 7, 339, 10, 8105), + (4773, 8, 142, 65, 0), + (4773, 9, 311, 0, 0), + (4773, 10, 134, 70, 0), + (4773, 11, 348, 10, 0), + (4773, 12, 137, 100, 0), + (4773, 13, 339, 10, 8105), + (4773, 14, 142, 65, 0), + (4773, 15, 311, 0, 0), + (4773, 16, 134, 70, 0), + (4773, 17, 348, 10, 0), + (4773, 18, 137, 79, 0), + (4773, 19, 339, 10, 8105), + (4773, 20, 142, 65, 0), + (4773, 21, 311, 0, 0), + (4773, 22, 134, 70, 0), + (4773, 23, 348, 10, 0), + (4773, 24, 137, 147, 0), + (4773, 25, 339, 10, 11404), + (4773, 26, 142, 71, 0), + (4773, 27, 311, 0, 0), + (4773, 28, 134, 75, 0), + (4773, 29, 348, 10, 0), + (4773, 30, 137, 0, 0), + (4773, 31, 339, 10, 11404), + (4773, 32, 142, 71, 0), + (4773, 33, 311, 0, 0), + (4773, 34, 134, 75, 0), + (4773, 35, 348, 10, 0), + (4773, 36, 137, 100, 0), + (4773, 37, 339, 10, 11404), + (4773, 38, 142, 71, 0), + (4773, 39, 311, 0, 0), + (4773, 40, 134, 75, 0), + (4773, 41, 348, 10, 0), + (4773, 42, 137, 79, 0), + (4773, 43, 339, 10, 11404), + (4773, 44, 142, 71, 0), + (4773, 45, 311, 0, 0), + (4773, 46, 134, 75, 0), + (4773, 47, 348, 10, 0), + (4773, 48, 137, 147, 0), + (4776, 1, 319, 12, 0), + (4777, 1, 319, 14, 0), + (4778, 1, 319, 16, 0), + (4779, 1, 274, 24, 0), + (4780, 1, 274, 26, 0), + (4781, 1, 274, 28, 0), + (4790, 1, 220, 288, 74), + (4791, 1, 220, 320, 74), + (4792, 1, 220, 352, 74), + (4793, 1, 220, 384, 74), + (4794, 1, 220, 416, 74), + (4795, 1, 279, 28, 0), + (4796, 1, 279, 29, 0), + (4797, 1, 279, 30, 0), + (4798, 1, 292, 65, 0), + (4799, 1, 292, 70, 0), + (4800, 1, 292, 75, 0), + (4801, 1, 227, 30, 32), + (4802, 1, 227, 60, 32), + (4803, 1, 227, 90, 32), + (4804, 1, 220, 448, 74), + (4805, 1, 220, 480, 74), + (4806, 1, 220, 512, 74), + (4807, 1, 220, 544, 74), + (4808, 1, 220, 576, 74), + (4809, 1, 216, 40, 74), + (4810, 1, 216, 80, 74), + (4811, 1, 216, 120, 74), + (4813, 1, 220, 70, 26), + (4813, 2, 220, 70, 30), + (4813, 3, 220, 70, 38), + (4814, 1, 220, 80, 26), + (4814, 2, 220, 80, 30), + (4814, 3, 220, 80, 38), + (4815, 1, 220, 90, 26), + (4815, 2, 220, 90, 30), + (4815, 3, 220, 90, 38), + (4819, 1, 239, 52, 0), + (4820, 1, 239, 54, 0), + (4821, 1, 239, 56, 0), + (4822, 1, 239, 58, 0), + (4823, 1, 239, 60, 0), + (4824, 1, 239, 52, 0), + (4825, 1, 239, 54, 0), + (4826, 1, 239, 56, 0), + (4827, 1, 239, 58, 0), + (4828, 1, 239, 60, 0), + (4829, 1, 264, 480, 420), + (4830, 1, 264, 600, 420), + (4831, 1, 264, 720, 420), + (4844, 1, 349, 5, 0), + (4845, 1, 349, 10, 0), + (4846, 1, 349, 15, 0), + (4847, 1, 349, 20, 0), + (4848, 1, 349, 25, 0), + (4861, 1, 264, 600, 68), + (4862, 1, 264, 1200, 68), + (4863, 1, 264, 1800, 68), + (4887, 1, 264, 120, 413), + (4888, 1, 264, 240, 413), + (4889, 1, 264, 360, 413), + (4897, 1, 280, 44, 0), + (4898, 1, 280, 47, 0), + (4899, 1, 280, 50, 0), + (4921, 1, 264, 1896, 117), + (4921, 2, 244, 75, 0), + (4922, 1, 264, 2496, 117), + (4922, 2, 244, 60, 0), + (4923, 1, 264, 3096, 117), + (4923, 2, 244, 45, 0), + (4924, 1, 273, 1, 0), + (4925, 1, 273, 2, 0), + (4926, 1, 273, 3, 0), + (4948, 1, 258, 35, 0), + (4949, 1, 258, 40, 0), + (4950, 1, 258, 45, 0), + (4951, 1, 220, 40, 8), + (4952, 1, 220, 50, 8), + (4953, 1, 220, 60, 8), + (4957, 1, 252, 55, 0), + (4958, 1, 252, 60, 0), + (4959, 1, 252, 65, 0), + (4960, 1, 280, 46, 0), + (4961, 1, 280, 51, 0), + (4962, 1, 280, 56, 0), + (4983, 1, 216, 65, 0), + (4983, 2, 216, 65, 1), + (4983, 3, 216, 65, 2), + (4983, 4, 216, 65, 3), + (4983, 5, 216, 65, 10), + (4983, 6, 216, 65, 28), + (4983, 7, 216, 65, 30), + (4983, 8, 216, 65, 36), + (4983, 9, 216, 65, 77), + (4984, 1, 216, 70, 0), + (4984, 2, 216, 70, 1), + (4984, 3, 216, 70, 2), + (4984, 4, 216, 70, 3), + (4984, 5, 216, 70, 10), + (4984, 6, 216, 70, 28), + (4984, 7, 216, 70, 30), + (4984, 8, 216, 70, 36), + (4984, 9, 216, 70, 77), + (4985, 1, 216, 75, 0), + (4985, 2, 216, 75, 1), + (4985, 3, 216, 75, 2), + (4985, 4, 216, 75, 3), + (4985, 5, 216, 75, 10), + (4985, 6, 216, 75, 28), + (4985, 7, 216, 75, 30), + (4985, 8, 216, 75, 36), + (4985, 9, 216, 75, 77), + (4986, 1, 217, 0, 52960), + (4986, 2, 346, 66, 40), + (4987, 1, 217, 0, 55400), + (4987, 2, 346, 68, 40), + (4988, 1, 217, 0, 60280), + (4988, 2, 346, 70, 40), + (4989, 1, 347, 8, 0), + (4990, 1, 347, 10, 0), + (4991, 1, 347, 12, 0), + (4992, 1, 279, 21, 0), + (4993, 1, 279, 23, 0), + (4994, 1, 279, 25, 0), + (4995, 1, 279, 27, 0), + (4996, 1, 279, 28, 0), + (5000, 1, 313, 80, 0), + (5001, 1, 313, 90, 0), + (5002, 1, 313, 100, 0), + (5010, 1, 264, 432, 35), + (5011, 1, 264, 864, 35), + (5012, 1, 264, 1296, 35), + (5013, 1, 293, 90, 0), + (5014, 1, 293, 100, 0), + (5029, 1, 85, 11621, 0), + (5030, 1, 85, 11622, 0), + (5031, 1, 85, 11623, 0), + (5032, 1, 274, 22, 0), + (5033, 1, 274, 24, 0), + (5034, 1, 274, 26, 0), + (5035, 1, 293, 60, 0), + (5036, 1, 293, 70, 0), + (5037, 1, 293, 80, 0), + (5038, 1, 219, 330, 2100), + (5039, 1, 219, 360, 2200), + (5040, 1, 219, 390, 2300), + (5045, 1, 180, 5, 0), + (5061, 1, 244, -25, 0), + (5085, 1, 360, 25, 11297), + (5086, 1, 360, 25, 11298), + (5087, 1, 360, 25, 11299), + (5118, 1, 264, 720, 396), + (5118, 2, 264, 720, 8504), + (5118, 3, 264, 720, 8505), + (5119, 1, 264, 1440, 396), + (5119, 2, 264, 1440, 8504), + (5119, 3, 264, 1440, 8505), + (5120, 1, 264, 2160, 396), + (5120, 2, 264, 2160, 8504), + (5120, 3, 264, 2160, 8505), + (5127, 1, 264, 300, 261), + (5128, 1, 264, 600, 261), + (5129, 1, 264, 900, 261), + (5133, 1, 294, 13, 100), + (5134, 1, 294, 15, 100), + (5135, 1, 294, 17, 100), + (5136, 1, 282, 20, 0), + (5137, 1, 282, 40, 0), + (5138, 1, 282, 60, 0), + (5139, 1, 282, 80, 0), + (5140, 1, 282, 100, 0), + (5141, 1, 279, 21, 0), + (5142, 1, 279, 23, 0), + (5143, 1, 279, 25, 0), + (5144, 1, 279, 27, 0), + (5145, 1, 279, 28, 0), + (5243, 1, 69, 600, 0), + (5244, 1, 69, 700, 0), + (5245, 1, 69, 800, 0), + (5246, 1, 69, 900, 0), + (5247, 1, 69, 1000, 0), + (5248, 1, 360, 10, 11232), + (5249, 1, 360, 20, 11232), + (5250, 1, 360, 30, 11232), + (5254, 1, 218, 6, 0), + (5255, 1, 218, 7, 0), + (5256, 1, 218, 8, 0), + (5257, 1, 218, 9, 0), + (5258, 1, 218, 10, 0), + (5259, 1, 218, 6, 0), + (5260, 1, 218, 7, 0), + (5261, 1, 218, 8, 0), + (5262, 1, 218, 9, 0), + (5263, 1, 218, 10, 0), + (5264, 1, 218, 1, 0), + (5265, 1, 218, 2, 0), + (5266, 1, 218, 3, 0), + (5267, 1, 218, 4, 0), + (5268, 1, 218, 5, 0), + (5269, 1, 131, 50, 50), + (5269, 2, 137, 82, 0), + (5270, 1, 303, 3000, 3000), + (5270, 2, 139, 2766, 0), + (5271, 1, 303, 3500, 3500), + (5271, 2, 139, 2766, 0), + (5272, 1, 303, 4000, 4000), + (5272, 2, 139, 2766, 0), + (5276, 1, 264, 60, 621), + (5276, 2, 264, 60, 622), + (5276, 3, 264, 60, 623), + (5276, 4, 264, 60, 784), + (5276, 5, 264, 60, 785), + (5276, 6, 264, 60, 786), + (5276, 7, 264, 60, 787), + (5276, 8, 264, 60, 624), + (5277, 1, 264, 120, 621), + (5277, 2, 264, 120, 622), + (5277, 3, 264, 120, 623), + (5277, 4, 264, 120, 784), + (5277, 5, 264, 120, 785), + (5277, 6, 264, 120, 786), + (5277, 7, 264, 120, 787), + (5277, 8, 264, 120, 624), + (5278, 1, 264, 180, 621), + (5278, 2, 264, 180, 622), + (5278, 3, 264, 180, 623), + (5278, 4, 264, 180, 784), + (5278, 5, 264, 180, 785), + (5278, 6, 264, 180, 786), + (5278, 7, 264, 180, 787), + (5278, 8, 264, 180, 624), + (5283, 1, 320, 1, 0), + (5284, 1, 320, 3, 0), + (5285, 1, 320, 5, 0), + (5286, 1, 294, 7, 100), + (5287, 1, 294, 8, 100), + (5288, 1, 294, 9, 100), + (5290, 1, 439, 0, 46480), + (5290, 2, 345, 62, 0), + (5291, 1, 439, 0, 52960), + (5291, 2, 345, 63, 0), + (5292, 1, 439, 0, 55400), + (5292, 2, 345, 64, 0), + (5293, 1, 439, 0, 60280), + (5293, 2, 345, 65, 0), + (5294, 1, 439, 0, 65440), + (5294, 2, 345, 66, 50), + (5295, 1, 360, 10, 11629), + (5296, 1, 360, 20, 11629), + (5297, 1, 360, 30, 11629), + (5301, 1, 189, 7, 0), + (5302, 1, 189, 8, 0), + (5303, 1, 189, 9, 0), + (5304, 1, 189, 10, 0), + (5305, 1, 189, 11, 0), + (5306, 1, 15, 4, 0), + (5307, 1, 15, 5, 0), + (5308, 1, 15, 6, 0), + (5309, 1, 15, 7, 0), + (5310, 1, 15, 8, 0), + (5317, 1, 114, -43, 0), + (5318, 1, 114, -46, 0), + (5319, 1, 114, -50, 0), + (5320, 1, 218, 11, 0), + (5321, 1, 218, 12, 0), + (5322, 1, 218, 13, 0), + (5323, 1, 218, 14, 0), + (5324, 1, 218, 15, 0), + (5325, 1, 280, 27, 0), + (5326, 1, 280, 34, 0), + (5327, 1, 280, 41, 0), + (5328, 1, 280, 44, 0), + (5329, 1, 280, 47, 0), + (5339, 1, 215, 24, 0), + (5347, 1, 375, 225, 0), + (5348, 1, 375, 230, 0), + (5360, 1, 397, 1300, 0), + (5366, 1, 247, 75, 20), + (5500, 1, 231, 5, 0), + (5501, 1, 231, 7, 0), + (5502, 1, 231, 9, 0), + (5516, 1, 320, 6, 0), + (5517, 1, 320, 7, 0), + (5518, 1, 320, 8, 0), + (5519, 1, 172, 40, 0), + (5520, 1, 172, 41, 0), + (5521, 1, 172, 42, 0), + (5522, 1, 172, 43, 0), + (5523, 1, 172, 44, 0), + (5524, 1, 259, 46, 0), + (5525, 1, 259, 47, 0), + (5526, 1, 259, 48, 0), + (5527, 1, 259, 49, 0), + (5528, 1, 259, 50, 0), + (5529, 1, 339, 11, 12680), + (5529, 2, 138, 1, 0), + (5529, 3, 141, 1, 0), + (5529, 4, 142, 60, 0), + (5529, 5, 137, 0, 0), + (5529, 6, 311, 0, 0), + (5529, 7, 134, 80, 0), + (5529, 8, 139, -265, 0), + (5529, 9, 139, -754, 0), + (5529, 10, 139, -1332, 0), + (5529, 11, 139, -1572, 0), + (5529, 12, 139, -2749, 0), + (5529, 13, 139, -4979, 0), + (5529, 14, 139, -5418, 0), + (5529, 15, 139, -5403, 0), + (5529, 16, 348, 10, 0), + (5530, 1, 339, 13, 12681), + (5530, 2, 138, 1, 0), + (5530, 3, 141, 1, 0), + (5530, 4, 142, 60, 0), + (5530, 5, 137, 0, 0), + (5530, 6, 311, 0, 0), + (5530, 7, 134, 80, 0), + (5530, 8, 139, -265, 0), + (5530, 9, 139, -754, 0), + (5530, 10, 139, -1332, 0), + (5530, 11, 139, -1572, 0), + (5530, 12, 139, -2749, 0), + (5530, 13, 139, -4979, 0), + (5530, 14, 139, -5418, 0), + (5530, 15, 139, -5403, 0), + (5530, 16, 348, 10, 0), + (5531, 1, 339, 15, 12682), + (5531, 2, 138, 1, 0), + (5531, 3, 141, 1, 0), + (5531, 4, 142, 60, 0), + (5531, 5, 137, 0, 0), + (5531, 6, 311, 0, 0), + (5531, 7, 134, 80, 0), + (5531, 8, 139, -265, 0), + (5531, 9, 139, -754, 0), + (5531, 10, 139, -1332, 0), + (5531, 11, 139, -1572, 0), + (5531, 12, 139, -2749, 0), + (5531, 13, 139, -4979, 0), + (5531, 14, 139, -5418, 0), + (5531, 15, 139, -5403, 0), + (5531, 16, 348, 10, 0), + (5532, 1, 339, 17, 12683), + (5532, 2, 138, 1, 0), + (5532, 3, 141, 1, 0), + (5532, 4, 142, 60, 0), + (5532, 5, 137, 0, 0), + (5532, 6, 311, 0, 0), + (5532, 7, 134, 80, 0), + (5532, 8, 139, -265, 0), + (5532, 9, 139, -754, 0), + (5532, 10, 139, -1332, 0), + (5532, 11, 139, -1572, 0), + (5532, 12, 139, -2749, 0), + (5532, 13, 139, -4979, 0), + (5532, 14, 139, -5418, 0), + (5532, 15, 139, -5403, 0), + (5532, 16, 348, 10, 0), + (5533, 1, 339, 19, 12684), + (5533, 2, 138, 1, 0), + (5533, 3, 141, 1, 0), + (5533, 4, 142, 60, 0), + (5533, 5, 137, 0, 0), + (5533, 6, 311, 0, 0), + (5533, 7, 134, 80, 0), + (5533, 8, 139, -265, 0), + (5533, 9, 139, -754, 0), + (5533, 10, 139, -1332, 0), + (5533, 11, 139, -1572, 0), + (5533, 12, 139, -2749, 0), + (5533, 13, 139, -4979, 0), + (5533, 14, 139, -5418, 0), + (5533, 15, 139, -5403, 0), + (5533, 16, 348, 10, 0), + (5534, 1, 266, 18, 0), + (5535, 1, 266, 20, 0), + (5536, 1, 266, 22, 0), + (5542, 1, 330, 110, 0), + (5542, 2, 330, 110, 1), + (5542, 3, 330, 110, 2), + (5542, 4, 330, 110, 3), + (5542, 5, 330, 110, 28), + (5542, 6, 330, 110, 36), + (5542, 7, 330, 110, 77), + (5543, 1, 330, 115, 0), + (5543, 2, 330, 115, 1), + (5543, 3, 330, 115, 2), + (5543, 4, 330, 115, 3), + (5543, 5, 330, 115, 28), + (5543, 6, 330, 115, 36), + (5543, 7, 330, 115, 77), + (5544, 1, 330, 120, 0), + (5544, 2, 330, 120, 1), + (5544, 3, 330, 120, 2), + (5544, 4, 330, 120, 3), + (5544, 5, 330, 120, 28), + (5544, 6, 330, 120, 36), + (5544, 7, 330, 120, 77), + (5545, 1, 330, 110, 0), + (5545, 2, 330, 110, 1), + (5545, 3, 330, 110, 2), + (5545, 4, 330, 110, 3), + (5545, 5, 330, 110, 28), + (5545, 6, 330, 110, 36), + (5546, 1, 330, 115, 0), + (5546, 2, 330, 115, 1), + (5546, 3, 330, 115, 2), + (5546, 4, 330, 115, 3), + (5546, 5, 330, 115, 28), + (5546, 6, 330, 115, 36), + (5547, 1, 330, 120, 0), + (5547, 2, 330, 120, 1), + (5547, 3, 330, 120, 2), + (5547, 4, 330, 120, 3), + (5547, 5, 330, 120, 28), + (5547, 6, 330, 120, 36), + (5548, 1, 330, 110, 0), + (5548, 2, 330, 110, 1), + (5548, 3, 330, 110, 2), + (5548, 4, 330, 110, 3), + (5548, 5, 330, 110, 28), + (5548, 6, 330, 110, 36), + (5548, 7, 330, 110, 77), + (5549, 1, 330, 115, 0), + (5549, 2, 330, 115, 1), + (5549, 3, 330, 115, 2), + (5549, 4, 330, 115, 3), + (5549, 5, 330, 115, 28), + (5549, 6, 330, 115, 36), + (5549, 7, 330, 115, 77), + (5550, 1, 330, 120, 0), + (5550, 2, 330, 120, 1), + (5550, 3, 330, 120, 2), + (5550, 4, 330, 120, 3), + (5550, 5, 330, 120, 28), + (5550, 6, 330, 120, 36), + (5550, 7, 330, 120, 77), + (5551, 1, 330, 85, 0), + (5551, 2, 330, 85, 1), + (5551, 3, 330, 85, 2), + (5551, 4, 330, 85, 3), + (5551, 5, 330, 85, 28), + (5551, 6, 330, 85, 36), + (5551, 7, 330, 85, 77), + (5552, 1, 330, 90, 0), + (5552, 2, 330, 90, 1), + (5552, 3, 330, 90, 2), + (5552, 4, 330, 90, 3), + (5552, 5, 330, 90, 28), + (5552, 6, 330, 90, 36), + (5552, 7, 330, 90, 77), + (5553, 1, 330, 95, 0), + (5553, 2, 330, 95, 1), + (5553, 3, 330, 95, 2), + (5553, 4, 330, 95, 3), + (5553, 5, 330, 95, 28), + (5553, 6, 330, 95, 36), + (5553, 7, 330, 95, 77), + (5554, 1, 278, 700, 44340), + (5554, 2, 440, 71, 100), + (5555, 1, 278, 720, 47230), + (5555, 2, 440, 73, 100), + (5556, 1, 278, 750, 51057), + (5556, 2, 440, 75, 100), + (5557, 1, 341, 110, 0), + (5558, 1, 341, 120, 0), + (5559, 1, 341, 130, 0), + (5560, 1, 341, 140, 0), + (5561, 1, 341, 150, 0), + (5562, 1, 360, 40, 11023), + (5563, 1, 360, 50, 11023), + (5564, 1, 360, 60, 11023), + (5566, 1, 318, 11, 0), + (5567, 1, 318, 12, 0), + (5568, 1, 318, 13, 0), + (5569, 1, 318, 14, 0), + (5570, 1, 318, 15, 0), + (5571, 1, 294, 16, 100), + (5572, 1, 294, 17, 100), + (5573, 1, 294, 18, 100), + (5574, 1, 294, 0, 170), + (5575, 1, 294, 0, 175), + (5576, 1, 294, 0, 180), + (5577, 1, 294, 0, 145), + (5578, 1, 294, 0, 150), + (5579, 1, 294, 0, 155), + (5580, 1, 266, 30, 0), + (5581, 1, 266, 31, 0), + (5582, 1, 266, 32, 0), + (5586, 1, 114, -53, 0), + (5587, 1, 114, -56, 0), + (5588, 1, 114, -59, 0), + (5589, 1, 319, 17, 0), + (5590, 1, 319, 19, 0), + (5591, 1, 319, 21, 0), + (5592, 1, 274, 30, 0), + (5593, 1, 274, 32, 0), + (5594, 1, 274, 34, 0), + (5595, 1, 279, 31, 0), + (5596, 1, 279, 32, 0), + (5597, 1, 279, 33, 0), + (5611, 1, 274, 28, 0), + (5612, 1, 274, 30, 0), + (5613, 1, 274, 32, 0), + (5617, 1, 294, 18, 100), + (5618, 1, 294, 19, 100), + (5619, 1, 294, 20, 100), + (5620, 1, 320, 6, 0), + (5621, 1, 320, 7, 0), + (5622, 1, 320, 8, 0), + (5623, 1, 15, 9, 0), + (5624, 1, 15, 10, 0), + (5625, 1, 15, 11, 0), + (5626, 1, 15, 12, 0), + (5627, 1, 15, 13, 0), + (5628, 1, 114, -53, 0), + (5629, 1, 114, -56, 0), + (5630, 1, 114, -59, 0), + (5729, 1, 218, 11, 0), + (5730, 1, 218, 12, 0), + (5731, 1, 218, 13, 0), + (5732, 1, 218, 14, 0), + (5733, 1, 218, 15, 0), + (5738, 1, 280, 62, 0), + (5739, 1, 280, 63, 0), + (5740, 1, 280, 64, 0), + (5776, 1, 169, 5, -1), + (5777, 1, 169, 10, -1), + (5778, 1, 169, 15, -1), + (5797, 1, 264, 2520, 396), + (5797, 2, 264, 2520, 8504), + (5797, 3, 264, 2520, 8505), + (5798, 1, 264, 2880, 396), + (5798, 2, 264, 2880, 8504), + (5798, 3, 264, 2880, 8505), + (5799, 1, 264, 3240, 396), + (5799, 2, 264, 3240, 8504), + (5799, 3, 264, 3240, 8505), + (5806, 1, 279, 7, 0), + (5807, 1, 279, 11, 0), + (5808, 1, 279, 15, 0), + (5825, 1, 244, -40, 0), + (5850, 1, 287, 2, 1), + (5850, 2, 137, 31, 0), + (5850, 3, 136, 5, 0), + (5860, 1, 243, 40, 0), + (5861, 1, 243, 45, 0), + (5862, 1, 243, 50, 0), + (5880, 1, 287, 8, 0), + (5880, 2, 385, 2754, 1), + (5881, 1, 287, 10, 0), + (5881, 2, 385, 2754, 1), + (5882, 1, 287, 12, 0), + (5882, 2, 385, 2754, 1), + (5883, 2, 139, 2754, 1), + (5886, 1, 274, 12, 0), + (5887, 1, 274, 14, 0), + (5888, 1, 274, 16, 0), + (5889, 1, 280, 51, 0), + (5890, 1, 280, 52, 0), + (5891, 1, 280, 53, 0), + (5909, 1, 279, 29, 0), + (5910, 1, 279, 30, 0), + (5911, 1, 279, 31, 0), + (5912, 1, 279, 32, 0), + (5913, 1, 279, 33, 0), + (5917, 1, 220, 100, 26), + (5917, 2, 220, 100, 30), + (5917, 3, 220, 100, 38), + (5918, 1, 220, 110, 26), + (5918, 2, 220, 110, 30), + (5918, 3, 220, 110, 38), + (5919, 1, 220, 120, 26), + (5919, 2, 220, 120, 30), + (5919, 3, 220, 120, 38), + (5922, 1, 292, 35, 0), + (5923, 1, 292, 40, 0), + (5924, 1, 292, 45, 0), + (5939, 1, 218, 6, 0), + (5940, 1, 218, 7, 0), + (5941, 1, 218, 8, 0), + (5942, 1, 218, 9, 0), + (5943, 1, 218, 10, 0), + (5944, 1, 273, 4, 0), + (5945, 1, 273, 5, 0), + (5946, 1, 273, 6, 0), + (5950, 1, 264, 240, 175), + (5950, 2, 264, 240, 792), + (5951, 1, 264, 300, 175), + (5951, 2, 264, 300, 792), + (5952, 1, 264, 360, 175), + (5952, 2, 264, 360, 792), + (5954, 1, 264, 2400, 68), + (5955, 1, 264, 3000, 68), + (5956, 1, 264, 3600, 68), + (5972, 1, 264, 2880, 6001), + (5972, 2, 264, 2880, 3676), + (5973, 1, 264, 2880, 6000), + (5973, 2, 264, 2880, 87), + (6003, 1, 279, 29, 0), + (6004, 1, 279, 30, 0), + (6005, 1, 279, 31, 0), + (6006, 1, 279, 32, 0), + (6007, 1, 279, 33, 0), + (6011, 1, 216, 95, 0), + (6011, 2, 216, 95, 1), + (6011, 3, 216, 95, 2), + (6011, 4, 216, 95, 3), + (6011, 5, 216, 95, 10), + (6011, 6, 216, 95, 28), + (6011, 7, 216, 95, 30), + (6011, 8, 216, 95, 36), + (6011, 9, 216, 95, 77), + (6012, 1, 216, 100, 0), + (6012, 2, 216, 100, 1), + (6012, 3, 216, 100, 2), + (6012, 4, 216, 100, 3), + (6012, 5, 216, 100, 10), + (6012, 6, 216, 100, 28), + (6012, 7, 216, 100, 30), + (6012, 8, 216, 100, 36), + (6012, 9, 216, 100, 77), + (6013, 1, 216, 105, 0), + (6013, 2, 216, 105, 1), + (6013, 3, 216, 105, 2), + (6013, 4, 216, 105, 3), + (6013, 5, 216, 105, 10), + (6013, 6, 216, 105, 28), + (6013, 7, 216, 105, 30), + (6013, 8, 216, 105, 36), + (6013, 9, 216, 105, 77), + (6014, 1, 360, 40, 12617), + (6015, 1, 360, 50, 12617), + (6016, 1, 360, 60, 12617), + (6017, 1, 217, 0, 65440), + (6017, 2, 346, 72, 28), + (6018, 1, 217, 0, 70880), + (6018, 2, 346, 74, 28), + (6019, 1, 217, 0, 76600), + (6019, 2, 346, 76, 28), + (6020, 1, 220, 15, 21), + (6020, 2, 220, 15, 23), + (6020, 3, 220, 30, 52), + (6020, 4, 220, 15, 28), + (6021, 1, 220, 25, 21), + (6021, 2, 220, 25, 23), + (6021, 3, 220, 50, 52), + (6021, 4, 220, 25, 28), + (6022, 1, 220, 35, 21), + (6022, 2, 220, 35, 23), + (6022, 3, 220, 70, 52), + (6022, 4, 220, 35, 28), + (6023, 1, 278, 900, 66950), + (6023, 2, 440, 82, 100), + (6024, 1, 278, 900, 70230), + (6024, 2, 440, 84, 100), + (6025, 1, 278, 900, 74935), + (6025, 2, 440, 86, 100), + (6026, 1, 127, 10, 0), + (6026, 2, 139, 16106, 0), + (6027, 1, 127, 25, 0), + (6027, 2, 139, 16106, 0), + (6028, 1, 127, 50, 0), + (6028, 2, 139, 16106, 0), + (6029, 1, 216, 200, 8), + (6030, 1, 216, 250, 8), + (6031, 1, 216, 300, 8), + (6032, 1, 439, 0, 70880), + (6032, 2, 345, 68, 50), + (6033, 1, 439, 0, 76600), + (6033, 2, 345, 70, 50), + (6034, 1, 439, 0, 82600), + (6034, 2, 345, 72, 35), + (6035, 1, 258, 48, 0), + (6036, 1, 258, 51, 0), + (6037, 1, 258, 54, 0), + (6042, 1, 220, 70, 8), + (6043, 1, 220, 80, 8), + (6044, 1, 220, 100, 8), + (6045, 1, 220, 45, 21), + (6045, 2, 220, 45, 23), + (6045, 3, 220, 90, 52), + (6045, 4, 220, 45, 28), + (6046, 1, 220, 55, 21), + (6046, 2, 220, 55, 23), + (6046, 3, 220, 110, 52), + (6046, 4, 220, 55, 28), + (6047, 1, 220, 65, 21), + (6047, 2, 220, 65, 23), + (6047, 3, 220, 130, 52), + (6047, 4, 220, 65, 28), + (6048, 1, 220, 75, 21), + (6048, 2, 220, 75, 23), + (6048, 3, 220, 150, 52), + (6048, 4, 220, 75, 28), + (6049, 1, 220, 85, 21), + (6049, 2, 220, 85, 23), + (6049, 3, 220, 170, 52), + (6049, 4, 220, 85, 28), + (6050, 1, 220, 95, 21), + (6050, 2, 220, 95, 23), + (6050, 3, 220, 190, 52), + (6050, 4, 220, 95, 28), + (6051, 1, 213, 1, 0), + (6052, 1, 213, 3, 0), + (6053, 1, 213, 5, 0), + (6057, 1, 220, 105, 21), + (6057, 2, 220, 105, 23), + (6057, 3, 220, 210, 52), + (6057, 4, 220, 105, 28), + (6058, 1, 220, 115, 21), + (6058, 2, 220, 115, 23), + (6058, 3, 220, 230, 52), + (6058, 4, 220, 115, 28), + (6059, 1, 220, 125, 21), + (6059, 2, 220, 125, 23), + (6059, 3, 220, 250, 52), + (6059, 4, 220, 125, 28), + (6060, 1, 247, 5, 76), + (6061, 1, 247, 10, 76), + (6063, 1, 303, 4500, 4500), + (6063, 2, 139, 2766, 0), + (6064, 1, 303, 5000, 5000), + (6064, 2, 139, 2766, 0), + (6065, 1, 303, 5500, 5500), + (6065, 2, 139, 2766, 0), + (6066, 1, 85, 12629, 0), + (6067, 1, 85, 12630, 0), + (6068, 1, 85, 12631, 0), + (6069, 1, 85, 12632, 0), + (6070, 1, 85, 12633, 0), + (6071, 1, 85, 12634, 0), + (6072, 1, 302, 266, 266), + (6072, 2, 385, 99, 0), + (6073, 1, 302, 290, 290), + (6073, 2, 385, 99, 0), + (6074, 1, 302, 310, 310), + (6074, 2, 385, 99, 0), + (6075, 1, 59, -18, 0), + (6076, 1, 59, -21, 0), + (6077, 1, 59, -24, 0), + (6078, 1, 59, -27, 0), + (6079, 1, 59, -30, 0), + (6080, 1, 189, 12, 0), + (6081, 1, 189, 13, 0), + (6082, 1, 247, 50, 20), + (6083, 1, 247, 75, 20), + (6084, 1, 247, 100, 20), + (6085, 1, 292, 20, 0), + (6086, 1, 292, 30, 0), + (6087, 1, 292, 40, 0), + (6088, 1, 264, 180, 392), + (6089, 1, 264, 360, 392), + (6090, 1, 264, 540, 392), + (6112, 1, 131, 10, 10), + (6112, 2, 348, 10, 0), + (6112, 3, 137, -32, 0), + (6113, 1, 287, 2, 0), + (6113, 2, 137, 100, 0), + (6113, 3, 385, -4232, 0), + (6113, 4, 385, -4332, 0), + (6113, 5, 139, -2741, 0), + (6113, 6, 385, -16192, 0), + (6113, 7, 139, -16843, 0), + (6114, 1, 287, 3, 0), + (6114, 2, 137, 100, 0), + (6114, 3, 385, -4232, 0), + (6114, 4, 385, -4332, 0), + (6114, 5, 139, -2741, 0), + (6114, 6, 385, -16192, 0), + (6114, 7, 139, -16843, 0), + (6115, 1, 287, 4, 0), + (6115, 2, 137, 100, 0), + (6115, 3, 385, -4232, 0), + (6115, 4, 385, -4332, 0), + (6115, 5, 139, -2741, 0), + (6115, 6, 385, -16192, 0), + (6115, 7, 139, -16843, 0), + (6119, 1, 69, 100, 0), + (6120, 1, 69, 200, 0), + (6121, 1, 69, 300, 0), + (6122, 1, 69, 400, 0), + (6123, 1, 69, 500, 0), + (6124, 1, 320, 1, 0), + (6125, 1, 320, 3, 0), + (6126, 1, 320, 5, 0), + (6127, 1, 320, 6, 0), + (6128, 1, 320, 7, 0), + (6129, 1, 320, 8, 0), + (6130, 1, 255, 48, 0), + (6131, 1, 255, 60, 0), + (6132, 1, 255, 72, 0), + (6136, 1, 264, 360, 300), + (6202, 1, 247, 10, 35), + (6203, 1, 247, 20, 35), + (6204, 1, 247, 60, 35), + (6209, 1, 264, 720, 245), + (6210, 1, 264, 1440, 245), + (6211, 1, 264, 2160, 245), + (6215, 1, 247, 5, 76), + (6216, 1, 247, 10, 76), + (6217, 1, 247, 15, 76), + (6223, 1, 232, 11, 4544), + (6224, 1, 232, 12, 4544), + (6225, 1, 232, 13, 4544), + (6226, 1, 232, 14, 4544), + (6227, 1, 232, 15, 4544), + (6228, 1, 264, 120, 404), + (6229, 1, 264, 240, 404), + (6230, 1, 264, 360, 404), + (6231, 1, 264, 480, 404), + (6233, 1, 264, 1728, 43), + (6234, 1, 264, 2160, 43), + (6235, 1, 264, 2592, 43), + (6236, 1, 287, 1, 0), + (6236, 2, 137, 3, 0), + (6236, 3, 137, 99, 0), + (6236, 4, 138, 0, 0), + (6236, 5, 244, 50, 0), + (6237, 1, 287, 2, 0), + (6237, 2, 137, 3, 0), + (6237, 3, 137, 99, 0), + (6237, 4, 138, 0, 0), + (6237, 5, 244, 38, 0), + (6238, 1, 287, 3, 0), + (6238, 2, 137, 3, 0), + (6238, 3, 137, 99, 0), + (6238, 4, 138, 0, 0), + (6238, 5, 244, 25, 0), + (6240, 1, 273, 3, 0), + (6241, 1, 273, 6, 0), + (6242, 1, 273, 9, 0), + (6243, 1, 273, 12, 0), + (6244, 1, 273, 15, 0), + (6245, 1, 273, 18, 0), + (6249, 1, 310, 1000, 0), + (6249, 2, 139, 11903, 0), + (6249, 3, 310, 1000, 0), + (6249, 4, 139, 11904, 0), + (6249, 5, 310, 1000, 0), + (6249, 6, 139, 11905, 0), + (6249, 7, 310, 1000, 0), + (6249, 8, 139, 1362, 0), + (6249, 9, 310, 1000, 0), + (6249, 10, 139, 8032, 0), + (6249, 11, 310, 1000, 0), + (6249, 12, 385, 6131, 0), + (6249, 13, 385, 6231, 0), + (6249, 14, 385, 6331, 0), + (6249, 15, 385, 6431, 0), + (6249, 16, 385, 6531, 0), + (6249, 17, 385, 6631, 0), + (6250, 1, 310, 2000, 0), + (6250, 2, 139, 11903, 0), + (6250, 3, 310, 2000, 0), + (6250, 4, 139, 11904, 0), + (6250, 5, 310, 2000, 0), + (6250, 6, 139, 11905, 0), + (6250, 7, 310, 2000, 0), + (6250, 8, 139, 1362, 0), + (6250, 9, 310, 2000, 0), + (6250, 10, 139, 8032, 0), + (6250, 11, 310, 2000, 0), + (6250, 12, 385, 6131, 0), + (6250, 13, 385, 6231, 0), + (6250, 14, 385, 6331, 0), + (6250, 15, 385, 6431, 0), + (6250, 16, 385, 6531, 0), + (6250, 17, 385, 6631, 0), + (6251, 1, 310, 3000, 0), + (6251, 2, 139, 11903, 0), + (6251, 3, 310, 3000, 0), + (6251, 4, 139, 11904, 0), + (6251, 5, 310, 3000, 0), + (6251, 6, 139, 11905, 0), + (6251, 7, 310, 3000, 0), + (6251, 8, 139, 1362, 0), + (6251, 9, 310, 3000, 0), + (6251, 10, 139, 8032, 0), + (6251, 11, 310, 3000, 0), + (6251, 12, 385, 6131, 0), + (6251, 13, 385, 6231, 0), + (6251, 14, 385, 6331, 0), + (6251, 15, 385, 6431, 0), + (6251, 16, 385, 6531, 0), + (6251, 17, 385, 6631, 0), + (6252, 1, 310, 4000, 0), + (6252, 2, 139, 11903, 0), + (6252, 3, 310, 4000, 0), + (6252, 4, 139, 11904, 0), + (6252, 5, 310, 4000, 0), + (6252, 6, 139, 11905, 0), + (6252, 7, 310, 4000, 0), + (6252, 8, 139, 1362, 0), + (6252, 9, 310, 4000, 0), + (6252, 10, 139, 8032, 0), + (6252, 11, 310, 4000, 0), + (6252, 12, 385, 6131, 0), + (6252, 13, 385, 6231, 0), + (6252, 14, 385, 6331, 0), + (6252, 15, 385, 6431, 0), + (6252, 16, 385, 6531, 0), + (6252, 17, 385, 6631, 0), + (6253, 1, 310, 5000, 0), + (6253, 2, 139, 11903, 0), + (6253, 3, 310, 5000, 0), + (6253, 4, 139, 11904, 0), + (6253, 5, 310, 5000, 0), + (6253, 6, 139, 11905, 0), + (6253, 7, 310, 5000, 0), + (6253, 8, 139, 1362, 0), + (6253, 9, 310, 5000, 0), + (6253, 10, 139, 8032, 0), + (6253, 11, 310, 5000, 0), + (6253, 12, 385, 6131, 0), + (6253, 13, 385, 6231, 0), + (6253, 14, 385, 6331, 0), + (6253, 15, 385, 6431, 0), + (6253, 16, 385, 6531, 0), + (6253, 17, 385, 6631, 0), + (6257, 1, 128, 5, 5), + (6257, 2, 138, 1, 0), + (6257, 3, 140, 1, 0), + (6257, 4, 139, -2741, 0), + (6257, 5, 139, -16843, 0), + (6257, 6, 385, -16192, 0), + (6258, 1, 128, 15, 15), + (6258, 2, 138, 1, 0), + (6258, 3, 140, 1, 0), + (6258, 4, 139, -2741, 0), + (6258, 5, 139, -16843, 0), + (6258, 6, 385, -16192, 0), + (6259, 1, 128, 30, 30), + (6259, 2, 138, 1, 0), + (6259, 3, 140, 1, 0), + (6259, 4, 139, -2741, 0), + (6259, 5, 139, -16843, 0), + (6259, 6, 385, -16192, 0), + (6260, 1, 264, 720, 98), + (6261, 1, 264, 900, 98), + (6262, 1, 264, 1080, 98), + (6266, 1, 224, 20, 10), + (6266, 2, 173, 1, 0), + (6267, 1, 224, 35, 10), + (6267, 2, 173, 2, 0), + (6268, 1, 224, 50, 10), + (6268, 2, 173, 3, 0), + (6269, 1, 224, 20, 30), + (6269, 2, 173, 1, 0), + (6270, 1, 224, 35, 30), + (6270, 2, 173, 2, 0), + (6271, 1, 224, 50, 30), + (6271, 2, 173, 3, 0), + (6272, 1, 264, 15, 672), + (6273, 1, 264, 30, 672), + (6274, 1, 264, 45, 672), + (6275, 1, 224, 20, 8), + (6275, 2, 173, 1, 0), + (6276, 1, 224, 35, 8), + (6276, 2, 173, 2, 0), + (6277, 1, 224, 50, 8), + (6277, 2, 173, 3, 0), + (6283, 1, 85, 13200, 0), + (6284, 1, 85, 13200, 25), + (6285, 1, 85, 13200, 50), + (6287, 1, 224, 20, 30), + (6287, 2, 173, 1, 0), + (6288, 1, 224, 35, 30), + (6288, 2, 173, 3, 0), + (6289, 1, 224, 50, 30), + (6289, 2, 173, 3, 0), + (6300, 1, 247, 20, 76), + (6301, 1, 247, 25, 76), + (6302, 1, 264, 120, 3710), + (6303, 1, 264, 240, 3710), + (6304, 1, 264, 360, 3710), + (6319, 1, 264, 1728, 107), + (6320, 1, 264, 2160, 107), + (6321, 1, 264, 2592, 107), + (6322, 1, 216, 5, 51), + (6323, 1, 216, 15, 51), + (6324, 1, 216, 25, 51), + (6331, 1, 252, 70, 0), + (6332, 1, 252, 75, 0), + (6334, 1, 185, 5, 51), + (6335, 1, 185, 10, 51), + (6336, 1, 185, 15, 51), + (6337, 1, 264, 60, 553), + (6338, 1, 264, 120, 553), + (6339, 1, 264, 180, 553), + (6340, 1, 264, 180, 777), + (6341, 1, 264, 360, 777), + (6342, 1, 264, 540, 777), + (6343, 1, 264, 5, 468), + (6343, 2, 264, 5, 469), + (6343, 3, 264, 5, 470), + (6344, 1, 264, 10, 468), + (6344, 2, 264, 10, 469), + (6344, 3, 264, 10, 470), + (6345, 1, 264, 15, 468), + (6345, 2, 264, 15, 469), + (6345, 3, 264, 15, 470), + (6346, 1, 264, 180, 494), + (6347, 1, 264, 360, 494), + (6348, 1, 264, 540, 494), + (6349, 1, 264, 180, 500), + (6350, 1, 264, 360, 500), + (6351, 1, 264, 540, 500), + (6355, 1, 310, 360000, 0), + (6355, 2, 139, 4506, 0), + (6355, 3, 310, 360000, 0), + (6355, 4, 385, 11122, 0), + (6355, 5, 385, 11222, 0), + (6355, 6, 385, 11322, 0), + (6355, 7, 385, 11522, 0), + (6356, 1, 310, 720000, 0), + (6356, 2, 139, 4506, 0), + (6356, 3, 310, 720000, 0), + (6356, 4, 385, 11122, 0), + (6356, 5, 385, 11222, 0), + (6356, 6, 385, 11322, 0), + (6356, 7, 385, 11522, 0), + (6357, 1, 310, 1080000, 0), + (6357, 2, 139, 4506, 0), + (6357, 3, 310, 1080000, 0), + (6357, 4, 385, 11122, 0), + (6357, 5, 385, 11222, 0), + (6357, 6, 385, 11322, 0), + (6357, 7, 385, 11522, 0), + (6358, 1, 310, 1440000, 0), + (6358, 2, 139, 4506, 0), + (6358, 3, 310, 1440000, 0), + (6358, 4, 385, 11122, 0), + (6358, 5, 385, 11222, 0), + (6358, 6, 385, 11322, 0), + (6358, 7, 385, 11522, 0), + (6359, 1, 310, 1800000, 0), + (6359, 2, 139, 4506, 0), + (6359, 3, 310, 1800000, 0), + (6359, 4, 385, 11122, 0), + (6359, 5, 385, 11222, 0), + (6359, 6, 385, 11322, 0), + (6359, 7, 385, 11522, 0), + (6360, 1, 310, 2160000, 0), + (6360, 2, 139, 4506, 0), + (6360, 3, 310, 2160000, 0), + (6360, 4, 385, 11122, 0), + (6360, 5, 385, 11222, 0), + (6360, 6, 385, 11322, 0), + (6360, 7, 385, 11522, 0), + (6361, 1, 213, 3, 0), + (6362, 1, 310, 120000, 0), + (6362, 2, 139, 5040, 0), + (6363, 1, 310, 240000, 0), + (6363, 2, 139, 5040, 0), + (6364, 1, 310, 360000, 0), + (6364, 2, 139, 5040, 0), + (6365, 1, 310, 480000, 0), + (6365, 2, 139, 5040, 0), + (6366, 1, 310, 600000, 0), + (6366, 2, 139, 5040, 0), + (6375, 1, 375, 107, 0), + (6376, 1, 375, 115, 0), + (6377, 1, 375, 125, 0), + (6383, 1, 215, 5, 0), + (6384, 1, 215, 7, 0), + (6385, 1, 215, 10, 0), + (6386, 1, 293, 5, 0), + (6387, 1, 293, 10, 0), + (6388, 1, 293, 15, 0), + (6389, 1, 293, 20, 0), + (6390, 1, 0, 16, 0), + (6391, 1, 0, 17, 0), + (6392, 1, 0, 18, 0), + (6393, 1, 0, 19, 0), + (6394, 1, 0, 20, 0), + (6395, 1, 85, 13502, 0), + (6396, 1, 85, 13503, 0), + (6397, 1, 85, 13504, 0), + (6403, 1, 294, 11, 100), + (6404, 1, 294, 13, 100), + (6405, 1, 294, 15, 100), + (6406, 1, 360, 25, 13201), + (6407, 1, 360, 25, 13202), + (6408, 1, 360, 25, 13203), + (6409, 1, 247, 5, 76), + (6410, 1, 247, 10, 76), + (6411, 1, 247, 15, 76), + (6412, 1, 247, 20, 76), + (6413, 1, 247, 25, 76), + (6414, 1, 247, 30, 76), + (6415, 1, 247, 35, 76), + (6416, 1, 247, 40, 76), + (6417, 1, 247, 45, 76), + (6418, 1, 247, 50, 76), + (6419, 1, 247, 5, 76), + (6420, 1, 247, 10, 76), + (6421, 1, 247, 15, 76), + (6422, 1, 214, 100, 0), + (6423, 1, 214, 200, 0), + (6424, 1, 214, 300, 0), + (6428, 1, 320, 1, 0), + (6429, 1, 320, 3, 0), + (6430, 1, 320, 5, 0), + (6431, 1, 317, 6, 0), + (6432, 1, 317, 7, 0), + (6433, 1, 317, 8, 0), + (6434, 1, 317, 9, 0), + (6435, 1, 317, 10, 0), + (6436, 1, 244, 70, 0), + (6437, 1, 244, 60, 0), + (6438, 1, 244, 50, 0), + (6439, 1, 264, 720, 41), + (6440, 1, 264, 900, 41), + (6441, 1, 264, 840, 420), + (6442, 1, 264, 540, 362), + (6443, 1, 264, 630, 362), + (6445, 1, 127, 15, 0), + (6445, 2, 139, 3248, 0), + (6445, 3, 127, 15, 0), + (6445, 4, 139, 3249, 0), + (6446, 1, 127, 30, 0), + (6446, 2, 139, 3248, 0), + (6446, 3, 127, 30, 0), + (6446, 4, 139, 3249, 0), + (6447, 1, 127, 50, 0), + (6447, 2, 139, 3248, 0), + (6447, 3, 127, 50, 0), + (6447, 4, 139, 3249, 0), + (6452, 1, 310, 1000, 0), + (6452, 2, 403, 7, 0), + (6452, 3, 404, 35, 0), + (6452, 4, 144, 2000, 0), + (6452, 5, 310, 5000, 0), + (6452, 6, 403, 7, 0), + (6452, 7, 404, 35, 0), + (6452, 8, 144, 10000, 0), + (6453, 1, 310, 2000, 0), + (6453, 2, 403, 7, 0), + (6453, 3, 404, 35, 0), + (6453, 4, 144, 2000, 0), + (6453, 5, 310, 10000, 0), + (6453, 6, 403, 7, 0), + (6453, 7, 404, 35, 0), + (6453, 8, 144, 10000, 0), + (6454, 1, 310, 3000, 0), + (6454, 2, 403, 7, 0), + (6454, 3, 404, 35, 0), + (6454, 4, 144, 2000, 0), + (6454, 5, 310, 15000, 0), + (6454, 6, 403, 7, 0), + (6454, 7, 404, 35, 0), + (6454, 8, 144, 10000, 0), + (6458, 1, 310, 30000, 0), + (6458, 2, 385, 5137, 0), + (6458, 3, 385, 5237, 0), + (6458, 4, 385, 5337, 0), + (6458, 5, 385, 5437, 0), + (6458, 6, 385, 5537, 0), + (6458, 7, 385, 5637, 0), + (6458, 8, 127, 15, 15), + (6458, 9, 385, 5137, 0), + (6458, 10, 385, 5237, 0), + (6458, 11, 385, 5337, 0), + (6458, 12, 385, 5437, 0), + (6458, 13, 385, 5537, 0), + (6458, 14, 385, 5637, 0), + (6459, 1, 310, 60000, 0), + (6459, 2, 385, 5137, 0), + (6459, 3, 385, 5237, 0), + (6459, 4, 385, 5337, 0), + (6459, 5, 385, 5437, 0), + (6459, 6, 385, 5537, 0), + (6459, 7, 385, 5637, 0), + (6459, 8, 127, 30, 30), + (6459, 9, 385, 5137, 0), + (6459, 10, 385, 5237, 0), + (6459, 11, 385, 5337, 0), + (6459, 12, 385, 5437, 0), + (6459, 13, 385, 5537, 0), + (6459, 14, 385, 5637, 0), + (6460, 1, 310, 90000, 0), + (6460, 2, 385, 5137, 0), + (6460, 3, 385, 5237, 0), + (6460, 4, 385, 5337, 0), + (6460, 5, 385, 5437, 0), + (6460, 6, 385, 5537, 0), + (6460, 7, 385, 5637, 0), + (6460, 8, 127, 50, 50), + (6460, 9, 385, 5137, 0), + (6460, 10, 385, 5237, 0), + (6460, 11, 385, 5337, 0), + (6460, 12, 385, 5437, 0), + (6460, 13, 385, 5537, 0), + (6460, 14, 385, 5637, 0), + (6461, 1, 127, 15, 0), + (6461, 2, 385, 14130, 0), + (6461, 3, 385, 14230, 0), + (6461, 4, 385, 14330, 0), + (6461, 5, 385, 14430, 0), + (6461, 6, 385, 14530, 0), + (6461, 7, 385, 14630, 0), + (6461, 8, 310, 30000, 0), + (6461, 9, 385, 14130, 0), + (6461, 10, 385, 14230, 0), + (6461, 11, 385, 14330, 0), + (6461, 12, 385, 14430, 0), + (6461, 13, 385, 14530, 0), + (6461, 14, 385, 14630, 0), + (6462, 1, 127, 30, 0), + (6462, 2, 385, 14130, 0), + (6462, 3, 385, 14230, 0), + (6462, 4, 385, 14330, 0), + (6462, 5, 385, 14430, 0), + (6462, 6, 385, 14530, 0), + (6462, 7, 385, 14630, 0), + (6462, 8, 310, 60000, 0), + (6462, 9, 385, 14130, 0), + (6462, 10, 385, 14230, 0), + (6462, 11, 385, 14330, 0), + (6462, 12, 385, 14430, 0), + (6462, 13, 385, 14530, 0), + (6462, 14, 385, 14630, 0), + (6463, 1, 127, 50, 0), + (6463, 2, 385, 14130, 0), + (6463, 3, 385, 14230, 0), + (6463, 4, 385, 14330, 0), + (6463, 5, 385, 14430, 0), + (6463, 6, 385, 14530, 0), + (6463, 7, 385, 14630, 0), + (6463, 8, 310, 90000, 0), + (6463, 9, 385, 14130, 0), + (6463, 10, 385, 14230, 0), + (6463, 11, 385, 14330, 0), + (6463, 12, 385, 14430, 0), + (6463, 13, 385, 14530, 0), + (6463, 14, 385, 14630, 0), + (6467, 1, 214, 100, 0), + (6468, 1, 214, 200, 0), + (6469, 1, 214, 300, 0), + (6470, 1, 247, 15, 76), + (6471, 1, 247, 20, 76), + (6472, 1, 247, 30, 76), + (6473, 1, 247, 35, 76), + (6474, 1, 247, 55, 76), + (6475, 1, 247, 60, 76), + (6476, 1, 247, 20, 76), + (6477, 1, 247, 25, 76), + (6478, 1, 264, 1, 3800), + (6479, 1, 264, 2, 3800), + (6480, 1, 264, 3, 3800), + (6481, 1, 264, 6480, 36), + (6482, 1, 264, 12960, 36), + (6483, 1, 264, 19440, 36), + (6484, 1, 264, 105, 558), + (6485, 1, 264, 120, 558), + (6486, 1, 264, 135, 558), + (6489, 1, 310, 600000, 0), + (6489, 2, 139, 4500, 0), + (6489, 3, 411, 8, 0), + (6490, 1, 310, 1200000, 0), + (6490, 2, 139, 4500, 0), + (6490, 3, 411, 8, 0), + (6491, 1, 310, 1800000, 0), + (6491, 2, 139, 4500, 0), + (6491, 3, 411, 8, 0), + (6500, 1, 273, 5, 0), + (6501, 1, 273, 6, 0), + (6502, 1, 273, 7, 0), + (6503, 1, 127, 12, 0), + (6503, 2, 385, 3338, 0), + (6504, 1, 127, 24, 0), + (6504, 2, 385, 3338, 0), + (6505, 1, 127, 36, 0), + (6505, 2, 385, 3338, 0), + (6506, 1, 127, 50, 0), + (6506, 2, 385, 3338, 0), + (6511, 1, 216, 5, 7), + (6512, 1, 216, 15, 7), + (6513, 1, 216, 25, 7), + (6514, 1, 127, 15, 0), + (6514, 2, 139, 5880, 0), + (6515, 1, 127, 30, 0), + (6515, 2, 139, 5880, 0), + (6516, 1, 127, 50, 0), + (6516, 2, 139, 5880, 0), + (6517, 1, 339, 10, 8105), + (6517, 2, 142, 65, 0), + (6517, 3, 311, 0, 0), + (6517, 4, 134, 70, 0), + (6517, 5, 348, 10, 0), + (6517, 6, 137, 0, 0), + (6517, 7, 339, 10, 8105), + (6517, 8, 142, 65, 0), + (6517, 9, 311, 0, 0), + (6517, 10, 134, 70, 0), + (6517, 11, 348, 10, 0), + (6517, 12, 137, 100, 0), + (6517, 13, 339, 10, 8105), + (6517, 14, 142, 65, 0), + (6517, 15, 311, 0, 0), + (6517, 16, 134, 70, 0), + (6517, 17, 348, 10, 0), + (6517, 18, 137, 79, 0), + (6517, 19, 339, 10, 8105), + (6517, 20, 142, 65, 0), + (6517, 21, 311, 0, 0), + (6517, 22, 134, 70, 0), + (6517, 23, 348, 10, 0), + (6517, 24, 137, 147, 0), + (6517, 25, 339, 10, 11404), + (6517, 26, 142, 71, 0), + (6517, 27, 311, 0, 0), + (6517, 28, 134, 75, 0), + (6517, 29, 348, 10, 0), + (6517, 30, 137, 0, 0), + (6517, 31, 339, 10, 11404), + (6517, 32, 142, 71, 0), + (6517, 33, 311, 0, 0), + (6517, 34, 134, 75, 0), + (6517, 35, 348, 10, 0), + (6517, 36, 137, 100, 0), + (6517, 37, 339, 10, 11404), + (6517, 38, 142, 71, 0), + (6517, 39, 311, 0, 0), + (6517, 40, 134, 75, 0), + (6517, 41, 348, 10, 0), + (6517, 42, 137, 79, 0), + (6517, 43, 339, 10, 11404), + (6517, 44, 142, 71, 0), + (6517, 45, 311, 0, 0), + (6517, 46, 134, 75, 0), + (6517, 47, 348, 10, 0), + (6517, 48, 137, 147, 0), + (6517, 49, 339, 10, 13199), + (6517, 50, 142, 76, 0), + (6517, 51, 311, 0, 0), + (6517, 52, 134, 80, 0), + (6517, 53, 348, 10, 0), + (6517, 54, 137, 0, 0), + (6517, 55, 339, 10, 13199), + (6517, 56, 142, 76, 0), + (6517, 57, 311, 0, 0), + (6517, 58, 134, 80, 0), + (6517, 59, 348, 10, 0), + (6517, 60, 137, 100, 0), + (6517, 61, 339, 10, 13199), + (6517, 62, 142, 76, 0), + (6517, 63, 311, 0, 0), + (6517, 64, 134, 80, 0), + (6517, 65, 348, 10, 0), + (6517, 66, 137, 79, 0), + (6517, 67, 339, 10, 13199), + (6517, 68, 142, 76, 0), + (6517, 69, 311, 0, 0), + (6517, 70, 134, 80, 0), + (6517, 71, 348, 10, 0), + (6517, 72, 137, 147, 0), + (6518, 1, 221, 18, 0), + (6519, 1, 221, 21, 0), + (6520, 1, 221, 24, 0), + (6521, 1, 327, 6, 0), + (6522, 1, 327, 7, 0), + (6523, 1, 328, 800, 0), + (6524, 1, 328, 850, 0), + (6525, 1, 328, 900, 0), + (6526, 1, 328, 950, 0), + (6527, 1, 328, 1000, 0), + (6528, 1, 264, 3024, 107), + (6531, 1, 360, 40, 11629), + (6532, 1, 360, 50, 11629), + (6533, 1, 360, 60, 11629), + (6540, 1, 363, 2, 0), + (6545, 1, 362, 2, 0), + (6546, 1, 2, 4, 0), + (6547, 1, 2, 8, 0), + (6548, 1, 2, 12, 0), + (6549, 1, 2, 16, 0), + (6550, 1, 2, 20, 0), + (6551, 1, 2, 24, 0), + (6552, 1, 2, 28, 0), + (6553, 1, 2, 32, 0), + (6554, 1, 2, 36, 0), + (6555, 1, 2, 40, 0), + (6556, 1, 2, 44, 0), + (6557, 1, 2, 48, 0), + (6558, 1, 2, 52, 0), + (6559, 1, 2, 56, 0), + (6560, 1, 2, 60, 0), + (6561, 1, 2, 64, 0), + (6562, 1, 2, 68, 0), + (6563, 1, 2, 72, 0), + (6564, 1, 2, 76, 0), + (6565, 1, 2, 80, 0), + (6566, 1, 2, 84, 0), + (6567, 1, 2, 88, 0), + (6568, 1, 2, 92, 0), + (6569, 1, 2, 96, 0), + (6570, 1, 2, 100, 0), + (6571, 1, 2, 104, 0), + (6601, 1, 339, 5, 13519), + (6601, 2, 137, 21, 0), + (6602, 1, 339, 10, 13519), + (6602, 2, 137, 21, 0), + (6603, 1, 339, 15, 13519), + (6603, 2, 137, 21, 0), + (6604, 1, 339, 20, 13519), + (6604, 2, 137, 21, 0), + (6605, 1, 339, 25, 13519), + (6605, 2, 137, 21, 0), + (6611, 1, 310, 120000, 0), + (6611, 2, 139, 4670, 0), + (6612, 1, 310, 240000, 0), + (6612, 2, 139, 4670, 0), + (6613, 1, 310, 360000, 0), + (6613, 2, 139, 4670, 0), + (6614, 1, 310, 120000, 0), + (6614, 2, 139, 4674, 0), + (6615, 1, 310, 240000, 0), + (6615, 2, 139, 4674, 0), + (6616, 1, 310, 360000, 0), + (6616, 2, 139, 4674, 0), + (6618, 1, 310, 480000, 0), + (6618, 2, 139, 4670, 0), + (6619, 1, 310, 600000, 0), + (6619, 2, 139, 4670, 0), + (6630, 1, 218, 1, 0), + (6631, 1, 218, 2, 0), + (6632, 1, 218, 3, 0), + (6633, 1, 218, 4, 0), + (6634, 1, 218, 5, 0), + (6636, 1, 294, 0, 107), + (6637, 1, 294, 0, 115), + (6638, 1, 294, 0, 125), + (6641, 1, 339, 10, 16101), + (6641, 2, 138, 0, 0), + (6641, 3, 142, 70, 0), + (6641, 4, 403, 4, 0), + (6641, 5, 348, 1, 0), + (6641, 6, 404, 2, 0), + (6641, 7, 141, 1, 0), + (6642, 1, 339, 10, 16102), + (6642, 2, 138, 0, 0), + (6642, 3, 142, 70, 0), + (6642, 4, 403, 4, 0), + (6642, 5, 348, 1, 0), + (6642, 6, 404, 2, 0), + (6642, 7, 141, 1, 0), + (6643, 1, 339, 10, 16103), + (6643, 2, 138, 0, 0), + (6643, 3, 142, 70, 0), + (6643, 4, 403, 4, 0), + (6643, 5, 348, 1, 0), + (6643, 6, 404, 2, 0), + (6643, 7, 141, 1, 0), + (6660, 1, 325, 55, 0), + (6661, 1, 325, 60, 0), + (6662, 1, 325, 65, 0), + (6666, 1, 287, 2, 0), + (6666, 2, 139, 8001, 0), + (6666, 3, 385, 12529, 0), + (6667, 1, 287, 4, 0), + (6667, 2, 139, 8001, 0), + (6667, 3, 385, 12529, 0), + (6668, 1, 287, 2, 0), + (6668, 2, 139, 11251, 0), + (6668, 3, 139, 11252, 0), + (6668, 4, 139, 11253, 0), + (6669, 1, 287, 4, 0), + (6669, 2, 139, 11251, 0), + (6669, 3, 139, 11252, 0), + (6669, 4, 139, 11253, 0), + (6670, 1, 287, 6, 0), + (6670, 2, 139, 11251, 0), + (6670, 3, 139, 11252, 0), + (6670, 4, 139, 11253, 0), + (6697, 1, 264, 30, 857), + (6698, 1, 264, 60, 857), + (6699, 1, 264, 90, 857), + (6700, 1, 264, 120, 857), + (6701, 1, 264, 150, 857), + (6703, 1, 264, 10, 171), + (6704, 1, 264, 20, 171), + (6705, 1, 264, 30, 171), + (6709, 1, 127, 5, 0), + (6709, 2, 139, 3842, 0), + (6710, 1, 127, 10, 0), + (6710, 2, 139, 3842, 0), + (6711, 1, 127, 15, 0), + (6711, 2, 139, 3842, 0), + (6712, 1, 264, 30, 177), + (6713, 1, 264, 60, 177), + (6714, 1, 264, 90, 177), + (6715, 1, 264, 120, 177), + (6716, 1, 264, 150, 177), + (6751, 1, 310, 240000, 0), + (6751, 2, 139, 4519, 0), + (6752, 1, 310, 480000, 0), + (6752, 2, 139, 4519, 0), + (6753, 1, 310, 720000, 0), + (6753, 2, 139, 4519, 0), + (6761, 1, 292, 5, 0), + (6762, 1, 292, 10, 0), + (6763, 1, 292, 15, 0), + (6765, 1, 330, 15, 7), + (6766, 1, 330, 30, 7), + (6767, 1, 330, 50, 7), + (6768, 1, 310, 960000, 0), + (6768, 2, 139, 4519, 0), + (6769, 1, 310, 1200000, 0), + (6769, 2, 139, 4519, 0), + (6791, 1, 339, 20, 16139), + (6791, 2, 137, 21, 0), + (6791, 3, 385, -18000, 0), + (6791, 4, 339, 20, 16139), + (6791, 5, 137, 343, 0), + (6791, 6, 385, -18000, 0), + (6792, 1, 339, 20, 16140), + (6792, 2, 137, 21, 0), + (6792, 3, 385, -18000, 0), + (6792, 4, 339, 20, 16140), + (6792, 5, 137, 343, 0), + (6792, 6, 385, -18000, 0), + (6793, 1, 339, 20, 16141), + (6793, 2, 137, 21, 0), + (6793, 3, 385, -18000, 0), + (6793, 4, 339, 20, 16141), + (6793, 5, 137, 343, 0), + (6793, 6, 385, -18000, 0), + (6819, 1, 264, 180, 524), + (6820, 1, 264, 360, 524), + (6821, 1, 264, 540, 524), + (6823, 1, 264, 180, 320), + (6824, 1, 264, 360, 320), + (6825, 1, 264, 540, 320), + (6826, 1, 264, 720, 320), + (6827, 1, 264, 900, 320), + (6870, 1, 264, 180, 544), + (6871, 1, 264, 360, 544), + (6872, 1, 264, 540, 544), + (6873, 1, 279, 7, 0), + (6874, 1, 279, 11, 0), + (6875, 1, 279, 15, 0), + (6876, 1, 375, 107, 0), + (6877, 1, 375, 115, 0), + (6878, 1, 375, 125, 0), + (6879, 1, 243, 15, 0), + (6880, 1, 243, 25, 0), + (6881, 1, 243, 35, 0), + (6882, 1, 242, 5, 0), + (6883, 1, 242, 10, 0), + (6884, 1, 242, 15, 0), + (6900, 1, 264, 840, 465), + (6901, 1, 264, 1140, 465), + (6902, 1, 264, 1440, 465), + (6903, 1, 264, 1740, 465), + (6904, 1, 264, 2040, 465), + (6905, 1, 225, 33, 0), + (6906, 1, 225, 36, 0), + (6907, 1, 225, 39, 0), + (6908, 1, 264, 180, 499), + (6909, 1, 264, 360, 499), + (6910, 1, 264, 540, 499), + (6911, 1, 224, 60, 74), + (6911, 2, 173, 2, 0), + (6912, 1, 224, 70, 74), + (6912, 2, 173, 3, 0), + (6913, 1, 224, 80, 74), + (6913, 2, 173, 3, 0), + (6935, 1, 264, 180, 465), + (6936, 1, 264, 360, 465), + (6937, 1, 264, 540, 465), + (6938, 1, 361, 65, 16164), + (6939, 1, 361, 75, 16165), + (6940, 1, 361, 85, 16166), + (6941, 1, 264, 120, 962), + (6942, 1, 264, 240, 962), + (6943, 1, 264, 360, 962), + (6944, 1, 264, 480, 962), + (6945, 1, 264, 600, 962), + (6974, 1, 264, 3, 247), + (6974, 2, 264, 2, 986), + (6974, 3, 264, 2, 987), + (6974, 4, 264, 2, 988), + (6975, 1, 264, 6, 247), + (6975, 2, 264, 4, 986), + (6975, 3, 264, 4, 987), + (6975, 4, 264, 4, 988), + (6976, 1, 264, 12, 247), + (6976, 2, 264, 6, 986), + (6976, 3, 264, 6, 987), + (6976, 4, 264, 6, 988), + (6977, 1, 264, 6, 3817), + (6978, 1, 264, 12, 3817), + (6979, 1, 264, 18, 3817), + (6980, 1, 264, 45, 128), + (6981, 1, 264, 90, 128), + (6982, 1, 264, 135, 128), + (6987, 1, 353, 1, 0), + (6988, 1, 287, 1, 0), + (6988, 2, 385, 16439, 0), + (6988, 3, 411, 32768, 0), + (6989, 1, 287, 2, 0), + (6989, 2, 385, 16439, 0), + (6989, 3, 411, 32768, 0), + (6990, 1, 287, 3, 0), + (6990, 2, 385, 16439, 0), + (6990, 3, 411, 32768, 0), + (7005, 1, 264, 432, 789), + (7006, 1, 264, 864, 789), + (7007, 1, 264, 1296, 789), + (7008, 1, 439, 0, 109400), + (7008, 2, 345, 80, 35), + (7009, 1, 439, 0, 116800), + (7009, 2, 345, 82, 35), + (7010, 1, 378, 25, 96), + (7011, 1, 378, 30, 96), + (7012, 1, 378, 35, 96), + (7013, 1, 378, 40, 96), + (7014, 1, 378, 45, 96), + (7015, 1, 378, 50, 96), + (7033, 1, 421, 5, 0), + (7033, 2, 139, 16097, 0), + (7033, 3, 139, 23612, 0), + (7033, 4, 139, 32196, 0), + (7033, 5, 139, 32565, 0), + (7033, 6, 423, 6, 0), + (7033, 7, 422, 5, 0), + (7033, 8, 411, 2, 0), + (7034, 1, 421, 10, 0), + (7034, 2, 139, 16097, 0), + (7034, 3, 139, 23612, 0), + (7034, 4, 139, 32196, 0), + (7034, 5, 139, 32565, 0), + (7034, 6, 423, 6, 0), + (7034, 7, 422, 5, 0), + (7034, 8, 411, 2, 0), + (7035, 1, 421, 15, 0), + (7035, 2, 139, 16097, 0), + (7035, 3, 139, 23612, 0), + (7035, 4, 139, 32196, 0), + (7035, 5, 139, 32565, 0), + (7035, 6, 423, 6, 0), + (7035, 7, 422, 5, 0), + (7035, 8, 411, 2, 0), + (7036, 1, 264, 10, 3646), + (7037, 1, 264, 20, 3646), + (7038, 1, 264, 30, 3646), + (7050, 1, 265, 62, 0), + (7051, 1, 265, 64, 0), + (7052, 1, 265, 66, 0), + (7053, 1, 265, 67, 0), + (7054, 1, 265, 69, 0), + (7055, 1, 265, 71, 0), + (7056, 1, 265, 62, 0), + (7057, 1, 265, 64, 0), + (7058, 1, 265, 66, 0), + (7059, 1, 265, 67, 0), + (7060, 1, 265, 69, 0), + (7061, 1, 265, 71, 0), + (7062, 1, 372, 50, 0), + (7063, 1, 265, 72, 0), + (7064, 1, 265, 74, 0), + (7065, 1, 265, 76, 0), + (7066, 1, 265, 72, 0), + (7067, 1, 265, 74, 0), + (7068, 1, 265, 76, 0), + (7100, 1, 264, 180, 254), + (7101, 1, 264, 360, 254), + (7102, 1, 264, 540, 254), + (7103, 1, 264, 432, 286), + (7103, 2, 264, 432, 10753), + (7103, 3, 264, 432, 9101), + (7104, 1, 264, 864, 286), + (7104, 2, 264, 864, 10753), + (7104, 3, 264, 864, 9101), + (7105, 1, 264, 1296, 286), + (7105, 2, 264, 1296, 10753), + (7105, 3, 264, 1296, 9101), + (7106, 1, 224, 20, 30), + (7106, 2, 173, 1, 0), + (7107, 1, 224, 35, 30), + (7107, 2, 173, 2, 0), + (7108, 1, 224, 50, 30), + (7108, 2, 173, 3, 0), + (7112, 1, 85, 13596, 50), + (7113, 1, 85, 13597, 50), + (7114, 1, 85, 13598, 50), + (7116, 1, 264, 360, 110), + (7117, 1, 264, 450, 110), + (7118, 1, 264, 540, 110), + (7122, 1, 349, 30, 0), + (7123, 1, 349, 35, 0), + (7124, 1, 349, 40, 0), + (7125, 1, 349, 45, 0), + (7126, 1, 349, 50, 0), + (7128, 1, 264, 240, 109), + (7129, 1, 264, 300, 109), + (7130, 1, 264, 360, 109), + (7131, 1, 439, 0, 88880), + (7131, 2, 345, 74, 28), + (7132, 1, 439, 0, 95440), + (7132, 2, 345, 76, 28), + (7133, 1, 439, 0, 102280), + (7133, 2, 345, 78, 28), + (7134, 1, 220, 120, 8), + (7135, 1, 220, 140, 8), + (7136, 1, 220, 165, 8), + (7137, 1, 264, 60, 672), + (7138, 1, 264, 75, 672), + (7139, 1, 264, 90, 672), + (7146, 1, 252, 80, 0), + (7147, 1, 252, 85, 0), + (7148, 1, 216, 350, 8), + (7149, 1, 216, 400, 8), + (7150, 1, 216, 450, 8), + (7151, 1, 258, 59, 0), + (7152, 1, 258, 64, 0), + (7153, 1, 258, 69, 0), + (7160, 1, 227, 120, 32), + (7161, 1, 227, 150, 32), + (7162, 1, 227, 180, 32), + (7163, 1, 220, 130, 26), + (7163, 2, 220, 130, 30), + (7163, 3, 220, 130, 38), + (7164, 1, 220, 140, 26), + (7164, 2, 220, 140, 30), + (7164, 3, 220, 140, 38), + (7165, 1, 220, 150, 26), + (7165, 2, 220, 150, 30), + (7165, 3, 220, 150, 38), + (7166, 1, 264, 20, 468), + (7166, 2, 264, 20, 469), + (7166, 3, 264, 20, 470), + (7167, 1, 264, 25, 468), + (7167, 2, 264, 25, 469), + (7167, 3, 264, 25, 470), + (7168, 1, 264, 30, 468), + (7168, 2, 264, 30, 469), + (7168, 3, 264, 30, 470), + (7169, 1, 220, 135, 21), + (7169, 2, 220, 135, 23), + (7169, 3, 220, 270, 52), + (7169, 4, 220, 135, 28), + (7170, 1, 220, 145, 21), + (7170, 2, 220, 145, 23), + (7170, 3, 220, 290, 52), + (7170, 4, 220, 145, 28), + (7171, 1, 220, 155, 21), + (7171, 2, 220, 155, 23), + (7171, 3, 220, 310, 52), + (7171, 4, 220, 155, 28), + (7175, 1, 283, 120, 0), + (7176, 1, 283, 140, 0), + (7177, 1, 283, 160, 0), + (7196, 1, 169, 20, -1), + (7197, 1, 169, 25, -1), + (7198, 1, 169, 30, -1), + (7204, 1, 218, 11, 0), + (7205, 1, 218, 12, 0), + (7206, 1, 218, 13, 0), + (7207, 1, 218, 14, 0), + (7208, 1, 218, 15, 0), + (7210, 1, 280, 50, 0), + (7211, 1, 280, 53, 0), + (7212, 1, 280, 56, 0), + (7213, 1, 280, 59, 0), + (7214, 1, 280, 62, 0), + (7215, 1, 264, 4200, 68), + (7216, 1, 264, 4800, 68), + (7220, 1, 360, 60, 12701), + (7221, 1, 360, 60, 12702), + (7222, 1, 360, 60, 12703), + (7232, 1, 294, 0, 185), + (7233, 1, 294, 0, 190), + (7234, 1, 294, 0, 195), + (7260, 1, 287, 14, 0), + (7260, 2, 385, 2754, 1), + (7261, 1, 287, 16, 0), + (7261, 2, 385, 2754, 1), + (7262, 1, 287, 18, 0), + (7262, 2, 385, 2754, 1), + (7263, 1, 274, 18, 0), + (7264, 1, 274, 20, 0), + (7265, 1, 274, 22, 0), + (7267, 1, 280, 54, 0), + (7268, 1, 280, 55, 0), + (7269, 1, 280, 56, 0), + (7270, 1, 218, 16, 0), + (7271, 1, 218, 17, 0), + (7272, 1, 218, 18, 0), + (7273, 1, 218, 19, 0), + (7274, 1, 218, 20, 0), + (7279, 1, 310, 6000, 0), + (7279, 2, 139, 11903, 0), + (7279, 3, 310, 6000, 0), + (7279, 4, 139, 11904, 0), + (7279, 5, 310, 6000, 0), + (7279, 6, 139, 11905, 0), + (7279, 7, 310, 6000, 0), + (7279, 8, 139, 1362, 0), + (7279, 9, 310, 6000, 0), + (7279, 10, 139, 8032, 0), + (7279, 11, 310, 6000, 0), + (7279, 12, 385, 6131, 0), + (7279, 13, 385, 6231, 0), + (7279, 14, 385, 6331, 0), + (7279, 15, 385, 6431, 0), + (7279, 16, 385, 6531, 0), + (7279, 17, 385, 6631, 0), + (7280, 1, 310, 7000, 0), + (7280, 2, 139, 11903, 0), + (7280, 3, 310, 7000, 0), + (7280, 4, 139, 11904, 0), + (7280, 5, 310, 7000, 0), + (7280, 6, 139, 11905, 0), + (7280, 7, 310, 7000, 0), + (7280, 8, 139, 1362, 0), + (7280, 9, 310, 7000, 0), + (7280, 10, 139, 8032, 0), + (7280, 11, 310, 7000, 0), + (7280, 12, 385, 6131, 0), + (7280, 13, 385, 6231, 0), + (7280, 14, 385, 6331, 0), + (7280, 15, 385, 6431, 0), + (7280, 16, 385, 6531, 0), + (7280, 17, 385, 6631, 0), + (7281, 1, 310, 8000, 0), + (7281, 2, 139, 11903, 0), + (7281, 3, 310, 8000, 0), + (7281, 4, 139, 11904, 0), + (7281, 5, 310, 8000, 0), + (7281, 6, 139, 11905, 0), + (7281, 7, 310, 8000, 0), + (7281, 8, 139, 1362, 0), + (7281, 9, 310, 8000, 0), + (7281, 10, 139, 8032, 0), + (7281, 11, 310, 8000, 0), + (7281, 12, 385, 6131, 0), + (7281, 13, 385, 6231, 0), + (7281, 14, 385, 6331, 0), + (7281, 15, 385, 6431, 0), + (7281, 16, 385, 6531, 0), + (7281, 17, 385, 6631, 0), + (7282, 1, 310, 9000, 0), + (7282, 2, 139, 11903, 0), + (7282, 3, 310, 9000, 0), + (7282, 4, 139, 11904, 0), + (7282, 5, 310, 9000, 0), + (7282, 6, 139, 11905, 0), + (7282, 7, 310, 9000, 0), + (7282, 8, 139, 1362, 0), + (7282, 9, 310, 9000, 0), + (7282, 10, 139, 8032, 0), + (7282, 11, 310, 9000, 0), + (7282, 12, 385, 6131, 0), + (7282, 13, 385, 6231, 0), + (7282, 14, 385, 6331, 0), + (7282, 15, 385, 6431, 0), + (7282, 16, 385, 6531, 0), + (7282, 17, 385, 6631, 0), + (7283, 1, 310, 10000, 0), + (7283, 2, 139, 11903, 0), + (7283, 3, 310, 10000, 0), + (7283, 4, 139, 11904, 0), + (7283, 5, 310, 10000, 0), + (7283, 6, 139, 11905, 0), + (7283, 7, 310, 10000, 0), + (7283, 8, 139, 1362, 0), + (7283, 9, 310, 10000, 0), + (7283, 10, 139, 8032, 0), + (7283, 11, 310, 10000, 0), + (7283, 12, 385, 6131, 0), + (7283, 13, 385, 6231, 0), + (7283, 14, 385, 6331, 0), + (7283, 15, 385, 6431, 0), + (7283, 16, 385, 6531, 0), + (7283, 17, 385, 6631, 0), + (7284, 1, 287, 3, 0), + (7284, 2, 137, 31, 0), + (7284, 3, 136, 5, 0), + (7313, 1, 244, 40, 0), + (7314, 1, 244, 30, 0), + (7315, 1, 244, 20, 0), + (7316, 1, 264, 1080, 41), + (7317, 1, 264, 1260, 41), + (7318, 1, 339, 25, 16015), + (7318, 2, 137, 21, 0), + (7319, 1, 339, 25, 16016), + (7319, 2, 137, 21, 0), + (7320, 1, 339, 25, 16017), + (7320, 2, 137, 21, 0), + (7321, 1, 339, 25, 16018), + (7321, 2, 137, 21, 0), + (7322, 1, 339, 25, 16019), + (7322, 2, 137, 21, 0), + (7323, 1, 264, 720, 254), + (7324, 1, 264, 900, 254), + (7325, 1, 264, 1080, 254), + (7326, 1, 264, 1728, 286), + (7326, 2, 264, 1728, 10753), + (7326, 3, 264, 1728, 9101), + (7327, 1, 264, 2160, 286), + (7327, 2, 264, 2160, 10753), + (7327, 3, 264, 2160, 9101), + (7328, 1, 264, 2592, 286), + (7328, 2, 264, 2592, 10753), + (7328, 3, 264, 2592, 9101), + (7336, 1, 85, 16029, 0), + (7337, 1, 85, 16030, 0), + (7338, 1, 85, 16031, 0), + (7353, 1, 216, 115, 0), + (7353, 2, 216, 115, 1), + (7353, 3, 216, 115, 2), + (7353, 4, 216, 115, 3), + (7353, 5, 216, 115, 10), + (7353, 6, 216, 115, 28), + (7353, 7, 216, 115, 30), + (7353, 8, 216, 115, 36), + (7353, 9, 216, 115, 77), + (7354, 1, 216, 120, 0), + (7354, 2, 216, 120, 1), + (7354, 3, 216, 120, 2), + (7354, 4, 216, 120, 3), + (7354, 5, 216, 120, 10), + (7354, 6, 216, 120, 28), + (7354, 7, 216, 120, 30), + (7354, 8, 216, 120, 36), + (7354, 9, 216, 120, 77), + (7355, 1, 216, 125, 0), + (7355, 2, 216, 125, 1), + (7355, 3, 216, 125, 2), + (7355, 4, 216, 125, 3), + (7355, 5, 216, 125, 10), + (7355, 6, 216, 125, 28), + (7355, 7, 216, 125, 30), + (7355, 8, 216, 125, 36), + (7355, 9, 216, 125, 77), + (7356, 1, 360, 60, 16056), + (7357, 1, 360, 60, 16057), + (7358, 1, 360, 60, 16058), + (7359, 1, 217, 0, 82600), + (7359, 2, 346, 78, 22), + (7360, 1, 217, 0, 88880), + (7360, 2, 346, 80, 22), + (7361, 1, 217, 0, 95440), + (7361, 2, 346, 82, 22), + (7362, 1, 59, -18, 0), + (7363, 1, 59, -21, 0), + (7364, 1, 59, -24, 0), + (7365, 1, 59, -27, 0), + (7366, 1, 59, -30, 0), + (7373, 1, 2, 108, 0), + (7374, 1, 2, 112, 0), + (7375, 1, 2, 116, 0), + (7376, 1, 2, 120, 0), + (7377, 1, 2, 124, 0), + (7378, 1, 347, 14, 0), + (7379, 1, 347, 16, 0), + (7380, 1, 347, 18, 0), + (7381, 1, 347, 20, 0), + (7382, 1, 347, 22, 0), + (7383, 1, 347, 24, 0), + (7384, 1, 360, 25, 16063), + (7385, 1, 360, 25, 16064), + (7386, 1, 360, 25, 16065), + (7390, 1, 303, 6000, 6000), + (7390, 2, 139, 2766, 0), + (7391, 1, 303, 6500, 6500), + (7391, 2, 139, 2766, 0), + (7392, 1, 303, 7500, 8500), + (7392, 2, 139, 2766, 0), + (7393, 1, 85, 16066, 0), + (7394, 1, 85, 16067, 0), + (7395, 1, 85, 16068, 0), + (7396, 1, 85, 16069, 0), + (7397, 1, 85, 16070, 0), + (7398, 1, 85, 16071, 0), + (7399, 1, 302, 350, 350), + (7399, 2, 385, 99, 0), + (7400, 1, 302, 370, 370), + (7400, 2, 385, 99, 0), + (7401, 1, 302, 400, 400), + (7401, 2, 385, 99, 0), + (7402, 1, 59, -33, 0), + (7403, 1, 59, -36, 0), + (7404, 1, 59, -39, 0), + (7405, 1, 59, -42, 0), + (7406, 1, 59, -45, 0), + (7407, 1, 181, 100, -1), + (7448, 1, 264, 240, 553), + (7449, 1, 264, 300, 553), + (7450, 1, 264, 360, 553), + (7451, 1, 264, 720, 777), + (7452, 1, 264, 900, 777), + (7453, 1, 264, 1080, 777), + (7478, 1, 264, 2880, 245), + (7489, 1, 218, 16, 0), + (7490, 1, 218, 17, 0), + (7491, 1, 218, 18, 0), + (7492, 1, 218, 19, 0), + (7493, 1, 218, 20, 0), + (7494, 1, 280, 65, 0), + (7495, 1, 280, 66, 0), + (7496, 1, 280, 67, 0), + (7500, 1, 363, 3, 0), + (7501, 1, 172, 45, 0), + (7502, 1, 172, 46, 0), + (7503, 1, 172, 47, 0), + (7504, 1, 172, 48, 0), + (7505, 1, 172, 49, 0), + (7506, 1, 259, 51, 0), + (7507, 1, 259, 52, 0), + (7508, 1, 259, 53, 0), + (7509, 1, 259, 54, 0), + (7510, 1, 259, 55, 0), + (7511, 1, 328, 1050, 0), + (7512, 1, 328, 1100, 0), + (7513, 1, 328, 1150, 0), + (7514, 1, 328, 1200, 0), + (7515, 1, 328, 1250, 0), + (7516, 1, 262, 30, 7), + (7516, 2, 262, 30, 8), + (7516, 3, 262, 30, 9), + (7516, 4, 262, 30, 10), + (7516, 5, 262, 30, 11), + (7517, 1, 262, 35, 7), + (7517, 2, 262, 35, 8), + (7517, 3, 262, 35, 9), + (7517, 4, 262, 35, 10), + (7517, 5, 262, 35, 11), + (7518, 1, 262, 40, 7), + (7518, 2, 262, 40, 8), + (7518, 3, 262, 40, 9), + (7518, 4, 262, 40, 10), + (7518, 5, 262, 40, 11), + (7519, 1, 262, 45, 7), + (7519, 2, 262, 45, 8), + (7519, 3, 262, 45, 9), + (7519, 4, 262, 45, 10), + (7519, 5, 262, 45, 11), + (7520, 1, 262, 50, 7), + (7520, 2, 262, 50, 8), + (7520, 3, 262, 50, 9), + (7520, 4, 262, 50, 10), + (7520, 5, 262, 50, 11), + (7521, 1, 317, 11, 0), + (7522, 1, 317, 12, 0), + (7523, 1, 317, 13, 0), + (7524, 1, 317, 14, 0), + (7525, 1, 317, 15, 0), + (7526, 1, 69, 600, 0), + (7527, 1, 69, 700, 0), + (7528, 1, 69, 800, 0), + (7529, 1, 69, 900, 0), + (7530, 1, 69, 1000, 0), + (7534, 1, 0, 21, 0), + (7535, 1, 0, 22, 0), + (7536, 1, 0, 23, 0), + (7537, 1, 0, 24, 0), + (7538, 1, 0, 25, 0), + (7539, 1, 327, 8, 0), + (7540, 1, 327, 9, 0), + (7541, 1, 214, 1100, 0), + (7542, 1, 214, 1200, 0), + (7543, 1, 214, 1300, 0), + (7544, 1, 221, 27, 0), + (7545, 1, 221, 30, 0), + (7546, 1, 221, 33, 0), + (7547, 1, 262, 80, 0), + (7547, 2, 262, 80, 1), + (7547, 3, 262, 80, 2), + (7547, 4, 262, 80, 3), + (7547, 5, 262, 80, 4), + (7547, 6, 262, 80, 5), + (7547, 7, 262, 80, 6), + (7548, 1, 262, 85, 0), + (7548, 2, 262, 85, 1), + (7548, 3, 262, 85, 2), + (7548, 4, 262, 85, 3), + (7548, 5, 262, 85, 4), + (7548, 6, 262, 85, 5), + (7548, 7, 262, 85, 6), + (7549, 1, 262, 90, 0), + (7549, 2, 262, 90, 1), + (7549, 3, 262, 90, 2), + (7549, 4, 262, 90, 3), + (7549, 5, 262, 90, 4), + (7549, 6, 262, 90, 5), + (7549, 7, 262, 90, 6), + (7550, 1, 262, 95, 0), + (7550, 2, 262, 95, 1), + (7550, 3, 262, 95, 2), + (7550, 4, 262, 95, 3), + (7550, 5, 262, 95, 4), + (7550, 6, 262, 95, 5), + (7550, 7, 262, 95, 6), + (7551, 1, 262, 100, 0), + (7551, 2, 262, 100, 1), + (7551, 3, 262, 100, 2), + (7551, 4, 262, 100, 3), + (7551, 5, 262, 100, 4), + (7551, 6, 262, 100, 5), + (7551, 7, 262, 100, 6), + (7553, 1, 326, 3, 0), + (7554, 1, 339, 20, 16194), + (7554, 2, 138, 1, 0), + (7554, 3, 141, 1, 0), + (7554, 4, 142, 65, 0), + (7554, 5, 137, 0, 0), + (7554, 6, 311, 0, 0), + (7554, 7, 134, 85, 0), + (7554, 8, 139, -265, 0), + (7554, 9, 139, -754, 0), + (7554, 10, 139, -1332, 0), + (7554, 11, 139, -1572, 0), + (7554, 12, 139, -2749, 0), + (7554, 13, 139, -4979, 0), + (7554, 14, 139, -5418, 0), + (7554, 15, 139, -5403, 0), + (7554, 16, 348, 10, 0), + (7555, 1, 339, 21, 16195), + (7555, 2, 138, 1, 0), + (7555, 3, 141, 1, 0), + (7555, 4, 142, 65, 0), + (7555, 5, 137, 0, 0), + (7555, 6, 311, 0, 0), + (7555, 7, 134, 85, 0), + (7555, 8, 139, -265, 0), + (7555, 9, 139, -754, 0), + (7555, 10, 139, -1332, 0), + (7555, 11, 139, -1572, 0), + (7555, 12, 139, -2749, 0), + (7555, 13, 139, -4979, 0), + (7555, 14, 139, -5418, 0), + (7555, 15, 139, -5403, 0), + (7555, 16, 348, 10, 0), + (7556, 1, 339, 22, 16196), + (7556, 2, 138, 1, 0), + (7556, 3, 141, 1, 0), + (7556, 4, 142, 65, 0), + (7556, 5, 137, 0, 0), + (7556, 6, 311, 0, 0), + (7556, 7, 134, 85, 0), + (7556, 8, 139, -265, 0), + (7556, 9, 139, -754, 0), + (7556, 10, 139, -1332, 0), + (7556, 11, 139, -1572, 0), + (7556, 12, 139, -2749, 0), + (7556, 13, 139, -4979, 0), + (7556, 14, 139, -5418, 0), + (7556, 15, 139, -5403, 0), + (7556, 16, 348, 10, 0), + (7557, 1, 339, 23, 16417), + (7557, 2, 138, 1, 0), + (7557, 3, 141, 1, 0), + (7557, 4, 142, 65, 0), + (7557, 5, 137, 0, 0), + (7557, 6, 311, 0, 0), + (7557, 7, 134, 85, 0), + (7557, 8, 139, -265, 0), + (7557, 9, 139, -754, 0), + (7557, 10, 139, -1332, 0), + (7557, 11, 139, -1572, 0), + (7557, 12, 139, -2749, 0), + (7557, 13, 139, -4979, 0), + (7557, 14, 139, -5418, 0), + (7557, 15, 139, -5403, 0), + (7557, 16, 348, 10, 0), + (7558, 1, 339, 24, 16418), + (7558, 2, 138, 1, 0), + (7558, 3, 141, 1, 0), + (7558, 4, 142, 65, 0), + (7558, 5, 137, 0, 0), + (7558, 6, 311, 0, 0), + (7558, 7, 134, 85, 0), + (7558, 8, 139, -265, 0), + (7558, 9, 139, -754, 0), + (7558, 10, 139, -1332, 0), + (7558, 11, 139, -1572, 0), + (7558, 12, 139, -2749, 0), + (7558, 13, 139, -4979, 0), + (7558, 14, 139, -5418, 0), + (7558, 15, 139, -5403, 0), + (7558, 16, 348, 10, 0), + (7559, 1, 266, 23, 0), + (7560, 1, 266, 24, 0), + (7561, 1, 266, 25, 0), + (7562, 1, 330, 125, 0), + (7562, 2, 330, 125, 1), + (7562, 3, 330, 125, 2), + (7562, 4, 330, 125, 3), + (7562, 5, 330, 125, 28), + (7562, 6, 330, 125, 36), + (7562, 7, 330, 125, 77), + (7563, 1, 330, 130, 0), + (7563, 2, 330, 130, 1), + (7563, 3, 330, 130, 2), + (7563, 4, 330, 130, 3), + (7563, 5, 330, 130, 28), + (7563, 6, 330, 130, 36), + (7563, 7, 330, 130, 77), + (7564, 1, 330, 135, 0), + (7564, 2, 330, 135, 1), + (7564, 3, 330, 135, 2), + (7564, 4, 330, 135, 3), + (7564, 5, 330, 135, 28), + (7564, 6, 330, 135, 36), + (7564, 7, 330, 135, 77), + (7565, 1, 278, 800, 54510), + (7565, 2, 440, 76, 100), + (7566, 1, 278, 850, 58400), + (7566, 2, 440, 78, 100), + (7567, 1, 278, 900, 62680), + (7567, 2, 440, 80, 100), + (7568, 1, 341, 160, 0), + (7569, 1, 341, 170, 0), + (7570, 1, 341, 180, 0), + (7571, 1, 341, 190, 0), + (7572, 1, 341, 200, 0), + (7573, 1, 360, 70, 11023), + (7574, 1, 360, 80, 11023), + (7575, 1, 360, 90, 11023), + (7576, 1, 318, 16, 0), + (7577, 1, 318, 17, 0), + (7578, 1, 318, 18, 0), + (7579, 1, 318, 19, 0), + (7580, 1, 318, 20, 0), + (7581, 1, 294, 0, 160), + (7582, 1, 294, 0, 165), + (7583, 1, 294, 0, 170), + (7584, 1, 114, -60, 0), + (7585, 1, 114, -61, 0), + (7586, 1, 114, -62, 0), + (7587, 1, 319, 22, 0), + (7588, 1, 319, 23, 0), + (7589, 1, 319, 24, 0), + (7590, 1, 274, 35, 0), + (7591, 1, 274, 36, 0), + (7592, 1, 274, 37, 0), + (7593, 1, 15, 14, 0), + (7594, 1, 15, 15, 0), + (7595, 1, 15, 16, 0), + (7596, 1, 15, 17, 0), + (7597, 1, 15, 18, 0), + (7598, 1, 114, -60, 0), + (7599, 1, 114, -61, 0), + (7600, 1, 114, -62, 0), + (7601, 1, 213, 7, 0), + (7602, 1, 213, 9, 0), + (7603, 1, 213, 11, 0), + (7604, 1, 189, 14, 0), + (7605, 1, 189, 15, 0), + (7612, 1, 270, 70, 0), + (7613, 1, 270, 75, 0), + (7614, 1, 270, 80, 0), + (7615, 1, 264, 720, 494), + (7616, 1, 264, 900, 494), + (7617, 1, 264, 1080, 494), + (7618, 1, 264, 720, 500), + (7619, 1, 264, 900, 500), + (7620, 1, 264, 1080, 500), + (7621, 1, 339, 10, 8105), + (7621, 2, 142, 65, 0), + (7621, 3, 311, 0, 0), + (7621, 4, 134, 70, 0), + (7621, 5, 348, 10, 0), + (7621, 6, 137, 0, 0), + (7621, 7, 339, 10, 8105), + (7621, 8, 142, 65, 0), + (7621, 9, 311, 0, 0), + (7621, 10, 134, 70, 0), + (7621, 11, 348, 10, 0), + (7621, 12, 137, 100, 0), + (7621, 13, 339, 10, 8105), + (7621, 14, 142, 65, 0), + (7621, 15, 311, 0, 0), + (7621, 16, 134, 70, 0), + (7621, 17, 348, 10, 0), + (7621, 18, 137, 79, 0), + (7621, 19, 339, 10, 8105), + (7621, 20, 142, 65, 0), + (7621, 21, 311, 0, 0), + (7621, 22, 134, 70, 0), + (7621, 23, 348, 10, 0), + (7621, 24, 137, 147, 0), + (7621, 25, 339, 10, 11404), + (7621, 26, 142, 71, 0), + (7621, 27, 311, 0, 0), + (7621, 28, 134, 75, 0), + (7621, 29, 348, 10, 0), + (7621, 30, 137, 0, 0), + (7621, 31, 339, 10, 11404), + (7621, 32, 142, 71, 0), + (7621, 33, 311, 0, 0), + (7621, 34, 134, 75, 0), + (7621, 35, 348, 10, 0), + (7621, 36, 137, 100, 0), + (7621, 37, 339, 10, 11404), + (7621, 38, 142, 71, 0), + (7621, 39, 311, 0, 0), + (7621, 40, 134, 75, 0), + (7621, 41, 348, 10, 0), + (7621, 42, 137, 79, 0), + (7621, 43, 339, 10, 11404), + (7621, 44, 142, 71, 0), + (7621, 45, 311, 0, 0), + (7621, 46, 134, 75, 0), + (7621, 47, 348, 10, 0), + (7621, 48, 137, 147, 0), + (7621, 49, 339, 10, 13199), + (7621, 50, 142, 76, 0), + (7621, 51, 311, 0, 0), + (7621, 52, 134, 80, 0), + (7621, 53, 348, 10, 0), + (7621, 54, 137, 0, 0), + (7621, 55, 339, 10, 13199), + (7621, 56, 142, 76, 0), + (7621, 57, 311, 0, 0), + (7621, 58, 134, 80, 0), + (7621, 59, 348, 10, 0), + (7621, 60, 137, 100, 0), + (7621, 61, 339, 10, 13199), + (7621, 62, 142, 76, 0), + (7621, 63, 311, 0, 0), + (7621, 64, 134, 80, 0), + (7621, 65, 348, 10, 0), + (7621, 66, 137, 79, 0), + (7621, 67, 339, 10, 13199), + (7621, 68, 142, 76, 0), + (7621, 69, 311, 0, 0), + (7621, 70, 134, 80, 0), + (7621, 71, 348, 10, 0), + (7621, 72, 137, 147, 0), + (7621, 73, 339, 10, 13830), + (7621, 74, 142, 81, 0), + (7621, 75, 311, 0, 0), + (7621, 76, 134, 85, 0), + (7621, 77, 348, 10, 0), + (7621, 78, 137, 0, 0), + (7621, 79, 339, 10, 13830), + (7621, 80, 142, 81, 0), + (7621, 81, 311, 0, 0), + (7621, 82, 134, 85, 0), + (7621, 83, 348, 10, 0), + (7621, 84, 137, 100, 0), + (7621, 85, 339, 10, 13830), + (7621, 86, 142, 81, 0), + (7621, 87, 311, 0, 0), + (7621, 88, 134, 85, 0), + (7621, 89, 348, 10, 0), + (7621, 90, 137, 79, 0), + (7621, 91, 339, 10, 13830), + (7621, 92, 142, 81, 0), + (7621, 93, 311, 0, 0), + (7621, 94, 134, 85, 0), + (7621, 95, 348, 10, 0), + (7621, 96, 137, 147, 0), + (7622, 1, 265, 79, 0), + (7623, 1, 265, 80, 0), + (7624, 1, 265, 81, 0), + (7625, 1, 265, 79, 0), + (7626, 1, 265, 80, 0), + (7627, 1, 265, 81, 0), + (7628, 1, 292, 46, 0), + (7629, 1, 292, 47, 0), + (7630, 1, 292, 48, 0), + (7631, 1, 279, 34, 0), + (7632, 1, 279, 35, 0), + (7633, 1, 279, 36, 0), + (7634, 1, 279, 34, 0), + (7635, 1, 279, 35, 0), + (7636, 1, 279, 36, 0), + (7637, 1, 279, 34, 0), + (7638, 1, 279, 35, 0), + (7639, 1, 279, 36, 0), + (7640, 1, 200, 60, 0), + (7641, 1, 294, 17, 100), + (7642, 1, 294, 19, 100), + (7643, 1, 294, 21, 100), + (7644, 1, 375, 130, 0), + (7645, 1, 375, 135, 0), + (7646, 1, 375, 140, 0), + (7647, 1, 229, 20, 0), + (7648, 1, 229, 25, 0), + (7649, 1, 229, 30, 0), + (7650, 1, 330, 125, 0), + (7650, 2, 330, 125, 1), + (7650, 3, 330, 125, 2), + (7650, 4, 330, 125, 3), + (7650, 5, 330, 125, 28), + (7650, 6, 330, 125, 36), + (7651, 1, 330, 130, 0), + (7651, 2, 330, 130, 1), + (7651, 3, 330, 130, 2), + (7651, 4, 330, 130, 3), + (7651, 5, 330, 130, 28), + (7651, 6, 330, 130, 36), + (7652, 1, 330, 135, 0), + (7652, 2, 330, 135, 1), + (7652, 3, 330, 135, 2), + (7652, 4, 330, 135, 3), + (7652, 5, 330, 135, 28), + (7652, 6, 330, 135, 36), + (7653, 1, 330, 125, 0), + (7653, 2, 330, 125, 1), + (7653, 3, 330, 125, 2), + (7653, 4, 330, 125, 3), + (7653, 5, 330, 125, 28), + (7653, 6, 330, 125, 36), + (7653, 7, 330, 125, 77), + (7654, 1, 330, 130, 0), + (7654, 2, 330, 130, 1), + (7654, 3, 330, 130, 2), + (7654, 4, 330, 130, 3), + (7654, 5, 330, 130, 28), + (7654, 6, 330, 130, 36), + (7654, 7, 330, 130, 77), + (7655, 1, 330, 135, 0), + (7655, 2, 330, 135, 1), + (7655, 3, 330, 135, 2), + (7655, 4, 330, 135, 3), + (7655, 5, 330, 135, 28), + (7655, 6, 330, 135, 36), + (7655, 7, 330, 135, 77), + (7656, 1, 330, 100, 0), + (7656, 2, 330, 100, 1), + (7656, 3, 330, 100, 2), + (7656, 4, 330, 100, 3), + (7656, 5, 330, 100, 28), + (7656, 6, 330, 100, 36), + (7656, 7, 330, 100, 77), + (7657, 1, 330, 105, 0), + (7657, 2, 330, 105, 1), + (7657, 3, 330, 105, 2), + (7657, 4, 330, 105, 3), + (7657, 5, 330, 105, 28), + (7657, 6, 330, 105, 36), + (7657, 7, 330, 105, 77), + (7658, 1, 330, 110, 0), + (7658, 2, 330, 110, 1), + (7658, 3, 330, 110, 2), + (7658, 4, 330, 110, 3), + (7658, 5, 330, 110, 28), + (7658, 6, 330, 110, 36), + (7658, 7, 330, 110, 77), + (7659, 1, 264, 72, 153), + (7660, 1, 264, 90, 153), + (7661, 1, 264, 108, 153), + (7663, 1, 375, 150, 0), + (7664, 1, 264, 10, 170), + (7665, 1, 264, 20, 170), + (7666, 1, 264, 30, 170), + (7667, 1, 264, 40, 170), + (7668, 1, 264, 50, 170), + (7670, 1, 229, 35, 0), + (7671, 1, 229, 40, 0), + (7672, 1, 229, 45, 0), + (7673, 1, 220, 50, 10), + (7674, 1, 220, 65, 10), + (7675, 1, 220, 80, 10), + (7676, 1, 220, 95, 10), + (7677, 1, 220, 110, 10), + (7678, 1, 231, 11, 0), + (7679, 1, 231, 13, 0), + (7680, 1, 231, 15, 0), + (7681, 1, 326, 4, 0), + (7682, 1, 264, 5400, 68), + (7683, 1, 327, 10, 0), + (7684, 1, 327, 11, 0), + (7685, 1, 327, 12, 0), + (7686, 1, 349, 55, 0), + (7687, 1, 349, 60, 0), + (7688, 1, 349, 65, 0), + (7690, 1, 353, 1, 0), + (7692, 1, 319, 25, 0), + (7693, 1, 319, 26, 0), + (7694, 1, 319, 27, 0), + (7695, 1, 127, 5, 0), + (7695, 2, 385, 14232, 0), + (7696, 1, 127, 10, 0), + (7696, 2, 385, 14232, 0), + (7697, 1, 127, 15, 0), + (7697, 2, 385, 14232, 0), + (7699, 1, 181, 100, 0), + (7700, 1, 279, 7, 0), + (7701, 1, 279, 11, 0), + (7702, 1, 279, 15, 0), + (7704, 1, 264, 540, 3707), + (7705, 1, 264, 720, 3707), + (7706, 1, 264, 900, 3707), + (7707, 1, 303, 8500, 9500), + (7707, 2, 139, 2766, 0), + (7708, 1, 303, 9500, 11000), + (7708, 2, 139, 2766, 0), + (7709, 1, 303, 11000, 14000), + (7709, 2, 139, 2766, 0), + (7713, 1, 274, 34, 0), + (7714, 1, 274, 36, 0), + (7715, 1, 264, 2, 901), + (7716, 1, 264, 4, 901), + (7717, 1, 264, 6, 901), + (7718, 1, 281, 90, 0), + (7722, 1, 339, 25, 23492), + (7722, 2, 138, 1, 0), + (7722, 3, 141, 1, 0), + (7722, 4, 142, 70, 0), + (7722, 5, 137, 0, 0), + (7722, 6, 311, 0, 0), + (7722, 7, 134, 90, 0), + (7722, 8, 139, -265, 0), + (7722, 9, 139, -754, 0), + (7722, 10, 139, -1332, 0), + (7722, 11, 139, -1572, 0), + (7722, 12, 139, -2749, 0), + (7722, 13, 139, -4979, 0), + (7722, 14, 139, -5418, 0), + (7722, 15, 139, -5403, 0), + (7722, 16, 348, 10, 0), + (7723, 1, 339, 26, 23493), + (7723, 2, 138, 1, 0), + (7723, 3, 141, 1, 0), + (7723, 4, 142, 70, 0), + (7723, 5, 137, 0, 0), + (7723, 6, 311, 0, 0), + (7723, 7, 134, 90, 0), + (7723, 8, 139, -265, 0), + (7723, 9, 139, -754, 0), + (7723, 10, 139, -1332, 0), + (7723, 11, 139, -1572, 0), + (7723, 12, 139, -2749, 0), + (7723, 13, 139, -4979, 0), + (7723, 14, 139, -5418, 0), + (7723, 15, 139, -5403, 0), + (7723, 16, 348, 10, 0), + (7724, 1, 339, 27, 23494), + (7724, 2, 138, 1, 0), + (7724, 3, 141, 1, 0), + (7724, 4, 142, 70, 0), + (7724, 5, 137, 0, 0), + (7724, 6, 311, 0, 0), + (7724, 7, 134, 90, 0), + (7724, 8, 139, -265, 0), + (7724, 9, 139, -754, 0), + (7724, 10, 139, -1332, 0), + (7724, 11, 139, -1572, 0), + (7724, 12, 139, -2749, 0), + (7724, 13, 139, -4979, 0), + (7724, 14, 139, -5418, 0), + (7724, 15, 139, -5403, 0), + (7724, 16, 348, 10, 0), + (7725, 1, 339, 28, 23495), + (7725, 2, 138, 1, 0), + (7725, 3, 141, 1, 0), + (7725, 4, 142, 70, 0), + (7725, 5, 137, 0, 0), + (7725, 6, 311, 0, 0), + (7725, 7, 134, 90, 0), + (7725, 8, 139, -265, 0), + (7725, 9, 139, -754, 0), + (7725, 10, 139, -1332, 0), + (7725, 11, 139, -1572, 0), + (7725, 12, 139, -2749, 0), + (7725, 13, 139, -4979, 0), + (7725, 14, 139, -5418, 0), + (7725, 15, 139, -5403, 0), + (7725, 16, 348, 10, 0), + (7726, 1, 339, 29, 23496), + (7726, 2, 138, 1, 0), + (7726, 3, 141, 1, 0), + (7726, 4, 142, 70, 0), + (7726, 5, 137, 0, 0), + (7726, 6, 311, 0, 0), + (7726, 7, 134, 90, 0), + (7726, 8, 139, -265, 0), + (7726, 9, 139, -754, 0), + (7726, 10, 139, -1332, 0), + (7726, 11, 139, -1572, 0), + (7726, 12, 139, -2749, 0), + (7726, 13, 139, -4979, 0), + (7726, 14, 139, -5418, 0), + (7726, 15, 139, -5403, 0), + (7726, 16, 348, 10, 0), + (7733, 1, 257, 1, 0), + (7733, 2, 267, 1, 31), + (7733, 3, 267, 1, 32), + (7733, 4, 267, 1, 33), + (7733, 5, 267, 1, 15), + (7733, 6, 267, 1, 16), + (7733, 7, 267, 1, 17), + (7733, 8, 267, 1, 18), + (7733, 9, 267, 1, 19), + (7733, 10, 267, 1, 20), + (7743, 1, 264, 90, 184), + (7744, 1, 264, 180, 184), + (7745, 1, 264, 270, 184), + (7746, 1, 310, 2000, 0), + (7746, 2, 385, 11233, 0), + (7746, 3, 385, 11333, 0), + (7746, 4, 411, 16, 0), + (7748, 1, 271, 5, 0), + (7749, 1, 271, 10, 0), + (7750, 1, 271, 15, 0), + (7751, 1, 264, 60, 2234), + (7752, 1, 264, 120, 2234), + (7753, 1, 264, 180, 2234), + (7757, 1, 264, 120, 9403), + (7758, 1, 264, 240, 9403), + (7759, 1, 264, 360, 9403), + (7760, 1, 264, 2, 824), + (7761, 1, 264, 4, 824), + (7762, 1, 264, 6, 824), + (7763, 1, 310, 4000, 0), + (7763, 2, 385, 11233, 0), + (7763, 3, 385, 11333, 0), + (7763, 4, 411, 16, 0), + (7764, 1, 310, 6000, 0), + (7764, 2, 385, 11233, 0), + (7764, 3, 385, 11333, 0), + (7764, 4, 411, 16, 0), + (7765, 1, 392, 1000, 0), + (7765, 2, 139, 21820, 0), + (7765, 3, 411, 4, 0), + (7766, 1, 392, 2000, 0), + (7766, 2, 139, 21820, 0), + (7766, 3, 411, 4, 0), + (7767, 1, 392, 3000, 0), + (7767, 2, 139, 21820, 0), + (7767, 3, 411, 4, 0), + (7768, 1, 392, 4000, 0), + (7768, 2, 139, 21820, 0), + (7768, 3, 411, 4, 0), + (7818, 1, 288, 200, 51), + (7818, 2, 288, 50, 51), + (7819, 1, 405, 7, 0), + (7820, 1, 405, 9, 0), + (7821, 1, 405, 11, 0), + (7822, 1, 264, 1, 1154), + (7823, 1, 264, 2, 1154), + (7824, 1, 264, 3, 1154), + (7825, 1, 264, 4, 1154), + (7826, 1, 264, 5, 1154), + (7827, 1, 398, 9000, 0), + (7827, 2, 385, 7225, 0), + (7827, 3, 385, 7325, 0), + (7827, 4, 385, 7425, 0), + (7828, 1, 310, 2000, 0), + (7828, 2, 385, 7225, 0), + (7828, 3, 385, 7325, 0), + (7828, 4, 385, 7425, 0), + (7828, 5, 385, 7525, 0), + (7828, 6, 385, 7625, 0), + (7829, 1, 310, 4000, 0), + (7829, 2, 385, 7225, 0), + (7829, 3, 385, 7325, 0), + (7829, 4, 385, 7425, 0), + (7829, 5, 385, 7525, 0), + (7829, 6, 385, 7625, 0), + (7830, 1, 310, 6000, 0), + (7830, 2, 385, 7225, 0), + (7830, 3, 385, 7325, 0), + (7830, 4, 385, 7425, 0), + (7830, 5, 385, 7525, 0), + (7830, 6, 385, 7625, 0), + (7832, 1, 264, 60, 60), + (7833, 2, 264, 120, 60), + (7834, 3, 264, 180, 60), + (7835, 4, 264, 240, 60), + (7836, 5, 264, 300, 60), + (7837, 1, 262, 55, 7), + (7837, 2, 262, 55, 8), + (7837, 3, 262, 55, 9), + (7837, 4, 262, 55, 10), + (7837, 5, 262, 55, 11), + (7838, 1, 262, 60, 7), + (7838, 2, 262, 60, 8), + (7838, 3, 262, 60, 9), + (7838, 4, 262, 60, 10), + (7838, 5, 262, 60, 11), + (7839, 1, 262, 65, 7), + (7839, 2, 262, 65, 8), + (7839, 3, 262, 65, 9), + (7839, 4, 262, 65, 10), + (7839, 5, 262, 65, 11), + (7840, 1, 262, 70, 7), + (7840, 2, 262, 70, 8), + (7840, 3, 262, 70, 9), + (7840, 4, 262, 70, 10), + (7840, 5, 262, 70, 11), + (7841, 1, 262, 75, 7), + (7841, 2, 262, 75, 8), + (7841, 3, 262, 75, 9), + (7841, 4, 262, 75, 10), + (7841, 5, 262, 75, 11), + (7842, 1, 339, 30, 27695), + (7842, 2, 138, 1, 0), + (7842, 3, 141, 1, 0), + (7842, 4, 142, 70, 0), + (7842, 5, 137, 0, 0), + (7842, 6, 311, 0, 0), + (7842, 7, 134, 100, 0), + (7842, 8, 139, -265, 0), + (7842, 9, 139, -754, 0), + (7842, 10, 139, -1332, 0), + (7842, 11, 139, -1572, 0), + (7842, 12, 139, -2749, 0), + (7842, 13, 139, -4979, 0), + (7842, 14, 139, -5418, 0), + (7842, 15, 139, -5403, 0), + (7842, 16, 348, 10, 0), + (7843, 1, 339, 31, 27696), + (7843, 2, 138, 1, 0), + (7843, 3, 141, 1, 0), + (7843, 4, 142, 70, 0), + (7843, 5, 137, 0, 0), + (7843, 6, 311, 0, 0), + (7843, 7, 134, 100, 0), + (7843, 8, 139, -265, 0), + (7843, 9, 139, -754, 0), + (7843, 10, 139, -1332, 0), + (7843, 11, 139, -1572, 0), + (7843, 12, 139, -2749, 0), + (7843, 13, 139, -4979, 0), + (7843, 14, 139, -5418, 0), + (7843, 15, 139, -5403, 0), + (7843, 16, 348, 10, 0), + (7844, 1, 339, 32, 27697), + (7844, 2, 138, 1, 0), + (7844, 3, 141, 1, 0), + (7844, 4, 142, 70, 0), + (7844, 5, 137, 0, 0), + (7844, 6, 311, 0, 0), + (7844, 7, 134, 100, 0), + (7844, 8, 139, -265, 0), + (7844, 9, 139, -754, 0), + (7844, 10, 139, -1332, 0), + (7844, 11, 139, -1572, 0), + (7844, 12, 139, -2749, 0), + (7844, 13, 139, -4979, 0), + (7844, 14, 139, -5418, 0), + (7844, 15, 139, -5403, 0), + (7844, 16, 348, 10, 0), + (7881, 1, 405, 13, 0), + (7882, 1, 405, 15, 0), + (7883, 1, 405, 17, 0), + (7884, 1, 287, 1, 0), + (7884, 2, 139, 4691, 0), + (7884, 3, 411, 128, 0), + (7885, 1, 287, 1, 0), + (7885, 2, 385, 8111, 0), + (7885, 3, 385, 15008, 0), + (7885, 4, 385, 8411, 0), + (7885, 5, 385, 8511, 0), + (7885, 6, 411, 128, 0), + (7886, 1, 328, 1300, 0), + (7887, 1, 328, 1350, 0), + (7888, 1, 328, 1400, 0), + (7889, 1, 328, 1450, 0), + (7890, 1, 328, 1500, 0), + (7900, 1, 339, 45, 16189), + (7900, 2, 136, 11, 0), + (7900, 3, 383, 45, 16189), + (7900, 4, 385, 11012, 0), + (7900, 5, 383, 45, 16189), + (7900, 6, 385, 5130, 0), + (7900, 7, 383, 45, 16189), + (7900, 8, 385, 5230, 0), + (7900, 9, 383, 45, 16189), + (7900, 10, 136, 22, 0), + (7900, 11, 383, 45, 16189), + (7900, 12, 385, 5330, 0), + (7900, 13, 385, 5430, 0), + (7900, 14, 385, 5530, 0), + (7901, 1, 339, 45, 16190), + (7901, 2, 136, 11, 0), + (7901, 3, 383, 45, 16190), + (7901, 4, 385, 11012, 0), + (7901, 5, 383, 45, 16190), + (7901, 6, 385, 5130, 0), + (7901, 7, 383, 45, 16190), + (7901, 8, 385, 5230, 0), + (7901, 9, 383, 45, 16190), + (7901, 10, 136, 22, 0), + (7901, 11, 383, 45, 16190), + (7901, 12, 385, 5330, 0), + (7901, 13, 385, 5430, 0), + (7901, 14, 385, 5530, 0), + (7902, 1, 339, 45, 16191), + (7902, 2, 136, 11, 0), + (7902, 3, 383, 45, 16191), + (7902, 4, 385, 11012, 0), + (7902, 5, 383, 45, 16191), + (7902, 6, 385, 5130, 0), + (7902, 7, 383, 45, 16191), + (7902, 8, 385, 5230, 0), + (7902, 9, 383, 45, 16191), + (7902, 10, 136, 22, 0), + (7902, 11, 383, 45, 16191), + (7902, 12, 385, 5330, 0), + (7902, 13, 385, 5430, 0), + (7902, 14, 385, 5530, 0), + (7904, 1, 0, 26, 0), + (7905, 1, 0, 27, 0), + (7906, 1, 0, 28, 0), + (7907, 1, 0, 29, 0), + (7908, 1, 0, 30, 0), + (7940, 1, 264, 15, 558), + (7941, 1, 264, 30, 558), + (7942, 1, 264, 45, 558), + (7945, 1, 310, 2000, 0), + (7945, 2, 139, 8007, 0), + (7945, 3, 310, 2000, 0), + (7945, 4, 385, 4140, 0), + (7945, 5, 385, 4240, 0), + (7945, 6, 385, 4340, 0), + (7945, 7, 385, 4440, 0), + (7945, 8, 385, 4540, 0), + (7945, 9, 385, 4640, 0), + (7946, 1, 310, 4000, 0), + (7946, 2, 139, 8007, 0), + (7946, 3, 310, 4000, 0), + (7946, 4, 385, 4140, 0), + (7946, 5, 385, 4240, 0), + (7946, 6, 385, 4340, 0), + (7946, 7, 385, 4440, 0), + (7946, 8, 385, 4540, 0), + (7946, 9, 385, 4640, 0), + (7947, 1, 310, 6000, 0), + (7947, 2, 139, 8007, 0), + (7947, 3, 310, 6000, 0), + (7947, 4, 385, 4140, 0), + (7947, 5, 385, 4240, 0), + (7947, 6, 385, 4340, 0), + (7947, 7, 385, 4440, 0), + (7947, 8, 385, 4540, 0), + (7947, 9, 385, 4640, 0), + (7948, 1, 339, 25, 16197), + (7948, 2, 138, 1, 0), + (7948, 3, 142, 60, 0), + (7948, 4, 137, 35, 0), + (7948, 5, 134, 75, 0), + (7948, 6, 339, 25, 16197), + (7948, 7, 138, 1, 0), + (7948, 8, 142, 60, 0), + (7948, 9, 137, 36, 0), + (7948, 10, 134, 75, 0), + (7948, 11, 339, 25, 16197), + (7948, 12, 138, 1, 0), + (7948, 13, 142, 60, 0), + (7948, 14, 137, 369, 0), + (7948, 15, 134, 75, 0), + (7948, 16, 339, 25, 16197), + (7948, 17, 138, 1, 0), + (7948, 18, 142, 60, 0), + (7948, 19, 137, 116, 0), + (7948, 20, 134, 75, 0), + (7949, 1, 339, 25, 16198), + (7949, 2, 138, 1, 0), + (7949, 3, 142, 60, 0), + (7949, 4, 137, 35, 0), + (7949, 5, 134, 80, 0), + (7949, 6, 339, 25, 16198), + (7949, 7, 138, 1, 0), + (7949, 8, 142, 60, 0), + (7949, 9, 137, 36, 0), + (7949, 10, 134, 80, 0), + (7949, 11, 339, 25, 16198), + (7949, 12, 138, 1, 0), + (7949, 13, 142, 60, 0), + (7949, 14, 137, 369, 0), + (7949, 15, 134, 80, 0), + (7949, 16, 339, 25, 16198), + (7949, 17, 138, 1, 0), + (7949, 18, 142, 60, 0), + (7949, 19, 137, 116, 0), + (7949, 20, 134, 80, 0), + (7950, 1, 339, 25, 16199), + (7950, 2, 138, 1, 0), + (7950, 3, 142, 60, 0), + (7950, 4, 137, 35, 0), + (7950, 5, 134, 85, 0), + (7950, 6, 339, 25, 16199), + (7950, 7, 138, 1, 0), + (7950, 8, 142, 60, 0), + (7950, 9, 137, 36, 0), + (7950, 10, 134, 85, 0), + (7950, 11, 339, 25, 16199), + (7950, 12, 138, 1, 0), + (7950, 13, 142, 60, 0), + (7950, 14, 137, 369, 0), + (7950, 15, 134, 85, 0), + (7950, 16, 339, 25, 16199), + (7950, 17, 138, 1, 0), + (7950, 18, 142, 60, 0), + (7950, 19, 137, 116, 0), + (7950, 20, 134, 85, 0), + (7980, 1, 243, 15, 0), + (7981, 1, 243, 25, 0), + (7982, 1, 243, 35, 0), + (7983, 1, 264, 120, 520), + (7984, 1, 264, 240, 520), + (7985, 1, 264, 360, 520), + (7989, 1, 264, 30, 705), + (7989, 2, 264, 30, 1092), + (7989, 3, 264, 30, 10396), + (7989, 4, 264, 30, 10397), + (7990, 1, 264, 60, 705), + (7990, 2, 264, 60, 1092), + (7990, 3, 264, 60, 10396), + (7990, 4, 264, 60, 10397), + (7991, 1, 264, 90, 705), + (7991, 2, 264, 90, 1092), + (7991, 3, 264, 90, 10396), + (7991, 4, 264, 90, 10397), + (7992, 1, 264, 120, 705), + (7992, 2, 264, 120, 1092), + (7992, 3, 264, 120, 10396), + (7992, 4, 264, 120, 10397), + (7994, 1, 264, 240, 39), + (7994, 2, 264, 3456, 1061), + (7995, 1, 264, 300, 39), + (7995, 2, 264, 4320, 1061), + (8000, 1, 69, 200, 0), + (8000, 2, 2, 75, 0), + (8000, 3, 97, 200, 0), + (8000, 4, 317, 8, 0), + (8031, 1, 264, 30, 791), + (8032, 1, 264, 60, 791), + (8033, 1, 264, 90, 791), + (8035, 1, 264, 180, 521), + (8036, 1, 264, 360, 521), + (8037, 1, 264, 540, 521), + (8040, 1, 128, 5, 5), + (8040, 2, 138, 1, 0), + (8040, 3, 140, 1, 0), + (8040, 4, 311, 0, 0), + (8040, 5, 411, 256, 0), + (8040, 6, 137, -40, 0), + (8040, 7, 391, 1, 0), + (8041, 1, 128, 15, 15), + (8041, 2, 138, 1, 0), + (8041, 3, 140, 1, 0), + (8041, 4, 311, 0, 0), + (8041, 5, 411, 256, 0), + (8041, 6, 137, -40, 0), + (8041, 7, 391, 1, 0), + (8042, 1, 128, 30, 30), + (8042, 2, 138, 1, 0), + (8042, 3, 140, 1, 0), + (8042, 4, 311, 0, 0), + (8042, 5, 411, 256, 0), + (8042, 6, 137, -40, 0), + (8042, 7, 391, 1, 0), + (8043, 1, 128, 50, 50), + (8043, 2, 138, 1, 0), + (8043, 3, 140, 1, 0), + (8043, 4, 311, 0, 0), + (8043, 5, 411, 256, 0), + (8043, 6, 137, -40, 0), + (8043, 7, 391, 1, 0), + (8059, 1, 128, 50, 50), + (8059, 2, 138, 1, 0), + (8059, 3, 140, 1, 0), + (8059, 4, 311, 0, 0), + (8059, 5, 411, 66434, 0), + (8059, 6, 137, -40, 0), + (8069, 1, 244, -10, 0), + (8070, 1, 244, -15, 0), + (8071, 1, 244, -20, 0), + (8076, 1, 264, 360, 565), + (8076, 2, 264, 360, 793), + (8076, 3, 264, 360, 794), + (8077, 1, 264, 720, 565), + (8077, 2, 264, 720, 793), + (8077, 3, 264, 720, 794), + (8078, 1, 264, 1080, 565), + (8078, 2, 264, 1080, 793), + (8078, 3, 264, 1080, 794), + (8079, 1, 264, 1440, 565), + (8079, 2, 264, 1440, 793), + (8079, 3, 264, 1440, 794), + (8080, 1, 264, 1800, 565), + (8080, 2, 264, 1800, 793), + (8080, 3, 264, 1800, 794), + (8081, 1, 264, 2160, 565), + (8081, 2, 264, 2160, 793), + (8081, 3, 264, 2160, 794), + (8082, 1, 264, 60, 208), + (8083, 1, 264, 120, 208), + (8084, 1, 264, 180, 208), + (8190, 1, 280, 2, 0), + (8191, 1, 280, 4, 0), + (8192, 1, 280, 6, 0), + (8193, 1, 339, 100, 16225), + (8193, 2, 139, 6838, 0), + (8195, 1, 264, 120, 3707), + (8196, 1, 264, 240, 3707), + (8197, 1, 264, 360, 3707), + (8198, 1, 294, 0, 110), + (8199, 1, 294, 0, 120), + (8200, 1, 294, 0, 130), + (8201, 1, 218, 1, 0), + (8202, 1, 218, 2, 0), + (8203, 1, 218, 3, 0), + (8204, 1, 127, 10, 0), + (8204, 2, 137, 154, 0), + (8204, 3, 403, 2, 0), + (8204, 4, 404, 10, 0), + (8205, 1, 127, 20, 0), + (8205, 2, 137, 154, 0), + (8205, 3, 403, 2, 0), + (8205, 4, 404, 10, 0), + (8206, 1, 127, 30, 0), + (8206, 2, 137, 154, 0), + (8206, 3, 403, 2, 0), + (8206, 4, 404, 10, 0), + (8207, 1, 127, 10, 0), + (8207, 2, 137, 154, 0), + (8207, 3, 403, 2, 0), + (8207, 4, 404, 10, 0), + (8208, 1, 127, 20, 0), + (8208, 2, 137, 154, 0), + (8208, 3, 403, 2, 0), + (8208, 4, 404, 10, 0), + (8209, 1, 127, 30, 0), + (8209, 2, 137, 154, 0), + (8209, 3, 403, 2, 0), + (8209, 4, 404, 10, 0), + (8210, 1, 97, 50, 0), + (8211, 1, 97, 100, 0), + (8212, 1, 97, 150, 0), + (8213, 1, 97, 200, 0), + (8214, 1, 97, 250, 0), + (8215, 1, 190, 50, 0), + (8216, 1, 190, 100, 0), + (8217, 1, 190, 150, 0), + (8218, 1, 190, 200, 0), + (8219, 1, 190, 250, 0), + (8223, 1, 128, 50, 50), + (8223, 2, 138, 1, 0), + (8223, 3, 140, 1, 0), + (8223, 4, 139, -2741, 0), + (8223, 5, 139, -16843, 0), + (8223, 6, 385, -16192, 0), + (8224, 1, 339, 10, 16230), + (8224, 2, 138, 1, 0), + (8224, 3, 141, 1, 0), + (8224, 4, 142, 60, 0), + (8224, 5, 137, 0, 0), + (8224, 6, 311, 0, 0), + (8224, 7, 134, 80, 0), + (8224, 8, 139, -265, 0), + (8224, 9, 139, -754, 0), + (8224, 10, 139, -1332, 0), + (8224, 11, 139, -1572, 0), + (8224, 12, 139, -2749, 0), + (8224, 13, 139, -4979, 0), + (8224, 14, 139, -5418, 0), + (8224, 15, 139, -5403, 0), + (8225, 1, 339, 10, 16231), + (8225, 2, 138, 1, 0), + (8225, 3, 141, 1, 0), + (8225, 4, 142, 65, 0), + (8225, 5, 137, 0, 0), + (8225, 6, 311, 0, 0), + (8225, 7, 134, 85, 0), + (8225, 8, 139, -265, 0), + (8225, 9, 139, -754, 0), + (8225, 10, 139, -1332, 0), + (8225, 11, 139, -1572, 0), + (8225, 12, 139, -2749, 0), + (8225, 13, 139, -4979, 0), + (8225, 14, 139, -5418, 0), + (8225, 15, 139, -5403, 0), + (8226, 1, 339, 10, 16232), + (8226, 2, 138, 1, 0), + (8226, 3, 141, 1, 0), + (8226, 4, 142, 70, 0), + (8226, 5, 137, 0, 0), + (8226, 6, 311, 0, 0), + (8226, 7, 134, 90, 0), + (8226, 8, 139, -265, 0), + (8226, 9, 139, -754, 0), + (8226, 10, 139, -1332, 0), + (8226, 11, 139, -1572, 0), + (8226, 12, 139, -2749, 0), + (8226, 13, 139, -4979, 0), + (8226, 14, 139, -5418, 0), + (8226, 15, 139, -5403, 0), + (8228, 1, 378, 5, 22), + (8229, 1, 378, 10, 22), + (8230, 1, 378, 15, 22), + (8232, 1, 128, 5, 5), + (8232, 2, 138, 1, 0), + (8232, 3, 140, 1, 0), + (8232, 4, 311, 0, 0), + (8232, 5, 411, 66434, 0), + (8232, 6, 137, -40, 0), + (8233, 1, 128, 15, 15), + (8233, 2, 138, 1, 0), + (8233, 3, 140, 1, 0), + (8233, 4, 311, 0, 0), + (8233, 5, 411, 66434, 0), + (8233, 6, 137, -40, 0), + (8234, 1, 128, 30, 30), + (8234, 2, 138, 1, 0), + (8234, 3, 140, 1, 0), + (8234, 4, 311, 0, 0), + (8234, 5, 411, 66434, 0), + (8234, 6, 137, -40, 0), + (8235, 1, 1, 29, 0), + (8236, 1, 1, 58, 0), + (8237, 1, 1, 87, 0), + (8238, 1, 1, 116, 0), + (8239, 1, 1, 145, 0), + (8240, 1, 1, 31, 0), + (8241, 1, 1, 62, 0), + (8242, 1, 1, 93, 0), + (8243, 1, 1, 124, 0), + (8244, 1, 1, 155, 0), + (8245, 1, 1, 33, 0), + (8246, 1, 1, 66, 0), + (8247, 1, 1, 99, 0), + (8248, 1, 1, 132, 0), + (8249, 1, 1, 165, 0), + (8250, 1, 1, 40, 0), + (8251, 1, 1, 80, 0), + (8252, 1, 1, 120, 0), + (8253, 1, 1, 160, 0), + (8254, 1, 1, 200, 0), + (8255, 1, 1, 50, 0), + (8256, 1, 1, 100, 0), + (8257, 1, 1, 150, 0), + (8258, 1, 1, 200, 0), + (8259, 1, 1, 250, 0), + (8261, 1, 128, 65, 65), + (8261, 2, 138, 1, 0), + (8261, 3, 140, 1, 0), + (8261, 4, 311, 0, 0), + (8261, 5, 411, 66434, 0), + (8261, 6, 137, -40, 0), + (8262, 1, 128, 70, 70), + (8262, 2, 138, 1, 0), + (8262, 3, 140, 1, 0), + (8262, 4, 139, -2741, 0), + (8262, 5, 139, -16843, 0), + (8262, 6, 385, -16192, 0), + (8263, 1, 262, 5, 0), + (8264, 1, 262, 10, 0), + (8265, 1, 262, 15, 0), + (8266, 1, 262, 20, 0), + (8267, 1, 262, 25, 0), + (8268, 1, 262, 5, 1), + (8269, 1, 262, 10, 1), + (8270, 1, 262, 15, 1), + (8271, 1, 262, 20, 1), + (8272, 1, 262, 25, 1), + (8273, 1, 262, 5, 2), + (8274, 1, 262, 10, 2), + (8275, 1, 262, 15, 2), + (8276, 1, 262, 20, 2), + (8277, 1, 262, 25, 2), + (8278, 1, 262, 5, 3), + (8279, 1, 262, 10, 3), + (8280, 1, 262, 15, 3), + (8281, 1, 262, 20, 3), + (8282, 1, 262, 25, 3), + (8283, 1, 262, 5, 4), + (8284, 1, 262, 10, 4), + (8285, 1, 262, 15, 4), + (8286, 1, 262, 20, 4), + (8287, 1, 262, 25, 4), + (8288, 1, 262, 5, 5), + (8289, 1, 262, 10, 5), + (8290, 1, 262, 15, 5), + (8291, 1, 262, 20, 5), + (8292, 1, 262, 25, 5), + (8293, 1, 262, 5, 6), + (8294, 1, 262, 10, 6), + (8295, 1, 262, 15, 6), + (8296, 1, 262, 20, 6), + (8297, 1, 262, 25, 6), + (8304, 1, 1, 174, 0), + (8305, 1, 1, 203, 0), + (8306, 1, 1, 232, 0), + (8307, 1, 1, 261, 0), + (8308, 1, 1, 290, 0), + (8313, 1, 128, 65, 65), + (8313, 2, 138, 1, 0), + (8313, 3, 140, 1, 0), + (8313, 4, 311, 0, 0), + (8313, 5, 411, 256, 0), + (8313, 6, 137, -40, 0), + (8313, 7, 391, 1, 0), + (8314, 1, 378, 2, 3), + (8315, 1, 378, 3, 3), + (8316, 1, 378, 4, 3), + (8317, 1, 264, 1, 8205), + (8318, 1, 264, 2, 8205), + (8319, 1, 264, 2, 199), + (8320, 1, 264, 4, 199), + (8321, 1, 264, 6, 199), + (8322, 1, 378, 15, 31), + (8323, 1, 378, 20, 31), + (8324, 1, 378, 25, 31), + (8325, 1, 114, -3, 0), + (8326, 1, 114, -6, 0), + (8327, 1, 114, -9, 0), + (8328, 1, 268, 75, 56), + (8328, 2, 234, 1000, 0), + (8329, 1, 227, 4, 29), + (8329, 2, 227, 4, 42), + (8331, 1, 413, 10, 0), + (8331, 2, 139, 8001, 0), + (8331, 3, 385, 12529, 0), + (8331, 4, 411, 512, 0), + (8332, 1, 287, 1, 0), + (8332, 2, 385, 116121, 0), + (8333, 1, 287, 2, 0), + (8333, 2, 385, 116121, 0), + (8334, 1, 287, 3, 0), + (8334, 2, 385, 116121, 0), + (8335, 1, 127, 10, 0), + (8335, 2, 385, 16188, 0), + (8336, 1, 127, 20, 0), + (8336, 2, 385, 16188, 0), + (8337, 1, 127, 30, 0), + (8337, 2, 385, 16188, 0), + (8338, 1, 127, 40, 0), + (8338, 2, 385, 16188, 0), + (8339, 1, 127, 50, 0), + (8339, 2, 385, 16188, 0), + (8344, 1, 294, 0, 175), + (8345, 1, 294, 0, 180), + (8346, 1, 294, 0, 185), + (8347, 1, 264, 600, 616), + (8348, 1, 264, 1200, 616), + (8349, 1, 264, 1800, 616), + (8350, 1, 310, 1200, 0), + (8350, 2, 385, 6212, 0), + (8350, 3, 310, 600, 0), + (8350, 4, 385, 6215, 0), + (8350, 5, 310, 150, 0), + (8350, 6, 385, 6218, 0), + (8350, 7, 310, 9000, 0), + (8350, 8, 385, 6232, 0), + (8350, 9, 310, 600, 0), + (8350, 10, 385, 6243, 0), + (8350, 11, 310, 150, 0), + (8350, 12, 385, 6245, 0), + (8350, 13, 310, 1200, 0), + (8350, 14, 385, 6412, 0), + (8350, 15, 310, 600, 0), + (8350, 16, 385, 6415, 0), + (8350, 17, 310, 150, 0), + (8350, 18, 385, 6418, 0), + (8350, 19, 310, 9000, 0), + (8350, 20, 385, 6432, 0), + (8350, 21, 310, 600, 0), + (8350, 22, 385, 6443, 0), + (8350, 23, 310, 150, 0), + (8350, 24, 385, 6445, 0), + (8351, 1, 262, 30, 0), + (8352, 1, 262, 35, 0), + (8353, 1, 262, 40, 0), + (8354, 1, 262, 45, 0), + (8355, 1, 262, 50, 0), + (8356, 1, 262, 55, 0), + (8357, 1, 262, 60, 0), + (8358, 1, 262, 65, 0), + (8359, 1, 262, 70, 0), + (8360, 1, 262, 75, 0), + (8361, 1, 262, 30, 1), + (8362, 1, 262, 35, 1), + (8363, 1, 262, 40, 1), + (8364, 1, 262, 45, 1), + (8365, 1, 262, 50, 1), + (8366, 1, 262, 55, 1), + (8367, 1, 262, 60, 1), + (8368, 1, 262, 65, 1), + (8369, 1, 262, 70, 1), + (8370, 1, 262, 75, 1), + (8371, 1, 262, 30, 2), + (8372, 1, 262, 35, 2), + (8373, 1, 262, 40, 2), + (8374, 1, 262, 45, 2), + (8375, 1, 262, 50, 2), + (8376, 1, 262, 55, 2), + (8377, 1, 262, 60, 2), + (8378, 1, 262, 65, 2), + (8379, 1, 262, 70, 2), + (8380, 1, 262, 75, 2), + (8381, 1, 262, 30, 3), + (8382, 1, 262, 35, 3), + (8383, 1, 262, 40, 3), + (8384, 1, 262, 45, 3), + (8385, 1, 262, 50, 3), + (8386, 1, 262, 55, 3), + (8387, 1, 262, 60, 3), + (8388, 1, 262, 65, 3), + (8389, 1, 262, 70, 3), + (8390, 1, 262, 75, 3), + (8391, 1, 262, 30, 4), + (8392, 1, 262, 35, 4), + (8393, 1, 262, 40, 4), + (8394, 1, 262, 45, 4), + (8395, 1, 262, 50, 4), + (8396, 1, 262, 55, 4), + (8397, 1, 262, 60, 4), + (8398, 1, 262, 65, 4), + (8399, 1, 262, 70, 4), + (8400, 1, 262, 75, 4), + (8401, 1, 262, 30, 5), + (8402, 1, 262, 35, 5), + (8403, 1, 262, 40, 5), + (8404, 1, 262, 45, 5), + (8405, 1, 262, 50, 5), + (8406, 1, 262, 55, 5), + (8407, 1, 262, 60, 5), + (8408, 1, 262, 65, 5), + (8409, 1, 262, 70, 5), + (8410, 1, 262, 75, 5), + (8411, 1, 262, 30, 6), + (8412, 1, 262, 35, 6), + (8413, 1, 262, 40, 6), + (8414, 1, 262, 45, 6), + (8415, 1, 262, 50, 6), + (8416, 1, 262, 55, 6), + (8417, 1, 262, 60, 6), + (8418, 1, 262, 65, 6), + (8419, 1, 262, 70, 6), + (8420, 1, 262, 75, 6), + (8421, 1, 339, 10, 27535), + (8421, 2, 138, 1, 0), + (8421, 3, 141, 1, 0), + (8421, 4, 142, 75, 0), + (8421, 5, 137, 0, 0), + (8421, 6, 311, 0, 0), + (8421, 7, 134, 95, 0), + (8421, 8, 139, -265, 0), + (8421, 9, 139, -754, 0), + (8421, 10, 139, -1332, 0), + (8421, 11, 139, -1572, 0), + (8421, 12, 139, -2749, 0), + (8421, 13, 139, -4979, 0), + (8421, 14, 139, -5418, 0), + (8421, 15, 139, -5403, 0), + (8422, 1, 1, 198, 0), + (8423, 1, 1, 231, 0), + (8424, 1, 1, 264, 0), + (8425, 1, 1, 297, 0), + (8426, 1, 1, 330, 0), + (8427, 1, 264, 1260, 254), + (8428, 1, 264, 1440, 254), + (8429, 1, 264, 1620, 254), + (8430, 1, 328, 1600, 0), + (8435, 1, 0, 35, 0), + (8440, 1, 259, 66, 0), + (8445, 1, 426, 3, 0), + (8446, 1, 426, 4, 0), + (8447, 1, 426, 5, 0), + (8448, 1, 69, 2200, 0), + (8463, 1, 172, 60, 0), + (8464, 1, 172, 61, 0), + (8470, 1, 262, 80, 7), + (8470, 2, 262, 80, 8), + (8470, 3, 262, 80, 9), + (8470, 4, 262, 80, 10), + (8470, 5, 262, 80, 11), + (9001, 1, 247, 10, 58), + (9002, 1, 247, 20, 58), + (9003, 1, 247, 30, 58), + (9004, 1, 247, 40, 58), + (9005, 1, 247, 50, 58), + (9006, 1, 247, 60, 58), + (9007, 1, 247, 70, 58), + (9008, 1, 247, 80, 58), + (9009, 1, 247, 90, 58), + (9010, 1, 247, 100, 58), + (9011, 1, 247, 10, 58), + (9012, 1, 247, 20, 58), + (9013, 1, 247, 30, 58), + (9014, 1, 247, 40, 58), + (9015, 1, 247, 50, 58), + (9016, 1, 247, 60, 58), + (9017, 1, 247, 70, 58), + (9018, 1, 247, 80, 58), + (9019, 1, 247, 90, 58), + (9020, 1, 247, 100, 58), + (9021, 1, 247, 10, 58), + (9022, 1, 247, 20, 58), + (9023, 1, 247, 30, 58), + (9024, 1, 247, 40, 58), + (9025, 1, 247, 50, 58), + (9026, 1, 247, 60, 58), + (9027, 1, 247, 70, 58), + (9028, 1, 247, 80, 58), + (9029, 1, 247, 90, 58), + (9030, 1, 247, 100, 58), + (9033, 1, 264, 18000, 481), + (9033, 2, 264, 18000, 482), + (9033, 3, 264, 18000, 483), + (9033, 4, 264, 147600, 484), + (9033, 5, 264, 18000, 485), + (9033, 6, 264, 61200, 486), + (9033, 7, 264, 3600, 487), + (9033, 8, 264, 1080, 511), + (9033, 9, 264, 18000, 182), + (9033, 10, 264, 18000, 8081), + (9033, 11, 264, 18000, 8130), + (9033, 12, 264, 18000, 453), + (9033, 13, 264, 18000, 2000), + (9100, 1, 97, 10, 0), + (9100, 2, 262, 1, 5), + (9101, 1, 97, 20, 0), + (9101, 2, 262, 2, 5), + (9102, 1, 97, 30, 0), + (9102, 2, 262, 3, 5), + (9103, 1, 97, 40, 0), + (9103, 2, 262, 4, 5), + (9104, 1, 97, 50, 0), + (9104, 2, 262, 5, 5), + (9105, 1, 97, 60, 0), + (9105, 2, 262, 6, 5), + (9106, 1, 97, 70, 0), + (9106, 2, 262, 7, 5), + (9107, 1, 97, 80, 0), + (9107, 2, 262, 8, 5), + (9108, 1, 97, 90, 0), + (9108, 2, 262, 9, 5), + (9109, 1, 69, 10, 0), + (9109, 2, 262, 1, 1), + (9110, 1, 69, 20, 0), + (9110, 2, 262, 2, 1), + (9111, 1, 69, 30, 0), + (9111, 2, 262, 3, 1), + (9112, 1, 69, 40, 0), + (9112, 2, 262, 4, 1), + (9113, 1, 69, 50, 0), + (9113, 2, 262, 5, 1), + (9114, 1, 69, 60, 0), + (9114, 2, 262, 6, 1), + (9115, 1, 69, 70, 0), + (9115, 2, 262, 7, 1), + (9116, 1, 69, 80, 0), + (9116, 2, 262, 8, 1), + (9117, 1, 69, 90, 0), + (9117, 2, 262, 9, 1), + (9118, 1, 97, 10, 0), + (9118, 2, 262, 1, 5), + (9119, 1, 97, 20, 0), + (9119, 2, 262, 2, 5), + (9120, 1, 97, 30, 0), + (9120, 2, 262, 3, 5), + (9121, 1, 97, 40, 0), + (9121, 2, 262, 4, 5), + (9122, 1, 97, 50, 0), + (9122, 2, 262, 5, 5), + (9123, 1, 97, 60, 0), + (9123, 2, 262, 6, 5), + (9124, 1, 97, 70, 0), + (9124, 2, 262, 7, 5), + (9125, 1, 97, 80, 0), + (9125, 2, 262, 8, 5), + (9126, 1, 97, 90, 0), + (9126, 2, 262, 9, 5), + (9127, 1, 69, 10, 0), + (9127, 2, 262, 1, 5), + (9128, 1, 69, 20, 0), + (9128, 2, 262, 2, 5), + (9129, 1, 69, 30, 0), + (9129, 2, 262, 3, 5), + (9130, 1, 69, 40, 0), + (9130, 2, 262, 4, 5), + (9131, 1, 69, 50, 0), + (9131, 2, 262, 5, 5), + (9132, 1, 69, 60, 0), + (9132, 2, 262, 6, 5), + (9133, 1, 69, 70, 0), + (9133, 2, 262, 7, 5), + (9134, 1, 69, 80, 0), + (9134, 2, 262, 8, 5), + (9135, 1, 69, 90, 0), + (9135, 2, 262, 9, 5), + (9136, 1, 97, 10, 0), + (9136, 2, 262, 1, 4), + (9137, 1, 97, 20, 0), + (9137, 2, 262, 2, 4), + (9138, 1, 97, 30, 0), + (9138, 2, 262, 3, 4), + (9139, 1, 97, 40, 0), + (9139, 2, 262, 4, 4), + (9140, 1, 97, 50, 0), + (9140, 2, 262, 5, 4), + (9141, 1, 97, 60, 0), + (9141, 2, 262, 6, 4), + (9142, 1, 97, 70, 0), + (9142, 2, 262, 7, 4), + (9143, 1, 97, 80, 0), + (9143, 2, 262, 8, 4), + (9144, 1, 97, 90, 0), + (9144, 2, 262, 9, 4), + (9145, 1, 97, 10, 0), + (9145, 2, 262, 1, 4), + (9146, 1, 97, 20, 0), + (9146, 2, 262, 2, 4), + (9147, 1, 97, 30, 0), + (9147, 2, 262, 3, 4), + (9148, 1, 97, 40, 0), + (9148, 2, 262, 4, 4), + (9149, 1, 97, 50, 0), + (9149, 2, 262, 5, 4), + (9150, 1, 97, 60, 0), + (9150, 2, 262, 6, 4), + (9151, 1, 97, 70, 0), + (9151, 2, 262, 7, 4), + (9152, 1, 97, 80, 0), + (9152, 2, 262, 8, 4), + (9153, 1, 97, 90, 0), + (9153, 2, 262, 9, 4), + (9154, 1, 69, 10, 0), + (9154, 2, 262, 1, 1), + (9155, 1, 69, 20, 0), + (9155, 2, 262, 2, 1), + (9156, 1, 69, 30, 0), + (9156, 2, 262, 3, 1), + (9157, 1, 69, 40, 0), + (9157, 2, 262, 4, 1), + (9158, 1, 69, 50, 0), + (9158, 2, 262, 5, 1), + (9159, 1, 69, 60, 0), + (9159, 2, 262, 6, 1), + (9160, 1, 69, 70, 0), + (9160, 2, 262, 7, 1), + (9161, 1, 69, 80, 0), + (9161, 2, 262, 8, 1), + (9162, 1, 69, 90, 0), + (9162, 2, 262, 9, 1), + (9163, 1, 69, 10, 0), + (9163, 2, 262, 1, 3), + (9164, 1, 69, 20, 0), + (9164, 2, 262, 2, 3), + (9165, 1, 69, 30, 0), + (9165, 2, 262, 3, 3), + (9166, 1, 69, 40, 0), + (9166, 2, 262, 4, 3), + (9167, 1, 69, 50, 0), + (9167, 2, 262, 5, 3), + (9168, 1, 69, 60, 0), + (9168, 2, 262, 6, 3), + (9169, 1, 69, 70, 0), + (9169, 2, 262, 7, 3), + (9170, 1, 69, 80, 0), + (9170, 2, 262, 8, 3), + (9171, 1, 69, 90, 0), + (9171, 2, 262, 9, 3), + (9172, 1, 69, 10, 0), + (9172, 2, 262, 1, 0), + (9173, 1, 69, 20, 0), + (9173, 2, 262, 2, 0), + (9174, 1, 69, 30, 0), + (9174, 2, 262, 3, 0), + (9175, 1, 69, 40, 0), + (9175, 2, 262, 4, 0), + (9176, 1, 69, 50, 0), + (9176, 2, 262, 5, 0), + (9177, 1, 69, 60, 0), + (9177, 2, 262, 6, 0), + (9178, 1, 69, 70, 0), + (9178, 2, 262, 7, 0), + (9179, 1, 69, 80, 0), + (9179, 2, 262, 8, 0), + (9180, 1, 69, 90, 0), + (9180, 2, 262, 9, 0), + (9181, 1, 69, 10, 0), + (9181, 2, 262, 1, 0), + (9182, 1, 69, 20, 0), + (9182, 2, 262, 2, 0), + (9183, 1, 69, 30, 0), + (9183, 2, 262, 3, 0), + (9184, 1, 69, 40, 0), + (9184, 2, 262, 4, 0), + (9185, 1, 69, 50, 0), + (9185, 2, 262, 5, 0), + (9186, 1, 69, 60, 0), + (9186, 2, 262, 6, 0), + (9187, 1, 69, 70, 0), + (9187, 2, 262, 7, 0), + (9188, 1, 69, 80, 0), + (9188, 2, 262, 8, 0), + (9189, 1, 69, 90, 0), + (9189, 2, 262, 9, 0), + (9190, 1, 69, 10, 0), + (9190, 2, 262, 1, 0), + (9191, 1, 69, 20, 0), + (9191, 2, 262, 2, 0), + (9192, 1, 69, 30, 0), + (9192, 2, 262, 3, 0), + (9193, 1, 69, 40, 0), + (9193, 2, 262, 4, 0), + (9194, 1, 69, 50, 0), + (9194, 2, 262, 5, 0), + (9195, 1, 69, 60, 0), + (9195, 2, 262, 6, 0), + (9196, 1, 69, 70, 0), + (9196, 2, 262, 7, 0), + (9197, 1, 69, 80, 0), + (9197, 2, 262, 8, 0), + (9198, 1, 69, 90, 0), + (9198, 2, 262, 9, 0), + (9199, 1, 97, 10, 0), + (9199, 2, 262, 1, 0), + (9200, 1, 97, 20, 0), + (9200, 2, 262, 2, 0), + (9201, 1, 97, 30, 0), + (9201, 2, 262, 3, 0), + (9202, 1, 97, 40, 0), + (9202, 2, 262, 4, 0), + (9203, 1, 97, 50, 0), + (9203, 2, 262, 5, 0), + (9204, 1, 97, 60, 0), + (9204, 2, 262, 6, 0), + (9205, 1, 97, 70, 0), + (9205, 2, 262, 7, 0), + (9206, 1, 97, 80, 0), + (9206, 2, 262, 8, 0), + (9207, 1, 97, 90, 0), + (9207, 2, 262, 9, 0), + (9208, 1, 69, 10, 0), + (9208, 2, 262, 1, 0), + (9209, 1, 69, 20, 0), + (9209, 2, 262, 2, 0), + (9210, 1, 69, 30, 0), + (9210, 2, 262, 3, 0), + (9211, 1, 69, 40, 0), + (9211, 2, 262, 4, 0), + (9212, 1, 69, 50, 0), + (9212, 2, 262, 5, 0), + (9213, 1, 69, 60, 0), + (9213, 2, 262, 6, 0), + (9214, 1, 69, 70, 0), + (9214, 2, 262, 7, 0), + (9215, 1, 69, 80, 0), + (9215, 2, 262, 8, 0), + (9216, 1, 69, 90, 0), + (9216, 2, 262, 9, 0), + (9217, 1, 190, 10, 0), + (9217, 2, 262, 1, 0), + (9218, 1, 190, 20, 0), + (9218, 2, 262, 2, 0), + (9219, 1, 190, 30, 0), + (9219, 2, 262, 3, 0), + (9220, 1, 190, 40, 0), + (9220, 2, 262, 4, 0), + (9221, 1, 190, 50, 0), + (9221, 2, 262, 5, 0), + (9222, 1, 190, 60, 0), + (9222, 2, 262, 6, 0), + (9223, 1, 190, 70, 0), + (9223, 2, 262, 7, 0), + (9224, 1, 190, 80, 0), + (9224, 2, 262, 8, 0), + (9225, 1, 190, 90, 0), + (9225, 2, 262, 9, 0), + (9226, 1, 69, 10, 0), + (9226, 2, 262, 1, 0), + (9227, 1, 69, 20, 0), + (9227, 2, 262, 2, 0), + (9228, 1, 69, 30, 0), + (9228, 2, 262, 3, 0), + (9229, 1, 69, 40, 0), + (9229, 2, 262, 4, 0), + (9230, 1, 69, 50, 0), + (9230, 2, 262, 5, 0), + (9231, 1, 69, 60, 0), + (9231, 2, 262, 6, 0), + (9232, 1, 69, 70, 0), + (9232, 2, 262, 7, 0), + (9233, 1, 69, 80, 0), + (9233, 2, 262, 8, 0), + (9234, 1, 69, 90, 0), + (9234, 2, 262, 9, 0), + (9235, 1, 190, 10, 0), + (9235, 2, 262, 1, 0), + (9236, 1, 190, 20, 0), + (9236, 2, 262, 2, 0), + (9237, 1, 190, 30, 0), + (9237, 2, 262, 3, 0), + (9238, 1, 190, 40, 0), + (9238, 2, 262, 4, 0), + (9239, 1, 190, 50, 0), + (9239, 2, 262, 5, 0), + (9240, 1, 190, 60, 0), + (9240, 2, 262, 6, 0), + (9241, 1, 190, 70, 0), + (9241, 2, 262, 7, 0), + (9242, 1, 190, 80, 0), + (9242, 2, 262, 8, 0), + (9243, 1, 190, 90, 0), + (9243, 2, 262, 9, 0), + (9503, 1, 397, 100, 0), + (9504, 1, 397, 200, 0), + (9505, 1, 397, 300, 0), + (9506, 1, 398, 1000, 0), + (9506, 2, 137, 152, 0), + (9507, 1, 398, 2000, 0), + (9507, 2, 137, 152, 0), + (9508, 1, 398, 3000, 0), + (9508, 2, 137, 152, 0), + (9509, 1, 399, 1, 0), + (9509, 2, 141, 1, 0), + (9509, 3, 138, 0, 0), + (9509, 4, 134, 254, 0), + (9509, 5, 348, 10, 0), + (9509, 6, 137, 0, 0), + (9509, 7, 311, 0, 0), + (9509, 8, 137, -152, 0), + (9509, 9, 137, -39, 0), + (9510, 1, 399, 2, 0), + (9510, 2, 141, 1, 0), + (9510, 3, 138, 0, 0), + (9510, 4, 134, 254, 0), + (9510, 5, 348, 10, 0), + (9510, 6, 137, 0, 0), + (9510, 7, 311, 0, 0), + (9510, 8, 137, -152, 0), + (9510, 9, 137, -39, 0), + (9511, 1, 399, 3, 0), + (9511, 2, 141, 1, 0), + (9511, 3, 138, 0, 0), + (9511, 4, 134, 254, 0), + (9511, 5, 348, 10, 0), + (9511, 6, 137, 0, 0), + (9511, 7, 311, 0, 0), + (9511, 8, 137, -152, 0), + (9511, 9, 137, -39, 0), + (9512, 1, 405, 1, 0), + (9513, 1, 405, 3, 0), + (9514, 1, 405, 5, 0), + (9515, 1, 399, 4, 0), + (9515, 2, 141, 1, 0), + (9515, 3, 138, 0, 0), + (9515, 4, 134, 254, 0), + (9515, 5, 348, 10, 0), + (9515, 6, 137, 0, 0), + (9515, 7, 311, 0, 0), + (9515, 8, 137, -152, 0), + (9515, 9, 137, -39, 0), + (10004, 1, 310, 480000, 0), + (10004, 2, 139, 4674, 0), + (10005, 1, 310, 600000, 0), + (10005, 2, 139, 4674, 0), + (10007, 1, 85, 16500, 50), + (10008, 1, 85, 16501, 50), + (10009, 1, 85, 16502, 50), + (10025, 1, 339, 25, 16517), + (10025, 2, 137, 21, 0), + (10026, 1, 339, 25, 16518), + (10026, 2, 137, 21, 0), + (10027, 1, 339, 25, 16519), + (10027, 2, 137, 21, 0), + (10028, 1, 339, 25, 16520), + (10028, 2, 137, 21, 0), + (10029, 1, 339, 25, 16555), + (10029, 2, 137, 21, 0), + (10030, 1, 264, 60, 558), + (10031, 1, 264, 75, 558), + (10032, 1, 264, 90, 558), + (10033, 1, 310, 8000, 0), + (10033, 2, 139, 8007, 0), + (10033, 3, 310, 8000, 0), + (10033, 4, 385, 4140, 0), + (10033, 5, 385, 4240, 0), + (10033, 6, 385, 4340, 0), + (10033, 7, 385, 4440, 0), + (10033, 8, 385, 4540, 0), + (10033, 9, 385, 4640, 0), + (10034, 1, 310, 10000, 0), + (10034, 2, 139, 8007, 0), + (10034, 3, 310, 10000, 0), + (10034, 4, 385, 4140, 0), + (10034, 5, 385, 4240, 0), + (10034, 6, 385, 4340, 0), + (10034, 7, 385, 4440, 0), + (10034, 8, 385, 4540, 0), + (10034, 9, 385, 4640, 0), + (10035, 1, 339, 25, 16556), + (10035, 2, 138, 1, 0), + (10035, 3, 142, 60, 0), + (10035, 4, 137, 35, 0), + (10035, 5, 134, 85, 0), + (10035, 6, 339, 25, 16556), + (10035, 7, 138, 1, 0), + (10035, 8, 142, 60, 0), + (10035, 9, 137, 36, 0), + (10035, 10, 134, 85, 0), + (10035, 11, 339, 25, 16556), + (10035, 12, 138, 1, 0), + (10035, 13, 142, 60, 0), + (10035, 14, 137, 369, 0), + (10035, 15, 134, 85, 0), + (10035, 16, 339, 25, 16556), + (10035, 17, 138, 1, 0), + (10035, 18, 142, 60, 0), + (10035, 19, 137, 116, 0), + (10035, 20, 134, 85, 0), + (10036, 1, 339, 25, 16557), + (10036, 2, 138, 1, 0), + (10036, 3, 142, 60, 0), + (10036, 4, 137, 35, 0), + (10036, 5, 134, 85, 0), + (10036, 6, 339, 25, 16557), + (10036, 7, 138, 1, 0), + (10036, 8, 142, 60, 0), + (10036, 9, 137, 36, 0), + (10036, 10, 134, 85, 0), + (10036, 11, 339, 25, 16557), + (10036, 12, 138, 1, 0), + (10036, 13, 142, 60, 0), + (10036, 14, 137, 369, 0), + (10036, 15, 134, 85, 0), + (10036, 16, 339, 25, 16557), + (10036, 17, 138, 1, 0), + (10036, 18, 142, 60, 0), + (10036, 19, 137, 116, 0), + (10036, 20, 134, 85, 0), + (10037, 1, 339, 25, 16558), + (10037, 2, 138, 1, 0), + (10037, 3, 142, 60, 0), + (10037, 4, 137, 35, 0), + (10037, 5, 134, 85, 0), + (10037, 6, 339, 25, 16558), + (10037, 7, 138, 1, 0), + (10037, 8, 142, 60, 0), + (10037, 9, 137, 36, 0), + (10037, 10, 134, 85, 0), + (10037, 11, 339, 25, 16558), + (10037, 12, 138, 1, 0), + (10037, 13, 142, 60, 0), + (10037, 14, 137, 369, 0), + (10037, 15, 134, 85, 0), + (10037, 16, 339, 25, 16558), + (10037, 17, 138, 1, 0), + (10037, 18, 142, 60, 0), + (10037, 19, 137, 116, 0), + (10037, 20, 134, 85, 0), + (10041, 1, 294, 0, 135), + (10042, 1, 294, 0, 145), + (10043, 1, 294, 0, 155), + (10044, 1, 339, 20, 16564), + (10044, 2, 137, 21, 0), + (10044, 3, 385, -18000, 0), + (10044, 4, 339, 20, 16564), + (10044, 5, 137, 343, 0), + (10044, 6, 385, -18000, 0), + (10045, 1, 339, 20, 16565), + (10045, 2, 137, 21, 0), + (10045, 3, 385, -18000, 0), + (10045, 4, 339, 20, 16565), + (10045, 5, 137, 343, 0), + (10045, 6, 385, -18000, 0), + (10046, 1, 339, 20, 16566), + (10046, 2, 137, 21, 0), + (10046, 3, 385, -18000, 0), + (10046, 4, 339, 20, 16566), + (10046, 5, 137, 343, 0), + (10046, 6, 385, -18000, 0), + (10050, 1, 85, 16567, 0), + (10051, 1, 85, 16568, 0), + (10052, 1, 85, 16569, 0), + (10058, 1, 330, 55, 7), + (10059, 1, 330, 60, 7), + (10060, 1, 330, 65, 7), + (10064, 1, 347, 25, 0), + (10065, 1, 347, 26, 0), + (10066, 1, 347, 27, 0), + (10067, 1, 347, 28, 0), + (10068, 1, 347, 29, 0), + (10069, 1, 347, 30, 0), + (10070, 1, 218, 6, 0), + (10071, 1, 218, 7, 0), + (10072, 1, 218, 8, 0), + (10073, 1, 218, 9, 0), + (10074, 1, 218, 10, 0), + (10075, 1, 339, 10, 16581), + (10075, 2, 138, 0, 0), + (10075, 3, 142, 70, 0), + (10075, 4, 403, 4, 0), + (10075, 5, 348, 1, 0), + (10075, 6, 404, 2, 0), + (10075, 7, 141, 1, 0), + (10076, 1, 339, 10, 16582), + (10076, 2, 138, 0, 0), + (10076, 3, 142, 70, 0), + (10076, 4, 403, 4, 0), + (10076, 5, 348, 1, 0), + (10076, 6, 404, 2, 0), + (10076, 7, 141, 1, 0), + (10077, 1, 339, 10, 16583), + (10077, 2, 138, 0, 0), + (10077, 3, 142, 70, 0), + (10077, 4, 403, 4, 0), + (10077, 5, 348, 1, 0), + (10077, 6, 404, 2, 0), + (10077, 7, 141, 1, 0), + (10081, 1, 85, 16584, 0), + (10082, 1, 85, 16585, 0), + (10083, 1, 85, 16586, 0), + (10084, 1, 375, 175, 0), + (10085, 1, 375, 200, 0), + (10086, 1, 375, 215, 0), + (10087, 1, 397, 400, 0), + (10088, 1, 397, 600, 0), + (10089, 1, 397, 800, 0), + (10105, 1, 264, 60, 170), + (10106, 1, 264, 70, 170), + (10107, 1, 264, 80, 170), + (10108, 1, 264, 90, 170), + (10109, 1, 264, 100, 170), + (10110, 1, 264, 480, 520), + (10111, 1, 264, 600, 520), + (10112, 1, 264, 720, 520), + (10122, 1, 227, 210, 32), + (10123, 1, 227, 240, 32), + (10124, 1, 283, 180, 0), + (10125, 1, 283, 200, 0), + (10126, 1, 283, 220, 0), + (10130, 1, 264, 720, 544), + (10131, 1, 264, 900, 544), + (10132, 1, 264, 1080, 544), + (10133, 1, 279, 19, 0), + (10134, 1, 279, 23, 0), + (10135, 1, 279, 27, 0), + (10136, 1, 375, 130, 0), + (10137, 1, 375, 135, 0), + (10138, 1, 375, 140, 0), + (10153, 1, 264, 420, 553), + (10154, 1, 264, 480, 553), + (10155, 1, 264, 540, 553), + (10165, 1, 220, 195, 8), + (10166, 1, 220, 225, 8), + (10167, 1, 220, 255, 8), + (10171, 1, 252, 90, 0), + (10172, 1, 252, 95, 0), + (10173, 1, 258, 70, 0), + (10174, 1, 258, 71, 0), + (10175, 1, 258, 72, 0), + (10176, 1, 264, 40, 171), + (10177, 1, 264, 50, 171), + (10178, 1, 264, 60, 171), + (10182, 1, 264, 180, 177), + (10183, 1, 264, 210, 177), + (10184, 1, 264, 240, 177), + (10185, 1, 264, 270, 177), + (10186, 1, 264, 300, 177), + (10203, 1, 264, 720, 524), + (10204, 1, 264, 900, 524), + (10205, 1, 264, 1080, 524), + (10206, 1, 264, 1080, 320), + (10207, 1, 264, 1260, 320), + (10213, 1, 218, 16, 0), + (10214, 1, 218, 17, 0), + (10215, 1, 218, 18, 0), + (10216, 1, 218, 19, 0), + (10217, 1, 218, 20, 0), + (10219, 1, 280, 63, 0), + (10220, 1, 280, 64, 0), + (10221, 1, 280, 65, 0), + (10222, 1, 280, 66, 0), + (10223, 1, 280, 67, 0), + (10227, 1, 360, 60, 16720), + (10228, 1, 360, 60, 16721), + (10229, 1, 360, 60, 16722), + (10249, 1, 264, 240, 208), + (10250, 1, 264, 300, 208), + (10251, 1, 264, 360, 208), + (10262, 1, 274, 23, 0), + (10263, 1, 274, 24, 0), + (10264, 1, 274, 25, 0), + (10265, 1, 280, 57, 0), + (10266, 1, 280, 58, 0), + (10267, 1, 280, 59, 0), + (10268, 1, 339, 45, 16736), + (10268, 2, 136, 11, 0), + (10268, 3, 383, 45, 16736), + (10268, 4, 385, 11012, 0), + (10268, 5, 383, 45, 16736), + (10268, 6, 385, 5130, 0), + (10268, 7, 383, 45, 16736), + (10268, 8, 385, 5230, 0), + (10268, 9, 383, 45, 16736), + (10268, 10, 136, 22, 0), + (10268, 11, 383, 45, 16736), + (10268, 12, 385, 5330, 0), + (10268, 13, 385, 5430, 0), + (10268, 14, 385, 5530, 0), + (10269, 1, 339, 45, 16737), + (10269, 2, 136, 11, 0), + (10269, 3, 383, 45, 16737), + (10269, 4, 385, 11012, 0), + (10269, 5, 383, 45, 16737), + (10269, 6, 385, 5130, 0), + (10269, 7, 383, 45, 16737), + (10269, 8, 385, 5230, 0), + (10269, 9, 383, 45, 16737), + (10269, 10, 136, 22, 0), + (10269, 11, 383, 45, 16737), + (10269, 12, 385, 5330, 0), + (10269, 13, 385, 5430, 0), + (10269, 14, 385, 5530, 0), + (10270, 1, 339, 45, 16738), + (10270, 2, 136, 11, 0), + (10270, 3, 383, 45, 16738), + (10270, 4, 385, 11012, 0), + (10270, 5, 383, 45, 16738), + (10270, 6, 385, 5130, 0), + (10270, 7, 383, 45, 16738), + (10270, 8, 385, 5230, 0), + (10270, 9, 383, 45, 16738), + (10270, 10, 136, 22, 0), + (10270, 11, 383, 45, 16738), + (10270, 12, 385, 5330, 0), + (10270, 13, 385, 5430, 0), + (10270, 14, 385, 5530, 0), + (10282, 1, 264, 120, 791), + (10283, 1, 264, 150, 791), + (10284, 1, 264, 180, 791), + (10285, 1, 264, 720, 521), + (10286, 1, 264, 900, 521), + (10287, 1, 264, 1080, 521), + (10291, 1, 264, 15, 247), + (10291, 2, 264, 8, 986), + (10291, 3, 264, 8, 987), + (10291, 4, 264, 8, 988), + (10292, 1, 264, 18, 247), + (10292, 2, 264, 10, 986), + (10292, 3, 264, 10, 987), + (10292, 4, 264, 10, 988), + (10293, 1, 264, 21, 247), + (10293, 2, 264, 12, 986), + (10293, 3, 264, 12, 987), + (10293, 4, 264, 12, 988), + (10305, 1, 280, 68, 0), + (10306, 1, 280, 69, 0), + (10307, 1, 280, 70, 0), + (10311, 1, 220, 608, 74), + (10312, 1, 220, 640, 74), + (10313, 1, 220, 672, 74), + (10314, 1, 220, 704, 74), + (10315, 1, 220, 736, 74), + (10316, 1, 216, 160, 74), + (10317, 1, 216, 200, 74), + (10318, 1, 216, 240, 74), + (10329, 1, 264, 60, 3701), + (10332, 1, 287, 1, 0), + (10332, 2, 137, 22, 0), + (10332, 3, 411, 256, 0), + (10340, 1, 220, 100, 26), + (10341, 1, 220, 160, 26), + (10342, 1, 220, 235, 26), + (10343, 1, 264, 5, 469), + (10344, 1, 264, 10, 469), + (10345, 1, 264, 15, 469), + (10347, 1, 310, 12000, 0), + (10347, 2, 139, 8007, 0), + (10347, 3, 310, 12000, 0), + (10347, 4, 385, 4140, 0), + (10347, 5, 385, 4240, 0), + (10347, 6, 385, 4340, 0), + (10347, 7, 385, 4440, 0), + (10347, 8, 385, 4540, 0), + (10347, 9, 385, 4640, 0), + (10348, 1, 244, 60, 0), + (10349, 1, 244, 50, 0), + (10350, 1, 244, 40, 0), + (10355, 1, 124, 50, 50), + (10355, 2, 385, 19, 0), + (10355, 3, 144, 0, 0), + (10355, 4, 403, 3, 0), + (10355, 5, 404, 48, 0), + (10355, 6, 385, -21768, 0), + (10356, 1, 124, 100, 100), + (10356, 2, 385, 19, 0), + (10356, 3, 144, 0, 0), + (10356, 4, 403, 3, 0), + (10356, 5, 404, 48, 0), + (10356, 6, 385, -21768, 0), + (10357, 1, 124, 150, 150), + (10357, 2, 385, 19, 0), + (10357, 3, 144, 0, 0), + (10357, 4, 403, 3, 0), + (10357, 5, 404, 48, 0), + (10357, 6, 385, -21768, 0), + (10358, 1, 310, 10000, 0), + (10358, 2, 139, 1546, 0), + (10358, 3, 310, 10000, 0), + (10358, 4, 385, 4357, 0), + (10358, 5, 385, 4457, 0), + (10358, 6, 385, 4557, 0), + (10358, 7, 385, 4657, 0), + (10358, 8, 411, 4, 0), + (10359, 1, 310, 20000, 0), + (10359, 2, 139, 1546, 0), + (10359, 3, 310, 20000, 0), + (10359, 4, 385, 4357, 0), + (10359, 5, 385, 4457, 0), + (10359, 6, 385, 4557, 0), + (10359, 7, 385, 4657, 0), + (10359, 8, 411, 4, 0), + (10360, 1, 310, 30000, 0), + (10360, 2, 139, 1546, 0), + (10360, 3, 310, 30000, 0), + (10360, 4, 385, 4357, 0), + (10360, 5, 385, 4457, 0), + (10360, 6, 385, 4557, 0), + (10360, 7, 385, 4657, 0), + (10360, 8, 411, 4, 0), + (10361, 1, 232, 17, 4544), + (10362, 1, 232, 19, 4544), + (10363, 1, 232, 21, 4544), + (10364, 1, 413, -5, 0), + (10364, 2, 139, 480, 0), + (10364, 3, 385, 4352, 0), + (10364, 4, 385, 4452, 0), + (10365, 1, 413, -10, 0), + (10365, 2, 139, 480, 0), + (10365, 3, 385, 4352, 0), + (10365, 4, 385, 4452, 0), + (10366, 1, 413, -15, 0), + (10366, 2, 139, 480, 0), + (10366, 3, 385, 4352, 0), + (10366, 4, 385, 4452, 0), + (10370, 1, 114, -5, 0), + (10371, 1, 114, -10, 0), + (10372, 1, 114, -20, 0), + (10380, 1, 126, 5, 0), + (10380, 2, 134, 85, 0), + (10380, 3, 135, 4, 0), + (10380, 4, 135, 5, 0), + (10381, 1, 126, 10, 0), + (10381, 2, 134, 85, 0), + (10381, 3, 135, 4, 0), + (10381, 4, 135, 5, 0), + (10382, 1, 126, 15, 0), + (10382, 2, 134, 85, 0), + (10382, 3, 135, 4, 0), + (10382, 4, 135, 5, 0), + (10383, 1, 360, 25, 21770), + (10384, 1, 360, 25, 21771), + (10385, 1, 360, 25, 21772), + (10388, 1, 323, 21850, 0), + (10389, 1, 287, 5, 0), + (10389, 2, 385, 16107, 0), + (10389, 3, 411, 512, 0), + (10390, 1, 287, 10, 0), + (10390, 2, 385, 16107, 0), + (10390, 3, 411, 512, 0), + (10391, 1, 287, 15, 0), + (10391, 2, 385, 16107, 0), + (10391, 3, 411, 512, 0), + (10398, 1, 264, 120, 3701), + (10399, 1, 264, 180, 3701), + (10401, 1, 310, 30000, 0), + (10401, 2, 385, 3107, 0), + (10401, 3, 385, 3207, 0), + (10401, 4, 385, 3307, 0), + (10401, 5, 385, 3407, 0), + (10401, 6, 385, 3507, 0), + (10401, 7, 385, 3607, 0), + (10402, 1, 310, 60000, 0), + (10402, 2, 385, 3107, 0), + (10402, 3, 385, 3207, 0), + (10402, 4, 385, 3307, 0), + (10402, 5, 385, 3407, 0), + (10402, 6, 385, 3507, 0), + (10402, 7, 385, 3607, 0), + (10403, 1, 310, 90000, 0), + (10403, 2, 385, 3107, 0), + (10403, 3, 385, 3207, 0), + (10403, 4, 385, 3307, 0), + (10403, 5, 385, 3407, 0), + (10403, 6, 385, 3507, 0), + (10403, 7, 385, 3607, 0), + (10404, 1, 287, 1, 0), + (10404, 2, 139, 8003, 0), + (10405, 1, 310, 120000, 0), + (10405, 2, 139, 4590, 0), + (10406, 1, 310, 240000, 0), + (10406, 2, 139, 4590, 0), + (10407, 1, 310, 360000, 0), + (10407, 2, 139, 4590, 0), + (10408, 1, 310, 480000, 0), + (10408, 2, 139, 4590, 0), + (10409, 1, 310, 600000, 0), + (10409, 2, 139, 4590, 0), + (10410, 1, 247, 130, 76), + (10413, 1, 264, 60, 207), + (10414, 2, 264, 120, 207), + (10415, 3, 264, 180, 207), + (10416, 4, 264, 240, 207), + (10417, 5, 264, 300, 207), + (10431, 1, 264, 210, 791), + (10432, 1, 264, 240, 791), + (10433, 1, 264, 270, 791), + (10434, 1, 127, 16, 0), + (10434, 2, 385, 5921, 0), + (10435, 1, 127, 33, 0), + (10435, 2, 385, 5921, 0), + (10436, 1, 127, 50, 0), + (10436, 2, 385, 5921, 0), + (10437, 1, 339, 25, 23523), + (10437, 2, 137, 21, 0), + (10438, 1, 339, 25, 23524), + (10438, 2, 137, 21, 0), + (10439, 1, 339, 25, 23525), + (10439, 2, 137, 21, 0), + (10440, 1, 339, 25, 23526), + (10440, 2, 137, 21, 0), + (10442, 1, 413, -20, 0), + (10442, 2, 139, 480, 0), + (10442, 3, 385, 4352, 0), + (10442, 4, 385, 4452, 0), + (10443, 1, 413, -25, 0), + (10443, 2, 139, 480, 0), + (10443, 3, 385, 4352, 0), + (10443, 4, 385, 4452, 0), + (10453, 1, 126, 1, 1), + (10453, 2, 137, 21, 0), + (10453, 3, 231, 1, 0), + (10454, 1, 126, 2, 2), + (10454, 2, 137, 21, 0), + (10454, 3, 231, 2, 0), + (10455, 1, 126, 3, 3), + (10455, 2, 137, 21, 0), + (10455, 3, 231, 3, 0), + (10456, 1, 127, 15, 15), + (10456, 2, 139, 12786, 0), + (10457, 1, 127, 30, 30), + (10457, 2, 139, 12786, 0), + (10458, 1, 127, 50, 50), + (10458, 2, 139, 12786, 0), + (10459, 1, 310, 3000, 0), + (10459, 2, 139, 480, 0), + (10459, 3, 310, 3000, 0), + (10459, 4, 385, 4352, 0), + (10459, 5, 385, 4452, 0), + (10459, 6, 385, 4552, 0), + (10460, 1, 310, 6000, 0), + (10460, 2, 139, 480, 0), + (10460, 3, 310, 6000, 0), + (10460, 4, 385, 4352, 0), + (10460, 5, 385, 4452, 0), + (10460, 6, 385, 4552, 0), + (10461, 1, 310, 10000, 0), + (10461, 2, 139, 480, 0), + (10461, 3, 310, 10000, 0), + (10461, 4, 385, 4352, 0), + (10461, 5, 385, 4452, 0), + (10461, 6, 385, 4552, 0), + (10464, 1, 264, 120, 391), + (10465, 1, 264, 240, 391), + (10466, 1, 264, 360, 391), + (10467, 1, 128, 70, 70), + (10467, 2, 138, 1, 0), + (10467, 3, 140, 1, 0), + (10467, 4, 139, -2741, 0), + (10467, 5, 139, -16843, 0), + (10467, 6, 385, -16192, 0), + (10467, 7, 385, -10547, 0), + (10467, 8, 385, -13543, 0), + (10470, 1, 127, 10, 0), + (10470, 2, 385, 8048, 0), + (10471, 1, 127, 20, 0), + (10471, 2, 385, 8048, 0), + (10472, 1, 127, 30, 0), + (10472, 2, 385, 8048, 0), + (10473, 1, 265, 82, 0), + (10474, 1, 265, 83, 0), + (10475, 1, 265, 84, 0), + (10476, 1, 265, 85, 0), + (10477, 1, 265, 86, 0), + (10478, 1, 360, 3, 46246), + (10511, 1, 264, 60, 185), + (10511, 2, 264, 60, 10426), + (10512, 1, 264, 120, 185), + (10512, 2, 264, 120, 10426), + (10513, 1, 264, 180, 185), + (10513, 2, 264, 180, 10426), + (10514, 1, 264, 60, 519), + (10514, 2, 264, 60, 10427), + (10515, 1, 264, 180, 519), + (10515, 2, 264, 180, 10427), + (10516, 1, 264, 120, 519), + (10516, 2, 264, 120, 10427), + (10519, 1, 264, 60, 3213), + (10522, 1, 264, 2, 3732), + (10527, 1, 264, 30, 1400), + (10532, 1, 264, 30, 1401), + (10537, 1, 264, 30, 1402), + (10548, 1, 349, 10, 0), + (10548, 2, 200, 10, 0), + (10548, 3, 419, 27672, 20), + (10551, 1, 339, 10, 16825), + (10551, 2, 137, 31, 0), + (10552, 1, 339, 10, 16826), + (10552, 2, 137, 31, 0), + (10553, 1, 339, 10, 16827), + (10553, 2, 137, 31, 0), + (10554, 1, 339, 12, 8265), + (10554, 2, 138, 0, 0), + (10554, 3, 137, 31, 0), + (10554, 4, 311, 0, 0), + (10555, 1, 339, 14, 8265), + (10555, 2, 138, 0, 0), + (10555, 3, 137, 31, 0), + (10555, 4, 311, 0, 0), + (10556, 1, 339, 16, 8265), + (10556, 2, 138, 0, 0), + (10556, 3, 137, 31, 0), + (10556, 4, 311, 0, 0), + (10558, 1, 264, 60, 1120), + (10559, 1, 264, 120, 1120), + (10560, 1, 264, 180, 1120), + (10561, 1, 126, 5, 5), + (10561, 2, 139, 12576, 0), + (10561, 3, 126, 5, 5), + (10561, 4, 139, 12828, 0), + (10562, 1, 126, 10, 10), + (10562, 2, 139, 12576, 0), + (10562, 3, 126, 10, 10), + (10562, 4, 139, 12828, 0), + (10563, 1, 126, 15, 15), + (10563, 2, 139, 12576, 0), + (10563, 3, 126, 15, 15), + (10563, 4, 139, 12828, 0), + (10568, 1, 85, 23614, 50), + (10574, 1, 310, 720000, 0), + (10574, 2, 139, 4670, 0), + (10575, 1, 310, 720000, 0), + (10575, 2, 139, 4674, 0), + (10576, 1, 264, 420, 109), + (10579, 1, 264, 40, 3646), + (10580, 1, 264, 50, 3646), + (10588, 1, 264, 2, 601), + (10589, 1, 264, 4, 601), + (10590, 1, 264, 6, 601), + (10591, 1, 264, 8, 601), + (10592, 1, 264, 10, 601), + (10604, 1, 213, 13, 0), + (10605, 1, 213, 15, 0), + (10606, 1, 213, 17, 0), + (10607, 1, 215, 12, 0), + (10608, 1, 215, 14, 0), + (10609, 1, 215, 16, 0), + (10610, 1, 129, 25, 25), + (10610, 2, 385, 100265, 0), + (10611, 1, 129, 25, 25), + (10611, 2, 385, 100265, 0), + (10612, 1, 129, 25, 25), + (10612, 2, 385, 100265, 0), + (10621, 1, 264, 960, 180), + (10622, 1, 264, 1200, 180), + (10623, 1, 279, 19, 0), + (10624, 1, 279, 24, 0), + (10625, 1, 279, 30, 0), + (10627, 1, 224, 20, 74), + (10627, 2, 173, 1, 0), + (10628, 1, 224, 35, 74), + (10628, 2, 173, 2, 0), + (10629, 1, 224, 50, 74), + (10629, 2, 173, 3, 0), + (10632, 1, 265, 82, 0), + (10633, 1, 265, 83, 0), + (10634, 1, 265, 84, 0), + (10635, 1, 265, 85, 0), + (10636, 1, 265, 86, 0), + (10637, 1, 320, 12, 0), + (10638, 1, 320, 13, 0), + (10639, 1, 320, 14, 0), + (10641, 2, 385, 11064, 0), + (10643, 1, 124, 200, 200), + (10643, 2, 385, 19, 0), + (10643, 3, 144, 0, 0), + (10643, 4, 403, 3, 0), + (10643, 5, 404, 48, 0), + (10643, 6, 385, -21768, 0), + (10644, 1, 124, 250, 250), + (10644, 2, 385, 19, 0), + (10644, 3, 144, 0, 0), + (10644, 4, 403, 3, 0), + (10644, 5, 404, 48, 0), + (10644, 6, 385, -21768, 0), + (10645, 1, 124, 300, 300), + (10645, 2, 385, 19, 0), + (10645, 3, 144, 0, 0), + (10645, 4, 403, 3, 0), + (10645, 5, 404, 48, 0), + (10645, 6, 385, -21768, 0), + (10650, 1, 378, 1, 3), + (10651, 1, 378, 2, 3), + (10652, 1, 378, 3, 3), + (10653, 1, 310, 120000, 0), + (10653, 2, 139, 4502, 0), + (10653, 3, 139, 4509, 0), + (10654, 1, 310, 240000, 0), + (10654, 2, 139, 4502, 0), + (10654, 3, 139, 4509, 0), + (10655, 1, 310, 360000, 0), + (10655, 2, 139, 4502, 0), + (10655, 3, 139, 4509, 0), + (10656, 1, 287, 1, 0), + (10656, 2, 385, 15002, 0), + (10656, 3, 385, 15003, 0), + (10656, 4, 411, 128, 0), + (10657, 1, 264, 300, 276), + (10658, 1, 264, 600, 276), + (10659, 1, 264, 900, 276), + (10660, 1, 220, 175, 26), + (10660, 2, 220, 175, 30), + (10660, 3, 220, 175, 38), + (10661, 1, 220, 200, 26), + (10661, 2, 220, 200, 30), + (10661, 3, 220, 200, 38), + (10662, 1, 220, 225, 26), + (10662, 2, 220, 225, 30), + (10662, 3, 220, 225, 38), + (10663, 1, 220, 165, 21), + (10663, 2, 220, 165, 23), + (10663, 3, 220, 330, 52), + (10663, 4, 220, 165, 28), + (10664, 1, 220, 175, 21), + (10664, 2, 220, 175, 23), + (10664, 3, 220, 350, 52), + (10664, 4, 220, 175, 28), + (10665, 1, 220, 185, 21), + (10665, 2, 220, 185, 23), + (10665, 3, 220, 370, 52), + (10665, 4, 220, 185, 28), + (10666, 1, 264, 1200, 98), + (10667, 1, 264, 1320, 98), + (10668, 1, 264, 1440, 98), + (10671, 1, 310, 720000, 0), + (10671, 2, 139, 4590, 0), + (10672, 1, 310, 840000, 0), + (10672, 2, 139, 4590, 0), + (10673, 1, 310, 960000, 0), + (10673, 2, 139, 4590, 0), + (10674, 1, 310, 1080000, 0), + (10674, 2, 139, 4590, 0), + (10675, 1, 310, 1200000, 0), + (10675, 2, 139, 4590, 0), + (10676, 1, 339, 20, 23623), + (10676, 2, 137, 21, 0), + (10676, 3, 385, -18000, 0), + (10676, 4, 339, 20, 23623), + (10676, 5, 137, 343, 0), + (10676, 6, 385, -18000, 0), + (10677, 1, 339, 20, 23624), + (10677, 2, 137, 21, 0), + (10677, 3, 385, -18000, 0), + (10677, 4, 339, 20, 23624), + (10677, 5, 137, 343, 0), + (10677, 6, 385, -18000, 0), + (10678, 1, 339, 20, 23625), + (10678, 2, 137, 21, 0), + (10678, 3, 385, -18000, 0), + (10678, 4, 339, 20, 23625), + (10678, 5, 137, 343, 0), + (10678, 6, 385, -18000, 0), + (10685, 1, 266, 34, 0), + (10686, 1, 266, 39, 0), + (10687, 1, 266, 45, 0), + (10688, 1, 220, 125, 10), + (10689, 1, 220, 145, 10), + (10690, 1, 220, 165, 10), + (10691, 1, 220, 190, 10), + (10692, 1, 220, 220, 10), + (10705, 1, 85, 23542, 0), + (10706, 1, 85, 23543, 0), + (10707, 1, 85, 23544, 0), + (10714, 1, 264, 90, 873), + (10715, 1, 264, 180, 873), + (10717, 1, 264, 360, 184), + (10718, 1, 264, 450, 184), + (10719, 1, 264, 120, 872), + (10720, 1, 264, 240, 872), + (10721, 1, 264, 360, 872), + (10722, 1, 264, 120, 778), + (10723, 1, 264, 240, 778), + (10724, 1, 264, 360, 778), + (10725, 1, 264, 480, 778), + (10726, 1, 264, 600, 778), + (10727, 1, 264, 120, 2235), + (10728, 1, 264, 240, 2235), + (10730, 1, 264, 10, 870), + (10731, 1, 264, 20, 870), + (10733, 1, 264, 1, 219), + (10734, 1, 264, 2, 219), + (10735, 1, 264, 3, 219), + (10743, 1, 220, 135, 7), + (10744, 1, 220, 170, 7), + (10745, 1, 220, 205, 7), + (10748, 1, 59, -35, 0), + (10749, 1, 59, -42, 0), + (10750, 1, 264, 3024, 286), + (10750, 2, 264, 3024, 10753), + (10750, 3, 264, 3024, 9101), + (10751, 1, 264, 3456, 286), + (10751, 2, 264, 3456, 10753), + (10751, 3, 264, 3456, 9101), + (10755, 1, 59, -50, 0), + (10763, 1, 292, 50, 0), + (10764, 1, 292, 60, 0), + (10766, 1, 330, 70, 7), + (10767, 1, 330, 75, 7), + (10768, 1, 330, 80, 7), + (10769, 1, 310, 1440000, 0), + (10769, 2, 139, 4519, 0), + (10770, 1, 310, 1680000, 0), + (10770, 2, 139, 4519, 0), + (10778, 1, 274, 38, 0), + (10779, 1, 274, 40, 0), + (10780, 1, 274, 42, 0), + (10781, 1, 1, 186, 0), + (10782, 1, 1, 217, 0), + (10783, 1, 1, 248, 0), + (10784, 1, 1, 279, 0), + (10785, 1, 1, 310, 0), + (10788, 1, 363, 4, 0), + (10792, 1, 287, 1, 0), + (10792, 2, 385, 5240, 0), + (10792, 3, 385, 5340, 0), + (10792, 4, 385, 5440, 0), + (10792, 5, 385, 5540, 0), + (10792, 6, 385, 5640, 0), + (10793, 1, 287, 2, 0), + (10793, 2, 385, 5240, 0), + (10793, 3, 385, 5340, 0), + (10793, 4, 385, 5440, 0), + (10793, 5, 385, 5540, 0), + (10793, 6, 385, 5640, 0), + (10794, 1, 287, 3, 0), + (10794, 2, 385, 5240, 0), + (10794, 3, 385, 5340, 0), + (10794, 4, 385, 5440, 0), + (10794, 5, 385, 5540, 0), + (10794, 6, 385, 5640, 0), + (10795, 1, 287, 4, 0), + (10795, 2, 385, 5240, 0), + (10795, 3, 385, 5340, 0), + (10795, 4, 385, 5440, 0), + (10795, 5, 385, 5540, 0), + (10795, 6, 385, 5640, 0), + (10796, 1, 287, 5, 0), + (10796, 2, 385, 5240, 0), + (10796, 3, 385, 5340, 0), + (10796, 4, 385, 5440, 0), + (10796, 5, 385, 5540, 0), + (10796, 6, 385, 5640, 0), + (10800, 1, 264, 60, 462), + (10801, 1, 264, 120, 462), + (10802, 1, 264, 180, 462), + (10803, 1, 293, 25, 0), + (10804, 1, 293, 50, 0), + (10805, 1, 293, 75, 0), + (10815, 1, 185, 2, 1), + (10815, 2, 185, 2, 3), + (10816, 1, 185, 4, 1), + (10816, 2, 185, 4, 3), + (10817, 1, 185, 6, 1), + (10817, 2, 185, 6, 3), + (10818, 1, 185, 1, 36), + (10819, 1, 185, 3, 36), + (10820, 1, 185, 5, 36), + (10821, 1, 185, 2, 0), + (10821, 2, 185, 2, 2), + (10822, 1, 185, 4, 0), + (10822, 2, 185, 4, 2), + (10823, 1, 185, 6, 0), + (10823, 2, 185, 6, 2), + (10850, 1, 288, 100, 8), + (10851, 1, 288, 100, 8), + (10852, 1, 288, 100, 8), + (10853, 1, 292, 5, 0), + (10854, 1, 292, 10, 0), + (10855, 1, 292, 15, 0), + (10856, 1, 292, 20, 0), + (10857, 1, 292, 25, 0), + (10858, 1, 292, 30, 0), + (10859, 1, 292, 35, 0), + (10860, 1, 292, 40, 0), + (10861, 1, 292, 45, 0), + (10862, 1, 292, 46, 0), + (10863, 1, 292, 47, 0), + (10864, 1, 292, 48, 0), + (10865, 1, 216, 500, 8), + (10866, 1, 216, 550, 8), + (10867, 1, 216, 650, 8), + (10903, 1, 281, 25, 0), + (10904, 1, 281, 50, 0), + (10905, 1, 281, 75, 0), + (10906, 1, 59, -48, 0), + (10907, 1, 59, -51, 0), + (10908, 1, 59, -54, 0), + (10909, 1, 264, 60, 7007), + (10910, 1, 264, 120, 7007), + (10911, 1, 264, 180, 7007), + (10915, 1, 339, 10, 16876), + (10915, 2, 138, 0, 0), + (10915, 3, 142, 70, 0), + (10915, 4, 411, 32, 0), + (10915, 5, 348, 1, 0), + (10915, 6, 141, 1, 0), + (10916, 1, 339, 10, 16877), + (10916, 2, 138, 0, 0), + (10916, 3, 142, 70, 0), + (10916, 4, 411, 32, 0), + (10916, 5, 348, 1, 0), + (10916, 6, 141, 1, 0), + (10917, 1, 339, 10, 16878), + (10917, 2, 138, 0, 0), + (10917, 3, 142, 70, 0), + (10917, 4, 411, 32, 0), + (10917, 5, 348, 1, 0), + (10917, 6, 141, 1, 0), + (10950, 1, 287, 1, 0), + (10950, 2, 403, 4, 0), + (10950, 3, 404, 38, 0), + (10950, 4, 348, 1, 0), + (10950, 5, 137, 11, 0), + (10950, 6, 140, 2, 0), + (10951, 1, 264, 60, 447), + (10952, 1, 264, 120, 447), + (10953, 1, 264, 180, 447), + (10954, 1, 264, 60, 662), + (10955, 1, 264, 120, 662), + (10956, 1, 264, 180, 662), + (11000, 1, 227, 1, 73), + (11001, 1, 227, 2, 73), + (11002, 1, 227, 3, 73), + (11003, 1, 287, 1, 0), + (11003, 2, 137, 158, 0), + (11003, 3, 411, 2, 0), + (11004, 1, 287, 1, 0), + (11004, 2, 139, 8000, 0), + (11005, 1, 287, 2, 0), + (11005, 2, 139, 8000, 0), + (11006, 1, 287, 3, 0), + (11006, 2, 139, 8000, 0), + (11011, 1, 264, 480, 3710), + (11012, 1, 264, 600, 3710), + (11013, 1, 264, 720, 3710), + (11014, 1, 264, 10, 3899), + (11014, 2, 264, 10, 611), + (11014, 3, 264, 10, 960), + (11014, 4, 264, 10, 1252), + (11015, 1, 264, 20, 3899), + (11015, 2, 264, 20, 611), + (11015, 3, 264, 20, 960), + (11015, 4, 264, 20, 1252), + (11016, 1, 264, 30, 3899), + (11016, 2, 264, 30, 611), + (11016, 3, 264, 30, 960), + (11016, 4, 264, 30, 1252), + (11020, 1, 264, 40, 3899), + (11020, 2, 264, 40, 611), + (11020, 3, 264, 40, 960), + (11020, 4, 264, 40, 1252), + (11050, 1, 264, 360, 452), + (11050, 2, 264, 360, 6106), + (11050, 3, 264, 360, 493), + (11051, 1, 264, 720, 452), + (11051, 2, 264, 720, 6106), + (11051, 3, 264, 720, 493), + (11052, 1, 264, 1080, 452), + (11052, 2, 264, 1080, 6106), + (11052, 3, 264, 1080, 493), + (11053, 1, 264, 1260, 500), + (11054, 1, 264, 1440, 500), + (11059, 1, 264, 1440, 452), + (11059, 2, 264, 1440, 6106), + (11059, 3, 264, 1440, 493), + (11060, 1, 264, 1800, 452), + (11060, 2, 264, 1800, 6106), + (11060, 3, 264, 1800, 493), + (11061, 1, 114, -63, 0), + (11062, 1, 114, -64, 0), + (11063, 1, 114, -65, 0), + (11074, 1, 247, 100, 39), + (11075, 1, 247, 150, 39), + (11076, 1, 247, 200, 39), + (11077, 1, 264, 10, 986), + (11078, 1, 264, 10, 988), + (11079, 1, 264, 10, 987), + (11082, 1, 185, 40, 51), + (11083, 1, 185, 50, 51), + (11084, 1, 185, 60, 51), + (11085, 1, 247, 20, 2), + (11085, 2, 247, 20, 3), + (11085, 3, 247, 20, 77), + (11085, 4, 220, 25, 77), + (11085, 5, 220, 25, 2), + (11085, 6, 220, 25, 3), + (11086, 1, 247, 40, 2), + (11086, 2, 247, 40, 3), + (11086, 3, 247, 40, 77), + (11086, 4, 220, 35, 77), + (11086, 5, 220, 35, 2), + (11086, 6, 220, 35, 3), + (11087, 1, 247, 60, 2), + (11087, 2, 247, 60, 3), + (11087, 3, 247, 60, 77), + (11087, 4, 220, 50, 77), + (11087, 5, 220, 50, 2), + (11087, 6, 220, 50, 3), + (11088, 1, 264, 180, 505), + (11089, 1, 264, 360, 505), + (11090, 1, 264, 540, 505), + (11091, 1, 264, 720, 505), + (12396, 1, 172, 50, 0), + (12397, 1, 172, 51, 0), + (12398, 1, 172, 52, 0), + (12399, 1, 172, 53, 0), + (12400, 1, 172, 54, 0), + (12401, 1, 259, 56, 0), + (12402, 1, 259, 57, 0), + (12403, 1, 259, 58, 0), + (12404, 1, 259, 59, 0), + (12405, 1, 259, 60, 0), + (12406, 1, 69, 1100, 0), + (12407, 1, 69, 1200, 0), + (12408, 1, 69, 1300, 0), + (12409, 1, 69, 1400, 0), + (12410, 1, 69, 1500, 0), + (12411, 1, 1, 300, 0), + (12412, 1, 1, 350, 0), + (12413, 1, 1, 400, 0), + (12414, 1, 1, 450, 0), + (12415, 1, 1, 500, 0), + (12416, 1, 399, 3, 0), + (12416, 2, 141, 1, 0), + (12416, 3, 138, 0, 0), + (12416, 4, 142, 255, 0), + (12416, 5, 391, 0, 0), + (12416, 6, 311, 0, 0), + (12416, 7, 137, -152, 0), + (12416, 8, 411, 100350, 0), + (12416, 9, 137, -39, 0), + (12417, 1, 399, 6, 0), + (12417, 2, 141, 1, 0), + (12417, 3, 138, 0, 0), + (12417, 4, 142, 255, 0), + (12417, 5, 391, 0, 0), + (12417, 6, 311, 0, 0), + (12417, 7, 137, -152, 0), + (12417, 8, 411, 100350, 0), + (12417, 9, 137, -39, 0), + (12418, 1, 399, 9, 0), + (12418, 2, 141, 1, 0), + (12418, 3, 138, 0, 0), + (12418, 4, 142, 255, 0), + (12418, 5, 391, 0, 0), + (12418, 6, 311, 0, 0), + (12418, 7, 137, -152, 0), + (12418, 8, 411, 100350, 0), + (12418, 9, 137, -39, 0), + (12419, 1, 292, 15, 0), + (12420, 1, 292, 30, 0), + (12421, 1, 292, 45, 0), + (12423, 1, 273, 21, 0), + (12424, 1, 273, 24, 0), + (12425, 1, 273, 27, 0), + (12426, 1, 273, 21, 0), + (12427, 1, 273, 24, 0), + (12428, 1, 273, 27, 0), + (12432, 1, 294, 17, 100), + (12433, 1, 294, 19, 100), + (12434, 1, 294, 21, 100), + (12435, 1, 294, 23, 100), + (12436, 1, 294, 25, 100), + (12437, 1, 294, 27, 100), + (12438, 1, 200, 70, 0), + (12439, 1, 341, 210, 0), + (12440, 1, 341, 220, 0), + (12441, 1, 341, 230, 0), + (12442, 1, 341, 240, 0), + (12443, 1, 341, 250, 0), + (12444, 1, 318, 21, 0), + (12445, 1, 318, 22, 0), + (12446, 1, 318, 23, 0), + (12447, 1, 318, 24, 0), + (12448, 1, 318, 25, 0), + (12449, 1, 125, 31, 31), + (12449, 2, 137, 0, 0), + (12449, 3, 141, 1, 0), + (12449, 4, 139, -6233, 0), + (12449, 5, 139, -6265, 0), + (12449, 6, 125, 31, 31), + (12449, 7, 137, 147, 0), + (12449, 8, 141, 1, 0), + (12450, 1, 125, 34, 34), + (12450, 2, 137, 0, 0), + (12450, 3, 141, 1, 0), + (12450, 4, 139, -6233, 0), + (12450, 5, 139, -6265, 0), + (12450, 6, 125, 34, 34), + (12450, 7, 137, 147, 0), + (12450, 8, 141, 1, 0), + (12451, 1, 125, 37, 37), + (12451, 2, 137, 0, 0), + (12451, 3, 141, 1, 0), + (12451, 4, 139, -6233, 0), + (12451, 5, 139, -6265, 0), + (12451, 6, 125, 37, 37), + (12451, 7, 137, 147, 0), + (12451, 8, 141, 1, 0), + (12452, 1, 274, 38, 0), + (12453, 1, 274, 39, 0), + (12454, 1, 274, 40, 0), + (12455, 1, 15, 19, 0), + (12456, 1, 15, 20, 0), + (12457, 1, 15, 21, 0), + (12458, 1, 15, 22, 0), + (12459, 1, 15, 23, 0), + (12463, 1, 320, 9, 0), + (12464, 1, 320, 10, 0), + (12465, 1, 320, 11, 0), + (12466, 1, 320, 9, 0), + (12467, 1, 320, 10, 0), + (12468, 1, 320, 11, 0), + (12469, 1, 320, 9, 0), + (12470, 1, 320, 10, 0), + (12471, 1, 320, 11, 0), + (12472, 1, 320, 6, 0), + (12473, 1, 320, 7, 0), + (12474, 1, 320, 8, 0), + (12475, 1, 264, 180, 7003), + (12476, 1, 264, 360, 7003), + (12477, 1, 264, 540, 7003), + (12478, 1, 264, 60, 3705), + (12479, 1, 264, 120, 3705), + (12480, 1, 264, 180, 3705), + (12481, 1, 247, 40, 76), + (12482, 1, 247, 45, 76), + (12483, 1, 247, 65, 76), + (12484, 1, 247, 70, 76), + (12485, 1, 247, 30, 76), + (12486, 1, 247, 35, 76), + (12487, 1, 247, 25, 76), + (12488, 1, 247, 30, 76), + (12492, 1, 69, 1600, 0), + (12493, 1, 69, 1700, 0), + (12494, 1, 69, 1800, 0), + (12495, 1, 69, 1900, 0), + (12496, 1, 69, 2000, 0), + (12497, 1, 125, 40, 40), + (12497, 2, 137, 0, 0), + (12497, 3, 141, 1, 0), + (12497, 4, 139, -6233, 0), + (12497, 5, 139, -6265, 0), + (12497, 6, 125, 40, 40), + (12497, 7, 137, 147, 0), + (12497, 8, 141, 1, 0), + (12498, 1, 125, 43, 43), + (12498, 2, 137, 0, 0), + (12498, 3, 141, 1, 0), + (12498, 4, 139, -6233, 0), + (12498, 5, 139, -6265, 0), + (12498, 6, 125, 43, 43), + (12498, 7, 137, 147, 0), + (12498, 8, 141, 1, 0), + (12499, 1, 125, 46, 46), + (12499, 2, 137, 0, 0), + (12499, 3, 141, 1, 0), + (12499, 4, 139, -6233, 0), + (12499, 5, 139, -6265, 0), + (12499, 6, 125, 46, 46), + (12499, 7, 137, 147, 0), + (12499, 8, 141, 1, 0), + (12500, 1, 310, 1000, 0), + (12500, 2, 385, 4004, 0), + (12500, 3, 385, 11202, 0), + (12500, 4, 385, 11302, 0), + (12500, 5, 385, 11402, 0), + (12500, 6, 385, 11502, 0), + (12500, 7, 385, 11602, 0), + (12501, 1, 310, 2000, 0), + (12501, 2, 385, 4004, 0), + (12501, 3, 385, 11202, 0), + (12501, 4, 385, 11302, 0), + (12501, 5, 385, 11402, 0), + (12501, 6, 385, 11502, 0), + (12501, 7, 385, 11602, 0), + (12502, 1, 310, 3000, 0), + (12502, 2, 385, 4004, 0), + (12502, 3, 385, 11202, 0), + (12502, 4, 385, 11302, 0), + (12502, 5, 385, 11402, 0), + (12502, 6, 385, 11502, 0), + (12502, 7, 385, 11602, 0), + (12505, 1, 310, 4000, 0), + (12505, 2, 385, 4004, 0), + (12505, 3, 385, 11202, 0), + (12505, 4, 385, 11302, 0), + (12505, 5, 385, 11402, 0), + (12505, 6, 385, 11502, 0), + (12505, 7, 385, 11602, 0), + (12506, 1, 310, 5000, 0), + (12506, 2, 385, 4004, 0), + (12506, 3, 385, 11202, 0), + (12506, 4, 385, 11302, 0), + (12506, 5, 385, 11402, 0), + (12506, 6, 385, 11502, 0), + (12506, 7, 385, 11602, 0), + (12507, 1, 301, 120, 0), + (12508, 1, 247, 50, 76), + (12509, 1, 247, 55, 76), + (12510, 1, 247, 60, 76), + (12511, 1, 247, 75, 76), + (12512, 1, 247, 80, 76), + (12513, 1, 247, 85, 76), + (12514, 1, 247, 40, 76), + (12515, 1, 247, 45, 76), + (12516, 1, 247, 50, 76), + (12517, 1, 247, 35, 76), + (12518, 1, 247, 40, 76), + (12519, 1, 247, 45, 76), + (12523, 1, 294, 0, 200), + (12526, 1, 294, 0, 190), + (12527, 1, 294, 0, 195), + (12528, 1, 294, 0, 200), + (12529, 1, 294, 0, 165), + (12530, 1, 294, 0, 175), + (12531, 1, 294, 0, 185), + (12532, 1, 341, 260, 0), + (12533, 1, 341, 270, 0), + (12534, 1, 341, 280, 0), + (12535, 1, 341, 290, 0), + (12536, 1, 341, 300, 0), + (12537, 1, 318, 26, 0), + (12538, 1, 318, 27, 0), + (12539, 1, 318, 28, 0), + (12540, 1, 318, 29, 0), + (12541, 1, 318, 30, 0), + (12548, 1, 278, 900, 79230), + (12548, 2, 440, 87, 100), + (12549, 1, 278, 900, 86260), + (12549, 2, 440, 88, 100), + (12550, 1, 278, 900, 88260), + (12550, 2, 440, 89, 100), + (12551, 1, 278, 900, 91510), + (12551, 2, 440, 90, 100), + (12552, 1, 278, 900, 96305), + (12552, 2, 440, 91, 100), + (12553, 1, 294, 29, 102), + (12554, 1, 294, 31, 104), + (12555, 1, 294, 33, 106), + (12556, 1, 294, 23, 100), + (12557, 1, 294, 25, 100), + (12558, 1, 294, 27, 100), + (12559, 1, 190, 300, 0), + (12560, 1, 190, 350, 0), + (12561, 1, 190, 400, 0), + (12562, 1, 190, 450, 0), + (12563, 1, 190, 500, 0), + (12564, 1, 319, 28, 0), + (12565, 1, 319, 29, 0), + (12566, 1, 319, 30, 0), + (12567, 1, 274, 41, 0), + (12568, 1, 274, 42, 0), + (12569, 1, 274, 43, 0), + (12570, 1, 15, 24, 0), + (12571, 1, 15, 25, 0), + (12572, 1, 15, 26, 0), + (12573, 1, 15, 27, 0), + (12574, 1, 15, 28, 0), + (12575, 1, 292, 60, 0), + (12576, 1, 231, 17, 0), + (12577, 1, 231, 19, 0), + (12578, 1, 231, 21, 0), + (12579, 1, 85, 23569, 0), + (12580, 1, 85, 23570, 0), + (12581, 1, 85, 23571, 0), + (12582, 1, 264, 10, 9400), + (12583, 1, 264, 20, 9400), + (12584, 1, 264, 30, 9400), + (12587, 1, 264, 480, 9403), + (12588, 1, 264, 600, 9403), + (12589, 1, 264, 720, 9403), + (12591, 1, 247, 90, 76), + (12594, 1, 247, 55, 76), + (12597, 1, 247, 50, 76), + (12598, 1, 247, 55, 76), + (12600, 1, 310, 60000, 0), + (12600, 2, 139, 6197, 0), + (12600, 3, 411, 512, 0), + (12603, 1, 287, 1, 0), + (12603, 2, 139, 6197, 0), + (12603, 3, 411, 512, 0), + (12606, 1, 271, 5, 0), + (12607, 1, 310, 12000, 0), + (12607, 2, 385, 13007, 0), + (12607, 3, 385, 12105, 0), + (12607, 4, 385, 12205, 0), + (12607, 5, 310, 36000, 0), + (12607, 6, 385, 12305, 0), + (12607, 7, 385, 12405, 0), + (12607, 8, 385, 12505, 0), + (12607, 9, 411, 512, 0), + (12610, 1, 279, 19, 0), + (12612, 1, 439, 0, 124480), + (12612, 2, 345, 84, 25), + (12613, 1, 439, 0, 132440), + (12613, 2, 345, 86, 25), + (12615, 1, 310, 120000, 0), + (12615, 2, 139, 4695, 0), + (12615, 3, 411, 512, 0), + (12616, 1, 310, 240000, 0), + (12616, 2, 139, 4695, 0), + (12616, 3, 411, 512, 0), + (12617, 1, 310, 360000, 0), + (12617, 2, 139, 4695, 0), + (12617, 3, 411, 512, 0), + (12636, 1, 426, 1, 0), + (12637, 1, 426, 2, 0), + (12639, 1, 264, 240, 519), + (12639, 2, 264, 240, 10427), + (12642, 1, 264, 240, 185), + (12642, 2, 264, 240, 10426), + (12645, 1, 287, 1, 0), + (12645, 2, 385, 8190, 0), + (12645, 3, 287, 1, 0), + (12645, 4, 385, 21818, 0), + (12645, 5, 411, 64, 0), + (12646, 1, 287, 1, 0), + (12646, 2, 385, 3277, 0), + (12646, 3, 287, 1, 0), + (12646, 4, 385, 21816, 0), + (12652, 1, 399, 1, 0), + (12652, 2, 138, 1, 0), + (12652, 3, 137, 0, 0), + (12652, 4, 348, 10, 0), + (12652, 5, 311, 0, 0), + (12652, 6, 141, 1, 0), + (12652, 7, 134, 254, 0), + (12652, 8, 137, -39, 0), + (12653, 1, 399, 2, 0), + (12653, 2, 138, 1, 0), + (12653, 3, 137, 0, 0), + (12653, 4, 348, 10, 0), + (12653, 5, 311, 0, 0), + (12653, 6, 141, 1, 0), + (12653, 7, 134, 254, 0), + (12653, 8, 137, -39, 0), + (12654, 1, 399, 3, 0), + (12654, 2, 138, 1, 0), + (12654, 3, 137, 0, 0), + (12654, 4, 348, 10, 0), + (12654, 5, 311, 0, 0), + (12654, 6, 141, 1, 0), + (12654, 7, 134, 254, 0), + (12654, 8, 137, -39, 0), + (12664, 1, 264, 2, 3728), + (12667, 1, 220, 250, 26), + (12667, 2, 220, 250, 30), + (12667, 3, 220, 250, 38), + (12668, 1, 220, 275, 26), + (12668, 2, 220, 275, 30), + (12668, 3, 220, 275, 38), + (12669, 1, 220, 300, 26), + (12669, 2, 220, 300, 30), + (12669, 3, 220, 300, 38), + (12670, 1, 220, 200, 21), + (12670, 2, 220, 200, 23), + (12670, 3, 220, 400, 52), + (12670, 4, 220, 200, 28), + (12671, 1, 220, 215, 21), + (12671, 2, 220, 215, 23), + (12671, 3, 220, 450, 52), + (12671, 4, 220, 215, 28), + (12672, 1, 220, 235, 21), + (12672, 2, 220, 235, 23), + (12672, 3, 220, 510, 52), + (12672, 4, 220, 235, 28), + (12673, 1, 264, 960, 420), + (12674, 1, 227, 270, 32), + (12675, 1, 227, 300, 32), + (12676, 1, 227, 330, 32), + (12677, 1, 275, 92, 0), + (12678, 1, 287, 2, 0), + (12678, 2, 385, 15002, 0), + (12678, 3, 385, 15003, 0), + (12678, 4, 411, 128, 0), + (12679, 1, 264, 1200, 276), + (12680, 1, 264, 1500, 276), + (12681, 1, 264, 1800, 276), + (12685, 1, 292, 49, 0), + (12686, 1, 292, 50, 0), + (12687, 1, 292, 51, 0), + (12688, 1, 287, 1, 0), + (12688, 2, 385, 8473, 0), + (12688, 3, 385, 8318, 0), + (12688, 4, 385, 8418, 0), + (12688, 5, 385, 8518, 0), + (12688, 6, 411, 128, 0), + (12689, 1, 287, 2, 0), + (12689, 2, 139, 4691, 0), + (12689, 3, 411, 128, 0), + (12690, 1, 287, 2, 0), + (12690, 2, 385, 8111, 0), + (12690, 3, 385, 15008, 0), + (12690, 4, 385, 8411, 0), + (12690, 5, 385, 8511, 0), + (12690, 6, 411, 128, 0), + (12691, 1, 287, 1, 0), + (12691, 2, 385, 15007, 0), + (12691, 3, 411, 128, 0), + (12691, 4, 385, 8316, 0), + (12692, 1, 220, 255, 21), + (12692, 2, 220, 255, 23), + (12692, 3, 220, 570, 52), + (12692, 4, 220, 255, 28), + (12693, 1, 220, 275, 21), + (12693, 2, 220, 275, 23), + (12693, 3, 220, 630, 52), + (12693, 4, 220, 275, 28), + (12694, 1, 189, 16, 0), + (12695, 1, 189, 17, 0), + (12696, 1, 189, 18, 0), + (12697, 1, 330, 140, 0), + (12697, 2, 330, 140, 1), + (12697, 3, 330, 140, 2), + (12697, 4, 330, 140, 3), + (12697, 5, 330, 140, 28), + (12697, 6, 330, 140, 36), + (12697, 7, 330, 140, 77), + (12698, 1, 330, 145, 0), + (12698, 2, 330, 145, 1), + (12698, 3, 330, 145, 2), + (12698, 4, 330, 145, 3), + (12698, 5, 330, 145, 28), + (12698, 6, 330, 145, 36), + (12698, 7, 330, 145, 77), + (12699, 1, 330, 150, 0), + (12699, 2, 330, 150, 1), + (12699, 3, 330, 150, 2), + (12699, 4, 330, 150, 3), + (12699, 5, 330, 150, 28), + (12699, 6, 330, 150, 36), + (12699, 7, 330, 150, 77), + (12703, 1, 283, 240, 0), + (12704, 1, 283, 260, 0), + (12705, 1, 283, 280, 0), + (12706, 1, 220, 60, 28), + (12706, 2, 220, 60, 0), + (12706, 3, 427, 23598, 3), + (12706, 4, 428, 28, 0), + (12706, 5, 428, 0, 0), + (12707, 1, 220, 85, 28), + (12707, 2, 220, 85, 0), + (12707, 3, 427, 23598, 5), + (12707, 4, 428, 28, 0), + (12707, 5, 428, 0, 0), + (12708, 1, 220, 115, 28), + (12708, 2, 220, 115, 0), + (12708, 3, 427, 23598, 7), + (12708, 4, 428, 28, 0), + (12708, 5, 428, 0, 0), + (12709, 1, 287, 1, 0), + (12709, 2, 139, 4516, 0), + (12709, 3, 411, 256, 0), + (12710, 1, 310, 360000, 0), + (12710, 2, 139, 4516, 0), + (12710, 3, 411, 256, 0), + (12711, 1, 310, 720000, 0), + (12711, 2, 139, 4516, 0), + (12711, 3, 411, 256, 0), + (12712, 1, 310, 1080000, 0), + (12712, 2, 139, 4516, 0), + (12712, 3, 411, 256, 0), + (12713, 1, 264, 2, 8202), + (12714, 1, 264, 4, 8202), + (12715, 1, 264, 6, 8202), + (12716, 1, 264, 30, 3702), + (12717, 1, 264, 60, 3702), + (12718, 1, 264, 90, 3702), + (12719, 1, 128, 10, 0), + (12719, 2, 385, 12769, 0), + (12719, 3, 411, 256, 0), + (12720, 1, 287, 1, 0), + (12720, 2, 139, 12519, 0), + (12720, 3, 411, 256, 0), + (12721, 1, 264, 60, 3506), + (12722, 1, 264, 120, 3506), + (12723, 1, 264, 180, 3506), + (12727, 1, 264, 960, 359), + (12728, 1, 264, 1200, 359), + (12729, 1, 264, 1440, 359), + (12733, 1, 287, 2, 0), + (12733, 2, 137, 22, 0), + (12733, 3, 411, 256, 0), + (12734, 1, 375, 145, 0), + (12735, 1, 375, 150, 0), + (12736, 1, 375, 155, 0), + (12737, 1, 129, 5, 0), + (12737, 2, 385, 12768, 0), + (12737, 3, 411, 256, 0), + (12738, 1, 129, 10, 0), + (12738, 2, 385, 12768, 0), + (12738, 3, 411, 256, 0), + (12739, 1, 129, 15, 0), + (12739, 2, 385, 12768, 0), + (12739, 3, 411, 256, 0), + (12757, 1, 264, 6000, 68), + (12758, 1, 264, 6600, 68), + (12759, 1, 264, 7200, 68), + (12767, 1, 229, 50, 0), + (12768, 1, 229, 55, 0), + (12769, 1, 229, 60, 0), + (12773, 1, 264, 60, 1580), + (12774, 1, 264, 120, 1580), + (12775, 1, 264, 180, 1580), + (12776, 1, 264, 240, 1580), + (12777, 1, 264, 300, 1580), + (12779, 1, 264, 0, 826), + (12780, 1, 264, 1, 826), + (12781, 1, 264, 1, 826), + (12782, 1, 129, 10, 0), + (12782, 2, 385, 16106, 0), + (12783, 1, 129, 20, 0), + (12783, 2, 385, 16106, 0), + (12784, 1, 129, 30, 0), + (12784, 2, 385, 16106, 0), + (12792, 1, 397, 1000, 0), + (12793, 1, 397, 1200, 0), + (12794, 1, 397, 1250, 0), + (12795, 1, 213, 19, 0), + (12796, 1, 213, 21, 0), + (12797, 1, 213, 23, 0), + (12798, 1, 218, 21, 0), + (12799, 1, 218, 22, 0), + (12800, 1, 218, 23, 0), + (12801, 1, 215, 18, 0), + (12802, 1, 215, 20, 0), + (12803, 1, 215, 22, 0), + (12813, 1, 320, 2, 0), + (12814, 1, 320, 4, 0), + (12815, 1, 320, 6, 0), + (12816, 1, 128, 1, 0), + (12816, 2, 385, 2223, 0), + (12816, 3, 385, 2323, 0), + (12816, 4, 385, 2240, 0), + (12816, 5, 385, 2340, 0), + (12816, 6, 385, 2440, 0), + (12816, 7, 385, 2540, 0), + (12816, 8, 398, 6000, 0), + (12816, 9, 385, 11872, 0), + (12816, 10, 385, 14154, 0), + (12816, 11, 385, 18166, 0), + (12816, 12, 385, 27225, 0), + (12816, 13, 385, 2419, 0), + (12816, 14, 385, 2427, 0), + (12816, 15, 385, 30374, 0), + (12816, 16, 385, 2527, 0), + (12816, 17, 385, 36431, 0), + (12819, 1, 310, 23400, 0), + (12819, 2, 139, 4671, 0), + (12819, 3, 411, 32768, 0), + (12820, 1, 310, 46800, 0), + (12820, 2, 139, 4671, 0), + (12820, 3, 411, 32768, 0), + (12822, 1, 310, 153000, 0), + (12822, 2, 139, 8233, 0), + (12822, 3, 310, 120000, 0), + (12822, 4, 385, 2439, 0), + (12822, 5, 385, 2539, 0), + (12822, 6, 411, 32768, 0), + (12831, 1, 127, 17, 0), + (12831, 2, 385, 3291, 0), + (12831, 3, 385, 3817, 0), + (12831, 4, 411, 32768, 0), + (12834, 1, 264, 180, 128), + (12835, 1, 264, 225, 128), + (12840, 1, 264, 24, 3817), + (12841, 1, 264, 30, 3817), + (12843, 1, 225, 42, 0), + (12846, 1, 288, 20, 28), + (12846, 2, 288, 20, 0), + (12849, 1, 127, 14, 0), + (12849, 2, 385, 16794, 0), + (12849, 3, 411, 32768, 0), + (12860, 1, 294, 21, 102), + (12863, 1, 127, 15, 15), + (12863, 2, 137, 0, 0), + (12863, 3, 138, 0, 0), + (12863, 4, 141, 1, 0), + (12863, 5, 143, 3000, 0), + (12863, 6, 127, 15, 15), + (12863, 7, 385, 16555, 0), + (12863, 8, 385, 16655, 0), + (12871, 1, 264, 2160, 452), + (12871, 2, 264, 2160, 6106), + (12871, 3, 264, 2160, 493), + (12872, 1, 264, 2520, 452), + (12872, 2, 264, 2520, 6106), + (12872, 3, 264, 2520, 493), + (12874, 1, 264, 2572, 451), + (12876, 1, 264, 900, 7003), + (12877, 1, 264, 1260, 7003), + (12878, 1, 264, 1620, 7003), + (12881, 1, 264, 45, 172), + (12886, 1, 10, 0, 0), + (12887, 1, 10, 0, 0), + (12888, 1, 10, 0, 0), + (12889, 1, 10, 0, 0), + (12890, 1, 10, 0, 0), + (12894, 1, 264, 30, 1122), + (12899, 1, 264, 3456, 57), + (12899, 2, 264, 3456, 616), + (12900, 1, 264, 4320, 57), + (12900, 2, 264, 4320, 616), + (12902, 1, 264, 30, 1380), + (12903, 1, 264, 60, 1380), + (12907, 1, 264, 30, 1381), + (12908, 1, 264, 60, 1381), + (12912, 1, 264, 30, 1382), + (12913, 1, 264, 60, 1382), + (12920, 1, 130, 10, 10), + (12920, 2, 139, 2569, 0), + (12920, 3, 130, -10, -10), + (12920, 4, 139, 2568, 0), + (12929, 1, 287, 4, 0), + (12929, 2, 137, 3, 0), + (12929, 3, 137, 99, 0), + (12929, 4, 138, 0, 0), + (12929, 5, 244, 20, 0), + (12930, 1, 287, 5, 0), + (12930, 2, 137, 3, 0), + (12930, 3, 137, 99, 0), + (12930, 4, 138, 0, 0), + (12930, 5, 244, 15, 0), + (12945, 1, 280, 60, 0), + (12946, 1, 280, 61, 0), + (12947, 1, 280, 62, 0), + (12948, 1, 280, 63, 0), + (12949, 1, 280, 64, 0), + (12950, 1, 218, 21, 0), + (12951, 1, 218, 22, 0), + (12952, 1, 218, 23, 0), + (12953, 1, 218, 24, 0), + (12954, 1, 218, 25, 0), + (12966, 1, 131, 25, 25), + (12966, 2, 348, 10, 0), + (12966, 3, 137, -32, 0), + (12967, 1, 131, 50, 50), + (12967, 2, 348, 10, 0), + (12967, 3, 137, -32, 0), + (12968, 1, 264, 3, 1041), + (12969, 1, 264, 6, 1041), + (12970, 1, 264, 9, 1041), + (12977, 1, 287, 2, 0), + (12977, 2, 385, 16188, 0), + (12978, 1, 287, 4, 0), + (12978, 2, 385, 16188, 0), + (12979, 1, 287, 6, 0), + (12979, 2, 385, 16188, 0), + (12980, 1, 287, 8, 0), + (12980, 2, 385, 16188, 0), + (12981, 1, 287, 10, 0), + (12981, 2, 385, 16188, 0), + (12988, 1, 287, 3, 0), + (12988, 2, 140, 3, 0), + (12988, 3, 348, 1, 0), + (12988, 4, 138, 0, 0), + (12988, 5, 137, 0, 0), + (13001, 1, 264, 60, 9504), + (13002, 1, 264, 120, 9504), + (13003, 1, 264, 180, 9504), + (13005, 1, 264, 70, 171), + (13006, 1, 264, 80, 171), + (13007, 1, 264, 90, 171), + (13010, 1, 264, 10, 47), + (13011, 1, 264, 20, 47), + (13012, 1, 264, 30, 47), + (13013, 1, 264, 120, 446), + (13014, 1, 264, 240, 446), + (13015, 1, 264, 360, 446), + (13017, 1, 375, 15, 0), + (13018, 1, 375, 25, 0), + (13019, 1, 375, 35, 0), + (13021, 1, 247, 80, 2), + (13021, 2, 247, 80, 3), + (13021, 3, 247, 80, 77), + (13021, 4, 220, 75, 77), + (13021, 5, 220, 75, 2), + (13021, 6, 220, 75, 3), + (13023, 1, 330, 115, 0), + (13023, 2, 330, 115, 1), + (13023, 3, 330, 115, 2), + (13023, 4, 330, 115, 3), + (13023, 5, 330, 115, 28), + (13023, 6, 330, 115, 36), + (13023, 7, 330, 115, 77), + (13026, 1, 266, 26, 0), + (13027, 1, 266, 27, 0), + (13028, 1, 266, 28, 0), + (13029, 1, 288, 250, 51), + (13029, 2, 288, 60, 51), + (13032, 1, 185, 70, 51), + (13033, 1, 185, 80, 51), + (13035, 1, 220, 768, 74), + (13040, 1, 216, 280, 74), + (13043, 1, 169, 35, -1), + (13046, 1, 1, 240, 0), + (13047, 1, 1, 280, 0), + (13048, 1, 1, 320, 0), + (13049, 1, 1, 360, 0), + (13050, 1, 1, 400, 0), + (13051, 1, 287, 2, 0), + (13051, 2, 139, 8003, 0), + (13052, 1, 310, 120000, 0), + (13052, 2, 385, 3107, 0), + (13052, 3, 385, 3207, 0), + (13052, 4, 385, 3307, 0), + (13052, 5, 385, 3407, 0), + (13052, 6, 385, 3507, 0), + (13052, 7, 385, 3607, 0), + (13055, 1, 264, 60, 8400), + (13067, 1, 264, 120, 643), + (13072, 1, 310, 120000, 0), + (13072, 2, 139, 6197, 0), + (13072, 3, 411, 512, 0), + (13073, 1, 310, 180000, 0), + (13073, 2, 139, 6197, 0), + (13073, 3, 411, 512, 0), + (13074, 1, 330, 140, 0), + (13074, 2, 330, 140, 1), + (13074, 3, 330, 140, 2), + (13074, 4, 330, 140, 3), + (13074, 5, 330, 140, 28), + (13074, 6, 330, 140, 36), + (13075, 1, 330, 145, 0), + (13075, 2, 330, 145, 1), + (13075, 3, 330, 145, 2), + (13075, 4, 330, 145, 3), + (13075, 5, 330, 145, 28), + (13075, 6, 330, 145, 36), + (13076, 1, 330, 150, 0), + (13076, 2, 330, 150, 1), + (13076, 3, 330, 150, 2), + (13076, 4, 330, 150, 3), + (13076, 5, 330, 150, 28), + (13076, 6, 330, 150, 36), + (13077, 1, 330, 140, 0), + (13077, 2, 330, 140, 1), + (13077, 3, 330, 140, 2), + (13077, 4, 330, 140, 3), + (13077, 5, 330, 140, 28), + (13077, 6, 330, 140, 36), + (13077, 7, 330, 140, 77), + (13078, 1, 330, 145, 0), + (13078, 2, 330, 145, 1), + (13078, 3, 330, 145, 2), + (13078, 4, 330, 145, 3), + (13078, 5, 330, 145, 28), + (13078, 6, 330, 145, 36), + (13078, 7, 330, 145, 77), + (13080, 1, 172, 55, 0), + (13081, 1, 172, 56, 0), + (13082, 1, 172, 57, 0), + (13083, 1, 172, 58, 0), + (13084, 1, 172, 59, 0), + (13085, 1, 259, 61, 0), + (13086, 1, 259, 62, 0), + (13087, 1, 259, 63, 0), + (13088, 1, 259, 64, 0), + (13089, 1, 259, 65, 0), + (13090, 1, 339, 10, 8105), + (13090, 2, 142, 65, 0), + (13090, 3, 311, 0, 0), + (13090, 4, 134, 70, 0), + (13090, 5, 348, 10, 0), + (13090, 6, 137, 0, 0), + (13090, 7, 339, 10, 8105), + (13090, 8, 142, 65, 0), + (13090, 9, 311, 0, 0), + (13090, 10, 134, 70, 0), + (13090, 11, 348, 10, 0), + (13090, 12, 137, 100, 0), + (13090, 13, 339, 10, 8105), + (13090, 14, 142, 65, 0), + (13090, 15, 311, 0, 0), + (13090, 16, 134, 70, 0), + (13090, 17, 348, 10, 0), + (13090, 18, 137, 79, 0), + (13090, 19, 339, 10, 8105), + (13090, 20, 142, 65, 0), + (13090, 21, 311, 0, 0), + (13090, 22, 134, 70, 0), + (13090, 23, 348, 10, 0), + (13090, 24, 137, 147, 0), + (13090, 25, 339, 10, 11404), + (13090, 26, 142, 71, 0), + (13090, 27, 311, 0, 0), + (13090, 28, 134, 75, 0), + (13090, 29, 348, 10, 0), + (13090, 30, 137, 0, 0), + (13090, 31, 339, 10, 11404), + (13090, 32, 142, 71, 0), + (13090, 33, 311, 0, 0), + (13090, 34, 134, 75, 0), + (13090, 35, 348, 10, 0), + (13090, 36, 137, 100, 0), + (13090, 37, 339, 10, 11404), + (13090, 38, 142, 71, 0), + (13090, 39, 311, 0, 0), + (13090, 40, 134, 75, 0), + (13090, 41, 348, 10, 0), + (13090, 42, 137, 79, 0), + (13090, 43, 339, 10, 11404), + (13090, 44, 142, 71, 0), + (13090, 45, 311, 0, 0), + (13090, 46, 134, 75, 0), + (13090, 47, 348, 10, 0), + (13090, 48, 137, 147, 0), + (13090, 49, 339, 10, 13199), + (13090, 50, 142, 76, 0), + (13090, 51, 311, 0, 0), + (13090, 52, 134, 80, 0), + (13090, 53, 348, 10, 0), + (13090, 54, 137, 0, 0), + (13090, 55, 339, 10, 13199), + (13090, 56, 142, 76, 0), + (13090, 57, 311, 0, 0), + (13090, 58, 134, 80, 0), + (13090, 59, 348, 10, 0), + (13090, 60, 137, 100, 0), + (13090, 61, 339, 10, 13199), + (13090, 62, 142, 76, 0), + (13090, 63, 311, 0, 0), + (13090, 64, 134, 80, 0), + (13090, 65, 348, 10, 0), + (13090, 66, 137, 79, 0), + (13090, 67, 339, 10, 13199), + (13090, 68, 142, 76, 0), + (13090, 69, 311, 0, 0), + (13090, 70, 134, 80, 0), + (13090, 71, 348, 10, 0), + (13090, 72, 137, 147, 0), + (13090, 73, 339, 10, 13830), + (13090, 74, 142, 81, 0), + (13090, 75, 311, 0, 0), + (13090, 76, 134, 85, 0), + (13090, 77, 348, 10, 0), + (13090, 78, 137, 0, 0), + (13090, 79, 339, 10, 13830), + (13090, 80, 142, 81, 0), + (13090, 81, 311, 0, 0), + (13090, 82, 134, 85, 0), + (13090, 83, 348, 10, 0), + (13090, 84, 137, 100, 0), + (13090, 85, 339, 10, 13830), + (13090, 86, 142, 81, 0), + (13090, 87, 311, 0, 0), + (13090, 88, 134, 85, 0), + (13090, 89, 348, 10, 0), + (13090, 90, 137, 79, 0), + (13090, 91, 339, 10, 13830), + (13090, 92, 142, 81, 0), + (13090, 93, 311, 0, 0), + (13090, 94, 134, 85, 0), + (13090, 95, 348, 10, 0), + (13090, 96, 137, 147, 0), + (13090, 97, 339, 10, 27527), + (13090, 98, 142, 86, 0), + (13090, 99, 311, 0, 0), + (13090, 100, 134, 90, 0), + (13090, 101, 348, 10, 0), + (13090, 102, 137, 0, 0), + (13090, 103, 339, 10, 27527), + (13090, 104, 142, 86, 0), + (13090, 105, 311, 0, 0), + (13090, 106, 134, 90, 0), + (13090, 107, 348, 10, 0), + (13090, 108, 137, 100, 0), + (13090, 109, 339, 10, 27527), + (13090, 110, 142, 86, 0), + (13090, 111, 311, 0, 0), + (13090, 112, 134, 90, 0), + (13090, 113, 348, 10, 0), + (13090, 114, 137, 79, 0), + (13090, 115, 339, 10, 27527), + (13090, 116, 142, 86, 0), + (13090, 117, 311, 0, 0), + (13090, 118, 134, 90, 0), + (13090, 119, 348, 10, 0), + (13090, 120, 137, 147, 0), + (13091, 1, 339, 10, 8105), + (13091, 2, 142, 65, 0), + (13091, 3, 311, 0, 0), + (13091, 4, 134, 70, 0), + (13091, 5, 348, 10, 0), + (13091, 6, 137, 0, 0), + (13091, 7, 339, 10, 8105), + (13091, 8, 142, 65, 0), + (13091, 9, 311, 0, 0), + (13091, 10, 134, 70, 0), + (13091, 11, 348, 10, 0), + (13091, 12, 137, 100, 0), + (13091, 13, 339, 10, 8105), + (13091, 14, 142, 65, 0), + (13091, 15, 311, 0, 0), + (13091, 16, 134, 70, 0), + (13091, 17, 348, 10, 0), + (13091, 18, 137, 79, 0), + (13091, 19, 339, 10, 8105), + (13091, 20, 142, 65, 0), + (13091, 21, 311, 0, 0), + (13091, 22, 134, 70, 0), + (13091, 23, 348, 10, 0), + (13091, 24, 137, 147, 0), + (13091, 25, 339, 10, 11404), + (13091, 26, 142, 71, 0), + (13091, 27, 311, 0, 0), + (13091, 28, 134, 75, 0), + (13091, 29, 348, 10, 0), + (13091, 30, 137, 0, 0), + (13091, 31, 339, 10, 11404), + (13091, 32, 142, 71, 0), + (13091, 33, 311, 0, 0), + (13091, 34, 134, 75, 0), + (13091, 35, 348, 10, 0), + (13091, 36, 137, 100, 0), + (13091, 37, 339, 10, 11404), + (13091, 38, 142, 71, 0), + (13091, 39, 311, 0, 0), + (13091, 40, 134, 75, 0), + (13091, 41, 348, 10, 0), + (13091, 42, 137, 79, 0), + (13091, 43, 339, 10, 11404), + (13091, 44, 142, 71, 0), + (13091, 45, 311, 0, 0), + (13091, 46, 134, 75, 0), + (13091, 47, 348, 10, 0), + (13091, 48, 137, 147, 0), + (13091, 49, 339, 10, 13199), + (13091, 50, 142, 76, 0), + (13091, 51, 311, 0, 0), + (13091, 52, 134, 80, 0), + (13091, 53, 348, 10, 0), + (13091, 54, 137, 0, 0), + (13091, 55, 339, 10, 13199), + (13091, 56, 142, 76, 0), + (13091, 57, 311, 0, 0), + (13091, 58, 134, 80, 0), + (13091, 59, 348, 10, 0), + (13091, 60, 137, 100, 0), + (13091, 61, 339, 10, 13199), + (13091, 62, 142, 76, 0), + (13091, 63, 311, 0, 0), + (13091, 64, 134, 80, 0), + (13091, 65, 348, 10, 0), + (13091, 66, 137, 79, 0), + (13091, 67, 339, 10, 13199), + (13091, 68, 142, 76, 0), + (13091, 69, 311, 0, 0), + (13091, 70, 134, 80, 0), + (13091, 71, 348, 10, 0), + (13091, 72, 137, 147, 0), + (13091, 73, 339, 10, 13830), + (13091, 74, 142, 81, 0), + (13091, 75, 311, 0, 0), + (13091, 76, 134, 85, 0), + (13091, 77, 348, 10, 0), + (13091, 78, 137, 0, 0), + (13091, 79, 339, 10, 13830), + (13091, 80, 142, 81, 0), + (13091, 81, 311, 0, 0), + (13091, 82, 134, 85, 0), + (13091, 83, 348, 10, 0), + (13091, 84, 137, 100, 0), + (13091, 85, 339, 10, 13830), + (13091, 86, 142, 81, 0), + (13091, 87, 311, 0, 0), + (13091, 88, 134, 85, 0), + (13091, 89, 348, 10, 0), + (13091, 90, 137, 79, 0), + (13091, 91, 339, 10, 13830), + (13091, 92, 142, 81, 0), + (13091, 93, 311, 0, 0), + (13091, 94, 134, 85, 0), + (13091, 95, 348, 10, 0), + (13091, 96, 137, 147, 0), + (13091, 97, 339, 10, 27527), + (13091, 98, 142, 86, 0), + (13091, 99, 311, 0, 0), + (13091, 100, 134, 90, 0), + (13091, 101, 348, 10, 0), + (13091, 102, 137, 0, 0), + (13091, 103, 339, 10, 27527), + (13091, 104, 142, 86, 0), + (13091, 105, 311, 0, 0), + (13091, 106, 134, 90, 0), + (13091, 107, 348, 10, 0), + (13091, 108, 137, 100, 0), + (13091, 109, 339, 10, 27527), + (13091, 110, 142, 86, 0), + (13091, 111, 311, 0, 0), + (13091, 112, 134, 90, 0), + (13091, 113, 348, 10, 0), + (13091, 114, 137, 79, 0), + (13091, 115, 339, 10, 27527), + (13091, 116, 142, 86, 0), + (13091, 117, 311, 0, 0), + (13091, 118, 134, 90, 0), + (13091, 119, 348, 10, 0), + (13091, 120, 137, 147, 0), + (13092, 1, 217, 0, 102280), + (13092, 2, 346, 84, 18), + (13093, 1, 217, 0, 109400), + (13093, 2, 346, 86, 18), + (13094, 1, 217, 0, 116800), + (13094, 2, 346, 88, 18), + (13095, 1, 439, 0, 140680), + (13095, 2, 345, 88, 25), + (13096, 1, 287, 1, 0), + (13096, 2, 140, 3, 0), + (13096, 3, 348, 1, 0), + (13096, 4, 138, 0, 0), + (13096, 5, 137, 0, 0), + (13097, 1, 287, 2, 0), + (13097, 2, 140, 3, 0), + (13097, 3, 348, 1, 0), + (13097, 4, 138, 0, 0), + (13097, 5, 137, 0, 0), + (13098, 1, 287, 3, 0), + (13098, 2, 140, 3, 0), + (13098, 3, 348, 1, 0), + (13098, 4, 138, 0, 0), + (13098, 5, 137, 0, 0), + (13099, 1, 132, 15, 15), + (13101, 1, 360, 25, 27537), + (13102, 1, 360, 25, 27538), + (13103, 1, 360, 25, 27539), + (13104, 1, 303, 14000, 18000), + (13104, 2, 139, 2766, 0), + (13105, 1, 303, 18000, 22500), + (13105, 2, 139, 2766, 0), + (13106, 1, 303, 22500, 27500), + (13106, 2, 139, 2766, 0), + (13110, 1, 185, 8, 1), + (13110, 2, 185, 8, 3), + (13111, 1, 185, 10, 1), + (13111, 2, 185, 10, 3), + (13113, 1, 185, 7, 36), + (13114, 1, 185, 9, 36), + (13116, 1, 185, 8, 0), + (13116, 2, 185, 8, 2), + (13117, 1, 185, 10, 0), + (13117, 2, 185, 10, 2), + (13122, 1, 2, 128, 0), + (13123, 1, 2, 132, 0), + (13124, 1, 2, 136, 0), + (13127, 1, 287, 4, 0), + (13127, 2, 140, 3, 0), + (13127, 3, 348, 1, 0), + (13127, 4, 138, 0, 0), + (13127, 5, 137, 0, 0), + (13130, 1, 264, 1440, 7003), + (13140, 1, 264, 480, 391), + (13141, 1, 264, 600, 391), + (13142, 1, 264, 720, 391), + (13143, 1, 127, 17, 0), + (13143, 2, 385, 8054, 0), + (13144, 1, 127, 34, 0), + (13144, 2, 385, 8054, 0), + (13145, 1, 127, 50, 0), + (13145, 2, 385, 8054, 0), + (13146, 1, 127, 17, 0), + (13146, 2, 385, 8054, 0), + (13147, 1, 127, 34, 0), + (13147, 2, 385, 8054, 0), + (13148, 1, 127, 50, 0), + (13148, 2, 385, 8054, 0), + (13149, 1, 97, 550, 0), + (13150, 1, 97, 600, 0), + (13151, 1, 97, 650, 0), + (13152, 1, 97, 700, 0), + (13153, 1, 97, 750, 0), + (13166, 1, 264, 5, 749), + (13166, 2, 264, 5, 822), + (13166, 3, 264, 5, 1274), + (13166, 4, 264, 5, 1275), + (13167, 1, 264, 10, 749), + (13167, 2, 264, 10, 822), + (13167, 3, 264, 10, 1274), + (13167, 4, 264, 10, 1275), + (13168, 1, 264, 15, 749), + (13168, 2, 264, 15, 822), + (13168, 3, 264, 15, 1274), + (13168, 4, 264, 15, 1275), + (13184, 1, 220, 315, 26), + (13185, 1, 220, 400, 26), + (13186, 1, 220, 500, 26), + (13187, 1, 405, 19, 0), + (13188, 1, 405, 21, 0), + (13189, 1, 405, 23, 0), + (13196, 1, 279, 31, 0), + (13197, 1, 279, 35, 0), + (13198, 1, 279, 39, 0), + (13199, 1, 378, 30, 31), + (13200, 1, 378, 35, 31), + (13201, 1, 378, 40, 31), + (13204, 1, 264, 180, 8261), + (13205, 1, 264, 360, 8261), + (13206, 1, 264, 540, 8261), + (13207, 1, 288, 100, 8), + (13208, 1, 288, 100, 8), + (13209, 1, 288, 100, 8), + (13210, 1, 325, 70, 0), + (13211, 1, 325, 75, 0), + (13212, 1, 325, 80, 0), + (13213, 1, 220, 285, 8), + (13214, 1, 220, 315, 8), + (13215, 1, 220, 350, 8), + (13216, 1, 220, 390, 8), + (13217, 1, 220, 440, 8), + (13218, 1, 216, 750, 8), + (13219, 1, 114, -12, 0), + (13220, 1, 114, -15, 0), + (13221, 1, 114, -18, 0), + (13222, 1, 310, 240000, 0), + (13222, 2, 139, 6197, 0), + (13222, 3, 411, 512, 0), + (13223, 1, 310, 300000, 0), + (13223, 2, 139, 6197, 0), + (13223, 3, 411, 512, 0), + (13226, 1, 360, 60, 27593), + (13238, 1, 320, 9, 0), + (13239, 1, 320, 10, 0), + (13240, 1, 320, 11, 0), + (13262, 1, 264, 1008, 102), + (13263, 1, 264, 1152, 102), + (13264, 1, 264, 1290, 102), + (13278, 1, 213, 25, 0), + (13281, 1, 318, 31, 0), + (13286, 1, 278, 900, 102200), + (13286, 2, 440, 92, 100), + (13294, 1, 339, 10, 8105), + (13294, 2, 142, 65, 0), + (13294, 3, 311, 0, 0), + (13294, 4, 134, 70, 0), + (13294, 5, 348, 10, 0), + (13294, 6, 137, 0, 0), + (13294, 7, 339, 10, 8105), + (13294, 8, 142, 65, 0), + (13294, 9, 311, 0, 0), + (13294, 10, 134, 70, 0), + (13294, 11, 348, 10, 0), + (13294, 12, 137, 100, 0), + (13294, 13, 339, 10, 8105), + (13294, 14, 142, 65, 0), + (13294, 15, 311, 0, 0), + (13294, 16, 134, 70, 0), + (13294, 17, 348, 10, 0), + (13294, 18, 137, 79, 0), + (13294, 19, 339, 10, 8105), + (13294, 20, 142, 65, 0), + (13294, 21, 311, 0, 0), + (13294, 22, 134, 70, 0), + (13294, 23, 348, 10, 0), + (13294, 24, 137, 147, 0), + (13294, 25, 339, 10, 11404), + (13294, 26, 142, 71, 0), + (13294, 27, 311, 0, 0), + (13294, 28, 134, 75, 0), + (13294, 29, 348, 10, 0), + (13294, 30, 137, 0, 0), + (13294, 31, 339, 10, 11404), + (13294, 32, 142, 71, 0), + (13294, 33, 311, 0, 0), + (13294, 34, 134, 75, 0), + (13294, 35, 348, 10, 0), + (13294, 36, 137, 100, 0), + (13294, 37, 339, 10, 11404), + (13294, 38, 142, 71, 0), + (13294, 39, 311, 0, 0), + (13294, 40, 134, 75, 0), + (13294, 41, 348, 10, 0), + (13294, 42, 137, 79, 0), + (13294, 43, 339, 10, 11404), + (13294, 44, 142, 71, 0), + (13294, 45, 311, 0, 0), + (13294, 46, 134, 75, 0), + (13294, 47, 348, 10, 0), + (13294, 48, 137, 147, 0), + (13294, 49, 339, 10, 13199), + (13294, 50, 142, 76, 0), + (13294, 51, 311, 0, 0), + (13294, 52, 134, 80, 0), + (13294, 53, 348, 10, 0), + (13294, 54, 137, 0, 0), + (13294, 55, 339, 10, 13199), + (13294, 56, 142, 76, 0), + (13294, 57, 311, 0, 0), + (13294, 58, 134, 80, 0), + (13294, 59, 348, 10, 0), + (13294, 60, 137, 100, 0), + (13294, 61, 339, 10, 13199), + (13294, 62, 142, 76, 0), + (13294, 63, 311, 0, 0), + (13294, 64, 134, 80, 0), + (13294, 65, 348, 10, 0), + (13294, 66, 137, 79, 0), + (13294, 67, 339, 10, 13199), + (13294, 68, 142, 76, 0), + (13294, 69, 311, 0, 0), + (13294, 70, 134, 80, 0), + (13294, 71, 348, 10, 0), + (13294, 72, 137, 147, 0), + (13294, 73, 339, 10, 13830), + (13294, 74, 142, 81, 0), + (13294, 75, 311, 0, 0), + (13294, 76, 134, 85, 0), + (13294, 77, 348, 10, 0), + (13294, 78, 137, 0, 0), + (13294, 79, 339, 10, 13830), + (13294, 80, 142, 81, 0), + (13294, 81, 311, 0, 0), + (13294, 82, 134, 85, 0), + (13294, 83, 348, 10, 0), + (13294, 84, 137, 100, 0), + (13294, 85, 339, 10, 13830), + (13294, 86, 142, 81, 0), + (13294, 87, 311, 0, 0), + (13294, 88, 134, 85, 0), + (13294, 89, 348, 10, 0), + (13294, 90, 137, 79, 0), + (13294, 91, 339, 10, 13830), + (13294, 92, 142, 81, 0), + (13294, 93, 311, 0, 0), + (13294, 94, 134, 85, 0), + (13294, 95, 348, 10, 0), + (13294, 96, 137, 147, 0), + (13294, 97, 339, 10, 27527), + (13294, 98, 142, 86, 0), + (13294, 99, 311, 0, 0), + (13294, 100, 134, 90, 0), + (13294, 101, 348, 10, 0), + (13294, 102, 137, 0, 0), + (13294, 103, 339, 10, 27527), + (13294, 104, 142, 86, 0), + (13294, 105, 311, 0, 0), + (13294, 106, 134, 90, 0), + (13294, 107, 348, 10, 0), + (13294, 108, 137, 100, 0), + (13294, 109, 339, 10, 27527), + (13294, 110, 142, 86, 0), + (13294, 111, 311, 0, 0), + (13294, 112, 134, 90, 0), + (13294, 113, 348, 10, 0), + (13294, 114, 137, 79, 0), + (13294, 115, 339, 10, 27527), + (13294, 116, 142, 86, 0), + (13294, 117, 311, 0, 0), + (13294, 118, 134, 90, 0), + (13294, 119, 348, 10, 0), + (13294, 120, 137, 147, 0), + (13294, 121, 339, 10, 30644), + (13294, 122, 142, 91, 0), + (13294, 123, 311, 0, 0), + (13294, 124, 134, 95, 0), + (13294, 125, 348, 10, 0), + (13294, 126, 137, 0, 0), + (13294, 127, 339, 10, 30644), + (13294, 128, 142, 91, 0), + (13294, 129, 311, 0, 0), + (13294, 130, 134, 95, 0), + (13294, 131, 348, 10, 0), + (13294, 132, 137, 100, 0), + (13294, 133, 339, 10, 30644), + (13294, 134, 142, 91, 0), + (13294, 135, 311, 0, 0), + (13294, 136, 134, 95, 0), + (13294, 137, 348, 10, 0), + (13294, 138, 137, 79, 0), + (13294, 139, 339, 10, 30644), + (13294, 140, 142, 91, 0), + (13294, 141, 311, 0, 0), + (13294, 142, 134, 95, 0), + (13294, 143, 348, 10, 0), + (13294, 144, 137, 147, 0), + (13295, 1, 339, 10, 8105), + (13295, 2, 142, 65, 0), + (13295, 3, 311, 0, 0), + (13295, 4, 134, 70, 0), + (13295, 5, 348, 10, 0), + (13295, 6, 137, 0, 0), + (13295, 7, 339, 10, 8105), + (13295, 8, 142, 65, 0), + (13295, 9, 311, 0, 0), + (13295, 10, 134, 70, 0), + (13295, 11, 348, 10, 0), + (13295, 12, 137, 100, 0), + (13295, 13, 339, 10, 8105), + (13295, 14, 142, 65, 0), + (13295, 15, 311, 0, 0), + (13295, 16, 134, 70, 0), + (13295, 17, 348, 10, 0), + (13295, 18, 137, 79, 0), + (13295, 19, 339, 10, 8105), + (13295, 20, 142, 65, 0), + (13295, 21, 311, 0, 0), + (13295, 22, 134, 70, 0), + (13295, 23, 348, 10, 0), + (13295, 24, 137, 147, 0), + (13295, 25, 339, 10, 11404), + (13295, 26, 142, 71, 0), + (13295, 27, 311, 0, 0), + (13295, 28, 134, 75, 0), + (13295, 29, 348, 10, 0), + (13295, 30, 137, 0, 0), + (13295, 31, 339, 10, 11404), + (13295, 32, 142, 71, 0), + (13295, 33, 311, 0, 0), + (13295, 34, 134, 75, 0), + (13295, 35, 348, 10, 0), + (13295, 36, 137, 100, 0), + (13295, 37, 339, 10, 11404), + (13295, 38, 142, 71, 0), + (13295, 39, 311, 0, 0), + (13295, 40, 134, 75, 0), + (13295, 41, 348, 10, 0), + (13295, 42, 137, 79, 0), + (13295, 43, 339, 10, 11404), + (13295, 44, 142, 71, 0), + (13295, 45, 311, 0, 0), + (13295, 46, 134, 75, 0), + (13295, 47, 348, 10, 0), + (13295, 48, 137, 147, 0), + (13295, 49, 339, 10, 13199), + (13295, 50, 142, 76, 0), + (13295, 51, 311, 0, 0), + (13295, 52, 134, 80, 0), + (13295, 53, 348, 10, 0), + (13295, 54, 137, 0, 0), + (13295, 55, 339, 10, 13199), + (13295, 56, 142, 76, 0), + (13295, 57, 311, 0, 0), + (13295, 58, 134, 80, 0), + (13295, 59, 348, 10, 0), + (13295, 60, 137, 100, 0), + (13295, 61, 339, 10, 13199), + (13295, 62, 142, 76, 0), + (13295, 63, 311, 0, 0), + (13295, 64, 134, 80, 0), + (13295, 65, 348, 10, 0), + (13295, 66, 137, 79, 0), + (13295, 67, 339, 10, 13199), + (13295, 68, 142, 76, 0), + (13295, 69, 311, 0, 0), + (13295, 70, 134, 80, 0), + (13295, 71, 348, 10, 0), + (13295, 72, 137, 147, 0), + (13295, 73, 339, 10, 13830), + (13295, 74, 142, 81, 0), + (13295, 75, 311, 0, 0), + (13295, 76, 134, 85, 0), + (13295, 77, 348, 10, 0), + (13295, 78, 137, 0, 0), + (13295, 79, 339, 10, 13830), + (13295, 80, 142, 81, 0), + (13295, 81, 311, 0, 0), + (13295, 82, 134, 85, 0), + (13295, 83, 348, 10, 0), + (13295, 84, 137, 100, 0), + (13295, 85, 339, 10, 13830), + (13295, 86, 142, 81, 0), + (13295, 87, 311, 0, 0), + (13295, 88, 134, 85, 0), + (13295, 89, 348, 10, 0), + (13295, 90, 137, 79, 0), + (13295, 91, 339, 10, 13830), + (13295, 92, 142, 81, 0), + (13295, 93, 311, 0, 0), + (13295, 94, 134, 85, 0), + (13295, 95, 348, 10, 0), + (13295, 96, 137, 147, 0), + (13295, 97, 339, 10, 27527), + (13295, 98, 142, 86, 0), + (13295, 99, 311, 0, 0), + (13295, 100, 134, 90, 0), + (13295, 101, 348, 10, 0), + (13295, 102, 137, 0, 0), + (13295, 103, 339, 10, 27527), + (13295, 104, 142, 86, 0), + (13295, 105, 311, 0, 0), + (13295, 106, 134, 90, 0), + (13295, 107, 348, 10, 0), + (13295, 108, 137, 100, 0), + (13295, 109, 339, 10, 27527), + (13295, 110, 142, 86, 0), + (13295, 111, 311, 0, 0), + (13295, 112, 134, 90, 0), + (13295, 113, 348, 10, 0), + (13295, 114, 137, 79, 0), + (13295, 115, 339, 10, 27527), + (13295, 116, 142, 86, 0), + (13295, 117, 311, 0, 0), + (13295, 118, 134, 90, 0), + (13295, 119, 348, 10, 0), + (13295, 120, 137, 147, 0), + (13295, 121, 339, 10, 30644), + (13295, 122, 142, 91, 0), + (13295, 123, 311, 0, 0), + (13295, 124, 134, 95, 0), + (13295, 125, 348, 10, 0), + (13295, 126, 137, 0, 0), + (13295, 127, 339, 10, 30644), + (13295, 128, 142, 91, 0), + (13295, 129, 311, 0, 0), + (13295, 130, 134, 95, 0), + (13295, 131, 348, 10, 0), + (13295, 132, 137, 100, 0), + (13295, 133, 339, 10, 30644), + (13295, 134, 142, 91, 0), + (13295, 135, 311, 0, 0), + (13295, 136, 134, 95, 0), + (13295, 137, 348, 10, 0), + (13295, 138, 137, 79, 0), + (13295, 139, 339, 10, 30644), + (13295, 140, 142, 91, 0), + (13295, 141, 311, 0, 0), + (13295, 142, 134, 95, 0), + (13295, 143, 348, 10, 0), + (13295, 144, 137, 147, 0), + (13296, 1, 125, 49, 49), + (13296, 2, 137, 0, 0), + (13296, 3, 141, 1, 0), + (13296, 4, 139, -6233, 0), + (13296, 5, 139, -6265, 0), + (13296, 6, 125, 49, 49), + (13296, 7, 137, 147, 0), + (13296, 8, 141, 1, 0), + (13297, 1, 125, 52, 52), + (13297, 2, 137, 0, 0), + (13297, 3, 141, 1, 0), + (13297, 4, 139, -6233, 0), + (13297, 5, 139, -6265, 0), + (13297, 6, 125, 52, 52), + (13297, 7, 137, 147, 0), + (13297, 8, 141, 1, 0), + (13299, 1, 319, 31, 0), + (13302, 1, 274, 44, 0), + (13305, 1, 189, 19, 0), + (13308, 1, 265, 87, 0), + (13313, 1, 15, 29, 0), + (13318, 1, 97, 850, 0), + (13323, 1, 320, 15, 0), + (13326, 1, 330, 155, 0), + (13326, 2, 330, 155, 1), + (13326, 3, 330, 155, 2), + (13326, 4, 330, 155, 3), + (13326, 5, 330, 155, 28), + (13326, 6, 330, 155, 36), + (13332, 1, 330, 155, 0), + (13332, 2, 330, 155, 1), + (13332, 3, 330, 155, 2), + (13332, 4, 330, 155, 3), + (13332, 5, 330, 155, 28), + (13332, 6, 330, 155, 36), + (13332, 7, 330, 155, 77), + (13338, 1, 1, 370, 0), + (13343, 1, 1, 340, 0), + (13348, 1, 1, 440, 0), + (13353, 1, 1, 330, 0), + (13358, 1, 1, 540, 0), + (13396, 1, 375, 40, 0), + (13404, 1, 273, 8, 0), + (13411, 1, 399, 4, 0), + (13411, 2, 138, 1, 0), + (13411, 3, 137, 0, 0), + (13411, 4, 348, 10, 0), + (13411, 5, 311, 0, 0), + (13411, 6, 141, 1, 0), + (13411, 7, 134, 254, 0), + (13411, 8, 137, -39, 0), + (13413, 1, 399, 12, 0), + (13413, 2, 141, 1, 0), + (13413, 3, 138, 0, 0), + (13413, 4, 142, 255, 0), + (13413, 5, 391, 0, 0), + (13413, 6, 311, 0, 0), + (13413, 7, 137, -152, 0), + (13413, 8, 411, 100350, 0), + (13413, 9, 137, -39, 0), + (13415, 1, 264, 150, 705), + (13415, 2, 264, 150, 1092), + (13415, 3, 264, 150, 10396), + (13415, 4, 264, 150, 10397), + (13416, 1, 264, 20, 626), + (13438, 1, 266, 29, 0), + (13449, 1, 264, 2, 11073), + (13463, 1, 264, 90, 458), + (13474, 1, 264, 120, 444), + (13477, 1, 126, 20, 0), + (13477, 2, 134, 95, 0), + (13477, 3, 135, 4, 0), + (13477, 4, 135, 5, 0), + (13485, 1, 279, 3, 0), + (13502, 1, 375, 160, 0), + (13508, 1, 378, 5, 3), + (13511, 1, 279, 43, 0), + (13520, 1, 292, 70, 0), + (13521, 1, 293, 25, 0), + (13533, 1, 378, 55, 96), + (13545, 1, 323, 30787, 0), + (13562, 1, 264, 480, 872), + (13565, 1, 264, 60, 3804), + (13568, 1, 264, 60, 876), + (13578, 1, 244, 30, 0), + (13589, 1, 279, 34, 0), + (13590, 1, 279, 38, 0), + (13598, 1, 339, 20, 30809), + (13598, 2, 137, 21, 0), + (13598, 3, 385, -18000, 0), + (13598, 4, 339, 20, 30809), + (13598, 5, 137, 343, 0), + (13598, 6, 385, -18000, 0), + (13601, 1, 231, 22, 0), + (13607, 1, 126, 4, 4), + (13607, 2, 137, 21, 0), + (13607, 3, 231, 4, 4), + (13610, 1, 266, 47, 0), + (13613, 1, 220, 260, 10), + (13616, 1, 220, 150, 2), + (13616, 2, 220, 150, 3), + (13616, 3, 220, 150, 77), + (13617, 1, 220, 375, 2), + (13617, 2, 220, 375, 3), + (13617, 3, 220, 375, 77), + (13618, 1, 220, 500, 2), + (13618, 2, 220, 500, 3), + (13618, 3, 220, 500, 77), + (13621, 1, 218, 11, 0), + (13627, 1, 59, -59, 0), + (13628, 1, 59, -64, 0), + (13630, 1, 398, 10000, 0), + (13630, 2, 137, 152, 0), + (13667, 1, 287, 1, 0), + (13667, 2, 385, 8054, 0), + (13675, 1, 218, 24, 0), + (13684, 1, 399, 2, 0), + (13684, 2, 140, 2, 0), + (13684, 3, 348, 10, 0), + (13684, 4, 138, 0, 0), + (13684, 5, 137, -152, 0), + (13684, 6, 137, -39, 0), + (13685, 1, 399, 3, 0), + (13685, 2, 140, 2, 0), + (13685, 3, 348, 10, 0), + (13685, 4, 138, 0, 0), + (13685, 5, 137, -152, 0), + (13685, 6, 137, -39, 0), + (13686, 1, 399, 4, 0), + (13686, 2, 140, 2, 0), + (13686, 3, 348, 10, 0), + (13686, 4, 138, 0, 0), + (13686, 5, 137, -152, 0), + (13686, 6, 137, -39, 0), + (13689, 1, 127, 10, 0), + (13689, 2, 139, 27592, 0), + (13689, 3, 139, 31548, 0), + (13707, 1, 274, 26, 0), + (13710, 1, 280, 65, 0), + (13713, 1, 218, 26, 0), + (13753, 1, 264, 360, 534), + (13758, 1, 264, 360, 602), + (13763, 1, 287, 4, 0), + (13763, 2, 137, 31, 0), + (13763, 3, 136, 5, 0), + (13764, 1, 264, 60, 535), + (13767, 1, 439, 0, 153514), + (13767, 2, 345, 90, 22), + (13773, 1, 279, 21, 0), + (13774, 1, 279, 23, 0), + (13775, 1, 279, 25, 0), + (13779, 1, 288, 100, 8), + (13782, 1, 220, 490, 8), + (13789, 1, 216, 850, 8), + (13790, 1, 216, 950, 8), + (13795, 1, 258, 73, 0), + (13798, 1, 114, -21, 0), + (13804, 1, 378, 4, 3), + (13813, 1, 220, 150, 28), + (13813, 2, 220, 150, 0), + (13813, 3, 427, 23598, 9), + (13813, 4, 428, 28, 0), + (13813, 5, 428, 0, 0), + (13820, 1, 220, 325, 26), + (13820, 2, 220, 325, 30), + (13820, 3, 220, 325, 38), + (13823, 1, 220, 295, 21), + (13823, 2, 220, 295, 23), + (13823, 3, 220, 670, 52), + (13823, 4, 220, 295, 28), + (13826, 1, 405, 25, 0), + (13829, 1, 220, 550, 26), + (13835, 1, 283, 300, 0), + (13841, 1, 264, 17, 469), + (13873, 1, 264, 30, 961), + (13878, 1, 264, 60, 609), + (13881, 1, 264, 60, 387), + (13884, 1, 265, 87, 0), + (13889, 1, 264, 60, 1012), + (13894, 1, 327, 13, 0), + (13905, 1, 310, 24000, 0), + (13905, 2, 385, 15319, 0), + (13908, 1, 310, 3000, 0), + (13908, 2, 385, 15307, 0), + (13908, 3, 385, 15407, 0), + (13908, 4, 385, 15507, 0), + (13908, 5, 385, 15607, 0), + (13911, 1, 310, 3000, 0), + (13911, 2, 385, 16005, 0), + (13911, 3, 310, 3000, 0), + (13911, 4, 385, 15405, 0), + (13911, 5, 385, 15505, 0), + (13911, 6, 385, 15605, 0), + (13911, 7, 411, 2, 0), + (13917, 1, 264, 120, 606), + (13921, 1, 114, -66, 0), + (13924, 1, 114, -64, 0), + (13927, 1, 114, -25, 0), + (13930, 1, 341, 310, 0), + (13933, 1, 262, 80, 0), + (13943, 1, 262, 80, 1), + (13953, 1, 262, 80, 2), + (13963, 1, 262, 80, 3), + (13973, 1, 262, 80, 4), + (13983, 1, 262, 80, 5), + (13993, 1, 262, 80, 6), + (14011, 1, 264, 30, 10394), + (14017, 1, 69, 10, 0), + (14018, 1, 69, 10, 0), + (14026, 1, 185, 3, 2), + (14026, 2, 185, 3, 3), + (14026, 3, 185, 3, 77), + (14026, 4, 220, 50, 2), + (14026, 5, 220, 50, 3), + (14026, 6, 220, 50, 77), + (14029, 1, 395, 5, 5), + (14029, 2, 385, 9758, 0), + (14029, 3, 385, 9858, 0), + (14029, 4, 385, 9958, 0), + (14032, 1, 181, 100, 0), + (14037, 1, 264, 180, 804), + (14040, 1, 264, 180, 300), + (14043, 1, 85, 32197, 0), + (14046, 1, 264, 90, 87), + (14056, 1, 310, 360000, 0), + (14056, 2, 139, 4504, 0), + (14059, 1, 310, -180000, 0), + (14059, 2, 139, 4520, 0), + (14062, 1, 264, 60, 821), + (14065, 1, 264, 60, 3215), + (14068, 1, 264, 60, 3216), + (14076, 1, 310, 480000, 0), + (14076, 2, 139, 4518, 0), + (14082, 1, 360, 26, 32314), + (14085, 1, 264, 2, 741), + (14088, 1, 264, 30, 769), + (14091, 1, 264, 120, 701), + (14094, 1, 124, 325, 350), + (14094, 2, 385, 19, 0), + (14094, 3, 144, 0, 0), + (14094, 4, 403, 3, 0), + (14094, 5, 404, 48, 0), + (14094, 6, 385, -21768, 0), + (14097, 1, 85, 32317, 5), + (14100, 1, 127, 50, 0), + (14100, 2, 137, 21, 0), + (14100, 3, 143, 1, 0), + (14100, 4, 134, 253, 0), + (14100, 5, 348, 1, 0), + (14101, 1, 310, 2520000, 0), + (14101, 2, 139, 4506, 0), + (14101, 3, 310, 2520000, 0), + (14101, 4, 385, 11122, 0), + (14101, 5, 385, 11222, 0), + (14101, 6, 385, 11322, 0), + (14101, 7, 385, 11522, 0), + (14115, 1, 287, 1, 0), + (14115, 2, 385, 16130, 0), + (14129, 1, 220, 60, 36), + (14129, 2, 427, 32327, 3), + (14129, 3, 428, 36, 0), + (14130, 1, 220, 90, 36), + (14130, 2, 427, 32327, 5), + (14130, 3, 428, 36, 0), + (14132, 1, 264, 240, 2234), + (14135, 1, 310, 132000, 0), + (14135, 2, 385, 13005, 0), + (14135, 3, 385, 12423, 0), + (14135, 4, 385, 12504, 0), + (14135, 5, 310, 132000, 0), + (14135, 6, 139, 4676, 0), + (14135, 7, 411, 512, 0), + (14138, 1, 310, 480000, 0), + (14138, 2, 139, 4695, 0), + (14138, 3, 411, 512, 0), + (14140, 1, 310, 24000, 0), + (14140, 2, 385, 13007, 0), + (14140, 3, 385, 12105, 0), + (14140, 4, 385, 12205, 0), + (14140, 5, 310, 72000, 0), + (14140, 6, 385, 12305, 0), + (14140, 7, 385, 12405, 0), + (14140, 8, 385, 12505, 0), + (14140, 9, 411, 512, 0), + (14141, 1, 185, 2, 36), + (14144, 1, 287, 1, 0), + (14144, 2, 385, 13204, 0), + (14144, 3, 411, 512, 0), + (14148, 1, 310, 90000, 0), + (14148, 2, 139, 4691, 0), + (14151, 1, 185, 2, 26), + (14151, 2, 220, 100, 26), + (14154, 1, 264, 2100, 276), + (14157, 1, 216, 150, 26), + (14160, 1, 264, 60, 7001), + (14163, 1, 287, 1, 0), + (14163, 2, 385, 16178, 0), + (14163, 3, 411, 128, 0), + (14166, 1, 264, 60, 945), + (14169, 1, 310, 202500, 0), + (14169, 2, 139, 8030, 0), + (14169, 3, 411, 256, 0), + (14173, 1, 310, 1440000, 0), + (14173, 2, 139, 4516, 0), + (14173, 3, 411, 256, 0), + (14176, 1, 264, 660, 8261), + (14179, 1, 287, 1, 0), + (14179, 2, 385, 5830, 0), + (14179, 3, 411, 256, 0), + (14180, 1, 287, 1, 0), + (14180, 2, 139, 8030, 0), + (14180, 3, 411, 256, 0), + (14181, 1, 247, 25, 20), + (14186, 1, 247, 25, 76), + (14196, 1, 264, 2340, 465), + (14199, 1, 264, 720, 499), + (14200, 1, 288, 15, 2), + (14200, 2, 288, 15, 3), + (14200, 3, 288, 15, 51), + (14200, 4, 288, 15, 77), + (14203, 1, 310, 150000, 0), + (14203, 2, 385, 3419, 0), + (14203, 3, 385, 14005, 0), + (14203, 4, 385, 3519, 0), + (14203, 5, 411, 65536, 0), + (14210, 1, 310, 40000, 0), + (14210, 2, 139, 1546, 0), + (14210, 3, 310, 40000, 0), + (14210, 4, 385, 4357, 0), + (14210, 5, 385, 4457, 0), + (14210, 6, 385, 4557, 0), + (14210, 7, 385, 4657, 0), + (14210, 8, 411, 4, 0), + (14213, 1, 264, 120, 1065), + (14218, 1, 232, 23, 4544), + (14223, 1, 264, 40, 47), + (14225, 1, 127, 16, 0), + (14225, 2, 385, 3283, 0), + (14225, 3, 411, 1024, 0), + (14238, 1, 264, 12, 1041), + (14241, 1, 264, 180, 386), + (14244, 1, 286, 100, 0), + (14244, 2, 138, 0, 0), + (14244, 3, 143, 1, 0), + (14244, 4, 348, 1, 0), + (14244, 5, 411, 64, 0), + (14249, 1, 392, 200, 0), + (14249, 2, 138, 1, 0), + (14249, 3, 348, 1, 0), + (14254, 1, 287, 1, 0), + (14254, 2, 385, 2025, 0), + (14254, 3, 385, 5121, 0), + (14254, 4, 385, 5221, 0), + (14254, 5, 385, 5562, 0), + (14259, 1, 287, 1, 0), + (14259, 2, 139, 23585, 0), + (14275, 1, 239, 20, 0), + (14278, 1, 287, 4, 0), + (14278, 2, 385, 16439, 0), + (14278, 3, 411, 32768, 0), + (14279, 1, 320, 8, 0), + (14283, 1, 127, 17, 0), + (14283, 2, 385, 3151, 0), + (14283, 3, 385, 5887, 0), + (14286, 1, 287, 1, 0), + (14286, 2, 385, 4877, 0), + (14289, 1, 127, 10, 0), + (14289, 2, 385, 2754, 0), + (14292, 1, 127, 10, 0), + (14292, 2, 385, 3286, 0), + (14295, 1, 264, 1, 3816), + (14301, 1, 405, 5, 0), + (14304, 1, 264, 45, 8341), + (14308, 1, 264, 20, 431), + (14311, 1, 264, 360, 430), + (14314, 1, 264, 8, 901), + (14318, 1, 127, 10, 0), + (14318, 2, 139, 21754, 0), + (14328, 1, 264, 6, 1154), + (14331, 1, 264, 120, 515), + (14341, 1, 264, 360, 748), + (14349, 1, 294, 0, 205), + (14361, 1, 294, 35, 109), + (14364, 1, 264, 90, 173), + (14367, 1, 445, 1, 0), + (14764, 1, 339, 10, 33950), + (14764, 2, 137, 31, 0), + (15074, 1, 264, 5, 15073), + (15100, 1, 264, 2, 467), + (15105, 1, 264, 120, 131), + (15108, 1, 310, 60000, 0), + (15108, 2, 385, 15521, 0), + (15108, 3, 411, 2, 0), + (15111, 1, 287, 1, 0), + (15111, 2, 385, 21778, 0), + (15113, 1, 287, 3, 0), + (15113, 2, 385, 21778, 0), + (15113, 3, 411, 2, 0), + (15120, 1, 264, 60, 800), + (15123, 1, 310, 120000, 0), + (15123, 2, 385, 15422, 0), + (15123, 3, 411, 2, 0), + (15126, 1, 310, 1000, 0), + (15126, 2, 385, 15212, 0), + (15126, 3, 411, 2, 0), + (15132, 1, 264, 10, 660), + (15135, 1, 287, 1, 0), + (15135, 2, 139, 32313, 0), + (15141, 1, 219, 420, 2400), + (15150, 1, 127, 10, 0), + (15150, 2, 385, 10505, 0), + (15150, 3, 385, 10105, 0), + (15150, 4, 385, 10205, 0), + (15150, 5, 385, 10305, 0), + (15150, 6, 385, 10405, 0), + (15150, 7, 385, 10605, 0), + (15153, 1, 287, 1, 0), + (15153, 2, 139, 4518, 0), + (15154, 1, 287, 1, 0), + (15154, 2, 139, 32312, 0), + (15155, 1, 287, 1, 0), + (15155, 2, 385, 10320, 0), + (15155, 3, 385, 10420, 0), + (15155, 4, 385, 10520, 0), + (15158, 1, 287, 1, 0), + (15158, 2, 385, 32307, 0), + (15159, 1, 287, 1, 0), + (15159, 2, 385, 27537, 0), + (15162, 1, 264, 120, 659), + (15168, 1, 264, 60, 657), + (15172, 1, 302, 430, 430), + (15172, 2, 385, 99, 0), + (15174, 1, 264, 40, 9400), + (15179, 1, 127, 10, 0), + (15179, 2, 139, 21804, 0), + (15179, 3, 139, 38280, 0), + (15182, 1, 264, 840, 9403), + (15188, 1, 239, 62, 0), + (15194, 1, 287, 1, 0), + (15194, 2, 385, 13407, 0), + (15194, 3, 385, 13507, 0), + (15204, 1, 264, 60, 390), + (15207, 1, 264, 60, 323), + (15217, 1, 339, 10, 38319), + (15217, 2, 385, 11006, 0), + (15217, 3, 385, 7108, 0), + (15217, 4, 385, 7208, 0), + (15217, 5, 385, 7308, 0), + (15217, 6, 385, 7408, 0), + (15217, 7, 385, 7508, 0), + (15217, 8, 385, 7608, 0), + (15220, 1, 287, 1, 0), + (15220, 2, 385, 11065, 0), + (15223, 1, 287, 1, 0), + (15223, 2, 385, 11067, 0), + (15226, 1, 287, 1, 0), + (15226, 2, 385, 11064, 0), + (15229, 1, 287, 1, 0), + (15229, 2, 385, 11066, 0), + (15232, 1, 339, 100, 38322), + (15232, 2, 385, 7518, 0), + (15238, 1, 264, 240, 621), + (15238, 2, 264, 240, 622), + (15238, 3, 264, 240, 623), + (15238, 4, 264, 240, 784), + (15238, 5, 264, 240, 785), + (15238, 6, 264, 240, 786), + (15238, 7, 264, 240, 787), + (15238, 8, 264, 240, 624), + (15253, 1, 127, 10, 0), + (15253, 2, 385, 32322, 0), + (15258, 1, 264, 540, 184), + (15270, 1, 264, 1980, 7003), + (15280, 1, 264, 720, 778), + (15283, 1, 310, 1000, 0), + (15283, 2, 385, 11402, 0), + (15283, 3, 385, 11502, 0), + (15283, 4, 385, 11441, 0), + (15283, 5, 385, 11541, 0), + (15283, 6, 385, 11641, 0), + (15288, 1, 220, 50, 0), + (15288, 2, 220, 50, 1), + (15288, 3, 220, 100, 2), + (15288, 4, 220, 100, 3), + (15288, 5, 220, 50, 36), + (15288, 6, 220, 100, 77), + (15295, 1, 127, 10, 0), + (15295, 2, 385, 21654, 0), + (15314, 1, 264, 25920, 36), + (15317, 1, 264, 1728, 35), + (15320, 1, 264, 150, 558), + (15328, 1, 339, 25, 38037), + (15328, 2, 138, 1, 0), + (15328, 3, 142, 65, 0), + (15328, 4, 137, 35, 0), + (15328, 5, 134, 90, 0), + (15328, 6, 339, 25, 38037), + (15328, 7, 138, 1, 0), + (15328, 8, 142, 65, 0), + (15328, 9, 137, 36, 0), + (15328, 10, 134, 90, 0), + (15328, 11, 339, 25, 38037), + (15328, 12, 138, 1, 0), + (15328, 13, 142, 65, 0), + (15328, 14, 137, 369, 0), + (15328, 15, 134, 90, 0), + (15328, 16, 339, 25, 38037), + (15328, 17, 138, 1, 0), + (15328, 18, 142, 65, 0), + (15328, 19, 137, 116, 0), + (15328, 20, 134, 90, 0), + (15342, 1, 287, 1, 0), + (15342, 2, 385, 23605, 0), + (15344, 1, 264, 360, 38), + (15348, 1, 264, 240, 9504), + (15356, 1, 232, 20, 4544), + (15358, 1, 287, 1, 0), + (15358, 2, 385, 32350, 0), + (15359, 1, 264, 960, 50), + (15363, 1, 264, 240, 447), + (15371, 1, 264, 1, 3729), + (15374, 1, 195, 20, 0), + (15383, 1, 310, 1000, 0), + (15383, 2, 385, 5132, 0), + (15383, 3, 385, 5232, 0), + (15383, 4, 385, 5332, 0), + (15383, 5, 385, 5432, 0), + (15383, 6, 385, 5532, 0), + (15383, 7, 385, 5032, 0), + (15383, 8, 385, 5632, 0), + (15389, 1, 127, 16, 0), + (15389, 2, 385, 23575, 0), + (15396, 1, 127, 20, 20), + (15396, 2, 137, 0, 0), + (15396, 3, 138, 0, 0), + (15396, 4, 141, 1, 0), + (15396, 5, 143, 3000, 0), + (15396, 6, 127, 20, 20), + (15396, 7, 385, 16555, 0), + (15396, 8, 385, 16655, 0), + (15397, 1, 264, 1260, 494), + (15403, 1, 264, 10, 8604), + (15406, 1, 127, 10, 10), + (15406, 2, 385, 37097, 0), + (15414, 1, 287, 1, 0), + (15414, 2, 139, 30736, 0), + (15421, 1, 264, 3600, 245), + (15422, 1, 132, 15, 15), + (15426, 1, 239, 62, 0), + (15429, 1, 220, 135, 2), + (15432, 1, 184, 5, -1), + (15438, 1, 310, 180000, 0), + (15438, 2, 385, 8316, 0), + (15438, 3, 411, 128, 0), + (15441, 1, 279, 38, 0), + (15444, 1, 288, 60, 26), + (15450, 1, 310, 3000, 0), + (15450, 2, 385, 8202, 0), + (15450, 3, 385, 8302, 0), + (15450, 4, 385, 8402, 0), + (15450, 5, 385, 8502, 0), + (15450, 6, 385, 8602, 0), + (15450, 7, 411, 128, 0), + (15453, 1, 310, 60000, 0), + (15453, 2, 385, 8421, 0), + (15453, 3, 411, 128, 0), + (15456, 1, 264, 5, 470), + (15466, 1, 126, 20, 20), + (15466, 2, 139, 12576, 0), + (15466, 3, 126, 20, 20), + (15466, 4, 139, 12828, 0), + (15469, 1, 264, 240, 1120), + (15472, 1, 264, 1260, 521), + (15478, 1, 264, 120, 578), + (15485, 1, 339, 10, 38417), + (15485, 2, 142, 96, 0), + (15485, 3, 311, 0, 0), + (15485, 4, 134, 105, 0), + (15485, 5, 348, 10, 0), + (15485, 6, 137, 0, 0), + (15485, 7, 339, 10, 38417), + (15485, 8, 142, 96, 0), + (15485, 9, 311, 0, 0), + (15485, 10, 134, 105, 0), + (15485, 11, 348, 10, 0), + (15485, 12, 137, 100, 0), + (15485, 13, 339, 10, 38417), + (15485, 14, 142, 96, 0), + (15485, 15, 311, 0, 0), + (15485, 16, 134, 105, 0), + (15485, 17, 348, 10, 0), + (15485, 18, 137, 79, 0), + (15485, 19, 339, 10, 38417), + (15485, 20, 142, 96, 0), + (15485, 21, 311, 0, 0), + (15485, 22, 134, 105, 0), + (15485, 23, 348, 10, 0), + (15485, 24, 137, 147, 0), + (15493, 1, 127, 10, 0), + (15493, 2, 137, 31, 0), + (15502, 1, 310, 240000, 0), + (15502, 2, 139, 4673, 0), + (15502, 3, 411, 512, 0), + (15509, 1, 310, 3000, 0), + (15509, 2, 385, 12315, 0), + (15509, 3, 385, 12415, 0), + (15509, 4, 385, 12515, 0), + (15509, 5, 385, 12615, 0), + (15509, 10, 411, 512, 0), + (15512, 1, 288, 50, 8), + (15516, 1, 126, 20, 0), + (15516, 2, 139, 3066, 0), + (15516, 3, 411, 256, 0), + (15517, 1, 127, 16, 0), + (15517, 2, 139, 3066, 0), + (15517, 3, 411, 256, 0), + (15526, 1, 264, 120, 3702), + (15529, 1, 247, 60, 53), + (15540, 1, 185, 5, 1), + (15543, 1, 185, 5, 0), + (15546, 1, 185, 5, 36), + (15549, 1, 264, 15, 244), + (15552, 1, 264, 840, 3710), + (15555, 1, 339, 5, 38103), + (15555, 2, 385, 3208, 0), + (15555, 3, 385, 3308, 0), + (15555, 4, 385, 3408, 0), + (15555, 5, 385, 3508, 0), + (15564, 1, 220, 68, 51), + (15571, 1, 264, 180, 351), + (15579, 1, 287, 2, 0), + (15579, 2, 139, 16106, 0), + (15585, 1, 274, 44, 0), + (15591, 1, 127, 10, 0), + (15591, 2, 139, 16839, 0), + (15598, 1, 264, 180, 759), + (15598, 2, 264, 180, 1150), + (15598, 3, 264, 180, 1151), + (15598, 4, 264, 180, 1152), + (15602, 1, 124, 1, 0), + (15602, 2, 138, 0, 0), + (15602, 3, 141, 1, 0), + (15602, 4, 348, 10, 0), + (15606, 1, 244, -25, 0), + (15609, 1, 383, 10, 38134), + (15609, 2, 141, 1, 0), + (15609, 3, 348, 10, 0), + (15609, 4, 142, 85, 0), + (15609, 5, 143, 3000, 0), + (15622, 1, 127, 5, 5), + (15622, 2, 137, 0, 0), + (15622, 3, 138, 0, 0), + (15622, 4, 141, 1, 0), + (15625, 1, 330, 10, 8), + (15632, 1, 264, 1728, 789), + (15634, 1, 310, 1500, 0), + (15634, 2, 385, 12110, 0), + (15634, 3, 385, 12210, 0), + (15634, 4, 385, 12310, 0), + (15634, 5, 385, 12410, 0), + (15634, 6, 385, 12510, 0), + (15635, 1, 310, 3000, 0), + (15635, 2, 385, 12110, 0), + (15635, 3, 385, 12210, 0), + (15635, 4, 385, 12310, 0), + (15635, 5, 385, 12410, 0), + (15635, 6, 385, 12510, 0), + (15648, 1, 185, 3, 74), + (15694, 1, 190, 550, 0), + (15714, 1, 320, 12, 0), + (15719, 1, 320, 12, 0), + (15746, 1, 421, 20, 0), + (15746, 2, 139, 16097, 0), + (15746, 3, 139, 23612, 0), + (15746, 4, 139, 32196, 0), + (15746, 5, 139, 32565, 0), + (15746, 6, 423, 6, 0), + (15746, 7, 422, 5, 0), + (15746, 8, 411, 2, 0), + (15768, 1, 125, 1, 2), + (15768, 2, 136, 46, 0), + (15772, 1, 128, 80, 80), + (15772, 2, 138, 1, 0), + (15772, 3, 140, 1, 0), + (15772, 4, 311, 0, 0), + (15772, 5, 411, 66434, 0), + (15772, 6, 137, -40, 0), + (15773, 1, 128, 80, 80), + (15773, 2, 138, 1, 0), + (15773, 3, 140, 1, 0), + (15773, 4, 311, 0, 0), + (15773, 5, 411, 256, 0), + (15773, 6, 137, -40, 0), + (15773, 7, 391, 1, 0), + (15778, 1, 303, 27500, 32500), + (15778, 2, 139, 2766, 0), + (15833, 1, 264, 60, 2045), + (15836, 1, 264, 60, 463), + (15891, 1, 264, 20, 988), + (15893, 1, 264, 20, 987), + (15895, 1, 264, 20, 986), + (15908, 1, 220, 125, 0), + (15908, 2, 220, 200, 2), + (15909, 1, 220, 155, 0), + (15909, 2, 220, 290, 2), + (15910, 1, 220, 185, 0), + (15910, 2, 220, 385, 2), + (15954, 1, 292, 49, 0), + (15961, 1, 129, 20, 0), + (15961, 2, 385, 12768, 0), + (15961, 3, 411, 256, 0), + (16062, 1, 339, 20, 40941), + (16062, 2, 138, 0, 0), + (16062, 3, 137, 31, 0), + (16062, 4, 311, 0, 0), + (16084, 1, 158, 1, 0), + (16087, 1, 264, 432, 53), + (16094, 1, 264, 3024, 43), + (16104, 1, 10, 0, 0), + (16109, 1, 69, 3000, 0), + (16114, 1, 114, 2, 0), + (16117, 1, 171, 2, 0), + (16120, 1, 226, 1, 0), + (16121, 1, 310, 840000, 0), + (16121, 2, 139, 4670, 0), + (16124, 1, 264, 2, 3711), + (16128, 1, 127, 8, 0), + (16128, 2, 139, 13143, 0), + (16131, 1, 130, 10, 0), + (16131, 2, 385, 18000, 0), + (16137, 1, 287, 1, 0), + (16137, 2, 385, 21821, 0), + (16140, 1, 287, 1, 0), + (16140, 2, 385, 30666, 0), + (16146, 1, 339, 2, 41107), + (16146, 2, 142, 95, 0), + (16146, 3, 138, 1, 0), + (16146, 4, 137, 0, 0), + (16146, 5, 348, 10, 0), + (16146, 6, 141, 1, 0), + (16149, 1, 129, 20, 0), + (16149, 2, 385, 4357, 0), + (16149, 3, 385, 4457, 0), + (16149, 4, 385, 4557, 0), + (16149, 5, 411, 4, 0), + (16152, 1, 339, 3, 41108), + (16152, 2, 142, 90, 0), + (16152, 3, 138, 0, 0), + (16152, 4, 137, 0, 0), + (16152, 5, 348, 10, 0), + (16152, 6, 141, 1, 0), + (16156, 1, 392, 1000, 0), + (16156, 2, 385, 32341, 0), + (16159, 1, 287, 1, 0), + (16159, 2, 385, 32307, 0), + (16164, 1, 294, 0, 195), + (16170, 1, 360, 70, 41119), + (16173, 1, 320, 12, 0), + (16176, 1, 264, 2, 337), + (16179, 1, 288, 8, 7), + (16180, 1, 264, 5, 584), + (16186, 1, 288, 100, 30), + (16189, 1, 339, 12, 41127), + (16189, 2, 138, 0, 0), + (16189, 3, 142, 70, 0), + (16189, 4, 411, 32, 0), + (16189, 5, 348, 1, 0), + (16189, 6, 141, 1, 0), + (16192, 1, 339, 12, 41130), + (16192, 2, 138, 0, 0), + (16192, 3, 142, 70, 0), + (16192, 4, 403, 4, 0), + (16192, 5, 348, 1, 0), + (16192, 6, 404, 2, 0), + (16192, 7, 141, 1, 0), + (16208, 1, 247, 5, 27), + (16211, 1, 287, 1, 0), + (16211, 2, 139, 23581, 0), + (16211, 3, 139, 32359, 0), + (16218, 1, 264, 10, 403), + (16221, 1, 287, 1, 0), + (16221, 2, 385, 23586, 0), + (16225, 1, 264, 1, 219), + (16230, 1, 310, 1000, 0), + (16230, 2, 385, 2431, 0), + (16230, 3, 385, 2531, 0), + (16230, 4, 385, 2545, 0), + (16230, 5, 385, 2631, 0), + (16235, 1, 126, 35, 0), + (16235, 2, 134, 100, 0), + (16235, 3, 135, 3, 0), + (16238, 1, 287, 2, 0), + (16238, 2, 385, 23693, 0), + (16238, 3, 460, 1, 0), + (16249, 1, 275, 100, 0), + (16257, 1, 429, 37114, 2), + (16257, 2, 428, 52, 0), + (16260, 1, 427, 41160, 3), + (16260, 2, 428, 23, 0), + (16266, 1, 224, 50, 8), + (16266, 2, 173, 4, 0), + (16267, 1, 250, 52, 0), + (16272, 1, 175, 2, 0), + (16276, 1, 247, 10, 36), + (16287, 1, 264, 20, 669), + (16297, 1, 264, 600, 553), + (16300, 1, 264, 60, 668), + (16303, 1, 264, 240, 3506), + (16306, 1, 264, 1260, 777), + (16317, 1, 220, 100, -1), + (16327, 1, 310, 720000, 0), + (16327, 2, 139, 5040, 0), + (16330, 1, 330, 105, 74), + (16336, 1, 264, 30, 1257), + (16339, 1, 264, 10, 773), + (16342, 1, 127, 10, 0), + (16342, 2, 385, 38115, 0), + (16361, 1, 399, 5, 0), + (16361, 2, 141, 1, 0), + (16361, 3, 138, 0, 0), + (16361, 4, 134, 254, 0), + (16361, 5, 348, 10, 0), + (16361, 6, 137, 0, 0), + (16361, 7, 311, 0, 0), + (16361, 8, 137, -152, 0), + (16361, 9, 137, -39, 0), + (16366, 1, 286, 200, 0), + (16366, 2, 138, 0, 0), + (16366, 3, 143, 1, 0), + (16366, 4, 348, 10, 0), + (16371, 1, 129, 20, 0), + (16371, 2, 385, 2754, 0), + (16380, 1, 264, 30, 2061), + (16386, 1, 264, 10, 2064), + (16392, 1, 264, 90, 2202), + (16396, 1, 127, 5, 5), + (16396, 2, 137, 0, 0), + (16396, 3, 138, 0, 0), + (16396, 4, 141, 1, 0), + (16402, 1, 131, 60, 60), + (16402, 2, 348, 10, 0), + (16402, 3, 137, -32, 0), + (16414, 1, 317, 16, 0), + (16419, 1, 426, 6, 0), + (16420, 1, 426, 7, 0), + (16421, 1, 426, 8, 0), + (16440, 1, 247, 65, 76), + (16475, 1, 218, 4, 0), + (16489, 1, 294, 29, 102), + (16536, 1, 405, 3, 0), + (16604, 1, 264, 1440, 180), + (16644, 1, 264, 60, 747), + (16666, 1, 264, 60, 742), + (16730, 1, 347, 31, 0), + (16745, 1, 264, 60, 706), + (16887, 1, 280, 75, 0), + (16890, 1, 218, 21, 0), + (17004, 1, 225, 35, 0), + (17206, 1, 264, 12, 601), + (17209, 1, 264, 180, 111), + (17212, 1, 264, 60, 10367), + (17215, 1, 378, 2, 22), + (17215, 2, 378, 2, 31), + (17215, 3, 378, 2, 3), + (17215, 4, 378, 2, 20), + (17218, 1, 127, 10, 0), + (17218, 2, 139, 27560, 0), + (17229, 1, 220, 900, 3), + (17229, 2, 220, 900, 2), + (17229, 3, 220, 900, 77), + (17235, 1, 127, 15, 0), + (17235, 2, 385, 12609, 0), + (17239, 1, 310, 2400000, 0), + (17239, 2, 139, 4500, 0), + (17239, 3, 411, 8, 0), + (17242, 1, 378, 1, 22), + (17242, 2, 378, 1, 31), + (17242, 3, 378, 1, 3), + (17242, 4, 378, 1, 20), + (17245, 1, 378, 1, 22), + (17245, 2, 378, 1, 31), + (17245, 3, 378, 1, 3), + (17245, 4, 378, 1, 20), + (17249, 1, 264, 120, 651), + (17252, 1, 310, 3000, 0), + (17252, 2, 385, 13438, 0), + (17252, 3, 385, 13538, 0), + (17252, 4, 385, 13638, 0), + (17258, 1, 399, 2, 0), + (17258, 2, 137, 457, 0), + (17258, 3, 399, 2, 0), + (17258, 4, 134, 253, 0), + (17258, 5, 142, 100, 0), + (17258, 6, 138, 0, 0), + (17258, 7, 136, 13, 0), + (17258, 8, 136, 20, 0), + (17258, 9, 137, -39, 0), + (17267, 1, 127, 10, 0), + (17267, 2, 385, 13507, 0), + (17267, 3, 385, 13107, 0), + (17267, 4, 385, 13207, 0), + (17267, 5, 385, 13307, 0), + (17267, 6, 385, 13407, 0), + (17267, 7, 385, 13607, 0), + (17281, 1, 287, 1, 0), + (17281, 2, 385, 16646, 0), + (17288, 1, 264, 1440, 41), + (17289, 1, 264, 180, 1062), + (17295, 1, 229, 62, 0), + (17307, 1, 127, 8, 0), + (17307, 2, 139, 38058, 0), + (17310, 1, 310, 14000, 0), + (17310, 2, 139, 8007, 0), + (17310, 3, 310, 14000, 0), + (17310, 4, 385, 4140, 0), + (17310, 5, 385, 4240, 0), + (17310, 6, 385, 4340, 0), + (17310, 7, 385, 4440, 0), + (17310, 8, 385, 4540, 0), + (17310, 9, 385, 4640, 0), + (17317, 1, 264, 60, 1270), + (17334, 1, 287, 12, 0), + (17334, 2, 385, 16188, 0), + (17336, 1, 287, 1, 0), + (17336, 2, 385, 32348, 0), + (17339, 1, 264, 12, 760), + (17350, 1, 264, 110, 170), + (17357, 1, 287, 1, 0), + (17357, 2, 137, 100, 0), + (17357, 3, 138, 1, 0), + (17361, 1, 264, 60, 405), + (17361, 2, 264, 60, 426), + (17365, 1, 287, 6, 0), + (17365, 2, 385, 5240, 0), + (17365, 3, 385, 5340, 0), + (17365, 4, 385, 5440, 0), + (17365, 5, 385, 5540, 0), + (17365, 6, 385, 5640, 0), + (17370, 1, 287, 1, 0), + (17370, 2, 138, 0, 0), + (17370, 3, 137, 0, 0), + (17370, 4, 137, 100, 0), + (17370, 5, 140, 1, 0), + (17370, 6, 348, 10, 0), + (17375, 1, 127, 10, 0), + (17375, 2, 385, 38078, 0), + (17391, 1, 264, 1560, 98), + (17406, 1, 310, 480000, 0), + (17406, 2, 139, 4502, 0), + (17406, 3, 139, 4509, 0), + (17409, 1, 214, 205, 0), + (17409, 2, 259, 4, 0), + (17409, 3, 172, 4, 0), + (17414, 1, 264, 120, 673), + (17418, 1, 247, 10, 74), + (17428, 1, 288, 5, 51), + (17436, 1, 264, 60, 372), + (17439, 1, 287, 1, 0), + (17439, 2, 385, 6040, 0), + (17441, 1, 279, 37, 0), + (17445, 1, 310, 60000, 0), + (17445, 2, 385, 3312, 0), + (17448, 1, 287, 1, 0), + (17448, 2, 385, 14005, 0), + (17448, 3, 385, 3519, 0), + (17476, 1, 264, 240, 462), + (17492, 1, 264, 120, 840), + (17495, 1, 264, 20, 9702), + (17515, 1, 127, 25, 0), + (17515, 2, 385, 7125, 0), + (17517, 1, 127, 17, 0), + (17517, 2, 385, 23683, 0), + (17517, 3, 460, 1, 0), + (17522, 1, 264, 30, 764), + (17533, 1, 287, 1, 0), + (17533, 2, 139, 32399, 0), + (17533, 3, 460, 1, 0), + (17547, 1, 287, 1, 0), + (17547, 2, 137, 0, 0), + (17547, 3, 137, 100, 0), + (17547, 4, 140, 2, 0), + (17547, 5, 138, 0, 0), + (17547, 6, 348, 10, 0), + (17549, 1, 264, 10, 8700), + (17553, 1, 339, 8, 41768), + (17553, 2, 138, 0, 0), + (17553, 3, 141, 1, 0), + (17553, 4, 134, 253, 0), + (17553, 5, 142, 85, 0), + (17553, 6, 143, 1, 0), + (17553, 7, 311, 0, 0), + (17553, 8, 348, 1, 0), + (17553, 9, 137, 0, 0), + (17554, 1, 227, 2, 74), + (17555, 1, 286, 126, 2), + (17555, 2, 385, 9606, 0), + (17555, 3, 303, 252, 0), + (17555, 4, 385, 9606, 0), + (17558, 1, 413, 2, 2), + (17558, 2, 385, 9603, 0), + (17558, 3, 411, 2048, 0), + (17561, 1, 413, 2, 2), + (17561, 2, 385, 9609, 0), + (17561, 3, 411, 2048, 0), + (17564, 1, 413, 2, 2), + (17564, 2, 385, 9619, 0), + (17564, 3, 411, 2048, 0), + (17567, 1, 413, 2, 2), + (17567, 2, 385, 9613, 0), + (17567, 3, 411, 2048, 0), + (17570, 1, 413, 2, 2), + (17570, 2, 385, 9604, 0), + (17570, 3, 411, 2048, 0), + (17573, 1, 413, 2, 2), + (17573, 2, 385, 9651, 0), + (17573, 3, 411, 2048, 0), + (17576, 1, 413, 2, 2), + (17576, 2, 385, 16652, 0), + (17576, 3, 411, 4096, 0), + (17579, 1, 413, 2, 2), + (17579, 2, 385, 16629, 0), + (17579, 3, 411, 4096, 0), + (17582, 1, 413, 2, 2), + (17582, 2, 385, 16650, 0), + (17582, 3, 411, 4096, 0), + (17585, 1, 413, 2, 2), + (17585, 2, 385, 16608, 0), + (17585, 3, 411, 4096, 0), + (17588, 1, 413, 2, 2), + (17588, 2, 385, 16615, 0), + (17588, 3, 411, 4096, 0), + (17591, 1, 413, 2, 2), + (17591, 2, 385, 16618, 0), + (17591, 3, 411, 4096, 0), + (17594, 1, 413, 2, 2), + (17594, 2, 385, 16625, 0), + (17594, 3, 411, 4096, 0), + (17597, 1, 286, 345, 0), + (17597, 2, 385, 7604, 0), + (17600, 1, 413, 2, 2), + (17600, 2, 385, 7608, 0), + (17600, 3, 411, 8192, 0), + (17603, 1, 413, 2, 2), + (17603, 2, 385, 7612, 0), + (17603, 3, 411, 8192, 0), + (17606, 1, 392, 419, 0), + (17606, 2, 385, 7613, 0), + (17606, 3, 396, 838, 0), + (17606, 4, 385, 7613, 0), + (17609, 1, 413, 2, 2), + (17609, 2, 385, 7636, 0), + (17609, 3, 411, 8192, 0), + (17612, 1, 413, 2, 2), + (17612, 2, 385, 7618, 0), + (17612, 3, 411, 8192, 0), + (17615, 1, 286, 539, 0), + (17615, 2, 385, 7638, 0), + (17618, 1, 413, 2, 2), + (17618, 2, 385, 6664, 0), + (17618, 3, 411, 16384, 0), + (17621, 1, 413, 2, 2), + (17621, 2, 385, 6648, 0), + (17621, 3, 411, 16384, 0), + (17624, 1, 413, 2, 2), + (17624, 2, 385, 6649, 0), + (17624, 3, 411, 16384, 0), + (17627, 1, 413, 2, 2), + (17627, 2, 385, 6611, 0), + (17627, 3, 411, 16384, 0), + (17630, 1, 413, 2, 2), + (17630, 2, 385, 6652, 0), + (17630, 3, 411, 16384, 0), + (17633, 1, 413, 2, 2), + (17633, 2, 385, 6655, 0), + (17633, 3, 411, 16384, 0), + (17639, 1, 323, 37182, 100), + (18972, 1, 214, 210, 0), + (18972, 2, 259, 5, 0), + (18972, 3, 172, 5, 0), + (30050, 1, 69, 25, 0), + (30050, 2, 97, 25, 0), + (30050, 3, 190, 25, 0), + (30050, 4, 328, 25, 0), + (30100, 1, 1, 10, 0), + (30100, 2, 2, 10, 0), + (30100, 3, 341, 10, 0), + (30150, 1, 262, 5, 0), + (30150, 2, 262, 5, 1), + (30150, 3, 262, 5, 2), + (30150, 4, 262, 5, 3), + (30150, 5, 262, 5, 4), + (30150, 6, 262, 5, 5), + (30150, 7, 262, 5, 6), + (30150, 8, 159, 5, 0), + (30150, 9, 0, 2, 0), + (30150, 10, 15, 2, 0), + (30150, 11, 189, 2, 0), + (30150, 12, 317, 2, 0), + (30150, 13, 318, 2, 0), + (30175, 1, 271, 1, 0), + (30180, 1, 264, 1, 8202), + (30185, 1, 264, 1, 1011), + (30195, 1, 432, 1, 0), + (49999, 1, 10, 0, 0); + +DROP TABLE IF EXISTS `aa_rank_prereqs`; +CREATE TABLE IF NOT EXISTS `aa_rank_prereqs` ( + `rank_id` int(10) unsigned NOT NULL, + `aa_id` int(10) NOT NULL, + `points` int(10) NOT NULL, + PRIMARY KEY (`rank_id`,`aa_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `aa_rank_prereqs` (`rank_id`, `aa_id`, `points`) VALUES + (129, 19, 3), + (131, 19, 3), + (136, 19, 3), + (141, 23, 3), + (142, 23, 3), + (143, 23, 3), + (146, 224, 3), + (162, 224, 3), + (190, 30, 3), + (191, 30, 3), + (192, 30, 3), + (195, 31, 3), + (230, 17, 3), + (231, 17, 3), + (232, 17, 3), + (255, 309, 3), + (256, 309, 3), + (257, 309, 3), + (260, 31, 3), + (261, 31, 3), + (262, 31, 3), + (263, 17, 3), + (264, 17, 3), + (265, 17, 3), + (267, 23, 3), + (268, 23, 3), + (269, 23, 3), + (446, 26, 3), + (447, 26, 3), + (448, 26, 3), + (462, 39, 1), + (463, 39, 1), + (464, 39, 1), + (468, 41, 1), + (469, 41, 1), + (470, 41, 1), + (471, 57, 1), + (472, 57, 1), + (473, 57, 1), + (474, 50, 1), + (475, 50, 1), + (476, 50, 1), + (477, 43, 1), + (478, 43, 1), + (479, 43, 1), + (480, 117, 1), + (481, 117, 1), + (482, 117, 1), + (483, 58, 1), + (484, 58, 1), + (485, 58, 1), + (489, 110, 1), + (490, 110, 1), + (491, 110, 1), + (492, 109, 1), + (493, 109, 1), + (494, 109, 1), + (495, 98, 1), + (496, 98, 1), + (497, 98, 1), + (498, 102, 1), + (499, 102, 1), + (500, 102, 1), + (501, 107, 1), + (502, 107, 1), + (503, 107, 1), + (531, 19, 3), + (532, 19, 3), + (534, 6001, 11), + (535, 6001, 11), + (536, 6001, 11), + (537, 112, 3), + (538, 112, 3), + (539, 17, 3), + (540, 17, 3), + (541, 17, 3), + (542, 309, 3), + (543, 309, 3), + (544, 309, 3), + (567, 45, 1), + (574, 125, 1), + (575, 125, 1), + (576, 125, 1), + (583, 73, 1), + (584, 73, 1), + (585, 73, 1), + (586, 120, 1), + (587, 120, 1), + (588, 120, 1), + (589, 87, 1), + (590, 87, 1), + (591, 87, 1), + (592, 30, 1), + (593, 6001, 11), + (594, 6001, 11), + (595, 6001, 11), + (596, 6000, 11), + (597, 6000, 11), + (598, 6000, 11), + (637, 23, 3), + (638, 23, 3), + (639, 23, 3), + (640, 23, 3), + (641, 23, 3), + (642, 23, 3), + (643, 55, 1), + (644, 82, 1), + (702, 30, 1), + (703, 30, 1), + (704, 30, 1), + (705, 30, 1), + (706, 30, 1), + (715, 6001, 11), + (716, 6001, 11), + (717, 6001, 11), + (754, 153, 3), + (755, 153, 3), + (756, 153, 3), + (770, 23, 3), + (771, 23, 3), + (772, 23, 3), + (773, 217, 1), + (774, 217, 1), + (775, 217, 1), + (782, 35, 1), + (783, 35, 1), + (784, 35, 1), + (806, 81, 1), + (849, 180, 3), + (850, 180, 3), + (851, 180, 3), + (886, 102, 1), + (887, 102, 1), + (893, 87, 1), + (894, 87, 1), + (924, 23, 3), + (925, 23, 3), + (931, 23, 1), + (932, 23, 1), + (933, 23, 1), + (975, 102, 1), + (1018, 227, 3), + (1041, 30, 6), + (1042, 30, 6), + (1043, 30, 6), + (1044, 310, 6), + (1045, 310, 6), + (1046, 310, 6), + (1047, 311, 3), + (1048, 311, 3), + (1049, 311, 3), + (1050, 309, 6), + (1051, 309, 6), + (1052, 309, 6), + (1102, 30, 1), + (1103, 30, 1), + (1104, 30, 1), + (1105, 30, 1), + (1106, 30, 1), + (1107, 23, 3), + (1108, 23, 3), + (1109, 23, 3), + (1110, 187, 5), + (1111, 187, 5), + (1112, 187, 5), + (1122, 176, 2), + (1126, 58, 1), + (1127, 58, 1), + (1128, 58, 1), + (1129, 125, 1), + (1130, 125, 1), + (1150, 189, 3), + (1151, 189, 3), + (1152, 189, 3), + (1163, 309, 3), + (1164, 309, 3), + (1165, 309, 3), + (1203, 19, 3), + (1204, 19, 3), + (1205, 19, 3), + (1210, 114, 6), + (1211, 114, 6), + (1212, 114, 6), + (1213, 215, 6), + (1214, 215, 6), + (1215, 215, 6), + (1242, 173, 3), + (1243, 173, 3), + (1244, 173, 3), + (1251, 61, 1), + (1252, 64, 1), + (1253, 62, 1), + (1254, 63, 1), + (1274, 175, 3), + (1275, 175, 3), + (1276, 175, 3), + (1278, 6001, 11), + (1279, 6001, 11), + (1280, 6001, 11), + (1323, 47, 1), + (1337, 308, 3), + (1338, 308, 3), + (1339, 308, 3), + (1414, 451, 1), + (1415, 451, 1), + (1416, 451, 1), + (1417, 451, 1), + (1418, 451, 1), + (1420, 17, 3), + (1421, 17, 3), + (1422, 17, 3), + (1423, 17, 3), + (1424, 17, 3), + (1425, 374, 3), + (1426, 374, 3), + (1427, 374, 3), + (1428, 374, 3), + (1429, 374, 3), + (1435, 20, 3), + (1436, 20, 3), + (1437, 20, 3), + (1458, 375, 3), + (1459, 255, 5), + (1460, 255, 5), + (1461, 255, 5), + (1471, 362, 1), + (1472, 362, 1), + (1473, 362, 1), + (1474, 362, 1), + (1475, 362, 1), + (1483, 114, 6), + (1484, 114, 6), + (1485, 114, 6), + (1486, 19, 7), + (1487, 19, 7), + (1488, 19, 7), + (1489, 19, 7), + (1490, 19, 7), + (1494, 80, 1), + (1495, 185, 6), + (1496, 185, 6), + (1497, 185, 6), + (1501, 46, 1), + (1502, 46, 1), + (1503, 46, 1), + (1504, 60, 1), + (1505, 60, 1), + (1506, 60, 1), + (1511, 175, 3), + (1512, 175, 3), + (1513, 175, 3), + (1514, 259, 6), + (1515, 259, 6), + (1516, 259, 6), + (1524, 30, 3), + (1525, 30, 3), + (1526, 30, 3), + (1543, 439, 3), + (1544, 439, 3), + (1545, 439, 3), + (1546, 420, 1), + (1547, 420, 1), + (1548, 420, 1), + (1552, 13, 5), + (1553, 13, 5), + (1554, 13, 5), + (1555, 359, 3), + (1556, 359, 3), + (1557, 359, 3), + (1558, 46, 1), + (1559, 46, 1), + (1560, 46, 1), + (1572, 263, 1), + (1573, 263, 1), + (1574, 263, 1), + (1575, 263, 1), + (1576, 263, 1), + (1577, 58, 1), + (1578, 58, 1), + (1579, 58, 1), + (1583, 300, 6), + (1584, 300, 6), + (1585, 300, 6), + (1586, 300, 6), + (1587, 300, 6), + (1591, 222, 3), + (1601, 82, 1), + (1602, 82, 1), + (1603, 82, 1), + (1608, 82, 3), + (1609, 82, 3), + (1610, 82, 3), + (1611, 181, 2), + (1612, 181, 2), + (1613, 181, 2), + (1614, 181, 2), + (1615, 181, 2), + (1627, 13, 5), + (1628, 13, 5), + (1629, 13, 5), + (1638, 224, 3), + (1639, 565, 1), + (1640, 793, 1), + (1641, 121, 3), + (1642, 121, 3), + (1643, 77, 1), + (1644, 85, 1), + (1645, 77, 1), + (1646, 85, 1), + (1656, 153, 1), + (1657, 153, 1), + (1659, 285, 1), + (1660, 285, 1), + (1667, 570, 1), + (2400, 38, 1), + (2401, 38, 1), + (2402, 38, 1), + (3676, 35, 1), + (4666, 435, 3), + (4667, 435, 3), + (4668, 435, 3), + (4669, 435, 3), + (4670, 435, 3), + (4688, 497, 5), + (4689, 497, 5), + (4690, 497, 5), + (4691, 497, 5), + (4692, 497, 5), + (4707, 30, 6), + (4708, 30, 6), + (4709, 30, 6), + (4710, 310, 6), + (4711, 310, 6), + (4712, 310, 6), + (4713, 311, 3), + (4714, 311, 3), + (4715, 311, 3), + (4716, 309, 6), + (4717, 309, 6), + (4718, 309, 6), + (4749, 23, 3), + (4750, 23, 3), + (4751, 23, 3), + (4752, 114, 6), + (4753, 114, 6), + (4754, 114, 6), + (4755, 215, 6), + (4756, 215, 6), + (4757, 215, 6), + (4761, 526, 3), + (4762, 526, 3), + (4763, 526, 3), + (4773, 20, 3), + (4795, 309, 3), + (4796, 309, 3), + (4797, 309, 3), + (4829, 420, 1), + (4830, 420, 1), + (4831, 420, 1), + (4844, 435, 3), + (4845, 435, 3), + (4846, 435, 3), + (4847, 435, 3), + (4848, 435, 3), + (4861, 68, 1), + (4862, 68, 1), + (4863, 68, 1), + (4864, 175, 3), + (4865, 175, 3), + (4866, 175, 3), + (4887, 413, 3), + (4888, 413, 3), + (4889, 413, 3), + (4890, 57, 1), + (4894, 409, 3), + (4895, 409, 3), + (4896, 409, 3), + (4903, 784, 1), + (4906, 785, 1), + (4909, 786, 1), + (4912, 787, 1), + (4915, 794, 1), + (4916, 794, 1), + (4917, 794, 1), + (4921, 117, 1), + (4922, 117, 1), + (4923, 117, 1), + (4924, 740, 3), + (4925, 740, 3), + (4926, 740, 3), + (4931, 173, 8), + (4932, 173, 8), + (4933, 173, 8), + (4951, 439, 3), + (4952, 439, 3), + (4953, 439, 3), + (4975, 30, 1), + (4976, 30, 1), + (4977, 30, 1), + (4978, 30, 1), + (4979, 30, 1), + (4986, 82, 1), + (4987, 82, 1), + (4988, 82, 1), + (4989, 82, 3), + (4990, 82, 3), + (4991, 82, 3), + (5010, 35, 1), + (5011, 35, 1), + (5012, 35, 1), + (5038, 30, 3), + (5039, 30, 3), + (5040, 30, 3), + (5041, 6001, 11), + (5042, 6001, 11), + (5043, 6001, 11), + (5061, 45, 1), + (5069, 224, 3), + (5070, 19, 3), + (5071, 19, 3), + (5072, 19, 3), + (5080, 255, 5), + (5081, 255, 5), + (5082, 255, 5), + (5098, 73, 2), + (5118, 396, 1), + (5119, 396, 1), + (5120, 396, 1), + (5127, 261, 3), + (5128, 261, 3), + (5129, 261, 3), + (5133, 23, 3), + (5134, 23, 3), + (5135, 23, 3), + (5136, 496, 5), + (5137, 496, 5), + (5138, 496, 5), + (5139, 496, 5), + (5140, 496, 5), + (5251, 447, 3), + (5252, 447, 3), + (5253, 447, 3), + (5264, 278, 5), + (5265, 278, 5), + (5266, 278, 5), + (5267, 278, 5), + (5268, 278, 5), + (5270, 87, 1), + (5271, 87, 1), + (5272, 87, 1), + (5286, 23, 3), + (5287, 23, 3), + (5288, 23, 3), + (5311, 185, 6), + (5312, 185, 6), + (5313, 185, 6), + (5330, 1685, 1), + (5333, 1685, 1), + (5336, 1685, 1), + (5339, 1685, 1), + (5342, 1685, 1), + (5347, 1685, 1), + (5348, 1685, 1), + (5350, 707, 4), + (5350, 1685, 1), + (5353, 1685, 1), + (5356, 1685, 1), + (5357, 1685, 1), + (5360, 1685, 1), + (5363, 447, 3), + (5363, 1685, 1), + (5366, 1685, 1), + (5369, 1685, 1), + (5513, 58, 1), + (5514, 58, 1), + (5515, 58, 1), + (5529, 19, 7), + (5530, 19, 7), + (5531, 19, 7), + (5532, 19, 7), + (5533, 19, 7), + (5542, 30, 6), + (5543, 30, 6), + (5544, 30, 6), + (5545, 310, 6), + (5546, 310, 6), + (5547, 310, 6), + (5548, 311, 3), + (5549, 311, 3), + (5550, 311, 3), + (5551, 309, 6), + (5552, 309, 6), + (5553, 309, 6), + (5571, 23, 3), + (5572, 23, 3), + (5573, 23, 3), + (5574, 114, 6), + (5575, 114, 6), + (5576, 114, 6), + (5577, 215, 6), + (5578, 215, 6), + (5579, 215, 6), + (5595, 309, 3), + (5596, 309, 3), + (5597, 309, 3), + (5607, 794, 1), + (5608, 794, 1), + (5609, 794, 1), + (5617, 23, 3), + (5618, 23, 3), + (5619, 23, 3), + (5702, 30, 1), + (5703, 30, 1), + (5704, 30, 1), + (5705, 30, 1), + (5706, 30, 1), + (5759, 374, 3), + (5760, 374, 3), + (5761, 374, 3), + (5762, 374, 3), + (5763, 374, 3), + (5791, 19, 3), + (5792, 19, 3), + (5793, 19, 3), + (5797, 396, 1), + (5798, 396, 1), + (5799, 396, 1), + (5803, 255, 5), + (5804, 255, 5), + (5805, 255, 5), + (5806, 30, 3), + (5807, 30, 3), + (5808, 30, 3), + (5825, 45, 1), + (5826, 185, 6), + (5827, 185, 6), + (5828, 185, 6), + (5854, 217, 1), + (5855, 217, 1), + (5856, 217, 1), + (5857, 173, 3), + (5858, 173, 3), + (5859, 173, 3), + (5869, 57, 1), + (5871, 57, 1), + (5872, 57, 1), + (5880, 60, 1), + (5881, 60, 1), + (5882, 60, 1), + (5886, 58, 1), + (5887, 58, 1), + (5888, 58, 1), + (5892, 784, 1), + (5893, 785, 1), + (5894, 786, 1), + (5895, 787, 1), + (5939, 278, 5), + (5940, 278, 5), + (5941, 278, 5), + (5942, 278, 5), + (5943, 278, 5), + (5944, 740, 3), + (5945, 740, 3), + (5946, 740, 3), + (5947, 175, 3), + (5948, 175, 3), + (5949, 175, 3), + (5950, 175, 3), + (5951, 175, 3), + (5952, 175, 3), + (5954, 68, 1), + (5955, 68, 1), + (5956, 68, 1), + (5969, 6001, 11), + (5970, 6001, 11), + (5971, 6001, 11), + (5972, 6001, 11), + (5973, 6000, 11), + (5984, 702, 1), + (6017, 82, 1), + (6018, 82, 1), + (6019, 82, 1), + (6026, 826, 1), + (6027, 826, 1), + (6028, 826, 1), + (6042, 439, 3), + (6043, 439, 3), + (6044, 439, 3), + (6054, 173, 8), + (6055, 173, 8), + (6056, 173, 8), + (6063, 87, 1), + (6064, 87, 1), + (6065, 87, 1), + (6088, 392, 1), + (6089, 392, 1), + (6090, 392, 1), + (6092, 447, 3), + (6093, 447, 3), + (6094, 447, 3), + (6102, 224, 3), + (6106, 308, 3), + (6107, 308, 3), + (6108, 308, 3), + (6109, 308, 3), + (6110, 308, 3), + (6111, 308, 3), + (6130, 120, 1), + (6131, 120, 1), + (6132, 120, 1), + (6136, 300, 6), + (6158, 308, 3), + (6159, 308, 3), + (6160, 308, 3), + (6209, 245, 3), + (6210, 245, 3), + (6211, 245, 3), + (6228, 404, 1), + (6229, 404, 1), + (6230, 404, 1), + (6231, 404, 1), + (6233, 43, 1), + (6234, 43, 1), + (6235, 43, 1), + (6260, 98, 1), + (6261, 98, 1), + (6262, 98, 1), + (6272, 672, 1), + (6273, 672, 1), + (6274, 672, 1), + (6275, 790, 1), + (6276, 790, 1), + (6277, 790, 1), + (6302, 3710, 1), + (6303, 3710, 1), + (6304, 3710, 1), + (6319, 107, 1), + (6320, 107, 1), + (6321, 107, 1), + (6333, 125, 1), + (6337, 553, 1), + (6338, 553, 1), + (6339, 553, 1), + (6340, 777, 1), + (6341, 777, 1), + (6342, 777, 1), + (6346, 494, 3), + (6347, 494, 3), + (6348, 494, 3), + (6349, 500, 3), + (6350, 500, 3), + (6351, 500, 3), + (6352, 409, 3), + (6353, 409, 3), + (6354, 409, 3), + (6380, 128, 3), + (6381, 128, 3), + (6382, 128, 3), + (6400, 187, 5), + (6401, 187, 5), + (6402, 187, 5), + (6403, 23, 3), + (6404, 23, 3), + (6405, 23, 3), + (6439, 41, 1), + (6440, 41, 1), + (6441, 420, 1), + (6442, 362, 1), + (6443, 362, 1), + (6445, 176, 1), + (6446, 176, 1), + (6447, 176, 1), + (6478, 3800, 1), + (6479, 3800, 1), + (6480, 3800, 1), + (6481, 36, 1), + (6482, 36, 1), + (6483, 36, 1), + (6484, 558, 1), + (6485, 558, 1), + (6486, 558, 1), + (6499, 611, 1), + (6500, 526, 3), + (6501, 526, 3), + (6502, 526, 3), + (6503, 172, 1), + (6504, 172, 1), + (6505, 172, 1), + (6506, 172, 1), + (6514, 404, 1), + (6515, 404, 1), + (6516, 404, 1), + (6517, 20, 1), + (6528, 107, 1), + (6630, 278, 5), + (6631, 278, 5), + (6632, 278, 5), + (6633, 278, 5), + (6634, 278, 5), + (6636, 358, 3), + (6637, 358, 3), + (6638, 358, 3), + (6668, 672, 3), + (6669, 672, 3), + (6670, 672, 3), + (6697, 857, 1), + (6698, 857, 1), + (6699, 857, 1), + (6700, 857, 1), + (6701, 857, 1), + (6703, 171, 1), + (6704, 171, 1), + (6705, 171, 1), + (6712, 177, 1), + (6713, 177, 1), + (6714, 177, 1), + (6715, 177, 1), + (6716, 177, 1), + (6755, 184, 3), + (6756, 184, 3), + (6757, 184, 3), + (6819, 524, 1), + (6820, 524, 1), + (6821, 524, 1), + (6823, 320, 1), + (6824, 320, 1), + (6825, 320, 1), + (6826, 320, 1), + (6827, 320, 1), + (6870, 544, 1), + (6871, 544, 1), + (6872, 544, 1), + (6873, 3837, 3), + (6874, 3837, 3), + (6875, 3837, 3), + (6876, 259, 3), + (6877, 259, 3), + (6878, 259, 3), + (6900, 465, 3), + (6901, 465, 3), + (6902, 465, 3), + (6903, 465, 3), + (6904, 465, 3), + (6908, 499, 1), + (6909, 499, 1), + (6910, 499, 1), + (6930, 611, 1), + (6935, 465, 3), + (6936, 465, 3), + (6937, 465, 3), + (6941, 962, 1), + (6942, 962, 1), + (6943, 962, 1), + (6944, 962, 1), + (6945, 962, 1), + (6977, 3817, 1), + (6978, 3817, 1), + (6979, 3817, 1), + (6980, 128, 1), + (6981, 128, 1), + (6982, 128, 1), + (6983, 245, 3), + (6988, 985, 1), + (6989, 985, 1), + (6990, 985, 1), + (7005, 789, 1), + (7006, 789, 1), + (7007, 789, 1), + (7033, 804, 1), + (7034, 804, 1), + (7035, 804, 1), + (7036, 3646, 1), + (7037, 3646, 1), + (7038, 3646, 1), + (7050, 26, 3), + (7051, 26, 3), + (7052, 26, 3), + (7053, 26, 3), + (7054, 26, 3), + (7055, 26, 3), + (7063, 26, 3), + (7064, 26, 3), + (7065, 26, 3), + (7100, 254, 3), + (7101, 254, 3), + (7102, 254, 3), + (7103, 286, 1), + (7104, 286, 1), + (7105, 286, 1), + (7116, 110, 1), + (7117, 110, 1), + (7118, 110, 1), + (7122, 435, 3), + (7123, 435, 3), + (7124, 435, 3), + (7125, 435, 3), + (7126, 435, 3), + (7128, 109, 1), + (7129, 109, 1), + (7130, 109, 1), + (7134, 439, 3), + (7135, 439, 3), + (7136, 439, 3), + (7137, 672, 1), + (7138, 672, 1), + (7139, 672, 1), + (7184, 1685, 1), + (7199, 175, 3), + (7200, 175, 3), + (7201, 175, 3), + (7204, 278, 5), + (7205, 278, 5), + (7206, 278, 5), + (7207, 278, 5), + (7208, 278, 5), + (7215, 68, 1), + (7216, 68, 1), + (7232, 114, 6), + (7233, 114, 6), + (7234, 114, 6), + (7246, 794, 1), + (7247, 794, 1), + (7248, 794, 1), + (7253, 784, 1), + (7254, 785, 1), + (7255, 786, 1), + (7256, 787, 1), + (7260, 60, 1), + (7261, 60, 1), + (7262, 60, 1), + (7263, 58, 1), + (7264, 58, 1), + (7265, 58, 1), + (7266, 125, 1), + (7276, 217, 1), + (7277, 217, 1), + (7278, 217, 1), + (7285, 173, 3), + (7286, 173, 3), + (7287, 173, 3), + (7288, 409, 3), + (7289, 409, 3), + (7290, 409, 3), + (7291, 173, 8), + (7292, 173, 8), + (7293, 173, 8), + (7301, 19, 3), + (7302, 19, 3), + (7303, 19, 3), + (7310, 255, 5), + (7311, 255, 5), + (7312, 255, 5), + (7316, 41, 1), + (7317, 41, 1), + (7323, 254, 3), + (7324, 254, 3), + (7325, 254, 3), + (7326, 286, 1), + (7327, 286, 1), + (7328, 286, 1), + (7329, 6001, 11), + (7330, 6001, 11), + (7331, 6001, 11), + (7335, 702, 1), + (7359, 82, 1), + (7360, 82, 1), + (7361, 82, 1), + (7378, 82, 3), + (7379, 82, 3), + (7380, 82, 3), + (7381, 82, 3), + (7382, 82, 3), + (7383, 82, 3), + (7390, 87, 1), + (7391, 87, 1), + (7392, 87, 1), + (7407, 31, 3), + (7414, 185, 6), + (7415, 185, 6), + (7416, 185, 6), + (7433, 30, 1), + (7434, 30, 1), + (7435, 30, 1), + (7436, 30, 1), + (7437, 30, 1), + (7445, 187, 5), + (7446, 187, 5), + (7447, 187, 5), + (7448, 553, 1), + (7449, 553, 1), + (7450, 553, 1), + (7451, 777, 1), + (7452, 777, 1), + (7453, 777, 1), + (7466, 224, 3), + (7472, 447, 3), + (7473, 447, 3), + (7474, 447, 3), + (7478, 245, 3), + (7497, 128, 3), + (7498, 128, 3), + (7499, 128, 3), + (7554, 19, 7), + (7555, 19, 7), + (7556, 19, 7), + (7557, 19, 7), + (7558, 19, 7), + (7562, 30, 6), + (7563, 30, 6), + (7564, 30, 6), + (7581, 215, 6), + (7582, 215, 6), + (7583, 215, 6), + (7615, 494, 3), + (7616, 494, 3), + (7617, 494, 3), + (7618, 500, 3), + (7619, 500, 3), + (7620, 500, 3), + (7621, 20, 1), + (7622, 26, 3), + (7623, 26, 3), + (7624, 26, 3), + (7631, 309, 3), + (7632, 309, 3), + (7633, 309, 3), + (7650, 310, 6), + (7651, 310, 6), + (7652, 310, 6), + (7653, 311, 3), + (7654, 311, 3), + (7655, 311, 3), + (7656, 309, 6), + (7657, 309, 6), + (7658, 309, 6), + (7659, 153, 3), + (7660, 153, 3), + (7661, 153, 3), + (7664, 170, 3), + (7665, 170, 3), + (7666, 170, 3), + (7667, 170, 3), + (7668, 170, 3), + (7682, 68, 1), + (7686, 435, 3), + (7687, 435, 3), + (7688, 435, 3), + (7691, 224, 3), + (7695, 862, 3), + (7696, 862, 3), + (7697, 862, 3), + (7700, 310, 3), + (7701, 310, 3), + (7702, 310, 3), + (7704, 3707, 1), + (7705, 3707, 1), + (7706, 3707, 1), + (7707, 87, 1), + (7708, 87, 1), + (7709, 87, 1), + (7710, 702, 1), + (7711, 702, 1), + (7712, 3826, 1), + (7715, 901, 1), + (7716, 901, 1), + (7717, 901, 1), + (7718, 125, 1), + (7722, 19, 7), + (7723, 19, 7), + (7724, 19, 7), + (7725, 19, 7), + (7726, 19, 7), + (7733, 195, 3), + (7743, 184, 1), + (7744, 184, 1), + (7745, 184, 1), + (7748, 13, 5), + (7749, 13, 5), + (7750, 13, 5), + (7751, 2234, 1), + (7752, 2234, 1), + (7753, 2234, 1), + (7754, 85, 1), + (7757, 9403, 1), + (7758, 9403, 1), + (7759, 9403, 1), + (7760, 824, 1), + (7761, 824, 1), + (7762, 824, 1), + (7765, 7689, 1), + (7766, 7689, 1), + (7767, 7689, 1), + (7768, 7689, 1), + (7770, 19, 3), + (7771, 19, 3), + (7772, 19, 3), + (7773, 19, 3), + (7774, 19, 3), + (7775, 19, 3), + (7822, 1154, 1), + (7823, 1154, 1), + (7824, 1154, 1), + (7825, 1154, 1), + (7826, 1154, 1), + (7827, 1404, 3), + (7832, 60, 1), + (7833, 60, 1), + (7834, 60, 1), + (7835, 60, 1), + (7836, 60, 1), + (7842, 19, 7), + (7843, 19, 7), + (7844, 19, 7), + (7940, 558, 1), + (7941, 558, 1), + (7942, 558, 1), + (7943, 39, 1), + (7944, 41, 1), + (7951, 19, 3), + (7952, 19, 3), + (7953, 19, 3), + (7983, 520, 1), + (7984, 520, 1), + (7985, 520, 1), + (7986, 705, 1), + (7987, 705, 1), + (7988, 705, 1), + (7989, 1092, 1), + (7990, 1092, 1), + (7991, 1092, 1), + (7992, 1092, 1), + (7993, 39, 1), + (7994, 39, 1), + (7995, 39, 1), + (8031, 791, 1), + (8032, 791, 1), + (8033, 791, 1), + (8035, 521, 1), + (8036, 521, 1), + (8037, 521, 1), + (8069, 160, 4), + (8070, 160, 4), + (8071, 160, 4), + (8076, 565, 1), + (8077, 565, 1), + (8078, 565, 1), + (8079, 565, 1), + (8080, 565, 1), + (8081, 565, 1), + (8082, 208, 1), + (8083, 208, 1), + (8084, 208, 1), + (8195, 3707, 1), + (8196, 3707, 1), + (8197, 3707, 1), + (8198, 210, 1), + (8199, 210, 1), + (8200, 210, 1), + (8204, 153, 1), + (8205, 153, 1), + (8206, 153, 1), + (8207, 285, 1), + (8208, 285, 1), + (8209, 285, 1), + (8220, 3812, 1), + (8224, 516, 3), + (8225, 516, 3), + (8226, 516, 3), + (8260, 1211, 1), + (8263, 142, 20), + (8264, 142, 20), + (8265, 142, 20), + (8266, 142, 20), + (8267, 142, 20), + (8268, 142, 20), + (8269, 142, 20), + (8270, 142, 20), + (8271, 142, 20), + (8272, 142, 20), + (8273, 142, 20), + (8274, 142, 20), + (8275, 142, 20), + (8276, 142, 20), + (8277, 142, 20), + (8278, 142, 20), + (8279, 142, 20), + (8280, 142, 20), + (8281, 142, 20), + (8282, 142, 20), + (8283, 142, 20), + (8284, 142, 20), + (8285, 142, 20), + (8286, 142, 20), + (8287, 142, 20), + (8288, 142, 20), + (8289, 142, 20), + (8290, 142, 20), + (8291, 142, 20), + (8292, 142, 20), + (8293, 142, 20), + (8294, 142, 20), + (8295, 142, 20), + (8296, 142, 20), + (8297, 142, 20), + (8303, 309, 6), + (8309, 31, 3), + (8310, 31, 3), + (8311, 31, 3), + (8312, 110, 1), + (8317, 8205, 1), + (8318, 8205, 1), + (8319, 199, 1), + (8320, 199, 1), + (8321, 199, 1), + (8332, 861, 1), + (8333, 861, 1), + (8334, 861, 1), + (8335, 1041, 1), + (8336, 1041, 1), + (8337, 1041, 1), + (8338, 1041, 1), + (8339, 1041, 1), + (8344, 215, 6), + (8345, 215, 6), + (8346, 215, 6), + (8347, 616, 1), + (8348, 616, 1), + (8349, 616, 1), + (8351, 142, 20), + (8352, 142, 20), + (8353, 142, 20), + (8354, 142, 20), + (8355, 142, 20), + (8356, 142, 20), + (8357, 142, 20), + (8358, 142, 20), + (8359, 142, 20), + (8360, 142, 20), + (8361, 142, 20), + (8362, 142, 20), + (8363, 142, 20), + (8364, 142, 20), + (8365, 142, 20), + (8366, 142, 20), + (8367, 142, 20), + (8368, 142, 20), + (8369, 142, 20), + (8370, 142, 20), + (8371, 142, 20), + (8372, 142, 20), + (8373, 142, 20), + (8374, 142, 20), + (8375, 142, 20), + (8376, 142, 20), + (8377, 142, 20), + (8378, 142, 20), + (8379, 142, 20), + (8380, 142, 20), + (8381, 142, 20), + (8382, 142, 20), + (8383, 142, 20), + (8384, 142, 20), + (8385, 142, 20), + (8386, 142, 20), + (8387, 142, 20), + (8388, 142, 20), + (8389, 142, 20), + (8390, 142, 20), + (8391, 142, 20), + (8392, 142, 20), + (8393, 142, 20), + (8394, 142, 20), + (8395, 142, 20), + (8396, 142, 20), + (8397, 142, 20), + (8398, 142, 20), + (8399, 142, 20), + (8400, 142, 20), + (8401, 142, 20), + (8402, 142, 20), + (8403, 142, 20), + (8404, 142, 20), + (8405, 142, 20), + (8406, 142, 20), + (8407, 142, 20), + (8408, 142, 20), + (8409, 142, 20), + (8410, 142, 20), + (8411, 142, 20), + (8412, 142, 20), + (8413, 142, 20), + (8414, 142, 20), + (8415, 142, 20), + (8416, 142, 20), + (8417, 142, 20), + (8418, 142, 20), + (8419, 142, 20), + (8420, 142, 20), + (8421, 516, 3), + (8427, 254, 3), + (8428, 254, 3), + (8429, 254, 3), + (9103, 1350, 3), + (9104, 1350, 3), + (9105, 1350, 3), + (9106, 1351, 3), + (9107, 1351, 3), + (9108, 1351, 3), + (9112, 1390, 3), + (9113, 1390, 3), + (9114, 1390, 3), + (9115, 1391, 3), + (9116, 1391, 3), + (9117, 1391, 3), + (9121, 1370, 3), + (9122, 1370, 3), + (9123, 1370, 3), + (9124, 1371, 3), + (9125, 1371, 3), + (9126, 1371, 3), + (9130, 1380, 3), + (9131, 1380, 3), + (9132, 1380, 3), + (9133, 1381, 3), + (9134, 1381, 3), + (9135, 1381, 3), + (9139, 1470, 3), + (9140, 1470, 3), + (9141, 1470, 3), + (9142, 1471, 3), + (9143, 1471, 3), + (9144, 1471, 3), + (9148, 1480, 3), + (9149, 1480, 3), + (9150, 1480, 3), + (9151, 1481, 3), + (9152, 1481, 3), + (9153, 1481, 3), + (9157, 1490, 3), + (9158, 1490, 3), + (9159, 1490, 3), + (9160, 1491, 3), + (9161, 1491, 3), + (9162, 1491, 3), + (9166, 1460, 3), + (9167, 1460, 3), + (9168, 1460, 3), + (9169, 1461, 3), + (9170, 1461, 3), + (9171, 1461, 3), + (9175, 1450, 3), + (9176, 1450, 3), + (9177, 1450, 3), + (9178, 1451, 3), + (9179, 1451, 3), + (9180, 1451, 3), + (9184, 1440, 3), + (9185, 1440, 3), + (9186, 1440, 3), + (9187, 1441, 3), + (9188, 1441, 3), + (9189, 1441, 3), + (9193, 1420, 3), + (9194, 1420, 3), + (9195, 1420, 3), + (9196, 1421, 3), + (9197, 1421, 3), + (9198, 1421, 3), + (9202, 1430, 3), + (9203, 1430, 3), + (9204, 1430, 3), + (9205, 1431, 3), + (9206, 1431, 3), + (9207, 1431, 3), + (9211, 1400, 3), + (9212, 1400, 3), + (9213, 1400, 3), + (9214, 1401, 3), + (9215, 1401, 3), + (9216, 1401, 3), + (9220, 1360, 3), + (9221, 1360, 3), + (9222, 1360, 3), + (9223, 1361, 3), + (9224, 1361, 3), + (9225, 1361, 3), + (9229, 1500, 3), + (9230, 1500, 3), + (9231, 1500, 3), + (9232, 1501, 3), + (9233, 1501, 3), + (9234, 1501, 3), + (9238, 1410, 3), + (9239, 1410, 3), + (9240, 1410, 3), + (9241, 1411, 3), + (9242, 1411, 3), + (9243, 1411, 3), + (9300, 1300, 3), + (9301, 1300, 3), + (9302, 1300, 3), + (9303, 1300, 6), + (9304, 1300, 6), + (9305, 1300, 6), + (9306, 1300, 9), + (9307, 1300, 9), + (9308, 1300, 9), + (9309, 1313, 3), + (9310, 1313, 3), + (9311, 1313, 3), + (9312, 1313, 6), + (9313, 1313, 6), + (9314, 1313, 6), + (9315, 1313, 9), + (9316, 1313, 9), + (9317, 1313, 9), + (9318, 1302, 3), + (9319, 1302, 3), + (9320, 1302, 3), + (9321, 1302, 6), + (9322, 1302, 6), + (9323, 1302, 6), + (9324, 1302, 9), + (9325, 1302, 9), + (9326, 1302, 9), + (9327, 1303, 3), + (9328, 1303, 3), + (9329, 1303, 3), + (9330, 1303, 6), + (9331, 1303, 6), + (9332, 1303, 6), + (9333, 1303, 9), + (9334, 1303, 9), + (9335, 1303, 9), + (9336, 1301, 3), + (9337, 1301, 3), + (9338, 1301, 3), + (9339, 1301, 6), + (9340, 1301, 6), + (9341, 1301, 6), + (9342, 1301, 9), + (9343, 1301, 9), + (9344, 1301, 9), + (9345, 1312, 3), + (9346, 1312, 3), + (9347, 1312, 3), + (9348, 1312, 6), + (9349, 1312, 6), + (9350, 1312, 6), + (9351, 1312, 9), + (9352, 1312, 9), + (9353, 1312, 9), + (9354, 1315, 3), + (9355, 1315, 3), + (9356, 1315, 3), + (9357, 1315, 6), + (9358, 1315, 6), + (9359, 1315, 6), + (9360, 1315, 9), + (9361, 1315, 9), + (9362, 1315, 9), + (9363, 1310, 3), + (9364, 1310, 3), + (9365, 1310, 3), + (9366, 1310, 6), + (9367, 1310, 6), + (9368, 1310, 6), + (9369, 1310, 9), + (9370, 1310, 9), + (9371, 1310, 9), + (9372, 1311, 3), + (9373, 1311, 3), + (9374, 1311, 3), + (9375, 1311, 6), + (9376, 1311, 6), + (9377, 1311, 6), + (9378, 1311, 9), + (9379, 1311, 9), + (9380, 1311, 9), + (9381, 1309, 3), + (9382, 1309, 3), + (9383, 1309, 3), + (9384, 1309, 6), + (9385, 1309, 6), + (9386, 1309, 6), + (9387, 1309, 9), + (9388, 1309, 9), + (9389, 1309, 9), + (9390, 1308, 3), + (9391, 1308, 3), + (9392, 1308, 3), + (9393, 1308, 6), + (9394, 1308, 6), + (9395, 1308, 6), + (9396, 1308, 9), + (9397, 1308, 9), + (9398, 1308, 9), + (9399, 1307, 3), + (9400, 1307, 3), + (9401, 1307, 3), + (9402, 1307, 6), + (9403, 1307, 6), + (9404, 1307, 6), + (9405, 1307, 9), + (9406, 1307, 9), + (9407, 1307, 9), + (9408, 1304, 3), + (9409, 1304, 3), + (9410, 1304, 3), + (9411, 1304, 6), + (9412, 1304, 6), + (9413, 1304, 6), + (9414, 1304, 9), + (9415, 1304, 9), + (9416, 1304, 9), + (9417, 1305, 3), + (9418, 1305, 3), + (9419, 1305, 3), + (9420, 1305, 6), + (9421, 1305, 6), + (9422, 1305, 6), + (9423, 1305, 9), + (9424, 1305, 9), + (9425, 1305, 9), + (9426, 1306, 3), + (9427, 1306, 3), + (9428, 1306, 3), + (9429, 1306, 6), + (9430, 1306, 6), + (9431, 1306, 6), + (9432, 1306, 9), + (9433, 1306, 9), + (9434, 1306, 9), + (9435, 1314, 3), + (9436, 1314, 3), + (9437, 1314, 3), + (9438, 1314, 6), + (9439, 1314, 6), + (9440, 1314, 6), + (9441, 1314, 9), + (9442, 1314, 9), + (9443, 1314, 9), + (9500, 72, 1), + (10016, 19, 3), + (10017, 19, 3), + (10018, 19, 3), + (10030, 558, 1), + (10031, 558, 1), + (10032, 558, 1), + (10038, 19, 3), + (10039, 19, 3), + (10040, 19, 3), + (10041, 358, 3), + (10042, 358, 3), + (10043, 358, 3), + (10047, 6001, 11), + (10048, 6001, 11), + (10049, 6001, 11), + (10064, 82, 3), + (10065, 82, 3), + (10066, 82, 3), + (10067, 82, 3), + (10068, 82, 3), + (10069, 82, 3), + (10070, 278, 5), + (10071, 278, 5), + (10072, 278, 5), + (10073, 278, 5), + (10074, 278, 5), + (10093, 185, 6), + (10105, 170, 3), + (10106, 170, 3), + (10107, 170, 3), + (10108, 170, 3), + (10109, 170, 3), + (10110, 520, 1), + (10111, 520, 1), + (10112, 520, 1), + (10130, 544, 1), + (10131, 544, 1), + (10132, 544, 1), + (10133, 3837, 3), + (10134, 3837, 3), + (10135, 3837, 3), + (10136, 259, 3), + (10137, 259, 3), + (10138, 259, 3), + (10150, 187, 5), + (10151, 187, 5), + (10152, 187, 5), + (10153, 553, 1), + (10154, 553, 1), + (10155, 553, 1), + (10165, 439, 3), + (10166, 439, 3), + (10167, 439, 3), + (10176, 171, 1), + (10177, 171, 1), + (10178, 171, 1), + (10182, 177, 1), + (10183, 177, 1), + (10184, 177, 1), + (10185, 177, 1), + (10186, 177, 1), + (10197, 447, 3), + (10198, 447, 3), + (10199, 447, 3), + (10203, 524, 1), + (10204, 524, 1), + (10205, 524, 1), + (10206, 320, 1), + (10207, 320, 1), + (10209, 175, 3), + (10210, 175, 3), + (10211, 175, 3), + (10213, 278, 5), + (10214, 278, 5), + (10215, 278, 5), + (10216, 278, 5), + (10217, 278, 5), + (10249, 208, 1), + (10250, 208, 1), + (10251, 208, 1), + (10255, 784, 1), + (10256, 785, 1), + (10257, 786, 1), + (10258, 787, 1), + (10262, 58, 1), + (10263, 58, 1), + (10264, 58, 1), + (10271, 173, 3), + (10272, 173, 3), + (10273, 173, 3), + (10274, 173, 8), + (10275, 173, 8), + (10276, 173, 8), + (10282, 791, 1), + (10283, 791, 1), + (10284, 791, 1), + (10285, 521, 1), + (10286, 521, 1), + (10287, 521, 1), + (10308, 128, 3), + (10309, 128, 3), + (10310, 128, 3), + (10329, 3701, 1), + (10330, 199, 3), + (10332, 943, 3), + (10336, 941, 1), + (10337, 941, 1), + (10338, 941, 1), + (10354, 6001, 17), + (10389, 841, 1), + (10390, 841, 1), + (10391, 841, 1), + (10396, 705, 4), + (10397, 1092, 4), + (10398, 3701, 1), + (10399, 3701, 1), + (10413, 207, 1), + (10414, 207, 1), + (10415, 207, 1), + (10416, 207, 1), + (10417, 207, 1), + (10426, 185, 18), + (10427, 519, 15), + (10428, 173, 8), + (10429, 173, 8), + (10430, 173, 8), + (10431, 791, 1), + (10432, 791, 1), + (10433, 791, 1), + (10434, 792, 1), + (10435, 792, 1), + (10436, 792, 1), + (10450, 19, 9), + (10451, 19, 9), + (10452, 19, 9), + (10456, 3800, 1), + (10457, 3800, 1), + (10458, 3800, 1), + (10462, 396, 1), + (10463, 396, 1), + (10464, 391, 9), + (10465, 391, 9), + (10466, 391, 9), + (10468, 19, 9), + (10469, 19, 9), + (10470, 558, 1), + (10471, 558, 1), + (10472, 558, 1), + (10473, 26, 3), + (10474, 26, 3), + (10475, 26, 3), + (10476, 26, 3), + (10477, 26, 3), + (10510, 705, 1), + (10511, 185, 3), + (10512, 185, 3), + (10513, 185, 3), + (10514, 519, 3), + (10515, 519, 3), + (10516, 519, 3), + (10519, 3213, 1), + (10522, 3732, 1), + (10527, 1400, 1), + (10532, 1401, 1), + (10537, 1402, 1), + (10548, 605, 13), + (10554, 263, 1), + (10555, 263, 1), + (10556, 263, 1), + (10557, 1120, 1), + (10558, 1120, 1), + (10559, 1120, 1), + (10560, 1120, 1), + (10561, 3551, 1), + (10562, 3551, 1), + (10563, 3551, 1), + (10564, 217, 1), + (10565, 217, 1), + (10566, 217, 1), + (10576, 109, 1), + (10579, 3646, 1), + (10580, 3646, 1), + (10588, 601, 1), + (10589, 601, 1), + (10590, 601, 1), + (10591, 601, 1), + (10592, 601, 1), + (10610, 265, 5), + (10611, 265, 5), + (10612, 265, 5), + (10621, 180, 3), + (10622, 180, 3), + (10623, 30, 3), + (10624, 30, 3), + (10625, 30, 3), + (10626, 702, 1), + (10646, 3826, 1), + (10657, 276, 3), + (10658, 276, 3), + (10659, 276, 3), + (10666, 98, 1), + (10667, 98, 1), + (10668, 98, 1), + (10670, 19, 9), + (10708, 6001, 11), + (10709, 6001, 11), + (10710, 6001, 11), + (10711, 30, 6), + (10712, 30, 6), + (10713, 30, 6), + (10714, 873, 1), + (10715, 873, 1), + (10717, 184, 1), + (10718, 184, 1), + (10719, 872, 1), + (10720, 872, 1), + (10721, 872, 1), + (10722, 778, 1), + (10723, 778, 1), + (10724, 778, 1), + (10725, 778, 1), + (10726, 778, 1), + (10727, 2235, 1), + (10728, 2235, 1), + (10730, 870, 1), + (10731, 870, 1), + (10733, 219, 1), + (10734, 219, 1), + (10735, 219, 1), + (10750, 286, 1), + (10751, 286, 1), + (10752, 7108, 1), + (10753, 286, 1), + (10789, 10424, 1), + (10790, 705, 4), + (10791, 1092, 4), + (10800, 462, 3), + (10801, 462, 3), + (10802, 462, 3), + (10903, 125, 1), + (10904, 125, 1), + (10905, 125, 1), + (10909, 7007, 1), + (10910, 7007, 1), + (10911, 7007, 1), + (10915, 823, 3), + (10916, 823, 3), + (10917, 823, 3), + (10951, 447, 3), + (10952, 447, 3), + (10953, 447, 3), + (10954, 662, 3), + (10955, 662, 3), + (10956, 662, 3), + (11011, 3710, 1), + (11012, 3710, 1), + (11013, 3710, 1), + (11014, 3899, 1), + (11015, 3899, 1), + (11016, 3899, 1), + (11020, 3899, 1), + (11050, 452, 3), + (11051, 452, 3), + (11052, 452, 3), + (11053, 500, 3), + (11054, 500, 3), + (11059, 452, 3), + (11060, 452, 3), + (11077, 986, 1), + (11078, 988, 1), + (11079, 987, 1), + (11088, 505, 1), + (11089, 505, 1), + (11090, 505, 1), + (11091, 505, 1), + (12422, 1202, 1), + (12432, 23, 3), + (12433, 23, 3), + (12434, 23, 3), + (12435, 23, 3), + (12436, 23, 3), + (12437, 23, 3), + (12475, 7003, 1), + (12476, 7003, 1), + (12477, 7003, 1), + (12478, 3705, 9), + (12479, 3705, 9), + (12480, 3705, 9), + (12523, 114, 6), + (12526, 215, 6), + (12527, 215, 6), + (12528, 215, 6), + (12529, 358, 3), + (12530, 358, 3), + (12531, 358, 3), + (12553, 23, 3), + (12554, 23, 3), + (12555, 23, 3), + (12556, 23, 3), + (12557, 23, 3), + (12558, 23, 3), + (12582, 9400, 1), + (12583, 9400, 1), + (12584, 9400, 1), + (12587, 9403, 1), + (12588, 9403, 1), + (12589, 9403, 1), + (12600, 3514, 1), + (12606, 13, 5), + (12610, 310, 3), + (12626, 1410, 3), + (12629, 1411, 3), + (12632, 1412, 3), + (12635, 428, 2), + (12639, 519, 3), + (12642, 185, 3), + (12645, 519, 1), + (12646, 185, 1), + (12664, 3728, 1), + (12673, 420, 1), + (12677, 17, 3), + (12679, 276, 3), + (12680, 276, 3), + (12681, 276, 3), + (12697, 30, 6), + (12698, 30, 6), + (12699, 30, 6), + (12713, 8202, 1), + (12714, 8202, 1), + (12715, 8202, 1), + (12716, 3702, 1), + (12717, 3702, 1), + (12718, 3702, 1), + (12719, 3702, 1), + (12720, 3506, 1), + (12721, 3506, 1), + (12722, 3506, 1), + (12723, 3506, 1), + (12727, 359, 3), + (12728, 359, 3), + (12729, 359, 3), + (12730, 941, 1), + (12731, 941, 1), + (12732, 941, 1), + (12733, 943, 3), + (12734, 259, 3), + (12735, 259, 3), + (12736, 259, 3), + (12737, 3701, 1), + (12738, 3701, 1), + (12739, 3701, 1), + (12749, 30, 1), + (12750, 30, 1), + (12751, 30, 1), + (12757, 68, 1), + (12758, 68, 1), + (12759, 68, 1), + (12760, 175, 3), + (12761, 175, 3), + (12762, 175, 3), + (12773, 1580, 1), + (12774, 1580, 1), + (12775, 1580, 1), + (12776, 1580, 1), + (12777, 1580, 1), + (12779, 826, 1), + (12780, 826, 1), + (12781, 826, 1), + (12782, 826, 1), + (12783, 826, 1), + (12784, 826, 1), + (12798, 278, 5), + (12799, 278, 5), + (12800, 278, 5), + (12831, 128, 1), + (12834, 128, 1), + (12835, 128, 1), + (12840, 3817, 1), + (12841, 3817, 1), + (12849, 8303, 1), + (12860, 23, 3), + (12863, 23, 3), + (12865, 1155, 1), + (12866, 639, 1), + (12867, 6106, 6), + (12871, 452, 3), + (12872, 452, 3), + (12874, 451, 1), + (12876, 7003, 1), + (12877, 7003, 1), + (12878, 7003, 1), + (12881, 172, 1), + (12886, 304, 5), + (12887, 303, 5), + (12888, 305, 5), + (12889, 501, 1), + (12890, 507, 1), + (12892, 509, 3), + (12894, 1122, 1), + (12899, 57, 1), + (12900, 57, 1), + (12902, 1380, 1), + (12903, 1380, 1), + (12907, 1381, 1), + (12908, 1381, 1), + (12912, 1382, 1), + (12913, 1382, 1), + (12934, 173, 3), + (12956, 784, 1), + (12957, 786, 1), + (12958, 787, 1), + (12959, 785, 1), + (12964, 596, 1), + (12965, 597, 1), + (12968, 1041, 1), + (12969, 1041, 1), + (12970, 1041, 1), + (12977, 1041, 1), + (12978, 1041, 1), + (12979, 1041, 1), + (12980, 1041, 1), + (12981, 1041, 1), + (12992, 707, 4), + (12993, 707, 4), + (12994, 707, 4), + (13001, 9504, 1), + (13002, 9504, 1), + (13003, 9504, 1), + (13004, 153, 9), + (13005, 171, 1), + (13006, 171, 1), + (13007, 171, 1), + (13008, 859, 1), + (13009, 3730, 1), + (13010, 47, 1), + (13011, 47, 1), + (13012, 47, 1), + (13013, 446, 1), + (13014, 446, 1), + (13015, 446, 1), + (13017, 3815, 10), + (13018, 3815, 10), + (13019, 3815, 10), + (13023, 309, 6), + (13055, 8400, 1), + (13067, 643, 1), + (13072, 3514, 1), + (13073, 3514, 1), + (13074, 310, 6), + (13075, 310, 6), + (13076, 310, 6), + (13077, 311, 3), + (13078, 311, 3), + (13090, 20, 1), + (13092, 82, 1), + (13093, 82, 1), + (13094, 82, 1), + (13104, 87, 1), + (13105, 87, 1), + (13106, 87, 1), + (13130, 1685, 1), + (13140, 391, 9), + (13141, 391, 9), + (13142, 391, 9), + (13143, 500, 1), + (13144, 500, 1), + (13145, 500, 1), + (13146, 494, 1), + (13147, 494, 1), + (13148, 494, 1), + (13155, 705, 1), + (13166, 822, 1), + (13167, 822, 1), + (13168, 822, 1), + (13170, 128, 3), + (13190, 187, 5), + (13191, 187, 5), + (13192, 187, 5), + (13196, 3837, 3), + (13197, 3837, 3), + (13198, 3837, 3), + (13203, 199, 3), + (13204, 8261, 1), + (13205, 8261, 1), + (13206, 8261, 1), + (13213, 439, 3), + (13214, 439, 3), + (13215, 439, 3), + (13216, 439, 3), + (13217, 439, 3), + (13222, 3514, 1), + (13223, 3514, 1), + (13241, 173, 8), + (13244, 46, 1), + (13247, 409, 3), + (13253, 58, 1), + (13254, 58, 1), + (13255, 58, 1), + (13256, 224, 3), + (13257, 224, 3), + (13258, 224, 3), + (13262, 102, 1), + (13263, 102, 1), + (13264, 102, 1), + (13271, 1685, 1), + (13272, 1685, 1), + (13295, 20, 1), + (13308, 26, 3), + (13326, 310, 6), + (13326, 1685, 1), + (13332, 30, 6), + (13363, 1685, 1), + (13383, 1685, 1), + (13385, 1685, 1), + (13388, 1685, 1), + (13389, 1685, 1), + (13396, 1685, 1), + (13396, 3815, 10), + (13401, 1685, 1), + (13404, 259, 6), + (13404, 1685, 1), + (13410, 1685, 1), + (13413, 1685, 1), + (13415, 1092, 1), + (13415, 1685, 1), + (13416, 626, 1), + (13416, 1685, 1), + (13419, 1685, 1), + (13425, 1685, 1), + (13444, 1685, 1), + (13447, 1685, 1), + (13449, 1685, 1), + (13449, 11073, 1), + (13454, 1685, 1), + (13463, 458, 1), + (13463, 1685, 1), + (13466, 1685, 1), + (13467, 1685, 1), + (13468, 1685, 1), + (13472, 1685, 1), + (13474, 444, 1), + (13474, 1685, 1), + (13477, 1685, 1), + (13483, 1685, 1), + (13484, 1685, 1), + (13485, 1685, 1), + (13490, 1685, 1), + (13492, 199, 3), + (13492, 1685, 1), + (13493, 1685, 1), + (13496, 187, 5), + (13496, 1685, 1), + (13499, 30, 1), + (13499, 1685, 1), + (13502, 259, 3), + (13502, 1685, 1), + (13505, 1685, 1), + (13508, 1685, 1), + (13511, 1685, 1), + (13511, 3837, 3), + (13514, 1685, 1), + (13517, 941, 1), + (13517, 1685, 1), + (13520, 1685, 1), + (13521, 1685, 1), + (13524, 1685, 1), + (13527, 1685, 1), + (13528, 1685, 1), + (13529, 1685, 1), + (13530, 1685, 1), + (13533, 1685, 1), + (13542, 184, 3), + (13542, 1685, 1), + (13545, 1685, 1), + (13546, 1685, 1), + (13549, 1685, 1), + (13556, 1685, 1), + (13562, 872, 1), + (13562, 1685, 1), + (13565, 1685, 1), + (13565, 3804, 1), + (13568, 876, 1), + (13568, 1685, 1), + (13571, 1685, 1), + (13575, 1685, 1), + (13578, 1685, 1), + (13584, 1685, 1), + (13585, 1685, 1), + (13585, 3826, 1), + (13586, 1685, 1), + (13589, 30, 3), + (13589, 1685, 1), + (13590, 30, 3), + (13590, 1685, 1), + (13592, 702, 1), + (13592, 1685, 1), + (13595, 1685, 1), + (13595, 6001, 11), + (13598, 1685, 1), + (13601, 1685, 1), + (13604, 1685, 1), + (13607, 1685, 1), + (13610, 1685, 1), + (13613, 1685, 1), + (13616, 1685, 1), + (13617, 1685, 1), + (13618, 1685, 1), + (13619, 1685, 1), + (13621, 278, 5), + (13621, 1685, 1), + (13624, 1685, 1), + (13627, 1685, 1), + (13628, 1685, 1), + (13630, 1685, 1), + (13633, 1685, 1), + (13646, 1668, 1), + (13646, 1685, 1), + (13650, 1685, 1), + (13653, 1685, 1), + (13656, 1685, 1), + (13663, 1685, 1), + (13667, 500, 1), + (13667, 1685, 1), + (13670, 1685, 1), + (13673, 1158, 1), + (13674, 7754, 1), + (13675, 278, 5), + (13675, 1685, 1), + (13678, 1685, 1), + (13682, 1685, 1), + (13683, 1685, 1), + (13684, 1685, 1), + (13685, 1685, 1), + (13686, 1685, 1), + (13687, 1685, 1), + (13688, 1685, 1), + (13689, 751, 1), + (13689, 1685, 1), + (13692, 1685, 1), + (13693, 1685, 1), + (13695, 1685, 1), + (13698, 784, 1), + (13698, 1685, 1), + (13701, 785, 1), + (13701, 1685, 1), + (13704, 787, 1), + (13704, 1685, 1), + (13707, 58, 1), + (13707, 1685, 1), + (13710, 1685, 1), + (13713, 1685, 1), + (13718, 1685, 1), + (13720, 1685, 1), + (13723, 58, 1), + (13723, 1685, 1), + (13726, 1685, 1), + (13727, 25, 3), + (13727, 1685, 1), + (13734, 217, 1), + (13734, 1685, 1), + (13753, 534, 1), + (13753, 1685, 1), + (13758, 602, 1), + (13758, 1685, 1), + (13763, 1685, 1), + (13764, 535, 1), + (13764, 1685, 1), + (13767, 1685, 1), + (13770, 1685, 1), + (13771, 1685, 1), + (13773, 310, 3), + (13773, 1685, 1), + (13774, 310, 3), + (13774, 1685, 1), + (13775, 310, 3), + (13775, 1685, 1), + (13779, 1685, 1), + (13782, 439, 3), + (13782, 1685, 1), + (13785, 1685, 1), + (13789, 1685, 1), + (13790, 1685, 1), + (13792, 1685, 1), + (13795, 1685, 1), + (13798, 1685, 1), + (13804, 1685, 1), + (13807, 1685, 1), + (13810, 1685, 1), + (13813, 1685, 1), + (13816, 1685, 1), + (13819, 1685, 1), + (13820, 1685, 1), + (13823, 1685, 1), + (13826, 1685, 1), + (13829, 1685, 1), + (13832, 1685, 1), + (13835, 1685, 1), + (13838, 1685, 1), + (13841, 1685, 1), + (13845, 1685, 1), + (13872, 1685, 1), + (13873, 961, 1), + (13873, 1685, 1), + (13878, 609, 1), + (13878, 1685, 1), + (13881, 387, 1), + (13881, 1685, 1), + (13889, 1012, 1), + (13889, 1685, 1), + (13899, 1685, 1), + (13905, 1685, 1), + (13908, 1685, 1), + (13911, 1685, 1), + (13914, 1685, 1), + (13917, 606, 1), + (13917, 1685, 1), + (13920, 125, 1), + (13920, 1685, 1), + (13933, 142, 20), + (13943, 142, 20), + (13953, 142, 20), + (13963, 142, 20), + (13973, 142, 20), + (13983, 142, 20), + (13993, 142, 20), + (14003, 1685, 1), + (14006, 30, 6), + (14006, 1685, 1), + (14009, 1685, 1), + (14010, 1685, 1), + (14011, 1685, 1), + (14011, 10394, 1), + (14016, 1685, 1), + (14016, 6001, 17), + (14018, 1684, 1), + (14019, 1685, 1), + (14026, 1685, 1), + (14029, 1685, 1), + (14032, 1685, 1), + (14037, 804, 1), + (14037, 1685, 1), + (14040, 300, 1), + (14040, 1685, 1), + (14043, 1685, 1), + (14046, 87, 1), + (14046, 1685, 1), + (14051, 1685, 1), + (14052, 1685, 1), + (14053, 1685, 1), + (14054, 1685, 1), + (14055, 1685, 1), + (14056, 1685, 1), + (14059, 1685, 1), + (14062, 821, 1), + (14062, 1685, 1), + (14065, 1685, 1), + (14065, 3215, 1), + (14068, 1685, 1), + (14068, 3216, 1), + (14071, 1685, 1), + (14076, 1685, 1), + (14080, 1685, 1), + (14081, 1685, 1), + (14082, 1685, 1), + (14085, 741, 1), + (14085, 1685, 1), + (14088, 769, 1), + (14088, 1685, 1), + (14091, 701, 1), + (14091, 1685, 1), + (14094, 1685, 1), + (14097, 1685, 1), + (14100, 1685, 1), + (14101, 1685, 1), + (14111, 1685, 1), + (14112, 1685, 1), + (14115, 872, 1), + (14115, 1685, 1), + (14129, 1685, 1), + (14130, 1685, 1), + (14132, 1685, 1), + (14132, 2234, 1), + (14135, 1685, 1), + (14138, 1685, 1), + (14139, 1685, 1), + (14140, 1685, 1), + (14141, 1685, 1), + (14144, 1685, 1), + (14144, 3515, 1), + (14148, 1685, 1), + (14151, 1685, 1), + (14154, 276, 3), + (14154, 1685, 1), + (14157, 1685, 1), + (14160, 1685, 1), + (14160, 7001, 1), + (14163, 1685, 1), + (14163, 7001, 1), + (14166, 945, 1), + (14166, 1685, 1), + (14169, 1685, 1), + (14173, 1685, 1), + (14176, 1685, 1), + (14176, 8261, 1), + (14179, 359, 1), + (14179, 1685, 1), + (14180, 1685, 1), + (14181, 1685, 1), + (14181, 3837, 12), + (14186, 809, 5), + (14186, 1685, 1), + (14189, 1685, 1), + (14192, 1685, 1), + (14196, 465, 3), + (14196, 1685, 1), + (14199, 499, 1), + (14199, 1685, 1), + (14200, 1685, 1), + (14203, 1685, 1), + (14206, 1685, 1), + (14207, 1685, 1), + (14208, 1685, 1), + (14208, 7689, 1), + (14209, 1685, 1), + (14210, 1685, 1), + (14213, 1065, 1), + (14213, 1685, 1), + (14218, 1685, 1), + (14221, 1685, 1), + (14222, 224, 3), + (14222, 1685, 1), + (14223, 47, 1), + (14223, 1685, 1), + (14224, 1685, 1), + (14225, 177, 1), + (14225, 1685, 1), + (14229, 135, 1), + (14231, 1685, 1), + (14232, 1685, 1), + (14233, 1685, 1), + (14234, 1685, 1), + (14237, 1685, 1), + (14238, 1041, 1), + (14238, 1685, 1), + (14241, 386, 1), + (14241, 1685, 1), + (14244, 1685, 1), + (14249, 1685, 1), + (14254, 386, 1), + (14254, 1685, 1), + (14256, 1685, 1), + (14259, 384, 1), + (14259, 1685, 1), + (14265, 939, 1), + (14265, 1685, 1), + (14272, 1685, 1), + (14273, 1685, 1), + (14274, 1685, 1), + (14275, 1685, 1), + (14278, 985, 1), + (14278, 1685, 1), + (14280, 57, 1), + (14280, 1685, 1), + (14281, 291, 1), + (14281, 1685, 1), + (14282, 1685, 1), + (14282, 3812, 1), + (14283, 1685, 1), + (14286, 753, 1), + (14286, 1685, 1), + (14289, 1685, 1), + (14292, 207, 1), + (14292, 1685, 1), + (14295, 1685, 1), + (14295, 3816, 1), + (14304, 1685, 1), + (14304, 8341, 1), + (14307, 1685, 1), + (14308, 431, 1), + (14308, 1685, 1), + (14311, 430, 1), + (14311, 1685, 1), + (14314, 901, 1), + (14314, 1685, 1), + (14318, 1685, 1), + (14318, 7703, 1), + (14321, 1685, 1), + (14322, 1685, 1), + (14323, 1685, 1), + (14324, 1685, 1), + (14328, 1154, 1), + (14328, 1685, 1), + (14331, 515, 1), + (14331, 1685, 1), + (14338, 308, 3), + (14338, 1685, 1), + (14341, 748, 1), + (14341, 1685, 1), + (14346, 1685, 1), + (14349, 215, 6), + (14352, 175, 3), + (14352, 1685, 1), + (14355, 1685, 1), + (14358, 1685, 1), + (14359, 1685, 1), + (14360, 1685, 1), + (14361, 23, 3), + (14364, 173, 1), + (14364, 1685, 1), + (14372, 1685, 1), + (14690, 756, 1), + (14733, 786, 1), + (15100, 467, 1), + (15105, 131, 1), + (15113, 130, 1), + (15120, 800, 1), + (15132, 660, 1), + (15135, 660, 1), + (15141, 30, 3), + (15147, 701, 13), + (15154, 659, 1), + (15158, 657, 1), + (15159, 770, 1), + (15162, 659, 1), + (15168, 657, 1), + (15174, 9400, 1), + (15179, 7755, 1), + (15182, 9403, 1), + (15204, 390, 1), + (15207, 323, 1), + (15210, 1041, 1), + (15220, 622, 1), + (15223, 624, 1), + (15226, 621, 1), + (15229, 623, 1), + (15253, 462, 1), + (15258, 184, 1), + (15270, 7003, 1), + (15280, 778, 1), + (15295, 2234, 1), + (15314, 36, 1), + (15317, 35, 1), + (15320, 558, 1), + (15341, 19, 3), + (15342, 8500, 1), + (15344, 38, 1), + (15348, 9504, 1), + (15356, 149, 1), + (15358, 151, 1), + (15359, 50, 1), + (15363, 447, 3), + (15371, 3729, 1), + (15377, 638, 1), + (15389, 935, 1), + (15396, 23, 3), + (15397, 494, 3), + (15403, 8604, 1), + (15406, 3817, 1), + (15414, 241, 1), + (15421, 245, 3), + (15424, 247, 1), + (15424, 982, 6), + (15466, 3551, 1), + (15469, 1120, 1), + (15472, 521, 1), + (15478, 578, 1), + (15481, 398, 24), + (15482, 261, 1), + (15485, 495, 9), + (15486, 534, 3), + (15526, 3702, 1), + (15549, 244, 1), + (15552, 3710, 1), + (15571, 351, 1), + (15579, 826, 1), + (15591, 2899, 1), + (15598, 759, 1), + (15598, 1150, 1), + (15598, 1151, 1), + (15598, 1152, 1), + (15605, 639, 1), + (15606, 160, 4), + (15622, 23, 3), + (15632, 789, 1), + (15639, 749, 1), + (15640, 822, 2), + (15746, 804, 1), + (15778, 87, 1), + (15833, 2045, 1), + (15836, 463, 1), + (15839, 19, 9), + (15855, 153, 9), + (15891, 988, 1), + (15893, 987, 1), + (15895, 986, 1), + (15961, 3701, 1), + (16062, 263, 1), + (16071, 2209, 3), + (16087, 53, 1), + (16094, 43, 1), + (16103, 7703, 1), + (16105, 684, 1), + (16106, 684, 1), + (16107, 684, 1), + (16117, 309, 6), + (16124, 3711, 1), + (16128, 3711, 1), + (16131, 73, 1), + (16137, 10394, 1), + (16140, 489, 1), + (16156, 137, 1), + (16159, 2045, 1), + (16163, 260, 1), + (16163, 7747, 1), + (16164, 358, 3), + (16176, 337, 1), + (16180, 584, 1), + (16185, 9202, 1), + (16185, 9203, 1), + (16189, 823, 3), + (16203, 403, 1), + (16211, 152, 1), + (16218, 403, 1), + (16221, 393, 1), + (16225, 219, 1), + (16238, 443, 1), + (16246, 245, 3), + (16249, 17, 3), + (16257, 470, 20), + (16266, 790, 1), + (16287, 669, 1), + (16297, 553, 1), + (16300, 668, 1), + (16303, 3506, 1), + (16306, 777, 1), + (16336, 1257, 1), + (16339, 773, 1), + (16342, 1257, 1), + (16371, 60, 1), + (16380, 2061, 1), + (16386, 2064, 1), + (16392, 2202, 1), + (16489, 23, 3), + (16604, 180, 3), + (16644, 747, 1), + (16666, 742, 1), + (16730, 82, 3), + (16745, 706, 1), + (17206, 601, 1), + (17209, 111, 1), + (17212, 10367, 1), + (17218, 744, 1), + (17235, 3826, 1), + (17280, 8205, 1), + (17281, 359, 1), + (17288, 41, 1), + (17289, 1062, 1), + (17307, 2047, 1), + (17317, 1270, 1), + (17334, 1041, 1), + (17336, 148, 1), + (17339, 760, 1), + (17342, 148, 1), + (17350, 170, 3), + (17361, 405, 1), + (17361, 426, 1), + (17364, 935, 4), + (17375, 1239, 1), + (17391, 98, 1), + (17409, 120, 1), + (17414, 673, 1), + (17436, 372, 1), + (17439, 372, 1), + (17441, 309, 3), + (17476, 462, 3), + (17492, 840, 1), + (17495, 9702, 1), + (17515, 3841, 1), + (17517, 441, 1), + (17522, 764, 1), + (17533, 677, 1), + (17549, 8700, 1); From bc525e33c526a7429d89a308ed16110c1a0de593 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Sep 2015 15:28:29 -0500 Subject: [PATCH 318/846] Fixed an issue where tints and weapons weren't being refreshed on Mob::SendIllusion triggers from scripts --- zone/mob.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 0b46c8b12..24f17a531 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1757,6 +1757,10 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture, entity_list.QueueClients(this, outapp); safe_delete(outapp); + + /* Refresh armor and tints after send illusion packet */ + this->SendArmorAppearance(); + Log.Out(Logs::Detail, Logs::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", race, gender, texture, helmtexture, haircolor, beardcolor, eyecolor1, eyecolor2, hairstyle, luclinface, drakkin_heritage, drakkin_tattoo, drakkin_details, size); } @@ -2751,12 +2755,12 @@ void Mob::SendArmorAppearance(Client *one_client) if (!IsClient()) { const Item_Struct *item; - for (int i=0; i< 7 ; ++i) + for (int i = 0; i < 7; ++i) { - item=database.GetItem(GetEquipment(i)); + item = database.GetItem(GetEquipment(i)); if (item != 0) { - SendWearChange(i,one_client); + SendWearChange(i, one_client); } } } From ccbaccd0c13e1b819e24b8ff3b0aa3f4c8832ad2 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 21 Sep 2015 20:28:48 -0400 Subject: [PATCH 319/846] Added the latest spell effects to spdat.h for future implementation. --- common/spdat.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/common/spdat.h b/common/spdat.h index 938b659e1..722a00033 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -613,12 +613,25 @@ typedef enum { #define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. #define SE_FactionModPct 458 // implemented Modifies faction gains and losses by percent. #define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type +//#define SE_Ff_Override_NotFocusable 460 // +//#define SE_Fc_Damage_%2 461 // +//#define SE_Fc_Damage_Amt2 462 // +//#define SE_Shield_Target 463 // +//#define SE_PC_Pet_Rampage 464 // +//#define SE_PC_Pet_AE_Rampage 465 // +//#define SE_PC_Pet_Flurry_Chance 466 // +//#define SE_DS_Mitigation_Amount 467 // +//#define SE_DS_Mitigation_Percentage 468 // +//#define SE_Chance_Best_in_Spell_Grp 469 // +//#define SE_Trigger_Best_in_Spell Grp 470 // +//#define SE_Double_Melee_Round 471 // + // LAST #define DF_Permanent 50 -#define DF_Aura 51 +#define DF_Aura 51 // note this struct is historical, we don't actually need it to be // aligned to anything, but for maintaining it it is kept in the order that From cc0d0cc1267205aaceb29b2898d1909259d77a0f Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 22 Sep 2015 03:02:24 -0400 Subject: [PATCH 320/846] Implemented spells_new field 217 override_crit_chance Determines the maximum chance this spell has to critical hit. Ie. If set to 15, the spell will never critical more then 15% of the time regardless of your characters innate chance to critcal from AAs. --- common/shareddb.cpp | 1 + common/spdat.h | 3 ++- zone/effects.cpp | 11 ++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 7301346c9..d5d42a174 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1671,6 +1671,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].AllowRest = atoi(row[212]) != 0; sp[tempid].InCombat = atoi(row[213]) != 0; sp[tempid].OutofCombat = atoi(row[214]) != 0; + sp[tempid].override_crit_chance = atoi(row[217]); sp[tempid].aemaxtargets = atoi(row[218]); sp[tempid].maxtargets = atoi(row[219]); sp[tempid].persistdeath = atoi(row[224]) != 0; diff --git a/common/spdat.h b/common/spdat.h index 722a00033..a469be2e7 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -761,7 +761,8 @@ struct SPDat_Spell_Struct /* 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 - 217 */ +/* 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 maxtargets; //Is used for beam and ring spells for target # limits (not implemented) /* 220 - 223 */ diff --git a/zone/effects.cpp b/zone/effects.cpp index a18e80428..08f0073cf 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -73,6 +73,9 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { if (spell_id == SPELL_IMP_HARM_TOUCH && IsClient() && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) chance = 100; + if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance) + chance = spells[spell_id].override_crit_chance; + if (zone->random.Roll(chance)) { Critical = true; ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease; @@ -161,7 +164,10 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { chance += itembonuses.CriticalDoTChance + spellbonuses.CriticalDoTChance + aabonuses.CriticalDoTChance; if (spellbonuses.CriticalDotDecay) - chance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay); + chance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay); + + if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance) + chance = spells[spell_id].override_crit_chance; value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100); @@ -260,6 +266,9 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (spellbonuses.CriticalHealDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); + if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance) + chance = spells[spell_id].override_crit_chance; + if(chance && (zone->random.Roll(chance))) { Critical = true; modifier = 2; //At present time no critical heal amount modifier SPA exists. From d0f9a14217de91f90670c80f6d6882b85176a1ca Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 24 Sep 2015 19:33:16 -0400 Subject: [PATCH 321/846] Revert "Fix likely dev typo in sinister strikes calc" This reverts commit 72aaf56c79337e44b1ff5e5543b1a41a6d6446a4. --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index d8343cb8d..171b8d2fe 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2681,7 +2681,7 @@ uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand) else if (delay >= 45) return 4 + ((level - 28) / 3) + ((delay - 40) / 3); } else { - return 1 + ((level - 28) / 3) + (delay / 30); + return 1 + ((level - 28) / 3) * (delay / 30); } } else { // 2h damage bonus From 957aba7ae526520946494b7f6ad3999700f51950 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 24 Sep 2015 19:39:36 -0400 Subject: [PATCH 322/846] Fix Sinister Strikes calc --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 171b8d2fe..7a62aaff4 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2681,7 +2681,7 @@ uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand) else if (delay >= 45) return 4 + ((level - 28) / 3) + ((delay - 40) / 3); } else { - return 1 + ((level - 28) / 3) * (delay / 30); + return 1 + ((level - 40) / 3) * (delay / 30); // YOOO shit's useless waste of AAs } } else { // 2h damage bonus From a11816fddf94b9aaa0ab83bdada872f8df3234c0 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 25 Sep 2015 04:44:17 -0400 Subject: [PATCH 323/846] Implemented SE_PC_Pet_Rampage 464 - Base1 % chance to do rampage for base2 % of damage each melee round --- common/spdat.h | 4 ++-- zone/bonuses.cpp | 14 ++++++++++++++ zone/common.h | 1 + zone/mob_ai.cpp | 24 +++++++++++++++++------- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index a469be2e7..8288c0895 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -617,8 +617,8 @@ typedef enum { //#define SE_Fc_Damage_%2 461 // //#define SE_Fc_Damage_Amt2 462 // //#define SE_Shield_Target 463 // -//#define SE_PC_Pet_Rampage 464 // -//#define SE_PC_Pet_AE_Rampage 465 // +#define SE_PC_Pet_Rampage 464 // Base1 % chance to do rampage for base2 % of damage each melee round +#define SE_PC_Pet_AE_Rampage 465 // Base1 % chance to do aerampage for base2 % of damage each melee round //#define SE_PC_Pet_Flurry_Chance 466 // //#define SE_DS_Mitigation_Amount 467 // //#define SE_DS_Mitigation_Percentage 468 // diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 155dfc4ae..18a69637f 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1417,6 +1417,13 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_IncreaseExtTargetWindow: newbon->extra_xtargets += base1; break; + + case SE_PC_Pet_Rampage: { + newbon->PC_Pet_Rampage[0] += base1; //Chance to rampage + if (newbon->PC_Pet_Rampage[1] < base2) + newbon->PC_Pet_Rampage[1] = base2; //Damage modifer - take highest + break; + } // to do case SE_PetDiscipline: break; @@ -3120,6 +3127,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } + case SE_PC_Pet_Rampage: { + new_bonus->PC_Pet_Rampage[0] += effect_value; //Chance to rampage + if (new_bonus->PC_Pet_Rampage[1] < base2) + new_bonus->PC_Pet_Rampage[1] = base2; //Damage modifer - take highest + break; + } + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/common.h b/zone/common.h index 7901d511e..c59156c7b 100644 --- a/zone/common.h +++ b/zone/common.h @@ -405,6 +405,7 @@ struct StatBonuses { bool LimitToSkill[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 // AAs int8 Packrat; //weight reduction for items, 1 point = 10% diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 4be97897a..f54113f93 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1139,16 +1139,12 @@ void Mob::AI_Process() { } } - if (IsPet() || (IsNPC() && CastToNPC()->GetSwarmOwner())) { + if (IsPet() || IsTempPet()) { Mob *owner = nullptr; - - if (IsPet()) - owner = GetOwner(); - else - owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); + owner = GetOwner(); if (owner) { - int16 flurry_chance = owner->aabonuses.PetFlurry + + int16 flurry_chance = owner->aabonuses.PetFlurry + owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry; if (flurry_chance && zone->random.Roll(flurry_chance)) @@ -1156,6 +1152,19 @@ 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]; + Shout("CHance %i", chance); + if(zone->random.Roll(chance)) { + ExtraAttackOptions opts; + opts.damage_percent = dmg_mod / 100.0f; + Rampage(&opts); + } + } + } + if (GetSpecialAbility(SPECATK_RAMPAGE) && !specialed) { int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0); @@ -1245,6 +1254,7 @@ void Mob::AI_Process() { //now special attacks (kick, etc) if(IsNPC()) CastToNPC()->DoClassAttacks(target); + } AI_EngagedCastCheck(); } //end is within combat rangepet From 370b5d7810f4a6b58ff368deae48ad6e7a86c30a Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 25 Sep 2015 05:18:30 -0400 Subject: [PATCH 324/846] Implemented a few new stackable spell damage focus effects from live. Implemented SE_ImprovedDamage2 461 // Increase spell damage by percent (SE_Fc_Damage_%2) Implemented SE_FcDamageAmt2 462 // Increase spell damage by flat amount (SE_Fc_Damage_Amt2) --- common/spdat.h | 8 ++++---- zone/bonuses.cpp | 4 ++++ zone/common.h | 2 ++ zone/effects.cpp | 12 ++++++++++-- zone/mob_ai.cpp | 1 - zone/spell_effects.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- 6 files changed, 58 insertions(+), 9 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index 8288c0895..c49628d01 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -614,11 +614,11 @@ typedef enum { #define SE_FactionModPct 458 // implemented Modifies faction gains and losses by percent. #define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type //#define SE_Ff_Override_NotFocusable 460 // -//#define SE_Fc_Damage_%2 461 // -//#define SE_Fc_Damage_Amt2 462 // +#define SE_ImprovedDamage2 461 // implemented - Increase spell damage by percent (SE_Fc_Damage_%2) +#define SE_FcDamageAmt2 462 // implemented - Increase spell damage by flat amount (SE_Fc_Damage_Amt2) //#define SE_Shield_Target 463 // -#define SE_PC_Pet_Rampage 464 // Base1 % chance to do rampage for base2 % of damage each melee round -#define SE_PC_Pet_AE_Rampage 465 // Base1 % chance to do aerampage for base2 % of damage each melee round +#define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round +//#define SE_PC_Pet_AE_Rampage 465 // Would assume as above but need to confirm. //#define SE_PC_Pet_Flurry_Chance 466 // //#define SE_DS_Mitigation_Amount 467 // //#define SE_DS_Mitigation_Percentage 468 // diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 18a69637f..772f875e5 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -3437,6 +3437,8 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff { case SE_ImprovedDamage: return focusImprovedDamage; + case SE_ImprovedDamage2: + return focusImprovedDamage2; case SE_ImprovedHeal: return focusImprovedHeal; case SE_ReduceManaCost: @@ -3475,6 +3477,8 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff return focusSympatheticProc; case SE_FcDamageAmt: return focusFcDamageAmt; + case SE_FcDamageAmt2: + return focusFcDamageAmt2; case SE_FcDamageAmtCrit: return focusFcDamageAmtCrit; case SE_FcDamagePctCrit: diff --git a/zone/common.h b/zone/common.h index c59156c7b..af53e1a93 100644 --- a/zone/common.h +++ b/zone/common.h @@ -62,6 +62,7 @@ typedef enum { //focus types focusManaCost, focusImprovedHeal, focusImprovedDamage, + focusImprovedDamage2, focusImprovedDOT, //i dont know about this... focusFcDamagePctCrit, focusImprovedUndeadDamage, @@ -73,6 +74,7 @@ typedef enum { //focus types focusTwincast, focusSympatheticProc, focusFcDamageAmt, + focusFcDamageAmt2, focusFcDamageAmtCrit, focusSpellDurByTic, focusSwarmPetDuration, diff --git a/zone/effects.cpp b/zone/effects.cpp index 08f0073cf..2e43ad8f5 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -98,6 +98,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value = value_BaseEffect*ratio/100; value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100; + value += value_BaseEffect*GetFocusEffect(focusImprovedDamage2, spell_id)/100; value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100; @@ -109,6 +110,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100; value -= GetFocusEffect(focusFcDamageAmt, spell_id); + value -= GetFocusEffect(focusFcDamageAmt2, spell_id); if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100; @@ -129,6 +131,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value = value_BaseEffect; value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100; + value += value_BaseEffect*GetFocusEffect(focusImprovedDamage2, spell_id)/100; value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100; @@ -140,6 +143,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmtCrit, spell_id); value -= GetFocusEffect(focusFcDamageAmt, spell_id); + value -= GetFocusEffect(focusFcDamageAmt2, spell_id); if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); @@ -176,11 +180,13 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease; value = value_BaseEffect*ratio/100; value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100; + value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage2, spell_id)/100)*ratio/100; value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100; value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100; extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) + - GetFocusEffect(focusFcDamageAmt, spell_id); + GetFocusEffect(focusFcDamageAmt, spell_id) + + GetFocusEffect(focusFcDamageAmt2, spell_id); if (extra_dmg) { int duration = CalcBuffDuration(this, this, spell_id); @@ -194,11 +200,13 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { value = value_BaseEffect; value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100; + value += value_BaseEffect*GetFocusEffect(focusImprovedDamage2, spell_id)/100; value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100; value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100; extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + GetFocusEffect(focusFcDamageAmtCrit, spell_id) + - GetFocusEffect(focusFcDamageAmt, spell_id); + GetFocusEffect(focusFcDamageAmt, spell_id) + + GetFocusEffect(focusFcDamageAmt2, spell_id); if (extra_dmg) { int duration = CalcBuffDuration(this, this, spell_id); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index f54113f93..3f3911c8d 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1156,7 +1156,6 @@ void Mob::AI_Process() { 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]; - Shout("CHance %i", chance); if(zone->random.Roll(chance)) { ExtraAttackOptions opts; opts.damage_percent = dmg_mod / 100.0f; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4c1f1fa45..754ced55d 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2832,6 +2832,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Accuracy: case SE_Flurry: case SE_ImprovedDamage: + case SE_ImprovedDamage2: case SE_ImprovedHeal: case SE_IncreaseSpellHaste: case SE_IncreaseSpellDuration: @@ -2865,6 +2866,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_MaxHPChange: case SE_SympatheticProc: case SE_FcDamageAmt: + case SE_FcDamageAmt2: case SE_CriticalSpellChance: case SE_SpellCritChance: case SE_SpellCritDmgIncrease: @@ -4397,6 +4399,11 @@ int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) value = base1; break; + case SE_ImprovedDamage2: + if (type == focusImprovedDamage2 && base1 > value) + value = base1; + break; + case SE_ImprovedHeal: if (type == focusImprovedHeal && base1 > value) value = base1; @@ -4506,6 +4513,11 @@ int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) value = base1; break; + case SE_FcDamageAmt2: + if (type == focusFcDamageAmt2) + value = base1; + break; + case SE_FcDamageAmtCrit: if (type == focusFcDamageAmtCrit) value = base1; @@ -4845,6 +4857,24 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; + case SE_ImprovedDamage2: + if (type == focusImprovedDamage2) { + if (best_focus) { + if (focus_spell.base2[i] != 0) { + value = focus_spell.base2[i]; + } + else { + value = focus_spell.base[i]; + } + } + else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { + value = focus_spell.base[i]; + } else { + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); + } + } + break; + case SE_ImprovedHeal: if (type == focusImprovedHeal) { if (best_focus) { @@ -4974,6 +5004,11 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo value = focus_spell.base[i]; break; + case SE_FcDamageAmt2: + if (type == focusFcDamageAmt2) + value = focus_spell.base[i]; + break; + case SE_FcDamageAmtCrit: if (type == focusFcDamageAmtCrit) value = focus_spell.base[i]; @@ -5200,7 +5235,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) //Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages //In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance - if(RuleB(Spells, LiveLikeFocusEffects) && (type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage)) + if(RuleB(Spells, LiveLikeFocusEffects) && (type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage || type == focusImprovedDamage2)) rand_effectiveness = true; //Check if item focus effect exists for the client. @@ -5340,6 +5375,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) string_id = SPARKLES; break; case focusImprovedDamage: + case focusImprovedDamage2: if (realTotal) string_id = ALIVE_WITH_POWER; else @@ -5469,7 +5505,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { //Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages //In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance - if(RuleB(Spells, LiveLikeFocusEffects) && (type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage)) + if(RuleB(Spells, LiveLikeFocusEffects) && (type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage || type == focusImprovedDamage2)) rand_effectiveness = true; if (RuleB(Spells, NPC_UseFocusFromItems) && itembonuses.FocusEffects[type]){ From a1089fccd6d0402863206a3ea65353f5ed8d8044 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 25 Sep 2015 23:07:05 -0400 Subject: [PATCH 325/846] Implemented 'Inventory Snapshot' feature --- changelog.txt | 11 ++++ common/database.cpp | 9 +++ common/database.h | 2 + common/extprofile.h | 2 + common/ruletypes.h | 4 ++ common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2015_09_25_inventory_snapshots.sql | 46 +++++++++++++ world/net.cpp | 2 + zone/client.cpp | 11 ++++ zone/client.h | 7 ++ zone/command.cpp | 32 +++++++++ zone/command.h | 2 + zone/zonedb.cpp | 66 +++++++++++++++++-- zone/zonedb.h | 1 + 15 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 utils/sql/git/required/2015_09_25_inventory_snapshots.sql diff --git a/changelog.txt b/changelog.txt index d0d757df0..0fd73aeba 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,16 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/25/2015 == +Uleat: Implemented 'Inventory Snapshot' feature to track online player inventories at timed intervals. +rules: + 'Character:ActiveInvSnapshots' - active (true) or inactive (false - default) + 'Character:InvSnapshotMinIntervalM' - minimum time between snapshots (in minutes) + 'Character:InvSnapshotMinRetryM' - minimum time to attempt a retry after a failed snapshot (in minutes) + 'Character:InvSnapshotHistoryD' - minimum time to keep snapshot entries (in days) +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. diff --git a/common/database.cpp b/common/database.cpp index b27722fe9..570bcbb43 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2173,3 +2173,12 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) } } } + +void Database::ClearInvSnapshots(bool use_rule) +{ + uint32 del_time = time(nullptr); + if (use_rule) { del_time -= RuleI(Character, InvSnapshotHistoryD) * 86400; } + + std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time); + QueryDatabase(query); +} diff --git a/common/database.h b/common/database.h index f3b8ba8c1..1543a14e3 100644 --- a/common/database.h +++ b/common/database.h @@ -248,6 +248,8 @@ public: void SetLFP(uint32 CharID, bool LFP); void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); + void ClearInvSnapshots(bool use_rule = true); + /* EQEmuLogSys */ void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings); diff --git a/common/extprofile.h b/common/extprofile.h index a8447d4fc..49b8fb8f3 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -54,6 +54,8 @@ struct ExtendedProfile_Struct { uint32 mercTimerRemaining; /* Not Used */ uint8 mercGender; /* Not Used */ int32 mercState; /* Not Used */ + uint32 last_invsnapshot_time; /* Used */ + uint32 next_invsnapshot_time; /* Used */ }; #pragma pack() diff --git a/common/ruletypes.h b/common/ruletypes.h index b3f5e3460..8cb2ed0db 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -119,6 +119,10 @@ RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?) RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?) RULE_INT(Character, TrollCommonTongue, 95) // 95 By default (live-like?) +RULE_BOOL(Character, ActiveInvSnapshots, false) // Takes a periodic snapshot of inventory contents from online players +RULE_INT(Character, InvSnapshotMinIntervalM, 180) // Minimum time (in minutes) between inventory snapshots +RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt an inventory snapshot after a failure +RULE_INT(Character, InvSnapshotHistoryD, 30) // Time (in days) to keep snapshot entries RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/common/version.h b/common/version.h index 11a18cd0d..74dd0cbd6 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 9086 +#define CURRENT_BINARY_DATABASE_VERSION 9087 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 7394c7863..239fdbb67 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -340,6 +340,7 @@ 9084|2015_06_30_runspeed_adjustments.sql|SELECT `runspeed` FROM `npc_types` WHERE `runspeed` > 3|not_empty| 9085|2015_07_01_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty| 9086|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty| +9087|2015_09_25_inventory_snapshots.sql|SHOW TABLES LIKE 'inventory_snapshots'|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/2015_09_25_inventory_snapshots.sql b/utils/sql/git/required/2015_09_25_inventory_snapshots.sql new file mode 100644 index 000000000..12b167e8b --- /dev/null +++ b/utils/sql/git/required/2015_09_25_inventory_snapshots.sql @@ -0,0 +1,46 @@ +CREATE TABLE `inventory_snapshots` ( + `time_index` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `charid` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `slotid` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `itemid` INT(11) UNSIGNED NULL DEFAULT '0', + `charges` SMALLINT(3) UNSIGNED NULL DEFAULT '0', + `color` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `augslot1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augslot2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augslot3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augslot4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augslot5` MEDIUMINT(7) UNSIGNED NULL DEFAULT '0', + `augslot6` MEDIUMINT(7) NOT NULL DEFAULT '0', + `instnodrop` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', + `custom_data` TEXT NULL, + `ornamenticon` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `ornamentidfile` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `ornament_hero_model` INT(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`time_index`, `charid`, `slotid`) +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; + +ALTER TABLE `character_data` ADD COLUMN `e_last_invsnapshot` INT(11) UNSIGNED NOT NULL DEFAULT '0'; + +INSERT INTO `rule_values` VALUES +(1, 'Character:ActiveInvSnapshots', 'false', 'Takes a periodic snapshot of inventory contents from online players'), +(2, 'Character:ActiveInvSnapshots', 'false', 'Takes a periodic snapshot of inventory contents from online players'), +(4, 'Character:ActiveInvSnapshots', 'false', 'Takes a periodic snapshot of inventory contents from online players'), +(5, 'Character:ActiveInvSnapshots', 'false', 'Takes a periodic snapshot of inventory contents from online players'), +(10, 'Character:ActiveInvSnapshots', 'false', 'Takes a periodic snapshot of inventory contents from online players'), +(1, 'Character:InvSnapshotMinIntervalM', '180', 'Minimum time (in minutes) between inventory snapshots'), +(2, 'Character:InvSnapshotMinIntervalM', '180', 'Minimum time (in minutes) between inventory snapshots'), +(4, 'Character:InvSnapshotMinIntervalM', '180', 'Minimum time (in minutes) between inventory snapshots'), +(5, 'Character:InvSnapshotMinIntervalM', '180', 'Minimum time (in minutes) between inventory snapshots'), +(10, 'Character:InvSnapshotMinIntervalM', '180', 'Minimum time (in minutes) between inventory snapshots'), +(1, 'Character:InvSnapshotMinRetryM', '30', 'Time (in minutes) to re-attempt an inventory snapshot after a failure'), +(2, 'Character:InvSnapshotMinRetryM', '30', 'Time (in minutes) to re-attempt an inventory snapshot after a failure'), +(4, 'Character:InvSnapshotMinRetryM', '30', 'Time (in minutes) to re-attempt an inventory snapshot after a failure'), +(5, 'Character:InvSnapshotMinRetryM', '30', 'Time (in minutes) to re-attempt an inventory snapshot after a failure'), +(10, 'Character:InvSnapshotMinRetryM', '30', 'Time (in minutes) to re-attempt an inventory snapshot after a failure'), +(1, 'Character:InvSnapshotHistoryD', '30', 'Time (in days) to keep snapshot entries'), +(2, 'Character:InvSnapshotHistoryD', '30', 'Time (in days) to keep snapshot entries'), +(4, 'Character:InvSnapshotHistoryD', '30', 'Time (in days) to keep snapshot entries'), +(5, 'Character:InvSnapshotHistoryD', '30', 'Time (in days) to keep snapshot entries'), +(10, 'Character:InvSnapshotHistoryD', '30', 'Time (in days) to keep snapshot entries'); diff --git a/world/net.cpp b/world/net.cpp index 3032e4c97..7c8597bc5 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -310,6 +310,8 @@ int main(int argc, char** argv) { database.ClearRaid(); database.ClearRaidDetails(); database.ClearRaidLeader(); + Log.Out(Logs::General, Logs::World_Server, "Clearing inventory snapshots.."); + database.ClearInvSnapshots(); Log.Out(Logs::General, Logs::World_Server, "Loading items.."); if(!database.LoadItems(hotfix_name)) Log.Out(Logs::General, Logs::World_Server, "Error: Could not load item data. But ignoring"); diff --git a/zone/client.cpp b/zone/client.cpp index cce3dbd29..ef0c9bf7d 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -642,6 +642,17 @@ bool Client::Save(uint8 iCommitNow) { m_pp.hunger_level = EQEmu::Clamp(m_pp.hunger_level, 0, 50000); m_pp.thirst_level = EQEmu::Clamp(m_pp.thirst_level, 0, 50000); + + // perform snapshot before SaveCharacterData() so that m_epp will contain the updated time + if (RuleB(Character, ActiveInvSnapshots) && time(nullptr) >= GetNextInvSnapshotTime()) { + if (database.SaveCharacterInventorySnapshot(CharacterID())) { + SetNextInvSnapshot(RuleI(Character, InvSnapshotMinIntervalM)); + } + else { + SetNextInvSnapshot(RuleI(Character, InvSnapshotMinRetryM)); + } + } + database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp, &m_epp); /* Save Character Data */ return true; diff --git a/zone/client.h b/zone/client.h index 9fa68350e..885eb1407 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1250,6 +1250,13 @@ public: bool InterrogateInventory(Client* requester, bool log, bool silent, bool allowtrip, bool& error, bool autolog = true); + void SetNextInvSnapshot(uint32 interval_in_min) { + m_epp.last_invsnapshot_time = time(nullptr); + m_epp.next_invsnapshot_time = m_epp.last_invsnapshot_time + (interval_in_min * 60); + } + uint32 GetLastInvSnapshotTime() { return m_epp.last_invsnapshot_time; } + uint32 GetNextInvSnapshotTime() { return m_epp.next_invsnapshot_time; } + //Command #Tune functions virtual int32 Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false); diff --git a/zone/command.cpp b/zone/command.cpp index 144fada08..5fe6244ad 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -183,6 +183,7 @@ int command_init(void) { command_add("castspell", "[spellid] - Cast a spell", 50, command_castspell) || command_add("chat", "[channel num] [message] - Send a channel message to all zones", 200, command_chat) || command_add("checklos", "- Check for line of sight to your target", 50, command_checklos) || + command_add("clearinvsnapshots", "[use rule] - Clear inventory snapshot history (true - elapsed entries, false - all entries)", 200, command_clearinvsnapshots) || command_add("close_shop", nullptr, 100, command_merchantcloseshop) || command_add("connectworld", nullptr,0, command_connectworldserver) || command_add("connectworldserver", "- Make zone attempt to connect to worldserver", 200, command_connectworldserver) || @@ -260,6 +261,7 @@ int command_init(void) { command_add("instance", "- Modify Instances", 200, command_instance) || command_add("interrogateinv", "- use [help] argument for available options", 0, command_interrogateinv) || command_add("interrupt", "[message id] [color] - Interrupt your casting. Arguments are optional.", 50, command_interrupt) || + command_add("invsnapshot", "- Takes an inventory snapshot of your current target", 80, command_invsnapshot) || command_add("invul", nullptr,0, command_invul) || command_add("invulnerable", "[on/off] - Turn player target's or your invulnerable flag on or off", 80, command_invul) || command_add("ipban", "[IP address] - Ban IP by character name", 200, command_ipban) || @@ -2836,6 +2838,36 @@ void command_interrogateinv(Client *c, const Seperator *sep) c->Message(13, "An unknown error occurred while processing Client::InterrogateInventory()"); } +void command_invsnapshot(Client *c, const Seperator *sep) +{ + auto t = c->GetTarget(); + if (!t || !t->IsClient()) { + c->Message(0, "Target must be a client"); + return; + } + + if (database.SaveCharacterInventorySnapshot(((Client*)t)->CharacterID())) { + c->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinIntervalM)); + c->Message(0, "Successful inventory snapshot taken of %s", t->GetName()); + } + else { + c->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinRetryM)); + c->Message(0, "Failed to take inventory snapshot of %s", t->GetName()); + } +} + +void command_clearinvsnapshots(Client *c, const Seperator *sep) +{ + if (strcmp(sep->arg[1], "false") == 0) { + database.ClearInvSnapshots(false); + c->Message(0, "Inventory snapshots cleared using current time"); + } + else { + database.ClearInvSnapshots(); + c->Message(0, "Inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i days)", RuleI(Character, InvSnapshotHistoryD)); + } +} + void command_findnpctype(Client *c, const Seperator *sep) { if(sep->arg[1][0] == 0) { diff --git a/zone/command.h b/zone/command.h index 67f813456..03e30a786 100644 --- a/zone/command.h +++ b/zone/command.h @@ -154,6 +154,8 @@ void command_appearance(Client *c, const Seperator *sep); void command_nukeitem(Client *c, const Seperator *sep); void command_peekinv(Client *c, const Seperator *sep); void command_interrogateinv(Client *c, const Seperator *sep); +void command_invsnapshot(Client *c, const Seperator *sep); +void command_clearinvsnapshots(Client *c, const Seperator *sep); void command_findnpctype(Client *c, const Seperator *sep); void command_findzone(Client *c, const Seperator *sep); void command_viewnpctype(Client *c, const Seperator *sep); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 08a3dd38a..e92704fe6 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -887,7 +887,8 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* "RestTimer, " "`e_aa_effects`, " "`e_percent_to_aa`, " - "`e_expended_aa_spent` " + "`e_expended_aa_spent`, " + "`e_last_invsnapshot` " "FROM " "character_data " "WHERE `id` = %i ", character_id); @@ -983,7 +984,9 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp->RestTimer = atoi(row[r]); r++; // "RestTimer, " m_epp->aa_effects = atoi(row[r]); r++; // "`e_aa_effects`, " m_epp->perAA = atoi(row[r]); r++; // "`e_percent_to_aa`, " - m_epp->expended_aa = atoi(row[r]); r++; // "`e_expended_aa_spent` " + m_epp->expended_aa = atoi(row[r]); r++; // "`e_expended_aa_spent`, " + m_epp->last_invsnapshot_time = atoi(row[r]); r++; // "`e_last_invsnapshot` " + m_epp->next_invsnapshot_time = m_epp->last_invsnapshot_time + (RuleI(Character, InvSnapshotMinIntervalM) * 60); } return true; } @@ -1377,6 +1380,56 @@ bool ZoneDatabase::SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_ return true; } +bool ZoneDatabase::SaveCharacterInventorySnapshot(uint32 character_id){ + uint32 time_index = time(nullptr); + std::string query = StringFormat( + "INSERT INTO inventory_snapshots (" + " time_index," + " charid," + " slotid," + " itemid," + " charges," + " color," + " augslot1," + " augslot2," + " augslot3," + " augslot4," + " augslot5," + " augslot6," + " instnodrop," + " custom_data," + " ornamenticon," + " ornamentidfile," + " ornament_hero_model" + ")" + " SELECT" + " %u," + " charid," + " slotid," + " itemid," + " charges," + " color," + " augslot1," + " augslot2," + " augslot3," + " augslot4," + " augslot5," + " augslot6," + " instnodrop," + " custom_data," + " ornamenticon," + " ornamentidfile," + " ornament_hero_model" + " FROM inventory" + " WHERE charid = %u", + time_index, + character_id + ); + auto results = database.QueryDatabase(query); + Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterInventorySnapshot %i (%s)", character_id, (results.Success() ? "pass" : "fail")); + return results.Success(); +} + bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp){ clock_t t = std::clock(); /* Function timer start */ std::string query = StringFormat( @@ -1473,7 +1526,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla " RestTimer, " " e_aa_effects, " " e_percent_to_aa, " - " e_expended_aa_spent " + " e_expended_aa_spent, " + " e_last_invsnapshot " ") " "VALUES (" "%u," // id " id, " @@ -1568,7 +1622,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla "%u," // RestTimer pp->RestTimer, " RestTimer) " "%u," // e_aa_effects "%u," // e_percent_to_aa - "%u" // e_expended_aa_spent + "%u," // e_expended_aa_spent + "%u" // e_last_invsnapshot ")", character_id, // " id, " account_id, // " account_id, " @@ -1662,7 +1717,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla pp->RestTimer, // " RestTimer) " m_epp->aa_effects, m_epp->perAA, - m_epp->expended_aa + m_epp->expended_aa, + m_epp->last_invsnapshot_time ); auto results = database.QueryDatabase(query); Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); diff --git a/zone/zonedb.h b/zone/zonedb.h index 35275b654..9b2a5105b 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -290,6 +290,7 @@ public: bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon); bool SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); + bool SaveCharacterInventorySnapshot(uint32 character_id); /* Character Data Deletes */ bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); From 8323f6af7b648174328d17e6d0c72dcd70492622 Mon Sep 17 00:00:00 2001 From: Cilraaz Date: Wed, 30 Sep 2015 10:44:20 -0400 Subject: [PATCH 326/846] Update to give client access to the proper AAs for the expansions allowed Bit shifting by expansion value minus 1, rather than expansion value --- zone/aa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 307eb3ba8..84fc4a1f4 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1419,11 +1419,11 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { } if(IsClient()) { - if(!(CastToClient()->GetPP().expansions & (1 << rank->expansion))) { + if(!(CastToClient()->GetPP().expansions & (1 << (rank->expansion - 1)))) { return false; } } else { - if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { + if(!(RuleI(World, ExpansionSettings) & (1 << (rank->expansion - 1)))) { return false; } } From 0999278b751f55d96e35a45480419b920f533461 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 2 Oct 2015 18:57:51 -0400 Subject: [PATCH 327/846] Initial bots_updater commit --- common/version.h | 5 + utils/sql/git/bots/README | 7 +- utils/sql/git/bots/load_bots.sql | 280 ------------------ ..._03_22_BotGuildMember_ScriptFailureFix.sql | 27 -- world/net.cpp | 3 +- 5 files changed, 12 insertions(+), 310 deletions(-) delete mode 100644 utils/sql/git/bots/load_bots.sql delete mode 100644 utils/sql/git/bots/required/2014_03_22_BotGuildMember_ScriptFailureFix.sql diff --git a/common/version.h b/common/version.h index 74dd0cbd6..b74021225 100644 --- a/common/version.h +++ b/common/version.h @@ -31,6 +31,11 @@ */ #define CURRENT_BINARY_DATABASE_VERSION 9087 +#ifdef BOTS + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 8001 +#else + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 +#endif #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/git/bots/README b/utils/sql/git/bots/README index 3f3c94cb1..f3aaa0c16 100644 --- a/utils/sql/git/bots/README +++ b/utils/sql/git/bots/README @@ -1,3 +1,6 @@ -Use this new load_bots.sql to source bot information into your database. +Use the eqemu_update.pl script to source/update bot information into your database. -This file now contains all of the script information so that it may be run from inside of HeidiSQL. \ No newline at end of file + +Developers: Please prefix 'bots_' to sql file description (after the date) in order to prevent issues naming conflicts. + +Example: 1980_01_01_bots_file_description.sql \ No newline at end of file diff --git a/utils/sql/git/bots/load_bots.sql b/utils/sql/git/bots/load_bots.sql deleted file mode 100644 index 0dd030545..000000000 --- a/utils/sql/git/bots/load_bots.sql +++ /dev/null @@ -1,280 +0,0 @@ --- 'load_bots' sql script file --- current as of 10/15/2014 --- --- Use this file on databases where the player profile blob has been converted. --- --- Note: This file assumes a database free of bot remnants. If you have a prior --- bot installation and wish to reload the default schema and entries, then --- source 'drop_bots.sql' before sourcing this file. - - -ALTER TABLE `guild_members` DROP PRIMARY KEY; -ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); - -UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298); - --- old command kept for reference (`commands` now only has 2 columns - `command` and `access`) --- INSERT INTO `commands` VALUES ('bot', '0', 'Type \"#bot help\" to the see the list of available commands for bots.'); -INSERT INTO `commands` VALUES ('bot', '0'); - -INSERT INTO `rule_values` VALUES - ('1', 'Bots:BotAAExpansion', '8', 'The expansion through which bots will obtain AAs'), - ('1', 'Bots:BotFinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.'), - ('1', 'Bots:BotGroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.'), - ('1', 'Bots:BotManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.'), - ('1', 'Bots:BotQuest', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl'), - ('1', 'Bots:BotSpellQuest', 'false', 'Anita Thrall\'s (Anita_Thrall.pl) Bot Spell Scriber quests.'), - ('1', 'Bots:CreateBotCount', '150', 'Number of bots that each account can create'), - ('1', 'Bots:SpawnBotCount', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid'); - -CREATE TABLE `bots` ( - `BotID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotOwnerCharacterID` INT(10) UNSIGNED NOT NULL, - `BotSpellsID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Name` VARCHAR(64) NOT NULL, - `LastName` VARCHAR(32) DEFAULT NULL, - `BotLevel` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', - `Race` SMALLINT(5) NOT NULL DEFAULT '0', - `Class` TINYINT(2) NOT NULL DEFAULT '0', - `Gender` TINYINT(2) NOT NULL DEFAULT '0', - `Size` FLOAT NOT NULL DEFAULT '0', - `Face` INT(10) NOT NULL DEFAULT '1', - `LuclinHairStyle` INT(10) NOT NULL DEFAULT '1', - `LuclinHairColor` INT(10) NOT NULL DEFAULT '1', - `LuclinEyeColor` INT(10) NOT NULL DEFAULT '1', - `LuclinEyeColor2` INT(10) NOT NULL DEFAULT '1', - `LuclinBeardColor` INT(10) NOT NULL DEFAULT '1', - `LuclinBeard` INT(10) NOT NULL DEFAULT '0', - `DrakkinHeritage` INT(10) NOT NULL DEFAULT '0', - `DrakkinTattoo` INT(10) NOT NULL DEFAULT '0', - `DrakkinDetails` INT(10) NOT NULL DEFAULT '0', - `HP` INTEGER NOT NULL DEFAULT '0', - `Mana` INTEGER NOT NULL DEFAULT '0', - `MR` SMALLINT(5) NOT NULL DEFAULT '0', - `CR` SMALLINT(5) NOT NULL DEFAULT '0', - `DR` SMALLINT(5) NOT NULL DEFAULT '0', - `FR` SMALLINT(5) NOT NULL DEFAULT '0', - `PR` SMALLINT(5) NOT NULL DEFAULT '0', - `Corrup` SMALLINT(5) NOT NULL DEFAULT '0', - `AC` SMALLINT(5) NOT NULL DEFAULT '0', - `STR` MEDIUMINT(8) NOT NULL DEFAULT '75', - `STA` MEDIUMINT(8) NOT NULL DEFAULT '75', - `DEX` MEDIUMINT(8) NOT NULL DEFAULT '75', - `AGI` MEDIUMINT(8) NOT NULL DEFAULT '75', - `_INT` MEDIUMINT(8) NOT NULL DEFAULT '80', - `WIS` MEDIUMINT(8) NOT NULL DEFAULT '75', - `CHA` MEDIUMINT(8) NOT NULL DEFAULT '75', - `ATK` MEDIUMINT(9) NOT NULL DEFAULT '0', - `BotCreateDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - `LastSpawnDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', - `TotalPlayTime` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `LastZoneId` SMALLINT(6) NOT NULL DEFAULT '0', - `BotInspectMessage` VARCHAR(256) NOT NULL DEFAULT '', - PRIMARY KEY (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botstances` ( - `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `StanceID` TINYINT UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotID`), - CONSTRAINT `FK_botstances_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -); - -CREATE TABLE `bottimers` ( - `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `TimerID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Value` INT(10) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotID`), - CONSTRAINT `FK_bottimers_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -); - -CREATE TABLE `botbuffs` ( - `BotBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `DurationFormula` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `TicsRemaining` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `PoisonCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `DiseaseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `CurseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `CorruptionCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `HitCount` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `MeleeRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `MagicRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `DeathSaveSuccessChance` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterAARank` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Persistent` TINYINT(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`BotBuffId`), - KEY `FK_botbuff_1` (`BotId`), - CONSTRAINT `FK_botbuff_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botinventory` ( - `BotInventoryID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotID` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `SlotID` INTEGER SIGNED NOT NULL DEFAULT '0', - `ItemID` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `charges` TINYINT(3) UNSIGNED DEFAULT 0, - `color` INTEGER UNSIGNED NOT NULL DEFAULT 0, - `augslot1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot5` MEDIUMINT(7) UNSIGNED DEFAULT 0, - `instnodrop` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, - PRIMARY KEY (`BotInventoryID`), - KEY `FK_botinventory_1` (`BotID`), - CONSTRAINT `FK_botinventory_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botpets` ( - `BotPetsId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `PetId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `Name` VARCHAR(64) NULL, - `Mana` INTEGER NOT NULL DEFAULT '0', - `HitPoints` INTEGER NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetsId`), - KEY `FK_botpets_1` (`BotId`), - CONSTRAINT `FK_botpets_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`), - CONSTRAINT `U_botpets_1` UNIQUE (`BotId`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botpetbuffs` ( - `BotPetBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotPetsId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Duration` INT(11) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetBuffId`), - KEY `FK_botpetbuffs_1` (`BotPetsId`), - CONSTRAINT `FK_botpetbuffs_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botpetinventory` ( - `BotPetInventoryId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotPetsId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `ItemId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetInventoryId`), - KEY `FK_botpetinventory_1` (`BotPetsId`), - CONSTRAINT `FK_botpetinventory_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botgroup` ( - `BotGroupId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotGroupLeaderBotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotGroupName` VARCHAR(64) NOT NULL, - PRIMARY KEY (`BotGroupId`), - KEY `FK_botgroup_1` (`BotGroupLeaderBotId`), - CONSTRAINT `FK_botgroup_1` FOREIGN KEY (`BotGroupLeaderBotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botgroupmembers` ( - `BotGroupMemberId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotGroupId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotGroupMemberId`), - KEY `FK_botgroupmembers_1` (`BotGroupId`), - CONSTRAINT `FK_botgroupmembers_1` FOREIGN KEY (`BotGroupId`) REFERENCES `botgroup` (`BotGroupId`), - KEY `FK_botgroupmembers_2` (`BotId`), - CONSTRAINT `FK_botgroupmembers_2` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botguildmembers` ( - `char_id` INT(11) NOT NULL DEFAULT '0', - `guild_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', - `rank` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `tribute_enable` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `total_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `last_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `banker` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `public_note` TEXT NULL, - `alt` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`char_id`) -) ENGINE=InnoDB; - -DELIMITER $$ - -CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1) -BEGIN - DECLARE Result CHAR(1); - - SET Result = NULL; - - IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN - SET Result = 'C'; - ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN - SET Result = 'B'; - END IF; - - RETURN Result; -END$$ - -DELIMITER ; - -CREATE VIEW `vwBotCharacterMobs` AS -SELECT _utf8'C' AS mobtype, -c.`id`, -c.`name`, -c.`class`, -c.`level`, -c.`last_login`, -c.`zone_id` -FROM `character_data` AS c -UNION ALL -SELECT _utf8'B' AS mobtype, -b.`BotID` AS id, -b.`Name` AS name, -b.`Class` AS class, -b.`BotLevel` AS level, -0 AS timelaston, -0 AS zoneid -FROM bots AS b; - -CREATE VIEW `vwGroups` AS -SELECT g.`groupid` AS groupid, -GetMobType(g.`name`) AS mobtype, -g.`name` AS name, -g.`charid` AS mobid, -IFNULL(c.`level`, b.`BotLevel`) AS level -FROM `group_id` AS g -LEFT JOIN `character_data` AS c ON g.`name` = c.`name` -LEFT JOIN `bots` AS b ON g.`name` = b.`Name`; - -CREATE VIEW `vwBotGroups` AS -SELECT g.`BotGroupId`, -g.`BotGroupName`, -g.`BotGroupLeaderBotId`, -b.`Name` AS BotGroupLeaderName, -b.`BotOwnerCharacterId`, -c.`name` AS BotOwnerCharacterName -FROM `botgroup` AS g -JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID` -JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id` -ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`; - -CREATE VIEW `vwGuildMembers` AS -SELECT 'C' AS mobtype, -cm.`char_id`, -cm.`guild_id`, -cm.`rank`, -cm.`tribute_enable`, -cm.`total_tribute`, -cm.`last_tribute`, -cm.`banker`, -cm.`public_note`, -cm.`alt` -FROM `guild_members` AS cm -UNION ALL -SELECT 'B' AS mobtype, -bm.`char_id`, -bm.`guild_id`, -bm.`rank`, -bm.`tribute_enable`, -bm.`total_tribute`, -bm.`last_tribute`, -bm.`banker`, -bm.`public_note`, -bm.`alt` -FROM `botguildmembers` AS bm; diff --git a/utils/sql/git/bots/required/2014_03_22_BotGuildMember_ScriptFailureFix.sql b/utils/sql/git/bots/required/2014_03_22_BotGuildMember_ScriptFailureFix.sql deleted file mode 100644 index 47b735045..000000000 --- a/utils/sql/git/bots/required/2014_03_22_BotGuildMember_ScriptFailureFix.sql +++ /dev/null @@ -1,27 +0,0 @@ -ALTER TABLE `botguildmembers` ADD `alt` TINYINT UNSIGNED NOT NULL DEFAULT '0' AFTER `public_note`; - -DROP VIEW IF EXISTS `vwGuildMembers`; -CREATE VIEW `vwGuildMembers` AS - select 'C' as mobtype, -cm.char_id, -cm.guild_id, -cm.rank, -cm.tribute_enable, -cm.total_tribute, -cm.last_tribute, -cm.banker, -cm.public_note, -cm.alt -from guild_members as cm -union all -select 'B' as mobtype, -bm.char_id, -bm.guild_id, -bm.rank, -bm.tribute_enable, -bm.total_tribute, -bm.last_tribute, -bm.banker, -bm.public_note, -bm.alt -from botguildmembers as bm; \ No newline at end of file diff --git a/world/net.cpp b/world/net.cpp index 7c8597bc5..73489243f 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -118,9 +118,10 @@ int main(int argc, char** argv) { /* Database Version Check */ uint32 Database_Version = CURRENT_BINARY_DATABASE_VERSION; + uint32 Bots_Database_Version = CURRENT_BINARY_BOTS_DATABASE_VERSION; if (argc >= 2) { if (strcasecmp(argv[1], "db_version") == 0) { - std::cout << "Binary Database Version: " << Database_Version << std::endl; + std::cout << "Binary Database Version: " << Database_Version << " : " << Bots_Database_Version << std::endl; return 0; } } From a5f805e1f76529ff2f141dd2bbfd90139fd6ed24 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 2 Oct 2015 18:59:56 -0400 Subject: [PATCH 328/846] Unversioned... --- .../sql/git/bots/bots_db_update_manifest.txt | 23 ++ ..._03_22_BotGuildMember_ScriptFailureFix.sql | 27 ++ utils/sql/git/bots/deprecated/load_bots.sql | 280 ++++++++++++++++++ utils/sql/git/bots/required/bots.sql | 280 ++++++++++++++++++ .../git/bots/required/bots_fix_existing.sql | 280 ++++++++++++++++++ 5 files changed, 890 insertions(+) create mode 100644 utils/sql/git/bots/bots_db_update_manifest.txt create mode 100644 utils/sql/git/bots/deprecated/2014_03_22_BotGuildMember_ScriptFailureFix.sql create mode 100644 utils/sql/git/bots/deprecated/load_bots.sql create mode 100644 utils/sql/git/bots/required/bots.sql create mode 100644 utils/sql/git/bots/required/bots_fix_existing.sql diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt new file mode 100644 index 000000000..adb3e8b5e --- /dev/null +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -0,0 +1,23 @@ +8000|2015_09_30_bots_fix_existing.sql|SHOW TABLES LIKE 'bot%'|not_empty| +8001|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot%'|empty| + +9000|2015_09_30_bots_initial_updates.sql||| + +# Upgrade conditions: +# This won't be needed after this system is implemented, but it is used database that are not +# yet using the versioning system to figure out where the database is schema wise to determine +# which updates are necessary to run +# +# Example: Version|Filename.sql|Query_to_Check_Condition_For_Needed_Update|match type|text to match +# 0 = Database Version +# 1 = Filename.sql +# 2 = Query_to_Check_Condition_For_Needed_Update +# 3 = Match Type - If condition from match type to Value 4 is true, update will flag for needing to be ran +# contains = If query results contains text from 4th value +# match = If query results matches text from 4th value +# missing = If query result is missing text from 4th value +# empty = If the query results in no results +# not_empty = If the query is not empty +# 4 = Text to match +# +# diff --git a/utils/sql/git/bots/deprecated/2014_03_22_BotGuildMember_ScriptFailureFix.sql b/utils/sql/git/bots/deprecated/2014_03_22_BotGuildMember_ScriptFailureFix.sql new file mode 100644 index 000000000..47b735045 --- /dev/null +++ b/utils/sql/git/bots/deprecated/2014_03_22_BotGuildMember_ScriptFailureFix.sql @@ -0,0 +1,27 @@ +ALTER TABLE `botguildmembers` ADD `alt` TINYINT UNSIGNED NOT NULL DEFAULT '0' AFTER `public_note`; + +DROP VIEW IF EXISTS `vwGuildMembers`; +CREATE VIEW `vwGuildMembers` AS + select 'C' as mobtype, +cm.char_id, +cm.guild_id, +cm.rank, +cm.tribute_enable, +cm.total_tribute, +cm.last_tribute, +cm.banker, +cm.public_note, +cm.alt +from guild_members as cm +union all +select 'B' as mobtype, +bm.char_id, +bm.guild_id, +bm.rank, +bm.tribute_enable, +bm.total_tribute, +bm.last_tribute, +bm.banker, +bm.public_note, +bm.alt +from botguildmembers as bm; \ No newline at end of file diff --git a/utils/sql/git/bots/deprecated/load_bots.sql b/utils/sql/git/bots/deprecated/load_bots.sql new file mode 100644 index 000000000..0dd030545 --- /dev/null +++ b/utils/sql/git/bots/deprecated/load_bots.sql @@ -0,0 +1,280 @@ +-- 'load_bots' sql script file +-- current as of 10/15/2014 +-- +-- Use this file on databases where the player profile blob has been converted. +-- +-- Note: This file assumes a database free of bot remnants. If you have a prior +-- bot installation and wish to reload the default schema and entries, then +-- source 'drop_bots.sql' before sourcing this file. + + +ALTER TABLE `guild_members` DROP PRIMARY KEY; +ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); + +UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298); + +-- old command kept for reference (`commands` now only has 2 columns - `command` and `access`) +-- INSERT INTO `commands` VALUES ('bot', '0', 'Type \"#bot help\" to the see the list of available commands for bots.'); +INSERT INTO `commands` VALUES ('bot', '0'); + +INSERT INTO `rule_values` VALUES + ('1', 'Bots:BotAAExpansion', '8', 'The expansion through which bots will obtain AAs'), + ('1', 'Bots:BotFinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.'), + ('1', 'Bots:BotGroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.'), + ('1', 'Bots:BotManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.'), + ('1', 'Bots:BotQuest', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl'), + ('1', 'Bots:BotSpellQuest', 'false', 'Anita Thrall\'s (Anita_Thrall.pl) Bot Spell Scriber quests.'), + ('1', 'Bots:CreateBotCount', '150', 'Number of bots that each account can create'), + ('1', 'Bots:SpawnBotCount', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid'); + +CREATE TABLE `bots` ( + `BotID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotOwnerCharacterID` INT(10) UNSIGNED NOT NULL, + `BotSpellsID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Name` VARCHAR(64) NOT NULL, + `LastName` VARCHAR(32) DEFAULT NULL, + `BotLevel` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', + `Race` SMALLINT(5) NOT NULL DEFAULT '0', + `Class` TINYINT(2) NOT NULL DEFAULT '0', + `Gender` TINYINT(2) NOT NULL DEFAULT '0', + `Size` FLOAT NOT NULL DEFAULT '0', + `Face` INT(10) NOT NULL DEFAULT '1', + `LuclinHairStyle` INT(10) NOT NULL DEFAULT '1', + `LuclinHairColor` INT(10) NOT NULL DEFAULT '1', + `LuclinEyeColor` INT(10) NOT NULL DEFAULT '1', + `LuclinEyeColor2` INT(10) NOT NULL DEFAULT '1', + `LuclinBeardColor` INT(10) NOT NULL DEFAULT '1', + `LuclinBeard` INT(10) NOT NULL DEFAULT '0', + `DrakkinHeritage` INT(10) NOT NULL DEFAULT '0', + `DrakkinTattoo` INT(10) NOT NULL DEFAULT '0', + `DrakkinDetails` INT(10) NOT NULL DEFAULT '0', + `HP` INTEGER NOT NULL DEFAULT '0', + `Mana` INTEGER NOT NULL DEFAULT '0', + `MR` SMALLINT(5) NOT NULL DEFAULT '0', + `CR` SMALLINT(5) NOT NULL DEFAULT '0', + `DR` SMALLINT(5) NOT NULL DEFAULT '0', + `FR` SMALLINT(5) NOT NULL DEFAULT '0', + `PR` SMALLINT(5) NOT NULL DEFAULT '0', + `Corrup` SMALLINT(5) NOT NULL DEFAULT '0', + `AC` SMALLINT(5) NOT NULL DEFAULT '0', + `STR` MEDIUMINT(8) NOT NULL DEFAULT '75', + `STA` MEDIUMINT(8) NOT NULL DEFAULT '75', + `DEX` MEDIUMINT(8) NOT NULL DEFAULT '75', + `AGI` MEDIUMINT(8) NOT NULL DEFAULT '75', + `_INT` MEDIUMINT(8) NOT NULL DEFAULT '80', + `WIS` MEDIUMINT(8) NOT NULL DEFAULT '75', + `CHA` MEDIUMINT(8) NOT NULL DEFAULT '75', + `ATK` MEDIUMINT(9) NOT NULL DEFAULT '0', + `BotCreateDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `LastSpawnDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `TotalPlayTime` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `LastZoneId` SMALLINT(6) NOT NULL DEFAULT '0', + `BotInspectMessage` VARCHAR(256) NOT NULL DEFAULT '', + PRIMARY KEY (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botstances` ( + `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `StanceID` TINYINT UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotID`), + CONSTRAINT `FK_botstances_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +); + +CREATE TABLE `bottimers` ( + `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `TimerID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Value` INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotID`), + CONSTRAINT `FK_bottimers_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +); + +CREATE TABLE `botbuffs` ( + `BotBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `DurationFormula` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `TicsRemaining` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `PoisonCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `DiseaseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `CurseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `CorruptionCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `HitCount` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `MeleeRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `MagicRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `DeathSaveSuccessChance` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterAARank` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Persistent` TINYINT(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`BotBuffId`), + KEY `FK_botbuff_1` (`BotId`), + CONSTRAINT `FK_botbuff_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botinventory` ( + `BotInventoryID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotID` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `SlotID` INTEGER SIGNED NOT NULL DEFAULT '0', + `ItemID` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `charges` TINYINT(3) UNSIGNED DEFAULT 0, + `color` INTEGER UNSIGNED NOT NULL DEFAULT 0, + `augslot1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot5` MEDIUMINT(7) UNSIGNED DEFAULT 0, + `instnodrop` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`BotInventoryID`), + KEY `FK_botinventory_1` (`BotID`), + CONSTRAINT `FK_botinventory_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botpets` ( + `BotPetsId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `PetId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `Name` VARCHAR(64) NULL, + `Mana` INTEGER NOT NULL DEFAULT '0', + `HitPoints` INTEGER NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetsId`), + KEY `FK_botpets_1` (`BotId`), + CONSTRAINT `FK_botpets_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`), + CONSTRAINT `U_botpets_1` UNIQUE (`BotId`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botpetbuffs` ( + `BotPetBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotPetsId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Duration` INT(11) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetBuffId`), + KEY `FK_botpetbuffs_1` (`BotPetsId`), + CONSTRAINT `FK_botpetbuffs_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botpetinventory` ( + `BotPetInventoryId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotPetsId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `ItemId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetInventoryId`), + KEY `FK_botpetinventory_1` (`BotPetsId`), + CONSTRAINT `FK_botpetinventory_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botgroup` ( + `BotGroupId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotGroupLeaderBotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotGroupName` VARCHAR(64) NOT NULL, + PRIMARY KEY (`BotGroupId`), + KEY `FK_botgroup_1` (`BotGroupLeaderBotId`), + CONSTRAINT `FK_botgroup_1` FOREIGN KEY (`BotGroupLeaderBotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botgroupmembers` ( + `BotGroupMemberId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotGroupId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotGroupMemberId`), + KEY `FK_botgroupmembers_1` (`BotGroupId`), + CONSTRAINT `FK_botgroupmembers_1` FOREIGN KEY (`BotGroupId`) REFERENCES `botgroup` (`BotGroupId`), + KEY `FK_botgroupmembers_2` (`BotId`), + CONSTRAINT `FK_botgroupmembers_2` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botguildmembers` ( + `char_id` INT(11) NOT NULL DEFAULT '0', + `guild_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', + `rank` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `tribute_enable` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `total_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `last_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `banker` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `public_note` TEXT NULL, + `alt` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`char_id`) +) ENGINE=InnoDB; + +DELIMITER $$ + +CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1) +BEGIN + DECLARE Result CHAR(1); + + SET Result = NULL; + + IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN + SET Result = 'C'; + ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN + SET Result = 'B'; + END IF; + + RETURN Result; +END$$ + +DELIMITER ; + +CREATE VIEW `vwBotCharacterMobs` AS +SELECT _utf8'C' AS mobtype, +c.`id`, +c.`name`, +c.`class`, +c.`level`, +c.`last_login`, +c.`zone_id` +FROM `character_data` AS c +UNION ALL +SELECT _utf8'B' AS mobtype, +b.`BotID` AS id, +b.`Name` AS name, +b.`Class` AS class, +b.`BotLevel` AS level, +0 AS timelaston, +0 AS zoneid +FROM bots AS b; + +CREATE VIEW `vwGroups` AS +SELECT g.`groupid` AS groupid, +GetMobType(g.`name`) AS mobtype, +g.`name` AS name, +g.`charid` AS mobid, +IFNULL(c.`level`, b.`BotLevel`) AS level +FROM `group_id` AS g +LEFT JOIN `character_data` AS c ON g.`name` = c.`name` +LEFT JOIN `bots` AS b ON g.`name` = b.`Name`; + +CREATE VIEW `vwBotGroups` AS +SELECT g.`BotGroupId`, +g.`BotGroupName`, +g.`BotGroupLeaderBotId`, +b.`Name` AS BotGroupLeaderName, +b.`BotOwnerCharacterId`, +c.`name` AS BotOwnerCharacterName +FROM `botgroup` AS g +JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID` +JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id` +ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`; + +CREATE VIEW `vwGuildMembers` AS +SELECT 'C' AS mobtype, +cm.`char_id`, +cm.`guild_id`, +cm.`rank`, +cm.`tribute_enable`, +cm.`total_tribute`, +cm.`last_tribute`, +cm.`banker`, +cm.`public_note`, +cm.`alt` +FROM `guild_members` AS cm +UNION ALL +SELECT 'B' AS mobtype, +bm.`char_id`, +bm.`guild_id`, +bm.`rank`, +bm.`tribute_enable`, +bm.`total_tribute`, +bm.`last_tribute`, +bm.`banker`, +bm.`public_note`, +bm.`alt` +FROM `botguildmembers` AS bm; diff --git a/utils/sql/git/bots/required/bots.sql b/utils/sql/git/bots/required/bots.sql new file mode 100644 index 000000000..0dd030545 --- /dev/null +++ b/utils/sql/git/bots/required/bots.sql @@ -0,0 +1,280 @@ +-- 'load_bots' sql script file +-- current as of 10/15/2014 +-- +-- Use this file on databases where the player profile blob has been converted. +-- +-- Note: This file assumes a database free of bot remnants. If you have a prior +-- bot installation and wish to reload the default schema and entries, then +-- source 'drop_bots.sql' before sourcing this file. + + +ALTER TABLE `guild_members` DROP PRIMARY KEY; +ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); + +UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298); + +-- old command kept for reference (`commands` now only has 2 columns - `command` and `access`) +-- INSERT INTO `commands` VALUES ('bot', '0', 'Type \"#bot help\" to the see the list of available commands for bots.'); +INSERT INTO `commands` VALUES ('bot', '0'); + +INSERT INTO `rule_values` VALUES + ('1', 'Bots:BotAAExpansion', '8', 'The expansion through which bots will obtain AAs'), + ('1', 'Bots:BotFinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.'), + ('1', 'Bots:BotGroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.'), + ('1', 'Bots:BotManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.'), + ('1', 'Bots:BotQuest', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl'), + ('1', 'Bots:BotSpellQuest', 'false', 'Anita Thrall\'s (Anita_Thrall.pl) Bot Spell Scriber quests.'), + ('1', 'Bots:CreateBotCount', '150', 'Number of bots that each account can create'), + ('1', 'Bots:SpawnBotCount', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid'); + +CREATE TABLE `bots` ( + `BotID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotOwnerCharacterID` INT(10) UNSIGNED NOT NULL, + `BotSpellsID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Name` VARCHAR(64) NOT NULL, + `LastName` VARCHAR(32) DEFAULT NULL, + `BotLevel` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', + `Race` SMALLINT(5) NOT NULL DEFAULT '0', + `Class` TINYINT(2) NOT NULL DEFAULT '0', + `Gender` TINYINT(2) NOT NULL DEFAULT '0', + `Size` FLOAT NOT NULL DEFAULT '0', + `Face` INT(10) NOT NULL DEFAULT '1', + `LuclinHairStyle` INT(10) NOT NULL DEFAULT '1', + `LuclinHairColor` INT(10) NOT NULL DEFAULT '1', + `LuclinEyeColor` INT(10) NOT NULL DEFAULT '1', + `LuclinEyeColor2` INT(10) NOT NULL DEFAULT '1', + `LuclinBeardColor` INT(10) NOT NULL DEFAULT '1', + `LuclinBeard` INT(10) NOT NULL DEFAULT '0', + `DrakkinHeritage` INT(10) NOT NULL DEFAULT '0', + `DrakkinTattoo` INT(10) NOT NULL DEFAULT '0', + `DrakkinDetails` INT(10) NOT NULL DEFAULT '0', + `HP` INTEGER NOT NULL DEFAULT '0', + `Mana` INTEGER NOT NULL DEFAULT '0', + `MR` SMALLINT(5) NOT NULL DEFAULT '0', + `CR` SMALLINT(5) NOT NULL DEFAULT '0', + `DR` SMALLINT(5) NOT NULL DEFAULT '0', + `FR` SMALLINT(5) NOT NULL DEFAULT '0', + `PR` SMALLINT(5) NOT NULL DEFAULT '0', + `Corrup` SMALLINT(5) NOT NULL DEFAULT '0', + `AC` SMALLINT(5) NOT NULL DEFAULT '0', + `STR` MEDIUMINT(8) NOT NULL DEFAULT '75', + `STA` MEDIUMINT(8) NOT NULL DEFAULT '75', + `DEX` MEDIUMINT(8) NOT NULL DEFAULT '75', + `AGI` MEDIUMINT(8) NOT NULL DEFAULT '75', + `_INT` MEDIUMINT(8) NOT NULL DEFAULT '80', + `WIS` MEDIUMINT(8) NOT NULL DEFAULT '75', + `CHA` MEDIUMINT(8) NOT NULL DEFAULT '75', + `ATK` MEDIUMINT(9) NOT NULL DEFAULT '0', + `BotCreateDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `LastSpawnDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `TotalPlayTime` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `LastZoneId` SMALLINT(6) NOT NULL DEFAULT '0', + `BotInspectMessage` VARCHAR(256) NOT NULL DEFAULT '', + PRIMARY KEY (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botstances` ( + `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `StanceID` TINYINT UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotID`), + CONSTRAINT `FK_botstances_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +); + +CREATE TABLE `bottimers` ( + `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `TimerID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Value` INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotID`), + CONSTRAINT `FK_bottimers_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +); + +CREATE TABLE `botbuffs` ( + `BotBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `DurationFormula` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `TicsRemaining` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `PoisonCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `DiseaseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `CurseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `CorruptionCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `HitCount` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `MeleeRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `MagicRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `DeathSaveSuccessChance` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterAARank` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Persistent` TINYINT(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`BotBuffId`), + KEY `FK_botbuff_1` (`BotId`), + CONSTRAINT `FK_botbuff_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botinventory` ( + `BotInventoryID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotID` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `SlotID` INTEGER SIGNED NOT NULL DEFAULT '0', + `ItemID` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `charges` TINYINT(3) UNSIGNED DEFAULT 0, + `color` INTEGER UNSIGNED NOT NULL DEFAULT 0, + `augslot1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot5` MEDIUMINT(7) UNSIGNED DEFAULT 0, + `instnodrop` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`BotInventoryID`), + KEY `FK_botinventory_1` (`BotID`), + CONSTRAINT `FK_botinventory_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botpets` ( + `BotPetsId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `PetId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `Name` VARCHAR(64) NULL, + `Mana` INTEGER NOT NULL DEFAULT '0', + `HitPoints` INTEGER NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetsId`), + KEY `FK_botpets_1` (`BotId`), + CONSTRAINT `FK_botpets_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`), + CONSTRAINT `U_botpets_1` UNIQUE (`BotId`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botpetbuffs` ( + `BotPetBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotPetsId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Duration` INT(11) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetBuffId`), + KEY `FK_botpetbuffs_1` (`BotPetsId`), + CONSTRAINT `FK_botpetbuffs_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botpetinventory` ( + `BotPetInventoryId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotPetsId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `ItemId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetInventoryId`), + KEY `FK_botpetinventory_1` (`BotPetsId`), + CONSTRAINT `FK_botpetinventory_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botgroup` ( + `BotGroupId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotGroupLeaderBotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotGroupName` VARCHAR(64) NOT NULL, + PRIMARY KEY (`BotGroupId`), + KEY `FK_botgroup_1` (`BotGroupLeaderBotId`), + CONSTRAINT `FK_botgroup_1` FOREIGN KEY (`BotGroupLeaderBotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botgroupmembers` ( + `BotGroupMemberId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotGroupId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotGroupMemberId`), + KEY `FK_botgroupmembers_1` (`BotGroupId`), + CONSTRAINT `FK_botgroupmembers_1` FOREIGN KEY (`BotGroupId`) REFERENCES `botgroup` (`BotGroupId`), + KEY `FK_botgroupmembers_2` (`BotId`), + CONSTRAINT `FK_botgroupmembers_2` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botguildmembers` ( + `char_id` INT(11) NOT NULL DEFAULT '0', + `guild_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', + `rank` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `tribute_enable` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `total_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `last_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `banker` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `public_note` TEXT NULL, + `alt` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`char_id`) +) ENGINE=InnoDB; + +DELIMITER $$ + +CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1) +BEGIN + DECLARE Result CHAR(1); + + SET Result = NULL; + + IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN + SET Result = 'C'; + ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN + SET Result = 'B'; + END IF; + + RETURN Result; +END$$ + +DELIMITER ; + +CREATE VIEW `vwBotCharacterMobs` AS +SELECT _utf8'C' AS mobtype, +c.`id`, +c.`name`, +c.`class`, +c.`level`, +c.`last_login`, +c.`zone_id` +FROM `character_data` AS c +UNION ALL +SELECT _utf8'B' AS mobtype, +b.`BotID` AS id, +b.`Name` AS name, +b.`Class` AS class, +b.`BotLevel` AS level, +0 AS timelaston, +0 AS zoneid +FROM bots AS b; + +CREATE VIEW `vwGroups` AS +SELECT g.`groupid` AS groupid, +GetMobType(g.`name`) AS mobtype, +g.`name` AS name, +g.`charid` AS mobid, +IFNULL(c.`level`, b.`BotLevel`) AS level +FROM `group_id` AS g +LEFT JOIN `character_data` AS c ON g.`name` = c.`name` +LEFT JOIN `bots` AS b ON g.`name` = b.`Name`; + +CREATE VIEW `vwBotGroups` AS +SELECT g.`BotGroupId`, +g.`BotGroupName`, +g.`BotGroupLeaderBotId`, +b.`Name` AS BotGroupLeaderName, +b.`BotOwnerCharacterId`, +c.`name` AS BotOwnerCharacterName +FROM `botgroup` AS g +JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID` +JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id` +ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`; + +CREATE VIEW `vwGuildMembers` AS +SELECT 'C' AS mobtype, +cm.`char_id`, +cm.`guild_id`, +cm.`rank`, +cm.`tribute_enable`, +cm.`total_tribute`, +cm.`last_tribute`, +cm.`banker`, +cm.`public_note`, +cm.`alt` +FROM `guild_members` AS cm +UNION ALL +SELECT 'B' AS mobtype, +bm.`char_id`, +bm.`guild_id`, +bm.`rank`, +bm.`tribute_enable`, +bm.`total_tribute`, +bm.`last_tribute`, +bm.`banker`, +bm.`public_note`, +bm.`alt` +FROM `botguildmembers` AS bm; diff --git a/utils/sql/git/bots/required/bots_fix_existing.sql b/utils/sql/git/bots/required/bots_fix_existing.sql new file mode 100644 index 000000000..0dd030545 --- /dev/null +++ b/utils/sql/git/bots/required/bots_fix_existing.sql @@ -0,0 +1,280 @@ +-- 'load_bots' sql script file +-- current as of 10/15/2014 +-- +-- Use this file on databases where the player profile blob has been converted. +-- +-- Note: This file assumes a database free of bot remnants. If you have a prior +-- bot installation and wish to reload the default schema and entries, then +-- source 'drop_bots.sql' before sourcing this file. + + +ALTER TABLE `guild_members` DROP PRIMARY KEY; +ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); + +UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298); + +-- old command kept for reference (`commands` now only has 2 columns - `command` and `access`) +-- INSERT INTO `commands` VALUES ('bot', '0', 'Type \"#bot help\" to the see the list of available commands for bots.'); +INSERT INTO `commands` VALUES ('bot', '0'); + +INSERT INTO `rule_values` VALUES + ('1', 'Bots:BotAAExpansion', '8', 'The expansion through which bots will obtain AAs'), + ('1', 'Bots:BotFinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.'), + ('1', 'Bots:BotGroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.'), + ('1', 'Bots:BotManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.'), + ('1', 'Bots:BotQuest', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl'), + ('1', 'Bots:BotSpellQuest', 'false', 'Anita Thrall\'s (Anita_Thrall.pl) Bot Spell Scriber quests.'), + ('1', 'Bots:CreateBotCount', '150', 'Number of bots that each account can create'), + ('1', 'Bots:SpawnBotCount', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid'); + +CREATE TABLE `bots` ( + `BotID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotOwnerCharacterID` INT(10) UNSIGNED NOT NULL, + `BotSpellsID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Name` VARCHAR(64) NOT NULL, + `LastName` VARCHAR(32) DEFAULT NULL, + `BotLevel` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', + `Race` SMALLINT(5) NOT NULL DEFAULT '0', + `Class` TINYINT(2) NOT NULL DEFAULT '0', + `Gender` TINYINT(2) NOT NULL DEFAULT '0', + `Size` FLOAT NOT NULL DEFAULT '0', + `Face` INT(10) NOT NULL DEFAULT '1', + `LuclinHairStyle` INT(10) NOT NULL DEFAULT '1', + `LuclinHairColor` INT(10) NOT NULL DEFAULT '1', + `LuclinEyeColor` INT(10) NOT NULL DEFAULT '1', + `LuclinEyeColor2` INT(10) NOT NULL DEFAULT '1', + `LuclinBeardColor` INT(10) NOT NULL DEFAULT '1', + `LuclinBeard` INT(10) NOT NULL DEFAULT '0', + `DrakkinHeritage` INT(10) NOT NULL DEFAULT '0', + `DrakkinTattoo` INT(10) NOT NULL DEFAULT '0', + `DrakkinDetails` INT(10) NOT NULL DEFAULT '0', + `HP` INTEGER NOT NULL DEFAULT '0', + `Mana` INTEGER NOT NULL DEFAULT '0', + `MR` SMALLINT(5) NOT NULL DEFAULT '0', + `CR` SMALLINT(5) NOT NULL DEFAULT '0', + `DR` SMALLINT(5) NOT NULL DEFAULT '0', + `FR` SMALLINT(5) NOT NULL DEFAULT '0', + `PR` SMALLINT(5) NOT NULL DEFAULT '0', + `Corrup` SMALLINT(5) NOT NULL DEFAULT '0', + `AC` SMALLINT(5) NOT NULL DEFAULT '0', + `STR` MEDIUMINT(8) NOT NULL DEFAULT '75', + `STA` MEDIUMINT(8) NOT NULL DEFAULT '75', + `DEX` MEDIUMINT(8) NOT NULL DEFAULT '75', + `AGI` MEDIUMINT(8) NOT NULL DEFAULT '75', + `_INT` MEDIUMINT(8) NOT NULL DEFAULT '80', + `WIS` MEDIUMINT(8) NOT NULL DEFAULT '75', + `CHA` MEDIUMINT(8) NOT NULL DEFAULT '75', + `ATK` MEDIUMINT(9) NOT NULL DEFAULT '0', + `BotCreateDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `LastSpawnDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `TotalPlayTime` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `LastZoneId` SMALLINT(6) NOT NULL DEFAULT '0', + `BotInspectMessage` VARCHAR(256) NOT NULL DEFAULT '', + PRIMARY KEY (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botstances` ( + `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `StanceID` TINYINT UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotID`), + CONSTRAINT `FK_botstances_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +); + +CREATE TABLE `bottimers` ( + `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `TimerID` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Value` INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotID`), + CONSTRAINT `FK_bottimers_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +); + +CREATE TABLE `botbuffs` ( + `BotBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `DurationFormula` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `TicsRemaining` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `PoisonCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `DiseaseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `CurseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `CorruptionCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `HitCount` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `MeleeRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `MagicRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `DeathSaveSuccessChance` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterAARank` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Persistent` TINYINT(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`BotBuffId`), + KEY `FK_botbuff_1` (`BotId`), + CONSTRAINT `FK_botbuff_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botinventory` ( + `BotInventoryID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotID` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `SlotID` INTEGER SIGNED NOT NULL DEFAULT '0', + `ItemID` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `charges` TINYINT(3) UNSIGNED DEFAULT 0, + `color` INTEGER UNSIGNED NOT NULL DEFAULT 0, + `augslot1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, + `augslot5` MEDIUMINT(7) UNSIGNED DEFAULT 0, + `instnodrop` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`BotInventoryID`), + KEY `FK_botinventory_1` (`BotID`), + CONSTRAINT `FK_botinventory_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botpets` ( + `BotPetsId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `PetId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `Name` VARCHAR(64) NULL, + `Mana` INTEGER NOT NULL DEFAULT '0', + `HitPoints` INTEGER NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetsId`), + KEY `FK_botpets_1` (`BotId`), + CONSTRAINT `FK_botpets_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`), + CONSTRAINT `U_botpets_1` UNIQUE (`BotId`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botpetbuffs` ( + `BotPetBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `BotPetsId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `Duration` INT(11) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetBuffId`), + KEY `FK_botpetbuffs_1` (`BotPetsId`), + CONSTRAINT `FK_botpetbuffs_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botpetinventory` ( + `BotPetInventoryId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotPetsId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `ItemId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotPetInventoryId`), + KEY `FK_botpetinventory_1` (`BotPetsId`), + CONSTRAINT `FK_botpetinventory_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + +CREATE TABLE `botgroup` ( + `BotGroupId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotGroupLeaderBotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotGroupName` VARCHAR(64) NOT NULL, + PRIMARY KEY (`BotGroupId`), + KEY `FK_botgroup_1` (`BotGroupLeaderBotId`), + CONSTRAINT `FK_botgroup_1` FOREIGN KEY (`BotGroupLeaderBotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botgroupmembers` ( + `BotGroupMemberId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `BotGroupId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`BotGroupMemberId`), + KEY `FK_botgroupmembers_1` (`BotGroupId`), + CONSTRAINT `FK_botgroupmembers_1` FOREIGN KEY (`BotGroupId`) REFERENCES `botgroup` (`BotGroupId`), + KEY `FK_botgroupmembers_2` (`BotId`), + CONSTRAINT `FK_botgroupmembers_2` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) +) ENGINE=InnoDB; + +CREATE TABLE `botguildmembers` ( + `char_id` INT(11) NOT NULL DEFAULT '0', + `guild_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', + `rank` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `tribute_enable` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `total_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `last_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `banker` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `public_note` TEXT NULL, + `alt` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`char_id`) +) ENGINE=InnoDB; + +DELIMITER $$ + +CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1) +BEGIN + DECLARE Result CHAR(1); + + SET Result = NULL; + + IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN + SET Result = 'C'; + ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN + SET Result = 'B'; + END IF; + + RETURN Result; +END$$ + +DELIMITER ; + +CREATE VIEW `vwBotCharacterMobs` AS +SELECT _utf8'C' AS mobtype, +c.`id`, +c.`name`, +c.`class`, +c.`level`, +c.`last_login`, +c.`zone_id` +FROM `character_data` AS c +UNION ALL +SELECT _utf8'B' AS mobtype, +b.`BotID` AS id, +b.`Name` AS name, +b.`Class` AS class, +b.`BotLevel` AS level, +0 AS timelaston, +0 AS zoneid +FROM bots AS b; + +CREATE VIEW `vwGroups` AS +SELECT g.`groupid` AS groupid, +GetMobType(g.`name`) AS mobtype, +g.`name` AS name, +g.`charid` AS mobid, +IFNULL(c.`level`, b.`BotLevel`) AS level +FROM `group_id` AS g +LEFT JOIN `character_data` AS c ON g.`name` = c.`name` +LEFT JOIN `bots` AS b ON g.`name` = b.`Name`; + +CREATE VIEW `vwBotGroups` AS +SELECT g.`BotGroupId`, +g.`BotGroupName`, +g.`BotGroupLeaderBotId`, +b.`Name` AS BotGroupLeaderName, +b.`BotOwnerCharacterId`, +c.`name` AS BotOwnerCharacterName +FROM `botgroup` AS g +JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID` +JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id` +ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`; + +CREATE VIEW `vwGuildMembers` AS +SELECT 'C' AS mobtype, +cm.`char_id`, +cm.`guild_id`, +cm.`rank`, +cm.`tribute_enable`, +cm.`total_tribute`, +cm.`last_tribute`, +cm.`banker`, +cm.`public_note`, +cm.`alt` +FROM `guild_members` AS cm +UNION ALL +SELECT 'B' AS mobtype, +bm.`char_id`, +bm.`guild_id`, +bm.`rank`, +bm.`tribute_enable`, +bm.`total_tribute`, +bm.`last_tribute`, +bm.`banker`, +bm.`public_note`, +bm.`alt` +FROM `botguildmembers` AS bm; From cbcfa2f2dfdf5a044c6fbf40167262623fd2f115 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 2 Oct 2015 19:35:02 -0500 Subject: [PATCH 329/846] Fix issue with an old SQL update and newer database engines [skip ci] --- .../required/2014_12_31_npc_types_default_values_update.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/sql/git/required/2014_12_31_npc_types_default_values_update.sql b/utils/sql/git/required/2014_12_31_npc_types_default_values_update.sql index b75544981..d06f3f74c 100644 --- a/utils/sql/git/required/2014_12_31_npc_types_default_values_update.sql +++ b/utils/sql/git/required/2014_12_31_npc_types_default_values_update.sql @@ -1,3 +1,6 @@ +UPDATE `npc_types` SET `bodytype` = 0 WHERE `bodytype` IS NULL; ALTER TABLE `npc_types` MODIFY `bodytype` INT(11) NOT NULL DEFAULT '1'; +UPDATE `npc_types` SET `d_melee_texture1` = 0 WHERE `d_melee_texture1` IS NULL; ALTER TABLE `npc_types` MODIFY `d_melee_texture1` INT(11) NOT NULL DEFAULT '0'; +UPDATE `npc_types` SET `d_melee_texture2` = 0 WHERE `d_melee_texture2` IS NULL; ALTER TABLE `npc_types` MODIFY `d_melee_texture2` INT(11) NOT NULL DEFAULT '0'; From 1e3f7b14c8c9b005b6997eeb4dad7a50336da86e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 2 Oct 2015 19:40:58 -0500 Subject: [PATCH 330/846] Bots database versioning (prep) [skip ci] --- common/version.h | 2 +- utils/sql/git/bots/bots_db_update_manifest.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/version.h b/common/version.h index b74021225..ed3167e9a 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9087 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 8001 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9001 #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 adb3e8b5e..413f91444 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 @@ -8000|2015_09_30_bots_fix_existing.sql|SHOW TABLES LIKE 'bot%'|not_empty| -8001|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot%'|empty| +9000|2015_09_30_bots_fix_existing.sql|SHOW TABLES LIKE 'bot%'|not_empty| +9001|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot%'|empty| -9000|2015_09_30_bots_initial_updates.sql||| +9002|2015_09_30_bots_initial_updates.sql||| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 07ee9901b710fbddf505ab8fa8b72df0317ddc64 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 2 Oct 2015 20:48:24 -0400 Subject: [PATCH 331/846] Name change for base bot schema sql files --- utils/sql/git/bots/required/{bots.sql => 2015_09_30_bots.sql} | 0 .../{bots_fix_existing.sql => 2015_09_30_bots_fix_existing.sql} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename utils/sql/git/bots/required/{bots.sql => 2015_09_30_bots.sql} (100%) rename utils/sql/git/bots/required/{bots_fix_existing.sql => 2015_09_30_bots_fix_existing.sql} (100%) diff --git a/utils/sql/git/bots/required/bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql similarity index 100% rename from utils/sql/git/bots/required/bots.sql rename to utils/sql/git/bots/required/2015_09_30_bots.sql diff --git a/utils/sql/git/bots/required/bots_fix_existing.sql b/utils/sql/git/bots/required/2015_09_30_bots_fix_existing.sql similarity index 100% rename from utils/sql/git/bots/required/bots_fix_existing.sql rename to utils/sql/git/bots/required/2015_09_30_bots_fix_existing.sql From 3e42cae123eb9887c6ac8b1bee9abfa93dedffe8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 2 Oct 2015 20:30:30 -0500 Subject: [PATCH 332/846] Complete support for bots database versioning in eqemu_update.pl (Option 10), ready for Uleat to take it from here [skip ci] - The one thing to note is that world bootup will not be interrupted with required bot updates, however full versioning is supported. --- utils/scripts/eqemu_update.pl | 306 ++++++++++++++++++++++------------ 1 file changed, 204 insertions(+), 102 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 67e741030..37a2505d9 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -22,14 +22,14 @@ if($Config{osname}=~/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 = 8; +$current_version = 9; 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"; - GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); exit; } else{ @@ -38,6 +38,9 @@ if($ARGV[0] eq "V"){ 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"; @@ -102,7 +105,7 @@ if($OS eq "Linux"){ #::: 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 "Exiting...\n"; + print "script_exiting...\n"; exit; } @@ -110,13 +113,13 @@ if($path eq ""){ mkdir('db_update'); #::: Check if db_version table exists... -if(trim(GetMySQLResult("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ - print GetMySQLResult("DROP TABLE db_version"); +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"; } -if(GetMySQLResult("SHOW TABLES LIKE 'db_version'") eq "" && $db){ - print GetMySQLResult(" +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; @@ -128,7 +131,7 @@ 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(GetMySQLResult("SELECT version FROM db_version LIMIT 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"){ @@ -140,8 +143,13 @@ else{ } if($db){ - print " Binary Database Version: (" . $bin_db_ver . ")\n"; - print " Local Database Version: (" . $local_db_ver . ")\n\n"; + print " Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; + + #::: Bots + $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); + 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"){ @@ -150,39 +158,38 @@ if($db){ exit; } - print "Retrieving latest database manifest...\n"; - GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } 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 - ShowMenuPrompt(); + show_menu_prompt(); } else{ #::: Most likely ran standalone print "\n"; - ShowMenuPrompt(); + show_menu_prompt(); } -sub UpdateSelf{ - GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); +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 ShowMenuPrompt { +sub show_menu_prompt { my %dispatch = ( 1 => \&database_dump, 2 => \&database_dump_compress, - 3 => \&Run_Database_Check, - 4 => \&AA_Fetch, - 5 => \&OpCodes_Fetch, - 6 => \&MapFiles_Fetch, - 7 => \&Plugins_Fetch, - 8 => \&QuestFiles_Fetch, - 9 => \&LUA_Modules_Fetch, - 20 => \&UpdateSelf, - 0 => \&Exit, + 3 => \&main_db_management, + 4 => \&aa_fetch, + 5 => \&opcodes_fetch, + 6 => \&map_files_fetch, + 7 => \&plugins_fetch, + 8 => \&quest_files_fetch, + 9 => \&lua_modules_fetch, + 10 => \&bots_db_management, + 20 => \&do_update_self, + 0 => \&script_exit, ); while (1) { @@ -192,7 +199,7 @@ sub ShowMenuPrompt { $menu_show++; next; } - print MenuOptions(), '> '; + print menu_options(), '> '; $menu_displayed++; if($menu_displayed > 50){ print "Safety: Menu looping too many times, exiting...\n"; @@ -219,13 +226,25 @@ sub ShowMenuPrompt { } } -sub MenuOptions { - +sub menu_options { if(@total_updates){ - $option[3] = "Run pending REQUIRED updates... (" . scalar (@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..."; + } + } } else{ $option[3] = "Check and stage pending REQUIRED Database updates"; + $bots_management = "Check for Bot REQUIRED database updates..."; } return < ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"], @@ -407,13 +428,13 @@ sub OpCodes_Fetch{ } print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; - GetRemoteFile($opcodes{$loop}[1], $file_name); + get_remote_file($opcodes{$loop}[1], $file_name); $loop++; } print "\nDone...\n\n"; } -sub CopyFile{ +sub copy_file{ $l_source_file = $_[0]; $l_dest_file = $_[1]; if($l_dest_file=~/\//i){ @@ -437,10 +458,10 @@ sub CopyFile{ copy $l_source_file, $l_dest_file; } -sub MapFiles_Fetch{ +sub map_files_fetch{ print "\n --- Fetching Latest Maps --- \n"; - GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); + 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"); @@ -462,7 +483,7 @@ sub MapFiles_Fetch{ my $file_existing_size = (stat $file_existing)[7]; if($file_existing_size != $maps_manifest[$m][1]){ print "Updating: '" . $maps_manifest[$m][0] . "'\n"; - GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); $fc++; } } @@ -472,13 +493,13 @@ sub MapFiles_Fetch{ } } -sub QuestFiles_Fetch{ +sub quest_files_fetch{ if (!-e "updates_staged/Quests-Plugins-master/quests/") { print "\n --- Fetching Latest Quests --- \n"; - GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + 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/'); + unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } $fc = 0; @@ -498,12 +519,12 @@ sub QuestFiles_Fetch{ $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; if (!-e $dest_file) { - CopyFile($staged_file, $dest_file); + copy_file($staged_file, $dest_file); print "Installing :: '" . $dest_file . "'\n"; $fc++; } else{ - $diff = Diff($dest_file, $staged_file); + $diff = do_file_diff($dest_file, $staged_file); if($diff ne ""){ $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; @@ -514,7 +535,7 @@ sub QuestFiles_Fetch{ if($input=~/N/i){} else{ #::: Make a backup - CopyFile($dest_file, $backup_dest); + copy_file($dest_file, $backup_dest); #::: Copy staged to running copy($staged_file, $dest_file); print "Installing :: '" . $dest_file . "'\n\n"; @@ -530,12 +551,12 @@ sub QuestFiles_Fetch{ } } -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"; - GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + 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/'); + unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } $fc = 0; @@ -555,12 +576,12 @@ sub LUA_Modules_Fetch{ $dest_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; if (!-e $dest_file) { - CopyFile($staged_file, $dest_file); + copy_file($staged_file, $dest_file); print "Installing :: '" . $dest_file . "'\n"; $fc++; } else{ - $diff = Diff($dest_file, $staged_file); + $diff = do_file_diff($dest_file, $staged_file); if($diff ne ""){ $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; print $diff . "\n"; @@ -570,7 +591,7 @@ sub LUA_Modules_Fetch{ if($input=~/N/i){} else{ #::: Make a backup - CopyFile($dest_file, $backup_dest); + copy_file($dest_file, $backup_dest); #::: Copy staged to running copy($staged_file, $dest_file); print "Installing :: '" . $dest_file . "'\n\n"; @@ -586,12 +607,12 @@ sub LUA_Modules_Fetch{ } } -sub Plugins_Fetch{ +sub plugins_fetch{ if (!-e "updates_staged/Quests-Plugins-master/plugins/") { print "\n --- Fetching Latest Plugins --- \n"; - GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + 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/'); + unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } $fc = 0; @@ -611,12 +632,12 @@ sub Plugins_Fetch{ $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; if (!-e $dest_file) { - CopyFile($staged_file, $dest_file); + copy_file($staged_file, $dest_file); print "Installing :: '" . $dest_file . "'\n"; $fc++; } else{ - $diff = Diff($dest_file, $staged_file); + $diff = do_file_diff($dest_file, $staged_file); if($diff ne ""){ $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; print $diff . "\n"; @@ -626,7 +647,7 @@ sub Plugins_Fetch{ if($input=~/N/i){} else{ #::: Make a backup - CopyFile($dest_file, $backup_dest); + copy_file($dest_file, $backup_dest); #::: Copy staged to running copy($staged_file, $dest_file); print "Installing :: '" . $dest_file . "'\n\n"; @@ -642,7 +663,7 @@ sub Plugins_Fetch{ } } -sub Diff{ +sub do_file_diff{ $file_1 = $_[0]; $file_2 = $_[1]; if($OS eq "Windows"){ @@ -656,7 +677,7 @@ sub Diff{ } } -sub UnZip{ +sub unzip{ $archive_to_unzip = $_[0]; $dest_folder = $_[1]; @@ -674,7 +695,7 @@ sub UnZip{ } } -sub AreFileSizesDifferent{ +sub are_file_sizes_different{ $file_1 = $_[0]; $file_2 = $_[1]; my $file_1 = (stat $file_1)[7]; @@ -686,35 +707,103 @@ sub AreFileSizesDifferent{ return; } +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; + + #::: 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 "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")); + + 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{ +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(defined(@total_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 GetMySQLResultFromFile("db_update/$file_name"); - print GetMySQLResult("UPDATE db_version SET version = $val WHERE version < $val"); - } - } - + print get_mysql_result_from_file("db_update/$file_name"); + print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); + } + $db_run_stage = 2; + } #::: Run 1 - Initial checking of needed updates... - 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]; + 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 = (); @@ -730,9 +819,9 @@ sub Run_Database_Check{ #::: Match type update if($match_type eq "contains"){ - if(trim(GetMySQLResult($query_check))=~/$match_text/i){ + if(trim(get_mysql_result($query_check))=~/$match_text/i){ print "Missing DB Update " . $i . " '" . $file_name . "' \n"; - FetchMissingUpdate($i, $file_name); + fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ @@ -742,22 +831,22 @@ sub Run_Database_Check{ print_break(); } if($match_type eq "missing"){ - if(GetMySQLResult($query_check)=~/$match_text/i){ + 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"; - FetchMissingUpdate($i, $file_name); + fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } print_match_debug(); print_break(); } if($match_type eq "empty"){ - if(GetMySQLResult($query_check) eq ""){ + if(get_mysql_result($query_check) eq ""){ print "Missing DB Update " . $i . " '" . $file_name . "' \n"; - FetchMissingUpdate($i, $file_name); + fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ @@ -767,9 +856,9 @@ sub Run_Database_Check{ print_break(); } if($match_type eq "not_empty"){ - if(GetMySQLResult($query_check) ne ""){ + if(get_mysql_result($query_check) ne ""){ print "Missing DB Update " . $i . " '" . $file_name . "' \n"; - FetchMissingUpdate($i, $file_name); + fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ @@ -779,23 +868,36 @@ sub Run_Database_Check{ print_break(); } } - print "\n"; + print "\n"; - if(scalar (@total_updates) == 0){ + if(scalar (@total_updates) == 0 && $db_run_stage == 2){ print "No updates need to be run...\n"; - print "Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; - GetMySQLResult("UPDATE db_version SET version = $bin_db_ver"); + 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 FetchMissingUpdate{ +sub fetch_missing_db_update{ $db_update = $_[0]; $update_file = $_[1]; - if($db_update >= 9000){ - GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + 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){ - GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/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 . ""); } } @@ -804,7 +906,7 @@ sub print_match_debug{ print " Match Type: '" . $match_type . "'\n"; print " Match Text: '" . $match_text . "'\n"; print " Query Check: '" . $query_check . "'\n"; - print " Result: '" . trim(GetMySQLResult($query_check)) . "'\n"; + print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; } sub print_break{ if(!$debug){ return; } From 625df2ad9b9849255dad0af4cd9f3b3d56594df4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 2 Oct 2015 20:31:24 -0500 Subject: [PATCH 333/846] Forgot one part [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 abd3fafb8..8270527c9 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -494,7 +494,7 @@ bool Database::CheckDatabaseConversions() { /* 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 8"); + system("perl eqemu_update.pl V 9"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); From 9bf4f399da61e93e2e3fcfd953390e76976836fd Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 3 Oct 2015 13:42:00 -0400 Subject: [PATCH 334/846] Temporarily disabled bot versioning until script methods are corrected --- common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 5 +- .../required/2015_09_30_bots_fix_existing.sql | 280 ------------------ 3 files changed, 2 insertions(+), 285 deletions(-) delete mode 100644 utils/sql/git/bots/required/2015_09_30_bots_fix_existing.sql diff --git a/common/version.h b/common/version.h index ed3167e9a..e2cda9a31 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9087 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9001 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // temporarily disabled #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 413f91444..91cdd7b69 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -1,7 +1,4 @@ -9000|2015_09_30_bots_fix_existing.sql|SHOW TABLES LIKE 'bot%'|not_empty| -9001|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot%'|empty| - -9002|2015_09_30_bots_initial_updates.sql||| +9000|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot%'|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/2015_09_30_bots_fix_existing.sql b/utils/sql/git/bots/required/2015_09_30_bots_fix_existing.sql deleted file mode 100644 index 0dd030545..000000000 --- a/utils/sql/git/bots/required/2015_09_30_bots_fix_existing.sql +++ /dev/null @@ -1,280 +0,0 @@ --- 'load_bots' sql script file --- current as of 10/15/2014 --- --- Use this file on databases where the player profile blob has been converted. --- --- Note: This file assumes a database free of bot remnants. If you have a prior --- bot installation and wish to reload the default schema and entries, then --- source 'drop_bots.sql' before sourcing this file. - - -ALTER TABLE `guild_members` DROP PRIMARY KEY; -ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); - -UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298); - --- old command kept for reference (`commands` now only has 2 columns - `command` and `access`) --- INSERT INTO `commands` VALUES ('bot', '0', 'Type \"#bot help\" to the see the list of available commands for bots.'); -INSERT INTO `commands` VALUES ('bot', '0'); - -INSERT INTO `rule_values` VALUES - ('1', 'Bots:BotAAExpansion', '8', 'The expansion through which bots will obtain AAs'), - ('1', 'Bots:BotFinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.'), - ('1', 'Bots:BotGroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.'), - ('1', 'Bots:BotManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.'), - ('1', 'Bots:BotQuest', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl'), - ('1', 'Bots:BotSpellQuest', 'false', 'Anita Thrall\'s (Anita_Thrall.pl) Bot Spell Scriber quests.'), - ('1', 'Bots:CreateBotCount', '150', 'Number of bots that each account can create'), - ('1', 'Bots:SpawnBotCount', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid'); - -CREATE TABLE `bots` ( - `BotID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotOwnerCharacterID` INT(10) UNSIGNED NOT NULL, - `BotSpellsID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Name` VARCHAR(64) NOT NULL, - `LastName` VARCHAR(32) DEFAULT NULL, - `BotLevel` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', - `Race` SMALLINT(5) NOT NULL DEFAULT '0', - `Class` TINYINT(2) NOT NULL DEFAULT '0', - `Gender` TINYINT(2) NOT NULL DEFAULT '0', - `Size` FLOAT NOT NULL DEFAULT '0', - `Face` INT(10) NOT NULL DEFAULT '1', - `LuclinHairStyle` INT(10) NOT NULL DEFAULT '1', - `LuclinHairColor` INT(10) NOT NULL DEFAULT '1', - `LuclinEyeColor` INT(10) NOT NULL DEFAULT '1', - `LuclinEyeColor2` INT(10) NOT NULL DEFAULT '1', - `LuclinBeardColor` INT(10) NOT NULL DEFAULT '1', - `LuclinBeard` INT(10) NOT NULL DEFAULT '0', - `DrakkinHeritage` INT(10) NOT NULL DEFAULT '0', - `DrakkinTattoo` INT(10) NOT NULL DEFAULT '0', - `DrakkinDetails` INT(10) NOT NULL DEFAULT '0', - `HP` INTEGER NOT NULL DEFAULT '0', - `Mana` INTEGER NOT NULL DEFAULT '0', - `MR` SMALLINT(5) NOT NULL DEFAULT '0', - `CR` SMALLINT(5) NOT NULL DEFAULT '0', - `DR` SMALLINT(5) NOT NULL DEFAULT '0', - `FR` SMALLINT(5) NOT NULL DEFAULT '0', - `PR` SMALLINT(5) NOT NULL DEFAULT '0', - `Corrup` SMALLINT(5) NOT NULL DEFAULT '0', - `AC` SMALLINT(5) NOT NULL DEFAULT '0', - `STR` MEDIUMINT(8) NOT NULL DEFAULT '75', - `STA` MEDIUMINT(8) NOT NULL DEFAULT '75', - `DEX` MEDIUMINT(8) NOT NULL DEFAULT '75', - `AGI` MEDIUMINT(8) NOT NULL DEFAULT '75', - `_INT` MEDIUMINT(8) NOT NULL DEFAULT '80', - `WIS` MEDIUMINT(8) NOT NULL DEFAULT '75', - `CHA` MEDIUMINT(8) NOT NULL DEFAULT '75', - `ATK` MEDIUMINT(9) NOT NULL DEFAULT '0', - `BotCreateDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - `LastSpawnDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', - `TotalPlayTime` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `LastZoneId` SMALLINT(6) NOT NULL DEFAULT '0', - `BotInspectMessage` VARCHAR(256) NOT NULL DEFAULT '', - PRIMARY KEY (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botstances` ( - `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `StanceID` TINYINT UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotID`), - CONSTRAINT `FK_botstances_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -); - -CREATE TABLE `bottimers` ( - `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `TimerID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Value` INT(10) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotID`), - CONSTRAINT `FK_bottimers_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -); - -CREATE TABLE `botbuffs` ( - `BotBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `DurationFormula` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `TicsRemaining` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `PoisonCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `DiseaseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `CurseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `CorruptionCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `HitCount` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `MeleeRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `MagicRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `DeathSaveSuccessChance` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterAARank` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Persistent` TINYINT(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`BotBuffId`), - KEY `FK_botbuff_1` (`BotId`), - CONSTRAINT `FK_botbuff_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botinventory` ( - `BotInventoryID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotID` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `SlotID` INTEGER SIGNED NOT NULL DEFAULT '0', - `ItemID` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `charges` TINYINT(3) UNSIGNED DEFAULT 0, - `color` INTEGER UNSIGNED NOT NULL DEFAULT 0, - `augslot1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot5` MEDIUMINT(7) UNSIGNED DEFAULT 0, - `instnodrop` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, - PRIMARY KEY (`BotInventoryID`), - KEY `FK_botinventory_1` (`BotID`), - CONSTRAINT `FK_botinventory_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botpets` ( - `BotPetsId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `PetId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `Name` VARCHAR(64) NULL, - `Mana` INTEGER NOT NULL DEFAULT '0', - `HitPoints` INTEGER NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetsId`), - KEY `FK_botpets_1` (`BotId`), - CONSTRAINT `FK_botpets_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`), - CONSTRAINT `U_botpets_1` UNIQUE (`BotId`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botpetbuffs` ( - `BotPetBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotPetsId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Duration` INT(11) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetBuffId`), - KEY `FK_botpetbuffs_1` (`BotPetsId`), - CONSTRAINT `FK_botpetbuffs_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botpetinventory` ( - `BotPetInventoryId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotPetsId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `ItemId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetInventoryId`), - KEY `FK_botpetinventory_1` (`BotPetsId`), - CONSTRAINT `FK_botpetinventory_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botgroup` ( - `BotGroupId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotGroupLeaderBotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotGroupName` VARCHAR(64) NOT NULL, - PRIMARY KEY (`BotGroupId`), - KEY `FK_botgroup_1` (`BotGroupLeaderBotId`), - CONSTRAINT `FK_botgroup_1` FOREIGN KEY (`BotGroupLeaderBotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botgroupmembers` ( - `BotGroupMemberId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotGroupId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotGroupMemberId`), - KEY `FK_botgroupmembers_1` (`BotGroupId`), - CONSTRAINT `FK_botgroupmembers_1` FOREIGN KEY (`BotGroupId`) REFERENCES `botgroup` (`BotGroupId`), - KEY `FK_botgroupmembers_2` (`BotId`), - CONSTRAINT `FK_botgroupmembers_2` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botguildmembers` ( - `char_id` INT(11) NOT NULL DEFAULT '0', - `guild_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', - `rank` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `tribute_enable` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `total_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `last_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `banker` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `public_note` TEXT NULL, - `alt` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`char_id`) -) ENGINE=InnoDB; - -DELIMITER $$ - -CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1) -BEGIN - DECLARE Result CHAR(1); - - SET Result = NULL; - - IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN - SET Result = 'C'; - ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN - SET Result = 'B'; - END IF; - - RETURN Result; -END$$ - -DELIMITER ; - -CREATE VIEW `vwBotCharacterMobs` AS -SELECT _utf8'C' AS mobtype, -c.`id`, -c.`name`, -c.`class`, -c.`level`, -c.`last_login`, -c.`zone_id` -FROM `character_data` AS c -UNION ALL -SELECT _utf8'B' AS mobtype, -b.`BotID` AS id, -b.`Name` AS name, -b.`Class` AS class, -b.`BotLevel` AS level, -0 AS timelaston, -0 AS zoneid -FROM bots AS b; - -CREATE VIEW `vwGroups` AS -SELECT g.`groupid` AS groupid, -GetMobType(g.`name`) AS mobtype, -g.`name` AS name, -g.`charid` AS mobid, -IFNULL(c.`level`, b.`BotLevel`) AS level -FROM `group_id` AS g -LEFT JOIN `character_data` AS c ON g.`name` = c.`name` -LEFT JOIN `bots` AS b ON g.`name` = b.`Name`; - -CREATE VIEW `vwBotGroups` AS -SELECT g.`BotGroupId`, -g.`BotGroupName`, -g.`BotGroupLeaderBotId`, -b.`Name` AS BotGroupLeaderName, -b.`BotOwnerCharacterId`, -c.`name` AS BotOwnerCharacterName -FROM `botgroup` AS g -JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID` -JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id` -ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`; - -CREATE VIEW `vwGuildMembers` AS -SELECT 'C' AS mobtype, -cm.`char_id`, -cm.`guild_id`, -cm.`rank`, -cm.`tribute_enable`, -cm.`total_tribute`, -cm.`last_tribute`, -cm.`banker`, -cm.`public_note`, -cm.`alt` -FROM `guild_members` AS cm -UNION ALL -SELECT 'B' AS mobtype, -bm.`char_id`, -bm.`guild_id`, -bm.`rank`, -bm.`tribute_enable`, -bm.`total_tribute`, -bm.`last_tribute`, -bm.`banker`, -bm.`public_note`, -bm.`alt` -FROM `botguildmembers` AS bm; From bcf2a5c852f0e1677c67da23f75e69457155fda9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 3 Oct 2015 16:03:53 -0500 Subject: [PATCH 335/846] eqemu_update.pl minor adjustment, v10 [skip ci] --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 8270527c9..c3c54cde5 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -494,7 +494,7 @@ bool Database::CheckDatabaseConversions() { /* 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 9"); + system("perl eqemu_update.pl V 10"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 37a2505d9..00d506630 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -22,7 +22,7 @@ if($Config{osname}=~/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 = 9; +$current_version = 10; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -146,9 +146,12 @@ if($db){ print " Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; #::: Bots - $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); - if($bots_local_db_version > 0){ - print " (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; + #::: 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... @@ -707,6 +710,16 @@ sub are_file_sizes_different{ return; } +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]); @@ -724,13 +737,7 @@ sub bots_db_management{ #::: Set on flag for running bot updates... $bots_db_management = 1; - #::: 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 "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")); + $bots_local_db_version = get_bots_db_version(); run_database_check(); } From 658b6ba5703e3366350f307b5214470e4243a9bf Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 3 Oct 2015 20:23:39 -0500 Subject: [PATCH 336/846] Adjustments to eqemu_update.pl menu (V11) --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 38 +++++++++++++++++---------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index c3c54cde5..510d98f76 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -494,7 +494,7 @@ bool Database::CheckDatabaseConversions() { /* 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 10"); + system("perl eqemu_update.pl V 11"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 00d506630..eb3e49f53 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -22,7 +22,7 @@ if($Config{osname}=~/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 = 10; +$current_version = 11; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -241,31 +241,33 @@ sub menu_options { $bots_management = "Install bots database pre-requisites (Requires bots server binaries)"; } else{ - $bots_management = "Check for Bot pending REQUIRED database updates..."; + $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..."; + $bots_management = "Check for Bot REQUIRED database updates... (Must have bots enabled)"; } return < Date: Sat, 3 Oct 2015 22:13:16 -0500 Subject: [PATCH 337/846] Fix menu links [skip ci] --- 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 eb3e49f53..48a3f28c3 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -184,13 +184,13 @@ sub show_menu_prompt { 1 => \&database_dump, 2 => \&database_dump_compress, 3 => \&main_db_management, - 4 => \&aa_fetch, + 10 => \&aa_fetch, 5 => \&opcodes_fetch, 6 => \&map_files_fetch, 7 => \&plugins_fetch, 8 => \&quest_files_fetch, 9 => \&lua_modules_fetch, - 10 => \&bots_db_management, + 4 => \&bots_db_management, 20 => \&do_update_self, 0 => \&script_exit, ); From aaae583dabdaddd455c6ae50fb3f89b8da0f24ee Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 4 Oct 2015 20:48:11 -0500 Subject: [PATCH 338/846] Fix hash order [skip ci] --- 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 48a3f28c3..f34d5b9af 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -184,13 +184,13 @@ sub show_menu_prompt { 1 => \&database_dump, 2 => \&database_dump_compress, 3 => \&main_db_management, - 10 => \&aa_fetch, + 4 => \&bots_db_management, 5 => \&opcodes_fetch, 6 => \&map_files_fetch, 7 => \&plugins_fetch, 8 => \&quest_files_fetch, 9 => \&lua_modules_fetch, - 4 => \&bots_db_management, + 10 => \&aa_fetch, 20 => \&do_update_self, 0 => \&script_exit, ); From 2680fc1a8379d59e1466945cb699e493e566fc8d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 5 Oct 2015 01:07:59 -0500 Subject: [PATCH 339/846] Preliminary routines for modular installer efforts [skip ci] --- utils/scripts/eqemu_update.pl | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index f34d5b9af..2c9393162 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -66,6 +66,16 @@ while() { elsif(/(.*)<\/db>/i) { $db = $1; } } +if($ARGV[0] eq "installer"){ + print "Running EQEmu Server installer routines...\n"; + map_files_fetch_bulk(); + opcodes_fetch(); + plugins_fetch(); + quest_files_fetch(); + lua_modules_fetch(); + exit; +} + $console_output = "============================================================ EQEmu: Automatic Upgrade Check @@ -463,6 +473,28 @@ sub copy_file{ copy $l_source_file, $l_dest_file; } +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"; @@ -551,6 +583,8 @@ sub quest_files_fetch{ } } + rmtree('updates_staged'); + if($fc == 0){ print "\nNo Quest Updates found... \n\n"; } From ffe1bede52ebf59d75d9328790d517397772a5d1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Oct 2015 14:26:53 -0500 Subject: [PATCH 340/846] eqemu_update.pl additions for EQEmu Installer to come [skip ci] --- utils/scripts/eqemu_update.pl | 173 +++++++++++++++++++++++++--------- 1 file changed, 128 insertions(+), 45 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 2c9393162..c7c7e94b2 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -14,6 +14,7 @@ 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()); @@ -49,9 +50,6 @@ no warnings; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); -#::: Cleanup staged folder... -rmtree("updates_staged/"); - my $confile = "eqemu_config.xml"; #default open(F, "<$confile"); my $indb = 0; @@ -66,16 +64,6 @@ while() { elsif(/(.*)<\/db>/i) { $db = $1; } } -if($ARGV[0] eq "installer"){ - print "Running EQEmu Server installer routines...\n"; - map_files_fetch_bulk(); - opcodes_fetch(); - plugins_fetch(); - quest_files_fetch(); - lua_modules_fetch(); - exit; -} - $console_output = "============================================================ EQEmu: Automatic Upgrade Check @@ -113,12 +101,40 @@ if($OS eq "Linux"){ } #::: Path not found, error and exit -if($path eq ""){ +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 "installer"){ + print "Running EQEmu Server installer routines...\n"; + mkdir('logs'); + mkdir('updates_staged'); + fetch_latest_windows_binaries(); + map_files_fetch_bulk(); + opcodes_fetch(); + plugins_fetch(); + quest_files_fetch(); + lua_modules_fetch(); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); + + #::: Database Routines + print "MariaDB :: Creating Database 'peq'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE peq;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(); + exit; +} + #::: Create db_update working directory if not created mkdir('db_update'); @@ -128,15 +144,19 @@ if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" print "Old db_version table present, dropping...\n\n"; } -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_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`); } @@ -307,7 +327,10 @@ sub database_dump_compress { print `perl db_dumper.pl database="$db" loc="backups" compress`; } -sub script_exit{ } +sub script_exit{ + #::: Cleanup staged folder... + rmtree("updates_staged/"); +} #::: Returns Tab Delimited MySQL Result from Command Line sub get_mysql_result{ @@ -357,35 +380,48 @@ sub get_remote_file{ if($OS eq "Windows"){ #::: For non-text type requests... if($content_type == 1){ - use LWP::Simple qw(getstore); - if(!getstore($URL, $Dest_File)){ - print "Error, no connection or failed request...\n\n"; - } - else{ - print " o URL: (" . $URL . ")\n"; - print " o Saved: (" . $Dest_File . ") \n"; + $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{ - 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); - print " o URL: (" . $URL . ")\n"; - print " o Saved: (" . $Dest_File . ") \n"; - } - else { - print "Error, no connection or failed request...\n\n"; + $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"){ + 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"; @@ -473,6 +509,53 @@ sub copy_file{ 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_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); From 893f7525207651d901551c1c1f78f5ae6f5cd451 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 8 Oct 2015 09:41:47 -0500 Subject: [PATCH 341/846] Fix for proper script exit eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index c7c7e94b2..9c1556d21 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -330,6 +330,7 @@ sub database_dump_compress { sub script_exit{ #::: Cleanup staged folder... rmtree("updates_staged/"); + exit; } #::: Returns Tab Delimited MySQL Result from Command Line From c35eacbc99caa73dab35d580b3f29fd540fff8bd Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 8 Oct 2015 11:49:21 -0400 Subject: [PATCH 342/846] Update/Implementation of various fields in spells_new 219 not_extendable - > not_focusable - No focus are applied to these spells 217 maxtargets -> no_heal_damage_item_mod - Not applied to these spells. 232 -> no_remove -> Can not click off these spells even if beneficial 209 powerful_flag -> no_resist -> Unresistable spell --- common/ruletypesx.h | 562 +++++++++++++++++++++++++++++++++++++++++ common/shareddb.cpp | 7 +- common/spdat.h | 11 +- zone/aggro.cpp | 2 +- zone/client_packet.cpp | 2 +- zone/effects.cpp | 9 +- zone/lua_spell.cpp | 4 +- zone/mob.cpp | 6 +- zone/spell_effects.cpp | 8 +- zone/spells.cpp | 2 +- 10 files changed, 590 insertions(+), 23 deletions(-) create mode 100644 common/ruletypesx.h diff --git a/common/ruletypesx.h b/common/ruletypesx.h new file mode 100644 index 000000000..de0dbb587 --- /dev/null +++ b/common/ruletypesx.h @@ -0,0 +1,562 @@ + + + +#ifndef RULE_CATEGORY +#define RULE_CATEGORY(name) +#endif +#ifndef RULE_INT +#define RULE_INT(cat, rule, default_value) +#endif +#ifndef RULE_REAL +#define RULE_REAL(cat, rule, default_value) +#endif +#ifndef RULE_BOOL +#define RULE_BOOL(cat, rule, default_value) +#endif +#ifndef RULE_CATEGORY_END +#define RULE_CATEGORY_END() +#endif + + + + +RULE_CATEGORY( Character ) +RULE_INT ( Character, MaxLevel, 65 ) +RULE_BOOL ( Character, PerCharacterQglobalMaxLevel, false) // This will check for qglobal 'CharMaxLevel' character qglobal (Type 5), if player tries to level beyond that point, it will not go beyond that level +RULE_INT ( Character, MaxExpLevel, 0 ) //Sets the Max Level attainable via Experience +RULE_INT ( Character, DeathExpLossLevel, 10 ) // Any level greater than this will lose exp on death +RULE_INT ( Character, DeathExpLossMaxLevel, 255 ) // Any level greater than this will no longer lose exp on death +RULE_INT ( Character, DeathItemLossLevel, 10 ) +RULE_INT ( Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost +RULE_BOOL( Character, UseDeathExpLossMult, false ) //Adjust to use the above multiplier or to use code default. +RULE_INT ( Character, CorpseDecayTimeMS, 10800000 ) +RULE_INT ( Character, CorpseResTimeMS, 10800000 ) // time before cant res corpse(3 hours) +RULE_BOOL( Character, LeaveCorpses, true ) +RULE_BOOL( Character, LeaveNakedCorpses, false ) +RULE_INT ( Character, MaxDraggedCorpses, 2 ) +RULE_REAL( Character, DragCorpseDistance, 400) // If the corpse is <= this distance from the player, it won't move +RULE_REAL( Character, ExpMultiplier, 0.5 ) +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, LightBlueModifier, 40 ) +RULE_INT ( Character, BlueModifier, 90 ) +RULE_INT ( Character, WhiteModifier, 100 ) +RULE_INT ( Character, YellowModifier, 125 ) +RULE_INT ( Character, RedModifier, 150 ) +RULE_INT ( Character, AutosaveIntervalS, 300 ) //0=disabled +RULE_INT ( Character, HPRegenMultiplier, 100) +RULE_INT ( Character, ManaRegenMultiplier, 100) +RULE_INT ( Character, EnduranceRegenMultiplier, 100) +RULE_INT ( Character, ConsumptionMultiplier, 100) //item's hunger restored = this value * item's food level, 100 = normal, 50 = people eat 2x as fast, 200 = people eat 2x as slow +RULE_BOOL( Character, HealOnLevel, false) +RULE_BOOL( Character, FeignKillsPet, false) +RULE_INT ( Character, ItemManaRegenCap, 15) +RULE_INT ( Character, ItemHealthRegenCap, 35) +RULE_INT ( Character, ItemDamageShieldCap, 30) +RULE_INT ( Character, ItemAccuracyCap, 150) +RULE_INT ( Character, ItemAvoidanceCap, 100) +RULE_INT ( Character, ItemCombatEffectsCap, 100) +RULE_INT ( Character, ItemShieldingCap, 35) +RULE_INT ( Character, ItemSpellShieldingCap, 35) +RULE_INT ( Character, ItemDoTShieldingCap, 35) +RULE_INT ( Character, ItemStunResistCap, 35) +RULE_INT ( Character, ItemStrikethroughCap, 35) +RULE_INT ( Character, ItemATKCap, 250) +RULE_INT ( Character, ItemHealAmtCap, 250) +RULE_INT ( Character, ItemSpellDmgCap, 250) +RULE_INT ( Character, ItemClairvoyanceCap, 250) +RULE_INT ( Character, ItemDSMitigationCap, 50) +RULE_INT ( Character, ItemEnduranceRegenCap, 15) +RULE_INT ( Character, ItemExtraDmgCap, 150) // Cap for bonuses to melee skills like Bash, Frenzy, etc +RULE_INT ( Character, HasteCap, 100) // Haste cap for non-v3(overhaste) haste. +RULE_INT ( Character, SkillUpModifier, 100) //skill ups are at 100% +RULE_BOOL ( Character, SharedBankPlat, false) //off by default to prevent duping for now +RULE_BOOL ( Character, BindAnywhere, false) +RULE_INT ( Character, RestRegenPercent, 0) // Set to >0 to enable rest state bonus HP and mana regen. +RULE_INT ( Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in. +RULE_BOOL ( Character, RestRegenEndurance, false) // Whether rest regen will work for endurance or not. +RULE_INT ( Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA +RULE_INT ( Character, KillsPerRaidLeadershipAA, 250) // Number of dark blues or above per Raid Leadership AA +RULE_INT ( Character, MaxFearDurationForPlayerCharacter, 4) //4 tics, each tic calculates every 6 seconds. +RULE_INT ( Character, MaxCharmDurationForPlayerCharacter, 15) +RULE_INT ( Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values +RULE_BOOL ( Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas +RULE_BOOL ( Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses +RULE_BOOL ( Character, RespawnFromHover, false) // Use Respawn window, or not. +RULE_INT ( Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS +RULE_BOOL ( Character, UseNewStatsWindow, true) // New stats window shows everything +RULE_BOOL ( Character, ItemCastsUseFocus, false) // If true, this allows item clickies to use focuses that have limited max levels on them +RULE_INT ( Character, MinStatusForNoDropExemptions, 80) // This allows status x and higher to trade no drop items. +RULE_INT ( Character, SkillCapMaxLevel, 75 ) // Sets the Max Level used for Skill Caps (from skill_caps table). -1 makes it use MaxLevel rule value. It is set to 75 because PEQ only has skillcaps up to that level, and grabbing the players' skill past 75 will return 0, breaking all skills past that level. This helps servers with obsurd level caps (75+ level cap) function without any modifications. +RULE_INT ( Character, StatCap, 0 ) +RULE_BOOL ( Character, CheckCursorEmptyWhenLooting, true ) // If true, a player cannot loot a corpse (player or NPC) with an item on their cursor +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, 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. +RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. +RULE_CATEGORY_END() + +RULE_CATEGORY( Mercs ) +RULE_INT (Mercs, SuspendIntervalMS, 10000) +RULE_INT (Mercs, UpkeepIntervalMS, 180000) +RULE_INT (Mercs, SuspendIntervalS, 10) +RULE_INT (Mercs, UpkeepIntervalS, 180) +RULE_BOOL (Mercs, AllowMercs, false) +RULE_BOOL (Mercs, ChargeMercPurchaseCost, false) +RULE_BOOL (Mercs, ChargeMercUpkeepCost, false) +RULE_INT (Mercs, AggroRadius, 100) // Determines the distance from which a merc will aggro group member's target(also used to determine the distance at which a healer merc will begin healing a group member) +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_CATEGORY_END() + +RULE_CATEGORY( Guild ) +RULE_INT ( Guild, MaxMembers, 2048 ) +RULE_BOOL ( Guild, PlayerCreationAllowed, false) // Allow players to create a guild using the window in Underfoot+ +RULE_INT ( Guild, PlayerCreationLimit, 1) // Only allow use of the UF+ window if the account has < than this number of guild leaders on it +RULE_INT ( Guild, PlayerCreationRequiredStatus, 0) // Required admin status. +RULE_INT ( Guild, PlayerCreationRequiredLevel, 0) // Required Level of the player attempting to create the guild. +RULE_INT ( Guild, PlayerCreationRequiredTime, 0) // Required Time Entitled On Account (in Minutes) to create the guild. + +RULE_CATEGORY_END() + +RULE_CATEGORY( Skills ) +RULE_INT ( Skills, MaxTrainTradeskills, 21 ) +RULE_BOOL ( Skills, UseLimitTradeskillSearchSkillDiff, true ) +RULE_INT ( Skills, MaxTradeskillSearchSkillDiff, 50 ) +RULE_INT ( Skills, MaxTrainSpecializations, 50 ) // Max level a GM trainer will train casting specializations +RULE_CATEGORY_END() + +RULE_CATEGORY( Pets ) +RULE_REAL( Pets, AttackCommandRange, 150 ) +RULE_BOOL( Pets, UnTargetableSwarmPet, false ) +RULE_BOOL( Pets, SwarmPetNotTargetableWithHotKey, false ) //On SOF+ clients this a semi-hack to make swarm pets not F8 targetable. +RULE_CATEGORY_END() + +RULE_CATEGORY( GM ) +RULE_INT ( GM, MinStatusToSummonItem, 250) +RULE_INT ( GM, MinStatusToZoneAnywhere, 250 ) +RULE_CATEGORY_END() + +RULE_CATEGORY( World ) +RULE_INT ( World, ZoneAutobootTimeoutMS, 60000 ) +RULE_INT ( World, ClientKeepaliveTimeoutMS, 65000 ) +RULE_BOOL ( World, UseBannedIPsTable, false ) // Toggle whether or not to check incoming client connections against the Banned_IPs table. Set this value to false to disable this feature. +RULE_BOOL ( World, EnableTutorialButton, true) +RULE_BOOL ( World, EnableReturnHomeButton, true) +RULE_INT ( World, MaxLevelForTutorial, 10) +RULE_INT ( World, TutorialZoneID, 189) +RULE_INT ( World, GuildBankZoneID, 345) +RULE_INT ( World, MinOfflineTimeToReturnHome, 21600) // 21600 seconds is 6 Hours +RULE_INT ( World, MaxClientsPerIP, -1 ) // Maximum number of clients allowed to connect per IP address if account status is < AddMaxClientsStatus. Default value: -1 (feature disabled) +RULE_INT ( World, ExemptMaxClientsStatus, -1 ) // Exempt accounts from the MaxClientsPerIP and AddMaxClientsStatus rules, if their status is >= this value. Default value: -1 (feature disabled) +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, 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) +RULE_INT ( World, ExemptAccountLimitStatus, -1 ) //Min status required to be exempt from multi-session per account limiting (-1 is disabled) +RULE_BOOL ( World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts. +RULE_INT ( World, MinGMAntiHackStatus, 1 ) //Minimum GM status to check against AntiHack list +RULE_INT ( World, SoFStartZoneID, -1 ) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) +RULE_INT ( World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS. +RULE_INT ( World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules. +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_CATEGORY_END() + +RULE_CATEGORY( Zone ) +RULE_INT ( Zone, NPCPositonUpdateTicCount, 32 ) //ms between intervals of sending a position update to the entire zone. +RULE_INT ( Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection +RULE_INT ( Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone +RULE_BOOL ( Zone, EnableShadowrest, 1 ) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. +RULE_BOOL ( Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses. +RULE_INT ( Zone, MQWarpExemptStatus, -1 ) // Required status level to exempt the MQWarpDetector. Set to -1 to disable this feature. +RULE_INT ( Zone, MQZoneExemptStatus, -1 ) // Required status level to exempt the MQZoneDetector. Set to -1 to disable this feature. +RULE_INT ( Zone, MQGateExemptStatus, -1 ) // Required status level to exempt the MQGateDetector. Set to -1 to disable this feature. +RULE_INT ( Zone, MQGhostExemptStatus, -1 ) // Required status level to exempt the MGhostDetector. Set to -1 to disable this feature. +RULE_BOOL ( Zone, EnableMQWarpDetector, true ) // Enable the MQWarp Detector. Set to False to disable this feature. +RULE_BOOL ( Zone, EnableMQZoneDetector, true ) // Enable the MQZone Detector. Set to False to disable this feature. +RULE_BOOL ( Zone, EnableMQGateDetector, true ) // Enable the MQGate Detector. Set to False to disable this feature. +RULE_BOOL ( Zone, EnableMQGhostDetector, true ) // Enable the MQGhost Detector. Set to False to disable this feature. +RULE_REAL ( Zone, MQWarpDetectionDistanceFactor, 9.0) //clients move at 4.4 about if in a straight line but with movement and to acct for lag we raise it a bit +RULE_BOOL ( Zone, MarkMQWarpLT, false ) +RULE_INT ( Zone, AutoShutdownDelay, 5000 ) //How long a dynamic zone stays loaded while empty +RULE_INT ( Zone, PEQZoneReuseTime, 900 ) //How long, in seconds, until you can reuse the #peqzone command. +RULE_INT ( Zone, PEQZoneDebuff1, 4454 ) //First debuff casted by #peqzone Default is Cursed Keeper's Blight. +RULE_INT ( Zone, PEQZoneDebuff2, 2209 ) //Second debuff casted by #peqzone Default is Tendrils of Apathy. +RULE_BOOL ( Zone, UsePEQZoneDebuffs, true ) //Will determine if #peqzone will debuff players or not when used. +RULE_REAL ( Zone, HotZoneBonus, 0.75 ) +RULE_INT ( Zone, ReservedInstances, 30 ) //Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running. +RULE_INT ( Zone, EbonCrystalItemID, 40902) +RULE_INT ( Zone, RadiantCrystalItemID, 40903) +RULE_BOOL ( Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mods table in consideration to your players EXP hits +RULE_INT ( Zone, WeatherTimer, 600) // Weather timer when no duration is available +RULE_CATEGORY_END() + +RULE_CATEGORY( Map ) +//enable these to help prevent mob hopping when they are pathing +RULE_BOOL ( Map, FixPathingZWhenLoading, true ) //increases zone boot times a bit to reduce hopping. +RULE_BOOL ( Map, FixPathingZAtWaypoints, false ) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time. +RULE_BOOL ( Map, FixPathingZWhenMoving, false ) //very CPU intensive, but helps hopping with widely spaced waypoints. +RULE_BOOL ( Map, FixPathingZOnSendTo, false ) //try to repair Z coords in the SendTo routine as well. +RULE_REAL ( Map, FixPathingZMaxDeltaMoving, 20 ) //at runtime while pathing: max change in Z to allow the BestZ code to apply. +RULE_REAL ( Map, FixPathingZMaxDeltaWaypoint, 20 ) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. +RULE_REAL ( Map, FixPathingZMaxDeltaSendTo, 20 ) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. +RULE_REAL ( Map, FixPathingZMaxDeltaLoading, 45 ) //while loading each waypoint: max change in Z to allow the BestZ code to apply. +RULE_BOOL ( Map, UseClosestZ, false) // Move mobs to the nearest Z above or below, rather than just the nearest below. + // Only set UseClosestZ true if all your .map files generated from EQGs were created + // with azone2. + // +RULE_INT ( Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position +RULE_CATEGORY_END() + +RULE_CATEGORY( Pathing ) +// Some of these rules may benefit by being made into columns in the zone table, +// for instance, in dungeons, the min LOS distances could be substantially lowered. +RULE_BOOL ( Pathing, Aggro, true ) // Enable pathing for aggroed mobs. +RULE_BOOL ( Pathing, AggroReturnToGrid, true ) // Enable pathing for aggroed roaming mobs returning to their previous waypoint. +RULE_BOOL ( Pathing, Guard, true ) // Enable pathing for mobs moving to their guard point. +RULE_BOOL ( Pathing, Find, true ) // Enable pathing for FindPerson requests from the client. +RULE_BOOL ( Pathing, Fear, true ) // Enable pathing for fear +RULE_REAL ( Pathing, ZDiffThreshold, 10) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. +RULE_INT ( Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds). +RULE_INT ( Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved. +RULE_INT ( Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved. +// When a path has a path node route and it's target changes position, if it has RouteUpdateFrequencyNodeCount or less nodes to go on it's +// current path, it will recalculate it's path based on the RouteUpdateFrequencyShort timer, otherwise it will use the +// RouteUpdateFrequencyLong timer. +RULE_INT ( Pathing, RouteUpdateFrequencyNodeCount, 5) +RULE_REAL ( Pathing, MinDistanceForLOSCheckShort, 40000) // (NoRoot). While following a path, only check for LOS to target within this distance. +RULE_REAL ( Pathing, MinDistanceForLOSCheckLong, 1000000) // (NoRoot). Min distance when initially attempting to acquire the target. +RULE_INT ( Pathing, MinNodesLeftForLOSCheck, 4) // Only check for LOS when we are down to this many path nodes left to run. +// This next rule was put in for situations where the mob and it's target may be on different sides of a 'hazard', e.g. a pit +// If the mob has LOS to it's target, even though there is a hazard in it's way, it may break off from the node path and run at +// the target, only to later detect the hazard and re-acquire a node path. Depending upon the placement of the path nodes, this +// can lead to the mob looping. The rule is intended to allow the mob to at least get closer to it's target each time before +// checking LOS and trying to head straight for it. +RULE_INT ( Pathing, MinNodesTraversedForLOSCheck, 3) // Only check for LOS after we have traversed this many path nodes. +RULE_INT ( Pathing, CullNodesFromStart, 1) // Checks LOS from Start point to second node for this many nodes and removes first node if there is LOS +RULE_INT ( Pathing, CullNodesFromEnd, 1) // Checks LOS from End point to second to last node for this many nodes and removes last node if there is LOS +RULE_REAL ( Pathing, CandidateNodeRangeXY, 400) // When searching for path start/end nodes, only nodes within this range will be considered. +RULE_REAL ( Pathing, CandidateNodeRangeZ, 10) // When searching for path start/end nodes, only nodes within this range will be considered. + +RULE_CATEGORY_END() + +RULE_CATEGORY( Watermap ) +// enable these to use the water detection code. Requires Water Maps generated by awater utility +RULE_BOOL ( Watermap, CheckWaypointsInWaterWhenLoading, false ) // Does not apply BestZ as waypoints are loaded if they are in water +RULE_BOOL ( Watermap, CheckForWaterAtWaypoints, false) // Check if a mob has moved into/out of water when at waypoints and sets flymode +RULE_BOOL ( Watermap, CheckForWaterWhenMoving, false) // Checks if a mob has moved into/out of water each time it's loc is recalculated +RULE_BOOL ( Watermap, CheckForWaterOnSendTo, false) // Checks if a mob has moved into/out of water on SendTo +RULE_BOOL ( Watermap, CheckForWaterWhenFishing, false) // Only lets a player fish near water (if a water map exists for the zone) +RULE_REAL ( Watermap, FishingRodLength, 30) // How far in front of player water must be for fishing to work +RULE_REAL ( Watermap, FishingLineLength, 40) // If water is more than this far below the player, it is considered too far to fish +RULE_CATEGORY_END() + +RULE_CATEGORY( Spells ) +RULE_INT ( Spells, AutoResistDiff, 15) +RULE_REAL ( Spells, ResistChance, 2.0) //chance to resist given no resists and same level +RULE_REAL ( Spells, ResistMod, 0.40) //multiplier, chance to resist = this * ResistAmount +RULE_REAL ( Spells, PartialHitChance, 0.7) //The chance when a spell is resisted that it will partial hit. +RULE_REAL ( Spells, PartialHitChanceFear, 0.25) //The chance when a fear spell is resisted that it will partial hit. +RULE_INT ( Spells, BaseCritChance, 0) //base % chance that everyone has to crit a spell +RULE_INT ( Spells, BaseCritRatio, 100) //base % bonus to damage on a successful spell crit. 100 = 2x damage +RULE_INT ( Spells, WizCritLevel, 12) //level wizards first get spell crits +RULE_INT ( Spells, WizCritChance, 7) //wiz's crit chance, on top of BaseCritChance +RULE_INT ( Spells, WizCritRatio, 0) //wiz's crit bonus, on top of BaseCritRatio (should be 0 for Live-like) +RULE_INT ( Spells, ResistPerLevelDiff, 85) //8.5 resist per level difference. +RULE_INT ( Spells, TranslocateTimeLimit, 0) // If not zero, time in seconds to accept a Translocate. +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, 25) // 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 +RULE_BOOL( Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized +RULE_INT ( Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0. +RULE_BOOL ( Spells, NPCIgnoreBaseImmunity, true) // Whether or not NPCs get to ignore the BaseImmunityLevel for their spells. +RULE_REAL ( Spells, AvgSpellProcsPerMinute, 6.0) //Adjust rate for sympathetic spell procs +RULE_INT ( Spells, ResistFalloff, 67) //Max that level that will adjust our resist chance based on level modifiers +RULE_INT ( Spells, CharismaEffectiveness, 10) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. +RULE_INT ( Spells, CharismaEffectivenessCap, 255) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. +RULE_BOOL ( Spells, CharismaCharmDuration, false) // Allow CHA resist mod to extend charm duration. +RULE_INT ( Spells, CharmBreakCheckChance, 25) //Determines chance for a charm break check to occur each buff tick. +RULE_INT ( Spells, MaxCastTimeReduction, 50) //Max percent your spell cast time can be reduced by spell haste +RULE_INT ( Spells, RootBreakFromSpells, 55) //Chance for root to break when cast on. +RULE_INT ( Spells, DeathSaveCharismaMod, 3) //Determines how much charisma effects chance of death save firing. +RULE_INT ( Spells, DivineInterventionHeal, 8000) //Divine intervention heal amount. +RULE_BOOL ( Spells, AdditiveBonusValues, false) //Allow certain bonuses to be calculated by adding together the value from each item, instead of taking the highest value. (ie Add together all Cleave Effects) +RULE_BOOL ( Spells, UseCHAScribeHack, false) //ScribeSpells and TrainDiscs quest functions will ignore entries where field 12 is CHA. What's the best way to do this? +RULE_BOOL ( Spells, BuffLevelRestrictions, true) //Buffs will not land on low level toons like live +RULE_INT ( Spells, RootBreakCheckChance, 70) //Determines chance for a root break check to occur each buff tick. +RULE_INT ( Spells, FearBreakCheckChance, 70) //Determines chance for a fear break check to occur each buff tick. +RULE_INT ( Spells, SuccorFailChance, 2) //Determines chance for a succor spell not to teleport an invidual player +RULE_INT ( Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clients for Fire 'spell projectile'. +RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'. +RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'. +RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file. +RULE_BOOL ( Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects. +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, 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_BOOL ( Combat, UseIntervalAC, true) +RULE_INT ( Combat, PetAttackMagicLevel, 30) +RULE_BOOL ( Combat, EnableFearPathing, true) +RULE_REAL ( Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker. +RULE_INT ( Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee. +RULE_BOOL ( Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it. +RULE_BOOL ( Combat, AdjustProcPerMinute, true) +RULE_REAL ( Combat, AvgProcsPerMinute, 2.0) +RULE_REAL ( Combat, ProcPerMinDexContrib, 0.075) +RULE_REAL ( Combat, BaseProcChance, 0.035) +RULE_REAL ( Combat, ProcDexDivideBy, 11000) +RULE_REAL ( Combat, BaseHitChance, 69.0) +RULE_REAL ( Combat, NPCBonusHitChance, 26.0) +RULE_REAL ( Combat, HitFalloffMinor, 5.0) //hit will fall off up to 5% over the initial level range +RULE_REAL ( Combat, HitFalloffModerate, 7.0) //hit will fall off up to 7% over the three levels after the initial level range +RULE_REAL ( Combat, HitFalloffMajor, 50.0) //hit will fall off sharply if we're outside the minor and moderate range +RULE_REAL ( Combat, HitBonusPerLevel, 1.2) //You gain this % of hit for every level you are above your target +RULE_REAL ( Combat, WeaponSkillFalloff, 0.33) //For every weapon skill point that's not maxed you lose this % of hit +RULE_REAL ( Combat, ArcheryHitPenalty, 0.25) //Archery has a hit penalty to try to help balance it with the plethora of long term +hit modifiers for it +RULE_REAL ( Combat, AgiHitFactor, 0.01) +RULE_INT ( Combat, MinRangedAttackDist, 25) //Minimum Distance to use Ranged Attacks +RULE_BOOL ( Combat, ArcheryBonusRequiresStationary, true) //does the 2x archery bonus chance require a stationary npc +RULE_REAL ( Combat, ArcheryBaseDamageBonus, 1) // % Modifier to Base Archery Damage (.5 = 50% base damage, 1 = 100%, 2 = 200%) +RULE_REAL ( Combat, ArcheryNPCMultiplier, 1.0) // this is multiplied by the regular dmg to get the archery dmg +RULE_BOOL ( Combat, AssistNoTargetSelf, true) //when assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like) +RULE_INT ( Combat, MaxRampageTargets, 3) //max number of people hit with rampage +RULE_INT ( Combat, DefaultRampageTargets, 1) // default number of people to hit with rampage +RULE_BOOL ( Combat, RampageHitsTarget, false) // rampage will hit the target if it still has targets left +RULE_INT ( Combat, MaxFlurryHits, 2) //max number of extra hits from flurry +RULE_INT ( Combat, MonkDamageTableBonus, 5) //% bonus monks get to their damage table calcs +RULE_INT ( Combat, FlyingKickBonus, 25) //% Modifier that this skill gets to str and skill bonuses +RULE_INT ( Combat, DragonPunchBonus, 20) //% Modifier that this skill gets to str and skill bonuses +RULE_INT ( Combat, EagleStrikeBonus, 15) //% Modifier that this skill gets to str and skill bonuses +RULE_INT ( Combat, TigerClawBonus, 10) //% Modifier that this skill gets to str and skill bonuses +RULE_INT ( Combat, RoundKickBonus, 5) //% Modifier that this skill gets to str and skill bonuses +RULE_INT ( Combat, FrenzyBonus, 0) //% Modifier to damage +RULE_BOOL ( Combat, ProcTargetOnly, true) //true = procs will only affect our target, false = procs will affect all of our targets +RULE_REAL ( Combat, NPCACFactor, 2.25) +RULE_INT ( Combat, ClothACSoftcap, 75) +RULE_INT ( Combat, LeatherACSoftcap, 100) +RULE_INT ( Combat, MonkACSoftcap, 120) +RULE_INT ( Combat, ChainACSoftcap, 200) +RULE_INT ( Combat, PlateACSoftcap, 300) +RULE_REAL ( Combat, AAMitigationACFactor, 3.0) +RULE_REAL ( Combat, WarriorACSoftcapReturn, 0.45) +RULE_REAL ( Combat, KnightACSoftcapReturn, 0.33) +RULE_REAL ( Combat, LowPlateChainACSoftcapReturn, 0.23) +RULE_REAL ( Combat, LowChainLeatherACSoftcapReturn, 0.17) +RULE_REAL ( Combat, CasterACSoftcapReturn, 0.06) +RULE_REAL ( Combat, MiscACSoftcapReturn, 0.3) +RULE_BOOL ( Combat, OldACSoftcapRules, false) // use old softcaps +RULE_BOOL ( Combat, UseOldDamageIntervalRules, false) // use old damage formulas for everything +RULE_REAL ( Combat, WarACSoftcapReturn, 0.3448) // new AC returns +RULE_REAL ( Combat, ClrRngMnkBrdACSoftcapReturn, 0.3030) +RULE_REAL ( Combat, PalShdACSoftcapReturn, 0.3226) +RULE_REAL ( Combat, DruNecWizEncMagACSoftcapReturn, 0.2000) +RULE_REAL ( Combat, RogShmBstBerACSoftcapReturn, 0.2500) +RULE_REAL ( Combat, SoftcapFactor, 1.88) +RULE_REAL ( Combat, ACthac0Factor, 0.55) +RULE_REAL ( Combat, ACthac20Factor, 0.55) +RULE_INT ( Combat, HitCapPre20, 40) // live has it capped at 40 for whatever dumb reason... this is mainly for custom servers +RULE_INT ( Combat, HitCapPre10, 20) // live has it capped at 20, see above :p +RULE_INT ( Combat, MinHastedDelay, 400) // how fast we can get with haste. +RULE_REAL ( Combat, AvgDefProcsPerMinute, 2.0) +RULE_REAL ( Combat, DefProcPerMinAgiContrib, 0.075) //How much agility contributes to defensive proc rate +RULE_INT ( Combat, SpecialAttackACBonus, 15) //Percent amount of damage per AC gained for certain special attacks (damage = AC*SpecialAttackACBonus/100). +RULE_INT ( Combat, NPCFlurryChance, 20) // Chance for NPC to flurry. +RULE_BOOL (Combat,TauntOverLevel, 1) //Allows you to taunt NPC's over warriors level. +RULE_REAL (Combat,TauntSkillFalloff, 0.33)//For every taunt skill point that's not maxed you lose this % chance to taunt. +RULE_BOOL (Combat,EXPFromDmgShield, false) //Determine if damage from a damage shield counts for EXP gain. +RULE_INT ( Combat, MonkACBonusWeight, 15) +RULE_INT ( Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target +RULE_INT ( Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers +RULE_BOOL ( Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll +RULE_INT ( Combat, ArcheryBonusChance, 50) +RULE_INT ( Combat, BerserkerFrenzyStart, 35) +RULE_INT ( Combat, BerserkerFrenzyEnd, 45) +RULE_BOOL ( Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round +RULE_CATEGORY_END() + +RULE_CATEGORY( NPC ) +RULE_INT ( NPC, MinorNPCCorpseDecayTimeMS, 450000 ) //level<55 +RULE_INT ( NPC, MajorNPCCorpseDecayTimeMS, 1500000 ) //level>=55 +RULE_INT ( NPC, CorpseUnlockTimer, 150000 ) +RULE_INT ( NPC, EmptyNPCCorpseDecayTimeMS, 0 ) +RULE_BOOL (NPC, UseItemBonusesForNonPets, true) +RULE_INT ( NPC, SayPauseTimeInSec, 5) +RULE_INT ( NPC, OOCRegen, 0) +RULE_BOOL ( NPC, BuffFriends, false ) +RULE_BOOL ( NPC, EnableNPCQuestJournal, false) +RULE_INT ( NPC, LastFightingDelayMovingMin, 10000) +RULE_INT ( NPC, LastFightingDelayMovingMax, 20000) +RULE_BOOL ( NPC, SmartLastFightingDelayMoving, true) +RULE_BOOL ( NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPCs that don't have an EVENT_TRADE sub in their script +RULE_INT ( NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage +RULE_BOOL ( NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage +RULE_CATEGORY_END() + +RULE_CATEGORY ( Aggro ) +RULE_BOOL ( Aggro, SmartAggroList, true ) +RULE_INT ( Aggro, SittingAggroMod, 35 ) //35% +RULE_INT ( Aggro, MeleeRangeAggroMod, 10 ) //10% +RULE_INT ( Aggro, CurrentTargetAggroMod, 0 ) //0% -- will prefer our current target to any other; makes it harder for our npcs to switch targets. +RULE_INT ( Aggro, CriticallyWoundedAggroMod, 100 ) //100% +RULE_INT ( Aggro, SpellAggroMod, 100 ) +RULE_INT ( Aggro, SongAggroMod, 33 ) +RULE_INT ( Aggro, PetSpellAggroMod, 10 ) +RULE_REAL ( Aggro, TunnelVisionAggroMod, 0.75 ) //people not currently the top hate generate this much hate on a Tunnel Vision mob +RULE_INT ( Aggro, MaxStunProcAggro, 400 ) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add. +RULE_INT ( Aggro, IntAggroThreshold, 75 ) // Int <= this will aggro regardless of level difference. +RULE_CATEGORY_END() + +RULE_CATEGORY ( TaskSystem) +RULE_BOOL ( TaskSystem, EnableTaskSystem, true) // Globally enable or disable the Task system +RULE_INT ( TaskSystem, PeriodicCheckTimer, 5) // Seconds between checks for failed tasks. Also used by the 'Touch' activity +RULE_BOOL ( TaskSystem, RecordCompletedTasks, true) +RULE_BOOL ( TaskSystem, RecordCompletedOptionalActivities, false) +RULE_BOOL ( TaskSystem, KeepOneRecordPerCompletedTask, true) +RULE_BOOL ( TaskSystem, EnableTaskProximity, true) +RULE_CATEGORY_END() + +#ifdef BOTS +RULE_CATEGORY ( Bots ) +RULE_REAL ( Bots, BotManaRegen, 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, BotFinishBuffing, false ) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. +RULE_INT ( Bots, CreateBotCount, 150 ) // Number of bots that each account can create +RULE_INT ( Bots, SpawnBotCount, 71 ) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid +RULE_BOOL ( Bots, BotQuest, 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, BotGroupBuffing, 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_BOOL ( Bots, BotSpellQuest, false ) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. +RULE_INT ( Bots, BotAAExpansion, 8 ) // Bots get AAs through this expansion +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. +RULE_BOOL ( Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) +RULE_CATEGORY_END() +#endif + +RULE_CATEGORY ( Chat ) +RULE_BOOL ( Chat, ServerWideOOC, true) +RULE_BOOL ( Chat, ServerWideAuction, true) +RULE_BOOL ( Chat, EnableVoiceMacros, true) +RULE_BOOL ( Chat, EnableMailKeyIPVerification, true) +RULE_BOOL ( Chat, EnableAntiSpam, true) +RULE_INT ( Chat, MinStatusToBypassAntiSpam, 100) +RULE_INT ( Chat, MinimumMessagesPerInterval, 4) +RULE_INT ( Chat, MaximumMessagesPerInterval, 12) +RULE_INT ( Chat, MaxMessagesBeforeKick, 20) +RULE_INT ( Chat, IntervalDurationMS, 60000) +RULE_INT ( Chat, KarmaUpdateIntervalMS, 1200000) +RULE_INT ( Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able to talk in ooc/auction/chat below the level limit +RULE_INT ( Chat, GlobalChatLevelLimit, 8) //level limit you need to of reached to talk in ooc/auction/chat if your karma is too low. +RULE_CATEGORY_END() + +RULE_CATEGORY ( Merchant ) +RULE_BOOL ( Merchant, UsePriceMod, true) // Use faction/charisma price modifiers. +RULE_REAL ( Merchant, SellCostMod, 1.05) // Modifier for NPC sell price. +RULE_REAL ( Merchant, BuyCostMod, 0.95) // Modifier for NPC buy price. +RULE_INT ( Merchant, PriceBonusPct, 4) // Determines maximum price bonus from having good faction/CHA. Value is a percent. +RULE_INT ( Merchant, PricePenaltyPct, 4) // Determines maximum price penalty from having bad faction/CHA. Value is a percent. +RULE_REAL( Merchant, ChaBonusMod, 3.45) // Determines CHA cap, from 104 CHA. 3.45 is 132 CHA at apprehensive. 0.34 is 400 CHA at apprehensive. +RULE_REAL ( Merchant, ChaPenaltyMod, 1.52) // Determines CHA bottom, up to 102 CHA. 1.52 is 37 CHA at apprehensive. 0.98 is 0 CHA at apprehensive. +RULE_BOOL ( Merchant, EnableAltCurrencySell, true) // Enables the ability to resell items to alternate currency merchants + +RULE_CATEGORY_END() + +RULE_CATEGORY ( Bazaar ) +RULE_BOOL ( Bazaar, AuditTrail, false) +RULE_INT ( Bazaar, MaxSearchResults, 50) +RULE_BOOL ( Bazaar, EnableWarpToTrader, true) +RULE_INT ( Bazaar, MaxBarterSearchResults, 200) // The max results returned in the /barter search +RULE_CATEGORY_END() + +RULE_CATEGORY ( Mail ) +RULE_BOOL ( Mail, EnableMailSystem, true) // If false, client won't bring up the Mail window. +RULE_INT ( Mail, ExpireTrash, 0) // Time in seconds. 0 will delete all messages in the trash when the mailserver starts +RULE_INT ( Mail, ExpireRead, 31536000 ) // 1 Year. Set to -1 for never +RULE_INT ( Mail, ExpireUnread, 31536000 ) // 1 Year. Set to -1 for never +RULE_CATEGORY_END() + +RULE_CATEGORY ( Channels ) +RULE_INT ( Channels, RequiredStatusAdmin, 251) // Required status to administer chat channels +RULE_INT ( Channels, RequiredStatusListAll, 251) // Required status to list all chat channels +RULE_INT ( Channels, DeleteTimer, 1440) // Empty password protected channels will be deleted after this many minutes +RULE_CATEGORY_END() + +RULE_CATEGORY ( EventLog ) +RULE_BOOL ( EventLog, RecordSellToMerchant, false ) // Record sales from a player to an NPC merchant in eventlog table +RULE_BOOL ( EventLog, RecordBuyFromMerchant, false ) // Record purchases by a player from an NPC merchant in eventlog table +RULE_CATEGORY_END() + +RULE_CATEGORY ( Adventure ) +RULE_INT ( Adventure, MinNumberForGroup, 2 ) +RULE_INT ( Adventure, MaxNumberForGroup, 6 ) +RULE_INT ( Adventure, MinNumberForRaid, 18 ) +RULE_INT ( Adventure, MaxNumberForRaid, 36 ) +RULE_INT ( Adventure, MaxLevelRange, 9 ) +RULE_INT ( Adventure, NumberKillsForBossSpawn, 45) +RULE_REAL ( Adventure, DistanceForRescueAccept, 10000.0) +RULE_REAL ( Adventure, DistanceForRescueComplete, 2500.0) +RULE_INT ( Adventure, ItemIDToEnablePorts, 41000 ) //0 to disable, otherwise using a LDoN portal will require the user to have this item. +RULE_INT ( Adventure, LDoNTrapDistanceUse, 625 ) +RULE_REAL ( Adventure, LDoNBaseTrapDifficulty, 15.0 ) +RULE_REAL ( Adventure, LDoNCriticalFailTrapThreshold, 10.0 ) +RULE_INT ( Adventure, LDoNAdventureExpireTime, 1800) //30 minutes to expire +RULE_CATEGORY_END() + +RULE_CATEGORY ( AA ) +RULE_INT ( AA, ExpPerPoint, 23976503) //Amount of exp per AA. Is the same as the amount of exp to go from level 51 to level 52. +RULE_BOOL ( AA, Stacking, true) //Allow AA that belong to the same group to stack on SOF+ clients. +RULE_CATEGORY_END() + +RULE_CATEGORY( Console ) +RULE_INT ( Console, SessionTimeOut, 600000 ) // Amount of time in ms for the console session to time out +RULE_CATEGORY_END() + +RULE_CATEGORY( QueryServ ) +RULE_BOOL( QueryServ, PlayerChatLogging, false) // Logs Player Chat +RULE_BOOL( QueryServ, PlayerLogTrades, false) // Logs Player Trades +RULE_BOOL( QueryServ, PlayerLogHandins, false) // Logs Player Handins +RULE_BOOL( QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills +RULE_BOOL( QueryServ, PlayerLogDeletes, false) // Logs Player Deletes +RULE_BOOL( QueryServ, PlayerLogMoves, false) // Logs Player Moves +RULE_BOOL( QueryServ, MerchantLogTransactions, false) // Logs Merchant Transactions +RULE_BOOL( QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events +RULE_CATEGORY_END() + +RULE_CATEGORY( Inventory ) +RULE_BOOL ( Inventory, EnforceAugmentRestriction, true) // Forces augment slot restrictions +RULE_BOOL ( Inventory, EnforceAugmentUsability, true) // Forces augmented item usability +RULE_BOOL ( Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation +RULE_CATEGORY_END() + +#undef RULE_CATEGORY +#undef RULE_INT +#undef RULE_REAL +#undef RULE_BOOL +#undef RULE_CATEGORY_END + diff --git a/common/shareddb.cpp b/common/shareddb.cpp index d5d42a174..9ace76873 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1659,27 +1659,28 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].directional_start = static_cast(atoi(row[194])); sp[tempid].directional_end = static_cast(atoi(row[195])); sp[tempid].sneak = atoi(row[196]) != 0; - sp[tempid].not_extendable = atoi(row[197]) != 0; + sp[tempid].not_focusable = atoi(row[197]) != 0; sp[tempid].suspendable = atoi(row[200]) != 0; sp[tempid].viral_range = atoi(row[201]); sp[tempid].songcap = atoi(row[202]); sp[tempid].no_block = atoi(row[205]); sp[tempid].spellgroup=atoi(row[207]); sp[tempid].rank = atoi(row[208]); - sp[tempid].powerful_flag=atoi(row[209]); + sp[tempid].no_resist=atoi(row[209]); sp[tempid].CastRestriction = atoi(row[211]); sp[tempid].AllowRest = atoi(row[212]) != 0; sp[tempid].InCombat = atoi(row[213]) != 0; sp[tempid].OutofCombat = atoi(row[214]) != 0; sp[tempid].override_crit_chance = atoi(row[217]); sp[tempid].aemaxtargets = atoi(row[218]); - sp[tempid].maxtargets = atoi(row[219]); + sp[tempid].no_heal_damage_item_mod = atoi(row[219]); sp[tempid].persistdeath = atoi(row[224]) != 0; sp[tempid].min_dist = atof(row[227]); sp[tempid].min_dist_mod = atof(row[228]); sp[tempid].max_dist = atof(row[229]); sp[tempid].max_dist_mod = atof(row[230]); sp[tempid].min_range = static_cast(atoi(row[231])); + sp[tempid].no_remove = atoi(row[232]) != 0; sp[tempid].DamageShieldType = 0; } diff --git a/common/spdat.h b/common/spdat.h index c49628d01..76515ae42 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -486,7 +486,7 @@ typedef enum { #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_CastOnRuneFadeEffect 333 // implemented +#define SE_CastOnRuneFadeEffect 333 // implemented #define SE_BardAEDot 334 // implemented #define SE_BlockNextSpellFocus 335 // implemented - base1 chance to block next spell ie Puratus (8494) //#define SE_IllusionaryTarget 336 // not used @@ -744,7 +744,7 @@ struct SPDat_Spell_Struct /* 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_extendable; +/* 197 */ bool not_focusable; //prevents focus effects from being applied to spell /* 198- 199 */ /* 200 */ bool suspendable; // buff is suspended in suspended buff zones /* 201 */ int viral_range; @@ -755,7 +755,7 @@ struct SPDat_Spell_Struct /* 206 */ /* 207 */ int spellgroup; /* 208 */ int rank; //increments AA effects with same name -/* 209 */ int powerful_flag; // Need more investigation to figure out what to call this, for now we know -1 makes charm spells not break before their duration is complete, it does alot more though +/* 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; @@ -764,7 +764,7 @@ struct SPDat_Spell_Struct /* 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 maxtargets; //Is used for beam and ring spells for target # limits (not implemented) +/* 219 */ int no_heal_damage_item_mod; //Is used for beam and ring spells for target # limits (not implemented) /* 220 - 223 */ /* 224 */ bool persistdeath; // buff doesn't get stripped on death /* 225 - 226 */ @@ -773,7 +773,8 @@ struct SPDat_Spell_Struct /* 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 - 236 */ +/* 232 */ bool no_remove; //prevents buff from being removed by click +/* 233 - 236 */ uint8 DamageShieldType; // This field does not exist in spells_us.txt }; diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 06716b3df..09f173ac5 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1240,7 +1240,7 @@ bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) { if(IsCharmSpell(spell_id)) { - if (spells[spell_id].powerful_flag == -1) //If charm spell has this set(-1), it can not break till end of duration. + if (spells[spell_id].no_resist) //If charm spell has this set(-1), it can not break till end of duration. return true; //1: The mob has a default 25% chance of being allowed a resistance check against the charm. diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f1ec8e8ec..51ad0f3e8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3734,7 +3734,7 @@ void Client::Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app) uint16 SpellID = m->GetSpellIDFromSlot(brrs->SlotID); - if (SpellID && IsBeneficialSpell(SpellID)) + if (SpellID && IsBeneficialSpell(SpellID) && !spells[SpellID].no_remove) m->BuffFadeBySlot(brrs->SlotID, true); } diff --git a/zone/effects.cpp b/zone/effects.cpp index 2e43ad8f5..f2706cae1 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -112,7 +112,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); value -= GetFocusEffect(focusFcDamageAmt2, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100; else if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -145,7 +145,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); value -= GetFocusEffect(focusFcDamageAmt2, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -287,7 +287,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { value += GetFocusEffect(focusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier; value += value*target->GetHealRate(spell_id, this)/100; @@ -430,9 +430,6 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) { - if (spells[spell_id].not_extendable) - return duration; - int increase = 100; increase += GetFocusEffect(focusSpellDuration, spell_id); int tic_inc = 0; diff --git a/zone/lua_spell.cpp b/zone/lua_spell.cpp index e99b9ba84..18353efaa 100644 --- a/zone/lua_spell.cpp +++ b/zone/lua_spell.cpp @@ -406,7 +406,7 @@ int Lua_Spell::GetSpellGroup() { int Lua_Spell::GetPowerfulFlag() { Lua_Safe_Call_Int(); - return self->powerful_flag; + return self->no_resist; } int Lua_Spell::GetCastRestriction() { @@ -436,7 +436,7 @@ int Lua_Spell::GetAEMaxTargets() { int Lua_Spell::GetMaxTargets() { Lua_Safe_Call_Int(); - return self->maxtargets; + return self->no_heal_damage_item_mod; } bool Lua_Spell::GetPersistDeath() { diff --git a/zone/mob.cpp b/zone/mob.cpp index 24f17a531..fc46aac75 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5598,18 +5598,18 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) else if (id == "NimbusEffect") {return spells[spell_id].NimbusEffect; } else if (id == "directional_start") {return static_cast(spells[spell_id].directional_start); } else if (id == "directional_end") {return static_cast(spells[spell_id].directional_end); } - else if (id == "not_extendable") {return spells[spell_id].not_extendable; } + else if (id == "not_focusable") {return spells[spell_id].not_focusable; } else if (id == "suspendable") {return spells[spell_id].suspendable; } else if (id == "viral_range") {return spells[spell_id].viral_range; } else if (id == "spellgroup") {return spells[spell_id].spellgroup; } else if (id == "rank") {return spells[spell_id].rank; } - else if (id == "powerful_flag") {return spells[spell_id].powerful_flag; } + else if (id == "no_resist") {return spells[spell_id].no_resist; } else if (id == "CastRestriction") {return spells[spell_id].CastRestriction; } else if (id == "AllowRest") {return spells[spell_id].AllowRest; } else if (id == "InCombat") {return spells[spell_id].InCombat; } else if (id == "OutofCombat") {return spells[spell_id].OutofCombat; } else if (id == "aemaxtargets") {return spells[spell_id].aemaxtargets; } - else if (id == "maxtargets") {return spells[spell_id].maxtargets; } + else if (id == "no_heal_damage_item_mod") {return spells[spell_id].no_heal_damage_item_mod; } else if (id == "persistdeath") {return spells[spell_id].persistdeath; } else if (id == "min_dist") {return static_cast(spells[spell_id].min_dist); } else if (id == "min_dist_mod") {return static_cast(spells[spell_id].min_dist_mod); } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 754ced55d..8d3b252ad 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -780,7 +780,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove // define spells with fixed duration // charm spells with -1 in field 209 are all of fixed duration, so lets use that instead of spell_ids - if(spells[spell_id].powerful_flag == -1) + if(spells[spell_id].no_resist) bBreak = true; if (!bBreak) @@ -5228,6 +5228,9 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) if (IsBardSong(spell_id) && type != focusFcBaseEffects && type != focusSpellDuration) return 0; + if (spells[spell_id].not_focusable) + return 0; + int16 realTotal = 0; int16 realTotal2 = 0; int16 realTotal3 = 0; @@ -5499,6 +5502,9 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { + if (spells[spell_id].not_focusable) + return 0; + int16 realTotal = 0; int16 realTotal2 = 0; bool rand_effectiveness = false; diff --git a/zone/spells.cpp b/zone/spells.cpp index 44bd8e3de..6967598d0 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4298,7 +4298,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use } //Get the resist chance for the target - if(resist_type == RESIST_NONE) + if(resist_type == RESIST_NONE || spells[spell_id].no_resist) { Log.Out(Logs::Detail, Logs::Spells, "Spell was unresistable"); return 100; From 9bff5baa1cfc8e074543f41398ed723d539af536 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 8 Oct 2015 13:36:04 -0400 Subject: [PATCH 343/846] Nuked. --- common/ruletypesx.h | 562 -------------------------------------------- 1 file changed, 562 deletions(-) delete mode 100644 common/ruletypesx.h diff --git a/common/ruletypesx.h b/common/ruletypesx.h deleted file mode 100644 index de0dbb587..000000000 --- a/common/ruletypesx.h +++ /dev/null @@ -1,562 +0,0 @@ - - - -#ifndef RULE_CATEGORY -#define RULE_CATEGORY(name) -#endif -#ifndef RULE_INT -#define RULE_INT(cat, rule, default_value) -#endif -#ifndef RULE_REAL -#define RULE_REAL(cat, rule, default_value) -#endif -#ifndef RULE_BOOL -#define RULE_BOOL(cat, rule, default_value) -#endif -#ifndef RULE_CATEGORY_END -#define RULE_CATEGORY_END() -#endif - - - - -RULE_CATEGORY( Character ) -RULE_INT ( Character, MaxLevel, 65 ) -RULE_BOOL ( Character, PerCharacterQglobalMaxLevel, false) // This will check for qglobal 'CharMaxLevel' character qglobal (Type 5), if player tries to level beyond that point, it will not go beyond that level -RULE_INT ( Character, MaxExpLevel, 0 ) //Sets the Max Level attainable via Experience -RULE_INT ( Character, DeathExpLossLevel, 10 ) // Any level greater than this will lose exp on death -RULE_INT ( Character, DeathExpLossMaxLevel, 255 ) // Any level greater than this will no longer lose exp on death -RULE_INT ( Character, DeathItemLossLevel, 10 ) -RULE_INT ( Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost -RULE_BOOL( Character, UseDeathExpLossMult, false ) //Adjust to use the above multiplier or to use code default. -RULE_INT ( Character, CorpseDecayTimeMS, 10800000 ) -RULE_INT ( Character, CorpseResTimeMS, 10800000 ) // time before cant res corpse(3 hours) -RULE_BOOL( Character, LeaveCorpses, true ) -RULE_BOOL( Character, LeaveNakedCorpses, false ) -RULE_INT ( Character, MaxDraggedCorpses, 2 ) -RULE_REAL( Character, DragCorpseDistance, 400) // If the corpse is <= this distance from the player, it won't move -RULE_REAL( Character, ExpMultiplier, 0.5 ) -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, LightBlueModifier, 40 ) -RULE_INT ( Character, BlueModifier, 90 ) -RULE_INT ( Character, WhiteModifier, 100 ) -RULE_INT ( Character, YellowModifier, 125 ) -RULE_INT ( Character, RedModifier, 150 ) -RULE_INT ( Character, AutosaveIntervalS, 300 ) //0=disabled -RULE_INT ( Character, HPRegenMultiplier, 100) -RULE_INT ( Character, ManaRegenMultiplier, 100) -RULE_INT ( Character, EnduranceRegenMultiplier, 100) -RULE_INT ( Character, ConsumptionMultiplier, 100) //item's hunger restored = this value * item's food level, 100 = normal, 50 = people eat 2x as fast, 200 = people eat 2x as slow -RULE_BOOL( Character, HealOnLevel, false) -RULE_BOOL( Character, FeignKillsPet, false) -RULE_INT ( Character, ItemManaRegenCap, 15) -RULE_INT ( Character, ItemHealthRegenCap, 35) -RULE_INT ( Character, ItemDamageShieldCap, 30) -RULE_INT ( Character, ItemAccuracyCap, 150) -RULE_INT ( Character, ItemAvoidanceCap, 100) -RULE_INT ( Character, ItemCombatEffectsCap, 100) -RULE_INT ( Character, ItemShieldingCap, 35) -RULE_INT ( Character, ItemSpellShieldingCap, 35) -RULE_INT ( Character, ItemDoTShieldingCap, 35) -RULE_INT ( Character, ItemStunResistCap, 35) -RULE_INT ( Character, ItemStrikethroughCap, 35) -RULE_INT ( Character, ItemATKCap, 250) -RULE_INT ( Character, ItemHealAmtCap, 250) -RULE_INT ( Character, ItemSpellDmgCap, 250) -RULE_INT ( Character, ItemClairvoyanceCap, 250) -RULE_INT ( Character, ItemDSMitigationCap, 50) -RULE_INT ( Character, ItemEnduranceRegenCap, 15) -RULE_INT ( Character, ItemExtraDmgCap, 150) // Cap for bonuses to melee skills like Bash, Frenzy, etc -RULE_INT ( Character, HasteCap, 100) // Haste cap for non-v3(overhaste) haste. -RULE_INT ( Character, SkillUpModifier, 100) //skill ups are at 100% -RULE_BOOL ( Character, SharedBankPlat, false) //off by default to prevent duping for now -RULE_BOOL ( Character, BindAnywhere, false) -RULE_INT ( Character, RestRegenPercent, 0) // Set to >0 to enable rest state bonus HP and mana regen. -RULE_INT ( Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in. -RULE_BOOL ( Character, RestRegenEndurance, false) // Whether rest regen will work for endurance or not. -RULE_INT ( Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA -RULE_INT ( Character, KillsPerRaidLeadershipAA, 250) // Number of dark blues or above per Raid Leadership AA -RULE_INT ( Character, MaxFearDurationForPlayerCharacter, 4) //4 tics, each tic calculates every 6 seconds. -RULE_INT ( Character, MaxCharmDurationForPlayerCharacter, 15) -RULE_INT ( Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values -RULE_BOOL ( Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas -RULE_BOOL ( Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses -RULE_BOOL ( Character, RespawnFromHover, false) // Use Respawn window, or not. -RULE_INT ( Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS -RULE_BOOL ( Character, UseNewStatsWindow, true) // New stats window shows everything -RULE_BOOL ( Character, ItemCastsUseFocus, false) // If true, this allows item clickies to use focuses that have limited max levels on them -RULE_INT ( Character, MinStatusForNoDropExemptions, 80) // This allows status x and higher to trade no drop items. -RULE_INT ( Character, SkillCapMaxLevel, 75 ) // Sets the Max Level used for Skill Caps (from skill_caps table). -1 makes it use MaxLevel rule value. It is set to 75 because PEQ only has skillcaps up to that level, and grabbing the players' skill past 75 will return 0, breaking all skills past that level. This helps servers with obsurd level caps (75+ level cap) function without any modifications. -RULE_INT ( Character, StatCap, 0 ) -RULE_BOOL ( Character, CheckCursorEmptyWhenLooting, true ) // If true, a player cannot loot a corpse (player or NPC) with an item on their cursor -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, 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. -RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. -RULE_CATEGORY_END() - -RULE_CATEGORY( Mercs ) -RULE_INT (Mercs, SuspendIntervalMS, 10000) -RULE_INT (Mercs, UpkeepIntervalMS, 180000) -RULE_INT (Mercs, SuspendIntervalS, 10) -RULE_INT (Mercs, UpkeepIntervalS, 180) -RULE_BOOL (Mercs, AllowMercs, false) -RULE_BOOL (Mercs, ChargeMercPurchaseCost, false) -RULE_BOOL (Mercs, ChargeMercUpkeepCost, false) -RULE_INT (Mercs, AggroRadius, 100) // Determines the distance from which a merc will aggro group member's target(also used to determine the distance at which a healer merc will begin healing a group member) -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_CATEGORY_END() - -RULE_CATEGORY( Guild ) -RULE_INT ( Guild, MaxMembers, 2048 ) -RULE_BOOL ( Guild, PlayerCreationAllowed, false) // Allow players to create a guild using the window in Underfoot+ -RULE_INT ( Guild, PlayerCreationLimit, 1) // Only allow use of the UF+ window if the account has < than this number of guild leaders on it -RULE_INT ( Guild, PlayerCreationRequiredStatus, 0) // Required admin status. -RULE_INT ( Guild, PlayerCreationRequiredLevel, 0) // Required Level of the player attempting to create the guild. -RULE_INT ( Guild, PlayerCreationRequiredTime, 0) // Required Time Entitled On Account (in Minutes) to create the guild. - -RULE_CATEGORY_END() - -RULE_CATEGORY( Skills ) -RULE_INT ( Skills, MaxTrainTradeskills, 21 ) -RULE_BOOL ( Skills, UseLimitTradeskillSearchSkillDiff, true ) -RULE_INT ( Skills, MaxTradeskillSearchSkillDiff, 50 ) -RULE_INT ( Skills, MaxTrainSpecializations, 50 ) // Max level a GM trainer will train casting specializations -RULE_CATEGORY_END() - -RULE_CATEGORY( Pets ) -RULE_REAL( Pets, AttackCommandRange, 150 ) -RULE_BOOL( Pets, UnTargetableSwarmPet, false ) -RULE_BOOL( Pets, SwarmPetNotTargetableWithHotKey, false ) //On SOF+ clients this a semi-hack to make swarm pets not F8 targetable. -RULE_CATEGORY_END() - -RULE_CATEGORY( GM ) -RULE_INT ( GM, MinStatusToSummonItem, 250) -RULE_INT ( GM, MinStatusToZoneAnywhere, 250 ) -RULE_CATEGORY_END() - -RULE_CATEGORY( World ) -RULE_INT ( World, ZoneAutobootTimeoutMS, 60000 ) -RULE_INT ( World, ClientKeepaliveTimeoutMS, 65000 ) -RULE_BOOL ( World, UseBannedIPsTable, false ) // Toggle whether or not to check incoming client connections against the Banned_IPs table. Set this value to false to disable this feature. -RULE_BOOL ( World, EnableTutorialButton, true) -RULE_BOOL ( World, EnableReturnHomeButton, true) -RULE_INT ( World, MaxLevelForTutorial, 10) -RULE_INT ( World, TutorialZoneID, 189) -RULE_INT ( World, GuildBankZoneID, 345) -RULE_INT ( World, MinOfflineTimeToReturnHome, 21600) // 21600 seconds is 6 Hours -RULE_INT ( World, MaxClientsPerIP, -1 ) // Maximum number of clients allowed to connect per IP address if account status is < AddMaxClientsStatus. Default value: -1 (feature disabled) -RULE_INT ( World, ExemptMaxClientsStatus, -1 ) // Exempt accounts from the MaxClientsPerIP and AddMaxClientsStatus rules, if their status is >= this value. Default value: -1 (feature disabled) -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, 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) -RULE_INT ( World, ExemptAccountLimitStatus, -1 ) //Min status required to be exempt from multi-session per account limiting (-1 is disabled) -RULE_BOOL ( World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts. -RULE_INT ( World, MinGMAntiHackStatus, 1 ) //Minimum GM status to check against AntiHack list -RULE_INT ( World, SoFStartZoneID, -1 ) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) -RULE_INT ( World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS. -RULE_INT ( World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules. -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_CATEGORY_END() - -RULE_CATEGORY( Zone ) -RULE_INT ( Zone, NPCPositonUpdateTicCount, 32 ) //ms between intervals of sending a position update to the entire zone. -RULE_INT ( Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection -RULE_INT ( Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone -RULE_BOOL ( Zone, EnableShadowrest, 1 ) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. -RULE_BOOL ( Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses. -RULE_INT ( Zone, MQWarpExemptStatus, -1 ) // Required status level to exempt the MQWarpDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQZoneExemptStatus, -1 ) // Required status level to exempt the MQZoneDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQGateExemptStatus, -1 ) // Required status level to exempt the MQGateDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQGhostExemptStatus, -1 ) // Required status level to exempt the MGhostDetector. Set to -1 to disable this feature. -RULE_BOOL ( Zone, EnableMQWarpDetector, true ) // Enable the MQWarp Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQZoneDetector, true ) // Enable the MQZone Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQGateDetector, true ) // Enable the MQGate Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQGhostDetector, true ) // Enable the MQGhost Detector. Set to False to disable this feature. -RULE_REAL ( Zone, MQWarpDetectionDistanceFactor, 9.0) //clients move at 4.4 about if in a straight line but with movement and to acct for lag we raise it a bit -RULE_BOOL ( Zone, MarkMQWarpLT, false ) -RULE_INT ( Zone, AutoShutdownDelay, 5000 ) //How long a dynamic zone stays loaded while empty -RULE_INT ( Zone, PEQZoneReuseTime, 900 ) //How long, in seconds, until you can reuse the #peqzone command. -RULE_INT ( Zone, PEQZoneDebuff1, 4454 ) //First debuff casted by #peqzone Default is Cursed Keeper's Blight. -RULE_INT ( Zone, PEQZoneDebuff2, 2209 ) //Second debuff casted by #peqzone Default is Tendrils of Apathy. -RULE_BOOL ( Zone, UsePEQZoneDebuffs, true ) //Will determine if #peqzone will debuff players or not when used. -RULE_REAL ( Zone, HotZoneBonus, 0.75 ) -RULE_INT ( Zone, ReservedInstances, 30 ) //Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running. -RULE_INT ( Zone, EbonCrystalItemID, 40902) -RULE_INT ( Zone, RadiantCrystalItemID, 40903) -RULE_BOOL ( Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mods table in consideration to your players EXP hits -RULE_INT ( Zone, WeatherTimer, 600) // Weather timer when no duration is available -RULE_CATEGORY_END() - -RULE_CATEGORY( Map ) -//enable these to help prevent mob hopping when they are pathing -RULE_BOOL ( Map, FixPathingZWhenLoading, true ) //increases zone boot times a bit to reduce hopping. -RULE_BOOL ( Map, FixPathingZAtWaypoints, false ) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time. -RULE_BOOL ( Map, FixPathingZWhenMoving, false ) //very CPU intensive, but helps hopping with widely spaced waypoints. -RULE_BOOL ( Map, FixPathingZOnSendTo, false ) //try to repair Z coords in the SendTo routine as well. -RULE_REAL ( Map, FixPathingZMaxDeltaMoving, 20 ) //at runtime while pathing: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaWaypoint, 20 ) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaSendTo, 20 ) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaLoading, 45 ) //while loading each waypoint: max change in Z to allow the BestZ code to apply. -RULE_BOOL ( Map, UseClosestZ, false) // Move mobs to the nearest Z above or below, rather than just the nearest below. - // Only set UseClosestZ true if all your .map files generated from EQGs were created - // with azone2. - // -RULE_INT ( Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position -RULE_CATEGORY_END() - -RULE_CATEGORY( Pathing ) -// Some of these rules may benefit by being made into columns in the zone table, -// for instance, in dungeons, the min LOS distances could be substantially lowered. -RULE_BOOL ( Pathing, Aggro, true ) // Enable pathing for aggroed mobs. -RULE_BOOL ( Pathing, AggroReturnToGrid, true ) // Enable pathing for aggroed roaming mobs returning to their previous waypoint. -RULE_BOOL ( Pathing, Guard, true ) // Enable pathing for mobs moving to their guard point. -RULE_BOOL ( Pathing, Find, true ) // Enable pathing for FindPerson requests from the client. -RULE_BOOL ( Pathing, Fear, true ) // Enable pathing for fear -RULE_REAL ( Pathing, ZDiffThreshold, 10) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. -RULE_INT ( Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds). -RULE_INT ( Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved. -RULE_INT ( Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved. -// When a path has a path node route and it's target changes position, if it has RouteUpdateFrequencyNodeCount or less nodes to go on it's -// current path, it will recalculate it's path based on the RouteUpdateFrequencyShort timer, otherwise it will use the -// RouteUpdateFrequencyLong timer. -RULE_INT ( Pathing, RouteUpdateFrequencyNodeCount, 5) -RULE_REAL ( Pathing, MinDistanceForLOSCheckShort, 40000) // (NoRoot). While following a path, only check for LOS to target within this distance. -RULE_REAL ( Pathing, MinDistanceForLOSCheckLong, 1000000) // (NoRoot). Min distance when initially attempting to acquire the target. -RULE_INT ( Pathing, MinNodesLeftForLOSCheck, 4) // Only check for LOS when we are down to this many path nodes left to run. -// This next rule was put in for situations where the mob and it's target may be on different sides of a 'hazard', e.g. a pit -// If the mob has LOS to it's target, even though there is a hazard in it's way, it may break off from the node path and run at -// the target, only to later detect the hazard and re-acquire a node path. Depending upon the placement of the path nodes, this -// can lead to the mob looping. The rule is intended to allow the mob to at least get closer to it's target each time before -// checking LOS and trying to head straight for it. -RULE_INT ( Pathing, MinNodesTraversedForLOSCheck, 3) // Only check for LOS after we have traversed this many path nodes. -RULE_INT ( Pathing, CullNodesFromStart, 1) // Checks LOS from Start point to second node for this many nodes and removes first node if there is LOS -RULE_INT ( Pathing, CullNodesFromEnd, 1) // Checks LOS from End point to second to last node for this many nodes and removes last node if there is LOS -RULE_REAL ( Pathing, CandidateNodeRangeXY, 400) // When searching for path start/end nodes, only nodes within this range will be considered. -RULE_REAL ( Pathing, CandidateNodeRangeZ, 10) // When searching for path start/end nodes, only nodes within this range will be considered. - -RULE_CATEGORY_END() - -RULE_CATEGORY( Watermap ) -// enable these to use the water detection code. Requires Water Maps generated by awater utility -RULE_BOOL ( Watermap, CheckWaypointsInWaterWhenLoading, false ) // Does not apply BestZ as waypoints are loaded if they are in water -RULE_BOOL ( Watermap, CheckForWaterAtWaypoints, false) // Check if a mob has moved into/out of water when at waypoints and sets flymode -RULE_BOOL ( Watermap, CheckForWaterWhenMoving, false) // Checks if a mob has moved into/out of water each time it's loc is recalculated -RULE_BOOL ( Watermap, CheckForWaterOnSendTo, false) // Checks if a mob has moved into/out of water on SendTo -RULE_BOOL ( Watermap, CheckForWaterWhenFishing, false) // Only lets a player fish near water (if a water map exists for the zone) -RULE_REAL ( Watermap, FishingRodLength, 30) // How far in front of player water must be for fishing to work -RULE_REAL ( Watermap, FishingLineLength, 40) // If water is more than this far below the player, it is considered too far to fish -RULE_CATEGORY_END() - -RULE_CATEGORY( Spells ) -RULE_INT ( Spells, AutoResistDiff, 15) -RULE_REAL ( Spells, ResistChance, 2.0) //chance to resist given no resists and same level -RULE_REAL ( Spells, ResistMod, 0.40) //multiplier, chance to resist = this * ResistAmount -RULE_REAL ( Spells, PartialHitChance, 0.7) //The chance when a spell is resisted that it will partial hit. -RULE_REAL ( Spells, PartialHitChanceFear, 0.25) //The chance when a fear spell is resisted that it will partial hit. -RULE_INT ( Spells, BaseCritChance, 0) //base % chance that everyone has to crit a spell -RULE_INT ( Spells, BaseCritRatio, 100) //base % bonus to damage on a successful spell crit. 100 = 2x damage -RULE_INT ( Spells, WizCritLevel, 12) //level wizards first get spell crits -RULE_INT ( Spells, WizCritChance, 7) //wiz's crit chance, on top of BaseCritChance -RULE_INT ( Spells, WizCritRatio, 0) //wiz's crit bonus, on top of BaseCritRatio (should be 0 for Live-like) -RULE_INT ( Spells, ResistPerLevelDiff, 85) //8.5 resist per level difference. -RULE_INT ( Spells, TranslocateTimeLimit, 0) // If not zero, time in seconds to accept a Translocate. -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, 25) // 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 -RULE_BOOL( Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized -RULE_INT ( Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0. -RULE_BOOL ( Spells, NPCIgnoreBaseImmunity, true) // Whether or not NPCs get to ignore the BaseImmunityLevel for their spells. -RULE_REAL ( Spells, AvgSpellProcsPerMinute, 6.0) //Adjust rate for sympathetic spell procs -RULE_INT ( Spells, ResistFalloff, 67) //Max that level that will adjust our resist chance based on level modifiers -RULE_INT ( Spells, CharismaEffectiveness, 10) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. -RULE_INT ( Spells, CharismaEffectivenessCap, 255) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. -RULE_BOOL ( Spells, CharismaCharmDuration, false) // Allow CHA resist mod to extend charm duration. -RULE_INT ( Spells, CharmBreakCheckChance, 25) //Determines chance for a charm break check to occur each buff tick. -RULE_INT ( Spells, MaxCastTimeReduction, 50) //Max percent your spell cast time can be reduced by spell haste -RULE_INT ( Spells, RootBreakFromSpells, 55) //Chance for root to break when cast on. -RULE_INT ( Spells, DeathSaveCharismaMod, 3) //Determines how much charisma effects chance of death save firing. -RULE_INT ( Spells, DivineInterventionHeal, 8000) //Divine intervention heal amount. -RULE_BOOL ( Spells, AdditiveBonusValues, false) //Allow certain bonuses to be calculated by adding together the value from each item, instead of taking the highest value. (ie Add together all Cleave Effects) -RULE_BOOL ( Spells, UseCHAScribeHack, false) //ScribeSpells and TrainDiscs quest functions will ignore entries where field 12 is CHA. What's the best way to do this? -RULE_BOOL ( Spells, BuffLevelRestrictions, true) //Buffs will not land on low level toons like live -RULE_INT ( Spells, RootBreakCheckChance, 70) //Determines chance for a root break check to occur each buff tick. -RULE_INT ( Spells, FearBreakCheckChance, 70) //Determines chance for a fear break check to occur each buff tick. -RULE_INT ( Spells, SuccorFailChance, 2) //Determines chance for a succor spell not to teleport an invidual player -RULE_INT ( Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clients for Fire 'spell projectile'. -RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'. -RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'. -RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file. -RULE_BOOL ( Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects. -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, 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_BOOL ( Combat, UseIntervalAC, true) -RULE_INT ( Combat, PetAttackMagicLevel, 30) -RULE_BOOL ( Combat, EnableFearPathing, true) -RULE_REAL ( Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker. -RULE_INT ( Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee. -RULE_BOOL ( Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it. -RULE_BOOL ( Combat, AdjustProcPerMinute, true) -RULE_REAL ( Combat, AvgProcsPerMinute, 2.0) -RULE_REAL ( Combat, ProcPerMinDexContrib, 0.075) -RULE_REAL ( Combat, BaseProcChance, 0.035) -RULE_REAL ( Combat, ProcDexDivideBy, 11000) -RULE_REAL ( Combat, BaseHitChance, 69.0) -RULE_REAL ( Combat, NPCBonusHitChance, 26.0) -RULE_REAL ( Combat, HitFalloffMinor, 5.0) //hit will fall off up to 5% over the initial level range -RULE_REAL ( Combat, HitFalloffModerate, 7.0) //hit will fall off up to 7% over the three levels after the initial level range -RULE_REAL ( Combat, HitFalloffMajor, 50.0) //hit will fall off sharply if we're outside the minor and moderate range -RULE_REAL ( Combat, HitBonusPerLevel, 1.2) //You gain this % of hit for every level you are above your target -RULE_REAL ( Combat, WeaponSkillFalloff, 0.33) //For every weapon skill point that's not maxed you lose this % of hit -RULE_REAL ( Combat, ArcheryHitPenalty, 0.25) //Archery has a hit penalty to try to help balance it with the plethora of long term +hit modifiers for it -RULE_REAL ( Combat, AgiHitFactor, 0.01) -RULE_INT ( Combat, MinRangedAttackDist, 25) //Minimum Distance to use Ranged Attacks -RULE_BOOL ( Combat, ArcheryBonusRequiresStationary, true) //does the 2x archery bonus chance require a stationary npc -RULE_REAL ( Combat, ArcheryBaseDamageBonus, 1) // % Modifier to Base Archery Damage (.5 = 50% base damage, 1 = 100%, 2 = 200%) -RULE_REAL ( Combat, ArcheryNPCMultiplier, 1.0) // this is multiplied by the regular dmg to get the archery dmg -RULE_BOOL ( Combat, AssistNoTargetSelf, true) //when assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like) -RULE_INT ( Combat, MaxRampageTargets, 3) //max number of people hit with rampage -RULE_INT ( Combat, DefaultRampageTargets, 1) // default number of people to hit with rampage -RULE_BOOL ( Combat, RampageHitsTarget, false) // rampage will hit the target if it still has targets left -RULE_INT ( Combat, MaxFlurryHits, 2) //max number of extra hits from flurry -RULE_INT ( Combat, MonkDamageTableBonus, 5) //% bonus monks get to their damage table calcs -RULE_INT ( Combat, FlyingKickBonus, 25) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, DragonPunchBonus, 20) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, EagleStrikeBonus, 15) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, TigerClawBonus, 10) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, RoundKickBonus, 5) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, FrenzyBonus, 0) //% Modifier to damage -RULE_BOOL ( Combat, ProcTargetOnly, true) //true = procs will only affect our target, false = procs will affect all of our targets -RULE_REAL ( Combat, NPCACFactor, 2.25) -RULE_INT ( Combat, ClothACSoftcap, 75) -RULE_INT ( Combat, LeatherACSoftcap, 100) -RULE_INT ( Combat, MonkACSoftcap, 120) -RULE_INT ( Combat, ChainACSoftcap, 200) -RULE_INT ( Combat, PlateACSoftcap, 300) -RULE_REAL ( Combat, AAMitigationACFactor, 3.0) -RULE_REAL ( Combat, WarriorACSoftcapReturn, 0.45) -RULE_REAL ( Combat, KnightACSoftcapReturn, 0.33) -RULE_REAL ( Combat, LowPlateChainACSoftcapReturn, 0.23) -RULE_REAL ( Combat, LowChainLeatherACSoftcapReturn, 0.17) -RULE_REAL ( Combat, CasterACSoftcapReturn, 0.06) -RULE_REAL ( Combat, MiscACSoftcapReturn, 0.3) -RULE_BOOL ( Combat, OldACSoftcapRules, false) // use old softcaps -RULE_BOOL ( Combat, UseOldDamageIntervalRules, false) // use old damage formulas for everything -RULE_REAL ( Combat, WarACSoftcapReturn, 0.3448) // new AC returns -RULE_REAL ( Combat, ClrRngMnkBrdACSoftcapReturn, 0.3030) -RULE_REAL ( Combat, PalShdACSoftcapReturn, 0.3226) -RULE_REAL ( Combat, DruNecWizEncMagACSoftcapReturn, 0.2000) -RULE_REAL ( Combat, RogShmBstBerACSoftcapReturn, 0.2500) -RULE_REAL ( Combat, SoftcapFactor, 1.88) -RULE_REAL ( Combat, ACthac0Factor, 0.55) -RULE_REAL ( Combat, ACthac20Factor, 0.55) -RULE_INT ( Combat, HitCapPre20, 40) // live has it capped at 40 for whatever dumb reason... this is mainly for custom servers -RULE_INT ( Combat, HitCapPre10, 20) // live has it capped at 20, see above :p -RULE_INT ( Combat, MinHastedDelay, 400) // how fast we can get with haste. -RULE_REAL ( Combat, AvgDefProcsPerMinute, 2.0) -RULE_REAL ( Combat, DefProcPerMinAgiContrib, 0.075) //How much agility contributes to defensive proc rate -RULE_INT ( Combat, SpecialAttackACBonus, 15) //Percent amount of damage per AC gained for certain special attacks (damage = AC*SpecialAttackACBonus/100). -RULE_INT ( Combat, NPCFlurryChance, 20) // Chance for NPC to flurry. -RULE_BOOL (Combat,TauntOverLevel, 1) //Allows you to taunt NPC's over warriors level. -RULE_REAL (Combat,TauntSkillFalloff, 0.33)//For every taunt skill point that's not maxed you lose this % chance to taunt. -RULE_BOOL (Combat,EXPFromDmgShield, false) //Determine if damage from a damage shield counts for EXP gain. -RULE_INT ( Combat, MonkACBonusWeight, 15) -RULE_INT ( Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target -RULE_INT ( Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers -RULE_BOOL ( Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll -RULE_INT ( Combat, ArcheryBonusChance, 50) -RULE_INT ( Combat, BerserkerFrenzyStart, 35) -RULE_INT ( Combat, BerserkerFrenzyEnd, 45) -RULE_BOOL ( Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round -RULE_CATEGORY_END() - -RULE_CATEGORY( NPC ) -RULE_INT ( NPC, MinorNPCCorpseDecayTimeMS, 450000 ) //level<55 -RULE_INT ( NPC, MajorNPCCorpseDecayTimeMS, 1500000 ) //level>=55 -RULE_INT ( NPC, CorpseUnlockTimer, 150000 ) -RULE_INT ( NPC, EmptyNPCCorpseDecayTimeMS, 0 ) -RULE_BOOL (NPC, UseItemBonusesForNonPets, true) -RULE_INT ( NPC, SayPauseTimeInSec, 5) -RULE_INT ( NPC, OOCRegen, 0) -RULE_BOOL ( NPC, BuffFriends, false ) -RULE_BOOL ( NPC, EnableNPCQuestJournal, false) -RULE_INT ( NPC, LastFightingDelayMovingMin, 10000) -RULE_INT ( NPC, LastFightingDelayMovingMax, 20000) -RULE_BOOL ( NPC, SmartLastFightingDelayMoving, true) -RULE_BOOL ( NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPCs that don't have an EVENT_TRADE sub in their script -RULE_INT ( NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage -RULE_BOOL ( NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage -RULE_CATEGORY_END() - -RULE_CATEGORY ( Aggro ) -RULE_BOOL ( Aggro, SmartAggroList, true ) -RULE_INT ( Aggro, SittingAggroMod, 35 ) //35% -RULE_INT ( Aggro, MeleeRangeAggroMod, 10 ) //10% -RULE_INT ( Aggro, CurrentTargetAggroMod, 0 ) //0% -- will prefer our current target to any other; makes it harder for our npcs to switch targets. -RULE_INT ( Aggro, CriticallyWoundedAggroMod, 100 ) //100% -RULE_INT ( Aggro, SpellAggroMod, 100 ) -RULE_INT ( Aggro, SongAggroMod, 33 ) -RULE_INT ( Aggro, PetSpellAggroMod, 10 ) -RULE_REAL ( Aggro, TunnelVisionAggroMod, 0.75 ) //people not currently the top hate generate this much hate on a Tunnel Vision mob -RULE_INT ( Aggro, MaxStunProcAggro, 400 ) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add. -RULE_INT ( Aggro, IntAggroThreshold, 75 ) // Int <= this will aggro regardless of level difference. -RULE_CATEGORY_END() - -RULE_CATEGORY ( TaskSystem) -RULE_BOOL ( TaskSystem, EnableTaskSystem, true) // Globally enable or disable the Task system -RULE_INT ( TaskSystem, PeriodicCheckTimer, 5) // Seconds between checks for failed tasks. Also used by the 'Touch' activity -RULE_BOOL ( TaskSystem, RecordCompletedTasks, true) -RULE_BOOL ( TaskSystem, RecordCompletedOptionalActivities, false) -RULE_BOOL ( TaskSystem, KeepOneRecordPerCompletedTask, true) -RULE_BOOL ( TaskSystem, EnableTaskProximity, true) -RULE_CATEGORY_END() - -#ifdef BOTS -RULE_CATEGORY ( Bots ) -RULE_REAL ( Bots, BotManaRegen, 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, BotFinishBuffing, false ) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. -RULE_INT ( Bots, CreateBotCount, 150 ) // Number of bots that each account can create -RULE_INT ( Bots, SpawnBotCount, 71 ) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid -RULE_BOOL ( Bots, BotQuest, 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, BotGroupBuffing, 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_BOOL ( Bots, BotSpellQuest, false ) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. -RULE_INT ( Bots, BotAAExpansion, 8 ) // Bots get AAs through this expansion -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. -RULE_BOOL ( Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) -RULE_CATEGORY_END() -#endif - -RULE_CATEGORY ( Chat ) -RULE_BOOL ( Chat, ServerWideOOC, true) -RULE_BOOL ( Chat, ServerWideAuction, true) -RULE_BOOL ( Chat, EnableVoiceMacros, true) -RULE_BOOL ( Chat, EnableMailKeyIPVerification, true) -RULE_BOOL ( Chat, EnableAntiSpam, true) -RULE_INT ( Chat, MinStatusToBypassAntiSpam, 100) -RULE_INT ( Chat, MinimumMessagesPerInterval, 4) -RULE_INT ( Chat, MaximumMessagesPerInterval, 12) -RULE_INT ( Chat, MaxMessagesBeforeKick, 20) -RULE_INT ( Chat, IntervalDurationMS, 60000) -RULE_INT ( Chat, KarmaUpdateIntervalMS, 1200000) -RULE_INT ( Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able to talk in ooc/auction/chat below the level limit -RULE_INT ( Chat, GlobalChatLevelLimit, 8) //level limit you need to of reached to talk in ooc/auction/chat if your karma is too low. -RULE_CATEGORY_END() - -RULE_CATEGORY ( Merchant ) -RULE_BOOL ( Merchant, UsePriceMod, true) // Use faction/charisma price modifiers. -RULE_REAL ( Merchant, SellCostMod, 1.05) // Modifier for NPC sell price. -RULE_REAL ( Merchant, BuyCostMod, 0.95) // Modifier for NPC buy price. -RULE_INT ( Merchant, PriceBonusPct, 4) // Determines maximum price bonus from having good faction/CHA. Value is a percent. -RULE_INT ( Merchant, PricePenaltyPct, 4) // Determines maximum price penalty from having bad faction/CHA. Value is a percent. -RULE_REAL( Merchant, ChaBonusMod, 3.45) // Determines CHA cap, from 104 CHA. 3.45 is 132 CHA at apprehensive. 0.34 is 400 CHA at apprehensive. -RULE_REAL ( Merchant, ChaPenaltyMod, 1.52) // Determines CHA bottom, up to 102 CHA. 1.52 is 37 CHA at apprehensive. 0.98 is 0 CHA at apprehensive. -RULE_BOOL ( Merchant, EnableAltCurrencySell, true) // Enables the ability to resell items to alternate currency merchants - -RULE_CATEGORY_END() - -RULE_CATEGORY ( Bazaar ) -RULE_BOOL ( Bazaar, AuditTrail, false) -RULE_INT ( Bazaar, MaxSearchResults, 50) -RULE_BOOL ( Bazaar, EnableWarpToTrader, true) -RULE_INT ( Bazaar, MaxBarterSearchResults, 200) // The max results returned in the /barter search -RULE_CATEGORY_END() - -RULE_CATEGORY ( Mail ) -RULE_BOOL ( Mail, EnableMailSystem, true) // If false, client won't bring up the Mail window. -RULE_INT ( Mail, ExpireTrash, 0) // Time in seconds. 0 will delete all messages in the trash when the mailserver starts -RULE_INT ( Mail, ExpireRead, 31536000 ) // 1 Year. Set to -1 for never -RULE_INT ( Mail, ExpireUnread, 31536000 ) // 1 Year. Set to -1 for never -RULE_CATEGORY_END() - -RULE_CATEGORY ( Channels ) -RULE_INT ( Channels, RequiredStatusAdmin, 251) // Required status to administer chat channels -RULE_INT ( Channels, RequiredStatusListAll, 251) // Required status to list all chat channels -RULE_INT ( Channels, DeleteTimer, 1440) // Empty password protected channels will be deleted after this many minutes -RULE_CATEGORY_END() - -RULE_CATEGORY ( EventLog ) -RULE_BOOL ( EventLog, RecordSellToMerchant, false ) // Record sales from a player to an NPC merchant in eventlog table -RULE_BOOL ( EventLog, RecordBuyFromMerchant, false ) // Record purchases by a player from an NPC merchant in eventlog table -RULE_CATEGORY_END() - -RULE_CATEGORY ( Adventure ) -RULE_INT ( Adventure, MinNumberForGroup, 2 ) -RULE_INT ( Adventure, MaxNumberForGroup, 6 ) -RULE_INT ( Adventure, MinNumberForRaid, 18 ) -RULE_INT ( Adventure, MaxNumberForRaid, 36 ) -RULE_INT ( Adventure, MaxLevelRange, 9 ) -RULE_INT ( Adventure, NumberKillsForBossSpawn, 45) -RULE_REAL ( Adventure, DistanceForRescueAccept, 10000.0) -RULE_REAL ( Adventure, DistanceForRescueComplete, 2500.0) -RULE_INT ( Adventure, ItemIDToEnablePorts, 41000 ) //0 to disable, otherwise using a LDoN portal will require the user to have this item. -RULE_INT ( Adventure, LDoNTrapDistanceUse, 625 ) -RULE_REAL ( Adventure, LDoNBaseTrapDifficulty, 15.0 ) -RULE_REAL ( Adventure, LDoNCriticalFailTrapThreshold, 10.0 ) -RULE_INT ( Adventure, LDoNAdventureExpireTime, 1800) //30 minutes to expire -RULE_CATEGORY_END() - -RULE_CATEGORY ( AA ) -RULE_INT ( AA, ExpPerPoint, 23976503) //Amount of exp per AA. Is the same as the amount of exp to go from level 51 to level 52. -RULE_BOOL ( AA, Stacking, true) //Allow AA that belong to the same group to stack on SOF+ clients. -RULE_CATEGORY_END() - -RULE_CATEGORY( Console ) -RULE_INT ( Console, SessionTimeOut, 600000 ) // Amount of time in ms for the console session to time out -RULE_CATEGORY_END() - -RULE_CATEGORY( QueryServ ) -RULE_BOOL( QueryServ, PlayerChatLogging, false) // Logs Player Chat -RULE_BOOL( QueryServ, PlayerLogTrades, false) // Logs Player Trades -RULE_BOOL( QueryServ, PlayerLogHandins, false) // Logs Player Handins -RULE_BOOL( QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills -RULE_BOOL( QueryServ, PlayerLogDeletes, false) // Logs Player Deletes -RULE_BOOL( QueryServ, PlayerLogMoves, false) // Logs Player Moves -RULE_BOOL( QueryServ, MerchantLogTransactions, false) // Logs Merchant Transactions -RULE_BOOL( QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events -RULE_CATEGORY_END() - -RULE_CATEGORY( Inventory ) -RULE_BOOL ( Inventory, EnforceAugmentRestriction, true) // Forces augment slot restrictions -RULE_BOOL ( Inventory, EnforceAugmentUsability, true) // Forces augmented item usability -RULE_BOOL ( Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation -RULE_CATEGORY_END() - -#undef RULE_CATEGORY -#undef RULE_INT -#undef RULE_REAL -#undef RULE_BOOL -#undef RULE_CATEGORY_END - From 20bdbdd52d9109dc319a02fa6b51d5031cb104e5 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 8 Oct 2015 16:05:14 -0400 Subject: [PATCH 344/846] Implemented spells_new field 198 = no_detrimental_spell_aggro Spells with this flag will not generate any aggro Note: DOT portions of spells wilth this flag STILL generate aggro. Example Harminous Arrow (Ranger AA) 16127 --- common/shareddb.cpp | 1 + common/spdat.cpp | 8 ++++++++ common/spdat.h | 6 ++++-- zone/aggro.cpp | 3 +++ zone/attack.cpp | 13 ++++++++----- zone/mob.h | 2 +- zone/spells.cpp | 12 ++++++------ 7 files changed, 31 insertions(+), 14 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 9ace76873..b2dbc8175 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1660,6 +1660,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].directional_end = static_cast(atoi(row[195])); sp[tempid].sneak = atoi(row[196]) != 0; sp[tempid].not_focusable = atoi(row[197]) != 0; + sp[tempid].no_detrimental_spell_aggro = atoi(row[198]) != 0; sp[tempid].suspendable = atoi(row[200]) != 0; sp[tempid].viral_range = atoi(row[201]); sp[tempid].songcap = atoi(row[202]); diff --git a/common/spdat.cpp b/common/spdat.cpp index bb6097566..02803b173 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1092,6 +1092,14 @@ bool DetrimentalSpellAllowsRest(uint16 spell_id) return false; } +bool NoDetrimentalSpellAggro(uint16 spell_id) +{ + if (IsValidSpell(spell_id)) + return spells[spell_id].no_detrimental_spell_aggro; + + return false; +} + uint32 GetNimbusEffect(uint16 spell_id) { if (IsValidSpell(spell_id)) diff --git a/common/spdat.h b/common/spdat.h index 76515ae42..b70be171a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -745,7 +745,8 @@ struct SPDat_Spell_Struct /* 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- 199 */ +/* 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 @@ -764,7 +765,7 @@ struct SPDat_Spell_Struct /* 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; //Is used for beam and ring spells for target # limits (not implemented) +/* 219 */ int no_heal_damage_item_mod; /* 220 - 223 */ /* 224 */ bool persistdeath; // buff doesn't get stripped on death /* 225 - 226 */ @@ -880,6 +881,7 @@ uint32 GetPartialMeleeRuneReduction(uint32 spell_id); uint32 GetPartialMagicRuneReduction(uint32 spell_id); uint32 GetPartialMeleeRuneAmount(uint32 spell_id); uint32 GetPartialMagicRuneAmount(uint32 spell_id); +bool NoDetrimentalSpellAggro(uint16 spell_id); int CalcPetHp(int levelb, int classb, int STA = 75); const char *GetRandPetName(); diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 09f173ac5..574ac335d 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -960,6 +960,9 @@ bool Mob::CheckLosFN(float posX, float posY, float posZ, float mobSize) { //offensive spell aggro int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) { + if (NoDetrimentalSpellAggro(spell_id)) + return 0; + int32 AggroAmount = 0; int32 nonModifiedAggro = 0; uint16 slevel = GetLevel(); diff --git a/zone/attack.cpp b/zone/attack.cpp index 7a62aaff4..3089aa573 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2410,7 +2410,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack return true; } -void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/) +void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/, uint16 spell_id) { if(!other) return; @@ -2466,6 +2466,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b if(IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO)) return; + if (spell_id != SPELL_UNKNOWN && NoDetrimentalSpellAggro(spell_id)) + return; + if (other == myowner) return; @@ -3139,15 +3142,15 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons 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); + AddToHateList(attacker, 0, damage, true, false, iBuffTic, spell_id); } else { if(!attacker->CastToClient()->GetFeigned()) - AddToHateList(attacker, 0, damage, true, false, iBuffTic); + AddToHateList(attacker, 0, damage, true, false, iBuffTic, spell_id); } } else - AddToHateList(attacker, 0, damage, true, false, iBuffTic); + AddToHateList(attacker, 0, damage, true, false, iBuffTic, spell_id); } if(damage > 0) { @@ -3172,7 +3175,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons { if (!pet->IsHeld()) { Log.Out(Logs::Detail, Logs::Aggro, "Sending pet %s into battle due to attack.", pet->GetName()); - pet->AddToHateList(attacker, 1); + pet->AddToHateList(attacker, 1,0, true, false, false, spell_id); pet->SetTarget(attacker); Message_StringID(10, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName()); } diff --git a/zone/mob.h b/zone/mob.h index 651065296..e48eda680 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -489,7 +489,7 @@ public: inline uint32 GetLevelCon(uint8 iOtherLevel) const { return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GREEN; } virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, - bool bFrenzy = false, bool iBuffTic = false); + bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN); bool RemoveFromHateList(Mob* mob); void SetHateAmountOnEnt(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);} void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate > 1 ? in_hate / 2 : 1)); } diff --git a/zone/spells.cpp b/zone/spells.cpp index 6967598d0..ce45b6d83 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4067,7 +4067,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(aggro > 0) { AddToHateList(caster, aggro); } else { - AddToHateList(caster, 1); + AddToHateList(caster, 1,0,true,false,false,spell_id); } return true; } @@ -4094,7 +4094,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(aggro > 0) { AddToHateList(caster, aggro); } else { - AddToHateList(caster, 1); + AddToHateList(caster, 1,0,true,false,false,spell_id); } return true; } @@ -4110,7 +4110,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(aggro > 0) { AddToHateList(caster, aggro); } else { - AddToHateList(caster, 1); + AddToHateList(caster, 1,0,true,false,false,spell_id); } return true; } else if(IsClient() && caster->IsClient() && (caster->CastToClient()->GetGM() == false)) @@ -4127,7 +4127,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if (aggro > 0) { AddToHateList(caster, aggro); } else { - AddToHateList(caster, 1); + AddToHateList(caster, 1,0,true,false,false,spell_id); } return true; } @@ -4150,7 +4150,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(aggro > 0) { AddToHateList(caster, aggro); } else { - AddToHateList(caster, 1); + AddToHateList(caster, 1,0,true,false,false,spell_id); } return true; } @@ -4190,7 +4190,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(aggro > 0) { AddToHateList(caster, aggro); } else { - AddToHateList(caster, 1); + AddToHateList(caster, 1,0,true,false,false,spell_id); } return true; } From 43671fa749d147680f178f5acf11bbb226ce4f99 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 8 Oct 2015 19:26:04 -0400 Subject: [PATCH 345/846] Implemented SE_PC_Pet_Flurry_Chance 466 // Base1 % chance to do flurry from double attack hit. --- common/spdat.h | 2 +- zone/attack.cpp | 18 ++++++++++++++++-- zone/bonuses.cpp | 13 +++++++++++-- zone/common.h | 1 + 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index b70be171a..75c6e60c0 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -619,7 +619,7 @@ typedef enum { //#define SE_Shield_Target 463 // #define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round //#define SE_PC_Pet_AE_Rampage 465 // Would assume as above but need to confirm. -//#define SE_PC_Pet_Flurry_Chance 466 // +#define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit. //#define SE_DS_Mitigation_Amount 467 // //#define SE_DS_Mitigation_Percentage 468 // //#define SE_Chance_Best_in_Spell_Grp 469 // diff --git a/zone/attack.cpp b/zone/attack.cpp index 3089aa573..2f94716bf 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4763,8 +4763,15 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec // 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); - if (CanThisClassDoubleAttack() && CheckDoubleAttack()) + if (CanThisClassDoubleAttack() && CheckDoubleAttack()){ Attack(target, MainPrimary, false, false, false, opts, special); + + if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ + int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; + if (chance && zone->random.Roll(chance)) + Flurry(nullptr); + } + } return; } @@ -4814,8 +4821,15 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int speci GetEquipment(MaterialSecondary) != 0) { if (CheckDualWield()) { Attack(target, MainSecondary, false, false, false, opts, special); - if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()) + if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()){ Attack(target, MainSecondary, false, false, false, opts, special); + + if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ + int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; + if (chance && zone->random.Roll(chance)) + Flurry(nullptr); + } + } } } } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 772f875e5..bcf70a873 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1423,7 +1423,12 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) if (newbon->PC_Pet_Rampage[1] < base2) newbon->PC_Pet_Rampage[1] = base2; //Damage modifer - take highest break; - } + } + + case SE_PC_Pet_Flurry_Chance: + newbon->PC_Pet_Flurry += base1; //Chance to Flurry + break; + // to do case SE_PetDiscipline: break; @@ -3132,7 +3137,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne if (new_bonus->PC_Pet_Rampage[1] < base2) new_bonus->PC_Pet_Rampage[1] = base2; //Damage modifer - take highest break; - } + } + + case SE_PC_Pet_Flurry_Chance: + new_bonus->PC_Pet_Flurry += effect_value; //Chance to Flurry + break; //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/common.h b/zone/common.h index af53e1a93..b76a2d21a 100644 --- a/zone/common.h +++ b/zone/common.h @@ -408,6 +408,7 @@ struct StatBonuses { 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 + uint32 PC_Pet_Flurry; // Percent chance flurry from double attack // AAs int8 Packrat; //weight reduction for items, 1 point = 10% From 2cf59ae2f2ce0ffb0deac5ee9d16aa811341ad7b Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 9 Oct 2015 13:08:24 -0400 Subject: [PATCH 346/846] Updated a few AA effects to use database values instead of hardcoded values. --- common/spdat.h | 6 +- zone/bonuses.cpp | 30 ++++++++-- zone/client_packet.cpp | 76 +++++++++--------------- zone/common.h | 3 + zone/tradeskills.cpp | 129 +---------------------------------------- 5 files changed, 59 insertions(+), 185 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index 75c6e60c0..b89d88307 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -381,7 +381,7 @@ typedef enum { #define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance. #define SE_TwoHandBash 226 // *not implemented as bonus #define SE_ReduceSkillTimer 227 // implemented -#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling +#define SE_ReduceFallDamage 228 // implented - reduce the damage that you take from falling #define SE_PersistantCasting 229 // implemented #define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability #define SE_StunBashChance 231 // implemented - increase chance to stun from bash. @@ -409,7 +409,7 @@ typedef enum { #define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage. #define SE_Blank 254 // implemented #define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield -#define SE_ShroudofStealth 256 // not implemented as bonus - rogue improved invs +#define SE_ShroudofStealth 256 // implemented #define SE_PetDiscipline 257 // not implemented as bonus - /pet hold #define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab #define SE_CombatStability 259 // implemented[AA] - damage mitigation @@ -421,7 +421,7 @@ typedef enum { #define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled #define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon. #define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast -#define SE_ReduceTradeskillFail 268 // *not implemented? - reduces chance to fail with given tradeskill by a percent chance +#define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance #define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound. #define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo) #define SE_BaseMovementSpeed 271 // implemented[AA] - mods basemove speed, doesn't stack with other move mods diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index bcf70a873..fcf952627 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1429,13 +1429,23 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->PC_Pet_Flurry += base1; //Chance to Flurry break; + case SE_ShroudofStealth: + newbon->ShroudofStealth = true; + break; + + case SE_ReduceFallDamage: + newbon->ReduceFallDamage += base1; + break; + + case SE_ReduceTradeskillFail: + newbon->ReduceTradeskillFail[base2] += base1; + break; + // to do case SE_PetDiscipline: break; case SE_PetDiscipline2: break; - case SE_ReduceTradeskillFail: - break; case SE_PotionBeltSlots: break; case SE_BandolierSlots: @@ -1458,13 +1468,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_TrapCircumvention: break; - case SE_ShroudofStealth: - break; case SE_FeignedMinion: break; - // handled client side - case SE_ReduceFallDamage: // not handled here case SE_HastenedAASkill: // not handled here but don't want to clutter debug log -- these may need to be verified to ignore @@ -3143,6 +3149,18 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->PC_Pet_Flurry += effect_value; //Chance to Flurry break; + case SE_ShroudofStealth: + new_bonus->ShroudofStealth = true; + break; + + case SE_ReduceFallDamage: + new_bonus->ReduceFallDamage += effect_value; + break; + + case SE_ReduceTradeskillFail: + new_bonus->ReduceTradeskillFail[base2] += effect_value; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 51ad0f3e8..d8ffb6a68 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5076,18 +5076,12 @@ void Client::Handle_OP_DisarmTraps(const EQApplicationPacket *app) Message(13, "Ability recovery time not yet met."); return; } - int reuse = DisarmTrapsReuseTime; - switch (GetAA(aaAdvTrapNegotiation)) { - case 1: - reuse -= 1; - break; - case 2: - reuse -= 3; - break; - case 3: - reuse -= 5; - break; - } + + int reuse = DisarmTrapsReuseTime - GetSkillReuseTime(SkillDisarmTraps); + + if (reuse < 1) + reuse = 1; + p_timers.Start(pTimerDisarmTraps, reuse - 1); Trap* trap = entity_list.FindNearbyTrap(this, 60); @@ -5359,17 +5353,9 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app) if (ed->dmgtype == 252) { - switch (GetAA(aaAcrobatics)) { //Don't know what acrobatics effect is yet but it should be done client side via aa effect.. till then - case 1: - damage = damage * 95 / 100; - break; - case 2: - damage = damage * 90 / 100; - break; - case 3: - damage = damage * 80 / 100; - break; - } + int mod = spellbonuses.ReduceFallDamage + itembonuses.ReduceFallDamage + aabonuses.ReduceFallDamage; + + damage -= damage * mod / 100; } if (damage < 0) @@ -5443,19 +5429,13 @@ void Client::Handle_OP_FeignDeath(const EQApplicationPacket *app) Message(13, "Ability recovery time not yet met."); return; } + int reuse = FeignDeathReuseTime; - switch (GetAA(aaRapidFeign)) - { - case 1: - reuse -= 1; - break; - case 2: - reuse -= 2; - break; - case 3: - reuse -= 5; - break; - } + reuse -= GetSkillReuseTime(SkillFeignDeath); + + if (reuse < 1) + reuse = 1; + p_timers.Start(pTimerFeignDeath, reuse - 1); //BreakInvis(); @@ -7762,7 +7742,11 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) Message(13, "Ability recovery time not yet met."); return; } - int reuse = HideReuseTime - GetAA(209); + int reuse = HideReuseTime - GetSkillReuseTime(SkillHide); + + if (reuse < 1) + reuse = 1; + p_timers.Start(pTimerHide, reuse - 1); float hidechance = ((GetSkill(SkillHide) / 250.0f) + .25) * 100; @@ -7776,7 +7760,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) sa_out->parameter = 1; entity_list.QueueClients(this, outapp, true); safe_delete(outapp); - if (GetAA(aaShroudofStealth)){ + if (spellbonuses.ShroudofStealth || aabonuses.ShroudofStealth || itembonuses.ShroudofStealth){ improved_hidden = true; hidden = true; } @@ -11698,18 +11682,12 @@ void Client::Handle_OP_SenseTraps(const EQApplicationPacket *app) Message(13, "Ability recovery time not yet met."); return; } - int reuse = SenseTrapsReuseTime; - switch (GetAA(aaAdvTrapNegotiation)) { - case 1: - reuse -= 1; - break; - case 2: - reuse -= 3; - break; - case 3: - reuse -= 5; - break; - } + + int reuse = SenseTrapsReuseTime - GetSkillReuseTime(SkillSenseTraps); + + if (reuse < 1) + reuse = 1; + p_timers.Start(pTimerSenseTraps, reuse - 1); Trap* trap = entity_list.FindNearbyTrap(this, 800); diff --git a/zone/common.h b/zone/common.h index b76a2d21a..77981412d 100644 --- a/zone/common.h +++ b/zone/common.h @@ -467,6 +467,9 @@ struct StatBonuses { int32 PetMeleeMitigation; // Add AC to owner's pet. bool IllusionPersistence; // Causes illusions not to fade. 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. }; typedef struct diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 6ed516da0..e5fe49813 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -941,135 +941,10 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { float res = zone->random.Real(0, 99); int aa_chance = 0; - //AA modifiers - //can we do this with nested switches? - if(spec->tradeskill == SkillAlchemy){ - switch(GetAA(aaAlchemyMastery)){ - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } + aa_chance = spellbonuses.ReduceTradeskillFail[spec->tradeskill] + itembonuses.ReduceTradeskillFail[spec->tradeskill] + aabonuses.ReduceTradeskillFail[spec->tradeskill]; - if(spec->tradeskill == SkillJewelryMaking){ - switch(GetAA(aaJewelCraftMastery)){ - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } const Item_Struct* item = nullptr; - - if (spec->tradeskill == SkillBlacksmithing) { - switch(GetAA(aaBlacksmithingMastery)) { - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } - - if (spec->tradeskill == SkillBaking) { - switch(GetAA(aaBakingMastery)) { - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } - - if (spec->tradeskill == SkillBrewing) { - switch(GetAA(aaBrewingMastery)) { - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } - - if (spec->tradeskill == SkillFletching) { - switch(GetAA(aaFletchingMastery2)) { - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } - - if (spec->tradeskill == SkillPottery) { - switch(GetAA(aaPotteryMastery)) { - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } - - if (spec->tradeskill == SkillTailoring) { - switch(GetAA(aaTailoringMastery)) { - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } - - if (spec->tradeskill == SkillResearch) { - switch(GetAA(aaArcaneTongues)) { - case 1: - aa_chance = 10; - break; - case 2: - aa_chance = 25; - break; - case 3: - aa_chance = 50; - break; - } - } - + chance = mod_tradeskill_chance(chance, spec); if (((spec->tradeskill==75) || GetGM() || (chance > res)) || zone->random.Roll(aa_chance)) { From 79c9862131b6731d347704b8be2b2a605c23a2f5 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 9 Oct 2015 14:04:39 -0400 Subject: [PATCH 347/846] Few more AA updates to use database instead of hard coded values. --- common/spdat.h | 6 +++--- zone/bonuses.cpp | 24 +++++++++++++++++------- zone/client.cpp | 14 ++------------ zone/common.h | 3 ++- zone/tradeskills.cpp | 5 +++-- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index b89d88307..41fd35f1f 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -400,7 +400,7 @@ typedef enum { #define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break. #define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest #define SE_SetBreathLevel 246 // *not implemented as bonus -#define SE_RaiseSkillCap 247 // *not implemented[AA] - adds skill over the skill cap. +#define SE_RaiseSkillCap 247 // implemented[AA] - adds skill over the skill cap. #define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100) #define SE_SecondaryDmgInc 249 // implemented[AA] Allows off hand weapon to recieve a damage bonus (Sinister Strikes) #define SE_SpellProcChance 250 // implemented - Increase chance to proc from melee proc spells (ie Spirit of Panther) @@ -416,7 +416,7 @@ typedef enum { #define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType #define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live) #define SE_RaiseStatCap 262 // implemented -#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master. +#define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master. #define SE_HastenedAASkill 264 // implemented #define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled #define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon. @@ -478,7 +478,7 @@ typedef enum { #define SE_GateToHomeCity 322 // implemented #define SE_DefensiveProc 323 // implemented #define SE_HPToMana 324 // implemented -//#define SE_ChanceInvsBreakToAoE 325 // *not implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell. +//#define SE_NoBreakAESneak 325 // *not implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell. #define SE_SpellSlotIncrease 326 // *not implemented as bonus - increases your spell slot availability #define SE_MysticalAttune 327 // implemented - increases amount of buffs that a player can have #define SE_DelayDeath 328 // implemented - increases how far you can fall below 0 hp before you die diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index fcf952627..88d627dcd 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1199,13 +1199,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) 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 - } + if (newbon->RaiseSkillCap[base2] < base1) + newbon->RaiseSkillCap[base2] = base1; break; } @@ -1441,6 +1438,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->ReduceTradeskillFail[base2] += base1; break; + case SE_TradeSkillMastery: + if (newbon->TradeSkillMastery < base1) + newbon->TradeSkillMastery = base1; + break; + // to do case SE_PetDiscipline: break; @@ -1452,8 +1454,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_ForageSkill: break; - case SE_TradeSkillMastery: - break; case SE_SecondaryForte: break; case SE_FeignedCastOnChance: @@ -3161,6 +3161,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->ReduceTradeskillFail[base2] += effect_value; break; + case SE_TradeSkillMastery: + if (new_bonus->TradeSkillMastery < effect_value) + new_bonus->TradeSkillMastery = effect_value; + break; + + case SE_RaiseSkillCap: + if (new_bonus->RaiseSkillCap[base2] < effect_value) + new_bonus->RaiseSkillCap[base2] = effect_value; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/client.cpp b/zone/client.cpp index ef0c9bf7d..24a916b2a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2439,18 +2439,8 @@ uint16 Client::GetMaxSkillAfterSpecializationRules(SkillUseTypes skillid, uint16 } } - // This should possibly be handled by bonuses rather than here. - switch(skillid) - { - case SkillTracking: - { - Result += ((GetAA(aaAdvancedTracking) * 10) + (GetAA(aaTuneofPursuance) * 10)); - break; - } - - default: - break; - } + + Result += spellbonuses.RaiseSkillCap[skillid] + itembonuses.RaiseSkillCap[skillid] + aabonuses.RaiseSkillCap[skillid]; return Result; } diff --git a/zone/common.h b/zone/common.h index 77981412d..88aa58264 100644 --- a/zone/common.h +++ b/zone/common.h @@ -439,7 +439,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[2]; // Raise a specific skill cap (1 = value, 2=skill) + uint32 RaiseSkillCap[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,6 +470,7 @@ struct StatBonuses { 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. + uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill. }; typedef struct diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index e5fe49813..903c7c34c 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1403,8 +1403,9 @@ bool Client::CanIncreaseTradeskill(SkillUseTypes tradeskill) { uint8 Pottery = (GetRawSkill(SkillPottery) > 200) ? 1 : 0; uint8 Tailoring = (GetRawSkill(SkillTailoring) > 200) ? 1 : 0; uint8 SkillTotal = Baking + Smithing + Brewing + Fletching + Jewelry + Pottery + Tailoring; //Tradeskills above 200 - uint32 aaLevel = GetAA(aaNewTanaanCraftingMastery); //New Tanaan AA: Each level allows an additional tradeskill above 200 (first one is free) - + //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: From aae073f58814ce5edf6f927aa023b766181069b0 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 9 Oct 2015 14:29:15 -0400 Subject: [PATCH 348/846] update --- zone/bonuses.cpp | 24 +++++++++++++++++++++--- zone/spells.cpp | 8 -------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 88d627dcd..ab7d8bfee 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1201,6 +1201,10 @@ 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) + break; + if (newbon->RaiseSkillCap[base2] < base1) newbon->RaiseSkillCap[base2] = base1; break; @@ -1434,9 +1438,14 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->ReduceFallDamage += base1; break; - case SE_ReduceTradeskillFail: + case SE_ReduceTradeskillFail:{ + + if (base2 > HIGHEST_SKILL) + break; + newbon->ReduceTradeskillFail[base2] += base1; break; + } case SE_TradeSkillMastery: if (newbon->TradeSkillMastery < base1) @@ -3157,19 +3166,28 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->ReduceFallDamage += effect_value; break; - case SE_ReduceTradeskillFail: + case SE_ReduceTradeskillFail:{ + + if (base2 > HIGHEST_SKILL) + break; + new_bonus->ReduceTradeskillFail[base2] += effect_value; break; + } case SE_TradeSkillMastery: if (new_bonus->TradeSkillMastery < effect_value) new_bonus->TradeSkillMastery = effect_value; break; - case SE_RaiseSkillCap: + case SE_RaiseSkillCap: { + if (base2 > HIGHEST_SKILL) + break; + if (new_bonus->RaiseSkillCap[base2] < effect_value) new_bonus->RaiseSkillCap[base2] = effect_value; break; + } //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/spells.cpp b/zone/spells.cpp index ce45b6d83..999ab684d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -750,14 +750,6 @@ bool Client::CheckFizzle(uint16 spell_id) // always at least 1% chance to fail or 5% to succeed fizzlechance = fizzlechance < 1 ? 1 : (fizzlechance > 95 ? 95 : fizzlechance); - /* - if(IsBardSong(spell_id)) - { - //This was a channel chance modifier - no evidence for fizzle reduction - fizzlechance -= GetAA(aaInternalMetronome) * 1.5f; - } - */ - float fizzle_roll = zone->random.Real(0, 100); Log.Out(Logs::Detail, Logs::Spells, "Check Fizzle %s spell %d fizzlechance: %0.2f%% diff: %0.2f roll: %0.2f", GetName(), spell_id, fizzlechance, diff, fizzle_roll); From ecd695ff9b40a389a7708d0761e98fd6cfd26f18 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 9 Oct 2015 21:34:31 -0400 Subject: [PATCH 349/846] Script and server code query updates for bots_updater --- common/database.cpp | 8 +- common/database.h | 1 - common/database_conversions.cpp | 158 --- common/guild_base.cpp | 16 +- common/ruletypes.h | 18 +- common/shareddb.cpp | 29 +- common/shareddb.h | 7 +- .../sql/git/bots/bots_db_update_manifest.txt | 2 +- .../drop_bots (pre-update script).sql | 88 ++ utils/sql/git/bots/drop_bots.sql | 119 +- .../sql/git/bots/required/2015_09_30_bots.sql | 959 ++++++++++---- zone/bot.cpp | 1110 ++++++++++++----- zone/botspellsai.cpp | 2 +- zone/questmgr.cpp | 8 +- 14 files changed, 1722 insertions(+), 803 deletions(-) create mode 100644 utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql diff --git a/common/database.cpp b/common/database.cpp index 570bcbb43..475b48258 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -348,11 +348,11 @@ bool Database::DeleteCharacter(char *name) { query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); QueryDatabase(query); query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); QueryDatabase(query); query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); QueryDatabase(query); -#ifdef BOTS - query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); -#else +#ifdef BOTS + query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); // note: only use of GetMobTypeById() +#else query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", charid); -#endif +#endif QueryDatabase(query); return true; diff --git a/common/database.h b/common/database.h index 1543a14e3..c3771f67c 100644 --- a/common/database.h +++ b/common/database.h @@ -209,7 +209,6 @@ public: /* Database Conversions 'database_conversions.cpp' */ bool CheckDatabaseConversions(); - bool CheckDatabaseConvertBotsPostPPDeblob(); bool CheckDatabaseConvertCorpseDeblob(); bool CheckDatabaseConvertPPDeblob(); diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index c3c54cde5..aa772c8b1 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -470,7 +470,6 @@ static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) bool Database::CheckDatabaseConversions() { CheckDatabaseConvertPPDeblob(); - CheckDatabaseConvertBotsPostPPDeblob(); CheckDatabaseConvertCorpseDeblob(); /* Fetch Automatic Upgrade Script */ @@ -1491,163 +1490,6 @@ bool Database::CheckDatabaseConvertPPDeblob(){ return true; } -bool Database::CheckDatabaseConvertBotsPostPPDeblob(){ -#ifdef BOTS - int runbotsconvert = 0; - - /* Check For Legacy Bot References */ - std::string rquery = StringFormat("SHOW CREATE VIEW `vwBotCharacterMobs`"); - auto results = QueryDatabase(rquery); - if (results.RowCount() == 1){ - auto row = results.begin(); - std::string table_check = row[1]; - - if (table_check.find("character_data") == -1){ - runbotsconvert = 1; - printf("\n\n::: Legacy Bot Views and Function Detected... \n"); - printf("----------------------------------------------------------\n\n"); - printf(" Database currently has bot view/function linkage to obselete \n"); - printf(" table references and will now be converted...\n\n"); - printf(" It is recommended that you backup your database \n"); - printf(" before continuing the automatic conversion process...\n\n"); - printf("----------------------------------------------------------\n\n"); - std::cout << "Press ENTER to continue....." << std::endl << std::endl; - std::cin.ignore(1); - } - } - - if (runbotsconvert == 1){ - printf("Running bot views/function database conversion... \n"); - - /* Update view `vwbotcharactermobs` */ - rquery = StringFormat("DROP VIEW `vwBotCharacterMobs`;"); - results = QueryDatabase(rquery); - - rquery = StringFormat( - "CREATE VIEW `vwBotCharacterMobs` AS\n" - "SELECT _utf8'C' AS mobtype,\n" // Natedog: '_utf8' - "c.`id`,\n" - "c.`name`,\n" - "c.`class`,\n" - "c.`level`,\n" - "c.`last_login`,\n" - "c.`zone_id`\n" - "FROM `character_data` AS c\n" - "UNION ALL\n" - "SELECT _utf8'B' AS mobtype,\n" // Natedog: '_utf8' - "b.`BotID` AS id,\n" - "b.`Name` AS name,\n" - "b.`Class` AS class,\n" - "b.`BotLevel` AS level,\n" - "0 AS timelaston,\n" - "0 AS zoneid\n" - "FROM bots AS b;" - ); - results = QueryDatabase(rquery); - - - /* Update function `GetMobType` */ - rquery = StringFormat("DROP FUNCTION IF EXISTS `GetMobType`;"); - results = QueryDatabase(rquery); - - rquery = StringFormat( - "CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1)\n" - "BEGIN\n" - " DECLARE Result CHAR(1);\n" - "\n" - " SET Result = NULL;\n" - "\n" - " IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN\n" - " SET Result = 'C';\n" - " ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN\n" - " SET Result = 'B';\n" - " END IF;\n " - "\n" - " RETURN Result;\n" - "END" - ); - results = QueryDatabase(rquery); - - - /* Update view `vwgroups` */ - rquery = StringFormat("DROP VIEW IF EXISTS `vwGroups`;"); - results = QueryDatabase(rquery); - - rquery = StringFormat( - "CREATE VIEW `vwGroups` AS\n" - "SELECT g.`groupid` AS groupid,\n" - "GetMobType(g.`name`) AS mobtype,\n" - "g.`name` AS name,\n" - "g.`charid` AS mobid,\n" - "IFNULL(c.`level`, b.`BotLevel`) AS level\n" - "FROM `group_id` AS g\n" - "LEFT JOIN `character_data` AS c ON g.`name` = c.`name`\n" - "LEFT JOIN `bots` AS b ON g.`name` = b.`Name`;" - ); - results = QueryDatabase(rquery); - - - /* Update view `vwbotgroups` */ - rquery = StringFormat("DROP VIEW IF EXISTS `vwBotGroups`;"); - results = QueryDatabase(rquery); - - rquery = StringFormat( - "CREATE VIEW `vwBotGroups` AS\n" - "SELECT g.`BotGroupId`,\n" - "g.`BotGroupName`,\n" - "g.`BotGroupLeaderBotId`,\n" - "b.`Name` AS BotGroupLeaderName,\n" - "b.`BotOwnerCharacterId`,\n" - "c.`name` AS BotOwnerCharacterName\n" - "FROM `botgroup` AS g\n" - "JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID`\n" - "JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id`\n" - "ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`;" - ); - results = QueryDatabase(rquery); - - - /* Update view `vwguildmembers` */ - rquery = StringFormat("DROP VIEW IF EXISTS `vwGuildMembers`;"); - results = QueryDatabase(rquery); - - rquery = StringFormat( - "CREATE VIEW `vwGuildMembers` AS\n" - "SELECT 'C' AS mobtype,\n" - "cm.`char_id`,\n" - "cm.`guild_id`,\n" - "cm.`rank`,\n" - "cm.`tribute_enable`,\n" - "cm.`total_tribute`,\n" - "cm.`last_tribute`,\n" - "cm.`banker`,\n" - "cm.`public_note`,\n" - "cm.`alt`\n" - "FROM `guild_members` AS cm\n" - "UNION ALL\n" - "SELECT 'B' AS mobtype,\n" - "bm.`char_id`,\n" - "bm.`guild_id`,\n" - "bm.`rank`,\n" - "bm.`tribute_enable`,\n" - "bm.`total_tribute`,\n" - "bm.`last_tribute`,\n" - "bm.`banker`,\n" - "bm.`public_note`,\n" - "bm.`alt`\n" - "FROM `botguildmembers` AS bm;" - ); - results = QueryDatabase(rquery); - } - - if (runbotsconvert == 1){ - printf("\n\nBot views/function conversion complete, continuing world bootup...\n"); - } - -#endif - return true; -} - bool Database::CheckDatabaseConvertCorpseDeblob(){ Convert::DBPlayerCorpse_Struct_temp* dbpc; Convert::classic_db_temp::DBPlayerCorpse_Struct_temp* dbpc_c; diff --git a/common/guild_base.cpp b/common/guild_base.cpp index bfd9f4126..58e7675c5 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -867,16 +867,16 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) { //factored out so I dont have to copy this crap. #ifdef BOTS #define GuildMemberBaseQuery \ -"SELECT c.id,c.name,c.class,c.level,c.last_login,c.zone_id," \ -" g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \ -" g.banker,g.public_note,g.alt" \ -" FROM vwBotCharacterMobs AS c LEFT JOIN vwGuildMembers AS g ON c.id=g.char_id AND c.mobtype = g.mobtype " +"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \ +" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \ +" g.`banker`, g.`public_note`, g.`alt`" \ +" FROM `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` " #else #define GuildMemberBaseQuery \ -"SELECT c.id,c.name,c.class,c.level,c.last_login,c.zone_id," \ -" g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \ -" g.banker,g.public_note,g.alt " \ -" FROM `character_data` AS c LEFT JOIN guild_members AS g ON c.id=g.char_id " +"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \ +" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \ +" g.`banker`, g.`public_note`, g.`alt` " \ +" FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` " #endif static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) { //fields from `characer_` diff --git a/common/ruletypes.h b/common/ruletypes.h index 8cb2ed0db..1b4baa371 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -502,16 +502,16 @@ RULE_CATEGORY_END() #ifdef BOTS RULE_CATEGORY(Bots) -RULE_REAL(Bots, BotManaRegen, 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, BotFinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. -RULE_INT(Bots, CreateBotCount, 150) // Number of bots that each account can create -RULE_INT(Bots, SpawnBotCount, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid -RULE_BOOL(Bots, BotQuest, 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, BotGroupBuffing, 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_BOOL(Bots, BotSpellQuest, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. -RULE_INT(Bots, BotAAExpansion, 8) // Bots get AAs through this expansion +RULE_INT(Bots, AAExpansion, 8) // Bots get AAs through this expansion +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_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, 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_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. +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) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index d5d42a174..7ccfa5cbd 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -2007,24 +2007,21 @@ void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const Insp auto results = QueryDatabase(query); } -void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) { - - std::string query = StringFormat("SELECT BotInspectMessage FROM bots WHERE BotID = %i", botid); +#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); - if (!results.Success()) { - return; + 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)); } - - if (results.RowCount() != 1) - return; - - auto row = results.begin(); - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } -void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message) { - std::string msg = EscapeString(message->text); - std::string query = StringFormat("UPDATE bots SET BotInspectMessage = '%s' WHERE BotID = %i", msg.c_str(), botid); - QueryDatabase(query); +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 923e5b775..36239bc35 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -51,8 +51,6 @@ class SharedDatabase : public Database int32 DeleteStalePlayerCorpses(); void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message); void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message); - void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message); - void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message); bool GetCommandSettings(std::map &commands); uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID); @@ -128,6 +126,11 @@ 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/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 91cdd7b69..1612046dd 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -1,4 +1,4 @@ -9000|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot%'|empty| +9000|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot_data'|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/deprecated/drop_bots (pre-update script).sql b/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql new file mode 100644 index 000000000..9699c157a --- /dev/null +++ b/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql @@ -0,0 +1,88 @@ +-- 'drop_bots (pre-update script)' sql script file +-- current as of 10/09/2015 +-- +-- Note: This file will remove bot schema loaded by 'load_bots' sql scripts. +-- There may still be remnants of bot activity in tables `guild_members` and +-- `group_id`. If these entries are causing issues, you may need to manually +-- remove them. + + +SELECT "dropping views..."; +DROP VIEW IF EXISTS `vwGuildMembers`; +DROP VIEW IF EXISTS `vwGroups`; +DROP VIEW IF EXISTS `vwBotGroups`; +DROP VIEW IF EXISTS `vwBotCharacterMobs`; + + +SELECT "dropping functions..."; +DROP FUNCTION IF EXISTS `GetMobTypeByName`; +DROP FUNCTION IF EXISTS `GetMobTypeByID`; +DROP FUNCTION IF EXISTS `GetMobType`; + + +SELECT "dropping tables..."; +DROP TABLE IF EXISTS `botguildmembers`; +DROP TABLE IF EXISTS `botgroupmembers`; +DROP TABLE IF EXISTS `botgroup`; +DROP TABLE IF EXISTS `botgroups`; -- this table is not a part of 'load_bots.sql' +DROP TABLE IF EXISTS `botpetinventory`; +DROP TABLE IF EXISTS `botpetbuffs`; +DROP TABLE IF EXISTS `botpets`; +DROP TABLE IF EXISTS `botinventory`; +DROP TABLE IF EXISTS `botbuffs`; +DROP TABLE IF EXISTS `bottimers`; +DROP TABLE IF EXISTS `botstances`; +DROP TABLE IF EXISTS `bots`; + +DROP PROCEDURE IF EXISTS `DropBotsSchema`; + + +DELIMITER $$ + +CREATE PROCEDURE `DropBotsSchema` () +BEGIN + + SELECT "deleting rules..."; + DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots%'; + + + SELECT "deleting command..."; + DELETE FROM `commands` WHERE `command` LIKE 'bot'; + + + SELECT "restoring keys..."; + IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + -- IF ((SHOW KEYS IN `group_id` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN + ALTER TABLE `group_id` DROP PRIMARY KEY; + END IF; + ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`); + + IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + -- IF ((SHOW KEYS IN `guild_members` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN + ALTER TABLE `guild_members` DROP PRIMARY KEY; + END IF; + ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`); + + SELECT "de-activating spawns..."; + UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298); + + + SELECT "clearing database version..."; + IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'db_version' AND `COLUMN_NAME` = 'bots_version') > 0) THEN + -- IF ((SHOW COLUMNS FROM `db_version` LIKE 'bots_version') != '') THEN + UPDATE `db_version` + SET `bots_version` = 0; + END IF; + +END$$ + +DELIMITER ; + + +CALL `DropBotsSchema`(); + +SELECT "dropping procedure..."; +DROP PROCEDURE IF EXISTS `DropBotsSchema`; + + +-- End of File diff --git a/utils/sql/git/bots/drop_bots.sql b/utils/sql/git/bots/drop_bots.sql index df8ca4fa8..5645a38b5 100644 --- a/utils/sql/git/bots/drop_bots.sql +++ b/utils/sql/git/bots/drop_bots.sql @@ -1,41 +1,100 @@ -- 'drop_bots' sql script file --- current as of 10/15/2014 +-- current as of 10/09/2015 -- --- Note: This file will revert all changes made by either 'load_bots' sql file. +-- Note: This file will remove bot schema loaded by 'load_bots' sql scripts. -- There may still be remnants of bot activity in tables `guild_members` and -- `group_id`. If these entries are causing issues, you may need to manually -- remove them. --- --- If this script fails due to a 'SQL Error (1068): Multiple primary key defined' --- error, run this query: ALTER TABLE `guild_members` DROP PRIMARY KEY; --- and it should remove the key so this script will process in its entirety. -ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`); -ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`); +SELECT "dropping views..."; +DROP VIEW IF EXISTS `vw_guild_members`; +DROP VIEW IF EXISTS `vw_groups`; +DROP VIEW IF EXISTS `vw_bot_groups`; +DROP VIEW IF EXISTS `vw_bot_character_mobs`; -UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298); - -DELETE FROM `commands` WHERE `command` = 'bot'; -DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots%'; - -DROP VIEW IF EXISTS `vwBotCharacterMobs`; -DROP VIEW IF EXISTS `vwBotGroups`; -DROP VIEW IF EXISTS `vwGroups`; -DROP VIEW IF EXISTS `vwGuildMembers`; +SELECT "dropping functions..."; +DROP FUNCTION IF EXISTS `GetMobTypeByName`; +DROP FUNCTION IF EXISTS `GetMobTypeByID`; DROP FUNCTION IF EXISTS `GetMobType`; -DROP TABLE IF EXISTS `botguildmembers`; -DROP TABLE IF EXISTS `botgroupmembers`; --- this table is not a part of 'load_bots.sql' -DROP TABLE IF EXISTS `botgroups`; -DROP TABLE IF EXISTS `botgroup`; -DROP TABLE IF EXISTS `botpetinventory`; -DROP TABLE IF EXISTS `botpetbuffs`; -DROP TABLE IF EXISTS `botpets`; -DROP TABLE IF EXISTS `botinventory`; -DROP TABLE IF EXISTS `botbuffs`; -DROP TABLE IF EXISTS `bottimers`; -DROP TABLE IF EXISTS `botstances`; -DROP TABLE IF EXISTS `bots`; + +SELECT "dropping tables..."; +DROP TABLE IF EXISTS `botguildmembers_old`; +DROP TABLE IF EXISTS `botgroupmembers_old`; +DROP TABLE IF EXISTS `botgroup_old`; +DROP TABLE IF EXISTS `botpetinventory_old`; +DROP TABLE IF EXISTS `botpetbuffs_old`; +DROP TABLE IF EXISTS `botpets_old`; +DROP TABLE IF EXISTS `botinventory_old`; +DROP TABLE IF EXISTS `botbuffs_old`; +DROP TABLE IF EXISTS `bottimers_old`; +DROP TABLE IF EXISTS `botstances_old`; +DROP TABLE IF EXISTS `bots_old`; + +DROP TABLE IF EXISTS `bot_guild_members`; +DROP TABLE IF EXISTS `bot_group_members`; +DROP TABLE IF EXISTS `bot_groups`; +DROP TABLE IF EXISTS `bot_pet_inventories`; +DROP TABLE IF EXISTS `bot_pet_buffs`; +DROP TABLE IF EXISTS `bot_pets`; +DROP TABLE IF EXISTS `bot_inventories`; +DROP TABLE IF EXISTS `bot_buffs`; +DROP TABLE IF EXISTS `bot_timers`; +DROP TABLE IF EXISTS `bot_stances`; +DROP TABLE IF EXISTS `bot_inspect_messages`; +DROP TABLE IF EXISTS `bot_data`; + +DROP PROCEDURE IF EXISTS `DropBotsSchema`; + + +DELIMITER $$ + +CREATE PROCEDURE `DropBotsSchema` () +BEGIN + + SELECT "deleting rules..."; + DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots%'; + + + SELECT "deleting command..."; + DELETE FROM `commands` WHERE `command` LIKE 'bot'; + + + SELECT "restoring keys..."; + IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + -- IF ((SHOW KEYS IN `group_id` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN + ALTER TABLE `group_id` DROP PRIMARY KEY; + END IF; + ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`); + + IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + -- IF ((SHOW KEYS IN `guild_members` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN + ALTER TABLE `guild_members` DROP PRIMARY KEY; + END IF; + ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`); + + SELECT "de-activating spawns..."; + UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298); + + + SELECT "clearing database version..."; + IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'db_version' AND `COLUMN_NAME` = 'bots_version') > 0) THEN + -- IF ((SHOW COLUMNS FROM `db_version` LIKE 'bots_version') != '') THEN + UPDATE `db_version` + SET `bots_version` = 0; + END IF; + +END$$ + +DELIMITER ; + + +CALL `DropBotsSchema`(); + +SELECT "dropping procedure..."; +DROP PROCEDURE IF EXISTS `DropBotsSchema`; + + +-- End of File diff --git a/utils/sql/git/bots/required/2015_09_30_bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql index 0dd030545..5551b8a30 100644 --- a/utils/sql/git/bots/required/2015_09_30_bots.sql +++ b/utils/sql/git/bots/required/2015_09_30_bots.sql @@ -1,220 +1,724 @@ --- 'load_bots' sql script file --- current as of 10/15/2014 +-- '2015_09_30_bots' sql script file +-- current as of 10/09/2015 -- --- Use this file on databases where the player profile blob has been converted. --- --- Note: This file assumes a database free of bot remnants. If you have a prior --- bot installation and wish to reload the default schema and entries, then --- source 'drop_bots.sql' before sourcing this file. +-- Use eqemu_update.pl to administer this script -ALTER TABLE `guild_members` DROP PRIMARY KEY; -ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); +-- Clean-up +DROP VIEW IF EXISTS `vwBotCharacterMobs`; +DROP VIEW IF EXISTS `vwBotGroups`; +DROP VIEW IF EXISTS `vwGroups`; +DROP VIEW IF EXISTS `vwGuildMembers`; -UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298); +DROP VIEW IF EXISTS `vw_bot_character_mobs`; +DROP VIEW IF EXISTS `vw_bot_groups`; +DROP VIEW IF EXISTS `vw_groups`; +DROP VIEW IF EXISTS `vw_guild_members`; --- old command kept for reference (`commands` now only has 2 columns - `command` and `access`) --- INSERT INTO `commands` VALUES ('bot', '0', 'Type \"#bot help\" to the see the list of available commands for bots.'); -INSERT INTO `commands` VALUES ('bot', '0'); +DROP FUNCTION IF EXISTS `GetMobType`; +DROP FUNCTION IF EXISTS `GetMobTypeByName`; +DROP FUNCTION IF EXISTS `GetMobTypeByID`; -INSERT INTO `rule_values` VALUES - ('1', 'Bots:BotAAExpansion', '8', 'The expansion through which bots will obtain AAs'), - ('1', 'Bots:BotFinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.'), - ('1', 'Bots:BotGroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.'), - ('1', 'Bots:BotManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.'), - ('1', 'Bots:BotQuest', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl'), - ('1', 'Bots:BotSpellQuest', 'false', 'Anita Thrall\'s (Anita_Thrall.pl) Bot Spell Scriber quests.'), - ('1', 'Bots:CreateBotCount', '150', 'Number of bots that each account can create'), - ('1', 'Bots:SpawnBotCount', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid'); +DROP PROCEDURE IF EXISTS `LoadBotsSchema`; -CREATE TABLE `bots` ( - `BotID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotOwnerCharacterID` INT(10) UNSIGNED NOT NULL, - `BotSpellsID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Name` VARCHAR(64) NOT NULL, - `LastName` VARCHAR(32) DEFAULT NULL, - `BotLevel` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', - `Race` SMALLINT(5) NOT NULL DEFAULT '0', - `Class` TINYINT(2) NOT NULL DEFAULT '0', - `Gender` TINYINT(2) NOT NULL DEFAULT '0', - `Size` FLOAT NOT NULL DEFAULT '0', - `Face` INT(10) NOT NULL DEFAULT '1', - `LuclinHairStyle` INT(10) NOT NULL DEFAULT '1', - `LuclinHairColor` INT(10) NOT NULL DEFAULT '1', - `LuclinEyeColor` INT(10) NOT NULL DEFAULT '1', - `LuclinEyeColor2` INT(10) NOT NULL DEFAULT '1', - `LuclinBeardColor` INT(10) NOT NULL DEFAULT '1', - `LuclinBeard` INT(10) NOT NULL DEFAULT '0', - `DrakkinHeritage` INT(10) NOT NULL DEFAULT '0', - `DrakkinTattoo` INT(10) NOT NULL DEFAULT '0', - `DrakkinDetails` INT(10) NOT NULL DEFAULT '0', - `HP` INTEGER NOT NULL DEFAULT '0', - `Mana` INTEGER NOT NULL DEFAULT '0', - `MR` SMALLINT(5) NOT NULL DEFAULT '0', - `CR` SMALLINT(5) NOT NULL DEFAULT '0', - `DR` SMALLINT(5) NOT NULL DEFAULT '0', - `FR` SMALLINT(5) NOT NULL DEFAULT '0', - `PR` SMALLINT(5) NOT NULL DEFAULT '0', - `Corrup` SMALLINT(5) NOT NULL DEFAULT '0', - `AC` SMALLINT(5) NOT NULL DEFAULT '0', - `STR` MEDIUMINT(8) NOT NULL DEFAULT '75', - `STA` MEDIUMINT(8) NOT NULL DEFAULT '75', - `DEX` MEDIUMINT(8) NOT NULL DEFAULT '75', - `AGI` MEDIUMINT(8) NOT NULL DEFAULT '75', - `_INT` MEDIUMINT(8) NOT NULL DEFAULT '80', - `WIS` MEDIUMINT(8) NOT NULL DEFAULT '75', - `CHA` MEDIUMINT(8) NOT NULL DEFAULT '75', - `ATK` MEDIUMINT(9) NOT NULL DEFAULT '0', - `BotCreateDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - `LastSpawnDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', - `TotalPlayTime` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `LastZoneId` SMALLINT(6) NOT NULL DEFAULT '0', - `BotInspectMessage` VARCHAR(256) NOT NULL DEFAULT '', - PRIMARY KEY (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botstances` ( - `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `StanceID` TINYINT UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotID`), - CONSTRAINT `FK_botstances_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -); - -CREATE TABLE `bottimers` ( - `BotID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `TimerID` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Value` INT(10) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotID`), - CONSTRAINT `FK_bottimers_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -); - -CREATE TABLE `botbuffs` ( - `BotBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `DurationFormula` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `TicsRemaining` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `PoisonCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `DiseaseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `CurseCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `CorruptionCounters` INT(11) UNSIGNED NOT NULL DEFAULT '0', - `HitCount` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `MeleeRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `MagicRune` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `DeathSaveSuccessChance` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterAARank` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Persistent` TINYINT(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`BotBuffId`), - KEY `FK_botbuff_1` (`BotId`), - CONSTRAINT `FK_botbuff_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botinventory` ( - `BotInventoryID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotID` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `SlotID` INTEGER SIGNED NOT NULL DEFAULT '0', - `ItemID` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `charges` TINYINT(3) UNSIGNED DEFAULT 0, - `color` INTEGER UNSIGNED NOT NULL DEFAULT 0, - `augslot1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT 0, - `augslot5` MEDIUMINT(7) UNSIGNED DEFAULT 0, - `instnodrop` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, - PRIMARY KEY (`BotInventoryID`), - KEY `FK_botinventory_1` (`BotID`), - CONSTRAINT `FK_botinventory_1` FOREIGN KEY (`BotID`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botpets` ( - `BotPetsId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `PetId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `Name` VARCHAR(64) NULL, - `Mana` INTEGER NOT NULL DEFAULT '0', - `HitPoints` INTEGER NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetsId`), - KEY `FK_botpets_1` (`BotId`), - CONSTRAINT `FK_botpets_1` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`), - CONSTRAINT `U_botpets_1` UNIQUE (`BotId`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botpetbuffs` ( - `BotPetBuffId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `BotPetsId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `SpellId` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `CasterLevel` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `Duration` INT(11) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetBuffId`), - KEY `FK_botpetbuffs_1` (`BotPetsId`), - CONSTRAINT `FK_botpetbuffs_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botpetinventory` ( - `BotPetInventoryId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotPetsId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `ItemId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotPetInventoryId`), - KEY `FK_botpetinventory_1` (`BotPetsId`), - CONSTRAINT `FK_botpetinventory_1` FOREIGN KEY (`BotPetsId`) REFERENCES `botpets` (`BotPetsID`) -) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - -CREATE TABLE `botgroup` ( - `BotGroupId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotGroupLeaderBotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotGroupName` VARCHAR(64) NOT NULL, - PRIMARY KEY (`BotGroupId`), - KEY `FK_botgroup_1` (`BotGroupLeaderBotId`), - CONSTRAINT `FK_botgroup_1` FOREIGN KEY (`BotGroupLeaderBotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botgroupmembers` ( - `BotGroupMemberId` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `BotGroupId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - `BotId` INTEGER UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`BotGroupMemberId`), - KEY `FK_botgroupmembers_1` (`BotGroupId`), - CONSTRAINT `FK_botgroupmembers_1` FOREIGN KEY (`BotGroupId`) REFERENCES `botgroup` (`BotGroupId`), - KEY `FK_botgroupmembers_2` (`BotId`), - CONSTRAINT `FK_botgroupmembers_2` FOREIGN KEY (`BotId`) REFERENCES `bots` (`BotID`) -) ENGINE=InnoDB; - -CREATE TABLE `botguildmembers` ( - `char_id` INT(11) NOT NULL DEFAULT '0', - `guild_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', - `rank` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `tribute_enable` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `total_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `last_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `banker` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - `public_note` TEXT NULL, - `alt` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', - PRIMARY KEY (`char_id`) -) ENGINE=InnoDB; DELIMITER $$ -CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1) +CREATE PROCEDURE `LoadBotsSchema` () +BEGIN + -- Activate + UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298); + + + -- Alter + IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + -- IF ((SHOW KEYS IN `guild_members` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN + ALTER TABLE `guild_members` DROP PRIMARY KEY; + END IF; + + IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + -- IF ((SHOW KEYS IN `group_id` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN + ALTER TABLE `group_id` DROP PRIMARY KEY; + END IF; + ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); + -- + -- From original bots.sql (for reference) + -- ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`); + -- ALTER TABLE `guild_members` DROP PRIMARY KEY; + -- ALTER TABLE `group_id` ADD UNIQUE INDEX `U_group_id_1`(`name`); + -- ALTER TABLE `group_leaders` ADD UNIQUE INDEX `U_group_leaders_1`(`leadername`); + + + -- Commands + IF ((SELECT COUNT(`command`) FROM `commands` WHERE `command` LIKE 'bot') = 0) THEN + INSERT INTO `commands` VALUES ('bot', '0'); + END IF; + + + -- Rules + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion') > 0) THEN + UPDATE `rule_values` SET `rule_name` = 'Bots:AAExpansion' WHERE `rule_name` LIKE 'Bots:BotAAExpansion'; + END IF; + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion') = 0) THEN + INSERT INTO `rule_values` VALUES ('1', 'Bots:AAExpansion', '8', 'The expansion through which bots will obtain AAs'); + END IF; + + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount') > 0) THEN + UPDATE `rule_values` SET `rule_name` = 'Bots:CreationLimit' WHERE `rule_name` LIKE 'Bots:CreateBotCount'; + END IF; + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit') = 0) THEN + INSERT INTO `rule_values` VALUES ('1', 'Bots:CreationLimit', '150', 'Number of bots that each account can create'); + END IF; + + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing') > 0) THEN + UPDATE `rule_values` SET `rule_name` = 'Bots:FinishBuffing' WHERE `rule_name` LIKE 'Bots:BotFinishBuffing'; + END IF; + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing') = 0) THEN + 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.'); + END IF; + + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing') > 0) THEN + UPDATE `rule_values` SET `rule_name` = 'Bots:GroupBuffing' WHERE `rule_name` LIKE 'Bots:BotGroupBuffing'; + END IF; + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing') = 0) THEN + 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.'); + END IF; + + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen') > 0) THEN + UPDATE `rule_values` SET `rule_name` = 'Bots:ManaRegen' WHERE `rule_name` LIKE 'Bots:BotManaRegen'; + END IF; + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen') = 0) THEN + 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.'); + END IF; + + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest') > 0) THEN + UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpawnLimit' WHERE `rule_name` LIKE 'Bots:BotQuest'; + END IF; + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit') = 0) THEN + 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'); + END IF; + + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest') > 0) THEN + UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpells' WHERE `rule_name` LIKE 'Bots:BotSpellQuest'; + END IF; + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells') = 0) THEN + INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpells', 'false', 'Anita Thrall\'s (Anita_Thrall.pl) Bot Spell Scriber quests.'); + END IF; + + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount') > 0) THEN + UPDATE `rule_values` SET `rule_name` = 'Bots:SpawnLimit' WHERE `rule_name` LIKE 'Bots:SpawnBotCount'; + END IF; + IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit') = 0) THEN + 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'); + END IF; + + + -- Tables + CREATE TABLE `bot_data` ( + `bot_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `owner_id` INT(11) UNSIGNED NOT NULL, + `spells_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `name` VARCHAR(64) NOT NULL DEFAULT '', + `last_name` VARCHAR(64) NOT NULL DEFAULT '', -- Change unused (64) from (32) + `title` VARCHAR(32) NOT NULL DEFAULT '', -- Unused + `suffix` VARCHAR(32) NOT NULL DEFAULT '', -- Unused + `zone_id` SMALLINT(6) NOT NULL DEFAULT '0', + `gender` TINYINT(2) NOT NULL DEFAULT '0', + `race` SMALLINT(5) NOT NULL DEFAULT '0', + `class` TINYINT(2) NOT NULL DEFAULT '0', + `level` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', + `deity` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused + `creation_day` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `last_spawn` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `time_spawned` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `size` FLOAT NOT NULL DEFAULT '0', + `face` INT(10) NOT NULL DEFAULT '1', + `hair_color` INT(10) NOT NULL DEFAULT '1', + `hair_style` INT(10) NOT NULL DEFAULT '1', + `beard` INT(10) NOT NULL DEFAULT '0', + `beard_color` INT(10) NOT NULL DEFAULT '1', + `eye_color_1` INT(10) NOT NULL DEFAULT '1', + `eye_color_2` INT(10) NOT NULL DEFAULT '1', + `drakkin_heritage` INT(10) NOT NULL DEFAULT '0', + `drakkin_tattoo` INT(10) NOT NULL DEFAULT '0', + `drakkin_details` INT(10) NOT NULL DEFAULT '0', + `ac` SMALLINT(5) NOT NULL DEFAULT '0', + `atk` MEDIUMINT(9) NOT NULL DEFAULT '0', + `hp` INTEGER NOT NULL DEFAULT '0', + `mana` INTEGER NOT NULL DEFAULT '0', + `str` MEDIUMINT(8) NOT NULL DEFAULT '75', + `sta` MEDIUMINT(8) NOT NULL DEFAULT '75', + `cha` MEDIUMINT(8) NOT NULL DEFAULT '75', + `dex` MEDIUMINT(8) NOT NULL DEFAULT '75', + `int` MEDIUMINT(8) NOT NULL DEFAULT '75', + `agi` MEDIUMINT(8) NOT NULL DEFAULT '75', + `wis` MEDIUMINT(8) NOT NULL DEFAULT '75', + `fire` SMALLINT(5) NOT NULL DEFAULT '0', + `cold` SMALLINT(5) NOT NULL DEFAULT '0', + `magic` SMALLINT(5) NOT NULL DEFAULT '0', + `poison` SMALLINT(5) NOT NULL DEFAULT '0', + `disease` SMALLINT(5) NOT NULL DEFAULT '0', + `corruption` SMALLINT(5) NOT NULL DEFAULT '0', + `show_helm` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused + PRIMARY KEY (`bot_id`) + ) ENGINE=InnoDB; + CREATE TABLE `bot_inspect_messages` ( + `bot_id` INT(11) UNSIGNED NOT NULL, + `inspect_message` VARCHAR(256) NOT NULL DEFAULT '', + PRIMARY KEY (`bot_id`), + INDEX `bot_id` (`bot_id`) + ) ENGINE=InnoDB; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'bots') > 0) THEN + -- IF ((SHOW TABLES LIKE 'bots') != '') THEN + 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`, + `BotCreateDate`, + `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`; + + INSERT INTO `bot_inspect_messages` ( + `bot_id`, + `inspect_message` + ) + SELECT + `BotID`, + `BotInspectMessage` + FROM `bots`; + + RENAME TABLE `bots` TO `bots_old`; + END IF; + + CREATE TABLE `bot_stances` ( + `bot_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `stance_id` TINYINT UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`bot_id`), + CONSTRAINT `FK_bot_stances_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) + ); + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botstances') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botstances') != '') THEN + INSERT INTO `bot_stances` ( + `bot_id`, + `stance_id` + ) + SELECT + `BotID`, + `StanceID` + FROM `botstances`; + + RENAME TABLE `botstances` TO `botstances_old`; + END IF; + + CREATE TABLE `bot_timers` ( + `bot_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `timer_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `timer_value` INT(11) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`bot_id`), + CONSTRAINT `FK_bot_timers_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) + ); + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'bottimers') > 0) THEN + -- IF ((SHOW TABLES LIKE 'bottimers') != '') THEN + INSERT INTO `bot_timers` ( + `bot_id`, + `timer_id`, + `timer_value` + ) + SELECT + `BotID`, + `TimerID`, + `Value` + FROM `bottimers`; + + RENAME TABLE `bottimers` TO `bottimers_old`; + END IF; + + CREATE TABLE `bot_buffs` ( + `buffs_index` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `bot_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `spell_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `caster_level` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `duration_formula` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `tics_remaining` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `poison_counters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `disease_counters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `curse_counters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `corruption_counters` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `numhits` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `melee_rune` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `magic_rune` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `dot_rune` INT(10) UNSIGNED NOT NULL DEFAULT '0', -- Fix + `persistent` TINYINT(1) NOT NULL DEFAULT '0', + `caston_x` INT(10) NOT NULL DEFAULT '0', -- Fix + `caston_y` INT(10) NOT NULL DEFAULT '0', -- Fix + `caston_z` INT(10) NOT NULL DEFAULT '0', -- Fix + `extra_di_chance` INT(10) UNSIGNED NOT NULL DEFAULT '0', -- Fix + `instrument_mod` INT(10) NOT NULL DEFAULT '10', -- Unused + PRIMARY KEY (`buffs_index`), + KEY `FK_bot_buffs_1` (`bot_id`), + CONSTRAINT `FK_bot_buffs_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) + ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botbuffs') != '') THEN + 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 + `BotBuffId`, + `BotId`, + `SpellId`, + `CasterLevel`, + `DurationFormula`, + `TicsRemaining`, + `PoisonCounters`, + `DiseaseCounters`, + `CurseCounters`, + `CorruptionCounters`, + `HitCount`, + `MeleeRune`, + `MagicRune`, + `Persistent` + FROM `botbuffs`; + + IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'dot_rune') > 0) THEN + -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'dot_rune') != '') THEN + UPDATE `bot_buffs` + SET `dot_rune` = `botbuffs`.`dot_rune` + WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + END IF; + + IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_x') > 0) THEN + -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'caston_x') != '') THEN + UPDATE `bot_buffs` + SET `caston_x` = `botbuffs`.`caston_x` + WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + END IF; + + IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_y') > 0) THEN + -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'caston_y') != '') THEN + UPDATE `bot_buffs` + SET `caston_y` = `botbuffs`.`caston_y` + WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + END IF; + + IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_z') > 0) THEN + -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'caston_z') != '') THEN + UPDATE `bot_buffs` + SET `caston_z` = `botbuffs`.`caston_z` + WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + END IF; + + IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'ExtraDIChance') > 0) THEN + -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'ExtraDIChance') != '') THEN + UPDATE `bot_buffs` + SET `extra_di_chance` = `botbuffs`.`ExtraDIChance` + WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + END IF; + + RENAME TABLE `botbuffs` TO `botbuffs_old`; + END IF; + + CREATE TABLE `bot_inventories` ( + `inventories_index` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `bot_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `slot_id` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `item_id` INT(11) UNSIGNED NULL DEFAULT '0', + `inst_charges` TINYINT(3) UNSIGNED DEFAULT 0, + `inst_color` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `inst_no_drop` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', + `inst_custom_data` TEXT NULL, -- Unused + `ornament_icon` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused + `ornament_id_file` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused + `ornament_hero_model` INT(11) NOT NULL DEFAULT '0', -- Unused + `augment_1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augment_2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augment_3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augment_4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augment_5` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', + `augment_6` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', -- Unused + PRIMARY KEY (`inventories_index`), + KEY `FK_bot_inventories_1` (`bot_id`), + CONSTRAINT `FK_bot_inventories_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) + ) ENGINE=InnoDB; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botinventory') != '') THEN + 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 + `BotInventoryID`, + `BotID`, + `SlotID`, + `ItemID`, + `charges`, + `color`, + `instnodrop`, + `augslot1`, + `augslot2`, + `augslot3`, + `augslot4`, + `augslot5` + FROM `botinventory`; + + IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory' AND `COLUMN_NAME` = 'augslot6') > 0) THEN + -- IF ((SHOW COLUMNS FROM `botinventory` LIKE 'augslot6') != '') THEN + UPDATE `bot_inventories` + SET `augment_6` = `botinventory`.`augslot6` + WHERE `inventories_index` = `botinventory`.`BotInventoryID` AND `bot_id` = `botinventory`.`BotID`; + END IF; + + RENAME TABLE `botinventory` TO `botinventory_old`; + END IF; + + CREATE TABLE `bot_pets` ( + `pets_index` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `pet_id` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `bot_id` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `name` VARCHAR(64) NULL, + `mana` INTEGER NOT NULL DEFAULT '0', + `hp` INTEGER NOT NULL DEFAULT '0', + PRIMARY KEY (`pets_index`), + KEY `FK_bot_pets_1` (`bot_id`), + CONSTRAINT `FK_bot_pets_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`), + CONSTRAINT `U_bot_pets_1` UNIQUE (`bot_id`) + ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpets') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botpets') != '') THEN + INSERT INTO `bot_pets` ( + `pets_index`, + `pet_id`, + `bot_id`, + `name`, + `mana`, + `hp` + ) + SELECT + `BotPetsId`, + `PetId`, + `BotId`, + `Name`, + `Mana`, + `HitPoints` + FROM `botpets`; + + RENAME TABLE `botpets` TO `botpets_old`; + END IF; + + CREATE TABLE `bot_pet_buffs` ( + `pet_buffs_index` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `pets_index` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `spell_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `caster_level` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `duration` INT(11) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`pet_buffs_index`), + KEY `FK_bot_pet_buffs_1` (`pets_index`), + CONSTRAINT `FK_bot_pet_buffs_1` FOREIGN KEY (`pets_index`) REFERENCES `bot_pets` (`pets_index`) + ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpetbuffs') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botpetbuffs') != '') THEN + INSERT INTO `bot_pet_buffs` ( + `pet_buffs_index`, + `pets_index`, + `spell_id`, + `caster_level`, + `duration` + ) + SELECT + `BotPetBuffId`, + `BotPetsId`, + `SpellId`, + `CasterLevel`, + `Duration` + FROM `botpetbuffs`; + + RENAME TABLE `botpetbuffs` TO `botpetbuffs_old`; + END IF; + + CREATE TABLE `bot_pet_inventories` ( + `pet_inventories_index` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `pets_index` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `item_id` INTEGER UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`pet_inventories_index`), + KEY `FK_bot_pet_inventories_1` (`pets_index`), + CONSTRAINT `FK_bot_pet_inventories_1` FOREIGN KEY (`pets_index`) REFERENCES `bot_pets` (`pets_index`) + ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpetinventory') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botpetinventory') != '') THEN + INSERT INTO `bot_pet_inventories` ( + `pet_inventories_index`, + `pets_index`, + `item_id` + ) + SELECT + `BotPetInventoryId`, + `BotPetsId`, + `ItemId` + FROM `botpetinventory`; + + RENAME TABLE `botpetinventory` TO `botpetinventory_old`; + END IF; + + CREATE TABLE `bot_groups` ( + `groups_index` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `group_leader_id` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `group_name` VARCHAR(64) NOT NULL, + PRIMARY KEY (`groups_index`), + KEY `FK_bot_groups_1` (`group_leader_id`), + CONSTRAINT `FK_bot_groups_1` FOREIGN KEY (`group_leader_id`) REFERENCES `bot_data` (`bot_id`) + ) ENGINE=InnoDB; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botgroup') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botgroup') != '') THEN + INSERT INTO `bot_groups` ( + `groups_index`, + `group_leader_id`, + `group_name` + ) + SELECT + `BotGroupId`, + `BotGroupLeaderBotId`, + `BotGroupName` + FROM `botgroup`; + + RENAME TABLE `botgroup` TO `botgroup_old`; + END IF; + + CREATE TABLE `bot_group_members` ( + `group_members_index` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `groups_index` INTEGER UNSIGNED NOT NULL DEFAULT '0', + `bot_id` INTEGER UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`group_members_index`), + KEY `FK_bot_group_members_1` (`groups_index`), + CONSTRAINT `FK_bot_group_members_1` FOREIGN KEY (`groups_index`) REFERENCES `bot_groups` (`groups_index`), + KEY `FK_bot_group_members_2` (`bot_id`), + CONSTRAINT `FK_bot_group_members_2` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) + ) ENGINE=InnoDB; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botgroupmembers') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botgroupmembers') != '') THEN + INSERT INTO `bot_group_members` ( + `group_members_index`, + `groups_index`, + `bot_id` + ) + SELECT + `BotGroupMemberId`, + `BotGroupId`, + `BotId` + FROM `botgroupmembers`; + + RENAME TABLE `botgroupmembers` TO `botgroupmembers_old`; + END IF; + + CREATE TABLE `bot_guild_members` ( + `bot_id` INT(11) NOT NULL DEFAULT '0', + `guild_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', + `rank` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `tribute_enable` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `total_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `last_tribute` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `banker` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `public_note` TEXT NULL, + `alt` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`bot_id`) + ) ENGINE=InnoDB; + IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botguildmembers') > 0) THEN + -- IF ((SHOW TABLES LIKE 'botguildmembers') != '') THEN + INSERT INTO `bot_guild_members` ( + `bot_id`, + `guild_id`, + `rank`, + `tribute_enable`, + `total_tribute`, + `last_tribute`, + `banker`, + `public_note`, + `alt` + ) + SELECT + `char_id`, + `guild_id`, + `rank`, + `tribute_enable`, + `total_tribute`, + `last_tribute`, + `banker`, + `public_note`, + `alt` + FROM `botguildmembers`; + + RENAME TABLE `botguildmembers` TO `botguildmembers_old`; + END IF; + +END$$ + +DELIMITER ; + + +CALL `LoadBotsSchema`(); + +DROP PROCEDURE IF EXISTS `LoadBotsSchema`; + + +-- Functions +DELIMITER $$ + +-- (no code references) +CREATE FUNCTION `GetMobType` (mob_name VARCHAR(64)) RETURNS CHAR(1) BEGIN DECLARE Result CHAR(1); SET Result = NULL; - IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN + IF ((SELECT COUNT(*) FROM `character_data` WHERE `name` = mob_name) > 0) THEN SET Result = 'C'; - ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN + ELSEIF ((SELECT COUNT(*) FROM `bot_data` WHERE `name` = mob_name) > 0) THEN SET Result = 'B'; END IF; RETURN Result; END$$ +-- (one code reference in /common/database.cpp) +CREATE FUNCTION `GetMobTypeById` (mob_id INTEGER UNSIGNED) RETURNS CHAR(1) +BEGIN + DECLARE Result CHAR(1); + + SET Result = NULL; + + IF ((select `id` from `character_data` where `id` = mob_id) > 0) THEN + SET Result = 'C'; + ELSEIF ((select `bot_id` from `bot_data` where `bot_id` = mob_id) > 0) THEN + SET Result = 'B'; + END IF; + + RETURN Result; +END$$ + +-- (for reference only) +-- CREATE FUNCTION `GetMobTypeByName` (mob_name VARCHAR(64)) RETURNS CHAR(1) +-- BEGIN +-- DECLARE Result CHAR(1); +-- +-- SET Result = NULL; +-- +-- IF (select `id` from `character_data` where `name` = mob_name) > 0 THEN +-- SET Result = 'C'; +-- ELSEIF (select `bot_id` from `bot_data` where `name` = mob_name) > 0 THEN +-- SET Result = 'B'; +-- END IF; +-- +-- RETURN Result; +-- END $$ + DELIMITER ; -CREATE VIEW `vwBotCharacterMobs` AS -SELECT _utf8'C' AS mobtype, + +-- Views +CREATE VIEW `vw_bot_character_mobs` AS +SELECT +_utf8'C' AS mob_type, c.`id`, c.`name`, c.`class`, @@ -223,39 +727,42 @@ c.`last_login`, c.`zone_id` FROM `character_data` AS c UNION ALL -SELECT _utf8'B' AS mobtype, -b.`BotID` AS id, -b.`Name` AS name, -b.`Class` AS class, -b.`BotLevel` AS level, -0 AS timelaston, -0 AS zoneid -FROM bots AS b; +SELECT _utf8'B' AS mob_type, +b.`bot_id` AS id, +b.`name`, +b.`class`, +b.`level`, +b.`last_spawn` AS last_login, +b.`zone_id` +FROM `bot_data` AS b; -CREATE VIEW `vwGroups` AS -SELECT g.`groupid` AS groupid, -GetMobType(g.`name`) AS mobtype, +CREATE VIEW `vw_bot_groups` AS +SELECT +g.`groups_index`, +g.`group_name`, +g.`group_leader_id`, +b.`name` AS group_leader_name, +b.`owner_id`, +c.`name` AS owner_name +FROM `bot_groups` AS g +JOIN `bot_data` AS b ON g.`group_leader_id` = b.`bot_id` +JOIN `character_data` AS c ON b.`owner_id` = c.`id` +ORDER BY b.`owner_id`, g.`group_name`; + +CREATE VIEW `vw_groups` AS +SELECT +g.`groupid` AS group_id, +GetMobType(g.`name`) AS mob_type, g.`name` AS name, -g.`charid` AS mobid, -IFNULL(c.`level`, b.`BotLevel`) AS level +g.`charid` AS mob_id, +IFNULL(c.`level`, b.`level`) AS level FROM `group_id` AS g LEFT JOIN `character_data` AS c ON g.`name` = c.`name` -LEFT JOIN `bots` AS b ON g.`name` = b.`Name`; +LEFT JOIN `bot_data` AS b ON g.`name` = b.`name`; -CREATE VIEW `vwBotGroups` AS -SELECT g.`BotGroupId`, -g.`BotGroupName`, -g.`BotGroupLeaderBotId`, -b.`Name` AS BotGroupLeaderName, -b.`BotOwnerCharacterId`, -c.`name` AS BotOwnerCharacterName -FROM `botgroup` AS g -JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID` -JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id` -ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`; - -CREATE VIEW `vwGuildMembers` AS -SELECT 'C' AS mobtype, +CREATE VIEW `vw_guild_members` AS +SELECT +'C' AS mob_type, cm.`char_id`, cm.`guild_id`, cm.`rank`, @@ -267,8 +774,9 @@ cm.`public_note`, cm.`alt` FROM `guild_members` AS cm UNION ALL -SELECT 'B' AS mobtype, -bm.`char_id`, +SELECT +'B' AS mob_type, +bm.`bot_id` AS char_id, bm.`guild_id`, bm.`rank`, bm.`tribute_enable`, @@ -277,4 +785,7 @@ bm.`last_tribute`, bm.`banker`, bm.`public_note`, bm.`alt` -FROM `botguildmembers` AS bm; +FROM `bot_guild_members` AS bm; + + +-- End of File diff --git a/zone/bot.cpp b/zone/bot.cpp index cbc951c34..d515303e7 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1260,7 +1260,7 @@ int32 Bot::GenerateBaseHitPoints() { } void Bot::LoadAAs() { - int maxAAExpansion = RuleI(Bots, BotAAExpansion); //get expansion to get AAs up to + int maxAAExpansion = RuleI(Bots, AAExpansion); //get expansion to get AAs up to aa_ranks.clear(); int id = 0; @@ -1535,7 +1535,7 @@ bool Bot::IsBotNameAvailable(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 vwBotCharacterMobs WHERE name LIKE '%s'", botName); + 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()); @@ -1548,78 +1548,248 @@ bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { return true; //We made it with a valid name! } -bool Bot::Save() { +bool Bot::Save() +{ if(this->GetBotID() == 0) { // New bot record - std::string query = StringFormat("INSERT INTO bots (BotOwnerCharacterID, BotSpellsID, Name, LastName, " - "BotLevel, Race, Class, Gender, Size, Face, LuclinHairStyle, " - "LuclinHairColor, LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, " - "LuclinBeard, DrakkinHeritage, DrakkinTattoo, DrakkinDetails, HP, Mana, " - "MR, CR, DR, FR, PR, Corrup, AC, STR, STA, DEX, AGI, _INT, WIS, CHA, ATK, " - "LastSpawnDate, TotalPlayTime, LastZoneId) " - "VALUES('%u', '%u', '%s', '%s', '%u', '%i', '%i', '%i', '%f', '%i', '%i', " - "'%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', " - "'%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', " - "'%i', NOW(), 0, %i)", - this->_botOwnerCharacterID, this->GetBotSpellID(), this->GetCleanName(), - this->lastname, this->GetLevel(), GetRace(), GetClass(), GetGender(), - GetSize(), this->GetLuclinFace(), this->GetHairStyle(), GetHairColor(), - this->GetEyeColor1(), this->GetEyeColor2(), this->GetBeardColor(), - this->GetBeard(), this->GetDrakkinHeritage(), this->GetDrakkinTattoo(), - this->GetDrakkinDetails(), GetHP(), GetMana(), GetMR(), GetCR(), GetDR(), - GetFR(), GetPR(), GetCorrup(), GetAC(), GetSTR(), GetSTA(), GetDEX(), - GetAGI(), GetINT(), GetWIS(), GetCHA(), GetATK(), _lastZoneId); - auto results = database.QueryDatabase(query); + std::string query = StringFormat( + "INSERT INTO `bot_data` (" + " `owner_id`," + " `spells_id`," + " `name`," + " `last_name`," + " `zone_id`," + " `gender`," + " `race`," + " `class`," + " `level`," + /*creation_day - not needed for bot creation*/ + " `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`" + ")" + " VALUES (" + "'%u'," /*owner_id*/ + " '%u'," /*spells_id*/ + " '%s'," /*name*/ + " '%s'," /*last_name*/ + " '%i'," /*zone_id*/ + " '%i'," /*gender*/ + " '%i'," /*race*/ + " '%i'," /*class*/ + " '%u'," /*level*/ + /*creation_day*/ + " NOW()," /*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*/ + ")", + 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() + ); + auto results = database.QueryDatabase(query); if(!results.Success()) { - auto botOwner = GetBotOwner(); + auto botOwner = GetBotOwner(); if (botOwner) - botOwner->Message(13, results.ErrorMessage().c_str()); - - return false; + botOwner->Message(13, results.ErrorMessage().c_str()); + + return false; } - - SetBotID(results.LastInsertedID()); - SaveBuffs(); + + SetBotID(results.LastInsertedID()); + SaveBuffs(); SavePet(); SaveStance(); SaveTimers(); - return true; + return true; } - - // Update existing bot record - std::string query = StringFormat("UPDATE bots SET BotOwnerCharacterID = '%u', BotSpellsID = '%u', " - "Name = '%s', LastName = '%s', BotLevel = '%u', Race = '%i', " - "Class = '%i', Gender = '%i', Size = '%f', Face = '%i', " - "LuclinHairStyle = '%i', LuclinHairColor = '%i', " - "LuclinEyeColor = '%i', LuclinEyeColor2 = '%i', " - "LuclinBeardColor = '%i', LuclinBeard = '%i', DrakkinHeritage = '%i', " - "DrakkinTattoo = '%i', DrakkinDetails = '%i', HP = '%i', Mana = '%i', " - "MR = '%i', CR = '%i', DR = '%i', FR = '%i', PR = '%i', " - "Corrup = '%i', AC = '%i', STR = '%i', STA = '%i', DEX = '%i', " - "AGI = '%i', _INT = '%i', WIS = '%i', CHA = '%i', ATK = '%i', " - "LastSpawnDate = NOW(), TotalPlayTime = '%u', LastZoneId = %i " - "WHERE BotID = '%u'", - _botOwnerCharacterID, this->GetBotSpellID(), this->GetCleanName(), - this->lastname, this->GetLevel(), _baseRace, this->GetClass(), - _baseGender, GetSize(), this->GetLuclinFace(), this->GetHairStyle(), - GetHairColor(), this->GetEyeColor1(), this->GetEyeColor2(), - this->GetBeardColor(), this->GetBeard(), this->GetDrakkinHeritage(), - GetDrakkinTattoo(), GetDrakkinDetails(), GetHP(), GetMana(), - _baseMR, _baseCR, _baseDR, _baseFR, _basePR, _baseCorrup, _baseAC, - _baseSTR, _baseSTA, _baseDEX, _baseAGI, _baseINT, _baseWIS, _baseCHA, - _baseATK, GetTotalPlayTime(), _lastZoneId, GetBotID()); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - auto botOwner = GetBotOwner(); - if (botOwner) - botOwner->Message(13, results.ErrorMessage().c_str()); - - return false; - } - SaveBuffs(); - SavePet(); - SaveStance(); - SaveTimers(); + + // 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'," + /*creation_day - check to see how client is handled*/ + " `last_spawn` = NOW()," + " `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'," + " WHERE `bot_id` = '%u'", + _botOwnerCharacterID, + this->GetBotSpellID(), + this->GetCleanName(), + this->lastname, + _lastZoneId, + _baseGender, + _baseRace, + this->GetClass(), + this->GetLevel(), + /*creation_day*/ + 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, + GetBotID() + ); + auto results = database.QueryDatabase(query); + if(!results.Success()) { + auto botOwner = GetBotOwner(); + if (botOwner) + botOwner->Message(13, results.ErrorMessage().c_str()); + + return false; + } + SaveBuffs(); + SavePet(); + SaveStance(); + SaveTimers(); return true; } @@ -1634,82 +1804,152 @@ uint32 Bot::GetTotalPlayTime() { return Result; } -void Bot::SaveBuffs() { - // Remove any existing buff saves - std::string query = StringFormat("DELETE FROM botbuffs WHERE BotId = %u", GetBotID()); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; - - 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 botbuffs (BotId, SpellId, CasterLevel, DurationFormula, " - "TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, " - "CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, " - "caston_x, Persistent, caston_y, caston_z, ExtraDIChance) " - "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %i, %u, " - "%i, %i, %i)", - 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, - buffs[buffIndex].caston_x, isPersistent, buffs[buffIndex].caston_y, - buffs[buffIndex].caston_z, buffs[buffIndex].ExtraDIChance); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; - } -} - -void Bot::LoadBuffs() { - std::string query = StringFormat("SELECT SpellId, CasterLevel, DurationFormula, TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, caston_x, Persistent, caston_y, caston_z, ExtraDIChance FROM botbuffs WHERE BotId = %u", GetBotID()); - auto results = database.QueryDatabase(query); +void Bot::SaveBuffs() +{ + // 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; - - 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]); - buffs[buffCount].ticsremaining = atoi(row[3]); - 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].caston_x = atoi(row[12]); - buffs[buffCount].casterid = 0; - buffs[buffCount].persistant_buff = atoi(row[13])? true: false; - buffs[buffCount].caston_y = atoi(row[14]); - buffs[buffCount].caston_z = atoi(row[15]); - buffs[buffCount].ExtraDIChance = atoi(row[16]); - buffCount++; - } - query = StringFormat("DELETE FROM botbuffs WHERE BotId = %u", GetBotID()); - results = database.QueryDatabase(query); + + 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; + } } -uint32 Bot::GetPetSaveId() { - std::string query = StringFormat("SELECT BotPetsId FROM botpets WHERE BotId = %u", GetBotID()); +void Bot::LoadBuffs() +{ + 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; + + 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]); + + 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); +} + +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; @@ -1745,11 +1985,12 @@ void Bot::LoadPet() { } } -void Bot::LoadPetStats(std::string* petName, uint32* petMana, uint32* petHitPoints, uint32* botPetId, uint32 botPetSaveId) { +void Bot::LoadPetStats(std::string* petName, uint32* petMana, uint32* petHitPoints, uint32* botPetId, uint32 botPetSaveId) +{ if(botPetSaveId == 0) return; - std::string query = StringFormat("SELECT PetId, Name, Mana, HitPoints FROM botpets WHERE BotPetsId = %u", botPetSaveId); + 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; @@ -1765,7 +2006,7 @@ void Bot::LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { if(!petBuffs || botPetSaveId == 0) return; - std::string query = StringFormat("SELECT SpellId, CasterLevel, Duration FROM botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); + 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; @@ -1780,7 +2021,7 @@ void Bot::LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { petBuffs[buffIndex].duration = atoi(row[2]); buffIndex++; } - query = StringFormat("DELETE FROM botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); + query = StringFormat("DELETE FROM `bot_pet_buffs` WHERE `pets_index` = %u;", botPetSaveId); results = database.QueryDatabase(query); } @@ -1788,7 +2029,7 @@ void Bot::LoadPetItems(uint32* petItems, uint32 botPetSaveId) { if(!petItems || botPetSaveId == 0) return; - std::string query = StringFormat("SELECT ItemId FROM botpetinventory WHERE BotPetsId = %u;", botPetSaveId); + 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; @@ -1801,7 +2042,7 @@ void Bot::LoadPetItems(uint32* petItems, uint32 botPetSaveId) { petItems[itemIndex] = atoi(row[0]); itemIndex++; } - query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u", botPetSaveId); + query = StringFormat("DELETE FROM `bot_pet_inventories` WHERE `pets_index` = %u", botPetSaveId); results = database.QueryDatabase(query); } @@ -1833,28 +2074,58 @@ void Bot::SavePet() { } } -uint32 Bot::SavePetStats(std::string petName, uint32 petMana, uint32 petHitPoints, uint32 botPetId) { - std::string query = StringFormat("REPLACE INTO botpets SET PetId = %u, BotId = %u, Name = '%s', Mana = %u, HitPoints = %u", botPetId, GetBotID(), petName.c_str(), petMana, petHitPoints); - auto results = database.QueryDatabase(query); +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 0; } -void Bot::SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { +void Bot::SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) +{ if(!petBuffs || botPetSaveId == 0) - return; - + return; + int buffIndex = 0; while(buffIndex < BUFF_COUNT) { - if(petBuffs[buffIndex].spellid > 0 && petBuffs[buffIndex].spellid != SPELL_UNKNOWN) { - - std::string query = StringFormat("INSERT INTO botpetbuffs (BotPetsId, SpellId, CasterLevel, 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++; - } - + 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) { @@ -1865,7 +2136,7 @@ void Bot::SavePetItems(uint32* petItems, uint32 botPetSaveId) { if(petItems[itemIndex] == 0) continue; - std::string query = StringFormat("INSERT INTO botpetinventory (BotPetsId, ItemId) VALUES(%u, %u)", botPetSaveId, petItems[itemIndex]); + 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; @@ -1876,7 +2147,7 @@ void Bot::DeletePetBuffs(uint32 botPetSaveId) { if(botPetSaveId == 0) return; - std::string query = StringFormat("DELETE FROM botpetbuffs WHERE BotPetsId = %u", botPetSaveId); + std::string query = StringFormat("DELETE FROM `bot_pet_buffs` WHERE `pets_index` = %u", botPetSaveId); auto results = database.QueryDatabase(query); } @@ -1884,7 +2155,7 @@ void Bot::DeletePetItems(uint32 botPetSaveId) { if(botPetSaveId == 0) return; - std::string query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u", botPetSaveId); + std::string query = StringFormat("DELETE FROM `bot_pet_inventories` WHERE `pets_index` = %u", botPetSaveId); auto results = database.QueryDatabase(query); } @@ -1892,12 +2163,13 @@ void Bot::DeletePetStats(uint32 botPetSaveId) { if(botPetSaveId == 0) return; - std::string query = StringFormat("DELETE from botpets where BotPetsId = %u", botPetSaveId); + 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 StanceID FROM botstances WHERE BotID = %u", GetBotID()); +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()"); @@ -1912,42 +2184,54 @@ void Bot::SaveStance() { if(_baseBotStance == _botStance) return; - std::string query = StringFormat("REPLACE INTO botstances (BotID, StanceId) VALUES(%u, %u)", GetBotID(), GetBotStance()); + 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.TimerID, 0) As TimerID, IfNull(bt.Value, 0) As Value, " - "IfNull(MAX(sn.recast_time), 0) AS MaxTimer FROM bottimers bt, spells_new sn " - "WHERE bt.BotID = %u AND sn.EndurTimerIndex = " - "(SELECT case WHEN TimerID > %i THEN TimerID - %i ELSE TimerID END AS TimerID " - "FROM bottimers WHERE TimerID = bt.TimerID AND BotID = bt.BotID ) " - "AND sn.classes%i <= %i", - GetBotID(), DisciplineReuseStart-1, DisciplineReuseStart-1, GetClass(), GetLevel()); - auto results = database.QueryDatabase(query); +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; } - - 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; - } - + + 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; + } } void Bot::SaveTimers() { bool hadError = false; - std::string query = StringFormat("DELETE FROM bottimers WHERE BotID = %u", GetBotID()); + std::string query = StringFormat("DELETE FROM `bot_timers` WHERE `bot_id` = %u", GetBotID()); auto results = database.QueryDatabase(query); if(!results.Success()) hadError = true; @@ -1956,7 +2240,7 @@ void Bot::SaveTimers() { if(timers[timerIndex] <= Timer::GetCurrentTime()) continue; - query = StringFormat("REPLACE INTO bottimers (BotID, TimerID, Value) VALUES(%u, %u, %u)", GetBotID(), timerIndex + 1, timers[timerIndex]); + 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; @@ -2975,28 +3259,28 @@ bool Bot::DeleteBot(std::string* errorMessage) { 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 botinventory WHERE botid = '%u'", this->GetBotID()); + 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 botbuffs WHERE botid = '%u'", this->GetBotID()); + 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 botstances WHERE BotID = '%u'", this->GetBotID()); + 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 bots WHERE BotID = '%u'", this->GetBotID()); + query = StringFormat("DELETE FROM `bot_data` WHERE `bot_id` = '%u'", this->GetBotID()); results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -3052,28 +3336,61 @@ 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) { +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 }; if (this->GetBotID() == 0 || slotID < EmuConstants::EQUIPMENT_BEGIN || itemID <= NO_ITEM) - return; + 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; - } - } + 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 botinventory (botid, slotid, itemid, charges, instnodrop, color, " - "augslot1, augslot2, augslot3, augslot4, augslot5) " - "VALUES(%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)", - (unsigned long)this->GetBotID(), (unsigned long)slotID, (unsigned long)itemID, - (unsigned long)inst->GetCharges(), (unsigned long)(inst->IsAttuned()? 1: 0), - (unsigned long)inst->GetColor(), (unsigned long)augslot[0], (unsigned long)augslot[1], - (unsigned long)augslot[2], (unsigned long)augslot[3], (unsigned long)augslot[4]); - auto results = database.QueryDatabase(query); - if(!results.Success()) - *errorMessage = std::string(results.ErrorMessage()); + std::string query = StringFormat( + "REPLACE INTO `bot_inventories` (" + "`bot_id`," + " `slot_id`," + " `item_id`," + " `inst_charges`," + " `inst_color`," + " `inst_no_drop`," + " `augment_1`," + " `augment_2`," + " `augment_3`," + " `augment_4`," + " `augment_5`" + ")" + " VALUES (" + "%lu," /*bot_id*/ + " %lu," /*slot_id*/ + " %lu," /*item_id*/ + " %lu," /*inst_charges*/ + " %lu," /*inst_color*/ + " %lu," /*inst_no_drop*/ + " %lu," /*augment_1*/ + " %lu," /*augment_2*/ + " %lu," /*augment_3*/ + " %lu," /*augment_4*/ + " %lu" /*augment_5*/ + ")", + (unsigned long)this->GetBotID(), + (unsigned long)slotID, + (unsigned long)itemID, + (unsigned long)inst->GetCharges(), + (unsigned long)inst->GetColor(), + (unsigned long)(inst->IsAttuned()? 1: 0), // does this match the current flag implementation? + (unsigned long)augslot[0], + (unsigned long)augslot[1], + (unsigned long)augslot[2], + (unsigned long)augslot[3], + (unsigned long)augslot[4] + ); + 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. @@ -3081,7 +3398,7 @@ void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) { if(this->GetBotID() == 0) return; - std::string query = StringFormat("DELETE FROM botinventory WHERE botid = %i AND slotid = %i", this->GetBotID(), slotID); + 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()); @@ -3091,61 +3408,75 @@ void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) { } // Retrieves all the inventory records from the database for this bot. -void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { +void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) +{ if(this->GetBotID() == 0) - return; + return; - std::string query = StringFormat("SELECT slotid, itemid, charges, color, " - "augslot1, augslot2, augslot3, augslot4, " - "augslot5, instnodrop FROM botinventory " - "WHERE botid = %i ORDER BY slotid", this->GetBotID()); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - 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 color = atoul(row[3]); - uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; - 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; - ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]); - if (!inst) { - Log.Out(Logs::General, Logs::Error, "Warning: botid %i has an invalid item_id %i in inventory slot %i", this->GetBotID(), item_id, slot_id); - continue; - } - - int16 put_slot_id = INVALID_INDEX; - - if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == 9999) && inst->GetItem()->Attuneable)) - inst->SetAttuned(true); - - if (color > 0) - inst->SetColor(color); - - if (charges == 255) - inst->SetCharges(-1); - else - inst->SetCharges(charges); - - if (slot_id < 8000 || slot_id > 8999) - put_slot_id = inv.PutItem(slot_id, *inst); - - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) - Log.Out(Logs::General, Logs::Error, "Warning: Invalid slot_id for item in inventory: botid=%i, item_id=%i, slot_id=%i",this->GetBotID(), item_id, slot_id); - } + std::string query = StringFormat( + "SELECT" + " `slot_id`," + " `item_id`," + " `inst_charges`," + " `inst_color`," + " `augment_1`," + " `augment_2`," + " `augslot_3`," + " `augslot_4`, " + " `augslot_5`," + " `inst_no_drop`" + " 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()); + 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 color = atoul(row[3]); + uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; + 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; + ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]); + 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; + } + + int16 put_slot_id = INVALID_INDEX; + + if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == 9999) && inst->GetItem()->Attuneable)) + inst->SetAttuned(true); + + if (color > 0) + inst->SetColor(color); + + if (charges == 255) + inst->SetCharges(-1); + else + inst->SetCharges(charges); + + if (slot_id < 8000 || slot_id > 8999) + put_slot_id = inv.PutItem(slot_id, *inst); + + safe_delete(inst); + + // Save ptr to item in inventory + 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(); } @@ -3154,7 +3485,7 @@ uint32 Bot::GetBotItemBySlot(uint32 slotID) { if(this->GetBotID() == 0 || slotID < EmuConstants::EQUIPMENT_BEGIN) return 0; - std::string query = StringFormat("SELECT itemid FROM botinventory WHERE botid = %i AND slotid = %i", GetBotID(), slotID); + 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; @@ -3168,7 +3499,7 @@ uint32 Bot::GetBotItemsCount(std::string *errorMessage) { if(this->GetBotID() == 0) return 0; - std::string query = StringFormat("SELECT COUNT(*) FROM botinventory WHERE botid = %i", this->GetBotID()); + 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()); @@ -3302,7 +3633,7 @@ uint32 Bot::GetBotIDByBotName(std::string botName) { if(botName.empty()) return 0; - std::string query = StringFormat("SELECT BotID FROM bots WHERE Name = '%s'", botName.c_str()); + 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; @@ -3311,58 +3642,134 @@ uint32 Bot::GetBotIDByBotName(std::string botName) { return atoi(row[0]); } -Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) { +Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) +{ Bot* loadedBot = nullptr; if(botID == 0) - return nullptr; + return nullptr; + + std::string query = StringFormat( + "SELECT" + " `owner_id`," + " `spells_id`," + " `name`," + " `last_name`," + " `level`," + " `race`," + " `class`," + " `gender`," + " `size`," + " `face`," + " `hair_style`," + " `hair_color`," + " `eye_color_1`," + " `eye_color_2`," + " `beard_color`," + " `beard`," + " `drakkin_heritage`," + " `drakkin_tattoo`," + " `drakkin_details`," + " `hp`," + " `mana`," + " `magic`," + " `cold`," + " `disease`," + " `fire`," + " `poison`," + " `corruption`," + " `ac`," + " `str`," + " `sta`," + " `dex`," + " `agi`," + " `int`," + " `wis`," + " `cha`," + " `atk`," + " `creation_day`," + " `last_spawn`," + " `time_spawned`," + " `zone_id`" + " FROM `bot_data`" + " WHERE `bot_id` = '%u'", + botID + ); + auto results = database.QueryDatabase(query); + if(!results.Success()) { + *errorMessage = std::string(results.ErrorMessage()); + return nullptr; + } - std::string query = StringFormat("SELECT BotOwnerCharacterID, BotSpellsID, Name, LastName, BotLevel, " - "Race, Class, Gender, Size, Face, LuclinHairStyle, LuclinHairColor, " - "LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, LuclinBeard, " - "DrakkinHeritage, DrakkinTattoo, DrakkinDetails, HP, Mana, MR, CR, " - "DR, FR, PR, Corrup, AC, STR, STA, DEX, AGI, _INT, WIS, CHA, ATK, " - "BotCreateDate, LastSpawnDate, TotalPlayTime, LastZoneId " - "FROM bots WHERE BotID = '%u'", botID); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return nullptr; - } - - if (results.RowCount() == 0) - return nullptr; - - auto row = results.begin(); - NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7])); - NPCType tempNPCStruct = FillNPCTypeStruct(atoi(row[1]), std::string(row[2]), std::string(row[3]), atoi(row[4]), - atoi(row[5]), atoi(row[6]), atoi(row[7]), atof(row[8]), atoi(row[9]), - atoi(row[10]), atoi(row[11]), atoi(row[12]), atoi(row[13]), atoi(row[14]), - atoi(row[15]), atoi(row[16]), atoi(row[17]), atoi(row[18]), atoi(row[19]), - atoi(row[20]), 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); - loadedBot = new Bot(botID, atoi(row[0]), atoi(row[1]), atof(row[38]), atoi(row[39]), tempNPCStruct); + if (results.RowCount() == 0) + return nullptr; + + auto row = results.begin(); + NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7])); + NPCType tempNPCStruct = FillNPCTypeStruct( + atoi(row[1]), + std::string(row[2]), + std::string(row[3]), + atoi(row[4]), + atoi(row[5]), + atoi(row[6]), + atoi(row[7]), + atof(row[8]), + atoi(row[9]), + atoi(row[10]), + atoi(row[11]), + atoi(row[12]), + atoi(row[13]), + atoi(row[14]), + atoi(row[15]), + atoi(row[16]), + atoi(row[17]), + atoi(row[18]), + atoi(row[19]), + atoi(row[20]), + 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 + ); + loadedBot = new Bot(botID, atoi(row[0]), atoi(row[1]), atof(row[38]), atoi(row[39]), tempNPCStruct); return loadedBot; } -std::list Bot::GetGroupedBotsByGroupId(uint32 groupId, std::string* errorMessage) { +std::list Bot::GetGroupedBotsByGroupId(uint32 groupId, std::string* errorMessage) +{ std::list groupedBots; if(groupId == 0) - return groupedBots; - - std::string query = StringFormat("SELECT g.mobid AS BotID FROM vwGroups AS g JOIN bots AS b ON g.mobid = b.BotId AND g.mobtype = 'B' WHERE g.groupid = %u", groupId); - auto results = database.QueryDatabase(query); + 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])); - + for (auto row = results.begin(); row != results.end(); ++row) + groupedBots.push_back(atoi(row[0])); + return groupedBots; } @@ -3421,7 +3828,7 @@ std::list Bot::GetBotList(uint32 botOwnerCharacterID, std::st if(botOwnerCharacterID == 0) return ownersBots; - std::string query = StringFormat("SELECT BotID, Name, Class, BotLevel, Race FROM bots WHERE BotOwnerCharacterID = '%u'", botOwnerCharacterID); + std::string query = StringFormat("SELECT `bot_id`, `name`, `class`, `level`, `race` FROM `bot_data` WHERE `owner_id` = '%u'", botOwnerCharacterID); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -3442,9 +3849,10 @@ std::list Bot::GetBotList(uint32 botOwnerCharacterID, std::st std::list Bot::ListSpawnedBots(uint32 characterID, std::string* errorMessage) { std::list spawnedBots; - if(characterID == 0) - return 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()) { @@ -3473,7 +3881,7 @@ void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* e uint32 botGroupId = 0; uint32 botGroupLeaderBotId = tempGroupLeader->CastToBot()->GetBotID(); - std::string query = StringFormat("INSERT INTO botgroup (BotGroupLeaderBotId, BotGroupName) VALUES (%u, '%s')", botGroupLeaderBotId, botGroupName.c_str()); + 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()); @@ -3489,7 +3897,7 @@ void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* e continue; uint32 botGroupMemberBotId = tempBot->CastToBot()->GetBotID(); - query = StringFormat("INSERT INTO botgroupmembers (BotGroupId, BotId) VALUES (%u, %u)", botGroupId, botGroupMemberBotId); + 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()); @@ -3505,14 +3913,14 @@ void Bot::DeleteBotGroup(std::string botGroupName, std::string* errorMessage) { if(!errorMessage->empty() || botGroupId== 0) return; - std::string query = StringFormat("DELETE FROM botgroupmembers WHERE BotGroupId = %u", botGroupId); + 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 botgroup WHERE BotGroupId = %u", botGroupId); + query = StringFormat("DELETE FROM `bot_groups` WHERE `groups_index` = %u", botGroupId); results = database.QueryDatabase(query); if(!results.Success()) *errorMessage = std::string(results.ErrorMessage()); @@ -3527,7 +3935,7 @@ std::list Bot::LoadBotGroup(std::string botGroupName, std::string* err if(botGroupId == 0) return botGroup; - std::string query = StringFormat("SELECT BotId FROM botgroupmembers WHERE BotGroupId = %u", botGroupId); + 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()); @@ -3548,7 +3956,7 @@ std::list Bot::GetBotGroupListByBotOwnerCharacterId(uint32 botOwne if(botOwnerCharacterId == 0) return botGroups; - std::string query = StringFormat("SELECT BotGroupName, BotGroupLeaderName FROM vwBotGroups WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); + 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()); @@ -3568,7 +3976,7 @@ bool Bot::DoesBotGroupNameExist(std::string botGroupName) { if(botGroupName.empty()) return false; - std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups WHERE BotGroupName = '%s'", botGroupName.c_str()); + 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; @@ -3587,7 +3995,7 @@ uint32 Bot::CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName if(botOwnerCharacterId == 0 || botGroupName.empty()) return 0; - std::string query = StringFormat("SELECT BotGroupId, BotGroupName FROM vwBotGroups WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); + 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()); @@ -3611,7 +4019,7 @@ uint32 Bot::GetBotGroupIdByBotGroupName(std::string botGroupName, std::string* e if(botGroupName.empty()) return 0; - std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups WHERE BotGroupName = '%s'", botGroupName.c_str()); + 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()); @@ -3629,7 +4037,7 @@ uint32 Bot::GetBotGroupLeaderIdByBotGroupName(std::string botGroupName) { if(botGroupName.empty()) return 0; - std::string query = StringFormat("SELECT BotGroupLeaderBotId FROM vwBotGroups WHERE BotGroupName = '%s'", botGroupName.c_str()); + 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; @@ -3669,7 +4077,7 @@ uint32 Bot::CreatedBotCount(uint32 botOwnerCharacterID, std::string* errorMessag if(botOwnerCharacterID == 0) return 0; - std::string query = StringFormat("SELECT COUNT(BotID) FROM bots WHERE BotOwnerCharacterID=%i", botOwnerCharacterID); + 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()); @@ -3688,7 +4096,7 @@ uint32 Bot::GetBotOwnerCharacterID(uint32 botID, std::string* errorMessage) { if(botID == 0) return 0; - std::string query = StringFormat("SELECT BotOwnerCharacterID FROM bots WHERE BotID = %u", botID); + 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()); @@ -6415,28 +6823,40 @@ void Bot::SetBotGuildMembership(uint32 botId, uint32 guildid, uint8 rank) { return; if(guildid > 0) { - std::string query = StringFormat("REPLACE INTO botguildmembers SET char_id = %u, guild_id = %u, rank = %u", botId, guildid, rank); + 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 botguildmembers WHERE char_id = %u", botId); + 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) { +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 vwGuildMembers AS gm JOIN guilds AS g ON gm.guild_id = g.id WHERE gm.char_id = %u AND gm.mobtype = '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]); + 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() { @@ -7189,7 +7609,7 @@ bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, uint16 slot bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { if(spellTarget) { - if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, BotGroupBuffing)) { + if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, GroupBuffing)) { bool noGroupSpell = false; uint16 thespell = spell_id; for(int i = 0; i < AIspells.size(); i++) { @@ -7725,7 +8145,7 @@ int32 Bot::CalcManaRegen() { regen += aabonuses.ManaRegen; regen = ((regen * RuleI(Character, ManaRegenMultiplier)) / 100); - float mana_regen_rate = RuleR(Bots, BotManaRegen); + float mana_regen_rate = RuleR(Bots, ManaRegen); if(mana_regen_rate < 0.0f) mana_regen_rate = 0.0f; @@ -8847,7 +9267,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { std::string query; if (setslot == -1) { int slots[] = { 2, 7, 9, 12, 17, 18, 19 }; - query = StringFormat("UPDATE botinventory SET color = %u WHERE slotID IN (2, 7, 9, 12, 17, 18, 19) AND botID = %u", setcolor, botid); + query = StringFormat("UPDATE `bot_inventories` SET `inst_color` = %u WHERE `slot_id` IN (2, 7, 9, 12, 17, 18, 19) AND `bot_id` = %u", setcolor, botid); auto results = database.QueryDatabase(query); if (!results.Success()) return; @@ -8857,7 +9277,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); } } else { - query = StringFormat("UPDATE botinventory SET color = %u WHERE slotID = %i AND botID = %u", setcolor, setslot, botid); + 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; @@ -8934,7 +9354,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - uint32 MaxBotCreate = RuleI(Bots, CreateBotCount); + uint32 MaxBotCreate = RuleI(Bots, CreationLimit); if(CreatedBotCount(c->CharacterID(), &TempErrorMessage) >= MaxBotCreate) { c->Message(0, "You cannot create more than %i bots.", MaxBotCreate); return; @@ -9135,7 +9555,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - if(RuleB(Bots, BotQuest) && !c->GetGM()) { + 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()); @@ -9154,7 +9574,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } - if(spawnedBotCount >= RuleI(Bots, SpawnBotCount) && !c->GetGM()) { + if(spawnedBotCount >= RuleI(Bots, SpawnLimit) && !c->GetGM()) { c->Message(0, "You cannot spawn more than %i bots.", spawnedBotCount); return; } @@ -11206,7 +11626,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - if(RuleB(Bots, BotQuest)) { + if(RuleB(Bots, QuestableSpawnLimit)) { const int allowedBotsBQ = AllowedBotSpawns(c->CharacterID(), &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -11224,7 +11644,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } - const int allowedBotsSBC = RuleI(Bots, SpawnBotCount); + 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; @@ -12651,7 +13071,7 @@ uint32 Bot::GetEquipmentColor(uint8 material_slot) const { if (slotid == INVALID_INDEX) return 0; - std::string query = StringFormat("SELECT color FROM botinventory WHERE BotID = %u AND SlotID = %u", botid, slotid); + 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; diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index cd8d28275..66afc345d 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -883,7 +883,7 @@ bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain int32 hasMana = GetMana(); // Allow bots to cast buff spells even if they are out of mana - if(RuleB(Bots, BotFinishBuffing)) { + if(RuleB(Bots, FinishBuffing)) { if(manaCost > hasMana) { // Let's have the bots complete the buff time process if(AIspells[i].type & SpellType_Buff) { diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index a15724325..fd157f372 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2041,23 +2041,23 @@ void QuestManager::popup(const char *title, const char *text, uint32 popupid, ui #ifdef BOTS int QuestManager::createbotcount() { - return RuleI(Bots, CreateBotCount); + return RuleI(Bots, CreationLimit); } int QuestManager::spawnbotcount() { - return RuleI(Bots, SpawnBotCount); + return RuleI(Bots, SpawnLimit); } bool QuestManager::botquest() { - return RuleB(Bots, BotQuest); + return RuleB(Bots, QuestableSpawnLimit); } 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, CreateBotCount); + uint32 MaxBotCreate = RuleI(Bots, CreationLimit); if (initiator && initiator->IsClient()) { From 261b6a4623a4621ffedfaa26d99a3115df22cc86 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 10 Oct 2015 15:16:49 -0400 Subject: [PATCH 350/846] Invisible/Hide mechanics when cast on Updated mechanics to be consistent with live regarding how invisible breaks when the client is the target of a spell. Invisible will drop whenever a client is hit with a detrimental spell, regardless of if resisted, if it does damage or AOE. Hide skill now also follows the same rules as above. Implemented support for Rogue AA - Nerves of Steel which gives a chance for hide NOT to break when client is hit with an AOE spell. --- changelog.txt | 7 +++++ common/spdat.h | 2 +- zone/attack.cpp | 6 ++-- zone/bonuses.cpp | 10 +++++++ zone/client.h | 1 + zone/common.h | 1 + zone/mob.h | 3 +- zone/special_attacks.cpp | 6 ++-- zone/spell_effects.cpp | 64 ++++++++++++++++++++++++++++++++++++++++ zone/spells.cpp | 8 +++++ zone/string_ids.h | 2 ++ 11 files changed, 102 insertions(+), 8 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0fd73aeba..e5f887e2d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/10/2015 == +Kayen: Updated mechanics to be consistent with live regarding how invisible breaks when the client is the target of a spell. +Invisible will drop whenever a client is hit with a detrimental spell, regardless of if resisted, if it does damage or AOE. +Hide skill now also follows the same rules as above. +Implemented support for Rogue AA - Nerves of Steel which gives a chance for hide NOT to break +when client is hit with an AOE spell. + == 09/25/2015 == Uleat: Implemented 'Inventory Snapshot' feature to track online player inventories at timed intervals. rules: diff --git a/common/spdat.h b/common/spdat.h index 41fd35f1f..6ea3033b0 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -478,7 +478,7 @@ typedef enum { #define SE_GateToHomeCity 322 // implemented #define SE_DefensiveProc 323 // implemented #define SE_HPToMana 324 // implemented -//#define SE_NoBreakAESneak 325 // *not implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell. +#define SE_NoBreakAESneak 325 // implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell. #define SE_SpellSlotIncrease 326 // *not implemented as bonus - increases your spell slot availability #define SE_MysticalAttune 327 // implemented - increases amount of buffs that a player can have #define SE_DelayDeath 328 // implemented - increases how far you can fall below 0 hp before you die diff --git a/zone/attack.cpp b/zone/attack.cpp index 2f94716bf..2752752aa 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1382,7 +1382,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0) TrySkillProc(other, skillinuse, 0, true, Hand); - CommonBreakInvisible(); + CommonBreakInvisibleFromCombat(); if(GetTarget()) TriggerDefensiveProcs(weapon, other, Hand, damage); @@ -1940,7 +1940,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool MeleeLifeTap(damage); - CommonBreakInvisible(); + CommonBreakInvisibleFromCombat(); //I doubt this works... if (!GetTarget()) @@ -4487,7 +4487,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes s CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); } -void Mob::CommonBreakInvisible() +void Mob::CommonBreakInvisibleFromCombat() { //break invis when you attack if(invisible) { diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index ab7d8bfee..8038e4a24 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1452,6 +1452,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->TradeSkillMastery = base1; break; + case SE_NoBreakAESneak: + if (newbon->NoBreakAESneak < base1) + newbon->NoBreakAESneak = base1; + break; + // to do case SE_PetDiscipline: break; @@ -3188,6 +3193,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->RaiseSkillCap[base2] = effect_value; break; } + + case SE_NoBreakAESneak: + if (new_bonus->NoBreakAESneak < effect_value) + new_bonus->NoBreakAESneak = effect_value; + break; //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/client.h b/zone/client.h index 885eb1407..f7527319c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -878,6 +878,7 @@ public: void SetFilter(eqFilterType filter_id, eqFilterMode value) { ClientFilters[filter_id]=value; } void BreakInvis(); + void BreakSneakWhenCastOn(Mob* caster, bool IsResisted); void LeaveGroup(); bool Hungry() const {if (GetGM()) return false; return m_pp.hunger_level <= 3000;} diff --git a/zone/common.h b/zone/common.h index 88aa58264..68accf746 100644 --- a/zone/common.h +++ b/zone/common.h @@ -471,6 +471,7 @@ struct StatBonuses { uint16 ReduceFallDamage; // reduce fall damage by percent int32 ReduceTradeskillFail[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 }; typedef struct diff --git a/zone/mob.h b/zone/mob.h index e48eda680..cb5948241 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -164,7 +164,8 @@ public: virtual inline bool IsBerserk() { return false; } // only clients void RogueEvade(Mob *other); void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse); - void CommonBreakInvisible(); + void BreakInvisibleSpells(); + void CommonBreakInvisibleFromCombat(); bool HasDied(); virtual bool CheckDualWield(); void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 1a134d167..c43c8f432 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -805,7 +805,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { } CheckIncreaseSkill(SkillArchery, GetTarget(), -15); - CommonBreakInvisible(); + CommonBreakInvisibleFromCombat(); } void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, @@ -1237,7 +1237,7 @@ void NPC::RangedAttack(Mob* other) DoRangedAttackDmg(other); - CommonBreakInvisible(); + CommonBreakInvisibleFromCombat(); } } @@ -1433,7 +1433,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 //consume ammo DeleteItemInInventory(ammo_slot, 1, true); CheckIncreaseSkill(SkillThrowing, GetTarget()); - CommonBreakInvisible(); + 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) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 8d3b252ad..a57be6351 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6707,3 +6707,67 @@ void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster) SetSpellPowerDistanceMod(static_cast(mod)); } } + +void Mob::BreakInvisibleSpells() +{ + 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; + } +} + +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; + target = caster->GetTarget(); + if (target && target == this){ + IsCastersTarget = true; + } + } + + if (!IsCastersTarget){ + + int chance = spellbonuses.NoBreakAESneak + itembonuses.NoBreakAESneak + aabonuses.NoBreakAESneak; + + if (IsResisted) + chance *= 2; + + 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; + 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, 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); + } + } +} \ No newline at end of file diff --git a/zone/spells.cpp b/zone/spells.cpp index 999ab684d..f5a0ffd0d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3679,6 +3679,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r // not all unresistable, so changing this to only check certain spells if(IsResistableSpell(spell_id)) { + spelltar->BreakInvisibleSpells(); //Any detrimental spell cast on you will drop invisible (can be AOE, non damage ect). + if (IsCharmSpell(spell_id) || IsMezSpell(spell_id) || IsFearSpell(spell_id)) spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resisttype, spell_id, this, use_resist_adjust, resist_adjust, true, false, false, level_override); else @@ -3712,6 +3714,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r } } + if (spelltar->IsClient()) + spelltar->CastToClient()->BreakSneakWhenCastOn(this, true); + spelltar->CheckNumHitsRemaining(NumHit::IncomingSpells); CheckNumHitsRemaining(NumHit::OutgoingSpells); @@ -3719,6 +3724,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r return false; } } + if (spelltar->IsClient()){ + spelltar->CastToClient()->BreakSneakWhenCastOn(this, false); + } } else { diff --git a/zone/string_ids.h b/zone/string_ids.h index 19d7436d0..44d5924be 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -384,6 +384,8 @@ #define TARGET_PLAYER_FOR_GUILD_STATUS 12260 #define GROUP_INVITEE_NOT_FOUND 12268 //You must target a player or use /invite to invite someone to your group. #define GROUP_INVITEE_SELF 12270 //12270 You cannot invite yourself. +#define NO_LONGER_HIDDEN 12337 //You are no longer hidden. +#define STOP_SNEAKING 12338 //You stop sneaking #define NOT_IN_CONTROL 12368 //You do not have control of yourself right now. #define ALREADY_CASTING 12442 //You are already casting a spell! #define SHIMMERS_BRIEFLY 12444 //Your %1 shimmers briefly. From e1a5853389e758c5bfdaafb8eb1c51341ec45293 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 10 Oct 2015 19:27:39 -0400 Subject: [PATCH 351/846] Updated bots load/drop scripts (thanks Shendare!) --- .../drop_bots (pre-update script).sql | 5 +- utils/sql/git/bots/drop_bots.sql | 5 +- .../sql/git/bots/required/2015_09_30_bots.sql | 69 ++++++++----------- 3 files changed, 32 insertions(+), 47 deletions(-) diff --git a/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql b/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql index 9699c157a..b55ce120b 100644 --- a/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql +++ b/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql @@ -41,7 +41,6 @@ DELIMITER $$ CREATE PROCEDURE `DropBotsSchema` () BEGIN - SELECT "deleting rules..."; DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots%'; @@ -52,24 +51,22 @@ BEGIN SELECT "restoring keys..."; IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN - -- IF ((SHOW KEYS IN `group_id` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN ALTER TABLE `group_id` DROP PRIMARY KEY; END IF; ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`); IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN - -- IF ((SHOW KEYS IN `guild_members` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN ALTER TABLE `guild_members` DROP PRIMARY KEY; END IF; ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`); + SELECT "de-activating spawns..."; UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298); SELECT "clearing database version..."; IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'db_version' AND `COLUMN_NAME` = 'bots_version') > 0) THEN - -- IF ((SHOW COLUMNS FROM `db_version` LIKE 'bots_version') != '') THEN UPDATE `db_version` SET `bots_version` = 0; END IF; diff --git a/utils/sql/git/bots/drop_bots.sql b/utils/sql/git/bots/drop_bots.sql index 5645a38b5..76c91fc47 100644 --- a/utils/sql/git/bots/drop_bots.sql +++ b/utils/sql/git/bots/drop_bots.sql @@ -53,7 +53,6 @@ DELIMITER $$ CREATE PROCEDURE `DropBotsSchema` () BEGIN - SELECT "deleting rules..."; DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots%'; @@ -64,24 +63,22 @@ BEGIN SELECT "restoring keys..."; IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN - -- IF ((SHOW KEYS IN `group_id` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN ALTER TABLE `group_id` DROP PRIMARY KEY; END IF; ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`); IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN - -- IF ((SHOW KEYS IN `guild_members` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN ALTER TABLE `guild_members` DROP PRIMARY KEY; END IF; ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`); + SELECT "de-activating spawns..."; UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298); SELECT "clearing database version..."; IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'db_version' AND `COLUMN_NAME` = 'bots_version') > 0) THEN - -- IF ((SHOW COLUMNS FROM `db_version` LIKE 'bots_version') != '') THEN UPDATE `db_version` SET `bots_version` = 0; END IF; diff --git a/utils/sql/git/bots/required/2015_09_30_bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql index 5551b8a30..88a1789d6 100644 --- a/utils/sql/git/bots/required/2015_09_30_bots.sql +++ b/utils/sql/git/bots/required/2015_09_30_bots.sql @@ -32,19 +32,15 @@ BEGIN -- Alter IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN - -- IF ((SHOW KEYS IN `guild_members` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN ALTER TABLE `guild_members` DROP PRIMARY KEY; END IF; IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN - -- IF ((SHOW KEYS IN `group_id` WHERE `Key_name` LIKE 'PRIMARY') != '') THEN ALTER TABLE `group_id` DROP PRIMARY KEY; END IF; ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); -- -- From original bots.sql (for reference) - -- ALTER TABLE `group_id` DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`); - -- ALTER TABLE `guild_members` DROP PRIMARY KEY; -- ALTER TABLE `group_id` ADD UNIQUE INDEX `U_group_id_1`(`name`); -- ALTER TABLE `group_leaders` ADD UNIQUE INDEX `U_group_leaders_1`(`leadername`); @@ -169,7 +165,6 @@ BEGIN INDEX `bot_id` (`bot_id`) ) ENGINE=InnoDB; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'bots') > 0) THEN - -- IF ((SHOW TABLES LIKE 'bots') != '') THEN INSERT INTO `bot_data` ( `bot_id`, `owner_id`, @@ -276,7 +271,6 @@ BEGIN CONSTRAINT `FK_bot_stances_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ); IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botstances') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botstances') != '') THEN INSERT INTO `bot_stances` ( `bot_id`, `stance_id` @@ -297,7 +291,6 @@ BEGIN CONSTRAINT `FK_bot_timers_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ); IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'bottimers') > 0) THEN - -- IF ((SHOW TABLES LIKE 'bottimers') != '') THEN INSERT INTO `bot_timers` ( `bot_id`, `timer_id`, @@ -338,7 +331,6 @@ BEGIN CONSTRAINT `FK_bot_buffs_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botbuffs') != '') THEN INSERT INTO `bot_buffs` ( `buffs_index`, `bot_id`, @@ -373,38 +365,43 @@ BEGIN FROM `botbuffs`; IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'dot_rune') > 0) THEN - -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'dot_rune') != '') THEN - UPDATE `bot_buffs` - SET `dot_rune` = `botbuffs`.`dot_rune` - WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + 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`; END IF; IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_x') > 0) THEN - -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'caston_x') != '') THEN - UPDATE `bot_buffs` - SET `caston_x` = `botbuffs`.`caston_x` - WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + 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`; END IF; IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_y') > 0) THEN - -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'caston_y') != '') THEN - UPDATE `bot_buffs` - SET `caston_y` = `botbuffs`.`caston_y` - WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + 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`; END IF; IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_z') > 0) THEN - -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'caston_z') != '') THEN - UPDATE `bot_buffs` - SET `caston_z` = `botbuffs`.`caston_z` - WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + 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`; END IF; IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'ExtraDIChance') > 0) THEN - -- IF ((SHOW COLUMNS FROM `botbuffs` LIKE 'ExtraDIChance') != '') THEN - UPDATE `bot_buffs` - SET `extra_di_chance` = `botbuffs`.`ExtraDIChance` - WHERE `buffs_index` = `botbuffs`.`BotBuffId` AND `bot_id` = `botbuffs`.`BotID`; + 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`; END IF; RENAME TABLE `botbuffs` TO `botbuffs_old`; @@ -433,7 +430,6 @@ BEGIN CONSTRAINT `FK_bot_inventories_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ) ENGINE=InnoDB; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botinventory') != '') THEN INSERT INTO `bot_inventories` ( `inventories_index`, `bot_id`, @@ -464,10 +460,11 @@ BEGIN FROM `botinventory`; IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory' AND `COLUMN_NAME` = 'augslot6') > 0) THEN - -- IF ((SHOW COLUMNS FROM `botinventory` LIKE 'augslot6') != '') THEN - UPDATE `bot_inventories` - SET `augment_6` = `botinventory`.`augslot6` - WHERE `inventories_index` = `botinventory`.`BotInventoryID` AND `bot_id` = `botinventory`.`BotID`; + 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`; END IF; RENAME TABLE `botinventory` TO `botinventory_old`; @@ -486,7 +483,6 @@ BEGIN CONSTRAINT `U_bot_pets_1` UNIQUE (`bot_id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpets') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botpets') != '') THEN INSERT INTO `bot_pets` ( `pets_index`, `pet_id`, @@ -518,7 +514,6 @@ BEGIN CONSTRAINT `FK_bot_pet_buffs_1` FOREIGN KEY (`pets_index`) REFERENCES `bot_pets` (`pets_index`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpetbuffs') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botpetbuffs') != '') THEN INSERT INTO `bot_pet_buffs` ( `pet_buffs_index`, `pets_index`, @@ -546,7 +541,6 @@ BEGIN CONSTRAINT `FK_bot_pet_inventories_1` FOREIGN KEY (`pets_index`) REFERENCES `bot_pets` (`pets_index`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpetinventory') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botpetinventory') != '') THEN INSERT INTO `bot_pet_inventories` ( `pet_inventories_index`, `pets_index`, @@ -570,7 +564,6 @@ BEGIN CONSTRAINT `FK_bot_groups_1` FOREIGN KEY (`group_leader_id`) REFERENCES `bot_data` (`bot_id`) ) ENGINE=InnoDB; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botgroup') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botgroup') != '') THEN INSERT INTO `bot_groups` ( `groups_index`, `group_leader_id`, @@ -596,7 +589,6 @@ BEGIN CONSTRAINT `FK_bot_group_members_2` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ) ENGINE=InnoDB; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botgroupmembers') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botgroupmembers') != '') THEN INSERT INTO `bot_group_members` ( `group_members_index`, `groups_index`, @@ -624,7 +616,6 @@ BEGIN PRIMARY KEY (`bot_id`) ) ENGINE=InnoDB; IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botguildmembers') > 0) THEN - -- IF ((SHOW TABLES LIKE 'botguildmembers') != '') THEN INSERT INTO `bot_guild_members` ( `bot_id`, `guild_id`, From f19648f615fd3c7214aabf04eebb52c418f72bd8 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 10 Oct 2015 22:06:54 -0700 Subject: [PATCH 352/846] Will prefer libmysql(dynamic) over mysqlclient(static) library for linking. Update travis.yml for new travis-ci container types. --- .travis.yml | 14 ++++++++++---- cmake/FindMySQL.cmake | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 71606e74c..74e5701ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,17 @@ language: cpp compiler: gcc -before_install: - - sudo apt-get update -qq - - sudo apt-get install -y libmysqlclient-dev libperl-dev libboost-dev liblua5.1-0-dev zlib1g-dev +sudo: false +addons: + apt: + packages: + - libmysqlclient-dev + - libperl-dev + - libboost-dev + - liblua5.1-0-dev + - zlib1g-dev script: - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON - - make + - make -j8 - ./bin/tests branches: only: diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake index 14d08b695..0578c8b0c 100644 --- a/cmake/FindMySQL.cmake +++ b/cmake/FindMySQL.cmake @@ -30,7 +30,7 @@ ELSE(MYSQL_ROOT) ENDIF(MYSQL_ROOT) # Library -SET(MySQL_NAMES mysqlclient_r mysqlclient) +SET(MySQL_NAMES libmysql mysqlclient_r mysqlclient) IF(MYSQL_ROOT) FIND_LIBRARY(MySQL_LIBRARY_DEBUG NAMES ${MySQL_NAMES} From 71d36af3efcdfcb88f4a1578a5b3450d01265f2a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 11 Oct 2015 17:10:10 -0500 Subject: [PATCH 353/846] eqemu_update.pl minor fix [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 9c1556d21..3a7c956a7 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -842,7 +842,7 @@ sub get_bots_db_version{ sub bots_db_management{ #::: Main Binary Database version - $bin_db_ver = trim($db_version[2]); + $bin_db_ver = trim($db_version[1]); #::: If we have stale data from main db run if($db_run_stage > 0 && $bots_db_management == 0){ From eb4e970c303f1029e310ed02ac5d89b48b82716c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 11 Oct 2015 21:59:16 -0500 Subject: [PATCH 354/846] Unfix the fix [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 3a7c956a7..9c1556d21 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -842,7 +842,7 @@ sub get_bots_db_version{ sub bots_db_management{ #::: Main Binary Database version - $bin_db_ver = trim($db_version[1]); + $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){ From 8ed255ad01db54a53aa099ce303fd1ff4a843942 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 12 Oct 2015 14:07:14 -0400 Subject: [PATCH 355/846] Fix expansionless AAs --- zone/aa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 84fc4a1f4..7e00da07c 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1419,11 +1419,11 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { } if(IsClient()) { - if(!(CastToClient()->GetPP().expansions & (1 << (rank->expansion - 1)))) { + if(rank->expansion && !(CastToClient()->GetPP().expansions & (1 << (rank->expansion - 1)))) { return false; } } else { - if(!(RuleI(World, ExpansionSettings) & (1 << (rank->expansion - 1)))) { + if(rank->expansion && !(RuleI(World, ExpansionSettings) & (1 << (rank->expansion - 1)))) { return false; } } From 79eb2d3d4bab15c7fb7d0412841c71baf7fffdf8 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 12 Oct 2015 17:17:07 -0400 Subject: [PATCH 356/846] Remote testing and some final updates --- common/version.h | 2 +- utils/scripts/eqemu_update.pl | 21 +++-- utils/sql/git/bots/README | 2 +- .../sql/git/bots/required/2015_09_30_bots.sql | 13 +-- zone/bot.cpp | 83 +++++++++---------- 5 files changed, 63 insertions(+), 58 deletions(-) diff --git a/common/version.h b/common/version.h index e2cda9a31..d8a6b6077 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9087 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // temporarily disabled + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 9c1556d21..2026086ce 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -30,7 +30,8 @@ if($ARGV[0] eq "V"){ 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"); + #get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); exit; } else{ @@ -205,7 +206,8 @@ else{ } sub do_update_self{ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + #get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); die "Rerun eqemu_update.pl"; } @@ -308,7 +310,8 @@ sub check_for_database_dump_script{ } 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"); + #get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_dumper.pl", "db_dumper.pl"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/scripts/db_dumper.pl", "db_dumper.pl"); } } @@ -897,12 +900,14 @@ 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("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("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/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("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } } @@ -1017,10 +1022,12 @@ 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("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/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("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); } } elsif($db_update >= 5000 && $db_update <= 9000){ diff --git a/utils/sql/git/bots/README b/utils/sql/git/bots/README index f3aaa0c16..844709fb9 100644 --- a/utils/sql/git/bots/README +++ b/utils/sql/git/bots/README @@ -3,4 +3,4 @@ Use the eqemu_update.pl script to source/update bot information into your databa Developers: Please prefix 'bots_' to sql file description (after the date) in order to prevent issues naming conflicts. -Example: 1980_01_01_bots_file_description.sql \ No newline at end of file +Example: 1970_01_01_bots_file_description.sql diff --git a/utils/sql/git/bots/required/2015_09_30_bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql index 88a1789d6..2f827c779 100644 --- a/utils/sql/git/bots/required/2015_09_30_bots.sql +++ b/utils/sql/git/bots/required/2015_09_30_bots.sql @@ -124,9 +124,9 @@ BEGIN `class` TINYINT(2) NOT NULL DEFAULT '0', `level` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', `deity` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused - `creation_day` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - `last_spawn` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', - `time_spawned` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `creation_day` INT(11) UNSIGNED NOT NULL DEFAULT UNIX_TIMESTAMP, + `last_spawn` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `time_spawned` INT(11) UNSIGNED NOT NULL DEFAULT '0', `size` FLOAT NOT NULL DEFAULT '0', `face` INT(10) NOT NULL DEFAULT '1', `hair_color` INT(10) NOT NULL DEFAULT '1', @@ -156,6 +156,7 @@ BEGIN `disease` SMALLINT(5) NOT NULL DEFAULT '0', `corruption` SMALLINT(5) NOT NULL DEFAULT '0', `show_helm` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused + `follow_distance` INT(11) UNSIGNED NOT NULL DEFAULT '200', -- Unused PRIMARY KEY (`bot_id`) ) ENGINE=InnoDB; CREATE TABLE `bot_inspect_messages` ( @@ -219,8 +220,8 @@ BEGIN `Race`, `Class`, `BotLevel`, - `BotCreateDate`, - `LastSpawnDate`, + UNIX_TIMESTAMP(`BotCreateDate`), + UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, @@ -655,7 +656,7 @@ DROP PROCEDURE IF EXISTS `LoadBotsSchema`; -- Functions DELIMITER $$ --- (no code references) +-- (no code references - see `vw_groups` below) CREATE FUNCTION `GetMobType` (mob_name VARCHAR(64)) RETURNS CHAR(1) BEGIN DECLARE Result CHAR(1); diff --git a/zone/bot.cpp b/zone/bot.cpp index d515303e7..3d01f53aa 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1563,7 +1563,6 @@ bool Bot::Save() " `race`," " `class`," " `level`," - /*creation_day - not needed for bot creation*/ " `last_spawn`," " `time_spawned`," " `size`," @@ -1605,8 +1604,7 @@ bool Bot::Save() " '%i'," /*race*/ " '%i'," /*class*/ " '%u'," /*level*/ - /*creation_day*/ - " NOW()," /*last_spawn*/ + " UNIX_TIMESTAMP(),"/*last_spawn*/ " 0," /*time_spawned*/ " '%f'," /*size*/ " '%i'," /*face*/ @@ -1705,8 +1703,7 @@ bool Bot::Save() " `race` = '%i'," " `class` = '%i'," " `level` = '%u'," - /*creation_day - check to see how client is handled*/ - " `last_spawn` = NOW()," + " `last_spawn` = UNIX_TIMESTAMP()," " `time_spawned` = '%u'," " `size` = '%f'," " `face` = '%i'," @@ -1735,7 +1732,7 @@ bool Bot::Save() " `magic` = '%i'," " `poison` = '%i'," " `disease` = '%i'," - " `corruption` = '%i'," + " `corruption` = '%i'" " WHERE `bot_id` = '%u'", _botOwnerCharacterID, this->GetBotSpellID(), @@ -1746,7 +1743,6 @@ bool Bot::Save() _baseRace, this->GetClass(), this->GetLevel(), - /*creation_day*/ GetTotalPlayTime(), GetSize(), this->GetLuclinFace(), @@ -1892,7 +1888,7 @@ void Bot::LoadBuffs() " `duration_formula`," " `tics_remaining`," " `poison_counters`," - " `disease_counters," + " `disease_counters`," " `curse_counters`," " `corruption_counters`," " `numhits`," @@ -1905,7 +1901,7 @@ void Bot::LoadBuffs() " `caston_z`," " `extra_di_chance`" " FROM `bot_buffs`" - " WHERE `bot_id` = %u", + " WHERE `bot_id` = '%u'", GetBotID() ); auto results = database.QueryDatabase(query); @@ -2091,7 +2087,7 @@ uint32 Bot::SavePetStats(std::string petName, uint32 petMana, uint32 petHitPoint petHitPoints ); auto results = database.QueryDatabase(query); - return 0; + return results.LastInsertedID(); } void Bot::SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) @@ -3421,9 +3417,9 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) " `inst_color`," " `augment_1`," " `augment_2`," - " `augslot_3`," - " `augslot_4`, " - " `augslot_5`," + " `augment_3`," + " `augment_4`, " + " `augment_5`," " `inst_no_drop`" " FROM `bot_inventories`" " WHERE `bot_id` = %i" @@ -3871,38 +3867,39 @@ std::list Bot::ListSpawnedBots(uint32 characterID, std::string* return spawnedBots; } -void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage) { +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; - } - - 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()); - } + 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) { From df88107697423d9186e5a2e1836c17e1678b4c47 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 12 Oct 2015 17:59:29 -0400 Subject: [PATCH 357/846] Missed on final review... --- utils/sql/git/bots/required/2015_09_30_bots.sql | 2 +- zone/bot.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/sql/git/bots/required/2015_09_30_bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql index 2f827c779..b9ac09b19 100644 --- a/utils/sql/git/bots/required/2015_09_30_bots.sql +++ b/utils/sql/git/bots/required/2015_09_30_bots.sql @@ -124,7 +124,7 @@ BEGIN `class` TINYINT(2) NOT NULL DEFAULT '0', `level` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', `deity` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused - `creation_day` INT(11) UNSIGNED NOT NULL DEFAULT UNIX_TIMESTAMP, + `creation_day` INT(11) UNSIGNED NOT NULL DEFAULT '0', `last_spawn` INT(11) UNSIGNED NOT NULL DEFAULT '0', `time_spawned` INT(11) UNSIGNED NOT NULL DEFAULT '0', `size` FLOAT NOT NULL DEFAULT '0', diff --git a/zone/bot.cpp b/zone/bot.cpp index 3d01f53aa..f74d4ebfc 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1563,6 +1563,7 @@ bool Bot::Save() " `race`," " `class`," " `level`," + " `creation_date`," " `last_spawn`," " `time_spawned`," " `size`," @@ -1604,6 +1605,7 @@ bool Bot::Save() " '%i'," /*race*/ " '%i'," /*class*/ " '%u'," /*level*/ + " UNIX_TIMESTAMP(),"/*creation_date*/ " UNIX_TIMESTAMP(),"/*last_spawn*/ " 0," /*time_spawned*/ " '%f'," /*size*/ From eeab7baef9c035ece99b9a2d5bbdbf913e5c5274 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 12 Oct 2015 18:27:26 -0400 Subject: [PATCH 358/846] Final commit for bots database versioning --- changelog.txt | 4 ++++ utils/scripts/eqemu_update.pl | 21 +++++++-------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/changelog.txt b/changelog.txt index e5f887e2d..2412ce5c0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/12/2015 == +Uleat: Implemented 'bots' database versioning +Note: See thread for more information: http://www.eqemulator.org/forums/showthread.php?t=40091 + == 10/10/2015 == Kayen: Updated mechanics to be consistent with live regarding how invisible breaks when the client is the target of a spell. Invisible will drop whenever a client is hit with a detrimental spell, regardless of if resisted, if it does damage or AOE. diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 2026086ce..9c1556d21 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -30,8 +30,7 @@ if($ARGV[0] eq "V"){ 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"); - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); exit; } else{ @@ -206,8 +205,7 @@ else{ } sub do_update_self{ - #get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); die "Rerun eqemu_update.pl"; } @@ -310,8 +308,7 @@ sub check_for_database_dump_script{ } 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"); - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/scripts/db_dumper.pl", "db_dumper.pl"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_dumper.pl", "db_dumper.pl"); } } @@ -900,14 +897,12 @@ 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("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); + 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"); - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } } @@ -1022,12 +1017,10 @@ 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("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/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("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/bots_updater/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){ From e2e8d444e9cc91084ecea1d454baea5ac7aea870 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 12 Oct 2015 18:51:41 -0400 Subject: [PATCH 359/846] Feign death will now break when hit by casted spells, consisted with live. Implemented suport for AA/spell effect which provides a chance to avoid FD breaking from spells. --- changelog.txt | 4 ++++ common/spdat.h | 2 +- zone/bonuses.cpp | 12 ++++++++++-- zone/client.h | 1 + zone/common.h | 1 + zone/spell_effects.cpp | 19 +++++++++++++++++++ zone/spells.cpp | 6 +++++- zone/string_ids.h | 2 ++ 8 files changed, 43 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 2412ce5c0..2f97b5f4f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,9 +1,13 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- + == 10/12/2015 == Uleat: Implemented 'bots' database versioning Note: See thread for more information: http://www.eqemulator.org/forums/showthread.php?t=40091 +Kayen: Feign death will now break when hit by casted spells, consisted with live. +Implemented suport for AA/spell effect which provides a chance to avoid FD breaking from spells. + == 10/10/2015 == Kayen: Updated mechanics to be consistent with live regarding how invisible breaks when the client is the target of a spell. Invisible will drop whenever a client is hit with a detrimental spell, regardless of if resisted, if it does damage or AOE. diff --git a/common/spdat.h b/common/spdat.h index 6ea3033b0..555ea67ef 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -392,7 +392,7 @@ typedef enum { //#define SE_FreePet 236 // not used #define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity) #define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed. -#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. +#define SE_FeignedCastOnChance 239 // implemented - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. //#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.] #define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet. #define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 8038e4a24..3aa9cc4a1 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1457,6 +1457,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->NoBreakAESneak = base1; break; + case SE_FeignedCastOnChance: + if (newbon->FeignedCastOnChance < base1) + newbon->FeignedCastOnChance = base1; + break; + // to do case SE_PetDiscipline: break; @@ -1470,8 +1475,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_SecondaryForte: break; - case SE_FeignedCastOnChance: - break; case SE_ExtendedShielding: break; case SE_ShieldDuration: @@ -3198,6 +3201,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne if (new_bonus->NoBreakAESneak < effect_value) new_bonus->NoBreakAESneak = effect_value; break; + + case SE_FeignedCastOnChance: + if (new_bonus->FeignedCastOnChance < effect_value) + new_bonus->FeignedCastOnChance = effect_value; + break; //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/client.h b/zone/client.h index f7527319c..e31f68b26 100644 --- a/zone/client.h +++ b/zone/client.h @@ -879,6 +879,7 @@ public: void BreakInvis(); void BreakSneakWhenCastOn(Mob* caster, bool IsResisted); + void BreakFeignDeathWhenCastOn(bool IsResisted); void LeaveGroup(); bool Hungry() const {if (GetGM()) return false; return m_pp.hunger_level <= 3000;} diff --git a/zone/common.h b/zone/common.h index 68accf746..a637e94bd 100644 --- a/zone/common.h +++ b/zone/common.h @@ -472,6 +472,7 @@ struct StatBonuses { int32 ReduceTradeskillFail[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 }; typedef struct diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a57be6351..ecb0698e0 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6770,4 +6770,23 @@ void Client::BreakSneakWhenCastOn(Mob* caster, bool IsResisted) Message_StringID(MT_Skills,STOP_SNEAKING); } } +} + +void Client::BreakFeignDeathWhenCastOn(bool IsResisted) +{ + if(GetFeigned()){ + + int chance = spellbonuses.FeignedCastOnChance + itembonuses.FeignedCastOnChance + aabonuses.FeignedCastOnChance; + + if (IsResisted) + chance *= 2; + + if(chance && (zone->random.Roll(chance))){ + Message_StringID(MT_SpellFailure,FD_CAST_ON_NO_BREAK); + return; + } + + SetFeigned(false); + Message_StringID(MT_SpellFailure,FD_CAST_ON); + } } \ No newline at end of file diff --git a/zone/spells.cpp b/zone/spells.cpp index f5a0ffd0d..6b4467dfe 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3714,8 +3714,10 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r } } - if (spelltar->IsClient()) + if (spelltar->IsClient()){ spelltar->CastToClient()->BreakSneakWhenCastOn(this, true); + spelltar->CastToClient()->BreakFeignDeathWhenCastOn(true); + } spelltar->CheckNumHitsRemaining(NumHit::IncomingSpells); CheckNumHitsRemaining(NumHit::OutgoingSpells); @@ -3724,8 +3726,10 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r return false; } } + if (spelltar->IsClient()){ spelltar->CastToClient()->BreakSneakWhenCastOn(this, false); + spelltar->CastToClient()->BreakFeignDeathWhenCastOn(false); } } else diff --git a/zone/string_ids.h b/zone/string_ids.h index 44d5924be..e3b943744 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -78,6 +78,7 @@ #define ONLY_ONE_PET 246 //You cannot have more than one pet at a time. #define CANNOT_CHARM_YET 248 //Your target is too high of a level for your charm spell. #define CANNOT_AFFECT_NPC 251 //That spell can not affect this target NPC. +#define FD_CAST_ON 254 //You are no longer feigning death, because a spell hit you. #define SUSPEND_MINION_HAS_AGGRO 256 //Your pet is the focus of something's attention. #define NO_PET 255 //You do not have a pet. #define GATE_FAIL 260 //Your gate is too unstable, and collapses. @@ -356,6 +357,7 @@ #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. +#define FD_CAST_ON_NO_BREAK 9174 //The strength of your will allows you to resume feigning death. #define SNEAK_RESTRICT 9240 //You can not use this ability because you have not been hidden for long enough. #define PET_NOW_FOCUSING 9254 //Focusing on one target, Master. #define PET_NOT_FOCUSING 9263 //No longer focusing on one target, Master. From b85850052a3585371c15d7f5b0813a72d517fe87 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 12 Oct 2015 21:16:54 -0400 Subject: [PATCH 360/846] Fix for `creation_date` mis-naming --- zone/bot.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index f74d4ebfc..b1546b8d5 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1563,7 +1563,7 @@ bool Bot::Save() " `race`," " `class`," " `level`," - " `creation_date`," + " `creation_day`," " `last_spawn`," " `time_spawned`," " `size`," @@ -1605,7 +1605,7 @@ bool Bot::Save() " '%i'," /*race*/ " '%i'," /*class*/ " '%u'," /*level*/ - " UNIX_TIMESTAMP(),"/*creation_date*/ + " UNIX_TIMESTAMP(),"/*creation_day*/ " UNIX_TIMESTAMP(),"/*last_spawn*/ " 0," /*time_spawned*/ " '%f'," /*size*/ From d3755cdb08a7bbada4fefbd81c4c94fb2f75ce72 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 13 Oct 2015 00:30:23 -0400 Subject: [PATCH 361/846] Temporarily disabled the bot script until a linux issue can be sorted out --- common/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index d8a6b6077..1d8d3963a 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9087 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // temporarily disabled (9000) #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif From 285bd3a62716cde191a04dc1d2fcfaad1b21c312 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 13 Oct 2015 14:00:51 -0400 Subject: [PATCH 362/846] Updated '2015_09_30_bots.sql' to alleviate import failures due to broken contraints --- changelog.txt | 3 + common/version.h | 2 +- .../sql/git/bots/required/2015_09_30_bots.sql | 166 ++++++++++-------- 3 files changed, 99 insertions(+), 72 deletions(-) diff --git a/changelog.txt b/changelog.txt index 2f97b5f4f..f0c254442 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/13/2015 == +Uleat: Important update to 2015_09_30_bots.sql - fix for orphaned entries causing crashes during the conversion process +Note: Please visit the thread below if you encounter issues during the conversion process == 10/12/2015 == Uleat: Implemented 'bots' database versioning diff --git a/common/version.h b/common/version.h index 1d8d3963a..d8a6b6077 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9087 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // temporarily disabled (9000) + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/required/2015_09_30_bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql index b9ac09b19..38f5fb274 100644 --- a/utils/sql/git/bots/required/2015_09_30_bots.sql +++ b/utils/sql/git/bots/required/2015_09_30_bots.sql @@ -1,5 +1,5 @@ -- '2015_09_30_bots' sql script file --- current as of 10/09/2015 +-- current as of 10/13/2015 -- -- Use eqemu_update.pl to administer this script @@ -277,9 +277,11 @@ BEGIN `stance_id` ) SELECT - `BotID`, - `StanceID` - FROM `botstances`; + bs.`BotID`, + bs.`StanceID` + FROM `botstances` bs + INNER JOIN `bot_data` bd + ON bs.`BotID` = bd.`bot_id`; RENAME TABLE `botstances` TO `botstances_old`; END IF; @@ -298,10 +300,12 @@ BEGIN `timer_value` ) SELECT - `BotID`, - `TimerID`, - `Value` - FROM `bottimers`; + bt.`BotID`, + bt.`TimerID`, + bt.`Value` + FROM `bottimers` bt + INNER JOIN `bot_data` bd + ON bt.`BotID` = bd.`bot_id`; RENAME TABLE `bottimers` TO `bottimers_old`; END IF; @@ -349,21 +353,23 @@ BEGIN `persistent` ) SELECT - `BotBuffId`, - `BotId`, - `SpellId`, - `CasterLevel`, - `DurationFormula`, - `TicsRemaining`, - `PoisonCounters`, - `DiseaseCounters`, - `CurseCounters`, - `CorruptionCounters`, - `HitCount`, - `MeleeRune`, - `MagicRune`, - `Persistent` - FROM `botbuffs`; + 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 ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'dot_rune') > 0) THEN UPDATE `bot_buffs` bb @@ -446,19 +452,21 @@ BEGIN `augment_5` ) SELECT - `BotInventoryID`, - `BotID`, - `SlotID`, - `ItemID`, - `charges`, - `color`, - `instnodrop`, - `augslot1`, - `augslot2`, - `augslot3`, - `augslot4`, - `augslot5` - FROM `botinventory`; + 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 ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory' AND `COLUMN_NAME` = 'augslot6') > 0) THEN UPDATE `bot_inventories` bi @@ -493,13 +501,15 @@ BEGIN `hp` ) SELECT - `BotPetsId`, - `PetId`, - `BotId`, - `Name`, - `Mana`, - `HitPoints` - FROM `botpets`; + 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`; RENAME TABLE `botpets` TO `botpets_old`; END IF; @@ -523,12 +533,14 @@ BEGIN `duration` ) SELECT - `BotPetBuffId`, - `BotPetsId`, - `SpellId`, - `CasterLevel`, - `Duration` - FROM `botpetbuffs`; + bpb.`BotPetBuffId`, + bpb.`BotPetsId`, + bpb.`SpellId`, + bpb.`CasterLevel`, + bpb.`Duration` + FROM `botpetbuffs` bpb + INNER JOIN `bot_pets` bp + ON bpb.`BotPetsId` = bp.`pets_index`; RENAME TABLE `botpetbuffs` TO `botpetbuffs_old`; END IF; @@ -548,10 +560,12 @@ BEGIN `item_id` ) SELECT - `BotPetInventoryId`, - `BotPetsId`, - `ItemId` - FROM `botpetinventory`; + bpi.`BotPetInventoryId`, + bpi.`BotPetsId`, + bpi.`ItemId` + FROM `botpetinventory` bpi + INNER JOIN `bot_pets` bp + ON bpi.`BotPetsId` = bp.`pets_index`; RENAME TABLE `botpetinventory` TO `botpetinventory_old`; END IF; @@ -571,10 +585,12 @@ BEGIN `group_name` ) SELECT - `BotGroupId`, - `BotGroupLeaderBotId`, - `BotGroupName` - FROM `botgroup`; + bg.`BotGroupId`, + bg.`BotGroupLeaderBotId`, + bg.`BotGroupName` + FROM `botgroup` bg + INNER JOIN `bot_data` bd + ON bg.`BotGroupLeaderBotId` = bd.`bot_id`; RENAME TABLE `botgroup` TO `botgroup_old`; END IF; @@ -596,10 +612,14 @@ BEGIN `bot_id` ) SELECT - `BotGroupMemberId`, - `BotGroupId`, - `BotId` - FROM `botgroupmembers`; + 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`; RENAME TABLE `botgroupmembers` TO `botgroupmembers_old`; END IF; @@ -629,16 +649,20 @@ BEGIN `alt` ) SELECT - `char_id`, - `guild_id`, - `rank`, - `tribute_enable`, - `total_tribute`, - `last_tribute`, - `banker`, - `public_note`, - `alt` - FROM `botguildmembers`; + 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`; RENAME TABLE `botguildmembers` TO `botguildmembers_old`; END IF; From 98bc7f0ccd77980e56059778cd6ce28d4dfae61c Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 13 Oct 2015 19:29:49 -0400 Subject: [PATCH 363/846] Activated load/save of new bot inventory fields (not use implementation) --- .../sql/git/bots/required/2015_09_30_bots.sql | 10 +- zone/bot.cpp | 131 +++++++++++++----- 2 files changed, 104 insertions(+), 37 deletions(-) diff --git a/utils/sql/git/bots/required/2015_09_30_bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql index 38f5fb274..aba11fa94 100644 --- a/utils/sql/git/bots/required/2015_09_30_bots.sql +++ b/utils/sql/git/bots/required/2015_09_30_bots.sql @@ -422,16 +422,16 @@ BEGIN `inst_charges` TINYINT(3) UNSIGNED DEFAULT 0, `inst_color` INT(11) UNSIGNED NOT NULL DEFAULT '0', `inst_no_drop` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', - `inst_custom_data` TEXT NULL, -- Unused - `ornament_icon` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused - `ornament_id_file` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused - `ornament_hero_model` INT(11) NOT NULL DEFAULT '0', -- Unused + `inst_custom_data` TEXT NULL, + `ornament_icon` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `ornament_id_file` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `ornament_hero_model` INT(11) NOT NULL DEFAULT '0', `augment_1` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', `augment_2` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', `augment_3` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', `augment_4` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', `augment_5` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', - `augment_6` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', -- Unused + `augment_6` MEDIUMINT(7) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY (`inventories_index`), KEY `FK_bot_inventories_1` (`bot_id`), CONSTRAINT `FK_bot_inventories_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) diff --git a/zone/bot.cpp b/zone/bot.cpp index b1546b8d5..68b32b296 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3336,7 +3336,7 @@ 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 }; + 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; @@ -3355,11 +3355,16 @@ void Bot::SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, s " `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_5`," + " `augment_6`" ")" " VALUES (" "%lu," /*bot_id*/ @@ -3368,23 +3373,33 @@ void Bot::SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, s " %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_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), // does this match the current flag implementation? + (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[4], + (unsigned long)augslot[5] ); auto results = database.QueryDatabase(query); if(!results.Success()) @@ -3417,12 +3432,17 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) " `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`," - " `inst_no_drop`" + " `augment_6`" " FROM `bot_inventories`" " WHERE `bot_id` = %i" " ORDER BY `slot_id`", @@ -3438,39 +3458,73 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) int16 slot_id = atoi(row[0]); uint32 item_id = atoi(row[1]); uint16 charges = atoi(row[2]); - uint32 color = atoul(row[3]); uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; - 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; - ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]); + 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; } - int16 put_slot_id = INVALID_INDEX; - - if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == 9999) && inst->GetItem()->Attuneable)) - inst->SetAttuned(true); - - if (color > 0) - inst->SetColor(color); - 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); - // Save ptr to item in inventory 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); } @@ -9265,15 +9319,28 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 setcolor = (red << 16) | (green << 8) | blue; std::string query; if (setslot == -1) { - int slots[] = { 2, 7, 9, 12, 17, 18, 19 }; - query = StringFormat("UPDATE `bot_inventories` SET `inst_color` = %u WHERE `slot_id` IN (2, 7, 9, 12, 17, 18, 19) AND `bot_id` = %u", setcolor, botid); + 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 = 0; i < 7; i++) { - uint8 slotmaterial = Inventory::CalcMaterialFromSlot((uint8)slots[i]); - c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); + 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); @@ -9281,8 +9348,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if (!results.Success()) return; - uint8 slotmaterial = Inventory::CalcMaterialFromSlot(setslot); - c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); + c->GetTarget()->CastToBot()->SendWearChange(Inventory::CalcMaterialFromSlot(setslot)); } } @@ -9294,11 +9360,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "armorcolor")){ c->Message(0, "-----------------#bot armorcolor help-----------------------------"); - c->Message(0, "Armor: -1(All), 2(Helm), 7(Arms), 9(Bracer), 12(Hands), 17(Chest/Robe), 18(Legs), 19(Boots)"); + 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 17 0 255 0 - this would make the chest bright green"); + c->Message(0, "Example: #bot armorcolor %u 0 255 0 - this would make the chest bright green", MainChest); return; } From efeb80cc8b19f1eccfe278b35d0f3d36022f797c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 14 Oct 2015 16:36:38 -0400 Subject: [PATCH 364/846] Fix MGB not always turning off and make it work for discs --- zone/effects.cpp | 5 +---- zone/mob.h | 2 ++ zone/spells.cpp | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index f2706cae1..dc069fb2a 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -626,10 +626,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { return(false); } - if(GetEndurance() > spell.EndurCost) { - SetEndurance(GetEndurance() - spell.EndurCost); - TryTriggerOnValueAmount(false, false, true); - } else { + if(GetEndurance() < spell.EndurCost) { Message(11, "You are too fatigued to use this skill right now."); return(false); } diff --git a/zone/mob.h b/zone/mob.h index cb5948241..5032abcf6 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -425,6 +425,8 @@ public: virtual int32 CalcMaxHP(); inline int32 GetMaxMana() const { return max_mana; } inline int32 GetMana() const { return cur_mana; } + virtual int32 GetEndurance() const { return 0; } + virtual void SetEndurance(int32 newEnd) { return; } int32 GetItemHPBonuses(); int32 GetSpellHPBonuses(); virtual const int32& SetMana(int32 amount); diff --git a/zone/spells.cpp b/zone/spells.cpp index 6b4467dfe..86c489185 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -75,6 +75,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/skills.h" #include "../common/spdat.h" #include "../common/string_util.h" +#include "../common/data_verification.h" #include "quest_parser_collection.h" #include "string_ids.h" @@ -2248,13 +2249,13 @@ 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) { mana_used = GetActSpellCost(spell_id, mana_used); - if (HasMGB() && spells[spell_id].can_mgb) { + if (mgb) { mana_used *= 2; - SetMGB(false); } // clamp if we some how got focused above our current mana if (GetMana() < mana_used) @@ -2265,6 +2266,16 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 TryTriggerOnValueAmount(false, true); } } + // one may want to check if this is a disc or not, but we actually don't, there are non disc stuff that have end cost + if (spells[spell_id].EndurCost) { + auto end_cost = spells[spell_id].EndurCost; + if (mgb) + end_cost *= 2; + SetEndurance(GetEndurance() - EQEmu::ClampUpper(end_cost, GetEndurance())); + TryTriggerOnValueAmount(false, false, true); + } + if (mgb) + SetMGB(false); //set our reuse timer on long ass reuse_time spells... if(IsClient() && !isproc) From e2f14566245458b932d741ef3769f8f0e2a3c6c5 Mon Sep 17 00:00:00 2001 From: Cilraaz Date: Wed, 14 Oct 2015 22:57:17 -0400 Subject: [PATCH 365/846] Allow For Old Race/Class Experience Modifiers Add new ruletypes 'Character:UseOldRaceExpPenalties' and 'Character:UseOldClassExpPenalties' When set to true, adds in bonuses/penalties that existed in Classic Class-based penalties were disabled during Velious, while race-based penalties were not removed until TSS This method uses the original SOE method of increase exp needed to level, rather than decreasing exp gained --- common/ruletypes.h | 2 ++ zone/exp.cpp | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/common/ruletypes.h b/common/ruletypes.h index 1b4baa371..9c05821e5 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -85,6 +85,8 @@ RULE_INT(Character, MaxCharmDurationForPlayerCharacter, 15) RULE_INT(Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values RULE_BOOL(Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas RULE_BOOL(Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses +RULE_BOOL(Character, UseOldRaceExpPenalties, false) // Setting this to true will enable racial exp penalties for Iksar, Troll, Ogre, and Barbarian, as well as the bonus for Halflings +RULE_BOOL(Character, UseOldClassExpPenalties, false) // Setting this to true will enable old class exp penalties for Paladin, SK, Ranger, Bard, Monk, Wizard, Enchanter, Magician, and Necromancer, as well as the bonus for Rogues and Warriors RULE_BOOL(Character, RespawnFromHover, false) // Use Respawn window, or not. RULE_INT(Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS RULE_BOOL(Character, UseNewStatsWindow, true) // New stats window shows everything diff --git a/zone/exp.cpp b/zone/exp.cpp index 0172263e7..2e231cc36 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -665,6 +665,41 @@ uint32 Client::GetEXPForLevel(uint16 check_level) mod *= 1000; uint32 finalxp = uint32(base * mod); + + if(RuleB(Character,UseOldRaceExpPenalties)) + { + float racemod = 1.0; + if(GetBaseRace() == TROLL || GetBaseRace() == IKSAR) { + racemod = 1.2; + } else if(GetBaseRace() == OGRE) { + racemod = 1.15; + } else if(GetBaseRace() == BARBARIAN) { + racemod = 1.05; + } else if(GetBaseRace() == HALFLING) { + racemod = 0.95; + } + + finalxp = uint32(finalxp * racemod); + } + + if(RuleB(Character,UseOldClassExpPenalties)) + { + float classmod = 1.0; + if(GetClass() == PALADIN || GetClass() == SHADOWKNIGHT || GetClass() == RANGER || GetClass() == BARD) { + classmod = 1.4; + } else if(GetClass() == MONK) { + classmod = 1.2; + } else if(GetClass() == WIZARD || GetClass() == ENCHANTER || GetClass() == MAGICIAN || GetClass() == NECROMANCER) { + classmod = 1.1; + } else if(GetClass() == ROGUE) { + classmod = 0.91; + } else if(GetClass() == WARRIOR) { + classmod = 0.9; + } + + finalxp = uint32(finalxp * classmod); + } + finalxp = mod_client_xp_for_level(finalxp, check_level); return finalxp; From 190ebbbc6f3f9ce65ac5ae5dc0946bccf0e4f329 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 15 Oct 2015 18:22:56 -0400 Subject: [PATCH 366/846] Optional but recommended SQL to update spells_new table fields. --- utils/sql/git/optional/2015_10_15_spells_new_update.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 utils/sql/git/optional/2015_10_15_spells_new_update.sql diff --git a/utils/sql/git/optional/2015_10_15_spells_new_update.sql b/utils/sql/git/optional/2015_10_15_spells_new_update.sql new file mode 100644 index 000000000..23dc2abb1 --- /dev/null +++ b/utils/sql/git/optional/2015_10_15_spells_new_update.sql @@ -0,0 +1,7 @@ +ALTER TABLE `spells_new` CHANGE `field209` `no_resist` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field232` `no_remove` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `maxtargets` `no_hd_item_mod` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `not_extendable` `not_focusable` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field217` `override_crit` INT(11) NOT NULL DEFAULT '0'; + + From 85adea631d49dcce3cbfc0a3e85b29bc0a4f6d79 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 16 Oct 2015 18:09:22 -0400 Subject: [PATCH 367/846] Activated load/save of new bot data fields; added command '#bot clearfollowdistance' --- changelog.txt | 3 + .../sql/git/bots/required/2015_09_30_bots.sql | 4 +- zone/bot.cpp | 170 +++++++++++++----- zone/bot.h | 2 + 4 files changed, 128 insertions(+), 51 deletions(-) diff --git a/changelog.txt b/changelog.txt index f0c254442..e3f74ce08 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/16/2015 == +Uleat: Added command '#bot clearfollowdistance [ | spawned | all ]' to coincide with the activation of the load/save feature for follow_distance + == 10/13/2015 == Uleat: Important update to 2015_09_30_bots.sql - fix for orphaned entries causing crashes during the conversion process Note: Please visit the thread below if you encounter issues during the conversion process diff --git a/utils/sql/git/bots/required/2015_09_30_bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql index aba11fa94..b4e080846 100644 --- a/utils/sql/git/bots/required/2015_09_30_bots.sql +++ b/utils/sql/git/bots/required/2015_09_30_bots.sql @@ -155,8 +155,8 @@ BEGIN `poison` SMALLINT(5) NOT NULL DEFAULT '0', `disease` SMALLINT(5) NOT NULL DEFAULT '0', `corruption` SMALLINT(5) NOT NULL DEFAULT '0', - `show_helm` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused - `follow_distance` INT(11) UNSIGNED NOT NULL DEFAULT '200', -- Unused + `show_helm` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `follow_distance` INT(11) UNSIGNED NOT NULL DEFAULT '200', PRIMARY KEY (`bot_id`) ) ENGINE=InnoDB; CREATE TABLE `bot_inspect_messages` ( diff --git a/zone/bot.cpp b/zone/bot.cpp index 68b32b296..ac84ffc5c 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -66,7 +66,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm SetShowHelm(true); CalcChanceToCast(); rest_timer.Disable(); - SetFollowDistance(184); + SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); // Do this once and only in this constructor GenerateAppearance(); GenerateBaseStats(); @@ -144,7 +144,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetNumHealRotationMembers(0); CalcChanceToCast(); rest_timer.Disable(); - SetFollowDistance(184); + SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); strcpy(this->name, this->GetCleanName()); database.GetBotInspectMessage(this->GetBotID(), &_botInspectMessage); LoadGuildMembership(&_guildId, &_guildRank, &_guildName); @@ -1593,7 +1593,9 @@ bool Bot::Save() " `magic`," " `poison`," " `disease`," - " `corruption`" + " `corruption`," + " `show_helm`," + " `follow_distance`" ")" " VALUES (" "'%u'," /*owner_id*/ @@ -1635,7 +1637,9 @@ bool Bot::Save() " '%i'," /*magic*/ " '%i'," /*poison*/ " '%i'," /*disease*/ - " '%i'" /*corruption*/ + " '%i'," /*corruption*/ + " '1'," /*show_helm*/ + " '%i'" /*follow_distance*/ ")", this->_botOwnerCharacterID, this->GetBotSpellID(), @@ -1673,7 +1677,8 @@ bool Bot::Save() GetMR(), GetPR(), GetDR(), - GetCorrup() + GetCorrup(), + BOT_DEFAULT_FOLLOW_DISTANCE ); auto results = database.QueryDatabase(query); if(!results.Success()) { @@ -1734,7 +1739,9 @@ bool Bot::Save() " `magic` = '%i'," " `poison` = '%i'," " `disease` = '%i'," - " `corruption` = '%i'" + " `corruption` = '%i'," + " `show_helm` = '%i'," + " `follow_distance` = '%i'" " WHERE `bot_id` = '%u'", _botOwnerCharacterID, this->GetBotSpellID(), @@ -1774,6 +1781,8 @@ bool Bot::Save() _basePR, _baseDR, _baseCorrup, + (GetShowHelm() ? 1 : 0), + GetFollowDistance(), GetBotID() ); auto results = database.QueryDatabase(query); @@ -3626,13 +3635,13 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.is_npc = 0; // 0=no, 1=yes ns->spawn.is_pet = 0; ns->spawn.guildrank = 0; - ns->spawn.showhelm = GetShowHelm(); + ns->spawn.showhelm = GetShowHelm() ? 1 : 0; ns->spawn.flymode = 0; 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.helm = (GetShowHelm() ? helmtexture : 0); //0xFF; + ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; const Item_Struct* item = 0; const ItemInst* inst = 0; @@ -3696,7 +3705,6 @@ uint32 Bot::GetBotIDByBotName(std::string botName) { Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) { - Bot* loadedBot = nullptr; if(botID == 0) return nullptr; @@ -3706,46 +3714,52 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) " `spells_id`," " `name`," " `last_name`," - " `level`," + " `title`," /*planned use[4]*/ + " `suffix`," /*planned use[5]*/ + " `zone_id`," + " `gender`," " `race`," " `class`," - " `gender`," + " `level`," + " `deity`," /*planned use[11]*/ + " `creation_day`," /*not in-use[12]*/ + " `last_spawn`," /*not in-use[13]*/ + " `time_spawned`," " `size`," " `face`," - " `hair_style`," " `hair_color`," + " `hair_style`," + " `beard`," + " `beard_color`," " `eye_color_1`," " `eye_color_2`," - " `beard_color`," - " `beard`," " `drakkin_heritage`," " `drakkin_tattoo`," " `drakkin_details`," - " `hp`," - " `mana`," - " `magic`," - " `cold`," - " `disease`," - " `fire`," - " `poison`," - " `corruption`," - " `ac`," - " `str`," - " `sta`," - " `dex`," - " `agi`," - " `int`," - " `wis`," - " `cha`," + " `ac`," /*not in-use[26]*/ " `atk`," - " `creation_day`," - " `last_spawn`," - " `time_spawned`," - " `zone_id`" + " `hp`," + " `mana`," /*not in-use[29]*/ + " `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`," + " `follow_distance`" " FROM `bot_data`" " WHERE `bot_id` = '%u'", botID ); + auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -3755,29 +3769,30 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) if (results.RowCount() == 0) return nullptr; + // 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[4]), atoi(row[5]), atoi(row[6]), atoi(row[7])); + 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[4]), - atoi(row[5]), - atoi(row[6]), - atoi(row[7]), - atof(row[8]), - atoi(row[9]), atoi(row[10]), - atoi(row[11]), - atoi(row[12]), - atoi(row[13]), - atoi(row[14]), - atoi(row[15]), + atoi(row[8]), + atoi(row[9]), + atoi(row[7]), + atof(row[15]), atoi(row[16]), - atoi(row[17]), atoi(row[18]), - atoi(row[19]), + 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[27]), + atoi(row[28]), defaultNPCTypeStruct.MR, defaultNPCTypeStruct.CR, defaultNPCTypeStruct.DR, @@ -3794,7 +3809,13 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) defaultNPCTypeStruct.CHA, defaultNPCTypeStruct.ATK ); - loadedBot = new Bot(botID, atoi(row[0]), atoi(row[1]), atof(row[38]), atoi(row[39]), tempNPCStruct); + + 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; } @@ -9244,6 +9265,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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."); @@ -9300,6 +9322,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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)) { @@ -12713,6 +12772,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { 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")); } } diff --git a/zone/bot.h b/zone/bot.h index aa77c5f59..701f96dd4 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -18,6 +18,8 @@ #include +#define BOT_DEFAULT_FOLLOW_DISTANCE 184 + extern WorldServer worldserver; const int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this From 376b04a37ba60aaab8e3a543d138549c8d05ab98 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 19 Oct 2015 10:05:20 -0700 Subject: [PATCH 368/846] Allow ModifyNPCStat to change an NPCs spell list --- zone/npc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/npc.cpp b/zone/npc.cpp index effd04a4a..cd20c3eb7 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1978,6 +1978,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) else if(id == "loottable_id") { loottable_id = atof(val.c_str()); return; } else if(id == "healscale") { healscale = atof(val.c_str()); return; } else if(id == "spellscale") { spellscale = atof(val.c_str()); return; } + else if(id == "npc_spells_id") { AI_AddNPCSpells(atoi(val.c_str())); return; } } void NPC::LevelScale() { From ec36a3787d6774d68da502e7106a23f88ac53acf Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Wed, 21 Oct 2015 01:20:53 -0700 Subject: [PATCH 369/846] Allow ModifyNPCStat to change npc spell effects lists --- zone/npc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/npc.cpp b/zone/npc.cpp index cd20c3eb7..72264a1a2 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1979,6 +1979,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) else if(id == "healscale") { healscale = atof(val.c_str()); return; } else if(id == "spellscale") { spellscale = atof(val.c_str()); return; } else if(id == "npc_spells_id") { AI_AddNPCSpells(atoi(val.c_str())); return; } + else if(id == "npc_spells_effects_id") { AI_AddNPCSpellsEffects(atoi(val.c_str())); CalcBonuses(); return; } } void NPC::LevelScale() { From 1dd911b150e4ece1f14ef40f8d6f878867c864ad Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 30 Oct 2015 16:45:34 -0400 Subject: [PATCH 370/846] Correct charm invis breaking --- zone/mob.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index fc46aac75..82875d451 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -503,13 +503,9 @@ void Mob::SetInvisible(uint8 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); - } + auto formerpet = GetPet(); + if (formerpet && formerpet->GetPetType() == petCharmed && (invisible || hidden || improved_hidden)) + formerpet->BuffFadeByEffect(SE_Charm); } //check to see if `this` is invisible to `other` From ab3e31154cce7ce947205b0eda565cdf3018ea7c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 31 Oct 2015 18:32:23 -0500 Subject: [PATCH 371/846] Adjust AI Aggro check timers for NPC's with npc_aggro flag set to be far less excessive (Performance increase) --- common/features.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/features.h b/common/features.h index 0860788e1..44f83c648 100644 --- a/common/features.h +++ b/common/features.h @@ -154,7 +154,7 @@ enum { //reuse times enum { //timer settings, all in milliseconds AImovement_duration = 100, AIthink_duration = 150, - AIscanarea_delay = 500, + AIscanarea_delay = 6000, AIfeignremember_delay = 500, AItarget_check_duration = 500, AIClientScanarea_delay = 750, //used in REVERSE_AGGRO From 33917fe2a94aafa7e4160d09a6abd03dcff0a633 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 31 Oct 2015 20:19:57 -0500 Subject: [PATCH 372/846] - Add Zone Process ID (OS PID) as information passed back to world, ultimately with the ability to display it in the telnet console under 'zonestatus' - Refactored some zoneserver/worldserver code for readability --- common/servertalk.h | 1 + world/zonelist.cpp | 116 ++++++++++++++++++++++++++-------------- world/zoneserver.cpp | 80 ++++++++++++++------------- world/zoneserver.h | 54 ++++++++++--------- zone/bot.cpp | 2 +- zone/client.cpp | 4 +- zone/client_packet.cpp | 2 +- zone/client_process.cpp | 2 +- zone/entity.cpp | 4 +- zone/guild_mgr.cpp | 10 ++-- zone/merc.cpp | 4 +- zone/net.cpp | 6 +-- zone/npc.cpp | 2 +- zone/spell_effects.cpp | 2 +- zone/spells.cpp | 2 +- zone/worldserver.cpp | 63 ++++++++++++---------- zone/worldserver.h | 2 +- zone/zone.cpp | 20 +++---- 18 files changed, 216 insertions(+), 160 deletions(-) diff --git a/common/servertalk.h b/common/servertalk.h index 0945d500d..ee5e41a52 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -548,6 +548,7 @@ struct ServerConnectInfo { char address[250]; char local_address[250]; uint16 port; + uint32 process_id; }; struct ServerGMGoto_Struct { diff --git a/world/zonelist.cpp b/world/zonelist.cpp index 22d783f5d..a887a4d43 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -283,57 +283,84 @@ void ZSList::ListLockedZones(const char* to, WorldTCPConnection* connection) { } void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* connection) { + LinkedListIterator iterator(list); struct in_addr in; iterator.Reset(); char locked[4]; - if (WorldConfig::get()->Locked == true) + if (WorldConfig::get()->Locked == true){ strcpy(locked, "Yes"); - else + } + else { strcpy(locked, "No"); + } char* output = 0; uint32 outsize = 0, outlen = 0; - if (connection->IsConsole()) + + if (connection->IsConsole()){ AppendAnyLenString(&output, &outsize, &outlen, "World Locked: %s\r\n", locked); - else + } + else{ AppendAnyLenString(&output, &outsize, &outlen, "World Locked: %s^", locked); - if (connection->IsConsole()) + } + if (connection->IsConsole()){ AppendAnyLenString(&output, &outsize, &outlen, "Zoneservers online:\r\n"); - else + } + else{ AppendAnyLenString(&output, &outsize, &outlen, "Zoneservers online:^"); -// connection->SendEmoteMessage(to, 0, 0, 0, "World Locked: %s", locked); -// connection->SendEmoteMessage(to, 0, 0, 0, "Zoneservers online:"); - int v=0, w=0, x=0, y=0, z=0; - char tmpStatic[2] = { 0, 0 }, tmpZone[64]; - memset(tmpZone, 0, sizeof(tmpZone)); - ZoneServer* zs = 0; - while(iterator.MoreElements()) { - zs = iterator.GetData(); - in.s_addr = zs->GetIP(); + } - if(zs->IsStaticZone()) + int v = 0, w = 0, x = 0, y = 0, z = 0; + char is_static_string[2] = { 0, 0 }, zone_data_string[64]; + memset(zone_data_string, 0, sizeof(zone_data_string)); + + ZoneServer* zone_server_data = 0; + + while (iterator.MoreElements()) { + zone_server_data = iterator.GetData(); + in.s_addr = zone_server_data->GetIP(); + + if (zone_server_data->IsStaticZone()){ z++; - else if (zs->GetZoneID() != 0) + } + else if (zone_server_data->GetZoneID() != 0){ w++; - else if(zs->GetZoneID() == 0 && !zs->IsBootingUp()) + } + else if (zone_server_data->GetZoneID() == 0 && !zone_server_data->IsBootingUp()){ v++; + } - if (zs->IsStaticZone()) - tmpStatic[0] = 'S'; + if (zone_server_data->IsStaticZone()) + is_static_string[0] = 'S'; else - tmpStatic[0] = ' '; + is_static_string[0] = 'D'; if (admin >= 150) { - if (zs->GetZoneID()) - snprintf(tmpZone, sizeof(tmpZone), "%s (%i)", zs->GetZoneName(), zs->GetZoneID()); - else if (zs->IsBootingUp()) - strcpy(tmpZone, "..."); - else - tmpZone[0] = 0; + if (zone_server_data->GetZoneID()){ + snprintf(zone_data_string, sizeof(zone_data_string), "%s (%i)", zone_server_data->GetZoneName(), zone_server_data->GetZoneID()); + } + else if (zone_server_data->IsBootingUp()){ + strcpy(zone_data_string, "..."); + } + else{ + zone_data_string[0] = 0; + } - AppendAnyLenString(&output, &outsize, &outlen, " #%-3i %s %15s:%-5i %2i %s:%i %s", zs->GetID(), tmpStatic, inet_ntoa(in), zs->GetPort(), zs->NumPlayers(), zs->GetCAddress(), zs->GetCPort(), tmpZone); + AppendAnyLenString(&output, &outsize, &outlen, + "#%-3i :: %s :: %15s:%-5i :: %2i :: %s:%i :: %s :: (%u)", + zone_server_data->GetID(), + is_static_string, + inet_ntoa(in), + zone_server_data->GetPort(), + zone_server_data->NumPlayers(), + zone_server_data->GetCAddress(), + zone_server_data->GetCPort(), + zone_data_string, + zone_server_data->GetZoneOSProcessID() + ); + if (outlen >= 3584) { connection->SendEmoteMessageRaw(to, 0, 0, 10, output); safe_delete(output); @@ -348,12 +375,12 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con } x++; } - else if (zs->GetZoneID() != 0) { - if (zs->GetZoneID()) - strcpy(tmpZone, zs->GetZoneName()); + else if (zone_server_data->GetZoneID() != 0) { + if (zone_server_data->GetZoneID()) + strcpy(zone_data_string, zone_server_data->GetZoneName()); else - tmpZone[0] = 0; - AppendAnyLenString(&output, &outsize, &outlen, " #%i %s %s", zs->GetID(), tmpStatic, tmpZone); + zone_data_string[0] = 0; + AppendAnyLenString(&output, &outsize, &outlen, " #%i %s %s", zone_server_data->GetID(), is_static_string, zone_data_string); if (outlen >= 3584) { connection->SendEmoteMessageRaw(to, 0, 0, 10, output); safe_delete(output); @@ -361,25 +388,32 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con outlen = 0; } else { - if (connection->IsConsole()) + if (connection->IsConsole()){ AppendAnyLenString(&output, &outsize, &outlen, "\r\n"); - else + } + else{ AppendAnyLenString(&output, &outsize, &outlen, "^"); + } } x++; } y++; iterator.Advance(); } - if (connection->IsConsole()) + + if (connection->IsConsole()){ AppendAnyLenString(&output, &outsize, &outlen, "%i servers listed. %i servers online.\r\n", x, y); - else + } + else { AppendAnyLenString(&output, &outsize, &outlen, "%i servers listed. %i servers online.^", x, y); - AppendAnyLenString(&output, &outsize, &outlen, "%i zones are static zones, %i zones are booted zones, %i zones available.",z,w,v); -// connection->SendEmoteMessage(to, 0, 0, "%i servers listed. %i servers online.", x, y); -// connection->SendEmoteMessage(to,0,0,"%i zones are static zones, %i zones are booted zones, %i zones available.",z,w,v); - if (output) + } + + AppendAnyLenString(&output, &outsize, &outlen, "%i zones are static zones, %i zones are booted zones, %i zones available.", z, w, v); + + if (output){ connection->SendEmoteMessageRaw(to, 0, 0, 10, output); + } + safe_delete(output); } diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index d36507f04..207beacd1 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -49,20 +49,24 @@ extern QueryServConnection QSLink; void CatchSignal(int sig_num); ZoneServer::ZoneServer(EmuTCPConnection* itcpc) -: WorldTCPConnection(), tcpc(itcpc), ls_zboot(5000) { - ID = zoneserver_list.GetNextID(); +: WorldTCPConnection(), tcpc(itcpc), zone_boot_timer(5000) { + + /* Set Process tracking variable defaults */ + memset(zone_name, 0, sizeof(zone_name)); memset(compiled, 0, sizeof(compiled)); - zoneID = 0; - instanceID = 0; + memset(client_address, 0, sizeof(client_address)); + memset(client_local_address, 0, sizeof(client_local_address)); - memset(clientaddress, 0, sizeof(clientaddress)); - memset(clientlocaladdress, 0, sizeof(clientlocaladdress)); - clientport = 0; - BootingUp = false; - authenticated = false; - staticzone = false; - pNumPlayers = 0; + zone_server_id = zoneserver_list.GetNextID(); + zone_server_zone_id = 0; + instance_id = 0; + zone_os_process_id = 0; + client_port = 0; + is_booting_up = false; + is_authenticated = false; + is_static_zone = false; + zone_player_count = 0; } ZoneServer::~ZoneServer() { @@ -72,7 +76,7 @@ ZoneServer::~ZoneServer() { } bool ZoneServer::SetZone(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { - BootingUp = false; + is_booting_up = false; const char* zn = MakeLowerString(database.GetZoneName(iZoneID)); char* longname; @@ -81,17 +85,17 @@ bool ZoneServer::SetZone(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { Log.Out(Logs::Detail, Logs::World_Server,"Setting to '%s' (%d:%d)%s",(zn) ? zn : "",iZoneID, iInstanceID, iStaticZone ? " (Static)" : ""); - zoneID = iZoneID; - instanceID = iInstanceID; + zone_server_zone_id = iZoneID; + instance_id = iInstanceID; if(iZoneID!=0) - oldZoneID = iZoneID; - if (zoneID == 0) { + zone_server_previous_zone_id = iZoneID; + if (zone_server_zone_id == 0) { client_list.CLERemoveZSRef(this); - pNumPlayers = 0; + zone_player_count = 0; LSSleepUpdate(GetPrevZoneID()); } - staticzone = iStaticZone; + is_static_zone = iStaticZone; if (zn) { @@ -111,7 +115,7 @@ bool ZoneServer::SetZone(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { } client_list.ZoneBootup(this); - ls_zboot.Start(); + zone_boot_timer.Start(); return true; } @@ -172,19 +176,19 @@ void ZoneServer::LSSleepUpdate(uint32 zoneid){ bool ZoneServer::Process() { if (!tcpc->Connected()) return false; - if(ls_zboot.Check()){ + if(zone_boot_timer.Check()){ LSBootUpdate(GetZoneID(), true); - ls_zboot.Disable(); + zone_boot_timer.Disable(); } ServerPacket *pack = 0; while((pack = tcpc->PopPacket())) { - if (!authenticated) { + if (!is_authenticated) { if (WorldConfig::get()->SharedKey.length() > 0) { 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) - authenticated = true; + is_authenticated = true; else { struct in_addr in; in.s_addr = GetIP(); @@ -210,7 +214,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."); - authenticated = true; + is_authenticated = true; } } switch(pack->opcode) { @@ -582,29 +586,33 @@ bool ZoneServer::Process() { ServerConnectInfo* sci = (ServerConnectInfo*) pack->pBuffer; if (!sci->port) { - clientport = zoneserver_list.GetAvailableZonePort(); + client_port = zoneserver_list.GetAvailableZonePort(); ServerPacket p(ServerOP_SetConnectInfo, sizeof(ServerConnectInfo)); memset(p.pBuffer,0,sizeof(ServerConnectInfo)); ServerConnectInfo* sci = (ServerConnectInfo*) p.pBuffer; - sci->port = clientport; + sci->port = client_port; SendPacket(&p); - Log.Out(Logs::Detail, Logs::World_Server,"Auto zone port configuration. Telling zone to use port %d",clientport); + Log.Out(Logs::Detail, Logs::World_Server,"Auto zone port configuration. Telling zone to use port %d",client_port); } else { - clientport = sci->port; - Log.Out(Logs::Detail, Logs::World_Server,"Zone specified port %d.",clientport); + client_port = sci->port; + Log.Out(Logs::Detail, Logs::World_Server,"Zone specified port %d.",client_port); } if(sci->address[0]) { - strn0cpy(clientaddress, sci->address, 250); + strn0cpy(client_address, sci->address, 250); Log.Out(Logs::Detail, Logs::World_Server, "Zone specified address %s.", sci->address); } if(sci->local_address[0]) { - strn0cpy(clientlocaladdress, sci->local_address, 250); + strn0cpy(client_local_address, sci->local_address, 250); Log.Out(Logs::Detail, Logs::World_Server, "Zone specified local address %s.", sci->address); } + if (sci->process_id){ + zone_os_process_id = sci->process_id; + } + } case ServerOP_SetLaunchName: { if(pack->size != sizeof(LaunchName_Struct)) @@ -1411,13 +1419,13 @@ void ZoneServer::ChangeWID(uint32 iCharID, uint32 iWID) { void ZoneServer::TriggerBootup(uint32 iZoneID, uint32 iInstanceID, const char* adminname, bool iMakeStatic) { - BootingUp = true; - zoneID = iZoneID; - instanceID = iInstanceID; + is_booting_up = true; + zone_server_zone_id = iZoneID; + instance_id = iInstanceID; auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct)); ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *) pack->pBuffer; - s->ZoneServerID = ID; + s->ZoneServerID = zone_server_id; if (adminname != 0) strcpy(s->adminname, adminname); @@ -1434,7 +1442,7 @@ void ZoneServer::TriggerBootup(uint32 iZoneID, uint32 iInstanceID, const char* a } void ZoneServer::IncomingClient(Client* client) { - BootingUp = true; + is_booting_up = true; auto pack = new ServerPacket(ServerOP_ZoneIncClient, sizeof(ServerZoneIncomingClient_Struct)); ServerZoneIncomingClient_Struct* s = (ServerZoneIncomingClient_Struct*) pack->pBuffer; s->zoneid = GetZoneID(); diff --git a/world/zoneserver.h b/world/zoneserver.h index 125ac33f9..8d26271d1 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -44,7 +44,7 @@ public: void LSBootUpdate(uint32 zoneid, uint32 iInstanceID = 0, bool startup = false); void LSSleepUpdate(uint32 zoneid); void LSShutDownUpdate(uint32 zoneid); - uint32 GetPrevZoneID() { return oldZoneID; } + uint32 GetPrevZoneID() { return zone_server_previous_zone_id; } void ChangeWID(uint32 iCharID, uint32 iWID); void SendGroupIDs(); @@ -52,41 +52,45 @@ public: inline const char* GetZoneLongName() const { return long_name; } const char* GetCompileTime() const{ return compiled; } void SetCompile(char* in_compile){ strcpy(compiled,in_compile); } - inline uint32 GetZoneID() const { return zoneID; } + inline uint32 GetZoneID() const { return zone_server_zone_id; } inline uint32 GetIP() const { return tcpc->GetrIP(); } inline uint16 GetPort() const { return tcpc->GetrPort(); } - inline const char* GetCAddress() const { return clientaddress; } - inline const char* GetCLocalAddress() const { return clientlocaladdress; } - inline uint16 GetCPort() const { return clientport; } - inline uint32 GetID() const { return ID; } - inline bool IsBootingUp() const { return BootingUp; } - inline bool IsStaticZone() const{ return staticzone; } - inline uint32 NumPlayers() const { return pNumPlayers; } - inline void AddPlayer() { pNumPlayers++; } - inline void RemovePlayer() { pNumPlayers--; } + inline const char* GetCAddress() const { return client_address; } + inline const char* GetCLocalAddress() const { return client_local_address; } + inline uint16 GetCPort() const { return client_port; } + inline uint32 GetID() const { return zone_server_id; } + inline bool IsBootingUp() const { return is_booting_up; } + inline bool IsStaticZone() const{ return is_static_zone; } + inline uint32 NumPlayers() const { return zone_player_count; } + inline void AddPlayer() { zone_player_count++; } + inline void RemovePlayer() { zone_player_count--; } inline const char * GetLaunchName() const { return(launcher_name.c_str()); } inline const char * GetLaunchedName() const { return(launched_name.c_str()); } - inline uint32 GetInstanceID() { return instanceID; } - inline void SetInstanceID(uint32 i) { instanceID = i; } + inline uint32 GetInstanceID() { return instance_id; } + inline void SetInstanceID(uint32 i) { instance_id = i; } + + inline uint32 GetZoneOSProcessID() { return zone_os_process_id; } + private: EmuTCPConnection* const tcpc; - uint32 ID; - char clientaddress[250]; - char clientlocaladdress[250]; - uint16 clientport; - bool BootingUp; - bool staticzone; - bool authenticated; - uint32 pNumPlayers; + uint32 zone_server_id; + char client_address[250]; + char client_local_address[250]; + uint16 client_port; + bool is_booting_up; + bool is_static_zone; + bool is_authenticated; + uint32 zone_player_count; char compiled[25]; char zone_name[32]; char long_name[256]; - uint32 zoneID; - uint32 oldZoneID; - Timer ls_zboot; - uint32 instanceID; //instance ids contain a zone id, and a zone version + uint32 zone_server_zone_id; + uint32 zone_server_previous_zone_id; + Timer zone_boot_timer; + uint32 instance_id; //instance ids contain a zone id, and a zone version + uint32 zone_os_process_id; std::string launcher_name; //the launcher which started us std::string launched_name; //the name of the zone we launched. }; diff --git a/zone/bot.cpp b/zone/bot.cpp index ac84ffc5c..29e5e0614 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6,7 +6,7 @@ #include "quest_parser_collection.h" #include "../common/string_util.h" -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; // This constructor is used during the bot create command Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1) { diff --git a/zone/client.cpp b/zone/client.cpp index 24a916b2a..f65a30350 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -53,7 +53,7 @@ extern volatile bool RunLoops; extern QueryServ* QServ; extern EntityList entity_list; extern Zone* zone; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; extern WorldServer worldserver; extern uint32 numclients; extern PetitionList petition_list; @@ -371,7 +371,7 @@ Client::~Client() { GetTarget()->IsTargeted(-1); //if we are in a group and we are not zoning, force leave the group - if(isgrouped && !zoning && ZoneLoaded) + if(isgrouped && !zoning && is_zone_loaded) LeaveGroup(); UpdateWho(2); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index d8ffb6a68..2ee01fe25 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -66,7 +66,7 @@ extern QueryServ* QServ; extern Zone* zone; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; extern WorldServer worldserver; extern PetitionList petition_list; extern EntityList entity_list; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index f7fb46d12..a0be235a7 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -55,7 +55,7 @@ extern QueryServ* QServ; extern Zone* zone; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; extern WorldServer worldserver; extern PetitionList petition_list; extern EntityList entity_list; diff --git a/zone/entity.cpp b/zone/entity.cpp index 69b13e6eb..c427d82d7 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -51,7 +51,7 @@ #endif extern Zone *zone; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; extern WorldServer worldserver; extern NetConnection net; extern uint32 numclients; @@ -2340,7 +2340,7 @@ void EntityList::Clear() void EntityList::UpdateWho(bool iSendFullUpdate) { - if ((!worldserver.Connected()) || !ZoneLoaded) + if ((!worldserver.Connected()) || !is_zone_loaded) return; uint32 tmpNumUpdates = numclients + 5; ServerPacket* pack = 0; diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index a5188def9..8754a60e8 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -29,7 +29,7 @@ ZoneGuildManager guild_mgr; GuildBankManager *GuildBanks; extern WorldServer worldserver; -extern volatile bool ZoneLoaded; +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); @@ -334,7 +334,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { case ServerOP_GuildRankUpdate: { - if(ZoneLoaded) + if(is_zone_loaded) { if(pack->size != sizeof(ServerGuildRankUpdate_Struct)) { @@ -388,7 +388,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { { ServerGuildMemberUpdate_Struct *sgmus = (ServerGuildMemberUpdate_Struct*)pack->pBuffer; - if(ZoneLoaded) + if(is_zone_loaded) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildMemberUpdate, sizeof(GuildMemberUpdate_Struct)); @@ -407,7 +407,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { break; } case ServerOP_OnlineGuildMembersResponse: - if (ZoneLoaded) + if (is_zone_loaded) { char *Buffer = (char *)pack->pBuffer; @@ -443,7 +443,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { case ServerOP_LFGuildUpdate: { - if(ZoneLoaded) + if(is_zone_loaded) { char GuildName[33]; char Comments[257]; diff --git a/zone/merc.cpp b/zone/merc.cpp index 68907fb5b..84f29634b 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -18,7 +18,7 @@ #include "../common/string_util.h" #include "../common/rulesys.h" -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; 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) @@ -5777,7 +5777,7 @@ bool Merc::RemoveMercFromGroup(Merc* merc, Group* group) { { merc->SetFollowID(0); - if (group->GroupCount() <= 2 && merc->GetGroup() == group && ZoneLoaded) + if (group->GroupCount() <= 2 && merc->GetGroup() == group && is_zone_loaded) { group->DisbandGroup(); } diff --git a/zone/net.cpp b/zone/net.cpp index acf217b84..84d338a28 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -84,7 +84,7 @@ #endif volatile bool RunLoops = true; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; TimeoutManager timeout_manager; NetConnection net; @@ -437,12 +437,12 @@ int main(int argc, char** argv) { worldwasconnected = true; } else { - if (worldwasconnected && ZoneLoaded) + if (worldwasconnected && is_zone_loaded) entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost"); worldwasconnected = false; } - if (ZoneLoaded && zoneupdate_timer.Check()) { + if (is_zone_loaded && zoneupdate_timer.Check()) { { if(net.group_timer.Enabled() && net.group_timer.Check()) entity_list.GroupProcess(); diff --git a/zone/npc.cpp b/zone/npc.cpp index 72264a1a2..02b85a2e3 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -53,7 +53,7 @@ #endif extern Zone* zone; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; extern EntityList entity_list; NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int iflymode, bool IsCorpse) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ecb0698e0..c1c3dffda 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -38,7 +38,7 @@ extern Zone* zone; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; extern WorldServer worldserver; diff --git a/zone/spells.cpp b/zone/spells.cpp index 86c489185..6b5707278 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -101,7 +101,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) extern Zone* zone; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; extern WorldServer worldserver; // this is run constantly for every mob diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 029975efe..daf450bff 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -53,7 +53,7 @@ extern EntityList entity_list; extern Zone* zone; -extern volatile bool ZoneLoaded; +extern volatile bool is_zone_loaded; extern void CatchSignal(int); extern WorldServer worldserver; extern NetConnection net; @@ -85,7 +85,7 @@ WorldServer::~WorldServer() { safe_delete(pack); }*/ -void WorldServer::SetZone(uint32 iZoneID, uint32 iInstanceID) { +void WorldServer::SetZoneData(uint32 iZoneID, uint32 iInstanceID) { ServerPacket* pack = new ServerPacket(ServerOP_SetZone, sizeof(SetZone_Struct)); SetZone_Struct* szs = (SetZone_Struct*) pack->pBuffer; szs->zoneid = iZoneID; @@ -99,10 +99,9 @@ void WorldServer::SetZone(uint32 iZoneID, uint32 iInstanceID) { void WorldServer::OnConnected() { WorldConnection::OnConnected(); - ServerPacket* pack; - //tell the launcher what name we were started with. + /* Tell the launcher what our information is */ pack = new ServerPacket(ServerOP_SetLaunchName,sizeof(LaunchName_Struct)); LaunchName_Struct* ln = (LaunchName_Struct*)pack->pBuffer; strn0cpy(ln->launcher_name, m_launcherName.c_str(), 32); @@ -110,28 +109,38 @@ void WorldServer::OnConnected() { SendPacket(pack); safe_delete(pack); + /* Tell the Worldserver basic information about this zone process */ pack = new ServerPacket(ServerOP_SetConnectInfo, sizeof(ServerConnectInfo)); ServerConnectInfo* sci = (ServerConnectInfo*) pack->pBuffer; + auto config = ZoneConfig::get(); sci->port = ZoneConfig::get()->ZonePort; if(config->WorldAddress.length() > 0) { strn0cpy(sci->address, config->WorldAddress.c_str(), 250); } - if(config->LocalAddress.length() > 0) { strn0cpy(sci->local_address, config->LocalAddress.c_str(), 250); } + /* Fetch process ID */ + if (getpid()){ + sci->process_id = getpid(); + } + else { + sci->process_id = 0; + } + SendPacket(pack); safe_delete(pack); - if (ZoneLoaded) { - this->SetZone(zone->GetZoneID(), zone->GetInstanceID()); + if (is_zone_loaded) { + this->SetZoneData(zone->GetZoneID(), zone->GetInstanceID()); entity_list.UpdateWho(true); this->SendEmoteMessage(0, 0, 15, "Zone connect: %s", zone->GetLongName()); - zone->GetTimeSync(); - } else { - this->SetZone(0); + zone->GetTimeSync(); + } + else { + this->SetZoneData(0); } pack = new ServerPacket(ServerOP_LSZoneBoot,sizeof(ZoneBoot_Struct)); @@ -174,7 +183,7 @@ void WorldServer::Process() { break; } case ServerOP_ChannelMessage: { - if (!ZoneLoaded) + if (!is_zone_loaded) break; ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer; if (scm->deliverto[0] == 0) { @@ -207,7 +216,7 @@ void WorldServer::Process() { } case ServerOP_VoiceMacro: { - if (!ZoneLoaded) + if (!is_zone_loaded) break; ServerVoiceMacro_Struct* svm = (ServerVoiceMacro_Struct*) pack->pBuffer; @@ -264,7 +273,7 @@ void WorldServer::Process() { case ServerOP_SpawnCondition: { if(pack->size != sizeof(ServerSpawnCondition_Struct)) break; - if (!ZoneLoaded) + if (!is_zone_loaded) break; ServerSpawnCondition_Struct* ssc = (ServerSpawnCondition_Struct*) pack->pBuffer; @@ -274,7 +283,7 @@ void WorldServer::Process() { case ServerOP_SpawnEvent: { if(pack->size != sizeof(ServerSpawnEvent_Struct)) break; - if (!ZoneLoaded) + if (!is_zone_loaded) break; ServerSpawnEvent_Struct* sse = (ServerSpawnEvent_Struct*) pack->pBuffer; @@ -285,7 +294,7 @@ void WorldServer::Process() { case ServerOP_AcceptWorldEntrance: { if(pack->size != sizeof(WorldToZone_Struct)) break; - if (!ZoneLoaded) + if (!is_zone_loaded) break; WorldToZone_Struct* wtz = (WorldToZone_Struct*) pack->pBuffer; @@ -300,7 +309,7 @@ void WorldServer::Process() { case ServerOP_ZoneToZoneRequest: { if(pack->size != sizeof(ZoneToZone_Struct)) break; - if (!ZoneLoaded) + if (!is_zone_loaded) break; ZoneToZone_Struct* ztz = (ZoneToZone_Struct*) pack->pBuffer; @@ -376,7 +385,7 @@ void WorldServer::Process() { break; } case ServerOP_WhoAllReply:{ - if(!ZoneLoaded) + if(!is_zone_loaded) break; @@ -403,7 +412,7 @@ void WorldServer::Process() { break; } case ServerOP_EmoteMessage: { - if (!ZoneLoaded) + if (!is_zone_loaded) break; ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*) pack->pBuffer; if (sem->to[0] != 0) { @@ -461,8 +470,8 @@ void WorldServer::Process() { break; } // Annouce the change to the world - if (!ZoneLoaded) { - SetZone(0); + if (!is_zone_loaded) { + SetZoneData(0); } else { SendEmoteMessage(0, 0, 15, "Zone shutdown: %s", zone->GetLongName()); @@ -479,8 +488,8 @@ void WorldServer::Process() { break; } ServerZoneStateChange_struct* zst = (ServerZoneStateChange_struct *) pack->pBuffer; - if (ZoneLoaded) { - SetZone(zone->GetZoneID(), zone->GetInstanceID()); + if (is_zone_loaded) { + SetZoneData(zone->GetZoneID(), zone->GetInstanceID()); if (zst->zoneid == zone->GetZoneID()) { // This packet also doubles as "incoming client" notification, lets not shut down before they get here zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); @@ -503,8 +512,8 @@ void WorldServer::Process() { break; } ServerZoneIncomingClient_Struct* szic = (ServerZoneIncomingClient_Struct*) pack->pBuffer; - if (ZoneLoaded) { - SetZone(zone->GetZoneID(), zone->GetInstanceID()); + if (is_zone_loaded) { + SetZoneData(zone->GetZoneID(), zone->GetInstanceID()); if (szic->zoneid == zone->GetZoneID()) { zone->AddAuth(szic); // This packet also doubles as "incoming client" notification, lets not shut down before they get here @@ -540,7 +549,7 @@ void WorldServer::Process() { if (client != 0) { if (skp->adminrank >= client->Admin()) { client->WorldKick(); - if (ZoneLoaded) + if (is_zone_loaded) SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: %s booted in zone %s.", skp->name, zone->GetShortName()); else SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: %s booted.", skp->name); @@ -556,7 +565,7 @@ void WorldServer::Process() { if (client != 0) { if (skp->admin >= client->Admin()) { client->GMKill(); - if (ZoneLoaded) + if (is_zone_loaded) SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: %s killed in zone %s.", skp->target, zone->GetShortName()); else SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: %s killed.", skp->target); @@ -594,7 +603,7 @@ void WorldServer::Process() { std::cout << "Wrong size on ServerOP_GMGoto. Got: " << pack->size << ", Expected: " << sizeof(ServerGMGoto_Struct) << std::endl; break; } - if (!ZoneLoaded) + if (!is_zone_loaded) break; ServerGMGoto_Struct* gmg = (ServerGMGoto_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(gmg->gotoname); diff --git a/zone/worldserver.h b/zone/worldserver.h index c1e86421f..e1831ea4c 100644 --- a/zone/worldserver.h +++ b/zone/worldserver.h @@ -37,7 +37,7 @@ public: bool SendEmoteMessage(const char* to, uint32 to_guilddbid, uint32 type, const char* message, ...); bool SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...); bool SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 MacroNumber, uint32 GroupOrRaidID = 0); - void SetZone(uint32 iZoneID, uint32 iInstanceID = 0); + void SetZoneData(uint32 iZoneID, uint32 iInstanceID = 0); uint32 SendGroupIdRequest(); bool RezzPlayer(EQApplicationPacket* rpack, uint32 rezzexp, uint32 dbid, uint16 opcode); bool IsOOCMuted() const { return(oocmuted); } diff --git a/zone/zone.cpp b/zone/zone.cpp index 63730d0aa..14c0674c6 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -74,7 +74,7 @@ extern Zone* zone; Mutex MZoneShutdown; -volatile bool ZoneLoaded = false; +volatile bool is_zone_loaded = false; Zone* zone = 0; bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { @@ -82,9 +82,9 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { if (iZoneID == 0 || zonename == 0) return false; - if (zone != 0 || ZoneLoaded) { + if (zone != 0 || is_zone_loaded) { std::cerr << "Error: Zone::Bootup call when zone already booted!" << std::endl; - worldserver.SetZone(0); + worldserver.SetZoneData(0); return false; } @@ -97,7 +97,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { if (!zone->Init(iStaticZone)) { safe_delete(zone); std::cerr << "Zone->Init failed" << std::endl; - worldserver.SetZone(0); + worldserver.SetZoneData(0); return false; } zone->zonemap = Map::LoadMapFile(zone->map_name); @@ -131,9 +131,9 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { } } - ZoneLoaded = true; + is_zone_loaded = true; - worldserver.SetZone(iZoneID, iInstanceID); + worldserver.SetZoneData(iZoneID, iInstanceID); if(iInstanceID != 0) { ServerPacket *pack = new ServerPacket(ServerOP_AdventureZoneData, sizeof(uint16)); @@ -660,12 +660,12 @@ void Zone::LoadMercSpells(){ } bool Zone::IsLoaded() { - return ZoneLoaded; + return is_zone_loaded; } void Zone::Shutdown(bool quite) { - if (!ZoneLoaded) + if (!is_zone_loaded) return; entity_list.StopMobAI(); @@ -699,7 +699,7 @@ void Zone::Shutdown(bool quite) zone->SetZoneHasCurrentTime(false); if (!quite) Log.Out(Logs::General, Logs::Normal, "Zone shutdown: going to sleep"); - ZoneLoaded = false; + is_zone_loaded = false; zone->ResetAuth(); safe_delete(zone); @@ -846,7 +846,7 @@ Zone::~Zone() { safe_delete(watermap); safe_delete(pathing); if (worldserver.Connected()) { - worldserver.SetZone(0); + worldserver.SetZoneData(0); } safe_delete_array(short_name); safe_delete_array(long_name); From 53c8d63981e7068555cffdd6e1a6a9280fcaf543 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 15:59:24 -0600 Subject: [PATCH 373/846] Implement Perl Export Variable settings map (Huge performance boost) (Preliminary) --- common/database.h | 1 + common/eqemu_logsys.cpp | 2 +- common/servertalk.h | 1 + world/zonelist.cpp | 2 +- world/zoneserver.cpp | 5 ++++ zone/command.cpp | 13 +++++++++++ zone/command.h | 1 + zone/embparser.cpp | 35 ++++++++++++++++++++-------- zone/embparser.h | 1 + zone/net.cpp | 5 ++++ zone/quest_parser_collection.cpp | 39 ++++++++++++++++++++++++++++++++ zone/quest_parser_collection.h | 21 +++++++++++++++++ zone/worldserver.cpp | 8 +++++++ zone/zonedb.cpp | 6 ++--- zone/zonedb.h | 1 + 15 files changed, 126 insertions(+), 15 deletions(-) diff --git a/common/database.h b/common/database.h index c3771f67c..f066cb417 100644 --- a/common/database.h +++ b/common/database.h @@ -23,6 +23,7 @@ #include "global_define.h" #include "eqemu_logsys.h" + #include "types.h" #include "dbcore.h" #include "linked_list.h" diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 36176c399..189c45bf6 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -116,7 +116,7 @@ void EQEmuLogSys::LoadLogSettingsDefaults() platform_file_name = "ucs"; else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) platform_file_name = "login"; - else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) + else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) platform_file_name = "launcher"; } diff --git a/common/servertalk.h b/common/servertalk.h index ee5e41a52..e7ce947c5 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -182,6 +182,7 @@ #define ServerOP_CZMessagePlayer 0x4008 #define ServerOP_ReloadWorld 0x4009 #define ServerOP_ReloadLogs 0x4010 +#define ServerOP_ReloadPerlExportSettings 0x4011 /* Query Server OP Codes */ #define ServerOP_QSPlayerLogTrades 0x5010 #define ServerOP_QSPlayerLogHandins 0x5011 diff --git a/world/zonelist.cpp b/world/zonelist.cpp index a887a4d43..3332e0578 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -349,7 +349,7 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con } AppendAnyLenString(&output, &outsize, &outlen, - "#%-3i :: %s :: %15s:%-5i :: %2i :: %s:%i :: %s :: (%u)", + "#%-3i :: %s :: %15s:%-5i :: %2i :: %s:%i :: %s :: (%u)", zone_server_data->GetID(), is_static_string, inet_ntoa(in), diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 207beacd1..f6447f3f4 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -826,6 +826,11 @@ bool ZoneServer::Process() { RuleManager::Instance()->LoadRules(&database, "default"); break; } + case ServerOP_ReloadPerlExportSettings: + { + zoneserver_list.SendPacket(pack); + break; + } case ServerOP_CameraShake: { zoneserver_list.SendPacket(pack); diff --git a/zone/command.cpp b/zone/command.cpp index 5fe6244ad..db41619f4 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -334,6 +334,7 @@ int command_init(void) { command_add("reloadallrules", "Executes a reload of all rules.", 80, command_reloadallrules) || command_add("reloademote", "Reloads NPC Emotes", 80, command_reloademote) || command_add("reloadlevelmods", nullptr,255, command_reloadlevelmods) || + command_add("reloadperlexportsettings", nullptr, 255, command_reloadperlexportsettings) || command_add("reloadqst", " - Clear quest cache (any argument causes it to also stop all timers)", 150, command_reloadqst) || command_add("reloadquest", " - Clear quest cache (any argument causes it to also stop all timers)", 150, command_reloadqst) || command_add("reloadrulesworld", "Executes a reload of all rules in world specifically.", 80, command_reloadworldrules) || @@ -10768,4 +10769,16 @@ void command_apply_shared_memory(Client *c, const Seperator *sep) { strcpy((char*)pack.pBuffer, hotfix_name.c_str()); } worldserver.SendPacket(&pack); +} + +void command_reloadperlexportsettings(Client *c, const Seperator *sep) +{ + if (c) + { + ServerPacket *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); + + } } \ No newline at end of file diff --git a/zone/command.h b/zone/command.h index 03e30a786..e4130cfff 100644 --- a/zone/command.h +++ b/zone/command.h @@ -332,6 +332,7 @@ void command_load_shared_memory(Client *c, const Seperator *sep); void command_apply_shared_memory(Client *c, const Seperator *sep); void command_untraindisc(Client *c, const Seperator *sep); void command_untraindiscs(Client *c, const Seperator *sep); +void command_reloadperlexportsettings(Client *c, const Seperator *sep); #ifdef EQPROFILE void command_profiledump(Client *c, const Seperator *sep); diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 389f93d1f..617d17d2e 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -183,15 +183,31 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da int char_id = 0; ExportCharID(package_name, char_id, npcmob, mob); - ExportQGlobals(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, - package_name, npcmob, mob, char_id); + + /* Check for QGlobal export event enable */ + if (parse->perl_event_export_settings[event].qglobals){ + ExportQGlobals(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, package_name, npcmob, mob, char_id); + } - //ExportGenericVariables(); - ExportMobVariables(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, - package_name, mob, npcmob); - ExportZoneVariables(package_name); - ExportItemVariables(package_name, mob); - ExportEventVariables(package_name, event, objid, data, npcmob, iteminst, mob, extradata, extra_pointers); + /* Check for Mob export event enable */ + if (parse->perl_event_export_settings[event].mob){ + ExportMobVariables(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, package_name, mob, npcmob); + } + + /* Check for Zone export event enable */ + if (parse->perl_event_export_settings[event].zone){ + ExportZoneVariables(package_name); + } + + /* Check for Item export event enable */ + if (parse->perl_event_export_settings[event].item){ + ExportItemVariables(package_name, mob); + } + + /* 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); + } if(isPlayerQuest || isGlobalPlayerQuest){ return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr); @@ -199,8 +215,7 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da else if(isItemQuest) { return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, iteminst); } - else if(isSpellQuest) - { + else if(isSpellQuest){ if(mob) { return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr); } else { diff --git a/zone/embparser.h b/zone/embparser.h index 1357ae20b..9b33b1ad2 100644 --- a/zone/embparser.h +++ b/zone/embparser.h @@ -75,6 +75,7 @@ public: virtual std::string GetVar(std::string name); virtual void ReloadQuests(); virtual uint32 GetIdentifier() { return 0xf8b05c11; } + private: Embperl *perl; diff --git a/zone/net.cpp b/zone/net.cpp index 84d338a28..d950fc15a 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -110,6 +110,7 @@ extern void MapOpcodes(); int main(int argc, char** argv) { RegisterExecutablePlatform(ExePlatformZone); Log.LoadLogSettingsDefaults(); + set_exception_handler(); QServ = new QueryServ; @@ -339,6 +340,10 @@ int main(int argc, char** argv) { #ifdef EMBPERL PerlembParser *perl_parser = new PerlembParser(); parse->RegisterQuestInterface(perl_parser, "pl"); + + /* Load Perl Event Export Settings */ + parse->LoadPerlEventExportSettings(parse->perl_event_export_settings); + #endif //now we have our parser, load the quests diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 845769532..1f4f99c0e 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -1032,3 +1032,42 @@ int QuestParserCollection::DispatchEventSpell(QuestEventID evt, NPC* npc, Client } return ret; } + +void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings* perl_event_export_settings) { + + Log.Out(Logs::General, Logs::Zone_Server, "Loading Perl Event Export Settings..."); + + /* Write Defaults First (All Enabled) */ + for (int i = 0; i < _LargestEventID; i++){ + perl_event_export_settings[i].qglobals = 1; + perl_event_export_settings[i].mob = 1; + perl_event_export_settings[i].zone = 1; + perl_event_export_settings[i].item = 1; + perl_event_export_settings[i].event_variables = 1; + } + + std::string query = + "SELECT " + "event_id, " + "event_description, " + "export_qglobals, " + "export_mob, " + "export_zone, " + "export_item, " + "export_event " + "FROM " + "perl_event_export_settings " + "ORDER BY event_id"; + + int event_id = 0; + auto results = database.QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + event_id = atoi(row[0]); + perl_event_export_settings[event_id].qglobals = atoi(row[2]); + perl_event_export_settings[event_id].mob = atoi(row[3]); + perl_event_export_settings[event_id].zone = atoi(row[4]); + perl_event_export_settings[event_id].item = atoi(row[5]); + 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 3ebce378c..7a0cec274 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -77,6 +77,27 @@ public: void GetErrors(std::list &err); + /* + Internally used memory reference for all Perl Event Export Settings + Some exports are very taxing on CPU given how much an event is called. + + These are loaded via DB and have defaults loaded in PerlEventExportSettingsDefaults. + + Database loaded via Database::LoadPerlEventExportSettings(log_settings) + */ + + struct PerlEventExportSettings { + uint8 qglobals; + uint8 mob; + uint8 zone; + uint8 item; + uint8 event_variables; + }; + + PerlEventExportSettings perl_event_export_settings[_LargestEventID]; + + void LoadPerlEventExportSettings(PerlEventExportSettings* perl_event_export_settings); + private: bool HasQuestSubLocal(uint32 npcid, QuestEventID evt); bool HasQuestSubGlobal(QuestEventID evt); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index daf450bff..5f32992bc 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -39,6 +39,7 @@ #include "client.h" #include "corpse.h" #include "entity.h" +#include "quest_parser_collection.h" #include "guild_mgr.h" #include "mob.h" #include "net.h" @@ -60,6 +61,9 @@ extern NetConnection net; extern PetitionList petition_list; extern uint32 numclients; extern volatile bool RunLoops; +extern QuestParserCollection *parse; + +// QuestParserCollection *parse = 0; WorldServer::WorldServer() : WorldConnection(EmuTCPConnection::packetModeZone) @@ -1742,6 +1746,10 @@ void WorldServer::Process() { database.LoadLogSettings(Log.log_settings); break; } + case ServerOP_ReloadPerlExportSettings: { + parse->LoadPerlEventExportSettings(parse->perl_event_export_settings); + break; + } case ServerOP_CameraShake: { if(zone) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e92704fe6..591f8c3d3 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -46,7 +46,7 @@ void ZoneDatabase::ZDBInitVars() { ZoneDatabase::~ZoneDatabase() { unsigned int x; if (npc_spells_cache) { - for (x=0; x<=npc_spells_maxid; x++) { + for (x = 0; x <= npc_spells_maxid; x++) { safe_delete_array(npc_spells_cache[x]); } safe_delete_array(npc_spells_cache); @@ -54,7 +54,7 @@ ZoneDatabase::~ZoneDatabase() { safe_delete_array(npc_spells_loadtried); if (npc_spellseffects_cache) { - for (x=0; x<=npc_spellseffects_maxid; x++) { + for (x = 0; x <= npc_spellseffects_maxid; x++) { safe_delete_array(npc_spellseffects_cache[x]); } safe_delete_array(npc_spellseffects_cache); @@ -62,7 +62,7 @@ ZoneDatabase::~ZoneDatabase() { safe_delete_array(npc_spellseffects_loadtried); if (faction_array != nullptr) { - for (x=0; x <= max_faction; x++) { + for (x = 0; x <= max_faction; x++) { if (faction_array[x] != 0) safe_delete(faction_array[x]); } diff --git a/zone/zonedb.h b/zone/zonedb.h index 9b2a5105b..f49a9bf0d 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -7,6 +7,7 @@ #include "../common/faction.h" #include "../common/eqemu_logsys.h" #include "aa_ability.h" +#include "event_codes.h" class Client; class Corpse; From 624c7341c5a5ad8d86fb768dc0607e004a306fd1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 16:02:41 -0600 Subject: [PATCH 374/846] Refactor cfp to currently_fleeing for readability --- zone/bot.cpp | 2 +- zone/fearpath.cpp | 14 +++++++------- zone/merc.cpp | 2 +- zone/mob.cpp | 4 ++-- zone/mob.h | 2 +- zone/mob_ai.cpp | 4 ++-- zone/npc.cpp | 2 +- zone/spell_effects.cpp | 12 ++++++------ 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 29e5e0614..c57d17aaf 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2286,7 +2286,7 @@ bool Bot::Process() { BuffProcess(); CalcRestState(); - if(curfp) + if(currently_fleeing) ProcessFlee(); if(GetHP() < GetMaxHP()) diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index 0fd5ffa98..bbcf4d4c6 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -33,7 +33,7 @@ extern Zone* zone; //this is called whenever we are damaged to process possible fleeing void Mob::CheckFlee() { //if were allready fleeing, dont need to check more... - if(flee_mode && curfp) + if(flee_mode && currently_fleeing) return; //dont bother if we are immune to fleeing @@ -101,7 +101,7 @@ void Mob::ProcessFlee() //When ImmuneToFlee effect fades it will turn fear back on and check if it can still flee. if (flee_mode && (GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) && !spellbonuses.IsFeared && !spellbonuses.IsBlind) { - curfp = false; + currently_fleeing = false; return; } @@ -118,7 +118,7 @@ void Mob::ProcessFlee() //see if we are legitimately feared or blind now if (!spellbonuses.IsFeared && !spellbonuses.IsBlind) { //not feared or blind... were done... - curfp = false; + currently_fleeing = false; return; } } @@ -140,7 +140,7 @@ void Mob::CalculateNewFearpoint() if(Route.size() > 0) { m_FearWalkTarget = glm::vec3(Loc.x, Loc.y, Loc.z); - curfp = true; + currently_fleeing = true; Log.Out(Logs::Detail, Logs::None, "Feared to node %i (%8.3f, %8.3f, %8.3f)", Node, Loc.x, Loc.y, Loc.z); return; @@ -151,7 +151,7 @@ void Mob::CalculateNewFearpoint() int loop = 0; float ranx, rany, ranz; - curfp = false; + currently_fleeing = false; while (loop < 100) //Max 100 tries { int ran = 250 - (loop*2); @@ -164,11 +164,11 @@ void Mob::CalculateNewFearpoint() float fdist = ranz - GetZ(); if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(),GetY(),GetZ(),ranx,rany,ranz)) { - curfp = true; + currently_fleeing = true; break; } } - if (curfp) + if (currently_fleeing) m_FearWalkTarget = glm::vec3(ranx, rany, ranz); else //Break fear BuffFadeByEffect(SE_Fear); diff --git a/zone/merc.cpp b/zone/merc.cpp index 84f29634b..18ca17abd 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1428,7 +1428,7 @@ void Merc::AI_Process() { if(RuleB(Combat, EnableFearPathing)) { CalculateNewFearpoint(); - if(curfp) { + if(currently_fleeing) { return; } } diff --git a/zone/mob.cpp b/zone/mob.cpp index 82875d451..eccf04a76 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -113,7 +113,7 @@ Mob::Mob(const char* in_name, targeted = 0; tar_ndx=0; tar_vector=0; - curfp = false; + currently_fleeing = false; AI_Init(); SetMoving(false); @@ -371,7 +371,7 @@ Mob::Mob(const char* in_name, follow=0; follow_dist = 100; // Default Distance for Follow flee_mode = false; - curfp = false; + currently_fleeing = false; flee_timer.Start(); permarooted = (runspeed > 0) ? false : true; diff --git a/zone/mob.h b/zone/mob.h index 5032abcf6..7fff5a1c4 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1295,7 +1295,7 @@ protected: int patrol; glm::vec3 m_FearWalkTarget; - bool curfp; + bool currently_fleeing; // Pathing // diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 3f3911c8d..4ac408055 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -759,7 +759,7 @@ void Client::AI_Process() } if(RuleB(Combat, EnableFearPathing)){ - if(curfp) { + if(currently_fleeing) { if(IsRooted()) { //make sure everybody knows were not moving, for appearance sake if(IsMoving()) @@ -955,7 +955,7 @@ void Mob::AI_Process() { // Begin: Additions for Wiz Fear Code // if(RuleB(Combat, EnableFearPathing)){ - if(curfp) { + if(currently_fleeing) { if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) { //make sure everybody knows were not moving, for appearance sake if(IsMoving()) diff --git a/zone/npc.cpp b/zone/npc.cpp index 02b85a2e3..ebdd8a79d 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -605,7 +605,7 @@ bool NPC::Process() parse->EventNPC(EVENT_TICK, this, nullptr, "", 0); BuffProcess(); - if(curfp) + if(currently_fleeing) ProcessFlee(); uint32 bonus = 0; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index c1c3dffda..4b92fc688 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -864,7 +864,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } CalculateNewFearpoint(); - if(curfp) + if(currently_fleeing) { break; } @@ -3944,8 +3944,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) } case SE_Blind: - if (curfp && !FindType(SE_Fear)) - curfp = false; + if (currently_fleeing && !FindType(SE_Fear)) + currently_fleeing = false; break; case SE_Fear: @@ -3958,8 +3958,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) CastToClient()->AI_Stop(); } - if(curfp) { - curfp = false; + if(currently_fleeing) { + currently_fleeing = false; break; } } @@ -3974,7 +3974,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) { if(RuleB(Combat, EnableFearPathing)){ if(flee_mode) { - curfp = true; + currently_fleeing = true; CheckFlee(); break; } From e5ad5e13db7042cf847df92d324bf79e53ad3c2f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 16:11:25 -0600 Subject: [PATCH 375/846] Comment out Log.Out super hot path line --- zone/waypoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index e900c6838..34ec6eef7 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -484,7 +484,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): Jumping pure Z.", x, y, z); return true; } - Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f) inWater=%d: We are there.", x, y, z, inWater); + // Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f) inWater=%d: We are there.", x, y, z, inWater); return false; } else if ((std::abs(m_Position.x - x) < 0.1) && (std::abs(m_Position.y - y) < 0.1)) { Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): X/Y difference <0.1, Jumping to target.", x, y, z); From 2a69ae42ee36853bfa13f9685cdd72ab699234c3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 17:02:52 -0600 Subject: [PATCH 376/846] (Performance) Rate limit the rate in which signals are processed for NPC's --- common/features.h | 1 + zone/mob.h | 1 + zone/mob_ai.cpp | 7 ++++++- zone/net.cpp | 8 ++++---- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/common/features.h b/common/features.h index 44f83c648..2ede4b4be 100644 --- a/common/features.h +++ b/common/features.h @@ -159,6 +159,7 @@ enum { //timer settings, all in milliseconds AItarget_check_duration = 500, 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, CombatEventTimer_expire = 12000, Tribute_duration = 600000, diff --git a/zone/mob.h b/zone/mob.h index 7fff5a1c4..a45dd464d 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1262,6 +1262,7 @@ protected: std::unique_ptr AIscanarea_timer; std::unique_ptr AIwalking_timer; std::unique_ptr AIfeignremember_timer; + std::unique_ptr AI_check_signal_timer; uint32 pLastFightingDelayMoving; HateList hate_list; std::set feign_memory_list; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 4ac408055..fca550499 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -429,6 +429,8 @@ void Mob::AI_Init() AItarget_check_timer.reset(nullptr); AIfeignremember_timer.reset(nullptr); AIscanarea_timer.reset(nullptr); + AI_check_signal_timer.reset(nullptr); + minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); @@ -479,6 +481,8 @@ void Mob::AI_Start(uint32 iMoveDelay) { AItarget_check_timer = std::unique_ptr(new Timer(AItarget_check_duration)); AIfeignremember_timer = std::unique_ptr(new Timer(AIfeignremember_delay)); AIscanarea_timer = std::unique_ptr(new Timer(AIscanarea_delay)); + AI_check_signal_timer = std::unique_ptr(new Timer(AI_check_signal_timer_delay)); + #ifdef REVERSE_AGGRO if(IsNPC() && !CastToNPC()->WillAggroNPCs()) AIscanarea_timer->Disable(); @@ -544,6 +548,7 @@ void Mob::AI_Stop() { AItarget_check_timer.reset(nullptr); AIscanarea_timer.reset(nullptr); AIfeignremember_timer.reset(nullptr); + AI_check_signal_timer.reset(nullptr); hate_list.WipeHateList(); } @@ -998,7 +1003,7 @@ void Mob::AI_Process() { } // trigger EVENT_SIGNAL if required - if(IsNPC()) { + if (AI_check_signal_timer->Check() && IsNPC()) { CastToNPC()->CheckSignal(); } diff --git a/zone/net.cpp b/zone/net.cpp index d950fc15a..0d5d546d6 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -393,10 +393,10 @@ int main(int argc, char** argv) { worldserver.Process(); - if (!eqsf.IsOpen() && Config->ZonePort!=0) { - Log.Out(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d",Config->ZonePort); + if (!eqsf.IsOpen() && Config->ZonePort != 0) { + Log.Out(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort); if (!eqsf.Open(Config->ZonePort)) { - Log.Out(Logs::General, Logs::Error, "Failed to open port %d",Config->ZonePort); + Log.Out(Logs::General, Logs::Error, "Failed to open port %d", Config->ZonePort); ZoneConfig::SetZonePort(0); worldserver.Disconnect(); worldwasconnected = false; @@ -410,7 +410,7 @@ int main(int argc, char** argv) { //structures and opcodes for that patch. struct in_addr in; in.s_addr = eqss->GetRemoteIP(); - Log.Out(Logs::Detail, Logs::World_Server, "New connection from %s:%d", inet_ntoa(in),ntohs(eqss->GetRemotePort())); + Log.Out(Logs::Detail, Logs::World_Server, "New connection from %s:%d", inet_ntoa(in), ntohs(eqss->GetRemotePort())); stream_identifier.AddStream(eqss); //takes the stream } From ce0011ab1872c4a5b7d5dccda695eaced252c3da Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 17:12:14 -0600 Subject: [PATCH 377/846] Renaming of some timers --- zone/aggro.cpp | 16 ++++----- zone/bot.cpp | 10 +++--- zone/merc.cpp | 8 ++--- zone/mob.h | 16 ++++----- zone/mob_ai.cpp | 82 +++++++++++++++++++++++----------------------- zone/waypoints.cpp | 24 +++++++------- 6 files changed, 78 insertions(+), 78 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 574ac335d..a1903c8ca 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1189,21 +1189,21 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib } void Mob::AddFeignMemory(Client* attacker) { - if(feign_memory_list.empty() && AIfeignremember_timer != nullptr) - AIfeignremember_timer->Start(AIfeignremember_delay); + if(feign_memory_list.empty() && AI_feign_remember_timer != nullptr) + AI_feign_remember_timer->Start(AIfeignremember_delay); feign_memory_list.insert(attacker->CharacterID()); } void Mob::RemoveFromFeignMemory(Client* attacker) { feign_memory_list.erase(attacker->CharacterID()); - if(feign_memory_list.empty() && AIfeignremember_timer != nullptr) - AIfeignremember_timer->Disable(); + if(feign_memory_list.empty() && AI_feign_remember_timer != nullptr) + AI_feign_remember_timer->Disable(); if(feign_memory_list.empty()) { minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); - if(AIfeignremember_timer != nullptr) - AIfeignremember_timer->Disable(); + if(AI_feign_remember_timer != nullptr) + AI_feign_remember_timer->Disable(); } } @@ -1220,8 +1220,8 @@ void Mob::ClearFeignMemory() { feign_memory_list.clear(); minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); - if(AIfeignremember_timer != nullptr) - AIfeignremember_timer->Disable(); + if(AI_feign_remember_timer != nullptr) + AI_feign_remember_timer->Disable(); } bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) { diff --git a/zone/bot.cpp b/zone/bot.cpp index c57d17aaf..6a684aeac 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2685,7 +2685,7 @@ void Bot::AI_Process() { if(GetHasBeenSummoned()) { if(IsBotCaster() || IsBotArcher()) { - if (AImovement_timer->Check()) { + if (AI_movement_timer->Check()) { if(!GetTarget() || (IsBotCaster() && !IsBotCasterCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistanceSquaredNoZ(static_cast(m_Position), m_PreSummonLocation) < 10)) { if(GetTarget()) FaceTarget(GetTarget()); @@ -2831,7 +2831,7 @@ void Bot::AI_Process() { } } - if(AImovement_timer->Check()) { + if(AI_movement_timer->Check()) { if(!IsMoving() && GetClass() == ROGUE && !BehindMob(GetTarget(), GetX(), GetY())) { // Move the rogue to behind the mob float newX = 0; @@ -2967,7 +2967,7 @@ void Bot::AI_Process() { AI_PursueCastCheck(); } - if (AImovement_timer->Check()) { + 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()); @@ -2995,7 +2995,7 @@ void Bot::AI_Process() { if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); - if(!IsMoving() && AIthink_timer->Check() && !spellend_timer.Enabled()) { + if(!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled()) { if(GetBotStance() != BotStancePassive) { if(!AI_IdleCastCheck() && !IsCasting()) BotMeditate(true); @@ -3004,7 +3004,7 @@ void Bot::AI_Process() { BotMeditate(true); } - if(AImovement_timer->Check()) { + if(AI_movement_timer->Check()) { if(GetFollowID()) { Mob* follow = entity_list.GetMob(GetFollowID()); if(follow) { diff --git a/zone/merc.cpp b/zone/merc.cpp index 18ca17abd..b4125735e 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1500,7 +1500,7 @@ void Merc::AI_Process() { } } - if(AImovement_timer->Check()) + if(AI_movement_timer->Check()) { if(!IsMoving() && GetClass() == ROGUE && !BehindMob(GetTarget(), GetX(), GetY())) { @@ -1645,7 +1645,7 @@ void Merc::AI_Process() { AI_PursueCastCheck(); } - if (AImovement_timer->Check()) + if (AI_movement_timer->Check()) { if(!IsRooted()) { Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName()); @@ -1687,7 +1687,7 @@ void Merc::AI_Process() { if(!check_target_timer.Enabled()) check_target_timer.Start(2000, false); - if(!IsMoving() && AIthink_timer->Check() && !spellend_timer.Enabled()) + if(!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled()) { //TODO: Implement passive stances. //if(GetStance() != MercStancePassive) { @@ -1698,7 +1698,7 @@ void Merc::AI_Process() { } } - if(AImovement_timer->Check()) + if(AI_movement_timer->Check()) { if(GetFollowID()) { diff --git a/zone/mob.h b/zone/mob.h index a45dd464d..2ca027023 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -925,8 +925,8 @@ public: virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; } inline bool IsTrackable() const { return(trackable); } - Timer* GetAIThinkTimer() { return AIthink_timer.get(); } - Timer* GetAIMovementTimer() { return AImovement_timer.get(); } + Timer* GetAIThinkTimer() { return AI_think_timer.get(); } + Timer* GetAIMovementTimer() { return AI_movement_timer.get(); } Timer GetAttackTimer() { return attack_timer; } Timer GetAttackDWTimer() { return attack_dw_timer; } inline bool IsFindable() { return findable; } @@ -1254,14 +1254,14 @@ protected: uint32 maxLastFightingDelayMoving; float pAggroRange; float pAssistRange; - std::unique_ptr AIthink_timer; - std::unique_ptr AImovement_timer; - std::unique_ptr AItarget_check_timer; + std::unique_ptr AI_think_timer; + std::unique_ptr AI_movement_timer; + std::unique_ptr AI_target_check_timer; bool movetimercompleted; bool permarooted; - std::unique_ptr AIscanarea_timer; - std::unique_ptr AIwalking_timer; - std::unique_ptr AIfeignremember_timer; + std::unique_ptr AI_scan_area_timer; + std::unique_ptr AI_walking_timer; + std::unique_ptr AI_feign_remember_timer; std::unique_ptr AI_check_signal_timer; uint32 pLastFightingDelayMoving; HateList hate_list; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index fca550499..b16a3819e 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -423,12 +423,12 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float void Mob::AI_Init() { pAIControlled = false; - AIthink_timer.reset(nullptr); - AIwalking_timer.reset(nullptr); - AImovement_timer.reset(nullptr); - AItarget_check_timer.reset(nullptr); - AIfeignremember_timer.reset(nullptr); - AIscanarea_timer.reset(nullptr); + AI_think_timer.reset(nullptr); + AI_walking_timer.reset(nullptr); + AI_movement_timer.reset(nullptr); + AI_target_check_timer.reset(nullptr); + AI_feign_remember_timer.reset(nullptr); + AI_scan_area_timer.reset(nullptr); AI_check_signal_timer.reset(nullptr); minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); @@ -474,18 +474,18 @@ void Mob::AI_Start(uint32 iMoveDelay) { pLastFightingDelayMoving = 0; pAIControlled = true; - AIthink_timer = std::unique_ptr(new Timer(AIthink_duration)); - AIthink_timer->Trigger(); - AIwalking_timer = std::unique_ptr(new Timer(0)); - AImovement_timer = std::unique_ptr(new Timer(AImovement_duration)); - AItarget_check_timer = std::unique_ptr(new Timer(AItarget_check_duration)); - AIfeignremember_timer = std::unique_ptr(new Timer(AIfeignremember_delay)); - AIscanarea_timer = std::unique_ptr(new Timer(AIscanarea_delay)); + AI_think_timer = std::unique_ptr(new Timer(AIthink_duration)); + AI_think_timer->Trigger(); + AI_walking_timer = std::unique_ptr(new Timer(0)); + AI_movement_timer = std::unique_ptr(new Timer(AImovement_duration)); + AI_target_check_timer = std::unique_ptr(new Timer(AItarget_check_duration)); + AI_feign_remember_timer = std::unique_ptr(new Timer(AIfeignremember_delay)); + AI_scan_area_timer = std::unique_ptr(new Timer(AIscanarea_delay)); AI_check_signal_timer = std::unique_ptr(new Timer(AI_check_signal_timer_delay)); #ifdef REVERSE_AGGRO if(IsNPC() && !CastToNPC()->WillAggroNPCs()) - AIscanarea_timer->Disable(); + AI_scan_area_timer->Disable(); #endif if (GetAggroRange() == 0) @@ -542,12 +542,12 @@ void Mob::AI_Stop() { pAIControlled = false; - AIthink_timer.reset(nullptr); - AIwalking_timer.reset(nullptr); - AImovement_timer.reset(nullptr); - AItarget_check_timer.reset(nullptr); - AIscanarea_timer.reset(nullptr); - AIfeignremember_timer.reset(nullptr); + AI_think_timer.reset(nullptr); + AI_walking_timer.reset(nullptr); + AI_movement_timer.reset(nullptr); + AI_target_check_timer.reset(nullptr); + AI_scan_area_timer.reset(nullptr); + AI_feign_remember_timer.reset(nullptr); AI_check_signal_timer.reset(nullptr); hate_list.WipeHateList(); @@ -730,7 +730,7 @@ void Client::AI_Process() if (!IsAIControlled()) return; - if (!(AIthink_timer->Check() || attack_timer.Check(false))) + if (!(AI_think_timer->Check() || attack_timer.Check(false))) return; if (IsCasting()) @@ -776,7 +776,7 @@ void Client::AI_Process() //continue on to attack code, ensuring that we execute the engaged code engaged = true; } else { - if(AImovement_timer->Check()) { + if(AI_movement_timer->Check()) { int speed = GetFearSpeed(); animation = speed; speed *= 2; @@ -813,7 +813,7 @@ void Client::AI_Process() SetTarget(hate_list.GetClosestEntOnHateList(this)); else { - if(AItarget_check_timer->Check()) + if(AI_target_check_timer->Check()) { SetTarget(hate_list.GetEntWithMostHateOnList(this)); } @@ -837,7 +837,7 @@ void Client::AI_Process() DoClassAttacks(GetTarget()); } - if (AImovement_timer->Check()) { + if (AI_movement_timer->Check()) { if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) { SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); @@ -863,7 +863,7 @@ void Client::AI_Process() } else { if(!IsRooted()) { - if(AImovement_timer->Check()) + if(AI_movement_timer->Check()) { int newspeed = GetRunspeed(); animation = newspeed; @@ -894,7 +894,7 @@ void Client::AI_Process() } else { - if(AIfeignremember_timer->Check()) { + if(AI_feign_remember_timer->Check()) { std::set::iterator RememberedCharID; RememberedCharID = feign_memory_list.begin(); while (RememberedCharID != feign_memory_list.end()) { @@ -922,7 +922,7 @@ void Client::AI_Process() float dist = DistanceSquared(m_Position, owner->GetPosition()); if (dist >= 400) { - if(AImovement_timer->Check()) + if(AI_movement_timer->Check()) { int nspeed = (dist >= 5625 ? GetRunspeed() : GetWalkspeed()); animation = nspeed; @@ -948,7 +948,7 @@ void Mob::AI_Process() { if (!IsAIControlled()) return; - if (!(AIthink_timer->Check() || attack_timer.Check(false))) + if (!(AI_think_timer->Check() || attack_timer.Check(false))) return; if (IsCasting()) @@ -973,7 +973,7 @@ void Mob::AI_Process() { //continue on to attack code, ensuring that we execute the engaged code engaged = true; } else { - if(AImovement_timer->Check()) { + if(AI_movement_timer->Check()) { // Check if we have reached the last fear point if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) && (std::abs(GetY() - m_FearWalkTarget.y) < 0.1)) { @@ -1017,7 +1017,7 @@ void Mob::AI_Process() { SetTarget(hate_list.GetClosestEntOnHateList(this)); else { - if(AItarget_check_timer->Check()) + if(AI_target_check_timer->Check()) { if (IsFocused()) { if (!target) { @@ -1079,7 +1079,7 @@ void Mob::AI_Process() { if (is_combat_range) { - if (AImovement_timer->Check()) + if (AI_movement_timer->Check()) { if(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) { @@ -1273,7 +1273,7 @@ void Mob::AI_Process() { WipeHateList(); Heal(); BuffFadeAll(); - AIwalking_timer->Start(100); + AI_walking_timer->Start(100); pLastFightingDelayMoving = Timer::GetCurrentTime(); return; } else if(tar != nullptr) { @@ -1295,7 +1295,7 @@ void Mob::AI_Process() { if(AI_PursueCastCheck()){ //we did something, so do not process movement. } - else if (AImovement_timer->Check()) + else if (AI_movement_timer->Check()) { if(!IsRooted()) { Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName()); @@ -1328,7 +1328,7 @@ void Mob::AI_Process() { { if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); - if(AIfeignremember_timer->Check()) { + if(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. @@ -1353,7 +1353,7 @@ void Mob::AI_Process() { { //we processed a spell action, so do nothing else. } - else if (AIscanarea_timer->Check()) + else if (AI_scan_area_timer->Check()) { /* * This is where NPCs look around to see if they want to attack anybody. @@ -1368,7 +1368,7 @@ void Mob::AI_Process() { if (tmptar) AddToHateList(tmptar); } - else if (AImovement_timer->Check() && !IsRooted()) + else if (AI_movement_timer->Check() && !IsRooted()) { if (IsPet()) { @@ -1539,10 +1539,10 @@ void NPC::AI_DoMovement() { } else if (roamer) { - if (AIwalking_timer->Check()) + if (AI_walking_timer->Check()) { movetimercompleted=true; - AIwalking_timer->Disable(); + AI_walking_timer->Disable(); } @@ -1552,7 +1552,7 @@ void NPC::AI_DoMovement() { if (movetimercompleted==true) { // time to pause at wp is over AI_SetupNextWaypoint(); } // endif (movetimercompleted==true) - else if (!(AIwalking_timer->Enabled())) + else if (!(AI_walking_timer->Enabled())) { // currently moving bool doMove = true; if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY()) @@ -1573,7 +1573,7 @@ void NPC::AI_DoMovement() { sprintf(temp, "%d", cur_wp); parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0); // start moving directly to next waypoint if we're at a 0 pause waypoint and we didn't get quest halted. - if (!AIwalking_timer->Enabled()) + if (!AI_walking_timer->Enabled()) AI_SetupNextWaypoint(); else doMove = false; @@ -1764,7 +1764,7 @@ void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) { void Mob::AI_Event_NoLongerEngaged() { if (!IsAIControlled()) return; - this->AIwalking_timer->Start(RandomTimer(3000,20000)); + this->AI_walking_timer->Start(RandomTimer(3000,20000)); pLastFightingDelayMoving = Timer::GetCurrentTime(); if (minLastFightingDelayMoving == maxLastFightingDelayMoving) pLastFightingDelayMoving += minLastFightingDelayMoving; diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 34ec6eef7..5ab46dc1f 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -94,7 +94,7 @@ void NPC::ResumeWandering() { if (GetGrid() < 0) { // we were paused by a quest - AIwalking_timer->Disable(); + AI_walking_timer->Disable(); SetGrid( 0 - GetGrid()); if (cur_wp==-1) { // got here by a MoveTo() @@ -103,10 +103,10 @@ void NPC::ResumeWandering() } Log.Out(Logs::Detail, Logs::Pathing, "Resume Wandering requested. Grid %d, wp %d", GetGrid(), cur_wp); } - else if (AIwalking_timer->Enabled()) + else if (AI_walking_timer->Enabled()) { // we are at a waypoint paused normally Log.Out(Logs::Detail, Logs::Pathing, "Resume Wandering on timed pause. Grid %d, wp %d", GetGrid(), cur_wp); - AIwalking_timer->Trigger(); // disable timer to end pause now + AI_walking_timer->Trigger(); // disable timer to end pause now } else { @@ -145,7 +145,7 @@ void NPC::PauseWandering(int pausetime) } else { // specified waiting time, he'll resume after that - AIwalking_timer->Start(pausetime*1000); // set the timer + AI_walking_timer->Start(pausetime*1000); // set the timer } } else { Log.Out(Logs::General, Logs::Error, "NPC not on grid - can't pause wandering: %lu", (unsigned long)GetNPCTypeID()); @@ -162,7 +162,7 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot) SetGrid( 0 - GetGrid()); // get him moving again Log.Out(Logs::Detail, Logs::AI, "MoveTo during quest wandering. Canceling quest wandering and going back to grid %d when MoveTo is done.", GetGrid()); } - AIwalking_timer->Disable(); // disable timer in case he is paused at a wp + AI_walking_timer->Disable(); // disable timer in case he is paused at a wp if (cur_wp>=0) { // we've not already done a MoveTo() save_wp=cur_wp; // save the current waypoint @@ -193,8 +193,8 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot) m_CurrentWayPoint = position; cur_wp_pause = 0; pLastFightingDelayMoving = 0; - if(AIwalking_timer->Enabled()) - AIwalking_timer->Start(100); + if(AI_walking_timer->Enabled()) + AI_walking_timer->Start(100); } void NPC::UpdateWaypoint(int wp_index) @@ -393,8 +393,8 @@ void NPC::SetWaypointPause() //Declare time to wait on current WP if (cur_wp_pause == 0) { - AIwalking_timer->Start(100); - AIwalking_timer->Trigger(); + AI_walking_timer->Start(100); + AI_walking_timer->Trigger(); } else { @@ -402,13 +402,13 @@ void NPC::SetWaypointPause() switch (pausetype) { case 0: //Random Half - AIwalking_timer->Start((cur_wp_pause - zone->random.Int(0, cur_wp_pause-1)/2)*1000); + AI_walking_timer->Start((cur_wp_pause - zone->random.Int(0, cur_wp_pause-1)/2)*1000); break; case 1: //Full - AIwalking_timer->Start(cur_wp_pause*1000); + AI_walking_timer->Start(cur_wp_pause*1000); break; case 2: //Random Full - AIwalking_timer->Start(zone->random.Int(0, cur_wp_pause-1)*1000); + AI_walking_timer->Start(zone->random.Int(0, cur_wp_pause-1)*1000); break; } } From 66c7deb2ac4ecb2e8edc8906f5fc78b6933c9900 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 17:46:00 -0600 Subject: [PATCH 378/846] Remove some debug junk --- zone/mob_ai.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b16a3819e..36bddf809 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1861,9 +1861,6 @@ bool NPC::AI_PursueCastCheck() { 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, AISpellVar.idle_beneficial_chance, SpellType_Heal | SpellType_Buff | SpellType_Pet)) { if(!entity_list.AICheckCloseBeneficialSpells(this, 33, MobAISpellRange, SpellType_Heal | SpellType_Buff)) { From 6de2bb720fc46a5fa02334c1627c8ca9756ce602 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 17:49:45 -0600 Subject: [PATCH 379/846] Adjust AI_scan_area_timer to randomly start between 1-3 ticks (6-18 seconds) --- 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 36bddf809..1602699a2 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -480,7 +480,7 @@ void Mob::AI_Start(uint32 iMoveDelay) { AI_movement_timer = std::unique_ptr(new Timer(AImovement_duration)); AI_target_check_timer = std::unique_ptr(new Timer(AItarget_check_duration)); AI_feign_remember_timer = std::unique_ptr(new Timer(AIfeignremember_delay)); - AI_scan_area_timer = std::unique_ptr(new Timer(AIscanarea_delay)); + AI_scan_area_timer = std::unique_ptr(new Timer(RandomTimer(6000, 18000))); AI_check_signal_timer = std::unique_ptr(new Timer(AI_check_signal_timer_delay)); #ifdef REVERSE_AGGRO From e8d18cb014fc2123518056fe5dbf9d8f17360da6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 20:29:51 -0600 Subject: [PATCH 380/846] 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) 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 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() methods instead as they don't reference the hashmap $qglobals{} that is rebuilt every single time a sub event is triggered - A stress test conducted with 10,000 samples shows an excess of time taken to export variables: http://i.imgur.com/NEpW1tS.png - After the Perl Export Settings table is implemented, and all exports are shut off you see the following test result: http://i.imgur.com/Du5hth9.png - The difference of eliminating uneeded exports brings the overhead and footprint of 10,000 triggers from 54 seconds to 2 seconds - In a 10,000 sample test (10,000 sub event triggers), exporting item variables adds 12 seconds alone, when item variables are only needed in EVENT_ITEM and EVENT_SAY a majority of the time if at all - In a 10,000 sample test (10,000 sub event triggers), exporting qglobals with approximately 1,000 global qglobals in the database creates about 11-20 seconds of delay on its own (Depending on hardware of course) - I've written a parser that has determined which of these exports are needed in which sub routines and have turned off all of the unneeded exports in sub routines that do not need them and used it to create the default table that will be installed in the database. - The export table is called 'perl_event_export_settings' and it resembles the following structure and contains all current 81 EVENTS - If an entry doesn't exist in this table and a new subroutine is added to the source, all exports will be on by default for that routine +----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+ | event_id | event_description | export_qglobals | export_mob | export_zone | export_item | export_event | +----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+ | 0 | EVENT_SAY | 1 | 1 | 1 | 1 | 1 | | 1 | EVENT_ITEM | 1 | 1 | 1 | 0 | 1 | | 2 | EVENT_DEATH | 1 | 1 | 1 | 0 | 1 | | 3 | EVENT_SPAWN | 1 | 1 | 1 | 0 | 1 | | 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: (export_qglobals) (Heavy) : $qglobals https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L916 (export_item) (Heavy) : $itemcount{} $hasitem{} $oncursor{} https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1103 (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 --- changelog.txt | 42 +++++++ common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2015_11_01_perl_event_export_settings.sql | 116 ++++++++++++++++++ 4 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2015_11_01_perl_event_export_settings.sql diff --git a/changelog.txt b/changelog.txt index e3f74ce08..7aa6ee7e1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,47 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/1/2015 == +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 + 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() + methods instead as they don't reference the hashmap $qglobals{} that is rebuilt every single time a sub event is triggered + - A stress test conducted with 10,000 samples shows an excess of time taken to export variables: http://i.imgur.com/NEpW1tS.png + - After the Perl Export Settings table is implemented, and all exports are shut off you see the following test result: + http://i.imgur.com/Du5hth9.png + - The difference of eliminating uneeded exports brings the overhead and footprint of 10,000 triggers from 54 seconds to 2 seconds + - In a 10,000 sample test (10,000 sub event triggers), exporting item variables adds 12 seconds alone, when item variables are only needed in + EVENT_ITEM and EVENT_SAY a majority of the time if at all + - In a 10,000 sample test (10,000 sub event triggers), exporting qglobals with approximately 1,000 global qglobals in the database creates + about 11-20 seconds of delay on its own (Depending on hardware of course) + - I've written a parser that has determined which of these exports are needed in which sub routines and have turned off all of the unneeded + exports in sub routines that do not need them and used it to create the default table that will be installed in the database. + - The export table is called 'perl_event_export_settings' and it resembles the following structure and contains all current 81 EVENTS + - If an entry doesn't exist in this table and a new subroutine is added to the source, all exports will be on by default for that routine + + +----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+ + | event_id | event_description | export_qglobals | export_mob | export_zone | export_item | export_event | + +----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+ + | 0 | EVENT_SAY | 1 | 1 | 1 | 1 | 1 | + | 1 | EVENT_ITEM | 1 | 1 | 1 | 0 | 1 | + | 2 | EVENT_DEATH | 1 | 1 | 1 | 0 | 1 | + | 3 | EVENT_SPAWN | 1 | 1 | 1 | 0 | 1 | + | 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: + (export_qglobals) (Heavy) : $qglobals https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L916 + (export_item) (Heavy) : $itemcount{} $hasitem{} $oncursor{} https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1103 + (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 diff --git a/common/version.h b/common/version.h index d8a6b6077..3a3969ec1 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 9087 +#define CURRENT_BINARY_DATABASE_VERSION 9088 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 239fdbb67..2ffc2f452 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -341,6 +341,7 @@ 9085|2015_07_01_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty| 9086|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty| 9087|2015_09_25_inventory_snapshots.sql|SHOW TABLES LIKE 'inventory_snapshots'|empty| +9088|2015_11_01_perl_event_export_settings.sql|SHOW TABLES LIKE 'perl_event_export_settings'|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/2015_11_01_perl_event_export_settings.sql b/utils/sql/git/required/2015_11_01_perl_event_export_settings.sql new file mode 100644 index 000000000..1a06535d0 --- /dev/null +++ b/utils/sql/git/required/2015_11_01_perl_event_export_settings.sql @@ -0,0 +1,116 @@ +/* +Navicat MySQL Data Transfer + +Source Server : localhost +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : peq + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2015-11-01 20:28:21 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for perl_event_export_settings +-- ---------------------------- +DROP TABLE IF EXISTS `perl_event_export_settings`; +CREATE TABLE `perl_event_export_settings` ( + `event_id` int(11) NOT NULL, + `event_description` varchar(150) DEFAULT NULL, + `export_qglobals` smallint(11) DEFAULT '0', + `export_mob` smallint(11) DEFAULT '0', + `export_zone` smallint(11) DEFAULT '0', + `export_item` smallint(11) DEFAULT '0', + `export_event` smallint(11) DEFAULT '0', + PRIMARY KEY (`event_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- ---------------------------- +-- Records of perl_event_export_settings +-- ---------------------------- +INSERT INTO `perl_event_export_settings` VALUES ('0', 'EVENT_SAY', '1', '1', '1', '1', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('1', 'EVENT_ITEM', '1', '1', '1', '1', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('2', 'EVENT_DEATH', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('3', 'EVENT_SPAWN', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('4', 'EVENT_ATTACK', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('5', 'EVENT_COMBAT', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('6', 'EVENT_AGGRO', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('7', 'EVENT_SLAY', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('8', 'EVENT_NPC_SLAY', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('9', 'EVENT_WAYPOINT_ARRIVE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('10', 'EVENT_WAYPOINT_DEPART', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('11', 'EVENT_TIMER', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('12', 'EVENT_SIGNAL', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('13', 'EVENT_HP', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('14', 'EVENT_ENTER', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('15', 'EVENT_EXIT', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('16', 'EVENT_ENTERZONE', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('17', 'EVENT_CLICKDOOR', '1', '1', '1', '1', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('18', 'EVENT_LOOT', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('19', 'EVENT_ZONE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('20', 'EVENT_LEVEL_UP', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('21', 'EVENT_KILLED_MERIT', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('22', 'EVENT_CAST_ON', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('23', 'EVENT_TASKACCEPTED', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('24', 'EVENT_TASK_STAGE_COMPLETE', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('25', 'EVENT_TASK_UPDATE', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('26', 'EVENT_TASK_COMPLETE', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('27', 'EVENT_TASK_FAIL', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('28', 'EVENT_AGGRO_SAY', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('29', 'EVENT_PLAYER_PICKUP', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('30', 'EVENT_POPUPRESPONSE', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('31', 'EVENT_ENVIRONMENTAL_DAMAGE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('32', 'EVENT_PROXIMITY_SAY', '1', '1', '1', '1', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('33', 'EVENT_CAST', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('34', 'EVENT_CAST_BEGIN', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('35', 'EVENT_SCALE_CALC', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('36', 'EVENT_ITEM_ENTER_ZONE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('37', 'EVENT_TARGET_CHANGE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('38', 'EVENT_HATE_LIST', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('39', 'EVENT_SPELL_EFFECT_CLIENT', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('40', 'EVENT_SPELL_EFFECT_NPC', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('41', 'EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('42', 'EVENT_SPELL_EFFECT_BUFF_TIC_NPC', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('43', 'EVENT_SPELL_FADE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('44', 'EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('45', 'EVENT_COMBINE_SUCCESS', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('46', 'EVENT_COMBINE_FAILURE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('47', 'EVENT_ITEM_CLICK', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('48', 'EVENT_ITEM_CLICK_CAST', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('49', 'EVENT_GROUP_CHANGE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('50', 'EVENT_FORAGE_SUCCESS', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('51', 'EVENT_FORAGE_FAILURE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('52', 'EVENT_FISH_START', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('53', 'EVENT_FISH_SUCCESS', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('54', 'EVENT_FISH_FAILURE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('55', 'EVENT_CLICK_OBJECT', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('56', 'EVENT_DISCOVER_ITEM', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('57', 'EVENT_DISCONNECT', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('58', 'EVENT_CONNECT', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('59', 'EVENT_ITEM_TICK', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('60', 'EVENT_DUEL_WIN', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('61', 'EVENT_DUEL_LOSE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('62', 'EVENT_ENCOUNTER_LOAD', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('63', 'EVENT_ENCOUNTER_UNLOAD', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('64', 'EVENT_SAY', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('65', 'EVENT_DROP_ITEM', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('66', 'EVENT_DESTROY_ITEM', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('67', 'EVENT_FEIGN_DEATH', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('68', 'EVENT_WEAPON_PROC', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('69', 'EVENT_EQUIP_ITEM', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('70', 'EVENT_UNEQUIP_ITEM', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('71', 'EVENT_AUGMENT_ITEM', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('72', 'EVENT_UNAUGMENT_ITEM', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('73', 'EVENT_AUGMENT_INSERT', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('74', 'EVENT_AUGMENT_REMOVE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('75', 'EVENT_ENTER_AREA', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('76', 'EVENT_LEAVE_AREA', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('77', 'EVENT_RESPAWN', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('78', 'EVENT_DEATH_COMPLETE', '1', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('79', 'EVENT_UNHANDLED_OPCODE', '0', '1', '1', '0', '1'); +INSERT INTO `perl_event_export_settings` VALUES ('80', 'EVENT_TICK', '0', '1', '1', '0', '1'); From 0ee70a663ccb04e1c692c593d541c903121559e6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 20:31:01 -0600 Subject: [PATCH 381/846] Small adjustments to my rushing [skip ci] --- .../2015_11_01_perl_event_export_settings.sql | 21 ------------------- zone/mob_ai.cpp | 2 ++ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/utils/sql/git/required/2015_11_01_perl_event_export_settings.sql b/utils/sql/git/required/2015_11_01_perl_event_export_settings.sql index 1a06535d0..14efd90a5 100644 --- a/utils/sql/git/required/2015_11_01_perl_event_export_settings.sql +++ b/utils/sql/git/required/2015_11_01_perl_event_export_settings.sql @@ -1,24 +1,3 @@ -/* -Navicat MySQL Data Transfer - -Source Server : localhost -Source Server Version : 50505 -Source Host : localhost:3306 -Source Database : peq - -Target Server Type : MYSQL -Target Server Version : 50505 -File Encoding : 65001 - -Date: 2015-11-01 20:28:21 -*/ - -SET FOREIGN_KEY_CHECKS=0; - --- ---------------------------- --- Table structure for perl_event_export_settings --- ---------------------------- -DROP TABLE IF EXISTS `perl_event_export_settings`; CREATE TABLE `perl_event_export_settings` ( `event_id` int(11) NOT NULL, `event_description` varchar(150) DEFAULT NULL, diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 1602699a2..06a9fdbfb 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1364,6 +1364,8 @@ void Mob::AI_Process() { * */ + Log.Out(Logs::General, Logs::Zone_Server, "AI Scan area timer check for :: %s", this->GetCleanName()); + Mob* tmptar = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange()); if (tmptar) AddToHateList(tmptar); From f4983f090d4e3f38d3f5db0eca0cac5e1cac1120 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 1 Nov 2015 20:56:03 -0600 Subject: [PATCH 382/846] Once again another adjustment to npc to npc aggro check timer [skip cki] --- common/ruletypes.h | 2 ++ zone/mob_ai.cpp | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 1b4baa371..456c9f378 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -475,6 +475,8 @@ RULE_BOOL(NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPC RULE_INT(NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage RULE_BOOL(NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage 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_CATEGORY_END() RULE_CATEGORY(Aggro) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 06a9fdbfb..0a2219428 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -480,7 +480,7 @@ void Mob::AI_Start(uint32 iMoveDelay) { AI_movement_timer = std::unique_ptr(new Timer(AImovement_duration)); AI_target_check_timer = std::unique_ptr(new Timer(AItarget_check_duration)); AI_feign_remember_timer = std::unique_ptr(new Timer(AIfeignremember_delay)); - AI_scan_area_timer = std::unique_ptr(new Timer(RandomTimer(6000, 18000))); + AI_scan_area_timer = std::unique_ptr(new Timer(RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax)))); AI_check_signal_timer = std::unique_ptr(new Timer(AI_check_signal_timer_delay)); #ifdef REVERSE_AGGRO @@ -1364,8 +1364,6 @@ void Mob::AI_Process() { * */ - Log.Out(Logs::General, Logs::Zone_Server, "AI Scan area timer check for :: %s", this->GetCleanName()); - Mob* tmptar = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange()); if (tmptar) AddToHateList(tmptar); From 21acd79acf381f53111b8be6390311a84018daf4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 2 Nov 2015 17:58:35 -0500 Subject: [PATCH 383/846] Fix procs that have end cost from consuming end --- zone/spells.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 6b5707278..9ec68c3ff 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2267,7 +2267,9 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } } // one may want to check if this is a disc or not, but we actually don't, there are non disc stuff that have end cost - if (spells[spell_id].EndurCost) { + // lets not consume end for custom items that have disc procs. + // One might also want to filter out USE_ITEM_SPELL_SLOT, but DISCIPLINE_SPELL_SLOT are both #defined to the same thing ... + if (spells[spell_id].EndurCost && !isproc) { auto end_cost = spells[spell_id].EndurCost; if (mgb) end_cost *= 2; From f884d8d7388f000c8db024e63bf2311d4ddb30e5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 2 Nov 2015 21:33:36 -0600 Subject: [PATCH 384/846] Fix an issue where during a depop cycle and NPC's are engaged by wiping hatelist before issuing NPC depop --- zone/entity.cpp | 2 ++ zone/mob_ai.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/zone/entity.cpp b/zone/entity.cpp index c427d82d7..643b27177 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2438,6 +2438,8 @@ void EntityList::Depop(bool StartSpawnTimer) if (pnpc->IsFindable()) UpdateFindableNPCState(pnpc, true); + pnpc->WipeHateList(); + pnpc->Depop(StartSpawnTimer); } } diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 0a2219428..6bde54d0a 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1867,6 +1867,9 @@ bool NPC::AI_IdleCastCheck() { //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(AISpellVar.idle_no_sp_recast_min, AISpellVar.idle_no_sp_recast_max), false); + + Log.Out(Logs::Moderate, Logs::Spells, "Triggering AI_IdleCastCheck :: Mob %s - Min : %u Max : %u", this->GetCleanName(), AISpellVar.idle_no_sp_recast_min, AISpellVar.idle_no_sp_recast_max); + } //else, spell casting finishing will reset the timer. } //else, spell casting finishing will reset the timer. return(true); From 63051dda9c438290dce276e75caa5a64d9761e05 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 2 Nov 2015 22:12:41 -0600 Subject: [PATCH 385/846] Performance boost (exponential) - Adjusted default idle cast check timers in rules - NPC:NPCToNPCAggroTimerMin 500 (Now 6000) 6 seconds - NPC:NPCToNPCAggroTimerMax 2000 (Now 60000) 60 seconds - 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 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) --- changelog.txt | 13 +++++++++++++ common/ruletypes.h | 4 ++-- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + ...1_02_ai_idle_no_spell_recast_default_changes.sql | 2 ++ 5 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 utils/sql/git/required/2015_11_02_ai_idle_no_spell_recast_default_changes.sql diff --git a/changelog.txt b/changelog.txt index 7aa6ee7e1..1b1e9630a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,18 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/2/2015 == +Akkadius: Performance boost (exponential) - Adjusted default idle cast check timers in rules + - NPC:NPCToNPCAggroTimerMin 500 (Now 6000) 6 seconds + - NPC:NPCToNPCAggroTimerMax 2000 (Now 60000) 60 seconds + - 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 + 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) + == 11/1/2015 == 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) diff --git a/common/ruletypes.h b/common/ruletypes.h index 456c9f378..411489ca1 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -347,8 +347,8 @@ RULE_INT(Spells, AI_EngagedDetrimentalChance, 20) // Chance during third AI Cast RULE_INT(Spells, AI_PursueNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while chasing target. (min time in random) RULE_INT(Spells, AI_PursueNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) RULE_INT(Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target to cast a detrimental spell. -RULE_INT(Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random) -RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) +RULE_INT(Spells, AI_IdleNoSpellMinRecast, 6000) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random) +RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 60000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) RULE_INT(Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others. RULE_BOOL(Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false) RULE_BOOL(Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014 diff --git a/common/version.h b/common/version.h index 3a3969ec1..4f39b595c 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 9088 +#define CURRENT_BINARY_DATABASE_VERSION 9089 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 2ffc2f452..aa1e46be9 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -342,6 +342,7 @@ 9086|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty| 9087|2015_09_25_inventory_snapshots.sql|SHOW TABLES LIKE 'inventory_snapshots'|empty| 9088|2015_11_01_perl_event_export_settings.sql|SHOW TABLES LIKE 'perl_event_export_settings'|empty| +9089|2015_11_02_ai_idle_no_spell_recast_default_changes.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Spells:AI_IdleNoSpellMinRecast%' AND `rule_value` = '500'|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/2015_11_02_ai_idle_no_spell_recast_default_changes.sql b/utils/sql/git/required/2015_11_02_ai_idle_no_spell_recast_default_changes.sql new file mode 100644 index 000000000..fe09523c7 --- /dev/null +++ b/utils/sql/git/required/2015_11_02_ai_idle_no_spell_recast_default_changes.sql @@ -0,0 +1,2 @@ +UPDATE `rule_values` SET `rule_value` = '6000' WHERE `rule_value` = '500' AND `rule_name` = 'Spells:AI_IdleNoSpellMinRecast'; +UPDATE `rule_values` SET `rule_value` = '60000' WHERE `rule_value` = '2000' AND `rule_name` = 'Spells:AI_IdleNoSpellMaxRecast'; \ No newline at end of file From 9304e09eca12e7bd412f4a40122b1aa4f9841c8a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 2 Nov 2015 22:15:40 -0600 Subject: [PATCH 386/846] Adjust changelog.txt [skip ci] --- changelog.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 1b1e9630a..0b93e015c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,10 +5,8 @@ Akkadius: Performance boost (exponential) - Adjusted default idle cast check tim - NPC:NPCToNPCAggroTimerMin 500 (Now 6000) 6 seconds - NPC:NPCToNPCAggroTimerMax 2000 (Now 60000) 60 seconds - 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 + - 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 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) From 67c7254fd15e08cdca0eae9ec32b052c6559de49 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 2 Nov 2015 22:48:17 -0600 Subject: [PATCH 387/846] Copy paste fail [skip ci] --- changelog.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0b93e015c..5a1c346de 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,8 +2,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 11/2/2015 == Akkadius: Performance boost (exponential) - Adjusted default idle cast check timers in rules - - NPC:NPCToNPCAggroTimerMin 500 (Now 6000) 6 seconds - - NPC:NPCToNPCAggroTimerMax 2000 (Now 60000) 60 seconds + - Spells:AI_IdleNoSpellMinRecast 500 (Now 6000) 6 seconds + - Spells:AI_IdleNoSpellMaxRecast 2000 (Now 60000) 60 seconds - 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 From 27c8a85f6149a51984ba6054505ffc7b2b639a20 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 2 Nov 2015 23:23:04 -0600 Subject: [PATCH 388/846] Change AI_scan_area_timer to have a little variability in renewing a new timer time versus deciding one on spawn and sticking with it --- zone/mob_ai.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 6bde54d0a..25ed72441 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1364,9 +1364,14 @@ void Mob::AI_Process() { * */ - Mob* tmptar = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange()); - if (tmptar) - AddToHateList(tmptar); + Mob* temp_target = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange()); + if (temp_target){ + AddToHateList(temp_target); + } + + AI_scan_area_timer->Disable(); + AI_scan_area_timer->Start(RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax)), false); + } else if (AI_movement_timer->Check() && !IsRooted()) { From 835fbb81cbf349e102320154b0e7e1deddbea5c6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 3 Nov 2015 14:09:22 -0500 Subject: [PATCH 389/846] Expand Casting Restrictions Mostly to nerf HT, not fully implemented --- zone/spell_effects.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4b92fc688..f7e794334 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6224,16 +6224,17 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama Range 410 - 411 : UNKOWN Range 500 - 599 : Heal if HP less than a specified value Range 600 - 699 : Limit to Body Type [base2 - 600 = Body] - Range 700 : UNKNOWN + Range 700 : UNKNOWN -- Was added to higher HTs in Oct 21 2015 live patch Range 701 : NOT PET Range 800 : UKNOWN Range 818 - 819 : If Undead/If Not Undead Range 820 - 822 : UKNOWN Range 835 : Unknown *not implemented - Range 836 - 837 : Progression Server / Live Server *not implemented - Range 839 : Unknown *not implemented + Range 836 - 837 : Progression Server / Live Server *not fully implemented + Range 839 : Progression Server and GoD released -- broken until Oct 21 2015 on live *not fully implemented Range 842 - 844 : Humaniod lv MAX ((842 - 800) * 2) Range 845 - 847 : UNKNOWN + Range 860 - 871 : Humanoid lv MAX 860 = 90, 871 = 104 *not implemented Range 10000 - 11000 : Limit to Race [base2 - 10000 = Race] (*Not on live: Too useful a function to not implement) THIS IS A WORK IN PROGRESS */ @@ -6402,6 +6403,15 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama return true; break; + case 836: + return true; // todo implement progression flag assume not progression for now + + case 837: + return false; // todo implement progression flag assume not progression for now + + case 839: + return true; // todo implement progression flag assume not progression for now, this one is a check if GoD is live + case 842: if (GetBodyType() == BT_Humanoid && GetLevel() <= 84) return true; @@ -6789,4 +6799,4 @@ void Client::BreakFeignDeathWhenCastOn(bool IsResisted) SetFeigned(false); Message_StringID(MT_SpellFailure,FD_CAST_ON); } -} \ No newline at end of file +} From e7184f402d66dbca0a3a80c612fb3333cee08ca0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 3 Nov 2015 14:13:56 -0500 Subject: [PATCH 390/846] Add Casting Restrictions to SE_CurrentHPOnce --- zone/spell_effects.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index f7e794334..a0f2aa8ee 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -283,9 +283,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove //do any AAs apply to these spells? if(dmg < 0) { + if (!PassCastRestriction(false, spells[spell_id].base2[i], true)) + break; dmg = -dmg; Damage(caster, dmg, spell_id, spell.skill, false, buffslot, false); } else { + if (!PassCastRestriction(false, spells[spell_id].base2[i], true)) + break; HealDamage(dmg, caster); } break; From 63ae7ac3157e316f679c972d349912de588f84c7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 3 Nov 2015 14:15:55 -0500 Subject: [PATCH 391/846] Add Casting Restrictions to SE_CurrentHP (DoTs) buff processing --- zone/spell_effects.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a0f2aa8ee..f96ac88fd 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3433,6 +3433,8 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) switch (effect) { case SE_CurrentHP: { + if (!PassCastRestriction(false, spells[buff.spellid].base2[i], true)) + break; effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod, caster, buff.ticsremaining); // Handle client cast DOTs here. From 8d80f39ead7bc5872287a10498b771815dcbc9d3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 3 Nov 2015 14:17:55 -0500 Subject: [PATCH 392/846] Fix copy paste error --- 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 f96ac88fd..a2e769320 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -288,7 +288,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove dmg = -dmg; Damage(caster, dmg, spell_id, spell.skill, false, buffslot, false); } else { - if (!PassCastRestriction(false, spells[spell_id].base2[i], true)) + if (!PassCastRestriction(false, spells[spell_id].base2[i], false)) break; HealDamage(dmg, caster); } From a6f6e18969c0067f7cfb59fc91ff9c4cff8a2922 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 3 Nov 2015 18:43:47 -0500 Subject: [PATCH 393/846] Implement cast restriction 700 (NPC only) --- zone/spell_effects.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a2e769320..e866d1e0f 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6230,7 +6230,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama Range 410 - 411 : UNKOWN Range 500 - 599 : Heal if HP less than a specified value Range 600 - 699 : Limit to Body Type [base2 - 600 = Body] - Range 700 : UNKNOWN -- Was added to higher HTs in Oct 21 2015 live patch + 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 818 - 819 : If Undead/If Not Undead @@ -6394,6 +6394,11 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama return true; break; + case 700: + if (IsNPC()) + return true; + break; + case 701: if (!IsPet()) return true; From 86f35e45d322401edddeaf9686f4c42c840db44f Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 4 Nov 2015 23:30:46 -0500 Subject: [PATCH 394/846] Fix for LoadBot() hp issue --- zone/bot.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 6a684aeac..477581eba 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3737,9 +3737,9 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) " `drakkin_tattoo`," " `drakkin_details`," " `ac`," /*not in-use[26]*/ - " `atk`," + " `atk`," /*not in-use[27]*/ " `hp`," - " `mana`," /*not in-use[29]*/ + " `mana`," " `str`," /*not in-use[30]*/ " `sta`," /*not in-use[31]*/ " `cha`," /*not in-use[32]*/ @@ -3753,8 +3753,8 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) " `poison`," /*not in-use[40]*/ " `disease`," /*not in-use[41]*/ " `corruption`," /*not in-use[42]*/ - " `show_helm`," - " `follow_distance`" + " `show_helm`,"//43 + " `follow_distance`"//44 " FROM `bot_data`" " WHERE `bot_id` = '%u'", botID @@ -3791,8 +3791,8 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) atoi(row[23]), atoi(row[24]), atoi(row[25]), - atoi(row[27]), atoi(row[28]), + atoi(row[29]), defaultNPCTypeStruct.MR, defaultNPCTypeStruct.CR, defaultNPCTypeStruct.DR, From d64205124f97bf97c342e030d50dcc5567f79c7a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 7 Nov 2015 13:20:24 -0600 Subject: [PATCH 395/846] Implemented #repopclose [distance in units] - Used for development purposes, defaults to 500 units - Real case use: Large zones with 700 NPC's and you are making fast quick tweaks to nearby NPC's you can refresh just the NPC's around you instead of all in the zone - This can be quite the time saver - This command will depop all NPC's and only respawn the NPC's that are 500 units around you or unless you specify otherwise --- changelog.txt | 6 +++ zone/command.cpp | 36 ++++++++++++++-- zone/command.h | 1 + zone/spawn2.cpp | 106 +++++++++++++++++++++++++++++++++++++++++++++++ zone/zone.cpp | 23 ++++++++++ zone/zone.h | 1 + zone/zonedb.h | 1 + 7 files changed, 171 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5a1c346de..742edb5a5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/7/2015 == +Akkadius: Implemented #repopclose [distance in units] - Used for development purposes, defaults to 500 units + - Real case use: Large zones with 700 NPC's and you are making fast quick tweaks to nearby NPC's you can refresh just the NPC's around you instead of all in the zone + - This can be quite the time saver + - This command will depop all NPC's and only respawn the NPC's that are 500 units around you or unless you specify otherwise + == 11/2/2015 == Akkadius: Performance boost (exponential) - Adjusted default idle cast check timers in rules - Spells:AI_IdleNoSpellMinRecast 500 (Now 6000) 6 seconds diff --git a/zone/command.cpp b/zone/command.cpp index db41619f4..1aaf159b0 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -344,6 +344,7 @@ int command_init(void) { command_add("reloadzonepoints", "- Reload zone points from database", 150, command_reloadzps) || command_add("reloadzps", nullptr,0, command_reloadzps) || command_add("repop", "[delay] - Repop the zone with optional delay", 100, command_repop) || + command_add("repopclose", "[distance in units] Repops only NPC's nearby for fast development purposes", 100, command_repopclose) || command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", 200, command_resetaa) || command_add("resetaa_timer", "Command to reset AA cooldown timers.", 200, command_resetaa_timer) || command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) || @@ -3921,9 +3922,11 @@ void command_repop(Client *c, const Seperator *sep) LinkedListIterator iterator(zone->spawn2_list); iterator.Reset(); while (iterator.MoreElements()) { - std::string query = StringFormat("DELETE FROM respawn_times WHERE id = %lu AND instance_id = %lu", - (unsigned long)iterator.GetData()->GetID(), - (unsigned long)zone->GetInstanceID()); + std::string query = StringFormat( + "DELETE FROM respawn_times WHERE id = %lu AND instance_id = %lu", + (unsigned long)iterator.GetData()->GetID(), + (unsigned long)zone->GetInstanceID() + ); auto results = database.QueryDatabase(query); iterator.Advance(); } @@ -3940,6 +3943,33 @@ void command_repop(Client *c, const Seperator *sep) zone->Repop(atoi(sep->arg[timearg])*1000); } +void command_repopclose(Client *c, const Seperator *sep) +{ + int repop_distance = 500; + + if (sep->arg[1] && strcasecmp(sep->arg[1], "force") == 0) { + + LinkedListIterator iterator(zone->spawn2_list); + iterator.Reset(); + while (iterator.MoreElements()) { + std::string query = StringFormat( + "DELETE FROM respawn_times WHERE id = %lu AND instance_id = %lu", + (unsigned long)iterator.GetData()->GetID(), + (unsigned long)zone->GetInstanceID() + ); + auto results = database.QueryDatabase(query); + iterator.Advance(); + } + c->Message(0, "Zone depop: Force resetting spawn timers."); + } + if (sep->IsNumber(1)) { + repop_distance = atoi(sep->arg[1]); + } + + c->Message(0, "Zone depoped. Repopping NPC's within %i distance units", repop_distance); + zone->RepopClose(c->GetPosition(), repop_distance); +} + void command_spawnstatus(Client *c, const Seperator *sep) { if((sep->arg[1][0] == 'e') | (sep->arg[1][0] == 'E')) diff --git a/zone/command.h b/zone/command.h index e4130cfff..ac6107a20 100644 --- a/zone/command.h +++ b/zone/command.h @@ -187,6 +187,7 @@ void command_myskills(Client *c, const Seperator *sep); void command_depop(Client *c, const Seperator *sep); void command_depopzone(Client *c, const Seperator *sep); void command_repop(Client *c, const Seperator *sep); +void command_repopclose(Client *c, const Seperator *sep); void command_spawnstatus(Client *c, const Seperator *sep); void command_nukebuffs(Client *c, const Seperator *sep); void command_zuwcoords(Client *c, const Seperator *sep); diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index c42356ea9..f2461ed4b 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -351,6 +351,112 @@ void Spawn2::DeathReset(bool realdeath) } } +bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList &spawn2_list, int16 version, const glm::vec4& client_position, uint32 repop_distance) +{ + std::unordered_map spawn_times; + + float mob_distance = 0; + + timeval tv; + gettimeofday(&tv, nullptr); + + /* Bulk Load NPC Types Data into the cache */ + database.LoadNPCTypesData(0, true); + + std::string spawn_query = StringFormat( + "SELECT " + "respawn_times.id, " + "respawn_times.`start`, " + "respawn_times.duration " + "FROM " + "respawn_times " + "WHERE instance_id = %u", + zone->GetInstanceID() + ); + auto results = QueryDatabase(spawn_query); + for (auto row = results.begin(); row != results.end(); ++row) { + uint32 start_duration = atoi(row[1]) > 0 ? atoi(row[1]) : 0; + uint32 end_duration = atoi(row[2]) > 0 ? atoi(row[2]) : 0; + + /* Our current time was expired */ + if ((start_duration + end_duration) <= tv.tv_sec) { + spawn_times[atoi(row[0])] = 0; + } + /* We still have time left on this timer */ + else { + spawn_times[atoi(row[0])] = ((start_duration + end_duration) - tv.tv_sec) * 1000; + } + } + + const char *zone_name = database.GetZoneName(zoneid); + std::string query = StringFormat( + "SELECT " + "id, " + "spawngroupID, " + "x, " + "y, " + "z, " + "heading, " + "respawntime, " + "variance, " + "pathgrid, " + "_condition, " + "cond_value, " + "enabled, " + "animation " + "FROM " + "spawn2 " + "WHERE zone = '%s' AND version = %u", + zone_name, + version + ); + results = QueryDatabase(query); + + if (!results.Success()) { + return false; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + + uint32 spawn_time_left = 0; + Spawn2* new_spawn = 0; + bool perl_enabled = atoi(row[11]) == 1 ? true : false; + + if (spawn_times.count(atoi(row[0])) != 0) + spawn_time_left = spawn_times[atoi(row[0])]; + + glm::vec4 point; + point.x = atof(row[2]); + point.y = atof(row[3]); + + mob_distance = DistanceNoZ(client_position, point); + + if (mob_distance > repop_distance) + continue; + + new_spawn = new Spawn2( // + atoi(row[0]), // uint32 in_spawn2_id + atoi(row[1]), // uint32 spawngroup_id + atof(row[2]), // float in_x + atof(row[3]), // float in_y + atof(row[4]), // float in_z + atof(row[5]), // float in_heading + atoi(row[6]), // uint32 respawn + atoi(row[7]), // uint32 variance + spawn_time_left, // uint32 timeleft + atoi(row[8]), // uint32 grid + atoi(row[9]), // uint16 in_cond_id + atoi(row[10]), // int16 in_min_value + perl_enabled, // bool in_enabled + (EmuAppearance)atoi(row[12]) // EmuAppearance anim + ); + + spawn2_list.Insert(new_spawn); + } + + return true; +} + bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spawn2_list, int16 version, uint32 repopdelay) { std::unordered_map spawn_times; diff --git a/zone/zone.cpp b/zone/zone.cpp index 14c0674c6..b3a6fc1ca 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1445,6 +1445,29 @@ void Zone::ClearNPCTypeCache(int id) { } } +void Zone::RepopClose(const glm::vec4& client_position, uint32 repop_distance) +{ + + if (!Depop()) + return; + + LinkedListIterator iterator(spawn2_list); + + iterator.Reset(); + while (iterator.MoreElements()) { + iterator.RemoveCurrent(); + } + + quest_manager.ClearAllTimers(); + + if (!database.PopulateZoneSpawnListClose(zoneid, spawn2_list, GetInstanceVersion(), client_position, repop_distance)) + Log.Out(Logs::General, Logs::None, "Error in Zone::Repop: database.PopulateZoneSpawnList failed"); + + initgrids_timer.Start(); + + mod_repop(); +} + void Zone::Repop(uint32 delay) { if(!Depop()) diff --git a/zone/zone.h b/zone/zone.h index 94bba72e4..cbac77da9 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -140,6 +140,7 @@ public: bool Depop(bool StartSpawnTimer = false); void Repop(uint32 delay = 0); + void RepopClose(const glm::vec4& client_position, uint32 repop_distance); void ClearNPCTypeCache(int id); void SpawnStatus(Mob* client); void ShowEnabledSpawnStatus(Mob* client); diff --git a/zone/zonedb.h b/zone/zonedb.h index f49a9bf0d..66bb13e9e 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -359,6 +359,7 @@ public: bool LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list); bool LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list); bool PopulateZoneSpawnList(uint32 zoneid, LinkedList &spawn2_list, int16 version, uint32 repopdelay = 0); + bool PopulateZoneSpawnListClose(uint32 zoneid, LinkedList &spawn2_list, int16 version, const glm::vec4& client_position, uint32 repop_distance); Spawn2* LoadSpawn2(LinkedList &spawn2_list, uint32 spawn2id, uint32 timeleft); bool CreateSpawn2(Client *c, uint32 spawngroup, const char* zone, const glm::vec4& position, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value); void UpdateRespawnTime(uint32 id, uint16 instance_id,uint32 timeleft); From 18c97ca63779b5805d780976a8798a766b6ab1e6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 7 Nov 2015 13:23:15 -0600 Subject: [PATCH 396/846] Fix some indents, not sure how they got messed up [skip ci] --- zone/zone.h | 2 +- zone/zonedb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/zone.h b/zone/zone.h index cbac77da9..d7ecc6237 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -140,7 +140,7 @@ public: bool Depop(bool StartSpawnTimer = false); void Repop(uint32 delay = 0); - void RepopClose(const glm::vec4& client_position, uint32 repop_distance); + void RepopClose(const glm::vec4& client_position, uint32 repop_distance); void ClearNPCTypeCache(int id); void SpawnStatus(Mob* client); void ShowEnabledSpawnStatus(Mob* client); diff --git a/zone/zonedb.h b/zone/zonedb.h index 66bb13e9e..c4d26792d 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -359,7 +359,7 @@ public: bool LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list); bool LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list); bool PopulateZoneSpawnList(uint32 zoneid, LinkedList &spawn2_list, int16 version, uint32 repopdelay = 0); - bool PopulateZoneSpawnListClose(uint32 zoneid, LinkedList &spawn2_list, int16 version, const glm::vec4& client_position, uint32 repop_distance); + bool PopulateZoneSpawnListClose(uint32 zoneid, LinkedList &spawn2_list, int16 version, const glm::vec4& client_position, uint32 repop_distance); Spawn2* LoadSpawn2(LinkedList &spawn2_list, uint32 spawn2id, uint32 timeleft); bool CreateSpawn2(Client *c, uint32 spawngroup, const char* zone, const glm::vec4& position, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value); void UpdateRespawnTime(uint32 id, uint16 instance_id,uint32 timeleft); From ad04b308c06bcb2453e52da9f4821f7f12a618b5 Mon Sep 17 00:00:00 2001 From: Shendare Date: Sun, 8 Nov 2015 22:18:51 -0800 Subject: [PATCH 397/846] Quick query logging addition Reports records affected by inserts, updates, and deletes as well as the records returned by selects. --- common/dbcore.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/dbcore.cpp b/common/dbcore.cpp index d256f7b42..33c691afc 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -128,7 +128,12 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql)); if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1) - Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount()); + { + if ((strlen(query) > 6) && (_memicmp(query, "select", 6) == 0)) + Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s returned)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s"); + else + Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s affected)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s"); + } return requestResult; } From 992797f6108c0aa47a11602bf512a00e7d61d74c Mon Sep 17 00:00:00 2001 From: Shendare Date: Sun, 8 Nov 2015 22:41:39 -0800 Subject: [PATCH 398/846] Fixed query logging addition Resolved platform specific function use. --- common/dbcore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 33c691afc..76e87cde1 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -129,7 +129,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1) { - if ((strlen(query) > 6) && (_memicmp(query, "select", 6) == 0)) + if ((strncasecmp(query, "select", 6) == 0)) Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s returned)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s"); else Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s affected)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s"); From 9e5bfabf9195771d20d8ee5943a80d68fd3a8eab Mon Sep 17 00:00:00 2001 From: Shendare Date: Mon, 9 Nov 2015 22:43:25 -0800 Subject: [PATCH 399/846] Augmentation Feature Patch RoF+ clients now support the built-in adding, swapping, destroying, and removing of augments in equipment, updating an equipped item's look in case of ornamentation changes. All clients will now verify that the proper distiller (or a perfected distiller for RoF+) is being sent for consumption for safely removing augments. Hard-coded item IDs for distillers have been replaced with checks on item types. --- zone/client_packet.cpp | 323 ++++++++++++++++++++++++++++------------- zone/tradeskills.cpp | 27 ++-- 2 files changed, 240 insertions(+), 110 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2ee01fe25..7d392ec37 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2931,139 +2931,260 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { ItemInst *itemOneToPush = nullptr, *itemTwoToPush = nullptr; - //Message(15, "%i %i %i %i %i %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); + //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); - // Adding augment - if (in_augment->augment_action == 0) + ItemInst *tobe_auged = nullptr, *new_aug = nullptr, *old_aug = nullptr, *aug = nullptr, *solvent = nullptr; + Inventory& 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 + + if (item_slot == INVALID_INDEX || solvent_slot == INVALID_INDEX) { - ItemInst *tobe_auged = nullptr, *auged_with = nullptr; - int8 slot = -1; - Inventory& user_inv = GetInv(); + Message(13, "Error: Invalid Aug Index."); + return; + } - uint16 slot_id = in_augment->container_slot; - uint16 aug_slot_id = in_augment->augment_slot; - if (slot_id == INVALID_INDEX || aug_slot_id == INVALID_INDEX) + tobe_auged = user_inv.GetItem(item_slot); + solvent = user_inv.GetItem(solvent_slot); + new_aug = user_inv.GetItem(MainCursor); + + if (!tobe_auged) + { + Message(13, "Error: Invalid item passed for augmenting."); + return; + } + + if ((in_augment->augment_action == 1) || (in_augment->augment_action == 2)) + { + // Check for valid distiller if safely removing / swapping an augmentation + + if (!solvent) { - Message(13, "Error: Invalid Aug Index."); + Log.Out(Logs::General, Logs::Error, "Player tried to safely remove an augment without a distiller."); + Message(13, "Error: Missing an augmentation distiller for safely removing this augment."); return; } - - tobe_auged = user_inv.GetItem(slot_id); - auged_with = user_inv.GetItem(MainCursor); - - if (tobe_auged && auged_with) + else if (solvent->GetItem()->ItemType == ItemUseTypes::ItemTypeAugmentationDistiller) { - if (((tobe_auged->IsAugmentSlotAvailable(auged_with->GetAugmentType(), in_augment->augment_index)) != -1) && - (tobe_auged->AvailableWearSlot(auged_with->GetItem()->Slots))) + old_aug = tobe_auged->GetAugment(in_augment->augment_index); + + if (!old_aug) { - tobe_auged->PutAugment(in_augment->augment_index, *auged_with); - tobe_auged->UpdateOrnamentationInfo(); + Log.Out(Logs::General, Logs::Error, "Player tried to safely remove a nonexistent augment."); + Message(13, "Error: No augment found in slot %i for safely removing.", in_augment->augment_index); + return; + } + else if (solvent->GetItem()->ID != old_aug->GetItem()->AugDistiller) + { + Log.Out(Logs::General, Logs::Error, "Player tried to safely remove an augment with the wrong distiller (item %u vs expected %u).", solvent->GetItem()->ID, old_aug->GetItem()->AugDistiller); + Message(13, "Error: Wrong augmentation distiller for safely removing this augment."); + return; + } + } + else if (solvent->GetItem()->ItemType != ItemUseTypes::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."); + return; + } + } - ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index); - if (aug) { - std::vector args; - args.push_back(aug); - parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); - - args.assign(1, tobe_auged); - parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args); - } - else + switch (in_augment->augment_action) + { + case 0: // Adding an augment + case 2: // Swapping augment + if (new_aug) + { + if (((tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), in_augment->augment_index)) != -1) && + (tobe_auged->AvailableWearSlot(new_aug->GetItem()->Slots))) { - Message(13, "Error: Could not find augmentation at index %i. Aborting.", in_augment->augment_index); - return; - } - - itemOneToPush = tobe_auged->Clone(); - // Must push items after the items in inventory are deleted - necessary due to lore items... - if (itemOneToPush) - { - DeleteItemInInventory(slot_id, 0, true); - DeleteItemInInventory(MainCursor, 0, true); - - if (PutItemInInventory(slot_id, *itemOneToPush, true)) + old_aug = tobe_auged->RemoveAugment(in_augment->augment_index); + if (old_aug) { + // An old augment was removed in order to be replaced with the new one (augment_action 2) + CalcBonuses(); - // Successfully added an augment to the item + + std::vector args; + args.push_back(old_aug); + parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + + args.assign(1, tobe_auged); + args.push_back(false); + + parse->EventItem(EVENT_AUGMENT_REMOVE, this, old_aug, nullptr, "", in_augment->augment_index, &args); + } + + tobe_auged->PutAugment(in_augment->augment_index, *new_aug); + tobe_auged->UpdateOrnamentationInfo(); + + aug = tobe_auged->GetAugment(in_augment->augment_index); + if (aug) + { + std::vector args; + args.push_back(aug); + parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + + args.assign(1, tobe_auged); + parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args); + } + else + { + Message(13, "Error: Could not properly insert augmentation into augment slot %i. Aborting.", in_augment->augment_index); + return; + } + + itemOneToPush = tobe_auged->Clone(); + if (old_aug) + { + itemTwoToPush = old_aug->Clone(); + } + + // Must push items after the items in inventory are deleted - necessary due to lore items... + if (itemOneToPush) + { + DeleteItemInInventory(item_slot, 0, true); + DeleteItemInInventory(MainCursor, new_aug->IsStackable() ? 1 : 0, true); + + if (solvent) + { + // Consume the augment distiller + DeleteItemInInventory(solvent_slot, solvent->IsStackable() ? 1 : 0, true); + } + + if (itemTwoToPush) + { + // Return the old aug to the player's cursor + + PutItemInInventory(MainCursor, *itemTwoToPush, true); + } + + if (PutItemInInventory(item_slot, *itemOneToPush, true)) + { + CalcBonuses(); + // Successfully added an augment to the item + if (mat != _MaterialInvalid) + { + SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. + } + return; + } + else + { + Message(13, "Error: No available slot for end result. Please free up the augment slot."); + } + return; } else { - Message(13, "Error: No available slot for end result. Please free up the augment slot."); + Message(13, "Error in cloning item for augment. Aborted."); } } else { - Message(13, "Error in cloning item for augment. Aborted."); + Message(13, "Error: No available slot for augment in that item."); } + } + break; + case 1: // Removing augment safely (distiller) + aug = tobe_auged->GetAugment(in_augment->augment_index); + if (aug) + { + std::vector args; + args.push_back(aug); + parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + args.assign(1, tobe_auged); + + args.push_back(false); + + parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); } else { - Message(13, "Error: No available slot for augment in that item."); + Message(13, "Error: Could not find augmentation to remove at index %i. Aborting.", in_augment->augment_index); + return; } - } - } - else if (in_augment->augment_action == 1) - { - ItemInst *tobe_auged = nullptr, *auged_with = nullptr; - int8 slot = -1; - Inventory& user_inv = GetInv(); + old_aug = tobe_auged->RemoveAugment(in_augment->augment_index); + tobe_auged->UpdateOrnamentationInfo(); - uint16 slot_id = in_augment->container_slot; - uint16 aug_slot_id = in_augment->augment_slot; //it's actually solvent slot - if (slot_id == INVALID_INDEX || aug_slot_id == INVALID_INDEX) - { - Message(13, "Error: Invalid Aug Index."); - return; - } - - tobe_auged = user_inv.GetItem(slot_id); - auged_with = user_inv.GetItem(aug_slot_id); - - ItemInst *old_aug = nullptr; - if (!auged_with) - return; - const uint32 id = auged_with->GetID(); - ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index); - if (aug) { - std::vector args; - args.push_back(aug); - parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); - - args.assign(1, tobe_auged); - - args.push_back(false); - - parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); - } - else - { - Message(13, "Error: Could not find augmentation at index %i. Aborting."); - return; - } - old_aug = tobe_auged->RemoveAugment(in_augment->augment_index); - tobe_auged->UpdateOrnamentationInfo(); - - itemOneToPush = tobe_auged->Clone(); - if (old_aug) - itemTwoToPush = old_aug->Clone(); - if (itemOneToPush && itemTwoToPush && auged_with) - { - DeleteItemInInventory(slot_id, 0, true); - DeleteItemInInventory(aug_slot_id, auged_with->IsStackable() ? 1 : 0, true); - - if (!PutItemInInventory(slot_id, *itemOneToPush, true)) + itemOneToPush = tobe_auged->Clone(); + if (old_aug) + itemTwoToPush = old_aug->Clone(); + if (itemOneToPush && itemTwoToPush) { - Message(15, "Failed to remove augment properly!"); + DeleteItemInInventory(item_slot, 0, true); + DeleteItemInInventory(solvent_slot, solvent->IsStackable() ? 1 : 0, true); + + if (!PutItemInInventory(item_slot, *itemOneToPush, true)) + { + Message(15, "Failed to remove augment properly!"); + } + + if (PutItemInInventory(MainCursor, *itemTwoToPush, true)) + { + CalcBonuses(); + //Message(15, "Successfully removed an augmentation!"); + if (mat != _MaterialInvalid) + { + SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. + } + } + } + break; + case 3: // Destroying augment (formerly done in birdbath/sealer with a solvent) + + // RoF client does not require an augmentation solvent for destroying an augmentation in an item. + // Augments can be destroyed with a right click -> Destroy at any time. + + aug = tobe_auged->GetAugment(in_augment->augment_index); + if (aug) + { + std::vector args; + args.push_back(aug); + parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + + args.assign(1, tobe_auged); + + args.push_back(true); + + parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); + } + else + { + Message(13, "Error: Could not find augmentation to remove at index %i. Aborting."); + return; } - if (PutItemInInventory(MainCursor, *itemTwoToPush, true)) + tobe_auged->DeleteAugment(in_augment->augment_index); + tobe_auged->UpdateOrnamentationInfo(); + + itemOneToPush = tobe_auged->Clone(); + if (itemOneToPush) { - CalcBonuses(); - //Message(15, "Successfully removed an augmentation!"); + DeleteItemInInventory(item_slot, 0, true); + + if (!PutItemInInventory(item_slot, *itemOneToPush, true)) + { + Message(15, "Failed to destroy augment properly!"); + } } - } + + CalcBonuses(); + //Message(15, "Successfully removed an augmentation!"); + if (mat != _MaterialInvalid) + { + SendWearChange(mat); + } + break; + default: // Unknown + Log.Out(Logs::General, Logs::Inventory, "Unrecognized augmentation action - 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); + break; } } else diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 903c7c34c..2efed1e93 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -166,25 +166,34 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme else { ItemInst *old_aug = nullptr; - const uint32 id = auged_with->GetID(); + bool isSolvent = auged_with->GetItem()->ItemType == ItemUseTypes::ItemTypeAugmentationSolvent; + if (!isSolvent && auged_with->GetItem()->ItemType != ItemUseTypes::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."); + + return; + } + ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_slot); - if(aug) { + if (aug) { + if (!isSolvent && auged_with->GetItem()->ID != aug->GetItem()->AugDistiller) + { + Log.Out(Logs::General, Logs::Error, "Player tried to safely remove an augment with the wrong distiller (item %u vs expected %u).", auged_with->GetItem()->ID, aug->GetItem()->AugDistiller); + user->Message(13, "Error: Wrong augmentation distiller for safely removing this augment."); + return; + } std::vector args; args.push_back(aug); parse->EventItem(EVENT_UNAUGMENT_ITEM, user, tobe_auged, nullptr, "", slot, &args); args.assign(1, tobe_auged); - bool destroyed = false; - if(id == 40408 || id == 40409 || id == 40410) { - destroyed = true; - } - - args.push_back(&destroyed); + args.push_back(&isSolvent); parse->EventItem(EVENT_AUGMENT_REMOVE, user, aug, nullptr, "", slot, &args); } - if(id == 40408 || id == 40409 || id == 40410) + if (isSolvent) tobe_auged->DeleteAugment(in_augment->augment_slot); else old_aug = tobe_auged->RemoveAugment(in_augment->augment_slot); From 78c75501f7040804e412c9d2de2ca909f9643969 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 10 Nov 2015 03:27:30 -0500 Subject: [PATCH 400/846] Reply to the request made on opening XTarget window This allows the Extended Targets option in the EQ Menu to open the window --- common/emu_oplist.h | 2 ++ utils/patches/patch_RoF.conf | 2 ++ utils/patches/patch_RoF2.conf | 2 ++ utils/patches/patch_UF.conf | 2 ++ zone/client_packet.cpp | 13 +++++++++++++ zone/client_packet.h | 1 + 6 files changed, 22 insertions(+) diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 4ef1761bd..28ec9af0f 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -535,6 +535,8 @@ N(OP_WorldLogout), N(OP_WorldObjectsSent), N(OP_WorldUnknown001), N(OP_XTargetAutoAddHaters), +N(OP_XTargetOpen), +N(OP_XTargetOpenResponse), N(OP_XTargetRequest), N(OP_XTargetResponse), N(OP_YellForHelp), diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 6e3f0ab1a..dfd8f0e84 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -235,6 +235,8 @@ OP_TargetHoTT=0x3af5 OP_XTargetResponse=0x7f64 OP_XTargetRequest=0x6753 OP_XTargetAutoAddHaters=0x5f51 +OP_XTargetOpen=0x7423 +OP_XTargetOpenResponse=0x27e8 OP_TargetBuffs=0x1c71 OP_BuffCreate=0x71f5 OP_BuffRemoveRequest=0x7efd diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 5e67f4c11..0d1cb20ec 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -235,6 +235,8 @@ OP_TargetBuffs=0x4f4b OP_XTargetResponse=0x4d59 OP_XTargetRequest=0x3763 OP_XTargetAutoAddHaters=0x672f +OP_XTargetOpen=0x61df +OP_XTargetOpenResponse=0x3ef8 OP_BuffCreate=0x3377 OP_BuffRemoveRequest=0x64f2 OP_DeleteSpawn=0x7280 diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index 6f94c92db..e3af9aa7d 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -239,6 +239,8 @@ OP_TargetHoTT=0x790c # C OP_XTargetResponse=0x6eb5 # OP_XTargetRequest=0x4750 # OP_XTargetAutoAddHaters=0x1a28 # +OP_XTargetOpen=0x11ae +OP_XTargetOpenResponse=0x45d3 OP_TargetBuffs=0x3f24 # C OP_BuffCreate=0x2121 # V OP_BuffRemoveRequest=0x4065 diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2ee01fe25..c955399b8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -386,6 +386,7 @@ void MapOpcodes() ConnectedOpcodes[OP_WhoAllRequest] = &Client::Handle_OP_WhoAllRequest; ConnectedOpcodes[OP_WorldUnknown001] = &Client::Handle_OP_Ignore; ConnectedOpcodes[OP_XTargetAutoAddHaters] = &Client::Handle_OP_XTargetAutoAddHaters; + ConnectedOpcodes[OP_XTargetOpen] = &Client::Handle_OP_XTargetOpen; ConnectedOpcodes[OP_XTargetRequest] = &Client::Handle_OP_XTargetRequest; ConnectedOpcodes[OP_YellForHelp] = &Client::Handle_OP_YellForHelp; ConnectedOpcodes[OP_ZoneChange] = &Client::Handle_OP_ZoneChange; @@ -13925,6 +13926,18 @@ void Client::Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app) XTargetAutoAddHaters = app->ReadUInt8(0); } +void Client::Handle_OP_XTargetOpen(const EQApplicationPacket *app) +{ + if (app->size != 4) { + Log.Out(Logs::General, Logs::None, "Size mismatch in OP_XTargetOpen, expected 1, got %i", app->size); + DumpPacket(app); + return; + } + + auto outapp = new EQApplicationPacket(OP_XTargetOpenResponse, 0); + FastQueuePacket(&outapp); +} + void Client::Handle_OP_XTargetRequest(const EQApplicationPacket *app) { if (app->size < 12) diff --git a/zone/client_packet.h b/zone/client_packet.h index a39e3fb74..2635724dd 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -292,6 +292,7 @@ void Handle_OP_WearChange(const EQApplicationPacket *app); void Handle_OP_WhoAllRequest(const EQApplicationPacket *app); void Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app); + void Handle_OP_XTargetOpen(const EQApplicationPacket *app); void Handle_OP_XTargetRequest(const EQApplicationPacket *app); void Handle_OP_YellForHelp(const EQApplicationPacket *app); void Handle_OP_ZoneChange(const EQApplicationPacket *app); From f6c2c07a941ce75dbccf0ca9e82e1df0d89d239b Mon Sep 17 00:00:00 2001 From: Shendare Date: Tue, 10 Nov 2015 18:14:47 -0800 Subject: [PATCH 401/846] Augmentation Feature Patch Code Cleanup Avoided an extraneous GetItem() call when performing an action that doesn't return an augment to the player. Added additional error checking and logging. Improved error messages and code comments. --- zone/client_packet.cpp | 71 +++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7d392ec37..36c4e1da8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2924,7 +2924,6 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) return; } - // Delegate to tradeskill object to perform combine AugmentItem_Struct* in_augment = (AugmentItem_Struct*)app->pBuffer; bool deleteItems = false; if (GetClientVersion() >= ClientVersion::RoF) @@ -2934,7 +2933,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) //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, *new_aug = nullptr, *old_aug = nullptr, *aug = nullptr, *solvent = nullptr; + ItemInst *tobe_auged = nullptr, *old_aug = nullptr, *new_aug = nullptr, *aug = nullptr, *solvent = nullptr; Inventory& user_inv = GetInv(); uint16 item_slot = in_augment->container_slot; @@ -2949,7 +2948,6 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) tobe_auged = user_inv.GetItem(item_slot); solvent = user_inv.GetItem(solvent_slot); - new_aug = user_inv.GetItem(MainCursor); if (!tobe_auged) { @@ -2996,7 +2994,15 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { case 0: // Adding an augment case 2: // Swapping augment - if (new_aug) + new_aug = user_inv.GetItem(MainCursor); + + if (!new_aug) // Shouldn't get the OP code without the augment on the user's cursor, but maybe it's h4x. + { + Log.Out(Logs::General, Logs::Error, "AugmentItem OpCode with 'Insert' or 'Swap' action received, but no augment on client's cursor."); + Message(13, "Error: No augment found on cursor for inserting."); + return; + } + else { if (((tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), in_augment->augment_index)) != -1) && (tobe_auged->AvailableWearSlot(new_aug->GetItem()->Slots))) @@ -3014,7 +3020,6 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) args.assign(1, tobe_auged); args.push_back(false); - parse->EventItem(EVENT_AUGMENT_REMOVE, this, old_aug, nullptr, "", in_augment->augment_index, &args); } @@ -3057,27 +3062,29 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (itemTwoToPush) { - // Return the old aug to the player's cursor - - PutItemInInventory(MainCursor, *itemTwoToPush, true); + // This is a swap. Return the old aug to the player's cursor. + if (PutItemInInventory(MainCursor, *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!"); + } } if (PutItemInInventory(item_slot, *itemOneToPush, true)) { - CalcBonuses(); // Successfully added an augment to the item + + CalcBonuses(); + if (mat != _MaterialInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } - return; } else { Message(13, "Error: No available slot for end result. Please free up the augment slot."); } - - return; } else { @@ -3109,37 +3116,49 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) Message(13, "Error: Could not find augmentation to remove at index %i. Aborting.", in_augment->augment_index); return; } + old_aug = tobe_auged->RemoveAugment(in_augment->augment_index); tobe_auged->UpdateOrnamentationInfo(); itemOneToPush = tobe_auged->Clone(); if (old_aug) itemTwoToPush = old_aug->Clone(); + if (itemOneToPush && itemTwoToPush) { - DeleteItemInInventory(item_slot, 0, true); + // Consume the augment distiller DeleteItemInInventory(solvent_slot, solvent->IsStackable() ? 1 : 0, true); + // Remove the augmented item + DeleteItemInInventory(item_slot, 0, true); + + // Replace it with the unaugmented item if (!PutItemInInventory(item_slot, *itemOneToPush, true)) { - Message(15, "Failed to remove augment properly!"); + Log.Out(Logs::General, Logs::Error, "Problem returning equipment item to player's inventory after safe augment removal."); + Message(15, "Error: Failed to return item after de-augmentation!"); } - if (PutItemInInventory(MainCursor, *itemTwoToPush, true)) + CalcBonuses(); + + if (mat != _MaterialInvalid) { - CalcBonuses(); - //Message(15, "Successfully removed an augmentation!"); - if (mat != _MaterialInvalid) - { - SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. - } + 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)) + { + 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!"); + return; } } break; case 3: // Destroying augment (formerly done in birdbath/sealer with a solvent) - // RoF client does not require an augmentation solvent for destroying an augmentation in an item. - // Augments can be destroyed with a right click -> Destroy at any time. + // RoF client does not require an augmentation solvent for destroying an augmentation in an item. + // Augments can be destroyed with a right click -> Destroy at any time. aug = tobe_auged->GetAugment(in_augment->augment_index); if (aug) @@ -3170,12 +3189,13 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (!PutItemInInventory(item_slot, *itemOneToPush, true)) { - Message(15, "Failed to destroy augment properly!"); + Log.Out(Logs::General, Logs::Error, "Problem returning equipment item to player's inventory after augment deletion."); + Message(15, "Error: Failed to return item after destroying augment!"); } } CalcBonuses(); - //Message(15, "Successfully removed an augmentation!"); + if (mat != _MaterialInvalid) { SendWearChange(mat); @@ -3189,6 +3209,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) } else { + // Delegate to tradeskill object to perform combine Object::HandleAugmentation(this, in_augment, m_tradeskill_object); } return; From ee2d8a3d6d04766a4417bfee449b9406276e7d60 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 11 Nov 2015 13:49:10 -0800 Subject: [PATCH 402/846] Fix for FindMySQL not preferring mysql_root hint. --- cmake/FindMySQL.cmake | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake index 0578c8b0c..8a8673f35 100644 --- a/cmake/FindMySQL.cmake +++ b/cmake/FindMySQL.cmake @@ -21,6 +21,12 @@ IF(MYSQL_ROOT) NAMES mysql.h PATHS ${MYSQL_ROOT}/include PATH_SUFFIXES mysql + NO_DEFAULT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + ) + FIND_PATH(MySQL_INCLUDE_DIR + NAMES mysql.h + PATH_SUFFIXES mysql ) ELSE(MYSQL_ROOT) FIND_PATH(MySQL_INCLUDE_DIR @@ -30,49 +36,46 @@ ELSE(MYSQL_ROOT) ENDIF(MYSQL_ROOT) # Library -SET(MySQL_NAMES libmysql mysqlclient_r mysqlclient) +SET(MySQL_NAMES libmysql) IF(MYSQL_ROOT) - FIND_LIBRARY(MySQL_LIBRARY_DEBUG + FIND_LIBRARY(MySQL_LIBRARY NAMES ${MySQL_NAMES} - PATHS ${MYSQL_ROOT}/lib/debug /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 + PATHS ${MYSQL_ROOT}/lib PATH_SUFFIXES mysql + NO_DEFAULT_PATH + NO_SYSTEM_ENVIRONMENT_PATH ) - - FIND_LIBRARY(MySQL_LIBRARY_RELEASE + + FIND_LIBRARY(MySQL_LIBRARY NAMES ${MySQL_NAMES} - PATHS ${MYSQL_ROOT}/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 PATH_SUFFIXES mysql ) ELSE(MYSQL_ROOT) - FIND_LIBRARY(MySQL_LIBRARY_DEBUG - NAMES ${MySQL_NAMES} - PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 - PATH_SUFFIXES mysql - ) - - FIND_LIBRARY(MySQL_LIBRARY_RELEASE + FIND_LIBRARY(MySQL_LIBRARY NAMES ${MySQL_NAMES} PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 PATH_SUFFIXES mysql ) ENDIF(MYSQL_ROOT) -IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE) +IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY) SET(MySQL_FOUND TRUE) - SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} ) -ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE) + SET( MySQL_LIBRARIES ${MySQL_LIBRARY} ) +ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY) SET(MySQL_FOUND FALSE) SET( MySQL_LIBRARIES ) -ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE) +ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY) # handle the QUIETLY and REQUIRED arguments and set MySQL_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY_DEBUG MySQL_LIBRARY_RELEASE MySQL_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY MySQL_INCLUDE_DIR) IF(MySQL_FOUND) - SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} ) + SET( MySQL_LIBRARY_RELEASE ${MySQL_LIBRARY} ) + SET( MySQL_LIBRARY_DEBUG ${MySQL_LIBRARY} ) + SET( MySQL_LIBRARIES ${MySQL_LIBRARY_RELEASE} ${MySQL_LIBRARY_DEBUG} ) ELSE(MySQL_FOUND) SET( MySQL_LIBRARIES ) ENDIF(MySQL_FOUND) From f188851bfb8fe3f1ab649816a9f57456f35c597c Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 11 Nov 2015 13:52:52 -0800 Subject: [PATCH 403/846] Wont look for mysql .so on non-root systems --- cmake/FindMySQL.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake index 8a8673f35..5a7927552 100644 --- a/cmake/FindMySQL.cmake +++ b/cmake/FindMySQL.cmake @@ -52,7 +52,7 @@ IF(MYSQL_ROOT) ) ELSE(MYSQL_ROOT) FIND_LIBRARY(MySQL_LIBRARY - NAMES ${MySQL_NAMES} + NAMES ${MySQL_NAMES} mysqlclient_r mysqlclient PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 PATH_SUFFIXES mysql ) From 7c4abcc68d22754a344691a95cadb1bfb262382e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 14 Nov 2015 14:37:24 -0500 Subject: [PATCH 404/846] Fix int16 spell ID limit with items (click, procs, etc) See issue #7 (Did we resolve it yet?) --- common/item_struct.h | 2 +- common/patches/rof2_structs.h | 4 ++-- common/patches/rof_structs.h | 4 ++-- common/patches/sod_structs.h | 4 ++-- common/patches/sof_structs.h | 4 ++-- common/patches/uf_structs.h | 4 ++-- common/shareddb.cpp | 10 +++++----- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/common/item_struct.h b/common/item_struct.h index 1fcb49f51..64292f490 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -51,7 +51,7 @@ ** */ struct ItemEffect_Struct { - int16 Effect; + int32 Effect; uint8 Type; uint8 Level; uint8 Level2; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 22748af8d..81fc48eaa 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4624,7 +4624,7 @@ struct ClickEffectStruct struct ProcEffectStruct { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; @@ -4639,7 +4639,7 @@ struct ProcEffectStruct struct WornEffectStruct //worn, focus and scroll effect { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index adbfbb7fa..beb550cbc 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4623,7 +4623,7 @@ struct ClickEffectStruct struct ProcEffectStruct { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; @@ -4638,7 +4638,7 @@ struct ProcEffectStruct struct WornEffectStruct //worn, focus and scroll effect { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 4e537221c..d9abef4c6 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4111,7 +4111,7 @@ struct ClickEffectStruct struct ProcEffectStruct { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; @@ -4126,7 +4126,7 @@ struct ProcEffectStruct struct WornEffectStruct //worn, focus and scroll effect { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index d15f20999..db7cfe028 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3965,7 +3965,7 @@ struct ClickEffectStruct struct ProcEffectStruct { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; @@ -3980,7 +3980,7 @@ struct ProcEffectStruct struct WornEffectStruct //worn, focus and scroll effect { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 046eb5138..3631edea3 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -4206,7 +4206,7 @@ struct ClickEffectStruct struct ProcEffectStruct { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; @@ -4221,7 +4221,7 @@ struct ProcEffectStruct struct WornEffectStruct //worn, focus and scroll effect { - uint32 effect; + int32 effect; uint8 level2; uint32 type; uint8 level; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index ed4106598..0c8fae730 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -997,23 +997,23 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ strcpy(item.CharmFile,row[ItemField::charmfile]); - item.Proc.Effect = (uint16)atoul(row[ItemField::proceffect]); + item.Proc.Effect = (int32)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.Effect = (int32)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.Effect = (int32)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.Effect = (int32)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.Effect = (int32)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]); From 7c414728773f3a756bd9ad6960eb7f1ffb8b5865 Mon Sep 17 00:00:00 2001 From: Shendare Date: Sat, 14 Nov 2015 11:40:28 -0800 Subject: [PATCH 405/846] Fixed swapping error message You now get the error message if the augment swap doesn't work, instead of when it works. One little bang. --- 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 36c4e1da8..b42b53e04 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -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(MainCursor, *itemTwoToPush, true)) + if (!PutItemInInventory(MainCursor, *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!"); From 525a39912fa149197230692633faceb1813d1375 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 15 Nov 2015 16:35:11 -0500 Subject: [PATCH 406/846] Override Mob::GetEndurancePercent() for Merc This allows their endurance to show in group! --- zone/merc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/merc.h b/zone/merc.h index 4f52d7367..1e409e0ce 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -192,6 +192,7 @@ public: virtual void ScaleStats(int scalepercent, bool setmax = false); 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; } From 8464a0e3b51805edda1877e3f006e46e31f05c0e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 Nov 2015 18:15:46 -0500 Subject: [PATCH 407/846] Implement Guild Banks for RoF/RoF2 Everything appears to work, but please test! --- common/base_packet.h | 2 + common/emu_oplist.h | 1 + common/eq_packet_structs.h | 16 ++++ common/patches/rof.cpp | 134 ++++++++++++++++++++++++++++++++++ common/patches/rof2.cpp | 134 ++++++++++++++++++++++++++++++++++ common/patches/rof2_ops.h | 2 + common/patches/rof2_structs.h | 108 +++++++++++++++++++++++++++ common/patches/rof_ops.h | 2 + common/patches/rof_structs.h | 108 +++++++++++++++++++++++++++ utils/patches/patch_RoF.conf | 1 + utils/patches/patch_RoF2.conf | 1 + zone/client_packet.cpp | 14 ---- zone/guild.cpp | 4 +- zone/guild_mgr.cpp | 89 ++++++++++++++++++---- 14 files changed, 585 insertions(+), 31 deletions(-) diff --git a/common/base_packet.h b/common/base_packet.h index 027b8d2fb..16a527ade 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -67,6 +67,8 @@ public: uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; } uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; } + uint16 ReadUInt16() { uint16 value = *(uint16 *)(pBuffer + _rpos); _rpos += sizeof(uint16); return value; } + uint16 ReadUInt16(uint32 Offset) const { uint16 value = *(uint16 *)(pBuffer + Offset); return value; } uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; } uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; } void ReadString(char *str) { uint32 len = static_cast(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; } diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 28ec9af0f..223491ecd 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -215,6 +215,7 @@ N(OP_GroupUpdate), N(OP_GroupUpdateB), N(OP_GroupUpdateLeaderAA), N(OP_GuildBank), +N(OP_GuildBankItemList), N(OP_GuildCreate), N(OP_GuildDelete), N(OP_GuildDemote), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 3f6476ba9..74eb9536e 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4724,6 +4724,22 @@ struct GuildBankItemUpdate_Struct /*226*/ uint16 Unknown226; }; +// newer clients (RoF+) send a list that contains 240 entries +// The packets don't actually use all 64 chars in the strings, but we'll just overallocate for these +struct GuildBankItemListEntry_Struct +{ + uint8 vaild; + uint32 permissions; + char whofor[64]; + char donator[64]; + uint32 item_id; + uint32 item_icon; + uint32 quantity; + uint8 allow_merge; // 1 here for non-full stacks + uint8 usable; + char item_name[64]; +}; + struct GuildBankClear_Struct { /*00*/ uint32 Action; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 4ee6d4ec0..79c7271fd 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1179,6 +1179,54 @@ namespace RoF dest->FastQueuePacket(&outapp); } + ENCODE(OP_GuildBank) + { + auto in = *p; + *p = nullptr; + auto outapp = new EQApplicationPacket(OP_GuildBank, in->size + 4); // all of them are 4 bytes bigger + + // The first action in the enum was removed, everything 1 less + // Normally we cast them to their structs, but there are so many here! will only do when it's easier + switch (in->ReadUInt32()) { + case 10: // GuildBankAcknowledge + outapp->WriteUInt32(9); + outapp->WriteUInt32(in->ReadUInt32()); + outapp->WriteUInt32(0); + break; + case 5: // GuildBankDeposit (ack) + outapp->WriteUInt32(4); + outapp->WriteUInt32(in->ReadUInt32()); + outapp->WriteUInt32(0); + outapp->WriteUInt32(in->ReadUInt32()); + break; + case 1: { // GuildBankItemUpdate + auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer; + auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer; + eq->Action = 0; + OUT(Unknown004); + eq->Unknown08 = 0; + OUT(SlotID); + OUT(Area); + OUT(Unknown012); + OUT(ItemID); + OUT(Icon); + OUT(Quantity); + OUT(Permissions); + OUT(AllowMerge); + OUT(Useable); + OUT_str(ItemName); + OUT_str(Donator); + OUT_str(WhoFor); + OUT(Unknown226); + break; + } + default: + break; + } + delete in; + dest->FastQueuePacket(&outapp); + } + ENCODE(OP_GuildMemberList) { //consume the packet @@ -4590,6 +4638,92 @@ namespace RoF DECODE_FORWARD(OP_GroupInvite); } + DECODE(OP_GuildBank) + { + // all actions are 1 off due to the removal of one of enums + switch (__packet->ReadUInt32()) { + case 2: {// GuildBankPromote + DECODE_LENGTH_EXACT(structs::GuildBankPromote_Struct); + SETUP_DIRECT_DECODE(GuildBankPromote_Struct, structs::GuildBankPromote_Struct); + emu->Action = 3; + IN(Unknown04); + IN(Slot); + IN(Slot2); + FINISH_DIRECT_DECODE(); + return; + } + case 3: { // GuildBankViewItem + DECODE_LENGTH_EXACT(structs::GuildBankViewItem_Struct); + SETUP_DIRECT_DECODE(GuildBankViewItem_Struct, structs::GuildBankViewItem_Struct); + emu->Action = 4; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Unknown16); + FINISH_DIRECT_DECODE(); + return; + } + case 4: { // GuildBankDeposit + __packet->WriteUInt32(5); + return; + } + case 5: { // GuildBankPermissions + DECODE_LENGTH_EXACT(structs::GuildBankPermissions_Struct); + SETUP_DIRECT_DECODE(GuildBankPermissions_Struct, structs::GuildBankPermissions_Struct); + emu->Action = 6; + IN(Unknown04); + IN(SlotID); + IN(Unknown10); + IN(ItemID); + IN(Permissions); + strn0cpy(emu->MemberName, eq->MemberName, 64); + FINISH_DIRECT_DECODE(); + return; + } + case 6: { // GuildBankWithdraw + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 7; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + case 7: { // GuildBankSplitStacks + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 8; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + case 8: { // GuildBankMergeStacks + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 9; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + default: + Log.Out(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action"); + __packet->SetOpcode(OP_Unknown); /* invalidate the packet */ + return; + } + } + DECODE(OP_GuildDemote) { DECODE_LENGTH_EXACT(structs::GuildDemoteStruct); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 7319dc98b..e5cc77791 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1250,6 +1250,54 @@ namespace RoF2 dest->FastQueuePacket(&outapp); } + ENCODE(OP_GuildBank) + { + auto in = *p; + *p = nullptr; + auto outapp = new EQApplicationPacket(OP_GuildBank, in->size + 4); // all of them are 4 bytes bigger + + // The first action in the enum was removed, everything 1 less + // Normally we cast them to their structs, but there are so many here! will only do when it's easier + switch (in->ReadUInt32()) { + case 10: // GuildBankAcknowledge + outapp->WriteUInt32(9); + outapp->WriteUInt32(in->ReadUInt32()); + outapp->WriteUInt32(0); + break; + case 5: // GuildBankDeposit (ack) + outapp->WriteUInt32(4); + outapp->WriteUInt32(in->ReadUInt32()); + outapp->WriteUInt32(0); + outapp->WriteUInt32(in->ReadUInt32()); + break; + case 1: { // GuildBankItemUpdate + auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer; + auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer; + eq->Action = 0; + OUT(Unknown004); + eq->Unknown08 = 0; + OUT(SlotID); + OUT(Area); + OUT(Unknown012); + OUT(ItemID); + OUT(Icon); + OUT(Quantity); + OUT(Permissions); + OUT(AllowMerge); + OUT(Useable); + OUT_str(ItemName); + OUT_str(Donator); + OUT_str(WhoFor); + OUT(Unknown226); + break; + } + default: + break; + } + delete in; + dest->FastQueuePacket(&outapp); + } + ENCODE(OP_GuildMemberList) { //consume the packet @@ -4739,6 +4787,92 @@ namespace RoF2 DECODE_FORWARD(OP_GroupInvite); } + DECODE(OP_GuildBank) + { + // all actions are 1 off due to the removal of one of enums + switch (__packet->ReadUInt32()) { + case 2: {// GuildBankPromote + DECODE_LENGTH_EXACT(structs::GuildBankPromote_Struct); + SETUP_DIRECT_DECODE(GuildBankPromote_Struct, structs::GuildBankPromote_Struct); + emu->Action = 3; + IN(Unknown04); + IN(Slot); + IN(Slot2); + FINISH_DIRECT_DECODE(); + return; + } + case 3: { // GuildBankViewItem + DECODE_LENGTH_EXACT(structs::GuildBankViewItem_Struct); + SETUP_DIRECT_DECODE(GuildBankViewItem_Struct, structs::GuildBankViewItem_Struct); + emu->Action = 4; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Unknown16); + FINISH_DIRECT_DECODE(); + return; + } + case 4: { // GuildBankDeposit + __packet->WriteUInt32(5); + return; + } + case 5: { // GuildBankPermissions + DECODE_LENGTH_EXACT(structs::GuildBankPermissions_Struct); + SETUP_DIRECT_DECODE(GuildBankPermissions_Struct, structs::GuildBankPermissions_Struct); + emu->Action = 6; + IN(Unknown04); + IN(SlotID); + IN(Unknown10); + IN(ItemID); + IN(Permissions); + strn0cpy(emu->MemberName, eq->MemberName, 64); + FINISH_DIRECT_DECODE(); + return; + } + case 6: { // GuildBankWithdraw + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 7; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + case 7: { // GuildBankSplitStacks + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 8; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + case 8: { // GuildBankMergeStacks + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 9; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + default: + Log.Out(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action"); + __packet->SetOpcode(OP_Unknown); /* invalidate the packet */ + return; + } + } + DECODE(OP_GuildDemote) { DECODE_LENGTH_EXACT(structs::GuildDemoteStruct); diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 3bb69af5e..9fe76e33c 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -57,6 +57,7 @@ E(OP_GroupFollow) E(OP_GroupFollow2) E(OP_GroupInvite) E(OP_GroupUpdate) +E(OP_GuildBank) E(OP_GuildMemberList) E(OP_GuildMemberUpdate) E(OP_GuildsList) @@ -152,6 +153,7 @@ D(OP_GroupFollow) D(OP_GroupFollow2) D(OP_GroupInvite) D(OP_GroupInvite2) +D(OP_GuildBank) D(OP_GuildDemote) D(OP_GuildRemove) D(OP_GuildStatus) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 81fc48eaa..1e93b7434 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1859,6 +1859,114 @@ struct GuildUpdate_Struct { GuildsListEntry_Struct entry; }; +struct GuildBankAck_Struct +{ +/*00*/ uint32 Action; // 10 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +}; + +struct GuildBankDepositAck_Struct +{ +/*00*/ uint32 Action; // 10 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint32 Fail; //1 = Fail, 0 = Success +}; + +struct GuildBankPromote_Struct +{ +/*00*/ uint32 Action; // 3 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*12*/ uint32 Slot; +/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3 +/*20*/ uint32 unknown20; +}; + +struct GuildBankPermissions_Struct +{ +/*00*/ uint32 Action; // 6 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; +/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits +/*12*/ uint32 ItemID; +/*16*/ uint32 Permissions; +/*20*/ char MemberName[64]; +}; + +struct GuildBankViewItem_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area +/*10*/ uint16 Area; +/*12*/ uint32 Unknown12; +/*16*/ uint32 Unknown16; +}; + +struct GuildBankWithdrawItem_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; +/*10*/ uint16 Area; +/*12*/ uint32 Unknown12; +/*16*/ uint32 Quantity; +/*20*/ +}; + +struct GuildBankItemUpdate_Struct +{ + void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity, + uint32 inPermissions, uint32 inAllowMerge, bool inUseable) + { + Action = inAction; + Unknown004 = inUnknown004; + SlotID = inSlotID; + Area = inArea; + Unknown012 = inUnknown012; + ItemID = inItemID; + Icon = inIcon; + Quantity = inQuantity; + Permissions = inPermissions; + AllowMerge = inAllowMerge; + Useable = inUseable; + ItemName[0] = '\0'; + Donator[0] = '\0'; + WhoFor[0] = '\0'; + }; + +/*000*/ uint32 Action; +/*004*/ uint32 Unknown004; +/*008*/ uint32 Unknown08; +/*012*/ uint16 SlotID; +/*014*/ uint16 Area; +/*016*/ uint32 Unknown012; +/*020*/ uint32 ItemID; +/*024*/ uint32 Icon; +/*028*/ uint32 Quantity; +/*032*/ uint32 Permissions; +/*036*/ uint8 AllowMerge; +/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission. +/*038*/ char ItemName[64]; +/*102*/ char Donator[64]; +/*166*/ char WhoFor[64]; +/*230*/ uint16 Unknown226; +}; + +struct GuildBankClear_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*12*/ uint32 DepositAreaCount; +/*16*/ uint32 MainAreaCount; +}; + /* ** Money Loot ** Length: 22 Bytes diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 8e9adfdc9..606c51c62 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -42,6 +42,7 @@ E(OP_GroupFollow) E(OP_GroupFollow2) E(OP_GroupInvite) E(OP_GroupUpdate) +E(OP_GuildBank) E(OP_GuildMemberList) E(OP_GuildMemberUpdate) E(OP_GuildsList) @@ -137,6 +138,7 @@ D(OP_GroupFollow) D(OP_GroupFollow2) D(OP_GroupInvite) D(OP_GroupInvite2) +D(OP_GuildBank) D(OP_GuildDemote) D(OP_GuildRemove) D(OP_GuildStatus) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index beb550cbc..e24935d35 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1889,6 +1889,114 @@ struct GuildUpdate_Struct { GuildsListEntry_Struct entry; }; +struct GuildBankAck_Struct +{ +/*00*/ uint32 Action; // 10 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +}; + +struct GuildBankDepositAck_Struct +{ +/*00*/ uint32 Action; // 10 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint32 Fail; //1 = Fail, 0 = Success +}; + +struct GuildBankPromote_Struct +{ +/*00*/ uint32 Action; // 3 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*12*/ uint32 Slot; +/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3 +/*20*/ uint32 unknown20; +}; + +struct GuildBankPermissions_Struct +{ +/*00*/ uint32 Action; // 6 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; +/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits +/*12*/ uint32 ItemID; +/*16*/ uint32 Permissions; +/*20*/ char MemberName[64]; +}; + +struct GuildBankViewItem_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area +/*10*/ uint16 Area; +/*12*/ uint32 Unknown12; +/*16*/ uint32 Unknown16; +}; + +struct GuildBankWithdrawItem_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; +/*10*/ uint16 Area; +/*12*/ uint32 Unknown12; +/*16*/ uint32 Quantity; +/*20*/ +}; + +struct GuildBankItemUpdate_Struct +{ + void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity, + uint32 inPermissions, uint32 inAllowMerge, bool inUseable) + { + Action = inAction; + Unknown004 = inUnknown004; + SlotID = inSlotID; + Area = inArea; + Unknown012 = inUnknown012; + ItemID = inItemID; + Icon = inIcon; + Quantity = inQuantity; + Permissions = inPermissions; + AllowMerge = inAllowMerge; + Useable = inUseable; + ItemName[0] = '\0'; + Donator[0] = '\0'; + WhoFor[0] = '\0'; + }; + +/*000*/ uint32 Action; +/*004*/ uint32 Unknown004; +/*008*/ uint32 Unknown08; +/*012*/ uint16 SlotID; +/*014*/ uint16 Area; +/*016*/ uint32 Unknown012; +/*020*/ uint32 ItemID; +/*024*/ uint32 Icon; +/*028*/ uint32 Quantity; +/*032*/ uint32 Permissions; +/*036*/ uint8 AllowMerge; +/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission. +/*038*/ char ItemName[64]; +/*102*/ char Donator[64]; +/*166*/ char WhoFor[64]; +/*230*/ uint16 Unknown226; +}; + +struct GuildBankClear_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*12*/ uint32 DepositAreaCount; +/*16*/ uint32 MainAreaCount; +}; + /* ** Money Loot ** Length: 22 Bytes diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index dfd8f0e84..7a33eb459 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -131,6 +131,7 @@ OP_GuildPromote=0x2945 OP_GuildPublicNote=0x3c2c OP_GuildManageBanker=0x389c # Was 0x096d OP_GuildBank=0x2ab0 # Was 0x10c3 +OP_GuildBankItemList=0x1cbf OP_SetGuildRank=0x3599 OP_GuildUpdateURLAndChannel=0x7851 OP_GuildStatus=0x25a5 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 0d1cb20ec..6afb7209e 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -130,6 +130,7 @@ OP_GuildPromote=0x6a98 OP_GuildPublicNote=0x5053 OP_GuildManageBanker=0x3f35 OP_GuildBank=0x5134 +OP_GuildBankItemList=0x7850 OP_SetGuildRank=0x0b9c OP_GuildUpdateURLAndChannel=0x2958 OP_GuildStatus=0x7326 diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c955399b8..a766f0470 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6683,20 +6683,6 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buffer); uint32 sentAction = Action; - if (GetClientVersion() >= ClientVersion::RoF) - { - Action += 1; - /* - // Need to find all of the action types for RoF and switch case here - switch(Action) - { - case 4: - Action = 5; - break; - } - */ - } - if (!IsInAGuild()) { Message(13, "You must be in a Guild to use the Guild Bank."); diff --git a/zone/guild.cpp b/zone/guild.cpp index 12f785b02..7b3c104f8 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -248,7 +248,9 @@ void Client::RefreshGuildInfo() if((guild_id != OldGuildID) && GuildBanks) { - ClearGuildBank(); + // Unsure about this for RoF+ ... But they don't have that action anymore so fuck it + if (GetClientVersion() < ClientVersion::RoF) + ClearGuildBank(); if(guild_id != GUILD_NONE) GuildBanks->SendGuildBank(this); diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index 8754a60e8..ed9957908 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -688,11 +688,68 @@ void GuildBankManager::SendGuildBank(Client *c) return; } + 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) { + 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); + if (Item) { + outapp->WriteUInt8(1); + outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Permissions); + outapp->WriteString(guild_bank->Items.DepositArea[i].WhoFor); + outapp->WriteString(guild_bank->Items.DepositArea[i].Donator); + outapp->WriteUInt32(Item->ID); + outapp->WriteUInt32(Item->Icon); + if (Item->Stackable) { + outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Quantity); + outapp->WriteUInt8(Item->StackSize == guild_bank->Items.DepositArea[i].Quantity ? 0 : 1); + } else { + outapp->WriteUInt32(1); + outapp->WriteUInt8(0); + } + outapp->WriteUInt8(Item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()) ? 1 : 0); + outapp->WriteString(Item->Name); + } else { + outapp->WriteUInt8(0); // empty + } + } + 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); + if (Item) { + outapp->WriteUInt8(1); + outapp->WriteUInt32(guild_bank->Items.MainArea[i].Permissions); + outapp->WriteString(guild_bank->Items.MainArea[i].WhoFor); + outapp->WriteString(guild_bank->Items.MainArea[i].Donator); + outapp->WriteUInt32(Item->ID); + outapp->WriteUInt32(Item->Icon); + if (Item->Stackable) { + outapp->WriteUInt32(guild_bank->Items.MainArea[i].Quantity); + outapp->WriteUInt8(Item->StackSize == guild_bank->Items.MainArea[i].Quantity ? 0 : 1); + } else { + outapp->WriteUInt32(1); + outapp->WriteUInt8(0); + } + outapp->WriteUInt8(Item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()) ? 1 : 0); + outapp->WriteString(Item->Name); + } else { + outapp->WriteUInt8(0); // empty + } + } + + outapp->size = outapp->GetWritePosition(); // truncate to used size + c->FastQueuePacket(&outapp); + return; + } + for(int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) { - if((*Iterator)->Items.DepositArea[i].ItemID > 0) + if(guild_bank->Items.DepositArea[i].ItemID > 0) { - const Item_Struct *Item = database.GetItem((*Iterator)->Items.DepositArea[i].ItemID); + const Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); if(!Item) continue; @@ -703,22 +760,22 @@ void GuildBankManager::SendGuildBank(Client *c) if(!Item->Stackable) gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon, 1, - (*Iterator)->Items.DepositArea[i].Permissions, 0, 0); + guild_bank->Items.DepositArea[i].Permissions, 0, 0); else { - if((*Iterator)->Items.DepositArea[i].Quantity == Item->StackSize) + if(guild_bank->Items.DepositArea[i].Quantity == Item->StackSize) gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon, - (*Iterator)->Items.DepositArea[i].Quantity, (*Iterator)->Items.DepositArea[i].Permissions, 0, 0); + guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 0, 0); else gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon, - (*Iterator)->Items.DepositArea[i].Quantity, (*Iterator)->Items.DepositArea[i].Permissions, 1, 0); + guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 1, 0); } strn0cpy(gbius->ItemName, Item->Name, sizeof(gbius->ItemName)); - strn0cpy(gbius->Donator, (*Iterator)->Items.DepositArea[i].Donator, sizeof(gbius->Donator)); + strn0cpy(gbius->Donator, guild_bank->Items.DepositArea[i].Donator, sizeof(gbius->Donator)); - strn0cpy(gbius->WhoFor, (*Iterator)->Items.DepositArea[i].WhoFor, sizeof(gbius->WhoFor)); + strn0cpy(gbius->WhoFor, guild_bank->Items.DepositArea[i].WhoFor, sizeof(gbius->WhoFor)); c->FastQueuePacket(&outapp); } @@ -726,9 +783,9 @@ void GuildBankManager::SendGuildBank(Client *c) for(int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) { - if((*Iterator)->Items.MainArea[i].ItemID > 0) + if(guild_bank->Items.MainArea[i].ItemID > 0) { - const Item_Struct *Item = database.GetItem((*Iterator)->Items.MainArea[i].ItemID); + const Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); if(!Item) continue; @@ -741,22 +798,22 @@ void GuildBankManager::SendGuildBank(Client *c) if(!Item->Stackable) gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon, 1, - (*Iterator)->Items.MainArea[i].Permissions, 0, Useable); + guild_bank->Items.MainArea[i].Permissions, 0, Useable); else { - if((*Iterator)->Items.MainArea[i].Quantity == Item->StackSize) + if(guild_bank->Items.MainArea[i].Quantity == Item->StackSize) gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon, - (*Iterator)->Items.MainArea[i].Quantity, (*Iterator)->Items.MainArea[i].Permissions, 0, Useable); + guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 0, Useable); else gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon, - (*Iterator)->Items.MainArea[i].Quantity, (*Iterator)->Items.MainArea[i].Permissions, 1, Useable); + guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 1, Useable); } strn0cpy(gbius->ItemName, Item->Name, sizeof(gbius->ItemName)); - strn0cpy(gbius->Donator, (*Iterator)->Items.MainArea[i].Donator, sizeof(gbius->Donator)); + strn0cpy(gbius->Donator, guild_bank->Items.MainArea[i].Donator, sizeof(gbius->Donator)); - strn0cpy(gbius->WhoFor, (*Iterator)->Items.MainArea[i].WhoFor, sizeof(gbius->WhoFor)); + strn0cpy(gbius->WhoFor, guild_bank->Items.MainArea[i].WhoFor, sizeof(gbius->WhoFor)); c->FastQueuePacket(&outapp); } From f3120f26ee7e073cac261db26d1d5415bb0164fd Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Fri, 20 Nov 2015 12:03:43 -0500 Subject: [PATCH 408/846] Fix issue with mobs no depopping (due to spawn_events) while zone is idle. --- zone/entity.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 69b13e6eb..af256a9ba 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -468,17 +468,27 @@ void EntityList::CorpseProcess() void EntityList::MobProcess() { -#ifdef IDLE_WHEN_EMPTY - if (numclients < 1) - return; -#endif + bool mob_dead; + auto it = mob_list.begin(); while (it != mob_list.end()) { uint16 id = it->first; Mob *mob = it->second; size_t sz = mob_list.size(); - bool p_val = mob->Process(); + +#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 { + mob_dead = !mob->Process(); + } +#else + mob_dead = !mob->Process(); +#endif size_t a_sz = mob_list.size(); if(a_sz > sz) { @@ -491,7 +501,7 @@ void EntityList::MobProcess() ++it; } - if(!p_val) { + if(mob_dead) { if(mob->IsNPC()) { entity_list.RemoveNPC(id); } From d383ecc5b716ee5108888fd0b3f2eae75b3f2d0f Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 22 Nov 2015 18:31:32 -0500 Subject: [PATCH 409/846] Fix for loginserver project compile failure --- changelog.txt | 3 +++ loginserver/CMakeLists.txt | 2 +- loginserver/database_mysql.cpp | 2 -- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 742edb5a5..8533293f0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/22/2015 == +Uleat: Fix for loginserver project compile failure + == 11/7/2015 == Akkadius: Implemented #repopclose [distance in units] - Used for development purposes, defaults to 500 units - Real case use: Large zones with 700 NPC's and you are making fast quick tweaks to nearby NPC's you can refresh just the NPC's around you instead of all in the zone diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index f588cbc48..bdd1bba07 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -43,7 +43,7 @@ ADD_EXECUTABLE(loginserver ${eqlogin_sources} ${eqlogin_headers}) INSTALL(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) -TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE}) +TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) IF(MSVC) SET_TARGET_PROPERTIES(loginserver PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index cffec5548..2e69dfca3 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -26,8 +26,6 @@ extern ErrorLog *server_log; extern LoginServer server; -#pragma comment(lib, "mysqlclient.lib") - DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, string name) { this->user = user; From 4bc844fe3b153c42530f2a19f8a0018ef49d8c66 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Tue, 24 Nov 2015 16:25:19 -0800 Subject: [PATCH 410/846] Work around for Bot::LoadPetBuffs loading buffs with counters --- zone/bot.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index 477581eba..9909c6d5d 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2026,6 +2026,16 @@ void Bot::LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { 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); From 6016ba514013f4da4f3df8b5d99a38515460902f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 30 Nov 2015 00:08:36 -0600 Subject: [PATCH 411/846] Add some things to future installer [skip ci] --- utils/scripts/eqemu_update.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 9c1556d21..3b9c46185 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -111,6 +111,7 @@ 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(); @@ -121,7 +122,8 @@ if($ARGV[0] eq "installer"){ #::: Database Routines print "MariaDB :: Creating Database 'peq'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE peq;CREATE DATABASE peq"`; + 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]); From c2b0e00cdddea9d476a129198b2a6fa95d41e8b2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 30 Nov 2015 00:34:10 -0600 Subject: [PATCH 412/846] Update eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 3b9c46185..02ba2ec75 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -134,6 +134,14 @@ if($ARGV[0] eq "installer"){ main_db_management(); print "\nApplying Latest Database Updates...\n"; main_db_management(); + if($OS eq "Windows"){ + check_windows_firewall_rules(); + } + + exit; +} +if($ARGV[0] eq "firewall_rules"){ + check_windows_firewall_rules(); exit; } @@ -511,6 +519,39 @@ sub copy_file{ } copy $l_source_file, $l_dest_file; } + +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_latest_windows_binaries{ print "\n --- Fetching Latest Windows Binaries... --- \n"; From 3135c923407e727d43214fefa3349ee593649971 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 Nov 2015 18:33:27 -0500 Subject: [PATCH 413/846] Changed criteria in a few bots scripts from count to null-result check --- changelog.txt | 3 + .../drop_bots (pre-update script).sql | 8 +- utils/sql/git/bots/drop_bots.sql | 8 +- .../sql/git/bots/required/2015_09_30_bots.sql | 74 +++++++++---------- 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/changelog.txt b/changelog.txt index 8533293f0..254b53845 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/30/2015 == +Uleat: Changed criteria for a few bots scripts from count to null/not null in hopes of fixing special case failures + == 11/22/2015 == Uleat: Fix for loginserver project compile failure diff --git a/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql b/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql index b55ce120b..24dcccb02 100644 --- a/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql +++ b/utils/sql/git/bots/deprecated/drop_bots (pre-update script).sql @@ -1,5 +1,5 @@ -- 'drop_bots (pre-update script)' sql script file --- current as of 10/09/2015 +-- current as of 11/30/2015 -- -- Note: This file will remove bot schema loaded by 'load_bots' sql scripts. -- There may still be remnants of bot activity in tables `guild_members` and @@ -50,12 +50,12 @@ BEGIN SELECT "restoring keys..."; - IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + IF (EXISTS(SELECT `CONSTRAINT_NAME` FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY')) THEN ALTER TABLE `group_id` DROP PRIMARY KEY; END IF; ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`); - IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + IF (EXISTS(SELECT `CONSTRAINT_NAME` FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY')) THEN ALTER TABLE `guild_members` DROP PRIMARY KEY; END IF; ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`); @@ -66,7 +66,7 @@ BEGIN SELECT "clearing database version..."; - IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'db_version' AND `COLUMN_NAME` = 'bots_version') > 0) THEN + IF (EXISTS(SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'db_version' AND `COLUMN_NAME` = 'bots_version')) THEN UPDATE `db_version` SET `bots_version` = 0; END IF; diff --git a/utils/sql/git/bots/drop_bots.sql b/utils/sql/git/bots/drop_bots.sql index 76c91fc47..59ae79773 100644 --- a/utils/sql/git/bots/drop_bots.sql +++ b/utils/sql/git/bots/drop_bots.sql @@ -1,5 +1,5 @@ -- 'drop_bots' sql script file --- current as of 10/09/2015 +-- current as of 11/30/2015 -- -- Note: This file will remove bot schema loaded by 'load_bots' sql scripts. -- There may still be remnants of bot activity in tables `guild_members` and @@ -62,12 +62,12 @@ BEGIN SELECT "restoring keys..."; - IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + IF (EXISTS(SELECT `CONSTRAINT_NAME` FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY')) THEN ALTER TABLE `group_id` DROP PRIMARY KEY; END IF; ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`); - IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + IF (EXISTS(SELECT `CONSTRAINT_NAME` FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY')) THEN ALTER TABLE `guild_members` DROP PRIMARY KEY; END IF; ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`); @@ -78,7 +78,7 @@ BEGIN SELECT "clearing database version..."; - IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'db_version' AND `COLUMN_NAME` = 'bots_version') > 0) THEN + IF (EXISTS(SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'db_version' AND `COLUMN_NAME` = 'bots_version')) THEN UPDATE `db_version` SET `bots_version` = 0; END IF; diff --git a/utils/sql/git/bots/required/2015_09_30_bots.sql b/utils/sql/git/bots/required/2015_09_30_bots.sql index b4e080846..97d225a61 100644 --- a/utils/sql/git/bots/required/2015_09_30_bots.sql +++ b/utils/sql/git/bots/required/2015_09_30_bots.sql @@ -1,5 +1,5 @@ -- '2015_09_30_bots' sql script file --- current as of 10/13/2015 +-- current as of 11/30/2015 -- -- Use eqemu_update.pl to administer this script @@ -31,11 +31,11 @@ BEGIN -- Alter - IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + IF (EXISTS(SELECT `CONSTRAINT_NAME` FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'guild_members' AND `CONSTRAINT_NAME` = 'PRIMARY')) THEN ALTER TABLE `guild_members` DROP PRIMARY KEY; END IF; - IF ((SELECT COUNT(*) FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY') > 0) THEN + IF (EXISTS(SELECT `CONSTRAINT_NAME` FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'group_id' AND `CONSTRAINT_NAME` = 'PRIMARY')) THEN ALTER TABLE `group_id` DROP PRIMARY KEY; END IF; ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`); @@ -46,65 +46,65 @@ BEGIN -- Commands - IF ((SELECT COUNT(`command`) FROM `commands` WHERE `command` LIKE 'bot') = 0) THEN + IF (NOT EXISTS(SELECT `command` FROM `commands` WHERE `command` LIKE 'bot')) THEN INSERT INTO `commands` VALUES ('bot', '0'); END IF; -- Rules - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion') > 0) THEN + IF (EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion')) THEN UPDATE `rule_values` SET `rule_name` = 'Bots:AAExpansion' WHERE `rule_name` LIKE 'Bots:BotAAExpansion'; END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion') = 0) THEN + IF (NOT EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion')) THEN INSERT INTO `rule_values` VALUES ('1', 'Bots:AAExpansion', '8', 'The expansion through which bots will obtain AAs'); END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount') > 0) THEN + IF (EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount')) THEN UPDATE `rule_values` SET `rule_name` = 'Bots:CreationLimit' WHERE `rule_name` LIKE 'Bots:CreateBotCount'; END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit') = 0) THEN + IF (NOT EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit')) THEN INSERT INTO `rule_values` VALUES ('1', 'Bots:CreationLimit', '150', 'Number of bots that each account can create'); END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing') > 0) THEN + IF (EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing')) THEN UPDATE `rule_values` SET `rule_name` = 'Bots:FinishBuffing' WHERE `rule_name` LIKE 'Bots:BotFinishBuffing'; END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing') = 0) THEN + IF (NOT EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing')) THEN 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.'); END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing') > 0) THEN + IF (EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing')) THEN UPDATE `rule_values` SET `rule_name` = 'Bots:GroupBuffing' WHERE `rule_name` LIKE 'Bots:BotGroupBuffing'; END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing') = 0) THEN + IF (NOT EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing')) THEN 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.'); END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen') > 0) THEN + IF (EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen')) THEN UPDATE `rule_values` SET `rule_name` = 'Bots:ManaRegen' WHERE `rule_name` LIKE 'Bots:BotManaRegen'; END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen') = 0) THEN + IF (NOT EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen')) THEN 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.'); END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest') > 0) THEN + IF (EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest')) THEN UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpawnLimit' WHERE `rule_name` LIKE 'Bots:BotQuest'; END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit') = 0) THEN + IF (NOT EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit')) THEN 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'); END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest') > 0) THEN + IF (EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest')) THEN UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpells' WHERE `rule_name` LIKE 'Bots:BotSpellQuest'; END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells') = 0) THEN + IF (NOT EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells')) THEN INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpells', 'false', 'Anita Thrall\'s (Anita_Thrall.pl) Bot Spell Scriber quests.'); END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount') > 0) THEN + IF (EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount')) THEN UPDATE `rule_values` SET `rule_name` = 'Bots:SpawnLimit' WHERE `rule_name` LIKE 'Bots:SpawnBotCount'; END IF; - IF ((SELECT COUNT(`rule_name`) FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit') = 0) THEN + IF (NOT EXISTS(SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit')) THEN 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'); END IF; @@ -165,7 +165,7 @@ BEGIN PRIMARY KEY (`bot_id`), INDEX `bot_id` (`bot_id`) ) ENGINE=InnoDB; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'bots') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'bots')) THEN INSERT INTO `bot_data` ( `bot_id`, `owner_id`, @@ -271,7 +271,7 @@ BEGIN PRIMARY KEY (`bot_id`), CONSTRAINT `FK_bot_stances_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ); - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botstances') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botstances')) THEN INSERT INTO `bot_stances` ( `bot_id`, `stance_id` @@ -293,7 +293,7 @@ BEGIN PRIMARY KEY (`bot_id`), CONSTRAINT `FK_bot_timers_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ); - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'bottimers') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'bottimers')) THEN INSERT INTO `bot_timers` ( `bot_id`, `timer_id`, @@ -335,7 +335,7 @@ BEGIN KEY `FK_bot_buffs_1` (`bot_id`), CONSTRAINT `FK_bot_buffs_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs')) THEN INSERT INTO `bot_buffs` ( `buffs_index`, `bot_id`, @@ -371,7 +371,7 @@ BEGIN INNER JOIN `bot_data` bd ON bb.`BotId` = bd.`bot_id`; - IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'dot_rune') > 0) THEN + IF (EXISTS(SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'dot_rune')) THEN UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` @@ -379,7 +379,7 @@ BEGIN WHERE bb.`bot_id` = bbo.`BotID`; END IF; - IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_x') > 0) THEN + IF (EXISTS(SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_x')) THEN UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` @@ -387,7 +387,7 @@ BEGIN WHERE bb.`bot_id` = bbo.`BotID`; END IF; - IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_y') > 0) THEN + IF (EXISTS(SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_y')) THEN UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` @@ -395,7 +395,7 @@ BEGIN WHERE bb.`bot_id` = bbo.`BotID`; END IF; - IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_z') > 0) THEN + IF (EXISTS(SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'caston_z')) THEN UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` @@ -403,7 +403,7 @@ BEGIN WHERE bb.`bot_id` = bbo.`BotID`; END IF; - IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'ExtraDIChance') > 0) THEN + IF (EXISTS(SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botbuffs' AND `COLUMN_NAME` = 'ExtraDIChance')) THEN UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` @@ -436,7 +436,7 @@ BEGIN KEY `FK_bot_inventories_1` (`bot_id`), CONSTRAINT `FK_bot_inventories_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ) ENGINE=InnoDB; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory')) THEN INSERT INTO `bot_inventories` ( `inventories_index`, `bot_id`, @@ -468,7 +468,7 @@ BEGIN INNER JOIN `bot_data` bd ON bi.`BotID` = bd.`bot_id`; - IF ((SELECT COUNT(*) FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory' AND `COLUMN_NAME` = 'augslot6') > 0) THEN + IF (EXISTS(SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botinventory' AND `COLUMN_NAME` = 'augslot6')) THEN UPDATE `bot_inventories` bi INNER JOIN `botinventory` bio ON bi.`inventories_index` = bio.`BotInventoryID` @@ -491,7 +491,7 @@ BEGIN CONSTRAINT `FK_bot_pets_1` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`), CONSTRAINT `U_bot_pets_1` UNIQUE (`bot_id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpets') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpets')) THEN INSERT INTO `bot_pets` ( `pets_index`, `pet_id`, @@ -524,7 +524,7 @@ BEGIN KEY `FK_bot_pet_buffs_1` (`pets_index`), CONSTRAINT `FK_bot_pet_buffs_1` FOREIGN KEY (`pets_index`) REFERENCES `bot_pets` (`pets_index`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpetbuffs') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpetbuffs')) THEN INSERT INTO `bot_pet_buffs` ( `pet_buffs_index`, `pets_index`, @@ -553,7 +553,7 @@ BEGIN KEY `FK_bot_pet_inventories_1` (`pets_index`), CONSTRAINT `FK_bot_pet_inventories_1` FOREIGN KEY (`pets_index`) REFERENCES `bot_pets` (`pets_index`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpetinventory') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botpetinventory')) THEN INSERT INTO `bot_pet_inventories` ( `pet_inventories_index`, `pets_index`, @@ -578,7 +578,7 @@ BEGIN KEY `FK_bot_groups_1` (`group_leader_id`), CONSTRAINT `FK_bot_groups_1` FOREIGN KEY (`group_leader_id`) REFERENCES `bot_data` (`bot_id`) ) ENGINE=InnoDB; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botgroup') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botgroup')) THEN INSERT INTO `bot_groups` ( `groups_index`, `group_leader_id`, @@ -605,7 +605,7 @@ BEGIN KEY `FK_bot_group_members_2` (`bot_id`), CONSTRAINT `FK_bot_group_members_2` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) ) ENGINE=InnoDB; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botgroupmembers') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botgroupmembers')) THEN INSERT INTO `bot_group_members` ( `group_members_index`, `groups_index`, @@ -636,7 +636,7 @@ BEGIN `alt` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY (`bot_id`) ) ENGINE=InnoDB; - IF ((SELECT COUNT(*) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botguildmembers') > 0) THEN + IF (EXISTS(SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'botguildmembers')) THEN INSERT INTO `bot_guild_members` ( `bot_id`, `guild_id`, From 6f8600b885a1c740eff18377e0e02af244d9b859 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 Nov 2015 20:16:21 -0500 Subject: [PATCH 414/846] Draft versions of bot command spell scripts (may still be tweaked based on actual command implementation) --- .../_blank_spells.sql | 135 +++++++++++ .../bind_affinity_spells.sql | 78 +++++++ .../charm_spells.sql | 73 ++++++ .../bot_command_spell_scripts/cure_spells.sql | 193 +++++++++++++++ .../depart_spells.sql | 61 +++++ .../escape_spells.sql | 45 ++++ .../bot_command_spell_scripts/grow_spells.sql | 39 ++++ .../invisibility_spells.sql | 151 ++++++++++++ .../levitation_spells.sql | 94 ++++++++ .../bot_command_spell_scripts/lull_spells.sql | 86 +++++++ .../mesmerize_spells.sql | 76 ++++++ .../movement_speed_spells.sql | 74 ++++++ .../resistance_spells.sql | 221 ++++++++++++++++++ .../resurrect_spells.sql | 71 ++++++ .../bot_command_spell_scripts/rune_spells.sql | 40 ++++ .../shrink_spells.sql | 49 ++++ .../water_breathing_spells.sql | 84 +++++++ 17 files changed, 1570 insertions(+) create mode 100644 utils/scripts/bot_command_spell_scripts/_blank_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/charm_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/cure_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/depart_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/escape_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/grow_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/invisibility_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/levitation_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/lull_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/resistance_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/resurrect_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/rune_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/shrink_spells.sql create mode 100644 utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql diff --git a/utils/scripts/bot_command_spell_scripts/_blank_spells.sql b/utils/scripts/bot_command_spell_scripts/_blank_spells.sql new file mode 100644 index 000000000..2250c7fa4 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/_blank_spells.sql @@ -0,0 +1,135 @@ +SELECT +-- base + CASE + WHEN `targettype` = '1' AND `CastRestriction` = '0' THEN 'TargetOptional' + WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' + WHEN `targettype` = '4' AND `CastRestriction` = '0' THEN 'AECaster' + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '5' AND `CastRestriction` = '150' THEN 'Animal' + WHEN `targettype` = '6' AND `CastRestriction` = '0' THEN 'Self' + WHEN `targettype` = '8' AND `CastRestriction` = '0' THEN 'AETarget' + WHEN `targettype` = '9' AND `CastRestriction` = '0' THEN 'Animal' + WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' + WHEN `targettype` = '11' AND `CastRestriction` = '0' THEN 'Summoned' + WHEN `targettype` = '13' AND `CastRestriction` = '0' THEN 'Tap' + WHEN `targettype` = '14' AND `CastRestriction` = '0' THEN 'Pet' + WHEN `targettype` = '15' AND `CastRestriction` = '0' THEN 'Corpse' + WHEN `targettype` = '16' AND `CastRestriction` = '0' THEN 'Plant' + WHEN `targettype` = '17' AND `CastRestriction` = '0' THEN 'Giant' + WHEN `targettype` = '18' AND `CastRestriction` = '0' THEN 'Dragon' + WHEN `targettype` = '34' AND `CastRestriction` = '0' THEN 'LDoNChest_Cursed' + WHEN `targettype` = '38' AND `CastRestriction` = '0' THEN 'SummonedPet' + WHEN `targettype` = '39' AND `CastRestriction` = '0' THEN 'GroupNoPets' -- V1 or V2? + WHEN `targettype` = '40' AND `CastRestriction` = '0' THEN 'AEBard' + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + WHEN `targettype` = '42' AND `CastRestriction` = '0' THEN 'Directional' + WHEN `targettype` = '43' AND `CastRestriction` = '0' THEN 'GroupClientAndPet' + WHEN `targettype` = '44' AND `CastRestriction` = '0' THEN 'Beam' + WHEN `targettype` = '45' AND `CastRestriction` = '0' THEN 'Ring' + WHEN `targettype` = '46' AND `CastRestriction` = '0' THEN 'TargetsTarget' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name +-- base + +FROM ( + SELECT 'WARRIOR' caster_class, `classes1` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes1` NOT IN ('254', '255') +UNION ALL + SELECT 'CLERIC' caster_class, `classes2` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes2` NOT IN ('254', '255') +UNION ALL + SELECT 'PALADIN' caster_class, `classes3` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes3` NOT IN ('254', '255') +UNION ALL + SELECT 'RANGER' caster_class, `classes4` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes4` NOT IN ('254', '255') +UNION ALL + SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes5` NOT IN ('254', '255') +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') +UNION ALL + SELECT 'MONK' caster_class, `classes7` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes7` NOT IN ('254', '255') +UNION ALL + SELECT 'BARD' caster_class, `classes8` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes8` NOT IN ('254', '255') +UNION ALL + SELECT 'ROGUE' caster_class, `classes9` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes9` NOT IN ('254', '255') +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') +UNION ALL + SELECT 'WIZARD' caster_class, `classes12` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes12` NOT IN ('254', '255') +UNION ALL + SELECT 'MAGICIAN' caster_class, `classes13` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes13` NOT IN ('254', '255') +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') +UNION ALL + SELECT 'BEASTLORD' caster_class, `classes15` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes15` NOT IN ('254', '255') +UNION ALL + SELECT 'BERSERKER' caster_class, `classes16` spell_level, + `spells_new`.* + FROM `spells_new` + WHERE `classes16` NOT IN ('254', '255') +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Animal', 'Undead', 'Summoned', 'Pet', 'Plant', 'TargetsTarget', 'Single', 'Self', 'GroupV1', 'GroupV2', 'GroupNoPets', 'AECaster', 'AETarget', 'Corpse'), + zone_type, + FIELD(caster_class, 'WARRIOR', 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'MONK', 'BARD', 'ROGUE', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'MAGICIAN', 'ENCHANTER', 'BEASTLORD', 'BERSERKER'), + spell_level, + spell_id, + spell_name diff --git a/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql b/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql new file mode 100644 index 000000000..a48b3318b --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql @@ -0,0 +1,78 @@ +SELECT +-- base + CASE + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost +-- base + +FROM ( + SELECT 'CLERIC' caster_class, `classes2` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes2` NOT IN ('254', '255') + AND `SpellAffectIndex` = '14' + AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` = '14' + AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` = '14' + AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` = '14' + AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'WIZARD' caster_class, `classes12` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes12` NOT IN ('254', '255') + AND `SpellAffectIndex` = '14' + AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'MAGICIAN' caster_class, `classes13` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes13` NOT IN ('254', '255') + AND `SpellAffectIndex` = '14' + AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` = '14' + AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY mana_cost DESC, + FIELD(target_type, 'Single'), + spell_level, + FIELD(caster_class, 'CLERIC', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/charm_spells.sql b/utils/scripts/bot_command_spell_scripts/charm_spells.sql new file mode 100644 index 000000000..f2c5e82b8 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/charm_spells.sql @@ -0,0 +1,73 @@ +SELECT +-- base + CASE + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '9' AND `CastRestriction` = '0' THEN 'Animal' + WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' + WHEN `targettype` = '11' AND `CastRestriction` = '0' THEN 'Summoned' + WHEN `targettype` = '16' AND `CastRestriction` = '0' THEN 'Plant' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + `ResistDiff` resist_diff, + `max1` max_target_level +-- extra + +FROM ( + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'MAGICIAN' caster_class, `classes13` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes13` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY resist_diff, + FIELD(target_type, 'Animal', 'Undead', 'Summoned', 'Plant', 'Single'), + max_target_level DESC, + spell_level, + FIELD(caster_class, 'DRUID', 'SHAMAN', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/cure_spells.sql b/utils/scripts/bot_command_spell_scripts/cure_spells.sql new file mode 100644 index 000000000..75ef1d25c --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/cure_spells.sql @@ -0,0 +1,193 @@ +SELECT +-- base + CASE + WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + ( + (IF(('20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '1', '0')) | + (IF(('35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '2', '0')) | + (IF(('36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '4', '0')) | + (IF(('116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '8', '0')) | + (IF(('369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '16', '0')) + ) cure_mask +-- extra + +FROM ( + SELECT 'CLERIC' caster_class, `classes2` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes2` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'PALADIN' caster_class, `classes3` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes3` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'RANGER' caster_class, `classes4` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes4` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes5` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'BARD' caster_class, `classes8` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes8` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'BEASTLORD' caster_class, `classes15` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes15` NOT IN ('254', '255') + AND `SpellAffectIndex` = '1' +-- 6-self, 10-undead, 14-pet, 45-ring + AND `targettype` NOT IN ('6', '10', '14', '45') + AND ( +-- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption + '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), + spell_level DESC, + cure_mask DESC, + FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'BARD', 'SHAMAN', 'NECROMANCER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/depart_spells.sql b/utils/scripts/bot_command_spell_scripts/depart_spells.sql new file mode 100644 index 000000000..205ba27f1 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/depart_spells.sql @@ -0,0 +1,61 @@ +SELECT +-- base + CASE + WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + CONCAT('"', `teleport_zone`, '"') short_name, + CONCAT('"', IFNULL((SELECT `long_name` FROM `zone` WHERE `short_name` = `teleport_zone` LIMIT 1), 'Unreachable Destination'), '"') long_name +-- extra + +FROM ( + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `teleport_zone` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` = '40' + AND ( + '83' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '86' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR ( + '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + AND `teleport_zone` NOT LIKE 'same' + ) + ) +UNION ALL + SELECT 'WIZARD' caster_class, `classes12` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `teleport_zone` + FROM `spells_new` + WHERE `classes12` NOT IN ('254', '255') + AND `SpellAffectIndex` = '40' + AND ( + '83' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '86' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR ( + '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + AND `teleport_zone` NOT LIKE 'same' + ) + ) +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'GroupV1'), + FIELD(caster_class, 'DRUID', 'WIZARD'), + spell_level, + spell_name diff --git a/utils/scripts/bot_command_spell_scripts/escape_spells.sql b/utils/scripts/bot_command_spell_scripts/escape_spells.sql new file mode 100644 index 000000000..4e08ddeb0 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/escape_spells.sql @@ -0,0 +1,45 @@ +SELECT +-- base + CASE + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost +-- base + +FROM ( + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` = '40' + AND '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + AND `teleport_zone` LIKE 'same' +UNION ALL + SELECT 'WIZARD' caster_class, `classes12` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes12` NOT IN ('254', '255') + AND `SpellAffectIndex` = '40' + AND '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + AND `teleport_zone` LIKE 'same' +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'GroupV2'), + FIELD(caster_class, 'DRUID', 'WIZARD'), + spell_level, + spell_name diff --git a/utils/scripts/bot_command_spell_scripts/grow_spells.sql b/utils/scripts/bot_command_spell_scripts/grow_spells.sql new file mode 100644 index 000000000..4dbca1a06 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/grow_spells.sql @@ -0,0 +1,39 @@ +SELECT +-- base + CASE + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost +-- base + +FROM ( + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` = '10' +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '89' -- implementation restricted to `effectid1` + AND `effect_base_value1` > 100 -- implementation restricted to `effect_base_value1` +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Single'), + FIELD(caster_class, 'SHAMAN'), + spell_level, + spell_name diff --git a/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql b/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql new file mode 100644 index 000000000..8545cab30 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql @@ -0,0 +1,151 @@ +SELECT +-- base + CASE + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + CASE + WHEN `effectid1` = '12' THEN 'Living' + WHEN `effectid1` = '13' THEN 'See' + WHEN `effectid1` = '28' THEN 'Undead' + WHEN `effectid1` = '29' THEN 'Animal' + ELSE `effectid1` -- 'UNDEFINED' + END invis_type +-- extra + +FROM ( + SELECT 'CLERIC' caster_class, `classes2` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes2` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'PALADIN' caster_class, `classes3` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes3` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'RANGER' caster_class, `classes4` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes4` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes5` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'WIZARD' caster_class, `classes12` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes12` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'MAGICIAN' caster_class, `classes13` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes13` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +UNION ALL + SELECT 'BEASTLORD' caster_class, `classes15` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` + FROM `spells_new` + WHERE `classes15` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('5', '9') +-- 6-self + AND `targettype` NOT IN ('6') +-- 12-living, 13-see, 28-undead, 29-animal + AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(invis_type, 'Animal', 'Undead', 'Living', 'See'), + FIELD(target_type, 'Single', 'GroupV2'), + zone_type, + spell_level DESC, + spell_name, + FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'MAGICIAN', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/levitation_spells.sql b/utils/scripts/bot_command_spell_scripts/levitation_spells.sql new file mode 100644 index 000000000..2193c75b7 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/levitation_spells.sql @@ -0,0 +1,94 @@ +SELECT +-- base + CASE + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost +-- base + +FROM ( + SELECT 'RANGER' caster_class, `classes4` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes4` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '28') +-- 6-self, 43-groupclientandpet + AND `targettype` NOT IN ('6', '43') + AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '28') +-- 6-self, 43-groupclientandpet + AND `targettype` NOT IN ('6', '43') + AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '28') +-- 6-self, 43-groupclientandpet + AND `targettype` NOT IN ('6', '43') + AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '28') +-- 6-self, 43-groupclientandpet + AND `targettype` NOT IN ('6', '43') + AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'WIZARD' caster_class, `classes12` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes12` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '28') +-- 6-self, 43-groupclientandpet + AND `targettype` NOT IN ('6', '43') + AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '28') +-- 6-self, 43-groupclientandpet + AND `targettype` NOT IN ('6', '43') + AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'BEASTLORD' caster_class, `classes15` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes15` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '28') +-- 6-self, 43-groupclientandpet + AND `targettype` NOT IN ('6', '43') + AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Single', 'GroupV2'), + zone_type, + spell_level DESC, + spell_name, + FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/lull_spells.sql b/utils/scripts/bot_command_spell_scripts/lull_spells.sql new file mode 100644 index 000000000..2d0989b85 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/lull_spells.sql @@ -0,0 +1,86 @@ +-- needs criteria refinement + +SELECT +-- base + CASE + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '8' AND `CastRestriction` = '0' THEN 'AETarget' + WHEN `targettype` = '9' AND `CastRestriction` = '0' THEN 'Animal' + WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost +-- base + +FROM ( + SELECT 'CLERIC' caster_class, `classes2` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes2` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'PALADIN' caster_class, `classes3` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes3` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'RANGER' caster_class, `classes4` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes4` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes5` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` = '12' + AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Animal', 'Undead', 'Single', 'AETarget'), + target_type, + zone_type, + FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'NECROMANCER', 'ENCHANTER'), + spell_level, + spell_id, + spell_name diff --git a/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql b/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql new file mode 100644 index 000000000..a23d62af6 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql @@ -0,0 +1,76 @@ +-- needs criteria refinement + +SELECT +-- base + CASE + WHEN `targettype` = '4' AND `CastRestriction` = '0' THEN 'AECaster' + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '8' AND `CastRestriction` = '0' THEN 'AETarget' + WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' + WHEN `targettype` = '11' AND `CastRestriction` = '0' THEN 'Summoned' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + `ResistDiff` resist_diff, + `max1` max_target_level +-- extra + +FROM ( + SELECT 'BARD' caster_class, `classes8` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes8` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') +-- 45-ring + AND `targettype` NOT IN ('45') + AND `effectid1` = '31' +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') +-- 45-ring + AND `targettype` NOT IN ('45') + AND `effectid1` = '31' +UNION ALL + SELECT 'MAGICIAN' caster_class, `classes13` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes13` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') +-- 45-ring + AND `targettype` NOT IN ('45') + AND `effectid1` = '31' +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') +-- 45-ring + AND `targettype` NOT IN ('45') + AND `effectid1` = '31' +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY resist_diff, + FIELD(target_type, 'Undead', 'Summoned', 'Single', 'AECaster', 'AETarget'), + max_target_level DESC, + spell_level DESC, + FIELD(caster_class, 'BARD', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql b/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql new file mode 100644 index 000000000..aaabf2fa2 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql @@ -0,0 +1,74 @@ +SELECT +-- base + CASE + WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + `effect_base_value2` base_speed +-- extra + +FROM ( + SELECT 'RANGER' caster_class, `classes4` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` + FROM `spells_new` + WHERE `classes4` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('7', '10') +-- 6-self + AND `targettype` NOT IN ('6') + AND `CastRestriction` = '0' + AND `effectdescnum` = '65' +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('7', '10') +-- 6-self + AND `targettype` NOT IN ('6') + AND `CastRestriction` = '0' + AND `effectdescnum` = '65' +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('7', '10') +-- 6-self + AND `targettype` NOT IN ('6') + AND `CastRestriction` = '0' + AND `effectdescnum` = '65' +UNION ALL + SELECT 'BEASTLORD' caster_class, `classes15` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` + FROM `spells_new` + WHERE `classes15` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('7', '10') +-- 6-self + AND `targettype` NOT IN ('6') + AND `CastRestriction` = '0' + AND `effectdescnum` = '65' +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), + effect_base_value2 DESC, + spell_level, + FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/resistance_spells.sql b/utils/scripts/bot_command_spell_scripts/resistance_spells.sql new file mode 100644 index 000000000..0cda671e7 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/resistance_spells.sql @@ -0,0 +1,221 @@ +SELECT +-- base + CASE + WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + ( + (IF(('46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '1', '0')) | + (IF(('47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '2', '0')) | + (IF(('48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '4', '0')) | + (IF(('49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '8', '0')) | + (IF(('50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '16', '0')) | + (IF(('370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '32', '0')) + ) resist_type +-- extra + +FROM ( + SELECT 'CLERIC' caster_class, `classes2` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes2` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'PALADIN' caster_class, `classes3` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes3` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'RANGER' caster_class, `classes4` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes4` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes5` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'MAGICIAN' caster_class, `classes13` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes13` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +UNION ALL + SELECT 'BEASTLORD' caster_class, `classes15` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, + `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` + FROM `spells_new` + WHERE `classes15` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' +-- 6-self, 14-pet, 39-groupnopets, 46-targetstarget + AND `targettype` NOT IN ('6', '14', '39', '46') + AND ( + + '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) + ) +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), + spell_level DESC, + resist_type DESC, + FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'SHAMAN', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql b/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql new file mode 100644 index 000000000..ac5903727 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql @@ -0,0 +1,71 @@ +SELECT +-- base + CASE + WHEN `targettype` = '4' AND `CastRestriction` = '0' THEN 'AECaster' + WHEN `targettype` = '15' AND `CastRestriction` = '0' THEN 'Corpse' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + `effect_base_value1` percent +-- extra + +FROM ( + SELECT 'CLERIC' caster_class, `classes2` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` + FROM `spells_new` + WHERE `classes2` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('1', '13') + AND `effectid1` = '81' +UNION ALL + SELECT 'PALADIN' caster_class, `classes3` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` + FROM `spells_new` + WHERE `classes3` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('1', '13') + AND `effectid1` = '81' +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('1', '13') + AND `effectid1` = '81' +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('1', '13') + AND `effectid1` = '81' +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('1', '13') + AND `effectid1` = '81' +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY percent DESC, + FIELD(target_type, 'Corpse', 'AETarget'), + zone_type, + FIELD(caster_class, 'CLERIC', 'PALADIN', 'DRUID', 'SHAMAN', 'NECROMANCER'), + spell_level, + spell_id, + spell_name diff --git a/utils/scripts/bot_command_spell_scripts/rune_spells.sql b/utils/scripts/bot_command_spell_scripts/rune_spells.sql new file mode 100644 index 000000000..30ebee130 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/rune_spells.sql @@ -0,0 +1,40 @@ +SELECT +-- base + CASE + WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost, +-- base +-- extra + `max1` max_absorbtion +-- extra + +FROM ( + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `max1` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` = '2' + AND `effectid1` = '55' +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), + spell_level DESC, + max1 DESC diff --git a/utils/scripts/bot_command_spell_scripts/shrink_spells.sql b/utils/scripts/bot_command_spell_scripts/shrink_spells.sql new file mode 100644 index 000000000..26ee84883 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/shrink_spells.sql @@ -0,0 +1,49 @@ +SELECT +-- base + CASE + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost +-- base + +FROM ( + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` = '10' +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '89' -- implementation restricted to `effectid1` + AND `effect_base_value1` < 100 -- implementation restricted to `effect_base_value1` +UNION ALL + SELECT 'BEASTLORD' caster_class, `classes15` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes15` NOT IN ('254', '255') + AND `SpellAffectIndex` = '10' +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '89' -- implementation restricted to `effectid1` + AND `effect_base_value1` < 100 -- implementation restricted to `effect_base_value1` +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Single'), + FIELD(caster_class, 'SHAMAN', 'BEASTLORD'), + spell_level, + spell_name diff --git a/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql b/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql new file mode 100644 index 000000000..b6f815429 --- /dev/null +++ b/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql @@ -0,0 +1,84 @@ +SELECT +-- base + CASE + WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' + WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' + ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' + END target_type, + CASE + WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` + ELSE '0' + END zone_type, + caster_class, + spell_level, + `id` spell_id, + CONCAT('"', `name`, '"') spell_name, + `mana` mana_cost +-- base + +FROM ( + SELECT 'RANGER' caster_class, `classes4` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes4` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '14') +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '14' +UNION ALL + SELECT 'DRUID' caster_class, `classes6` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes6` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '14') +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '14' +UNION ALL + SELECT 'SHAMAN' caster_class, `classes10` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes10` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '14') +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '14' +UNION ALL + SELECT 'NECROMANCER' caster_class, `classes11` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes11` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '14') +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '14' +UNION ALL + SELECT 'ENCHANTER' caster_class, `classes14` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes14` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '14') +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '14' +UNION ALL + SELECT 'BEASTLORD' caster_class, `classes15` spell_level, + `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` + FROM `spells_new` + WHERE `classes15` NOT IN ('254', '255') + AND `SpellAffectIndex` IN ('2', '14') +-- 6-self + AND `targettype` NOT IN ('6') + AND `effectid1` = '14' +) spells + +-- WHERE `name` NOT LIKE '%II' +-- --- +-- WHERE `name` NOT LIKE '%Rk. II%' +-- AND `name` NOT LIKE '%Rk.II%' +-- AND `name` NOT LIKE '%Rk. III%' +-- AND `name` NOT LIKE '%Rk.III%' +ORDER BY FIELD(target_type, 'Single', 'GroupV2'), + spell_level, + spell_name, + FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'NECROMANCER', 'ENCHANTER', 'BEASTLORD') From 549cabe7e8886c95ee20265fe21fee48f9ce1f08 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 1 Dec 2015 15:25:26 -0600 Subject: [PATCH 415/846] Added Options 11) and 12) to eqemu_update.pl, updated to version 12 11) [Windows Server Build] :: Download Latest and Stable Server Build (Overwrites existing .exe's, includes .dll's) 12) [Windows Server .dll's] :: Download Pre-Requisite Server .dll's --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 56 +++++++++------------------------ 2 files changed, 15 insertions(+), 43 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index fb2cc80d1..fc5877e05 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -493,7 +493,7 @@ bool Database::CheckDatabaseConversions() { /* 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 11"); + system("perl eqemu_update.pl V 12"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 02ba2ec75..358384f68 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -23,7 +23,7 @@ if($Config{osname}=~/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 = 11; +$current_version = 12; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -119,6 +119,8 @@ if($ARGV[0] eq "installer"){ quest_files_fetch(); lua_modules_fetch(); 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); #::: Database Routines print "MariaDB :: Creating Database 'peq'\n"; @@ -134,14 +136,6 @@ if($ARGV[0] eq "installer"){ main_db_management(); print "\nApplying Latest Database Updates...\n"; main_db_management(); - if($OS eq "Windows"){ - check_windows_firewall_rules(); - } - - exit; -} -if($ARGV[0] eq "firewall_rules"){ - check_windows_firewall_rules(); exit; } @@ -231,6 +225,8 @@ sub show_menu_prompt { 8 => \&quest_files_fetch, 9 => \&lua_modules_fetch, 10 => \&aa_fetch, + 11 => \&fetch_latest_windows_binaries, + 12 => \&fetch_server_dlls, 20 => \&do_update_self, 0 => \&script_exit, ); @@ -304,6 +300,8 @@ return < Date: Tue, 1 Dec 2015 15:27:07 -0600 Subject: [PATCH 416/846] Re-add some nuked code eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 358384f68..4a3d993b2 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -136,6 +136,9 @@ if($ARGV[0] eq "installer"){ main_db_management(); print "\nApplying Latest Database Updates...\n"; main_db_management(); + if($OS eq "Windows"){ + check_windows_firewall_rules(); + } exit; } @@ -541,6 +544,39 @@ sub fetch_latest_windows_binaries{ rmtree('updates_staged'); } +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); From fe48f18f716478598024219f8d07ea035efb5824 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 1 Dec 2015 20:30:43 -0500 Subject: [PATCH 417/846] Added rule-based check for race/class restriction of spell scribing --- common/ruletypes.h | 1 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2015_12_01_spell_scribe_restriction_rule.sql | 7 +++++++ zone/client_process.cpp | 5 +++++ 5 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2015_12_01_spell_scribe_restriction_rule.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index 06b908e76..91d3479be 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -125,6 +125,7 @@ RULE_BOOL(Character, ActiveInvSnapshots, false) // Takes a periodic snapshot of RULE_INT(Character, InvSnapshotMinIntervalM, 180) // Minimum time (in minutes) between inventory snapshots RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt an inventory snapshot after a failure 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_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/common/version.h b/common/version.h index 4f39b595c..1e1a9dc35 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 9089 +#define CURRENT_BINARY_DATABASE_VERSION 9090 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index aa1e46be9..3a34e4b09 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -343,6 +343,7 @@ 9087|2015_09_25_inventory_snapshots.sql|SHOW TABLES LIKE 'inventory_snapshots'|empty| 9088|2015_11_01_perl_event_export_settings.sql|SHOW TABLES LIKE 'perl_event_export_settings'|empty| 9089|2015_11_02_ai_idle_no_spell_recast_default_changes.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Spells:AI_IdleNoSpellMinRecast%' AND `rule_value` = '500'|not_empty| +9090|2015_12_01_spell_scribe_restriction_rule.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Character:RestrictSpellScribing'|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/2015_12_01_spell_scribe_restriction_rule.sql b/utils/sql/git/required/2015_12_01_spell_scribe_restriction_rule.sql new file mode 100644 index 000000000..277e66882 --- /dev/null +++ b/utils/sql/git/required/2015_12_01_spell_scribe_restriction_rule.sql @@ -0,0 +1,7 @@ +INSERT INTO `rule_values` VALUES ('0', 'Character:RestrictSpellScribing', 'false', 'Restricts spell scribing to allowable races/classes of spell scroll, if true'); +INSERT INTO `rule_values` VALUES ('1', 'Character:RestrictSpellScribing', 'false', 'Restricts spell scribing to allowable races/classes of spell scroll, if true'); +INSERT INTO `rule_values` VALUES ('2', 'Character:RestrictSpellScribing', 'false', 'Restricts spell scribing to allowable races/classes of spell scroll, if true'); +INSERT INTO `rule_values` VALUES ('3', 'Character:RestrictSpellScribing', 'false', 'Restricts spell scribing to allowable races/classes of spell scroll, if true'); +INSERT INTO `rule_values` VALUES ('4', 'Character:RestrictSpellScribing', 'false', 'Restricts spell scribing to allowable races/classes of spell scroll, if true'); +INSERT INTO `rule_values` VALUES ('5', 'Character:RestrictSpellScribing', 'false', 'Restricts spell scribing to allowable races/classes of spell scroll, if true'); +INSERT INTO `rule_values` VALUES ('10', 'Character:RestrictSpellScribing', 'false', 'Restricts spell scribing to allowable races/classes of spell scroll, if true'); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index a0be235a7..3b973e7b7 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1153,6 +1153,11 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) { const Item_Struct* item = inst->GetItem(); + if (RuleB(Character, RestrictSpellScribing) && !item->IsEquipable(GetRace(), GetClass())) { + Message_StringID(13, CANNOT_USE_ITEM); + break; + } + if(item && item->Scroll.Effect == (int32)(memspell->spell_id)) { ScribeSpell(memspell->spell_id, memspell->slot); From af183775054abbcc3c50a8cbd5891512a5387bfc Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 2 Dec 2015 13:14:26 -0600 Subject: [PATCH 418/846] Some loginserver refactoring --- common/servertalk.h | 2 +- loginserver/client.cpp | 8 +- loginserver/database_mysql.cpp | 56 +++++------ loginserver/login_server.h | 6 +- loginserver/main.cpp | 130 +++++++++----------------- loginserver/world_server.cpp | 164 ++++++++++++++++----------------- loginserver/world_server.h | 12 +-- world/login_server.cpp | 2 +- 8 files changed, 169 insertions(+), 211 deletions(-) diff --git a/common/servertalk.h b/common/servertalk.h index e7ce947c5..e476d023d 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -523,7 +523,7 @@ struct ServerLSPlayerZoneChange_Struct { uint32 from; // 0 = world uint32 to; // 0 = world }; -struct ServerLSClientAuth { +struct ClientAuth_Struct { uint32 lsaccount_id; // ID# in login server's db char name[30]; // username in login server's db char key[30]; // the Key the client will present diff --git a/loginserver/client.cpp b/loginserver/client.cpp index fe43e6675..28836f915 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -245,7 +245,7 @@ void Client::Handle_Login(const char* data, unsigned int size) if(result) { - server.CM->RemoveExistingClient(d_account_id); + server.client_manager->RemoveExistingClient(d_account_id); in_addr in; in.s_addr = connection->GetRemoteIP(); server.db->UpdateLSAccountData(d_account_id, string(inet_ntoa(in))); @@ -347,12 +347,12 @@ void Client::Handle_Play(const char* data) this->play_server_id = (unsigned int)play->ServerNumber; play_sequence_id = sequence_in; play_server_id = server_id_in; - server.SM->SendUserToWorldRequest(server_id_in, account_id); + server.server_manager->SendUserToWorldRequest(server_id_in, account_id); } void Client::SendServerListPacket() { - EQApplicationPacket *outapp = server.SM->CreateServerListPacket(this); + EQApplicationPacket *outapp = server.server_manager->CreateServerListPacket(this); if(server.options.IsDumpOutPacketsOn()) { @@ -378,7 +378,7 @@ void Client::GenerateKey() { key.clear(); int count = 0; - while(count < 10) + while (count < 10) { static const char key_selection[] = { diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index 2e69dfca3..0f309d7b4 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -61,7 +61,7 @@ DatabaseMySQL::~DatabaseMySQL() bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id) { - if(!db) + if (!db) { return false; } @@ -73,7 +73,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u query << name; query << "'"; - if(mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(db, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; @@ -81,9 +81,9 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u res = mysql_use_result(db); - if(res) + if (res) { - while((row = mysql_fetch_row(res)) != nullptr) + while ((row = mysql_fetch_row(res)) != nullptr) { id = atoi(row[0]); password = row[1]; @@ -97,9 +97,9 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u } bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id, - unsigned int &trusted, string &list_desc, string &account, string &password) + unsigned int &trusted, string &list_desc, string &account, string &password) { - if(!db) + if (!db) { return false; } @@ -109,7 +109,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un char escaped_short_name[101]; unsigned long length; length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); - escaped_short_name[length+1] = 0; + escaped_short_name[length + 1] = 0; stringstream query(stringstream::in | stringstream::out); query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, "; query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable(); @@ -118,16 +118,16 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un query << escaped_short_name; query << "'"; - if(mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(db, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; } res = mysql_use_result(db); - if(res) + if (res) { - if((row = mysql_fetch_row(res)) != nullptr) + if ((row = mysql_fetch_row(res)) != nullptr) { id = atoi(row[0]); desc = row[1]; @@ -137,22 +137,22 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un int db_account_id = atoi(row[5]); mysql_free_result(res); - if(db_account_id > 0) + if (db_account_id > 0) { stringstream query(stringstream::in | stringstream::out); query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable(); query << " WHERE ServerAdminID = " << db_account_id; - if(mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(db, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; } res = mysql_use_result(db); - if(res) + if (res) { - if((row = mysql_fetch_row(res)) != nullptr) + if ((row = mysql_fetch_row(res)) != nullptr) { account = row[0]; password = row[1]; @@ -174,7 +174,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address) { - if(!db) + if (!db) { return; } @@ -185,7 +185,7 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address) query << "', LastLoginDate = now() where LoginServerID = "; query << id; - if(mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(db, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); } @@ -193,7 +193,7 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address) void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string password, string email) { - if(!db) + if (!db) { return; } @@ -204,7 +204,7 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email; query << "', LastIPAddress = '0.0.0.0', LastLoginDate = now()"; - if(mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(db, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); } @@ -212,7 +212,7 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address) { - if(!db) + if (!db) { return; } @@ -220,7 +220,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s char escaped_long_name[101]; unsigned long length; length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length()); - escaped_long_name[length+1] = 0; + escaped_long_name[length + 1] = 0; stringstream query(stringstream::in | stringstream::out); query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '"; query << ip_address; @@ -229,7 +229,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s query << "' WHERE ServerID = "; query << id; - if(mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(db, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); } @@ -237,7 +237,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, unsigned int &id) { - if(!db) + if (!db) { return false; } @@ -248,22 +248,22 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, char escaped_short_name[101]; unsigned long length; length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length()); - escaped_long_name[length+1] = 0; + escaped_long_name[length + 1] = 0; length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); - escaped_short_name[length+1] = 0; + escaped_short_name[length + 1] = 0; stringstream query(stringstream::in | stringstream::out); query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable(); - if(mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(db, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; } res = mysql_use_result(db); - if(res) + if (res) { - if((row = mysql_fetch_row(res)) != nullptr) + if ((row = mysql_fetch_row(res)) != nullptr) { id = atoi(row[0]) + 1; mysql_free_result(res); @@ -273,7 +273,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name; query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''"; - if(mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(db, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; diff --git a/loginserver/login_server.h b/loginserver/login_server.h index f83154b8f..bae3079b7 100644 --- a/loginserver/login_server.h +++ b/loginserver/login_server.h @@ -40,7 +40,7 @@ public: * but it's the most trivial way to do this. */ #ifdef WIN32 - LoginServer() : config(nullptr), db(nullptr), eq_crypto(nullptr), SM(nullptr) { } + LoginServer() : config(nullptr), db(nullptr), eq_crypto(nullptr), server_manager(nullptr) { } #else LoginServer() : config(nullptr), db(nullptr) { } #endif @@ -48,8 +48,8 @@ public: Config *config; Database *db; Options options; - ServerManager *SM; - ClientManager *CM; + ServerManager *server_manager; + ClientManager *client_manager; #ifdef WIN32 Encryption *eq_crypto; diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 0d51a69ff..a6e4cdf82 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -44,7 +44,7 @@ int main() RegisterExecutablePlatform(ExePlatformLogin); set_exception_handler(); - //Create our error log, is of format login_.log + /* Start Loginserver log */ time_t current_time = time(nullptr); std::stringstream log_name(std::stringstream::in | std::stringstream::out); #ifdef WIN32 @@ -55,92 +55,55 @@ int main() server_log = new ErrorLog(log_name.str().c_str()); server_log->Log(log_debug, "Logging System Init."); - //Create our subsystem and parse the ini file. + /* Parse out login.ini */ server.config = new Config(); server_log->Log(log_debug, "Config System Init."); server.config->Parse("login.ini"); - //Parse unregistered allowed option. - if(server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0) - { + if (server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0) server.options.AllowUnregistered(false); - } - //Parse trace option. - if(server.config->GetVariable("options", "trace").compare("TRUE") == 0) - { + if (server.config->GetVariable("options", "trace").compare("TRUE") == 0) server.options.Trace(true); - } - //Parse trace option. - if(server.config->GetVariable("options", "world_trace").compare("TRUE") == 0) - { + if (server.config->GetVariable("options", "world_trace").compare("TRUE") == 0) server.options.WorldTrace(true); - } - //Parse packet inc dump option. - if(server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0) - { + if (server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0) server.options.DumpInPackets(true); - } - //Parse packet out dump option. - if(server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0) - { + if (server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0) server.options.DumpOutPackets(true); - } - //Parse encryption mode option. std::string mode = server.config->GetVariable("security", "mode"); - if(mode.size() > 0) - { + if (mode.size() > 0) server.options.EncryptionMode(atoi(mode.c_str())); - } - //Parse local network option. - std::string ln = server.config->GetVariable("options", "local_network"); - if(ln.size() > 0) - { - server.options.LocalNetwork(ln); - } + std::string local_network = server.config->GetVariable("options", "local_network"); + if (local_network.size() > 0) + server.options.LocalNetwork(local_network); - //Parse reject duplicate servers option. - if(server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0) - { + if (server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0) server.options.RejectDuplicateServers(true); - } - //Parse account table option. - ln = server.config->GetVariable("schema", "account_table"); - if(ln.size() > 0) - { - server.options.AccountTable(ln); - } + local_network = server.config->GetVariable("schema", "account_table"); + if (local_network.size() > 0) + server.options.AccountTable(local_network); - //Parse world account table option. - ln = server.config->GetVariable("schema", "world_registration_table"); - if(ln.size() > 0) - { - server.options.WorldRegistrationTable(ln); - } + local_network = server.config->GetVariable("schema", "world_registration_table"); + if (local_network.size() > 0) + server.options.WorldRegistrationTable(local_network); - //Parse admin world account table option. - ln = server.config->GetVariable("schema", "world_admin_registration_table"); - if(ln.size() > 0) - { - server.options.WorldAdminRegistrationTable(ln); - } + local_network = server.config->GetVariable("schema", "world_admin_registration_table"); + if (local_network.size() > 0) + server.options.WorldAdminRegistrationTable(local_network); - //Parse world type table option. - ln = server.config->GetVariable("schema", "world_server_type_table"); - if(ln.size() > 0) - { - server.options.WorldServerTypeTable(ln); - } + local_network = server.config->GetVariable("schema", "world_server_type_table"); + if (local_network.size() > 0) + server.options.WorldServerTypeTable(local_network); //Create our DB from options. - if(server.config->GetVariable("database", "subsystem").compare("MySQL") == 0) - { + if (server.config->GetVariable("database", "subsystem").compare("MySQL") == 0) { #ifdef EQEMU_MYSQL_ENABLED server_log->Log(log_debug, "MySQL Database Init."); server.db = (Database*)new DatabaseMySQL( @@ -151,8 +114,7 @@ int main() server.config->GetVariable("database", "db")); #endif } - else if(server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0) - { + else if (server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0) { #ifdef EQEMU_POSTGRESQL_ENABLED server_log->Log(log_debug, "PostgreSQL Database Init."); server.db = (Database*)new DatabasePostgreSQL( @@ -164,9 +126,8 @@ int main() #endif } - //Make sure our database got created okay, otherwise cleanup and exit. - if(!server.db) - { + /* Make sure our database got created okay, otherwise cleanup and exit. */ + if (!server.db) { server_log->Log(log_error, "Database Initialization Failure."); server_log->Log(log_debug, "Config System Shutdown."); delete server.config; @@ -179,12 +140,10 @@ int main() //initialize our encryption. server_log->Log(log_debug, "Encryption Initialize."); server.eq_crypto = new Encryption(); - if(server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin"))) - { + if (server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin"))) { server_log->Log(log_debug, "Encryption Loaded Successfully."); } - else - { + else { //We can't run without encryption, cleanup and exit. server_log->Log(log_error, "Encryption Failed to Load."); server_log->Log(log_debug, "Database System Shutdown."); @@ -199,15 +158,16 @@ int main() //create our server manager. server_log->Log(log_debug, "Server Manager Initialize."); - server.SM = new ServerManager(); - if(!server.SM) - { + server.server_manager = new ServerManager(); + if (!server.server_manager) { //We can't run without a server manager, cleanup and exit. server_log->Log(log_error, "Server Manager Failed to Start."); + #ifdef WIN32 server_log->Log(log_debug, "Encryption System Shutdown."); delete server.eq_crypto; #endif + server_log->Log(log_debug, "Database System Shutdown."); delete server.db; server_log->Log(log_debug, "Config System Shutdown."); @@ -219,17 +179,18 @@ int main() //create our client manager. server_log->Log(log_debug, "Client Manager Initialize."); - server.CM = new ClientManager(); - if(!server.CM) - { + server.client_manager = new ClientManager(); + if (!server.client_manager) { //We can't run without a client manager, cleanup and exit. server_log->Log(log_error, "Client Manager Failed to Start."); server_log->Log(log_debug, "Server Manager Shutdown."); - delete server.SM; + delete server.server_manager; + #ifdef WIN32 server_log->Log(log_debug, "Encryption System Shutdown."); delete server.eq_crypto; #endif + server_log->Log(log_debug, "Database System Shutdown."); delete server.db; server_log->Log(log_debug, "Config System Shutdown."); @@ -248,23 +209,24 @@ int main() #endif server_log->Log(log_debug, "Server Started."); - while(run_server) - { + while (run_server) { Timer::SetCurrentTime(); - server.CM->Process(); - server.SM->Process(); + server.client_manager->Process(); + server.server_manager->Process(); Sleep(100); } server_log->Log(log_debug, "Server Shutdown."); server_log->Log(log_debug, "Client Manager Shutdown."); - delete server.CM; + delete server.client_manager; server_log->Log(log_debug, "Server Manager Shutdown."); - delete server.SM; + delete server.server_manager; + #ifdef WIN32 server_log->Log(log_debug, "Encryption System Shutdown."); delete server.eq_crypto; #endif + server_log->Log(log_debug, "Database System Shutdown."); delete server.db; server_log->Log(log_debug, "Config System Shutdown."); diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index c91f1b702..64f7de02c 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -28,19 +28,18 @@ WorldServer::WorldServer(EmuTCPConnection *c) connection = c; zones_booted = 0; players_online = 0; - status = 0; + server_status = 0; runtime_id = 0; server_list_id = 0; server_type = 0; - authorized = false; - trusted = false; - logged_in = false; + is_server_authorized = false; + is_server_trusted = false; + is_server_logged_in = false; } WorldServer::~WorldServer() { - if(connection) - { + if(connection) { connection->Free(); } } @@ -49,12 +48,12 @@ void WorldServer::Reset() { zones_booted = 0; players_online = 0; - status = 0; + server_status = 0; runtime_id; server_list_id = 0; server_type = 0; - authorized = false; - logged_in = false; + is_server_authorized = false; + is_server_logged_in = false; } bool WorldServer::Process() @@ -142,7 +141,7 @@ bool WorldServer::Process() UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)app->pBuffer; server_log->Log(log_client, "Trying to find client with user id of %u.", utwr->lsaccountid); - Client *c = server.CM->GetClient(utwr->lsaccountid); + Client *c = server.client_manager->GetClient(utwr->lsaccountid); if(c) { server_log->Log(log_client, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str()); @@ -210,7 +209,7 @@ bool WorldServer::Process() server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str()); ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)app->pBuffer; - if(trusted) + if(is_server_trusted) { server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount); string name; @@ -237,7 +236,7 @@ bool WorldServer::Process() void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { - if(logged_in) + if(is_server_logged_in) { server_log->Log(log_network_error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting."); return; @@ -344,11 +343,11 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } server_type = i->servertype; - logged_in = true; + is_server_logged_in = true; if(server.options.IsRejectingDuplicateServers()) { - if(server.SM->ServerExists(long_name, short_name, this)) + if(server.server_manager->ServerExists(long_name, short_name, this)) { server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name."); return; @@ -356,10 +355,10 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - if(server.SM->ServerExists(long_name, short_name, this)) + if(server.server_manager->ServerExists(long_name, short_name, this)) { server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name."); - server.SM->DestroyServerByName(long_name, short_name, this); + server.server_manager->DestroyServerByName(long_name, short_name, this); } } @@ -380,7 +379,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { server_log->Log(log_world, "Server %s(%s) successfully logged into account that had no user/password requirement.", long_name.c_str(), short_name.c_str()); - authorized = true; + is_server_authorized = true; SetRuntimeID(s_id); server_list_id = s_list_type; desc = s_desc; @@ -389,89 +388,90 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { server_log->Log(log_world, "Server %s(%s) successfully logged in.", long_name.c_str(), short_name.c_str()); - authorized = true; + is_server_authorized = true; SetRuntimeID(s_id); server_list_id = s_list_type; desc = s_desc; - if(s_trusted) - { + if(s_trusted) { server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world"); - trusted = true; + is_server_trusted = true; ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0); connection->SendPacket(outapp); } } - else - { + else { server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only" " registered servers are allowed.", long_name.c_str(), short_name.c_str()); return; } } - else - { + else { server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.", long_name.c_str(), short_name.c_str()); return; } } - else - { + else { server_log->Log(log_world, "Server %s(%s) did not attempt to log in but only registered servers are allowed.", long_name.c_str(), short_name.c_str()); return; } } - else - { - unsigned int s_id = 0; - unsigned int s_list_type = 0; - unsigned int s_trusted = 0; - string s_desc; - string s_list_desc; - string s_acct_name; - string s_acct_pass; - if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass)) + else { + unsigned int server_id = 0; + unsigned int server_list_type = 0; + unsigned int is_server_trusted = 0; + string server_description; + string server_list_description; + string server_account_name; + string server_account_password; + + + if(server.db->GetWorldRegistration( + long_name, + short_name, + server_id, + server_description, + server_list_type, + is_server_trusted, + server_list_description, + server_account_name, + server_account_password)) { - if(account_name.size() > 0 && account_password.size() > 0) - { - if(s_acct_name.compare(account_name) == 0 && s_acct_pass.compare(account_password) == 0) - { + + if(account_name.size() > 0 && account_password.size() > 0) { + if(server_account_name.compare(account_name) == 0 && server_account_password.compare(account_password) == 0) { server_log->Log(log_world, "Server %s(%s) successfully logged in.", long_name.c_str(), short_name.c_str()); - authorized = true; - SetRuntimeID(s_id); - server_list_id = s_list_type; - desc = s_desc; - if(s_trusted) - { + is_server_authorized = true; + SetRuntimeID(server_id); + server_list_id = server_list_type; + desc = server_description; + + if(is_server_trusted) { server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world"); - trusted = true; + is_server_trusted = true; ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0); connection->SendPacket(outapp); } } - else - { + else { // this is the first of two cases where we should deny access even if unregistered is allowed server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.", long_name.c_str(), short_name.c_str()); } } - else - { - if(s_acct_name.size() > 0 || s_acct_pass.size() > 0) - { + else { + if(server_account_name.size() > 0 || server_account_password.size() > 0) { // this is the second of two cases where we should deny access even if unregistered is allowed server_log->Log(log_world, "Server %s(%s) did not attempt to log in but this server requires a password.", long_name.c_str(), short_name.c_str()); } - else - { + else { server_log->Log(log_world, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.", long_name.c_str(), short_name.c_str()); - authorized = true; - SetRuntimeID(s_id); + is_server_authorized = true; + SetRuntimeID(server_id); server_list_id = 3; } } @@ -480,10 +480,9 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.", long_name.c_str(), short_name.c_str()); - if(server.db->CreateWorldRegistration(long_name, short_name, s_id)) - { - authorized = true; - SetRuntimeID(s_id); + if(server.db->CreateWorldRegistration(long_name, short_name, server_id)) { + is_server_authorized = true; + SetRuntimeID(server_id); server_list_id = 3; } } @@ -493,9 +492,9 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) in.s_addr = connection->GetrIP(); server.db->UpdateWorldRegistration(GetRuntimeID(), long_name, string(inet_ntoa(in))); - if(authorized) + if(is_server_authorized) { - server.CM->UpdateServerList(); + server.client_manager->UpdateServerList(); } } @@ -503,43 +502,40 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s) { players_online = s->num_players; zones_booted = s->num_zones; - status = s->status; + server_status = s->status; } void WorldServer::SendClientAuth(unsigned int ip, string account, string key, unsigned int account_id) { - ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ServerLSClientAuth)); - ServerLSClientAuth* slsca = (ServerLSClientAuth*)outapp->pBuffer; + ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ClientAuth_Struct)); + ClientAuth_Struct* client_auth = (ClientAuth_Struct*)outapp->pBuffer; - slsca->lsaccount_id = account_id; - strncpy(slsca->name, account.c_str(), account.size() > 30 ? 30 : account.size()); - strncpy(slsca->key, key.c_str(), 10); - slsca->lsadmin = 0; - slsca->worldadmin = 0; - slsca->ip = ip; + client_auth->lsaccount_id = account_id; + strncpy(client_auth->name, account.c_str(), account.size() > 30 ? 30 : account.size()); + strncpy(client_auth->key, key.c_str(), 10); + client_auth->lsadmin = 0; + client_auth->worldadmin = 0; + client_auth->ip = ip; in_addr in; - in.s_addr = ip;connection->GetrIP(); + in.s_addr = ip; connection->GetrIP(); string client_address(inet_ntoa(in)); in.s_addr = connection->GetrIP(); string world_address(inet_ntoa(in)); - if(client_address.compare(world_address) == 0) - { - slsca->local = 1; + if (client_address.compare(world_address) == 0) { + client_auth->local = 1; } - else if(client_address.find(server.options.GetLocalNetwork()) != string::npos) - { - slsca->local = 1; + else if (client_address.find(server.options.GetLocalNetwork()) != string::npos) { + client_auth->local = 1; } - else - { - slsca->local = 0; + else { + client_auth->local = 0; } connection->SendPacket(outapp); - if(server.options.IsDumpInPacketsOn()) + if (server.options.IsDumpInPacketsOn()) { DumpPacket(outapp); } diff --git a/loginserver/world_server.h b/loginserver/world_server.h index 0d8ed4251..b9a64ffe5 100644 --- a/loginserver/world_server.h +++ b/loginserver/world_server.h @@ -86,7 +86,7 @@ public: /** * Gets whether the server is authorized to show up on the server list or not. */ - bool IsAuthorized() const { return authorized; } + bool IsAuthorized() const { return is_server_authorized; } /** * Gets the local ip of the server. @@ -106,7 +106,7 @@ public: /** * Gets the status of the server. */ - int GetStatus() const { return status; } + int GetStatus() const { return server_status; } /** * Gets the number of zones online on the server. @@ -138,7 +138,7 @@ private: EmuTCPConnection *connection; unsigned int zones_booted; unsigned int players_online; - int status; + int server_status; unsigned int runtime_id; unsigned int server_list_id; unsigned int server_type; @@ -151,9 +151,9 @@ private: std::string local_ip; std::string protocol; std::string version; - bool authorized; - bool logged_in; - bool trusted; + bool is_server_authorized; + bool is_server_logged_in; + bool is_server_trusted; }; #endif diff --git a/world/login_server.cpp b/world/login_server.cpp index 450ecb0a3..a6b46a6ea 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -145,7 +145,7 @@ bool LoginServer::Process() { break; } case ServerOP_LSClientAuth: { - ServerLSClientAuth* slsca = (ServerLSClientAuth*) pack->pBuffer; + ClientAuth_Struct* slsca = (ClientAuth_Struct*) pack->pBuffer; if (RuleI(World, AccountSessionLimit) >= 0) { // Enforce the limit on the number of characters on the same account that can be From a936796b45cc81ba689c48fc9d558b40b3bcafd2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 2 Dec 2015 13:46:16 -0600 Subject: [PATCH 419/846] Some more loginserver refactoring to make things more sane to read --- loginserver/database_mysql.cpp | 60 ++++----- loginserver/database_mysql.h | 6 +- loginserver/error_log.cpp | 55 ++++----- loginserver/main.cpp | 2 +- loginserver/server_manager.cpp | 220 +++++++++++++-------------------- 5 files changed, 150 insertions(+), 193 deletions(-) diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index 0f309d7b4..292cf753e 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -33,15 +33,15 @@ DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, this->host = host; this->name = name; - db = mysql_init(nullptr); - if(db) + database = mysql_init(nullptr); + if(database) { my_bool r = 1; - mysql_options(db, MYSQL_OPT_RECONNECT, &r); - if(!mysql_real_connect(db, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0)) + mysql_options(database, MYSQL_OPT_RECONNECT, &r); + if(!mysql_real_connect(database, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0)) { - mysql_close(db); - server_log->Log(log_database, "Failed to connect to MySQL database. Error: %s", mysql_error(db)); + mysql_close(database); + server_log->Log(log_database, "Failed to connect to MySQL database. Error: %s", mysql_error(database)); exit(1); } } @@ -53,15 +53,15 @@ DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, DatabaseMySQL::~DatabaseMySQL() { - if(db) + if(database) { - mysql_close(db); + mysql_close(database); } } bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id) { - if (!db) + if (!database) { return false; } @@ -73,13 +73,13 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u query << name; query << "'"; - if (mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(database, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; } - res = mysql_use_result(db); + res = mysql_use_result(database); if (res) { @@ -99,7 +99,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id, unsigned int &trusted, string &list_desc, string &account, string &password) { - if (!db) + if (!database) { return false; } @@ -108,7 +108,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un MYSQL_ROW row; char escaped_short_name[101]; unsigned long length; - length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); + length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); escaped_short_name[length + 1] = 0; stringstream query(stringstream::in | stringstream::out); query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, "; @@ -118,13 +118,13 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un query << escaped_short_name; query << "'"; - if (mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(database, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; } - res = mysql_use_result(db); + res = mysql_use_result(database); if (res) { if ((row = mysql_fetch_row(res)) != nullptr) @@ -143,13 +143,13 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable(); query << " WHERE ServerAdminID = " << db_account_id; - if (mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(database, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; } - res = mysql_use_result(db); + res = mysql_use_result(database); if (res) { if ((row = mysql_fetch_row(res)) != nullptr) @@ -174,7 +174,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address) { - if (!db) + if (!database) { return; } @@ -185,7 +185,7 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address) query << "', LastLoginDate = now() where LoginServerID = "; query << id; - if (mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(database, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); } @@ -193,7 +193,7 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address) void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string password, string email) { - if (!db) + if (!database) { return; } @@ -204,7 +204,7 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email; query << "', LastIPAddress = '0.0.0.0', LastLoginDate = now()"; - if (mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(database, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); } @@ -212,14 +212,14 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address) { - if (!db) + if (!database) { return; } char escaped_long_name[101]; unsigned long length; - length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length()); + length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length()); escaped_long_name[length + 1] = 0; stringstream query(stringstream::in | stringstream::out); query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '"; @@ -229,7 +229,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s query << "' WHERE ServerID = "; query << id; - if (mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(database, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); } @@ -237,7 +237,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, unsigned int &id) { - if (!db) + if (!database) { return false; } @@ -247,20 +247,20 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, char escaped_long_name[201]; char escaped_short_name[101]; unsigned long length; - length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length()); + length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length()); escaped_long_name[length + 1] = 0; - length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); + length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); escaped_short_name[length + 1] = 0; stringstream query(stringstream::in | stringstream::out); query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable(); - if (mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(database, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; } - res = mysql_use_result(db); + res = mysql_use_result(database); if (res) { if ((row = mysql_fetch_row(res)) != nullptr) @@ -273,7 +273,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name; query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''"; - if (mysql_query(db, query.str().c_str()) != 0) + if (mysql_query(database, query.str().c_str()) != 0) { server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); return false; diff --git a/loginserver/database_mysql.h b/loginserver/database_mysql.h index 4249cb614..165d787c7 100644 --- a/loginserver/database_mysql.h +++ b/loginserver/database_mysql.h @@ -35,7 +35,7 @@ public: /** * Constructor, sets our database to null. */ - DatabaseMySQL() { db = nullptr; } + DatabaseMySQL() { database = nullptr; } /** * Constructor, tries to set our database to connect to the supplied options. @@ -50,7 +50,7 @@ public: /** * @return Returns true if the database successfully connected. */ - virtual bool IsConnected() { return (db != nullptr); } + virtual bool IsConnected() { return (database != nullptr); } /** * Retrieves the login data (password hash and account id) from the account name provided @@ -88,7 +88,7 @@ public: virtual bool CreateWorldRegistration(std::string long_name, std::string short_name, unsigned int &id); protected: std::string user, pass, host, port, name; - MYSQL *db; + MYSQL *database; }; #endif diff --git a/loginserver/error_log.cpp b/loginserver/error_log.cpp index 03021f6c7..950a5d0d8 100644 --- a/loginserver/error_log.cpp +++ b/loginserver/error_log.cpp @@ -41,7 +41,7 @@ ErrorLog::ErrorLog(const char* file_name) ErrorLog::~ErrorLog() { log_mutex->lock(); - if(error_log) + if (error_log) { fclose(error_log); } @@ -51,7 +51,7 @@ ErrorLog::~ErrorLog() void ErrorLog::Log(eqLogType type, const char *message, ...) { - if(type >= _log_largest_type) + if (type >= _log_largest_type) { return; } @@ -70,21 +70,21 @@ void ErrorLog::Log(eqLogType type, const char *message, ...) log_mutex->lock(); printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n", eqLogTypes[type], - m_time->tm_mon+1, + m_time->tm_mon + 1, m_time->tm_mday, - m_time->tm_year%100, + m_time->tm_year % 100, m_time->tm_hour, m_time->tm_min, m_time->tm_sec, buffer); - if(error_log) + if (error_log) { fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n", eqLogTypes[type], - m_time->tm_mon+1, + m_time->tm_mon + 1, m_time->tm_mday, - m_time->tm_year%100, + m_time->tm_year % 100, m_time->tm_hour, m_time->tm_min, m_time->tm_sec, @@ -98,7 +98,7 @@ void ErrorLog::Log(eqLogType type, const char *message, ...) void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size) { - if(type >= _log_largest_type) + if (type >= _log_largest_type) { return; } @@ -112,21 +112,21 @@ void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size) log_mutex->lock(); printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u:\n", eqLogTypes[type], - m_time->tm_mon+1, + m_time->tm_mon + 1, m_time->tm_mday, - m_time->tm_year%100, + m_time->tm_year % 100, m_time->tm_hour, m_time->tm_min, m_time->tm_sec, (unsigned int)size); - if(error_log) + if (error_log) { fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u\n", eqLogTypes[type], - m_time->tm_mon+1, + m_time->tm_mon + 1, m_time->tm_mday, - m_time->tm_year%100, + m_time->tm_year % 100, m_time->tm_hour, m_time->tm_min, m_time->tm_sec, @@ -138,14 +138,14 @@ void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size) size_t j = 0; size_t i = 0; - for(; i < size; ++i) + for (; i < size; ++i) { - if(i % 16 == 0) + if (i % 16 == 0) { - if(i != 0) + if (i != 0) { printf(" | %s\n", ascii); - if(error_log) + if (error_log) { fprintf(error_log, " | %s\n", ascii); } @@ -154,22 +154,22 @@ void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size) memset(ascii, 0, 17); j = 0; } - else if(i % 8 == 0) + else if (i % 8 == 0) { printf("- "); - if(error_log) + if (error_log) { fprintf(error_log, "- "); } } printf("%02X ", (unsigned int)data[i]); - if(error_log) + if (error_log) { fprintf(error_log, "%02X ", (unsigned int)data[i]); } - if(data[i] >= 32 && data[i] < 127) + if (data[i] >= 32 && data[i] < 127) { ascii[j++] = data[i]; } @@ -180,31 +180,30 @@ void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size) } size_t k = (i - 1) % 16; - if(k < 8) + if (k < 8) { printf(" "); - if(error_log) + if (error_log) { fprintf(error_log, " "); } } - for(size_t h = k + 1; h < 16; ++h) + for (size_t h = k + 1; h < 16; ++h) { printf(" "); - if(error_log) + if (error_log) { fprintf(error_log, " "); } } printf(" | %s\n", ascii); - if(error_log) + if (error_log) { fprintf(error_log, " | %s\n", ascii); fflush(error_log); } log_mutex->unlock(); -} - +} \ No newline at end of file diff --git a/loginserver/main.cpp b/loginserver/main.cpp index a6e4cdf82..62973cd16 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -102,7 +102,7 @@ int main() if (local_network.size() > 0) server.options.WorldServerTypeTable(local_network); - //Create our DB from options. + /* Create database connection */ if (server.config->GetVariable("database", "subsystem").compare("MySQL") == 0) { #ifdef EQEMU_MYSQL_ENABLED server_log->Log(log_debug, "MySQL Database Init."); diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index 6a1b57d6f..3da497523 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -31,12 +31,10 @@ ServerManager::ServerManager() int listen_port = atoi(server.config->GetVariable("options", "listen_port").c_str()); tcps = new EmuTCPServer(listen_port, true); - if(tcps->Open(listen_port, error_buffer)) - { + if(tcps->Open(listen_port, error_buffer)) { server_log->Log(log_network, "ServerManager listening on port %u", listen_port); } - else - { + else { server_log->Log(log_error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer); run_server = false; } @@ -44,8 +42,7 @@ ServerManager::ServerManager() ServerManager::~ServerManager() { - if(tcps) - { + if (tcps) { tcps->Close(); delete tcps; } @@ -55,38 +52,32 @@ void ServerManager::Process() { ProcessDisconnect(); EmuTCPConnection *tcp_c = nullptr; - while(tcp_c = tcps->NewQueuePop()) - { + while (tcp_c = tcps->NewQueuePop()) { in_addr tmp; tmp.s_addr = tcp_c->GetrIP(); server_log->Log(log_network, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort()); - WorldServer *cur = GetServerByAddress(tcp_c->GetrIP()); - if(cur) - { + WorldServer *server_entity = GetServerByAddress(tcp_c->GetrIP()); + if (server_entity) { server_log->Log(log_network, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp)); - cur->GetConnection()->Free(); - cur->SetConnection(tcp_c); - cur->Reset(); + server_entity->GetConnection()->Free(); + server_entity->SetConnection(tcp_c); + server_entity->Reset(); } - else - { + else { WorldServer *w = new WorldServer(tcp_c); world_servers.push_back(w); } } list::iterator iter = world_servers.begin(); - while(iter != world_servers.end()) - { - if((*iter)->Process() == false) - { + while (iter != world_servers.end()) { + if ((*iter)->Process() == false) { server_log->Log(log_world, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str()); delete (*iter); iter = world_servers.erase(iter); } - else - { + else { ++iter; } } @@ -95,20 +86,17 @@ void ServerManager::Process() void ServerManager::ProcessDisconnect() { list::iterator iter = world_servers.begin(); - while(iter != world_servers.end()) - { - EmuTCPConnection *c = (*iter)->GetConnection(); - if(!c->Connected()) - { + while (iter != world_servers.end()) { + EmuTCPConnection *connection = (*iter)->GetConnection(); + if (!connection->Connected()) { in_addr tmp; - tmp.s_addr = c->GetrIP(); + tmp.s_addr = connection->GetrIP(); server_log->Log(log_network, "World server disconnected from the server, removing server and freeing connection."); - c->Free(); + connection->Free(); delete (*iter); iter = world_servers.erase(iter); } - else - { + else { ++iter; } } @@ -117,10 +105,8 @@ void ServerManager::ProcessDisconnect() WorldServer* ServerManager::GetServerByAddress(unsigned int address) { list::iterator iter = world_servers.begin(); - while(iter != world_servers.end()) - { - if((*iter)->GetConnection()->GetrIP() == address) - { + while (iter != world_servers.end()) { + if ((*iter)->GetConnection()->GetrIP() == address) { return (*iter); } ++iter; @@ -138,10 +124,8 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c) string client_ip = inet_ntoa(in); list::iterator iter = world_servers.begin(); - while(iter != world_servers.end()) - { - if((*iter)->IsAuthorized() == false) - { + while (iter != world_servers.end()) { + if ((*iter)->IsAuthorized() == false) { ++iter; continue; } @@ -149,16 +133,13 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c) in.s_addr = (*iter)->GetConnection()->GetrIP(); string world_ip = inet_ntoa(in); - if(world_ip.compare(client_ip) == 0) - { + if (world_ip.compare(client_ip) == 0) { packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24; } - else if(client_ip.find(server.options.GetLocalNetwork()) != string::npos) - { + else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) { packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24; } - else - { + else { packet_size += (*iter)->GetLongName().size() + (*iter)->GetRemoteIP().size() + 24; } @@ -167,98 +148,87 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c) } EQApplicationPacket *outapp = new EQApplicationPacket(OP_ServerListResponse, packet_size); - ServerListHeader_Struct *sl = (ServerListHeader_Struct*)outapp->pBuffer; - sl->Unknown1 = 0x00000004; - sl->Unknown2 = 0x00000000; - sl->Unknown3 = 0x01650000; - /** - * Not sure what this is but it should be noted setting it to - * 0xFFFFFFFF crashes the client so: don't do that. - */ - sl->Unknown4 = 0x00000000; - sl->NumberOfServers = server_count; + ServerListHeader_Struct *server_list = (ServerListHeader_Struct*)outapp->pBuffer; + server_list->Unknown1 = 0x00000004; + server_list->Unknown2 = 0x00000000; + server_list->Unknown3 = 0x01650000; - unsigned char *data_ptr = outapp->pBuffer; - data_ptr += sizeof(ServerListHeader_Struct); + /** + * Not sure what this is but it should be noted setting it to + * 0xFFFFFFFF crashes the client so: don't do that. + */ + server_list->Unknown4 = 0x00000000; + server_list->NumberOfServers = server_count; + + unsigned char *data_pointer = outapp->pBuffer; + data_pointer += sizeof(ServerListHeader_Struct); iter = world_servers.begin(); - while(iter != world_servers.end()) - { - if((*iter)->IsAuthorized() == false) - { + while (iter != world_servers.end()) { + if ((*iter)->IsAuthorized() == false) { ++iter; continue; } in.s_addr = (*iter)->GetConnection()->GetrIP(); string world_ip = inet_ntoa(in); - if(world_ip.compare(client_ip) == 0) - { - memcpy(data_ptr, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); - data_ptr += ((*iter)->GetLocalIP().size() + 1); + if (world_ip.compare(client_ip) == 0) { + memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); + data_pointer += ((*iter)->GetLocalIP().size() + 1); } - else if(client_ip.find(server.options.GetLocalNetwork()) != string::npos) - { - memcpy(data_ptr, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); - data_ptr += ((*iter)->GetLocalIP().size() + 1); + else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) { + memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); + data_pointer += ((*iter)->GetLocalIP().size() + 1); } - else - { - memcpy(data_ptr, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size()); - data_ptr += ((*iter)->GetRemoteIP().size() + 1); + else { + memcpy(data_pointer, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size()); + data_pointer += ((*iter)->GetRemoteIP().size() + 1); } - switch((*iter)->GetServerListID()) - { - case 1: - { - *(unsigned int*)data_ptr = 0x00000030; + switch ((*iter)->GetServerListID()) { + case 1: { + *(unsigned int*)data_pointer = 0x00000030; break; } - case 2: - { - *(unsigned int*)data_ptr = 0x00000009; + case 2: { + *(unsigned int*)data_pointer = 0x00000009; break; } - default: - { - *(unsigned int*)data_ptr = 0x00000001; + default: { + *(unsigned int*)data_pointer = 0x00000001; } } - data_ptr += 4; - *(unsigned int*)data_ptr = (*iter)->GetRuntimeID(); - data_ptr += 4; + data_pointer += 4; - memcpy(data_ptr, (*iter)->GetLongName().c_str(), (*iter)->GetLongName().size()); - data_ptr += ((*iter)->GetLongName().size() + 1); + *(unsigned int*)data_pointer = (*iter)->GetRuntimeID(); + data_pointer += 4; - memcpy(data_ptr, "EN", 2); - data_ptr += 3; + memcpy(data_pointer, (*iter)->GetLongName().c_str(), (*iter)->GetLongName().size()); + data_pointer += ((*iter)->GetLongName().size() + 1); - memcpy(data_ptr, "US", 2); - data_ptr += 3; + memcpy(data_pointer, "EN", 2); + data_pointer += 3; + + memcpy(data_pointer, "US", 2); + data_pointer += 3; // 0 = Up, 1 = Down, 2 = Up, 3 = down, 4 = locked, 5 = locked(down) - if((*iter)->GetStatus() < 0) - { - if((*iter)->GetZonesBooted() == 0) - { - *(uint32*)data_ptr = 0x01; + if ((*iter)->GetStatus() < 0) { + if ((*iter)->GetZonesBooted() == 0) { + *(uint32*)data_pointer = 0x01; } - else - { - *(uint32*)data_ptr = 0x04; + else { + *(uint32*)data_pointer = 0x04; } } - else - { - *(uint32*)data_ptr = 0x02; + else { + *(uint32*)data_pointer = 0x02; } - data_ptr += 4; + data_pointer += 4; - *(uint32*)data_ptr = (*iter)->GetPlayersOnline(); - data_ptr += 4; + *(uint32*)data_pointer = (*iter)->GetPlayersOnline(); + data_pointer += 4; ++iter; } @@ -270,10 +240,8 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int { list::iterator iter = world_servers.begin(); bool found = false; - while(iter != world_servers.end()) - { - if((*iter)->GetRuntimeID() == server_id) - { + while (iter != world_servers.end()) { + if ((*iter)->GetRuntimeID() == server_id) { ServerPacket *outapp = new ServerPacket(ServerOP_UsertoWorldReq, sizeof(UsertoWorldRequest_Struct)); UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct*)outapp->pBuffer; utwr->worldid = server_id; @@ -281,8 +249,7 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int (*iter)->GetConnection()->SendPacket(outapp); found = true; - if(server.options.IsDumpInPacketsOn()) - { + if (server.options.IsDumpInPacketsOn()) { DumpPacket(outapp); } delete outapp; @@ -290,8 +257,7 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int ++iter; } - if(!found && server.options.IsTraceOn()) - { + if (!found && server.options.IsTraceOn()) { server_log->Log(log_client_error, "Client requested a user to world but supplied an invalid id of %u.", server_id); } } @@ -299,16 +265,13 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *ignore) { list::iterator iter = world_servers.begin(); - while(iter != world_servers.end()) - { - if((*iter) == ignore) - { + while (iter != world_servers.end()) { + if ((*iter) == ignore) { ++iter; continue; } - if((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) - { + if ((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) { return true; } @@ -320,18 +283,14 @@ bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *igno void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServer *ignore) { list::iterator iter = world_servers.begin(); - while(iter != world_servers.end()) - { - if((*iter) == ignore) - { + while (iter != world_servers.end()) { + if ((*iter) == ignore) { ++iter; } - if((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) - { + if ((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) { EmuTCPConnection *c = (*iter)->GetConnection(); - if(c->Connected()) - { + if (c->Connected()) { c->Disconnect(); } c->Free(); @@ -341,5 +300,4 @@ void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServe ++iter; } -} - +} \ No newline at end of file From f07e708f22d48af0a44b009a01d144b073bdf260 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 2 Dec 2015 15:41:57 -0600 Subject: [PATCH 420/846] Update eqemu_update.pl [skip ci] :: Add option 13) [Windows Server Loginserver Setup] :: Download and install Windows Loginserver --- utils/scripts/eqemu_update.pl | 104 +++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 4a3d993b2..4e2b476e0 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -126,7 +126,7 @@ if($ARGV[0] eq "installer"){ 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 "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(); @@ -142,6 +142,12 @@ if($ARGV[0] eq "installer"){ 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'); @@ -230,6 +236,7 @@ sub show_menu_prompt { 10 => \&aa_fetch, 11 => \&fetch_latest_windows_binaries, 12 => \&fetch_server_dlls, + 13 => \&do_windows_login_server_setup, 20 => \&do_update_self, 0 => \&script_exit, ); @@ -305,6 +312,7 @@ return <; #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); @@ -567,7 +667,7 @@ sub check_windows_firewall_rules{ 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 `; + 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"; From 1c0192dce3a384765271a513153e0d06f6c92165 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 2 Dec 2015 18:33:49 -0500 Subject: [PATCH 421/846] Fix for guild rank sql error when using bots (thanks N0ctrnl!) --- common/guild_base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 58e7675c5..aa4f7c509 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -969,7 +969,7 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) { //load up the rank info for each guild. std::string query; #ifdef BOTS - query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mobtype = 'C'", char_id); + query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C'", char_id); #else query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d", char_id); #endif From 6f1ad1fbc19528c9c51fe543f2dfbdc528600d07 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 7 Dec 2015 19:28:13 -0500 Subject: [PATCH 422/846] Major change to how commands are loaded --- changelog.txt | 15 + common/shareddb.cpp | 25 +- common/shareddb.h | 2 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2015_12_07_command_settings.sql | 11 + zone/command.cpp | 202 +++---- zone/command.h | 552 +++++++++--------- 8 files changed, 396 insertions(+), 414 deletions(-) create mode 100644 utils/sql/git/required/2015_12_07_command_settings.sql diff --git a/changelog.txt b/changelog.txt index 254b53845..5d2345521 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,20 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/07/2016 == +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` + - Adding command aliases require that the command contain an entry in `command_settings`.`command` + - Only 'real' commands go inside of the command_init() function in command.cpp .. if you wish to add aliases, you must enter them into the database + - 'Real' commands are loaded first .. then any access/alias data is loaded and applied afterwards + - Duplicate aliases will be ignored .. only the first encountered occurrence will be honored - if it does not conflict with an existing command name + - Aliases should not contain whitespace and should be '|' (pipe) delimited + - The restriction on the number of aliases has been removed .. though each alias will still be limited to the access level of the parent command + - 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 == Uleat: Changed criteria for a few bots scripts from count to null/not null in hopes of fixing special case failures diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 0c8fae730..59a2a118b 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1325,19 +1325,28 @@ int32 SharedDatabase::DeleteStalePlayerCorpses() { return results.RowsAffected(); } -bool SharedDatabase::GetCommandSettings(std::map &commands) { +bool SharedDatabase::GetCommandSettings(std::map>> &command_settings) +{ + command_settings.clear(); - const std::string query = "SELECT command, access FROM commands"; + std::string query = "SELECT `command`, `access`, `aliases` FROM `command_settings`"; auto results = QueryDatabase(query); - if (!results.Success()) { + if (!results.Success()) return false; + + for (auto row = results.begin(); row != results.end(); ++row) { + command_settings[row[0]].first = atoi(row[1]); + if (row[2][0] == 0) + continue; + + std::vector aliases = SplitString(row[2], '|'); + for (std::vector::iterator iter = aliases.begin(); iter != aliases.end(); ++iter) { + if (iter->empty()) + continue; + command_settings[row[0]].second.push_back(*iter); + } } - commands.clear(); - - for (auto row = results.begin(); row != results.end(); ++row) - commands[row[0]]=atoi(row[1]); - return true; } diff --git a/common/shareddb.h b/common/shareddb.h index 36239bc35..ebb2ae961 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -51,7 +51,7 @@ class SharedDatabase : public Database int32 DeleteStalePlayerCorpses(); void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message); void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message); - bool GetCommandSettings(std::map &commands); + bool GetCommandSettings(std::map>> &command_settings); uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID); /* diff --git a/common/version.h b/common/version.h index 1e1a9dc35..2e5af617c 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 9090 +#define CURRENT_BINARY_DATABASE_VERSION 9091 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 3a34e4b09..2f37dfe84 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -344,6 +344,7 @@ 9088|2015_11_01_perl_event_export_settings.sql|SHOW TABLES LIKE 'perl_event_export_settings'|empty| 9089|2015_11_02_ai_idle_no_spell_recast_default_changes.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Spells:AI_IdleNoSpellMinRecast%' AND `rule_value` = '500'|not_empty| 9090|2015_12_01_spell_scribe_restriction_rule.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Character:RestrictSpellScribing'|empty| +9091|2015_12_07_command_settings.sql|SHOW TABLES LIKE 'command_settings'|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/2015_12_07_command_settings.sql b/utils/sql/git/required/2015_12_07_command_settings.sql new file mode 100644 index 000000000..470525d4c --- /dev/null +++ b/utils/sql/git/required/2015_12_07_command_settings.sql @@ -0,0 +1,11 @@ +RENAME TABLE `commands` to `commands_old`; + +CREATE TABLE `command_settings` ( + `command` varchar(128) NOT NULL DEFAULT '', + `access` int(11) NOT NULL DEFAULT '0', + `aliases` varchar(256) NOT NULL DEFAULT '', + PRIMARY KEY (`command`), + UNIQUE KEY `UK_command_settings_1` (`command`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `command_settings` VALUES ('acceptrules', '90', ''),('advnpcspawn', '150', 'advnpc'),('aggro', '80', ''),('aggrozone', '200', ''),('ai', '100', ''),('appearance', '150', ''),('apply_shared_memory', '250', ''),('attack', '150', ''),('augmentitem', '250', 'aug'),('ban', '200', ''),('beard', '80', ''),('beardcolor', '80', ''),('bestz', '80', ''),('bind', '80', ''),('camerashake', '80', ''),('castspell', '90', 'cast'),('chat', '200', ''),('checklos', '50', 'los'),('clearinvsnapshots', '200', ''),('connectworldserver', '200', 'connectworld'),('corpse', '90', ''),('crashtest', '201', ''),('cvs', '80', ''),('damage', '150', ''),('date', '150', ''),('dbspawn2', '100', ''),('delacct', '200', ''),('deletegraveyard', '200', ''),('delpetition', '80', ''),('depop', '100', ''),('depopzone', '100', ''),('details', '80', ''),('disablerecipe', '80', ''),('disarmtrap', '80', ''),('distance', '80', ''),('doanim', '50', ''),('emote', '150', ''),('emotesearch', '80', ''),('emoteview', '80', ''),('enablerecipe', '80', ''),('equipitem', '50', ''),('face', '80', ''),('findnpctype', '90', 'fn'),('findspell', '90', 'fs|spfind'),('findzone', '1', 'fz'),('fixmob', '150', ''),('flag', '201', ''),('flagedit', '150', ''),('flags', '80', ''),('flymode', '80', ''),('fov', '80', ''),('freeze', '100', ''),('gassign', '150', ''),('gender', '90', ''),('getplayerburiedcorpsecount', '100', ''),('getvariable', '200', ''),('ginfo', '20', ''),('giveitem', '150', 'gi'),('givemoney', '150', ''),('globalview', '80', ''),('gm', '80', ''),('gmspeed', '80', ''),('goto', '80', ''),('grid', '150', ''),('guild', '80', 'guilds'),('guildapprove', '0', ''),('guildcreate', '0', ''),('guildlist', '0', ''),('hair', '80', ''),('haircolor', '80', ''),('haste', '100', ''),('hatelist', '80', ''),('heal', '100', ''),('helm', '80', ''),('help', '0', ''),('heritage', '80', ''),('heromodel', '200', 'hm'),('hideme', '80', 'gmhideme'),('hotfix', '250', ''),('hp', '90', ''),('incstat', '200', ''),('instance', '80', ''),('interrogateinv', '0', ''),('interrupt', '50', ''),('invsnapshot', '80', ''),('invul', '80', 'invulnerable'),('ipban', '201', ''),('iplookup', '200', ''),('iteminfo', '10', ''),('itemsearch', '90', 'fi|finditem|search'),('kick', '80', ''),('kill', '80', ''),('lastname', '80', ''),('level', '150', ''),('listnpcs', '90', ''),('listpetition', '80', ''),('load_shared_memory', '250', ''),('loc', '0', ''),('lock', '200', ''),('logs', '250', ''),('logtest', '250', ''),('makepet', '150', ''),('mana', '100', ''),('maxskills', '90', ''),('memspell', '100', ''),('merchant_close_shop', '100', 'close_shop'),('merchant_open_shop', '100', 'open_shop'),('modifynpcstat', '150', ''),('motd', '200', ''),('movechar', '80', ''),('myskills', '0', ''),('mysqltest', '250', ''),('mysql', '255', ''),('mystats', '50', ''),('name', '100', ''),('netstats', '200', ''),('npccast', '90', ''),('npcedit', '150', ''),('npcemote', '80', ''),('npcloot', '150', ''),('npcsay', '80', ''),('npcshout', '90', ''),('npcspawn', '100', ''),('npcspecialattk', '150', 'npcspecialatk|npcspecialattack'),('npcstats', '90', ''),('npctype_cache', '250', ''),('npctypespawn', '90', 'dbspawn'),('nukebuffs', '100', ''),('nukeitem', '150', ''),('object', '100', ''),('oocmute', '200', ''),('opcode', '250', ''),('path', '200', ''),('peekinv', '80', ''),('peqzone', '2', ''),('permaclass', '150', ''),('permagender', '150', ''),('permarace', '150', ''),('petitioninfo', '20', ''),('pf', '0', ''),('picklock', '0', ''),('pvp', '80', ''),('qglobal', '150', ''),('questerrors', '0', ''),('race', '90', ''),('raidloot', '0', ''),('randomfeatures', '90', ''),('refreshgroup', '0', ''),('reloadaa', '200', ''),('reloadallrules', '80', ''),('reloademote', '80', ''),('reloadlevelmods', '255', ''),('reloadperlexportsettings', '255', ''),('reloadqst', '80', 'reloadquest|rq'),('reloadrulesworld', '80', ''),('reloadstatic', '150', ''),('reloadtitles', '150', ''),('reloadworld', '255', ''),('reloadzps', '150', 'reloadzonepoints'),('repop', '90', ''),('repopclose', '100', ''),('resetaa', '100', ''),('resetaa_timer', '200', ''),('revoke', '80', ''),('rules', '200', ''),('save', '80', ''),('scribespell', '90', ''),('scribespells', '100', ''),('sendzonespawns', '200', ''),('sensetrap', '0', ''),('serverinfo', '201', ''),('serverrules', '90', ''),('setaapts', '100', 'setaapoints'),('setaaxp', '100', 'setaaexp'),('setadventurepoints', '200', ''),('setanim', '200', ''),('setcrystals', '100', ''),('setfaction', '170', ''),('setgraveyard', '200', ''),('setlanguage', '50', ''),('setlsinfo', '0', ''),('setpass', '150', ''),('setpvppoints', '100', ''),('setskill', '90', ''),('setskillall', '100', 'setallskill|setallskills'),('setstartzone', '80', ''),('setstat', '255', ''),('setxp', '100', 'setexp'),('showbonusstats', '50', ''),('showbuffs', '80', ''),('shownumhits', '0', ''),('showskills', '50', ''),('showspellslist', '100', ''),('showstats', '80', ''),('shutdown', '200', ''),('size', '90', ''),('spawn', '150', ''),('spawnfix', '80', ''),('spawnstatus', '150', ''),('spellinfo', '10', ''),('spoff', '0', ''),('spon', '0', ''),('stun', '100', ''),('summon', '80', ''),('summonburiedplayercorpse', '100', ''),('summonitem', '150', 'si'),('suspend', '100', ''),('task', '150', ''),('tattoo', '80', ''),('tempname', '100', ''),('texture', '150', ''),('time', '90', ''),('timers', '200', ''),('timezone', '90', ''),('title', '100', ''),('titlesuffix', '50', ''),('traindisc', '100', ''),('tune', '100', ''),('undyeme', '0', ''),('unfreeze', '100', ''),('unlock', '150', ''),('unscribespell', '90', ''),('unscribespells', '100', ''),('untraindisc', '180', ''),('untraindiscs', '180', ''),('uptime', '10', ''),('version', '0', ''),('viewnpctype', '100', ''),('viewpetition', '80', ''),('wc', '200', ''),('weather', '90', ''),('worldshutdown', '200', ''),('wp', '150', ''),('wpadd', '150', ''),('wpinfo', '150', ''),('xtargets', '250', ''),('zclip', '150', ''),('zcolor', '150', ''),('zheader', '150', ''),('zone', '80', ''),('zonebootup', '100', ''),('zoneinstance', '80', ''),('zonelock', '200', ''),('zoneshutdown', '200', ''),('zonespawn', '250', ''),('zonestatus', '150', ''),('zopp', '250', ''),('zsafecoords', '150', ''),('zsave', '200', ''), ('zsky', '150', ''),('zstats', '80', ''),('zunderworld', '80', ''),('zuwcoords', '80', ''); diff --git a/zone/command.cpp b/zone/command.cpp index 1aaf159b0..f2f9ed5a9 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -73,9 +73,7 @@ extern TaskManager *taskmanager; void CatchSignal(int sig_num); - -//struct cl_struct *commandlist; // the actual linked list of commands -int commandcount; // how many commands we have +int commandcount; // how many commands we have // this is the pointer to the dispatch function, updated once // init has been performed to point at the real function @@ -90,7 +88,6 @@ std::map commandlist; //All allocated CommandRecords get put in here so they get deleted on shutdown LinkedList cleanup_commandlist; - /* * command_notavail * This is the default dispatch function when commands aren't loaded. @@ -139,31 +136,15 @@ Access Levels: * Parameters: * none * - * When adding a command, if it's the first time that function pointer is - * used it is a new command. If that function pointer is used for another - * command, the command is added as an alias; description and access level - * are not used and can be nullptr. + * When adding a new command, only hard-code 'real' commands - + * all command aliases are added later through a database call * */ -int command_init(void) { - - if - ( - -#ifdef PACKET_PROFILER - command_add("packetprofile", "- Dump packet profile for target or self.", 250, command_packetprofile) || -#endif -#ifdef EQPROFILE - command_add("profiledump", "- Dump profiling info to logs", 250, command_profiledump) || - command_add("profilereset", "- Reset profiling info", 250, command_profilereset) || -#endif -#ifdef BOTS - command_add("bot", "- Type \"#bot help\" to the see the list of available commands for bots.", 0, command_bot) || -#endif - +int command_init(void) +{ + if ( command_add("acceptrules", "[acceptrules] - Accept the EQEmu Agreement", 0, command_acceptrules) || - command_add("advnpc", "analog for advnpcspawn [maketype|makegroup|addgroupentry|addgroupspawn][removegroupspawn|movespawn|editgroupbox|cleargroupbox]", 150, command_advnpcspawn) || command_add("advnpcspawn", "[maketype|makegroup|addgroupentry|addgroupspawn][removegroupspawn|movespawn|editgroupbox|cleargroupbox]", 150, command_advnpcspawn) || command_add("aggro", "(range) [-v] - Display aggro information for all mobs 'range' distance from your target. -v is verbose faction info.", 80, command_aggro) || command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", 100, command_aggrozone) || @@ -172,27 +153,27 @@ int command_init(void) { command_add("apply_shared_memory", "[shared_memory_name] - Tells every zone and world to apply a specific shared memory segment by name.", 250, command_apply_shared_memory) || command_add("attack", "[targetname] - Make your NPC target attack targetname", 150, command_attack) || command_add("augmentitem", "Force augments an item. Must have the augment item window open.", 250, command_augmentitem) || - command_add("aug", nullptr, 250, command_augmentitem) || command_add("ban", "[name] [reason]- Ban by character name", 150, command_ban) || command_add("beard", "- Change the beard of your target", 80, command_beard) || command_add("beardcolor", "- Change the beard color of your target", 80, command_beardcolor) || command_add("bestz", "- Ask map for a good Z coord for your x,y coords.", 0, command_bestz) || 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) || +#endif + command_add("camerashake", "Shakes the camera on everyone's screen globally.", 80, command_camerashake) || - command_add("cast", nullptr,0, command_castspell) || command_add("castspell", "[spellid] - Cast a spell", 50, command_castspell) || command_add("chat", "[channel num] [message] - Send a channel message to all zones", 200, command_chat) || command_add("checklos", "- Check for line of sight to your target", 50, command_checklos) || command_add("clearinvsnapshots", "[use rule] - Clear inventory snapshot history (true - elapsed entries, false - all entries)", 200, command_clearinvsnapshots) || - command_add("close_shop", nullptr, 100, command_merchantcloseshop) || - command_add("connectworld", nullptr,0, command_connectworldserver) || command_add("connectworldserver", "- Make zone attempt to connect to worldserver", 200, command_connectworldserver) || command_add("corpse", "- Manipulate corpses, use with no arguments for help", 50, command_corpse) || - command_add("crashtest", "- Crash the zoneserver", 255, command_crashtest) || - command_add("cvs", "- Summary of client versions currently online.", 200, command_cvs) || + command_add("crashtest", "- Crash the zoneserver", 255, command_crashtest) || + command_add("cvs", "- Summary of client versions currently online.", 200, command_cvs) || command_add("damage", "[amount] - Damage your target", 100, command_damage) || command_add("date", "[yyyy] [mm] [dd] [HH] [MM] - Set EQ time", 90, command_date) || - command_add("dbspawn", nullptr,10, command_npctypespawn) || command_add("dbspawn2", "[spawngroup] [respawn] [variance] - Spawn an NPC from a predefined row in the spawn2 table", 100, command_dbspawn2) || command_add("delacct", "[accountname] - Delete an account", 150, command_delacct) || command_add("deletegraveyard", "[zone name] - Deletes the graveyard for the specified zone.", 200, command_deletegraveyard) || @@ -210,8 +191,6 @@ int command_init(void) { command_add("enablerecipe", "[recipe_id] - Enables a recipe using the recipe id.", 80, command_enablerecipe) || command_add("equipitem", "[slotid(0-21)] - Equip the item on your cursor into the specified slot", 50, command_equipitem) || command_add("face", "- Change the face of your target", 80, command_face) || - command_add("fi", nullptr,10, command_itemsearch) || - command_add("finditem", nullptr,10, command_itemsearch) || command_add("findnpctype", "[search criteria] - Search database NPC types", 100, command_findnpctype) || command_add("findspell", "[searchstring] - Search for a spell", 50, command_findspell) || command_add("findzone", "[search criteria] - Search database zones", 100, command_findzone) || @@ -220,22 +199,17 @@ int command_init(void) { command_add("flagedit", "- Edit zone flags on your target", 100, command_flagedit) || command_add("flags", "- displays the flags of you or your target", 0, command_flags) || command_add("flymode", "[0/1/2] - Set your or your player target's flymode to off/on/levitate", 50, command_flymode) || - command_add("fn", nullptr, 100, command_findnpctype) || command_add("fov", "- Check wether you're behind or in your target's field of view", 80, command_fov) || command_add("freeze", "- Freeze your target", 80, command_freeze) || - command_add("fs", nullptr, 50, command_findspell) || - command_add("fz", nullptr, 100, command_findzone) || command_add("gassign", "[id] - Assign targetted NPC to predefined wandering grid id", 100, command_gassign) || command_add("gender", "[0/1/2] - Change your or your target's gender to male/female/neuter", 50, command_gender) || command_add("getplayerburiedcorpsecount", "- Get the target's total number of buried player corpses.", 100, command_getplayerburiedcorpsecount) || command_add("getvariable", "[varname] - Get the value of a variable from the database", 200, command_getvariable) || - command_add("gi", nullptr,200, command_giveitem) || command_add("ginfo", "- get group info on target.", 20, command_ginfo) || command_add("giveitem", "[itemid] [charges] - Summon an item onto your target's cursor. Charges are optional.", 200, command_giveitem) || command_add("givemoney", "[pp] [gp] [sp] [cp] - Gives specified amount of money to the target player.", 200, command_givemoney) || command_add("globalview", "Lists all qglobals in cache if you were to do a quest with this target.", 80, command_globalview) || command_add("gm", "- Turn player target's or your GM flag on or off", 80, command_gm) || - command_add("gmhideme", nullptr,0, command_hideme) || command_add("gmspeed", "[on/off] - Turn GM speed hack on/off for you or your player target", 100, command_gmspeed) || command_add("goto", "[x] [y] [z] - Teleport to the provided coordinates or to your target", 10, command_goto) || command_add("grid", "[add/delete] [grid_num] [wandertype] [pausetype] - Create/delete a wandering grid", 170, command_grid) || @@ -243,7 +217,6 @@ int command_init(void) { command_add("guildapprove", "[guildapproveid] - Approve a guild with specified ID (guild creator receives the id)", 0, command_guildapprove) || command_add("guildcreate", "[guildname] - Creates an approval setup for guild name specified", 0, command_guildcreate) || command_add("guildlist", "[guildapproveid] - Lists character names who have approved the guild specified by the approve id", 0, command_guildlist) || - command_add("guilds", nullptr,0, command_guild) || command_add("hair", "- Change the hair style of your target", 80, command_hair) || command_add("haircolor", "- Change the hair color of your target", 80, command_haircolor) || command_add("haste", "[percentage] - Set your haste percentage", 100, command_haste) || @@ -254,7 +227,6 @@ int command_init(void) { command_add("heritage", "- Change the heritage of your target (Drakkin Only)", 80, command_heritage) || command_add("heromodel", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.", 200, command_heromodel) || command_add("hideme", "[on/off] - Hide yourself from spawn lists.", 80, command_hideme) || - command_add("hm", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.)", 200, command_heromodel) || command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix, equiv to load_shared_memory followed by apply_shared_memory", 250, command_hotfix) || command_add("hp", "- Refresh your HP bar from the server.", 0, command_hp) || command_add("incstat", "- Increases or Decreases a client's stats permanently.", 200, command_incstat) || @@ -262,8 +234,7 @@ int command_init(void) { command_add("interrogateinv", "- use [help] argument for available options", 0, command_interrogateinv) || command_add("interrupt", "[message id] [color] - Interrupt your casting. Arguments are optional.", 50, command_interrupt) || command_add("invsnapshot", "- Takes an inventory snapshot of your current target", 80, command_invsnapshot) || - command_add("invul", nullptr,0, command_invul) || - command_add("invulnerable", "[on/off] - Turn player target's or your invulnerable flag on or off", 80, command_invul) || + command_add("invul", "[on/off] - Turn player target's or your invulnerable flag on or off", 80, command_invul) || command_add("ipban", "[IP address] - Ban IP by character name", 200, command_ipban) || command_add("iplookup", "[charname] - Look up IP address of charname", 200, command_iplookup) || command_add("iteminfo", "- Get information about the item on your cursor", 10, command_iteminfo) || @@ -279,10 +250,9 @@ int command_init(void) { command_add("lock", "- Lock the worldserver", 150, command_lock) || command_add("logs", "Manage anything to do with logs", 250, command_logs) || command_add("logtest", "Performs log performance testing.", 250, command_logtest) || - command_add("los", nullptr,0, command_checklos) || command_add("makepet", "[level] [class] [race] [texture] - Make a pet", 50, command_makepet) || command_add("mana", "- Fill your or your target's mana", 50, command_mana) || - command_add("maxskills", "Maxes skills for you.", 200, command_max_all_skills) || + command_add("maxskills", "Maxes skills for you.", 200, command_max_all_skills) || command_add("memspell", "[slotid] [spellid] - Memorize spellid in the specified slot", 50, command_memspell) || command_add("merchant_close_shop", "Closes a merchant shop", 100, command_merchantcloseshop) || command_add("merchant_open_shop", "Opens a merchants shop", 100, command_merchantopenshop) || @@ -291,7 +261,7 @@ int command_init(void) { command_add("movechar", "[charname] [zonename] - Move charname to zonename", 50, command_movechar) || command_add("myskills", "- Show details about your current skill levels", 0, command_myskills) || command_add("mysqltest", "Akkadius MySQL Bench Test", 250, command_mysqltest) || - command_add("mysql", "Mysql CLI, see 'help' for options.", 250, command_mysql) || + command_add("mysql", "Mysql CLI, see 'help' for options.", 250, command_mysql) || command_add("mystats", "- Show details about you or your pet", 50, command_mystats) || command_add("name", "[newname] - Rename your player target", 150, command_name) || command_add("netstats", "- Gets the network stats for a stream.", 200, command_netstats) || @@ -302,8 +272,6 @@ int command_init(void) { command_add("npcsay", "[message] - Make your NPC target say a message.", 150, command_npcsay) || command_add("npcshout", "[message] - Make your NPC target shout a message.", 150, command_npcshout) || command_add("npcspawn", "[create/add/update/remove/delete] - Manipulate spawn DB", 170, command_npcspawn) || - command_add("npcspecialatk", nullptr,0, command_npcspecialattk) || - command_add("npcspecialattack", nullptr,0, command_npcspecialattk) || command_add("npcspecialattk", "[flagchar] [perm] - Set NPC special attack flags. Flags are E(nrage) F(lurry) R(ampage) S(ummon).", 80, command_npcspecialattk) || command_add("npcstats", "- Show stats about target NPC", 80, command_npcstats) || command_add("npctype_cache", "[id] or all - Clears the npc type cache for either the id or all npcs.", 250, command_npctype_cache) || @@ -313,7 +281,11 @@ int command_init(void) { command_add("object", "List|Add|Edit|Move|Rotate|Copy|Save|Undo|Delete - Manipulate static and tradeskill objects within the zone", 100, command_object) || command_add("oocmute", "[1/0] - Mutes OOC chat", 200, command_oocmute) || command_add("opcode", "- opcode management", 250, command_opcode) || - command_add("open_shop", nullptr, 100, command_merchantopenshop) || + +#ifdef PACKET_PROFILER + command_add("packetprofile", "- Dump packet profile for target or self.", 250, command_packetprofile) || +#endif + command_add("path", "- view and edit pathing", 200, command_path) || command_add("peekinv", "[worn/inv/cursor/trib/bank/trade/world/all] - Print out contents of your player target's inventory", 100, command_peekinv) || command_add("peqzone", "[zonename] - Go to specified zone, if you have > 75% health", 0, command_peqzone) || @@ -323,9 +295,15 @@ int command_init(void) { command_add("petitioninfo", "[petition number] - Get info about a petition", 20, command_petitioninfo) || command_add("pf", "- Display additional mob coordinate and wandering data", 0, command_pf) || command_add("picklock", "Analog for ldon pick lock for the newer clients since we still don't have it working.", 0, command_picklock) || + +#ifdef EQPROFILE + command_add("profiledump", "- Dump profiling info to logs", 250, command_profiledump) || + command_add("profilereset", "- Reset profiling info", 250, command_profilereset) || +#endif + command_add("pvp", "[on/off] - Set your or your player target's PVP status", 100, command_pvp) || command_add("qglobal", "[on/off/view] - Toggles qglobal functionality on an NPC", 100, command_qglobal) || - command_add("questerrors", "Shows quest errors.", 100, command_questerrors) || + command_add("questerrors", "Shows quest errors.", 100, command_questerrors) || command_add("race", "[racenum] - Change your or your target's race. Use racenum 0 to return to normal", 50, command_race) || command_add("raidloot", "LEADER|GROUPLEADER|SELECTED|ALL - Sets your raid loot settings if you have permission to do so.", 0, command_raidloot) || command_add("randomfeatures", "- Temporarily randomizes the Facial Features of your target", 80, command_randomfeatures) || @@ -333,41 +311,32 @@ int command_init(void) { command_add("reloadaa", "Reloads AA data", 200, command_reloadaa) || command_add("reloadallrules", "Executes a reload of all rules.", 80, command_reloadallrules) || command_add("reloademote", "Reloads NPC Emotes", 80, command_reloademote) || - command_add("reloadlevelmods", nullptr,255, command_reloadlevelmods) || + command_add("reloadlevelmods", nullptr, 255, command_reloadlevelmods) || command_add("reloadperlexportsettings", nullptr, 255, command_reloadperlexportsettings) || command_add("reloadqst", " - Clear quest cache (any argument causes it to also stop all timers)", 150, command_reloadqst) || - command_add("reloadquest", " - Clear quest cache (any argument causes it to also stop all timers)", 150, command_reloadqst) || command_add("reloadrulesworld", "Executes a reload of all rules in world specifically.", 80, command_reloadworldrules) || command_add("reloadstatic", "- Reload Static Zone Data", 150, command_reloadstatic) || command_add("reloadtitles", "- Reload player titles from the database", 150, command_reloadtitles) || command_add("reloadworld", "[0|1] - Clear quest cache (0 - no repop, 1 - repop)", 255, command_reloadworld) || - command_add("reloadzonepoints", "- Reload zone points from database", 150, command_reloadzps) || - command_add("reloadzps", nullptr,0, command_reloadzps) || + command_add("reloadzps", "- Reload zone points from database", 150, command_reloadzps) || command_add("repop", "[delay] - Repop the zone with optional delay", 100, command_repop) || command_add("repopclose", "[distance in units] Repops only NPC's nearby for fast development purposes", 100, command_repopclose) || command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", 200, command_resetaa) || command_add("resetaa_timer", "Command to reset AA cooldown timers.", 200, command_resetaa_timer) || command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) || - command_add("rq", nullptr, 150, command_reloadqst) || - command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) || + command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) || command_add("save", "- Force your player or player corpse target to be saved to the database", 50, command_save) || - command_add("scribespell", "[spellid] - Scribe specified spell in your target's spell book.", 180, command_scribespell) || + command_add("scribespell", "[spellid] - Scribe specified spell in your target's spell book.", 180, command_scribespell) || command_add("scribespells", "[max level] [min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", 150, command_scribespells) || - command_add("search", nullptr,10, command_itemsearch) || command_add("sendzonespawns", "- Refresh spawn list for all clients in zone", 150, command_sendzonespawns) || command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", 0, command_sensetrap) || command_add("serverinfo", "- Get OS info about server host", 200, command_serverinfo) || command_add("serverrules", "- Read this server's rules", 0, command_serverrules) || - command_add("setaaexp", nullptr,0, command_setaaxp) || - command_add("setaapoints", nullptr,0, command_setaapts) || command_add("setaapts", "[value] - Set your or your player target's available AA points", 100, command_setaapts) || command_add("setaaxp", "[value] - Set your or your player target's AA experience", 100, command_setaaxp) || command_add("setadventurepoints", "- Set your or your player target's available adventure points", 150, command_set_adventure_points) || - command_add("setallskill", nullptr,0, command_setskillall) || - command_add("setallskills", nullptr,0, command_setskillall) || command_add("setanim", "[animnum] - Set target's appearance to animnum", 200, command_setanim) || command_add("setcrystals", "[value] - Set your or your player target's available radiant or ebon crystals", 100, command_setcrystals) || - command_add("setexp", nullptr,0, command_setxp) || command_add("setfaction", "[faction number] - Sets targeted NPC's faction in the database", 170, command_setfaction) || command_add("setgraveyard", "[zone name] - Creates a graveyard for the specified zone based on your target's LOC.", 200, command_setgraveyard) || command_add("setlanguage", "[language ID] [value] - Set your target's language skillnum to value", 50, command_setlanguage) || @@ -386,13 +355,11 @@ int command_init(void) { command_add("showspellslist", "Shows spell list of targeted NPC", 100, command_showspellslist) || command_add("showstats", "- Show details about you or your target", 50, command_showstats) || command_add("shutdown", "- Shut this zone process down", 150, command_shutdown) || - command_add("si", nullptr,200, command_summonitem) || command_add("size", "[size] - Change size of you or your target", 50, command_size) || command_add("spawn", "[name] [race] [level] [material] [hp] [gender] [class] [priweapon] [secweapon] [merchantid] - Spawn an NPC", 10, command_spawn) || command_add("spawnfix", "- Find targeted NPC in database based on its X/Y/heading and update the database to make it spawn at your current location/heading.", 170, command_spawnfix) || command_add("spawnstatus", "- Show respawn timer status", 100, command_spawnstatus) || command_add("spellinfo", "[spellid] - Get detailed info about a spell", 10, command_spellinfo) || - command_add("spfind", nullptr,0, command_findspell) || command_add("spoff", "- Sends OP_ManaChange", 80, command_spoff) || command_add("spon", "- Sends OP_MemorizeSpell", 80, command_spon) || command_add("stun", "[duration] - Stuns you or your target for duration", 100, command_stun) || @@ -414,7 +381,7 @@ int command_init(void) { command_add("undyeme", "- Remove dye from all of your armor slots", 0, command_undyeme) || command_add("unfreeze", "- Unfreeze your target", 80, command_unfreeze) || command_add("unlock", "- Unlock the worldserver", 150, command_unlock) || - command_add("unscribespell", "[spellid] - Unscribe specified spell from your target's spell book.", 180, command_unscribespell) || + command_add("unscribespell", "[spellid] - Unscribe specified spell from your target's spell book.", 180, command_unscribespell) || command_add("unscribespells", "- Clear out your or your player target's spell book.", 180, command_unscribespells) || command_add("untraindisc", "[spellid] - Untrain specified discipline from your target.", 180, command_untraindisc) || command_add("untraindiscs", "- Untrains all disciplines from your target.", 180, command_untraindiscs) || @@ -446,27 +413,35 @@ int command_init(void) { command_add("zstats", "- Show info about zone header", 80, command_zstats) || command_add("zunderworld", "[zcoord] - Sets the underworld using zcoord", 80, command_zunderworld) || command_add("zuwcoords", "[z coord] - Set underworld coord", 80, command_zuwcoords) - ) - { + ) { command_deinit(); return -1; } - - std::map::iterator cur,end; - cur = commandlist.begin(); - end = commandlist.end(); - std::map command_settings; - std::map::iterator itr; + + std::map>> command_settings; database.GetCommandSettings(command_settings); - for(; cur != end; ++cur) { - if ((itr=command_settings.find(cur->first))!=command_settings.end()) { - cur->second->access = itr->second; - Log.Out(Logs::General, Logs::Commands, "command_init(): - Command '%s' set to access level %d.", cur->first.c_str(), itr->second); + for (std::map::iterator iter_cl = commandlist.begin(); iter_cl != commandlist.end(); ++iter_cl) { + std::map>>::iterator 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()); + continue; } - else - { - if(cur->second->access == 0) - Log.Out(Logs::General, Logs::Commands, "command_init(): Warning: Command '%s' defaulting to access level 0!" , cur->first.c_str()); + + iter_cl->second->access = iter_cs->second.first; + Log.Out(Logs::General, Logs::Commands, "command_init(): - Command '%s' set to access level %d.", iter_cl->first.c_str(), iter_cs->second.first); + 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) { + if (iter_aka->empty()) + continue; + if (commandlist.find(*iter_aka) != commandlist.end()) { + Log.Out(Logs::General, Logs::Commands, "command_init(): Warning: Alias '%s' already exists as a command - skipping!", iter_aka->c_str()); + continue; + } + + commandlist[*iter_aka] = iter_cl->second; } } @@ -496,53 +471,38 @@ void command_deinit(void) * adds a command to the command list; used by command_init * * Parameters: - * command_string - the command ex: "spawn" - * desc - text description of command for #help - * access - default access level required to use command + * command_name - the command ex: "spawn" + * desc - text description of command for #help + * access - default access level required to use command * function - pointer to function that handles command * */ -int command_add(const char *command_string, const char *desc, int access, CmdFuncPtr function) +int command_add(std::string command_name, const char *desc, int access, CmdFuncPtr function) { - if(function == nullptr) - return(-1); - - std::string cstr(command_string); - - if(commandlist.count(cstr) != 0) { - Log.Out(Logs::General, Logs::Error, "command_add() - Command '%s' is a duplicate - check command.cpp." , command_string); - return(-1); + if (command_name.empty()) { + Log.Out(Logs::General, Logs::Error, "command_add() - Command added with empty name string - check command.cpp."); + return -1; + } + if (function == nullptr) { + Log.Out(Logs::General, Logs::Error, "command_add() - Command '%s' added without a valid function pointer - check command.cpp.", command_name.c_str()); + return -1; + } + if (commandlist.count(command_name) != 0) { + 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) { + 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; } - //look for aliases... - std::map::iterator cur,end,del; - cur = commandlist.begin(); - end = commandlist.end(); - for(; cur != end; ++cur) { - if(cur->second->function == function) { - int r; - for(r = 1; r < CMDALIASES; r++) { - if(cur->second->command[r] == nullptr) { - cur->second->command[r] = command_string; - break; - } - } - commandlist[cstr] = cur->second; - return(0); - } - } - - CommandRecord *c = new CommandRecord; + CommandRecord *c = new CommandRecord{ access, desc, function }; + commandlist[command_name] = c; cleanup_commandlist.Append(c); - c->desc = desc; - c->access = access; - c->function = function; - memset(c->command, 0, sizeof(c->command)); - c->command[0] = command_string; - - commandlist[cstr] = c; - commandcount++; + return 0; } diff --git a/zone/command.h b/zone/command.h index ac6107a20..45aa31fa6 100644 --- a/zone/command.h +++ b/zone/command.h @@ -25,324 +25,311 @@ class Seperator; #include "../common/types.h" -#define COMMAND_CHAR '#' -#define CMDALIASES 5 +#define COMMAND_CHAR '#' typedef void (*CmdFuncPtr)(Client *,const Seperator *); -// this is a command list item -/*struct cl_struct -{ - char *command[CMDALIASES]; // the command(s) - char *desc; // description of command - CmdFuncPtr function; // the function to call - int access; // the required 'status' level - - struct cl_struct *next; // linked list -}; - -extern struct cl_struct *commandlist; // the head of the list -*/ - typedef struct { - const char *command[CMDALIASES]; // the command(s) int access; - const char *desc; // description of command - CmdFuncPtr function; //null means perl function + const char *desc; // description of command + CmdFuncPtr function; // null means perl function } CommandRecord; extern int (*command_dispatch)(Client *,char const*); -extern int commandcount; // number of commands loaded +extern int commandcount; // number of commands loaded // the command system: int command_init(void); void command_deinit(void); -int command_add(const char *command_string, const char *desc, int access, CmdFuncPtr function); +int command_add(std::string command_name, const char *desc, int access, CmdFuncPtr function); int command_notavail(Client *c, const char *message); int command_realdispatch(Client *c, char const *message); void command_logcommand(Client *c, const char *message); //commands -void command_resetaa(Client* c,const Seperator *sep); -void command_bind(Client* c,const Seperator *sep); -void command_sendop(Client *c, const Seperator *sep); -void command_optest(Client *c, const Seperator *sep); -void command_setstat(Client *c, const Seperator *sep); -void command_incstat(Client *c, const Seperator *sep); -void command_help(Client *c, const Seperator *sep); -void command_version(Client *c, const Seperator *sep); -void command_setfaction(Client *c, const Seperator *sep); -void command_serversidename(Client *c, const Seperator *sep); -void command_testspawnkill(Client *c, const Seperator *sep); -void command_testspawn(Client *c, const Seperator *sep); -void command_wc(Client *c, const Seperator *sep); -void command_heromodel(Client *c, const Seperator *sep); -void command_numauths(Client *c, const Seperator *sep); -void command_setanim(Client *c, const Seperator *sep); -void command_connectworldserver(Client *c, const Seperator *sep); -void command_serverinfo(Client *c, const Seperator *sep); -void command_crashtest(Client *c, const Seperator *sep); -void command_getvariable(Client *c, const Seperator *sep); -void command_chat(Client *c, const Seperator *sep); -void command_showpetspell(Client *c, const Seperator *sep); -void command_ipc(Client *c, const Seperator *sep); -void command_npcloot(Client *c, const Seperator *sep); -void command_gm(Client *c, const Seperator *sep); -void command_summon(Client *c, const Seperator *sep); -void command_zone(Client *c, const Seperator *sep); -void command_zone_instance(Client *c, const Seperator *sep); -void command_peqzone(Client *c, const Seperator *sep); -void command_showbuffs(Client *c, const Seperator *sep); -void command_movechar(Client *c, const Seperator *sep); -void command_viewpetition(Client *c, const Seperator *sep); -void command_petitioninfo(Client *c, const Seperator *sep); -void command_delpetition(Client *c, const Seperator *sep); -void command_listnpcs(Client *c, const Seperator *sep); -void command_date(Client *c, const Seperator *sep); -void command_timezone(Client *c, const Seperator *sep); -void command_synctod(Client *c, const Seperator *sep); -void command_invul(Client *c, const Seperator *sep); -void command_hideme(Client *c, const Seperator *sep); -void command_emote(Client *c, const Seperator *sep); -void command_fov(Client *c, const Seperator *sep); -void command_manastat(Client *c, const Seperator *sep); -void command_npcstats(Client *c, const Seperator *sep); -void command_zclip(Client *c, const Seperator *sep); -void command_npccast(Client *c, const Seperator *sep); -void command_zstats(Client *c, const Seperator *sep); -void command_permaclass(Client *c, const Seperator *sep); -void command_permarace(Client *c, const Seperator *sep); -void command_permagender(Client *c, const Seperator *sep); -void command_weather(Client *c, const Seperator *sep); -void command_zheader(Client *c, const Seperator *sep); -void command_zsky(Client *c, const Seperator *sep); -void command_zcolor(Client *c, const Seperator *sep); -void command_spon(Client *c, const Seperator *sep); -void command_spoff(Client *c, const Seperator *sep); -void command_itemtest(Client *c, const Seperator *sep); -void command_gassign(Client *c, const Seperator *sep); +void command_acceptrules(Client *c, const Seperator *sep); +void command_advnpcspawn(Client *c, const Seperator *sep); +void command_aggro(Client *c, const Seperator *sep); +void command_aggrozone(Client *c, const Seperator *sep); void command_ai(Client *c, const Seperator *sep); -void command_worldshutdown(Client *c, const Seperator *sep); -void command_sendzonespawns(Client *c, const Seperator *sep); -void command_zsave(Client *c, const Seperator *sep); -void command_dbspawn2(Client *c, const Seperator *sep); -void command_shutdown(Client *c, const Seperator *sep); -void command_delacct(Client *c, const Seperator *sep); -void command_setpass(Client *c, const Seperator *sep); -void command_setlsinfo(Client *c, const Seperator *sep); -void command_grid(Client *c, const Seperator *sep); -void command_wp(Client *c, const Seperator *sep); -void command_iplookup(Client *c, const Seperator *sep); -void command_size(Client *c, const Seperator *sep); -void command_mana(Client *c, const Seperator *sep); -void command_flymode(Client *c, const Seperator *sep); -void command_showskills(Client *c, const Seperator *sep); -void command_findspell(Client *c, const Seperator *sep); -void command_castspell(Client *c, const Seperator *sep); -void command_setlanguage(Client *c, const Seperator *sep); -void command_setskill(Client *c, const Seperator *sep); -void command_setskillall(Client *c, const Seperator *sep); -void command_race(Client *c, const Seperator *sep); -void command_gender(Client *c, const Seperator *sep); -void command_makepet(Client *c, const Seperator *sep); -void command_level(Client *c, const Seperator *sep); -void command_spawn(Client *c, const Seperator *sep); -void command_texture(Client *c, const Seperator *sep); -void command_npctypespawn(Client *c, const Seperator *sep); -void command_heal(Client *c, const Seperator *sep); void command_appearance(Client *c, const Seperator *sep); -void command_nukeitem(Client *c, const Seperator *sep); -void command_peekinv(Client *c, const Seperator *sep); -void command_interrogateinv(Client *c, const Seperator *sep); -void command_invsnapshot(Client *c, const Seperator *sep); -void command_clearinvsnapshots(Client *c, const Seperator *sep); -void command_findnpctype(Client *c, const Seperator *sep); -void command_findzone(Client *c, const Seperator *sep); -void command_viewnpctype(Client *c, const Seperator *sep); -void command_reloadqst(Client *c, const Seperator *sep); -void command_reloadworld(Client *c, const Seperator *sep); -void command_reloadzps(Client *c, const Seperator *sep); -void command_zoneshutdown(Client *c, const Seperator *sep); -void command_zonebootup(Client *c, const Seperator *sep); -void command_kick(Client *c, const Seperator *sep); +void command_apply_shared_memory(Client *c, const Seperator *sep); void command_attack(Client *c, const Seperator *sep); -void command_lock(Client *c, const Seperator *sep); -void command_unlock(Client *c, const Seperator *sep); -void command_motd(Client *c, const Seperator *sep); -void command_listpetition(Client *c, const Seperator *sep); -void command_equipitem(Client *c, const Seperator *sep); -void command_zonelock(Client *c, const Seperator *sep); -void command_corpse(Client *c, const Seperator *sep); -void command_fixmob(Client *c, const Seperator *sep); -void command_gmspeed(Client *c, const Seperator *sep); -void command_title(Client *c, const Seperator *sep); -void command_titlesuffix(Client *c, const Seperator *sep); -void command_spellinfo(Client *c, const Seperator *sep); -void command_lastname(Client *c, const Seperator *sep); -void command_memspell(Client *c, const Seperator *sep); -void command_save(Client *c, const Seperator *sep); -void command_showstats(Client *c, const Seperator *sep); -void command_mystats(Client *c, const Seperator *sep); -void command_myskills(Client *c, const Seperator *sep); -void command_depop(Client *c, const Seperator *sep); -void command_depopzone(Client *c, const Seperator *sep); -void command_repop(Client *c, const Seperator *sep); -void command_repopclose(Client *c, const Seperator *sep); -void command_spawnstatus(Client *c, const Seperator *sep); -void command_nukebuffs(Client *c, const Seperator *sep); -void command_zuwcoords(Client *c, const Seperator *sep); -void command_zunderworld(Client *c, const Seperator *sep); -void command_zsafecoords(Client *c, const Seperator *sep); -void command_freeze(Client *c, const Seperator *sep); -void command_unfreeze(Client *c, const Seperator *sep); -void command_pvp(Client *c, const Seperator *sep); -void command_setxp(Client *c, const Seperator *sep); -void command_setpvppoints(Client *c, const Seperator *sep); -void command_name(Client *c, const Seperator *sep); -void command_tempname(Client *c, const Seperator *sep); -void command_npcspecialattk(Client *c, const Seperator *sep); -void command_kill(Client *c, const Seperator *sep); -void command_haste(Client *c, const Seperator *sep); -void command_damage(Client *c, const Seperator *sep); -void command_zonespawn(Client *c, const Seperator *sep); -void command_npcspawn(Client *c, const Seperator *sep); -void command_spawnfix(Client *c, const Seperator *sep); -void command_loc(Client *c, const Seperator *sep); -void command_goto(Client *c, const Seperator *sep); +void command_augmentitem(Client *c, const Seperator *sep); +void command_ban(Client *c, const Seperator *sep); +void command_beard(Client *c, const Seperator *sep); +void command_beardcolor(Client *c, const Seperator *sep); +void command_bind(Client* c, const Seperator *sep); + #ifdef BUGTRACK void command_bug(Client *c, const Seperator *sep); #endif -void command_iteminfo(Client *c, const Seperator *sep); -void command_uptime(Client *c, const Seperator *sep); -void command_flag(Client *c, const Seperator *sep); -void command_time(Client *c, const Seperator *sep); -void command_guild(Client *c, const Seperator *sep); -bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value); -void command_zonestatus(Client *c, const Seperator *sep); -void command_doanim(Client *c, const Seperator *sep); -void command_randomfeatures(Client *c, const Seperator *sep); -void command_face(Client *c, const Seperator *sep); -void command_helm(Client *c, const Seperator *sep); -void command_hair(Client *c, const Seperator *sep); -void command_haircolor(Client *c, const Seperator *sep); -void command_beard(Client *c, const Seperator *sep); -void command_beardcolor(Client *c, const Seperator *sep); -void command_tattoo(Client *c, const Seperator *sep); -void command_heritage(Client *c, const Seperator *sep); -void command_details(Client *c, const Seperator *sep); -void command_scribespells(Client *c, const Seperator *sep); -void command_unscribespells(Client *c, const Seperator *sep); -void command_wpinfo(Client *c, const Seperator *sep); -void command_wpadd(Client *c, const Seperator *sep); -void command_interrupt(Client *c, const Seperator *sep); + +void command_camerashake(Client *c, const Seperator *sep); +void command_castspell(Client *c, const Seperator *sep); +void command_chat(Client *c, const Seperator *sep); +void command_checklos(Client *c, const Seperator *sep); +void command_clearinvsnapshots(Client *c, const Seperator *sep); +void command_connectworldserver(Client *c, const Seperator *sep); +void command_corpse(Client *c, const Seperator *sep); +void command_crashtest(Client *c, const Seperator *sep); +void command_cvs(Client *c, const Seperator *sep); void command_d1(Client *c, const Seperator *sep); -void command_summonitem(Client *c, const Seperator *sep); +void command_damage(Client *c, const Seperator *sep); +void command_date(Client *c, const Seperator *sep); +void command_dbspawn2(Client *c, const Seperator *sep); +void command_delacct(Client *c, const Seperator *sep); +void command_deletegraveyard(Client *c, const Seperator *sep); +void command_delpetition(Client *c, const Seperator *sep); +void command_depop(Client *c, const Seperator *sep); +void command_depopzone(Client *c, const Seperator *sep); +void command_details(Client *c, const Seperator *sep); +void command_disablerecipe(Client *c, const Seperator *sep); +void command_disarmtrap(Client *c, const Seperator *sep); +void command_distance(Client *c, const Seperator *sep); +void command_doanim(Client *c, const Seperator *sep); +void command_emote(Client *c, const Seperator *sep); +void command_emotesearch(Client* c, const Seperator *sep); +void command_emoteview(Client* c, const Seperator *sep); +void command_enablerecipe(Client *c, const Seperator *sep); +void command_equipitem(Client *c, const Seperator *sep); +void command_face(Client *c, const Seperator *sep); +void command_findnpctype(Client *c, const Seperator *sep); +void command_findspell(Client *c, const Seperator *sep); +void command_findzone(Client *c, const Seperator *sep); +void command_fixmob(Client *c, const Seperator *sep); +void command_flag(Client *c, const Seperator *sep); +void command_flagedit(Client *c, const Seperator *sep); +void command_flags(Client *c, const Seperator *sep); +void command_flymode(Client *c, const Seperator *sep); +void command_fov(Client *c, const Seperator *sep); +void command_freeze(Client *c, const Seperator *sep); +void command_gassign(Client *c, const Seperator *sep); +void command_gender(Client *c, const Seperator *sep); +void command_getplayerburiedcorpsecount(Client *c, const Seperator *sep); +void command_getvariable(Client *c, const Seperator *sep); +void command_ginfo(Client *c, const Seperator *sep); void command_giveitem(Client *c, const Seperator *sep); void command_givemoney(Client *c, const Seperator *sep); -void command_itemsearch(Client *c, const Seperator *sep); -void command_setaaxp(Client *c, const Seperator *sep); -void command_setaapts(Client *c, const Seperator *sep); -void command_setcrystals(Client *c, const Seperator *sep); -void command_stun(Client *c, const Seperator *sep); -void command_ban(Client *c, const Seperator *sep); -void command_suspend(Client *c, const Seperator *sep); +void command_globalview(Client* c, const Seperator *sep); +void command_gm(Client *c, const Seperator *sep); +void command_gmspeed(Client *c, const Seperator *sep); +void command_goto(Client *c, const Seperator *sep); +void command_grid(Client *c, const Seperator *sep); +void command_guild(Client *c, const Seperator *sep); +bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value); +void command_guildapprove(Client *c, const Seperator *sep); +void command_guildcreate(Client *c, const Seperator *sep); +void command_guildlist(Client *c, const Seperator *sep); +void command_hair(Client *c, const Seperator *sep); +void command_haircolor(Client *c, const Seperator *sep); +void command_haste(Client *c, const Seperator *sep); +void command_hatelist(Client *c, const Seperator *sep); +void command_heal(Client *c, const Seperator *sep); +void command_helm(Client *c, const Seperator *sep); +void command_help(Client *c, const Seperator *sep); +void command_heritage(Client *c, const Seperator *sep); +void command_heromodel(Client *c, const Seperator *sep); +void command_hideme(Client *c, const Seperator *sep); +void command_hotfix(Client *c, const Seperator *sep); +void command_hp(Client *c, const Seperator *sep); +void command_incstat(Client *c, const Seperator *sep); +void command_instance(Client *c, const Seperator *sep); +void command_interrogateinv(Client *c, const Seperator *sep); +void command_interrupt(Client *c, const Seperator *sep); +void command_invsnapshot(Client *c, const Seperator *sep); +void command_invul(Client *c, const Seperator *sep); void command_ipban(Client *c, const Seperator *sep); -void command_oocmute(Client *c, const Seperator *sep); -void command_revoke(Client *c, const Seperator *sep); -void command_checklos(Client *c, const Seperator *sep); -void command_set_adventure_points(Client *c, const Seperator *sep); +void command_ipc(Client *c, const Seperator *sep); +void command_iplookup(Client *c, const Seperator *sep); +void command_iteminfo(Client *c, const Seperator *sep); +void command_itemsearch(Client *c, const Seperator *sep); +void command_itemtest(Client *c, const Seperator *sep); +void command_kick(Client *c, const Seperator *sep); +void command_kill(Client *c, const Seperator *sep); +void command_lastname(Client *c, const Seperator *sep); +void command_level(Client *c, const Seperator *sep); +void command_listnpcs(Client *c, const Seperator *sep); +void command_listpetition(Client *c, const Seperator *sep); +void command_load_shared_memory(Client *c, const Seperator *sep); +void command_loc(Client *c, const Seperator *sep); +void command_lock(Client *c, const Seperator *sep); +void command_logs(Client *c, const Seperator *sep); +void command_logtest(Client *c, const Seperator *sep); +void command_makepet(Client *c, const Seperator *sep); +void command_mana(Client *c, const Seperator *sep); +void command_manastat(Client *c, const Seperator *sep); +void command_max_all_skills(Client *c, const Seperator *sep); +void command_memspell(Client *c, const Seperator *sep); +void command_merchantcloseshop(Client *c, const Seperator *sep); +void command_merchantopenshop(Client *c, const Seperator *sep); +void command_modifynpcstat(Client *c, const Seperator *sep); +void command_motd(Client *c, const Seperator *sep); +void command_movechar(Client *c, const Seperator *sep); +void command_myskills(Client *c, const Seperator *sep); +void command_mysql(Client *c, const Seperator *sep); +void command_mysqltest(Client *c, const Seperator *sep); +void command_mystats(Client *c, const Seperator *sep); +void command_name(Client *c, const Seperator *sep); +void command_netstats(Client *c, const Seperator *sep); +void command_npccast(Client *c, const Seperator *sep); +void command_npcedit(Client *c, const Seperator *sep); +void command_npcemote(Client *c, const Seperator *sep); +void command_npcloot(Client *c, const Seperator *sep); void command_npcsay(Client *c, const Seperator *sep); void command_npcshout(Client *c, const Seperator *sep); -void command_npcemote(Client *c, const Seperator *sep); -void command_npcedit(Client *c, const Seperator *sep); -void command_timers(Client *c, const Seperator *sep); -void command_undye(Client *c, const Seperator *sep); -void command_undyeme(Client *c, const Seperator *sep); -void command_hp(Client *c, const Seperator *sep); -void command_ginfo(Client *c, const Seperator *sep); -void command_qglobal(Client *c, const Seperator *sep); -void command_path(Client *c, const Seperator *sep); -void command_ginfo(Client *c, const Seperator *sep); -void command_opcode(Client *c, const Seperator *sep); -void command_aggro(Client *c, const Seperator *sep); -void command_hatelist(Client *c, const Seperator *sep); -void command_aggrozone(Client *c, const Seperator *sep); -void command_reloadstatic(Client *c, const Seperator *sep); -void command_flags(Client *c, const Seperator *sep); -void command_flagedit(Client *c, const Seperator *sep); -void command_serverrules(Client *c, const Seperator *sep); -void command_acceptrules(Client *c, const Seperator *sep); -void command_guildcreate(Client *c, const Seperator *sep); -void command_guildapprove(Client *c, const Seperator *sep); -void command_guildlist(Client *c, const Seperator *sep); -void command_rules(Client *c, const Seperator *sep); -void command_task(Client *c, const Seperator *sep); -void command_reloadtitles(Client *c, const Seperator *sep); -void command_refundaa(Client *c, const Seperator *sep); -void command_traindisc(Client *c, const Seperator *sep); -void command_deletegraveyard(Client *c, const Seperator *sep); -void command_setgraveyard(Client *c, const Seperator *sep); -void command_getplayerburiedcorpsecount(Client *c, const Seperator *sep); -void command_summonburiedplayercorpse(Client *c, const Seperator *sep); -void command_unscribespell(Client *c, const Seperator *sep); -void command_scribespell(Client *c, const Seperator *sep); -void command_refreshgroup(Client *c, const Seperator *sep); -void command_advnpcspawn(Client *c, const Seperator *sep); -void command_modifynpcstat(Client *c, const Seperator *sep); -void command_instance(Client *c, const Seperator *sep); -void command_setstartzone(Client *c, const Seperator *sep); -void command_netstats(Client *c, const Seperator *sep); -void command_object(Client* c, const Seperator *sep); -void command_raidloot(Client* c, const Seperator *sep); -void command_globalview(Client* c, const Seperator *sep); -void command_emoteview(Client* c, const Seperator *sep); -void command_reloademote(Client* c, const Seperator *sep); -void command_emotesearch(Client* c, const Seperator *sep); -void command_distance(Client *c, const Seperator *sep); -void command_cvs(Client *c, const Seperator *sep); -void command_max_all_skills(Client *c, const Seperator *sep); -void command_showbonusstats(Client *c, const Seperator *sep); -void command_reloadallrules(Client *c, const Seperator *sep); -void command_reloadworldrules(Client *c, const Seperator *sep); -void command_reloadlevelmods(Client *c, const Seperator *sep); -void command_camerashake(Client *c, const Seperator *sep); -void command_disarmtrap(Client *c, const Seperator *sep); -void command_sensetrap(Client *c, const Seperator *sep); -void command_picklock(Client *c, const Seperator *sep); -void command_qtest(Client *c, const Seperator *sep); -void command_mysql(Client *c, const Seperator *sep); -void command_xtargets(Client *c, const Seperator *sep); -void command_zopp(Client *c, const Seperator *sep); -void command_augmentitem(Client *c, const Seperator *sep); -void command_questerrors(Client *c, const Seperator *sep); -void command_enablerecipe(Client *c, const Seperator *sep); -void command_disablerecipe(Client *c, const Seperator *sep); -void command_showspellslist(Client *c, const Seperator *sep); +void command_npcspawn(Client *c, const Seperator *sep); +void command_npcspecialattk(Client *c, const Seperator *sep); +void command_npcstats(Client *c, const Seperator *sep); void command_npctype_cache(Client *c, const Seperator *sep); -void command_merchantopenshop(Client *c, const Seperator *sep); -void command_merchantcloseshop(Client *c, const Seperator *sep); -void command_shownumhits(Client *c, const Seperator *sep); -void command_tune(Client *c, const Seperator *sep); -void command_logtest(Client *c, const Seperator *sep); -void command_mysqltest(Client *c, const Seperator *sep); -void command_logs(Client *c, const Seperator *sep); -void command_resetaa_timer(Client *c, const Seperator *sep); -void command_reloadaa(Client *c, const Seperator *sep); -void command_hotfix(Client *c, const Seperator *sep); -void command_load_shared_memory(Client *c, const Seperator *sep); -void command_apply_shared_memory(Client *c, const Seperator *sep); -void command_untraindisc(Client *c, const Seperator *sep); -void command_untraindiscs(Client *c, const Seperator *sep); -void command_reloadperlexportsettings(Client *c, const Seperator *sep); +void command_npctypespawn(Client *c, const Seperator *sep); +void command_nukebuffs(Client *c, const Seperator *sep); +void command_nukeitem(Client *c, const Seperator *sep); +void command_numauths(Client *c, const Seperator *sep); +void command_object(Client* c, const Seperator *sep); +void command_oocmute(Client *c, const Seperator *sep); +void command_opcode(Client *c, const Seperator *sep); +void command_optest(Client *c, const Seperator *sep); + +#ifdef PACKET_PROFILER +void command_packetprofile(Client *c, const Seperator *sep); +#endif + +void command_path(Client *c, const Seperator *sep); +void command_peekinv(Client *c, const Seperator *sep); +void command_peqzone(Client *c, const Seperator *sep); +void command_permaclass(Client *c, const Seperator *sep); +void command_permagender(Client *c, const Seperator *sep); +void command_permarace(Client *c, const Seperator *sep); +void command_petitioninfo(Client *c, const Seperator *sep); +void command_picklock(Client *c, const Seperator *sep); #ifdef EQPROFILE void command_profiledump(Client *c, const Seperator *sep); void command_profilereset(Client *c, const Seperator *sep); #endif -#ifdef PACKET_PROFILER -void command_packetprofile(Client *c, const Seperator *sep); -#endif +void command_pvp(Client *c, const Seperator *sep); +void command_qglobal(Client *c, const Seperator *sep); +void command_qtest(Client *c, const Seperator *sep); +void command_questerrors(Client *c, const Seperator *sep); +void command_race(Client *c, const Seperator *sep); +void command_raidloot(Client* c, const Seperator *sep); +void command_randomfeatures(Client *c, const Seperator *sep); +void command_refreshgroup(Client *c, const Seperator *sep); +void command_refundaa(Client *c, const Seperator *sep); +void command_reloadaa(Client *c, const Seperator *sep); +void command_reloadallrules(Client *c, const Seperator *sep); +void command_reloademote(Client* c, const Seperator *sep); +void command_reloadlevelmods(Client *c, const Seperator *sep); +void command_reloadperlexportsettings(Client *c, const Seperator *sep); +void command_reloadqst(Client *c, const Seperator *sep); +void command_reloadstatic(Client *c, const Seperator *sep); +void command_reloadtitles(Client *c, const Seperator *sep); +void command_reloadworld(Client *c, const Seperator *sep); +void command_reloadworldrules(Client *c, const Seperator *sep); +void command_reloadzps(Client *c, const Seperator *sep); +void command_repop(Client *c, const Seperator *sep); +void command_repopclose(Client *c, const Seperator *sep); +void command_resetaa(Client* c,const Seperator *sep); +void command_resetaa_timer(Client *c, const Seperator *sep); +void command_revoke(Client *c, const Seperator *sep); +void command_rules(Client *c, const Seperator *sep); +void command_save(Client *c, const Seperator *sep); +void command_scribespell(Client *c, const Seperator *sep); +void command_scribespells(Client *c, const Seperator *sep); +void command_sendop(Client *c, const Seperator *sep); +void command_sendzonespawns(Client *c, const Seperator *sep); +void command_sensetrap(Client *c, const Seperator *sep); +void command_serverinfo(Client *c, const Seperator *sep); +void command_serverrules(Client *c, const Seperator *sep); +void command_serversidename(Client *c, const Seperator *sep); +void command_set_adventure_points(Client *c, const Seperator *sep); +void command_setaapts(Client *c, const Seperator *sep); +void command_setaaxp(Client *c, const Seperator *sep); +void command_setanim(Client *c, const Seperator *sep); +void command_setcrystals(Client *c, const Seperator *sep); +void command_setfaction(Client *c, const Seperator *sep); +void command_setgraveyard(Client *c, const Seperator *sep); +void command_setlanguage(Client *c, const Seperator *sep); +void command_setlsinfo(Client *c, const Seperator *sep); +void command_setpass(Client *c, const Seperator *sep); +void command_setpvppoints(Client *c, const Seperator *sep); +void command_setskill(Client *c, const Seperator *sep); +void command_setskillall(Client *c, const Seperator *sep); +void command_setstartzone(Client *c, const Seperator *sep); +void command_setstat(Client *c, const Seperator *sep); +void command_setxp(Client *c, const Seperator *sep); +void command_showbonusstats(Client *c, const Seperator *sep); +void command_showbuffs(Client *c, const Seperator *sep); +void command_shownumhits(Client *c, const Seperator *sep); +void command_showpetspell(Client *c, const Seperator *sep); +void command_showskills(Client *c, const Seperator *sep); +void command_showspellslist(Client *c, const Seperator *sep); +void command_showstats(Client *c, const Seperator *sep); +void command_shutdown(Client *c, const Seperator *sep); +void command_size(Client *c, const Seperator *sep); +void command_spawn(Client *c, const Seperator *sep); +void command_spawnfix(Client *c, const Seperator *sep); +void command_spawnstatus(Client *c, const Seperator *sep); +void command_spellinfo(Client *c, const Seperator *sep); +void command_spoff(Client *c, const Seperator *sep); +void command_spon(Client *c, const Seperator *sep); +void command_stun(Client *c, const Seperator *sep); +void command_summon(Client *c, const Seperator *sep); +void command_summonburiedplayercorpse(Client *c, const Seperator *sep); +void command_summonitem(Client *c, const Seperator *sep); +void command_suspend(Client *c, const Seperator *sep); +void command_synctod(Client *c, const Seperator *sep); +void command_task(Client *c, const Seperator *sep); +void command_tattoo(Client *c, const Seperator *sep); +void command_tempname(Client *c, const Seperator *sep); +void command_testspawn(Client *c, const Seperator *sep); +void command_testspawnkill(Client *c, const Seperator *sep); +void command_texture(Client *c, const Seperator *sep); +void command_time(Client *c, const Seperator *sep); +void command_timers(Client *c, const Seperator *sep); +void command_timezone(Client *c, const Seperator *sep); +void command_title(Client *c, const Seperator *sep); +void command_titlesuffix(Client *c, const Seperator *sep); +void command_traindisc(Client *c, const Seperator *sep); +void command_tune(Client *c, const Seperator *sep); +void command_undye(Client *c, const Seperator *sep); +void command_undyeme(Client *c, const Seperator *sep); +void command_unfreeze(Client *c, const Seperator *sep); +void command_unlock(Client *c, const Seperator *sep); +void command_unscribespell(Client *c, const Seperator *sep); +void command_unscribespells(Client *c, const Seperator *sep); +void command_untraindisc(Client *c, const Seperator *sep); +void command_untraindiscs(Client *c, const Seperator *sep); +void command_uptime(Client *c, const Seperator *sep); +void command_version(Client *c, const Seperator *sep); +void command_viewnpctype(Client *c, const Seperator *sep); +void command_viewpetition(Client *c, const Seperator *sep); +void command_wc(Client *c, const Seperator *sep); +void command_weather(Client *c, const Seperator *sep); +void command_worldshutdown(Client *c, const Seperator *sep); +void command_wp(Client *c, const Seperator *sep); +void command_wpadd(Client *c, const Seperator *sep); +void command_wpinfo(Client *c, const Seperator *sep); +void command_xtargets(Client *c, const Seperator *sep); +void command_zclip(Client *c, const Seperator *sep); +void command_zcolor(Client *c, const Seperator *sep); +void command_zheader(Client *c, const Seperator *sep); +void command_zone(Client *c, const Seperator *sep); +void command_zone_instance(Client *c, const Seperator *sep); +void command_zonebootup(Client *c, const Seperator *sep); +void command_zonelock(Client *c, const Seperator *sep); +void command_zoneshutdown(Client *c, const Seperator *sep); +void command_zonespawn(Client *c, const Seperator *sep); +void command_zonestatus(Client *c, const Seperator *sep); +void command_zopp(Client *c, const Seperator *sep); +void command_zsafecoords(Client *c, const Seperator *sep); +void command_zsave(Client *c, const Seperator *sep); +void command_zsky(Client *c, const Seperator *sep); +void command_zstats(Client *c, const Seperator *sep); +void command_zunderworld(Client *c, const Seperator *sep); +void command_zuwcoords(Client *c, const Seperator *sep); #ifdef BOTS #include "bot.h" @@ -350,4 +337,3 @@ void command_bot(Client*c, const Seperator *sep); #endif #endif - From 2159d18920b97f61753b9aec09ae3d38e5439659 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 8 Dec 2015 21:15:41 -0500 Subject: [PATCH 423/846] Fix for VS2012 command.cpp:501 error --- zone/command.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index f2f9ed5a9..8cea3ae32 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -498,7 +498,11 @@ int command_add(std::string command_name, const char *desc, int access, CmdFuncP return -1; } - CommandRecord *c = new CommandRecord{ access, desc, function }; + CommandRecord *c = new CommandRecord; + c->access = access; + c->desc = desc; + c->function = function; + commandlist[command_name] = c; cleanup_commandlist.Append(c); commandcount++; From 98f77668753f030ca46c667cfd8d1f7981ccf4c6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 00:21:30 -0600 Subject: [PATCH 424/846] Update eqemu_update.pl --- utils/scripts/eqemu_update.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 4e2b476e0..f3fe2a569 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -136,6 +136,9 @@ if($ARGV[0] eq "installer"){ 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(); } @@ -143,8 +146,7 @@ if($ARGV[0] eq "installer"){ } if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); - + do_windows_login_server_setup(); exit; } From b499dcc89d657357487bbc9a82cf5d82fe2a0d34 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 01:00:27 -0600 Subject: [PATCH 425/846] Update eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index f3fe2a569..0c34cec39 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -145,6 +145,7 @@ if($ARGV[0] eq "installer"){ exit; } +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); } if($ARGV[0] eq "login_server_setup"){ do_windows_login_server_setup(); exit; From f474e171ed8510ce8939be3e0ca0b43f9c890e0b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 01:02:42 -0600 Subject: [PATCH 426/846] 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 0c34cec39..dea7834d8 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -145,7 +145,7 @@ if($ARGV[0] eq "installer"){ exit; } -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); } +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } if($ARGV[0] eq "login_server_setup"){ do_windows_login_server_setup(); exit; From e297de383040481acbb4b6383a363ca1f594231d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 01:14:07 -0600 Subject: [PATCH 427/846] Update eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index dea7834d8..c8f29cc99 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -118,10 +118,20 @@ if($ARGV[0] eq "installer"){ 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 + 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); + + #::: Database Routines print "MariaDB :: Creating Database 'peq'\n"; print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS peq;"`; @@ -145,7 +155,7 @@ if($ARGV[0] eq "installer"){ exit; } -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); } if($ARGV[0] eq "login_server_setup"){ do_windows_login_server_setup(); exit; From acb8e63d9ceb02ba2b77d1df879752c610ad1bb5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 01:14:45 -0600 Subject: [PATCH 428/846] 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 c8f29cc99..eb79ab7d1 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -155,7 +155,7 @@ if($ARGV[0] eq "installer"){ exit; } -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); } +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } if($ARGV[0] eq "login_server_setup"){ do_windows_login_server_setup(); exit; From 22496e2ae2b8123a21e4b737a4d940d731e9c873 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 19:28:56 -0600 Subject: [PATCH 429/846] Update eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index eb79ab7d1..b6c4ab1d0 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -130,6 +130,7 @@ if($ARGV[0] eq "installer"){ 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); #::: Database Routines From 75cddbea716a74da41bbb6c9e93d01e10884f864 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 20:30:47 -0600 Subject: [PATCH 430/846] Loginserver conversion to new Logging system --- common/eqemu_logsys.cpp | 1 + common/eqemu_logsys.h | 2 + loginserver/client.cpp | 46 ++++++++--------- loginserver/client_manager.cpp | 29 ++++++----- loginserver/config.cpp | 12 ++--- loginserver/encryption.cpp | 12 ++--- loginserver/main.cpp | 69 ++++++++++++------------- loginserver/server_manager.cpp | 18 ++++--- loginserver/world_server.cpp | 93 ++++++++++++++++++---------------- 9 files changed, 146 insertions(+), 136 deletions(-) diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 189c45bf6..4c0ee1c9f 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -102,6 +102,7 @@ void EQEmuLogSys::LoadLogSettingsDefaults() log_settings[Logs::UCS_Server].log_to_console = Logs::General; log_settings[Logs::Crash].log_to_console = Logs::General; log_settings[Logs::MySQLError].log_to_console = Logs::General; + log_settings[Logs::Login_Server].log_to_console = Logs::General; /* Declare process file names for log writing If there is no process_file_name declared, no log file will be written, simply diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index a99b3b439..153d61582 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -82,6 +82,7 @@ namespace Logs { Client_Server_Packet_Unhandled, Server_Client_Packet_With_Dump, Client_Server_Packet_With_Dump, + Login_Server, MaxCategoryID /* Don't Remove this*/ }; @@ -130,6 +131,7 @@ namespace Logs { "Packet :: Client -> Server Unhandled", "Packet :: Server -> Client (Dump)", "Packet :: Client -> Server (Dump)", + "Login Server" }; } diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 28836f915..a6cea46bf 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -16,12 +16,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "client.h" -#include "error_log.h" #include "login_server.h" #include "login_structures.h" #include "../common/misc_functions.h" +#include "../common/eqemu_logsys.h" -extern ErrorLog *server_log; +extern EQEmuLogSys Log; extern LoginServer server; Client::Client(std::shared_ptr c, LSClientVersion v) @@ -41,7 +41,7 @@ bool Client::Process() { if(server.options.IsTraceOn()) { - server_log->Log(log_network, "Application packet received from client (size %u)", app->Size()); + Log.Out(Logs::General, Logs::Login_Server, "Application packet received from client (size %u)", app->Size()); } if(server.options.IsDumpInPacketsOn()) @@ -55,7 +55,7 @@ bool Client::Process() { if(server.options.IsTraceOn()) { - server_log->Log(log_network, "Session ready received from client."); + Log.Out(Logs::General, Logs::Login_Server, "Session ready received from client."); } Handle_SessionReady((const char*)app->pBuffer, app->Size()); break; @@ -64,13 +64,13 @@ bool Client::Process() { if(app->Size() < 20) { - server_log->Log(log_network_error, "Login received but it is too small, discarding."); + Log.Out(Logs::General, Logs::Error, "Login received but it is too small, discarding."); break; } if(server.options.IsTraceOn()) { - server_log->Log(log_network, "Login received from client."); + Log.Out(Logs::General, Logs::Login_Server, "Login received from client."); } Handle_Login((const char*)app->pBuffer, app->Size()); @@ -80,7 +80,7 @@ bool Client::Process() { if(server.options.IsTraceOn()) { - server_log->Log(log_network, "Server list request received from client."); + Log.Out(Logs::General, Logs::Login_Server, "Server list request received from client."); } SendServerListPacket(); @@ -90,7 +90,7 @@ bool Client::Process() { if(app->Size() < sizeof(PlayEverquestRequest_Struct)) { - server_log->Log(log_network_error, "Play received but it is too small, discarding."); + Log.Out(Logs::General, Logs::Error, "Play received but it is too small, discarding."); break; } @@ -101,7 +101,7 @@ bool Client::Process() { char dump[64]; app->build_header_dump(dump); - server_log->Log(log_network_error, "Recieved unhandled application packet from the client: %s.", dump); + Log.Out(Logs::General, Logs::Error, "Recieved unhandled application packet from the client: %s.", dump); } } @@ -116,20 +116,20 @@ void Client::Handle_SessionReady(const char* data, unsigned int size) { if(status != cs_not_sent_session_ready) { - server_log->Log(log_network_error, "Session ready received again after already being received."); + Log.Out(Logs::General, Logs::Error, "Session ready received again after already being received."); return; } if(size < sizeof(unsigned int)) { - server_log->Log(log_network_error, "Session ready was too small."); + Log.Out(Logs::General, Logs::Error, "Session ready was too small."); return; } unsigned int mode = *((unsigned int*)data); if(mode == (unsigned int)lm_from_world) { - server_log->Log(log_network, "Session ready indicated logged in from world(unsupported feature), disconnecting."); + Log.Out(Logs::General, Logs::Login_Server, "Session ready indicated logged in from world(unsupported feature), disconnecting."); connection->Close(); return; } @@ -177,13 +177,13 @@ void Client::Handle_Login(const char* data, unsigned int size) { if(status != cs_waiting_for_login) { - server_log->Log(log_network_error, "Login received after already having logged in."); + Log.Out(Logs::General, Logs::Error, "Login received after already having logged in."); return; } if((size - 12) % 8 != 0) { - server_log->Log(log_network_error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size); + Log.Out(Logs::General, Logs::Error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size); return; } @@ -204,8 +204,8 @@ void Client::Handle_Login(const char* data, unsigned int size) if(server.options.IsTraceOn()) { - server_log->Log(log_client, "User: %s", e_user.c_str()); - server_log->Log(log_client, "Hash: %s", e_hash.c_str()); + Log.Out(Logs::General, Logs::Debug, "User: %s", e_user.c_str()); + Log.Out(Logs::General, Logs::Debug, "Hash: %s", e_hash.c_str()); } server.eq_crypto->DeleteHeap(e_buffer); @@ -218,8 +218,8 @@ void Client::Handle_Login(const char* data, unsigned int size) if(server.options.IsTraceOn()) { - server_log->Log(log_client, "User: %s", e_user.c_str()); - server_log->Log(log_client, "Hash: %s", e_hash.c_str()); + Log.Out(Logs::General, Logs::Debug, "User: %s", e_user.c_str()); + Log.Out(Logs::General, Logs::Debug, "Hash: %s", e_hash.c_str()); } _HeapDeleteCharBuffer(e_buffer); @@ -228,7 +228,7 @@ void Client::Handle_Login(const char* data, unsigned int size) bool result; if(server.db->GetLoginDataFromAccountName(e_user, d_pass_hash, d_account_id) == false) { - server_log->Log(log_client_error, "Error logging in, user %s does not exist in the database.", e_user.c_str()); + Log.Out(Logs::General, Logs::Error, "Error logging in, user %s does not exist in the database.", e_user.c_str()); result = false; } else @@ -331,7 +331,7 @@ void Client::Handle_Play(const char* data) { if(status != cs_logged_in) { - server_log->Log(log_client_error, "Client sent a play request when they either were not logged in, discarding."); + Log.Out(Logs::General, Logs::Error, "Client sent a play request when they either were not logged in, discarding."); return; } @@ -341,7 +341,7 @@ void Client::Handle_Play(const char* data) if(server.options.IsTraceOn()) { - server_log->Log(log_network, "Play received from client, server number %u sequence %u.", server_id_in, sequence_in); + Log.Out(Logs::General, Logs::Login_Server, "Play received from client, server number %u sequence %u.", server_id_in, sequence_in); } this->play_server_id = (unsigned int)play->ServerNumber; @@ -367,8 +367,8 @@ void Client::SendPlayResponse(EQApplicationPacket *outapp) { if(server.options.IsTraceOn()) { - server_log->Log(log_network_trace, "Sending play response for %s.", GetAccountName().c_str()); - server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size); + Log.Out(Logs::General, Logs::Netcode, "Sending play response for %s.", GetAccountName().c_str()); + // server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size); } connection->QueuePacket(outapp); status = cs_logged_in; diff --git a/loginserver/client_manager.cpp b/loginserver/client_manager.cpp index eb982f613..c600d58f5 100644 --- a/loginserver/client_manager.cpp +++ b/loginserver/client_manager.cpp @@ -16,13 +16,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "client_manager.h" -#include "error_log.h" #include "login_server.h" -extern ErrorLog *server_log; extern LoginServer server; extern bool run_server; +#include "../common/eqemu_logsys.h" +extern EQEmuLogSys Log; + ClientManager::ClientManager() { int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str()); @@ -30,18 +31,18 @@ ClientManager::ClientManager() titanium_ops = new RegularOpcodeManager; if(!titanium_ops->LoadOpcodes(server.config->GetVariable("Titanium", "opcodes").c_str())) { - server_log->Log(log_error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.", + Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.", server.config->GetVariable("Titanium", "opcodes").c_str()); run_server = false; } if(titanium_stream->Open()) { - server_log->Log(log_network, "ClientManager listening on Titanium stream."); + Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on Titanium stream."); } else { - server_log->Log(log_error, "ClientManager fatal error: couldn't open Titanium stream."); + Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open Titanium stream."); run_server = false; } @@ -50,18 +51,18 @@ ClientManager::ClientManager() sod_ops = new RegularOpcodeManager; if(!sod_ops->LoadOpcodes(server.config->GetVariable("SoD", "opcodes").c_str())) { - server_log->Log(log_error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.", + Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.", server.config->GetVariable("SoD", "opcodes").c_str()); run_server = false; } if(sod_stream->Open()) { - server_log->Log(log_network, "ClientManager listening on SoD stream."); + Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on SoD stream."); } else { - server_log->Log(log_error, "ClientManager fatal error: couldn't open SoD stream."); + Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open SoD stream."); run_server = false; } } @@ -99,7 +100,7 @@ void ClientManager::Process() { struct in_addr in; in.s_addr = cur->GetRemoteIP(); - server_log->Log(log_network, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort())); + Log.Out(Logs::General, Logs::Login_Server, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort())); cur->SetOpcodeManager(&titanium_ops); Client *c = new Client(cur, cv_titanium); @@ -112,7 +113,7 @@ void ClientManager::Process() { struct in_addr in; in.s_addr = cur->GetRemoteIP(); - server_log->Log(log_network, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort())); + Log.Out(Logs::General, Logs::Login_Server, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort())); cur->SetOpcodeManager(&sod_ops); Client *c = new Client(cur, cv_sod); @@ -125,7 +126,7 @@ void ClientManager::Process() { if((*iter)->Process() == false) { - server_log->Log(log_client, "Client had a fatal error and had to be removed from the login."); + Log.Out(Logs::General, Logs::Debug, "Client had a fatal error and had to be removed from the login."); delete (*iter); iter = clients.erase(iter); } @@ -144,7 +145,7 @@ void ClientManager::ProcessDisconnect() std::shared_ptr c = (*iter)->GetConnection(); if(c->CheckClosed()) { - server_log->Log(log_network, "Client disconnected from the server, removing client."); + Log.Out(Logs::General, Logs::Login_Server, "Client disconnected from the server, removing client."); delete (*iter); iter = clients.erase(iter); } @@ -172,7 +173,7 @@ void ClientManager::RemoveExistingClient(unsigned int account_id) { if((*iter)->GetAccountID() == account_id) { - server_log->Log(log_network, "Client attempting to log in and existing client already logged in, removing existing client."); + Log.Out(Logs::General, Logs::Login_Server, "Client attempting to log in and existing client already logged in, removing existing client."); delete (*iter); iter = clients.erase(iter); } @@ -200,7 +201,7 @@ Client *ClientManager::GetClient(unsigned int account_id) if(count > 1) { - server_log->Log(log_client_error, "More than one client with a given account_id existed in the client list."); + Log.Out(Logs::General, Logs::Error, "More than one client with a given account_id existed in the client list."); } return cur; } diff --git a/loginserver/config.cpp b/loginserver/config.cpp index 96a4c8568..ee17bdbed 100644 --- a/loginserver/config.cpp +++ b/loginserver/config.cpp @@ -16,10 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "../common/global_define.h" +#include "../common/eqemu_logsys.h" #include "config.h" -#include "error_log.h" -extern ErrorLog *server_log; +extern EQEmuLogSys Log; /** * Retrieves the variable we want from our title or theme * First gets the map from the title @@ -48,7 +48,7 @@ void Config::Parse(const char *file_name) { if(file_name == nullptr) { - server_log->Log(log_error, "Config::Parse(), file_name passed was null."); + Log.Out(Logs::General, Logs::Error, "Config::Parse(), file_name passed was null."); return; } @@ -71,7 +71,7 @@ void Config::Parse(const char *file_name) ++iter; if(iter == tokens.end()) { - server_log->Log(log_error, "Config::Parse(), EOF before title done parsing."); + Log.Out(Logs::General, Logs::Error, "Config::Parse(), EOF before title done parsing."); fclose(input); vars.clear(); return; @@ -104,7 +104,7 @@ void Config::Parse(const char *file_name) mode++; if((*iter).compare("=") != 0) { - server_log->Log(log_error, "Config::Parse(), invalid parse token where = should be."); + Log.Out(Logs::General, Logs::Error, "Config::Parse(), invalid parse token where = should be."); fclose(input); vars.clear(); return; @@ -133,7 +133,7 @@ void Config::Parse(const char *file_name) } else { - server_log->Log(log_error, "Config::Parse(), file was unable to be opened for parsing."); + Log.Out(Logs::General, Logs::Error, "Config::Parse(), file was unable to be opened for parsing."); } } diff --git a/loginserver/encryption.cpp b/loginserver/encryption.cpp index b00f5e88b..3c9ebd49f 100644 --- a/loginserver/encryption.cpp +++ b/loginserver/encryption.cpp @@ -17,16 +17,16 @@ */ #include "../common/global_define.h" #include "encryption.h" -#include "error_log.h" #include -extern ErrorLog *server_log; +#include "../common/eqemu_logsys.h" +extern EQEmuLogSys Log; bool Encryption::LoadCrypto(std::string name) { if(!Load(name.c_str())) { - server_log->Log(log_error, "Failed to load %s from the operating system.", name.c_str()); + Log.Out(Logs::General, Logs::Error, "Failed to load %s from the operating system.", name.c_str()); return false; } else @@ -34,21 +34,21 @@ bool Encryption::LoadCrypto(std::string name) encrypt_func = (DLLFUNC_Encrypt)GetSym("Encrypt"); if(encrypt_func == NULL) { - server_log->Log(log_error, "Failed to attach Encrypt."); + Log.Out(Logs::General, Logs::Error, "Failed to attach Encrypt."); Unload(); return false; } decrypt_func = (DLLFUNC_DecryptUsernamePassword)GetSym("DecryptUsernamePassword"); if(decrypt_func == NULL) { - server_log->Log(log_error, "Failed to attach DecryptUsernamePassword."); + Log.Out(Logs::General, Logs::Error, "Failed to attach DecryptUsernamePassword."); Unload(); return false; } delete_func = (DLLFUNC_HeapDelete)GetSym("_HeapDeleteCharBuffer"); if(delete_func == NULL) { - server_log->Log(log_error, "Failed to attach _HeapDeleteCharBuffer."); + Log.Out(Logs::General, Logs::Error, "Failed to attach _HeapDeleteCharBuffer."); Unload(); return false; } diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 62973cd16..7d3abd87c 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -43,6 +43,7 @@ int main() { RegisterExecutablePlatform(ExePlatformLogin); set_exception_handler(); + Log.LoadLogSettingsDefaults(); /* Start Loginserver log */ time_t current_time = time(nullptr); @@ -53,11 +54,11 @@ int main() log_name << "./logs/login_" << (unsigned int)current_time << ".log"; #endif server_log = new ErrorLog(log_name.str().c_str()); - server_log->Log(log_debug, "Logging System Init."); + Log.Out(Logs::General, Logs::Login_Server, "Logging System Init."); /* Parse out login.ini */ server.config = new Config(); - server_log->Log(log_debug, "Config System Init."); + Log.Out(Logs::General, Logs::Login_Server, "Config System Init."); server.config->Parse("login.ini"); if (server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0) @@ -105,7 +106,7 @@ int main() /* Create database connection */ if (server.config->GetVariable("database", "subsystem").compare("MySQL") == 0) { #ifdef EQEMU_MYSQL_ENABLED - server_log->Log(log_debug, "MySQL Database Init."); + Log.Out(Logs::General, Logs::Login_Server, "MySQL Database Init."); server.db = (Database*)new DatabaseMySQL( server.config->GetVariable("database", "user"), server.config->GetVariable("database", "password"), @@ -116,7 +117,7 @@ int main() } else if (server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0) { #ifdef EQEMU_POSTGRESQL_ENABLED - server_log->Log(log_debug, "PostgreSQL Database Init."); + Log.Out(Logs::General, Logs::Login_Server, "PostgreSQL Database Init."); server.db = (Database*)new DatabasePostgreSQL( server.config->GetVariable("database", "user"), server.config->GetVariable("database", "password"), @@ -128,74 +129,74 @@ int main() /* Make sure our database got created okay, otherwise cleanup and exit. */ if (!server.db) { - server_log->Log(log_error, "Database Initialization Failure."); - server_log->Log(log_debug, "Config System Shutdown."); + Log.Out(Logs::General, Logs::Error, "Database Initialization Failure."); + Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - server_log->Log(log_debug, "Log System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); delete server_log; return 1; } #if WIN32 //initialize our encryption. - server_log->Log(log_debug, "Encryption Initialize."); + Log.Out(Logs::General, Logs::Login_Server, "Encryption Initialize."); server.eq_crypto = new Encryption(); if (server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin"))) { - server_log->Log(log_debug, "Encryption Loaded Successfully."); + Log.Out(Logs::General, Logs::Login_Server, "Encryption Loaded Successfully."); } else { //We can't run without encryption, cleanup and exit. - server_log->Log(log_error, "Encryption Failed to Load."); - server_log->Log(log_debug, "Database System Shutdown."); + Log.Out(Logs::General, Logs::Error, "Encryption Failed to Load."); + Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown."); delete server.db; - server_log->Log(log_debug, "Config System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - server_log->Log(log_debug, "Log System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); delete server_log; return 1; } #endif //create our server manager. - server_log->Log(log_debug, "Server Manager Initialize."); + Log.Out(Logs::General, Logs::Login_Server, "Server Manager Initialize."); server.server_manager = new ServerManager(); if (!server.server_manager) { //We can't run without a server manager, cleanup and exit. - server_log->Log(log_error, "Server Manager Failed to Start."); + Log.Out(Logs::General, Logs::Error, "Server Manager Failed to Start."); #ifdef WIN32 - server_log->Log(log_debug, "Encryption System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown."); delete server.eq_crypto; #endif - server_log->Log(log_debug, "Database System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown."); delete server.db; - server_log->Log(log_debug, "Config System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - server_log->Log(log_debug, "Log System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); delete server_log; return 1; } //create our client manager. - server_log->Log(log_debug, "Client Manager Initialize."); + Log.Out(Logs::General, Logs::Login_Server, "Client Manager Initialize."); server.client_manager = new ClientManager(); if (!server.client_manager) { //We can't run without a client manager, cleanup and exit. - server_log->Log(log_error, "Client Manager Failed to Start."); - server_log->Log(log_debug, "Server Manager Shutdown."); + Log.Out(Logs::General, Logs::Error, "Client Manager Failed to Start."); + Log.Out(Logs::General, Logs::Login_Server, "Server Manager Shutdown."); delete server.server_manager; #ifdef WIN32 - server_log->Log(log_debug, "Encryption System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown."); delete server.eq_crypto; #endif - server_log->Log(log_debug, "Database System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown."); delete server.db; - server_log->Log(log_debug, "Config System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - server_log->Log(log_debug, "Log System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); delete server_log; return 1; } @@ -208,7 +209,7 @@ int main() #endif #endif - server_log->Log(log_debug, "Server Started."); + Log.Out(Logs::General, Logs::Login_Server, "Server Started."); while (run_server) { Timer::SetCurrentTime(); server.client_manager->Process(); @@ -216,22 +217,22 @@ int main() Sleep(100); } - server_log->Log(log_debug, "Server Shutdown."); - server_log->Log(log_debug, "Client Manager Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Server Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Client Manager Shutdown."); delete server.client_manager; - server_log->Log(log_debug, "Server Manager Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Server Manager Shutdown."); delete server.server_manager; #ifdef WIN32 - server_log->Log(log_debug, "Encryption System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown."); delete server.eq_crypto; #endif - server_log->Log(log_debug, "Database System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown."); delete server.db; - server_log->Log(log_debug, "Config System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - server_log->Log(log_debug, "Log System Shutdown."); + Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); delete server_log; return 0; } diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index 3da497523..f63e72b4e 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -21,7 +21,9 @@ #include "login_structures.h" #include -extern ErrorLog *server_log; +#include "../common/eqemu_logsys.h" + +extern EQEmuLogSys Log; extern LoginServer server; extern bool run_server; @@ -32,10 +34,10 @@ ServerManager::ServerManager() int listen_port = atoi(server.config->GetVariable("options", "listen_port").c_str()); tcps = new EmuTCPServer(listen_port, true); if(tcps->Open(listen_port, error_buffer)) { - server_log->Log(log_network, "ServerManager listening on port %u", listen_port); + Log.Out(Logs::General, Logs::Login_Server, "ServerManager listening on port %u", listen_port); } else { - server_log->Log(log_error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer); + Log.Out(Logs::General, Logs::Error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer); run_server = false; } } @@ -55,11 +57,11 @@ void ServerManager::Process() while (tcp_c = tcps->NewQueuePop()) { in_addr tmp; tmp.s_addr = tcp_c->GetrIP(); - server_log->Log(log_network, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort()); + Log.Out(Logs::General, Logs::Login_Server, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort()); WorldServer *server_entity = GetServerByAddress(tcp_c->GetrIP()); if (server_entity) { - server_log->Log(log_network, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp)); + Log.Out(Logs::General, Logs::Login_Server, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp)); server_entity->GetConnection()->Free(); server_entity->SetConnection(tcp_c); server_entity->Reset(); @@ -73,7 +75,7 @@ void ServerManager::Process() list::iterator iter = world_servers.begin(); while (iter != world_servers.end()) { if ((*iter)->Process() == false) { - server_log->Log(log_world, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str()); + Log.Out(Logs::General, Logs::World_Server, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str()); delete (*iter); iter = world_servers.erase(iter); } @@ -91,7 +93,7 @@ void ServerManager::ProcessDisconnect() if (!connection->Connected()) { in_addr tmp; tmp.s_addr = connection->GetrIP(); - server_log->Log(log_network, "World server disconnected from the server, removing server and freeing connection."); + Log.Out(Logs::General, Logs::Login_Server, "World server disconnected from the server, removing server and freeing connection."); connection->Free(); delete (*iter); iter = world_servers.erase(iter); @@ -258,7 +260,7 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int } if (!found && server.options.IsTraceOn()) { - server_log->Log(log_client_error, "Client requested a user to world but supplied an invalid id of %u.", server_id); + Log.Out(Logs::General, Logs::Error, "Client requested a user to world but supplied an invalid id of %u.", server_id); } } diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index 64f7de02c..8e912e285 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -16,11 +16,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "world_server.h" -#include "error_log.h" #include "login_server.h" #include "login_structures.h" +#include "config.h" -extern ErrorLog *server_log; +#include "../common/eqemu_logsys.h" + +extern EQEmuLogSys Log; extern LoginServer server; WorldServer::WorldServer(EmuTCPConnection *c) @@ -63,7 +65,7 @@ bool WorldServer::Process() { if(server.options.IsWorldTraceOn()) { - server_log->Log(log_network_trace, "Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size); + Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size); } if(server.options.IsDumpInPacketsOn()) @@ -77,14 +79,14 @@ bool WorldServer::Process() { if(app->size < sizeof(ServerNewLSInfo_Struct)) { - server_log->Log(log_network_error, "Received application packet from server that had opcode ServerOP_NewLSInfo, " + Log.Out(Logs::General, Logs::Error, "Received application packet from server that had opcode ServerOP_NewLSInfo, " "but was too small. Discarded to avoid buffer overrun."); break; } if(server.options.IsWorldTraceOn()) { - server_log->Log(log_network_trace, "New Login Info Recieved."); + Log.Out(Logs::General, Logs::Netcode, "New Login Info Recieved."); } ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)app->pBuffer; @@ -95,14 +97,14 @@ bool WorldServer::Process() { if(app->size < sizeof(ServerLSStatus_Struct)) { - server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerOP_LSStatus, " + Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_LSStatus, " "but was too small. Discarded to avoid buffer overrun."); break; } if(server.options.IsWorldTraceOn()) { - server_log->Log(log_network_trace, "World Server Status Recieved."); + Log.Out(Logs::General, Logs::Netcode, "World Server Status Recieved."); } ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)app->pBuffer; @@ -126,7 +128,7 @@ bool WorldServer::Process() { if(app->size < sizeof(UsertoWorldResponse_Struct)) { - server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, " + Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, " "but was too small. Discarded to avoid buffer overrun."); break; } @@ -136,21 +138,22 @@ bool WorldServer::Process() //While keeping world server spam with multiple servers connected almost impossible. if(server.options.IsTraceOn()) { - server_log->Log(log_network_trace, "User-To-World Response received."); + Log.Out(Logs::General, Logs::Netcode, "User-To-World Response received."); } UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)app->pBuffer; - server_log->Log(log_client, "Trying to find client with user id of %u.", utwr->lsaccountid); + Log.Out(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid); Client *c = server.client_manager->GetClient(utwr->lsaccountid); if(c) { - server_log->Log(log_client, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str()); + Log.Out(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str()); EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct)); PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer; per->Sequence = c->GetPlaySequence(); per->ServerNumber = c->GetPlayServerID(); - server_log->Log(log_client, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID()); - server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size); + Log.Out(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID()); + + Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str()); if(utwr->response > 0) { @@ -179,9 +182,9 @@ bool WorldServer::Process() if(server.options.IsTraceOn()) { - server_log->Log(log_network_trace, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u", + Log.Out(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u", per->Allowed, per->Sequence, per->ServerNumber, per->Message); - server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size); + Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str()); } if(server.options.IsDumpOutPacketsOn()) @@ -194,7 +197,7 @@ bool WorldServer::Process() } else { - server_log->Log(log_client_error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid); + Log.Out(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid); } break; } @@ -202,16 +205,16 @@ bool WorldServer::Process() { if(app->size < sizeof(ServerLSAccountUpdate_Struct)) { - server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, " + Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, " "but was too small. Discarded to avoid buffer overrun."); break; } - server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str()); + Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str()); ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)app->pBuffer; if(is_server_trusted) { - server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount); + Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount); string name; string password; string email; @@ -224,7 +227,7 @@ bool WorldServer::Process() } default: { - server_log->Log(log_network_error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", app->opcode); + Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", app->opcode); } } @@ -238,7 +241,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { if(is_server_logged_in) { - server_log->Log(log_network_error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting."); + Log.Out(Logs::General, Logs::Error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting."); return; } @@ -248,7 +251,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - server_log->Log(log_network_error, "Handle_NewLSInfo error, account name was too long."); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, account name was too long."); return; } @@ -258,7 +261,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - server_log->Log(log_network_error, "Handle_NewLSInfo error, account password was too long."); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, account password was too long."); return; } @@ -268,7 +271,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - server_log->Log(log_network_error, "Handle_NewLSInfo error, long name was too long."); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, long name was too long."); return; } @@ -278,7 +281,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - server_log->Log(log_network_error, "Handle_NewLSInfo error, short name was too long."); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, short name was too long."); return; } @@ -286,7 +289,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { if(strlen(i->local_address) == 0) { - server_log->Log(log_network_error, "Handle_NewLSInfo error, local address was null, defaulting to localhost"); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, local address was null, defaulting to localhost"); local_ip = "127.0.0.1"; } else @@ -296,7 +299,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - server_log->Log(log_network_error, "Handle_NewLSInfo error, local address was too long."); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, local address was too long."); return; } @@ -307,7 +310,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) in_addr in; in.s_addr = GetConnection()->GetrIP(); remote_ip = inet_ntoa(in); - server_log->Log(log_network_error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str()); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str()); } else { @@ -319,7 +322,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) in_addr in; in.s_addr = GetConnection()->GetrIP(); remote_ip = inet_ntoa(in); - server_log->Log(log_network_error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str()); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str()); } if(strlen(i->serverversion) <= 64) @@ -328,7 +331,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - server_log->Log(log_network_error, "Handle_NewLSInfo error, server version was too long."); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, server version was too long."); return; } @@ -338,7 +341,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - server_log->Log(log_network_error, "Handle_NewLSInfo error, protocol version was too long."); + Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, protocol version was too long."); return; } @@ -349,7 +352,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { if(server.server_manager->ServerExists(long_name, short_name, this)) { - server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name."); + Log.Out(Logs::General, Logs::Error, "World tried to login but there already exists a server that has that name."); return; } } @@ -357,7 +360,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { if(server.server_manager->ServerExists(long_name, short_name, this)) { - server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name."); + Log.Out(Logs::General, Logs::Error, "World tried to login but there already exists a server that has that name."); server.server_manager->DestroyServerByName(long_name, short_name, this); } } @@ -377,7 +380,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) { if(s_acct_name.size() == 0 || s_acct_pass.size() == 0) { - server_log->Log(log_world, "Server %s(%s) successfully logged into account that had no user/password requirement.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged into account that had no user/password requirement.", long_name.c_str(), short_name.c_str()); is_server_authorized = true; SetRuntimeID(s_id); @@ -386,33 +389,33 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else if(s_acct_name.compare(account_name) == 0 && s_acct_pass.compare(account_password) == 0) { - server_log->Log(log_world, "Server %s(%s) successfully logged in.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged in.", long_name.c_str(), short_name.c_str()); is_server_authorized = true; SetRuntimeID(s_id); server_list_id = s_list_type; desc = s_desc; if(s_trusted) { - server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world"); + Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world"); is_server_trusted = true; ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0); connection->SendPacket(outapp); } } else { - server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only" + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only" " registered servers are allowed.", long_name.c_str(), short_name.c_str()); return; } } else { - server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.", long_name.c_str(), short_name.c_str()); return; } } else { - server_log->Log(log_world, "Server %s(%s) did not attempt to log in but only registered servers are allowed.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but only registered servers are allowed.", long_name.c_str(), short_name.c_str()); return; } @@ -441,7 +444,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) if(account_name.size() > 0 && account_password.size() > 0) { if(server_account_name.compare(account_name) == 0 && server_account_password.compare(account_password) == 0) { - server_log->Log(log_world, "Server %s(%s) successfully logged in.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged in.", long_name.c_str(), short_name.c_str()); is_server_authorized = true; SetRuntimeID(server_id); @@ -449,7 +452,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) desc = server_description; if(is_server_trusted) { - server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world"); + Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world"); is_server_trusted = true; ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0); connection->SendPacket(outapp); @@ -457,18 +460,18 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { // this is the first of two cases where we should deny access even if unregistered is allowed - server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.", long_name.c_str(), short_name.c_str()); } } else { if(server_account_name.size() > 0 || server_account_password.size() > 0) { // this is the second of two cases where we should deny access even if unregistered is allowed - server_log->Log(log_world, "Server %s(%s) did not attempt to log in but this server requires a password.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but this server requires a password.", long_name.c_str(), short_name.c_str()); } else { - server_log->Log(log_world, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.", long_name.c_str(), short_name.c_str()); is_server_authorized = true; SetRuntimeID(server_id); @@ -478,7 +481,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i) } else { - server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.", + Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.", long_name.c_str(), short_name.c_str()); if(server.db->CreateWorldRegistration(long_name, short_name, server_id)) { is_server_authorized = true; From efe09f6fe5129bc90d95c39ef88bf1f1adcc0d45 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 20:33:20 -0600 Subject: [PATCH 431/846] Remove old error_log system from the Loginserver --- loginserver/CMakeLists.txt | 2 - loginserver/error_log.cpp | 209 ------------------------------------- loginserver/error_log.h | 79 -------------- 3 files changed, 290 deletions(-) delete mode 100644 loginserver/error_log.cpp delete mode 100644 loginserver/error_log.h diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index bdd1bba07..82e912edc 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -6,7 +6,6 @@ SET(eqlogin_sources config.cpp database_mysql.cpp database_postgresql.cpp - error_log.cpp main.cpp server_manager.cpp world_server.cpp @@ -26,7 +25,6 @@ SET(eqlogin_headers database_postgresql.h encryption.h eq_crypto_api.h - error_log.h login_server.h login_structures.h options.h diff --git a/loginserver/error_log.cpp b/loginserver/error_log.cpp deleted file mode 100644 index 950a5d0d8..000000000 --- a/loginserver/error_log.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2010 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 -#include "error_log.h" - -const char *eqLogTypes[_log_largest_type] = -{ - "Debug", - "Error", - "Database", - "Network", - "Network Trace", - "Network Error", - "World", - "World Error", - "Client", - "Client Error" -}; - -ErrorLog::ErrorLog(const char* file_name) -{ - log_mutex = new Mutex(); - error_log = fopen(file_name, "w"); -} - -ErrorLog::~ErrorLog() -{ - log_mutex->lock(); - if (error_log) - { - fclose(error_log); - } - log_mutex->unlock(); - delete log_mutex; -} - -void ErrorLog::Log(eqLogType type, const char *message, ...) -{ - if (type >= _log_largest_type) - { - return; - } - - va_list argptr; - char *buffer = new char[4096]; - va_start(argptr, message); - vsnprintf(buffer, 4096, message, argptr); - va_end(argptr); - - time_t m_clock; - struct tm *m_time; - time(&m_clock); - m_time = localtime(&m_clock); - - log_mutex->lock(); - printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n", - eqLogTypes[type], - m_time->tm_mon + 1, - m_time->tm_mday, - m_time->tm_year % 100, - m_time->tm_hour, - m_time->tm_min, - m_time->tm_sec, - buffer); - - if (error_log) - { - fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n", - eqLogTypes[type], - m_time->tm_mon + 1, - m_time->tm_mday, - m_time->tm_year % 100, - m_time->tm_hour, - m_time->tm_min, - m_time->tm_sec, - buffer); - fflush(error_log); - } - - log_mutex->unlock(); - delete[] buffer; -} - -void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size) -{ - if (type >= _log_largest_type) - { - return; - } - - log_mutex->lock(); - time_t m_clock; - struct tm *m_time; - time(&m_clock); - m_time = localtime(&m_clock); - - log_mutex->lock(); - printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u:\n", - eqLogTypes[type], - m_time->tm_mon + 1, - m_time->tm_mday, - m_time->tm_year % 100, - m_time->tm_hour, - m_time->tm_min, - m_time->tm_sec, - (unsigned int)size); - - if (error_log) - { - fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u\n", - eqLogTypes[type], - m_time->tm_mon + 1, - m_time->tm_mday, - m_time->tm_year % 100, - m_time->tm_hour, - m_time->tm_min, - m_time->tm_sec, - (unsigned int)size); - } - - char ascii[17]; //16 columns + 1 null term - memset(ascii, 0, 17); - - size_t j = 0; - size_t i = 0; - for (; i < size; ++i) - { - if (i % 16 == 0) - { - if (i != 0) - { - printf(" | %s\n", ascii); - if (error_log) - { - fprintf(error_log, " | %s\n", ascii); - } - } - printf("%.4u: ", (unsigned int)i); - memset(ascii, 0, 17); - j = 0; - } - else if (i % 8 == 0) - { - printf("- "); - if (error_log) - { - fprintf(error_log, "- "); - } - } - - printf("%02X ", (unsigned int)data[i]); - if (error_log) - { - fprintf(error_log, "%02X ", (unsigned int)data[i]); - } - - if (data[i] >= 32 && data[i] < 127) - { - ascii[j++] = data[i]; - } - else - { - ascii[j++] = '.'; - } - } - - size_t k = (i - 1) % 16; - if (k < 8) - { - printf(" "); - if (error_log) - { - fprintf(error_log, " "); - } - } - - for (size_t h = k + 1; h < 16; ++h) - { - printf(" "); - if (error_log) - { - fprintf(error_log, " "); - } - } - - printf(" | %s\n", ascii); - if (error_log) - { - fprintf(error_log, " | %s\n", ascii); - fflush(error_log); - } - - log_mutex->unlock(); -} \ No newline at end of file diff --git a/loginserver/error_log.h b/loginserver/error_log.h deleted file mode 100644 index ad54e12b7..000000000 --- a/loginserver/error_log.h +++ /dev/null @@ -1,79 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2010 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 EQEMU_ERROR_LOG_H -#define EQEMU_ERROR_LOG_H - -#include -#include -#include -#include - -#include "../common/mutex.h" - -/** - * Dictates the log type specified in ErrorLog for Log(...) - */ -enum eqLogType -{ - log_debug, - log_error, - log_database, - log_network, - log_network_trace, - log_network_error, - log_world, - log_world_error, - log_client, - log_client_error, - _log_largest_type -}; - -/** - * Basic error logging class. - * Thread safe logging class that records time and date to both a file and to console(if exists). - */ -class ErrorLog -{ -public: - /** - * Constructor: opens the log file for writing and creates our mutex for writing to the log. - */ - ErrorLog(const char* file_name); - - /** - * Closes the file and destroys the mutex. - */ - ~ErrorLog(); - - /** - * Writes to the log system a variable message. - */ - void Log(eqLogType type, const char *message, ...); - - /** - * Writes to the log system a packet. - */ - void LogPacket(eqLogType type, const char *data, size_t size); - -protected: - Mutex *log_mutex; - FILE* error_log; -}; - -#endif - From 7a17089b8a0ce640c4ad398d3177954927245f38 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 20:47:59 -0600 Subject: [PATCH 432/846] Fix remaining loginserver log things --- loginserver/database_mysql.cpp | 32 ++++++++++++++--------------- loginserver/database_postgresql.cpp | 14 ++++++------- loginserver/login_server.h | 1 - loginserver/main.cpp | 19 ----------------- loginserver/server_manager.cpp | 1 - 5 files changed, 23 insertions(+), 44 deletions(-) diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index 292cf753e..9d1d8b57b 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -20,10 +20,10 @@ #ifdef EQEMU_MYSQL_ENABLED #include "database_mysql.h" -#include "error_log.h" #include "login_server.h" +#include "../common/eqemu_logsys.h" -extern ErrorLog *server_log; +extern EQEmuLogSys Log; extern LoginServer server; DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, string name) @@ -41,13 +41,13 @@ DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, if(!mysql_real_connect(database, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0)) { mysql_close(database); - server_log->Log(log_database, "Failed to connect to MySQL database. Error: %s", mysql_error(database)); + Log.Out(Logs::General, Logs::Error, "Failed to connect to MySQL database. Error: %s", mysql_error(database)); exit(1); } } else { - server_log->Log(log_database, "Failed to create db object in MySQL database."); + Log.Out(Logs::General, Logs::Error, "Failed to create db object in MySQL database."); } } @@ -75,7 +75,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u if (mysql_query(database, query.str().c_str()) != 0) { - server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); return false; } @@ -92,7 +92,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u } } - server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str()); return false; } @@ -120,7 +120,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un if (mysql_query(database, query.str().c_str()) != 0) { - server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); return false; } @@ -145,7 +145,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un if (mysql_query(database, query.str().c_str()) != 0) { - server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); return false; } @@ -161,14 +161,14 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un } } - server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str()); return false; } return true; } } - server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str()); return false; } @@ -187,7 +187,7 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address) if (mysql_query(database, query.str().c_str()) != 0) { - server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); } } @@ -206,7 +206,7 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas if (mysql_query(database, query.str().c_str()) != 0) { - server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); } } @@ -231,7 +231,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s if (mysql_query(database, query.str().c_str()) != 0) { - server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); } } @@ -256,7 +256,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, if (mysql_query(database, query.str().c_str()) != 0) { - server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); return false; } @@ -275,13 +275,13 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, if (mysql_query(database, query.str().c_str()) != 0) { - server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str()); + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); return false; } return true; } } - server_log->Log(log_database, "World registration did not exist in the database for %s %s", long_name.c_str(), short_name.c_str()); + Log.Out(Logs::General, Logs::Error, "World registration did not exist in the database for %s %s", long_name.c_str(), short_name.c_str()); return false; } diff --git a/loginserver/database_postgresql.cpp b/loginserver/database_postgresql.cpp index 3dc20d3f3..fba9aa8ec 100644 --- a/loginserver/database_postgresql.cpp +++ b/loginserver/database_postgresql.cpp @@ -23,7 +23,7 @@ #include "error_log.h" #include "login_server.h" -extern ErrorLog *server_log; + extern LoginServer server; #pragma comment(lib, "libpq.lib") @@ -34,12 +34,12 @@ DatabasePostgreSQL::DatabasePostgreSQL(string user, string pass, string host, st db = PQsetdbLogin(host.c_str(), port.c_str(), nullptr, nullptr, name.c_str(), user.c_str(), pass.c_str()); if(!db) { - server_log->Log(log_database, "Failed to connect to PostgreSQL Database."); + Log.Out(Logs::General, Logs::Error, "Failed to connect to PostgreSQL Database."); } if(PQstatus(db) != CONNECTION_OK) { - server_log->Log(log_database, "Failed to connect to PostgreSQL Database."); + Log.Out(Logs::General, Logs::Error, "Failed to connect to PostgreSQL Database."); PQfinish(db); db = nullptr; } @@ -83,7 +83,7 @@ bool DatabasePostgreSQL::GetLoginDataFromAccountName(string name, string &passwo char *error = PQresultErrorMessage(res); if(strlen(error) > 0) { - server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error); + Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error); PQclear(res); return false; } @@ -135,7 +135,7 @@ bool DatabasePostgreSQL::GetWorldRegistration(string long_name, string short_nam char *error = PQresultErrorMessage(res); if(strlen(error) > 0) { - server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetWorldRegistration(): %s", error); + Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetWorldRegistration(): %s", error); PQclear(res); return false; } @@ -188,7 +188,7 @@ void DatabasePostgreSQL::UpdateLSAccountData(unsigned int id, string ip_address) char *error = PQresultErrorMessage(res); if(strlen(error) > 0) { - server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error); + Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error); } PQclear(res); } @@ -225,7 +225,7 @@ void DatabasePostgreSQL::UpdateWorldRegistration(unsigned int id, string long_na char *error = PQresultErrorMessage(res); if(strlen(error) > 0) { - server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error); + Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error); } PQclear(res); } diff --git a/loginserver/login_server.h b/loginserver/login_server.h index bae3079b7..1f0743a46 100644 --- a/loginserver/login_server.h +++ b/loginserver/login_server.h @@ -18,7 +18,6 @@ #ifndef EQEMU_LOGINSERVER_H #define EQEMU_LOGINSERVER_H -#include "error_log.h" #include "config.h" #include "database.h" #include "database_mysql.h" diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 7d3abd87c..b5cf00102 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -32,7 +32,6 @@ TimeoutManager timeout_manager; LoginServer server; EQEmuLogSys Log; -ErrorLog *server_log; bool run_server = true; void CatchSignal(int sig_num) @@ -45,15 +44,6 @@ int main() set_exception_handler(); Log.LoadLogSettingsDefaults(); - /* Start Loginserver log */ - time_t current_time = time(nullptr); - std::stringstream log_name(std::stringstream::in | std::stringstream::out); -#ifdef WIN32 - log_name << ".\\logs\\login_" << (unsigned int)current_time << ".log"; -#else - log_name << "./logs/login_" << (unsigned int)current_time << ".log"; -#endif - server_log = new ErrorLog(log_name.str().c_str()); Log.Out(Logs::General, Logs::Login_Server, "Logging System Init."); /* Parse out login.ini */ @@ -133,7 +123,6 @@ int main() Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); - delete server_log; return 1; } @@ -151,8 +140,6 @@ int main() delete server.db; Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); - delete server_log; return 1; } #endif @@ -173,8 +160,6 @@ int main() delete server.db; Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); - delete server_log; return 1; } @@ -196,8 +181,6 @@ int main() delete server.db; Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); - delete server_log; return 1; } @@ -232,8 +215,6 @@ int main() delete server.db; Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown."); delete server.config; - Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown."); - delete server_log; return 0; } diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index f63e72b4e..87e269854 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -17,7 +17,6 @@ */ #include "server_manager.h" #include "login_server.h" -#include "error_log.h" #include "login_structures.h" #include From d7ca2440d340cc914d2509818610856cdfa4d651 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 22:24:17 -0600 Subject: [PATCH 433/846] More loginserver stuff [skip ci] --- loginserver/client.cpp | 68 +++++++++++++++++----------------- loginserver/login_structures.h | 4 +- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/loginserver/client.cpp b/loginserver/client.cpp index a6cea46bf..66a62efe7 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -255,50 +255,49 @@ void Client::Handle_Login(const char* data, unsigned int size) EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80); const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data; - LoginLoginAccepted_Struct* llas = (LoginLoginAccepted_Struct *)outapp->pBuffer; - llas->unknown1 = llrs->unknown1; - llas->unknown2 = llrs->unknown2; - llas->unknown3 = llrs->unknown3; - llas->unknown4 = llrs->unknown4; - llas->unknown5 = llrs->unknown5; + LoginAccepted_Struct* login_accepted = (LoginAccepted_Struct *)outapp->pBuffer; + login_accepted->unknown1 = llrs->unknown1; + login_accepted->unknown2 = llrs->unknown2; + login_accepted->unknown3 = llrs->unknown3; + login_accepted->unknown4 = llrs->unknown4; + login_accepted->unknown5 = llrs->unknown5; - Login_ReplyBlock_Struct * lrbs = new Login_ReplyBlock_Struct; - memset(lrbs, 0, sizeof(Login_ReplyBlock_Struct)); + LoginFailedAttempts_Struct * login_failed_attempts = new LoginFailedAttempts_Struct; + memset(login_failed_attempts, 0, sizeof(LoginFailedAttempts_Struct)); - lrbs->failed_attempts = 0; - lrbs->message = 0x01; - lrbs->lsid = d_account_id; - lrbs->unknown3[3] = 0x03; - lrbs->unknown4[3] = 0x02; - lrbs->unknown5[0] = 0xe7; - lrbs->unknown5[1] = 0x03; - lrbs->unknown6[0] = 0xff; - lrbs->unknown6[1] = 0xff; - lrbs->unknown6[2] = 0xff; - lrbs->unknown6[3] = 0xff; - lrbs->unknown7[0] = 0xa0; - lrbs->unknown7[1] = 0x05; - lrbs->unknown8[3] = 0x02; - lrbs->unknown9[0] = 0xff; - lrbs->unknown9[1] = 0x03; - lrbs->unknown11[0] = 0x63; - lrbs->unknown12[0] = 0x01; - memcpy(lrbs->key, key.c_str(), key.size()); + login_failed_attempts->failed_attempts = 0; + login_failed_attempts->message = 0x01; + login_failed_attempts->lsid = d_account_id; + login_failed_attempts->unknown3[3] = 0x03; + login_failed_attempts->unknown4[3] = 0x02; + login_failed_attempts->unknown5[0] = 0xe7; + login_failed_attempts->unknown5[1] = 0x03; + login_failed_attempts->unknown6[0] = 0xff; + login_failed_attempts->unknown6[1] = 0xff; + login_failed_attempts->unknown6[2] = 0xff; + login_failed_attempts->unknown6[3] = 0xff; + login_failed_attempts->unknown7[0] = 0xa0; + login_failed_attempts->unknown7[1] = 0x05; + login_failed_attempts->unknown8[3] = 0x02; + login_failed_attempts->unknown9[0] = 0xff; + login_failed_attempts->unknown9[1] = 0x03; + login_failed_attempts->unknown11[0] = 0x63; + login_failed_attempts->unknown12[0] = 0x01; + memcpy(login_failed_attempts->key, key.c_str(), key.size()); #ifdef WIN32 unsigned int e_size; - char *encrypted_buffer = server.eq_crypto->Encrypt((const char*)lrbs, 75, e_size); - memcpy(llas->encrypt, encrypted_buffer, 80); + char *encrypted_buffer = server.eq_crypto->Encrypt((const char*)login_failed_attempts, 75, e_size); + memcpy(login_accepted->encrypt, encrypted_buffer, 80); server.eq_crypto->DeleteHeap(encrypted_buffer); #else unsigned int e_size; - char *encrypted_buffer = Encrypt((const char*)lrbs, 75, e_size); - memcpy(llas->encrypt, encrypted_buffer, 80); + char *encrypted_buffer = Encrypt((const char*)login_failed_attempts, 75, e_size); + memcpy(login_accepted->encrypt, encrypted_buffer, 80); _HeapDeleteCharBuffer(encrypted_buffer); #endif - if(server.options.IsDumpOutPacketsOn()) - { + if(server.options.IsDumpOutPacketsOn()) { DumpPacket(outapp); } @@ -317,8 +316,7 @@ void Client::Handle_Login(const char* data, unsigned int size) llas->unknown5 = llrs->unknown5; memcpy(llas->unknown6, FailedLoginResponseData, sizeof(FailedLoginResponseData)); - if(server.options.IsDumpOutPacketsOn()) - { + if(server.options.IsDumpOutPacketsOn()) { DumpPacket(outapp); } diff --git a/loginserver/login_structures.h b/loginserver/login_structures.h index 60d10a653..f9d3cc054 100644 --- a/loginserver/login_structures.h +++ b/loginserver/login_structures.h @@ -38,7 +38,7 @@ struct LoginLoginRequest_Struct { char unknown6[16]; }; -struct LoginLoginAccepted_Struct { +struct LoginAccepted_Struct { short unknown1; short unknown2; short unknown3; @@ -47,7 +47,7 @@ struct LoginLoginAccepted_Struct { char encrypt[80]; }; -struct Login_ReplyBlock_Struct +struct LoginFailedReply_Struct { char message; //0x01 char unknown2[7]; //0x00 From ffe46bd4d2de3046eeb8fa6948cda63964358e11 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 23:01:07 -0600 Subject: [PATCH 434/846] Implement Loginserver auto account creation via login.ini option auto_create_accounts = TRUE --- loginserver/client.cpp | 101 ++++++++++++++++++--------------- loginserver/database.h | 2 + loginserver/database_mysql.cpp | 27 +++++++++ loginserver/database_mysql.h | 2 + loginserver/login_structures.h | 2 +- 5 files changed, 86 insertions(+), 48 deletions(-) diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 66a62efe7..9a6a81593 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -175,83 +175,91 @@ void Client::Handle_SessionReady(const char* data, unsigned int size) void Client::Handle_Login(const char* data, unsigned int size) { - if(status != cs_waiting_for_login) - { + if(status != cs_waiting_for_login) { Log.Out(Logs::General, Logs::Error, "Login received after already having logged in."); return; } - if((size - 12) % 8 != 0) - { + if((size - 12) % 8 != 0) { Log.Out(Logs::General, Logs::Error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size); return; } status = cs_logged_in; - string e_user; - string e_hash; - char *e_buffer = nullptr; - unsigned int d_account_id = 0; - string d_pass_hash; + string entered_username; + string entered_password_hash_result; + + char *login_packet_buffer = nullptr; + + unsigned int db_account_id = 0; + string db_account_password_hash; #ifdef WIN32 - e_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); + login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); - int buffer_len = strlen(e_buffer); - e_hash.assign(e_buffer, buffer_len); - e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1)); + int login_packet_buffer_length = strlen(login_packet_buffer); + entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length); + entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1)); - if(server.options.IsTraceOn()) - { - Log.Out(Logs::General, Logs::Debug, "User: %s", e_user.c_str()); - Log.Out(Logs::General, Logs::Debug, "Hash: %s", e_hash.c_str()); + if(server.options.IsTraceOn()) { + Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str()); + Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str()); } - server.eq_crypto->DeleteHeap(e_buffer); + server.eq_crypto->DeleteHeap(login_packet_buffer); #else - e_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); + login_packet_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); - int buffer_len = strlen(e_buffer); - e_hash.assign(e_buffer, buffer_len); - e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1)); + int login_packet_buffer_length = strlen(login_packet_buffer); + entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length); + entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1)); - if(server.options.IsTraceOn()) - { - Log.Out(Logs::General, Logs::Debug, "User: %s", e_user.c_str()); - Log.Out(Logs::General, Logs::Debug, "Hash: %s", e_hash.c_str()); + if(server.options.IsTraceOn()) { + Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str()); + Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str()); } - _HeapDeleteCharBuffer(e_buffer); + _HeapDeleteCharBuffer(login_packet_buffer); #endif bool result; - if(server.db->GetLoginDataFromAccountName(e_user, d_pass_hash, d_account_id) == false) - { - Log.Out(Logs::General, Logs::Error, "Error logging in, user %s does not exist in the database.", e_user.c_str()); - result = false; - } - else - { - if(d_pass_hash.compare(e_hash) == 0) - { + if(server.db->GetLoginDataFromAccountName(entered_username, db_account_password_hash, db_account_id) == false) { + /* If we have auto_create_accounts enabled in the login.ini, we will process the creation of an account on our own*/ + if ( + server.config->GetVariable("options", "auto_create_accounts").compare("TRUE") == 0 && + server.db->CreateLoginData(entered_username, entered_password_hash_result, db_account_id) == true + ){ + Log.Out(Logs::General, Logs::Error, "User %s does not exist in the database, so we created it...", entered_username.c_str()); result = true; } - else - { + else{ + Log.Out(Logs::General, Logs::Error, "Error logging in, user %s does not exist in the database.", entered_username.c_str()); + result = false; + } + } + else { + if(db_account_password_hash.compare(entered_password_hash_result) == 0) { + result = true; + } + else { result = false; } } - if(result) - { - server.client_manager->RemoveExistingClient(d_account_id); + /* Login Accepted */ + if(result) { + + server.client_manager->RemoveExistingClient(db_account_id); + in_addr in; in.s_addr = connection->GetRemoteIP(); - server.db->UpdateLSAccountData(d_account_id, string(inet_ntoa(in))); + + server.db->UpdateLSAccountData(db_account_id, string(inet_ntoa(in))); GenerateKey(); - account_id = d_account_id; - account_name = e_user; + + account_id = db_account_id; + account_name = entered_username; EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80); const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data; @@ -267,7 +275,7 @@ void Client::Handle_Login(const char* data, unsigned int size) login_failed_attempts->failed_attempts = 0; login_failed_attempts->message = 0x01; - login_failed_attempts->lsid = d_account_id; + login_failed_attempts->lsid = db_account_id; login_failed_attempts->unknown3[3] = 0x03; login_failed_attempts->unknown4[3] = 0x02; login_failed_attempts->unknown5[0] = 0xe7; @@ -304,8 +312,7 @@ void Client::Handle_Login(const char* data, unsigned int size) connection->QueuePacket(outapp); delete outapp; } - else - { + else { EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, sizeof(LoginLoginFailed_Struct)); const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data; LoginLoginFailed_Struct* llas = (LoginLoginFailed_Struct *)outapp->pBuffer; diff --git a/loginserver/database.h b/loginserver/database.h index 7244f2e79..b7e9f9d24 100644 --- a/loginserver/database.h +++ b/loginserver/database.h @@ -44,6 +44,8 @@ public: */ virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id) { return false; } + virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id) { return false; } + /** * Retrieves the world registration from the long and short names provided. * Needed for world login procedure. diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index 9d1d8b57b..b9536de7e 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -96,6 +96,33 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u return false; } + +bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int &id) +{ + if (!database) { + return false; + } + + MYSQL_RES *result; + MYSQL_ROW row; + stringstream query(stringstream::in | stringstream::out); + + query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) "; + query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); "; + + if (mysql_query(database, query.str().c_str()) != 0) { + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); + return false; + } + else{ + id = mysql_insert_id(database); + return true; + } + + Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str()); + return false; +} + bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id, unsigned int &trusted, string &list_desc, string &account, string &password) { diff --git a/loginserver/database_mysql.h b/loginserver/database_mysql.h index 165d787c7..5cadff34a 100644 --- a/loginserver/database_mysql.h +++ b/loginserver/database_mysql.h @@ -59,6 +59,8 @@ public: */ virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id); + virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id); + /** * Retrieves the world registration from the long and short names provided. * Needed for world login procedure. diff --git a/loginserver/login_structures.h b/loginserver/login_structures.h index f9d3cc054..6e3f290e9 100644 --- a/loginserver/login_structures.h +++ b/loginserver/login_structures.h @@ -47,7 +47,7 @@ struct LoginAccepted_Struct { char encrypt[80]; }; -struct LoginFailedReply_Struct +struct LoginFailedAttempts_Struct { char message; //0x01 char unknown2[7]; //0x00 From c2af87431adc91396337a6fe164f715a6f32c67c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 23:21:19 -0600 Subject: [PATCH 435/846] Fixed a ridiculous issue where world wasn't trying to reconnect to loginservers --- world/net.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/world/net.cpp b/world/net.cpp index 73489243f..6d8017de1 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -481,19 +481,16 @@ int main(int argc, char** argv) { if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); - // AsyncLoadVariables(dbasync, &database); - ReconnectCounter++; - if (ReconnectCounter >= 12) { // only create thread to reconnect every 10 minutes. previously we were creating a new thread every 10 seconds - ReconnectCounter = 0; - if (loginserverlist.AllConnected() == false) { + + if (loginserverlist.AllConnected() == false) { #ifdef _WINDOWS - _beginthread(AutoInitLoginServer, 0, nullptr); + _beginthread(AutoInitLoginServer, 0, nullptr); #else - pthread_t thread; - pthread_create(&thread, nullptr, &AutoInitLoginServer, nullptr); + pthread_t thread; + pthread_create(&thread, nullptr, &AutoInitLoginServer, nullptr); #endif - } } + } if (numclients == 0) { Sleep(50); From 80ef4c7f9f0091e1a85f468b3d2d263dd5df8445 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 9 Dec 2015 23:24:53 -0600 Subject: [PATCH 436/846] Adjust default Loginserver log settings [skip ci] --- loginserver/main.cpp | 2 ++ world/net.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/loginserver/main.cpp b/loginserver/main.cpp index b5cf00102..55d745b92 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -44,6 +44,8 @@ int main() set_exception_handler(); Log.LoadLogSettingsDefaults(); + Log.log_settings[Logs::Error].log_to_console = Logs::General; + Log.Out(Logs::General, Logs::Login_Server, "Logging System Init."); /* Parse out login.ini */ diff --git a/world/net.cpp b/world/net.cpp index 6d8017de1..d7669ce12 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -114,6 +114,9 @@ void CatchSignal(int sig_num); int main(int argc, char** argv) { RegisterExecutablePlatform(ExePlatformWorld); Log.LoadLogSettingsDefaults(); + + + set_exception_handler(); /* Database Version Check */ From 6802f2a9e891e058e690bddf88863951d2d5ff01 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 11 Dec 2015 22:39:18 -0500 Subject: [PATCH 437/846] Conversion of 2015_09_30_bots.sql fail points to perl script; Added drop bots feature to eqemu_update.pl menu --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 218 ++++- utils/sql/git/bots/drop_bots.sql | 77 +- .../sql/git/bots/required/2015_09_30_bots.sql | 833 ++++-------------- 4 files changed, 431 insertions(+), 699 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index fc5877e05..fa7c57a12 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -493,7 +493,7 @@ bool Database::CheckDatabaseConversions() { /* 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 12"); + system("perl eqemu_update.pl V 13"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index b6c4ab1d0..8fd3af540 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -23,7 +23,7 @@ if($Config{osname}=~/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 = 12; +$current_version = 13; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -251,6 +251,7 @@ sub show_menu_prompt { 11 => \&fetch_latest_windows_binaries, 12 => \&fetch_server_dlls, 13 => \&do_windows_login_server_setup, + 19 => \&do_bots_db_schema_drop, 20 => \&do_update_self, 0 => \&script_exit, ); @@ -327,6 +328,7 @@ return < Date: Sat, 12 Dec 2015 00:37:31 -0600 Subject: [PATCH 438/846] Some rule code cleanup --- common/rulesys.cpp | 297 +++++++++++++++++++-------------------------- 1 file changed, 127 insertions(+), 170 deletions(-) diff --git a/common/rulesys.cpp b/common/rulesys.cpp index a53dbcabe..13e342fe5 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -17,43 +17,14 @@ */ #include "rulesys.h" - #include "database.h" #include "string_util.h" #include #include /* - - FatherNitwit: Added new rules subsystem to allow game rules to be changed - at runtime. more about this will come as time goes on. -FatherNitwit: Added #rules command to manage rules data from in game. -FatherNitwit: Renamed old #rules to #serverrules -FatherNitwit: Moved max level into the rules system (Character:MaxLevel) -Requred SQL: - - - -CREATE TABLE rule_sets ( - ruleset_id TINYINT UNSIGNED NOT NULL auto_increment, - name VARCHAR(255) NOT NULL, - PRIMARY KEY(ruleset_id) -); -INSERT INTO rule_sets VALUES(0, "default"); -UPDATE rule_sets SET ruleset_id=0; - -CREATE TABLE rule_values ( - ruleset_id TINYINT UNSIGNED NOT NULL, - rule_name VARCHAR(64) NOT NULL, - rule_value VARCHAR(10) NOT NULL, - INDEX(ruleset_id), - PRIMARY KEY(ruleset_id,rule_name) -); - - - -Commands: -#rules: + Commands: + #rules: current -> lists current set name switch (set name) -> change set in the DB, but dont reload load (set name) -> load set into this zone without changing the world @@ -94,28 +65,28 @@ RuleManager::RuleManager() } RuleManager::CategoryType RuleManager::FindCategory(const char *catname) { - int r; - for(r = 0; r < _CatCount; r++) { - if(strcasecmp(catname, s_categoryNames[r]) == 0) - return((CategoryType) r); + int i; + for (i = 0; i < _CatCount; i++) { + if (strcasecmp(catname, s_categoryNames[i]) == 0) + return((CategoryType)i); } return(InvalidCategory); } bool RuleManager::ListRules(const char *catname, std::vector &into) { CategoryType cat = InvalidCategory; - if(catname != nullptr) { + if (catname != nullptr) { cat = FindCategory(catname); - if(cat == InvalidCategory) { + if (cat == InvalidCategory) { Log.Out(Logs::Detail, Logs::Rules, "Unable to find category '%s'", catname); return(false); } } - int r; - int rcount = CountRules(); - for(r = 0; r < rcount; r++) { - const RuleInfo &rule = s_RuleInfo[r]; - if(catname == nullptr || cat == rule.category) { + int i; + int rule_count = CountRules(); + for (i = 0; i < rule_count; i++) { + const RuleInfo &rule = s_RuleInfo[i]; + if (catname == nullptr || cat == rule.category) { into.push_back(rule.name); } } @@ -123,15 +94,14 @@ bool RuleManager::ListRules(const char *catname, std::vector &into } bool RuleManager::ListCategories(std::vector &into) { - int r; - for(r = 0; r < _CatCount; r++) { - into.push_back(s_categoryNames[r]); + int i; + for (i = 0; i < _CatCount; i++) { + into.push_back(s_categoryNames[i]); } return(true); } - -bool RuleManager::GetRule(const char *rule_name, std::string &ret_val) { +bool RuleManager::GetRule(const char *rule_name, std::string &return_value) { RuleType type; uint16 index; if (!_FindRule(rule_name, type, index)) @@ -151,12 +121,12 @@ bool RuleManager::GetRule(const char *rule_name, std::string &ret_val) { break; } - ret_val = tmp; + return_value = tmp; return true; } -bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *db, bool db_save) { +bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save) { if(rule_name == nullptr || rule_value == nullptr) return(false); @@ -166,25 +136,26 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas return(false); switch(type) { - case IntRule: - m_RuleIntValues [index] = atoi(rule_value); - Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]); - break; - case RealRule: - m_RuleRealValues[index] = atof(rule_value); - Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]); - break; - case BoolRule: - uint32 val = 0; - if(!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1")) - val = 1; - m_RuleBoolValues[index] = val; - Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ?"true":"false"); - break; + case IntRule: + m_RuleIntValues[index] = atoi(rule_value); + Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]); + break; + case RealRule: + m_RuleRealValues[index] = atof(rule_value); + Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]); + break; + case BoolRule: + uint32 val = 0; + if (!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1")) + val = 1; + + m_RuleBoolValues[index] = val; + Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false"); + break; } if(db_save) - _SaveRule(db, type, index); + _SaveRule(database, type, index); return(true); } @@ -201,14 +172,14 @@ void RuleManager::ResetRules() { } bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into) { - if(rule_name == nullptr) + if (rule_name == nullptr) return(false); - int r; - int rcount = CountRules(); - for(r = 0; r < rcount; r++) { - const RuleInfo &rule = s_RuleInfo[r]; - if(strcmp(rule_name, rule.name) == 0) { + int i; + int rule_count = CountRules(); + for (i = 0; i < rule_count; i++) { + const RuleInfo &rule = s_RuleInfo[i]; + if (strcmp(rule_name, rule.name) == 0) { type_into = rule.type; index_into = rule.rule_index; return(true); @@ -220,191 +191,177 @@ bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 & //assumes index is valid! const char *RuleManager::_GetRuleName(RuleType type, uint16 index) { - switch(type) { - case IntRule: - return(s_RuleInfo[index].name); - case RealRule: - return(s_RuleInfo[index+_IntRuleCount].name); - case BoolRule: - return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name); + switch (type) { + case IntRule: + return(s_RuleInfo[index].name); + case RealRule: + return(s_RuleInfo[index + _IntRuleCount].name); + case BoolRule: + return(s_RuleInfo[index + _IntRuleCount + _RealRuleCount].name); } //should never happen return("InvalidRule??"); } -void RuleManager::SaveRules(Database *db, const char *ruleset) { +void RuleManager::SaveRules(Database *database, const char *ruleset_name) { - if(ruleset != nullptr) { + if (ruleset_name != nullptr) { //saving to a specific name - if(m_activeName != ruleset) { + if (m_activeName != ruleset_name) { //a new name... - m_activeRuleset = _FindOrCreateRuleset(db, ruleset); - if(m_activeRuleset == -1) { - Log.Out(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset); + m_activeRuleset = _FindOrCreateRuleset(database, ruleset_name); + if (m_activeRuleset == -1) { + Log.Out(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset_name); return; } - m_activeName = ruleset; + m_activeName = ruleset_name; } - Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset, m_activeRuleset); - } else { + Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset_name, m_activeRuleset); + } + else { Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into running rule set %s", m_activeName.c_str(), m_activeRuleset); } - int r; - for(r = 0; r < _IntRuleCount; r++) { - _SaveRule(db, IntRule, r); + int i; + for (i = 0; i < _IntRuleCount; i++) { + _SaveRule(database, IntRule, i); } - for(r = 0; r < _RealRuleCount; r++) { - _SaveRule(db, RealRule, r); + for (i = 0; i < _RealRuleCount; i++) { + _SaveRule(database, RealRule, i); } - for(r = 0; r < _BoolRuleCount; r++) { - _SaveRule(db, BoolRule, r); + for (i = 0; i < _BoolRuleCount; i++) { + _SaveRule(database, BoolRule, i); } } +bool RuleManager::LoadRules(Database *database, const char *ruleset_name) { - -bool RuleManager::LoadRules(Database *db, const char *ruleset) { - - int rsid = GetRulesetID(db, ruleset); - if(rsid < 0) { - Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset); + int ruleset_id = GetRulesetID(database, ruleset_name); + if (ruleset_id < 0) { + Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name); return(false); } - Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset, rsid); + Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset_name, ruleset_id); - m_activeRuleset = rsid; - m_activeName = ruleset; + m_activeRuleset = ruleset_id; + m_activeName = ruleset_name; - std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", rsid); - auto results = db->QueryDatabase(query); + std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id); + auto results = database->QueryDatabase(query); if (!results.Success()) - { return false; - } - for(auto row = results.begin(); row != results.end(); ++row) - if(!SetRule(row[0], row[1], nullptr, false)) - Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]); + for (auto row = results.begin(); row != results.end(); ++row) + if (!SetRule(row[0], row[1], nullptr, false)) + Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]); return true; } -void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) { - char vstr[100]; +void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) { + char value_string[100]; switch(type) { - case IntRule: - sprintf(vstr, "%d", m_RuleIntValues[index]); - break; - case RealRule: - sprintf(vstr, "%.13f", m_RuleRealValues[index]); - break; - case BoolRule: - sprintf(vstr, "%s", m_RuleBoolValues[index]?"true":"false"); - break; + case IntRule: + sprintf(value_string, "%d", m_RuleIntValues[index]); + break; + case RealRule: + sprintf(value_string, "%.13f", m_RuleRealValues[index]); + break; + case BoolRule: + sprintf(value_string, "%s", m_RuleBoolValues[index]?"true":"false"); + break; } std::string query = StringFormat("REPLACE INTO rule_values " "(ruleset_id, rule_name, rule_value) " " VALUES(%d, '%s', '%s')", - m_activeRuleset, _GetRuleName(type, index), vstr); - auto results = db->QueryDatabase(query); + m_activeRuleset, _GetRuleName(type, index), value_string); + auto results = database->QueryDatabase(query); } -int RuleManager::GetRulesetID(Database *db, const char *rulesetname) { +int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) { - uint32 len = strlen(rulesetname); - char* rst = new char[2*len+1]; - db->DoEscapeString(rst, rulesetname, len); + uint32 len = strlen(ruleset_name); + char* 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); - safe_delete_array(rst); - auto results = db->QueryDatabase(query); - if (!results.Success()) { - return -1; - } + std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst); + safe_delete_array(rst); + auto results = database->QueryDatabase(query); + if (!results.Success()) + return -1; - if (results.RowCount() == 0) - return -1; + if (results.RowCount() == 0) + return -1; - auto row = results.begin(); + auto row = results.begin(); return atoi(row[0]); } -int RuleManager::_FindOrCreateRuleset(Database *db, const char *ruleset) { +int RuleManager::_FindOrCreateRuleset(Database *database, const char *in_ruleset_name) { - int res = GetRulesetID(db, ruleset); - if(res >= 0) - return res; //found and existing one... + int ruleset_id = GetRulesetID(database, in_ruleset_name); + if (ruleset_id >= 0) + return ruleset_id; //found and existing one... - uint32 len = strlen(ruleset); - char* rst = new char[2*len+1]; - db->DoEscapeString(rst, ruleset, len); + uint32 len = strlen(in_ruleset_name); + char* 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')", rst); - safe_delete_array(rst); - auto results = db->QueryDatabase(query); + std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", ruleset_name); + safe_delete_array(ruleset_name); + auto results = database->QueryDatabase(query); if (!results.Success()) - { return -1; - } - return results.LastInsertedID(); + return results.LastInsertedID(); } -std::string RuleManager::GetRulesetName(Database *db, int id) { - - std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", id); - auto results = db->QueryDatabase(query); +std::string RuleManager::GetRulesetName(Database *database, int ruleset_id) { + std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", ruleset_id); + auto results = database->QueryDatabase(query); if (!results.Success()) - { - return ""; - } + return ""; if (results.RowCount() == 0) - return ""; + return ""; - auto row = results.begin(); + auto row = results.begin(); return row[0]; } -bool RuleManager::ListRulesets(Database *db, std::map &into) { +bool RuleManager::ListRulesets(Database *database, std::map &into) { //start out with the default set which is always present. into[0] = "default"; - std::string query = "SELECT ruleset_id, name FROM rule_sets"; - auto results = db->QueryDatabase(query); + std::string query = "SELECT ruleset_id, name FROM rule_sets"; + auto results = database->QueryDatabase(query); if (results.Success()) - { return false; - } for (auto row = results.begin(); row != results.end(); ++row) - into[ atoi(row[0]) ] = row[1]; + into[atoi(row[0])] = row[1]; return true; } -int32 RuleManager::GetIntRule(RuleManager::IntType t) const -{ +int32 RuleManager::GetIntRule(RuleManager::IntType t) const{ return(m_RuleIntValues[t]); } -float RuleManager::GetRealRule(RuleManager::RealType t) const -{ +float RuleManager::GetRealRule(RuleManager::RealType t) const{ return(m_RuleRealValues[t]); } -bool RuleManager::GetBoolRule(RuleManager::BoolType t) const -{ +bool RuleManager::GetBoolRule(RuleManager::BoolType t) const{ return (m_RuleBoolValues[t] == 1); } From cfde67fcb3202fb25c2e6abaa4a628997c9b4d18 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 12 Dec 2015 17:22:29 -0500 Subject: [PATCH 439/846] Missed a 'command' note --- zone/command.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index 8cea3ae32..33c93a49c 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -23,12 +23,12 @@ 1. At the bottom of command.h you must add a prototype for it. 2. Add the function in this file. 3. In the command_init function you must add a call to command_add - for your function. If you want an alias for your command, add - a second call to command_add with the description and access args - set to nullptr and 0 respectively since they aren't used when adding - an alias. The function pointers being equal is makes it an alias. - The access level you set with command_add is only a default if - the command isn't listed in the commands db table. + for your function. + + Note: If you want an alias for your command, add an entry to the + `command_settings` table in your database. The access level you + set with command_add is the default setting if the command isn't + listed in the commands db table. */ From ee644f7b3ed927ba47ee611d7ecb968c49862cc6 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 12 Dec 2015 21:36:14 -0500 Subject: [PATCH 440/846] Make better sense things do, after cups of coffee two --- zone/command.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index 33c93a49c..3ec0328ee 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -25,10 +25,10 @@ 3. In the command_init function you must add a call to command_add for your function. - Note: If you want an alias for your command, add an entry to the + Notes: If you want an alias for your command, add an entry to the `command_settings` table in your database. The access level you set with command_add is the default setting if the command isn't - listed in the commands db table. + listed in the `command_settings` db table. */ From baaf5801ff1406cf17e81f3ae91b462cfef7e819 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 14 Dec 2015 01:18:19 -0800 Subject: [PATCH 441/846] Added ability to manipulate disciplines for perl and lua. Also ability to remove spells from spell bar with spellID. --- zone/client.h | 3 ++ zone/effects.cpp | 27 +++++++++++++++ zone/lua_client.cpp | 18 ++++++++++ zone/lua_client.h | 3 ++ zone/perl_client.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++ zone/spells.cpp | 10 ++++++ 6 files changed, 139 insertions(+) diff --git a/zone/client.h b/zone/client.h index e31f68b26..b5d3728e1 100644 --- a/zone/client.h +++ b/zone/client.h @@ -712,6 +712,7 @@ public: // use this one instead void MemSpell(uint16 spell_id, int slot, bool update_client = true); void UnmemSpell(int slot, bool update_client = true); + void UnmemSpellBySpellID(int32 spell_id); void UnmemSpellAll(bool update_client = true); void ScribeSpell(uint16 spell_id, int slot, bool update_client = true); void UnscribeSpell(int slot, bool update_client = true); @@ -925,6 +926,8 @@ public: void ResetTrade(); void DropInst(const ItemInst* inst); bool TrainDiscipline(uint32 itemid); + void TrainDiscBySpellID(int32 spell_id); + int GetDiscSlotBySpellID(int32 spellid); void SendDisciplineUpdate(); void SendDisciplineTimer(uint32 timer_id, uint32 duration); bool UseDiscipline(uint32 spell_id, uint32 target); diff --git a/zone/effects.cpp b/zone/effects.cpp index dc069fb2a..dc3392403 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -571,6 +571,33 @@ bool Client::TrainDiscipline(uint32 itemid) { return(false); } +void Client::TrainDiscBySpellID(int32 spell_id) +{ + int i; + for(i = 0; i < MAX_PP_DISCIPLINES; i++) { + if(m_pp.disciplines.values[i] == 0) { + m_pp.disciplines.values[i] = spell_id; + database.SaveCharacterDisc(this->CharacterID(), i, spell_id); + SendDisciplineUpdate(); + Message(15, "You have learned a new combat ability!"); + return; + } + } +} + +int Client::GetDiscSlotBySpellID(int32 spellid) +{ + int i; + + for(i = 0; i < MAX_PP_DISCIPLINES; i++) + { + if(m_pp.disciplines.values[i] == spellid) + return i; + } + + return -1; +} + void Client::SendDisciplineUpdate() { EQApplicationPacket app(OP_DisciplineUpdate, sizeof(Disciplines_Struct)); Disciplines_Struct *d = (Disciplines_Struct*)app.pBuffer; diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index b7dad0ce3..1e785ce9b 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -530,6 +530,11 @@ void Lua_Client::UnmemSpell(int slot, bool update_client) { self->UnmemSpell(slot, update_client); } +void Lua_Client::UnmemSpellBySpellID(int32 spell_id) { + Lua_Safe_Call_Void(); + self->UnmemSpellBySpellID(spell_id); +} + void Lua_Client::UnmemSpellAll() { Lua_Safe_Call_Void(); self->UnmemSpellAll(); @@ -575,6 +580,16 @@ void Lua_Client::TrainDisc(int itemid) { self->TrainDiscipline(itemid); } +void Lua_Client::TrainDiscBySpellID(int32 spell_id) { + Lua_Safe_Call_Void(); + self->TrainDiscBySpellID(spell_id); +} + +int Lua_Client::GetDiscSlotBySpellID(int32 spell_id) { + Lua_Safe_Call_Int(); + return self->GetDiscSlotBySpellID(spell_id); +} + void Lua_Client::UntrainDisc(int slot) { Lua_Safe_Call_Void(); self->UntrainDisc(slot); @@ -1426,6 +1441,7 @@ luabind::scope lua_register_client() { .def("MemSpell", (void(Lua_Client::*)(int,int,bool))&Lua_Client::MemSpell) .def("UnmemSpell", (void(Lua_Client::*)(int))&Lua_Client::UnmemSpell) .def("UnmemSpell", (void(Lua_Client::*)(int,bool))&Lua_Client::UnmemSpell) + .def("UnmemSpellBySpellID", (void(Lua_Client::*)(int32))&Lua_Client::UnmemSpellBySpellID) .def("UnmemSpellAll", (void(Lua_Client::*)(void))&Lua_Client::UnmemSpellAll) .def("UnmemSpellAll", (void(Lua_Client::*)(bool))&Lua_Client::UnmemSpellAll) .def("ScribeSpell", (void(Lua_Client::*)(int,int))&Lua_Client::ScribeSpell) @@ -1435,6 +1451,8 @@ luabind::scope lua_register_client() { .def("UnscribeSpellAll", (void(Lua_Client::*)(void))&Lua_Client::UnscribeSpellAll) .def("UnscribeSpellAll", (void(Lua_Client::*)(bool))&Lua_Client::UnscribeSpellAll) .def("TrainDisc", (void(Lua_Client::*)(int))&Lua_Client::TrainDisc) + .def("TrainDiscBySpellID", (void(Lua_Client::*)(int32))&Lua_Client::TrainDiscBySpellID) + .def("GetDiscSlotBySpellID", (int(Lua_Client::*)(int32))&Lua_Client::GetDiscSlotBySpellID) .def("UntrainDisc", (void(Lua_Client::*)(int))&Lua_Client::UntrainDisc) .def("UntrainDisc", (void(Lua_Client::*)(int,bool))&Lua_Client::UntrainDisc) .def("UntrainDiscAll", (void(Lua_Client::*)(void))&Lua_Client::UntrainDiscAll) diff --git a/zone/lua_client.h b/zone/lua_client.h index e50a16b98..4584edfd0 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -131,6 +131,7 @@ public: void MemSpell(int spell_id, int slot, bool update_client); void UnmemSpell(int slot); void UnmemSpell(int slot, bool update_client); + void UnmemSpellBySpellID(int32 spell_id); void UnmemSpellAll(); void UnmemSpellAll(bool update_client); void ScribeSpell(int spell_id, int slot); @@ -140,6 +141,8 @@ public: void UnscribeSpellAll(); void UnscribeSpellAll(bool update_client); void TrainDisc(int itemid); + void TrainDiscBySpellID(int32 spell_id); + int GetDiscSlotBySpellID(int32 spell_id); void UntrainDisc(int slot); void UntrainDisc(int slot, bool update_client); void UntrainDiscAll(); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 3858eac0e..d4c5f34d0 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -2445,6 +2445,30 @@ XS(XS_Client_UnmemSpell) XSRETURN_EMPTY; } +XS(XS_Client_UnmemSpellBySpellID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_UnmemSpellBySpellID) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::UnmemSpellBySpellID(THIS, spell_id)"); + { + Client * THIS; + int32 spell_id = (int32)SvIV(ST(1)); + + 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."); + + THIS->UnmemSpellBySpellID(spell_id); + } + XSRETURN_EMPTY; +} + XS(XS_Client_UnmemSpellAll); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_UnmemSpellAll) { @@ -2568,6 +2592,57 @@ XS(XS_Client_UnscribeSpellAll) XSRETURN_EMPTY; } +XS(XS_Client_TrainDiscBySpellID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_TrainDiscBySpellID) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::TrainDiscBySpellID(THIS, spell_id)"); + { + Client * THIS; + int32 spell_id = (int32)SvIV(ST(1)); + + 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."); + + THIS->TrainDiscBySpellID(spell_id); + } + XSRETURN_EMPTY; +} + +XS(XS_Client_GetDiscSlotBySpellID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetDiscSlotBySpellID) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::GetDiscSlotBySpellID(THIS, spell_id)"); + { + Client * THIS; + int RETVAL; + int32 spell_id = (int32)SvIV(ST(1)); + 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->GetDiscSlotBySpellID(spell_id); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + XS(XS_Client_UntrainDisc); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_UntrainDisc) { @@ -6443,10 +6518,13 @@ XS(boot_Client) newXSproto(strcpy(buf, "ResetAA"), XS_Client_ResetAA, file, "$"); newXSproto(strcpy(buf, "MemSpell"), XS_Client_MemSpell, file, "$$$;$"); newXSproto(strcpy(buf, "UnmemSpell"), XS_Client_UnmemSpell, file, "$$;$"); + newXSproto(strcpy(buf, "UnmemSpellBySpellID"), XS_Client_UnmemSpellBySpellID, file, "$$"); newXSproto(strcpy(buf, "UnmemSpellAll"), XS_Client_UnmemSpellAll, file, "$;$"); newXSproto(strcpy(buf, "ScribeSpell"), XS_Client_ScribeSpell, file, "$$$;$"); newXSproto(strcpy(buf, "UnscribeSpell"), XS_Client_UnscribeSpell, file, "$$;$"); newXSproto(strcpy(buf, "UnscribeSpellAll"), XS_Client_UnscribeSpellAll, file, "$;$"); + newXSproto(strcpy(buf, "TrainDiscBySpellID"), XS_Client_TrainDiscBySpellID, file, "$$"); + newXSproto(strcpy(buf, "GetDiscSlotBySpellID"), XS_Client_GetDiscSlotBySpellID, file, "$$"); newXSproto(strcpy(buf, "UntrainDisc"), XS_Client_UntrainDisc, file, "$$;$"); newXSproto(strcpy(buf, "UntrainDiscAll"), XS_Client_UntrainDiscAll, file, "$;$"); newXSproto(strcpy(buf, "IsSitting"), XS_Client_IsSitting, file, "$"); diff --git a/zone/spells.cpp b/zone/spells.cpp index 9ec68c3ff..18de9a444 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4910,6 +4910,16 @@ void Client::UnmemSpell(int slot, bool update_client) } } +void Client::UnmemSpellBySpellID(int32 spell_id) +{ + for(int i = 0; i < MAX_PP_MEMSPELL; i++) { + if(m_pp.mem_spells[i] == spell_id) { + UnmemSpell(i, true); + break; + } + } +} + void Client::UnmemSpellAll(bool update_client) { int i; From b3afc684de48fe978c83ff1031ee6cae90e877f5 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 14 Dec 2015 11:14:49 -0800 Subject: [PATCH 442/846] Allow updating instance timers through perl and lua. --- zone/embparser_api.cpp | 14 ++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 16 ++++++++++++++++ zone/questmgr.h | 1 + 4 files changed, 36 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index f5de73698..126e8169d 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2906,6 +2906,19 @@ XS(XS__DestroyInstance) { XSRETURN_EMPTY; } +XS(XS__UpdateInstanceTimer); +XS(XS__UpdateInstanceTimer) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: UpdateInstanceTimer(instance_id, new_duration)"); + + uint16 instance_id = (uint16)SvUV(ST(0)); + uint32 new_duration = (uint32)SvUV(ST(1)); + quest_manager.UpdateInstanceTimer(instance_id, new_duration); + + XSRETURN_EMPTY; +} + XS(XS__GetInstanceID); XS(XS__GetInstanceID) { dXSARGS; @@ -3636,6 +3649,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "ChooseRandom"), XS__ChooseRandom, file); newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file); newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file); + newXS(strcpy(buf, "UpdateInstanceTimer"), XS__UpdateInstanceTimer, file); newXS(strcpy(buf, "FlagInstanceByGroupLeader"), XS__FlagInstanceByGroupLeader, file); newXS(strcpy(buf, "FlagInstanceByRaidLeader"), XS__FlagInstanceByRaidLeader, file); newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 15a11604b..bed0fd7bc 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -804,6 +804,10 @@ void lua_destroy_instance(uint32 instance_id) { quest_manager.DestroyInstance(instance_id); } +void lua_update_instance_timer(uint16 instance_id, uint32 new_duration) { + quest_manager.UpdateInstanceTimer(instance_id, new_duration); +} + int lua_get_instance_id(const char *zone, uint32 version) { return quest_manager.GetInstanceID(zone, version); } @@ -1576,6 +1580,7 @@ luabind::scope lua_register_general() { luabind::def("get_guild_name_by_id", &lua_get_guild_name_by_id), luabind::def("create_instance", &lua_create_instance), luabind::def("destroy_instance", &lua_destroy_instance), + luabind::def("update_instance_timer", &lua_update_instance_timer), luabind::def("get_instance_id", &lua_get_instance_id), luabind::def("get_characters_in_instance", &lua_get_characters_in_instance), luabind::def("assign_to_instance", &lua_assign_to_instance), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fd157f372..cb70f93d3 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2582,6 +2582,22 @@ void QuestManager::DestroyInstance(uint16 instance_id) database.DeleteInstance(instance_id); } +void QuestManager::UpdateInstanceTimer(uint16 instance_id, uint32 new_duration) +{ + std::string query = StringFormat("UPDATE instance_list SET duration = %lu, start_time = UNIX_TIMESTAMP() WHERE id = %lu", + (unsigned long)new_duration, (unsigned long)instance_id); + auto results = database.QueryDatabase(query); + + if (results.Success()) { + auto pack = new ServerPacket(ServerOP_InstanceUpdateTime, sizeof(ServerInstanceUpdateTime_Struct)); + ServerInstanceUpdateTime_Struct *ut = (ServerInstanceUpdateTime_Struct*)pack->pBuffer; + ut->instance_id = instance_id; + ut->new_duration = new_duration; + worldserver.SendPacket(pack); + safe_delete(pack); + } +} + uint16 QuestManager::GetInstanceID(const char *zone, int16 version) { QuestManagerCurrentQuestVars(); diff --git a/zone/questmgr.h b/zone/questmgr.h index 78f4b34ed..cd1c4a303 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -217,6 +217,7 @@ public: void MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity = 0); uint32 MerchantCountItem(uint32 NPCid, uint32 itemid); uint16 CreateInstance(const char *zone, int16 version, uint32 duration); + void UpdateInstanceTimer(uint16 instance_id, uint32 new_duration); void DestroyInstance(uint16 instance_id); uint16 GetInstanceID(const char *zone, int16 version); void AssignToInstance(uint16 instance_id); From 6949f292950acb8a91b89436140cec95af2fd680 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 14 Dec 2015 14:57:03 -0500 Subject: [PATCH 443/846] Adds IsBlind() and IsFeared() functionality to Perl and Lua. --- changelog.txt | 5 ++++- zone/lua_mob.cpp | 12 +++++++++++ zone/lua_mob.h | 2 ++ zone/perl_mob.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 5d2345521..0e135c1db 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 12/07/2016 == +== 12/14/2015 == +Kinglykrab: Added IsBlind() and IsFeared() functionality to Perl and Lua. + - Note: Both methods are Mob methods and may be used on NPCs or PCs. +== 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` - Adding command aliases require that the command contain an entry in `command_settings`.`command` diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 2f0712ec0..3963ec64c 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1871,6 +1871,16 @@ void Lua_Mob::SetPseudoRoot(bool in) { self->SetPseudoRoot(in); } +bool Lua_Mob::IsFeared() { + Lua_Safe_Call_Bool(); + return self->IsFeared(); +} + +bool Lua_Mob::IsBlind() { + Lua_Safe_Call_Bool(); + return self->IsBlind(); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2156,6 +2166,8 @@ luabind::scope lua_register_mob() { .def("WearChange", (void(Lua_Mob::*)(int,int,uint32))&Lua_Mob::WearChange) .def("DoKnockback", (void(Lua_Mob::*)(Lua_Mob,uint32,uint32))&Lua_Mob::DoKnockback) .def("RemoveNimbusEffect", (void(Lua_Mob::*)(int))&Lua_Mob::RemoveNimbusEffect) + .def("IsFeared", (bool(Lua_Mob::*)(void))&Lua_Mob::IsFeared) + .def("IsBlind", (bool(Lua_Mob::*)(void))&Lua_Mob::IsBlind) .def("IsRunning", (bool(Lua_Mob::*)(void))&Lua_Mob::IsRunning) .def("SetRunning", (void(Lua_Mob::*)(bool))&Lua_Mob::SetRunning) .def("SetBodyType", (void(Lua_Mob::*)(int,bool))&Lua_Mob::SetBodyType) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 4f427aca5..3b98b4af3 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -40,6 +40,8 @@ public: void SetLevel(int level, bool command); void SendWearChange(int material_slot); bool IsMoving(); + bool IsFeared(); + bool IsBlind(); void GotoBind(); void Gate(); bool Attack(Lua_Mob other); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 323d22b36..adbdd0301 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8440,6 +8440,56 @@ XS(XS_Mob_CanClassEquipItem) XSRETURN(1); } +XS(XS_Mob_IsFeared); +XS(XS_Mob_IsFeared) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::IsFeared(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->IsFeared(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_IsBlind); +XS(XS_Mob_IsBlind) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::IsBlind(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->IsBlind(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -8751,6 +8801,8 @@ XS(boot_Mob) newXSproto(strcpy(buf, "ClearSpecialAbilities"), XS_Mob_ClearSpecialAbilities, file, "$"); newXSproto(strcpy(buf, "ProcessSpecialAbilities"), XS_Mob_ProcessSpecialAbilities, file, "$$"); newXSproto(strcpy(buf, "CanClassEquipItem"), XS_Mob_CanClassEquipItem, file, "$$"); + newXSproto(strcpy(buf, "IsFeared"), XS_Mob_IsFeared, file, "$"); + newXSproto(strcpy(buf, "IsBlind"), XS_Mob_IsBlind, file, "$"); XSRETURN_YES; } From f0222bb94be2a15bf1c2fec7afbdce09c632c504 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 14 Dec 2015 12:36:44 -0800 Subject: [PATCH 444/846] Adjust changelog.txt [skip ci] --- changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.txt b/changelog.txt index 0e135c1db..adc272817 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 12/14/2015 == 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` From c9ecca1a56108096dc1209e93e4e2717dd80c760 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 14 Dec 2015 17:38:24 -0500 Subject: [PATCH 445/846] Added 'alias added' message and commmandaliases list (future use) --- zone/command.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zone/command.cpp b/zone/command.cpp index 3ec0328ee..ca6521789 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -84,6 +84,7 @@ void command_bestz(Client *c, const Seperator *message); 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 LinkedList cleanup_commandlist; @@ -418,6 +419,8 @@ int command_init(void) return -1; } + commandaliases.clear(); + std::map>> command_settings; database.GetCommandSettings(command_settings); for (std::map::iterator iter_cl = commandlist.begin(); iter_cl != commandlist.end(); ++iter_cl) { @@ -442,6 +445,9 @@ int command_init(void) } commandlist[*iter_aka] = iter_cl->second; + commandaliases[*iter_aka] = iter_cl->first; + + Log.Out(Logs::General, Logs::Commands, "command_init(): - Alias '%s' added to command '%s'.", iter_aka->c_str(), commandaliases[*iter_aka].c_str()); } } @@ -461,6 +467,7 @@ int command_init(void) void command_deinit(void) { commandlist.clear(); + commandaliases.clear(); command_dispatch = command_notavail; commandcount = 0; From 78f22599f423e64252678650bb1b5a740ecbb021 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 15 Dec 2015 19:03:24 -0500 Subject: [PATCH 446/846] Tweak to commandaliases behavior --- zone/command.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index ca6521789..5eede229f 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -144,6 +144,8 @@ Access Levels: int command_init(void) { + commandaliases.clear(); + if ( command_add("acceptrules", "[acceptrules] - Accept the EQEmu Agreement", 0, command_acceptrules) || command_add("advnpcspawn", "[maketype|makegroup|addgroupentry|addgroupspawn][removegroupspawn|movespawn|editgroupbox|cleargroupbox]", 150, command_advnpcspawn) || @@ -419,8 +421,6 @@ int command_init(void) return -1; } - commandaliases.clear(); - std::map>> command_settings; database.GetCommandSettings(command_settings); for (std::map::iterator iter_cl = commandlist.begin(); iter_cl != commandlist.end(); ++iter_cl) { @@ -511,6 +511,7 @@ int command_add(std::string command_name, const char *desc, int access, CmdFuncP c->function = function; commandlist[command_name] = c; + commandaliases[command_name] = command_name; cleanup_commandlist.Append(c); commandcount++; From bc77439d117a20bc587aafc33aab69f58d1b16e2 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 16 Dec 2015 09:05:27 -0500 Subject: [PATCH 447/846] When binding someone else's wounds, the code tried to send a bind would response to client with a type of 2. The intent (based on comments was to get the client to display a "stand still" message on the receiving client. That reply message was not generating that message, but if the client you were binding was also binding his own wounds, it would cause your target to stand up, interrupting his bind. I replaced this client reply with a simple, directed client message. It all seems to work fine now. --- zone/client.cpp | 9 ++------- zone/string_ids.h | 1 + 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index f65a30350..4b81cf250 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2577,12 +2577,7 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ else { // send bindmob "stand still" if(!bindmob->IsAIControlled() && bindmob != this ) { - bind_out->type = 2; // ? - //bind_out->type = 3; // ? - bind_out->to = GetID(); // ? - bindmob->CastToClient()->QueuePacket(outapp); - bind_out->type = 0; - bind_out->to = 0; + bindmob->CastToClient()->Message_StringID(clientMessageYellow, YOU_ARE_BEING_BANDAGED); } else if (bindmob->IsAIControlled() && bindmob != this ){ ; // Tell IPC to stand still? @@ -2668,7 +2663,7 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ else { //I dont have the real, live Message(15, "You cannot bind wounds above %d%% hitpoints.", max_percent); - if(bindmob->IsClient()) + 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. } diff --git a/zone/string_ids.h b/zone/string_ids.h index e3b943744..be05b1eb2 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -27,6 +27,7 @@ #define GAIN_XP 138 //You gain experience!! #define GAIN_GROUPXP 139 //You gain party experience!! #define BOW_DOUBLE_DAMAGE 143 //Your bow shot did double dmg. +#define YOU_ARE_BEING_BANDAGED 147 //Someone is bandaging you. #define FORAGE_GRUBS 150 //You have scrounged up some fishing grubs. #define FORAGE_WATER 151 //You have scrounged up some water. #define FORAGE_FOOD 152 //You have scrounged up some food. From 07ab58483dbaabd7728236e9b7975a660706567f Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 16 Dec 2015 09:16:27 -0500 Subject: [PATCH 448/846] Updated changelog --- changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.txt b/changelog.txt index adc272817..f708219e8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 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. + == 12/14/2015 == Kinglykrab: Added IsBlind() and IsFeared() functionality to Perl and Lua. - Note: Both methods are Mob methods and may be used on NPCs or PCs. From 17bbd8dfbec00ac21c148e14df778a59dbb78975 Mon Sep 17 00:00:00 2001 From: regneq Date: Thu, 17 Dec 2015 14:14:04 -0800 Subject: [PATCH 449/846] eqtime is now stored in the DB. required/2015_12_17_eqtime.sql --- common/database.cpp | 39 ++++++++++++ common/database.h | 2 + common/eqemu_config.cpp | 8 --- common/eqemu_config.h | 2 - common/eqtime.cpp | 66 -------------------- common/eqtime.h | 6 -- utils/sql/git/required/2015_12_17_eqtime.sql | 11 ++++ world/net.cpp | 13 ++-- world/zoneserver.cpp | 4 +- 9 files changed, 63 insertions(+), 88 deletions(-) create mode 100644 utils/sql/git/required/2015_12_17_eqtime.sql diff --git a/common/database.cpp b/common/database.cpp index 475b48258..b8ea025ae 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2182,3 +2182,42 @@ void Database::ClearInvSnapshots(bool use_rule) std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time); QueryDatabase(query); } + +struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) +{ + + TimeOfDay_Struct eqTime; + std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1"); + auto results = QueryDatabase(query); + + if (!results.Success() || results.RowCount() == 0) + { + Log.Out(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults."); + eqTime.minute = 0; + eqTime.hour = 9; + eqTime.day = 1; + eqTime.month = 1; + eqTime.year = 3100; + realtime = time(0); + } + + auto row = results.begin(); + + eqTime.minute = atoi(row[0]); + eqTime.hour = atoi(row[1]); + eqTime.day = atoi(row[2]); + eqTime.month = atoi(row[3]); + eqTime.year = atoi(row[4]); + realtime = atoi(row[5]); + + return eqTime; +} + +bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year) +{ + std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0)); + auto results = QueryDatabase(query); + + return results.Success(); + +} \ No newline at end of file diff --git a/common/database.h b/common/database.h index f066cb417..02110b9a6 100644 --- a/common/database.h +++ b/common/database.h @@ -241,6 +241,8 @@ public: uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level); void AddReport(std::string who, std::string against, std::string lines); + struct TimeOfDay_Struct LoadTime(time_t &realtime); + bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year); void ClearMerchantTemp(); void ClearPTimers(uint32 charid); void SetFirstLogon(uint32 CharID, uint8 firstlogon); diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 6e1400904..fb295cec1 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -254,10 +254,6 @@ void EQEmuConfig::do_files(TiXmlElement *ele) if (text) { OpCodesFile = text; } - text = ParseTextBlock(ele, "eqtime", true); - if (text) { - EQTimeFile = text; - } } void EQEmuConfig::do_directories(TiXmlElement *ele) @@ -408,9 +404,6 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const if (var_name == "OpCodesFile") { return (OpCodesFile); } - if (var_name == "EQTimeFile") { - return (EQTimeFile); - } if (var_name == "MapDir") { return (MapDir); } @@ -475,7 +468,6 @@ void EQEmuConfig::Dump() const std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl; std::cout << "SpellsFile = " << SpellsFile << std::endl; std::cout << "OpCodesFile = " << OpCodesFile << std::endl; - std::cout << "EQTimeFile = " << EQTimeFile << std::endl; std::cout << "MapDir = " << MapDir << std::endl; std::cout << "QuestDir = " << QuestDir << std::endl; std::cout << "PluginDir = " << PluginDir << std::endl; diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 1ad2174dc..039b6c327 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -79,7 +79,6 @@ class EQEmuConfig : public XMLParser // From std::string SpellsFile; std::string OpCodesFile; - std::string EQTimeFile; // From std::string MapDir; @@ -154,7 +153,6 @@ class EQEmuConfig : public XMLParser // Files SpellsFile = "spells_us.txt"; OpCodesFile = "opcodes.conf"; - EQTimeFile = "eqtime.cfg"; // Dirs MapDir = "Maps"; QuestDir = "quests"; diff --git a/common/eqtime.cpp b/common/eqtime.cpp index e504964b8..8ece4ad69 100644 --- a/common/eqtime.cpp +++ b/common/eqtime.cpp @@ -133,72 +133,6 @@ int EQTime::SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real) return 1; } -//saveFile and loadFile need to use long for the save datatype... -//For some reason, ifstream/ofstream have problems with EQEmu datatypes in files. -bool EQTime::saveFile(const char *filename) -{ - std::ofstream of; - of.open(filename); - if (!of) - { - Log.Out(Logs::General, Logs::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename); - return false; - } - //Enable for debugging - of << EQT_VERSION << std::endl; - of << (long)eqTime.start_eqtime.day << std::endl; - of << (long)eqTime.start_eqtime.hour << std::endl; - of << (long)eqTime.start_eqtime.minute << std::endl; - of << (long)eqTime.start_eqtime.month << std::endl; - of << eqTime.start_eqtime.year << std::endl; - of << eqTime.start_realtime << std::endl; - of.close(); - return true; -} - -bool EQTime::loadFile(const char *filename) -{ - int version=0; - long in_data=0; - std::ifstream in; - in.open(filename); - if(!in) - { - Log.Out(Logs::General, Logs::Error, "Could not load EQTime file %s", filename); - return false; - } - in >> version; - in.ignore(80, '\n'); - if(version != EQT_VERSION) - { - Log.Out(Logs::General, Logs::Error, "'%s' is NOT a valid EQTime file. File version is %i, EQTime version is %i", filename, version, EQT_VERSION); - return false; - } - //in >> eqTime.start_eqtime.day; - in >> in_data; - in.ignore(80, '\n'); - eqTime.start_eqtime.day = in_data; - //in >> eqTime.start_eqtime.hour; - in >> in_data; - eqTime.start_eqtime.hour = in_data; - in.ignore(80, '\n'); - //in >> eqTime.start_eqtime.minute; - in >> in_data; - in.ignore(80, '\n'); - eqTime.start_eqtime.minute = in_data; - //in >> eqTime.start_eqtime.month; - in >> in_data; - in.ignore(80, '\n'); - eqTime.start_eqtime.month = in_data; - in >> eqTime.start_eqtime.year; - in.ignore(80, '\n'); - in >> eqTime.start_realtime; - //Enable for debugging... - in.close(); - return true; -} - - bool EQTime::IsTimeBefore(TimeOfDay_Struct *base, TimeOfDay_Struct *test) { if (base->year > test->year) return(true); diff --git a/common/eqtime.h b/common/eqtime.h index aeda9f0f6..f40b855f6 100644 --- a/common/eqtime.h +++ b/common/eqtime.h @@ -39,12 +39,6 @@ public: static void ToString(TimeOfDay_Struct *t, std::string &str); - //Database functions - //bool loadDB(Database q); - //bool setDB(Database q); - bool loadFile(const char *filename); - bool saveFile(const char *filename); - private: //This is our reference clock. eqTimeOfDay eqTime; diff --git a/utils/sql/git/required/2015_12_17_eqtime.sql b/utils/sql/git/required/2015_12_17_eqtime.sql new file mode 100644 index 000000000..c264edf27 --- /dev/null +++ b/utils/sql/git/required/2015_12_17_eqtime.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS `eqtime`; +CREATE TABLE `eqtime` ( + `minute` tinyint(4) not null default 0, + `hour` tinyint(4) not null default 0, + `day` tinyint(4) not null default 0, + `month` tinyint(4) not null default 0, + `year` int(4) not null default 0, + `realtime` int(11) not null default 0 +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +INSERT INTO eqtime values (0,1,28,12,3766,1444035661); \ No newline at end of file diff --git a/world/net.cpp b/world/net.cpp index d7669ce12..b5c29fecb 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -345,8 +345,11 @@ int main(int argc, char** argv) { database.ClearMerchantTemp(); } Log.Out(Logs::General, Logs::World_Server, "Loading EQ time of day.."); - if (!zoneserver_list.worldclock.loadFile(Config->EQTimeFile.c_str())) - Log.Out(Logs::General, Logs::World_Server, "Unable to load %s", Config->EQTimeFile.c_str()); + TimeOfDay_Struct eqTime; + time_t realtime; + eqTime = database.LoadTime(realtime); + zoneserver_list.worldclock.SetCurrentEQTimeOfDay(eqTime, realtime); + Log.Out(Logs::General, Logs::World_Server, "Loading launcher list.."); launcher_list.LoadList(); @@ -519,8 +522,10 @@ int main(int argc, char** argv) { void CatchSignal(int sig_num) { Log.Out(Logs::General, Logs::World_Server,"Caught signal %d",sig_num); - if(zoneserver_list.worldclock.saveFile(WorldConfig::get()->EQTimeFile.c_str())==false) - Log.Out(Logs::General, Logs::World_Server,"Failed to save time file."); + TimeOfDay_Struct eqTime; + zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(0), &eqTime); + if (!database.SaveTime(eqTime.minute, eqTime.hour, eqTime.day, eqTime.month, eqTime.year)) + Log.Out(Logs::General, Logs::World_Server, "Failed to save eqtime."); RunLoops = false; } diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index f6447f3f4..580053a3b 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -989,8 +989,8 @@ bool ZoneServer::Process() { Log.Out(Logs::Detail, Logs::World_Server,"Received SetWorldTime"); eqTimeOfDay* newtime = (eqTimeOfDay*) pack->pBuffer; zoneserver_list.worldclock.SetCurrentEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime); - Log.Out(Logs::Detail, Logs::World_Server,"New time = %d-%d-%d %d:%d (%d)\n", newtime->start_eqtime.year, newtime->start_eqtime.month, (int)newtime->start_eqtime.day, (int)newtime->start_eqtime.hour, (int)newtime->start_eqtime.minute, (int)newtime->start_realtime); - zoneserver_list.worldclock.saveFile(WorldConfig::get()->EQTimeFile.c_str()); + Log.Out(Logs::Detail, Logs::World_Server, "New time = %d-%d-%d %d:%d (%d)\n", newtime->start_eqtime.year, newtime->start_eqtime.month, (int)newtime->start_eqtime.day, (int)newtime->start_eqtime.hour, (int)newtime->start_eqtime.minute, (int)newtime->start_realtime); + database.SaveTime((int)newtime->start_eqtime.minute, (int)newtime->start_eqtime.hour, (int)newtime->start_eqtime.day, newtime->start_eqtime.month, newtime->start_eqtime.year); zoneserver_list.SendTimeSync(); break; } From d449d4f54c7d1eb03eb91dfef27031663871414d Mon Sep 17 00:00:00 2001 From: regneq Date: Thu, 17 Dec 2015 15:49:37 -0800 Subject: [PATCH 450/846] EQTime will now save to the DB once every 10 real world minutes. --- world/net.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/world/net.cpp b/world/net.cpp index b5c29fecb..86f794af0 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -349,6 +349,8 @@ int main(int argc, char** argv) { time_t realtime; eqTime = database.LoadTime(realtime); zoneserver_list.worldclock.SetCurrentEQTimeOfDay(eqTime, realtime); + Timer EQTimeTimer(600000); + EQTimeTimer.Start(600000); Log.Out(Logs::General, Logs::World_Server, "Loading launcher list.."); launcher_list.LoadList(); @@ -473,6 +475,16 @@ int main(int argc, char** argv) { database.PurgeExpiredInstances(); } + if (EQTimeTimer.Check()) + { + TimeOfDay_Struct tod; + zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(0), &tod); + if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year)) + Log.Out(Logs::General, Logs::World_Server, "Failed to save eqtime."); + else + Log.Out(Logs::General, Logs::World_Server, "EQTime successfully saved."); + } + //check for timeouts in other threads timeout_manager.CheckTimeouts(); loginserverlist.Process(); @@ -522,10 +534,6 @@ int main(int argc, char** argv) { void CatchSignal(int sig_num) { Log.Out(Logs::General, Logs::World_Server,"Caught signal %d",sig_num); - TimeOfDay_Struct eqTime; - zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(0), &eqTime); - if (!database.SaveTime(eqTime.minute, eqTime.hour, eqTime.day, eqTime.month, eqTime.year)) - Log.Out(Logs::General, Logs::World_Server, "Failed to save eqtime."); RunLoops = false; } From 488be05e0e68ce30d8da001d252c1d3a764d1d8c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 17 Dec 2015 19:50:33 -0500 Subject: [PATCH 451/846] Add DB manifest for eqtime change --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index 2e5af617c..c3dfa1c26 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 9091 +#define CURRENT_BINARY_DATABASE_VERSION 9092 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 2f37dfe84..adc9009c2 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -345,6 +345,7 @@ 9089|2015_11_02_ai_idle_no_spell_recast_default_changes.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Spells:AI_IdleNoSpellMinRecast%' AND `rule_value` = '500'|not_empty| 9090|2015_12_01_spell_scribe_restriction_rule.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Character:RestrictSpellScribing'|empty| 9091|2015_12_07_command_settings.sql|SHOW TABLES LIKE 'command_settings'|empty| +9092|2015_12_17_eqtime.sql|SHOW TABLES LIKE 'eqtime'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From f8867ea73d81b9e2f1a35b2aa52f7fd63d5a5173 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 18 Dec 2015 13:46:05 -0500 Subject: [PATCH 452/846] Bump up initial aggro from Yell for Help to match initial aggro I guess I forgot this one --- zone/aggro.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index a1903c8ca..5febe5767 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -476,7 +476,7 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) { attacker->GetName(), DistanceSquared(mob->GetPosition(), sender->GetPosition()), fabs(sender->GetZ()+mob->GetZ())); #endif - mob->AddToHateList(attacker, 1, 0, false); + mob->AddToHateList(attacker, 25, 0, false); } } } From 03592e58f903d2a5066c3710c46c90fe485e3061 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 18 Dec 2015 17:41:57 -0500 Subject: [PATCH 453/846] Port EQMacEmu's Assist Aggro code This code also allows you to toggle on Tick Pulling (Aggro:AllowTickPulling) which was a pulling technique (exploit) fixed sometime in 2006 This code also implements assist caps to cut down on trains (5 by default) Unsure if live what this number is (it exists) or if it's a per NPC basis An NPC with Assist Aggro will not call for help, only NPCs with Primary Aggro will --- common/ruletypes.h | 3 +++ zone/aggro.cpp | 10 ++++++++++ zone/attack.cpp | 5 +++++ zone/mob.cpp | 5 +++++ zone/mob.h | 14 ++++++++++++++ zone/mob_ai.cpp | 6 +++++- zone/npc.cpp | 12 +++++++++++- 7 files changed, 53 insertions(+), 2 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 91d3479be..83ef9aff3 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -459,6 +459,8 @@ RULE_BOOL(Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arr RULE_BOOL(Combat, MeleePush, true) // enable melee push RULE_INT(Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad RULE_BOOL(Combat, UseLiveCombatRounds, true) // turn this false if you don't want to worry about fixing up combat rounds for NPCs +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_CATEGORY_END() RULE_CATEGORY(NPC) @@ -494,6 +496,7 @@ RULE_INT(Aggro, PetSpellAggroMod, 10) RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate generate this much hate on a Tunnel Vision mob 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_CATEGORY_END() RULE_CATEGORY(TaskSystem) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 5febe5767..a2ee52357 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -431,11 +431,20 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) { if (sender->GetPrimaryFaction() == 0 ) return; // well, if we dont have a faction set, we're gonna be indiff to everybody + if (sender->HasAssistAggro()) + return; + for (auto it = npc_list.begin(); it != npc_list.end(); ++it) { NPC *mob = it->second; if (!mob) continue; + if (mob->CheckAggro(attacker)) + continue; + + if (sender->NPCAssistCap() >= RuleI(Combat, NPCAssistCap)) + break; + float r = mob->GetAssistRange(); r = r * r; @@ -477,6 +486,7 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) { sender->GetPosition()), fabs(sender->GetZ()+mob->GetZ())); #endif mob->AddToHateList(attacker, 25, 0, false); + sender->AddAssistCap(); } } } diff --git a/zone/attack.cpp b/zone/attack.cpp index 2752752aa..6b2534a43 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2422,6 +2422,11 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b hate = 1; } + if (iYellForHelp) + SetPrimaryAggro(true); + else + SetAssistAggro(true); + bool wasengaged = IsEngaged(); Mob* owner = other->GetOwner(); Mob* mypet = this->GetPet(); diff --git a/zone/mob.cpp b/zone/mob.cpp index eccf04a76..6e778f004 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -433,6 +433,9 @@ Mob::Mob(const char* in_name, emoteid = 0; endur_upkeep = false; + PrimaryAggro = false; + AssistAggro = false; + npc_assist_cap = 0; } Mob::~Mob() @@ -2693,6 +2696,8 @@ bool Mob::RemoveFromHateList(Mob* mob) { AI_Event_NoLongerEngaged(); zone->DelAggroMob(); + if (IsNPC() && !RuleB(Aggro, AllowTickPulling)) + ResetAssistCap(); } } if(GetTarget() == mob) diff --git a/zone/mob.h b/zone/mob.h index 2ca027023..d02e0f089 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -504,6 +504,10 @@ public: Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();} Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} bool IsEngaged() { return(!hate_list.IsHateListEmpty()); } + bool HasPrimaryAggro() { return PrimaryAggro; } + bool HasAssistAggro() { return AssistAggro; } + void SetPrimaryAggro(bool value) { PrimaryAggro = value; if (value) AssistAggro = false; } + void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; } bool HateSummon(); void FaceTarget(Mob* MobToFace = 0); void SetHeading(float iHeading) { if(m_Position.w != iHeading) { pLastChange = Timer::GetCurrentTime(); @@ -993,6 +997,11 @@ public: void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon); bool CheckAATimer(int timer); + int NPCAssistCap() { return npc_assist_cap; } + void AddAssistCap() { ++npc_assist_cap; } + void DelAssistCap() { --npc_assist_cap; } + void ResetAssistCap() { npc_assist_cap = 0; } + 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); @@ -1293,6 +1302,11 @@ protected: glm::vec4 m_CurrentWayPoint; int cur_wp_pause; + bool PrimaryAggro; + bool AssistAggro; + int npc_assist_cap; + Timer assist_cap_timer; // clear assist cap so more nearby mobs can be called for help + int patrol; glm::vec3 m_FearWalkTarget; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 25ed72441..79c4493ea 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1735,8 +1735,10 @@ void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) { if (iYellForHelp) { if(IsPet()) { GetOwner()->AI_Event_Engaged(attacker, iYellForHelp); - } else { + } else if (!HasAssistAggro() && NPCAssistCap() < RuleI(Combat, NPCAssistCap)) { entity_list.AIYellForHelp(this, attacker); + if (NPCAssistCap() > 0 && !assist_cap_timer.Enabled()) + assist_cap_timer.Start(RuleI(Combat, NPCAssistCapTimer)); } } @@ -1787,6 +1789,8 @@ void Mob::AI_Event_NoLongerEngaged() { if(IsNPC()) { + SetPrimaryAggro(false); + SetAssistAggro(false); if(CastToNPC()->GetCombatEvent() && GetHP() > 0) { if(entity_list.GetNPCByID(this->GetID())) diff --git a/zone/npc.cpp b/zone/npc.cpp index ebdd8a79d..fd7f6880c 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -712,8 +712,18 @@ bool NPC::Process() } //Handle assists... - if(assist_timer.Check() && IsEngaged() && !Charmed()) { + if (assist_cap_timer.Check()) { + if (NPCAssistCap() > 0) + DelAssistCap(); + else + assist_cap_timer.Disable(); + } + + if (assist_timer.Check() && IsEngaged() && !Charmed() && !HasAssistAggro() && + NPCAssistCap() < RuleI(Combat, NPCAssistCap)) { entity_list.AIYellForHelp(this, GetTarget()); + if (NPCAssistCap() > 0 && !assist_cap_timer.Enabled()) + assist_cap_timer.Start(RuleI(Combat, NPCAssistCapTimer)); } if(qGlobals) From b4b1324aceb942b537c687fec64888ec6a8e3487 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 19 Dec 2015 12:42:55 -0500 Subject: [PATCH 454/846] Updated client version bitmasks --- common/clientversions.h | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/common/clientversions.h b/common/clientversions.h index 4e575f8f4..308a5f091 100644 --- a/common/clientversions.h +++ b/common/clientversions.h @@ -24,20 +24,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "types.h" -static const uint32 BIT_Client62 = 1; -static const uint32 BIT_Titanium = 2; -static const uint32 BIT_SoF = 4; -static const uint32 BIT_SoD = 8; -static const uint32 BIT_UF = 16; -static const uint32 BIT_RoF = 32; -static const uint32 BIT_RoF2 = 64; +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_TitaniumAndEarlier = 0x00000003; -static const uint32 BIT_SoFAndLater = 0xFFFFFFFC; -static const uint32 BIT_SoDAndLater = 0xFFFFFFF8; -static const uint32 BIT_UFAndLater = 0xFFFFFFF0; -static const uint32 BIT_RoFAndLater = 0xFFFFFFE0; -static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; static const uint32 BIT_AllClients = 0xFFFFFFFF; enum class ClientVersion From 0177c8d7d9238be93beb241bec6d48ce0ef9e26f Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sat, 19 Dec 2015 15:23:04 -0500 Subject: [PATCH 455/846] Exported several Mob-based methods to Perl and Lua. --- changelog.txt | 22 ++ zone/lua_mob.cpp | 116 ++++++++++- zone/lua_mob.h | 19 ++ zone/perl_mob.cpp | 510 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 666 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index f708219e8..c64baec6c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,27 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/19/2015 == +Kinglykrab: Added many methods to Perl and Lua, list below: + - SeeInvisible() + - SeeInvisibleUndead() + - SeeHide() + - SeeImprovedHide() + - GetNimbusEffect1() - returns first nimbus effect + - GetNimbusEffect2() - returns second nimbus effect + - GetNimbusEffect3() - returns third nimbus effect + - IsTargetable() + - HasShieldEquiped() + - HasTwoHandBluntEquiped() + - HasTwoHanderEquiped() + - GetHerosForgeModel() - returns int32 Hero's Forge model + - IsEliteMaterialItem() - returns uint32 Hero's Forge Model + - GetBaseSize() - returns Mob's base size + - HasOwner() + - IsPet() + - 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. diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 3963ec64c..469e8cb2f 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1881,6 +1881,101 @@ bool Lua_Mob::IsBlind() { return self->IsBlind(); } +uint8 Lua_Mob::SeeInvisible() { + Lua_Safe_Call_Int(); + return self->SeeInvisible(); +} + +bool Lua_Mob::SeeInvisibleUndead() { + Lua_Safe_Call_Bool(); + return self->SeeInvisibleUndead(); +} + +bool Lua_Mob::SeeHide() { + Lua_Safe_Call_Bool(); + return self->SeeHide(); +} + +bool Lua_Mob::SeeImprovedHide() { + Lua_Safe_Call_Bool(); + return self->SeeImprovedHide(); +} + +uint8 Lua_Mob::GetNimbusEffect1() { + Lua_Safe_Call_Int(); + return self->GetNimbusEffect1(); +} + +uint8 Lua_Mob::GetNimbusEffect2() { + Lua_Safe_Call_Int(); + return self->GetNimbusEffect2(); +} + +uint8 Lua_Mob::GetNimbusEffect3() { + Lua_Safe_Call_Int(); + return self->GetNimbusEffect3(); +} + +bool Lua_Mob::IsTargetable() { + Lua_Safe_Call_Bool(); + return self->IsTargetable(); +} + +bool Lua_Mob::HasShieldEquiped() { + Lua_Safe_Call_Bool(); + return self->HasShieldEquiped(); +} + +bool Lua_Mob::HasTwoHandBluntEquiped() { + Lua_Safe_Call_Bool(); + return self->HasTwoHandBluntEquiped(); +} + +bool Lua_Mob::HasTwoHanderEquipped() { + Lua_Safe_Call_Bool(); + return self->HasTwoHanderEquipped(); +} + +uint32 Lua_Mob::GetHerosForgeModel(uint8 material_slot) { + Lua_Safe_Call_Int(); + return self->GetHerosForgeModel(material_slot); +} + +uint32 Lua_Mob::IsEliteMaterialItem(uint8 material_slot) { + Lua_Safe_Call_Int(); + return self->IsEliteMaterialItem(material_slot); +} + +float Lua_Mob::GetBaseSize() { + Lua_Safe_Call_Real(); + return self->GetBaseSize(); +} + +bool Lua_Mob::HasOwner() { + Lua_Safe_Call_Bool(); + return self->HasOwner(); +} + +bool Lua_Mob::IsPet() { + Lua_Safe_Call_Bool(); + return self->IsPet(); +} + +bool Lua_Mob::HasPet() { + Lua_Safe_Call_Bool(); + return self->HasPet(); +} + +bool Lua_Mob::IsSilenced() { + Lua_Safe_Call_Bool(); + return self->IsSilenced(); +} + +bool Lua_Mob::IsAmnesiad() { + Lua_Safe_Call_Bool(); + return self->IsAmnesiad(); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2203,7 +2298,26 @@ luabind::scope lua_register_mob() { .def("BuffFadeBySlot", (void(Lua_Mob::*)(int,bool))&Lua_Mob::BuffFadeBySlot) .def("CanBuffStack", (int(Lua_Mob::*)(int,int))&Lua_Mob::CanBuffStack) .def("CanBuffStack", (int(Lua_Mob::*)(int,int,bool))&Lua_Mob::CanBuffStack) - .def("SetPseudoRoot", (void(Lua_Mob::*)(bool))&Lua_Mob::SetPseudoRoot); + .def("SetPseudoRoot", (void(Lua_Mob::*)(void))&Lua_Mob::SetPseudoRoot) + .def("SeeInvisible", (uint8(Lua_Mob::*)(void))&Lua_Mob::SeeInvisible) + .def("SeeInvisibleUndead", (bool(Lua_Mob::*)(void))&Lua_Mob::SeeInvisibleUndead) + .def("SeeHide", (bool(Lua_Mob::*)(void))&Lua_Mob::SeeHide) + .def("SeeImprovedHide", (bool(Lua_Mob::*)(bool))&Lua_Mob::SeeImprovedHide) + .def("GetNimbusEffect1", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect1) + .def("GetNimbusEffect2", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect2) + .def("GetNimbusEffect3", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect3) + .def("IsTargetable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTargetable) + .def("HasShieldEquiped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasShieldEquiped) + .def("HasTwoHandBluntEquiped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasTwoHandBluntEquiped) + .def("HasTwoHanderEquipped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasTwoHanderEquipped) + .def("GetHerosForgeModel", (int32(Lua_Mob::*)(uint8))&Lua_Mob::GetHerosForgeModel) + .def("IsEliteMaterialItem", (uint32(Lua_Mob::*)(uint8))&Lua_Mob::IsEliteMaterialItem) + .def("GetBaseSize", (double(Lua_Mob::*)(void))&Lua_Mob::GetBaseSize) + .def("HasOwner", (bool(Lua_Mob::*)(void))&Lua_Mob::HasOwner) + .def("IsPet", (bool(Lua_Mob::*)(void))&Lua_Mob::IsPet) + .def("HasPet", (bool(Lua_Mob::*)(void))&Lua_Mob::HasPet) + .def("IsSilenced", (bool(Lua_Mob::*)(void))&Lua_Mob::IsSilenced) + .def("IsAmnesiad", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAmnesiad); } luabind::scope lua_register_special_abilities() { diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 3b98b4af3..c7530e391 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -358,6 +358,25 @@ public: int CanBuffStack(int spell_id, int caster_level); int CanBuffStack(int spell_id, int caster_level, bool fail_if_overwrite); void SetPseudoRoot(bool in); + uint8 SeeInvisible(); + bool SeeInvisibleUndead(); + bool SeeHide(); + bool SeeImprovedHide(); + uint8 GetNimbusEffect1(); + uint8 GetNimbusEffect2(); + uint8 GetNimbusEffect3(); + bool IsTargetable(); + bool HasShieldEquiped(); + bool HasTwoHandBluntEquiped(); + bool HasTwoHanderEquipped(); + uint32 GetHerosForgeModel(uint8 material_slot); + uint32 IsEliteMaterialItem(uint8 material_slot); + float GetBaseSize(); + bool HasOwner(); + bool IsPet(); + bool HasPet(); + bool IsSilenced(); + bool IsAmnesiad(); }; #endif diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index adbdd0301..2b2442fe6 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8490,6 +8490,497 @@ XS(XS_Mob_IsBlind) { XSRETURN(1); } +XS(XS_Mob_SeeInvisible); +XS(XS_Mob_SeeInvisible) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::SeeInvisible(THIS)"); + { + Mob* THIS; + uint8 RETVAL; + dXSTARG; + + 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."); + + RETVAL = THIS->SeeInvisible(); + XSprePUSH; + PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_SeeInvisibleUndead); +XS(XS_Mob_SeeInvisibleUndead) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::SeeInvisibleUndead(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->SeeInvisibleUndead(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_SeeHide); +XS(XS_Mob_SeeHide) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::SeeHide(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->SeeHide(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_SeeImprovedHide); +XS(XS_Mob_SeeImprovedHide) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::SeeImprovedHide(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->SeeImprovedHide(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_GetNimbusEffect1); +XS(XS_Mob_GetNimbusEffect1) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect1(THIS)"); + { + Mob* THIS; + uint8 RETVAL; + dXSTARG; + + 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."); + + RETVAL = THIS->GetNimbusEffect1(); + XSprePUSH; + PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_GetNimbusEffect2); +XS(XS_Mob_GetNimbusEffect2) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect2(THIS)"); + { + Mob* THIS; + uint8 RETVAL; + dXSTARG; + + 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."); + + RETVAL = THIS->GetNimbusEffect2(); + XSprePUSH; + PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_GetNimbusEffect3); +XS(XS_Mob_GetNimbusEffect3) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect3(THIS)"); + { + Mob* THIS; + uint8 RETVAL; + dXSTARG; + + 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."); + + RETVAL = THIS->GetNimbusEffect3(); + XSprePUSH; + PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_IsTargetable); +XS(XS_Mob_IsTargetable) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::IsTargetable(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->IsTargetable(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_HasShieldEquiped); +XS(XS_Mob_HasShieldEquiped) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::HasShieldEquiped(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->HasShieldEquiped(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_HasTwoHandBluntEquiped); +XS(XS_Mob_HasTwoHandBluntEquiped) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::HasTwoHandBluntEquiped(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->HasTwoHandBluntEquiped(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_HasTwoHanderEquipped); +XS(XS_Mob_HasTwoHanderEquipped) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::HasTwoHanderEquipped(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->HasTwoHanderEquipped(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_GetHerosForgeModel); +XS(XS_Mob_GetHerosForgeModel) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Mob::GetHerosForgeModel(THIS, material_slot)"); + { + Mob* THIS; + int32 RETVAL; + uint8 material_slot = (uint8)SvUV(ST(1)); + dXSTARG; + + 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."); + + RETVAL = THIS->GetHerosForgeModel(material_slot); + XSprePUSH; + PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_IsEliteMaterialItem); +XS(XS_Mob_IsEliteMaterialItem) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Mob::IsEliteMaterialItem(THIS, material_slot)"); + { + Mob* THIS; + uint32 RETVAL; + uint8 material_slot = (uint8)SvUV(ST(1)); + dXSTARG; + + 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."); + + RETVAL = THIS->IsEliteMaterialItem(material_slot); + XSprePUSH; + PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_GetBaseSize); +XS(XS_Mob_GetBaseSize) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::GetBaseSize(THIS)"); + { + Mob* THIS; + float RETVAL; + dXSTARG; + + 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."); + + RETVAL = THIS->GetBaseSize(); + XSprePUSH; + PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_HasOwner); +XS(XS_Mob_HasOwner) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::HasOwner(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->HasOwner(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_IsPet); +XS(XS_Mob_IsPet) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::IsPet(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->IsPet(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_HasPet); +XS(XS_Mob_HasPet) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::HasPet(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->HasPet(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_IsSilenced); +XS(XS_Mob_IsSilenced) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::IsSilenced(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->IsSilenced(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Mob_IsAmnesiad); +XS(XS_Mob_IsAmnesiad) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::IsAmnesiad(THIS)"); + { + Mob* THIS; + bool RETVAL; + 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."); + + RETVAL = THIS->IsAmnesiad(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -8803,6 +9294,25 @@ XS(boot_Mob) newXSproto(strcpy(buf, "CanClassEquipItem"), XS_Mob_CanClassEquipItem, file, "$$"); newXSproto(strcpy(buf, "IsFeared"), XS_Mob_IsFeared, file, "$"); newXSproto(strcpy(buf, "IsBlind"), XS_Mob_IsBlind, file, "$"); + newXSproto(strcpy(buf, "SeeInvisible"), XS_Mob_SeeInvisible, file, "$"); + newXSproto(strcpy(buf, "SeeInvisibleUndead"), XS_Mob_SeeInvisibleUndead, file, "$"); + newXSproto(strcpy(buf, "SeeHide"), XS_Mob_SeeHide, file, "$"); + newXSproto(strcpy(buf, "SeeImprovedHide"), XS_Mob_SeeImprovedHide, file, "$"); + newXSproto(strcpy(buf, "GetNimbusEffect1"), XS_Mob_GetNimbusEffect1, file, "$"); + newXSproto(strcpy(buf, "GetNimbusEffect2"), XS_Mob_GetNimbusEffect2, file, "$"); + newXSproto(strcpy(buf, "GetNimbusEffect3"), XS_Mob_GetNimbusEffect3, file, "$"); + newXSproto(strcpy(buf, "IsTargetable"), XS_Mob_IsTargetable, file, "$"); + newXSproto(strcpy(buf, "HasShieldEquiped"), XS_Mob_HasShieldEquiped, file, "$"); + newXSproto(strcpy(buf, "HasTwoHandBluntEquiped"), XS_Mob_HasTwoHandBluntEquiped, file, "$"); + newXSproto(strcpy(buf, "HasTwoHanderEquipped"), XS_Mob_HasTwoHanderEquipped, file, "$"); + newXSproto(strcpy(buf, "GetHerosForgeModel"), XS_Mob_GetHerosForgeModel, file, "$$"); + newXSproto(strcpy(buf, "IsEliteMaterialItem"), XS_Mob_IsEliteMaterialItem, file, "$$"); + newXSproto(strcpy(buf, "GetBaseSize"), XS_Mob_GetBaseSize, file, "$"); + newXSproto(strcpy(buf, "HasOwner"), XS_Mob_HasOwner, file, "$"); + newXSproto(strcpy(buf, "IsPet"), XS_Mob_IsPet, file, "$"); + newXSproto(strcpy(buf, "HasPet"), XS_Mob_HasPet, file, "$"); + newXSproto(strcpy(buf, "IsSilenced"), XS_Mob_IsSilenced, file, "$"); + newXSproto(strcpy(buf, "IsAmnesiad"), XS_Mob_IsAmnesiad, file, "$"); XSRETURN_YES; } From 8133f5312f9ef8980ca33b8f12a6beb602338f86 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 21 Dec 2015 05:27:20 -0800 Subject: [PATCH 456/846] First step into implementing evolving items, added fields to database that were missing. --- changelog.txt | 7 +++++++ common/item_fieldlist.h | 4 ++++ common/item_struct.h | 4 ++++ common/patches/rof.cpp | 10 +++++----- common/patches/rof2.cpp | 10 +++++----- common/patches/uf.cpp | 10 +++++----- common/patches/uf_structs.h | 2 +- common/shareddb.cpp | 5 ++++- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../git/required/2015_12_21_items_updates_evoitem.sql | 8 ++++++++ 11 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 utils/sql/git/required/2015_12_21_items_updates_evoitem.sql diff --git a/changelog.txt b/changelog.txt index c64baec6c..2ce2a68ad 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 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 + items in your shared bank. (but item field located on items table) + -NYI - SkillModMax: Max skill point modification from the percent mods. EX: + 100% 2HSlashing (Max 50) - can only increase 2hslash by 50 MAX! (item field located though) + == 12/19/2015 == Kinglykrab: Added many methods to Perl and Lua, list below: - SeeInvisible() diff --git a/common/item_fieldlist.h b/common/item_fieldlist.h index 1b3fe0cb0..665783498 100644 --- a/common/item_fieldlist.h +++ b/common/item_fieldlist.h @@ -41,6 +41,7 @@ F(ac) F(deity) F(skillmodvalue) F(UNK033) +F(skillmodmax) F(skillmodtype) F(banedmgrace) F(banedmgamt) @@ -172,7 +173,10 @@ F(bardlevel) F(questitemflag) F(svcorruption) F(purity) +F(evoitem) +F(evoid) F(evolvinglevel) +F(evomax) F(backstabdmg) F(dsmitigation) F(heroic_str) diff --git a/common/item_struct.h b/common/item_struct.h index 64292f490..ba8afcd14 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -130,6 +130,7 @@ struct Item_Struct { 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 @@ -218,7 +219,10 @@ struct Item_Struct { // Begin SoF Fields int32 SVCorruption; uint32 Purity; + uint8 EvolvingItem; + uint32 EvolvingID; uint8 EvolvingLevel; + uint8 EvolvingMax; uint32 BackstabDmg; uint32 DSMitigation; int32 HeroicStr; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 79c7271fd..76d62e3a4 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5231,19 +5231,19 @@ namespace RoF hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; - hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; + hdr.isEvolving = item->EvolvingItem; ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); - if (item->EvolvingLevel > 0) { + if (item->EvolvingItem > 0) { RoF::structs::EvolvingItem evotop; evotop.unknown001 = 0; evotop.unknown002 = 0; evotop.unknown003 = 0; evotop.unknown004 = 0; evotop.evoLevel = item->EvolvingLevel; - evotop.progress = 95.512; + evotop.progress = 0; evotop.Activated = 1; - evotop.evomaxlevel = 7; + evotop.evomaxlevel = item->EvolvingMax; ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON @@ -5353,7 +5353,7 @@ namespace RoF ibs.Races = item->Races; ibs.Deity = item->Deity; ibs.SkillModValue = item->SkillModValue; - ibs.SkillModMax = 0xffffffff; + ibs.SkillModMax = item->SkillModMax; ibs.SkillModType = (int8)(item->SkillModType); ibs.SkillModExtra = 0; ibs.BaneDmgRace = item->BaneDmgRace; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index e5cc77791..a8b231300 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -5432,19 +5432,19 @@ namespace RoF2 hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; - hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; + hdr.isEvolving = item->EvolvingItem; ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); - if (item->EvolvingLevel > 0) { + if (item->EvolvingItem > 0) { RoF2::structs::EvolvingItem evotop; evotop.unknown001 = 0; evotop.unknown002 = 0; evotop.unknown003 = 0; evotop.unknown004 = 0; evotop.evoLevel = item->EvolvingLevel; - evotop.progress = 95.512; + evotop.progress = 0; evotop.Activated = 1; - evotop.evomaxlevel = 7; + evotop.evomaxlevel = item->EvolvingMax; ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON @@ -5554,7 +5554,7 @@ namespace RoF2 ibs.Races = item->Races; ibs.Deity = item->Deity; ibs.SkillModValue = item->SkillModValue; - ibs.SkillModMax = 0xffffffff; + ibs.SkillModMax = item->SkillModMax; ibs.SkillModType = (int8)(item->SkillModType); ibs.SkillModExtra = 0; ibs.BaneDmgRace = item->BaneDmgRace; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 0e88a2a09..3535503a0 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -3835,19 +3835,19 @@ namespace UF hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; - hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; + hdr.isEvolving = item->EvolvingItem; ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader)); - if (item->EvolvingLevel > 0) { + if (item->EvolvingItem > 0) { UF::structs::EvolvingItem evotop; evotop.unknown001 = 0; evotop.unknown002 = 0; evotop.unknown003 = 0; evotop.unknown004 = 0; evotop.evoLevel = item->EvolvingLevel; - evotop.progress = 95.512; + evotop.progress = 0; evotop.Activated = 1; - evotop.evomaxlevel = 7; + evotop.evomaxlevel = item->EvolvingMax; ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON - @@ -3947,7 +3947,7 @@ namespace UF ibs.Races = item->Races; ibs.Deity = item->Deity; ibs.SkillModValue = item->SkillModValue; - ibs.unknown5 = 0; + ibs.SkillModMax = item->SkillModMax; ibs.SkillModType = item->SkillModType; ibs.BaneDmgRace = item->BaneDmgRace; ibs.BaneDmgBody = item->BaneDmgBody; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 3631edea3..7f3a7dcc0 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -4103,7 +4103,7 @@ struct ItemBodyStruct uint32 Races; uint32 Deity; int32 SkillModValue; - uint32 unknown5; + uint32 SkillModMax; uint32 SkillModType; uint32 BaneDmgRace; uint32 BaneDmgBody; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 59a2a118b..751093eaf 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -878,7 +878,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ item.AC = (int32)atoul(row[ItemField::ac]); item.Deity = (uint32)atoul(row[ItemField::deity]); item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]); - + item.SkillModMax = (int32)atoul(row[ItemField::skillmodmax]); item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]); item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]); item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]); @@ -1020,7 +1020,10 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ item.QuestItemFlag = (atoi(row[ItemField::questitemflag])==0) ? false : true; item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]); item.Purity = (uint32)atoul(row[ItemField::purity]); + item.EvolvingItem = (uint8)atoul(row[ItemField::evoitem]); + item.EvolvingID = (uint8)atoul(row[ItemField::evoid]); item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]); + item.EvolvingMax = (uint8)atoul(row[ItemField::evomax]); item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]); item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]); item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]); diff --git a/common/version.h b/common/version.h index c3dfa1c26..b2dd26212 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 9092 +#define CURRENT_BINARY_DATABASE_VERSION 9093 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index adc9009c2..db4078eb5 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -346,6 +346,7 @@ 9090|2015_12_01_spell_scribe_restriction_rule.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Character:RestrictSpellScribing'|empty| 9091|2015_12_07_command_settings.sql|SHOW TABLES LIKE 'command_settings'|empty| 9092|2015_12_17_eqtime.sql|SHOW TABLES LIKE 'eqtime'|empty| +9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|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/2015_12_21_items_updates_evoitem.sql b/utils/sql/git/required/2015_12_21_items_updates_evoitem.sql new file mode 100644 index 000000000..195df8a87 --- /dev/null +++ b/utils/sql/git/required/2015_12_21_items_updates_evoitem.sql @@ -0,0 +1,8 @@ +ALTER TABLE `items` + ADD COLUMN `evoitem` INT(11) NOT NULL DEFAULT '0' AFTER `purity`, + ADD COLUMN `evoid` INT(11) NOT NULL DEFAULT '0' AFTER `evoitem`, + ADD COLUMN `evomax` INT(11) NOT NULL DEFAULT '0' AFTER `evolvinglevel`, + CHANGE `UNK038` `skillmodmax` INT(11) NOT NULL DEFAULT '0', + CHANGE `UNK222` `heirloom` INT(11) NOT NULL DEFAULT '0', + CHANGE `UNK235` `placeable` INT(11) NOT NULL DEFAULT '0', + CHANGE `UNK242` `epicitem` INT(11) NOT NULL DEFAULT '0'; \ No newline at end of file From fc33a10ec07e5db61aa366e54c0d5ec2a6526e73 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 21 Dec 2015 07:36:14 -0800 Subject: [PATCH 457/846] Change GetSkill to use SkillModMax for clients --- zone/bonuses.cpp | 1 + zone/client.h | 2 +- zone/common.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 3aa9cc4a1..f8edee26d 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -490,6 +490,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) { newbon->skillmod[item->SkillModType] = item->SkillModValue; + newbon->skillmodmax[item->SkillModType] = item->SkillModMax; } } diff --git a/zone/client.h b/zone/client.h index b5d3728e1..6db22c5b0 100644 --- a/zone/client.h +++ b/zone/client.h @@ -679,7 +679,7 @@ public: void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= 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) ? m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100 : m_pp.skills[skill_id]); } return 0; } + 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; diff --git a/zone/common.h b/zone/common.h index a637e94bd..48749dbc3 100644 --- a/zone/common.h +++ b/zone/common.h @@ -278,6 +278,7 @@ struct StatBonuses { float AggroRange; // when calculate just replace original value with this float AssistRange; int32 skillmod[HIGHEST_SKILL+1]; + int32 skillmodmax[HIGHEST_SKILL+1]; int effective_casting_level; int reflect_chance; // chance to reflect incoming spell uint32 singingMod; From 7ad33f2445faa8cab9c08b8a4b9c52b3e7015e5c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 21 Dec 2015 12:33:32 -0500 Subject: [PATCH 458/846] Fix formatting --- common/shareddb.cpp | 422 ++++++++++++++++++++++---------------------- 1 file changed, 211 insertions(+), 211 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 751093eaf..129584159 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -802,264 +802,264 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { 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); +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 ndbuffer[4]; bool disableNoRent = false; - if(GetVariable("disablenorent", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { + 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') { + 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') { + 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') { + if (GetVariable("disablenotransfer", ndbuffer, 4)) { + if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { disableNoTransfer = true; } } - Item_Struct item; + Item_Struct item; const std::string query = "SELECT source," -#define F(x) "`"#x"`," +#define F(x) "`" #x "`," #include "item_fieldlist.h" #undef F "updated FROM items ORDER BY id"; auto results = QueryDatabase(query); - if (!results.Success()) { - return; - } + if (!results.Success()) { + return; + } - for(auto row = results.begin(); row != results.end(); ++row) { - memset(&item, 0, sizeof(Item_Struct)); + for (auto row = results.begin(); row != results.end(); ++row) { + 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.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.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.SkillModMax = (int32)atoul(row[ItemField::skillmodmax]); - 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.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.MaxCharges = (int16)atoi(row[ItemField::maxcharges]); - item.ItemType = (uint8)atoi(row[ItemField::itemtype]); + item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]); + item.ItemType = (uint8)atoi(row[ItemField::itemtype]); item.Material = (uint8)atoi(row[ItemField::material]); item.HerosForgeModel = (uint32)atoi(row[ItemField::herosforgemodel]); - item.SellRate = (float)atof(row[ItemField::sellrate]); - 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]); + item.SellRate = (float)atof(row[ItemField::sellrate]); + 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]); + 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.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.AugSlotType[5] = (uint8)atoi(row[ItemField::augslot6type]); item.AugSlotVisible[5] = (uint8)atoi(row[ItemField::augslot6visible]); item.AugSlotUnk2[5] = 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]); + 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]); + 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]); + 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]); + strcpy(item.CharmFile, row[ItemField::charmfile]); - item.Proc.Effect = (int32)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 = (int32)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 = (int32)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 = (int32)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 = (int32)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.Proc.Effect = (int32)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 = (int32)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 = (int32)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 = (int32)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 = (int32)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.EvolvingItem = (uint8)atoul(row[ItemField::evoitem]); item.EvolvingID = (uint8)atoul(row[ItemField::evoid]); - item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]); + item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]); item.EvolvingMax = (uint8)atoul(row[ItemField::evomax]); - 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]); + 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) { - Log.Out(Logs::General, Logs::Error, "Database::LoadItems: %s", ex.what()); - break; - } - } + 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) { + Log.Out(Logs::General, Logs::Error, "Database::LoadItems: %s", ex.what()); + break; + } + } } const Item_Struct* SharedDatabase::GetItem(uint32 id) { From c168d7b7b6f87d5c942fe1acfa69429d85836f43 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 21 Dec 2015 12:41:49 -0500 Subject: [PATCH 459/846] Fix macro hack? [skip ci] --- common/shareddb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 129584159..fe4ad1b5d 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -835,7 +835,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ Item_Struct item; const std::string query = "SELECT source," -#define F(x) "`" #x "`," +#define F(x) "`"#x"`," #include "item_fieldlist.h" #undef F "updated FROM items ORDER BY id"; From 9a1271805a3c41850fa8759ed5079c667900cf22 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 21 Dec 2015 15:43:56 -0500 Subject: [PATCH 460/846] Added GetMeleeMitigation() to Perl and Lua for Mobs (Clients/NPCs). --- changelog.txt | 2 ++ zone/lua_mob.cpp | 8 +++++++- zone/lua_mob.h | 1 + zone/mob.cpp | 8 ++++++++ zone/mob.h | 1 + zone/perl_mob.cpp | 28 ++++++++++++++++++++++++++++ 6 files changed, 47 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 2ce2a68ad..74b6ab113 100644 --- a/changelog.txt +++ b/changelog.txt @@ -6,6 +6,8 @@ Natedog: Updated item table fields and added a few missing fields for evolving i items in your shared bank. (but item field located on items table) -NYI - SkillModMax: Max skill point modification from the percent mods. EX: 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: diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 469e8cb2f..46b6b4a9b 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1976,6 +1976,11 @@ bool Lua_Mob::IsAmnesiad() { return self->IsAmnesiad(); } +int32 Lua_Mob::GetMeleeMitigation() { + Lua_Safe_Call_Int(); + return self->GetMeleeMitigation(); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2317,7 +2322,8 @@ luabind::scope lua_register_mob() { .def("IsPet", (bool(Lua_Mob::*)(void))&Lua_Mob::IsPet) .def("HasPet", (bool(Lua_Mob::*)(void))&Lua_Mob::HasPet) .def("IsSilenced", (bool(Lua_Mob::*)(void))&Lua_Mob::IsSilenced) - .def("IsAmnesiad", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAmnesiad); + .def("IsAmnesiad", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAmnesiad) + .def("GetMeleeMitigation", (int32(Lua_Mob::*)(void))&Lua_Mob::GetMeleeMitigation); } luabind::scope lua_register_special_abilities() { diff --git a/zone/lua_mob.h b/zone/lua_mob.h index c7530e391..4009ae2fa 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -377,6 +377,7 @@ public: bool HasPet(); bool IsSilenced(); bool IsAmnesiad(); + int32 GetMeleeMitigation(); }; #endif diff --git a/zone/mob.cpp b/zone/mob.cpp index 6e778f004..e28ccefcc 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5682,3 +5682,11 @@ void Mob::SetCurrentSpeed(int in){ } } } + +int32 Mob::GetMeleeMitigation() { + int32 mitigation = 0; + mitigation += spellbonuses.MeleeMitigationEffect; + mitigation += itembonuses.MeleeMitigationEffect; + mitigation += aabonuses.MeleeMitigationEffect; + return mitigation; +} \ No newline at end of file diff --git a/zone/mob.h b/zone/mob.h index d02e0f089..8fc7e7f08 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -752,6 +752,7 @@ public: inline bool GetInvul(void) { return invulnerable; } inline void SetExtraHaste(int Haste) { ExtraHaste = Haste; } virtual int GetHaste(); + int32 GetMeleeMitigation(); uint8 GetWeaponDamageBonus(const Item_Struct* weapon, bool offhand = false); uint16 GetDamageTable(SkillUseTypes skillinuse); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 2b2442fe6..40077c2c5 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8981,6 +8981,33 @@ XS(XS_Mob_IsAmnesiad) { XSRETURN(1); } +XS(XS_Mob_GetMeleeMitigation); +XS(XS_Mob_GetMeleeMitigation) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::GetMeleeMitigation(THIS)"); + { + Mob* THIS; + int32 RETVAL; + dXSTARG; + + 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."); + + RETVAL = THIS->GetMeleeMitigation(); + XSprePUSH; + PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -9313,6 +9340,7 @@ XS(boot_Mob) newXSproto(strcpy(buf, "HasPet"), XS_Mob_HasPet, file, "$"); newXSproto(strcpy(buf, "IsSilenced"), XS_Mob_IsSilenced, file, "$"); newXSproto(strcpy(buf, "IsAmnesiad"), XS_Mob_IsAmnesiad, file, "$"); + newXSproto(strcpy(buf, "GetMeleeMitigation"), XS_Mob_GetMeleeMitigation, file, "$"); XSRETURN_YES; } From 7223f2da067dc4fc6ed1e248e25c0b847431ec37 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Dec 2015 15:31:38 -0600 Subject: [PATCH 461/846] Add 13th floor item import script (Natedog/Akkadius) [skip ci] --- utils/scripts/import_13th_floor.pl | 245 +++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 utils/scripts/import_13th_floor.pl diff --git a/utils/scripts/import_13th_floor.pl b/utils/scripts/import_13th_floor.pl new file mode 100644 index 000000000..1478de4c2 --- /dev/null +++ b/utils/scripts/import_13th_floor.pl @@ -0,0 +1,245 @@ +######################################################################## +#::: 13th floor import script +#::: Current Source: http://items.sodeq.org/download.php +#::: Authors: (Natedog, Akkadius) +######################################################################## + +use DBI; +use DBD::mysql; + +my $database_name = ""; +my $total_items = 0; +my $read_items_file = "items.txt"; #default +my $dbh = LoadMysql(); + +read_items_file_from_13th_floor_text(); +update_items_table(); + +sub LoadMysql{ + #::: Config Variables + my $confile = "eqemu_config.xml"; + open(F, "<$confile") or die "Unable to open config: $confile\n"; + 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; } + } + $database_name = $db; + #::: DATA SOURCE NAME + $dsn = "dbi:mysql:$db:localhost:3306"; + #::: PERL DBI CONNECT + $connect = DBI->connect($dsn, $user, $pass); + return $connect; +} + +sub read_items_file_from_13th_floor_text { + + #::: Read from file and place into array + open(F, "<" . $read_items_file) or die "Unable to open itemfile: " . $read_items_file . "\n"; + my @item_file_lines = ; + close(F); + + #::: Chomp this array... + my @newitem_file_lines; + chomp($item_file_lines[0]); + @fields = split("(?prepare("SHOW TABLES LIKE 'items_floor'"); + $sth->execute(); + my $has_items_floor = $sth->fetchrow_array(); + + #::: If we have items_floor + if ($has_items_floor eq '') { + $dbh->do("CREATE TABLE `items_floor` (`" . join("` VARCHAR(64) NOT NULL DEFAULT '', `", @fields). "` VARCHAR(64) NOT NULL DEFAULT '', UNIQUE INDEX `ID` (`id`)) COLLATE='latin1_swedish_ci' ENGINE=MyISAM"); + $dbh->do("ALTER TABLE `items_floor` CHANGE `id` `id` INT(11) NOT NULL DEFAULT '0'"); + printf "Database items_floor created\n"; + } + + #::: Create REPLACE INTO header and define worker variables... + $master_insert = "REPLACE INTO `items_floor` (" . join(",", @fields) . ") VALUES "; + $query_insert_ph = ""; #::: Used for building placeholder values in query Ex: (?, ?, ?) + @field_values = (); #::: Used for stuffing mysql field values + $query_count = 0; #::: Used for chunking query updates + $print_cycle = 0; #::: Counter for console updates + $start_time = time(); #::: Start time for import + $total_items_file = scalar(grep $_, @item_file_lines) - 1; #::: Total items in text file + + #::: Iterate through each item in items.txt + for (1 .. $#item_file_lines) { + @f = split("(? 500){ + $query_insert_ph = substr($query_insert_ph, 0, -2); + $dbh->prepare($master_insert . " " . $query_insert_ph)->execute(@field_values); + $query_count = 0; + $query_insert_ph = ""; + @field_values = (); + } + + #::: Print updates to console + if($print_cycle > 25){ + print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r"; + $print_cycle = 0; + } + + #::: Counters + $total_items++; + $query_count++; + $print_cycle++; + } + + #::: One last processing print + print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r"; + + printf "\n" . $total_items . " items added to database... Took " . (time() - $start_time) . " second(s)... \n"; +} + +sub update_items_table { + + #::: Keep Items table sane + $query_handle = $dbh->prepare(" + ALTER TABLE `items` + MODIFY COLUMN `UNK132` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL; + "); + $query_handle->execute(); + + my @matching_table; + my @missing_items_table; + my @missing_items_floor_table; + + #::: Get columns from `items` + my $sth = $dbh->prepare("SHOW COLUMNS FROM `items`;"); + $sth->execute(); + my @items_table; + while (my @row = $sth->fetchrow_array()) { + push(@items_table, $row[0]); + } + + #::: Get columns from `items_floor` + $sth2 = $dbh->prepare("SHOW COLUMNS FROM `items_floor`"); + $sth2->execute(); + my @items_floor_table; + while (my @row = $sth2->fetchrow_array()) { + push(@items_floor_table, $row[0]); + } + + #::: Go through the original items table columns and line them up with what columns match on 13th floor + #::: This is so we can use the matching columns to update and insert item data into `items` table + foreach $value (@items_table) { + if ( grep( /^$value$/i, @items_floor_table ) ) { + push(@matching_table, $value); + } else { + #::: What values are we missing from EMU items table.. + push(@missing_items_table, $value); + } + } + + #::: What values are we missing from.. 13thFloor + foreach $value (@items_floor_table) { + if ( grep( /^$value$/i, @items_table ) ) { + #DO NOTHING... + } else { + push(@missing_items_floor_table, $value); + } + } + + #::: Go through the matched columns and build our query strings... + + my $items_field_list = ""; #::: Build the field list for the INSERT (field1, field2) + my $items_floor_field_list = ""; #::: What fields we will select from items_floor table to insert into items (matched columns) + my $update_fields = ""; #::: To update an existing item entry if it exists... + + foreach $match (@matching_table) { + $match = lc($match); + $update_fields .= "`" . $match . "` = fi.`" . $match . "`, "; + $items_field_list .= "`" . $match . "`, "; + $items_floor_field_list .= "fi.`" . $match . "`, "; + } + #::: Trim ', ' off the ends + $update_fields = substr($update_fields, 0, -2); + $items_field_list = substr($items_field_list, 0, -2); + $items_floor_field_list = substr($items_floor_field_list, 0, -2); + + #::: Mixed up fields... + $items_floor_field_list =~ s/booktype/booklang/g; #our booktype is mixed with theirs... + $update_fields =~ s/`booktype` = fi.`booktype`/`booktype` = fi.`booklang`/g; + + #::: FIELDS THAT DO NOT MATCH GO HERE + my @items_add = ( + "casttime_", "endur", "range", "attuneable", "evolvinglevel", "herosforgemodel", "scrolltype", + "scriptfileid", "powersourcecapacity", "augslot1unk2", "augslot2unk2", "augslot3unk2", "augslot4unk2", + "augslot5unk2", "augslot6unk2", "recskill", "book" + ); + my @items_floor_add = ( + "foodduration", "endurance", "therange", "attunable", "evolvl", "heroforge1", "scrolleffecttype", + "rightclickscriptid", "powersourcecap", "augslot1unk", "augslot2unk", "augslot3unk", "augslot4unk", + "augslot5unk", "augslot6unk", "reqskill", "booktype" + ); + + #::: Match the mis-matched fields... + my $spot = 0; + foreach $value (@items_add) { + $items_field_list .= ", `" . $value . "`"; + $update_fields .= ", `" . $value . "` = fi.`" . $items_floor_add[$spot] . "`"; + $spot++; + @missing_items_table = grep {$_ ne $value} @missing_items_table; + } + foreach $value (@items_floor_add) { + $items_floor_field_list .= ", fi.`" . $value . "`"; + @missing_items_floor_table = grep {$_ ne $value} @missing_items_floor_table; + } + + my $update_query = " + INSERT INTO items (" . $items_field_list . ") + SELECT " . $items_floor_field_list . " + FROM items_floor fi + ON DUPLICATE KEY UPDATE " . $update_fields; + + #::: Print missing fields to file + my $write_file = "missing_item_fields.txt"; + + open(F, ">$write_file") or die "Unable to open questfile: $write_file\n"; + print F "$update_query \n\n"; + print F "EQEMU items Table missing fields\n"; + foreach $value (@missing_items_table) { + print F "$value\n"; + } + print F "\n\n13thFloor items Table missing fields\n"; + foreach $value (@missing_items_floor_table) { + print F "$value\n"; + } + close(F); + + #::: Number of rows affected by query + $rows = $dbh->do($update_query); + + #::: Update stackables + $dbh->do("UPDATE items i SET i.stackable = 1 WHERE i.stacksize > 1"); + + print "Added all new items to Items table (" . $rows . ")!\n"; + +} + +sub trim($) { + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} \ No newline at end of file From 4b2f12cd67b547f58f9f6d0849f1dce63e204f75 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Dec 2015 15:32:59 -0600 Subject: [PATCH 462/846] Linux-ify 13th floor script [skip ci] --- utils/scripts/import_13th_floor.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/scripts/import_13th_floor.pl b/utils/scripts/import_13th_floor.pl index 1478de4c2..4c50eca7f 100644 --- a/utils/scripts/import_13th_floor.pl +++ b/utils/scripts/import_13th_floor.pl @@ -1,3 +1,5 @@ +#! /usr/bin/perl + ######################################################################## #::: 13th floor import script #::: Current Source: http://items.sodeq.org/download.php From dc58173f158f83e70e40e500ce657e1b5ce7b3c7 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Dec 2015 01:04:27 -0600 Subject: [PATCH 463/846] Remove unused script since we have a newer one now [skip ci] --- utils/scripts/load_13thfloor_items.pl | 77 --------------------------- 1 file changed, 77 deletions(-) delete mode 100644 utils/scripts/load_13thfloor_items.pl diff --git a/utils/scripts/load_13thfloor_items.pl b/utils/scripts/load_13thfloor_items.pl deleted file mode 100644 index 03fbfe5fb..000000000 --- a/utils/scripts/load_13thfloor_items.pl +++ /dev/null @@ -1,77 +0,0 @@ -#! /usr/bin/perl - -use DBI; -use Getopt::Std; - -getopts('d:h'); -$conf = "eqemu_config.xml"; -if($opt_h) { - die "Usage: load_13thfloor_items.pl [-d path/to/eqemu_config.xml]\n"; -} -if($opt_d) { - $conf = $opt_d; -} - -$db = "eq"; -$user = "eq"; -$pass = "eq"; -$host = "localhost"; -open(F, "<$conf") or die "Unable to open config $conf\n"; -$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(!$db || !$user || !$pass || !$host) { - die "Invalid db.ini, missing one of: host, user, password, database\n"; -} - -$source="DBI:mysql:database=$db;host=$host"; - -my $dbh = DBI->connect($source, $user, $pass) || die "Could not create db handle\n"; - -$_=; -chomp(); -s/'/\\'/g; -@fields=split("(? "itemuse" -); - -$insert="replace into items (".join(",",@fields).",source,updated) values ('"; -$insert=~s/UNK130/potionbeltslots/; -$insert=~s/UNK133/stackable/; - -#select(STDOUT); $|=1; -while() { - chomp(); - s/'/\\'/g; - @f=split("(?do($statement); - printf("Processing: %d %s \r",$f[4],$f[1]); - ++$count; -} -printf("Processed: %d items(s) \n",$count); - From 3a7d7c727f323733d5f1dda8b1c3a709c68ff9ed Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 26 Dec 2015 13:29:34 -0500 Subject: [PATCH 464/846] AA updates [skip ci] --- utils/sql/git/optional/2015_12_26_oow_aa_missing.sql | 3 +++ utils/sql/peq_aa_tables_post_rework.sql | 6 ++++++ 2 files changed, 9 insertions(+) create mode 100644 utils/sql/git/optional/2015_12_26_oow_aa_missing.sql diff --git a/utils/sql/git/optional/2015_12_26_oow_aa_missing.sql b/utils/sql/git/optional/2015_12_26_oow_aa_missing.sql new file mode 100644 index 000000000..50e3aade3 --- /dev/null +++ b/utils/sql/git/optional/2015_12_26_oow_aa_missing.sql @@ -0,0 +1,3 @@ +INSERT INTO `aa_ranks` (`id`, `upper_hotkey_sid`, `lower_hotkey_sid`, `title_sid`, `desc_sid`, `cost`, `level_req`, `spell`, `spell_type`, `recast_time`, `expansion`, `prev_id`, `next_id`) VALUES (1015, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1014, 1016); + +INSERT INTO `aa_rank_effects` (`rank_id`, `slot`, `effect_id`, `base1`, `base2`) VALUES (1015, 1, 262, 40, 7), (1015, 2, 262, 40, 8), (1015, 3, 262, 40, 9), (1015, 4, 262, 40, 10), (1015, 5, 262, 40, 11); diff --git a/utils/sql/peq_aa_tables_post_rework.sql b/utils/sql/peq_aa_tables_post_rework.sql index 53d465778..9d3b05eaf 100644 --- a/utils/sql/peq_aa_tables_post_rework.sql +++ b/utils/sql/peq_aa_tables_post_rework.sql @@ -2532,6 +2532,7 @@ INSERT INTO `aa_ranks` (`id`, `upper_hotkey_sid`, `lower_hotkey_sid`, `title_sid (1012, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1011, 1013), (1013, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1012, 1014), (1014, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1013, 1015), + (1015, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1014, 1016), (1016, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1015, -1), (1017, 1017, 1017, 1017, 1017, 6, 59, 16531, 75, 15, 15, -1, 13726), (1018, 1018, 1018, 1018, 1018, 2, 63, 16455, 69, 1, 15, -1, -1), @@ -9526,6 +9527,11 @@ INSERT INTO `aa_rank_effects` (`rank_id`, `slot`, `effect_id`, `base1`, `base2`) (1014, 3, 262, 32, 9), (1014, 4, 262, 32, 10), (1014, 5, 262, 32, 11), + (1015, 1, 262, 40, 7), + (1015, 2, 262, 40, 8), + (1015, 3, 262, 40, 9), + (1015, 4, 262, 40, 10), + (1015, 5, 262, 40, 11), (1016, 1, 262, 50, 7), (1016, 2, 262, 50, 8), (1016, 3, 262, 50, 9), From 1b4dbd1ce7003c031c6804ebf8f2dc534b2f39ea Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 27 Dec 2015 17:26:39 -0600 Subject: [PATCH 465/846] Adjust import_13th_floor.pl to flip slots 21 and 22 [skip ci] --- utils/scripts/import_13th_floor.pl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/utils/scripts/import_13th_floor.pl b/utils/scripts/import_13th_floor.pl index 4c50eca7f..6a66892f9 100644 --- a/utils/scripts/import_13th_floor.pl +++ b/utils/scripts/import_13th_floor.pl @@ -111,6 +111,14 @@ sub read_items_file_from_13th_floor_text { print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r"; printf "\n" . $total_items . " items added to database... Took " . (time() - $start_time) . " second(s)... \n"; + + print "Flipping slots 21 and 22..."; + $rows_affected = $dbh->prepare(" + UPDATE `items_floor` + SET `slots` = (`slots` ^ 6291456) + WHERE (`slots` & 6291456) + IN (2097152, 4194304)")->execute(); + print " Rows affected (" . $rows_affected . ")\n"; } sub update_items_table { From e423165bcb6fdb023e2c210f2bba34c4dfb447d2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 28 Dec 2015 02:25:01 -0600 Subject: [PATCH 466/846] DB Update System :: Implement SVN updates into the manifest (To support older databases) [skip ci] --- utils/sql/db_update_manifest.txt | 356 +++++++++++++++---------------- 1 file changed, 178 insertions(+), 178 deletions(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index db4078eb5..f62c89fbb 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -1,261 +1,261 @@ -5001|1_task_system.sql +5001|1_task_system.sql|SHOW TABLES LIKE 'tasks'|empty| # 5002|2_optional_maxclients.sql # 5003|14_optional_merchantlist.sql -5004|35_task_stepped.sql -5005|42_task_min_maxlevel.sql -5006|55_zone_shutdowndeleay.sql +5004|35_task_stepped.sql|SHOW COLUMNS FROM `tasks` LIKE 'stepped'|not_empty| +5005|42_task_min_maxlevel.sql|SHOW COLUMNS FROM `tasks` LIKE 'minlevel'|empty| +5006|55_zone_shutdowndeleay.sql|SHOW COLUMNS FROM `zone` LIKE 'shutdowndelay'|empty| # 5007|68_optional_character_maxexplevel.sql # 5008|103_optional_chat_rules.sql -5009|104_traps.sql +5009|104_traps.sql|SHOW COLUMNS FROM `traps` LIKE 'respawn_time'|empty| # 5010|106_optional_proc_rules.sql -5011|120_damageshieldtypes.sql -5012|125_aggrozone.sql +5011|120_damageshieldtypes.sql|SHOW TABLES LIKE 'damageshieldtypes'|empty| +# 5012|125_aggrozone.sql # 5013|127_optional_spell_rules.sql # 5014|129_optional_shared_plat_rule.sql # 5015|131_optional_combat_rules.sql -5016|133_task_repeatable.sql -5017|142_deathpeace_and_lifetap_aas.sql +5016|133_task_repeatable.sql|SHOW COLUMNS FROM `tasks` LIKE 'repeatable'|empty| +5017|142_deathpeace_and_lifetap_aas.sql|SELECT * FROM db_version WHERE version > 5016|empty| # 5018|158_optional_death_exp_loss.sql -5019|176_melody.sql -5020|189_character_.sql -5021|196_trader.sql -5022|210_undyeme.sql -5023|222_buyer.sql -5024|226_account_limiting.sql -5025|230_spells_table.sql -5026|235_horses_table.sql -5027|243_spawn_timers.sql -5028|247_mail.sql -5029|249_chatchannels.sql -5030|250_bot_spell_update.sql +# 5019|176_melody.sql +5020|189_character_.sql|SELECT * FROM db_version WHERE version >= 5020|empty| +5021|196_trader.sql|SHOW TABLES LIKE 'trader'|empty| +# 5022|210_undyeme.sql +5023|222_buyer.sql|SHOW TABLES LIKE 'buyer'|empty| +# 5024|226_account_limiting.sql +5025|230_spells_table.sql|SHOW TABLES LIKE 'spells_new'|empty| +5026|235_horses_table.sql|SHOW TABLES LIKE 'horses'|empty| +5027|243_spawn_timers.sql|SHOW TABLES LIKE 'respawn_times'|empty| +5028|247_mail.sql|SHOW TABLES LIKE 'mail'|empty| +5029|249_chatchannels.sql|SHOW TABLES LIKE 'chatchannels'|empty| +# 5030|250_bot_spell_update.sql # 5031|250_optional_bot_spell_update.sql # 5032|285_optional_bot_spell_update.sql -5033|292_augslots.sql -5034|294_merchant_logging.sql -5035|304_faction_list.sql -5036|326_aas.sql -5037|328_bot_management.sql +# 5033|292_augslots.sql|SELECT * FROM db_version WHERE version >= 5033|empty| +5034|294_merchant_logging.sql|SHOW COLUMNS FROM `eventlog` LIKE 'event_nid'|empty| +5035|304_faction_list.sql|SHOW COLUMNS FROM `faction_list` LIKE 'mod_c16'|empty| +5036|326_aas.sql|SELECT * FROM db_version WHERE version > 5035|empty| +# 5037|328_bot_management.sql # 5038|328_optional_bot_management.sql -5039|340_gm_ips.sql -5040|356_combat.sql -5041|360_peqzone.sql -5042|364_ranged_dist_rule.sql -5043|386_bot_save_raid.sql +5039|340_gm_ips.sql|SHOW TABLES LIKE 'gm_ips'|empty| +# 5040|356_combat.sql +# 5041|360_peqzone.sql +# 5042|364_ranged_dist_rule.sql +# 5043|386_bot_save_raid.sql # 5044|434_optional_rest_state_rules.sql -5045|447_sof_startzone_rule.sql -5046|463_altadv_vars.sql -5047|475_aa_actions.sql -5048|500_spawn2_optimization.sql -5049|503_bugs.sql -5050|518_drakkin_npc_type_features.sql -5051|524_rule_values_notes.sql -5052|527_npc_armor_tint.sql -5053|553_saylink_table.sql -5054|564_nokeyring.sql -5055|600_group_leadership.sql -5056|612_instance_changes.sql -5057|615_adventure_assassination.sql -5058|619_Adventure_Recruiter_Flavor.sql -5059|621_LDoNTraps.sql -5060|633_ucs.sql -5061|634_TrapTemplateDefaultValue.sql -5062|643_BotsTable.sql -5063|646_archery_penalty_rule.sql -5064|665_heroic_resists.sql -5065|667_titles.sql -5066|687_aa_table_changes.sql -5067|699_peqzone_rule.sql -5068|702_aashieldblock_tint_table.sql -5069|703_peqzone_rule.sql -5070|704_rules.sql -5071|710_tint_set_naming.sql -5072|721_pathing_rules.sql -5073|730_smart_delay_moving.sql -5074|731_rule_assist_notarget_self.sql -5075|732_sacrifice_rules.sql -5076|745_slow_mitigation.sql -5077|754_archery_base_damage_rule.sql -5078|755_sof_altadv_vars_updates.sql -5079|773_monk_rules.sql +# 5045|447_sof_startzone_rule.sql +# 5046|463_altadv_vars.sql +# 5047|475_aa_actions.sql +5048|500_spawn2_optimization.sql|SELECT * FROM db_version WHERE version >= 5048|empty| +5049|503_bugs.sql|SHOW TABLES LIKE 'bugs'|empty| +5050|518_drakkin_npc_type_features.sql|SHOW TABLES LIKE 'bugs'|empty| +5051|524_rule_values_notes.sql|SELECT * FROM db_version WHERE version >= 5051|empty| +5052|527_npc_armor_tint.sql|SELECT * FROM db_version WHERE version >= 5052|empty| +5053|553_saylink_table.sql|SHOW TABLES LIKE 'saylink'|empty| +5054|564_nokeyring.sql|SHOW COLUMNS FROM `doors` LIKE 'nokeyring'|empty| +5055|600_group_leadership.sql|SELECT * FROM db_version WHERE version >= 5055|empty| +5056|612_instance_changes.sql|SELECT * FROM db_version WHERE version >= 5056|empty| +5057|615_adventure_assassination.sql|SELECT * FROM db_version WHERE version >= 5057|empty| +5058|619_Adventure_Recruiter_Flavor.sql|SELECT * FROM db_version WHERE version >= 5058|empty| +5059|621_LDoNTraps.sql|SHOW TABLES LIKE 'ldon_trap_templates'|empty| +5060|633_ucs.sql|SHOW TABLES LIKE 'friends'|empty| +5061|634_TrapTemplateDefaultValue.sql|SHOW COLUMNS FROM `npc_types` LIKE 'trap_template'|empty| +# 5062|643_BotsTable.sql +# 5063|646_archery_penalty_rule.sql +5064|665_heroic_resists.sql|SELECT * FROM db_version WHERE version >= 5064|empty| +5065|667_titles.sql|SHOW TABLES LIKE 'titles'|empty| +5066|687_aa_table_changes.sql|SELECT * FROM db_version WHERE version >= 5066|empty| +# 5067|699_peqzone_rule.sql +5068|702_aashieldblock_tint_table.sql|SHOW TABLES LIKE 'npc_types_tint'|empty| +# 5069|703_peqzone_rule.sql +# 5070|704_rules.sql +5071|710_tint_set_naming.sql|SELECT * FROM db_version WHERE version >= 5071|empty| +5072|721_pathing_rules.sql|SELECT * FROM db_version WHERE version >= 5072|empty| +# 5073|730_smart_delay_moving.sql +# 5074|731_rule_assist_notarget_self.sql +# 5075|732_sacrifice_rules.sql +5076|745_slow_mitigation.sql|SELECT * FROM db_version WHERE version >= 5076|empty| +# 5077|754_archery_base_damage_rule.sql +5078|755_sof_altadv_vars_updates.sql|SELECT * FROM db_version WHERE version >= 5078|empty| +# 5079|773_monk_rules.sql # 5080|853_optional_rule_aaexp.sql # 5081|858_optional_rule_ip_limit_by_status.sql # 5082|892_optional_bots_table_mod.sql # 5083|893_optional_bots_table_mod.sql -5084|898_npc_maxlevel_scalerate.sql +5084|898_npc_maxlevel_scalerate.sql|SHOW COLUMNS FROM `npc_types` LIKE 'maxlevel'|empty| # 5085|902_optional_rule_snareflee.sql -5086|923_spawn2_enabled.sql -5087|962_hot_zone.sql -5088|964_reports.sql -5089|971_veteran_rewards.sql -5090|977_raid_npc_private_corpses.sql -5091|979_unique_spawn_by_name.sql -5092|980_account_ip.sql -5093|1022_botadventuring.sql -5094|1027_botactives.sql -5095|1030_botzoningsupport.sql -5096|1036_botbuffs.sql -5097|1038_botpetstatepersists.sql -5098|1038_grouptablesuniquecolumndefinitions.sql -5099|1039_botguilds.sql -5100|1040_DeprecatedBotRaidsSystems.sql -5101|1057_titles.sql -5102|1077_botgroups.sql -5103|1136_spell_globals.sql +5086|923_spawn2_enabled.sql|SHOW COLUMNS FROM `spawn2` LIKE 'enabled'|empty| +5087|962_hot_zone.sql|SHOW COLUMNS FROM `zone` LIKE 'hotzone'|empty| +5088|964_reports.sql|SHOW TABLES LIKE 'reports'|empty| +5089|971_veteran_rewards.sql|SHOW TABLES LIKE 'veteran_reward_templates'|empty| +5090|977_raid_npc_private_corpses.sql|SELECT * FROM db_version WHERE version >= 5090|empty| +5091|979_unique_spawn_by_name.sql|SHOW COLUMNS FROM `npc_types` LIKE 'unique_spawn_by_name'|empty| +5092|980_account_ip.sql|SHOW TABLES LIKE 'account_ip'|empty| +# 5093|1022_botadventuring.sql +# 5094|1027_botactives.sql +# 5095|1030_botzoningsupport.sql +# 5096|1036_botbuffs.sql +# 5097|1038_botpetstatepersists.sql +5098|1038_grouptablesuniquecolumndefinitions.sql|SELECT * FROM db_version WHERE version >= 5098|empty| +# 5099|1039_botguilds.sql +# 5100|1040_DeprecatedBotRaidsSystems.sql +5101|1057_titles.sql|SHOW TABLES LIKE 'player_titlesets'|empty| +# 5102|1077_botgroups.sql +5103|1136_spell_globals.sql|SHOW TABLES LIKE 'spell_globals'|empty| # 5104|1144_optional_rule_return_nodrop.sql -5105|1195_account_suspendeduntil.sql -5106|1259_npc_skill_types.sql -5107|1280_bot_augs.sql +5105|1195_account_suspendeduntil.sql|SELECT * FROM db_version WHERE version >= 5105|empty| +5106|1259_npc_skill_types.sql|SHOW COLUMNS FROM `npc_types` LIKE 'prim_melee_type'|empty| +# 5107|1280_bot_augs.sql # 5108|1290_optional_exp_loss_rule.sql -5109|1293_guild_bank.sql -5110|1379_loginserver_trusted_server.sql -5111|1392_recipe_learning.sql +5109|1293_guild_bank.sql|SHOW TABLES LIKE 'guild_bank'|empty| +# 5110|1379_loginserver_trusted_server.sql +5111|1392_recipe_learning.sql|SELECT * FROM db_version WHERE version >= 5111|empty| # 5112|1394_optional_rule_sod_hp_mana_end.sql -5113|1404_faction_list.sql +5113|1404_faction_list.sql|SELECT * FROM db_version WHERE version >= 5113|empty| # 5114|1410_optional_sod_aas_ht_and_loh.sql -5115|1436_login_server_table_fix.sql -5116|1446_allowrest_optional.sql -5117|1446_allowrest_required.sql -5118|1450_cvs.sql -5119|1451_guilds.sql -5120|1498_instance_adventure.sql -5121|1510_global_instances.sql -5122|1511_map_path_loading.sql -5123|1513_zone_points.sql -5124|1519_zone_primary_key_id.sql -5125|1542_items_table_cleanup.sql -5126|1548_nimbuseffect_required.sql -5127|1562_instanced_spawnconditions.sql -5128|1586_waypoints_optional.sql -5129|1610_tradeskill_required.sql -5130|1618_zone.sql +# 5115|1436_login_server_table_fix.sql +# 5116|1446_allowrest_optional.sql +5117|1446_allowrest_required.sql|SELECT * FROM db_version WHERE version >= 5117|empty| +# 5118|1450_cvs.sql +5119|1451_guilds.sql|SELECT * FROM db_version WHERE version >= 5119|empty| +5120|1498_instance_adventure.sql|SELECT * FROM db_version WHERE version >= 5120|empty| +5121|1510_global_instances.sql|SELECT * FROM db_version WHERE version >= 5121|empty| +5122|1511_map_path_loading.sql|SHOW COLUMNS FROM `zone` LIKE 'map_file_name'|empty| +5123|1513_zone_points.sql|SELECT * FROM db_version WHERE version >= 5123|empty| +5124|1519_zone_primary_key_id.sql|SELECT * FROM db_version WHERE version >= 5124|empty| +5125|1542_items_table_cleanup.sql|SELECT * FROM db_version WHERE version >= 5125|empty| +5126|1548_nimbuseffect_required.sql|SELECT * FROM db_version WHERE version >= 5126|empty| +5127|1562_instanced_spawnconditions.sql|SHOW TABLES LIKE 'spawn_condition_values'|empty| +# 5128|1586_waypoints_optional.sql +5129|1610_tradeskill_required.sql|SELECT * FROM db_version WHERE version >= 5129|empty| +5130|1618_zone.sql|SELECT * FROM db_version WHERE version >= 5130|empty| # 5131|1625_optional_rule_class_race_exp_bonus.sql # 5132|1672_optional_rules_respawn_window.sql # 5133|1679_optional_rules_blocked_buffs.sql -5134|1696_modify_zone_and_object_tables.sql -5135|1711_account_restricted_aa.sql +5134|1696_modify_zone_and_object_tables.sql|SELECT * FROM db_version WHERE version >= 5134|empty| +5135|1711_account_restricted_aa.sql|SHOW COLUMNS FROM `account` LIKE 'time_creation'|empty| # 5136|1717_optional_rule_bash_stun_chance.sql # 5137|1718_optional_rules_mod3s.sql # 5138|1719_optional_triggerOnCastAAs.sql # 5139|1720_optional_sql_AAs.sql -5140|1720_required_sql_AA_effects_update.sql +# 5140|1720_required_sql_AA_effects_update.sql # 5141|1721_optional_sql_drakkin_breath_update.sql -5142|1721_required_sql_altadv_vars_update.sql +# 5142|1721_required_sql_altadv_vars_update.sql # 5143|1723_optional_sql_new_stats_window_rule.sql -5144|1723_required_sql_corruption.sql +5144|1723_required_sql_corruption.sql|SELECT * FROM db_version WHERE version >= 5144|empty| # 5145|1736_optional_sql_feral_swipe.sql -5146|1737_required_sql_rule_and_aa_update.sql +# 5146|1737_required_sql_rule_and_aa_update.sql # 5147|1746_optional_sql_bot_manaregen.sql # 5148|1747_optional_HoT_zone_and_zonepoints.sql # 5149|1750_optional_sql_reflect_rule.sql # 5150|1753_optional_haste_cap_rule.sql -5151|1753_required_sql_healing_adept_aa.sql -5152|1754_required_sql_healing_adept_aa_fix.sql -5153|1755_required_sql_fear_resist_aas.sql +# 5151|1753_required_sql_healing_adept_aa.sql +# 5152|1754_required_sql_healing_adept_aa_fix.sql +# 5153|1755_required_sql_fear_resist_aas.sql # 5154|1784_optional_corpsedrag_rules.sql -5155|1786_required_update_to_aas.sql -5156|1790_required_aa_required_level_cost.sql -5157|1793_resist_adjust.sql +# 5155|1786_required_update_to_aas.sql +# 5156|1790_required_aa_required_level_cost.sql +5157|1793_resist_adjust.sql|SHOW COLUMNS FROM `npc_spells_entries` LIKE 'resist_adjust'|empty| # 5158|1799_optional_rest_regen_endurance_rule.sql -5159|1802_required_doppelganger.sql -5160|1803_required_tasks_xpreward_signed.sql -5161|1804_required_ae_melee_updates.sql +5159|1802_required_doppelganger.sql|SELECT * FROM db_version WHERE version >= 5159|empty| +5160|1803_required_tasks_xpreward_signed.sql|SELECT * FROM db_version WHERE version >= 5160|empty| +5161|1804_required_ae_melee_updates.sql|SELECT * FROM db_version WHERE version >= 5161|empty| # 5162|1809_optional_rules.sql -5163|1813_required_doppelganger_npcid_change.sql +5163|1813_required_doppelganger_npcid_change.sql|SELECT * FROM db_version WHERE version >= 5163|empty| # 5164|1817_optional_npc_archery_bonus_rule.sql # 5165|1823_optional_delay_death.sql -5166|1847_required_doors_dest_zone_size_32.sql +5166|1847_required_doors_dest_zone_size_32.sql|SELECT * FROM db_version WHERE version >= 5166|empty| # 5167|1859_optional_item_casts_use_focus_rule.sql # 5168|1884_optional_bot_spells_update.sql # 5169|1885_optional_rules_fv_pvp_expansions.sql # 5170|1889_optional_skill_cap_rule.sql -5171|1908_required_npc_types_definitions.sql +5171|1908_required_npc_types_definitions.sql|SHOW COLUMNS FROM `npc_types` LIKE 'attack_count'|empty| # 5172|1926_optional_stat_cap.sql -5173|1944_spawn2.sql -5174|1946_doors.sql +5173|1944_spawn2.sql|SHOW COLUMNS FROM `spawn2` LIKE 'animation'|empty| +5174|1946_doors.sql|SELECT * FROM db_version WHERE version >= 5166|empty| # 5175|1960_optional_console_timeout_rule.sql # 5176|1962_optional_guild_creation_window_rules.sql # 5177|1963_optional_rule_live_like_focuses.sql # 5178|1968_optional_enrage_rules.sql # 5179|1972_optional_extradmg_item_cap.sql -5180|1974_required_bot_spells_update.sql -5181|1977_underwater.sql +# 5180|1974_required_bot_spells_update.sql +5181|1977_underwater.sql|SHOW COLUMNS FROM `npc_types` LIKE 'underwater'|empty| # 5182|1998_optional_intoxication_and_looting_rules.sql -5183|2004_charges_alt_currency.sql +5183|2004_charges_alt_currency.sql|SHOW TABLES LIKE 'alternate_currency'|empty| # 5184|2015_optional_specialization_training_rule.sql # 5185|2016_optional_rule_bot_aa_expansion.sql # 5186|2023_optional_mysqlcli.sql # 5187|2024_optional_update_crystals.sql -5188|2024_required_update.sql -5189|2057_required_discovered_items.sql +5188|2024_required_update.sql|SHOW TABLES LIKE 'char_create_combinations'|empty| +5189|2057_required_discovered_items.sql|SHOW TABLES LIKE 'discovered_items'|empty| # 5190|2058_optional_rule_discovered_items.sql -5191|2062_required_version_changes.sql -5192|2069_required_pets.sql -5193|2079_player_speech.sql -5194|2087_required_bots_hp_and_mana_and_spell_updates.sql -5195|2098_required_zonepoint_version_changes.sql -5196|2099_required_discovered_items_account_status.sql -5197|2104_required_group_roles.sql -5198|2107_required_bot_stances.sql -5199|2129_required_lfguild.sql -5200|2133_required_faction_loot_despawn.sql -5201|2136_extended_targets.sql -5202|2142_emotes.sql +5191|2062_required_version_changes.sql|SELECT * FROM db_version WHERE version >= 5191|empty| +5192|2069_required_pets.sql|SHOW TABLES LIKE 'pets_equipmentset'|empty| +# 5193|2079_player_speech.sql +# 5194|2087_required_bots_hp_and_mana_and_spell_updates.sql +5195|2098_required_zonepoint_version_changes.sql|SELECT * FROM db_version WHERE version >= 5195|empty| +5196|2099_required_discovered_items_account_status.sql|SELECT * FROM db_version WHERE version >= 5196|empty| +5197|2104_required_group_roles.sql|SELECT * FROM db_version WHERE version >= 5197|empty| +# 5198|2107_required_bot_stances.sql +5199|2129_required_lfguild.sql|SHOW TABLES LIKE 'lfguild'|empty| +5200|2133_required_faction_loot_despawn.sql|SELECT * FROM db_version WHERE version >= 5200|empty| +5201|2136_extended_targets.sql|SELECT * FROM db_version WHERE version >= 5201|empty| +5202|2142_emotes.sql|SELECT * FROM db_version WHERE version >= 5202|empty| # 5203|2154_optional_rule_spell_procs_resists_falloff.sql # 5204|2156_optional_charm_break_rule.sql # 5205|2159_optional_defensiveproc_rules.sql -5206|2164_require_bots_bottimers.sql +# 5206|2164_require_bots_bottimers.sql # 5207|2171_optional_SpecialAttackACBonus_rule.sql # 5208|2176_optional_aa_expansion_SOF_fix.sql # 5209|2176_optional_FrenzyBonus_rule.sql -5210|2176_required_aa_updates.sql -5211|2178_required_aa_updates.sql +5210|2176_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5210|empty| +5211|2178_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5211|empty| # 5212|2183_optional_bot_xp_rule.sql # 5213|2185_optional_NPCFlurryChacne_rule # 5214|2185_optional_NPCFlurryChacne_rule.sql # 5215|2185_optional_NPCFlurryChance_rule.sql -5216|2185_required_aa_updates -5217|2185_required_aa_updates.sql +5216|2185_required_aa_updates|SELECT * FROM db_version WHERE version >= 5216|empty| +5217|2185_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5217|empty| # 5218|2188_optional_miscspelleffect_rules # 5219|2188_optional_miscspelleffect_rules.sql -5220|2188_required_aa_updates -5221|2188_required_aa_updates.sql +# 5220|2188_required_aa_updates +5221|2188_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5221|empty| # 5222|2189_optional_taunt_rules # 5223|2189_optional_taunt_rules.sql -5224|2195_required_sharedplatupdates.sql +5224|2195_required_sharedplatupdates.sql|SELECT * FROM db_version WHERE version >= 5224|empty| # 5225|2208_optional_aa_stacking_rule.sql # 5226|2208_optional_EnableSoulAbrasionAA.sql -5227|2208_required_aa_updates.sql +5227|2208_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5227|empty| # 5228|2209_optional_additive_bonus_rule.sql -5229|2213_loot_changes.sql -5230|2214_faction_list_mod.sql -5231|2215_required_aa_updates.sql +5229|2213_loot_changes.sql|SELECT * FROM db_version WHERE version >= 5229|empty| +5230|2214_faction_list_mod.sql|SHOW TABLES LIKE 'faction_list_mod'|empty| +5231|2215_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5231|empty| # 5232|2243_optional_char_max_level_rule.sql -5233|2260_probability.sql -5234|2262_required_pet_discipline_update.sql -5235|2264_required_aa_updates.sql -5236|2268_QueryServ.sql -5237|2268_required_updates.sql +# 5233|2260_probability.sql +5234|2262_required_pet_discipline_update.sql|SELECT * FROM db_version WHERE version >= 5234|empty| +5235|2264_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5235|empty| +# 5236|2268_QueryServ.sql +5237|2268_required_updates.sql|SELECT * FROM db_version WHERE version >= 5237|empty| # 5238|2274_optional_rule_iplimitdisconnectall.sql # 5239|2278_optional_rule_targetableswarmpet.sql # 5240|2280_optional_rule_targetableswarmpet-rename.sql -5241|2283_required_npc_changes.sql -5242|2299_required_inspectmessage_fields.sql +5241|2283_required_npc_changes.sql|SHOW COLUMNS FROM `npc_types` LIKE 'spellscale'|empty| +5242|2299_required_inspectmessage_fields.sql|SELECT * FROM db_version WHERE version >= 5242|empty| # 5243|2300_optional_loot_changes.sql -5244|2304_QueryServ.sql -5245|2340_required_maxbuffslotspet.sql -5246|2361_QueryServ.sql -5247|2361_required_qs_rule_values.sql -5248|2370_required_aa_updates.sql -5249|2376_required_aa_updates.sql -# 5250|2380_optional_merc_data.sql -# 5251|2380_optional_merc_merchant_npctypes_update.sql -# 5252|2380_optional_merc_rules.sql -5253|2383_required_group_ismerc.sql +# 5244|2304_QueryServ.sql +# 5245|2340_required_maxbuffslotspet.sql +# 5246|2361_QueryServ.sql +# 5247|2361_required_qs_rule_values.sql +5248|2370_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5248|empty| +5249|2376_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5249|empty| +5250|2380_optional_merc_data.sql|SELECT * FROM db_version WHERE version >= 5250|empty| +5251|2380_optional_merc_merchant_npctypes_update.sql|SELECT * FROM db_version WHERE version >= 5251|empty| +5252|2380_optional_merc_rules.sql|SELECT * FROM db_version WHERE version >= 5252|empty| +5253|2383_required_group_ismerc.sql|SELECT * FROM db_version WHERE version >= 5253|empty| # 5254|2428_optional_levelbasedexpmods.sql # 5255|2448_optional_stun_proc_aggro_rule.sql -5256|2471_required_aa_updates.sql -5257|2482_required_start_zones.sql -5258|2504_required_aa_updates.sql +5256|2471_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5256|empty| +5257|2482_required_start_zones.sql|SELECT * FROM db_version WHERE version >= 5257|empty| +5258|2504_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5258|empty| 8000|mercs.sql|SHOW TABLES LIKE 'merc_stats'|empty| 9000|2013_02_18_Merc_Rules_and_Tables.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Mercs:ResurrectRadius%'|empty| 9001|2013_02_25_Impr_HT_LT.sql|SHOW TABLES LIKE 'merc_inventory'|empty| @@ -340,7 +340,7 @@ 9084|2015_06_30_runspeed_adjustments.sql|SELECT `runspeed` FROM `npc_types` WHERE `runspeed` > 3|not_empty| 9085|2015_07_01_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty| 9086|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty| -9087|2015_09_25_inventory_snapshots.sql|SHOW TABLES LIKE 'inventory_snapshots'|empty| +9087|2015_09_25_inventory_snapshots.sql|SHOW COLUMNS FROM `character_data` LIKE 'e_last_invsnapshot'|empty| 9088|2015_11_01_perl_event_export_settings.sql|SHOW TABLES LIKE 'perl_event_export_settings'|empty| 9089|2015_11_02_ai_idle_no_spell_recast_default_changes.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Spells:AI_IdleNoSpellMinRecast%' AND `rule_value` = '500'|not_empty| 9090|2015_12_01_spell_scribe_restriction_rule.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Character:RestrictSpellScribing'|empty| From bda39c4f77352fcabff91e55c3b277179cb23ab3 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 28 Dec 2015 20:07:59 -0500 Subject: [PATCH 467/846] Revert accidental change to SetPseudoRoot in lua_mob.cpp. --- zone/lua_mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 46b6b4a9b..0d45c6c36 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -2303,7 +2303,7 @@ luabind::scope lua_register_mob() { .def("BuffFadeBySlot", (void(Lua_Mob::*)(int,bool))&Lua_Mob::BuffFadeBySlot) .def("CanBuffStack", (int(Lua_Mob::*)(int,int))&Lua_Mob::CanBuffStack) .def("CanBuffStack", (int(Lua_Mob::*)(int,int,bool))&Lua_Mob::CanBuffStack) - .def("SetPseudoRoot", (void(Lua_Mob::*)(void))&Lua_Mob::SetPseudoRoot) + .def("SetPseudoRoot", (void(Lua_Mob::*)(bool))&Lua_Mob::SetPseudoRoot) .def("SeeInvisible", (uint8(Lua_Mob::*)(void))&Lua_Mob::SeeInvisible) .def("SeeInvisibleUndead", (bool(Lua_Mob::*)(void))&Lua_Mob::SeeInvisibleUndead) .def("SeeHide", (bool(Lua_Mob::*)(void))&Lua_Mob::SeeHide) From ce71b6d9f07ac1ee0f4e3a86156389c8617a01e5 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 28 Dec 2015 22:04:19 -0500 Subject: [PATCH 468/846] Added GetInstanceTimer() to Perl and Lua. --- changelog.txt | 3 +++ zone/embparser_api.cpp | 12 ++++++++++++ zone/lua_general.cpp | 4 ++++ zone/questmgr.cpp | 8 ++++++++ zone/questmgr.h | 1 + 5 files changed, 28 insertions(+) diff --git a/changelog.txt b/changelog.txt index 74b6ab113..abb096988 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/28/2015 == +Kinglykrab: Added GetInstanceTimer() to 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 diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 126e8169d..8ac6d61bf 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2919,6 +2919,17 @@ XS(XS__UpdateInstanceTimer) { XSRETURN_EMPTY; } +XS(XS__GetInstanceTimer); +XS(XS__GetInstanceTimer) { + dXSARGS; + if (items != 0) + Perl_croak(aTHX_ "Usage: GetInstanceTimer()"); + + uint32 timer = quest_manager.GetInstanceTimer(); + + XSRETURN_UV(timer); +} + XS(XS__GetInstanceID); XS(XS__GetInstanceID) { dXSARGS; @@ -3650,6 +3661,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file); newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file); newXS(strcpy(buf, "UpdateInstanceTimer"), XS__UpdateInstanceTimer, file); + newXS(strcpy(buf, "GetInstanceTimer"), XS__GetInstanceTimer, file); newXS(strcpy(buf, "FlagInstanceByGroupLeader"), XS__FlagInstanceByGroupLeader, file); newXS(strcpy(buf, "FlagInstanceByRaidLeader"), XS__FlagInstanceByRaidLeader, file); newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index bed0fd7bc..0af3ed365 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -808,6 +808,10 @@ void lua_update_instance_timer(uint16 instance_id, uint32 new_duration) { quest_manager.UpdateInstanceTimer(instance_id, new_duration); } +uint32 lua_get_instance_timer() { + return quest_manager.GetInstanceTimer(); +} + int lua_get_instance_id(const char *zone, uint32 version) { return quest_manager.GetInstanceID(zone, version); } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index cb70f93d3..d1cf87dad 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2598,6 +2598,14 @@ void QuestManager::UpdateInstanceTimer(uint16 instance_id, uint32 new_duration) } } +uint32 QuestManager::GetInstanceTimer() { + if (zone && zone->GetInstanceID() > 0 && zone->GetInstanceTimer()) { + uint32 ttime = zone->GetInstanceTimer()->GetRemainingTime(); + return ttime; + } + return 0; +} + uint16 QuestManager::GetInstanceID(const char *zone, int16 version) { QuestManagerCurrentQuestVars(); diff --git a/zone/questmgr.h b/zone/questmgr.h index cd1c4a303..276fcfeca 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -218,6 +218,7 @@ public: uint32 MerchantCountItem(uint32 NPCid, uint32 itemid); uint16 CreateInstance(const char *zone, int16 version, uint32 duration); void UpdateInstanceTimer(uint16 instance_id, uint32 new_duration); + uint32 GetInstanceTimer(); void DestroyInstance(uint16 instance_id); uint16 GetInstanceID(const char *zone, int16 version); void AssignToInstance(uint16 instance_id); From ff876bd558519b44e4cd46858ef9e848b5832044 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Tue, 29 Dec 2015 00:55:17 -0500 Subject: [PATCH 469/846] Added GetInstanceTimerByID(instance_id) to Perl and Lua. --- changelog.txt | 2 ++ zone/embparser_api.cpp | 13 +++++++++++++ zone/lua_general.cpp | 4 ++++ zone/questmgr.cpp | 15 +++++++++++++++ zone/questmgr.h | 1 + 5 files changed, 35 insertions(+) diff --git a/changelog.txt b/changelog.txt index abb096988..77ccc5f49 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/28/2015 == Kinglykrab: Added GetInstanceTimer() to Perl and Lua. + - Added GetInstanceTimerByID(instance_id) 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. == 12/21/2015 == Natedog: Updated item table fields and added a few missing fields for evolving items diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 8ac6d61bf..c7d4b1a1f 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2930,6 +2930,18 @@ XS(XS__GetInstanceTimer) { XSRETURN_UV(timer); } +XS(XS__GetInstanceTimerByID); +XS(XS__GetInstanceTimerByID) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: GetInstanceTimerByID(instance_id)"); + + uint16 instance_id = (uint16)SvUV(ST(0)); + uint32 timer = quest_manager.GetInstanceTimerByID(instance_id); + + XSRETURN_UV(timer); +} + XS(XS__GetInstanceID); XS(XS__GetInstanceID) { dXSARGS; @@ -3662,6 +3674,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file); newXS(strcpy(buf, "UpdateInstanceTimer"), XS__UpdateInstanceTimer, file); newXS(strcpy(buf, "GetInstanceTimer"), XS__GetInstanceTimer, file); + newXS(strcpy(buf, "GetInstanceTimerByID"), XS__GetInstanceTimerByID, file); newXS(strcpy(buf, "FlagInstanceByGroupLeader"), XS__FlagInstanceByGroupLeader, file); newXS(strcpy(buf, "FlagInstanceByRaidLeader"), XS__FlagInstanceByRaidLeader, file); newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 0af3ed365..f731263a1 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -812,6 +812,10 @@ uint32 lua_get_instance_timer() { return quest_manager.GetInstanceTimer(); } +uint32 lua_get_instance_timer_by_id(uint16 instance_id) { + return quest_manager.GetInstanceTimerByID(instance_id); +} + int lua_get_instance_id(const char *zone, uint32 version) { return quest_manager.GetInstanceID(zone, version); } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index d1cf87dad..690d70bf0 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2606,6 +2606,21 @@ uint32 QuestManager::GetInstanceTimer() { return 0; } +uint32 QuestManager::GetInstanceTimerByID(uint16 instance_id) { + if (instance_id == 0) + return 0; + + std::string query = StringFormat("SELECT ((start_time + duration) - UNIX_TIMESTAMP()) AS `remaining` FROM `instance_list` WHERE `id` = %lu", (unsigned long)instance_id); + auto results = database.QueryDatabase(query); + + if (results.Success()) { + auto row = results.begin(); + uint32 timer = atoi(row[0]); + return timer; + } + return 0; +} + uint16 QuestManager::GetInstanceID(const char *zone, int16 version) { QuestManagerCurrentQuestVars(); diff --git a/zone/questmgr.h b/zone/questmgr.h index 276fcfeca..2b8963b70 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -219,6 +219,7 @@ public: uint16 CreateInstance(const char *zone, int16 version, uint32 duration); void UpdateInstanceTimer(uint16 instance_id, uint32 new_duration); uint32 GetInstanceTimer(); + uint32 GetInstanceTimerByID(uint16 instance_id = 0); void DestroyInstance(uint16 instance_id); uint16 GetInstanceID(const char *zone, int16 version); void AssignToInstance(uint16 instance_id); From 34e1dc9829e652a4eab973aaf651587ea911c5bb Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Tue, 29 Dec 2015 02:28:31 -0500 Subject: [PATCH 470/846] Added UpdateZoneHeader(type, value) to Perl and Lua. --- changelog.txt | 2 ++ zone/embparser_api.cpp | 14 ++++++++ zone/lua_general.cpp | 4 +++ zone/questmgr.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++ zone/questmgr.h | 1 + 5 files changed, 93 insertions(+) diff --git a/changelog.txt b/changelog.txt index 77ccc5f49..e31f3598a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) Kinglykrab: Added GetInstanceTimer() to Perl and Lua. - Added GetInstanceTimerByID(instance_id) 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 diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index c7d4b1a1f..bf43e43a1 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3637,6 +3637,19 @@ XS(XS__debug) XSRETURN_EMPTY; } +XS(XS__UpdateZoneHeader); +XS(XS__UpdateZoneHeader) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: UpdateZoneHeader(type, value)"); + + std::string type = (std::string)SvPV_nolen(ST(0)); + std::string value = (std::string)SvPV_nolen(ST(1)); + quest_manager.UpdateZoneHeader(type, value); + + XSRETURN_EMPTY; +} + /* This is the callback perl will look for to setup the @@ -3866,6 +3879,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "untraindiscs"), XS__untraindiscs, file); newXS(strcpy(buf, "updatespawntimer"), XS__UpdateSpawnTimer, file); newXS(strcpy(buf, "updatetaskactivity"), XS__updatetaskactivity, file); + newXS(strcpy(buf, "UpdateZoneHeader"), XS__UpdateZoneHeader, file); newXS(strcpy(buf, "varlink"), XS__varlink, file); newXS(strcpy(buf, "voicetell"), XS__voicetell, file); newXS(strcpy(buf, "we"), XS__we, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index f731263a1..ff0e357fb 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1304,6 +1304,10 @@ void lua_debug(std::string message, int level) { Log.Out(static_cast(level), Logs::QuestDebug, message); } +void lua_update_zone_header(std::string type, std::string value) { + quest_manager.UpdateZoneHeader(type, value); +} + #define LuaCreateNPCParse(name, c_type, default_value) do { \ cur = table[#name]; \ if(luabind::type(cur) != LUA_TNIL) { \ diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 690d70bf0..86b8cb7d9 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -3093,3 +3093,75 @@ std::string QuestManager::GetEncounter() const { return ""; } + +void QuestManager::UpdateZoneHeader(std::string type, std::string value) { + if (strcasecmp(type.c_str(), "ztype") == 0) + zone->newzone_data.ztype = atoi(value.c_str()); + else if (strcasecmp(type.c_str(), "fog_red") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.fog_red[i] = atoi(value.c_str()); + } + } else if (strcasecmp(type.c_str(), "fog_green") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.fog_green[i] = atoi(value.c_str()); + } + } else if (strcasecmp(type.c_str(), "fog_blue") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.fog_blue[i] = atoi(value.c_str()); + } + } else if (strcasecmp(type.c_str(), "fog_minclip") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.fog_minclip[i] = atof(value.c_str()); + } + } else if (strcasecmp(type.c_str(), "fog_maxclip") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.fog_maxclip[i] = atof(value.c_str()); + } + } + else if (strcasecmp(type.c_str(), "gravity") == 0) + zone->newzone_data.gravity = atof(value.c_str()); + else if (strcasecmp(type.c_str(), "time_type") == 0) + zone->newzone_data.time_type = atoi(value.c_str()); + else if (strcasecmp(type.c_str(), "rain_chance") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.rain_chance[i] = atoi(value.c_str()); + } + } else if (strcasecmp(type.c_str(), "rain_duration") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.rain_duration[i] = atoi(value.c_str()); + } + } else if (strcasecmp(type.c_str(), "snow_chance") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.snow_chance[i] = atoi(value.c_str()); + } + } else if (strcasecmp(type.c_str(), "snow_duration") == 0) { + for (int i = 0; i < 4; i++) { + zone->newzone_data.snow_duration[i] = atoi(value.c_str()); + } + } + else if (strcasecmp(type.c_str(), "sky") == 0) + zone->newzone_data.sky = atoi(value.c_str()); + else if (strcasecmp(type.c_str(), "safe_x") == 0) + zone->newzone_data.safe_x = atof(value.c_str()); + else if (strcasecmp(type.c_str(), "safe_y") == 0) + zone->newzone_data.safe_y = atof(value.c_str()); + else if (strcasecmp(type.c_str(), "safe_z") == 0) + zone->newzone_data.safe_z = atof(value.c_str()); + else if (strcasecmp(type.c_str(), "max_z") == 0) + zone->newzone_data.max_z = atof(value.c_str()); + else if (strcasecmp(type.c_str(), "underworld") == 0) + zone->newzone_data.underworld = atof(value.c_str()); + else if (strcasecmp(type.c_str(), "minclip") == 0) + zone->newzone_data.minclip = atof(value.c_str()); + else if (strcasecmp(type.c_str(), "maxclip") == 0) + zone->newzone_data.maxclip = atof(value.c_str()); + else if (strcasecmp(type.c_str(), "fog_density") == 0) + 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)); + memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); + entity_list.QueueClients(0, outapp); + safe_delete(outapp); +} \ No newline at end of file diff --git a/zone/questmgr.h b/zone/questmgr.h index 2b8963b70..a4cc2a38b 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -218,6 +218,7 @@ public: uint32 MerchantCountItem(uint32 NPCid, uint32 itemid); uint16 CreateInstance(const char *zone, int16 version, uint32 duration); void UpdateInstanceTimer(uint16 instance_id, uint32 new_duration); + void UpdateZoneHeader(std::string type, std::string value); uint32 GetInstanceTimer(); uint32 GetInstanceTimerByID(uint16 instance_id = 0); void DestroyInstance(uint16 instance_id); From 9757c380177cfcc9b52c88d8b9924c9bb35729fb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 29 Dec 2015 01:30:20 -0600 Subject: [PATCH 471/846] Adjust manifest [skip ci] --- utils/sql/db_update_manifest.txt | 2 +- zone/npc.cpp | 40 ++++++++++++++++++++++++++++++++ zone/npc.h | 1 + zone/spawn2.cpp | 2 ++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index f62c89fbb..0a73d4560 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -32,7 +32,7 @@ # 5032|285_optional_bot_spell_update.sql # 5033|292_augslots.sql|SELECT * FROM db_version WHERE version >= 5033|empty| 5034|294_merchant_logging.sql|SHOW COLUMNS FROM `eventlog` LIKE 'event_nid'|empty| -5035|304_faction_list.sql|SHOW COLUMNS FROM `faction_list` LIKE 'mod_c16'|empty| +5035|304_faction_list.sql|SELECT * FROM db_version WHERE version >= 5035|empty| 5036|326_aas.sql|SELECT * FROM db_version WHERE version > 5035|empty| # 5037|328_bot_management.sql # 5038|328_optional_bot_management.sql diff --git a/zone/npc.cpp b/zone/npc.cpp index fd7f6880c..9d39f4ad3 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -843,6 +843,46 @@ bool NPC::DatabaseCastAccepted(int spell_id) { return false; } +bool NPC::SpawnZoneController(){ + + NPCType* npc_type = new NPCType; + memset(npc_type, 0, sizeof(NPCType)); + + strncpy(npc_type->name, "zone_controller", 60); + npc_type->cur_hp = 2000000000; + npc_type->max_hp = 2000000000; + npc_type->race = 240; + npc_type->gender = 0; + npc_type->class_ = 1; + npc_type->deity = 1; + npc_type->level = 200; + npc_type->npc_id = 0; + npc_type->loottable_id = 0; + npc_type->texture = 3; + npc_type->runspeed = 0; + npc_type->d_melee_texture1 = 0; + npc_type->d_melee_texture2 = 0; + npc_type->merchanttype = 0; + npc_type->bodytype = 11; + + npc_type->prim_melee_type = 28; + npc_type->sec_melee_type = 28; + + strcpy(npc_type->special_abilities, "12,1^13,1^14,1^15,1^16,1^17,1^19,1^22,1^24,1^25,1^28,1^31,1^35,1^39,1^42,1"); + + glm::vec4 point; + point.x = 5000; + point.y = 5000; + point.z = -5000; + + NPC* npc = new NPC(npc_type, nullptr, point, FlyMode3); + npc->GiveNPCTypeData(npc_type); + + entity_list.AddNPC(npc); + + return true; +} + NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client) { if(spawncommand == 0 || spawncommand[0] == 0) { return 0; diff --git a/zone/npc.h b/zone/npc.h index 32afd0afd..327918c19 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -96,6 +96,7 @@ class NPC : public Mob { public: static NPC* SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client = nullptr); + static bool SpawnZoneController(); static int8 GetAILevel(bool iForceReRead = false); NPC(const NPCType* data, Spawn2* respawn, const glm::vec4& position, int iflymode, bool IsCorpse = false); diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index f2461ed4b..7cb3b1f3c 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -549,6 +549,8 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa spawn2_list.Insert(new_spawn); } + NPC::SpawnZoneController(); + return true; } From 3af9aeeeafadc332185bc97fce105def14e06ba0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 29 Dec 2015 01:45:53 -0600 Subject: [PATCH 472/846] Adjust manifest [skip ci] --- utils/sql/db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 0a73d4560..84ac931a7 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -340,7 +340,7 @@ 9084|2015_06_30_runspeed_adjustments.sql|SELECT `runspeed` FROM `npc_types` WHERE `runspeed` > 3|not_empty| 9085|2015_07_01_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty| 9086|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty| -9087|2015_09_25_inventory_snapshots.sql|SHOW COLUMNS FROM `character_data` LIKE 'e_last_invsnapshot'|empty| +9087|2015_09_25_inventory_snapshots.sql|SHOW TABLES LIKE 'inventory_snapshots'|empty| 9088|2015_11_01_perl_event_export_settings.sql|SHOW TABLES LIKE 'perl_event_export_settings'|empty| 9089|2015_11_02_ai_idle_no_spell_recast_default_changes.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Spells:AI_IdleNoSpellMinRecast%' AND `rule_value` = '500'|not_empty| 9090|2015_12_01_spell_scribe_restriction_rule.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Character:RestrictSpellScribing'|empty| From f25246e1a02069f5a2e8674950fb540d2231da89 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 29 Dec 2015 01:47:21 -0600 Subject: [PATCH 473/846] Adjust eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 8fd3af540..fa05c3f54 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -107,6 +107,33 @@ 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 "installer"){ print "Running EQEmu Server installer routines...\n"; mkdir('logs'); @@ -1316,8 +1343,14 @@ 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; + } + #::: Iterate through Manifest backwards from binary version down to local version... - for($i = $bin_db_ver; $i > 1000; $i--){ + for($i = $bin_db_ver; $i > $revision_check; $i--){ if(!defined($m_d{$i}[0])){ next; } $file_name = trim($m_d{$i}[1]); From 8425607460da820f7727267c6a94f75c5774a60b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 29 Dec 2015 04:08:10 -0600 Subject: [PATCH 474/846] Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true - When a zone boots, it will spawn an invisible npc by the name of zone_controller - Lua and Perl scripts can be represented with this npc as zone_controller.pl/lua - This NPC's ID is ruled be define ZONE_CONTROLLER_NPC_ID 10 - Two EVENT's uniquely are handled with this NPC/controller (They only work with the zone_controller NPC) - EVENT_SPAWN_ZONE :: All NPC spawns in the zone trigger the controller and pass the following variables: $spawned_entity_id $spawned_npc_id - EVENT_DEATH_ZONE :: All NPC deaths in the zone trigger the controller event and pass the following variables: $killer_id $killer_damage $killer_spell $killer_skill $killed_npc_id --- changelog.txt | 16 ++++++ common/features.h | 2 + common/ruletypes.h | 1 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2015_12_29_quest_zone_events.sql | 4 ++ zone/attack.cpp | 54 +++++++++++-------- zone/embparser.cpp | 19 ++++++- zone/entity.cpp | 10 ++++ zone/event_codes.h | 3 +- zone/lua_general.cpp | 4 +- zone/lua_parser.cpp | 4 +- zone/npc.cpp | 11 +++- zone/quest_parser_collection.cpp | 11 +++- 14 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 utils/sql/git/required/2015_12_29_quest_zone_events.sql diff --git a/changelog.txt b/changelog.txt index e31f3598a..f8ca4c917 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,21 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/29/2015 == +Akkadius: Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true + - When a zone boots, it will spawn an invisible npc by the name of zone_controller + - Lua and Perl scripts can be represented with this npc as zone_controller.pl/lua + - This NPC's ID is ruled be define ZONE_CONTROLLER_NPC_ID 10 + - Two EVENT's uniquely are handled with this NPC/controller (They only work with the zone_controller NPC) + - EVENT_SPAWN_ZONE :: All NPC spawns in the zone trigger the controller and pass the following variables: + $spawned_entity_id + $spawned_npc_id + - EVENT_DEATH_ZONE :: All NPC deaths in the zone trigger the controller event and pass the following variables: + $killer_id + $killer_damage + $killer_spell + $killer_skill + $killed_npc_id + == 12/28/2015 == Kinglykrab: Added GetInstanceTimer() to Perl and Lua. - Added GetInstanceTimerByID(instance_id) to Perl and Lua. diff --git a/common/features.h b/common/features.h index 2ede4b4be..8115efd82 100644 --- a/common/features.h +++ b/common/features.h @@ -233,6 +233,8 @@ enum { //some random constants #define GROUP_EXP_PER_POINT 1000 #define RAID_EXP_PER_POINT 2000 +#define ZONE_CONTROLLER_NPC_ID 10 + //Some hard coded statuses from commands and other places: enum { minStatusToBeGM = 40, diff --git a/common/ruletypes.h b/common/ruletypes.h index 83ef9aff3..41e4e22a4 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -233,6 +233,7 @@ RULE_BOOL(Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mod 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_CATEGORY_END() RULE_CATEGORY(Map) diff --git a/common/version.h b/common/version.h index b2dd26212..00a999add 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 9093 +#define CURRENT_BINARY_DATABASE_VERSION 9094 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 84ac931a7..86f7ebe7c 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -347,6 +347,7 @@ 9091|2015_12_07_command_settings.sql|SHOW TABLES LIKE 'command_settings'|empty| 9092|2015_12_17_eqtime.sql|SHOW TABLES LIKE 'eqtime'|empty| 9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty| +9094|2015_12_29_quest_zone_events.sql|SELECT * FROM perl_event_export_settings WHERE event_description = 'EVENT_SPAWN_ZONE'|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/2015_12_29_quest_zone_events.sql b/utils/sql/git/required/2015_12_29_quest_zone_events.sql new file mode 100644 index 000000000..783cb477e --- /dev/null +++ b/utils/sql/git/required/2015_12_29_quest_zone_events.sql @@ -0,0 +1,4 @@ +INSERT INTO `perl_event_export_settings` (`event_id`, `event_description`, `export_qglobals`, `export_mob`, `export_zone`, `export_item`, `export_event`) VALUES (81, 'EVENT_SPAWN_ZONE', 0, 0, 0, 0, 1); +INSERT INTO `perl_event_export_settings` (`event_id`, `event_description`, `export_qglobals`, `export_mob`, `export_zone`, `export_item`, `export_event`) VALUES (82, 'EVENT_DEATH_ZONE', 0, 0, 0, 0, 1); +ALTER TABLE `rule_values` +MODIFY COLUMN `notes` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL AFTER `rule_value`; \ No newline at end of file diff --git a/zone/attack.cpp b/zone/attack.cpp index 6b2534a43..5f7b19e80 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2009,15 +2009,15 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack } } -bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) { - Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill); +bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attack_skill) { + Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killer_mob->GetName(), damage, spell, attack_skill); Mob *oos = nullptr; - if(killerMob) { - oos = killerMob->GetOwnerOrSelf(); + if(killer_mob) { + oos = killer_mob->GetOwnerOrSelf(); char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); + snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill)); if(parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) { if(GetHP() < 0) { @@ -2026,15 +2026,15 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack return false; } - if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { + if(killer_mob && killer_mob->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)); + killer_mob->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)); + snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill)); if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0) { if(GetHP() < 0) { @@ -2072,21 +2072,21 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack 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->killer_id = killer_mob ? killer_mob->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); + entity_list.QueueClients(killer_mob, app, false); if(respawn2) { respawn2->DeathReset(1); } - if (killerMob) { + if (killer_mob) { if(GetClass() != LDON_TREASURE) - hate_list.AddEntToHateList(killerMob, damage); + hate_list.AddEntToHateList(killer_mob, damage); } safe_delete(app); @@ -2148,8 +2148,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack { if(!IsLdonTreasure && MerchantType == 0) { kr->SplitExp((finalxp), this); - if(killerMob && (kr->IsRaidMember(killerMob->GetName()) || kr->IsRaidMember(killerMob->GetUltimateOwner()->GetName()))) - killerMob->TrySpellOnKill(killed_level,spell); + if(killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName()))) + killer_mob->TrySpellOnKill(killed_level,spell); } /* Send the EVENT_KILLED_MERIT event for all raid members */ for (int i = 0; i < MAX_RAID_MEMBERS; i++) { @@ -2193,8 +2193,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack { if(!IsLdonTreasure && MerchantType == 0) { kg->SplitExp((finalxp), this); - if(killerMob && (kg->IsGroupMember(killerMob->GetName()) || kg->IsGroupMember(killerMob->GetUltimateOwner()->GetName()))) - killerMob->TrySpellOnKill(killed_level,spell); + if(killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName()))) + killer_mob->TrySpellOnKill(killed_level,spell); } /* Send the EVENT_KILLED_MERIT event and update kill tasks * for all group members */ @@ -2244,8 +2244,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack if(!GetOwner() || (GetOwner() && !GetOwner()->IsClient())) { give_exp_client->AddEXP((finalxp), conlevel); - if(killerMob && (killerMob->GetID() == give_exp_client->GetID() || killerMob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) - killerMob->TrySpellOnKill(killed_level,spell); + if(killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) + killer_mob->TrySpellOnKill(killed_level,spell); } } } @@ -2393,20 +2393,30 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack uint16 emoteid = oos->GetEmoteID(); if(emoteid != 0) oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid); - killerMob->TrySpellOnKill(killed_level, spell); + killer_mob->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.. + if(killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted + killer_mob->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)); + snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill)); parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, buffer, 0); + + /* Zone controller process EVENT_DEATH_ZONE (Death events) */ + if (RuleB(Zone, UseZoneController)) { + if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && this->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ + char data_pass[100] = { 0 }; + snprintf(data_pass, 99, "%d %d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill), this->GetNPCTypeID()); + parse->EventNPC(EVENT_DEATH_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0); + } + } + return true; } diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 617d17d2e..12501b089 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -114,7 +114,9 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_RESPAWN", "EVENT_DEATH_COMPLETE", "EVENT_UNHANDLED_OPCODE", - "EVENT_TICK" + "EVENT_TICK", + "EVENT_SPAWN_ZONE", + "EVENT_DEATH_ZONE", }; PerlembParser::PerlembParser() : perl(nullptr) { @@ -1424,6 +1426,21 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID ExportVar(package_name.c_str(), "slotid", extradata); break; } + case EVENT_SPAWN_ZONE: { + Seperator sep(data); + ExportVar(package_name.c_str(), "spawned_entity_id", sep.arg[0]); + ExportVar(package_name.c_str(), "spawned_npc_id", sep.arg[1]); + break; + } + case EVENT_DEATH_ZONE: { + Seperator sep(data); + ExportVar(package_name.c_str(), "killer_id", sep.arg[0]); + ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]); + ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]); + ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); + ExportVar(package_name.c_str(), "killed_npc_id", sep.arg[4]); + break; + } default: { break; diff --git a/zone/entity.cpp b/zone/entity.cpp index 23848f73e..92fefb2ec 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -641,8 +641,18 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) { npc->SetID(GetFreeID()); npc->SetMerchantProbability((uint8) zone->random.Int(0, 99)); + parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); + /* Zone controller process EVENT_SPAWN_ZONE */ + if (RuleB(Zone, UseZoneController)) { + if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ + char data_pass[100] = { 0 }; + snprintf(data_pass, 99, "%d %d", npc->GetID(), npc->GetNPCTypeID()); + parse->EventNPC(EVENT_SPAWN_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0); + } + } + uint16 emoteid = npc->GetEmoteID(); if (emoteid != 0) npc->DoNPCEmote(ONSPAWN, emoteid); diff --git a/zone/event_codes.h b/zone/event_codes.h index 7850b0eb3..1b0e18505 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -83,7 +83,8 @@ typedef enum { EVENT_DEATH_COMPLETE, EVENT_UNHANDLED_OPCODE, EVENT_TICK, - + EVENT_SPAWN_ZONE, + EVENT_DEATH_ZONE, _LargestEventID } QuestEventID; diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index ff0e357fb..a42efd592 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1731,7 +1731,9 @@ luabind::scope lua_register_events() { luabind::value("leave_area", static_cast(EVENT_LEAVE_AREA)), luabind::value("death_complete", static_cast(EVENT_DEATH_COMPLETE)), luabind::value("unhandled_opcode", static_cast(EVENT_UNHANDLED_OPCODE)), - luabind::value("tick", static_cast(EVENT_TICK)) + luabind::value("tick", static_cast(EVENT_TICK)), + luabind::value("spawn_zone", static_cast(EVENT_SPAWN_ZONE)), + luabind::value("death_zone", static_cast(EVENT_DEATH_ZONE)) ]; } diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 462752705..aeb1e3228 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -117,7 +117,9 @@ const char *LuaEvents[_LargestEventID] = { "event_respawn", "event_death_complete", "event_unhandled_opcode", - "event_tick" + "event_tick", + "event_spawn_zone", + "event_death_zone" }; extern Zone *zone; diff --git a/zone/npc.cpp b/zone/npc.cpp index 9d39f4ad3..8f09d3f40 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -845,18 +845,22 @@ bool NPC::DatabaseCastAccepted(int spell_id) { bool NPC::SpawnZoneController(){ + if (!RuleB(Zone, UseZoneController)) + return false; + NPCType* npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); strncpy(npc_type->name, "zone_controller", 60); npc_type->cur_hp = 2000000000; npc_type->max_hp = 2000000000; + npc_type->hp_regen = 100000000; npc_type->race = 240; - npc_type->gender = 0; + npc_type->gender = 2; npc_type->class_ = 1; npc_type->deity = 1; npc_type->level = 200; - npc_type->npc_id = 0; + npc_type->npc_id = ZONE_CONTROLLER_NPC_ID; npc_type->loottable_id = 0; npc_type->texture = 3; npc_type->runspeed = 0; @@ -868,6 +872,9 @@ bool NPC::SpawnZoneController(){ npc_type->prim_melee_type = 28; npc_type->sec_melee_type = 28; + npc_type->findable = 0; + npc_type->trackable = 0; + strcpy(npc_type->special_abilities, "12,1^13,1^14,1^15,1^16,1^17,1^19,1^22,1^24,1^25,1^28,1^31,1^35,1^39,1^42,1"); glm::vec4 point; diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 1f4f99c0e..4d2a2960a 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -484,10 +484,17 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string //second look for /quests/zone/npcname.ext (precedence) const NPCType *npc_type = database.LoadNPCTypesData(npcid); - if(!npc_type) { + if (!npc_type && npcid != ZONE_CONTROLLER_NPC_ID) { return nullptr; } - std::string npc_name = npc_type->name; + + std::string npc_name; + if (npcid == ZONE_CONTROLLER_NPC_ID){ + npc_name = "zone_controller"; + } + else{ + npc_name = npc_type->name; + } int sz = static_cast(npc_name.length()); for(int i = 0; i < sz; ++i) { if(npc_name[i] == '`') { From 8b35ae9921de54de5c0567d4e30d5710b6de7b00 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 29 Dec 2015 05:21:27 -0600 Subject: [PATCH 475/846] Change how rules are loaded and inherit values - When a custom ruleset is loaded, it will always first look for a value present in the ruleset id for that zone, when it is not present, it will load from the default ruleset instead of immediately falling back to the source value. This is to eliminate the excessive amount of duplicate entries in the rule_values tables --- common/rulesys.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/common/rulesys.cpp b/common/rulesys.cpp index 13e342fe5..670c090b5 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -236,7 +236,7 @@ void RuleManager::SaveRules(Database *database, const char *ruleset_name) { } bool RuleManager::LoadRules(Database *database, const char *ruleset_name) { - + int ruleset_id = GetRulesetID(database, ruleset_name); if (ruleset_id < 0) { Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name); @@ -248,6 +248,26 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) { m_activeRuleset = ruleset_id; m_activeName = ruleset_name; + /* Load default ruleset values first if we're loading something other than default */ + if (strcasecmp(ruleset_name, "default") != 0){ + std::string default_ruleset_name = "default"; + int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str()); + if (default_ruleset_id < 0) { + Log.Out(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.", default_ruleset_name.c_str()); + return(false); + } + Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name, default_ruleset_id); + + std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d", default_ruleset_id); + auto results = database->QueryDatabase(query); + if (!results.Success()) + return false; + + for (auto row = results.begin(); row != results.end(); ++row) + if (!SetRule(row[0], row[1], nullptr, false)) + Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]); + } + std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id); auto results = database->QueryDatabase(query); if (!results.Success()) From 2bf6c2788ee79a59b1cd5e180493c28c6d15e25c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 29 Dec 2015 05:40:34 -0600 Subject: [PATCH 476/846] eqemu_update.pl - Implement 14) [Remove Duplicate Rule Values] :: Looks for redundant rule_values entries and removes them --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_update.pl | 36 ++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index fa7c57a12..c7428c07e 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -493,7 +493,7 @@ bool Database::CheckDatabaseConversions() { /* 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 13"); + system("perl eqemu_update.pl V 14"); /* Run Automatic Database Upgrade Script */ system("perl eqemu_update.pl ran_from_world"); diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index fa05c3f54..c2fc92818 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -23,7 +23,7 @@ if($Config{osname}=~/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 = 13; +$current_version = 14; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ @@ -134,6 +134,11 @@ if($ARGV[0] eq "install_peq_db"){ 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'); @@ -278,6 +283,7 @@ sub show_menu_prompt { 11 => \&fetch_latest_windows_binaries, 12 => \&fetch_server_dlls, 13 => \&do_windows_login_server_setup, + 14 => \&remove_duplicate_rule_values, 19 => \&do_bots_db_schema_drop, 20 => \&do_update_self, 0 => \&script_exit, @@ -355,6 +361,7 @@ return < Date: Tue, 29 Dec 2015 06:06:12 -0600 Subject: [PATCH 477/846] Fix Travis --- common/rulesys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/rulesys.cpp b/common/rulesys.cpp index 670c090b5..56289b09a 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -256,7 +256,7 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) { Log.Out(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.", default_ruleset_name.c_str()); return(false); } - Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name, default_ruleset_id); + Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name.c_str(), default_ruleset_id); std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d", default_ruleset_id); auto results = database->QueryDatabase(query); From 7045581fdca8de2c7852682d19a09fc8f86e4eff Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 29 Dec 2015 15:22:09 -0500 Subject: [PATCH 478/846] Cap big bags to 10 slots for now --- common/shareddb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index fe4ad1b5d..402d77e76 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -954,7 +954,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ 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.BagSlots = (uint8)std::min(atoi(row[ItemField::bagslots]), 10); // FIXME: remove when big bags supported item.BagSize = (uint8)atoi(row[ItemField::bagsize]); item.BagWR = (uint8)atoi(row[ItemField::bagwr]); item.Book = (uint8)atoi(row[ItemField::book]); From 2d375eb5659f6f12d34ddce97e612060ded54a2a Mon Sep 17 00:00:00 2001 From: af4t Date: Wed, 30 Dec 2015 02:17:09 -0500 Subject: [PATCH 479/846] MSVC 2015 wants #included for std::min. If any other compilers require the same, feel free to alter the #if test. --- common/shareddb.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 402d77e76..0890f3fcf 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1,6 +1,10 @@ #include #include +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #include +#endif + #include "classes.h" #include "eq_packet_structs.h" #include "eqemu_exception.h" From fe61abc3cdfc011945598dd17932aecb335bbe1a Mon Sep 17 00:00:00 2001 From: Tim DeLong Date: Wed, 30 Dec 2015 11:42:49 -0500 Subject: [PATCH 480/846] * AddReport's who and against strings were not being escaped properly. --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index b8ea025ae..dcc3fbe77 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1564,7 +1564,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines char *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')", who.c_str(), against.c_str(), escape_str); + 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); QueryDatabase(query); safe_delete_array(escape_str); } From aad1396c73be1e9dddb93dda9742e89ecf6219ea Mon Sep 17 00:00:00 2001 From: Tim DeLong Date: Wed, 30 Dec 2015 23:30:52 -0500 Subject: [PATCH 481/846] * CheckNameFilter was enforcing minimum surname length of 3 instead of 4. * Minor refactoring of CheckNameFilter to eliminate redundant code. --- common/database.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index dcc3fbe77..932aa4229 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1183,21 +1183,16 @@ bool Database::CheckNameFilter(const char* name, bool surname) { std::string str_name = name; - if(surname) + // the minimum 4 is enforced by the client too + if (!name || strlen(name) < 4) { - // the minimum 4 is enforced by the client too - if(!name || strlen(name) < 3) - { - return false; - } + return false; } - else + + // Given name length is enforced by the client too + if (!surname && strlen(name) > 15) { - // the minimum 4 is enforced by the client too - if(!name || strlen(name) < 4 || strlen(name) > 15) - { - return false; - } + return false; } for (size_t i = 0; i < str_name.size(); i++) From 3996a70037a7bfd2c7818af16f95a8442d056d7f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 31 Dec 2015 01:08:04 -0500 Subject: [PATCH 482/846] 2h DB should match client closer I think the dev missed something when making it pretty for the forums This should match it better. --- zone/attack.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 5f7b19e80..ad5be845a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2703,16 +2703,38 @@ uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand) } } else { // 2h damage bonus + int damage_bonus = 1 + (level - 28) / 3; if (delay <= 27) - return 1 + ((level - 28) / 3); - else if (delay < 40) - return 1 + ((level - 28) / 3) + ((level - 30) / 5); - else if (delay < 43) - return 2 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3); - else if (delay < 45) - return 3 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3); - else if (delay >= 45) - return 4 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3); + return damage_bonus + 1; + // Client isn't reflecting what the dev quoted, this matches better + if (level > 29) { + int level_bonus = (level - 30) / 5 + 1; + if (level > 50) { + level_bonus++; + int level_bonus2 = level - 50; + if (level > 67) + level_bonus2 += 5; + else if (level > 59) + level_bonus2 += 4; + else if (level > 58) + level_bonus2 += 3; + else if (level > 56) + level_bonus2 += 2; + else if (level > 54) + level_bonus2++; + level_bonus += level_bonus2 * delay / 40; + } + damage_bonus += level_bonus; + } + if (delay >= 40) { + int delay_bonus = (delay - 40) / 3 + 1; + if (delay >= 45) + delay_bonus += 2; + else if (delay >= 43) + delay_bonus++; + damage_bonus += delay_bonus; + } + return damage_bonus; } } From 9ea9ed259077abbdab528fab4ab1ed6e07a43d4d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 31 Dec 2015 21:45:42 -0600 Subject: [PATCH 483/846] Update eqemu_update.pl to include loginserver setup in normal installer routine [skip ci] --- utils/scripts/eqemu_update.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index c2fc92818..6d9be10a2 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -184,6 +184,7 @@ if($ARGV[0] eq "installer"){ if($OS eq "Windows"){ check_windows_firewall_rules(); + do_windows_login_server_setup(); } exit; } From 647fbcd6b64a60cb80f77fada1b5d1f12defc61d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 1 Jan 2016 01:11:32 -0600 Subject: [PATCH 484/846] Adjust an incredibly spammy log message --- world/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/net.cpp b/world/net.cpp index 86f794af0..cd84c530a 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -482,7 +482,7 @@ int main(int argc, char** argv) { if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year)) Log.Out(Logs::General, Logs::World_Server, "Failed to save eqtime."); else - Log.Out(Logs::General, Logs::World_Server, "EQTime successfully saved."); + Log.Out(Logs::Detail, Logs::World_Server, "EQTime successfully saved."); } //check for timeouts in other threads From dfdfb18a7ecfed952d3a21a564063b1d22b3536d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 1 Jan 2016 01:12:49 -0600 Subject: [PATCH 485/846] VS2012 fix --- common/shareddb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 0890f3fcf..f82d54fad 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1,7 +1,7 @@ #include #include -#if defined(_MSC_VER) && _MSC_VER >= 1900 +#if defined(_MSC_VER) && _MSC_VER >= 1800 #include #endif From 11f3e3024509389eddea247337c9ba9632d0c7f2 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 2 Jan 2016 09:16:13 -0500 Subject: [PATCH 486/846] Fixed a ton of buffs when using an EE item (SendBuffDurationPacket). --- zone/spells.cpp | 54 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 18de9a444..4224e9ac3 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5310,6 +5310,7 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) EQApplicationPacket* outapp; outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffFade_Struct)); SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*) outapp->pBuffer; + int index; sbf->entityid = GetID(); sbf->slot = 2; @@ -5317,6 +5318,19 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) 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->effect=sbf->level; + if (IsEffectInSpell(buff.spellid, SE_TotalHP)) { // If any of the lower 6 bits are set, the GUI changes MAX_HP AGAIN. @@ -5327,25 +5341,45 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) 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, any - // other value has the GUI doing that value at the same time server - // is doing theirs. This makes the two match. - int index = GetSpellEffectIndex(buff.spellid, SE_CurrentHP); + // 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)) { - // Wish I knew what this sbf->effect field was trying to tell - // the client. 10 seems to not break SeeInvis spells. Level, + // 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 + 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)) { - // Default to what old code did until we find a better fix for - // other spell lines. - sbf->effect=sbf->level; + // This seems to work. Previosly stats got corrupted when sending + // level. + 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->bufffade = 0; From f754f06bec96e1710f85141c2deeb13e5214b8ae Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 2 Jan 2016 17:26:59 -0500 Subject: [PATCH 487/846] Added runspeed to mystats window. --- zone/client.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 4b81cf250..ccf561306 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6803,7 +6803,8 @@ void Client::SendStatsWindow(Client* client, bool use_window) /* AC */ indP << "AC: " << CalcAC() << "
" << /* AC2 */ indP << "- Mit: " << GetACMit() << " | Avoid: " << GetACAvoid() << " | 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) << "

" << + /* Haste2 */ indP << " - Item: " << itembonuses.haste << " + Spell: " << (spellbonuses.haste + spellbonuses.hastetype2) << " (Cap: " << RuleI(Character, HasteCap) << ") | Over: " << (spellbonuses.hastetype3 + ExtraHaste) << "
" << + /* RunSpeed*/ indP << "Runspeed: " << GetRunspeed() << "
" << /* RegenLbl */ indL << indS << "Regen
" << indS << indP << indP << " Base | Items (Cap) " << indP << " | Spell | A.A.s | Total
" << /* Regen */ regen_string << "
" << /* Stats */ stat_field << "

" << From 05de206aceb51ebbbf9a9b2232bd7ac74e0747c0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 3 Jan 2016 01:58:37 -0500 Subject: [PATCH 488/846] Rework quiver haste --- common/ruletypes.h | 2 +- zone/attack.cpp | 29 ++++++++++++++++------------- zone/client.cpp | 22 ++++++++++------------ zone/client.h | 2 +- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 41e4e22a4..493bb8ca6 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -450,7 +450,7 @@ RULE_REAL (Combat,TauntSkillFalloff, 0.33)//For every taunt skill point that's n RULE_BOOL (Combat,EXPFromDmgShield, false) //Determine if damage from a damage shield counts for EXP gain. RULE_INT(Combat, MonkACBonusWeight, 15) RULE_INT(Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target -RULE_INT(Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers +RULE_INT(Combat, QuiverHasteCap, 1000) //Quiver haste cap 1000 on live for a while, currently 700 on live RULE_BOOL(Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll RULE_INT(Combat, ArcheryBonusChance, 50) RULE_INT(Combat, BerserkerFrenzyStart, 35) diff --git a/zone/attack.cpp b/zone/attack.cpp index ad5be845a..accb7beff 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4649,28 +4649,31 @@ void Client::SetAttackTimer() int hhe = itembonuses.HundredHands + spellbonuses.HundredHands; int speed = 0; - int delay = 36; - float quiver_haste = 0.0f; + int delay = 3600; //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) - delay = GetMonkHandToHandDelay(); + delay = 100 * GetMonkHandToHandDelay(); } else { //we have a weapon, use its delay - delay = ItemToUse->Delay; - if (ItemToUse->ItemType == ItemTypeBow || ItemToUse->ItemType == ItemTypeLargeThrowing) - quiver_haste = GetQuiverHaste(); + delay = 100 * ItemToUse->Delay; + } + + speed = delay / haste_mod; + + if (ItemToUse && ItemToUse->ItemType == 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)); + } else { + if (RuleB(Spells, Jun182014HundredHandsRevamp)) + speed = static_cast(speed + ((hhe / 1000.0f) * speed)); + else + speed = static_cast(speed + ((hhe / 100.0f) * delay)); } - if (RuleB(Spells, Jun182014HundredHandsRevamp)) - speed = static_cast(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100); - else - speed = static_cast(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100); - // this is probably wrong - if (quiver_haste > 0) - speed *= quiver_haste; TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true, true); } } diff --git a/zone/client.cpp b/zone/client.cpp index ccf561306..ceedf19d7 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8356,21 +8356,19 @@ void Client::ShowNumHits() return; } -float Client::GetQuiverHaste() +int Client::GetQuiverHaste(int delay) { - float quiver_haste = 0; + const ItemInst *pi = nullptr; for (int r = EmuConstants::GENERAL_BEGIN; r <= EmuConstants::GENERAL_END; r++) { - const ItemInst *pi = GetInv().GetItem(r); - if (!pi) - continue; - if (pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver) { - float temp_wr = (pi->GetItem()->BagWR / RuleI(Combat, QuiverWRHasteDiv)); - quiver_haste = std::max(temp_wr, quiver_haste); - } + pi = GetInv().GetItem(r); + if (pi && pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver && + pi->GetItem()->BagWR > 0) + break; + if (r == EmuConstants::GENERAL_END) + // we will get here if we don't find a valid quiver + return 0; } - if (quiver_haste > 0) - quiver_haste = 1.0f / (1.0f + static_cast(quiver_haste) / 100.0f); - return quiver_haste; + return (pi->GetItem()->BagWR * 0.0025f * delay) + 1; } void Client::SendColoredText(uint32 color, std::string message) diff --git a/zone/client.h b/zone/client.h index 6db22c5b0..bc2f89b87 100644 --- a/zone/client.h +++ b/zone/client.h @@ -226,7 +226,7 @@ public: virtual inline bool IsBerserk() { return berserk; } virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); virtual void SetAttackTimer(); - float GetQuiverHaste(); + int GetQuiverHaste(int delay); void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false); void AI_Init(); From 5bcb9f0b35750a06e41fef32a46398bb7f7f7400 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 3 Jan 2016 14:38:50 -0500 Subject: [PATCH 489/846] Fix classic h2h dmg/delay also support for revamp The revamp was implemented during SoF Set Combat:UseRevampHandToHand to true to enable --- common/ruletypes.h | 1 + zone/attack.cpp | 182 +++++++++++++++++++++++++-------------------- zone/bot.cpp | 62 ++++++++------- zone/bot.h | 2 +- zone/lua_mob.cpp | 12 +-- zone/lua_mob.h | 4 +- zone/mob.h | 4 +- zone/perl_mob.cpp | 20 ++--- 8 files changed, 161 insertions(+), 126 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 493bb8ca6..f83ea0266 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -462,6 +462,7 @@ RULE_INT(Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed RULE_BOOL(Combat, UseLiveCombatRounds, true) // turn this false if you don't want to worry about fixing up combat rounds for NPCs 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_CATEGORY_END() RULE_CATEGORY(NPC) diff --git a/zone/attack.cpp b/zone/attack.cpp index accb7beff..532a53686 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -846,7 +846,7 @@ int Mob::GetWeaponDamage(Mob *against, const Item_Struct *weapon_item) { } else{ if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){ - dmg = GetMonkHandToHandDamage(); + dmg = GetHandToHandDamage(); } else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ //pets wouldn't actually use this but... @@ -868,12 +868,7 @@ int Mob::GetWeaponDamage(Mob *against, const Item_Struct *weapon_item) { dmg = dmg <= 0 ? 1 : dmg; } else{ - if(GetClass() == MONK || GetClass() == BEASTLORD){ - dmg = GetMonkHandToHandDamage(); - } - else{ - dmg = 1; - } + dmg = GetHandToHandDamage(); } } @@ -1006,7 +1001,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate if((GetClass() == MONK || GetClass() == BEASTLORD)) { if(MagicGloves || GetLevel() >= 30){ - dmg = GetMonkHandToHandDamage(); + dmg = GetHandToHandDamage(); if (hate) *hate += dmg; } } @@ -1041,13 +1036,8 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate } } else{ - if(GetClass() == MONK || GetClass() == BEASTLORD){ - dmg = GetMonkHandToHandDamage(); - if (hate) *hate += dmg; - } - else{ - dmg = 1; - } + dmg = GetHandToHandDamage(); + if (hate) *hate += dmg; } } @@ -2738,69 +2728,105 @@ uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand) } } -int Mob::GetMonkHandToHandDamage(void) +int Mob::GetHandToHandDamage(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]; + if (RuleB(Combat, UseRevampHandToHand)) { + // everyone uses this in the revamp! + int skill = GetSkill(SkillHandtoHand); + int epic = 0; + if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 46) + epic = 280; + if (epic > skill) + skill = epic; + return skill / 15 + 3; } + + static uint8 mnk_dmg[] = {99, + 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, // 1-10 + 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, // 11-20 + 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, // 21-30 + 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, // 31-40 + 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, // 41-50 + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, // 51-60 + 14, 14}; // 61-62 + static uint8 bst_dmg[] = {99, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, // 1-10 + 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, // 11-20 + 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, // 21-30 + 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 (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 50) + return 9; + if (level > 62) + return 15; + return mnk_dmg[level]; + } else if (GetClass() == BEASTLORD) { + if (level > 49) + return 13; + return bst_dmg[level]; + } + return 2; } -int Mob::GetMonkHandToHandDelay(void) +int Mob::GetHandToHandDelay(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]; - } + if (RuleB(Combat, UseRevampHandToHand)) { + // everyone uses this in the revamp! + int skill = GetSkill(SkillHandtoHand); + int epic = 0; + int iksar = 0; + if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 46) + epic = 280; + else if (GetRace() == IKSAR) + iksar = 1; + if (epic > skill) + skill = epic; + return iksar - skill / 21 + 38; } + + int delay = 35; + static uint8 mnk_hum_delay[] = {99, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, // 1-10 + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, // 11-20 + 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, // 21-30 + 34, 33, 33, 33, 33, 32, 32, 32, 32, 31, // 31-40 + 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, // 41-50 + 29, 28, 28, 28, 28, 27, 27, 27, 27, 26, // 51-60 + 24, 22}; // 61-62 + static uint8 mnk_iks_delay[] = {99, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, // 1-10 + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, // 11-20 + 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, // 21-30 + 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, // 31-40 + 33, 32, 32, 32, 32, 32, 32, 31, 31, 31, // 41-50 + 31, 31, 31, 30, 30, 30, 30, 30, 30, 29, // 51-60 + 25, 23}; // 61-62 + static uint8 bst_delay[] = {99, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, // 1-10 + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, // 11-20 + 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, // 21-30 + 34, 34, 34, 33, 33, 33, 33, 33, 32, 32, // 31-40 + 32, 32, 32, 31, 31, 31, 31, 31, 30, 30, // 41-50 + 30, 30, 30, 29, 29, 29, 29, 29, 28, 28, // 51-60 + 28, 28, 28, 27, 27, 27, 27, 27, 26, 26, // 61-70 + 26, 26, 26}; // 71-73 + + if (GetClass() == MONK) { + // Have a look to see if we have epic fists on + if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 50) + return 16; + int level = GetLevel(); + if (level > 62) + return GetRace() == IKSAR ? 21 : 20; + return GetRace() == IKSAR ? mnk_iks_delay[level] : mnk_hum_delay[level]; + } else if (GetClass() == BEASTLORD) { + int level = GetLevel(); + if (level > 73) + return 25; + return bst_delay[level]; + } + return 35; } int32 Mob::ReduceDamage(int32 damage) @@ -4649,18 +4675,14 @@ void Client::SetAttackTimer() int hhe = itembonuses.HundredHands + spellbonuses.HundredHands; int speed = 0; - int delay = 3600; + int delay = 3500; //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) - delay = 100 * GetMonkHandToHandDelay(); - } else { + if (ItemToUse == nullptr) + delay = 100 * GetHandToHandDelay(); + else //we have a weapon, use its delay delay = 100 * ItemToUse->Delay; - } speed = delay / haste_mod; diff --git a/zone/bot.cpp b/zone/bot.cpp index 9909c6d5d..01f2da41d 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6236,31 +6236,44 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) { return ProcChance; } -int Bot::GetMonkHandToHandDamage(void) { - 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 }; +int Bot::GetHandToHandDamage(void) { + if (RuleB(Combat, UseRevampHandToHand)) { + // everyone uses this in the revamp! + int skill = GetSkill(SkillHandtoHand); + int epic = 0; + if (CastToNPC()->GetEquipment(MaterialHands) == 10652 && GetLevel() > 46) + epic = 280; + if (epic > skill) + skill = epic; + return skill / 15 + 3; + } - uint32 botWeaponId = INVALID_ID; - botWeaponId = CastToNPC()->GetEquipment(MaterialHands); - if(botWeaponId == 10652) + static uint8 mnk_dmg[] = {99, + 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, // 1-10 + 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, // 11-20 + 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, // 21-30 + 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, // 31-40 + 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, // 41-50 + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, // 51-60 + 14, 14}; // 61-62 + static uint8 bst_dmg[] = {99, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, // 1-10 + 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, // 11-20 + 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, // 21-30 + 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) return 9; - else { - int Level = GetLevel(); - if(Level > 65) - return 19; - else - return damage[Level]; - } - - int Level = GetLevel(); - if (Level > 65) - return 19; - else - return damage[Level]; + if (level > 62) + return 15; + return mnk_dmg[level]; + } else if (GetClass() == BEASTLORD) { + if (level > 49) + return 13; + return bst_dmg[level]; + } + return 2; } bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) { @@ -7012,8 +7025,7 @@ void Bot::SetAttackTimer() { int speed = 0; int delay = 36; if (ItemToUse == nullptr) { - if ((GetClass() == MONK) || (GetClass() == BEASTLORD)) - delay = GetMonkHandToHandDelay(); + delay = GetHandToHandDelay(); } else { delay = ItemToUse->Delay; } diff --git a/zone/bot.h b/zone/bot.h index 701f96dd4..a280a2a58 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -171,7 +171,7 @@ public: uint16 BotGetSpellType(int spellslot) { return AIspells[spellslot].type; } uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; } virtual float GetProcChances(float ProcBonus, uint16 hand); - virtual int GetMonkHandToHandDamage(void); + virtual int GetHandToHandDamage(void); virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse); virtual void DoRiposte(Mob* defender); inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(SkillOffense)) * 9 / 10); } diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 0d45c6c36..38fd80cc7 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1023,14 +1023,14 @@ int Lua_Mob::GetHaste() { return self->GetHaste(); } -int Lua_Mob::GetMonkHandToHandDamage() { +int Lua_Mob::GetHandToHandDamage() { Lua_Safe_Call_Int(); - return self->GetMonkHandToHandDamage(); + return self->GetHandToHandDamage(); } -int Lua_Mob::GetMonkHandToHandDelay() { +int Lua_Mob::GetHandToHandDelay() { Lua_Safe_Call_Int(); - return self->GetMonkHandToHandDelay(); + return self->GetHandToHandDelay(); } void Lua_Mob::Mesmerize() { @@ -2165,8 +2165,8 @@ luabind::scope lua_register_mob() { .def("GetInvul", (bool(Lua_Mob::*)(void))&Lua_Mob::GetInvul) .def("SetExtraHaste", (void(Lua_Mob::*)(int))&Lua_Mob::SetExtraHaste) .def("GetHaste", (int(Lua_Mob::*)(void))&Lua_Mob::GetHaste) - .def("GetMonkHandToHandDamage", (int(Lua_Mob::*)(void))&Lua_Mob::GetMonkHandToHandDamage) - .def("GetMonkHandToHandDelay", (int(Lua_Mob::*)(void))&Lua_Mob::GetMonkHandToHandDelay) + .def("GetHandToHandDamage", (int(Lua_Mob::*)(void))&Lua_Mob::GetHandToHandDamage) + .def("GetHandToHandDelay", (int(Lua_Mob::*)(void))&Lua_Mob::GetHandToHandDelay) .def("Mesmerize", (void(Lua_Mob::*)(void))&Lua_Mob::Mesmerize) .def("IsMezzed", (bool(Lua_Mob::*)(void))&Lua_Mob::IsMezzed) .def("IsEnraged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEnraged) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 4009ae2fa..cbc34dc7d 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -217,8 +217,8 @@ public: bool GetInvul(); void SetExtraHaste(int haste); int GetHaste(); - int GetMonkHandToHandDamage(); - int GetMonkHandToHandDelay(); + int GetHandToHandDamage(); + int GetHandToHandDelay(); void Mesmerize(); bool IsMezzed(); bool IsEnraged(); diff --git a/zone/mob.h b/zone/mob.h index 8fc7e7f08..334c81e51 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -756,7 +756,7 @@ public: uint8 GetWeaponDamageBonus(const Item_Struct* weapon, bool offhand = false); uint16 GetDamageTable(SkillUseTypes skillinuse); - virtual int GetMonkHandToHandDamage(void); + virtual int GetHandToHandDamage(void); bool CanThisClassDoubleAttack(void) const; bool CanThisClassTripleAttack() const; @@ -766,7 +766,7 @@ public: bool CanThisClassParry(void) const; bool CanThisClassBlock(void) const; - int GetMonkHandToHandDelay(void); + int GetHandToHandDelay(void); uint32 GetClassLevelFactor(); void Mesmerize(); inline bool IsMezzed() const { return mezzed; } diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 40077c2c5..8f96849df 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -4721,12 +4721,12 @@ XS(XS_Mob_GetHaste) XSRETURN(1); } -XS(XS_Mob_GetMonkHandToHandDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMonkHandToHandDamage) +XS(XS_Mob_GetHandToHandDamage); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_GetHandToHandDamage) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMonkHandToHandDamage(THIS)"); + Perl_croak(aTHX_ "Usage: Mob::GetHandToHandDamage(THIS)"); { Mob * THIS; int RETVAL; @@ -4741,7 +4741,7 @@ XS(XS_Mob_GetMonkHandToHandDamage) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->GetMonkHandToHandDamage(); + RETVAL = THIS->GetHandToHandDamage(); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); @@ -4877,12 +4877,12 @@ XS(XS_Mob_CanThisClassParry) XSRETURN(1); } -XS(XS_Mob_GetMonkHandToHandDelay); /* prototype to pass -Wmissing-prototypes */ -XS(XS_Mob_GetMonkHandToHandDelay) +XS(XS_Mob_GetHandToHandDelay); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_GetHandToHandDelay) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: Mob::GetMonkHandToHandDelay(THIS)"); + Perl_croak(aTHX_ "Usage: Mob::GetHandToHandDelay(THIS)"); { Mob * THIS; int RETVAL; @@ -4897,7 +4897,7 @@ XS(XS_Mob_GetMonkHandToHandDelay) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->GetMonkHandToHandDelay(); + RETVAL = THIS->GetHandToHandDelay(); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); @@ -9192,13 +9192,13 @@ XS(boot_Mob) newXSproto(strcpy(buf, "GetInvul"), XS_Mob_GetInvul, file, "$"); newXSproto(strcpy(buf, "SetExtraHaste"), XS_Mob_SetExtraHaste, file, "$$"); newXSproto(strcpy(buf, "GetHaste"), XS_Mob_GetHaste, file, "$"); - newXSproto(strcpy(buf, "GetMonkHandToHandDamage"), XS_Mob_GetMonkHandToHandDamage, file, "$"); + newXSproto(strcpy(buf, "GetHandToHandDamage"), XS_Mob_GetHandToHandDamage, file, "$"); newXSproto(strcpy(buf, "CanThisClassDoubleAttack"), XS_Mob_CanThisClassDoubleAttack, file, "$"); newXSproto(strcpy(buf, "CanThisClassDualWield"), XS_Mob_CanThisClassDualWield, file, "$"); newXSproto(strcpy(buf, "CanThisClassRiposte"), XS_Mob_CanThisClassRiposte, file, "$"); newXSproto(strcpy(buf, "CanThisClassDodge"), XS_Mob_CanThisClassDodge, file, "$"); newXSproto(strcpy(buf, "CanThisClassParry"), XS_Mob_CanThisClassParry, file, "$"); - newXSproto(strcpy(buf, "GetMonkHandToHandDelay"), XS_Mob_GetMonkHandToHandDelay, file, "$"); + newXSproto(strcpy(buf, "GetHandToHandDelay"), XS_Mob_GetHandToHandDelay, file, "$"); newXSproto(strcpy(buf, "GetClassLevelFactor"), XS_Mob_GetClassLevelFactor, file, "$"); newXSproto(strcpy(buf, "Mesmerize"), XS_Mob_Mesmerize, file, "$"); newXSproto(strcpy(buf, "IsMezzed"), XS_Mob_IsMezzed, file, "$"); From 6a404a5a26686dd868e0d8c888a4607aacbd70d5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 4 Jan 2016 11:04:56 -0600 Subject: [PATCH 490/846] Put the zone controller somewhere where people can't see it even with a terrible GlobalLoad.txt [skip ci] --- zone/npc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 8f09d3f40..bad907936 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -878,9 +878,9 @@ bool NPC::SpawnZoneController(){ strcpy(npc_type->special_abilities, "12,1^13,1^14,1^15,1^16,1^17,1^19,1^22,1^24,1^25,1^28,1^31,1^35,1^39,1^42,1"); glm::vec4 point; - point.x = 5000; - point.y = 5000; - point.z = -5000; + point.x = 3000; + point.y = 1000; + point.z = -500; NPC* npc = new NPC(npc_type, nullptr, point, FlyMode3); npc->GiveNPCTypeData(npc_type); From 2155a53a0d40542f5be3fc25d5cb8046bbd4b8f3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 4 Jan 2016 11:16:26 -0600 Subject: [PATCH 491/846] Another slight adjustment [skip ci] --- zone/npc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index bad907936..11440e6e1 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -856,6 +856,7 @@ bool NPC::SpawnZoneController(){ npc_type->max_hp = 2000000000; npc_type->hp_regen = 100000000; npc_type->race = 240; + npc_type->size = 1; npc_type->gender = 2; npc_type->class_ = 1; npc_type->deity = 1; @@ -880,7 +881,7 @@ bool NPC::SpawnZoneController(){ glm::vec4 point; point.x = 3000; point.y = 1000; - point.z = -500; + point.z = 500; NPC* npc = new NPC(npc_type, nullptr, point, FlyMode3); npc->GiveNPCTypeData(npc_type); From 9174ccd6356b6b27eb81e7ea45e9c02a1f7db829 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 4 Jan 2016 17:11:59 -0600 Subject: [PATCH 492/846] Another slight adjustment [skip ci] --- zone/npc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 11440e6e1..22e4b4b0d 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -856,7 +856,7 @@ bool NPC::SpawnZoneController(){ npc_type->max_hp = 2000000000; npc_type->hp_regen = 100000000; npc_type->race = 240; - npc_type->size = 1; + npc_type->size = .1; npc_type->gender = 2; npc_type->class_ = 1; npc_type->deity = 1; From 20f5c42c3ec6f0f7b47ac5518ef126e830e89b76 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 5 Jan 2016 02:54:09 -0500 Subject: [PATCH 493/846] Fix 60+ resist caps --- zone/client_mods.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 13a8130bd..06c267fd4 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -58,8 +58,8 @@ int32 Client::GetMaxResist() const { int level = GetLevel(); int32 base = 500; - if (level > 60) { - base += ((level - 60) * 5); + if (level > 65) { + base += ((level - 65) * 5); } return base; } From 3a20bbd834acba48d361119dad98b1b057c1db51 Mon Sep 17 00:00:00 2001 From: Luke Wahlmeier Date: Tue, 5 Jan 2016 14:16:29 -0700 Subject: [PATCH 494/846] fixed else error case for eqtime table --- common/database.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 932aa4229..b8889fa06 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2185,8 +2185,7 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1"); auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) - { + if (!results.Success() || results.RowCount() == 0){ Log.Out(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults."); eqTime.minute = 0; eqTime.hour = 9; @@ -2195,15 +2194,16 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) eqTime.year = 3100; realtime = time(0); } + else{ + auto row = results.begin(); - auto row = results.begin(); - - eqTime.minute = atoi(row[0]); - eqTime.hour = atoi(row[1]); - eqTime.day = atoi(row[2]); - eqTime.month = atoi(row[3]); - eqTime.year = atoi(row[4]); - realtime = atoi(row[5]); + eqTime.minute = atoi(row[0]); + eqTime.hour = atoi(row[1]); + eqTime.day = atoi(row[2]); + eqTime.month = atoi(row[3]); + eqTime.year = atoi(row[4]); + realtime = atoi(row[5]); + } return eqTime; } @@ -2215,4 +2215,4 @@ bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year return results.Success(); -} \ No newline at end of file +} From 17c45c8d36fcc75c7eeac210437dcd3864d0b74a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 6 Jan 2016 13:30:50 -0500 Subject: [PATCH 495/846] Move triggered on cast things to after the spell This appears how live does it --- zone/spells.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 4224e9ac3..b8c3023b8 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1268,6 +1268,14 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, } } + // we're done casting, now try to apply the spell + 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(); + return; + } + if(IsClient()) { CheckNumHitsRemaining(NumHit::MatchingSpells); TrySympatheticProc(target, spell_id); @@ -1277,14 +1285,6 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, TryTriggerOnCast(spell_id, 0); - // we're done casting, now try to apply the spell - 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(); - return; - } - if(DeleteChargeFromSlot >= 0) CastToClient()->DeleteItemInInventory(DeleteChargeFromSlot, 1, true); From 2f129da08adde7f9e30096e6ee90439efa4632a3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 6 Jan 2016 15:48:10 -0500 Subject: [PATCH 496/846] Add GetAttackDelay to lua's NPC API --- zone/lua_npc.cpp | 6 ++++++ zone/lua_npc.h | 1 + 2 files changed, 7 insertions(+) diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index f7a8ad99c..6d6c69a62 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -428,6 +428,11 @@ float Lua_NPC::GetAttackSpeed() { return self->GetAttackSpeed(); } +int Lua_NPC::GetAttackDelay() { + Lua_Safe_Call_Int(); + return self->GetAttackDelay(); +} + int Lua_NPC::GetAccuracyRating() { Lua_Safe_Call_Int(); return self->GetAccuracyRating(); @@ -550,6 +555,7 @@ luabind::scope lua_register_npc() { .def("GetSpellFocusHeal", (void(Lua_NPC::*)(int))&Lua_NPC::GetSpellFocusHeal) .def("GetSlowMitigation", (int(Lua_NPC::*)(void))&Lua_NPC::GetSlowMitigation) .def("GetAttackSpeed", (float(Lua_NPC::*)(void))&Lua_NPC::GetAttackSpeed) + .def("GetAttackDelay", (int(Lua_NPC::*)(void))&Lua_NPC::GetAttackDelay) .def("GetAccuracyRating", (int(Lua_NPC::*)(void))&Lua_NPC::GetAccuracyRating) .def("GetSpawnKillCount", (int(Lua_NPC::*)(void))&Lua_NPC::GetSpawnKillCount) .def("GetScore", (int(Lua_NPC::*)(void))&Lua_NPC::GetScore) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index 2b201f323..f5bb4719d 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -111,6 +111,7 @@ public: int GetSpellFocusHeal(); float GetSlowMitigation(); float GetAttackSpeed(); + int GetAttackDelay(); int GetAccuracyRating(); int GetSpawnKillCount(); int GetScore(); From 2b0ee55752d320644d182d43e806054b341d347b Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 8 Jan 2016 17:19:10 -0500 Subject: [PATCH 497/846] Add command #findaliases --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2016_01_08_command_find_aliases.sql | 1 + zone/command.cpp | 33 +++++++++++++++++++ zone/command.h | 1 + 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2016_01_08_command_find_aliases.sql diff --git a/common/version.h b/common/version.h index 00a999add..b1be73905 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 9094 +#define CURRENT_BINARY_DATABASE_VERSION 9095 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 86f7ebe7c..952698c6a 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -348,6 +348,7 @@ 9092|2015_12_17_eqtime.sql|SHOW TABLES LIKE 'eqtime'|empty| 9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty| 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|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|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_01_08_command_find_aliases.sql b/utils/sql/git/required/2016_01_08_command_find_aliases.sql new file mode 100644 index 000000000..ad798dd6a --- /dev/null +++ b/utils/sql/git/required/2016_01_08_command_find_aliases.sql @@ -0,0 +1 @@ +INSERT INTO `command_settings` VALUES ('findaliases', 0, 'fa'); diff --git a/zone/command.cpp b/zone/command.cpp index 5eede229f..3f466fd04 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -194,6 +194,7 @@ int command_init(void) command_add("enablerecipe", "[recipe_id] - Enables a recipe using the recipe id.", 80, command_enablerecipe) || command_add("equipitem", "[slotid(0-21)] - Equip the item on your cursor into the specified slot", 50, command_equipitem) || command_add("face", "- Change the face of your target", 80, command_face) || + command_add("findaliases", "[search term]- Searches for available command aliases, by alias or command", 0, command_findaliases) || command_add("findnpctype", "[search criteria] - Search database NPC types", 100, command_findnpctype) || command_add("findspell", "[searchstring] - Search for a spell", 50, command_findspell) || command_add("findzone", "[search criteria] - Search database zones", 100, command_findzone) || @@ -4945,6 +4946,38 @@ void command_face(Client *c, const Seperator *sep) } } +void command_findaliases(Client *c, const Seperator *sep) +{ + if (!sep->arg[1][0]) { + c->Message(0, "Usage: #findaliases [alias | command]"); + return; + } + + std::map::iterator 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); + if (find_iter->second.empty() || command_iter == commandlist.end()) { + c->Message(0, "An unknown condition occurred..."); + return; + } + + 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) { + if (strcasecmp(find_iter->second.c_str(), alias_iter->second.c_str()) || c->Admin() < command_iter->second->access) + continue; + + c->Message(0, "%c%s", COMMAND_CHAR, alias_iter->first.c_str()); + ++commandaliasesshown; + } + c->Message(0, "%d command alias%s listed.", commandaliasesshown, commandaliasesshown != 1 ? "es" : ""); +} + void command_details(Client *c, const Seperator *sep) { Mob *target=c->GetTarget(); diff --git a/zone/command.h b/zone/command.h index 45aa31fa6..eb3633f57 100644 --- a/zone/command.h +++ b/zone/command.h @@ -94,6 +94,7 @@ void command_emoteview(Client* c, const Seperator *sep); void command_enablerecipe(Client *c, const Seperator *sep); void command_equipitem(Client *c, const Seperator *sep); void command_face(Client *c, const Seperator *sep); +void command_findaliases(Client *c, const Seperator *sep); void command_findnpctype(Client *c, const Seperator *sep); void command_findspell(Client *c, const Seperator *sep); void command_findzone(Client *c, const Seperator *sep); From 1aa98d34ca26c176087d30aa64fa32fe5b46426f Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 8 Jan 2016 17:35:50 -0500 Subject: [PATCH 498/846] Fix for manifest boo-boo --- utils/sql/db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 952698c6a..31f3d2ccf 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -348,7 +348,7 @@ 9092|2015_12_17_eqtime.sql|SHOW TABLES LIKE 'eqtime'|empty| 9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty| 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|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty| +9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 6fc5f8fba23885a423bb7060e5cd566e735a4d8f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 10 Jan 2016 15:31:04 -0500 Subject: [PATCH 499/846] Fix stacking issues with SE_DamageModifier and SE_MinDamageModifier --- zone/bonuses.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index f8edee26d..9e2461bd6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1555,9 +1555,12 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) NegateSpellsBonuses(buffs[i].spellid); } } + + // 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. + 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 *new_bonus, uint16 casterId, @@ -2209,10 +2212,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne // Bad data or unsupported new skill if (base2 > HIGHEST_SKILL) break; - if(base2 == ALL_SKILLS) - new_bonus->DamageModifier[HIGHEST_SKILL+1] += effect_value; - else - new_bonus->DamageModifier[base2] += effect_value; + int skill = base2 == ALL_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) + new_bonus->DamageModifier[skill] = effect_value; break; } @@ -2221,10 +2225,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne // Bad data or unsupported new skill if (base2 > HIGHEST_SKILL) break; - if(base2 == ALL_SKILLS) - new_bonus->DamageModifier2[HIGHEST_SKILL+1] += effect_value; - else - new_bonus->DamageModifier2[base2] += effect_value; + int skill = base2 == ALL_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) + new_bonus->DamageModifier2[skill] = effect_value; break; } @@ -2233,10 +2238,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne // Bad data or unsupported new skill if (base2 > HIGHEST_SKILL) break; - if(base2 == ALL_SKILLS) - new_bonus->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; - else - new_bonus->MinDamageModifier[base2] += effect_value; + int skill = base2 == ALL_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) + new_bonus->MinDamageModifier[skill] = effect_value; break; } From 1711b06836168fa12d5ef69991e0dd5290e0ffa8 Mon Sep 17 00:00:00 2001 From: Tim DeLong Date: Mon, 11 Jan 2016 09:11:38 -0500 Subject: [PATCH 500/846] * LightProfile_Struct::TypeToLevel. The case statement for lightLevelCandle should be lightTypeCandle as the check is on light types, not light levels. Light levels are used for the return value. --- common/item.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/item.cpp b/common/item.cpp index 8e8ec6f1a..7ce8e730d 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -2416,7 +2416,7 @@ uint8 LightProfile_Struct::TypeToLevel(uint8 lightType) return lightLevelSmallMagic; // 3 case lightTypeTorch: return lightLevelTorch; // 2 - case lightLevelCandle: + case lightTypeCandle: return lightLevelCandle; // 1 default: return lightLevelUnlit; // 0 From acb1d14fbd0d75ddac3b65797fffff990f75b8ad Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 11 Jan 2016 13:30:23 -0800 Subject: [PATCH 501/846] Cap Underfoot material / IDFile in the spawn packet to 99,9999 MAX. Anything higher will crash client --- common/patches/uf.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 3535503a0..0efa502c0 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -3048,11 +3048,21 @@ namespace UF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material); + if (emu->equipment[MaterialPrimary].Material > 99999) { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); + } else { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material); + } + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material); + if (emu->equipment[MaterialSecondary].Material > 99999) { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); + } else { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material); + } + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } @@ -3062,7 +3072,11 @@ namespace UF structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].Material = emu->equipment[k].Material; + if (emu->equipment[k].Material > 99999) { + Equipment[k].Material = 63; + } else { + Equipment[k].Material = emu->equipment[k].Material; + } Equipment[k].Unknown1 = emu->equipment[k].Unknown1; Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial; } From 21fc487c335cdd0324093b0e3571e222dc5c60e1 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 12 Jan 2016 18:44:51 -0500 Subject: [PATCH 502/846] World tradeskill objects should now exhibit pre-RoF behavior to all clients --- changelog.txt | 3 +++ zone/client_packet.cpp | 12 ++++-------- zone/object.cpp | 32 +++++++++++++++++++------------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/changelog.txt b/changelog.txt index f8ca4c917..899bcc22c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/12/2016 == +Uleat: Fix for tradeskill containers remaining locked after a RoF+ client leaves. Intermediary fix for RoF+ clients accessing tradeskill containers when in use by another player. + == 12/29/2015 == Akkadius: Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true - When a zone boots, it will spawn an invisible npc by the name of zone_controller diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f20ffb5f4..58381db62 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4253,15 +4253,11 @@ void Client::Handle_OP_ClickObjectAction(const EQApplicationPacket *app) EQApplicationPacket end_trade2(OP_FinishWindow2, 0); QueuePacket(&end_trade2); - return; - // RoF sends a 0 sized packet for closing objects - /* - Object* object = GetTradeskillObject(); - if (object) { - object->CastToObject()->Close(); - } - */ + if (GetTradeskillObject() && GetClientVersion() >= ClientVersion::RoF) + GetTradeskillObject()->CastToObject()->Close(); + + return; } else { diff --git a/zone/object.cpp b/zone/object.cpp index 7255cd9e9..d06a311c0 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -533,20 +533,26 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) ClickObjectAction_Struct* coa = (ClickObjectAction_Struct*)outapp->pBuffer; //TODO: there is prolly a better way to do this. - //if this is not the main user, send them a close and a message - if(user == nullptr || user == sender) - coa->open = 0x01; - else { - coa->open = 0x00; - //sender->Message(13, "Somebody is allready using that container."); - } - m_inuse = true; - coa->type = m_type; - coa->unknown16 = 0x0a; + m_inuse = true; + coa->type = m_type; + coa->unknown16 = 0x0a; - coa->drop_id = click_object->drop_id; - coa->player_id = click_object->player_id; - coa->icon = m_icon; + coa->drop_id = click_object->drop_id; + coa->player_id = click_object->player_id; + coa->icon = m_icon; + + //if this is not the main user, send them a close and a message + if (user == nullptr || user == sender) { + coa->open = 0x01; + } + else { + coa->open = 0x00; + + if (sender->GetClientVersion() >= ClientVersion::RoF) { + coa->drop_id = 0xFFFFFFFF; + sender->Message(0, "Someone else is using that. Try again later."); + } + } if(sender->IsLooting()) { From edeb7d79d174f9c625520ea949d3d896a10a9ce8 Mon Sep 17 00:00:00 2001 From: Athrogate Date: Tue, 12 Jan 2016 19:08:10 -0800 Subject: [PATCH 503/846] Add Lua_Client::ClearCompassMark(). --- changelog.txt | 4 ++++ zone/lua_client.cpp | 6 ++++++ zone/lua_client.h | 1 + 3 files changed, 11 insertions(+) diff --git a/changelog.txt b/changelog.txt index 899bcc22c..2adec24ba 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/12/2016 == +Athrogate: Adding ClearCompassMark() to Lua. + - Lua didn't have ClearCompassMark(). Perl already had this. + == 01/12/2016 == Uleat: Fix for tradeskill containers remaining locked after a RoF+ client leaves. Intermediary fix for RoF+ clients accessing tradeskill containers when in use by another player. diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 1e785ce9b..82167c85b 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1067,6 +1067,11 @@ void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, int co self->MarkSingleCompassLoc(in_x, in_y, in_z, count); } +void Lua_Client::ClearCompassMark() { + Lua_Safe_Call_Void(); + self->MarkSingleCompassLoc(0,0,0,0); +} + int Lua_Client::GetNextAvailableSpellBookSlot() { Lua_Safe_Call_Int(); return self->GetNextAvailableSpellBookSlot(); @@ -1548,6 +1553,7 @@ luabind::scope lua_register_client() { .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int, bool))&Lua_Client::GrantAlternateAdvancementAbility) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float))&Lua_Client::MarkSingleCompassLoc) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float,int))&Lua_Client::MarkSingleCompassLoc) + .def("ClearCompassMark",(void(Lua_Client::*)(void))&Lua_Client::ClearCompassMark) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(void))&Lua_Client::GetNextAvailableSpellBookSlot) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(int))&Lua_Client::GetNextAvailableSpellBookSlot) .def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID) diff --git a/zone/lua_client.h b/zone/lua_client.h index 4584edfd0..5353996c2 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -240,6 +240,7 @@ public: bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost); void MarkSingleCompassLoc(float in_x, float in_y, float in_z); void MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count); + void ClearCompassMark(); int GetNextAvailableSpellBookSlot(); int GetNextAvailableSpellBookSlot(int start); int FindSpellBookSlotBySpellID(int spell_id); From 09b6adf7267efb3cdf25299e4e9f5797c636720f Mon Sep 17 00:00:00 2001 From: Athrogate Date: Tue, 12 Jan 2016 19:08:10 -0800 Subject: [PATCH 504/846] Add Lua_Client::ClearCompassMark(). --- zone/lua_client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 82167c85b..34906bc00 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1058,8 +1058,8 @@ bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ig } void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z) { - Lua_Safe_Call_Void(); - self->MarkSingleCompassLoc(in_x, in_y, in_z); + Lua_Safe_Call_Void(); + self->MarkSingleCompassLoc(in_x, in_y, in_z); } void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count) { From 0fec2fdfdd37ed882c70f4a1f0154a724bec3fe9 Mon Sep 17 00:00:00 2001 From: Athrogate Date: Tue, 12 Jan 2016 19:08:10 -0800 Subject: [PATCH 505/846] Add Lua_Client::ClearCompassMark(). --- zone/lua_client.cpp | 6 +++--- zone/lua_client.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 82167c85b..d77b83c9f 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1068,8 +1068,8 @@ void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, int co } void Lua_Client::ClearCompassMark() { - Lua_Safe_Call_Void(); - self->MarkSingleCompassLoc(0,0,0,0); + Lua_Safe_Call_Void(); + self->MarkSingleCompassLoc(0,0,0,0); } int Lua_Client::GetNextAvailableSpellBookSlot() { @@ -1553,7 +1553,7 @@ luabind::scope lua_register_client() { .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int, bool))&Lua_Client::GrantAlternateAdvancementAbility) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float))&Lua_Client::MarkSingleCompassLoc) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float,int))&Lua_Client::MarkSingleCompassLoc) - .def("ClearCompassMark",(void(Lua_Client::*)(void))&Lua_Client::ClearCompassMark) + .def("ClearCompassMark",(void(Lua_Client::*)(void))&Lua_Client::ClearCompassMark) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(void))&Lua_Client::GetNextAvailableSpellBookSlot) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(int))&Lua_Client::GetNextAvailableSpellBookSlot) .def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID) diff --git a/zone/lua_client.h b/zone/lua_client.h index 5353996c2..36ea2b8a4 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -240,7 +240,7 @@ public: bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost); void MarkSingleCompassLoc(float in_x, float in_y, float in_z); void MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count); - void ClearCompassMark(); + void ClearCompassMark(); int GetNextAvailableSpellBookSlot(); int GetNextAvailableSpellBookSlot(int start); int FindSpellBookSlotBySpellID(int spell_id); From f8ce556acb834d0c6a3dd860016150b9ced5906e Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Wed, 13 Jan 2016 07:58:36 -0500 Subject: [PATCH 506/846] Modified #flag functionality for target-based account status refresh. --- changelog.txt | 4 ++++ zone/command.cpp | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 2adec24ba..4db0256cc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/13/2016 == +Kinglykrab: Modified #flag so you can refresh your target's account status (GM status level) without them having to relog. + - Just target the person whose flag you want to refresh and type #flag. + == 01/12/2016 == Athrogate: Adding ClearCompassMark() to Lua. - Lua didn't have ClearCompassMark(). Perl already had this. diff --git a/zone/command.cpp b/zone/command.cpp index 3f466fd04..8d4df2b46 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -4395,8 +4395,14 @@ void command_uptime(Client *c, const Seperator *sep) void command_flag(Client *c, const Seperator *sep) { if(sep->arg[2][0] == 0) { - c->UpdateAdmin(); - c->Message(0, "Refreshed your admin flag from DB."); + if (!c->GetTarget() || (c->GetTarget() && c->GetTarget() == c)) { + c->UpdateAdmin(); + c->Message(0, "Refreshed your admin flag from DB."); + } else if (c->GetTarget() && c->GetTarget() != c && c->GetTarget()->IsClient()) { + c->GetTarget()->CastToClient()->UpdateAdmin(); + c->Message(0, "%s's admin flag has been refreshed.", c->GetTarget()->GetName()); + c->GetTarget()->Message(0, "%s refreshed your admin flag.", c->GetName()); + } } else if (!sep->IsNumber(1) || atoi(sep->arg[1]) < -2 || atoi(sep->arg[1]) > 255 || strlen(sep->arg[2]) == 0) c->Message(0, "Usage: #flag [status] [acctname]"); From 6db397f07d71cd8526d5aa8fd0f020cd40b28e23 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 13 Jan 2016 15:10:21 -0500 Subject: [PATCH 507/846] Added item link functionality to #summonitem (thanks Kinglykrab!) --- changelog.txt | 2 +- zone/command.cpp | 74 ++++++++++++++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/changelog.txt b/changelog.txt index 4db0256cc..e23ef39c9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -9,7 +9,7 @@ Athrogate: Adding ClearCompassMark() to Lua. - Lua didn't have ClearCompassMark(). Perl already had this. == 01/12/2016 == -Uleat: Fix for tradeskill containers remaining locked after a RoF+ client leaves. Intermediary fix for RoF+ clients accessing tradeskill containers when in use by another player. +Uleat: Fix for tradeskill containers remaining locked after a RoF+ client leaves. Intermediary fix for RoF+ clients accessing tradeskill containers when in use by another player (thanks Natedog!) == 12/29/2015 == Akkadius: Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true diff --git a/zone/command.cpp b/zone/command.cpp index 8d4df2b46..4c25b25d2 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5484,36 +5484,54 @@ void command_interrupt(Client *c, const Seperator *sep) void command_summonitem(Client *c, const Seperator *sep) { - if (!sep->IsNumber(1)) - c->Message(0, "Usage: #summonitem [item id] [charges], charges are optional"); - else { - uint32 itemid = atoi(sep->arg[1]); - int16 item_status = 0; - const Item_Struct* item = database.GetItem(itemid); - if(item) { - item_status = static_cast(item->MinStatus); - } + uint32 itemid = 0; - if (item_status > c->Admin()) - c->Message(13, "Error: Insufficient status to summon this item."); - else if (sep->argnum==2 && sep->IsNumber(2)) - c->SummonItem(itemid, atoi(sep->arg[2])); - else if (sep->argnum==3) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3])); - else if (sep->argnum==4) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); - else if (sep->argnum==5) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5])); - else if (sep->argnum==6) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6])); - else if (sep->argnum==7) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7])); - else if (sep->argnum==8) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), atoi(sep->arg[8])); - else { - c->SummonItem(itemid); - } + 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) { + TextLinkBody_Struct link_body; + Client::TextLink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EmuConstants::TEXT_LINK_BODY_LENGTH)); + itemid = link_body.item_id; } + else if (!sep->IsNumber(1)) { + c->Message(0, "Usage: #summonitem [item id | link] [charges], charges are optional"); + return; + } + else { + itemid = atoi(sep->arg[1]); + } + if (!itemid) { + c->Message(0, "A valid item id number is required (derived: 0)"); + return; + } + + int16 item_status = 0; + const Item_Struct* item = database.GetItem(itemid); + if (item) { + item_status = static_cast(item->MinStatus); + } + + if (item_status > c->Admin()) + c->Message(13, "Error: Insufficient status to summon this item."); + else if (sep->argnum == 2 && sep->IsNumber(2)) + c->SummonItem(itemid, atoi(sep->arg[2])); + else if (sep->argnum == 3) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3])); + else if (sep->argnum == 4) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); + else if (sep->argnum == 5) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5])); + else if (sep->argnum == 6) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6])); + else if (sep->argnum == 7) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7])); + else if (sep->argnum == 8) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), atoi(sep->arg[8])); + else { + c->SummonItem(itemid); + } + } void command_giveitem(Client *c, const Seperator *sep) From e161805bc9f978324719e9aa1178195aeb4dff6a Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 13 Jan 2016 15:25:22 -0500 Subject: [PATCH 508/846] Added changelog entry for #summonitem [itemlink] change --- changelog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.txt b/changelog.txt index e23ef39c9..6bc29becc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 01/13/2016 == Kinglykrab: Modified #flag so you can refresh your target's account status (GM status level) without them having to relog. - 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. From f33f3bd4f552b2e6126ef7a3d17743842b90a2ee Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 15 Jan 2016 16:09:23 -0500 Subject: [PATCH 509/846] Fix Drakkin base resists and some missing class bonuses --- zone/client_mods.cpp | 57 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 06c267fd4..162bffbf8 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1633,13 +1633,19 @@ int32 Client::CalcMR() MR = 30; break; case DRAKKIN: - MR = 35; + { + MR = 25; + if (GetDrakkinHeritage() == 2) + MR += 10; + else if (GetDrakkinHeritage() == 5) + MR += 2; break; + } default: MR = 20; } MR += itembonuses.MR + spellbonuses.MR + aabonuses.MR; - if (GetClass() == WARRIOR) { + if (GetClass() == WARRIOR || GetClass() == BERSERKER) { MR += GetLevel() / 2; } if (MR < 1) { @@ -1701,8 +1707,14 @@ int32 Client::CalcFR() FR = 25; break; case DRAKKIN: + { FR = 25; + if (GetDrakkinHeritage() == 0) + FR += 10; + else if (GetDrakkinHeritage() == 5) + FR += 2; break; + } default: FR = 20; } @@ -1714,6 +1726,13 @@ int32 Client::CalcFR() FR += l - 49; } } + if (c == MONK) { + FR += 8; + int l = GetLevel(); + if (l > 49) { + FR += l - 49; + } + } FR += itembonuses.FR + spellbonuses.FR + aabonuses.FR; if (FR < 1) { FR = 1; @@ -1774,12 +1793,24 @@ int32 Client::CalcDR() DR = 15; break; case DRAKKIN: + { DR = 15; + if (GetDrakkinHeritage() == 1) + DR += 10; + else if (GetDrakkinHeritage() == 5) + DR += 2; break; + } default: DR = 15; } int c = GetClass(); + // the monk one is part of base resist + if (c == MONK) { + int l = GetLevel(); + if (l > 50) + DR += l - 50; + } if (c == PALADIN) { DR += 8; int l = GetLevel(); @@ -1787,7 +1818,7 @@ int32 Client::CalcDR() DR += l - 49; } } - else if (c == SHADOWKNIGHT) { + else if (c == SHADOWKNIGHT || c == BEASTLORD) { DR += 4; int l = GetLevel(); if (l > 49) { @@ -1854,12 +1885,24 @@ int32 Client::CalcPR() PR = 30; break; case DRAKKIN: + { PR = 15; + if (GetDrakkinHeritage() == 3) + PR += 10; + else if (GetDrakkinHeritage() == 5) + PR += 2; break; + } default: PR = 15; } int c = GetClass(); + // this monk bonus is part of the base + if (c == MONK) { + int l = GetLevel(); + if (l > 50) + PR += l = 50; + } if (c == ROGUE) { PR += 8; int l = GetLevel(); @@ -1934,13 +1977,19 @@ int32 Client::CalcCR() CR = 25; break; case DRAKKIN: + { CR = 25; + if (GetDrakkinHeritage() == 4) + CR += 10; + else if (GetDrakkinHeritage() == 5) + CR += 2; break; + } default: CR = 25; } int c = GetClass(); - if (c == RANGER) { + if (c == RANGER || c == BEASTLORD) { CR += 4; int l = GetLevel(); if (l > 49) { From 42f7e03b040f44107b635feb359ceccfd7e1e1a9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 15 Jan 2016 17:00:10 -0500 Subject: [PATCH 510/846] Fix typo in last commit --- zone/client_mods.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 162bffbf8..9fc36a57e 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1901,7 +1901,7 @@ int32 Client::CalcPR() if (c == MONK) { int l = GetLevel(); if (l > 50) - PR += l = 50; + PR += l - 50; } if (c == ROGUE) { PR += 8; From d7e44643b53045064de4454e409bb1db3815b30a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 15 Jan 2016 17:20:48 -0500 Subject: [PATCH 511/846] Fix resist display issue for RoF/RoF2 These need to be found for the other clients They are most likely a similar amount of bytes away from the potionbelt in all clients --- common/patches/rof.cpp | 15 ++++++++------- common/patches/rof2.cpp | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 76d62e3a4..988eba916 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2392,13 +2392,14 @@ namespace RoF outapp->WriteSInt32(234); // Endurance Total ? outapp->WriteSInt32(345); // Mana Total ? - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown + // these are needed to fix display bugs + outapp->WriteUInt32(0x19); // base CR + outapp->WriteUInt32(0x19); // base FR + outapp->WriteUInt32(0x19); // base MR + outapp->WriteUInt32(0xf); // base DR + outapp->WriteUInt32(0xf); // base PR + outapp->WriteUInt32(0xf); // base PhR? + outapp->WriteUInt32(0xf); // base Corrup outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index a8b231300..e0e8f307f 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2471,13 +2471,14 @@ namespace RoF2 outapp->WriteSInt32(234); // Endurance Total ? outapp->WriteSInt32(345); // Mana Total ? - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown + // these are needed to fix display bugs + outapp->WriteUInt32(0x19); // base CR + outapp->WriteUInt32(0x19); // base FR + outapp->WriteUInt32(0x19); // base MR + outapp->WriteUInt32(0xf); // base DR + outapp->WriteUInt32(0xf); // base PR + outapp->WriteUInt32(0xf); // base PhR? + outapp->WriteUInt32(0xf); // base Corrup outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown From 281344b0499ee48f2862750ddbf483fc31038118 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 16 Jan 2016 17:10:11 -0500 Subject: [PATCH 512/846] Add various GetItemStat totallers to ItemInst The intent of these functions is to simplify various locations in the code where we need to get a total of some stat on an item, including augs and we can not just grab the total from the itembonuses struct. This will also centralize where we need to add the powersource aug scaling when we implement them. Since they will need the Purity stat from the item it is in. Notes: - These functions recurse if the augments flag is true, which is false by default to make it so you have to be explicit about recursing or not - These functions don't take into account if you can equip or if you are below recommended level, you will have to do that where you call these functions. --- common/item.cpp | 702 ++++++++++++++++++++++++++++++++++++++++++++++++ common/item.h | 53 ++++ 2 files changed, 755 insertions(+) diff --git a/common/item.cpp b/common/item.cpp index 7ce8e730d..a7b6987de 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -2322,6 +2322,708 @@ void ItemInst::ClearTimers() { m_timers.clear(); } +int ItemInst::GetItemArmorClass(bool augments) const +{ + int ac = 0; + const auto item = GetItem(); + if (item) { + ac = item->AC; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + ac += GetAugment(i)->GetItemArmorClass(); + } + 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 +{ + const auto item = GetItem(); + if (item) { + switch (item->ElemDmgType) { + case RESIST_MAGIC: + magic = item->ElemDmgAmt; + break; + case RESIST_FIRE: + fire = item->ElemDmgAmt; + break; + case RESIST_COLD: + cold = item->ElemDmgAmt; + break; + case RESIST_POISON: + poison = item->ElemDmgAmt; + break; + case RESIST_DISEASE: + disease = item->ElemDmgAmt; + break; + case RESIST_CHROMATIC: + chromatic = item->ElemDmgAmt; + break; + case RESIST_PRISMATIC: + prismatic = item->ElemDmgAmt; + break; + case RESIST_PHYSICAL: + physical = item->ElemDmgAmt; + break; + case RESIST_CORRUPTION: + corruption = item->ElemDmgAmt; + break; + } + + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + GetAugment(i)->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption); + } + return magic + fire + cold + poison + disease + chromatic + prismatic + physical + corruption; +} + +int ItemInst::GetItemElementalFlag(bool augments) const +{ + int flag = 0; + const auto item = GetItem(); + if (item) { + flag = item->ElemDmgType; + if (flag) + return flag; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + if (GetAugment(i)) + flag = GetAugment(i)->GetItemElementalFlag(); + if (flag) + return flag; + } + } + } + return flag; +} + +int ItemInst::GetItemElementalDamage(bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + damage = item->ElemDmgAmt; + if (damage) + return damage; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + if (GetAugment(i)) + damage = GetAugment(i)->GetItemElementalDamage(); + if (damage) + return damage; + } + } + } + return damage; +} + +int ItemInst::GetItemRecommendedLevel(bool augments) const +{ + int level = 0; + const auto item = GetItem(); + if (item) { + level = item->RecLevel; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + int temp = 0; + if (GetAugment(i)) { + temp = GetAugment(i)->GetItemRecommendedLevel(); + if (temp > level) + level = temp; + } + } + } + } + + return level; +} + +int ItemInst::GetItemRequiredLevel(bool augments) const +{ + int level = 0; + const auto item = GetItem(); + if (item) { + level = item->ReqLevel; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + int temp = 0; + if (GetAugment(i)) { + temp = GetAugment(i)->GetItemRequiredLevel(); + if (temp > level) + level = temp; + } + } + } + } + + return level; +} + +int ItemInst::GetItemWeaponDamage(bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + damage = item->Damage; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + damage += GetAugment(i)->GetItemWeaponDamage(); + } + } + return damage; +} + +int ItemInst::GetItemBackstabDamage(bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + damage = item->BackstabDmg; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + damage += GetAugment(i)->GetItemBackstabDamage(); + } + } + return damage; +} + +int ItemInst::GetItemBaneDamageBody(bool augments) const +{ + int body = 0; + const auto item = GetItem(); + if (item) { + body = item->BaneDmgBody; + if (body) + return body; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) { + body = GetAugment(i)->GetItemBaneDamageBody(); + if (body) + return body; + } + } + } + return body; +} + +int ItemInst::GetItemBaneDamageRace(bool augments) const +{ + int race = 0; + const auto item = GetItem(); + if (item) { + race = item->BaneDmgRace; + if (race) + return race; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) { + race = GetAugment(i)->GetItemBaneDamageRace(); + if (race) + return race; + } + } + } + return race; +} + +int ItemInst::GetItemBaneDamageBody(bodyType against, bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + if (item->BaneDmgBody == against) + damage += item->BaneDmgAmt; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + damage += GetAugment(i)->GetItemBaneDamageBody(against); + } + } + return damage; +} + +int ItemInst::GetItemBaneDamageRace(uint16 against, bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + if (item->BaneDmgRace == against) + damage += item->BaneDmgRaceAmt; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + damage += GetAugment(i)->GetItemBaneDamageRace(against); + } + } + return damage; +} + +int ItemInst::GetItemMagical(bool augments) const +{ + const auto item = GetItem(); + if (item) { + if (item->Magic) + return 1; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i) && GetAugment(i)->GetItemMagical()) + return 1; + } + } + return 0; +} + +int ItemInst::GetItemHP(bool augments) const +{ + int hp = 0; + const auto item = GetItem(); + if (item) { + hp = item->HP; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + hp += GetAugment(i)->GetItemHP(); + } + return hp; +} + +int ItemInst::GetItemMana(bool augments) const +{ + int mana = 0; + const auto item = GetItem(); + if (item) { + mana = item->Mana; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + mana += GetAugment(i)->GetItemMana(); + } + return mana; +} + +int ItemInst::GetItemEndur(bool augments) const +{ + int endur = 0; + const auto item = GetItem(); + if (item) { + endur = item->Endur; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + endur += GetAugment(i)->GetItemEndur(); + } + return endur; +} + +int ItemInst::GetItemAttack(bool augments) const +{ + int atk = 0; + const auto item = GetItem(); + if (item) { + atk = item->Attack; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + atk += GetAugment(i)->GetItemAttack(); + } + return atk; +} + +int ItemInst::GetItemStr(bool augments) const +{ + int str = 0; + const auto item = GetItem(); + if (item) { + str = item->AStr; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + str += GetAugment(i)->GetItemStr(); + } + return str; +} + +int ItemInst::GetItemSta(bool augments) const +{ + int sta = 0; + const auto item = GetItem(); + if (item) { + sta = item->ASta; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + sta += GetAugment(i)->GetItemSta(); + } + return sta; +} + +int ItemInst::GetItemDex(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->ADex; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemDex(); + } + return total; +} + +int ItemInst::GetItemAgi(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->AAgi; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemAgi(); + } + return total; +} + +int ItemInst::GetItemInt(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->AInt; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemInt(); + } + return total; +} + +int ItemInst::GetItemWis(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->AWis; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemWis(); + } + return total; +} + +int ItemInst::GetItemCha(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->ACha; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemCha(); + } + return total; +} + +int ItemInst::GetItemMR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->MR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemMR(); + } + return total; +} + +int ItemInst::GetItemFR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->FR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemFR(); + } + return total; +} + +int ItemInst::GetItemCR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->CR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemCR(); + } + return total; +} + +int ItemInst::GetItemPR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->PR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemPR(); + } + return total; +} + +int ItemInst::GetItemDR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->DR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemDR(); + } + return total; +} + +int ItemInst::GetItemCorrup(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->SVCorruption; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemCorrup(); + } + return total; +} + +int ItemInst::GetItemHeroicStr(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicStr; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicStr(); + } + return total; +} + +int ItemInst::GetItemHeroicSta(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicSta; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicSta(); + } + return total; +} + +int ItemInst::GetItemHeroicDex(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicDex; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicDex(); + } + return total; +} + +int ItemInst::GetItemHeroicAgi(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicAgi; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicAgi(); + } + return total; +} + +int ItemInst::GetItemHeroicInt(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicInt; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicInt(); + } + return total; +} + +int ItemInst::GetItemHeroicWis(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicWis; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicWis(); + } + return total; +} + +int ItemInst::GetItemHeroicCha(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicCha; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicCha(); + } + return total; +} + +int ItemInst::GetItemHeroicMR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicMR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicMR(); + } + return total; +} + +int ItemInst::GetItemHeroicFR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicFR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicFR(); + } + return total; +} + +int ItemInst::GetItemHeroicCR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicCR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicCR(); + } + return total; +} + +int ItemInst::GetItemHeroicPR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicPR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicPR(); + } + return total; +} + +int ItemInst::GetItemHeroicDR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicDR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicDR(); + } + return total; +} + +int ItemInst::GetItemHeroicCorrup(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicSVCorrup; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicCorrup(); + } + return total; +} + +int ItemInst::GetItemHaste(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->Haste; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) { + int temp = GetAugment(i)->GetItemHaste(); + if (temp > total) + total = temp; + } + } + return total; +} // // class EvolveInfo diff --git a/common/item.h b/common/item.h index a5dd01f95..b6babde9f 100644 --- a/common/item.h +++ b/common/item.h @@ -29,6 +29,7 @@ class EvolveInfo; // Stores information about an evolving item family #include "../common/eq_constants.h" #include "../common/item_struct.h" #include "../common/timer.h" +#include "../common/bodytypes.h" #include #include @@ -418,6 +419,58 @@ public: void StopTimer(std::string name); void ClearTimers(); + // 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; + protected: ////////////////////////// // Protected Members From 8f0d9015be6fe15854479859ce9d68afc10e9b24 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 16 Jan 2016 17:17:09 -0500 Subject: [PATCH 513/846] Fix rec/req level issues --- zone/bonuses.cpp | 320 ++++++++++++++++++++++------------------------- zone/bot.cpp | 102 ++++++++------- zone/bot.h | 2 +- zone/client.h | 2 +- 4 files changed, 200 insertions(+), 226 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 9e2461bd6..e709bdef4 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -207,32 +207,31 @@ void Client::ProcessItemCaps() itembonuses.ATK = std::min(itembonuses.ATK, CalcItemATKCap()); } -void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) { - if(!inst || !inst->IsType(ItemClassCommon)) - { +void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAug, bool isTribute, int rec_override) +{ + if (!inst || !inst->IsType(ItemClassCommon)) { return; } - if(inst->GetAugmentType()==0 && isAug == true) - { + 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) + if (!isTribute && !inst->IsEquipable(GetBaseRace(), GetClass())) { + if (item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink) return; } - if(GetLevel() < item->ReqLevel) - { + if (GetLevel() < inst->GetItemRequiredLevel(true)) { return; } - if(GetLevel() >= item->RecLevel) - { + // So there isn't a very nice way to get the real rec level from the aug's inst, so we just pass it in, only + // used for augs + auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true); + if (GetLevel() >= rec_level) { newbon->AC += item->AC; newbon->HP += item->HP; newbon->Mana += item->Mana; @@ -281,280 +280,257 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu newbon->HeroicDR += item->HeroicDR; newbon->HeroicCorrup += item->HeroicSVCorrup; - } - else - { + } 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->ATK += CalcRecommendedLevelBonus( lvl, reclvl, item->Attack ); - 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->AC += CalcRecommendedLevelBonus(lvl, rec_level, item->AC); + newbon->HP += CalcRecommendedLevelBonus(lvl, rec_level, item->HP); + newbon->Mana += CalcRecommendedLevelBonus(lvl, rec_level, item->Mana); + newbon->Endurance += CalcRecommendedLevelBonus(lvl, rec_level, item->Endur); + newbon->ATK += CalcRecommendedLevelBonus(lvl, rec_level, item->Attack); + newbon->STR += CalcRecommendedLevelBonus(lvl, rec_level, (item->AStr + item->HeroicStr)); + newbon->STA += CalcRecommendedLevelBonus(lvl, rec_level, (item->ASta + item->HeroicSta)); + newbon->DEX += CalcRecommendedLevelBonus(lvl, rec_level, (item->ADex + item->HeroicDex)); + newbon->AGI += CalcRecommendedLevelBonus(lvl, rec_level, (item->AAgi + item->HeroicAgi)); + newbon->INT += CalcRecommendedLevelBonus(lvl, rec_level, (item->AInt + item->HeroicInt)); + newbon->WIS += CalcRecommendedLevelBonus(lvl, rec_level, (item->AWis + item->HeroicWis)); + newbon->CHA += CalcRecommendedLevelBonus(lvl, rec_level, (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->MR += CalcRecommendedLevelBonus(lvl, rec_level, (item->MR + item->HeroicMR)); + newbon->FR += CalcRecommendedLevelBonus(lvl, rec_level, (item->FR + item->HeroicFR)); + newbon->CR += CalcRecommendedLevelBonus(lvl, rec_level, (item->CR + item->HeroicCR)); + newbon->PR += CalcRecommendedLevelBonus(lvl, rec_level, (item->PR + item->HeroicPR)); + newbon->DR += CalcRecommendedLevelBonus(lvl, rec_level, (item->DR + item->HeroicDR)); + newbon->Corrup += + CalcRecommendedLevelBonus(lvl, rec_level, (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->STRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicStr); + newbon->STACapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSta); + newbon->DEXCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDex); + newbon->AGICapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicAgi); + newbon->INTCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicInt); + newbon->WISCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicWis); + newbon->CHACapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCha); + newbon->MRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicMR); + newbon->CRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicFR); + newbon->FRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCR); + newbon->PRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicPR); + newbon->DRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDR); + newbon->CorrupCapMod += CalcRecommendedLevelBonus(lvl, rec_level, 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 ); + newbon->HeroicSTR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicStr); + newbon->HeroicSTA += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSta); + newbon->HeroicDEX += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDex); + newbon->HeroicAGI += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicAgi); + newbon->HeroicINT += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicInt); + newbon->HeroicWIS += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicWis); + newbon->HeroicCHA += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCha); + newbon->HeroicMR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicMR); + newbon->HeroicFR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicFR); + newbon->HeroicCR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCR); + newbon->HeroicPR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicPR); + newbon->HeroicDR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDR); + newbon->HeroicCorrup += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSVCorrup); } - //FatherNitwit: New style haste, shields, and regens - if(newbon->haste < (int32)item->Haste) { + // FatherNitwit: New style haste, shields, and regens + if (newbon->haste < (int32)item->Haste) { newbon->haste = item->Haste; } - if(item->Regen > 0) + if (item->Regen > 0) newbon->HPRegen += item->Regen; - if(item->ManaRegen > 0) + if (item->ManaRegen > 0) newbon->ManaRegen += item->ManaRegen; - if(item->EnduranceRegen > 0) + if (item->EnduranceRegen > 0) newbon->EnduranceRegen += item->EnduranceRegen; - if(item->DamageShield > 0) { - if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap)) + 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)) + 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)) + 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)) + 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)) + 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)) + 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)) + 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)) + 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)) + 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)) + 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)) + 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)) + 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)) + 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 + if (item->Worn.Effect > 0 && item->Worn.Type == ET_WornEffect) { // 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 == ET_Focus)) { // focus effects ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); } - switch(item->BardType) - { + 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; - } + { + 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; - } + { + if (item->BardValue > newbon->singingMod) + newbon->singingMod = item->BardValue; + break; + } case 23: /* Wind */ - { - if(item->BardValue > newbon->windMod) - newbon->windMod = item->BardValue; - break; - } + { + if (item->BardValue > newbon->windMod) + newbon->windMod = item->BardValue; + break; + } case 24: /* stringed */ - { - if(item->BardValue > newbon->stringedMod) - newbon->stringedMod = item->BardValue; - break; - } + { + if (item->BardValue > newbon->stringedMod) + newbon->stringedMod = item->BardValue; + break; + } case 25: /* brass */ - { - if(item->BardValue > newbon->brassMod) - newbon->brassMod = item->BardValue; - break; - } + { + 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->BardValue > newbon->percussionMod) + newbon->percussionMod = item->BardValue; + break; + } } - if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL){ + 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)) - { + (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) { newbon->skillmod[item->SkillModType] = item->SkillModValue; newbon->skillmodmax[item->SkillModType] = item->SkillModMax; } } // Add Item Faction Mods - if (item->FactionMod1) - { - if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) - { + 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)) - { + } 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)) - { + 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)) - { + } 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)) - { + 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)) - { + } 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)) - { + 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)) - { + } 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)) + 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 < EmuConstants::ITEM_COMMON_SIZE; i++) { - AddItemBonuses(inst->GetAugment(i),newbon,true); - } + if (!isAug) { + for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) + AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level); } - } void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 01f2da41d..9207b5139 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8829,7 +8829,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) newbon->EnduranceRegen = CalcEnduranceRegenCap(); } -void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) { +void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute, in rec_override) { if(!inst || !inst->IsType(ItemClassCommon)) { return; @@ -8848,12 +8848,13 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, return; } - if(GetLevel() < item->ReqLevel) + if(GetLevel() < inst->GetItemRequiredLevel(true)) { return; } - if(GetLevel() >= item->RecLevel) + auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true); + if(GetLevel() >= rec_level) { newbon->AC += item->AC; newbon->HP += item->HP; @@ -8907,55 +8908,54 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, 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->ATK += CalcRecommendedLevelBonus( lvl, reclvl, item->Attack ); - 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->AC += CalcRecommendedLevelBonus( lvl, rec_level, item->AC ); + newbon->HP += CalcRecommendedLevelBonus( lvl, rec_level, item->HP ); + newbon->Mana += CalcRecommendedLevelBonus( lvl, rec_level, item->Mana ); + newbon->Endurance += CalcRecommendedLevelBonus( lvl, rec_level, item->Endur ); + newbon->ATK += CalcRecommendedLevelBonus( lvl, rec_level, item->Attack ); + newbon->STR += CalcRecommendedLevelBonus( lvl, rec_level, (item->AStr + item->HeroicStr) ); + newbon->STA += CalcRecommendedLevelBonus( lvl, rec_level, (item->ASta + item->HeroicSta) ); + newbon->DEX += CalcRecommendedLevelBonus( lvl, rec_level, (item->ADex + item->HeroicDex) ); + newbon->AGI += CalcRecommendedLevelBonus( lvl, rec_level, (item->AAgi + item->HeroicAgi) ); + newbon->INT += CalcRecommendedLevelBonus( lvl, rec_level, (item->AInt + item->HeroicInt) ); + newbon->WIS += CalcRecommendedLevelBonus( lvl, rec_level, (item->AWis + item->HeroicWis) ); + newbon->CHA += CalcRecommendedLevelBonus( lvl, rec_level, (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->MR += CalcRecommendedLevelBonus( lvl, rec_level, (item->MR + item->HeroicMR) ); + newbon->FR += CalcRecommendedLevelBonus( lvl, rec_level, (item->FR + item->HeroicFR) ); + newbon->CR += CalcRecommendedLevelBonus( lvl, rec_level, (item->CR + item->HeroicCR) ); + newbon->PR += CalcRecommendedLevelBonus( lvl, rec_level, (item->PR + item->HeroicPR) ); + newbon->DR += CalcRecommendedLevelBonus( lvl, rec_level, (item->DR + item->HeroicDR) ); + newbon->Corrup += CalcRecommendedLevelBonus( lvl, rec_level, (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->STRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicStr ); + newbon->STACapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSta ); + newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDex ); + newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicAgi ); + newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicInt ); + newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicWis ); + newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCha ); + newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicMR ); + newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicFR ); + newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCR ); + newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicPR ); + newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDR ); + newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, rec_level, 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 ); + newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicStr ); + newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSta ); + newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDex ); + newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicAgi ); + newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicInt ); + newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicWis ); + newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCha ); + newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicMR ); + newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicFR ); + newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCR ); + newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicPR ); + newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDR ); + newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSVCorrup ); } //FatherNitwit: New style haste, shields, and regens @@ -9124,10 +9124,8 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, if (!isAug) { - int i; - for (i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - AddItemBonuses(inst->GetAugment(i),newbon,true); - } + for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) + AddItemBonuses(inst->GetAugment(i),newbon,true, false, rec_level); } } diff --git a/zone/bot.h b/zone/bot.h index a280a2a58..c35fd1f7b 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -193,7 +193,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); + void AddItemBonuses(const ItemInst *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); diff --git a/zone/client.h b/zone/client.h index bc2f89b87..24522f63d 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1275,7 +1275,7 @@ public: protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false); + void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0); void AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); void CalcEdibleBonuses(StatBonuses* newbon); From ad1c91f204c2e05139a02260d5f9dde969eafb8c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 16 Jan 2016 17:52:21 -0500 Subject: [PATCH 514/846] Fix bots --- zone/bot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 9207b5139..5ce63714c 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8829,7 +8829,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) newbon->EnduranceRegen = CalcEnduranceRegenCap(); } -void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute, in rec_override) { +void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute, int rec_override) { if(!inst || !inst->IsType(ItemClassCommon)) { return; From 600866f5730f2b01803ddb37306fd39e553b668d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 16 Jan 2016 18:29:17 -0500 Subject: [PATCH 515/846] Rewrite Bane and Elemental Dmg stuff and GetWeaponDamage (client version) --- zone/attack.cpp | 253 +++++++++++++----------------------------------- zone/mob.cpp | 168 +++++++++++++++++++++++++++++++- zone/mob.h | 2 + 3 files changed, 234 insertions(+), 189 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 532a53686..85ee29e9d 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -928,231 +928,108 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate int banedmg = 0; int x = 0; - if(!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ + 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{ + // check for items being illegally attained + if (weapon_item) { + if (!weapon_item->GetItem()) + return 0; + + if (weapon_item->GetItemRequiredLevel(true) > GetLevel()) + return 0; + + if (!weapon_item->IsEquipable(GetBaseRace(), GetClass())) return 0; - } } - if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ - if(weapon_item){ + 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; + bool MagicWeapon = weapon_item->GetItemMagical(true) || spellbonuses.MagicWeapon || itembonuses.MagicWeapon; + if (MagicWeapon) { + auto rec_level = weapon_item->GetItemRecommendedLevel(true); + if (IsClient() && GetLevel() < rec_level) + dmg = CastToClient()->CalcRecommendedLevelBonus( + GetLevel(), rec_level, weapon_item->GetItemWeaponDamage(true)); else - // An augment on the weapon that is marked magic makes - // the item magical. - for(x = 0; MagicWeapon == false && x < EmuConstants::ITEM_COMMON_SIZE; x++) - { - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()) - { - if (weapon_item->GetAugment(x)->GetItem()->Magic) - 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 < EmuConstants::ITEM_COMMON_SIZE; 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 = weapon_item->GetItemWeaponDamage(true); dmg = dmg <= 0 ? 1 : dmg; - } - else + } else { return 0; - } - else{ - bool MagicGloves=false; + } + } else { + bool MagicGloves = false; if (IsClient()) { - ItemInst *gloves=CastToClient()->GetInv().GetItem(MainHands); - if (gloves != nullptr) { - MagicGloves = gloves->GetItem()->Magic; - } + const ItemInst *gloves = CastToClient()->GetInv().GetItem(MainHands); + if (gloves) + MagicGloves = gloves->GetItemMagical(true); } - if((GetClass() == MONK || GetClass() == BEASTLORD)) { - if(MagicGloves || GetLevel() >= 30){ + if (GetClass() == MONK || GetClass() == BEASTLORD) { + if (MagicGloves || GetLevel() >= 30) { dmg = GetHandToHandDamage(); - if (hate) *hate += dmg; + 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(MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)){ + } 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 (MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)) { dmg = 1; - } - else + } 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; + } else { + if (weapon_item) { + if (weapon_item->GetItem()) { + auto rec_level = weapon_item->GetItemRecommendedLevel(true); + if (IsClient() && GetLevel() < rec_level) { + dmg = CastToClient()->CalcRecommendedLevelBonus( + GetLevel(), rec_level, weapon_item->GetItemWeaponDamage(true)); + } else { + dmg = weapon_item->GetItemWeaponDamage(true); } - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; 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{ + } else { dmg = GetHandToHandDamage(); - if (hate) *hate += dmg; + if (hate) + *hate += dmg; } } 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 < EmuConstants::ITEM_COMMON_SIZE; 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_MAGIC)) { + if (weapon_item && weapon_item->GetItem() && weapon_item->GetItemElementalFlag(true)) + // the client actually has the way this is done, it does not appear to check req! + eledmg = against->ResistElementalWeaponDmg(weapon_item); } - 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 && weapon_item->GetItem() && + (weapon_item->GetItemBaneDamageBody(true) || weapon_item->GetItemBaneDamageRace(true))) + banedmg = against->CheckBaneDamage(weapon_item); - 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 < EmuConstants::ITEM_COMMON_SIZE; 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)) + if (against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) { + if (!eledmg && !banedmg) { + if (!GetSpecialAbility(SPECATK_BANE)) return 0; else return 1; - } - else { + } 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 < EmuConstants::ITEM_COMMON_SIZE; 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 (hate) + *hate += banedmg; } + } else { dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; + if (hate) + *hate += banedmg; } - if(dmg <= 0){ - return 0; - } - else - return dmg; + return std::max(0, dmg); } //note: throughout this method, setting `damage` to a negative is a way to diff --git a/zone/mob.cpp b/zone/mob.cpp index e28ccefcc..2ac1c7f5e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5689,4 +5689,170 @@ int32 Mob::GetMeleeMitigation() { mitigation += itembonuses.MeleeMitigationEffect; mitigation += aabonuses.MeleeMitigationEffect; return mitigation; -} \ No newline at end of file +} + +/* this is the mob being attacked. + * Pass in the weapon's ItemInst + */ +int Mob::ResistElementalWeaponDmg(const ItemInst *item) +{ + if (!item) + return 0; + int magic = 0, fire = 0, cold = 0, poison = 0, disease = 0, chromatic = 0, prismatic = 0, physical = 0, + corruption = 0; + int resist = 0; + int roll = 0; + /* this is how the client does the resist rolls for these. + * Given the difficulty of parsing out these resists, I'll trust the client + */ + if (item->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption, true)) { + if (magic) { + resist = GetMR(); + if (resist >= 201) { + magic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + magic = 0; + else if (roll < 100) + magic = magic * roll / 100; + } + } + + if (fire) { + resist = GetFR(); + if (resist >= 201) { + fire = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + fire = 0; + else if (roll < 100) + fire = fire * roll / 100; + } + } + + if (cold) { + resist = GetCR(); + if (resist >= 201) { + cold = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + cold = 0; + else if (roll < 100) + cold = cold * roll / 100; + } + } + + if (poison) { + resist = GetPR(); + if (resist >= 201) { + poison = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + poison = 0; + else if (roll < 100) + poison = poison * roll / 100; + } + } + + if (disease) { + resist = GetDR(); + if (resist >= 201) { + disease = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + disease = 0; + else if (roll < 100) + disease = disease * roll / 100; + } + } + + if (corruption) { + resist = GetCorrup(); + if (resist >= 201) { + corruption = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + corruption = 0; + else if (roll < 100) + corruption = corruption * roll / 100; + } + } + + if (chromatic) { + resist = GetFR(); + int temp = GetCR(); + if (temp < resist) + resist = temp; + + temp = GetMR(); + if (temp < resist) + resist = temp; + + temp = GetDR(); + if (temp < resist) + resist = temp; + + temp = GetPR(); + if (temp < resist) + resist = temp; + + if (resist >= 201) { + chromatic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + chromatic = 0; + else if (roll < 100) + chromatic = chromatic * roll / 100; + } + } + + if (prismatic) { + resist = (GetFR() + GetCR() + GetMR() + GetDR() + GetPR()) / 5; + if (resist >= 201) { + prismatic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + prismatic = 0; + else if (roll < 100) + prismatic = prismatic * roll / 100; + } + } + + if (physical) { + resist = GetPhR(); + if (resist >= 201) { + physical = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + physical = 0; + else if (roll < 100) + physical = physical * roll / 100; + } + } + } + + return magic + fire + cold + poison + disease + chromatic + prismatic + physical + corruption; +} + +/* this is the mob being attacked. + * Pass in the weapon's ItemInst + */ +int Mob::CheckBaneDamage(const ItemInst *item) +{ + if (!item) + return 0; + + int damage = item->GetItemBaneDamageBody(GetBodyType(), true); + damage += item->GetItemBaneDamageRace(GetRace(), true); + + return damage; +} diff --git a/zone/mob.h b/zone/mob.h index 334c81e51..516bdfe8b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -231,6 +231,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); uint16 GetSpecializeSkillValue(uint16 spell_id) const; void SendSpellBarDisable(); void SendSpellBarEnable(uint16 spellid); From 1ddbfdf4e9ee03b9a6ce0d599ad8f581930f59e0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 16 Jan 2016 18:46:32 -0500 Subject: [PATCH 516/846] Fix ItemInst::GetItemElementalDamage --- common/item.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/common/item.cpp b/common/item.cpp index a7b6987de..26ec154c3 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -2342,31 +2342,31 @@ int ItemInst::GetItemElementalDamage(int &magic, int &fire, int &cold, int &pois if (item) { switch (item->ElemDmgType) { case RESIST_MAGIC: - magic = item->ElemDmgAmt; + magic += item->ElemDmgAmt; break; case RESIST_FIRE: - fire = item->ElemDmgAmt; + fire += item->ElemDmgAmt; break; case RESIST_COLD: - cold = item->ElemDmgAmt; + cold += item->ElemDmgAmt; break; case RESIST_POISON: - poison = item->ElemDmgAmt; + poison += item->ElemDmgAmt; break; case RESIST_DISEASE: - disease = item->ElemDmgAmt; + disease += item->ElemDmgAmt; break; case RESIST_CHROMATIC: - chromatic = item->ElemDmgAmt; + chromatic += item->ElemDmgAmt; break; case RESIST_PRISMATIC: - prismatic = item->ElemDmgAmt; + prismatic += item->ElemDmgAmt; break; case RESIST_PHYSICAL: - physical = item->ElemDmgAmt; + physical += item->ElemDmgAmt; break; case RESIST_CORRUPTION: - corruption = item->ElemDmgAmt; + corruption += item->ElemDmgAmt; break; } From 04b7ba7a1d0ff983e0de2d2e6800e3ec7e334015 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 20 Jan 2016 21:54:18 -0500 Subject: [PATCH 517/846] Added proxy accessors for all TextLink fields --- zone/client.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++------- zone/client.h | 30 +++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index ceedf19d7..3fab7671e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8423,7 +8423,19 @@ void Client::TextLink::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_ProxyText = nullptr; m_TaskUse = false; m_Link.clear(); @@ -8439,8 +8451,8 @@ void Client::TextLink::generate_body() 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) + 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)); @@ -8492,13 +8504,36 @@ void Client::TextLink::generate_body() break; } - if (m_ProxyItemID != NOT_USED) { + 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) { + + if (m_TaskUse) m_LinkBodyStruct.hash = 0x14505DC2; - } m_LinkBody = StringFormat( "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", @@ -8515,7 +8550,7 @@ void Client::TextLink::generate_body() (0xFF & m_LinkBodyStruct.evolve_level), (0x000FFFFF & m_LinkBodyStruct.ornament_icon), (0xFFFFFFFF & m_LinkBodyStruct.hash) - ); + ); } void Client::TextLink::generate_text() diff --git a/zone/client.h b/zone/client.h index 24522f63d..d9f2f0dfc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -831,7 +831,22 @@ public: 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; } - void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } // mainly for saylinks..but, not limited to + + // 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; } @@ -855,7 +870,20 @@ public: 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; From d86307c7203eb55e2d341c960c823f91109f804f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 20 Jan 2016 22:31:35 -0500 Subject: [PATCH 518/846] Rework say links We now consume 1 item ID for say links, this means you will be able to create more items! We used ID 0xFFFFF for this, which is the max ID an item can be in the item links. You have the rest to play with! Normal say links pass the ID in the first aug slot and silent say links in the second aug slot. This means we can have MANY more say links as well! --- common/features.h | 3 + zone/bot.cpp | 5 +- zone/client_packet.cpp | 137 ++++++++++++++++++----------------------- zone/questmgr.cpp | 13 ++-- zone/zone.cpp | 2 +- 5 files changed, 72 insertions(+), 88 deletions(-) diff --git a/common/features.h b/common/features.h index 8115efd82..9ceddb31b 100644 --- a/common/features.h +++ b/common/features.h @@ -273,6 +273,9 @@ enum { #define NPC_DEFAULT_LOGGING_ENABLED false +// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars +#define SAYLINK_ITEM_ID 0xFFFFF + /* diff --git a/zone/bot.cpp b/zone/bot.cpp index 5ce63714c..01aafa4aa 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -13774,11 +13774,10 @@ std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) } safe_delete_array(escaped_string); - sayid += 500000; - Client::TextLink linker; linker.SetLinkType(linker.linkItemData); - linker.SetProxyItemID(sayid); + linker.SetProxyItemID(SAYLINK_ITEM_ID); + linker.SetProxyAugment1ID(sayid); linker.SetProxyText(name); auto say_link = linker.GenerateLink(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 58381db62..1475b6c74 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8090,97 +8090,80 @@ void Client::Handle_OP_InstillDoubt(const EQApplicationPacket *app) void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) { - if (app->size != sizeof(ItemViewRequest_Struct)){ - Log.Out(Logs::General, Logs::Error, "Wrong size on OP_ItemLinkClick. Got: %i, Expected: %i", app->size, sizeof(ItemViewRequest_Struct)); + if (app->size != sizeof(ItemViewRequest_Struct)) { + Log.Out(Logs::General, Logs::Error, "Wrong size on OP_ItemLinkClick. Got: %i, Expected: %i", app->size, + sizeof(ItemViewRequest_Struct)); DumpPacket(app); return; } DumpPacket(app); - ItemViewRequest_Struct* ivrs = (ItemViewRequest_Struct*)app->pBuffer; + ItemViewRequest_Struct *ivrs = (ItemViewRequest_Struct *)app->pBuffer; - //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 + // 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 Item_Struct *item = database.GetItem(ivrs->item_id); if (!item) { - if (ivrs->item_id > 500000) - { - std::string response = ""; - int sayid = ivrs->item_id - 500000; - bool silentsaylink = false; - - if (sayid > 250000) //Silent Saylink - { - sayid = sayid - 250000; - silentsaylink = true; - } - - if (sayid > 0) - { - - std::string query = StringFormat("SELECT `phrase` FROM saylink WHERE `id` = '%i'", sayid); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - Message(13, "Error: The saylink (%s) was not found in the database.", response.c_str()); - return; - } - - if (results.RowCount() != 1) { - Message(13, "Error: The saylink (%s) was not found in the database.", response.c_str()); - return; - } - - auto row = results.begin(); - response = row[0]; - - } - - if ((response).size() > 0) - { - if (!mod_saylink(response, silentsaylink)) { return; } - - if (GetTarget() && GetTarget()->IsNPC()) - { - if (silentsaylink) - { - parse->EventNPC(EVENT_SAY, GetTarget()->CastToNPC(), this, response.c_str(), 0); - parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0); - } - else - { - Message(7, "You say, '%s'", response.c_str()); - ChannelMessageReceived(8, 0, 100, response.c_str()); - } - return; - } - else - { - if (silentsaylink) - { - parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0); - } - else - { - Message(7, "You say, '%s'", response.c_str()); - ChannelMessageReceived(8, 0, 100, response.c_str()); - } - return; - } - } - else - { - Message(13, "Error: Say Link not found or is too long."); - return; - } - } - else { + if (ivrs->item_id != SAYLINK_ITEM_ID) { Message(13, "Error: The item for the link you have clicked on does not exist!"); return; } + // This new scheme will shuttle the ID in the first augment for non-silent links + // and the second augment for silent. + std::string response = ""; + bool silentsaylink = ivrs->augments[1] > 0 ? true : false; + int sayid = silentsaylink ? ivrs->augments[1] : ivrs->augments[0]; + if (sayid > 0) { + std::string query = StringFormat("SELECT `phrase` FROM saylink WHERE `id` = '%i'", sayid); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + Message(13, "Error: The saylink (%s) was not found in the database.", response.c_str()); + return; + } + + if (results.RowCount() != 1) { + Message(13, "Error: The saylink (%s) was not found in the database.", response.c_str()); + return; + } + + auto row = results.begin(); + response = row[0]; + } + + if ((response).size() > 0) { + if (!mod_saylink(response, silentsaylink)) { + return; + } + + if (GetTarget() && GetTarget()->IsNPC()) { + if (silentsaylink) { + parse->EventNPC(EVENT_SAY, GetTarget()->CastToNPC(), this, response.c_str(), 0); + parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0); + } else { + Message(7, "You say, '%s'", response.c_str()); + ChannelMessageReceived(8, 0, 100, response.c_str()); + } + return; + } else { + if (silentsaylink) { + parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0); + } else { + Message(7, "You say, '%s'", response.c_str()); + ChannelMessageReceived(8, 0, 100, response.c_str()); + } + return; + } + } else { + Message(13, "Error: Say Link not found or is too long."); + return; + } } - ItemInst* inst = database.CreateItem(item, item->MaxCharges, ivrs->augments[0], ivrs->augments[1], ivrs->augments[2], ivrs->augments[3], ivrs->augments[4], ivrs->augments[5]); + ItemInst *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) { SendItemPacket(0, inst, ItemPacketViewLink); safe_delete(inst); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 86b8cb7d9..fa8788bbf 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2766,14 +2766,13 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam } safe_delete_array(escaped_string); - if (silent) - sayid = sayid + 750000; - else - sayid = sayid + 500000; - //Create the say link as an item link hash Client::TextLink linker; - linker.SetProxyItemID(sayid); + linker.SetProxyItemID(SAYLINK_ITEM_ID); + if (silent) + linker.SetProxyAugment2ID(sayid); + else + linker.SetProxyAugment1ID(sayid); linker.SetProxyText(LinkName); auto say_link = linker.GenerateLink(); @@ -3164,4 +3163,4 @@ void QuestManager::UpdateZoneHeader(std::string type, std::string value) { memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(0, outapp); safe_delete(outapp); -} \ No newline at end of file +} diff --git a/zone/zone.cpp b/zone/zone.cpp index b3a6fc1ca..08a98fb10 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -292,7 +292,7 @@ bool Zone::LoadGroundSpawns() { char* name=0; uint32 gsnumber=0; for(gsindex=0;gsindex<50;gsindex++){ - if(groundspawn.spawn[gsindex].item>0 && groundspawn.spawn[gsindex].item<500000){ + if(groundspawn.spawn[gsindex].item>0 && groundspawn.spawn[gsindex].item Date: Thu, 21 Jan 2016 11:53:14 -0500 Subject: [PATCH 519/846] If an error occurs (!results.Success()) in loadlootdrops the method continues processing instead of exiting. --- common/shareddb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index f82d54fad..97f2f69ee 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1920,6 +1920,7 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { "ON lootdrop.id = lootdrop_entries.lootdrop_id ORDER BY lootdrop_id"; auto results = QueryDatabase(query); if (!results.Success()) { + return; } uint32 current_id = 0; From c4cdf811e3cbbf009d4d3b2ad6af7505e52f9def Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 22 Jan 2016 13:42:14 -0600 Subject: [PATCH 520/846] Fix for zone controller spawn events where npc isn't inserted into entity list yet --- zone/entity.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 92fefb2ec..a79d01609 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -644,15 +644,6 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); - /* Zone controller process EVENT_SPAWN_ZONE */ - if (RuleB(Zone, UseZoneController)) { - if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ - char data_pass[100] = { 0 }; - snprintf(data_pass, 99, "%d %d", npc->GetID(), npc->GetNPCTypeID()); - parse->EventNPC(EVENT_SPAWN_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0); - } - } - uint16 emoteid = npc->GetEmoteID(); if (emoteid != 0) npc->DoNPCEmote(ONSPAWN, emoteid); @@ -678,6 +669,16 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) npc_list.insert(std::pair(npc->GetID(), npc)); mob_list.insert(std::pair(npc->GetID(), npc)); + + /* Zone controller process EVENT_SPAWN_ZONE */ + if (RuleB(Zone, UseZoneController)) { + if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ + char data_pass[100] = { 0 }; + snprintf(data_pass, 99, "%d %d", npc->GetID(), npc->GetNPCTypeID()); + parse->EventNPC(EVENT_SPAWN_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0); + } + } + } void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue) From 15c92f019a92c3840b82bebbdb8c76b140c1fa1d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 25 Jan 2016 14:00:22 -0500 Subject: [PATCH 521/846] Mob::Charmed() should be useful now We should really clean this up, but this is quicker --- zone/mob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob.h b/zone/mob.h index 516bdfe8b..554634006 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -887,7 +887,7 @@ public: Mob* GetShieldTarget() const { return shield_target; } void SetShieldTarget(Mob* mob) { shield_target = mob; } bool HasActiveSong() const { return(bardsong != 0); } - bool Charmed() const { return charmed; } + bool Charmed() const { return typeofpet == petCharmed; } static uint32 GetLevelHP(uint8 tlevel); uint32 GetZoneID() const; //for perl virtual int32 CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc = false); From 1b7841f683c58a0c816cc6d4bfe9214d29f0b0e2 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 26 Jan 2016 15:08:41 -0500 Subject: [PATCH 522/846] Fix for Berserker 'Piercing' skill issues --- changelog.txt | 3 +++ common/eq_constants.h | 8 ++++---- common/patches/rof2_constants.h | 2 ++ common/patches/rof_constants.h | 2 ++ common/patches/sod_constants.h | 2 ++ common/patches/sof_constants.h | 2 ++ common/patches/titanium_constants.h | 2 ++ common/patches/uf_constants.h | 2 ++ common/skills.cpp | 2 +- common/skills.h | 4 ++-- world/client.cpp | 5 +++++ zone/attack.cpp | 22 ++++++++++------------ zone/bot.cpp | 6 +++--- zone/client.cpp | 15 ++++++++++++--- zone/client_process.cpp | 5 +++++ zone/common.h | 2 +- zone/mob.cpp | 7 ++++++- zone/special_attacks.cpp | 4 ++-- 18 files changed, 66 insertions(+), 29 deletions(-) diff --git a/changelog.txt b/changelog.txt index 6bc29becc..c758d165c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/26/2016 == +Uleat: Fix for Berserker 'Piercing' skill issues. Server Admins: If you run custom skill sets, this patch touches the code segments that you will need to modify if you have changed the default berserker 1H-/2H-piercing skill values. + == 01/13/2016 == Kinglykrab: Modified #flag so you can refresh your target's account status (GM status level) without them having to relog. - Just target the person whose flag you want to refresh and type #flag. diff --git a/common/eq_constants.h b/common/eq_constants.h index 0fec1f223..add66c2f4 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -799,10 +799,10 @@ static const uint8 SkillDamageTypes[HIGHEST_SKILL + 1] = // change to _SkillServ /*Intimidation*/ DamageTypeUnknown, /*Berserking*/ DamageTypeUnknown, /*Taunt*/ DamageTypeUnknown, -/*Frenzy*/ 74 //, -// /*RemoveTrap*/ DamageTypeUnknown, // Needs research (set for SenseTrap value) -// /*TripleAttack*/ DamageTypeUnknown, // Needs research (set for DoubleAttack value) -// /*2HPiercing*/ 36 // Needs research (set for 1HPiercing value - similar to slash/blunt) +/*Frenzy*/ 74, +/*RemoveTrap*/ DamageTypeUnknown, // Needs research (set for SenseTrap value) +/*TripleAttack*/ DamageTypeUnknown, // Needs research (set for DoubleAttack value) +/*2HPiercing*/ 36 // Needs research (set for 1HPiercing value - similar to slash/blunt) }; /* diff --git a/common/patches/rof2_constants.h b/common/patches/rof2_constants.h index 4c8245737..0732044ca 100644 --- a/common/patches/rof2_constants.h +++ b/common/patches/rof2_constants.h @@ -186,6 +186,8 @@ namespace RoF2 { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 56; + + static const size_t PLAYER_PROFILE_SKILL_MAX = Skill2HPiercing; } namespace limits { diff --git a/common/patches/rof_constants.h b/common/patches/rof_constants.h index 8b5fadbf2..b348f5fd5 100644 --- a/common/patches/rof_constants.h +++ b/common/patches/rof_constants.h @@ -185,6 +185,8 @@ namespace RoF { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 55; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; } namespace limits { diff --git a/common/patches/sod_constants.h b/common/patches/sod_constants.h index 5dad9bb09..ebd1d7d48 100644 --- a/common/patches/sod_constants.h +++ b/common/patches/sod_constants.h @@ -182,6 +182,8 @@ namespace SoD { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 50; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; } namespace limits { diff --git a/common/patches/sof_constants.h b/common/patches/sof_constants.h index 260722f00..4ffcdd525 100644 --- a/common/patches/sof_constants.h +++ b/common/patches/sof_constants.h @@ -182,6 +182,8 @@ namespace SoF { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 50; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; } namespace limits { diff --git a/common/patches/titanium_constants.h b/common/patches/titanium_constants.h index d7e2a4964..4915c829c 100644 --- a/common/patches/titanium_constants.h +++ b/common/patches/titanium_constants.h @@ -181,6 +181,8 @@ namespace Titanium { static const size_t POTION_BELT_ITEM_COUNT = 4; static const size_t TEXT_LINK_BODY_LENGTH = 45; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillFrenzy; } namespace limits { diff --git a/common/patches/uf_constants.h b/common/patches/uf_constants.h index 1a5a4cc44..b8096fd58 100644 --- a/common/patches/uf_constants.h +++ b/common/patches/uf_constants.h @@ -182,6 +182,8 @@ namespace UF { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 50; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; } namespace limits { diff --git a/common/skills.cpp b/common/skills.cpp index 5edca778b..85c660f6c 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -71,7 +71,7 @@ float EQEmu::GetSkillMeleePushForce(SkillUseTypes skill) case SkillEagleStrike: case SkillKick: case SkillTigerClaw: - //case Skill2HPiercing: + case Skill2HPiercing: return 0.2f; case SkillArchery: return 0.15f; diff --git a/common/skills.h b/common/skills.h index c79a522ee..4e1e9eb83 100644 --- a/common/skills.h +++ b/common/skills.h @@ -114,7 +114,7 @@ enum SkillUseTypes /*13049*/ SkillTripleAttack, // RoF2+ specific skills -// /*00789*/ Skill2HPiercing, +/*00789*/ Skill2HPiercing, // /*01216*/ SkillNone, // This needs to move down as new skills are added /*00000*/ _EmuSkillCount // move to last position of active enumeration labels @@ -171,7 +171,7 @@ enum SkillUseTypes }; // temporary until it can be sorted out... -#define HIGHEST_SKILL SkillTripleAttack +#define HIGHEST_SKILL Skill2HPiercing // Spell Effects use this value to determine if an effect applies to all skills. #define ALL_SKILLS -1 diff --git a/world/client.cpp b/world/client.cpp index 9a194e5ec..dc17d7b4d 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1814,6 +1814,11 @@ void Client::SetClassStartingSkills(PlayerProfile_Struct *pp) pp->skills[i] = database.GetSkillCap(pp->class_, (SkillUseTypes)i, 1); } } + + if (cle->GetClientVersion() < static_cast(ClientVersion::RoF2) && pp->class_ == BERSERKER) { + pp->skills[Skill1HPiercing] = pp->skills[Skill2HPiercing]; + pp->skills[Skill2HPiercing] = 0; + } } void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp ) diff --git a/zone/attack.cpp b/zone/attack.cpp index 85ee29e9d..2fdf5f115 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -76,7 +76,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w case ItemType1HPiercing: // Piercing { skillinuse = Skill1HPiercing; - type = animPiercing; + type = anim1HPiercing; break; } case ItemType1HBlunt: // 1H Blunt @@ -93,7 +93,10 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w } case ItemType2HPiercing: // 2H Piercing { - skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated + if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + skillinuse = Skill1HPiercing; + else + skillinuse = Skill2HPiercing; type = anim2HWeapon; break; } @@ -127,7 +130,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w } case Skill1HPiercing: // Piercing { - type = animPiercing; + type = anim1HPiercing; break; } case Skill1HBlunt: // 1H Blunt @@ -140,7 +143,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w type = anim2HSlashing; //anim2HWeapon break; } - case 99: // 2H Piercing // change to Skill2HPiercing once activated + case Skill2HPiercing: // 2H Piercing { type = anim2HWeapon; break; @@ -1652,10 +1655,10 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool skillinuse = Skill2HSlashing; break; case ItemType1HPiercing: - //skillinuse = Skill1HPiercing; - //break; + skillinuse = Skill1HPiercing; + break; case ItemType2HPiercing: - skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated + skillinuse = Skill2HPiercing; break; case ItemType1HBlunt: skillinuse = Skill1HBlunt; @@ -1683,11 +1686,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool 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) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 01aafa4aa..926df4fb0 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1179,7 +1179,7 @@ uint16 Bot::GetPrimarySkillValue() { break; } case ItemType2HPiercing: { - skill = Skill1HPiercing; // change to Skill2HPiercing once activated + skill = Skill2HPiercing; break; } case ItemTypeMartial: { @@ -6493,7 +6493,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { ndamage = -5; DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime); - DoAnim(animPiercing); + DoAnim(anim1HPiercing); } void Bot::RogueAssassinate(Mob* other) { @@ -6505,7 +6505,7 @@ void Bot::RogueAssassinate(Mob* other) { other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); } - DoAnim(animPiercing); + DoAnim(anim1HPiercing); } void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { diff --git a/zone/client.cpp b/zone/client.cpp index 3fab7671e..c8c1494e5 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2343,11 +2343,17 @@ bool Client::HasSkill(SkillUseTypes skill_id) const { } bool Client::CanHaveSkill(SkillUseTypes skill_id) const { + if (GetClientVersion() < ClientVersion::RoF2 && class_ == BERSERKER && skill_id == Skill1HPiercing) + skill_id = 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 (GetClientVersion() < ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) + skillid = Skill2HPiercing; + return(database.GetSkillCap(class_, skillid, level)); } @@ -4211,7 +4217,10 @@ uint16 Client::GetPrimarySkillValue() } case ItemType2HPiercing: // 2H Piercing { - skill = Skill1HPiercing; // change to Skill2HPiercing once activated + if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + skill = Skill1HPiercing; + else + skill = Skill2HPiercing; break; } case ItemTypeMartial: // Hand to Hand @@ -4950,11 +4959,11 @@ void Client::ShowSkillsWindow() const char* SkillName[] = {"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","Piercing","Ripost","Round Kick","Safe Fall","Sense Heading", + "Hide","Kick","Meditate","Mend","Offense","Parry","Pick Lock","1H Piercing","Ripost","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"}; + "Pottery","Percussion Instruments","Intimidation","Berserking","Taunt","Frenzy","Remove Traps","Triple Attack","2H Piercing"}; for(int i = 0; i <= (int)HIGHEST_SKILL; i++) Skills[SkillName[i]] = (SkillUseTypes)i; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 3b973e7b7..3154a9ca9 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1553,6 +1553,11 @@ void Client::OPGMTraining(const EQApplicationPacket *app) //Set it to 1 with CanHaveSkill or you wont be able to train past 1. } } + + if (GetClientVersion() < ClientVersion::RoF2 && GetClass() == BERSERKER) { + gmtrain->skills[Skill1HPiercing] = gmtrain->skills[Skill2HPiercing]; + gmtrain->skills[Skill2HPiercing] = 0; + } //#pragma GCC pop_options uchar ending[]={0x34,0x87,0x8a,0x3F,0x01 diff --git a/zone/common.h b/zone/common.h index 48749dbc3..bcae779a9 100644 --- a/zone/common.h +++ b/zone/common.h @@ -511,7 +511,7 @@ typedef struct //make DoAnim take it instead of int, to enforce its use. enum { //type arguments to DoAnim animKick = 1, - animPiercing = 2, //might be piercing? + anim1HPiercing = 2, //might be piercing? anim2HSlashing = 3, anim2HWeapon = 4, anim1HWeapon = 5, diff --git a/zone/mob.cpp b/zone/mob.cpp index 2ac1c7f5e..3dad9b247 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5029,7 +5029,10 @@ uint16 Mob::GetSkillByItemType(int ItemType) case ItemType2HBlunt: return Skill2HBlunt; case ItemType2HPiercing: - return Skill1HPiercing; // change to 2HPiercing once activated + if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + return Skill1HPiercing; + else + return Skill2HPiercing; case ItemTypeBow: return SkillArchery; case ItemTypeLargeThrowing: @@ -5057,6 +5060,8 @@ uint8 Mob::GetItemTypeBySkill(SkillUseTypes skill) return ItemType2HSlash; case Skill1HPiercing: return ItemType1HPiercing; + case Skill2HPiercing: // watch for undesired client behavior + return ItemType2HPiercing; case Skill1HBlunt: return ItemType1HBlunt; case Skill2HBlunt: diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index c43c8f432..2c763df13 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -660,7 +660,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) } DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime, false, false); - DoAnim(animPiercing); + DoAnim(anim1HPiercing); } // assassinate [No longer used for regular assassinate 6-29-14] @@ -673,7 +673,7 @@ void Mob::RogueAssassinate(Mob* other) }else{ other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); } - DoAnim(animPiercing); //piercing animation + DoAnim(anim1HPiercing); //piercing animation } void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { From 52541c6532bfce47754df3d7cdabaa8b2a78af91 Mon Sep 17 00:00:00 2001 From: Tim DeLong Date: Tue, 26 Jan 2016 16:44:11 -0500 Subject: [PATCH 523/846] Item weight was being downcast to uint8 which impacted any item with weight over 255. For SoD, SoF, and UF, prior to sending item info to the client we now cap weight at 255 to ensure the item remains heavy instead of being made (in most cases), super light. --- common/item_struct.h | 2 +- common/patches/sod.cpp | 3 ++- common/patches/sof.cpp | 3 ++- common/patches/uf.cpp | 3 ++- common/shareddb.cpp | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/common/item_struct.h b/common/item_struct.h index ba8afcd14..937c9e47c 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -83,7 +83,7 @@ struct Item_Struct { char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore char IDFile[30]; // Visible model uint32 ID; // Unique ID (also PK for DB) - uint8 Weight; // Item weight * 10 + 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 diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index bbd5acd45..d5a6035f4 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3623,7 +3623,8 @@ namespace SoD memset(&ibs, 0, sizeof(SoD::structs::ItemBodyStruct)); ibs.id = item->ID; - ibs.weight = item->Weight; + // weight is uint8 in the struct, and some weights exceed that, so capping at 255. + ibs.weight = (item->Weight > 255) ? 255 : item->Weight; ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index d8b7db541..f407ffdc0 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2945,7 +2945,8 @@ namespace SoF memset(&ibs, 0, sizeof(SoF::structs::ItemBodyStruct)); ibs.id = item->ID; - ibs.weight = item->Weight; + // weight is uint8 in the struct, and some weights exceed that, so capping at 255. + ibs.weight = (item->Weight > 255) ? 255 : item->Weight; ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 0efa502c0..c42de5145 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -3924,7 +3924,8 @@ namespace UF memset(&ibs, 0, sizeof(UF::structs::ItemBodyStruct)); ibs.id = item->ID; - ibs.weight = item->Weight; + // weight is uint8 in the struct, and some weights exceed that, so capping at 255. + ibs.weight = (item->Weight > 255) ? 255 : item->Weight; ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 97f2f69ee..79bac527e 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -857,7 +857,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ strcpy(item.IDFile, row[ItemField::idfile]); item.ID = (uint32)atoul(row[ItemField::id]); - item.Weight = (uint8)atoi(row[ItemField::weight]); + item.Weight = (int32)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]); From 430be0f2b7b91184339f3f6cf44ec037da0eb9cc Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 26 Jan 2016 19:02:07 -0500 Subject: [PATCH 524/846] Follow-up for Titanium client - item weight fix (WARNING: re-run shared_memory; Note: re-run cmake; see changelog.txt) --- changelog.txt | 3 +++ common/CMakeLists.txt | 6 ++++-- common/patches/titanium.cpp | 8 ++++++-- common/patches/titanium_itemfields_a.h | 19 +++++++++++++++++++ ...m_itemfields.h => titanium_itemfields_b.h} | 10 ++++------ 5 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 common/patches/titanium_itemfields_a.h rename common/patches/{titanium_itemfields.h => titanium_itemfields_b.h} (96%) diff --git a/changelog.txt b/changelog.txt index c758d165c..ee77f075d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 01/26/2016 == Uleat: Fix for Berserker 'Piercing' skill issues. Server Admins: If you run custom skill sets, this patch touches the code segments that you will need to modify if you have changed the default berserker 1H-/2H-piercing skill values. +Uleat (Daerath): Fix for precision-loss item weight conversions in older clients. + - WARNING: YOU MUST RE-RUN SHARED_MEMORY.EXE BEFORE STARTING SERVER OR ITEM LOSS WILL OCCUR! + - Note: Cmake must be re-run to include/exclude the required files == 01/13/2016 == Kinglykrab: Modified #flag so you can refresh your target's account status (GM status level) without them having to relog. diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f847957db..09ed7e02c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -213,7 +213,8 @@ SET(common_headers patches/rof2_structs.h patches/titanium.h patches/titanium_constants.h - patches/titanium_itemfields.h + patches/titanium_itemfields_a.h + patches/titanium_itemfields_b.h patches/titanium_ops.h patches/titanium_structs.h patches/uf.h @@ -265,7 +266,8 @@ SOURCE_GROUP(Patches FILES patches/rof2_constants.h patches/rof2_structs.h patches/titanium.h - patches/titanium_itemfields.h + patches/titanium_itemfields_a.h + patches/titanium_itemfields_b.h patches/titanium_ops.h patches/titanium_constants.h patches/titanium_structs.h diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 42544f3b9..d3873dd97 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -2126,7 +2126,9 @@ namespace Titanium #define C(field) "|%s" #define S(field) "|%s" #define F(field) "|%f" -#include "titanium_itemfields.h" +#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; @@ -2138,7 +2140,9 @@ namespace Titanium #define C(field) ,field #define S(field) ,item->field #define F(field) ,item->field -#include "titanium_itemfields.h" +#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] : "" diff --git a/common/patches/titanium_itemfields_a.h b/common/patches/titanium_itemfields_a.h new file mode 100644 index 000000000..ba8d7b1c6 --- /dev/null +++ b/common/patches/titanium_itemfields_a.h @@ -0,0 +1,19 @@ +/* + + +These fields must be in the order of how they are serialized! + + + +*/ + + +/* 000 */ //I(ItemClass) Leave this one off on purpose +/* 001 */ S(Name) +/* 002 */ S(Lore) +/* 003 */ S(IDFile) +/* 004 */ I(ID) + +/* 005 */ //I(Weight) handled manually + +// titanium_itemfields_b.h diff --git a/common/patches/titanium_itemfields.h b/common/patches/titanium_itemfields_b.h similarity index 96% rename from common/patches/titanium_itemfields.h rename to common/patches/titanium_itemfields_b.h index dc87a714e..194a31f1c 100644 --- a/common/patches/titanium_itemfields.h +++ b/common/patches/titanium_itemfields_b.h @@ -8,12 +8,10 @@ These fields must be in the order of how they are serialized! */ -/* 000 */ //I(ItemClass) Leave this one off on purpose -/* 001 */ S(Name) -/* 002 */ S(Lore) -/* 003 */ S(IDFile) -/* 004 */ I(ID) -/* 005 */ I(Weight) +// titanium_itemfields_a.h + +/* 005 */ //I(Weight) handled manually + /* 006 */ I(NoRent) /* 007 */ I(NoDrop) /* 008 */ I(Size) From f98c04ca7afd5fcc52431863f1d11ed828916670 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 27 Jan 2016 17:39:36 -0500 Subject: [PATCH 525/846] Fix for false triggering of warning message for command alias processing --- zone/command.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index 4c25b25d2..b5d060f87 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -424,7 +424,9 @@ int command_init(void) std::map>> command_settings; database.GetCommandSettings(command_settings); - for (std::map::iterator iter_cl = commandlist.begin(); iter_cl != commandlist.end(); ++iter_cl) { + + 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); if (iter_cs == command_settings.end()) { if (iter_cl->second->access == 0) From c19a5d7c756fa3fb633b1832b3d6c1a8ec4d5e4b Mon Sep 17 00:00:00 2001 From: Tim DeLong Date: Thu, 28 Jan 2016 08:15:38 -0500 Subject: [PATCH 526/846] Casttime was too small for the possible data values. The Potion of Serious Healing has a cast time of 90.0 sec (90000), but this was downcast to a lower value. Updated Casttime from uint16 to uint32. This change also makes CastTime have the same data type as Fulfilment which is notable as they are in a struct union and should have the same type. --- common/item_struct.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/item_struct.h b/common/item_struct.h index 937c9e47c..0d7505a2c 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -160,7 +160,7 @@ struct Item_Struct { //uint32 Unk059; union { uint32 Fulfilment; // Food fulfilment (How long it lasts) - int16 CastTime; // Cast Time for clicky effects, in milliseconds + uint32 CastTime; // Cast Time for clicky effects, in milliseconds }; uint32 EliteMaterial; int32 ProcRate; From 3ce3f591a83edb4d5f51746af8697c7a868f5182 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Thu, 28 Jan 2016 13:23:58 -0800 Subject: [PATCH 527/846] UF and ROF2 spawn packet packet for chests now working properly. --- common/patches/rof2.cpp | 81 ++++++++++++++++++++++++++++++++--- common/patches/uf.cpp | 11 +++-- utils/patches/patch_RoF2.conf | 3 ++ utils/patches/patch_UF.conf | 3 ++ zone/client.cpp | 2 +- 5 files changed, 90 insertions(+), 10 deletions(-) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index e0e8f307f..1b2da5cda 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4076,6 +4076,17 @@ namespace RoF2 if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; + if (emu->DestructibleObject || emu->class_ == 62) + { + if (emu->DestructibleObject) + PacketSize = PacketSize - 4; // No bodytype + + PacketSize += 53; // Fixed portion + PacketSize += strlen(emu->DestructibleModel) + 1; + PacketSize += strlen(emu->DestructibleName2) + 1; + PacketSize += strlen(emu->DestructibleString) + 1; + } + bool ShowName = 1; if (emu->bodytype >= 66) { @@ -4110,7 +4121,14 @@ namespace RoF2 VARSTRUCT_ENCODE_STRING(Buffer, emu->name); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); - VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height? + if (emu->DestructibleObject) + { + VARSTRUCT_ENCODE_TYPE(float, Buffer, 10); // was int and 0x41200000 + } + else + { + VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height? + } VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer; @@ -4130,6 +4148,12 @@ namespace RoF2 Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0; Bitfields->showname = ShowName; + if (emu->DestructibleObject) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x1d600000); + Buffer = Buffer - 4; + } + // Not currently found // Bitfields->statue = 0; // Bitfields->buyer = 0; @@ -4138,21 +4162,66 @@ namespace RoF2 uint8 OtherData = 0; + if (emu->class_ == 62) //LDoN Chest + OtherData = OtherData | 0x04; + if (strlen(emu->title)) OtherData = OtherData | 16; if (strlen(emu->suffix)) OtherData = OtherData | 32; + if (emu->DestructibleObject) + OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); - VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3 + if (emu->DestructibleObject) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); + } + else + { + VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3 + } VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 - // Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not - // present. Will sort that out later. - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype); + if (emu->DestructibleObject || emu->class_ == 62) + { + VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); + VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); + VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleString); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleAppearance); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk1); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID1); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID2); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID3); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID4); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk2); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk3); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk4); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk5); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk6); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk7); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructibleUnk8); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk9); + } + + + if (!emu->DestructibleObject) + { + // Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not + // present. Will sort that out later. + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype); + } + else + { + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + } VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->curHp); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->haircolor); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index c42de5145..adcd8f241 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2818,9 +2818,11 @@ namespace UF if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; - if (emu->DestructibleObject) + if (emu->DestructibleObject || emu->class_ == 62) { - PacketSize = PacketSize - 4; // No bodytype + if (emu->DestructibleObject) + PacketSize = PacketSize - 4; // No bodytype + PacketSize += 53; // Fixed portion PacketSize += strlen(emu->DestructibleModel) + 1; PacketSize += strlen(emu->DestructibleName2) + 1; @@ -2903,6 +2905,9 @@ namespace UF uint8 OtherData = 0; + if (emu->class_ == 62) //Ldon chest + OtherData = OtherData | 0x01; + if (strlen(emu->title)) OtherData = OtherData | 0x04; @@ -2924,7 +2929,7 @@ namespace UF } VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 - if (emu->DestructibleObject) + if (emu->DestructibleObject || emu->class_ == 62) { VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 6afb7209e..8ae8a1a69 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -540,6 +540,9 @@ OP_FeignDeath=0x52fa OP_Mend=0x0ecf OP_Bind_Wound=0x0386 OP_LDoNOpen=0x3d5c +#OP_LDoNDisarmTraps= #Same as OP_DisarmTraps in RoF +OP_LDoNPickLock=0x9be3 +OP_LDoNInspect=0x0438 # Task packets OP_TaskDescription=0x3714 diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index e3af9aa7d..1e57a202d 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -535,6 +535,9 @@ OP_InstillDoubt=0x221a # C OP_FeignDeath=0x002b # C OP_Mend=0x10a6 # C OP_LDoNOpen=0x032b # C +OP_LDoNDisarmTraps=0x1a84 +OP_LDoNPickLock=0x0370 +OP_LDoNInspect=0x0aaa # Task packets OP_TaskActivityComplete=0x5832 # C diff --git a/zone/client.cpp b/zone/client.cpp index c8c1494e5..e24c24627 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4638,7 +4638,7 @@ void Client::HandleLDoNOpen(NPC *target) AddEXP(target->GetLevel()*target->GetLevel()*2625/10, GetLevelCon(target->GetLevel())); } } - target->Death(this, 1, SPELL_UNKNOWN, SkillHandtoHand); + target->Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); } } } From 65b44248fb59752b1889c48852368989832393dc Mon Sep 17 00:00:00 2001 From: Xackery Date: Sat, 30 Jan 2016 00:01:06 -0800 Subject: [PATCH 528/846] table schema for character_corpses is zone_id, not zoneid. --- 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 f20ffb5f4..ec7c8e323 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6131,7 +6131,7 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app) char *escSearchString = new char[129]; database.DoEscapeString(escSearchString, gmscs->Name, strlen(gmscs->Name)); - std::string query = StringFormat("SELECT charname, zoneid, x, y, z, time_of_death, is_rezzed, is_buried " + std::string query = StringFormat("SELECT charname, zone_id, x, y, z, time_of_death, is_rezzed, is_buried " "FROM character_corpses WheRE charname LIKE '%%%s%%' ORDER BY charname LIMIT %i", escSearchString, maxResults); safe_delete_array(escSearchString); From 7efccad13e0a5f3c5f9ffe5450ddf4bd53f5f93d Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Tue, 2 Feb 2016 01:53:22 -0800 Subject: [PATCH 529/846] GetFreeGrid should no longer crash when trying to #wpadd in a zone that has no grids --- zone/waypoints.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 5ab46dc1f..51a7af4fb 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -1186,8 +1186,7 @@ uint32 ZoneDatabase::GetFreeGrid(uint16 zoneid) { return 0; auto row = results.begin(); - uint32 freeGridID = 1; - freeGridID = atoi(row[0]) + 1; + uint32 freeGridID = row[0] ? atoi(row[0]) + 1 : 1; return freeGridID; } From 33c7016a0e94f895088ef50c850babcea55c426d Mon Sep 17 00:00:00 2001 From: JJ Date: Thu, 4 Feb 2016 19:17:17 -0500 Subject: [PATCH 530/846] Simple spelling fix. [skip ci] --- zone/tasks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/tasks.cpp b/zone/tasks.cpp index d52ae842b..0e7de67cb 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -3043,7 +3043,7 @@ void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enfor NPC *npc = entity_list.GetID(NPCID)->CastToNPC(); if(!npc) { c->Message(clientMessageYellow, "Task Giver ID is %i", NPCID); - c->Message(clientMessageError, "Unable to find NPC to send EVENT_TASKACCEPTD to. Report this bug."); + c->Message(clientMessageError, "Unable to find NPC to send EVENT_TASKACCEPTED to. Report this bug."); safe_delete_array(buf); return; } From 306586fa7eaaa7dc8e2cc50ed5e8b2fe7fd34e24 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 6 Feb 2016 19:33:44 -0500 Subject: [PATCH 531/846] Exclude discs from buff slot stealing logic --- zone/spells.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index b8c3023b8..45c52a48b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3140,7 +3140,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid Log.Out(Logs::Detail, Logs::Spells, "Adding buff %d will overwrite spell %d in slot %d with caster level %d", spell_id, curbuf.spellid, buffslot, curbuf.casterlevel); // If this is the first buff it would override, use its slot - if (!will_overwrite) + if (!will_overwrite && !IsDisciplineBuff(spell_id)) emptyslot = buffslot; will_overwrite = true; overwrite_slots.push_back(buffslot); @@ -3190,7 +3190,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid // if we hadn't found a free slot before, or if this is earlier // we use it - if (emptyslot == -1 || *cur < emptyslot) + if (emptyslot == -1 || (*cur < emptyslot && !IsDisciplineBuff(spell_id))) emptyslot = *cur; } } From cdd56ec0e13e9d70361d21dccd94b57709d6ef87 Mon Sep 17 00:00:00 2001 From: hateborne Date: Wed, 10 Feb 2016 16:51:58 -0500 Subject: [PATCH 532/846] FlatItemExtraSpellAmt Custom Rule Addition Added FlatItemExtraSpellAmt rule (boolean) to allow SpellDmg on items to be added as raw damage versus scaled. --- changelog.txt | 3 +++ common/ruletypes.h | 1 + zone/effects.cpp | 3 +++ 3 files changed, 7 insertions(+) diff --git a/changelog.txt b/changelog.txt index ee77f075d..ec4fec5d9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/10/2016 == +Hateborne: Added FlatItemExtraSpellAmt rule (boolean) to allow SpellDmg on items to be added as raw damage versus scaled. + == 01/26/2016 == Uleat: Fix for Berserker 'Piercing' skill issues. Server Admins: If you run custom skill sets, this patch touches the code segments that you will need to modify if you have changed the default berserker 1H-/2H-piercing skill values. Uleat (Daerath): Fix for precision-loss item weight conversions in older clients. diff --git a/common/ruletypes.h b/common/ruletypes.h index f83ea0266..143c62c17 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -361,6 +361,7 @@ RULE_BOOL(Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell RULE_BOOL(Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects. RULE_BOOL(Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot. 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_CATEGORY_END() RULE_CATEGORY(Combat) diff --git a/zone/effects.cpp b/zone/effects.cpp index dc3392403..1fafb1426 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -225,6 +225,9 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg) { + if (RuleB(Spells, FlatItemExtraSpellAmt)) + return extra_spell_amt; + int total_cast_time = 0; if (spells[spell_id].recast_time >= spells[spell_id].recovery_time) From 31b6346f038d1b697569fdbf313257b33e323cb2 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Thu, 11 Feb 2016 13:07:42 -0800 Subject: [PATCH 533/846] Fix the math so berserkers aren't left out in spell related checks. --- zone/bot.cpp | 16 ++++++++-------- zone/effects.cpp | 8 ++++---- zone/merc.cpp | 2 +- zone/mob.cpp | 2 +- zone/oldcode.cpp | 4 ++-- zone/spell_effects.cpp | 8 ++++---- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 926df4fb0..dee437849 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -5463,7 +5463,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 LimitFound = true; break; case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass() % 16) - 1]; + spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = spell_level - base1; //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { @@ -5477,7 +5477,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 } break; case SE_LimitMinLevel: - if((spell.classes[(GetClass() % 16) - 1]) < base1) + if((spell.classes[(GetClass() % 17) - 1]) < base1) LimitFound = true; break; case SE_LimitCastTimeMin: @@ -5915,7 +5915,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel case SE_LimitMaxLevel:{ if (IsNPC()) break; - spell_level = spell.classes[(GetClass() % 16) - 1]; + spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = (spell_level - focus_spell.base[i]); if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { if(focus_spell.base2[i] > 0) { @@ -5931,7 +5931,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel case SE_LimitMinLevel: if (IsNPC()) break; - if (spell.classes[(GetClass() % 16) - 1] < focus_spell.base[i]) + if (spell.classes[(GetClass() % 17) - 1] < focus_spell.base[i]) return 0; break; @@ -7083,7 +7083,7 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value += (GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value) * ratio / 100); entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), -value); @@ -7102,7 +7102,7 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id); value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); return value; @@ -7135,7 +7135,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { value += GetBotFocusEffect(BotfocusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value += (GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier); value += (value * target->GetHealRate(spell_id, this) / 100); @@ -7239,7 +7239,7 @@ int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) { } int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { - if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) { + if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) { int32 mana_back = (this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100); if(mana_back > cost) mana_back = cost; diff --git a/zone/effects.cpp b/zone/effects.cpp index 1fafb1426..fb444c372 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -112,7 +112,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); value -= GetFocusEffect(focusFcDamageAmt2, spell_id); - if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100; else if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -145,7 +145,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); value -= GetFocusEffect(focusFcDamageAmt2, spell_id); - if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -290,7 +290,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { value += GetFocusEffect(focusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier; value += value*target->GetHealRate(spell_id, this)/100; @@ -339,7 +339,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) cost *= 2; // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell - if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) { int16 mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell diff --git a/zone/merc.cpp b/zone/merc.cpp index b4125735e..91a69f374 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -2678,7 +2678,7 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost) { // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell - if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) { int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell diff --git a/zone/mob.cpp b/zone/mob.cpp index 3dad9b247..0e2cd7d88 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5117,7 +5117,7 @@ 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 spell_level = spells[spell_id].classes[(GetClass()%17) - 1]; int effect_value = 0; int lvlModifier = 100; diff --git a/zone/oldcode.cpp b/zone/oldcode.cpp index 075923360..600e8ad5c 100644 --- a/zone/oldcode.cpp +++ b/zone/oldcode.cpp @@ -1082,11 +1082,11 @@ int32 Client::GenericFocus(uint16 spell_id, uint16 modspellid) switch( spells[modspellid].effectid[i] ) { case SE_LimitMaxLevel: - if (spell.classes[(GetClass()%16) - 1] > modspell.base[i]) + if (spell.classes[(GetClass()%17) - 1] > modspell.base[i]) return 100; break; case SE_LimitMinLevel: - if (spell.classes[(GetClass()%16) - 1] < modspell.base[i]) + if (spell.classes[(GetClass()%17) - 1] < modspell.base[i]) return 100; break; case SE_IncreaseRange: diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e866d1e0f..d5006a52b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4227,7 +4227,7 @@ int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) break; case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass() % 16) - 1]; + spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = spell_level - base1; // every level over cap reduces the effect by base2 percent unless from a clicky when // ItemCastsUseFocus is true @@ -4243,7 +4243,7 @@ int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) break; case SE_LimitMinLevel: - if ((spell.classes[(GetClass() % 16) - 1]) < base1) + if ((spell.classes[(GetClass() % 17) - 1]) < base1) LimitFailure = true; break; @@ -4661,7 +4661,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_LimitMaxLevel: if (IsNPC()) break; - spell_level = spell.classes[(GetClass() % 16) - 1]; + spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = spell_level - focus_spell.base[i]; // every level over cap reduces the effect by focus_spell.base2[i] percent unless from a clicky // when ItemCastsUseFocus is true @@ -4679,7 +4679,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_LimitMinLevel: if (IsNPC()) break; - if (spell.classes[(GetClass() % 16) - 1] < focus_spell.base[i]) + if (spell.classes[(GetClass() % 17) - 1] < focus_spell.base[i]) return (0); break; From b432830dfcf36989b4e6d3143c2ed26dcf48b0e9 Mon Sep 17 00:00:00 2001 From: hateborne Date: Thu, 11 Feb 2016 17:37:32 -0500 Subject: [PATCH 534/846] IgnoreSpellDmgLvlRestriction Rule Added (re-resubmitted) Added IgnoreSpellDmgLvlRestriction rule (boolean) to ignore the 5 level spread when checking to add SpellDmg. Resubmitting due to the change Natedog made ::shakefist:: --- changelog.txt | 3 +++ common/ruletypes.h | 1 + zone/effects.cpp | 10 ++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index ec4fec5d9..ce52c7384 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/11/2016 == +Hateborne: Added IgnoreSpellDmgLvlRestriction rule (boolean) to ignore the 5 level spread when checking to add SpellDmg + == 02/10/2016 == Hateborne: Added FlatItemExtraSpellAmt rule (boolean) to allow SpellDmg on items to be added as raw damage versus scaled. diff --git a/common/ruletypes.h b/common/ruletypes.h index 143c62c17..cc5316406 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -362,6 +362,7 @@ RULE_BOOL(Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item d RULE_BOOL(Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot. 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_CATEGORY_END() RULE_CATEGORY(Combat) diff --git a/zone/effects.cpp b/zone/effects.cpp index fb444c372..05f6cd927 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -112,7 +112,10 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); value -= GetFocusEffect(focusFcDamageAmt2, spell_id); - if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) + if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) + value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio / 100; + + else if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100; else if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -145,7 +148,10 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); value -= GetFocusEffect(focusFcDamageAmt2, spell_id); - if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) + if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) + value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); + + else if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); if (IsNPC() && CastToNPC()->GetSpellScale()) From a8f353518e324024fec382aa00b1d8a98378c761 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 12 Feb 2016 18:19:03 -0500 Subject: [PATCH 535/846] Allow backstabs done with bane weapons to hit targets immune to all melee except bane. Skill attacks will now give appropriate immune messages. --- zone/special_attacks.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 2c763df13..3758d2e1b 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -100,11 +100,14 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, //this really should go through the same code as normal melee damage to //pick up all the special behavior there - if (!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; - if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE) || who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) - return; //-5? + if (who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE) && skill != SkillBackstab) + max_damage = -5; uint32 hate = max_damage; if(hate_override > -1) From 2268e6ed34805da15dc5ec47bd5e06eb93516ad7 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 27 Feb 2016 01:37:35 -0800 Subject: [PATCH 536/846] Fix up Object packet for UF / RoF / RoF2. SolidType was incorrect as those fields are the XY tilt for the object. Need database values for these fields so they will actually be useful. --- common/patches/rof.cpp | 4 ++-- common/patches/rof2.cpp | 4 ++-- common/patches/rof2_structs.h | 3 ++- common/patches/rof_structs.h | 3 ++- common/patches/uf.cpp | 4 ++-- common/patches/uf_structs.h | 3 ++- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 988eba916..b5349b617 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -975,8 +975,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); // Normally 0, but seen (float)255.0 as well - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // 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 1b2da5cda..1724b8167 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1046,8 +1046,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); // Normally 0, but seen (float)255.0 as well - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // 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_structs.h b/common/patches/rof2_structs.h index 1e93b7434..20d3b47f2 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2845,7 +2845,8 @@ struct Object_Struct { /*00*/ uint32 drop_id; // Unique object id for zone /*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone? /*00*/ float heading; // heading -/*00*/ float unknown032[2]; // 00 00 00 00 00 00 00 00 +/*00*/ float x_tilt; //Tilt entire object on X axis +/*00*/ float y_tilt; //Tilt entire object on Y axis /*00*/ float size; // Size - default 1 /*00*/ float z; // z coord /*00*/ float x; // x coord diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index e24935d35..86f8b0872 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -2873,7 +2873,8 @@ struct Object_Struct { /*00*/ uint32 drop_id; // Unique object id for zone /*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone? /*00*/ float heading; // heading -/*00*/ float unknown032[2]; // 00 00 00 00 00 00 00 00 +/*00*/ float x_tilt; //Tilt entire object on X axis +/*00*/ float y_tilt; //Tilt entire object on Y axis /*00*/ float size; // Size - default 1 /*00*/ float z; // z coord /*00*/ float x; // x coord diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index adcd8f241..bc7d2906c 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -857,8 +857,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(uint32, OutBuffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown, observed 0 + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //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/uf_structs.h b/common/patches/uf_structs.h index 7f3a7dcc0..75e590abd 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -2450,7 +2450,8 @@ struct Object_Struct { /*20*/ uint32 unknown020; // 00 00 00 00 /*24*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone? /*40*/ float heading; // heading -/*32*/ uint8 unknown032[8]; // 00 00 00 00 00 00 00 00 +/*00*/ float x_tilt; //Tilt entire object on X axis +/*00*/ float y_tilt; //Tilt entire object on Y axis /*28*/ float size; // Size - default 1 /*44*/ float z; // z coord /*48*/ float x; // x coord From 63cce6875f05c299a3e3883201defa224d1bdc63 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 27 Feb 2016 20:27:11 -0500 Subject: [PATCH 537/846] Rework of NPC::PickPocket() - added stacking ability --- common/ruletypes.h | 1 + zone/npc.cpp | 239 +++++++++++++++++++-------------------------- 2 files changed, 100 insertions(+), 140 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index cc5316406..641266b2f 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -126,6 +126,7 @@ RULE_INT(Character, InvSnapshotMinIntervalM, 180) // Minimum time (in minutes) b RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt an inventory snapshot after a failure 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_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/zone/npc.cpp b/zone/npc.cpp index 22e4b4b0d..103b5548e 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1425,13 +1425,13 @@ uint32 NPC::GetMaxDamage(uint8 tlevel) return dmg; } -void NPC::PickPocket(Client* thief) { - +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)) { + //make sure were allowed to target them: + int over_level = GetLevel(); + if(over_level > (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 @@ -1447,150 +1447,109 @@ void NPC::PickPocket(Client* thief) { } 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); + int steal_chance = steal_skill * 100 / (5 * over_level + 5); + //Determine wheter to steal money or an item. - bool no_coin = ((money[0] + money[1] + money[2] + money[3]) == 0); - bool steal_item = (zone->random.Roll(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 != INVALID_INDEX - /*&& 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++; - } - } + int 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)); + + // still needs to have FindFreeSlot vs PutItemInInventory issue worked out + while (steal_item) { + 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)) + continue; + + loot_selection.push_back(std::make_pair(item_test, ((item_test->Stackable) ? (1) : (item_iter->charges)))); } - if (x > 0) - { - int random = zone->random.Int(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) - { + if (loot_selection.empty()) { 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 = zone->random.Int(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; - } - } + break; } - if (zone->random.Roll(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; - } + 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)); + if (slot_id == INVALID_INDEX) { + steal_item = false; + break; + } + + auto item_inst = database.CreateItem(loot_selection[random].first, loot_selection[random].second); + if (item_inst == nullptr) { + steal_item = false; + break; + } + + // Successful item pickpocket + if (item_inst->IsStackable() && RuleB(Character, UseStackablePickPocketing)) { + if (!thief->TryStacking(item_inst, ItemPacketTrade, false, false)) { + thief->PutItemInInventory(slot_id, *item_inst); + thief->SendItemPacket(slot_id, item_inst, ItemPacketTrade); } } - else - { - thief->SendPickPocketResponse(this, 0, PickPocketFailed); + else { + thief->PutItemInInventory(slot_id, *item_inst); + thief->SendItemPacket(slot_id, item_inst, ItemPacketTrade); } + RemoveItem(item_inst->GetID()); + thief->SendPickPocketResponse(this, 0, PickPocketItem, item_inst->GetItem()); + + return; } - safe_delete(inst); + + while (!steal_item && has_coin) { + uint32 coin_amount = zone->random.Int(1, (steal_skill / 25) + 1); + + int coin_type = PickPocketPlatinum; + while (coin_type <= PickPocketCopper) { + if (money[coin_type]) { + if (coin_amount > money[coin_type]) + coin_amount = money[coin_type]; + break; + } + ++coin_type; + } + if (coin_type > PickPocketCopper) + break; + + memset(money, 0, (sizeof(int) * 6)); + money[coin_type] = coin_amount; + + if (zone->random.Roll(steal_chance)) { // Successful coin pickpocket + switch (coin_type) { + case PickPocketPlatinum: + SetPlatinum(GetPlatinum() - coin_amount); + break; + case PickPocketGold: + SetGold(GetGold() - coin_amount); + break; + case PickPocketSilver: + SetSilver(GetSilver() - coin_amount); + break; + case PickPocketCopper: + SetCopper(GetCopper() - coin_amount); + break; + default: // has_coin..but, doesn't have coin? + thief->SendPickPocketResponse(this, 0, PickPocketFailed); + return; + } + + thief->AddMoneyToPP(money[3], money[2], money[1], money[0], false); + thief->SendPickPocketResponse(this, coin_amount, coin_type); + return; + } + + thief->SendPickPocketResponse(this, 0, PickPocketFailed); + return; + } + + thief->Message(0, "This target's pockets are empty"); + thief->SendPickPocketResponse(this, 0, PickPocketFailed); } void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) { From 02e0431a7924c4bc9693648393767c9cead149bf Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 29 Feb 2016 02:29:41 -0500 Subject: [PATCH 538/846] Fix for ammo weapon damage not calculating when launching projectiles with rule enabled. --- zone/special_attacks.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 3758d2e1b..6c6177d29 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -904,7 +904,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, RangeWeapon, Ammo, AmmoSlot, speed); + TryProjectileAttack(other, AmmoItem, SkillArchery, (WDmg + ADmg), RangeWeapon, Ammo, AmmoSlot, speed); return; } @@ -926,7 +926,10 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100; - Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg); + 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){ From abedfd3918542ffb8e9f9a972cc3738a073abbf0 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 29 Feb 2016 21:46:53 -0500 Subject: [PATCH 539/846] Add MainAmmo slot check for AddItemBonuses - only includes skill mods --- changelog.txt | 3 + common/item.cpp | 11 +- common/patches/sod.cpp | 2 +- common/patches/sod_structs.h | 2 +- common/patches/sof.cpp | 2 +- common/patches/sof_structs.h | 2 +- common/patches/titanium_itemfields_b.h | 2 +- zone/bonuses.cpp | 568 ++++++++++++------------- zone/client.h | 2 +- 9 files changed, 298 insertions(+), 296 deletions(-) diff --git a/changelog.txt b/changelog.txt index ce52c7384..a9239d1fe 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/29/2016 == +Uleat: Change in AddItemBonuses - now includes ammo slot for skill mods only. Defined SoD- client SkillModMax packet property (client does not show..but, does enforce.) + == 02/11/2016 == Hateborne: Added IgnoreSpellDmgLvlRestriction rule (boolean) to ignore the 5 level spread when checking to add SpellDmg diff --git a/common/item.cpp b/common/item.cpp index 26ec154c3..5d1142d2c 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -2230,11 +2230,12 @@ void ItemInst::ScaleItem() { m_scaledItem->Mana = (int32)((float)m_item->Mana*Mult); m_scaledItem->AC = (int32)((float)m_item->AC*Mult); - m_scaledItem->SkillModValue = (int32)((float)m_item->SkillModValue*Mult); - m_scaledItem->BaneDmgAmt = (int8)((float)m_item->BaneDmgAmt*Mult); - m_scaledItem->BardValue = (int32)((float)m_item->BardValue*Mult); - m_scaledItem->ElemDmgAmt = (uint8)((float)m_item->ElemDmgAmt*Mult); - m_scaledItem->Damage = (uint32)((float)m_item->Damage*Mult); + // check these..some may not need to be modified (really need to check all stats/bonuses) + //m_scaledItem->SkillModValue = (int32)((float)m_item->SkillModValue*Mult); + //m_scaledItem->BaneDmgAmt = (int8)((float)m_item->BaneDmgAmt*Mult); // watch (10 entries with charmfileid) + m_scaledItem->BardValue = (int32)((float)m_item->BardValue*Mult); // watch (no entries with charmfileid) + m_scaledItem->ElemDmgAmt = (uint8)((float)m_item->ElemDmgAmt*Mult); // watch (no entries with charmfileid) + m_scaledItem->Damage = (uint32)((float)m_item->Damage*Mult); // watch m_scaledItem->CombatEffects = (int8)((float)m_item->CombatEffects*Mult); m_scaledItem->Shielding = (int8)((float)m_item->Shielding*Mult); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index d5a6035f4..424ad5a22 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3661,7 +3661,7 @@ namespace SoD ibs.Races = item->Races; ibs.Deity = item->Deity; ibs.SkillModValue = item->SkillModValue; - ibs.unknown6 = 0; + ibs.SkillModMax = item->SkillModMax; ibs.SkillModType = item->SkillModType; ibs.BaneDmgRace = item->BaneDmgRace; ibs.BaneDmgBody = item->BaneDmgBody; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index d9abef4c6..20e2a56b4 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4006,7 +4006,7 @@ struct ItemBodyStruct uint32 Races; uint32 Deity; int32 SkillModValue; - uint32 unknown6; + uint32 SkillModMax; uint32 SkillModType; uint32 BaneDmgRace; uint32 BaneDmgBody; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index f407ffdc0..11e365a71 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2983,7 +2983,7 @@ namespace SoF ibs.Races = item->Races; ibs.Deity = item->Deity; ibs.SkillModValue = item->SkillModValue; - ibs.unknown6 = 0; + ibs.SkillModMax = item->SkillModMax; ibs.SkillModType = item->SkillModType; ibs.BaneDmgRace = item->BaneDmgRace; ibs.BaneDmgBody = item->BaneDmgBody; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index db7cfe028..d78277721 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3861,7 +3861,7 @@ struct ItemBodyStruct uint32 Races; uint32 Deity; int32 SkillModValue; - uint32 unknown6; + uint32 SkillModMax; uint32 SkillModType; uint32 BaneDmgRace; uint32 BaneDmgBody; diff --git a/common/patches/titanium_itemfields_b.h b/common/patches/titanium_itemfields_b.h index 194a31f1c..30dc73bff 100644 --- a/common/patches/titanium_itemfields_b.h +++ b/common/patches/titanium_itemfields_b.h @@ -39,7 +39,7 @@ These fields must be in the order of how they are serialized! /* 030 */ I(AC) /* 031 */ I(Deity) /* 032 */ I(SkillModValue) -/* 033 */ C("0") +/* 033 */ I(SkillModMax) /* 034 */ I(SkillModType) /* 035 */ I(BaneDmgRace) /* 036 */ I(BaneDmgAmt) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index e709bdef4..413b8d6c6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -144,12 +144,12 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { SetTwoHanderEquipped(false); unsigned int i; - //should not include 21 (SLOT_AMMO) - for (i = MainCharm; i < MainAmmo; i++) { + // Update: MainAmmo should only calc skill mods (TODO: Check for other cases) + for (i = MainCharm; i <= MainAmmo; i++) { const ItemInst* inst = m_inv[i]; if(inst == 0) continue; - AddItemBonuses(inst, newbon); + AddItemBonuses(inst, newbon, false, false, 0, (i == MainAmmo)); //These are given special flags due to how often they are checked for various spell effects. const Item_Struct *item = inst->GetItem(); @@ -207,7 +207,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) +void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAug, bool isTribute, int rec_override, bool ammo_slot_item) { if (!inst || !inst->IsType(ItemClassCommon)) { return; @@ -227,309 +227,307 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu if (GetLevel() < inst->GetItemRequiredLevel(true)) { return; } - + // So there isn't a very nice way to get the real rec level from the aug's inst, so we just pass it in, only // used for augs auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true); - if (GetLevel() >= rec_level) { - newbon->AC += item->AC; - newbon->HP += item->HP; - newbon->Mana += item->Mana; - newbon->Endurance += item->Endur; - newbon->ATK += item->Attack; - 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); + if (!ammo_slot_item) { + if (GetLevel() >= rec_level) { + newbon->AC += item->AC; + newbon->HP += item->HP; + newbon->Mana += item->Mana; + newbon->Endurance += item->Endur; + newbon->ATK += item->Attack; + 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->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->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->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; + 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; - } else { - int lvl = GetLevel(); + 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; - newbon->AC += CalcRecommendedLevelBonus(lvl, rec_level, item->AC); - newbon->HP += CalcRecommendedLevelBonus(lvl, rec_level, item->HP); - newbon->Mana += CalcRecommendedLevelBonus(lvl, rec_level, item->Mana); - newbon->Endurance += CalcRecommendedLevelBonus(lvl, rec_level, item->Endur); - newbon->ATK += CalcRecommendedLevelBonus(lvl, rec_level, item->Attack); - newbon->STR += CalcRecommendedLevelBonus(lvl, rec_level, (item->AStr + item->HeroicStr)); - newbon->STA += CalcRecommendedLevelBonus(lvl, rec_level, (item->ASta + item->HeroicSta)); - newbon->DEX += CalcRecommendedLevelBonus(lvl, rec_level, (item->ADex + item->HeroicDex)); - newbon->AGI += CalcRecommendedLevelBonus(lvl, rec_level, (item->AAgi + item->HeroicAgi)); - newbon->INT += CalcRecommendedLevelBonus(lvl, rec_level, (item->AInt + item->HeroicInt)); - newbon->WIS += CalcRecommendedLevelBonus(lvl, rec_level, (item->AWis + item->HeroicWis)); - newbon->CHA += CalcRecommendedLevelBonus(lvl, rec_level, (item->ACha + item->HeroicCha)); + } + else { + int lvl = GetLevel(); - newbon->MR += CalcRecommendedLevelBonus(lvl, rec_level, (item->MR + item->HeroicMR)); - newbon->FR += CalcRecommendedLevelBonus(lvl, rec_level, (item->FR + item->HeroicFR)); - newbon->CR += CalcRecommendedLevelBonus(lvl, rec_level, (item->CR + item->HeroicCR)); - newbon->PR += CalcRecommendedLevelBonus(lvl, rec_level, (item->PR + item->HeroicPR)); - newbon->DR += CalcRecommendedLevelBonus(lvl, rec_level, (item->DR + item->HeroicDR)); - newbon->Corrup += - CalcRecommendedLevelBonus(lvl, rec_level, (item->SVCorruption + item->HeroicSVCorrup)); + newbon->AC += CalcRecommendedLevelBonus(lvl, rec_level, item->AC); + newbon->HP += CalcRecommendedLevelBonus(lvl, rec_level, item->HP); + newbon->Mana += CalcRecommendedLevelBonus(lvl, rec_level, item->Mana); + newbon->Endurance += CalcRecommendedLevelBonus(lvl, rec_level, item->Endur); + newbon->ATK += CalcRecommendedLevelBonus(lvl, rec_level, item->Attack); + newbon->STR += CalcRecommendedLevelBonus(lvl, rec_level, (item->AStr + item->HeroicStr)); + newbon->STA += CalcRecommendedLevelBonus(lvl, rec_level, (item->ASta + item->HeroicSta)); + newbon->DEX += CalcRecommendedLevelBonus(lvl, rec_level, (item->ADex + item->HeroicDex)); + newbon->AGI += CalcRecommendedLevelBonus(lvl, rec_level, (item->AAgi + item->HeroicAgi)); + newbon->INT += CalcRecommendedLevelBonus(lvl, rec_level, (item->AInt + item->HeroicInt)); + newbon->WIS += CalcRecommendedLevelBonus(lvl, rec_level, (item->AWis + item->HeroicWis)); + newbon->CHA += CalcRecommendedLevelBonus(lvl, rec_level, (item->ACha + item->HeroicCha)); - newbon->STRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicStr); - newbon->STACapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSta); - newbon->DEXCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDex); - newbon->AGICapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicAgi); - newbon->INTCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicInt); - newbon->WISCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicWis); - newbon->CHACapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCha); - newbon->MRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicMR); - newbon->CRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicFR); - newbon->FRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCR); - newbon->PRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicPR); - newbon->DRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDR); - newbon->CorrupCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSVCorrup); + newbon->MR += CalcRecommendedLevelBonus(lvl, rec_level, (item->MR + item->HeroicMR)); + newbon->FR += CalcRecommendedLevelBonus(lvl, rec_level, (item->FR + item->HeroicFR)); + newbon->CR += CalcRecommendedLevelBonus(lvl, rec_level, (item->CR + item->HeroicCR)); + newbon->PR += CalcRecommendedLevelBonus(lvl, rec_level, (item->PR + item->HeroicPR)); + newbon->DR += CalcRecommendedLevelBonus(lvl, rec_level, (item->DR + item->HeroicDR)); + newbon->Corrup += + CalcRecommendedLevelBonus(lvl, rec_level, (item->SVCorruption + item->HeroicSVCorrup)); - newbon->HeroicSTR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicStr); - newbon->HeroicSTA += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSta); - newbon->HeroicDEX += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDex); - newbon->HeroicAGI += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicAgi); - newbon->HeroicINT += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicInt); - newbon->HeroicWIS += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicWis); - newbon->HeroicCHA += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCha); - newbon->HeroicMR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicMR); - newbon->HeroicFR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicFR); - newbon->HeroicCR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCR); - newbon->HeroicPR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicPR); - newbon->HeroicDR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDR); - newbon->HeroicCorrup += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSVCorrup); - } - - // FatherNitwit: New style haste, shields, and regens - if (newbon->haste < (int32)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->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, item->Worn.Type); - } - - if (item->Focus.Effect > 0 && (item->Focus.Type == ET_Focus)) { // focus effects - ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); - } - - 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; - } + newbon->STRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicStr); + newbon->STACapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSta); + newbon->DEXCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDex); + newbon->AGICapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicAgi); + newbon->INTCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicInt); + newbon->WISCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicWis); + newbon->CHACapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCha); + newbon->MRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicMR); + newbon->CRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicFR); + newbon->FRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCR); + newbon->PRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicPR); + newbon->DRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDR); + newbon->CorrupCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSVCorrup); + + newbon->HeroicSTR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicStr); + newbon->HeroicSTA += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSta); + newbon->HeroicDEX += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDex); + newbon->HeroicAGI += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicAgi); + newbon->HeroicINT += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicInt); + newbon->HeroicWIS += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicWis); + newbon->HeroicCHA += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCha); + newbon->HeroicMR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicMR); + newbon->HeroicFR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicFR); + newbon->HeroicCR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCR); + newbon->HeroicPR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicPR); + newbon->HeroicDR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDR); + newbon->HeroicCorrup += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSVCorrup); + } + + // FatherNitwit: New style haste, shields, and regens + if (newbon->haste < (int32)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->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, item->Worn.Type); + } + + if (item->Focus.Effect > 0 && (item->Focus.Type == ET_Focus)) { // focus effects + ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); + } + + 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; + } + + // 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; + } } + // Process when ammo_slot_item = true or false 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)) { + (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) { + newbon->skillmod[item->SkillModType] = item->SkillModValue; newbon->skillmodmax[item->SkillModType] = item->SkillModMax; } } - // 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) { for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) - AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level); + AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level, ammo_slot_item); } } diff --git a/zone/client.h b/zone/client.h index d9f2f0dfc..b1d43c49c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1303,7 +1303,7 @@ 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); + 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); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); void CalcEdibleBonuses(StatBonuses* newbon); From 66b62303e42f7f3125c8c6f1921ca89d83683c1b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 29 Feb 2016 22:01:33 -0600 Subject: [PATCH 540/846] Fix for shared_memory and clearing out hotfix_ when ran --- shared_memory/main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 3d47f217f..11d21153b 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -62,6 +62,18 @@ int main(int argc, char **argv) { database.LoadLogSettings(Log.log_settings); Log.StartFileLogs(); + 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 query = StringFormat("UPDATE `variables` SET `value`='' WHERE (`varname`='hotfix_name')"); + database.QueryDatabase(query); + } + } + std::string hotfix_name = ""; bool load_all = true; bool load_items = false; From 141d6e3e8b5777a2b5053b336d885ebd7b0422ca Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 1 Mar 2016 16:55:31 -0500 Subject: [PATCH 541/846] Fix for two possible crash points in NPC::Death() --- zone/attack.cpp | 222 +++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 117 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 2fdf5f115..247e31058 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1874,50 +1874,52 @@ 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) { - Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killer_mob->GetName(), damage, spell, attack_skill); +bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes 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); Mob *oos = nullptr; - if(killer_mob) { + if (killer_mob) { oos = killer_mob->GetOwnerOrSelf(); char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) - { - if(GetHP() < 0) { + snprintf(buffer, 47, "%d %d %d %d", killer_mob->GetID(), damage, spell, static_cast(attack_skill)); + + if (parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) { + if (GetHP() < 0) { SetHP(0); } return false; } - if(killer_mob && killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { - char val1[20]={0}; + 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)); } - } else { - + } + else { char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0) - { - if(GetHP() < 0) { + snprintf(buffer, 47, "%d %d %d %d", 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()) - { + if (IsEngaged()) { zone->DelAggroMob(); Log.Out(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount()); } + SetHP(0); SetPet(0); - if (GetSwarmOwner()){ + if (GetSwarmOwner()) { Mob* owner = entity_list.GetMobID(GetSwarmOwner()); if (owner) owner->SetTempPetCount(owner->GetTempPetCount() - 1); @@ -1927,14 +1929,14 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac entity_list.RemoveFromTargets(this, p_depop); - if(p_depop == true) + if (p_depop == true) return false; HasAISpellEffects = false; BuffFadeAll(); uint8 killed_level = GetLevel(); - EQApplicationPacket* app= new EQApplicationPacket(OP_Death,sizeof(Death_Struct)); + EQApplicationPacket* 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; @@ -1945,55 +1947,49 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac app->priority = 6; entity_list.QueueClients(killer_mob, app, false); - if(respawn2) { + safe_delete(app); + + if (respawn2) { respawn2->DeathReset(1); } - if (killer_mob) { - if(GetClass() != LDON_TREASURE) - hate_list.AddEntToHateList(killer_mob, damage); - } - - safe_delete(app); + if (killer_mob && GetClass() != LDON_TREASURE) + hate_list.AddEntToHateList(killer_mob, damage); Mob *give_exp = hate_list.GetDamageTopOnHateList(this); - if(give_exp == nullptr) + if (give_exp == nullptr) give_exp = killer; - if(give_exp && give_exp->HasOwner()) { + if (give_exp && give_exp->HasOwner()) { bool ownerInGroup = false; - if((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner())) + 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()))))) + || (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) { + if (!RuleB(Bots, BotGroupXP) && !ownerInGroup) { give_exp = nullptr; } #endif //BOTS } - if(give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) { - - if (give_exp->IsNPC() && give_exp->CastToNPC()->GetSwarmOwner()){ - Mob* temp_owner = nullptr; - temp_owner = entity_list.GetMobID(give_exp->CastToNPC()->GetSwarmOwner()); - + if (give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) { + if (give_exp->IsNPC() && give_exp->CastToNPC()->GetSwarmOwner()) { + Mob* temp_owner = entity_list.GetMobID(give_exp->CastToNPC()->GetSwarmOwner()); if (temp_owner) give_exp = temp_owner; } } - int PlayerCount = 0; // QueryServ Player Counting Client *give_exp_client = nullptr; - if(give_exp && give_exp->IsClient()) + if (give_exp && give_exp->IsClient()) give_exp_client = give_exp->CastToClient(); //do faction hits even if we are a merchant, so long as a player killed us @@ -2001,43 +1997,43 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac hate_list.DoFactionHits(GetNPCFactionID()); bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE); - if (give_exp_client && !IsCorpse()) - { + + if (give_exp_client && !IsCorpse()) { 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 && MerchantType == 0) { + if (kr) { + if (!IsLdonTreasure && MerchantType == 0) { kr->SplitExp((finalxp), this); - if(killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName()))) - killer_mob->TrySpellOnKill(killed_level,spell); + if (killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName()))) + killer_mob->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 && kr->members[i].member->IsClient()) { // If Group Member is Client Client *c = kr->members[i].member; parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); - if(RuleB(NPC, EnableMeritBasedFaction)) + if (RuleB(NPC, EnableMeritBasedFaction)) c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); mod_npc_killed_merit(kr->members[i].member); - if(RuleB(TaskSystem, EnableTaskSystem)) + if (RuleB(TaskSystem, EnableTaskSystem)) kr->members[i].member->UpdateTasksOnKill(GetNPCTypeID()); PlayerCount++; } } // QueryServ Logging - Raid Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ + 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; + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); QS->s1.ZoneID = this->GetZoneID(); QS->s1.Type = 2; // Raid Fight @@ -2054,13 +2050,13 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac // End QueryServ Logging } - else if (give_exp_client->IsGrouped() && kg != nullptr) - { - if(!IsLdonTreasure && MerchantType == 0) { + else if (give_exp_client->IsGrouped() && kg != nullptr) { + if (!IsLdonTreasure && MerchantType == 0) { kg->SplitExp((finalxp), this); - if(killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName()))) - killer_mob->TrySpellOnKill(killed_level,spell); + if (killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName()))) + killer_mob->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++) { @@ -2068,12 +2064,12 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac Client *c = kg->members[i]->CastToClient(); parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); - if(RuleB(NPC, EnableMeritBasedFaction)) + if (RuleB(NPC, EnableMeritBasedFaction)) c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); mod_npc_killed_merit(c); - if(RuleB(TaskSystem, EnableTaskSystem)) + if (RuleB(TaskSystem, EnableTaskSystem)) c->UpdateTasksOnKill(GetNPCTypeID()); PlayerCount++; @@ -2081,10 +2077,10 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } // QueryServ Logging - Group Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ + 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; + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); QS->s1.ZoneID = this->GetZoneID(); QS->s1.Type = 1; // Group Fight @@ -2100,36 +2096,34 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } // End QueryServ Logging } - else - { - if(!IsLdonTreasure && MerchantType == 0) { + else { + if (!IsLdonTreasure && MerchantType == 0) { int conlevel = give_exp->GetLevelCon(GetLevel()); - if (conlevel != CON_GREEN) - { - if(!GetOwner() || (GetOwner() && !GetOwner()->IsClient())) - { + if (conlevel != CON_GREEN) { + if (!GetOwner() || (GetOwner() && !GetOwner()->IsClient())) { give_exp_client->AddEXP((finalxp), conlevel); - if(killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) - killer_mob->TrySpellOnKill(killed_level,spell); + if (killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) + killer_mob->TrySpellOnKill(killed_level, spell); } } } - /* Send the EVENT_KILLED_MERIT event */ + + /* Send the EVENT_KILLED_MERIT event */ parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); - if(RuleB(NPC, EnableMeritBasedFaction)) + if (RuleB(NPC, EnableMeritBasedFaction)) give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(), - give_exp_client->GetBaseRace(), give_exp_client->GetDeity()); + give_exp_client->GetBaseRace(), give_exp_client->GetDeity()); mod_npc_killed_merit(give_exp_client); - if(RuleB(TaskSystem, EnableTaskSystem)) + if (RuleB(TaskSystem, EnableTaskSystem)) give_exp_client->UpdateTasksOnKill(GetNPCTypeID()); // QueryServ Logging - Solo - if(RuleB(QueryServ, PlayerLogNPCKills)){ + if (RuleB(QueryServ, PlayerLogNPCKills)) { ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); QS->s1.ZoneID = this->GetZoneID(); QS->s1.Type = 0; // Solo Fight @@ -2147,71 +2141,69 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac && 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()) + if (killer != 0) { + if (killer->GetOwner() != 0 && killer->GetOwner()->IsClient()) killer = killer->GetOwner(); - if(!killer->CastToClient()->GetGM() && killer->IsClient()) + if (killer->IsClient() && !killer->CastToClient()->GetGM()) 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)); + 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) + + if (killer != 0 && emoteid != 0) corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid); - if(killer != 0 && killer->IsClient()) { + if (killer != 0 && killer->IsClient()) { corpse->AllowPlayerLoot(killer, 0); - if(killer->IsGrouped()) { + 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->AllowPlayerLoot(group->members[i],i); + if (group != 0) { + for (int i = 0; i<6; i++) { // Doesnt work right, needs work + if (group->members[i] != nullptr) { + corpse->AllowPlayerLoot(group->members[i], i); } } } } - else if(killer->IsRaidGrouped()){ + else if (killer->IsRaidGrouped()) { Raid* r = entity_list.GetRaidByClient(killer->CastToClient()); - if(r){ + if (r) { int i = 0; - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - switch(r->GetLootType()) - { + 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){ + if (r->members[x].member && r->members[x].IsRaidLeader) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } break; case 2: - if(r->members[x].member && r->members[x].IsRaidLeader){ + if (r->members[x].member && r->members[x].IsRaidLeader) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } - else if(r->members[x].member && r->members[x].IsGroupLeader){ + else if (r->members[x].member && r->members[x].IsGroupLeader) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } break; case 3: - if(r->members[x].member && r->members[x].IsLooter){ + if (r->members[x].member && r->members[x].IsLooter) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } break; case 4: - if(r->members[x].member) - { + if (r->members[x].member) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } @@ -2222,41 +2214,36 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } } - if(zone && zone->adv_data) - { + if (zone && zone->adv_data) { ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; - if(sr->type == Adventure_Kill) - { + if (sr->type == Adventure_Kill) { zone->DoAdventureCountIncrease(); } - else if(sr->type == Adventure_Assassinate) - { - if(sr->data_id == GetNPCTypeID()) - { + else if (sr->type == Adventure_Assassinate) { + if (sr->data_id == GetNPCTypeID()) { zone->DoAdventureCountIncrease(); } - else - { + else { zone->DoAdventureAssassinationCountIncrease(); } } } } - else + else { entity_list.RemoveFromXTargets(this); + } // Parse quests even if we're killed by an NPC - if(oos) { + if (oos) { mod_npc_killed(oos); uint16 emoteid = this->GetEmoteID(); - if(emoteid != 0) + if (emoteid != 0) this->DoNPCEmote(ONDEATH, emoteid); - if(oos->IsNPC()) - { + if (oos->IsNPC()) { parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); uint16 emoteid = oos->GetEmoteID(); - if(emoteid != 0) + if (emoteid != 0) oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid); killer_mob->TrySpellOnKill(killed_level, spell); } @@ -2264,7 +2251,8 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac WipeHateList(); p_depop = true; - if(killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted + + if (killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted killer_mob->SetTarget(nullptr); //via AE effects and such.. entity_list.UpdateFindableNPCState(this, true); @@ -2275,7 +2263,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac /* Zone controller process EVENT_DEATH_ZONE (Death events) */ if (RuleB(Zone, UseZoneController)) { - if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && this->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ + if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && this->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID) { char data_pass[100] = { 0 }; snprintf(data_pass, 99, "%d %d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill), this->GetNPCTypeID()); parse->EventNPC(EVENT_DEATH_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0); From 09589edcdddd240288006506cf72d9e7f6bf8037 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 1 Mar 2016 18:23:36 -0500 Subject: [PATCH 542/846] Fix for LDoN treasure npcs poofing - please report any issues --- changelog.txt | 3 +++ zone/attack.cpp | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index a9239d1fe..3964d37b5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/01/2016 == +Uleat: Fix for LDoN treasure 'npcs' not leaving a corpse (please report any issues..) + == 02/29/2016 == Uleat: Change in AddItemBonuses - now includes ammo slot for skill mods only. Defined SoD- client SkillModMax packet property (client does not show..but, does enforce.) diff --git a/zone/attack.cpp b/zone/attack.cpp index 247e31058..c14a74059 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2138,8 +2138,9 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo() - && MerchantType == 0 && killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || + && MerchantType == 0 && ((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || (killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient()))) + || (killer_mob && IsLdonTreasure))) { if (killer != 0) { if (killer->GetOwner() != 0 && killer->GetOwner()->IsClient()) @@ -2213,6 +2214,11 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } } } + else if (killer_mob && IsLdonTreasure) { + auto u_owner = killer_mob->GetUltimateOwner(); + if (u_owner->IsClient()) + corpse->AllowPlayerLoot(u_owner, 0); + } if (zone && zone->adv_data) { ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; From 655d2d47baf7633e01edabcccd342844996a391d Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Tue, 1 Mar 2016 22:30:54 -0800 Subject: [PATCH 543/846] Fix the typo in this change. Pets size should scale up properly until 3x normal size. --- zone/pets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/pets.cpp b/zone/pets.cpp index f5f741f44..fd777fab4 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -283,7 +283,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, npc_type->level += 1 + ((int)act_power / 25) > npc_type->level + RuleR(Pets, PetPowerLevelCap) ? RuleR(Pets, PetPowerLevelCap) : 1 + ((int)act_power / 25); // gains an additional level for every 25 pet power npc_type->min_dmg = (npc_type->min_dmg * (1 + (scale_power / 2))); npc_type->max_dmg = (npc_type->max_dmg * (1 + (scale_power / 2))); - npc_type->size = npc_type->size * (1 + (scale_power / 2)) > npc_type->size * 3 ? npc_type->size * 3 : (1 + (scale_power / 2)); + npc_type->size = npc_type->size * (1 + (scale_power / 2)) > npc_type->size * 3 ? npc_type->size * 3 : npc_type-> size * (1 + (scale_power / 2)); } record.petpower = act_power; } From 9599501acec61a282a7855a56a1edb04d11771b8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 5 Mar 2016 16:28:53 -0500 Subject: [PATCH 544/846] Implement extra bind points (secondary recall) For SE_Gate, base2 is which bind to use (starting at 1) For SE_BindAffinity, base1 is which bind to set (starting at 1) For SE_GateCastersBindpoint, base1 is which bind to use (starting at 1) here was actually no spells that don't send to the main bind, but it uses a base1 of 1 which matches with SE_Gate This also doesn't break anything The quest stuff for now hasn't been updated to be able to make use of the extra binds There are a total of 5 bind points, with the 5th being your starting city --- changelog.txt | 8 +++ common/database.cpp | 4 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2016_03_05_secondary_recall.sql | 6 ++ world/worlddb.cpp | 12 ++-- zone/client.cpp | 7 +-- zone/client.h | 4 +- zone/lua_client.cpp | 10 +-- zone/mob.h | 2 +- zone/npc.h | 2 +- zone/perl_client.cpp | 2 +- zone/questmgr.cpp | 2 +- zone/spell_effects.cpp | 27 ++++---- zone/zonedb.cpp | 61 ++++++++++--------- zone/zonedb.h | 2 +- zone/zoning.cpp | 45 +++++++------- 17 files changed, 109 insertions(+), 88 deletions(-) create mode 100644 utils/sql/git/required/2016_03_05_secondary_recall.sql diff --git a/changelog.txt b/changelog.txt index 3964d37b5..e3762b3dd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,13 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/05/2016 == +mackal: Implement extra bind points (secondary recall) + For SE_Gate, base2 is which bind to use (starting at 1) + For SE_BindAffinity, base1 is which bind to set (starting at 1) + For SE_GateCastersBindpoint, base1 is which bind to use (starting at 1) + There was actually no spells that don't send to the main bind, but it uses a base1 of 1 which matches with SE_Gate + This also doesn't break anything + == 03/01/2016 == Uleat: Fix for LDoN treasure 'npcs' not leaving a corpse (please report any issues..) diff --git a/common/database.cpp b/common/database.cpp index b8889fa06..cdafaa165 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -636,11 +636,11 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe ); auto results = QueryDatabase(query); /* Save Bind Points */ - query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + 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)", 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[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 1 + 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); /* Save Skills */ diff --git a/common/version.h b/common/version.h index b1be73905..04bf9189c 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 9095 +#define CURRENT_BINARY_DATABASE_VERSION 9096 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 31f3d2ccf..6f48f983e 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -349,6 +349,7 @@ 9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty| 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| # 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_03_05_secondary_recall.sql b/utils/sql/git/required/2016_03_05_secondary_recall.sql new file mode 100644 index 000000000..7b0f02754 --- /dev/null +++ b/utils/sql/git/required/2016_03_05_secondary_recall.sql @@ -0,0 +1,6 @@ +ALTER TABLE `character_bind` ADD `slot` int(4) AFTER `id`; +UPDATE `character_bind` SET `slot`='0' WHERE `is_home`=0; +UPDATE `character_bind` SET `slot`='4' WHERE `is_home`=1; +ALTER TABLE `character_bind` DROP PRIMARY KEY, ADD PRIMARY KEY(`id`, `slot`); +ALTER TABLE `character_bind` DROP COLUMN `is_home`; + diff --git a/world/worlddb.cpp b/world/worlddb.cpp index b09758888..357ab3c33 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -159,10 +159,10 @@ 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`, `is_home` FROM `character_bind` WHERE `id` = %i LIMIT 2", character_id); + 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); for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) { - if (row_b[6] && atoi(row_b[6]) == 1){ has_home = 1; } + if (row_b[6] && atoi(row_b[6]) == 4){ has_home = 1; } if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; } } @@ -189,14 +189,14 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou pp.binds[0] = pp.binds[4]; /* If no home bind set, set it */ if (has_home == 0) { - std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + 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, 1); + character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 4); auto results_bset = QueryDatabase(query); } /* If no regular bind set, set it */ if (has_bind == 0) { - std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + 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[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0); auto results_bset = QueryDatabase(query); @@ -285,7 +285,7 @@ int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum) bindnum = 0; } - std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND is_home = %u LIMIT 1", CharID, bindnum == 4 ? 1 : 0); + std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND slot = %u LIMIT 1", CharID, bindnum); auto results = database.QueryDatabase(query); if(!results.Success() || results.RowCount() == 0) { return 0; diff --git a/zone/client.cpp b/zone/client.cpp index e24c24627..5a9724fa8 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -587,10 +587,9 @@ bool Client::Save(uint8 iCommitNow) { database.SaveCharacterCurrency(CharacterID(), &m_pp); /* Save Current Bind Points */ - auto regularBindPosition = glm::vec4(m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0.0f); - auto homeBindPosition = glm::vec4(m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0.0f); - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPosition, 0); /* Regular bind */ - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[4].zoneId, m_pp.binds[4].instance_id, homeBindPosition, 1); /* Home Bind */ + for (int i = 0; i < 5; i++) + if (m_pp.binds[i].zoneId) + database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i); /* Save Character Buffs */ database.SaveBuffs(this); diff --git a/zone/client.h b/zone/client.h index b1d43c49c..f36422d3a 100644 --- a/zone/client.h +++ b/zone/client.h @@ -582,8 +582,8 @@ public: void GoToBind(uint8 bindnum = 0); void GoToSafeCoords(uint16 zone_id, uint16 instance_id); - void Gate(); - void SetBindPoint(int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3()); + void Gate(uint8 bindnum = 0); + void SetBindPoint(int bind_num = 0, int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3()); void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f); uint32 GetStartZone(void); void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index d77b83c9f..3db1eabea 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -232,27 +232,27 @@ void Lua_Client::SetBindPoint() { void Lua_Client::SetBindPoint(int to_zone) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone); + self->SetBindPoint(0, to_zone); } void Lua_Client::SetBindPoint(int to_zone, int to_instance) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone, to_instance); + self->SetBindPoint(0, to_zone, to_instance); } void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f)); + self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f)); } void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f)); + self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f)); } void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); + self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); } float Lua_Client::GetBindX() { diff --git a/zone/mob.h b/zone/mob.h index 554634006..11c11573f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -468,7 +468,7 @@ public: inline bool IsMoving() const { return moving; } virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); } virtual void GoToBind(uint8 bindnum = 0) { } - virtual void Gate(); + virtual void Gate(uint8 bindnum = 0); int GetWalkspeed() const { return(_GetWalkSpeed()); } int GetRunspeed() const { return(_GetRunSpeed()); } void SetCurrentSpeed(int in); diff --git a/zone/npc.h b/zone/npc.h index 327918c19..fe658aab2 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -165,7 +165,7 @@ public: virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther); void GoToBind(uint8 bindnum = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); } - void Gate(); + void Gate(uint8 bindnum = 0); void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name); void SetPetState(SpellBuff_Struct *buffs, uint32 *items); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d4c5f34d0..9c51b8a92 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -1072,7 +1072,7 @@ XS(XS_Client_SetBindPoint) new_z = (float)SvNV(ST(5)); } - THIS->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); + THIS->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); } XSRETURN_EMPTY; } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fa8788bbf..b16613e75 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1565,7 +1565,7 @@ void QuestManager::ding() { void QuestManager::rebind(int zoneid, const glm::vec3& location) { QuestManagerCurrentQuestVars(); if(initiator && initiator->IsClient()) { - initiator->SetBindPoint(zoneid, 0, location); + initiator->SetBindPoint(0, zoneid, 0, location); } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index d5006a52b..ca10259a1 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -499,7 +499,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_GateCastersBindpoint: //Shin: Used on Teleport Bind. + case SE_GateCastersBindpoint: // Used on Teleport Bind. case SE_Teleport: // gates, rings, circles, etc case SE_Teleport2: { @@ -532,13 +532,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } if (effect == SE_GateCastersBindpoint && caster->IsClient()) - { //Shin: Teleport Bind uses caster's bind point - x = caster->CastToClient()->GetBindX(); - y = caster->CastToClient()->GetBindY(); - z = caster->CastToClient()->GetBindZ(); - heading = caster->CastToClient()->GetBindHeading(); + { // Teleport Bind uses caster's bind point + int index = spells[spell_id].base[i] - 1; + if (index < 0 || index > 4) + index = 0; + x = caster->CastToClient()->GetBindX(index); + y = caster->CastToClient()->GetBindY(index); + z = caster->CastToClient()->GetBindZ(index); + heading = caster->CastToClient()->GetBindHeading(index); //target_zone = caster->CastToClient()->GetBindZoneId(); target_zone doesn't work due to const char - CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(), 0, x, y, z, heading); + CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(index), 0, x, y, z, heading); break; } @@ -917,7 +920,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_packet); safe_delete(message_packet); @@ -966,7 +969,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_packet); safe_delete(message_packet); @@ -1002,7 +1005,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_packet); safe_delete(message_packet); @@ -1012,7 +1015,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Gate: //TO DO: Add support for secondary and tertiary gate abilities (base2) + case SE_Gate: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Gate"); @@ -1020,7 +1023,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(!spellbonuses.AntiGate){ if(zone->random.Roll(effect_value)) - Gate(); + Gate(spells[spell_id].base2[i] - 1); else caster->Message_StringID(MT_SpellFailure,GATE_FAIL); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 591f8c3d3..e90e64af5 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1260,30 +1260,27 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc return true; } -bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){ - std::string query = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %u LIMIT 2", character_id); +bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct *pp) +{ + std::string query = StringFormat("SELECT `slot`, `zone_id`, `instance_id`, `x`, `y`, `z`, `heading` FROM " + "`character_bind` WHERE `id` = %u LIMIT 5", + character_id); auto results = database.QueryDatabase(query); + if (!results.RowCount()) // SHIT -- this actually isn't good + return true; + for (auto row = results.begin(); row != results.end(); ++row) { - - /* Is home bind */ - if (atoi(row[6]) == 1){ - pp->binds[4].zoneId = atoi(row[0]); - pp->binds[4].instance_id = atoi(row[1]); - pp->binds[4].x = atoi(row[2]); - pp->binds[4].y = atoi(row[3]); - pp->binds[4].z = atoi(row[4]); - pp->binds[4].heading = atoi(row[5]); + int index = atoi(row[0]); + if (index < 0 || index > 4) continue; - } - /* Is regular bind point */ - pp->binds[0].zoneId = atoi(row[0]); - pp->binds[0].instance_id = atoi(row[1]); - pp->binds[0].x = atoi(row[2]); - pp->binds[0].y = atoi(row[3]); - pp->binds[0].z = atoi(row[4]); - pp->binds[0].heading = atoi(row[5]); + pp->binds[index].zoneId = atoi(row[1]); + pp->binds[index].instance_id = atoi(row[2]); + pp->binds[index].x = atoi(row[3]); + pp->binds[index].y = atoi(row[4]); + pp->binds[index].z = atoi(row[5]); + pp->binds[index].heading = atoi(row[6]); } return true; @@ -1295,19 +1292,23 @@ bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, ui return true; } -bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home){ - if (zone_id <= 0) { - return false; - } - +bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num) +{ /* Save Home Bind Point */ - std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, position.x, position.y, position.z, position.w, is_home); - Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u position: %s ishome: %u", character_id, zone_id, instance_id, to_string(position).c_str(), is_home); + 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, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num); + + Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u " + "instance_id: %u position: %f %f %f %f bind_num: %u", + character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num); + auto results = QueryDatabase(query); - if (!results.RowsAffected()) { - Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(), query.c_str()); - } + if (!results.RowsAffected()) + Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(), + query.c_str()); + return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index c4d26792d..b5e1d3509 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -277,7 +277,7 @@ public: bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Saves */ - bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home); + bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges); diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 5b60448ec..9c7ae87a4 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -707,37 +707,40 @@ void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) { } -void Mob::Gate() { - GoToBind(); +void Mob::Gate(uint8 bindnum) { + GoToBind(bindnum); } -void Client::Gate() { - Mob::Gate(); +void Client::Gate(uint8 bindnum) { + Mob::Gate(bindnum); } -void NPC::Gate() { +void NPC::Gate(uint8 bindnum) { entity_list.MessageClose_StringID(this, true, 200, MT_Spells, GATES, GetCleanName()); - Mob::Gate(); + Mob::Gate(bindnum); } -void Client::SetBindPoint(int to_zone, int to_instance, const glm::vec3& location) { +void Client::SetBindPoint(int bind_num, int to_zone, int to_instance, const glm::vec3 &location) +{ + if (bind_num < 0 || bind_num >= 4) + bind_num = 0; + if (to_zone == -1) { - m_pp.binds[0].zoneId = zone->GetZoneID(); - m_pp.binds[0].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0; - m_pp.binds[0].x = m_Position.x; - m_pp.binds[0].y = m_Position.y; - m_pp.binds[0].z = m_Position.z; + m_pp.binds[bind_num].zoneId = zone->GetZoneID(); + m_pp.binds[bind_num].instance_id = + (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0; + m_pp.binds[bind_num].x = m_Position.x; + m_pp.binds[bind_num].y = m_Position.y; + m_pp.binds[bind_num].z = m_Position.z; + } else { + m_pp.binds[bind_num].zoneId = to_zone; + m_pp.binds[bind_num].instance_id = to_instance; + m_pp.binds[bind_num].x = location.x; + m_pp.binds[bind_num].y = location.y; + m_pp.binds[bind_num].z = location.z; } - else { - m_pp.binds[0].zoneId = to_zone; - m_pp.binds[0].instance_id = to_instance; - m_pp.binds[0].x = location.x; - m_pp.binds[0].y = location.y; - m_pp.binds[0].z = location.z; - } - auto regularBindPoint = glm::vec4(m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0.0f); - database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPoint, 0); + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[bind_num], bind_num); } void Client::GoToBind(uint8 bindnum) { From 6382ec2cb883c19fa83c82ec63089b9d3afea2f2 Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Sun, 6 Mar 2016 18:36:57 -0800 Subject: [PATCH 545/846] Prevent crash in spell casting when raid doesn't exist --- zone/spells.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 45c52a48b..061b2fd38 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1732,7 +1732,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else if(IsRaidGrouped()) { - group_id_caster = (GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (GetRaid()->GetGroup(CastToClient()) + 1); + if (Raid* raid = GetRaid()) { + uint32 group_id = raid->GetGroup(CastToClient()); + group_id_caster = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + } } } else if(IsPet()) @@ -1744,7 +1747,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else if(owner->IsRaidGrouped()) { - group_id_caster = (owner->GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (owner->GetRaid()->GetGroup(CastToClient()) + 1); + if (Raid* raid = owner->GetRaid()) { + uint32 group_id = raid->GetGroup(owner->CastToClient()); + group_id_caster = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + } } } #ifdef BOTS @@ -1770,7 +1776,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else if(spell_target->IsRaidGrouped()) { - group_id_target = (spell_target->GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (spell_target->GetRaid()->GetGroup(CastToClient()) + 1); + if (Raid* raid = spell_target->GetRaid()) { + uint32 group_id = raid->GetGroup(spell_target->CastToClient()); + group_id_target = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + } } } else if(spell_target->IsPet()) @@ -1782,7 +1791,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else if(owner->IsRaidGrouped()) { - group_id_target = (owner->GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (owner->GetRaid()->GetGroup(CastToClient()) + 1); + if (Raid* raid = owner->GetRaid()) { + uint32 group_id = raid->GetGroup(owner->CastToClient()); + group_id_target = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + } } } #ifdef BOTS From 9291318a854e8be3a314a8233e69c90d0d3ee5e7 Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Sun, 6 Mar 2016 19:35:21 -0800 Subject: [PATCH 546/846] Fix formatting in last commit --- zone/spells.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 061b2fd38..90efd791f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1734,7 +1734,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce { if (Raid* raid = GetRaid()) { uint32 group_id = raid->GetGroup(CastToClient()); - group_id_caster = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + group_id_caster = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); } } } @@ -1749,7 +1749,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce { if (Raid* raid = owner->GetRaid()) { uint32 group_id = raid->GetGroup(owner->CastToClient()); - group_id_caster = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + group_id_caster = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); } } } @@ -1778,7 +1778,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce { if (Raid* raid = spell_target->GetRaid()) { uint32 group_id = raid->GetGroup(spell_target->CastToClient()); - group_id_target = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + group_id_target = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); } } } @@ -1793,7 +1793,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce { if (Raid* raid = owner->GetRaid()) { uint32 group_id = raid->GetGroup(owner->CastToClient()); - group_id_target = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + group_id_target = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); } } } From e2e1298523034f9231e869f0a04b416281ce584e Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 8 Mar 2016 16:25:05 -0500 Subject: [PATCH 547/846] Removed all bot command spell scripts but 'template' query --- .../bind_affinity_spells.sql | 78 ------- .../charm_spells.sql | 73 ------ .../bot_command_spell_scripts/cure_spells.sql | 193 --------------- .../depart_spells.sql | 61 ----- .../escape_spells.sql | 45 ---- .../bot_command_spell_scripts/grow_spells.sql | 39 ---- .../invisibility_spells.sql | 151 ------------ .../levitation_spells.sql | 94 -------- .../bot_command_spell_scripts/lull_spells.sql | 86 ------- .../mesmerize_spells.sql | 76 ------ .../movement_speed_spells.sql | 74 ------ .../resistance_spells.sql | 221 ------------------ .../resurrect_spells.sql | 71 ------ .../bot_command_spell_scripts/rune_spells.sql | 40 ---- .../shrink_spells.sql | 49 ---- .../water_breathing_spells.sql | 84 ------- 16 files changed, 1435 deletions(-) delete mode 100644 utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/charm_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/cure_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/depart_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/escape_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/grow_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/invisibility_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/levitation_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/lull_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/resistance_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/resurrect_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/rune_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/shrink_spells.sql delete mode 100644 utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql diff --git a/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql b/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql deleted file mode 100644 index a48b3318b..000000000 --- a/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql +++ /dev/null @@ -1,78 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY mana_cost DESC, - FIELD(target_type, 'Single'), - spell_level, - FIELD(caster_class, 'CLERIC', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/charm_spells.sql b/utils/scripts/bot_command_spell_scripts/charm_spells.sql deleted file mode 100644 index f2c5e82b8..000000000 --- a/utils/scripts/bot_command_spell_scripts/charm_spells.sql +++ /dev/null @@ -1,73 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '9' AND `CastRestriction` = '0' THEN 'Animal' - WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' - WHEN `targettype` = '11' AND `CastRestriction` = '0' THEN 'Summoned' - WHEN `targettype` = '16' AND `CastRestriction` = '0' THEN 'Plant' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `ResistDiff` resist_diff, - `max1` max_target_level --- extra - -FROM ( - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY resist_diff, - FIELD(target_type, 'Animal', 'Undead', 'Summoned', 'Plant', 'Single'), - max_target_level DESC, - spell_level, - FIELD(caster_class, 'DRUID', 'SHAMAN', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/cure_spells.sql b/utils/scripts/bot_command_spell_scripts/cure_spells.sql deleted file mode 100644 index 75ef1d25c..000000000 --- a/utils/scripts/bot_command_spell_scripts/cure_spells.sql +++ /dev/null @@ -1,193 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - ( - (IF(('20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '1', '0')) | - (IF(('35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '2', '0')) | - (IF(('36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '4', '0')) | - (IF(('116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '8', '0')) | - (IF(('369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '16', '0')) - ) cure_mask --- extra - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes5` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'BARD' caster_class, `classes8` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes8` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), - spell_level DESC, - cure_mask DESC, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'BARD', 'SHAMAN', 'NECROMANCER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/depart_spells.sql b/utils/scripts/bot_command_spell_scripts/depart_spells.sql deleted file mode 100644 index 205ba27f1..000000000 --- a/utils/scripts/bot_command_spell_scripts/depart_spells.sql +++ /dev/null @@ -1,61 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - CONCAT('"', `teleport_zone`, '"') short_name, - CONCAT('"', IFNULL((SELECT `long_name` FROM `zone` WHERE `short_name` = `teleport_zone` LIMIT 1), 'Unreachable Destination'), '"') long_name --- extra - -FROM ( - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `teleport_zone` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '40' - AND ( - '83' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '86' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR ( - '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - AND `teleport_zone` NOT LIKE 'same' - ) - ) -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `teleport_zone` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` = '40' - AND ( - '83' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '86' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR ( - '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - AND `teleport_zone` NOT LIKE 'same' - ) - ) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'GroupV1'), - FIELD(caster_class, 'DRUID', 'WIZARD'), - spell_level, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/escape_spells.sql b/utils/scripts/bot_command_spell_scripts/escape_spells.sql deleted file mode 100644 index 4e08ddeb0..000000000 --- a/utils/scripts/bot_command_spell_scripts/escape_spells.sql +++ /dev/null @@ -1,45 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '40' - AND '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - AND `teleport_zone` LIKE 'same' -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` = '40' - AND '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - AND `teleport_zone` LIKE 'same' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'GroupV2'), - FIELD(caster_class, 'DRUID', 'WIZARD'), - spell_level, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/grow_spells.sql b/utils/scripts/bot_command_spell_scripts/grow_spells.sql deleted file mode 100644 index 4dbca1a06..000000000 --- a/utils/scripts/bot_command_spell_scripts/grow_spells.sql +++ /dev/null @@ -1,39 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '10' --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '89' -- implementation restricted to `effectid1` - AND `effect_base_value1` > 100 -- implementation restricted to `effect_base_value1` -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single'), - FIELD(caster_class, 'SHAMAN'), - spell_level, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql b/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql deleted file mode 100644 index 8545cab30..000000000 --- a/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql +++ /dev/null @@ -1,151 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - CASE - WHEN `effectid1` = '12' THEN 'Living' - WHEN `effectid1` = '13' THEN 'See' - WHEN `effectid1` = '28' THEN 'Undead' - WHEN `effectid1` = '29' THEN 'Animal' - ELSE `effectid1` -- 'UNDEFINED' - END invis_type --- extra - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes5` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(invis_type, 'Animal', 'Undead', 'Living', 'See'), - FIELD(target_type, 'Single', 'GroupV2'), - zone_type, - spell_level DESC, - spell_name, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'MAGICIAN', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/levitation_spells.sql b/utils/scripts/bot_command_spell_scripts/levitation_spells.sql deleted file mode 100644 index 2193c75b7..000000000 --- a/utils/scripts/bot_command_spell_scripts/levitation_spells.sql +++ /dev/null @@ -1,94 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV2'), - zone_type, - spell_level DESC, - spell_name, - FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/lull_spells.sql b/utils/scripts/bot_command_spell_scripts/lull_spells.sql deleted file mode 100644 index 2d0989b85..000000000 --- a/utils/scripts/bot_command_spell_scripts/lull_spells.sql +++ /dev/null @@ -1,86 +0,0 @@ --- needs criteria refinement - -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '8' AND `CastRestriction` = '0' THEN 'AETarget' - WHEN `targettype` = '9' AND `CastRestriction` = '0' THEN 'Animal' - WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes5` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Animal', 'Undead', 'Single', 'AETarget'), - target_type, - zone_type, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'NECROMANCER', 'ENCHANTER'), - spell_level, - spell_id, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql b/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql deleted file mode 100644 index a23d62af6..000000000 --- a/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql +++ /dev/null @@ -1,76 +0,0 @@ --- needs criteria refinement - -SELECT --- base - CASE - WHEN `targettype` = '4' AND `CastRestriction` = '0' THEN 'AECaster' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '8' AND `CastRestriction` = '0' THEN 'AETarget' - WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' - WHEN `targettype` = '11' AND `CastRestriction` = '0' THEN 'Summoned' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `ResistDiff` resist_diff, - `max1` max_target_level --- extra - -FROM ( - SELECT 'BARD' caster_class, `classes8` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes8` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') --- 45-ring - AND `targettype` NOT IN ('45') - AND `effectid1` = '31' -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') --- 45-ring - AND `targettype` NOT IN ('45') - AND `effectid1` = '31' -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') --- 45-ring - AND `targettype` NOT IN ('45') - AND `effectid1` = '31' -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') --- 45-ring - AND `targettype` NOT IN ('45') - AND `effectid1` = '31' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY resist_diff, - FIELD(target_type, 'Undead', 'Summoned', 'Single', 'AECaster', 'AETarget'), - max_target_level DESC, - spell_level DESC, - FIELD(caster_class, 'BARD', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql b/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql deleted file mode 100644 index aaabf2fa2..000000000 --- a/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql +++ /dev/null @@ -1,74 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `effect_base_value2` base_speed --- extra - -FROM ( - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('7', '10') --- 6-self - AND `targettype` NOT IN ('6') - AND `CastRestriction` = '0' - AND `effectdescnum` = '65' -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('7', '10') --- 6-self - AND `targettype` NOT IN ('6') - AND `CastRestriction` = '0' - AND `effectdescnum` = '65' -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('7', '10') --- 6-self - AND `targettype` NOT IN ('6') - AND `CastRestriction` = '0' - AND `effectdescnum` = '65' -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('7', '10') --- 6-self - AND `targettype` NOT IN ('6') - AND `CastRestriction` = '0' - AND `effectdescnum` = '65' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), - effect_base_value2 DESC, - spell_level, - FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/resistance_spells.sql b/utils/scripts/bot_command_spell_scripts/resistance_spells.sql deleted file mode 100644 index 0cda671e7..000000000 --- a/utils/scripts/bot_command_spell_scripts/resistance_spells.sql +++ /dev/null @@ -1,221 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - ( - (IF(('46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '1', '0')) | - (IF(('47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '2', '0')) | - (IF(('48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '4', '0')) | - (IF(('49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '8', '0')) | - (IF(('50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '16', '0')) | - (IF(('370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '32', '0')) - ) resist_type --- extra - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes5` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), - spell_level DESC, - resist_type DESC, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'SHAMAN', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql b/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql deleted file mode 100644 index ac5903727..000000000 --- a/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql +++ /dev/null @@ -1,71 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '4' AND `CastRestriction` = '0' THEN 'AECaster' - WHEN `targettype` = '15' AND `CastRestriction` = '0' THEN 'Corpse' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `effect_base_value1` percent --- extra - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY percent DESC, - FIELD(target_type, 'Corpse', 'AETarget'), - zone_type, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'DRUID', 'SHAMAN', 'NECROMANCER'), - spell_level, - spell_id, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/rune_spells.sql b/utils/scripts/bot_command_spell_scripts/rune_spells.sql deleted file mode 100644 index 30ebee130..000000000 --- a/utils/scripts/bot_command_spell_scripts/rune_spells.sql +++ /dev/null @@ -1,40 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `max1` max_absorbtion --- extra - -FROM ( - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `max1` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' - AND `effectid1` = '55' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), - spell_level DESC, - max1 DESC diff --git a/utils/scripts/bot_command_spell_scripts/shrink_spells.sql b/utils/scripts/bot_command_spell_scripts/shrink_spells.sql deleted file mode 100644 index 26ee84883..000000000 --- a/utils/scripts/bot_command_spell_scripts/shrink_spells.sql +++ /dev/null @@ -1,49 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '10' --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '89' -- implementation restricted to `effectid1` - AND `effect_base_value1` < 100 -- implementation restricted to `effect_base_value1` -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` = '10' --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '89' -- implementation restricted to `effectid1` - AND `effect_base_value1` < 100 -- implementation restricted to `effect_base_value1` -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single'), - FIELD(caster_class, 'SHAMAN', 'BEASTLORD'), - spell_level, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql b/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql deleted file mode 100644 index b6f815429..000000000 --- a/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql +++ /dev/null @@ -1,84 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV2'), - spell_level, - spell_name, - FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'NECROMANCER', 'ENCHANTER', 'BEASTLORD') From 87d92fe809478a1214ec55027e8b2de602d62b0c Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 20 Mar 2016 17:27:08 -0400 Subject: [PATCH 548/846] Update to #myskills to show proper 'Piercing' skill - 1HPiercing will still show if there is a value..but, will not be available for use if your class doesn't support it. --- common/skills.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++++++ common/skills.h | 4 +++ zone/client.cpp | 43 ++++++++++-------------- 3 files changed, 107 insertions(+), 26 deletions(-) diff --git a/common/skills.cpp b/common/skills.cpp index 85c660f6c..987004a2a 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -106,3 +106,89 @@ bool EQEmu::IsBardInstrumentSkill(SkillUseTypes skill) return false; } } + +const std::map& EQEmu::GetSkillUseTypesMap() +{ + static const std::map skill_use_types_map = { + { Skill1HBlunt, "1H Blunt" }, + { Skill1HSlashing, "1H Slashing" }, + { Skill2HBlunt, "2H Blunt" }, + { Skill2HSlashing, "2H Slashing" }, + { SkillAbjuration, "Abjuration" }, + { SkillAlteration, "Alteration" }, + { SkillApplyPoison, "Apply Poison" }, + { SkillArchery, "Archery" }, + { SkillBackstab, "Backstab" }, + { SkillBindWound, "Bind Wound" }, + { SkillBash, "Bash" }, + { SkillBlock, "Block" }, + { SkillBrassInstruments, "Brass Instruments" }, + { SkillChanneling, "Channeling" }, + { SkillConjuration, "Conjuration" }, + { SkillDefense, "Defense" }, + { SkillDisarm, "Disarm" }, + { SkillDisarmTraps, "Disarm Traps" }, + { SkillDivination, "Divination" }, + { SkillDodge, "Dodge" }, + { SkillDoubleAttack, "Double Attack" }, + { SkillDragonPunch, "Dragon Punch" }, + { SkillDualWield, "Dual Wield" }, + { SkillEagleStrike, "Eagle Strike" }, + { SkillEvocation, "Evocation" }, + { SkillFeignDeath, "Feign Death" }, + { SkillFlyingKick, "Flying Kick" }, + { SkillForage, "Forage" }, + { SkillHandtoHand, "Hand to Hand" }, + { SkillHide, "Hide" }, + { SkillKick, "Kick" }, + { SkillMeditate, "Meditate" }, + { SkillMend, "Mend" }, + { SkillOffense, "Offense" }, + { SkillParry, "Parry" }, + { SkillPickLock, "Pick Lock" }, + { Skill1HPiercing, "1H Piercing" }, + { SkillRiposte, "Riposte" }, + { SkillRoundKick, "Round Kick" }, + { SkillSafeFall, "Safe Fall" }, + { SkillSenseHeading, "Sense Heading" }, + { SkillSinging, "Singing" }, + { SkillSneak, "Sneak" }, + { SkillSpecializeAbjure, "Specialize Abjuration" }, + { SkillSpecializeAlteration, "Specialize Alteration" }, + { SkillSpecializeConjuration, "Specialize Conjuration" }, + { SkillSpecializeDivination, "Specialize Divination" }, + { SkillSpecializeEvocation, "Specialize Evocation" }, + { SkillPickPockets, "Pick Pockets" }, + { SkillStringedInstruments, "Stringed Instruments" }, + { SkillSwimming, "Swimming" }, + { SkillThrowing, "Throwing" }, + { SkillTigerClaw, "Tiger Claw" }, + { SkillTracking, "Tracking" }, + { SkillWindInstruments, "Wind Instruments" }, + { SkillFishing, "Fishing" }, + { SkillMakePoison, "Make Poison" }, + { SkillTinkering, "Tinkering" }, + { SkillResearch, "Research" }, + { SkillAlchemy, "Alchemy" }, + { SkillBaking, "Baking" }, + { SkillTailoring, "Tailoring" }, + { SkillSenseTraps, "Sense Traps" }, + { SkillBlacksmithing, "Blacksmithing" }, + { SkillFletching, "Fletching" }, + { SkillBrewing, "Brewing" }, + { SkillAlcoholTolerance, "Alcohol Tolerance" }, + { SkillBegging, "Begging" }, + { SkillJewelryMaking, "Jewelry Making" }, + { SkillPottery, "Pottery" }, + { SkillPercussionInstruments, "Percussion Instruments" }, + { SkillIntimidation, "Intimidation" }, + { SkillBerserking, "Berserking" }, + { SkillTaunt, "Taunt" }, + { SkillFrenzy, "Frenzy" }, + { SkillRemoveTraps, "Remove Traps" }, + { SkillTripleAttack, "Triple Attack" }, + { Skill2HPiercing, "2H Piercing" } + }; + + return skill_use_types_map; +} diff --git a/common/skills.h b/common/skills.h index 4e1e9eb83..a9c5c6095 100644 --- a/common/skills.h +++ b/common/skills.h @@ -18,6 +18,8 @@ #ifndef SKILLS_H #define SKILLS_H +#include + /* ** This is really messed up... Are we using SkillTypes as a pseudo repository? The 76th skill really throws ** things for standardization... @@ -273,6 +275,8 @@ namespace EQEmu { bool IsSpecializedSkill(SkillUseTypes skill); float GetSkillMeleePushForce(SkillUseTypes skill); bool IsBardInstrumentSkill(SkillUseTypes skill); + + const std::map& GetSkillUseTypesMap(); } #endif diff --git a/zone/client.cpp b/zone/client.cpp index 5a9724fa8..f41e35bd2 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4950,36 +4950,27 @@ void Client::ShowSkillsWindow() { const char *WindowTitle = "Skills"; std::string WindowText; - // using a map for easy alphabetizing of the skills list - std::map Skills; - std::map::iterator it; + std::map Skills = EQEmu::GetSkillUseTypesMap(); - // this list of names must keep the same order as that in common/skills.h - const char* SkillName[] = {"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","Ripost","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"}; - for(int i = 0; i <= (int)HIGHEST_SKILL; i++) - Skills[SkillName[i]] = (SkillUseTypes)i; + if (GetClientVersion() < ClientVersion::RoF2) + Skills[Skill1HPiercing] = "Piercing"; // print out all available skills - for(it = Skills.begin(); it != Skills.end(); ++it) { - if(GetSkill(it->second) > 0 || MaxSkill(it->second) > 0) { - WindowText += it->first; - // line up the values - for (int j = 0; j < EmuConstants::ITEM_COMMON_SIZE; j++) - WindowText += " "; - WindowText += itoa(this->GetSkill(it->second)); - if (MaxSkill(it->second) > 0) { - WindowText += "/"; - WindowText += itoa(this->GetMaxSkillAfterSpecializationRules(it->second,this->MaxSkill(it->second))); - } - WindowText += "
"; + for (auto skills_iter : Skills) { + if (skills_iter.first == Skill2HPiercing && GetClientVersion() < ClientVersion::RoF2) + continue; + if (!GetSkill(skills_iter.first) && !MaxSkill(skills_iter.first)) + continue; + + WindowText += skills_iter.second; + // line up the values + WindowText += "      "; + WindowText += itoa(this->GetSkill(skills_iter.first)); + if (MaxSkill(skills_iter.first) > 0) { + WindowText += "/"; + WindowText += itoa(this->GetMaxSkillAfterSpecializationRules(skills_iter.first, this->MaxSkill(skills_iter.first))); } + WindowText += "
"; } this->SendPopupToClient(WindowTitle, WindowText.c_str()); } From 5c812fb824c3a3314847df5508fec97e606c99ed Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 20 Mar 2016 17:51:09 -0400 Subject: [PATCH 549/846] Fix for gcc fail --- common/skills.h | 96 +------------------------------------------------ 1 file changed, 1 insertion(+), 95 deletions(-) diff --git a/common/skills.h b/common/skills.h index a9c5c6095..5ffba33b9 100644 --- a/common/skills.h +++ b/common/skills.h @@ -18,15 +18,9 @@ #ifndef SKILLS_H #define SKILLS_H +#include #include -/* -** This is really messed up... Are we using SkillTypes as a pseudo repository? The 76th skill really throws -** things for standardization... -** -** Below is an attempt to clean this up a little... -*/ - /* ** Skill use types ** @@ -180,94 +174,6 @@ enum SkillUseTypes // server profile does not reflect this yet..so, prefixed with 'PACKET_' #define PACKET_SKILL_ARRAY_SIZE 100 -// TODO: add string return for skill names - -/* -** Old typedef enumeration -** -*/ -/* Correct Skill Numbers as of 4-14-2002 -typedef enum { - _1H_BLUNT = 0, - _1H_SLASHING = 1, - _2H_BLUNT = 2, - _2H_SLASHING = 3, - ABJURE = 4, - ALTERATION = 5, - APPLY_POISON = 6, - ARCHERY = 7, - BACKSTAB = 8, - BIND_WOUND = 9, - BASH = 10, - BLOCKSKILL = 11, - BRASS_INSTRUMENTS = 12, - CHANNELING = 13, - CONJURATION = 14, - DEFENSE = 15, - DISARM = 16, - DISARM_TRAPS = 17, - DIVINATION = 18, - DODGE = 19, - DOUBLE_ATTACK = 20, - DRAGON_PUNCH = 21, //aka Tail Rake - DUAL_WIELD = 22, - EAGLE_STRIKE = 23, - EVOCATION = 24, - FEIGN_DEATH = 25, - FLYING_KICK = 26, - FORAGE = 27, - HAND_TO_HAND = 28, - HIDE = 29, - KICK = 30, - MEDITATE = 31, - MEND = 32, - OFFENSE = 33, - PARRY = 34, - PICK_LOCK = 35, - PIERCING = 36, - RIPOSTE = 37, - ROUND_KICK = 38, - SAFE_FALL = 39, - SENSE_HEADING = 40, - SINGING = 41, - SNEAK = 42, - SPECIALIZE_ABJURE = 43, - SPECIALIZE_ALTERATION = 44, - SPECIALIZE_CONJURATION = 45, - SPECIALIZE_DIVINATION = 46, - SPECIALIZE_EVOCATION = 47, - PICK_POCKETS = 48, - STRINGED_INSTRUMENTS = 49, - SWIMMING = 50, - THROWING = 51, - TIGER_CLAW = 52, - TRACKING = 53, - WIND_INSTRUMENTS = 54, - FISHING = 55, - MAKE_POISON = 56, - TINKERING = 57, - RESEARCH = 58, - ALCHEMY = 59, - BAKING = 60, - TAILORING = 61, - SENSE_TRAPS = 62, - BLACKSMITHING = 63, - FLETCHING = 64, - BREWING = 65, - ALCOHOL_TOLERANCE = 66, - BEGGING = 67, - JEWELRY_MAKING = 68, - POTTERY = 69, - PERCUSSION_INSTRUMENTS = 70, - INTIMIDATION = 71, - BERSERKING = 72, - TAUNT = 73, - FRENZY = 74, - GENERIC_TRADESKILL = 75 -} SkillType; - -#define HIGHEST_SKILL FRENZY -*/ // for skill related helper functions namespace EQEmu { From 48425834268bf6d5cfff115983cf2f7444f30513 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 20 Mar 2016 20:09:14 -0400 Subject: [PATCH 550/846] Added some markers for skills.h and eq_constants.h enumerations --- common/eq_constants.h | 96 +++++++++++++++++++++---------------------- common/skills.h | 34 +++++++-------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/common/eq_constants.h b/common/eq_constants.h index add66c2f4..728013eba 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -32,17 +32,17 @@ enum LightTypes lightTypeTorch, lightTypeTinyGlowingSkull, lightTypeSmallLantern, - lightTypeSteinOfMoggok, + lightTypeSteinOfMoggok, // 5 lightTypeLargeLantern, lightTypeFlamelessLantern, lightTypeGlobeOfStars, lightTypeLightGlobe, - lightTypeLightstone, + lightTypeLightstone, // 10 lightTypeGreaterLightstone, lightTypeFireBeetleEye, lightTypeColdlight, lightTypeUnknown1, - lightTypeUnknown2 + lightTypeUnknown2 // 15 }; #define LIGHT_TYPES_COUNT 16 @@ -58,12 +58,12 @@ enum LightLevels lightLevelTorch, lightLevelSmallMagic, lightLevelRedLight, - lightLevelBlueLight, + lightLevelBlueLight, // 5 lightLevelSmallLantern, lightLevelMagicLantern, lightLevelLargeLantern, lightLevelLargeMagic, - lightLevelBrilliant + lightLevelBrilliant // 10 }; #define LIGHT_LEVELS_COUNT 11 @@ -111,62 +111,62 @@ enum ItemUseTypes : uint8 /*9140*/ ItemType1HPiercing, /*9139*/ ItemType1HBlunt, /*9142*/ ItemType2HBlunt, -/*5504*/ ItemTypeBow, +/*5504*/ ItemTypeBow, // 5 /*----*/ ItemTypeUnknown1, /*----*/ ItemTypeLargeThrowing, /*5505*/ ItemTypeShield, /*5506*/ ItemTypeScroll, -/*5507*/ ItemTypeArmor, +/*5507*/ ItemTypeArmor, // 10 /*5508*/ ItemTypeMisc, // a lot of random crap has this item use. /*7564*/ ItemTypeLockPick, /*----*/ ItemTypeUnknown2, /*5509*/ ItemTypeFood, -/*5510*/ ItemTypeDrink, +/*5510*/ ItemTypeDrink, // 15 /*5511*/ ItemTypeLight, /*5512*/ ItemTypeCombinable, // not all stackable items are this use... /*5513*/ ItemTypeBandage, /*----*/ ItemTypeSmallThrowing, -/*----*/ ItemTypeSpell, // spells and tomes +/*----*/ ItemTypeSpell, // 20 // spells and tomes /*5514*/ ItemTypePotion, /*----*/ ItemTypeUnknown3, /*0406*/ ItemTypeWindInstrument, /*0407*/ ItemTypeStringedInstrument, -/*0408*/ ItemTypeBrassInstrument, +/*0408*/ ItemTypeBrassInstrument, // 25 /*0405*/ ItemTypePercussionInstrument, /*5515*/ ItemTypeArrow, /*----*/ ItemTypeUnknown4, /*5521*/ ItemTypeJewelry, -/*----*/ ItemTypeSkull, +/*----*/ ItemTypeSkull, // 30 /*5516*/ ItemTypeBook, // skill-up tomes/books? (would probably need a pp flag if true...) /*5517*/ ItemTypeNote, /*5518*/ ItemTypeKey, /*----*/ ItemTypeCoin, -/*5520*/ ItemType2HPiercing, +/*5520*/ ItemType2HPiercing, // 35 /*----*/ ItemTypeFishingPole, /*----*/ ItemTypeFishingBait, /*5519*/ ItemTypeAlcohol, /*----*/ ItemTypeKey2, // keys and satchels?? (questable keys?) -/*----*/ ItemTypeCompass, +/*----*/ ItemTypeCompass, // 40 /*----*/ ItemTypeUnknown5, /*----*/ ItemTypePoison, // might be wrong, but includes poisons /*----*/ ItemTypeUnknown6, /*----*/ ItemTypeUnknown7, -/*5522*/ ItemTypeMartial, +/*5522*/ ItemTypeMartial, // 45 /*----*/ ItemTypeUnknown8, /*----*/ ItemTypeUnknown9, /*----*/ ItemTypeUnknown10, /*----*/ ItemTypeUnknown11, -/*----*/ ItemTypeSinging, +/*----*/ ItemTypeSinging, // 50 /*5750*/ ItemTypeAllInstrumentTypes, /*5776*/ ItemTypeCharm, /*----*/ ItemTypeDye, /*----*/ ItemTypeAugmentation, -/*----*/ ItemTypeAugmentationSolvent, +/*----*/ ItemTypeAugmentationSolvent, // 55 /*----*/ ItemTypeAugmentationDistiller, /*----*/ ItemTypeUnknown12, /*----*/ ItemTypeFellowshipKit, /*----*/ ItemTypeUnknown13, -/*----*/ ItemTypeRecipe, +/*----*/ ItemTypeRecipe, // 60 /*----*/ ItemTypeAdvancedRecipe, /*----*/ ItemTypeJournal, // only one(1) database entry /*----*/ ItemTypeAltCurrency, // alt-currency (as opposed to coinage) @@ -237,32 +237,32 @@ enum AugmentationUseTypes : uint8 { AugTypeGeneralMultipleStat, AugTypeGeneralSpellEffect, AugTypeWeaponGeneral, - AugTypeWeaponElemDamage, + AugTypeWeaponElemDamage, // 5 AugTypeWeaponBaseDamage, AugTypeGeneralGroup, AugTypeGeneralRaid, AugTypeGeneralDragonsPoints, - AugTypeCraftedCommon, + AugTypeCraftedCommon, // 10 AugTypeCraftedGroup1, AugTypeCraftedRaid1, AugTypeEnergeiacGroup, AugTypeEnergeiacRaid, - AugTypeEmblem, + AugTypeEmblem, // 15 AugTypeCraftedGroup2, AugTypeCraftedRaid2, AugTypeUnknown1, AugTypeUnknown2, - AugTypeOrnamentation, + AugTypeOrnamentation, // 20 AugTypeSpecialOrnamentation, AugTypeUnknown3, AugTypeUnknown4, AugTypeUnknown5, - AugTypeUnknown6, + AugTypeUnknown6, // 25 AugTypeUnknown7, AugTypeUnknown8, AugTypeUnknown9, AugTypeUnknown10, - AugTypeEpic25, + AugTypeEpic25, // 30 AugTypeTest, _AugTypeCount, AugTypeAll = 255 @@ -280,17 +280,17 @@ enum AugmentationRestrictionTypes : uint8 { /*9135*/ AugRestrWeapons, /*9136*/ AugRestr1HWeapons, /*9137*/ AugRestr2HWeapons, -/*9138*/ AugRestr1HSlash, +/*9138*/ AugRestr1HSlash, // 5 /*9139*/ AugRestr1HBlunt, /*9140*/ AugRestrPiercing, /*9148*/ AugRestrHandToHand, /*9141*/ AugRestr2HSlash, -/*9142*/ AugRestr2HBlunt, +/*9142*/ AugRestr2HBlunt, // 10 /*9143*/ AugRestr2HPierce, /*9144*/ AugRestrBows, /*9145*/ AugRestrShields, /*8052*/ AugRestr1HSlash1HBluntOrHandToHand, -/*9200*/ AugRestr1HBluntOrHandToHand, // no listed peq entries +/*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, @@ -317,57 +317,57 @@ enum ContainerUseTypes : uint8 /*3402*/ BagTypeQuiver, /*3403*/ BagTypeBeltPouch, /*3404*/ BagTypeWristPouch, -/*3405*/ BagTypeBackPack, +/*3405*/ BagTypeBackPack, // 5 /*3406*/ BagTypeSmallChest, /*3407*/ BagTypeLargeChest, /*----*/ BagTypeBandolier, // <*Database Reference Only> /*3408*/ BagTypeMedicineBag, -/*3409*/ BagTypeToolBox, +/*3409*/ BagTypeToolBox, // 10 /*3410*/ BagTypeLexicon, /*3411*/ BagTypeMortar, /*3412*/ BagTypeSelfDusting, // Quest container (Auto-clear contents?) /*3413*/ BagTypeMixingBowl, -/*3414*/ BagTypeOven, +/*3414*/ BagTypeOven, // 15 /*3415*/ BagTypeSewingKit, /*3416*/ BagTypeForge, /*3417*/ BagTypeFletchingKit, /*3418*/ BagTypeBrewBarrel, -/*3419*/ BagTypeJewelersKit, +/*3419*/ BagTypeJewelersKit, // 20 /*3420*/ BagTypePotteryWheel, /*3421*/ BagTypeKiln, /*3422*/ BagTypeKeymaker, // (no database entries as of peq rev 69) /*3423*/ BagTypeWizardsLexicon, -/*3424*/ BagTypeMagesLexicon, +/*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, // Quest container (Never-fail combines?) +/*3427*/ BagTypeAlwaysWorks, // 30 // Quest container (Never-fail combines?) /*3428*/ BagTypeKoadaDalForge, // High Elf /*3429*/ BagTypeTeirDalForge, // Dark Elf /*3430*/ BagTypeOggokForge, // Ogre /*3431*/ BagTypeStormguardForge, // Dwarf -/*3432*/ BagTypeAkanonForge, // Gnome +/*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, // Human 2 +/*3436*/ BagTypeRoyalQeynosForge, // 40 // Human 2 /*3439*/ BagTypeHalflingTailoringKit, /*3438*/ BagTypeErudTailoringKit, /*3440*/ BagTypeFierDalTailoringKit, // Wood Elf /*3441*/ BagTypeFierDalFletchingKit, // Wood Elf -/*3437*/ BagTypeIksarPotteryWheel, +/*3437*/ BagTypeIksarPotteryWheel, // 45 /*3442*/ BagTypeTackleBox, /*3443*/ BagTypeTrollForge, /*3445*/ BagTypeFierDalForge, // Wood Elf /*3444*/ BagTypeValeForge, // Halfling -/*3446*/ BagTypeErudForge, +/*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, // Ornamentation +/*6325*/ BagTypeTransformationmold, // 55 // Ornamentation /*6340*/ BagTypeDetransformationmold, // Ornamentation Stripper /*5400*/ BagTypeUnattuner, /*7684*/ BagTypeTradeskillBag, @@ -816,7 +816,7 @@ enum MaterialUseSlots : uint8 MaterialArms, MaterialWrist, MaterialHands, - MaterialLegs, + MaterialLegs, // 5 MaterialFeet, MaterialPrimary, MaterialSecondary, @@ -864,22 +864,22 @@ enum InventoryMapTypes : int16 { MapSharedBank, MapTrade, MapWorld, - MapLimbo, + MapLimbo, // 5 MapTribute, MapTrophyTribute, MapGuildTribute, MapMerchant, - MapDeleted, + MapDeleted, // 10 MapCorpse, MapBazaar, MapInspect, MapRealEstate, - MapViewMODPC, + MapViewMODPC, // 15 MapViewMODBank, MapViewMODSharedBank, MapViewMODLimbo, MapAltStorage, - MapArchived, + MapArchived, // 20 MapMail, MapGuildTrophyTribute, MapKrono, @@ -893,35 +893,35 @@ enum InventoryMainTypes : int16 { MainHead, MainFace, MainEar2, - MainNeck, + MainNeck, // 5 MainShoulders, MainArms, MainBack, MainWrist1, - MainWrist2, + MainWrist2, // 10 MainRange, MainHands, MainPrimary, MainSecondary, - MainFinger1, + MainFinger1, // 15 MainFinger2, MainChest, MainLegs, MainFeet, - MainWaist, + MainWaist, // 20 MainPowerSource = 9999, // temp MainAmmo = 21, // temp MainGeneral1, MainGeneral2, MainGeneral3, - MainGeneral4, + MainGeneral4, // 25 MainGeneral5, MainGeneral6, MainGeneral7, MainGeneral8, //MainGeneral9, //MainGeneral10, - MainCursor, + MainCursor, // 30 _MainCount }; diff --git a/common/skills.h b/common/skills.h index 5ffba33b9..0868c3329 100644 --- a/common/skills.h +++ b/common/skills.h @@ -33,84 +33,84 @@ enum SkillUseTypes /*13857*/ Skill2HBlunt, /*13858*/ Skill2HSlashing, /*13859*/ SkillAbjuration, -/*13861*/ SkillAlteration, +/*13861*/ SkillAlteration, // 5 /*13862*/ SkillApplyPoison, /*13863*/ SkillArchery, /*13864*/ SkillBackstab, /*13866*/ SkillBindWound, -/*13867*/ SkillBash, +/*13867*/ SkillBash, // 10 /*13871*/ SkillBlock, /*13872*/ SkillBrassInstruments, /*13874*/ SkillChanneling, /*13875*/ SkillConjuration, -/*13876*/ SkillDefense, +/*13876*/ SkillDefense, // 15 /*13877*/ SkillDisarm, /*13878*/ SkillDisarmTraps, /*13879*/ SkillDivination, /*13880*/ SkillDodge, -/*13881*/ SkillDoubleAttack, +/*13881*/ SkillDoubleAttack, // 20 /*13882*/ SkillDragonPunch, /*13924*/ SkillTailRake = SkillDragonPunch, // Iksar Monk equivilent /*13883*/ SkillDualWield, /*13884*/ SkillEagleStrike, /*13885*/ SkillEvocation, -/*13886*/ SkillFeignDeath, +/*13886*/ SkillFeignDeath, // 25 /*13888*/ SkillFlyingKick, /*13889*/ SkillForage, /*13890*/ SkillHandtoHand, /*13891*/ SkillHide, -/*13893*/ SkillKick, +/*13893*/ SkillKick, // 30 /*13894*/ SkillMeditate, /*13895*/ SkillMend, /*13896*/ SkillOffense, /*13897*/ SkillParry, -/*13899*/ SkillPickLock, +/*13899*/ SkillPickLock, // 35 /*13900*/ Skill1HPiercing, // Changed in RoF2(05-10-2013) /*13903*/ SkillRiposte, /*13904*/ SkillRoundKick, /*13905*/ SkillSafeFall, -/*13906*/ SkillSenseHeading, +/*13906*/ SkillSenseHeading, // 40 /*13908*/ SkillSinging, /*13909*/ SkillSneak, /*13910*/ SkillSpecializeAbjure, // No idea why they truncated this one..especially when there are longer ones... /*13911*/ SkillSpecializeAlteration, -/*13912*/ SkillSpecializeConjuration, +/*13912*/ SkillSpecializeConjuration, // 45 /*13913*/ SkillSpecializeDivination, /*13914*/ SkillSpecializeEvocation, /*13915*/ SkillPickPockets, /*13916*/ SkillStringedInstruments, -/*13917*/ SkillSwimming, +/*13917*/ SkillSwimming, // 50 /*13919*/ SkillThrowing, /*13920*/ SkillTigerClaw, /*13921*/ SkillTracking, /*13923*/ SkillWindInstruments, -/*13854*/ SkillFishing, +/*13854*/ SkillFishing, // 55 /*13853*/ SkillMakePoison, /*13852*/ SkillTinkering, /*13851*/ SkillResearch, /*13850*/ SkillAlchemy, -/*13865*/ SkillBaking, +/*13865*/ SkillBaking, // 60 /*13918*/ SkillTailoring, /*13907*/ SkillSenseTraps, /*13870*/ SkillBlacksmithing, /*13887*/ SkillFletching, -/*13873*/ SkillBrewing, +/*13873*/ SkillBrewing, // 65 /*13860*/ SkillAlcoholTolerance, /*13868*/ SkillBegging, /*13892*/ SkillJewelryMaking, /*13901*/ SkillPottery, -/*13898*/ SkillPercussionInstruments, +/*13898*/ SkillPercussionInstruments, // 70 /*13922*/ SkillIntimidation, /*13869*/ SkillBerserking, /*13902*/ SkillTaunt, -/*05837*/ SkillFrenzy, // This appears to be the only listed one not grouped with the others +/*05837*/ SkillFrenzy, // 74 // This appears to be the only listed one not grouped with the others // SoF+ specific skills -/*03670*/ SkillRemoveTraps, +/*03670*/ SkillRemoveTraps, // 75 /*13049*/ SkillTripleAttack, // RoF2+ specific skills -/*00789*/ Skill2HPiercing, +/*00789*/ Skill2HPiercing, // 77 // /*01216*/ SkillNone, // This needs to move down as new skills are added /*00000*/ _EmuSkillCount // move to last position of active enumeration labels From 1e344f2ad28a0e04122349ac719f89b064797759 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 21 Mar 2016 18:35:11 -0400 Subject: [PATCH 551/846] Added 'Open Chest' animation for LDoN chest death (thanks Natedog!) --- zone/attack.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/zone/attack.cpp b/zone/attack.cpp index c14a74059..858e6aee9 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1936,6 +1936,16 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac BuffFadeAll(); uint8 killed_level = GetLevel(); + if (GetClass() == LDON_TREASURE) { // open chest + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); + Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; + anim->spawnid = GetID(); + anim->action = 0x0F; + anim->speed = 10; + entity_list.QueueCloseClients(this, outapp); + safe_delete(outapp); + } + EQApplicationPacket* app = new EQApplicationPacket(OP_Death, sizeof(Death_Struct)); Death_Struct* d = (Death_Struct*)app->pBuffer; d->spawn_id = GetID(); From 8cbcd48461deaa4753c91ff5b9dabf00bb7374d6 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 24 Mar 2016 16:07:17 -0400 Subject: [PATCH 552/846] 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 553/846] 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 554/846] 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 555/846] 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 556/846] 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 557/846] 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 558/846] 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 559/846] 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 560/846] 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 561/846] 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 562/846] 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 563/846] 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 564/846] 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 565/846] 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 566/846] 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 567/846] 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 568/846] 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 569/846] 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 570/846] 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 571/846] 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 572/846] 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 573/846] 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 574/846] 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 575/846] 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 576/846] 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 577/846] 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 578/846] 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 579/846] 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 580/846] 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 581/846] 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 582/846] 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 583/846] 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 584/846] 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 585/846] 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 586/846] 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 587/846] 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 588/846] 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 589/846] 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 590/846] 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 591/846] 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 592/846] 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 593/846] 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 594/846] 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 595/846] 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 596/846] 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 597/846] 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 598/846] 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 599/846] 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 600/846] 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 601/846] 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 602/846] 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 603/846] 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 604/846] 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 605/846] 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 606/846] 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 607/846] 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 608/846] 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 609/846] 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 610/846] 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 611/846] 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 612/846] 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 613/846] 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 614/846] 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 615/846] 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 616/846] 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 617/846] 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 618/846] 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 619/846] 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 620/846] 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 621/846] 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 622/846] 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 623/846] 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 624/846] 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 625/846] 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 626/846] 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 627/846] 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 628/846] 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 629/846] 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 630/846] 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 631/846] 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 632/846] 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 633/846] 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 634/846] 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 635/846] 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 636/846] 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 637/846] 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 638/846] 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 639/846] 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 640/846] 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 641/846] 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 642/846] 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 643/846] 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 644/846] 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 645/846] 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 646/846] 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 647/846] 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 648/846] 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 649/846] 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 650/846] 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 651/846] 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 652/846] 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 653/846] 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 654/846] 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 655/846] 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 656/846] 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 657/846] 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 658/846] 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 659/846] 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 660/846] 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 661/846] 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 662/846] 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 663/846] 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 664/846] 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 665/846] 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 666/846] 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 667/846] 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 668/846] 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 669/846] 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 670/846] 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 671/846] 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 672/846] 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 673/846] 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 674/846] 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 675/846] 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 676/846] 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 677/846] 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 678/846] 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 679/846] 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 680/846] 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 681/846] 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 682/846] 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 683/846] 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 684/846] 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 685/846] 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 686/846] 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 687/846] 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 688/846] 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 689/846] 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 690/846] 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 691/846] 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 692/846] 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 693/846] 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 694/846] 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 695/846] 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 696/846] 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 697/846] 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 698/846] 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 699/846] 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 700/846] 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 701/846] 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 702/846] 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 703/846] 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 704/846] 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 705/846] 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 706/846] 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 707/846] 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 708/846] 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 709/846] 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 710/846] 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 711/846] 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 712/846] 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 713/846] 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 714/846] 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 715/846] 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 716/846] 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 717/846] 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 718/846] 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 719/846] 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 720/846] 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 721/846] 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 722/846] 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 723/846] 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 724/846] 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 725/846] 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 726/846] 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 727/846] 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 728/846] 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 729/846] 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 730/846] 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 731/846] 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 732/846] 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 733/846] 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 734/846] 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 735/846] 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 736/846] 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 737/846] 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 738/846] 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 739/846] 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 740/846] 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 741/846] 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 742/846] 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 743/846] 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 744/846] 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 745/846] 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 746/846] 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 747/846] 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 748/846] 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 749/846] 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 750/846] 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 751/846] 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 752/846] 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 753/846] 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 754/846] 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 755/846] 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 756/846] 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 757/846] 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 758/846] 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 759/846] 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 760/846] 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 761/846] 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 762/846] 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 763/846] 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 764/846] 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 765/846] 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 766/846] 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 767/846] 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 768/846] 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 769/846] 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 770/846] 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 771/846] 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 772/846] 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 773/846] 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 774/846] 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 775/846] 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 776/846] 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 777/846] 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 778/846] 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 779/846] 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 780/846] 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 781/846] 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 782/846] 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 783/846] 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 784/846] 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 785/846] 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 786/846] 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 787/846] 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 788/846] 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 789/846] 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 790/846] 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 791/846] 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 792/846] 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 793/846] 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 794/846] 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 795/846] 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 796/846] 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 797/846] 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 798/846] 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 799/846] 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 800/846] 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 801/846] 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 802/846] 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 803/846] 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 804/846] 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 805/846] 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 806/846] 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 807/846] 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 808/846] 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 809/846] 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 810/846] 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 811/846] 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 812/846] 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 813/846] 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 814/846] 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 815/846] 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 816/846] 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 817/846] 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 818/846] 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 819/846] 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 820/846] 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 821/846] 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 822/846] 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 823/846] 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 824/846] 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 825/846] 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 826/846] 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 827/846] 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 828/846] 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 829/846] 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 830/846] 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 831/846] 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 832/846] 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 833/846] 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 834/846] 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 835/846] 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 836/846] 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 837/846] 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 838/846] 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 839/846] 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 840/846] 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 841/846] 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 842/846] 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 843/846] 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 844/846] 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 845/846] 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 846/846] 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 {