From 4ad8500a3e8760f808d780feb2c87fdd55f66ff1 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 19 Nov 2014 21:01:57 -0800 Subject: [PATCH 01/96] luabind now compiles with warnings disabled for this library --- luabind/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/luabind/CMakeLists.txt b/luabind/CMakeLists.txt index 9f3288d4a..3024f3652 100644 --- a/luabind/CMakeLists.txt +++ b/luabind/CMakeLists.txt @@ -21,7 +21,7 @@ SET(lb_sources ) SET(lb_headers - + ) ADD_LIBRARY(luabind ${lb_sources} ${lb_headers}) @@ -29,6 +29,12 @@ ADD_LIBRARY(luabind ${lb_sources} ${lb_headers}) IF(UNIX) ADD_DEFINITIONS(-fPIC) + set_source_files_properties(${lb_sources} PROPERTY COMPILE_FLAGS -Wno-deprecated-declarations) + ENDIF(UNIX) +IF(MSVC) + set_source_files_properties(${lb_sources} PROPERTY COMPILE_FLAGS " /W0 " ) +ENDIF(MSVC) + SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) From fdd78e41dac5fdb422cfb52f1d143fad64038ae4 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 19 Nov 2014 21:22:37 -0800 Subject: [PATCH 02/96] warning from library file SocketLib\Mime.cpp disabled --- common/CMakeLists.txt | 2 ++ luabind/CMakeLists.txt | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ac42f5e4e..01fcd6df8 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -334,7 +334,9 @@ ADD_LIBRARY(common ${common_sources} ${common_headers}) IF(UNIX) ADD_DEFINITIONS(-fPIC) + SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0) ENDIF(UNIX) + SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/luabind/CMakeLists.txt b/luabind/CMakeLists.txt index 3024f3652..5efdf562f 100644 --- a/luabind/CMakeLists.txt +++ b/luabind/CMakeLists.txt @@ -30,7 +30,6 @@ ADD_LIBRARY(luabind ${lb_sources} ${lb_headers}) IF(UNIX) ADD_DEFINITIONS(-fPIC) set_source_files_properties(${lb_sources} PROPERTY COMPILE_FLAGS -Wno-deprecated-declarations) - ENDIF(UNIX) IF(MSVC) From 5970b0ee41fd7ab432f3e3bf780e73015407d828 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 23 Nov 2014 20:19:54 -0500 Subject: [PATCH 03/96] Fix for numhits counter being decreased 2x for Outgoing Hit Success from client melee attacks. --- zone/attack.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index da812e724..a04ed9985 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1362,11 +1362,8 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b MeleeLifeTap(damage); - if (damage > 0){ - CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); - if (HasSkillProcSuccess() && other && other->GetHP() > 0) - TrySkillProc(other, skillinuse, 0, true, Hand); - } + if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0) + TrySkillProc(other, skillinuse, 0, true, Hand); CommonBreakInvisible(); From 3266ed98e68f3b5bd5b5e5a9cff98dbe9d153f5b Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 23 Nov 2014 20:48:07 -0500 Subject: [PATCH 04/96] Fix for target type 39 GroupNoPets. Should no longer take hold on a pet if your targeting it when casting spell. --- zone/spells.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 06c28adaa..0757e4510 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1670,6 +1670,12 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else { spell_target = this; } + + if (spell_target && spell_target->IsPet() && spells[spell_id].targettype == ST_GroupNoPets){ + Message_StringID(13,NO_CAST_ON_PET); + return false; + } + CastAction = GroupSpell; break; } From ce4c6b0c8a175806b2c53880a0b6134e28eeab0e Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 23 Nov 2014 20:52:24 -0500 Subject: [PATCH 05/96] string --- zone/string_ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/string_ids.h b/zone/string_ids.h index 57711a40d..5375c2d7d 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -264,6 +264,7 @@ #define TRADESKILL_MISSING_COMPONENTS 3456 //Sorry, but you don't have everything you need for this recipe in your general inventory. #define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1! #define EXPEDITION_MIN_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end. +#define NO_CAST_ON_PET 4045 //You cannot cast this spell on your pet. #define REWIND_WAIT 4059 //You must wait a bit longer before using the rewind command again. #define CORPSEDRAG_LIMIT 4061 //You are already dragging as much as you can! #define CORPSEDRAG_ALREADY 4062 //You are already dragging %1. From 5c0fbac7b0361ce251cf575da185966893353b3f Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 23 Nov 2014 21:41:05 -0500 Subject: [PATCH 06/96] Removal of 2x numhits outgoing hit success call from special attack. --- zone/special_attacks.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 963bf51a8..3625c9180 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -2128,8 +2128,6 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if (HasDied()) return; - CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); - if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skillinuse){ int kb_chance = 25; kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100; From 3ca282abfa81c519f26528fc2212a09ad4bc754d Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 23 Nov 2014 22:06:15 -0500 Subject: [PATCH 07/96] Fix for numhits counter not working where buffslot was 0 in some situations. --- zone/mob.cpp | 4 ++-- zone/mob.h | 2 +- zone/spell_effects.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index a7d141b30..6c451f907 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3059,7 +3059,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) 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); + CheckNumHitsRemaining(NUMHIT_MatchingSpells,-1, focus_spell); } } } @@ -3396,7 +3396,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff); } - CheckNumHitsRemaining(NUMHIT_MatchingSpells, 0, focus_spell); + CheckNumHitsRemaining(NUMHIT_MatchingSpells, -1, focus_spell); } } diff --git a/zone/mob.h b/zone/mob.h index a4dd2d665..525cbb2e8 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -275,7 +275,7 @@ public: int16 GetBuffSlotFromType(uint16 type); uint16 GetSpellIDFromSlot(uint8 slot); int CountDispellableBuffs(); - void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, uint16 spell_id=SPELL_UNKNOWN); + void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=-1, 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; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 447d34efd..35d93127a 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5586,8 +5586,8 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id) } } } - } else if (type == 7) { - if (buff_slot > 0) { + } else if (type == NUMHIT_MatchingSpells) { + if (buff_slot >= 0) { if (--buffs[buff_slot].numhits == 0) { CastOnNumHitFade(buffs[buff_slot].spellid); if (!TryFadeEffect(buff_slot)) From f4d024fd478da28af51e01fb1e11c701ca766250 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 23 Nov 2014 23:44:14 -0500 Subject: [PATCH 08/96] Swarm pets will no longer assist owners if special ability '34' IMMUNE_AGGRO is set. --- zone/entity.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index ed5b99219..a17bf9317 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -3652,7 +3652,8 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy) NPC* n = it->second; if (n->GetSwarmInfo()) { if (n->GetSwarmInfo()->owner_id == owner->GetID()) { - n->CastToNPC()->hate_list.Add(other, 0, 0, bFrenzy); + if (!n->GetSpecialAbility(IMMUNE_AGGRO)) + n->hate_list.Add(other, 0, 0, bFrenzy); } } ++it; From 09e13d00341748b2988820591ba99fe84f0f7397 Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 25 Nov 2014 02:22:58 -0600 Subject: [PATCH 09/96] Spells that modify model size are now limited to 2 size adjustments from the base size. --- changelog.txt | 3 +++ .../optional/2014_11_24_EnableMeritBasedFaction.sql | 2 +- zone/merc.cpp | 6 +++--- zone/spell_effects.cpp | 11 ++++++++++- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3a72ea152..b75a58dbc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/24/2014 == +Trevius: Spells that modify model size are now limited to 2 size adjustments from the base size. + == 11/24/2014 == Trevius: Added Rule NPC:EnableMeritBasedFaction (disabled by default) - Allows faction gain to work similar to experience. diff --git a/utils/sql/git/optional/2014_11_24_EnableMeritBasedFaction.sql b/utils/sql/git/optional/2014_11_24_EnableMeritBasedFaction.sql index 67e1b1888..942b016ab 100644 --- a/utils/sql/git/optional/2014_11_24_EnableMeritBasedFaction.sql +++ b/utils/sql/git/optional/2014_11_24_EnableMeritBasedFaction.sql @@ -1 +1 @@ -INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'NPC:EnableMeritBasedFaction', 'false', 'If set to true, faction will given in the same way as experience (solo/group/raid).'); \ No newline at end of file +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'NPC:EnableMeritBasedFaction', 'false', 'If set to true, faction will be given in the same way as experience (solo/group/raid).'); \ No newline at end of file diff --git a/zone/merc.cpp b/zone/merc.cpp index 2ecd0849e..489b51e56 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4338,7 +4338,7 @@ Corpse* Merc::GetGroupMemberCorpse() { if(g->members[i] && g->members[i]->IsClient()) { corpse = entity_list.GetCorpseByOwnerWithinRange(g->members[i]->CastToClient(), this, RuleI(Mercs, ResurrectRadius)); - if(corpse && !corpse->IsRezzed()) { + if(corpse && !corpse->Rezzed()) { return corpse; } } @@ -5540,7 +5540,7 @@ void Client::SpawnMercOnZone() { } else { - int32 TimeDiff = GetMercInfo().SuspendedTime + RuleI(Mercs, SuspendIntervalS) - time(nullptr); + int32 TimeDiff = GetMercInfo().SuspendedTime - time(nullptr); if (TimeDiff > 0) { if (!GetPTimers().Enabled(pTimerMercSuspend)) @@ -6367,4 +6367,4 @@ uint32 Merc::CalcUpkeepCost(uint32 templateID , uint8 level, uint8 currency_type } return cost; -} +} \ No newline at end of file diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 447d34efd..d73c667a1 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1665,7 +1665,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Model Size: %d%%", effect_value); #endif - ChangeSize(GetSize() * (static_cast(effect_value) / 100.0f)); + // 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) || + (GetSize() >= GetBaseSize() && GetSize() < maxModAmount) || + (GetSize() <= GetBaseSize() && maxModAmount > 1.0f) || + (GetSize() >= GetBaseSize() && maxModAmount < 1.0f)) + { + ChangeSize(GetSize() * modifyAmount); + } break; } From b4862dea45ab81e94def92b3cf9c86cee79a8a51 Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 25 Nov 2014 02:54:02 -0600 Subject: [PATCH 10/96] Compile Fix and fix to prevent Mercenaries from being set as Group Leader. --- changelog.txt | 1 + zone/groups.cpp | 44 ++++++++++++++++++++++++++++++-------------- zone/merc.cpp | 2 +- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/changelog.txt b/changelog.txt index b75a58dbc..b05fc26ee 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 11/24/2014 == Trevius: Spells that modify model size are now limited to 2 size adjustments from the base size. +Trevius: Fix to prevent Mercenaries from being set as Group Leader. == 11/24/2014 == Trevius: Added Rule NPC:EnableMeritBasedFaction (disabled by default) - Allows faction gain to work similar to experience. diff --git a/zone/groups.cpp b/zone/groups.cpp index 2e7fb3cfe..3180e51f1 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -592,12 +592,15 @@ bool Group::DelMemberOOZ(const char *Name) { bool Group::DelMember(Mob* oldmember,bool ignoresender) { - if (oldmember == nullptr){ + if (oldmember == nullptr) + { return false; } - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == oldmember) { + 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); @@ -606,16 +609,6 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender) } } - //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; - } - } - } - /* This may seem pointless but the case above does not cover the following situation: * Group has Leader a, member b, member c * b and c are out of zone @@ -624,10 +617,33 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender) * a is still "leader" from GetLeader()'s perspective and will crash the zone when we DelMember(b) * Ultimately we should think up a better solution to this. */ - if(oldmember == GetLeader()) { + if(oldmember == GetLeader()) + { SetLeader(nullptr); } + //handle leader quitting group gracefully + if (oldmember == GetLeader() && GroupCount() >= 2) + { + for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) + { + if(members[nl]) + { + if (members[nl]->IsClient()) + { + ChangeLeader(members[nl]); + break; + } + } + } + } + + if (GetLeader() == nullptr) + { + DisbandGroup(); + return true; + } + ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; gl->gid = GetID(); diff --git a/zone/merc.cpp b/zone/merc.cpp index 489b51e56..b2793db73 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4338,7 +4338,7 @@ Corpse* Merc::GetGroupMemberCorpse() { if(g->members[i] && g->members[i]->IsClient()) { corpse = entity_list.GetCorpseByOwnerWithinRange(g->members[i]->CastToClient(), this, RuleI(Mercs, ResurrectRadius)); - if(corpse && !corpse->Rezzed()) { + if(corpse && !corpse->IsRezzed()) { return corpse; } } From 0598f7e87ccc791223617f17f763c32729c7e614 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 25 Nov 2014 22:47:50 -0600 Subject: [PATCH 11/96] Fixed an issue that has surfaced with new code behaving how it should, breaking old code. Naked corpses were not despawning on their decay timers because of incorrect return logic on a database function Removed ClearCorpseItems as it is no longer necessary as corpses deleted items appropriately when they are removed from the corpse General cleanup of functions and variables in corpse code --- zone/corpse.cpp | 236 ++++++++++++++++++++++-------------- zone/corpse.h | 4 +- zone/lua_corpse.cpp | 2 +- zone/perl_player_corpse.cpp | 2 +- zone/zonedb.cpp | 10 -- zone/zonedb.h | 1 - 6 files changed, 150 insertions(+), 105 deletions(-) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 8be978350..6572012bc 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -140,16 +140,58 @@ Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_ return pc; } -// To be used on NPC death and ZoneStateLoad -// Mongrel: added see_invis and see_invis_undead Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime) -// vesuvias - appearence fix -: Mob("Unnamed_Corpse","",0,0,in_npc->GetGender(),in_npc->GetRace(),in_npc->GetClass(),BT_Humanoid,//bodytype added - in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),in_npc->GetSize(),0, - in_npc->GetHeading(),in_npc->GetX(),in_npc->GetY(),in_npc->GetZ(),0, - 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), + : Mob("Unnamed_Corpse", // const char* in_name, + "", // const char* in_lastname, + 0, // int32 in_cur_hp, + 0, // int32 in_max_hp, + in_npc->GetGender(), // uint8 in_gender, + in_npc->GetRace(), // uint16 in_race, + in_npc->GetClass(), // uint8 in_class, + BT_Humanoid, // bodyType in_bodytype, + in_npc->GetDeity(), // uint8 in_deity, + in_npc->GetLevel(), // uint8 in_level, + in_npc->GetNPCTypeID(), // uint32 in_npctype_id, + in_npc->GetSize(), // float in_size, + 0, // float in_runspeed, + in_npc->GetHeading(), // float in_heading, + in_npc->GetX(), // float in_x_pos, + in_npc->GetY(), // float in_y_pos, + in_npc->GetZ(), // float in_z_pos, + 0, // uint8 in_light, + in_npc->GetTexture(), // uint8 in_texture, + in_npc->GetHelmTexture(), // uint8 in_helmtexture, + 0, // uint16 in_ac, + 0, // uint16 in_atk, + 0, // uint16 in_str, + 0, // uint16 in_sta, + 0, // uint16 in_dex, + 0, // uint16 in_agi, + 0, // uint16 in_int, + 0, // uint16 in_wis, + 0, // uint16 in_cha, + 0, // uint8 in_haircolor, + 0, // uint8 in_beardcolor, + 0, // uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye? + 0, // uint8 in_eyecolor2, + 0, // uint8 in_hairstyle, + 0, // uint8 in_luclinface, + 0, // uint8 in_beard, + 0, // uint32 in_drakkin_heritage, + 0, // uint32 in_drakkin_tattoo, + 0, // uint32 in_drakkin_details, + 0, // uint32 in_armor_tint[_MaterialCount], + 0xff, // uint8 in_aa_title, + 0, // uint8 in_see_invis, // see through invis/ivu + 0, // uint8 in_see_invis_undead, + 0, // uint8 in_see_hide, + 0, // uint8 in_see_improved_hide, + 0, // int32 in_hp_regen, + 0, // int32 in_mana_regen, + 0, // uint8 in_qglobal, + 0, // uint8 in_maxlevel, + 0 // uint32 in_scalerate +), corpse_decay_timer(in_decaytime), corpse_res_timer(0), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), @@ -157,7 +199,9 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP loot_cooldown_timer(10) { corpse_graveyard_timer.Disable(); + memset(item_tint, 0, sizeof(item_tint)); + is_corpse_changed = false; is_player_corpse = false; is_locked = false; @@ -396,7 +440,6 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( Save(); } -// solar: helper function for client corpse constructor std::list Corpse::MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot) { int bagindex; @@ -425,59 +468,59 @@ std::list Corpse::MoveItemToCorpse(Client *client, ItemInst *item, int16 return returnlist; } -// To be called from LoadFromDBData -// Mongrel: added see_invis and see_invis_undead +/* Called from Database Load */ + Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture,uint32 in_rezexp, bool wasAtGraveyard) -: Mob("Unnamed_Corpse", -"", -0, -0, -in_gender, -in_race, -in_class, -BT_Humanoid, -in_deity, -in_level, -0, -in_size, -0, -in_heading, -in_x, -in_y, -in_z, -0, -in_texture, -in_helmtexture, -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), + : Mob("Unnamed_Corpse", // const char* in_name, + "", // const char* in_lastname, + 0, // int32 in_cur_hp, + 0, // int32 in_max_hp, + in_gender, // uint8 in_gender, + in_race, // uint16 in_race, + in_class, // uint8 in_class, + BT_Humanoid, // bodyType in_bodytype, + in_deity, // uint8 in_deity, + in_level, // uint8 in_level, + 0, // uint32 in_npctype_id, + in_size, // float in_size, + 0, // float in_runspeed, + in_heading, // float in_heading, + in_x, // float in_x_pos, + in_y, // float in_y_pos, + in_z, // float in_z_pos, + 0, // uint8 in_light, + in_texture, // uint8 in_texture, + in_helmtexture, // uint8 in_helmtexture, + 0, // uint16 in_ac, + 0, // uint16 in_atk, + 0, // uint16 in_str, + 0, // uint16 in_sta, + 0, // uint16 in_dex, + 0, // uint16 in_agi, + 0, // uint16 in_int, + 0, // uint16 in_wis, + 0, // uint16 in_cha, + 0, // uint8 in_haircolor, + 0, // uint8 in_beardcolor, + 0, // uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye? + 0, // uint8 in_eyecolor2, + 0, // uint8 in_hairstyle, + 0, // uint8 in_luclinface, + 0, // uint8 in_beard, + 0, // uint32 in_drakkin_heritage, + 0, // uint32 in_drakkin_tattoo, + 0, // uint32 in_drakkin_details, + 0, // uint32 in_armor_tint[_MaterialCount], + 0xff, // uint8 in_aa_title, + 0, // uint8 in_see_invis, // see through invis/ivu + 0, // uint8 in_see_invis_undead, + 0, // uint8 in_see_hide, + 0, // uint8 in_see_improved_hide, + 0, // int32 in_hp_regen, + 0, // int32 in_mana_regen, + 0, // uint8 in_qglobal, + 0, // uint8 in_maxlevel, + 0), // uint32 in_scalerate corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_res_timer(RuleI(Character, CorpseResTimeMS)), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), @@ -487,8 +530,9 @@ in_helmtexture, LoadPlayerCorpseDecayTime(in_dbid); - if(!zone->HasGraveyard() || wasAtGraveyard) + if (!zone->HasGraveyard() || wasAtGraveyard){ corpse_graveyard_timer.Disable(); + } memset(item_tint, 0, sizeof(item_tint)); @@ -504,10 +548,12 @@ in_helmtexture, strcpy(orgname, in_charname); strcpy(name, in_charname); + this->copper = in_copper; this->silver = in_silver; this->gold = in_gold; this->platinum = in_plat; + rezzexp = in_rezexp; for (int i = 0; i < MAX_LOOTERS; i++){ @@ -757,16 +803,19 @@ void Corpse::RemoveCash() { bool Corpse::IsEmpty() const { if (copper != 0 || silver != 0 || gold != 0 || platinum != 0) return false; + return(itemlist.size() == 0); } bool Corpse::Process() { - if (player_corpse_depop) + if (player_corpse_depop){ return false; + } if(corpse_delay_timer.Check()) { - for (int i=0; iwrite(EQEMuLog::Debug, "Tagged %s player corpse has burried.", this->GetName()); } - else - { + else { LogFile->write(EQEMuLog::Error, "Unable to bury %s player corpse.", this->GetName()); return true; } @@ -828,19 +885,22 @@ void Corpse::SetDecayTimer(uint32 decaytime) { corpse_decay_timer.Start(decaytime); } -bool Corpse::CanMobLoot(int charid) { - uint8 z=0; - for(int i=0; iCastToClient()->CharacterID(); } -// @merth: this function needs some work void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* app) { // Added 12/08. Started compressing loot struct on live. char tmp[10]; @@ -883,18 +942,18 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } uint8 tCanLoot = 1; - bool lootcoin = false; - if(database.GetVariable("LootCoin", tmp, 9)) { lootcoin = (atoi(tmp) == 1); } + bool loot_coin = false; + if(database.GetVariable("LootCoin", tmp, 9)) { loot_coin = (atoi(tmp) == 1); } if(this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) { SendLootReqErrorPacket(client, 0); tCanLoot = 0; } else if(IsPlayerCorpse() && char_id == client->CharacterID()) { tCanLoot = 2; } - else if((IsNPCCorpse() || become_npc) && CanMobLoot(client->CharacterID())) { tCanLoot = 2; } - else if(GetPKItem() == -1 && CanMobLoot(client->CharacterID())) { tCanLoot = 3; } //pvp loot all items, variable cash - else if(GetPKItem() == 1 && CanMobLoot(client->CharacterID())) { tCanLoot = 4; } //pvp loot 1 item, variable cash - else if(GetPKItem() > 1 && CanMobLoot(client->CharacterID())) { tCanLoot = 5; } //pvp loot 1 set item, variable cash + else if((IsNPCCorpse() || become_npc) && CanPlayerLoot(client->CharacterID())) { tCanLoot = 2; } + else if(GetPKItem() == -1 && CanPlayerLoot(client->CharacterID())) { tCanLoot = 3; } //pvp loot all items, variable cash + else if(GetPKItem() == 1 && CanPlayerLoot(client->CharacterID())) { tCanLoot = 4; } //pvp loot 1 item, variable cash + else if(GetPKItem() > 1 && CanPlayerLoot(client->CharacterID())) { tCanLoot = 5; } //pvp loot 1 set item, variable cash if(tCanLoot == 1) { if(client->Admin() < 100 || !client->GetGM()) { SendLootReqErrorPacket(client, 2); } } @@ -906,7 +965,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a d->response = 1; d->unknown1 = 0x42; d->unknown2 = 0xef; - if(tCanLoot == 2 || (tCanLoot >= 3 && lootcoin)) { // dont take the coin off if it's a gm peeking at the corpse + if(tCanLoot == 2 || (tCanLoot >= 3 && loot_coin)) { // dont take the coin off if it's a gm peeking at the corpse if(!IsPlayerCorpse() && client->IsGrouped() && client->AutoSplitEnabled() && client->GetGroup()) { d->copper = 0; @@ -951,8 +1010,6 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - uint8 containercount = 0; - int corpselootlimit = EQLimits::InventoryMapSize(MapCorpse, client->GetClientVersion()); for(; cur != end; ++cur) { @@ -1045,7 +1102,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { SendEndLootErrorPacket(client); return; } - if (IsPlayerCorpse() && !CanMobLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) { + if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) { client->Message(13, "Error: This is a player corpse and you dont own it."); SendEndLootErrorPacket(client); return; @@ -1055,7 +1112,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { client->Message(13, "Error: Corpse locked by GM."); return; } - if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanMobLoot(client->CharacterID()) && GetPKItem() == 0){ + if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPKItem() == 0){ client->Message(13, "Error: You cannot loot any more items from this corpse."); SendEndLootErrorPacket(client); being_looted_by = 0xFFFFFFFF; @@ -1222,7 +1279,6 @@ void Corpse::EndLoot(Client* client, const EQApplicationPacket* app) { client->QueuePacket(outapp); safe_delete(outapp); - //client->Save(); //inventory operations auto-commit this->being_looted_by = 0xFFFFFFFF; if (this->IsEmpty()) Delete(); diff --git a/zone/corpse.h b/zone/corpse.h index f365dd041..4f0e96d05 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -69,7 +69,7 @@ public: inline uint32 GetDBID() { return corpse_db_id; } inline char* GetOwnerName() { return orgname;} - void SetDecayTimer(uint32 decaytime); + void SetDecayTimer(uint32 decay_time); bool IsEmpty() const; void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0); uint32 GetWornItem(int16 equipSlot) const; @@ -99,7 +99,7 @@ public: void CompleteRezz(); void SetPKItem(int32 id) { player_kill_item = id; } int32 GetPKItem() { return player_kill_item; } - bool CanMobLoot(int charid); + bool CanPlayerLoot(int charid); void AllowMobLoot(Mob *them, uint8 slot); void AddLooter(Mob *who); bool IsRezzed() { return rez; } diff --git a/zone/lua_corpse.cpp b/zone/lua_corpse.cpp index beada7e9a..5862bbe96 100644 --- a/zone/lua_corpse.cpp +++ b/zone/lua_corpse.cpp @@ -114,7 +114,7 @@ void Lua_Corpse::SetDecayTimer(uint32 decaytime) { bool Lua_Corpse::CanMobLoot(int charid) { Lua_Safe_Call_Bool(); - return self->CanMobLoot(charid); + return self->CanPlayerLoot(charid); } void Lua_Corpse::AllowMobLoot(Lua_Mob them, uint8 slot) { diff --git a/zone/perl_player_corpse.cpp b/zone/perl_player_corpse.cpp index af5c79f16..f8b2d4388 100644 --- a/zone/perl_player_corpse.cpp +++ b/zone/perl_player_corpse.cpp @@ -687,7 +687,7 @@ XS(XS_Corpse_CanMobLoot) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->CanMobLoot(charid); + RETVAL = THIS->CanPlayerLoot(charid); ST(0) = boolSV(RETVAL); sv_2mortal(ST(0)); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 11d76e4af..8794f3570 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3937,15 +3937,6 @@ uint32 ZoneDatabase::GetFirstCorpseID(uint32 char_id) { return 0; } -bool ZoneDatabase::ClearCorpseItems(uint32 db_id){ - std::string query = StringFormat("DELETE FROM `character_corpse_items` WHERE `corpse_id` = %u", db_id); - auto results = QueryDatabase(query); - if (results.Success() && results.RowsAffected() != 0){ - return true; - } - return false; -} - bool ZoneDatabase::DeleteItemOffCharacterCorpse(uint32 db_id, uint32 equip_slot, uint32 item_id){ std::string query = StringFormat("DELETE FROM `character_corpse_items` WHERE `corpse_id` = %u AND equip_slot = %u AND item_id = %u", db_id, equip_slot, item_id); auto results = QueryDatabase(query); @@ -3959,7 +3950,6 @@ bool ZoneDatabase::BuryCharacterCorpse(uint32 db_id) { std::string query = StringFormat("UPDATE `character_corpses` SET `is_buried` = 1 WHERE `id` = %u", db_id); auto results = QueryDatabase(query); if (results.Success() && results.RowsAffected() != 0){ - ClearCorpseItems(db_id); return true; } return false; diff --git a/zone/zonedb.h b/zone/zonedb.h index 33554aac3..3f8719946 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -295,7 +295,6 @@ public: bool NoRentExpired(const char* name); /* Corpses */ - bool ClearCorpseItems(uint32 db_id); bool DeleteItemOffCharacterCorpse(uint32 db_id, uint32 equip_slot, uint32 item_id); uint32 GetCharacterCorpseItemCount(uint32 corpse_id); bool LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct* pcs); From fbaae2b1e471a9c007c6b2e181c1c8eb735c86ca Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 25 Nov 2014 23:17:08 -0600 Subject: [PATCH 12/96] Renamed Corpse::LoadFromDBData to Corpse* Corpse::LoadCharacterCorpseEntity Corpse Private class descriptors added General cleanup --- zone/corpse.cpp | 125 ++++++++++++++++++++++++++++-------------------- zone/corpse.h | 39 +++++++-------- zone/npc.h | 3 +- zone/spells.cpp | 4 +- zone/zonedb.cpp | 8 ++-- 5 files changed, 100 insertions(+), 79 deletions(-) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 6572012bc..0b93306f1 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -63,8 +63,7 @@ void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) { safe_delete(outapp); } -Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard) -{ +Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, 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))]; PlayerCorpse_Struct *pcs = (PlayerCorpse_Struct*)buffer; @@ -105,11 +104,11 @@ Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_ pcs->exp, // uint32 in_rezexp was_at_graveyard // bool wasAtGraveyard ); - if (pcs->locked) + if (pcs->locked){ pc->Lock(); + } /* Load Item Tints */ - // memcpy(pc->item_tint, pcs->item_tint, sizeof(pc->item_tint)); 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; @@ -118,8 +117,7 @@ Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_ 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[8].color = pcs->item_tint[8].color; /* Load Physical Appearance */ pc->haircolor = pcs->haircolor; @@ -231,15 +229,15 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP corpse_decay_timer.SetTimer(RuleI(NPC,EmptyNPCCorpseDecayTimeMS)+1000); } + if(in_npc->HasPrivateCorpse()) { corpse_delay_timer.SetTimer(corpse_decay_timer.GetRemainingTime() + 1000); } - // Added By Hogie -- End for (int i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; } - this->rezzexp = 0; + this->rez_experience = 0; } Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( @@ -317,8 +315,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( } is_corpse_changed = true; - rezzexp = in_rezexp; - can_rez = true; + rez_experience = in_rezexp; + can_corpse_be_rezzed = true; is_player_corpse = true; is_locked = false; being_looted_by = 0xFFFFFFFF; @@ -386,9 +384,9 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( // this was mainly for client profile state reflection..should match db player inventory entries now. iter_queue it; - for(it=client->GetInv().cursor_begin(),i=8001; it!=client->GetInv().cursor_end(); ++it,i++) { + for (it = client->GetInv().cursor_begin(), i = 8001; it != client->GetInv().cursor_end(); ++it, i++) { item = *it; - if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) { + if ((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) { std::list slot_list = MoveItemToCorpse(client, item, i); removed_list.merge(slot_list); cursor = true; @@ -397,16 +395,17 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( } database.TransactionBegin(); - if(removed_list.size() != 0) { + if (removed_list.size() != 0) { std::stringstream ss(""); ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID(); ss << " AND ("; std::list::const_iterator iter = removed_list.begin(); bool first = true; - while(iter != removed_list.end()) { - if(first) { + while (iter != removed_list.end()) { + if (first) { first = false; - } else { + } + else { ss << " OR "; } ss << "slotid=" << (*iter); @@ -416,8 +415,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( database.QueryDatabase(ss.str().c_str()); } - if(cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false) - while(!client->GetInv().CursorEmpty()) + if (cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false) + while (!client->GetInv().CursorEmpty()) client->DeleteItemInInventory(MainCursor, 0, false, false); } else { // only visible cursor made it to corpse (client >= Sof and RespawnFromHover = true) @@ -451,13 +450,13 @@ std::list Corpse::MoveItemToCorpse(Client *client, ItemInst *item, int16 returnlist.push_back(equipslot); // Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea. - if(item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) { - for(bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) { + if (item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) { + for (bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) { // For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1) interior_slot = Inventory::CalcSlotId(equipslot, bagindex); interior_item = client->GetInv().GetItem(interior_slot); - if(interior_item) { + if (interior_item) { AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4)); returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex)); client->DeleteItemInInventory(interior_slot, 0, true, false); @@ -554,7 +553,7 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemLi this->gold = in_gold; this->platinum = in_plat; - rezzexp = in_rezexp; + rez_experience = in_rezexp; for (int i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; @@ -564,7 +563,7 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemLi Corpse::~Corpse() { if (is_player_corpse && !(player_corpse_depop && corpse_db_id == 0)) { - Save(); + Save(); } ItemList::iterator cur,end; cur = itemlist.begin(); @@ -618,7 +617,7 @@ bool Corpse::Save() { dbpc->level = level; dbpc->texture = this->texture; dbpc->helmtexture = this->helmtexture; - dbpc->exp = rezzexp; + dbpc->exp = rez_experience; memcpy(dbpc->item_tint, item_tint, sizeof(dbpc->item_tint)); dbpc->haircolor = haircolor; @@ -664,10 +663,10 @@ void Corpse::Delete() { } void Corpse::Bury() { - if (IsPlayerCorpse() && corpse_db_id != 0) + if (IsPlayerCorpse() && corpse_db_id != 0){ database.BuryCharacterCorpse(corpse_db_id); + } corpse_db_id = 0; - player_corpse_depop = true; } @@ -677,7 +676,7 @@ void Corpse::Depop() { } void Corpse::DepopCorpse() { - player_corpse_depop = true; + player_corpse_depop = true; } uint32 Corpse::CountItems() { @@ -689,7 +688,9 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui return; is_corpse_changed = true; + ServerLootItem_Struct* item = new ServerLootItem_Struct; + memset(item, 0, sizeof(ServerLootItem_Struct)); item->item_id = itemnum; item->charges = charges; @@ -705,7 +706,6 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data) { ServerLootItem_Struct *sitem = 0, *sitem2; - // find the item ItemList::iterator cur,end; cur = itemlist.begin(); end = itemlist.end(); @@ -721,9 +721,9 @@ ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** cur = itemlist.begin(); end = itemlist.end(); - for(; cur != end; ++cur) { + for (; cur != end; ++cur) { sitem2 = *cur; - if(sitem2->equip_slot >= bagstart && sitem2->equip_slot < bagstart + 10) { + if (sitem2->equip_slot >= bagstart && sitem2->equip_slot < bagstart + 10) { bag_item_data[sitem2->equip_slot - bagstart] = sitem2; } } @@ -753,7 +753,7 @@ void Corpse::RemoveItem(uint16 lootslot) { ItemList::iterator cur,end; cur = itemlist.begin(); end = itemlist.end(); - for(; cur != end; ++cur) { + for (; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; if (sitem->lootslot == lootslot) { RemoveItem(sitem); @@ -812,7 +812,7 @@ bool Corpse::Process() { return false; } - if(corpse_delay_timer.Check()) { + if (corpse_delay_timer.Check()) { for (int i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; } @@ -820,8 +820,8 @@ bool Corpse::Process() { return true; } - if(corpse_graveyard_timer.Check()) { - if(zone->HasGraveyard()) { + if (corpse_graveyard_timer.Check()) { + if (zone->HasGraveyard()) { Save(); player_corpse_depop = true; database.SendCharacterCorpseToGraveyard(corpse_db_id, zone->graveyard_zoneid(), @@ -849,7 +849,7 @@ bool Corpse::Process() { */ /* This is when a corpse hits decay timer and does checks*/ - if(corpse_decay_timer.Check()) { + if (corpse_decay_timer.Check()) { /* NPC */ if (IsNPCCorpse()){ corpse_decay_timer.Disable(); @@ -860,7 +860,7 @@ bool Corpse::Process() { Delete(); } else { - if(database.BuryCharacterCorpse(corpse_db_id)) { + if (database.BuryCharacterCorpse(corpse_db_id)) { Save(); player_corpse_depop = true; corpse_db_id = 0; @@ -887,7 +887,7 @@ void Corpse::SetDecayTimer(uint32 decaytime) { bool Corpse::CanPlayerLoot(int charid) { uint8 looters = 0; - for(int i = 0; i < MAX_LOOTERS; i++) { + for (int i = 0; i < MAX_LOOTERS; i++) { if (allowed_looters[i] != 0){ looters++; } @@ -933,31 +933,49 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a return; } - if(being_looted_by == 0) { being_looted_by = 0xFFFFFFFF; } + if(being_looted_by == 0) { + being_looted_by = 0xFFFFFFFF; + } if(this->being_looted_by != 0xFFFFFFFF) { // lets double check.... Entity* looter = entity_list.GetID(this->being_looted_by); - if(looter == 0) { this->being_looted_by = 0xFFFFFFFF; } + if(looter == 0) { + this->being_looted_by = 0xFFFFFFFF; + } } - uint8 tCanLoot = 1; + uint8 Loot_Request_Type = 1; bool loot_coin = false; if(database.GetVariable("LootCoin", tmp, 9)) { loot_coin = (atoi(tmp) == 1); } - if(this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) { + if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) { SendLootReqErrorPacket(client, 0); - tCanLoot = 0; + Loot_Request_Type = 0; + } + else if (IsPlayerCorpse() && char_id == client->CharacterID()) { + Loot_Request_Type = 2; + } + else if ((IsNPCCorpse() || become_npc) && CanPlayerLoot(client->CharacterID())) { + Loot_Request_Type = 2; + } + else if (GetPKItem() == -1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot all items, variable cash */ + Loot_Request_Type = 3; + } + else if (GetPKItem() == 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 item, variable cash */ + Loot_Request_Type = 4; + } + else if (GetPKItem() > 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 set item, variable cash */ + Loot_Request_Type = 5; } - else if(IsPlayerCorpse() && char_id == client->CharacterID()) { tCanLoot = 2; } - else if((IsNPCCorpse() || become_npc) && CanPlayerLoot(client->CharacterID())) { tCanLoot = 2; } - else if(GetPKItem() == -1 && CanPlayerLoot(client->CharacterID())) { tCanLoot = 3; } //pvp loot all items, variable cash - else if(GetPKItem() == 1 && CanPlayerLoot(client->CharacterID())) { tCanLoot = 4; } //pvp loot 1 item, variable cash - else if(GetPKItem() > 1 && CanPlayerLoot(client->CharacterID())) { tCanLoot = 5; } //pvp loot 1 set item, variable cash - if(tCanLoot == 1) { if(client->Admin() < 100 || !client->GetGM()) { SendLootReqErrorPacket(client, 2); } } + if (Loot_Request_Type == 1) { + if (client->Admin() < 100 || !client->GetGM()) { + SendLootReqErrorPacket(client, 2); + } + } - if(tCanLoot >= 2 || (tCanLoot == 1 && client->Admin() >= 100 && client->GetGM())) { + 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)); moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer; @@ -965,8 +983,9 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a d->response = 1; d->unknown1 = 0x42; d->unknown2 = 0xef; - if(tCanLoot == 2 || (tCanLoot >= 3 && loot_coin)) { // dont take the coin off if it's a gm peeking at the corpse + /* Dont take the coin off if it's a gm peeking at the corpse */ + if(Loot_Request_Type == 2 || (Loot_Request_Type >= 3 && loot_coin)) { if(!IsPlayerCorpse() && client->IsGrouped() && client->AutoSplitEnabled() && client->GetGroup()) { d->copper = 0; d->silver = 0; @@ -990,7 +1009,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a outapp->priority = 6; client->QueuePacket(outapp); safe_delete(outapp); - if(tCanLoot == 5) { + if(Loot_Request_Type == 5) { int pkitem = GetPKItem(); const Item_Struct* item = database.GetItem(pkitem); ItemInst* inst = database.CreateItem(item, item->MaxCharges); @@ -1019,7 +1038,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 || tCanLoot>=3 || + if(!IsPlayerCorpse() || item_data->equip_slot <= MainCursor || item_data->equip_slot == MainPowerSource || Loot_Request_Type>=3 || (item_data->equip_slot >= 8000 && item_data->equip_slot <= 8999)) { if(i < corpselootlimit) { item = database.GetItem(item_data->item_id); @@ -1398,7 +1417,7 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) { } void Corpse::CompleteRezz(){ - rezzexp = 0; + rez_experience = 0; is_corpse_changed = true; this->Save(); } diff --git a/zone/corpse.h b/zone/corpse.h index 4f0e96d05..9fe6a899a 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -36,7 +36,7 @@ public: Corpse(Client* client, int32 in_rezexp); Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false); ~Corpse(); - static Corpse* LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard); + static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard); //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } @@ -109,7 +109,7 @@ public: char orgname[64]; uint32 GetEquipment(uint8 material_slot) const; // returns item id uint32 GetEquipmentColor(uint8 material_slot) const; - inline int GetRezzExp() { return rezzexp; } + inline int GetRezzExp() { return rez_experience; } // these are a temporary work-around until corpse inventory is removed from the database blob static int16 ServerToCorpseSlot(int16 server_slot); // encode @@ -119,30 +119,31 @@ protected: std::list MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot); private: - bool is_player_corpse; - bool is_corpse_changed; - bool is_locked; - int32 player_kill_item; - uint32 corpse_db_id; - uint32 char_id; - ItemList itemlist; - uint32 copper; + bool is_player_corpse; /* Determines if Player Corpse or not */ + bool is_corpse_changed; /* Determines if corpse has changed or not */ + bool is_locked; /* Determines if corpse is locked */ + int32 player_kill_item; /* Determines if Player Kill Item */ + uint32 corpse_db_id; /* Corpse Database ID (Player Corpse) */ + uint32 char_id; /* Character ID */ + ItemList itemlist; /* Internal Item list used for corpses */ + uint32 copper; uint32 silver; uint32 gold; uint32 platinum; - bool player_corpse_depop; - uint32 being_looted_by; - uint32 rezzexp; + bool player_corpse_depop; /* Sets up Corpse::Process to depop the player corpse */ + uint32 being_looted_by; /* Determines what the corpse is being looted by internally for logic */ + uint32 rez_experience; /* Amount of experience that the corpse would rez for */ bool rez; - bool can_rez; + bool can_corpse_be_rezzed; /* Bool declaring whether or not a corpse can be rezzed */ bool become_npc; - int allowed_looters[MAX_LOOTERS]; // People allowed to loot the corpse, character id - Timer corpse_decay_timer; - Timer corpse_res_timer; - Timer corpse_delay_timer; + int allowed_looters[MAX_LOOTERS]; /* People allowed to loot the corpse, character id */ + Timer corpse_decay_timer; /* The amount of time in millseconds in which a corpse will take to decay (Depop/Poof) */ + Timer corpse_res_timer; /* The amount of time in millseconds in which a corpse can be rezzed */ + Timer corpse_delay_timer; Timer corpse_graveyard_timer; - Timer loot_cooldown_timer; + Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */ Color_Struct item_tint[9]; + }; #endif diff --git a/zone/npc.h b/zone/npc.h index 71e6596ad..a88ae9176 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -359,8 +359,9 @@ public: const bool GetCombatEvent() const { return combat_event; } void SetCombatEvent(bool b) { combat_event = b; } - //The corpse we make can only be looted by people who got credit for the kill + /* Only allows players that killed corpse to loot */ const bool HasPrivateCorpse() const { return NPCTypedata->private_corpse; } + const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; } const char* GetRawNPCTypeName() const { return NPCTypedata->name; } diff --git a/zone/spells.cpp b/zone/spells.cpp index 69ded563c..bcd2150c6 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3806,7 +3806,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r void Corpse::CastRezz(uint16 spellid, Mob* Caster) { - _log(SPELLS__REZ, "Corpse::CastRezz spellid %i, Rezzed() is %i, rezzexp is %i", spellid,IsRezzed(),rezzexp); + _log(SPELLS__REZ, "Corpse::CastRezz spellid %i, Rezzed() is %i, rezzexp is %i", spellid,IsRezzed(),rez_experience); if(IsRezzed()){ if(Caster && Caster->IsClient()) @@ -3838,7 +3838,7 @@ void Corpse::CastRezz(uint16 spellid, Mob* Caster) rezz->unknown020 = 0x00000000; rezz->unknown088 = 0x00000000; // We send this to world, because it needs to go to the player who may not be in this zone. - worldserver.RezzPlayer(outapp, rezzexp, corpse_db_id, OP_RezzRequest); + worldserver.RezzPlayer(outapp, rez_experience, corpse_db_id, OP_RezzRequest); _pkt(SPELLS__REZ, outapp); safe_delete(outapp); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8794f3570..4ffd70625 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3784,7 +3784,7 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { - NewCorpse = Corpse::LoadFromDBData( + NewCorpse = Corpse::LoadCharacterCorpseEntity( atoll(row[0]), // uint32 in_dbid char_id, // uint32 in_charid row[1], // char* in_charname @@ -3826,7 +3826,7 @@ bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { - NewCorpse = Corpse::LoadFromDBData( + NewCorpse = Corpse::LoadCharacterCorpseEntity( atoll(row[0]), char_id, row[1], @@ -3871,7 +3871,7 @@ Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) { ); auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { - NewCorpse = Corpse::LoadFromDBData( + NewCorpse = Corpse::LoadCharacterCorpseEntity( atoll(row[0]), // id uint32 in_dbid atoll(row[1]), // charid uint32 in_charid row[2], // char_name @@ -3911,7 +3911,7 @@ bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) { // std::cout << row[9] << std::endl; entity_list.AddCorpse( - Corpse::LoadFromDBData( + Corpse::LoadCharacterCorpseEntity( atoll(row[0]), // id uint32 in_dbid atoll(row[1]), // charid uint32 in_charid row[2], // char_name From b43cfa126f455ae8727ebc6e2847c35d083059e2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 25 Nov 2014 23:54:59 -0600 Subject: [PATCH 13/96] Renamed SetPKItem to SetPlayerKillItemID Renamed AllowMobLoot to AllowPlayerLoot Renamed DepopCorpse (PC) to DepopPlayerCorpse Renamed GetPKItem to GetPlayerKillItem Renamed Corpse class variable 'orgname' to 'corpse_name' Renamed CompleteRezz to CompleteResurrection Renamed GetDBID to GetCorpseDBID Removed CorpseToServerSlot as it is unnecessary Removed ServerToCorpseSlot as it is unnecessary Reogrganized corpse.h header --- zone/attack.cpp | 24 ++--- zone/client_process.cpp | 2 +- zone/command.cpp | 4 +- zone/corpse.cpp | 179 +++++++----------------------------- zone/corpse.h | 124 +++++++++++++------------ zone/entity.cpp | 10 +- zone/lua_corpse.cpp | 4 +- zone/mob.cpp | 2 +- zone/perl_player_corpse.cpp | 6 +- zone/questmgr.cpp | 2 +- zone/spells.cpp | 2 +- zone/worldserver.cpp | 2 +- zone/zonedb.cpp | 4 +- 13 files changed, 131 insertions(+), 234 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 51b8bb26a..eec84e3c4 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1631,14 +1631,14 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att database.GetVariable("PvPitem", tmp2, 9); int pvpitem = atoi(tmp2); if(pvpitem>0 && pvpitem<200000) - new_corpse->SetPKItem(pvpitem); + new_corpse->SetPlayerKillItemID(pvpitem); } else if(reward==2) - new_corpse->SetPKItem(-1); + new_corpse->SetPlayerKillItemID(-1); else if(reward==1) - new_corpse->SetPKItem(1); + new_corpse->SetPlayerKillItemID(1); else - new_corpse->SetPKItem(0); + new_corpse->SetPlayerKillItemID(0); if(killerMob->CastToClient()->isgrouped) { Group* group = entity_list.GetGroupByClient(killerMob->CastToClient()); if(group != 0) @@ -1647,7 +1647,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att { if(group->members[i] != nullptr) { - new_corpse->AllowMobLoot(group->members[i],i); + new_corpse->AllowPlayerLoot(group->members[i],i); } } } @@ -2301,13 +2301,13 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack if(killer != 0 && emoteid != 0) corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid); if(killer != 0 && killer->IsClient()) { - corpse->AllowMobLoot(killer, 0); + corpse->AllowPlayerLoot(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); + corpse->AllowPlayerLoot(group->members[i],i); } } } @@ -2323,30 +2323,30 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack case 0: case 1: if(r->members[x].member && r->members[x].IsRaidLeader){ - corpse->AllowMobLoot(r->members[x].member, i); + corpse->AllowPlayerLoot(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); + corpse->AllowPlayerLoot(r->members[x].member, i); i++; } else if(r->members[x].member && r->members[x].IsGroupLeader){ - corpse->AllowMobLoot(r->members[x].member, i); + corpse->AllowPlayerLoot(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); + corpse->AllowPlayerLoot(r->members[x].member, i); i++; } break; case 4: if(r->members[x].member) { - corpse->AllowMobLoot(r->members[x].member, i); + corpse->AllowPlayerLoot(r->members[x].member, i); i++; } break; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index c4eb01f4a..c07a73aea 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -2174,7 +2174,7 @@ void Client::HandleRespawnFromHover(uint32 Option) _log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed."); corpse->IsRezzed(true); - corpse->CompleteRezz(); + corpse->CompleteResurrection(); } } else //Not rez diff --git a/zone/command.cpp b/zone/command.cpp index 27516d5a5..12241de52 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -3421,7 +3421,7 @@ void command_corpse(Client *c, const Seperator *sep) c->Message(0, "Error: Target must be a player corpse."); else if (c->Admin() >= commandEditPlayerCorpses && target->IsPlayerCorpse()) { c->Message(0, "Depoping %s.", target->GetName()); - target->CastToCorpse()->DepopCorpse(); + target->CastToCorpse()->DepopPlayerCorpse(); if(!sep->arg[2][0] || atoi(sep->arg[2]) != 0) target->CastToCorpse()->Bury(); } @@ -3906,7 +3906,7 @@ void command_save(Client *c, const Seperator *sep) } else if (c->GetTarget()->IsPlayerCorpse()) { if (c->GetTarget()->CastToMob()->Save()) - c->Message(0, "%s successfully saved. (dbid=%u)", c->GetTarget()->GetName(), c->GetTarget()->CastToCorpse()->GetDBID()); + c->Message(0, "%s successfully saved. (dbid=%u)", c->GetTarget()->GetName(), c->GetTarget()->CastToCorpse()->GetCorpseDBID()); else c->Message(0, "Manual save for %s failed.", c->GetTarget()->GetName()); } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 0b93306f1..40ecccf80 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -69,13 +69,12 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std: PlayerCorpse_Struct *pcs = (PlayerCorpse_Struct*)buffer; database.LoadCharacterCorpseData(in_dbid, pcs); - /* Load Items */ + /* Load Items */ ItemList itemlist; ServerLootItem_Struct* tmp = 0; for (unsigned int i = 0; i < pcs->itemcount; i++) { tmp = new ServerLootItem_Struct; memcpy(tmp, &pcs->items[i], sizeof(player_lootitem::ServerLootItem_Struct)); - tmp->equip_slot = CorpseToServerSlot(tmp->equip_slot); itemlist.push_back(tmp); } @@ -191,7 +190,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP 0 // uint32 in_scalerate ), corpse_decay_timer(in_decaytime), - corpse_res_timer(0), + corpse_rez_timer(0), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), corpse_graveyard_timer(0), loot_cooldown_timer(10) @@ -212,13 +211,13 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP SetCash(in_npc->GetCopper(), in_npc->GetSilver(), in_npc->GetGold(), in_npc->GetPlatinum()); npctype_id = in_npctypeid; - SetPKItem(0); + SetPlayerKillItemID(0); char_id = 0; corpse_db_id = 0; player_corpse_depop = false; - strcpy(orgname, in_npc->GetName()); + strcpy(corpse_name, in_npc->GetName()); strcpy(name, in_npc->GetName()); - // Added By Hogie + for(int count = 0; count < 100; count++) { if ((level >= npcCorpseDecayTimes[count].minlvl) && (level <= npcCorpseDecayTimes[count].maxlvl)) { corpse_decay_timer.SetTimer(npcCorpseDecayTimes[count].seconds*1000); @@ -293,7 +292,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( 0 // uint32 in_scalerate ), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), - corpse_res_timer(RuleI(Character, CorpseResTimeMS)), + corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)), loot_cooldown_timer(10) @@ -328,13 +327,13 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( gold = 0; platinum = 0; - strcpy(orgname, pp->name); + strcpy(corpse_name, pp->name); strcpy(name, pp->name); /* become_npc was not being initialized which led to some pretty funky things with newly created corpses */ become_npc = false; - SetPKItem(0); + SetPlayerKillItemID(0); /* Check Rule to see if we can leave corpses */ if(!RuleB(Character, LeaveNakedCorpses) || @@ -521,7 +520,7 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemLi 0, // uint8 in_maxlevel, 0), // uint32 in_scalerate corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), - corpse_res_timer(RuleI(Character, CorpseResTimeMS)), + corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)), loot_cooldown_timer(10) @@ -545,7 +544,7 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemLi itemlist = *in_itemlist; in_itemlist->clear(); - strcpy(orgname, in_charname); + strcpy(corpse_name, in_charname); strcpy(name, in_charname); this->copper = in_copper; @@ -558,7 +557,7 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemLi for (int i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; } - SetPKItem(0); + SetPlayerKillItemID(0); } Corpse::~Corpse() { @@ -636,17 +635,16 @@ bool Corpse::Save() { end = itemlist.end(); for (; cur != end; ++cur) { ServerLootItem_Struct* item = *cur; - item->equip_slot = ServerToCorpseSlot(item->equip_slot); // temp hack until corpse blobs are removed memcpy((char*)&dbpc->items[x++], (char*)item, sizeof(ServerLootItem_Struct)); } /* Create New Corpse*/ if (corpse_db_id == 0) { - corpse_db_id = database.SaveCharacterCorpse(char_id, orgname, zone->GetZoneID(), zone->GetInstanceID(), dbpc, x_pos, y_pos, z_pos, heading); + corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, x_pos, y_pos, z_pos, heading); } /* Update Corpse Data */ else{ - corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, orgname, zone->GetZoneID(), zone->GetInstanceID(), dbpc, x_pos, y_pos, z_pos, heading, IsRezzed()); + corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, x_pos, y_pos, z_pos, heading, IsRezzed()); } safe_delete_array(dbpc); @@ -670,12 +668,12 @@ void Corpse::Bury() { player_corpse_depop = true; } -void Corpse::Depop() { +void Corpse::DepopNPCCorpse() { if (IsNPCCorpse()) player_corpse_depop = true; } -void Corpse::DepopCorpse() { +void Corpse::DepopPlayerCorpse() { player_corpse_depop = true; } @@ -903,7 +901,7 @@ bool Corpse::CanPlayerLoot(int charid) { return false; } -void Corpse::AllowMobLoot(Mob *them, uint8 slot) { +void Corpse::AllowPlayerLoot(Mob *them, uint8 slot) { if(slot >= MAX_LOOTERS) return; if(them == nullptr || !them->IsClient()) @@ -959,13 +957,13 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a else if ((IsNPCCorpse() || become_npc) && CanPlayerLoot(client->CharacterID())) { Loot_Request_Type = 2; } - else if (GetPKItem() == -1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot all items, variable cash */ + else if (GetPlayerKillItem() == -1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot all items, variable cash */ Loot_Request_Type = 3; } - else if (GetPKItem() == 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 item, variable cash */ + else if (GetPlayerKillItem() == 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 item, variable cash */ Loot_Request_Type = 4; } - else if (GetPKItem() > 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 set item, variable cash */ + else if (GetPlayerKillItem() > 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 set item, variable cash */ Loot_Request_Type = 5; } @@ -1010,14 +1008,14 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a client->QueuePacket(outapp); safe_delete(outapp); if(Loot_Request_Type == 5) { - int pkitem = GetPKItem(); + int pkitem = GetPlayerKillItem(); const Item_Struct* item = database.GetItem(pkitem); ItemInst* inst = database.CreateItem(item, item->MaxCharges); if(inst) { client->SendItemPacket(EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } - else { client->Message(13, "Could not find item number %i to send!!", GetPKItem()); } + else { client->Message(13, "Could not find item number %i to send!!", GetPlayerKillItem()); } client->QueuePacket(app); return; @@ -1068,14 +1066,14 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(IsPlayerCorpse() && i == 0 && itemlist.size() > 0) { // somehow, player corpse contains items, but client doesn't see them... client->Message(13, "This corpse contains items that are inaccessable!"); client->Message(15, "Contact a GM for item replacement, if necessary."); - client->Message(15, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetDBID(), GetName(), itemlist.size()); + client->Message(15, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetCorpseDBID(), GetName(), itemlist.size()); cur = itemlist.begin(); end = itemlist.end(); for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; item = database.GetItem(item_data->item_id); - LogFile->write(EQEMuLog::Debug, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner"); + LogFile->write(EQEMuLog::Debug, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetCorpseDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner"); client->Message(0, "Inaccessable Corpse Item: %s", item->Name); } } @@ -1131,7 +1129,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { client->Message(13, "Error: Corpse locked by GM."); return; } - if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPKItem() == 0){ + if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPlayerKillItem() == 0){ client->Message(13, "Error: You cannot loot any more items from this corpse."); SendEndLootErrorPacket(client); being_looted_by = 0xFFFFFFFF; @@ -1142,17 +1140,17 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; memset(bag_item_data, 0, sizeof(bag_item_data)); - if (GetPKItem() > 1){ - item = database.GetItem(GetPKItem()); + if (GetPlayerKillItem() > 1){ + item = database.GetItem(GetPlayerKillItem()); } - else if (GetPKItem() == -1 || GetPKItem() == 1){ + 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 } else{ item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN, bag_item_data); } - if (GetPKItem()<=1 && item_data != 0) { + if (GetPlayerKillItem()<=1 && item_data != 0) { item = database.GetItem(item_data->item_id); } @@ -1191,7 +1189,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { char buf[88]; char corpse_name[64]; - strcpy(corpse_name, orgname); + strcpy(corpse_name, corpse_name); snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(corpse_name)); buf[87] = '\0'; std::vector args; @@ -1236,7 +1234,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } /* Remove Bag Contents */ - if (item->ItemClass == ItemClassContainer && (GetPKItem() != -1 || GetPKItem() != 1)) { + if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { for (int i = SUB_BEGIN; i < EmuConstants::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 */ @@ -1247,8 +1245,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } } - if (GetPKItem() != -1){ - SetPKItem(0); + if (GetPlayerKillItem() != -1){ + SetPlayerKillItemID(0); } /* Send message with item link to groups and such */ @@ -1361,7 +1359,7 @@ void Corpse::QueryLoot(Client* to) { } if (IsPlayerCorpse()) { - to->Message(0, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetDBID()); + to->Message(0, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetCorpseDBID()); } else { to->Message(0, "%i %s on %s.", y, y==1?"item":"items", this->GetName()); @@ -1416,7 +1414,7 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) { return true; } -void Corpse::CompleteRezz(){ +void Corpse::CompleteResurrection(){ rez_experience = 0; is_corpse_changed = true; this->Save(); @@ -1461,7 +1459,7 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { } void Corpse::AddLooter(Mob* who) { - for (int i=0; iCastToClient()->CharacterID(); break; @@ -1486,111 +1484,4 @@ void Corpse::LoadPlayerCorpseDecayTime(uint32 corpse_db_id){ else { corpse_graveyard_timer.SetTimer(3000); } -} - -/* -** Corpse slot translations are needed until corpse database blobs are converted -** -** To account for the addition of MainPowerSource, MainGeneral9 and MainGeneral10 into -** the contiguous possessions slot enumeration, the following designations will be used: -** -** Designatiom Server Corpse Offset -** -------------------------------------------------- -** MainCharm 0 0 0 -** ... ... ... 0 -** MainWaist 20 20 0 -** MainPowerSource 21 9999 +9978 -** MainAmmo 22 21 -1 -** -** MainGeneral1 23 22 -1 -** ... ... ... -1 -** MainGeneral8 30 29 -1 -** MainGeneral9 31 9997 +9966 -** MainGeneral10 32 9998 +9966 -** -** MainCursor 33 30 -3 -** -** MainGeneral1_1 251 251 0 -** ... ... ... 0 -** MainGeneral8_10 330 330 0 -** MainGeneral9_1 331 341 +10 -** ... ... ... +10 -** MainGeneral10_10 350 360 +10 -** -** MainCursor_1 351 331 -20 -** ... ... ... -20 -** MainCursor_10 360 340 -20 -** -** (Not all slot designations are valid to all clients..see ##_constants.h files for valid slot enumerations) -*/ -int16 Corpse::ServerToCorpseSlot(int16 server_slot) -{ - return server_slot; // temporary return - - /* - switch (server_slot) - { - case MainPowerSource: - return 9999; - case MainGeneral9: - return 9997; - case MainGeneral10: - return 9998; - case MainCursor: - return 30; - case MainAmmo: - case MainGeneral1: - case MainGeneral2: - case MainGeneral3: - case MainGeneral4: - case MainGeneral5: - case MainGeneral6: - case MainGeneral7: - case MainGeneral8: - return server_slot - 1; - default: - if (server_slot >= EmuConstants::CURSOR_BAG_BEGIN && server_slot <= EmuConstants::CURSOR_BAG_END) - return server_slot - 20; - else if (server_slot >= EmuConstants::GENERAL_BAGS_END - 19 && server_slot <= EmuConstants::GENERAL_BAGS_END) - return server_slot + 10; - else - return server_slot; - } - */ -} - -int16 Corpse::CorpseToServerSlot(int16 corpse_slot) -{ - return corpse_slot; // temporary return - - /* - switch (corpse_slot) - { - case 9999: - return MainPowerSource; - case 9997: - return MainGeneral9; - case 9998: - return MainGeneral10; - case 30: - return MainCursor; - case 21: // old SLOT_AMMO - case 22: // old PERSONAL_BEGIN - case 23: - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: // old PERSONAL_END - return corpse_slot + 1; - default: - if (corpse_slot >= 331 && corpse_slot <= 340) - return corpse_slot + 20; - else if (corpse_slot >= 341 && corpse_slot <= 360) - return corpse_slot - 10; - else - return corpse_slot; - } - */ } \ No newline at end of file diff --git a/zone/corpse.h b/zone/corpse.h index 9fe6a899a..3a3d2bce9 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -27,7 +27,7 @@ class NPC; #define MAX_LOOTERS 72 class Corpse : public Mob { -public: + public: static void SendEndLootErrorPacket(Client* client); static void SendLootReqErrorPacket(Client* client, uint8 response = 2); @@ -35,85 +35,91 @@ public: Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000); Corpse(Client* client, int32 in_rezexp); Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false); - ~Corpse(); + + ~Corpse(); static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard); - //abstract virtual function implementations requird by base abstract class + /* 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 bool HasRaid() { return false; } - virtual bool HasGroup() { return false; } - virtual Raid* GetRaid() { return 0; } - virtual Group* GetGroup() { return 0; } - - void LoadPlayerCorpseDecayTime(uint32 dbid); - + virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, + bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { + return false; + } + virtual bool HasRaid() { return false; } + virtual bool HasGroup() { return false; } + virtual Raid* GetRaid() { return 0; } + virtual Group* GetGroup() { return 0; } + inline uint32 GetCorpseDBID() { return corpse_db_id; } + inline char* GetOwnerName() { return corpse_name; } + bool IsEmpty() const; bool IsCorpse() const { return true; } bool IsPlayerCorpse() const { return is_player_corpse; } bool IsNPCCorpse() const { return !is_player_corpse; } bool IsBecomeNPCCorpse() const { return become_npc; } + virtual void DepopNPCCorpse(); + virtual void DepopPlayerCorpse(); bool Process(); bool Save(); - uint32 GetCharID() { return char_id; } - uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; }; - uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); } - uint32 GetResTime() { if (!corpse_res_timer.Enabled()) return 0; else return corpse_res_timer.GetRemainingTime(); } + uint32 GetCharID() { return char_id; } + uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; }; + uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); } + uint32 GetRezTime() { if (!corpse_rez_timer.Enabled()) return 0; else return corpse_rez_timer.GetRemainingTime(); } + void SetDecayTimer(uint32 decay_time); + + void Delete(); + void Bury(); void CalcCorpseName(); - inline void Lock() { is_locked = true; } - inline void UnLock() { is_locked = false; } - inline bool IsLocked() { return is_locked; } - inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; } - inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); } - inline uint32 GetDBID() { return corpse_db_id; } - inline char* GetOwnerName() { return orgname;} + void LoadPlayerCorpseDecayTime(uint32 dbid); - void SetDecayTimer(uint32 decay_time); - bool IsEmpty() const; - void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0); + /* Corpse: Items */ uint32 GetWornItem(int16 equipSlot) const; - ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0); - void RemoveItem(uint16 lootslot); - void RemoveItem(ServerLootItem_Struct* item_data); - void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum); - void RemoveCash(); - void QueryLoot(Client* to); - uint32 CountItems(); - void Delete(); - void Bury(); - virtual void Depop(); - virtual void DepopCorpse(); - + ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0); + void SetPlayerKillItemID(int32 pk_item_id) { player_kill_item = pk_item_id; } + int32 GetPlayerKillItem() { return player_kill_item; } + void RemoveItem(uint16 lootslot); + void RemoveItem(ServerLootItem_Struct* item_data); + void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0); + + /* Corpse: Coin */ + void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum); + void RemoveCash(); uint32 GetCopper() { return copper; } uint32 GetSilver() { return silver; } uint32 GetGold() { return gold; } uint32 GetPlatinum() { return platinum; } - void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); - void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app); - void LootItem(Client* client, const EQApplicationPacket* app); - void EndLoot(Client* client, const EQApplicationPacket* app); - bool Summon(Client* client, bool spell, bool CheckDistance); - void CastRezz(uint16 spellid, Mob* Caster); - void CompleteRezz(); - void SetPKItem(int32 id) { player_kill_item = id; } - int32 GetPKItem() { return player_kill_item; } - bool CanPlayerLoot(int charid); - void AllowMobLoot(Mob *them, uint8 slot); - void AddLooter(Mob *who); + /* Corpse: Resurrection */ bool IsRezzed() { return rez; } void IsRezzed(bool in_rez) { rez = in_rez; } - void Spawn(); + void CastRezz(uint16 spellid, Mob* Caster); + void CompleteResurrection(); - char orgname[64]; - uint32 GetEquipment(uint8 material_slot) const; // returns item id + /* Corpse: Loot */ + void QueryLoot(Client* to); + void LootItem(Client* client, const EQApplicationPacket* app); + void EndLoot(Client* client, const EQApplicationPacket* app); + void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app); + void AllowPlayerLoot(Mob *them, uint8 slot); + void AddLooter(Mob *who); + uint32 CountItems(); + bool CanPlayerLoot(int charid); + + inline void Lock() { is_locked = true; } + inline void UnLock() { is_locked = false; } + inline bool IsLocked() { return is_locked; } + inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; } + inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); } + + /* Mob */ + void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); + bool Summon(Client* client, bool spell, bool CheckDistance); + void Spawn(); + + char corpse_name[64]; + uint32 GetEquipment(uint8 material_slot) const; uint32 GetEquipmentColor(uint8 material_slot) const; - inline int GetRezzExp() { return rez_experience; } - - // these are a temporary work-around until corpse inventory is removed from the database blob - static int16 ServerToCorpseSlot(int16 server_slot); // encode - static int16 CorpseToServerSlot(int16 corpse_slot); // decode + inline int GetRezExp() { return rez_experience; } protected: std::list MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot); @@ -138,7 +144,7 @@ private: bool become_npc; int allowed_looters[MAX_LOOTERS]; /* People allowed to loot the corpse, character id */ Timer corpse_decay_timer; /* The amount of time in millseconds in which a corpse will take to decay (Depop/Poof) */ - Timer corpse_res_timer; /* The amount of time in millseconds in which a corpse can be rezzed */ + Timer corpse_rez_timer; /* The amount of time in millseconds in which a corpse can be rezzed */ Timer corpse_delay_timer; Timer corpse_graveyard_timer; Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */ diff --git a/zone/entity.cpp b/zone/entity.cpp index 122e24582..eef15b2ff 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1606,7 +1606,7 @@ Corpse *EntityList::GetCorpseByDBID(uint32 dbid) { auto it = corpse_list.begin(); while (it != corpse_list.end()) { - if (it->second->GetDBID() == dbid) + if (it->second->GetCorpseDBID() == dbid) return it->second; ++it; } @@ -1660,7 +1660,7 @@ void EntityList::RemoveCorpseByDBID(uint32 dbid) { auto it = corpse_list.begin(); while (it != corpse_list.end()) { - if (it->second->GetDBID() == dbid) { + if (it->second->GetCorpseDBID() == dbid) { safe_delete(it->second); free_ids.push(it->first); it = corpse_list.erase(it); @@ -1677,9 +1677,9 @@ int EntityList::RezzAllCorpsesByCharID(uint32 charid) auto it = corpse_list.begin(); while (it != corpse_list.end()) { if (it->second->GetCharID() == charid) { - RezzExp += it->second->GetRezzExp(); + RezzExp += it->second->GetRezExp(); it->second->IsRezzed(true); - it->second->CompleteRezz(); + it->second->CompleteResurrection(); } ++it; } @@ -2655,7 +2655,7 @@ int32 EntityList::DeleteNPCCorpses() auto it = corpse_list.begin(); while (it != corpse_list.end()) { if (it->second->IsNPCCorpse()) { - it->second->Depop(); + it->second->DepopNPCCorpse(); x++; } ++it; diff --git a/zone/lua_corpse.cpp b/zone/lua_corpse.cpp index 5862bbe96..789555a54 100644 --- a/zone/lua_corpse.cpp +++ b/zone/lua_corpse.cpp @@ -39,7 +39,7 @@ void Lua_Corpse::ResetLooter() { uint32 Lua_Corpse::GetDBID() { Lua_Safe_Call_Int(); - return self->GetDBID(); + return self->GetCorpseDBID(); } bool Lua_Corpse::IsRezzed() { @@ -119,7 +119,7 @@ bool Lua_Corpse::CanMobLoot(int charid) { void Lua_Corpse::AllowMobLoot(Lua_Mob them, uint8 slot) { Lua_Safe_Call_Void(); - self->AllowMobLoot(them, slot); + self->AllowPlayerLoot(them, slot); } bool Lua_Corpse::Summon(Lua_Client client, bool spell, bool checkdistance) { diff --git a/zone/mob.cpp b/zone/mob.cpp index a7d141b30..55c3773c1 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1255,7 +1255,7 @@ void Mob::ShowStats(Client* client) } else if (IsCorpse()) { if (IsPlayerCorpse()) { - client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetDBID()); + client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetCorpseDBID()); } else { client->Message(0, " NPCCorpse", GetID()); diff --git a/zone/perl_player_corpse.cpp b/zone/perl_player_corpse.cpp index f8b2d4388..675ee9697 100644 --- a/zone/perl_player_corpse.cpp +++ b/zone/perl_player_corpse.cpp @@ -208,7 +208,7 @@ XS(XS_Corpse_GetDBID) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->GetDBID(); + RETVAL = THIS->GetCorpseDBID(); XSprePUSH; PUSHu((UV)RETVAL); } XSRETURN(1); @@ -662,7 +662,7 @@ XS(XS_Corpse_CompleteRezz) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - THIS->CompleteRezz(); + THIS->CompleteResurrection(); } XSRETURN_EMPTY; } @@ -723,7 +723,7 @@ XS(XS_Corpse_AllowMobLoot) if(them == nullptr) Perl_croak(aTHX_ "them is nullptr, avoiding crash."); - THIS->AllowMobLoot(them, slot); + THIS->AllowPlayerLoot(them, slot); } XSRETURN_EMPTY; } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index e014c01cd..458a448d9 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1786,7 +1786,7 @@ bool QuestManager::buryplayercorpse(uint32 char_id) if(corpse) { corpse->Save(); - corpse->DepopCorpse(); + corpse->DepopPlayerCorpse(); } else { diff --git a/zone/spells.cpp b/zone/spells.cpp index bcd2150c6..858bb6412 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3825,7 +3825,7 @@ void Corpse::CastRezz(uint16 spellid, Mob* Caster) EQApplicationPacket* 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->orgname,30); + memcpy(rezz->your_name,this->corpse_name,30); memcpy(rezz->corpse_name,this->name,30); memcpy(rezz->rezzer_name,Caster->GetName(),30); rezz->zone_id = zone->GetZoneID(); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index bae01e70f..d51cb0904 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -705,7 +705,7 @@ void WorldServer::Process() { _log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed."); // I don't know why Rezzed is not set to true in CompleteRezz(). corpse->IsRezzed(true); - corpse->CompleteRezz(); + corpse->CompleteResurrection(); } } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 4ffd70625..7c2c04550 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3652,7 +3652,7 @@ uint32 ZoneDatabase::GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid) { if (tmp) { itemid = tmp->GetWornItem(slotid); - tmp->DepopCorpse(); + tmp->DepopPlayerCorpse(); } return itemid; } @@ -3800,7 +3800,7 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z entity_list.AddCorpse(NewCorpse); NewCorpse->SetDecayTimer(RuleI(Character, CorpseDecayTimeMS)); NewCorpse->Spawn(); - if (!UnburyCharacterCorpse(NewCorpse->GetDBID(), dest_zone_id, dest_instance_id, dest_x, dest_y, dest_z, dest_heading)) + if (!UnburyCharacterCorpse(NewCorpse->GetCorpseDBID(), dest_zone_id, dest_instance_id, dest_x, dest_y, dest_z, dest_heading)) LogFile->write(EQEMuLog::Error, "Unable to unbury a summoned player corpse for character id %u.", char_id); } } From 08e787da59bd40016246dd7b1d1f7def75d701c0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 26 Nov 2014 00:24:31 -0600 Subject: [PATCH 14/96] Replaced atoll with more appropriate macro atoul --- zone/zonedb.cpp | 64 ++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 7c2c04550..8bc696888 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3372,7 +3372,7 @@ uint32 ZoneDatabase::GetCharacterCorpseDecayTimer(uint32 corpse_db_id){ auto results = QueryDatabase(query); auto row = results.begin(); if (results.Success() && results.RowsAffected() != 0){ - return atoll(row[0]); + return atoul(row[0]); } return 0; } @@ -3628,7 +3628,7 @@ uint32 ZoneDatabase::GetCharacterCorpseID(uint32 char_id, uint8 corpse) { for (auto row = results.begin(); row != results.end(); ++row) { for (int i = 0; i < corpse; i++) { - return atoll(row[0]); + return atoul(row[0]); } } return 0; @@ -3702,7 +3702,7 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct uint16 i = 0; for (auto row = results.begin(); row != results.end(); ++row) { pcs->locked = atoi(row[i++]); // is_locked, - pcs->exp = atoll(row[i++]); // exp, + pcs->exp = atoul(row[i++]); // exp, pcs->size = atoi(row[i++]); // size, pcs->level = atoi(row[i++]); // `level`, pcs->race = atoi(row[i++]); // race, @@ -3711,10 +3711,10 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct pcs->deity = atoi(row[i++]); // deity, pcs->texture = atoi(row[i++]); // texture, pcs->helmtexture = atoi(row[i++]); // helm_texture, - pcs->copper = atoll(row[i++]); // copper, - pcs->silver = atoll(row[i++]); // silver, - pcs->gold = atoll(row[i++]); // gold, - pcs->plat = atoll(row[i++]); // platinum, + pcs->copper = atoul(row[i++]); // copper, + pcs->silver = atoul(row[i++]); // silver, + pcs->gold = atoul(row[i++]); // gold, + pcs->plat = atoul(row[i++]); // platinum, pcs->haircolor = atoi(row[i++]); // hair_color, pcs->beardcolor = atoi(row[i++]); // beard_color, pcs->eyecolor1 = atoi(row[i++]); // eye_color_1, @@ -3722,18 +3722,18 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct pcs->hairstyle = atoi(row[i++]); // hair_style, pcs->face = atoi(row[i++]); // face, pcs->beard = atoi(row[i++]); // beard, - pcs->drakkin_heritage = atoll(row[i++]); // drakkin_heritage, - pcs->drakkin_tattoo = atoll(row[i++]); // drakkin_tattoo, - pcs->drakkin_details = atoll(row[i++]); // drakkin_details, - pcs->item_tint[0].color = atoll(row[i++]); // wc_1, - pcs->item_tint[1].color = atoll(row[i++]); // wc_2, - pcs->item_tint[2].color = atoll(row[i++]); // wc_3, - pcs->item_tint[3].color = atoll(row[i++]); // wc_4, - pcs->item_tint[4].color = atoll(row[i++]); // wc_5, - pcs->item_tint[5].color = atoll(row[i++]); // wc_6, - pcs->item_tint[6].color = atoll(row[i++]); // wc_7, - pcs->item_tint[7].color = atoll(row[i++]); // wc_8, - pcs->item_tint[8].color = atoll(row[i++]); // wc_9 + 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 } query = StringFormat( "SELECT \n" @@ -3749,7 +3749,6 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct "FROM \n" "character_corpse_items \n" "WHERE `corpse_id` = %u\n" - // "ORDER BY `equip_slot`" , corpse_id ); @@ -3761,7 +3760,7 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct for (auto row = results.begin(); row != results.end(); ++row) { memset(&pcs->items[i], 0, sizeof (player_lootitem::ServerLootItem_Struct)); pcs->items[i].equip_slot = atoi(row[r++]); // equip_slot, - pcs->items[i].item_id = atoll(row[r++]); // item_id, + pcs->items[i].item_id = atoul(row[r++]); // item_id, pcs->items[i].charges = atoi(row[r++]); // charges, pcs->items[i].aug_1 = atoi(row[r++]); // aug_1, pcs->items[i].aug_2 = atoi(row[r++]); // aug_2, @@ -3785,7 +3784,7 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z for (auto row = results.begin(); row != results.end(); ++row) { NewCorpse = Corpse::LoadCharacterCorpseEntity( - atoll(row[0]), // uint32 in_dbid + atoul(row[0]), // uint32 in_dbid char_id, // uint32 in_charid row[1], // char* in_charname dest_x, // float in_x @@ -3827,7 +3826,7 @@ bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id for (auto row = results.begin(); row != results.end(); ++row) { NewCorpse = Corpse::LoadCharacterCorpseEntity( - atoll(row[0]), + atoul(row[0]), char_id, row[1], dest_x, @@ -3872,8 +3871,8 @@ Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) { auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { NewCorpse = Corpse::LoadCharacterCorpseEntity( - atoll(row[0]), // id uint32 in_dbid - atoll(row[1]), // charid uint32 in_charid + atoul(row[0]), // id uint32 in_dbid + atoul(row[1]), // charid uint32 in_charid row[2], // char_name atof(row[3]), // x float in_x atof(row[4]), // y float in_y @@ -3899,21 +3898,10 @@ bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) { auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { - // std::cout << row[0] << std::endl; - // std::cout << row[1] << std::endl; - // std::cout << row[2] << std::endl; - // std::cout << row[3] << std::endl; - // std::cout << row[4] << std::endl; - // std::cout << row[5] << std::endl; - // std::cout << row[6] << std::endl; - // std::cout << row[7] << std::endl; - // std::cout << row[8] << std::endl; - // std::cout << row[9] << std::endl; - entity_list.AddCorpse( Corpse::LoadCharacterCorpseEntity( - atoll(row[0]), // id uint32 in_dbid - atoll(row[1]), // charid uint32 in_charid + atoul(row[0]), // id uint32 in_dbid + atoul(row[1]), // charid uint32 in_charid row[2], // char_name atof(row[3]), // x float in_x atof(row[4]), // y float in_y From 5c5cde7fe57b4fc2ec826e73a3b4b9bcd11b8c47 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 26 Nov 2014 00:31:50 -0600 Subject: [PATCH 15/96] Database::GetGroupLeaderForLogin fix --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index 241c4d171..82931e457 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -3254,7 +3254,7 @@ char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf) { strcpy(leaderbuf, ""); uint32 group_id = 0; - std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name = '%s'", name); + std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) From daec5bde662dcb6b9241e14b802c91f64be4358a Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Wed, 26 Nov 2014 13:57:18 -0800 Subject: [PATCH 16/96] Item Transformation now works! --- common/item.cpp | 56 +++++++++++++++++++ common/item.h | 7 +++ common/patches/rof.cpp | 10 ++++ common/patches/underfoot.cpp | 6 ++ common/ruletypes.h | 2 + common/shareddb.cpp | 27 +++++++-- .../2014_11_26_TransformationRules.sql | 3 + .../2014_11_26_InventoryTableUpdate.sql | 4 ++ world/worlddb.cpp | 3 + zone/client.cpp | 18 +++++- zone/client.h | 2 +- zone/client_packet.cpp | 4 ++ zone/inventory.cpp | 7 ++- zone/mob.cpp | 3 + zone/string_ids.h | 2 + zone/tradeskills.cpp | 20 +++++++ 16 files changed, 166 insertions(+), 8 deletions(-) create mode 100644 utils/sql/git/optional/2014_11_26_TransformationRules.sql create mode 100644 utils/sql/git/required/2014_11_26_InventoryTableUpdate.sql diff --git a/common/item.cpp b/common/item.cpp index e59edebe3..ca469aa6e 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1412,6 +1412,8 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) { m_scaledItem = nullptr; m_evolveInfo = nullptr; m_scaling = false; + m_ornamenticon = 0; + m_ornamentidfile = 0; } ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { @@ -1434,6 +1436,8 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { m_scaledItem = nullptr; m_evolveInfo = nullptr; m_scaling = false; + m_ornamenticon = 0; + m_ornamentidfile = 0; } ItemInst::ItemInst(ItemInstTypes use_type) { @@ -1451,6 +1455,8 @@ ItemInst::ItemInst(ItemInstTypes use_type) { m_scaledItem = nullptr; m_evolveInfo = nullptr; m_scaling = false; + m_ornamenticon = 0; + m_ornamentidfile = 0; } // Make a copy of an ItemInst object @@ -1501,6 +1507,8 @@ ItemInst::ItemInst(const ItemInst& copy) m_evolveInfo = nullptr; m_scaling = copy.m_scaling; + m_ornamenticon = copy.m_ornamenticon; + m_ornamentidfile = copy.m_ornamentidfile; } // Clean up container contents @@ -1789,6 +1797,54 @@ ItemInst* ItemInst::GetOrnamentationAug(int ornamentationAugtype) const return nullptr; } +bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll) { + if (!ItemToTry || !Container) return false; + + if (ItemToTry->ItemType == ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) + return false; + + if (AllowAll && Container->CharmFile != "ITEMTRANSFIGSHIELD" && Container->CharmFile != "ITEMTransfigBow") { + switch (ItemToTry->ItemType) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 35: + case 45: + return true; + } + } + + static std::map types = { + { "ITEMTransfig1HP", 2 }, + { "ITEMTransfig1HS", 0 }, + { "ITEMTransfig2HB", 4 }, + { "ITEMTransfig2HP", 35 }, + { "ITEMTransfig2HS", 1 }, + { "ITEMTransfigBlunt", 3 }, + { "ITEMTransfigBow", 5 }, + { "ITEMTransfigHTH", 45 }, + { "ITEMTRANSFIGSHIELD", 8 }, + { "ITEMTransfigSlashing", 0 } + }; + + auto i = types.find(Container->CharmFile); + if (i != types.end() && i->second == ItemToTry->ItemType) + return true; + + static std::map typestwo = { + { "ITEMTransfigBlunt", 4 }, + { "ITEMTransfigSlashing", 1 } + }; + + i = typestwo.find(Container->CharmFile); + if (i != typestwo.end() && i->second == ItemToTry->ItemType) + return true; + + return false; +} + uint32 ItemInst::GetAugmentItemID(uint8 slot) const { uint32 id = NO_ITEM; diff --git a/common/item.h b/common/item.h index e6d1e8bee..cce166eb0 100644 --- a/common/item.h +++ b/common/item.h @@ -330,6 +330,7 @@ public: ItemInst* RemoveAugment(uint8 index); bool IsAugmented(); ItemInst* GetOrnamentationAug(int ornamentationAugtype) const; + static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false); // Has attack/delay? bool IsWeapon() const; @@ -392,6 +393,10 @@ public: void SetActivated(bool activated) { m_activated = activated; } int8 GetEvolveLvl() const { return m_evolveLvl; } void SetScaling(bool v) { m_scaling = v; } + uint32 GetOrnamentationIcon() const { return m_ornamenticon; } + void SetOrnamentIcon(uint32 ornament_icon) { m_ornamenticon = ornament_icon; } + uint32 GetOrnamentationIDFile() const { return m_ornamentidfile; } + void SetOrnamentationIDFile(uint32 ornament_idfile) { m_ornamentidfile = ornament_idfile; } void Initialize(SharedDatabase *db = nullptr); void ScaleItem(); @@ -436,6 +441,8 @@ protected: Item_Struct* m_scaledItem; EvolveInfo* m_evolveInfo; bool m_scaling; + uint32 m_ornamenticon; + uint32 m_ornamentidfile; // // Items inside of this item (augs or contents); diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 092101d7d..c7efe0264 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -4888,6 +4888,16 @@ namespace RoF //Icon ornaIcon = aug_weap->Icon; } + else 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)); + ornaIcon = inst->GetOrnamentationIcon(); + } else { ss.write((const char*)&null_term, sizeof(uint8)); //no mh ss.write((const char*)&null_term, sizeof(uint8));//no of diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index adc4ed6e3..c9d726a25 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -3664,6 +3664,12 @@ namespace Underfoot ss.write((const char*)&null_term, sizeof(uint8)); ornaIcon = aug_weap->Icon; } + 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(); + } else { ss.write((const char*)&null_term, sizeof(uint8)); //no idfile } diff --git a/common/ruletypes.h b/common/ruletypes.h index 052571d82..b3e9b4f1c 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -586,6 +586,8 @@ 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_CATEGORY_END() RULE_CATEGORY( Client ) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index d543db87f..05c7b6962 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -199,14 +199,14 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i // Update/Insert item std::string query = StringFormat("REPLACE INTO inventory " "(charid, slotid, itemid, charges, instnodrop, custom_data, color, " - "augslot1, augslot2, augslot3, augslot4, augslot5) " + "augslot1, augslot2, augslot3, augslot4, augslot5, ornamenticon, ornamentidfile) " "VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, " - "%lu, %lu, %lu, %lu, %lu)", + "%lu, %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]); + (unsigned long)augslot[3],(unsigned long)augslot[4], (unsigned long)inst->GetOrnamentationIcon(), (unsigned long)inst->GetOrnamentationIDFile()); auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents @@ -488,7 +488,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) { bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { // Retrieve character inventory std::string query = StringFormat("SELECT slotid, itemid, charges, color, augslot1, " - "augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data " + "augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data, ornamenticon, ornamentidfile " "FROM inventory WHERE charid = %i ORDER BY slotid", char_id); auto results = QueryDatabase(query); if (!results.Success()) { @@ -513,6 +513,9 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { bool instnodrop = (row[9] && (uint16)atoi(row[9]))? true: false; + uint32 ornament_icon = (uint32)atoul(row[11]); + uint32 ornament_idfile = (uint32)atoul(row[12]); + const Item_Struct* item = GetItem(item_id); if (!item) { @@ -549,6 +552,11 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { value.push_back(v); } } + if (ornament_icon > 0) + inst->SetOrnamentIcon(ornament_icon); + + if (ornament_idfile > 0) + inst->SetOrnamentationIDFile(ornament_idfile); if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == MainPowerSource) && inst->GetItem()->Attuneable)) inst->SetInstNoDrop(true); @@ -591,7 +599,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) { // Retrieve character inventory std::string query = StringFormat("SELECT slotid, itemid, charges, color, augslot1, " - "augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data " + "augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data, ornamenticon, ornamentidfile " "FROM inventory INNER JOIN character_data ch " "ON ch.id = charid WHERE ch.name = '%s' AND ch.account_id = %i ORDER BY slotid", name, account_id); @@ -617,6 +625,9 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) aug[4] = (uint32)atoi(row[8]); bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; + uint32 ornament_icon = (uint32)atoul(row[11]); + uint32 ornament_idfile = (uint32)atoul(row[12]); + const Item_Struct* item = GetItem(item_id); int16 put_slot_id = INVALID_INDEX; if(!item) @@ -651,6 +662,12 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) } } + + if (ornament_icon > 0) + inst->SetOrnamentIcon(ornament_icon); + + if (ornament_idfile > 0) + inst->SetOrnamentationIDFile(ornament_idfile); if (color > 0) inst->SetColor(color); diff --git a/utils/sql/git/optional/2014_11_26_TransformationRules.sql b/utils/sql/git/optional/2014_11_26_TransformationRules.sql new file mode 100644 index 000000000..d31b6b26e --- /dev/null +++ b/utils/sql/git/optional/2014_11_26_TransformationRules.sql @@ -0,0 +1,3 @@ +--Optional Transformation Rules +INSERT INTO `rule_values` VALUES (1, 'Inventory:DeleteTransformationMold', 'true', 'false to keep transformation mold forever'); +INSERT INTO `rule_values` VALUES (1, 'Inventory:AllowAnyWeaponTransformation', 'false', 'True allows any MELEE weapon to use the other melee type transformatios'); diff --git a/utils/sql/git/required/2014_11_26_InventoryTableUpdate.sql b/utils/sql/git/required/2014_11_26_InventoryTableUpdate.sql new file mode 100644 index 000000000..ca25e4e2d --- /dev/null +++ b/utils/sql/git/required/2014_11_26_InventoryTableUpdate.sql @@ -0,0 +1,4 @@ +--Inventory table update +ALTER TABLE `inventory` + ADD COLUMN `ornamenticon` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `custom_data`, + ADD COLUMN `ornamentidfile` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `ornamenticon`; \ No newline at end of file diff --git a/world/worlddb.cpp b/world/worlddb.cpp index cd01e01b2..458025349 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -197,6 +197,9 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* if (item->GetOrnamentationAug(ornamentationAugtype)) { idfile = atoi(&item->GetOrnamentationAug(ornamentationAugtype)->GetItem()->IDFile[2]); } + else if (item->GetOrnamentationIcon() && item->GetOrnamentationIDFile()) { + idfile = item->GetOrnamentationIDFile(); + } else { idfile = atoi(&item->GetItem()->IDFile[2]); } diff --git a/zone/client.cpp b/zone/client.cpp index 9541959ba..7ceb12496 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1889,6 +1889,9 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) if (strlen(item->IDFile) > 2) ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]); } + else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { + ns->spawn.equipment[MaterialPrimary] = inst->GetOrnamentationIDFile(); + } else { item = inst->GetItem(); if (strlen(item->IDFile) > 2) @@ -1901,6 +1904,9 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) if (strlen(item->IDFile) > 2) ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]); } + else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { + ns->spawn.equipment[MaterialSecondary] = inst->GetOrnamentationIDFile(); + } else { item = inst->GetItem(); if (strlen(item->IDFile) > 2) @@ -2766,6 +2772,9 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); m_pp.item_material[MaterialPrimary] = atoi(item->IDFile + 2); } + else if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { + m_pp.item_material[MaterialPrimary] = inst->GetOrnamentationIDFile(); + } else { m_pp.item_material[MaterialPrimary] = atoi(item->IDFile + 2); } @@ -2776,6 +2785,9 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2); } + else if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { + m_pp.item_material[MaterialSecondary] = inst->GetOrnamentationIDFile(); + } else { m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2); } @@ -5832,7 +5844,11 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); strcpy(insr->itemnames[L], item->Name); insr->itemicons[L] = aug_weap->Icon; - } + } + else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { + strcpy(insr->itemnames[L], item->Name); + insr->itemicons[L] = inst->GetOrnamentationIcon(); + } else { strcpy(insr->itemnames[L], item->Name); insr->itemicons[L] = item->Icon; diff --git a/zone/client.h b/zone/client.h index dcf665bab..4c69917fd 100644 --- a/zone/client.h +++ b/zone/client.h @@ -810,7 +810,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, bool attuned = false, uint16 to_slot = MainCursor); + bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, bool attuned = false, uint16 to_slot = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 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_packet.cpp b/zone/client_packet.cpp index 000ed8fcc..a12247cc6 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8031,6 +8031,10 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) strcpy(insr->itemnames[L], item->Name); insr->itemicons[L] = aug_weap->Icon; } + else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { + strcpy(insr->itemnames[L], item->Name); + insr->itemicons[L] = inst->GetOrnamentationIcon(); + } else { strcpy(insr->itemnames[L], item->Name); insr->itemicons[L] = item->Icon; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 76b077e2d..a7f61819e 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -199,7 +199,7 @@ bool Client::CheckLoreConflict(const Item_Struct* item) { return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != INVALID_INDEX); } -bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) { +bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot, uint32 ornament_icon, uint32 ornament_idfile) { this->EVENT_ITEM_ScriptStopReturn(); // TODO: update calling methods and script apis to handle a failure return @@ -557,6 +557,11 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // attune item if(attuned && inst->GetItem()->Attuneable) inst->SetInstNoDrop(true); + + if(ornament_icon > 0 && ornament_idfile > 0) { + inst->SetOrnamentIcon(ornament_icon); + inst->SetOrnamentationIDFile(ornament_idfile); + } // check to see if item is usable in requested slot if(enforceusable && (((to_slot >= MainCharm) && (to_slot <= MainAmmo)) || (to_slot == MainPowerSource))) { diff --git a/zone/mob.cpp b/zone/mob.cpp index 15fb731e2..35a019252 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2455,6 +2455,9 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); return atoi(&item->IDFile[2]); } + else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { + return inst->GetOrnamentationIDFile(); + } else { if (strlen(item->IDFile) > 2) return atoi(&item->IDFile[2]); diff --git a/zone/string_ids.h b/zone/string_ids.h index 5375c2d7d..044dd215f 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -296,6 +296,8 @@ #define GUILD_BANK_FULL 6098 // There is no more room in the Guild Bank. #define GUILD_BANK_TRANSFERRED 6100 // '%1' transferred to Guild Bank from Deposits. #define GUILD_BANK_EMPTY_HANDS 6108 // You must empty your hands to withdraw from the Guild Bank. +#define TRANSFORM_FAILED 6326 //This mold cannot be applied to your %1. +#define TRANSFORM_COMPLETE 6327 //You have successfully transformed your %1. #define GENERIC_STRING 6688 //%1 (used to any basic message) #define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel. #define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel. diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index c7ac3339e..e9de6c4a6 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -283,6 +283,26 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } container = inst; + if (container->GetItem()->BagType == 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(); + 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->IsInstNoDrop(), MainCursor, 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); + } + else if (inst) { + user->Message_StringID(4, TRANSFORM_FAILED, inst->GetItem()->Name); + } + EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); + return; + } DBTradeskillRecipe_Struct spec; if (!database.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) { From c5c778f575b39d693e132bc9786d06bfd559170b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 26 Nov 2014 18:29:07 -0500 Subject: [PATCH 17/96] Minor bug fixes --- common/item.cpp | 30 +++++++++---------- .../2014_11_26_InventoryTableUpdate.sql | 4 +-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/common/item.cpp b/common/item.cpp index ca469aa6e..f23d87665 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1803,7 +1803,7 @@ bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Con if (ItemToTry->ItemType == ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) return false; - if (AllowAll && Container->CharmFile != "ITEMTRANSFIGSHIELD" && Container->CharmFile != "ITEMTransfigBow") { + if (AllowAll && !strncasecmp(Container->CharmFile, "ITEMTRANSFIGSHIELD", 18) && !strncasecmp(Container->CharmFile, "ITEMTransfigBow", 15)) { switch (ItemToTry->ItemType) { case 0: case 1: @@ -1817,28 +1817,28 @@ bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Con } static std::map types = { - { "ITEMTransfig1HP", 2 }, - { "ITEMTransfig1HS", 0 }, - { "ITEMTransfig2HB", 4 }, - { "ITEMTransfig2HP", 35 }, - { "ITEMTransfig2HS", 1 }, - { "ITEMTransfigBlunt", 3 }, - { "ITEMTransfigBow", 5 }, - { "ITEMTransfigHTH", 45 }, - { "ITEMTRANSFIGSHIELD", 8 }, - { "ITEMTransfigSlashing", 0 } + { "itemtransfig1hp", 2 }, + { "itemtransfig1hs", 0 }, + { "itemtransfig2hb", 4 }, + { "itemtransfig2hp", 35 }, + { "itemtransfig2hs", 1 }, + { "itemtransfigblunt", 3 }, + { "itemtransfigbow", 5 }, + { "itemtransfighth", 45 }, + { "itemtransfigshield", 8 }, + { "itemtransfigslashing", 0 } }; - auto i = types.find(Container->CharmFile); + auto i = types.find(MakeLowerString(Container->CharmFile)); if (i != types.end() && i->second == ItemToTry->ItemType) return true; static std::map typestwo = { - { "ITEMTransfigBlunt", 4 }, - { "ITEMTransfigSlashing", 1 } + { "itemtransfigblunt", 4 }, + { "itemtransfigslashing", 1 } }; - i = typestwo.find(Container->CharmFile); + i = typestwo.find(MakeLowerString(Container->CharmFile)); if (i != typestwo.end() && i->second == ItemToTry->ItemType) return true; diff --git a/utils/sql/git/required/2014_11_26_InventoryTableUpdate.sql b/utils/sql/git/required/2014_11_26_InventoryTableUpdate.sql index ca25e4e2d..27a6d6c37 100644 --- a/utils/sql/git/required/2014_11_26_InventoryTableUpdate.sql +++ b/utils/sql/git/required/2014_11_26_InventoryTableUpdate.sql @@ -1,4 +1,4 @@ ---Inventory table update +-- Inventory table update ALTER TABLE `inventory` ADD COLUMN `ornamenticon` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `custom_data`, - ADD COLUMN `ornamentidfile` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `ornamenticon`; \ No newline at end of file + ADD COLUMN `ornamentidfile` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `ornamenticon`; From 2814130aad846a65f9679a22a4cec1ea96352f24 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 26 Nov 2014 19:04:20 -0500 Subject: [PATCH 18/96] Fix for compilers w/o C++11 uniform initialization --- common/item.cpp | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/common/item.cpp b/common/item.cpp index f23d87665..af661626a 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1816,28 +1816,26 @@ bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Con } } - static std::map types = { - { "itemtransfig1hp", 2 }, - { "itemtransfig1hs", 0 }, - { "itemtransfig2hb", 4 }, - { "itemtransfig2hp", 35 }, - { "itemtransfig2hs", 1 }, - { "itemtransfigblunt", 3 }, - { "itemtransfigbow", 5 }, - { "itemtransfighth", 45 }, - { "itemtransfigshield", 8 }, - { "itemtransfigslashing", 0 } - }; + static std::map types; + types["itemtransfig1hp"] = 2; + types["itemtransfig1hs"] = 0; + types["itemtransfig2hb"] = 4; + types["itemtransfig2hp"] = 35; + types["itemtransfig2hs"] = 1; + types["itemtransfigblunt"] = 3; + types["itemtransfigbow"] = 5; + types["itemtransfighth"] = 45; + types["itemtransfigshield"] = 8; + types["itemtransfigslashing"] = 0; auto i = types.find(MakeLowerString(Container->CharmFile)); if (i != types.end() && i->second == ItemToTry->ItemType) return true; - static std::map typestwo = { - { "itemtransfigblunt", 4 }, - { "itemtransfigslashing", 1 } - }; - + static std::map typestwo; + typestwo["itemtransfigblunt"] = 4; + typestwo["itemtransfigslashing"] = 1; + i = typestwo.find(MakeLowerString(Container->CharmFile)); if (i != typestwo.end() && i->second == ItemToTry->ItemType) return true; From 32a034bd587890249e1e84c996295020a874afce Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 26 Nov 2014 19:12:04 -0500 Subject: [PATCH 19/96] Flipped logic wrong :P --- common/item.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/item.cpp b/common/item.cpp index af661626a..f92bc6a67 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1803,7 +1803,7 @@ bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Con if (ItemToTry->ItemType == ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) return false; - if (AllowAll && !strncasecmp(Container->CharmFile, "ITEMTRANSFIGSHIELD", 18) && !strncasecmp(Container->CharmFile, "ITEMTransfigBow", 15)) { + if (AllowAll && strncasecmp(Container->CharmFile, "ITEMTRANSFIGSHIELD", 18) && strncasecmp(Container->CharmFile, "ITEMTransfigBow", 15)) { switch (ItemToTry->ItemType) { case 0: case 1: From 56a96dc817915e327b4b0eea20d7c391d04c5547 Mon Sep 17 00:00:00 2001 From: af4t Date: Wed, 26 Nov 2014 19:55:46 -0500 Subject: [PATCH 20/96] Typo? --- utils/sql/git/optional/2014_11_26_TransformationRules.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/optional/2014_11_26_TransformationRules.sql b/utils/sql/git/optional/2014_11_26_TransformationRules.sql index d31b6b26e..d86e6811d 100644 --- a/utils/sql/git/optional/2014_11_26_TransformationRules.sql +++ b/utils/sql/git/optional/2014_11_26_TransformationRules.sql @@ -1,3 +1,3 @@ ---Optional Transformation Rules +/* Optional Transformation Rules */ INSERT INTO `rule_values` VALUES (1, 'Inventory:DeleteTransformationMold', 'true', 'false to keep transformation mold forever'); INSERT INTO `rule_values` VALUES (1, 'Inventory:AllowAnyWeaponTransformation', 'false', 'True allows any MELEE weapon to use the other melee type transformatios'); From cfa05587fc2d152d63a56192d89aaf606000e2f8 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 26 Nov 2014 21:05:43 -0500 Subject: [PATCH 21/96] Added versioning for required ornament inventory sql --- 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 caff584d8..88131e9be 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 9057 +#define CURRENT_BINARY_DATABASE_VERSION 9058 #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 721beb002..039b0135a 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -311,6 +311,7 @@ 9055|2014_10_30_special_abilities_null.sql|SHOW COLUMNS FROM `npc_types` LIKE 'special_abilities'|contains|NO 9056|2014_11_08_RaidMembers.sql|SHOW COLUMNS FROM `raid_members` LIKE 'groupid'|missing|unsigned 9057|2014_11_13_spells_new_updates.sql|SHOW COLUMNS FROM `spells_new` LIKE 'disallow_sit'|empty| +9058|2014_11_26_InventoryTableUpdate.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornamenticon'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 98c21635c20fffb4b1035439acab55480a6fba26 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 26 Nov 2014 23:45:08 -0600 Subject: [PATCH 22/96] db_update.pl self update routine Some linux adjustments --- utils/scripts/db_update.pl | 46 +++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/utils/scripts/db_update.pl b/utils/scripts/db_update.pl index d592bebc3..bf92ce60f 100644 --- a/utils/scripts/db_update.pl +++ b/utils/scripts/db_update.pl @@ -6,6 +6,21 @@ #::: Purpose: To upgrade databases with ease and maintain versioning ########################################################### + +#::: If current version is less than what world is reporting, then download a new one... +$current_version = 1; +if($ARGV[0] eq "V"){ + if($ARGV[1] > $current_version){ + print "Retrieving latest database manifest...\n"; + GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl", "db_update.pl"); + exit; + } + else{ + print "No update necessary \n"; + } + exit; +} + $perl_version = $^V; $perl_version =~s/v//g; print "Perl Version is " . $perl_version . "\n"; @@ -26,14 +41,14 @@ while() { elsif(/(.*)<\/db>/i) { $db = $1; } } -print +$console_output = "============================================================ EQEmu: Automatic Database Upgrade Check ============================================================ "; use Config; -print " Operating System is: $Config{osname}\n"; +$console_output .= " Operating System is: $Config{osname}\n"; if($Config{osname}=~/linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } @@ -48,9 +63,9 @@ if($OS eq "Windows"){ last; } } - print " (Windows) MySQL is in system path \n"; - print " Path = " . $path . "\n"; - print "============================================================\n"; + $console_output .= " (Windows) MySQL is in system path \n"; + $console_output .= " Path = " . $path . "\n"; + $console_output .= "============================================================\n"; } } @@ -62,9 +77,9 @@ if($OS eq "Linux"){ } $path =~s/\n//g; - print " (Linux) MySQL is in system path \n"; - print " Path = " . $path . "\n"; - print "============================================================\n"; + $console_output .= " (Linux) MySQL is in system path \n"; + $console_output .= " Path = " . $path . "\n"; + $console_output .= "============================================================\n"; } #::: Path not found, error and exit @@ -93,10 +108,21 @@ if(GetMySQLResult("SHOW TABLES LIKE 'db_version'") eq ""){ } if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } -if($OS eq "Linux"){ @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")); + +#::: If ran from Linux startup script, supress output +if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){ + print "Database up to date...\n"; + exit; +} +else{ + print $console_output; +} + + print " Binary Database Version: (" . $bin_db_ver . ")\n"; print " Local Database Version: (" . $local_db_ver . ")\n\n"; @@ -135,7 +161,7 @@ sub ShowMenuPrompt { while (1) { { local $| = 1; - if(!$menu_show && $ARGV[0] eq "ran_from_world"){ + if(!$menu_show && ($ARGV[0] eq "ran_from_world" || $ARGV[0] eq "ran_from_start")){ $menu_show++; next; } From 12ea532a7ad89f00bd6e53b03a4b2e7423150785 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 26 Nov 2014 23:50:08 -0600 Subject: [PATCH 23/96] Renamed db_update.pl to db_updater.pl --- utils/scripts/{db_update.pl => db_updater.pl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename utils/scripts/{db_update.pl => db_updater.pl} (100%) diff --git a/utils/scripts/db_update.pl b/utils/scripts/db_updater.pl similarity index 100% rename from utils/scripts/db_update.pl rename to utils/scripts/db_updater.pl From 521106e286901817d78a7e5f2ecb518554281e4c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 27 Nov 2014 00:01:26 -0600 Subject: [PATCH 24/96] Renamed back the db_update.pl file --- utils/scripts/{db_updater.pl => db_update.pl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename utils/scripts/{db_updater.pl => db_update.pl} (100%) diff --git a/utils/scripts/db_updater.pl b/utils/scripts/db_update.pl similarity index 100% rename from utils/scripts/db_updater.pl rename to utils/scripts/db_update.pl From f0881d4aa98c8db15eb407c1acc19c68f16421d3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 27 Nov 2014 00:03:49 -0600 Subject: [PATCH 25/96] Self patching db_update script for when new versions come out --- common/database.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/common/database.cpp b/common/database.cpp index 82931e457..ecf83dc57 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -910,6 +910,19 @@ bool Database::CheckDatabaseConversions() { #endif } + /* + Automatic Database Upgrade Script + Script: db_updater.pl V 1 - the number that world passes to the script will + force the script to check for a newer version to update itself with + db_updater.pl ran_from_world - won't bring up a menu if your database versions match + db_updater.pl - ran standalone will bring up a menu prompt + */ + + /* Check for a new version of this script, the arg passed + would have to be higher than the copy they have downloaded + locally and they will re fetch */ + system("perl db_update.pl V 1"); + /* Run Automatic Database Upgrade Script */ system("perl db_update.pl ran_from_world"); From 4e3842b9d80a29b98678569fb1d7600e7c12ca1d Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Thu, 27 Nov 2014 13:05:50 -0800 Subject: [PATCH 26/96] Detransformation of mold type ornamentations. --- zone/string_ids.h | 1 + zone/tradeskills.cpp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/zone/string_ids.h b/zone/string_ids.h index 044dd215f..e1e1bc7b3 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -298,6 +298,7 @@ #define GUILD_BANK_EMPTY_HANDS 6108 // You must empty your hands to withdraw from the Guild Bank. #define TRANSFORM_FAILED 6326 //This mold cannot be applied to your %1. #define TRANSFORM_COMPLETE 6327 //You have successfully transformed your %1. +#define DETRANSFORM_FAILED 6341 //%1 has no transformation that can be removed. #define GENERIC_STRING 6688 //%1 (used to any basic message) #define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel. #define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel. diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index e9de6c4a6..da5114ed2 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -304,6 +304,24 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob return; } + if (container->GetItem()->BagType == BagTypeDetransformationmold) { + const ItemInst* inst = container->GetItem(0); + if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) { + 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->IsInstNoDrop(), MainCursor, 0, 0); + user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); + } + else if (inst) { + user->Message_StringID(4, DETRANSFORM_FAILED, inst->GetItem()->Name); + } + EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); + return; + } + DBTradeskillRecipe_Struct spec; if (!database.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) { user->Message_StringID(MT_Emote,TRADESKILL_NOCOMBINE); From 191aa575f853a2db6afd8160745e499324939726 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 27 Nov 2014 22:12:13 -0500 Subject: [PATCH 27/96] Projectiles (ie Arrows) fired from an archery attacks will do damage upon actually hitting the target, instead of instantly when fired. Consistent with live. Optional SQL added to disable this. Throwing will be implemented in a future update. --- changelog.txt | 5 + common/ruletypes.h | 1 + .../2014_11_27_ProjectileDmgOnImpact.sql | 1 + zone/client_process.cpp | 2 + zone/common.h | 14 + zone/mob.cpp | 15 + zone/mob.h | 9 +- zone/special_attacks.cpp | 402 ++++++++++++------ 8 files changed, 323 insertions(+), 126 deletions(-) create mode 100644 utils/sql/git/optional/2014_11_27_ProjectileDmgOnImpact.sql diff --git a/changelog.txt b/changelog.txt index b05fc26ee..c05951538 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- + +== 11/27/2014 == +Kayen: Projectiles (ie Arrows) fired from archery will now do damage upon impact instead of instantly (consistent w/ live). +Optional SQL: utils/sql/git/optional/2014_11_27_ProjectileDmgOnImpact.sql + == 11/24/2014 == Trevius: Spells that modify model size are now limited to 2 size adjustments from the base size. Trevius: Fix to prevent Mercenaries from being set as Group Leader. diff --git a/common/ruletypes.h b/common/ruletypes.h index b3e9b4f1c..8ff077809 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -419,6 +419,7 @@ 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_CATEGORY_END() RULE_CATEGORY( NPC ) diff --git a/utils/sql/git/optional/2014_11_27_ProjectileDmgOnImpact.sql b/utils/sql/git/optional/2014_11_27_ProjectileDmgOnImpact.sql new file mode 100644 index 000000000..ce7e16905 --- /dev/null +++ b/utils/sql/git/optional/2014_11_27_ProjectileDmgOnImpact.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:ProjectileDmgOnImpact', 'true', 'If enabled, projectiles (ie arrows) will hit on impact, instead of instantly.'); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index c07a73aea..40b7420d3 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -579,6 +579,8 @@ bool Client::Process() { viral_timer_counter = 0; } + ProjectileAttack(); + if(projectile_timer.Check()) SpellProjectileEffect(); diff --git a/zone/common.h b/zone/common.h index ea299ab11..d1aad5e40 100644 --- a/zone/common.h +++ b/zone/common.h @@ -459,6 +459,20 @@ struct Shielders_Struct { uint16 shielder_bonus; }; +typedef struct +{ + uint16 increment; + uint16 hit_increment; + uint16 target_id; + int32 wpn_dmg; + float origin_x; + float origin_y; + float origin_z; + uint32 ranged_id; + uint32 ammo_id; + uint8 skill; +} tProjatk; + //eventually turn this into a typedef and //make DoAnim take it instead of int, to enforce its use. enum { //type arguments to DoAnim diff --git a/zone/mob.cpp b/zone/mob.cpp index 35a019252..3b74d2417 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -287,6 +287,21 @@ Mob::Mob(const char* in_name, for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_z[i] = 0; } projectile_timer.Disable(); + ActiveProjectileATK = false; + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) + { + ProjectileAtk[i].increment = 0; + ProjectileAtk[i].hit_increment = 0; + ProjectileAtk[i].target_id = 0; + ProjectileAtk[i].wpn_dmg = 0; + ProjectileAtk[i].origin_x = 0.0f; + ProjectileAtk[i].origin_y = 0.0f; + ProjectileAtk[i].origin_z = 0.0f; + ProjectileAtk[i].ranged_id = 0; + ProjectileAtk[i].ammo_id = 0; + ProjectileAtk[i].skill = 0; + } + memset(&itembonuses, 0, sizeof(StatBonuses)); memset(&spellbonuses, 0, sizeof(StatBonuses)); memset(&aabonuses, 0, sizeof(StatBonuses)); diff --git a/zone/mob.h b/zone/mob.h index 525cbb2e8..df694aae9 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -724,7 +724,11 @@ public: 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); + 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); + bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo); + void ProjectileAttack(); + inline bool HasProjectileAttack() const { return ActiveProjectileATK; } + inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } bool CanDoSpecialAttack(Mob *other); bool Flurry(ExtraAttackOptions *opts); bool Rampage(ExtraAttackOptions *opts); @@ -1096,6 +1100,9 @@ protected: uint8 projectile_increment[MAX_SPELL_PROJECTILE]; float projectile_x[MAX_SPELL_PROJECTILE], projectile_y[MAX_SPELL_PROJECTILE], projectile_z[MAX_SPELL_PROJECTILE]; + bool ActiveProjectileATK; + tProjatk ProjectileAtk[MAX_SPELL_PROJECTILE]; + float rewind_x; float rewind_y; float rewind_z; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 3625c9180..879515d20 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -789,8 +789,8 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { return; } - SendItemAnimation(GetTarget(), AmmoItem, SkillArchery); - DoArcheryAttackDmg(GetTarget(), RangeWeapon, Ammo); + //Shoots projectile and/or applies the archery damage + DoArcheryAttackDmg(GetTarget(), RangeWeapon, Ammo,0,0,0,0,0,0, AmmoItem); //EndlessQuiver AA base1 = 100% Chance to avoid consumption arrow. int ChanceAvoidConsume = aabonuses.ConsumeProjectile + itembonuses.ConsumeProjectile + spellbonuses.ConsumeProjectile; @@ -806,147 +806,206 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { CommonBreakInvisible(); } -void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime) { - if (!CanDoSpecialAttack(other)) +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) { + + if ((other == nullptr || + ((IsClient() && CastToClient()->dead) || + (other->IsClient() && other->CastToClient()->dead)) || + HasDied() || + (!IsAttackAllowed(other)) || + (other->GetInvul() || + other->GetSpecialAbility(IMMUNE_MELEE)))) + { return; + } - if (!other->CheckHitChance(this, SkillArchery, MainPrimary, chance_mod)) { + const ItemInst* _RangeWeapon = nullptr; + const ItemInst* _Ammo = nullptr; + const Item_Struct* ammo_lost = nullptr; + + /* + If LaunchProjectile is false this function will do archery damage on target, + otherwise it will shoot the projectile at the target, once the projectile hits target + this function is then run again to do the damage portion + */ + bool LaunchProjectile = false; + bool ProjectileMiss = false; + + if (RuleB(Combat, ProjectileDmgOnImpact)){ + + if (AmmoItem) + LaunchProjectile = true; + else{ + /* + Item sync check on projectile landing. + Weapon damage is already calculated so this only affects procs! + Ammo proc check will use database to find proc if you used up your last ammo. + If you change range item mid projectile flight, you loose your chance to proc from bow (Deal with it!). + */ + + if (!RangeWeapon && !Ammo && range_id && ammo_id){ + + if (weapon_damage == 0) + ProjectileMiss = true; //This indicates that MISS was originally calculated. + + if (IsClient()){ + + _RangeWeapon = CastToClient()->m_inv[MainRange]; + if (!_RangeWeapon || _RangeWeapon->GetItem()->ID != range_id) + RangeWeapon = nullptr; + else + RangeWeapon = _RangeWeapon; + + _Ammo = CastToClient()->m_inv[MainAmmo]; + if (!_Ammo || _Ammo->GetItem()->ID != ammo_id) + ammo_lost = database.GetItem(ammo_id); + else + Ammo = _Ammo; + } + } + } + } + else if (AmmoItem) + SendItemAnimation(other, AmmoItem, SkillArchery); + + if (ProjectileMiss || !other->CheckHitChance(this, SkillArchery, MainPrimary, chance_mod)) { mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName()); - other->Damage(this, 0, SPELL_UNKNOWN, SkillArchery); + + if (LaunchProjectile){ + TryProjectileAttack(other, AmmoItem, SkillArchery, 0, RangeWeapon, Ammo); + return; + } + else + other->Damage(this, 0, SPELL_UNKNOWN, SkillArchery); } else { mlog(COMBAT__RANGED, "Ranged attack hit %s.", other->GetName()); + bool HeadShot = false; + uint32 HeadShot_Dmg = TryHeadShot(other, SkillArchery); + if (HeadShot_Dmg) + HeadShot = true; - bool HeadShot = false; - uint32 HeadShot_Dmg = TryHeadShot(other, SkillArchery); - if (HeadShot_Dmg) - HeadShot = true; + int32 hate = 0; + int32 TotalDmg = 0; + int16 WDmg = 0; + int16 ADmg = 0; + if (!weapon_damage){ + WDmg = GetWeaponDamage(other, RangeWeapon); + ADmg = GetWeaponDamage(other, Ammo); + } + else + WDmg = weapon_damage; - int32 TotalDmg = 0; - int16 WDmg = 0; - int16 ADmg = 0; - if (!weapon_damage){ - WDmg = GetWeaponDamage(other, RangeWeapon); - ADmg = GetWeaponDamage(other, Ammo); - } - else - WDmg = weapon_damage; + if (LaunchProjectile){//1: Shoot the Projectile once we calculate weapon damage. + TryProjectileAttack(other, AmmoItem, SkillArchery, WDmg, RangeWeapon, Ammo); + return; + } - if (focus) //From FcBaseEffects - WDmg += WDmg*focus/100; + if (focus) //From FcBaseEffects + WDmg += WDmg*focus/100; - if((WDmg > 0) || (ADmg > 0)) { - if(WDmg < 0) - WDmg = 0; - if(ADmg < 0) - ADmg = 0; - uint32 MaxDmg = (RuleR(Combat, ArcheryBaseDamageBonus)*(WDmg+ADmg)*GetDamageTable(SkillArchery)) / 100; - int32 hate = ((WDmg+ADmg)); - - if (HeadShot) - MaxDmg = HeadShot_Dmg; - - uint16 bonusArcheryDamageModifier = aabonuses.ArcheryDamageModifier + itembonuses.ArcheryDamageModifier + spellbonuses.ArcheryDamageModifier; - - MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100; - - mlog(COMBAT__RANGED, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg); - - bool dobonus = false; - if(GetClass() == RANGER && GetLevel() > 50) - { - int bonuschance = RuleI(Combat, ArcheryBonusChance); - - bonuschance = mod_archery_bonus_chance(bonuschance, RangeWeapon); - - if( !RuleB(Combat, UseArcheryBonusRoll) || (MakeRandomInt(1, 100) < bonuschance) ) - { - if(RuleB(Combat, ArcheryBonusRequiresStationary)) - { - if(other->IsNPC() && !other->IsMoving() && !other->IsRooted()) - { - dobonus = true; - } - } - else - { - dobonus = true; - } - } - - if(dobonus) - { - MaxDmg *= 2; - hate *= 2; - MaxDmg = mod_archery_bonus_damage(MaxDmg, RangeWeapon); - - mlog(COMBAT__RANGED, "Ranger. Double damage success roll, doubling damage to %d", MaxDmg); - Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); - } - } - - if (MaxDmg == 0) - MaxDmg = 1; - - if(RuleB(Combat, UseIntervalAC)) - TotalDmg = MaxDmg; - else - TotalDmg = MakeRandomInt(1, MaxDmg); - - int minDmg = 1; - if(GetLevel() > 25){ - //twice, for ammo and weapon - TotalDmg += (2*((GetLevel()-25)/3)); - minDmg += (2*((GetLevel()-25)/3)); - minDmg += minDmg * GetMeleeMinDamageMod_SE(SkillArchery) / 100; - hate += (2*((GetLevel()-25)/3)); - } - - if (!HeadShot) - other->AvoidDamage(this, TotalDmg, false); - - other->MeleeMitigation(this, TotalDmg, minDmg); - if(TotalDmg > 0) - { - ApplyMeleeDamageBonus(SkillArchery, TotalDmg); - TotalDmg += other->GetFcDamageAmtIncoming(this, 0, true, SkillArchery); - TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(SkillArchery) / 100) + GetSkillDmgAmt(SkillArchery); - - TotalDmg = mod_archery_damage(TotalDmg, dobonus, RangeWeapon); - - TryCriticalHit(other, SkillArchery, TotalDmg); - other->AddToHateList(this, hate, 0, false); - CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); - } - } - else - TotalDmg = -5; + if((WDmg > 0) || (ADmg > 0)) { + if(WDmg < 0) + WDmg = 0; + if(ADmg < 0) + ADmg = 0; + uint32 MaxDmg = (RuleR(Combat, ArcheryBaseDamageBonus)*(WDmg+ADmg)*GetDamageTable(SkillArchery)) / 100; + hate = ((WDmg+ADmg)); if (HeadShot) - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName()); - - other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery); - - if (TotalDmg > 0 && HasSkillProcSuccess() && GetTarget() && other && !other->HasDied()){ - if (ReuseTime) - TrySkillProc(other, SkillArchery, ReuseTime); - else - TrySkillProc(other, SkillArchery, 0, true, MainRange); + MaxDmg = HeadShot_Dmg; + + uint16 bonusArcheryDamageModifier = aabonuses.ArcheryDamageModifier + itembonuses.ArcheryDamageModifier + spellbonuses.ArcheryDamageModifier; + + MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100; + + mlog(COMBAT__RANGED, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg); + + bool dobonus = false; + if(GetClass() == RANGER && GetLevel() > 50){ + + int bonuschance = RuleI(Combat, ArcheryBonusChance); + bonuschance = mod_archery_bonus_chance(bonuschance, RangeWeapon); + + if( !RuleB(Combat, UseArcheryBonusRoll) || (MakeRandomInt(1, 100) < bonuschance)){ + if(RuleB(Combat, ArcheryBonusRequiresStationary)){ + if(other->IsNPC() && !other->IsMoving() && !other->IsRooted()) + dobonus = true; + } + else + dobonus = true; + } + + if(dobonus){ + MaxDmg *= 2; + hate *= 2; + MaxDmg = mod_archery_bonus_damage(MaxDmg, RangeWeapon); + + mlog(COMBAT__RANGED, "Ranger. Double damage success roll, doubling damage to %d", MaxDmg); + Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); + } } + + if (MaxDmg == 0) + MaxDmg = 1; + + if(RuleB(Combat, UseIntervalAC)) + TotalDmg = MaxDmg; + else + TotalDmg = MakeRandomInt(1, MaxDmg); + + int minDmg = 1; + if(GetLevel() > 25){ + //twice, for ammo and weapon + TotalDmg += (2*((GetLevel()-25)/3)); + minDmg += (2*((GetLevel()-25)/3)); + minDmg += minDmg * GetMeleeMinDamageMod_SE(SkillArchery) / 100; + hate += (2*((GetLevel()-25)/3)); + } + + if (!HeadShot) + other->AvoidDamage(this, TotalDmg, false); + + other->MeleeMitigation(this, TotalDmg, minDmg); + if(TotalDmg > 0){ + CommonOutgoingHitSuccess(other, TotalDmg, SkillArchery); + TotalDmg = mod_archery_damage(TotalDmg, dobonus, RangeWeapon); + } + } + else + TotalDmg = -5; + + if (HeadShot) + entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName()); + + 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) + TrySkillProc(other, SkillArchery, ReuseTime); + else + TrySkillProc(other, SkillArchery, 0, true, MainRange); + } } - //try proc on hits and misses - if((RangeWeapon != nullptr) && GetTarget() && other && !other->HasDied()){ + if (LaunchProjectile) + return;//Shouldn't reach this point, but just in case. + + //Weapon Proc + if(!RangeWeapon && other && !other->HasDied()) TryWeaponProc(RangeWeapon, other, MainRange); - } - //Arrow procs because why not? - if((Ammo != NULL) && GetTarget() && other && !other->HasDied()) - { - TryWeaponProc(Ammo, other, MainRange); - } + //Ammo Proc + if (ammo_lost) + TryWeaponProc(nullptr, ammo_lost, other, MainRange); + else if(Ammo && other && !other->HasDied()) + TryWeaponProc(Ammo, other, MainRange); - if (HasSkillProcs() && GetTarget() && other && !other->HasDied()){ + //Skill Proc + if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, SkillArchery, ReuseTime); else @@ -954,6 +1013,99 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item } } +bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo){ + + if (!other) + return false; + + int slot = -1; + + //Make sure there is an avialable slot. + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { + if (ProjectileAtk[i].target_id == 0){ + slot = i; + break; + } + } + + if (slot < 0) + return false; + + float distance = other->CalculateDistance(GetX(), GetY(), GetZ()); + float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) + + ProjectileAtk[slot].increment = 1; + ProjectileAtk[slot].hit_increment = hit; //This projected hit time if target does NOT MOVE + ProjectileAtk[slot].target_id = other->GetID(); + ProjectileAtk[slot].wpn_dmg = weapon_dmg; + ProjectileAtk[slot].origin_x = GetX(); + ProjectileAtk[slot].origin_y = GetY(); + ProjectileAtk[slot].origin_z = GetZ(); + ProjectileAtk[slot].ranged_id = RangeWeapon->GetItem()->ID; + ProjectileAtk[slot].ammo_id = Ammo->GetItem()->ID; + ProjectileAtk[slot].skill = skillInUse; + + SetProjectileAttack(true); + + if(item) + SendItemAnimation(other, item, skillInUse); + else if (IsNPC()) + ProjectileAnimation(other, 0,false,0,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse); + + return true; +} + + +void Mob::ProjectileAttack() +{ + if (!HasProjectileAttack()) + return;; + + Mob* target = nullptr; + bool disable = true; + + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { + + if (ProjectileAtk[i].increment == 0){ + continue; + } + + disable = false; + Mob* target = entity_list.GetMobID(ProjectileAtk[i].target_id); + + float distance = 0.0f; + + if (target && IsMoving()){ //Only recalculate hit increment if target moving + distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); + float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) + ProjectileAtk[i].hit_increment = static_cast(hit); + } + + if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment){ + + if (ProjectileAtk[i].skill == SkillArchery) + DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id); + + ProjectileAtk[i].increment = 0; + ProjectileAtk[i].target_id = 0; + ProjectileAtk[i].wpn_dmg = 0; + ProjectileAtk[i].origin_x = 0.0f; + ProjectileAtk[i].origin_y = 0.0f; + ProjectileAtk[i].origin_z = 0.0f; + ProjectileAtk[i].ranged_id = 0; + ProjectileAtk[i].ammo_id = 0; + ProjectileAtk[i].skill = 0; + } + + else { + ProjectileAtk[i].increment++; + } + } + + if (disable) + SetProjectileAttack(false); +} + void NPC::RangedAttack(Mob* other) { From 6f67577115161953b4184e92ef949dee8d2e6319 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 27 Nov 2014 22:30:44 -0500 Subject: [PATCH 28/96] Crash fixes --- zone/tradeskills.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index da5114ed2..059a1b909 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -283,7 +283,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } container = inst; - if (container->GetItem()->BagType == BagTypeTransformationmold) { + if (containe->GetItem() && container->GetItem()->BagType == BagTypeTransformationmold) { const ItemInst* inst = container->GetItem(0); bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation); if (inst && ItemInst::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) { @@ -304,7 +304,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob return; } - if (container->GetItem()->BagType == BagTypeDetransformationmold) { + if (container->GetItem() && container->GetItem()->BagType == BagTypeDetransformationmold) { const ItemInst* inst = container->GetItem(0); if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) { const Item_Struct* new_weapon = inst->GetItem(); From cf1370b9e2dfcc71cf8c9091c1f7c781a678bf01 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Thu, 27 Nov 2014 22:56:40 -0500 Subject: [PATCH 29/96] Spelling matters! --- zone/tradeskills.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 059a1b909..82d84e5cf 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -283,7 +283,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } container = inst; - if (containe->GetItem() && container->GetItem()->BagType == BagTypeTransformationmold) { + if (container->GetItem() && container->GetItem()->BagType == BagTypeTransformationmold) { const ItemInst* inst = container->GetItem(0); bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation); if (inst && ItemInst::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) { From 6b45b2bc527d9079a3dd8bd8a8b2a152c5fa2a49 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 27 Nov 2014 23:14:49 -0500 Subject: [PATCH 30/96] Fix for better ammo slot sync check. --- zone/common.h | 1 + zone/mob.cpp | 1 + zone/mob.h | 4 ++-- zone/special_attacks.cpp | 15 ++++++++------- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/zone/common.h b/zone/common.h index d1aad5e40..c4f643525 100644 --- a/zone/common.h +++ b/zone/common.h @@ -470,6 +470,7 @@ typedef struct float origin_z; uint32 ranged_id; uint32 ammo_id; + int ammo_slot; uint8 skill; } tProjatk; diff --git a/zone/mob.cpp b/zone/mob.cpp index 3b74d2417..398bffd3d 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -299,6 +299,7 @@ Mob::Mob(const char* in_name, ProjectileAtk[i].origin_z = 0.0f; ProjectileAtk[i].ranged_id = 0; ProjectileAtk[i].ammo_id = 0; + ProjectileAtk[i].ammo_slot = 0; ProjectileAtk[i].skill = 0; } diff --git a/zone/mob.h b/zone/mob.h index df694aae9..63e687854 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -724,8 +724,8 @@ public: 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, uint32 range_id=0, uint32 ammo_id=0, const Item_Struct *AmmoItem=nullptr); - bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo); + 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); + bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot); void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 879515d20..10456e2fa 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -790,7 +790,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { } //Shoots projectile and/or applies the archery damage - DoArcheryAttackDmg(GetTarget(), RangeWeapon, Ammo,0,0,0,0,0,0, AmmoItem); + DoArcheryAttackDmg(GetTarget(), RangeWeapon, Ammo,0,0,0,0,0,0, AmmoItem, ammo_slot); //EndlessQuiver AA base1 = 100% Chance to avoid consumption arrow. int ChanceAvoidConsume = aabonuses.ConsumeProjectile + itembonuses.ConsumeProjectile + spellbonuses.ConsumeProjectile; @@ -807,7 +807,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) { + uint32 range_id, uint32 ammo_id, const Item_Struct *AmmoItem, int AmmoSlot) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -857,7 +857,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else RangeWeapon = _RangeWeapon; - _Ammo = CastToClient()->m_inv[MainAmmo]; + _Ammo = CastToClient()->m_inv[AmmoSlot]; if (!_Ammo || _Ammo->GetItem()->ID != ammo_id) ammo_lost = database.GetItem(ammo_id); else @@ -873,7 +873,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, SkillArchery, 0, RangeWeapon, Ammo); + TryProjectileAttack(other, AmmoItem, SkillArchery, 0, RangeWeapon, Ammo, AmmoSlot); return; } else @@ -898,7 +898,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); + TryProjectileAttack(other, AmmoItem, SkillArchery, WDmg, RangeWeapon, Ammo, AmmoSlot); return; } @@ -1013,7 +1013,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){ +bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot){ if (!other) return false; @@ -1043,6 +1043,7 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes ProjectileAtk[slot].origin_z = GetZ(); ProjectileAtk[slot].ranged_id = RangeWeapon->GetItem()->ID; ProjectileAtk[slot].ammo_id = Ammo->GetItem()->ID; + ProjectileAtk[slot].ammo_slot = 0; ProjectileAtk[slot].skill = skillInUse; SetProjectileAttack(true); @@ -1084,7 +1085,7 @@ void Mob::ProjectileAttack() if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment){ if (ProjectileAtk[i].skill == SkillArchery) - DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id); + DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id, nullptr, ProjectileAtk[i].ammo_slot); ProjectileAtk[i].increment = 0; ProjectileAtk[i].target_id = 0; From baa7a1feb948233f63e876a77c13c28ec20d51f6 Mon Sep 17 00:00:00 2001 From: akkadius Date: Thu, 27 Nov 2014 23:24:32 -0600 Subject: [PATCH 31/96] Disabling file check for db_updater.pl temporarily to force update the update script for users. Will leave it this way for a few weeks and the nre-enable it because the latest one supports automatic update checking --- common/database.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index ecf83dc57..558f1d5c0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -901,21 +901,21 @@ bool Database::CheckDatabaseConversions() { CheckDatabaseConvertCorpseDeblob(); /* Fetch Automatic Database Upgrade Script */ - if (!std::ifstream("db_update.pl")){ + // if (!std::ifstream("db_update.pl")){ std::cout << "Pulling down automatic database upgrade script...\n" << std::endl; #ifdef _WIN32 system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl'); if ($response->is_success){ open(FILE, '> db_update.pl'); print FILE $response->decoded_content; close(FILE); }\""); #else system("wget -O db_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl"); #endif - } + // } /* Automatic Database Upgrade Script - Script: db_updater.pl V 1 - the number that world passes to the script will + Script: db_update.pl V 1 - the number that world passes to the script will force the script to check for a newer version to update itself with - db_updater.pl ran_from_world - won't bring up a menu if your database versions match - db_updater.pl - ran standalone will bring up a menu prompt + db_update.pl ran_from_world - won't bring up a menu if your database versions match + db_update.pl - ran standalone will bring up a menu prompt */ /* Check for a new version of this script, the arg passed From 28ad768c0ad87b755e939fef1359150021007400 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 28 Nov 2014 01:05:57 -0500 Subject: [PATCH 32/96] fixes --- zone/mob.h | 2 +- zone/special_attacks.cpp | 32 ++++++++++++++++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index 63e687854..373650661 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -722,7 +722,7 @@ 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 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 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, uint32 ammo_id=0, int AmmoSlot=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, uint32 range_id=0, uint32 ammo_id=0, const Item_Struct *AmmoItem=nullptr, int AmmoSlot=0); bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 10456e2fa..04f2b199a 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -199,7 +199,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { SetAttackTimer(); ThrowingAttack(GetTarget()); if (CheckDoubleRangedAttack()) - RangedAttack(GetTarget(), true); + ThrowingAttack(GetTarget(), true); return; } //ranged attack (archery) @@ -1074,18 +1074,18 @@ void Mob::ProjectileAttack() disable = false; Mob* target = entity_list.GetMobID(ProjectileAtk[i].target_id); - float distance = 0.0f; - - if (target && IsMoving()){ //Only recalculate hit increment if target moving - distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); + if (target && target->IsMoving()){ //Only recalculate hit increment if target moving + float distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) ProjectileAtk[i].hit_increment = static_cast(hit); } if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment){ - if (ProjectileAtk[i].skill == 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); + if (target){ + if (ProjectileAtk[i].skill == 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); + } ProjectileAtk[i].increment = 0; ProjectileAtk[i].target_id = 0; @@ -1323,7 +1323,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 else if(DistNoRootNoZ(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ return; } - + Shout("SLOT = %i", ammo_slot); if(!IsAttackAllowed(GetTarget()) || IsCasting() || IsSitting() || @@ -1345,7 +1345,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 CommonBreakInvisible(); } -void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* item, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime) +void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* item, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 ammo_id, int AmmoSlot) { if (!CanDoSpecialAttack(other)) return; @@ -1358,8 +1358,12 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite int16 WDmg = 0; - if (!weapon_damage && item != nullptr) - WDmg = GetWeaponDamage(other, item); + if (!weapon_damage){ + if (IsClient() && RangeWeapon) + WDmg = GetWeaponDamage(other, RangeWeapon); + else if (item) + WDmg = GetWeaponDamage(other, item); + } else WDmg = weapon_damage; @@ -1396,7 +1400,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite other->AddToHateList(this, 2*WDmg, 0, false); other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillThrowing); - if (TotalDmg > 0 && HasSkillProcSuccess() && GetTarget() && other && !other->HasDied()){ + if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, SkillThrowing, ReuseTime); else @@ -1404,10 +1408,10 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } - if((RangeWeapon != nullptr) && GetTarget() && other && (other->GetHP() > -10)) + if((RangeWeapon != nullptr) && other && (other->GetHP() > -10)) TryWeaponProc(RangeWeapon, other, MainRange); - if (HasSkillProcs() && GetTarget() && other && !other->HasDied()){ + if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, SkillThrowing, ReuseTime); else From b7c19e4034bc4523726d9f385a94e54b68cfac46 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 28 Nov 2014 02:19:45 -0500 Subject: [PATCH 33/96] Fix model_name in RoF Arrow_Struct --- common/patches/rof_structs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 0a62a90bf..075e6633b 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4169,7 +4169,8 @@ struct Arrow_Struct { /*070*/ uint8 unknown070; /*071*/ uint8 item_type; /*072*/ uint8 skill; -/*073*/ char model_name[43]; +/*073*/ uint8 unknown073[16]; +/*089*/ char model_name[27]; /*116*/ }; From ac0933719ae39ced2c2da17ae8ad710cf6054d30 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 28 Nov 2014 05:42:36 -0500 Subject: [PATCH 34/96] Sanity check added before calculating distance. --- zone/common.h | 1 + zone/mob.cpp | 1 + zone/special_attacks.cpp | 11 ++++++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/zone/common.h b/zone/common.h index c4f643525..267831368 100644 --- a/zone/common.h +++ b/zone/common.h @@ -468,6 +468,7 @@ typedef struct float origin_x; float origin_y; float origin_z; + float sanitycheck; uint32 ranged_id; uint32 ammo_id; int ammo_slot; diff --git a/zone/mob.cpp b/zone/mob.cpp index 398bffd3d..b4645b115 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -297,6 +297,7 @@ Mob::Mob(const char* in_name, ProjectileAtk[i].origin_x = 0.0f; ProjectileAtk[i].origin_y = 0.0f; ProjectileAtk[i].origin_z = 0.0f; + ProjectileAtk[i].sanitycheck = 0.0f; ProjectileAtk[i].ranged_id = 0; ProjectileAtk[i].ammo_id = 0; ProjectileAtk[i].ammo_slot = 0; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 04f2b199a..5f8373cac 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1075,9 +1075,14 @@ void Mob::ProjectileAttack() Mob* target = entity_list.GetMobID(ProjectileAtk[i].target_id); if (target && target->IsMoving()){ //Only recalculate hit increment if target moving - float distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); - float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) - ProjectileAtk[i].hit_increment = static_cast(hit); + + //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].sanitycheck != target->GetX() * target->GetY()){ + ProjectileAtk[i].sanitycheck = target->GetX() * target->GetY(); + float distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); + float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) + ProjectileAtk[i].hit_increment = static_cast(hit); + } } if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment){ From 67863e364b48b5c4e0ea5b99dda0e006a9de5c72 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 28 Nov 2014 05:46:23 -0500 Subject: [PATCH 35/96] fix --- zone/special_attacks.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 5f8373cac..38cbceb3b 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1098,8 +1098,10 @@ void Mob::ProjectileAttack() ProjectileAtk[i].origin_x = 0.0f; ProjectileAtk[i].origin_y = 0.0f; ProjectileAtk[i].origin_z = 0.0f; + ProjectileAtk[i].sanitycheck = 0.0f; ProjectileAtk[i].ranged_id = 0; ProjectileAtk[i].ammo_id = 0; + ProjectileAtk[i].ammo_slot = 0; ProjectileAtk[i].skill = 0; } From 3d83f647bf9400e952885f05d755c5cac1e3163d Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 28 Nov 2014 07:08:28 -0500 Subject: [PATCH 36/96] Implemented projectile on impact for Throwing --- zone/mob.h | 2 +- zone/special_attacks.cpp | 108 ++++++++++++++++++++++++++++++--------- 2 files changed, 86 insertions(+), 24 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index 373650661..a0fcf2d79 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -722,7 +722,7 @@ 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 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, uint32 ammo_id=0, int AmmoSlot=0); + 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); 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); bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 38cbceb3b..48bf2aaba 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -852,16 +852,14 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (IsClient()){ _RangeWeapon = CastToClient()->m_inv[MainRange]; - if (!_RangeWeapon || _RangeWeapon->GetItem()->ID != range_id) - RangeWeapon = nullptr; - else - RangeWeapon = _RangeWeapon; + if (_RangeWeapon && !_RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id) + RangeWeapon = _RangeWeapon; _Ammo = CastToClient()->m_inv[AmmoSlot]; - if (!_Ammo || _Ammo->GetItem()->ID != ammo_id) - ammo_lost = database.GetItem(ammo_id); - else + if (_Ammo && _Ammo->GetItem() && _Ammo->GetItem()->ID == ammo_id) Ammo = _Ammo; + else + ammo_lost = database.GetItem(ammo_id); } } } @@ -1035,14 +1033,19 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) ProjectileAtk[slot].increment = 1; - ProjectileAtk[slot].hit_increment = hit; //This projected hit time if target does NOT MOVE + ProjectileAtk[slot].hit_increment = static_cast(hit); //This projected hit time if target does NOT MOVE ProjectileAtk[slot].target_id = other->GetID(); ProjectileAtk[slot].wpn_dmg = weapon_dmg; ProjectileAtk[slot].origin_x = GetX(); ProjectileAtk[slot].origin_y = GetY(); ProjectileAtk[slot].origin_z = GetZ(); - ProjectileAtk[slot].ranged_id = RangeWeapon->GetItem()->ID; - ProjectileAtk[slot].ammo_id = Ammo->GetItem()->ID; + + if (RangeWeapon && RangeWeapon->GetItem()) + ProjectileAtk[slot].ranged_id = RangeWeapon->GetItem()->ID; + + if (Ammo && Ammo->GetItem()) + ProjectileAtk[slot].ammo_id = Ammo->GetItem()->ID; + ProjectileAtk[slot].ammo_slot = 0; ProjectileAtk[slot].skill = skillInUse; @@ -1077,8 +1080,9 @@ void Mob::ProjectileAttack() 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].sanitycheck != target->GetX() * target->GetY()){ - ProjectileAtk[i].sanitycheck = target->GetX() * target->GetY(); + float _sanitycheck = target->GetX() * target->GetY(); + if (ProjectileAtk[i].sanitycheck != _sanitycheck){ + ProjectileAtk[i].sanitycheck = _sanitycheck; float distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) ProjectileAtk[i].hit_increment = static_cast(hit); @@ -1090,6 +1094,8 @@ void Mob::ProjectileAttack() if (target){ if (ProjectileAtk[i].skill == 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) + DoThrowingAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0, ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_slot); } ProjectileAtk[i].increment = 0; @@ -1330,7 +1336,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 else if(DistNoRootNoZ(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ return; } - Shout("SLOT = %i", ammo_slot); + if(!IsAttackAllowed(GetTarget()) || IsCasting() || IsSitting() || @@ -1341,8 +1347,6 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 (GetAppearance() == eaDead)){ return; } - //send item animation, also does the throw animation - SendItemAnimation(GetTarget(), item, SkillThrowing); DoThrowingAttackDmg(GetTarget(), RangeWeapon, item); @@ -1352,14 +1356,62 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 CommonBreakInvisible(); } -void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* item, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 ammo_id, int AmmoSlot) +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) { - if (!CanDoSpecialAttack(other)) + if ((other == nullptr || + ((IsClient() && CastToClient()->dead) || + (other->IsClient() && other->CastToClient()->dead)) || + HasDied() || + (!IsAttackAllowed(other)) || + (other->GetInvul() || + other->GetSpecialAbility(IMMUNE_MELEE)))) + { return; + } - if (!other->CheckHitChance(this, SkillThrowing, MainPrimary, chance_mod)){ + const ItemInst* _RangeWeapon = nullptr; + const Item_Struct* ammo_lost = nullptr; + + /* + If LaunchProjectile is false this function will do archery damage on target, + otherwise it will shoot the projectile at the target, once the projectile hits target + this function is then run again to do the damage portion + */ + bool LaunchProjectile = false; + bool ProjectileMiss = false; + + if (RuleB(Combat, ProjectileDmgOnImpact)){ + + if (AmmoItem) + LaunchProjectile = true; + else{ + if (!RangeWeapon && range_id){ + + if (weapon_damage == 0) + ProjectileMiss = true; //This indicates that MISS was originally calculated. + + if (IsClient()){ + + _RangeWeapon = CastToClient()->m_inv[AmmoSlot]; + if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID != range_id) + RangeWeapon = _RangeWeapon; + else + ammo_lost = database.GetItem(range_id); + } + } + } + } + else if (AmmoItem) + SendItemAnimation(other, AmmoItem, SkillThrowing); + + if (ProjectileMiss || !other->CheckHitChance(this, SkillThrowing, MainPrimary, chance_mod)){ mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName()); - other->Damage(this, 0, SPELL_UNKNOWN, SkillThrowing); + if (LaunchProjectile){ + TryProjectileAttack(other, AmmoItem, SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot); + return; + } + else + other->Damage(this, 0, SPELL_UNKNOWN, SkillThrowing); } else { mlog(COMBAT__RANGED, "Throwing attack hit %s.", other->GetName()); @@ -1368,8 +1420,13 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (!weapon_damage){ if (IsClient() && RangeWeapon) WDmg = GetWeaponDamage(other, RangeWeapon); - else if (item) - WDmg = GetWeaponDamage(other, item); + else if (AmmoItem) + WDmg = GetWeaponDamage(other, AmmoItem); + + if (LaunchProjectile){ + TryProjectileAttack(other, AmmoItem, SkillThrowing, WDmg, RangeWeapon, nullptr, AmmoSlot); + return; + } } else WDmg = weapon_damage; @@ -1415,7 +1472,13 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } - if((RangeWeapon != nullptr) && other && (other->GetHP() > -10)) + if (LaunchProjectile) + return; + + //Throwing item Proc + if (ammo_lost) + TryWeaponProc(nullptr, ammo_lost, other, MainRange); + else if(RangeWeapon && other && !other->HasDied()) TryWeaponProc(RangeWeapon, other, MainRange); if (HasSkillProcs() && other && !other->HasDied()){ @@ -1424,7 +1487,6 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else TrySkillProc(other, SkillThrowing, 0, false, MainRange); } - } void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse) { From 84fa042c75a0dd0231d70f98e6bc90782b953e17 Mon Sep 17 00:00:00 2001 From: Trevius Date: Fri, 28 Nov 2014 20:23:42 -0600 Subject: [PATCH 37/96] Fixed a zone crash related to numhits for spells. Fixed a query related to group leaders logging in. Fixed a world crash related to attempting to join an adventure with Mercenaries. --- changelog.txt | 7 ++++++- common/database.cpp | 7 +++++-- world/adventure.cpp | 17 +++++++++++------ zone/mob.h | 2 +- zone/spell_effects.cpp | 2 +- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/changelog.txt b/changelog.txt index b05fc26ee..cf7d51346 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 11/24/2014 == +== 11/28/2014 == +Trevius: Fixed a zone crash related to numhits for spells. +Trevius: Fixed a query related to group leaders logging in. +Trevius (Natedog): Fixed a world crash related to attempting to join an adventure with Mercenaries. + +== 11/25/2014 == Trevius: Spells that modify model size are now limited to 2 size adjustments from the base size. Trevius: Fix to prevent Mercenaries from being set as Group Leader. diff --git a/common/database.cpp b/common/database.cpp index 558f1d5c0..e950d8bd4 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -768,7 +768,10 @@ uint32 Database::GetCharacterID(const char *name) { std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); auto row = results.begin(); - if (row[0]){ return atoi(row[0]); } + if (results.RowCount() == 1) + { + return atoi(row[0]); + } return 0; } @@ -3277,7 +3280,7 @@ char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf) { if (group_id == 0) return leaderbuf; - query = StringFormat("SELECT `leadername` FROM `group_leader` WHERE `gid` = '%u' AND `groupid` = %u LIMIT 1", group_id); + query = StringFormat("SELECT `leadername` FROM `group_leaders` WHERE `gid` = '%u' LIMIT 1", group_id); results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) diff --git a/world/adventure.cpp b/world/adventure.cpp index ffb64779c..979347409 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -54,10 +54,10 @@ void Adventure::AddPlayer(std::string character_name, bool add_client_to_instanc { if(!PlayerExists(character_name)) { - int client_id = database.GetCharacterID(character_name.c_str()); - if(add_client_to_instance) + int32 character_id = database.GetCharacterID(character_name.c_str()); + if(character_id && add_client_to_instance) { - database.AddClientToInstance(instance_id, client_id); + database.AddClientToInstance(instance_id, character_id); } players.push_back(character_name); } @@ -68,11 +68,16 @@ void Adventure::RemovePlayer(std::string character_name) std::list::iterator iter = players.begin(); while(iter != players.end()) { + if((*iter).compare(character_name) == 0) { - database.RemoveClientFromInstance(instance_id, database.GetCharacterID(character_name.c_str())); - players.erase(iter); - return; + int32 character_id = database.GetCharacterID(character_name.c_str()); + if (character_id) + { + database.RemoveClientFromInstance(instance_id, character_id); + players.erase(iter); + return; + } } ++iter; } diff --git a/zone/mob.h b/zone/mob.h index 525cbb2e8..944dfc515 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -275,7 +275,7 @@ public: int16 GetBuffSlotFromType(uint16 type); uint16 GetSpellIDFromSlot(uint8 slot); int CountDispellableBuffs(); - void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=-1, uint16 spell_id=SPELL_UNKNOWN); + void CheckNumHitsRemaining(uint8 type, int32 buff_slot=-1, 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; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4a73926c3..b55102072 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5558,7 +5558,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { return realTotal + realTotal2 + realTotal3; } -void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id) +void Mob::CheckNumHitsRemaining(uint8 type, int32 buff_slot, uint16 spell_id) { /* Field 175 = numhits type From 8cd19670abef46d5bb0887d16f906a9c32f96f04 Mon Sep 17 00:00:00 2001 From: Trevius Date: Fri, 28 Nov 2014 20:30:35 -0600 Subject: [PATCH 38/96] Minor improvement to last commit. --- world/adventure.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/world/adventure.cpp b/world/adventure.cpp index 979347409..80b1dcaca 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -68,7 +68,6 @@ void Adventure::RemovePlayer(std::string character_name) std::list::iterator iter = players.begin(); while(iter != players.end()) { - if((*iter).compare(character_name) == 0) { int32 character_id = database.GetCharacterID(character_name.c_str()); @@ -76,8 +75,8 @@ void Adventure::RemovePlayer(std::string character_name) { database.RemoveClientFromInstance(instance_id, character_id); players.erase(iter); - return; } + return; } ++iter; } From ad9c0df5525237dcb29b7bb6ec718f9e8ffa75b5 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 03:12:34 -0600 Subject: [PATCH 39/96] #include and forward declaration cleanup of client.cpp net.cpp questmgr.cpp zone.cpp zone.h --- zone/client.cpp | 14 ---------- zone/net.cpp | 2 +- zone/questmgr.cpp | 71 ++++++++++------------------------------------- zone/zone.cpp | 63 +++++++++++++++++++---------------------- zone/zone.h | 28 +++++-------------- 5 files changed, 51 insertions(+), 127 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 7ceb12496..e4f2c823a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -17,13 +17,9 @@ */ #include "../common/debug.h" #include -#include -#include #include #include #include -#include -#include // for windows compile #ifdef _WINDOWS @@ -39,27 +35,17 @@ extern volatile bool RunLoops; #include "../common/features.h" -#include "../common/misc.h" #include "../common/spdat.h" -#include "../common/packet_dump.h" -#include "../common/packet_functions.h" -#include "../common/serverinfo.h" -#include "../common/zone_numbers.h" -#include "../common/moremath.h" #include "../common/guilds.h" -#include "../common/breakdowns.h" #include "../common/rulesys.h" #include "../common/string_util.h" #include "../common/data_verification.h" #include "net.h" -#include "masterentity.h" #include "worldserver.h" #include "zonedb.h" #include "petitions.h" -#include "forage.h" #include "command.h" #include "string_ids.h" -#include "npc_ai.h" #include "client_logs.h" #include "guild_mgr.h" #include "quest_parser_collection.h" diff --git a/zone/net.cpp b/zone/net.cpp index 498ed5102..034c30747 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -97,7 +97,7 @@ extern Zone* zone; EQStreamFactory eqsf(ZoneStream); npcDecayTimes_Struct npcCorpseDecayTimes[100]; TitleManager title_manager; -QueryServ *QServ = 0; +QueryServ *QServ = 0; TaskManager *taskmanager = 0; QuestParserCollection *parse = 0; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 458a448d9..2ce1dbc37 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -16,66 +16,28 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - -Assuming you want to add a new perl quest function named joe -that takes 1 integer argument.... - -1. Add the prototype to the quest manager: -questmgr.h: add (~line 50) - void joe(int arg); - -2. Define the actual function in questmgr.cpp: -void QuestManager::joe(int arg) { - //... do something -} - -3. Copy one of the XS routines in perlparser.cpp, preferably - one with the same number of arguments as your routine. Rename - as needed. - Finally, add your routine to the list at the bottom of perlparser.cpp - - -4. -If you want it to work in old mode perl and .qst, edit parser.cpp -Parser::ExCommands (~line 777) - else if (!strcmp(command,"joe")) { - quest_manager.joe(atoi(arglist[0])); - } - -And then at then end of embparser.cpp, add: -"sub joe{push(@cmd_queue,{func=>'joe',args=>join(',',@_)});}" - - - -*/ - -#include "../common/debug.h" -#include "entity.h" -#include "masterentity.h" -#include - -#include -#include -#include - -#include "worldserver.h" -#include "net.h" -#include "../common/skills.h" #include "../common/classes.h" -#include "../common/races.h" -#include "zonedb.h" +#include "../common/debug.h" +#include "../common/rulesys.h" +#include "../common/skills.h" #include "../common/spdat.h" -#include "../common/packet_functions.h" #include "../common/string_util.h" -#include "spawn2.h" -#include "zone.h" +#include "entity.h" #include "event_codes.h" #include "guild_mgr.h" -#include "../common/rulesys.h" +#include "net.h" #include "qglobals.h" -#include "quest_parser_collection.h" #include "queryserv.h" +#include "questmgr.h" +#include "quest_parser_collection.h" +#include "spawn2.h" +#include "worldserver.h" +#include "zone.h" +#include "zonedb.h" +#include +#include +#include + #ifdef BOTS #include "bot.h" #endif @@ -85,9 +47,6 @@ extern Zone* zone; extern WorldServer worldserver; extern EntityList entity_list; -#include "questmgr.h" - -//declare our global instance QuestManager quest_manager; #define QuestManagerCurrentQuestVars() \ diff --git a/zone/zone.cpp b/zone/zone.cpp index ecf10bcb5..9b42bfb68 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -15,17 +15,14 @@ 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 -#include -#include -#include #ifdef _WINDOWS -#include #define snprintf _snprintf #define vsnprintf _vsnprintf #else @@ -33,31 +30,26 @@ #include "../common/unix.h" #endif -#include "masterentity.h" +#include "../common/debug.h" #include "../common/features.h" -#include "spawngroup.h" -#include "spawn2.h" -#include "zone.h" -#include "worldserver.h" -#include "npc.h" -#include "net.h" -#include "../common/seperator.h" -#include "../common/packet_dump_file.h" -#include "../common/eq_stream_factory.h" -#include "../common/eq_stream.h" -#include "../common/string_util.h" -#include "zone_config.h" -#include "../common/breakdowns.h" -#include "map.h" -#include "water_map.h" -#include "object.h" -#include "petitions.h" -#include "pathing.h" -#include "event_codes.h" -#include "client_logs.h" #include "../common/rulesys.h" +#include "../common/seperator.h" +#include "../common/string_util.h" +#include "client_logs.h" #include "guild_mgr.h" +#include "map.h" +#include "net.h" +#include "npc.h" +#include "object.h" +#include "pathing.h" +#include "petitions.h" #include "quest_parser_collection.h" +#include "spawn2.h" +#include "spawngroup.h" +#include "water_map.h" +#include "worldserver.h" +#include "zone_config.h" +#include "zone.h" #ifdef _WINDOWS #define snprintf _snprintf @@ -65,18 +57,19 @@ #define strcasecmp _stricmp #endif - +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; -extern uint32 numclients; -extern NetConnection net; -extern uint16 adverrornum; -extern PetitionList petition_list; + Mutex MZoneShutdown; -extern bool staticzone; -Zone* zone = 0; + volatile bool ZoneLoaded = false; -extern QuestParserCollection* parse; +Zone* zone = 0; bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { const char* zonename = database.GetZoneName(iZoneID); diff --git a/zone/zone.h b/zone/zone.h index 0fa390512..2d74c9f17 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -18,25 +18,13 @@ #ifndef ZONE_H #define ZONE_H -#include "../common/mutex.h" -#include "../common/linked_list.h" -#include "../common/types.h" #include "../common/eqtime.h" -#include "../common/servertalk.h" +#include "../common/linked_list.h" #include "../common/rulesys.h" -#include "../common/eq_packet_structs.h" -#include "../common/features.h" -#include "spawngroup.h" -//#include "mob.h" -#include "zonedump.h" -#include "spawn2.h" -#include "tasks.h" -#include "pathing.h" +#include "../common/types.h" #include "qglobals.h" -#include - -class Map; -class WaterMap; +#include "spawn2.h" +#include "spawngroup.h" struct ZonePoint { @@ -78,12 +66,10 @@ struct item_tick_struct { std::string qglobal; }; -extern EntityList entity_list; -class database; +class Map; +class WaterMap; class PathManager; -struct SendAA_Struct; - -class database; +extern EntityList entity_list; class Zone { From 700de3f518a1a317822bbb5b18126995fb504a03 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 03:24:48 -0600 Subject: [PATCH 40/96] questmgr.h forward declarations client_process.cpp #include removals --- zone/client_process.cpp | 36 +++++++++++------------------------- zone/questmgr.h | 4 +++- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index c07a73aea..2c391bd34 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -20,13 +20,8 @@ */ #include "../common/debug.h" #include -#include -#include -#include #include -#include #include -#include #ifdef _WINDOWS #include @@ -41,29 +36,20 @@ #include #endif -#include "masterentity.h" -#include "zonedb.h" -#include "../common/packet_functions.h" -#include "../common/packet_dump.h" -#include "worldserver.h" -#include "../common/packet_dump_file.h" -#include "../common/string_util.h" -#include "../common/spdat.h" -#include "petitions.h" -#include "npc_ai.h" -#include "../common/skills.h" -#include "forage.h" -#include "zone.h" -#include "event_codes.h" -#include "../common/faction.h" -#include "../common/crc32.h" #include "../common/rulesys.h" -#include "string_ids.h" -#include "map.h" +#include "../common/skills.h" +#include "../common/spdat.h" +#include "../common/string_util.h" +#include "event_codes.h" #include "guild_mgr.h" -#include -#include "quest_parser_collection.h" +#include "map.h" +#include "petitions.h" #include "queryserv.h" +#include "quest_parser_collection.h" +#include "string_ids.h" +#include "worldserver.h" +#include "zone.h" +#include "zonedb.h" extern QueryServ* QServ; extern Zone* zone; diff --git a/zone/questmgr.h b/zone/questmgr.h index 6b47bab04..dd471d74f 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -25,8 +25,10 @@ #include #include -class NPC; class Client; +class ItemInst; +class Mob; +class NPC; class QuestManager { struct running_quest { From 82e96d7014f2c86cda16b1d340a8b3f78a2e6f1b Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 03:48:26 -0600 Subject: [PATCH 41/96] client_packet.cpp #include cleanup --- zone/client_packet.cpp | 46 +++++++++++++++--------------------------- zone/client_packet.h | 4 ++-- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a12247cc6..8f2450621 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -16,14 +16,11 @@ */ #include "../common/debug.h" -#include #include #include #include #include -#include #include -#include #include #include @@ -38,39 +35,28 @@ #include #endif -#include "../common/packet_functions.h" -#include "../common/packet_dump.h" -#include "worldserver.h" -#include "../common/rdtsc.h" -#include "../common/packet_dump_file.h" -#include "../common/string_util.h" -#include "../common/breakdowns.h" -#include "../common/guilds.h" -#include "../common/rulesys.h" -#include "../common/spdat.h" -#include "../common/data_verification.h" -#include "petitions.h" -#include "npc_ai.h" -#include "../common/skills.h" -#include "forage.h" -#include "zone.h" -#include "event_codes.h" -#include "../common/faction.h" #include "../common/crc32.h" +#include "../common/data_verification.h" +#include "../common/faction.h" +#include "../common/guilds.h" +#include "../common/rdtsc.h" +#include "../common/rulesys.h" +#include "../common/skills.h" +#include "../common/spdat.h" +#include "../common/string_util.h" +#include "../common/zone_numbers.h" +#include "event_codes.h" +#include "guild_mgr.h" +#include "merc.h" +#include "petitions.h" +#include "pets.h" +#include "queryserv.h" +#include "quest_parser_collection.h" #include "string_ids.h" #include "titles.h" #include "water_map.h" #include "worldserver.h" #include "zone.h" -#include "zone_config.h" -#include "guild_mgr.h" -#include "pathing.h" -#include "water_map.h" -#include "merc.h" -#include "pets.h" -#include "../common/zone_numbers.h" -#include "quest_parser_collection.h" -#include "queryserv.h" extern QueryServ* QServ; extern Zone* zone; diff --git a/zone/client_packet.h b/zone/client_packet.h index 0868b93ba..51b6713b7 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -1,4 +1,4 @@ - // connecting opcode handlers + /* Connecting OpCode Handlers */ void Handle_Connect_0x3e33(const EQApplicationPacket *app); void Handle_Connect_OP_ApproveZone(const EQApplicationPacket *app); void Handle_Connect_OP_ClientError(const EQApplicationPacket *app); @@ -20,7 +20,7 @@ void Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app); void Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app); void Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app); - // connected opcode handlers + /* Connected opcode handlers*/ void Handle_0x0193(const EQApplicationPacket *app); void Handle_0x01e7(const EQApplicationPacket *app); void Handle_OP_AAAction(const EQApplicationPacket *app); From 8da864bada536099577fcc4b8c8340f07e85f2d3 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 03:54:25 -0600 Subject: [PATCH 42/96] command.cpp #include cleanup command.h forward declaration --- zone/command.cpp | 27 +++++++++++---------------- zone/command.h | 3 +++ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index 12241de52..c9bef2e12 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -42,27 +42,22 @@ #endif #include "../common/debug.h" -#include "../common/ptimer.h" -#include "../common/packet_functions.h" -#include "../common/packet_dump.h" -#include "../common/serverinfo.h" -#include "../common/opcodemgr.h" #include "../common/eq_packet.h" -#include "../common/guilds.h" -#include "../common/rulesys.h" -#include "../common/string_util.h" -//#include "../common/servertalk.h" // for oocmute and revoke -#include "worldserver.h" -#include "masterentity.h" -#include "map.h" -#include "water_map.h" #include "../common/features.h" -#include "pathing.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 "client_logs.h" #include "guild_mgr.h" -#include "titles.h" -#include "../common/patches/patches.h" +#include "map.h" +#include "pathing.h" #include "queryserv.h" +#include "titles.h" +#include "water_map.h" +#include "worldserver.h" extern QueryServ* QServ; extern WorldServer worldserver; diff --git a/zone/command.h b/zone/command.h index db069b57c..ea710482b 100644 --- a/zone/command.h +++ b/zone/command.h @@ -20,6 +20,9 @@ #ifndef COMMAND_H #define COMMAND_H +class Client; +class Seperator; + #include "../common/seperator.h" #include "../common/eq_stream.h" #include "client.h" From 6d763256f148faf9da95fdcf22bad859faa48871 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 04:04:49 -0600 Subject: [PATCH 43/96] client_mods.cpp cleanup --- zone/client_mods.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 5431b2dfe..55b522378 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -18,23 +18,17 @@ #include #include "../common/debug.h" -#include "../common/spdat.h" -#include "../common/packet_dump.h" -#include "../common/packet_functions.h" -#include "../common/serverinfo.h" -#include "../common/zone_numbers.h" -#include "../common/moremath.h" -#include "../common/guilds.h" #include "../common/logsys.h" +#include "../common/spdat.h" +#include "../common/rulesys.h" #include "masterentity.h" -#include "worldserver.h" -#include "zonedb.h" +#include "npc_ai.h" #include "petitions.h" #include "string_ids.h" -#include "npc_ai.h" +#include "worldserver.h" +#include "zonedb.h" -// Return max stat value for level int32 Client::GetMaxStat() const { if((RuleI(Character, StatCap)) > 0) From e833f457a1e7e3b6f2cf6d1ae656de85fa17c21e Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 04:08:37 -0600 Subject: [PATCH 44/96] inventory.cpp #include clean/remove --- zone/inventory.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index a7f61819e..d290658d0 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -15,24 +15,13 @@ 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 "worldserver.h" -#include "net.h" -#include "zonedb.h" -#include "../common/spdat.h" -#include "../common/packet_dump.h" -#include "../common/packet_functions.h" -#include "petitions.h" -#include "../common/serverinfo.h" -#include "../common/zone_numbers.h" -#include "../common/moremath.h" -#include "../common/guilds.h" #include "../common/logsys.h" #include "../common/string_util.h" -#include "string_ids.h" -#include "npc_ai.h" #include "quest_parser_collection.h" +#include "worldserver.h" +#include "zonedb.h" extern WorldServer worldserver; // @merth: this needs to be touched up From 251e940fe83f494dd7f4bad2a6584cb996fb51ea Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 04:18:18 -0600 Subject: [PATCH 45/96] zonedb.h forward declarations zonedb.cpp #include cleanup --- zone/inventory.cpp | 1 + zone/zonedb.cpp | 19 +++++++------------ zone/zonedb.h | 26 +++++++++++++++++--------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index d290658d0..6b7a0b297 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -22,6 +22,7 @@ #include "quest_parser_collection.h" #include "worldserver.h" #include "zonedb.h" + extern WorldServer worldserver; // @merth: this needs to be touched up diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8bc696888..1f520ed88 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1,21 +1,16 @@ -#include "zonedb.h" -#include "../common/item.h" -#include "../common/string_util.h" #include "../common/extprofile.h" -#include "../common/guilds.h" +#include "../common/item.h" #include "../common/rulesys.h" -#include "../common/rdtsc.h" -#include "zone.h" -#include "corpse.h" +#include "../common/string_util.h" #include "client.h" -#include "merc.h" +#include "corpse.h" #include "groups.h" -#include "raids.h" -#include -#include -#include +#include "merc.h" +#include "zone.h" +#include "zonedb.h" #include +#include extern Zone* zone; diff --git a/zone/zonedb.h b/zone/zonedb.h index 3f8719946..5adc893ff 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -3,10 +3,24 @@ #include "../common/shareddb.h" #include "../common/eq_packet_structs.h" -#include "../common/loottable.h" -#include "zonedump.h" #include "../common/faction.h" -#include + +class Client; +class Corpse; +class Merc; +class NPC; +class Petition; +class Spawn2; +class SpawnGroupList; +class ItemInst; +struct CharacterEventLog_Struct; +struct Door; +struct ExtendedProfile_Struct; +struct NPCType; +struct PlayerCorpse_Struct; +struct ZonePoint; +struct npcDecayTimes_Struct; +template class LinkedList; //#include "doors.h" @@ -201,12 +215,6 @@ struct ClientMercEntry { uint32 npcid; }; -class ItemInst; -struct FactionMods; -struct FactionValue; -struct LootTable_Struct; - - class ZoneDatabase : public SharedDatabase { typedef std::list ItemList; public: From 5d5c3fbfd1784bdcf75311bd3c8eb576371720bd Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 04:30:03 -0600 Subject: [PATCH 46/96] database.h forward declaration database.cpp #include house-keeping --- common/database.cpp | 16 ++++++---------- common/database.h | 11 +++-------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e950d8bd4..4cafc56d1 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -17,19 +17,16 @@ */ #include "../common/debug.h" #include "../common/rulesys.h" -#include -#include +#include +#include #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include // Disgrace: for windows compile #ifdef _WINDOWS @@ -45,7 +42,6 @@ #include "database.h" #include "eq_packet_structs.h" -#include "guilds.h" #include "string_util.h" #include "extprofile.h" diff --git a/common/database.h b/common/database.h index 9be14f1cb..6325b4e3d 100644 --- a/common/database.h +++ b/common/database.h @@ -41,6 +41,7 @@ class SpawnGroupList; class Petition; class Client; class Merc; +class MySQLRequestResult; struct Combine_Struct; //struct Faction; //struct FactionMods; @@ -68,21 +69,15 @@ uint8 eventid; EventLogDetails_Struct eld[255]; }; - -// Added By Hogie -// INSERT into variables (varname,value) values('decaytime [minlevel] [maxlevel]','[number of seconds]'); -// IE: decaytime 1 54 = Levels 1 through 54 -// decaytime 55 100 = Levels 55 through 100 -// It will always put the LAST time for the level (I think) from the Database struct npcDecayTimes_Struct { uint16 minlvl; uint16 maxlvl; uint32 seconds; }; -// Added By Hogie -- End + struct VarCache_Struct { - char varname[26]; // varname is char(25) in database + char varname[26]; char value[0]; }; From 4faca5543ace09b9db836e73ebf80be2a9f6e544 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 04:56:42 -0600 Subject: [PATCH 47/96] net.h cleanup --- zone/net.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/zone/net.h b/zone/net.h index e81dd6d51..c49e1ec8e 100644 --- a/zone/net.h +++ b/zone/net.h @@ -26,9 +26,6 @@ #include #endif - -#include -#include #include "../common/types.h" #include "../common/timer.h" void CatchSignal(int); From 904ae416c51d4c7d439182d3dad6c4e9d03fdb58 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 05:01:49 -0600 Subject: [PATCH 48/96] Small world server cleanup --- zone/worldserver.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zone/worldserver.h b/zone/worldserver.h index 6feead496..c1e86421f 100644 --- a/zone/worldserver.h +++ b/zone/worldserver.h @@ -20,12 +20,10 @@ #include "../common/worldconn.h" #include "../common/eq_packet_structs.h" -#include -struct GuildJoin_Struct; +class ServerPacket; class EQApplicationPacket; class Client; -class Database; class WorldServer : public WorldConnection { public: From 35e9c3ad9804128b9971b1230eae0758778e45e3 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 05:22:27 -0600 Subject: [PATCH 49/96] special_attacks.cpp #include clean --- zone/special_attacks.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 3625c9180..6c29cade1 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -14,19 +14,18 @@ You should have received a copy of the GNU General Public 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 "masterentity.h" -#include "string_ids.h" #include "../common/misc_functions.h" #include "../common/rulesys.h" #include "../common/string_util.h" +#include "masterentity.h" +#include "string_ids.h" +#include +#include int Mob::GetKickDamage() { From 7db731a47de5b4c84611838a9a1fb2236af5a7d0 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 14:07:40 -0600 Subject: [PATCH 50/96] net.cpp #include cleanup net.cpp forward declaration --- zone/net.cpp | 89 ++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 51 deletions(-) diff --git a/zone/net.cpp b/zone/net.cpp index 034c30747..e82a29bca 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -18,57 +18,39 @@ #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/debug.h" +#include "../common/eq_stream_factory.h" +#include "../common/eq_stream_ident.h" +#include "../common/eqemu_error.h" +#include "../common/eqemu_exception.h" +#include "../common/features.h" #include "../common/ipc_mutex.h" #include "../common/memory_mapped_file.h" -#include "../common/eqemu_exception.h" +#include "../common/patches/patches.h" +#include "../common/platform.h" +#include "../common/rulesys.h" #include "../common/spdat.h" +#include "../common/timer.h" +#include "../common/version.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 "command.h" +#include "embparser.h" +#include "guild_mgr.h" +#include "lua_parser.h" +#include "net.h" +#include "queryserv.h" +#include "quest_parser_collection.h" #include "questmgr.h" +#include "tasks.h" +#include "titles.h" +#include "worldserver.h" +#include "zone_config.h" +#include "zone.h" -#include -#include -#include - -#include -#include #include -#include #ifdef _CRTDBG_MAP_ALLOC #undef new @@ -86,20 +68,25 @@ volatile bool RunLoops = true; extern volatile bool ZoneLoaded; -TimeoutManager timeout_manager; -NetConnection net; -EntityList entity_list; -WorldServer worldserver; -uint32 numclients = 0; +class EQStream; +class EQStreamInterface; + char errorname[32]; -uint16 adverrornum = 0; -extern Zone* zone; +EntityList entity_list; EQStreamFactory eqsf(ZoneStream); +extern Zone* zone; +NetConnection net; npcDecayTimes_Struct npcCorpseDecayTimes[100]; -TitleManager title_manager; QueryServ *QServ = 0; -TaskManager *taskmanager = 0; QuestParserCollection *parse = 0; +TaskManager *taskmanager = 0; +TimeoutManager timeout_manager; +TitleManager title_manager; +WorldServer worldserver; + +uint16 adverrornum = 0; +uint32 numclients = 0; + const SPDat_Spell_Struct* spells; void LoadSpells(EQEmu::MemoryMappedFile **mmf); From b06fec6ad0a5e5482d8ce4a0ba9a029c6efa64a5 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 14:11:16 -0600 Subject: [PATCH 51/96] attack.cpp #include cleanup --- zone/attack.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index ef18f6fae..65c3fd9d1 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -21,28 +21,22 @@ #endif #include "../common/debug.h" -#include -#include -#include -#include -#include -#include - -#include "masterentity.h" -#include "npc_ai.h" -#include "../common/packet_dump.h" -#include "../common/eq_packet_structs.h" #include "../common/eq_constants.h" +#include "../common/eq_packet_structs.h" +#include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" -#include "zone.h" -#include "string_ids.h" #include "../common/string_util.h" -#include "../common/rulesys.h" +#include "queryserv.h" #include "quest_parser_collection.h" +#include "string_ids.h" #include "water_map.h" #include "worldserver.h" -#include "queryserv.h" +#include "zone.h" + +#include +#include +#include extern QueryServ* QServ; extern WorldServer worldserver; From ad603fd213e429bfea0042c0c7ad3d9d92c42510 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 14:39:27 -0600 Subject: [PATCH 52/96] loottable.cpp #include fix, previously reliant on npc.h to get to loottable.h npc.cpp #include cleanup npc.h #include cleanup and forward declaration --- zone/loottables.cpp | 1 + zone/npc.cpp | 50 +++++++++++++++++++++++---------------------- zone/npc.h | 27 ++++++++++++------------ 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 0c66778bd..121dad8c5 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -22,6 +22,7 @@ #include "npc.h" #include "masterentity.h" #include "zonedb.h" +#include "../common/loottable.h" #include "../common/misc_functions.h" #ifdef _WINDOWS #define snprintf _snprintf diff --git a/zone/npc.cpp b/zone/npc.cpp index eae42b670..b8d838d6d 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -15,15 +15,34 @@ 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/bodytypes.h" +#include "../common/classes.h" #include "../common/debug.h" -#include -#include -#include -#include -#include "../common/moremath.h" -#include -#include "../common/packet_dump_file.h" +#include "../common/misc_functions.h" +#include "../common/rulesys.h" +#include "../common/seperator.h" +#include "../common/spdat.h" +#include "../common/string_util.h" +#include "../common/clientversions.h" +#include "../common/features.h" // +#include "../common/item.h" // +#include "../common/item_struct.h" // +#include "../common/linked_list.h" // +#include "../common/servertalk.h" + +#include "aa.h" +#include "client.h" +#include "entity.h" +#include "npc.h" +#include "string_ids.h" +#include "spawn2.h" #include "zone.h" + +#include +#include +#include + #ifdef _WINDOWS #define snprintf _snprintf #define strncasecmp _strnicmp @@ -33,27 +52,10 @@ #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/misc_functions.h" -#include "../common/string_util.h" -#include "../common/rulesys.h" -#include "string_ids.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 "quest_parser_collection.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, diff --git a/zone/npc.h b/zone/npc.h index a88ae9176..cccf3ecf0 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -18,20 +18,17 @@ #ifndef NPC_H #define NPC_H -class NPC; -#include "zonedb.h" -#include "mob.h" -//#include "spawn.h" - -#include -#include - -#include "spawn2.h" -#include "../common/loottable.h" -#include "zonedump.h" -#include "qglobals.h" #include "../common/rulesys.h" +#include "mob.h" +#include "qglobals.h" +#include "zonedb.h" +#include "zonedump.h" + +#include +#include + + #ifdef _WINDOWS #define M_PI 3.141592 #endif @@ -88,8 +85,12 @@ struct AISpellsVar_Struct { uint8 idle_beneficial_chance; }; - class AA_SwarmPetInfo; +class Client; +class Group; +class Raid; +class Spawn2; +struct Item_Struct; class NPC : public Mob { From cb6948b6fd526103b55a538498075d00aa46e303 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 15:02:34 -0600 Subject: [PATCH 53/96] npc.cpp #include cleanup entity.cpp #include cleanup --- zone/entity.cpp | 18 +++++++----------- zone/npc.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 781e1164e..cae20c3ce 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -30,19 +29,16 @@ #include "../common/unix.h" #endif -#include "net.h" -#include "masterentity.h" -#include "worldserver.h" -#include "../common/guilds.h" -#include "../common/packet_dump.h" -#include "../common/packet_functions.h" -#include "petitions.h" -#include "../common/spdat.h" #include "../common/features.h" -#include "string_ids.h" +#include "../common/guilds.h" +#include "../common/spdat.h" #include "guild_mgr.h" -#include "raids.h" +#include "net.h" +#include "petitions.h" #include "quest_parser_collection.h" +#include "raids.h" +#include "string_ids.h" +#include "worldserver.h" #ifdef _WINDOWS #define snprintf _snprintf diff --git a/zone/npc.cpp b/zone/npc.cpp index b8d838d6d..b5716e845 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -25,10 +25,10 @@ #include "../common/spdat.h" #include "../common/string_util.h" #include "../common/clientversions.h" -#include "../common/features.h" // -#include "../common/item.h" // -#include "../common/item_struct.h" // -#include "../common/linked_list.h" // +#include "../common/features.h" +#include "../common/item.h" +#include "../common/item_struct.h" +#include "../common/linked_list.h" #include "../common/servertalk.h" #include "aa.h" From 6d52f3c02aa6289d171725c7ddc555373129f77b Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 15:08:16 -0600 Subject: [PATCH 54/96] aa.cpp #include cleanup aa.h #include cleanup --- zone/aa.cpp | 78 ++++++++++------------------------------------------- zone/aa.h | 3 ++- 2 files changed, 16 insertions(+), 65 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 3a3101746..a8c6ff3d0 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -16,84 +16,34 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// Test 1 - -#include - -#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/debug.h" #include "../common/eq_packet_structs.h" #include "../common/packet_dump.h" +#include "../common/races.h" +#include "../common/spdat.h" #include "../common/string_util.h" -#include "../common/logsys.h" -#include "zonedb.h" -#include "string_ids.h" + +#include "aa.h" +#include "client.h" +#include "corpse.h" +#include "groups.h" +#include "mob.h" #include "queryserv.h" +#include "raids.h" +#include "string_ids.h" +#include "titles.h" +#include "zonedb.h" extern QueryServ* QServ; -//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); diff --git a/zone/aa.h b/zone/aa.h index b143aae9a..00f74e8c6 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -2,7 +2,8 @@ #ifndef AA_H #define AA_H -#include "../common/eq_packet_structs.h" +struct AA_Ability; +struct SendAA_Struct; #define MANA_BURN 664 From 88984a3960a1a194a68ed8d4f304fc3db913e841 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 15:44:09 -0600 Subject: [PATCH 55/96] petitions.cpp #include cleanup petititons.h #include cleanup --- zone/petitions.cpp | 15 +++------------ zone/petitions.h | 10 ++++++---- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/zone/petitions.cpp b/zone/petitions.cpp index ba57fe7f2..ad38bc04d 100644 --- a/zone/petitions.cpp +++ b/zone/petitions.cpp @@ -16,10 +16,6 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "../common/debug.h" -#include -#include -#include -#include #include #ifdef _WINDOWS #include @@ -32,16 +28,12 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif -#include "../common/string_util.h" -#include "../common/packet_functions.h" -#include "../common/packet_dump.h" -#include "../common/packet_dump_file.h" -#include "../common/emu_opcodes.h" + + #include "../common/eq_packet_structs.h" #include "../common/servertalk.h" +#include "../common/string_util.h" #include "entity.h" -#include "masterentity.h" - #include "petitions.h" #include "worldserver.h" @@ -49,7 +41,6 @@ PetitionList petition_list; extern WorldServer worldserver; - void Petition::SendPetitionToPlayer(Client* clientto) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_PetitionCheckout,sizeof(Petition_Struct)); Petition_Struct* pet = (Petition_Struct*) outapp->pBuffer; diff --git a/zone/petitions.h b/zone/petitions.h index 4b68362e0..604d4ddcc 100644 --- a/zone/petitions.h +++ b/zone/petitions.h @@ -19,11 +19,13 @@ #define PETITIONS_H #include "../common/linked_list.h" -#include "../common/types.h" -#include "zonedb.h" -#include "client.h" -#include "../common/mutex.h" #include "../common/misc_functions.h" +#include "../common/mutex.h" +#include "../common/types.h" +#include "client.h" +#include "zonedb.h" + +class Client; class Petition { From 3577ff5a8135a8f29a366bdf410e86c46baa43ab Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 15:53:17 -0600 Subject: [PATCH 56/96] waypoints.cpp #include cleanup --- zone/waypoints.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index cfefe73f3..908f0f946 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -19,21 +19,17 @@ #ifdef _EQDEBUG #include #endif -//#include -#include -#include -#include "npc.h" -#include "masterentity.h" -#include "npc_ai.h" -#include "map.h" -#include "water_map.h" -#include "../common/moremath.h" -#include "string_ids.h" -#include "../common/misc_functions.h" -#include "../common/string_util.h" -#include "../common/rulesys.h" + #include "../common/features.h" +#include "../common/misc_functions.h" +#include "../common/rulesys.h" +#include "../common/string_util.h" +#include "map.h" +#include "npc.h" #include "quest_parser_collection.h" +#include "water_map.h" +#include +#include struct wp_distance { From 2d052a7a283f1617008b60a01cd1890d5eebc834 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 15:56:51 -0600 Subject: [PATCH 57/96] mod_functions.cpp #include cleanup --- zone/mod_functions.cpp | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index b948dff38..6ae0eddad 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -1,22 +1,15 @@ -#include "../common/debug.h" -#include "../common/timer.h" -#include -#include -#include "spawn2.h" -#include "entity.h" -#include "masterentity.h" -#include "zone.h" -#include "spawngroup.h" -#include "zonedb.h" -#include "npc.h" -#include "mob.h" #include "client.h" +#include "entity.h" +#include "mob.h" +#include "npc.h" #include "worldserver.h" -#include "quest_parser_collection.h" -#include "event_codes.h" -#include "embparser.h" -#include -#include +#include "zone.h" + +class ItemInst; +class Spawn2; +struct Consider_Struct; +struct DBTradeskillRecipe_Struct; +struct Item_Struct; extern EntityList entity_list; extern Zone* zone; From f5ba442ba69dae323e602562ab388cd02fa9fe2f Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 15:59:24 -0600 Subject: [PATCH 58/96] spells.cpp #include cleanup --- zone/spells.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 1b78030e6..3bdc3557e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -66,20 +66,19 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) and not SpellFinished(). */ -#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/debug.h" +#include "../common/item.h" #include "../common/rulesys.h" +#include "../common/skills.h" +#include "../common/spdat.h" #include "../common/string_util.h" -#include +#include "quest_parser_collection.h" +#include "string_ids.h" +#include "worldserver.h" #include +#include #ifndef WIN32 #include @@ -90,8 +89,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/packet_dump_file.h" #endif -#include "string_ids.h" -#include "quest_parser_collection.h" + extern Zone* zone; extern volatile bool ZoneLoaded; From c7a79d81ca3100ee097f2fd384f3808bdb0356e7 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 16:28:48 -0600 Subject: [PATCH 59/96] pets.cpp #include cleanup --- zone/pets.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/zone/pets.cpp b/zone/pets.cpp index 1f61b227b..cf9ecab8c 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -15,30 +15,26 @@ 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/misc_functions.h" #include "../common/spdat.h" -#include "masterentity.h" -#include "../common/packet_dump.h" -#include "../common/moremath.h" -#include "../common/item.h" -#include "zonedb.h" -#include "worldserver.h" -#include "../common/skills.h" -#include "../common/bodytypes.h" -#include "../common/classes.h" #include "../common/string_util.h" +#include "../common/types.h" + +#include "entity.h" +#include "client.h" +#include "mob.h" + #include "pets.h" -#include -#include +#include "worldserver.h" +#include "zonedb.h" + #ifndef WIN32 #include #include "../common/unix.h" #endif -#include "string_ids.h" - -/////////////////////////////////////////////////////////////////////////////// -// pet related functions const char *GetRandPetName() { From 9821c7da6518247bf3f1fbd2632b167ef8d7fa72 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 16:32:49 -0600 Subject: [PATCH 60/96] zoning.cpp #include cleanup --- zone/zoning.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 6ac85cff6..71ea65dc8 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -15,17 +15,15 @@ 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 "zone.h" -#include "worldserver.h" -#include "masterentity.h" -#include "../common/packet_dump.h" +#include "../common/debug.h" #include "../common/rulesys.h" #include "../common/string_util.h" -#include "string_ids.h" -#include "quest_parser_collection.h" #include "queryserv.h" +#include "quest_parser_collection.h" +#include "string_ids.h" +#include "worldserver.h" +#include "zone.h" extern QueryServ* QServ; extern WorldServer worldserver; From 55620305949a515c4427594d3c33319f1b9bcce3 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 16:43:19 -0600 Subject: [PATCH 61/96] guild.cpp #include cleanup spell_effects.cpp #include cleanup --- zone/guild.cpp | 16 +++------------- zone/spell_effects.cpp | 20 +++++++++----------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/zone/guild.cpp b/zone/guild.cpp index 5f8378d2b..58b0f006e 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -15,23 +15,13 @@ 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 "worldserver.h" -#include "net.h" + #include "../common/database.h" -#include "../common/spdat.h" -#include "../common/packet_dump.h" -#include "../common/packet_functions.h" -#include "petitions.h" -#include "../common/serverinfo.h" -#include "../common/zone_numbers.h" -#include "../common/moremath.h" #include "../common/guilds.h" #include "../common/string_util.h" + #include "guild_mgr.h" -#include "string_ids.h" -#include "npc_ai.h" +#include "worldserver.h" extern WorldServer worldserver; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b55102072..620d2669c 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -15,26 +15,24 @@ 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/debug.h" +#include "../common/item.h" #include "../common/rulesys.h" +#include "../common/skills.h" +#include "../common/spdat.h" +#include "quest_parser_collection.h" +#include "string_ids.h" +#include "worldserver.h" #include -#include + #ifndef WIN32 #include #include "../common/unix.h" #endif -#include "string_ids.h" -#include "quest_parser_collection.h" extern Zone* zone; extern volatile bool ZoneLoaded; From 34b19508207cd2a499d63cef98bc9854850646b4 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 16:46:43 -0600 Subject: [PATCH 62/96] forage.cpp #include cleanup --- zone/forage.cpp | 68 ++++++++++--------------------------------------- 1 file changed, 13 insertions(+), 55 deletions(-) diff --git a/zone/forage.cpp b/zone/forage.cpp index d1008031a..cbb6550db 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -15,75 +15,33 @@ 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 - -#ifdef _WINDOWS -#define snprintf _snprintf -#endif - -#include "forage.h" -#include "entity.h" -#include "masterentity.h" -#include "npc.h" -#include "water_map.h" -#include "titles.h" -#include "string_ids.h" #include "../common/misc_functions.h" -#include "../common/string_util.h" #include "../common/rulesys.h" +#include "../common/string_util.h" +#include "entity.h" +#include "forage.h" +#include "npc.h" +#include "quest_parser_collection.h" +#include "string_ids.h" +#include "titles.h" +#include "water_map.h" #include "zonedb.h" + +#include + #ifdef _WINDOWS #define snprintf _snprintf #endif -#include "quest_parser_collection.h" +struct NPCType; //max number of items which can be in the foraging table //for a given zone. #define FORAGE_ITEM_LIMIT 50 -/* - -The fishing and foraging need some work... -foraging currently gives each item an equal chance of dropping -fishing gives items which come in last from the select a very -very low chance of dropping. - - -Schema: -CREATE TABLE forage ( - id int(11) NOT NULL auto_increment, - zoneid int(4) NOT NULL default '0', - Itemid int(11) NOT NULL default '0', - level smallint(6) NOT NULL default '0', - chance smallint(6) NOT NULL default '0', - PRIMARY KEY (id) -) TYPE=MyISAM; - -old table upgrade: -alter table forage add chance smallint(6) NOT NULL default '0'; -update forage set chance=100; - - -CREATE TABLE fishing ( - id int(11) NOT NULL auto_increment, - zoneid int(4) NOT NULL default '0', - Itemid int(11) NOT NULL default '0', - skill_level smallint(6) NOT NULL default '0', - chance smallint(6) NOT NULL default '0', - npc_id int NOT NULL default 0, - npc_chance int NOT NULL default 0, - PRIMARY KEY (id) -) TYPE=MyISAM; - - -*/ - -// This allows EqEmu to have zone specific foraging - BoB uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) { uint32 item[FORAGE_ITEM_LIMIT]; From 4a597a2b38869410ad25fdecb5a93f6ad4ab5996 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 16:48:48 -0600 Subject: [PATCH 63/96] tradeskills.cpp #include cleanup --- zone/tradeskills.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 82d84e5cf..fd9f5a632 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -24,17 +24,14 @@ #include //for htonl #endif -#include "masterentity.h" -#include "zonedb.h" -#include "../common/packet_functions.h" -#include "../common/packet_dump.h" -#include "titles.h" -#include "string_ids.h" #include "../common/misc_functions.h" -#include "../common/string_util.h" #include "../common/rulesys.h" -#include "quest_parser_collection.h" +#include "../common/string_util.h" #include "queryserv.h" +#include "quest_parser_collection.h" +#include "string_ids.h" +#include "titles.h" +#include "zonedb.h" extern QueryServ* QServ; From fde9517247ed1ffea4a019d137f928cdbcfe58ae Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 16:55:35 -0600 Subject: [PATCH 64/96] mob.cpp #include cleanup mob.h declarations mob.h #include cleanup --- zone/mob.cpp | 14 +++++++------- zone/mob.h | 13 ++++++++++--- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 35a019252..6772ff432 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -15,17 +15,17 @@ 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 "string_ids.h" -#include "worldserver.h" -#include "quest_parser_collection.h" #include "../common/string_util.h" -#include -#include +#include "quest_parser_collection.h" +#include "string_ids.h" +#include "worldserver.h" + #include +#include +#include extern EntityList entity_list; diff --git a/zone/mob.h b/zone/mob.h index 944dfc515..55147ff7a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -18,21 +18,28 @@ #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 Client; +class EQApplicationPacket; +class Group; +class ItemInst; +class NPC; +class Raid; +struct Item_Struct; +struct NewSpawn_Struct; +struct PlayerPositionUpdateServer_Struct; + class Mob : public Entity { public: enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD, From ad2fd9e4d5415f89b4baa17dc1a4029216af4c03 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 29 Nov 2014 21:10:51 -0500 Subject: [PATCH 65/96] update to projectile move check --- zone/common.h | 3 ++- zone/mob.cpp | 3 ++- zone/special_attacks.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/zone/common.h b/zone/common.h index 267831368..ddb7b4b0a 100644 --- a/zone/common.h +++ b/zone/common.h @@ -468,7 +468,8 @@ typedef struct float origin_x; float origin_y; float origin_z; - float sanitycheck; + float tlast_x; + float tlast_y; uint32 ranged_id; uint32 ammo_id; int ammo_slot; diff --git a/zone/mob.cpp b/zone/mob.cpp index 7261aeb46..58aafa1cb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -297,7 +297,8 @@ Mob::Mob(const char* in_name, ProjectileAtk[i].origin_x = 0.0f; ProjectileAtk[i].origin_y = 0.0f; ProjectileAtk[i].origin_z = 0.0f; - ProjectileAtk[i].sanitycheck = 0.0f; + ProjectileAtk[i].tlast_x = 0.0f; + ProjectileAtk[i].tlast_y = 0.0f; ProjectileAtk[i].ranged_id = 0; ProjectileAtk[i].ammo_id = 0; ProjectileAtk[i].ammo_slot = 0; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index c73a2cb11..0ba5ebe09 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1077,11 +1077,10 @@ void Mob::ProjectileAttack() 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. - float _sanitycheck = target->GetX() * target->GetY(); - if (ProjectileAtk[i].sanitycheck != _sanitycheck){ - ProjectileAtk[i].sanitycheck = _sanitycheck; + if (ProjectileAtk[i].tlast_x != target->GetX() || ProjectileAtk[i].tlast_y != target->GetY()){ + ProjectileAtk[i].tlast_x = target->GetX(); + ProjectileAtk[i].tlast_y = target->GetY(); float distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) ProjectileAtk[i].hit_increment = static_cast(hit); @@ -1103,7 +1102,8 @@ void Mob::ProjectileAttack() ProjectileAtk[i].origin_x = 0.0f; ProjectileAtk[i].origin_y = 0.0f; ProjectileAtk[i].origin_z = 0.0f; - ProjectileAtk[i].sanitycheck = 0.0f; + ProjectileAtk[i].tlast_x = 0.0f; + ProjectileAtk[i].tlast_y = 0.0f; ProjectileAtk[i].ranged_id = 0; ProjectileAtk[i].ammo_id = 0; ProjectileAtk[i].ammo_slot = 0; From 0d0917b779f3acfba564fb201d83d408d78c4299 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 29 Nov 2014 23:12:09 -0600 Subject: [PATCH 66/96] Temporary revert of net.cpp to wave 1 of cleanups --- zone/net.cpp | 92 +++++++++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/zone/net.cpp b/zone/net.cpp index e82a29bca..9b4080eb2 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -18,39 +18,57 @@ #define DONT_SHARED_OPCODES - -#include "../common/crash.h" #include "../common/debug.h" -#include "../common/eq_stream_factory.h" -#include "../common/eq_stream_ident.h" -#include "../common/eqemu_error.h" -#include "../common/eqemu_exception.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/patches/patches.h" -#include "../common/platform.h" -#include "../common/rulesys.h" +#include "../common/eqemu_exception.h" #include "../common/spdat.h" -#include "../common/timer.h" -#include "../common/version.h" -#include "client_logs.h" -#include "command.h" -#include "embparser.h" -#include "guild_mgr.h" -#include "lua_parser.h" -#include "net.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "questmgr.h" -#include "tasks.h" -#include "titles.h" -#include "worldserver.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 @@ -68,25 +86,20 @@ volatile bool RunLoops = true; extern volatile bool ZoneLoaded; -class EQStream; -class EQStreamInterface; - -char errorname[32]; -EntityList entity_list; -EQStreamFactory eqsf(ZoneStream); -extern Zone* zone; -NetConnection net; -npcDecayTimes_Struct npcCorpseDecayTimes[100]; -QueryServ *QServ = 0; -QuestParserCollection *parse = 0; -TaskManager *taskmanager = 0; TimeoutManager timeout_manager; -TitleManager title_manager; +NetConnection net; +EntityList entity_list; WorldServer worldserver; - -uint16 adverrornum = 0; 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); @@ -629,4 +642,3 @@ void UpdateWindowTitle(char* iNewTitle) { SetConsoleTitle(tmp); #endif } - From e04496188b118e56ce2dbc4a5d7a0ee4ffde6f63 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 30 Nov 2014 01:43:51 -0500 Subject: [PATCH 67/96] Spell Projectiles have been revamped to use new system. --- zone/client_process.cpp | 3 --- zone/common.h | 1 + zone/mob.cpp | 53 ++-------------------------------------- zone/mob.h | 17 ++++--------- zone/mob_ai.cpp | 1 - zone/npc.cpp | 3 +-- zone/special_attacks.cpp | 36 +++++++++++++++------------ zone/spell_effects.cpp | 47 ++++++++++++++++++++--------------- 8 files changed, 57 insertions(+), 104 deletions(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index dfadde437..c2e3ae1f3 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -566,9 +566,6 @@ bool Client::Process() { } ProjectileAttack(); - - if(projectile_timer.Check()) - SpellProjectileEffect(); if(spellbonuses.GravityEffect == 1) { if(gravity_timer.Check()) diff --git a/zone/common.h b/zone/common.h index ddb7b4b0a..477d5b876 100644 --- a/zone/common.h +++ b/zone/common.h @@ -474,6 +474,7 @@ typedef struct uint32 ammo_id; int ammo_slot; uint8 skill; + float speed_mod; } tProjatk; //eventually turn this into a typedef and diff --git a/zone/mob.cpp b/zone/mob.cpp index 58aafa1cb..afb9889fe 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -279,14 +279,6 @@ Mob::Mob(const char* in_name, 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(); - ActiveProjectileATK = false; for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { @@ -303,6 +295,8 @@ Mob::Mob(const char* in_name, ProjectileAtk[i].ammo_id = 0; ProjectileAtk[i].ammo_slot = 0; ProjectileAtk[i].skill = 0; + ProjectileAtk[i].speed_mod = 0.0f; + } memset(&itembonuses, 0, sizeof(StatBonuses)); @@ -4253,49 +4247,6 @@ bool Mob::TryReflectSpell(uint32 spell_id) 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 = static_cast(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; diff --git a/zone/mob.h b/zone/mob.h index 49c37d783..0e04c43b1 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -237,8 +237,7 @@ public: 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); + bool TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed = 1.5f); 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); @@ -729,10 +728,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 HitChance=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); + 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); - bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot); + 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); void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } @@ -851,7 +850,7 @@ public: // HP Event inline int GetNextHPEvent() const { return nexthpevent; } void SetNextHPEvent( int hpevent ); - void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse); + void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse, float velocity= 4.0); inline int& GetNextIncHPEvent() { return nextinchpevent; } void SetNextIncHPEvent( int inchpevent ); @@ -1101,12 +1100,6 @@ protected: 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]; - bool ActiveProjectileATK; tProjatk ProjectileAtk[MAX_SPELL_PROJECTILE]; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 614ba984d..30f435dfa 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -597,7 +597,6 @@ void Mob::AI_ShutDown() { tic_timer.Disable(); mana_timer.Disable(); spellend_timer.Disable(); - projectile_timer.Disable(); rewind_timer.Disable(); bindwound_timer.Disable(); stunned_timer.Disable(); diff --git a/zone/npc.cpp b/zone/npc.cpp index b5716e845..17ab9ed48 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -670,8 +670,7 @@ bool NPC::Process() viral_timer_counter = 0; } - if(projectile_timer.Check()) - SpellProjectileEffect(); + ProjectileAttack(); if(spellbonuses.GravityEffect == 1) { if(gravity_timer.Check()) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 0ba5ebe09..481599bac 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -596,7 +596,6 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = wpn->GetAugment(i); - if(aug) { backstab_dmg += aug->GetItem()->BackstabDmg; } @@ -806,7 +805,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) { + uint32 range_id, uint32 ammo_id, const Item_Struct *AmmoItem, int AmmoSlot, float speed) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -870,7 +869,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, SkillArchery, 0, RangeWeapon, Ammo, AmmoSlot); + TryProjectileAttack(other, AmmoItem, SkillArchery, 0, RangeWeapon, Ammo, AmmoSlot, speed); return; } else @@ -895,7 +894,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); + TryProjectileAttack(other, AmmoItem, SkillArchery, WDmg, RangeWeapon, Ammo, AmmoSlot, speed); return; } @@ -1010,7 +1009,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){ +bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ if (!other) return false; @@ -1024,12 +1023,15 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes break; } } - + speed = 2.0f; + Shout("Speed %.2f", speed); if (slot < 0) return false; + float speed_mod = speed * 0.45f; + float distance = other->CalculateDistance(GetX(), GetY(), GetZ()); - float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) + float hit = 60.0f + (distance / speed_mod); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) ProjectileAtk[slot].increment = 1; ProjectileAtk[slot].hit_increment = static_cast(hit); //This projected hit time if target does NOT MOVE @@ -1047,13 +1049,14 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes ProjectileAtk[slot].ammo_slot = 0; ProjectileAtk[slot].skill = skillInUse; + ProjectileAtk[slot].speed_mod = speed_mod; SetProjectileAttack(true); if(item) - SendItemAnimation(other, item, skillInUse); + SendItemAnimation(other, item, skillInUse, speed); else if (IsNPC()) - ProjectileAnimation(other, 0,false,0,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse); + ProjectileAnimation(other, 0,false,speed,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse); return true; } @@ -1082,7 +1085,7 @@ void Mob::ProjectileAttack() ProjectileAtk[i].tlast_x = target->GetX(); ProjectileAtk[i].tlast_y = target->GetY(); float distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); - float hit = 60.0f + (distance / 1.8f); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) + float hit = 60.0f + (distance / ProjectileAtk[i].speed_mod); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) ProjectileAtk[i].hit_increment = static_cast(hit); } } @@ -1094,6 +1097,8 @@ void Mob::ProjectileAttack() 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) 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)) + SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true); } ProjectileAtk[i].increment = 0; @@ -1108,6 +1113,7 @@ void Mob::ProjectileAttack() ProjectileAtk[i].ammo_id = 0; ProjectileAtk[i].ammo_slot = 0; ProjectileAtk[i].skill = 0; + ProjectileAtk[i].speed_mod = 0.0f; } else { @@ -1355,7 +1361,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 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) +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) || @@ -1406,7 +1412,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (ProjectileMiss || !other->CheckHitChance(this, SkillThrowing, MainPrimary, chance_mod)){ mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot); + TryProjectileAttack(other, AmmoItem, SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); return; } else @@ -1423,7 +1429,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite WDmg = GetWeaponDamage(other, AmmoItem); if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, SkillThrowing, WDmg, RangeWeapon, nullptr, AmmoSlot); + TryProjectileAttack(other, AmmoItem, SkillThrowing, WDmg, RangeWeapon, nullptr, AmmoSlot, speed); return; } } @@ -1488,7 +1494,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } -void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse) { +void Mob::SendItemAnimation(Mob *to, const 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; @@ -1516,7 +1522,7 @@ void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skil Arc causes the object to form an arc in motion. A value too high will */ - as->velocity = 4.0; + as->velocity = velocity; //these angle and tilt used together seem to make the arrow/knife throw as straight as I can make it diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 620d2669c..79fe70e00 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6400,17 +6400,16 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama return false; } -bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){ +bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){ /*For mage 'Bolt' line and other various spells. -This is mostly accurate for how the modern clients handle this effect. -It was changed at some point to use an actual projectile as done here (opposed to a particle effect in classic) - -The projectile graphic appears to be that of 'Ball of Sunlight' ID 80648 and will be visible to anyone in SoF+ -There is no LOS check to prevent a bolt from being cast. If you don't have LOS your bolt simply goes into whatever barrier 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 timer checks the distance from the initial cast to the target repeatedly - and calculates at what predicted time the bolt should hit that target in client_process (therefore accounting for any target movement). + -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 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. @@ -6422,31 +6421,41 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){ return false; uint8 anim = spells[spell_id].CastingAnim; - int bolt_id = -1; + int slot = -1; //Make sure there is an avialable bolt to be cast. for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { - if (projectile_spell_id[i] == 0){ - bolt_id = i; + if (ProjectileAtk[slot].target_id == 0){ + slot = i; break; } } - if (bolt_id < 0) + if (slot < 0) return false; if (CheckLosFN(spell_target)) { - projectile_spell_id[bolt_id] = spell_id; - projectile_target_id[bolt_id] = spell_target->GetID(); - projectile_x[bolt_id] = GetX(), projectile_y[bolt_id] = GetY(), projectile_z[bolt_id] = GetZ(); - projectile_increment[bolt_id] = 1; - projectile_timer.Start(250); + 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); + + ProjectileAtk[slot].increment = 1; + ProjectileAtk[slot].hit_increment = static_cast(hit); //This projected hit time if target does NOT MOVE + ProjectileAtk[slot].target_id = spell_target->GetID(); + ProjectileAtk[slot].wpn_dmg = spell_id; //Store spell_id in weapon damage field + ProjectileAtk[slot].origin_x = GetX(); + ProjectileAtk[slot].origin_y = GetY(); + ProjectileAtk[slot].origin_z = GetZ(); + ProjectileAtk[slot].skill = SkillConjuration; + ProjectileAtk[slot].speed_mod = speed_mod; + + SetProjectileAttack(true); } //This will use the correct graphic as defined in the player_1 field of spells_new table. Found in UF+ spell files. if (RuleB(Spells, UseLiveSpellProjectileGFX)) { - ProjectileAnimation(spell_target,0, false, 1.5,0,0,0, spells[spell_id].player_1); + 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. @@ -6456,19 +6465,17 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){ if (IsClient()){ if (CastToClient()->GetClientVersionBit() <= 4) //Titanium needs alternate graphic. - ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_Titanium)), false, 1.5); + ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_Titanium)), false, speed); else - ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_SOF)), false, 1.5); + ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_SOF)), false, speed); } else - ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_NPC)), false, 1.5); - + ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_NPC)), false, speed); } - //Default to an arrow if not using a mage bolt (Use up to date spell file and enable above rules for best results) else - ProjectileAnimation(spell_target,0, 1, 1.5); + ProjectileAnimation(spell_target,0, 1, speed); } if (spells[spell_id].CastingAnim == 64) From 8dfd61bbcf71e1447a784615413df1e335c21105 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 30 Nov 2014 01:58:23 -0500 Subject: [PATCH 68/96] fix --- zone/mob.cpp | 1 - zone/special_attacks.cpp | 3 +-- zone/spell_effects.cpp | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index afb9889fe..e56f3839c 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -296,7 +296,6 @@ Mob::Mob(const char* in_name, ProjectileAtk[i].ammo_slot = 0; ProjectileAtk[i].skill = 0; ProjectileAtk[i].speed_mod = 0.0f; - } memset(&itembonuses, 0, sizeof(StatBonuses)); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 481599bac..cf6a83c80 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1023,8 +1023,7 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes break; } } - speed = 2.0f; - Shout("Speed %.2f", speed); + if (slot < 0) return false; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 79fe70e00..d3ef1145d 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6425,7 +6425,7 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){ //Make sure there is an avialable bolt to be cast. for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { - if (ProjectileAtk[slot].target_id == 0){ + if (ProjectileAtk[i].target_id == 0){ slot = i; break; } @@ -6433,7 +6433,7 @@ 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. From de84065cde04a46b66a6b6cefb6f764dcedea69f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 30 Nov 2014 02:32:11 -0500 Subject: [PATCH 69/96] Fix some debug statements --- 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 8f2450621..e2884e738 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -460,10 +460,10 @@ int Client::HandlePacket(const EQApplicationPacket *app) mlog(CLIENT__NET_ERR, "Unhandled incoming opcode: %s", buffer); if(app->size < 1000) - DumpPacket(app->pBuffer, app->size); + DumpPacket(app, app->size); else{ std::cout << "Dump limited to 1000 characters:\n"; - DumpPacket(app->pBuffer, 1000); + DumpPacket(app, 1000); } #endif break; From 4a7984f04db66bc25fbf4bd5a11e68c7bbdebd99 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 30 Nov 2014 18:32:45 -0500 Subject: [PATCH 70/96] Fix clang compile error --- zone/command.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index c9bef2e12..b2914cf46 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -9996,7 +9996,8 @@ void command_object(Client *c, const Seperator *sep) // Couldn't copy the object. - if (results.ErrorMessage().c_str() != '\0') { + // got an error message + if (!results.Success()) { c->Message(0, "Database Error: %s", results.ErrorMessage().c_str()); return; } From 7198e670aeae9a18dbea55ad3d1fd819f2212a03 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 30 Nov 2014 18:56:01 -0500 Subject: [PATCH 71/96] Clang bots compile fix --- zone/bot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index a68273fae..496ddc7ae 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -11864,7 +11864,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') || !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 targetted) "); return; From 1054bfe476c389a073150073c9fdc45b7550503b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 30 Nov 2014 20:32:00 -0600 Subject: [PATCH 72/96] command.cpp #include cleanup command.h #include cleanup command.h forward declarations --- zone/command.cpp | 9 +++++---- zone/command.h | 4 +--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index b2914cf46..453c58ec9 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -50,11 +50,16 @@ #include "../common/rulesys.h" #include "../common/serverinfo.h" #include "../common/string_util.h" + #include "client_logs.h" +#include "command.h" #include "guild_mgr.h" #include "map.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" @@ -64,11 +69,7 @@ extern WorldServer worldserver; extern TaskManager *taskmanager; void CatchSignal(int sig_num); -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "command.h" -#include "qglobals.h" //struct cl_struct *commandlist; // the actual linked list of commands int commandcount; // how many commands we have diff --git a/zone/command.h b/zone/command.h index ea710482b..72ee5c06a 100644 --- a/zone/command.h +++ b/zone/command.h @@ -23,9 +23,7 @@ class Client; class Seperator; -#include "../common/seperator.h" -#include "../common/eq_stream.h" -#include "client.h" +#include "../common/types.h" #define COMMAND_CHAR '#' #define CMDALIASES 5 From c98964a9e84e1fda6fa0bbe1376d5b01ee281a8a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Mon, 1 Dec 2014 10:33:57 -0800 Subject: [PATCH 73/96] Lua, perl, boost, zlib, mysql, and glm include files are now being included marked as system (library) files. warnings for these libraries are now suppressed --- CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e2f5f9e2..0b7569ed5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,8 +24,8 @@ #EQEMU_DISABLE_LOGSYS #EQEMU_COMMANDS_LOGGING #EQEMU_BUILD_SERVER -#EQEMU_BUILD_LOGIN -#EQEMU_BUILD_TESTS +#EQEMU_BUILD_LOGIN +#EQEMU_BUILD_TESTS #EQEMU_BUILD_PERL #EQEMU_BUILD_LUA #EQEMU_SANITIZE_LUA_LIBS @@ -103,7 +103,7 @@ IF(MSVC) SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /SAFESEH:NO") SET(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO") ENDIF(EQEMU_DISABLE_SAFESEH) - + OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON) IF(EQEMU_BUILD_MSVC_MP) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") @@ -115,7 +115,7 @@ IF(MSVC) STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") ENDIF(${flag_var} MATCHES "/MD") ENDFOREACH(flag_var) - + ADD_DEFINITIONS(-DNOMINMAX) ELSE(MSVC) #Normally set by perl but we don't use the perl flags anymore so we set it. @@ -306,26 +306,26 @@ FIND_PACKAGE(ZLIB REQUIRED) FIND_PACKAGE(MySQL REQUIRED) IF(EQEMU_BUILD_PERL) FIND_PACKAGE(PerlLibs REQUIRED) - INCLUDE_DIRECTORIES("${PERL_INCLUDE_PATH}") + INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}") ENDIF(EQEMU_BUILD_PERL) IF(EQEMU_BUILD_LUA) FIND_PACKAGE(EQLua51 REQUIRED) SET(Boost_USE_STATIC_LIBS OFF) - SET(Boost_USE_MULTITHREADED ON) + SET(Boost_USE_MULTITHREADED ON) SET(Boost_USE_STATIC_RUNTIME OFF) SET(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/boost") FIND_PACKAGE(Boost REQUIRED) - INCLUDE_DIRECTORIES("${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "luabind") - + INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "luabind") + OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON) IF(EQEMU_SANITIZE_LUA_LIBS) ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS) ENDIF(EQEMU_SANITIZE_LUA_LIBS) ENDIF(EQEMU_BUILD_LUA) -INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm") +INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm") IF(EQEMU_BUILD_LUA) ADD_SUBDIRECTORY(luabind) From 395be050a3329a5cbf3532e71f7a5cf5e71a5894 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 1 Dec 2014 18:13:12 -0500 Subject: [PATCH 74/96] Switch random function to std::mt19937 Added class EQEmu::Random Functions: EQEmu::Random::Int(int low, int high) EQEmu::Random::Real(double low, double high) EQEmu::Random::Roll(int required) EQEmu::Random::Roll(double required) EQEmu::Random::Reseed() For zone, you will access the random object through the zone object ex. zone->random.Int(0, 100); Int returns a random int between low and high Real returns a random double between low and high Roll(int) returns true if Int(0, 99) < required is true Roll(double) returns true if Real(0.0, 1.0) <= required is true --- common/CMakeLists.txt | 1 + common/misc_functions.cpp | 154 ------------------------------------ common/random.h | 67 ++++++++++++++++ loginserver/client.cpp | 2 +- loginserver/client.h | 3 + world/adventure.cpp | 6 +- world/adventure_manager.cpp | 4 +- world/client.cpp | 20 ++--- world/net.cpp | 2 + world/zonelist.cpp | 4 +- zone/aggro.cpp | 6 +- zone/attack.cpp | 154 +++++++++++++++++------------------- zone/bot.cpp | 146 +++++++++++++++++----------------- zone/botspellsai.cpp | 8 +- zone/client.cpp | 24 +++--- zone/client_packet.cpp | 38 ++++----- zone/client_process.cpp | 14 ++-- zone/command.cpp | 125 ++++++++++++++--------------- zone/effects.cpp | 90 +++++++++------------ zone/embparser_api.cpp | 2 +- zone/entity.cpp | 10 +-- zone/fearpath.cpp | 4 +- zone/forage.cpp | 26 +++--- zone/hate_list.cpp | 4 +- zone/loottables.cpp | 16 ++-- zone/merc.cpp | 106 ++++++++++++------------- zone/mob.cpp | 30 +++---- zone/mob_ai.cpp | 63 ++++++++------- zone/npc.cpp | 24 +++--- zone/object.cpp | 4 +- zone/pathing.cpp | 2 +- zone/pets.cpp | 2 +- zone/spawn2.cpp | 4 +- zone/spawngroup.cpp | 4 +- zone/special_attacks.cpp | 131 +++++++++++++++--------------- zone/spell_effects.cpp | 116 ++++++++++++--------------- zone/spells.cpp | 22 +++--- zone/tradeskills.cpp | 10 +-- zone/trap.cpp | 12 +-- zone/waypoints.cpp | 10 +-- zone/zone.cpp | 6 +- zone/zone.h | 6 +- 42 files changed, 683 insertions(+), 799 deletions(-) create mode 100644 common/random.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 01fcd6df8..07fb4f098 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -168,6 +168,7 @@ SET(common_headers ptimer.h queue.h races.h + random.h rdtsc.h rulesys.h ruletypes.h diff --git a/common/misc_functions.cpp b/common/misc_functions.cpp index 882cc61c7..81fc2434b 100644 --- a/common/misc_functions.cpp +++ b/common/misc_functions.cpp @@ -54,20 +54,6 @@ #include #endif -static bool WELLRNG_init = false; -static int state_i = 0; -static unsigned int STATE[R]; -static unsigned int z0, z1, z2; -unsigned int (*WELLRNG19937)(void); -static unsigned int case_1 (void); -static unsigned int case_2 (void); -static unsigned int case_3 (void); -static unsigned int case_4 (void); -static unsigned int case_5 (void); -static unsigned int case_6 (void); -uint32 rnd_hash(time_t t, clock_t c); -void oneseed(const uint32 seed); - void CoutTimestamp(bool ms) { time_t rawtime; struct tm* gmt_t; @@ -179,41 +165,6 @@ const char * itoa(int num, char* a,int b) { } #endif -/* - * generate a random integer in the range low-high this - * should be used instead of the rand()%limit method - */ -int MakeRandomInt(int low, int high) -{ - if(low >= high) - return(low); - - //return (rand()%(high-low+1) + (low)); - if(!WELLRNG_init) { - WELLRNG_init = true; - oneseed( rnd_hash( time(nullptr), clock() ) ); - WELLRNG19937 = case_1; - } - unsigned int randomnum = ((WELLRNG19937)()); - if(randomnum == 0xffffffffUL) - return high; - return int ((randomnum / (double)0xffffffffUL) * (high - low + 1) + low); -} - -double MakeRandomFloat(double low, double high) -{ - if(low >= high) - return(low); - - //return (rand() / (double)RAND_MAX * (high - low) + low); - if(!WELLRNG_init) { - WELLRNG_init = true; - oneseed( rnd_hash( time(nullptr), clock() ) ); - WELLRNG19937 = case_1; - } - return ((WELLRNG19937)() / (double)0xffffffffUL * (high - low) + low); -} - uint32 rnd_hash( time_t t, clock_t c ) { // Get a uint32 from t and c @@ -239,111 +190,6 @@ uint32 rnd_hash( time_t t, clock_t c ) return ( h1 + differ++ ) ^ h2; } -void oneseed( const uint32 seed ) -{ - // Initialize generator state with seed - // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. - // In previous versions, most significant bits (MSBs) of the seed affect - // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. - register int j = 0; - STATE[j] = seed & 0xffffffffUL; - for (j = 1; j < R; j++) - { - STATE[j] = ( 1812433253UL * ( STATE[j-1] ^ (STATE[j-1] >> 30) ) + j ) & 0xffffffffUL; - } -} - -// WELL RNG code - -/* ***************************************************************************** */ -/* Copyright: Francois Panneton and Pierre L'Ecuyer, University of Montreal */ -/* Makoto Matsumoto, Hiroshima University */ -/* Notice: This code can be used freely for personal, academic, */ -/* or non-commercial purposes. For commercial purposes, */ -/* please contact P. L'Ecuyer at: lecuyer@iro.UMontreal.ca */ -/* A modified "maximally equidistributed" implementation */ -/* by Shin Harase, Hiroshima University. */ -/* ***************************************************************************** */ - -unsigned int case_1 (void){ - // state_i == 0 - z0 = (VRm1Under & MASKL) | (VRm2Under & MASKU); - z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1); - z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3); - newV1 = z1 ^ z2; - newV0Under = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1); - state_i = R - 1; - WELLRNG19937 = case_3; - return (STATE[state_i] ^ (newVM2Over & BITMASK)); -} - -static unsigned int case_2 (void){ - // state_i == 1 - z0 = (VRm1 & MASKL) | (VRm2Under & MASKU); - z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1); - z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3); - newV1 = z1 ^ z2; - newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1); - state_i = 0; - WELLRNG19937 = case_1; - return (STATE[state_i] ^ (newVM2 & BITMASK)); -} - -static unsigned int case_3 (void){ - // state_i+M1 >= R - z0 = (VRm1 & MASKL) | (VRm2 & MASKU); - z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1Over); - z2 = MAT3POS (9, VM2Over) ^ MAT0POS (1, VM3Over); - newV1 = z1 ^ z2; - newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1); - state_i--; - if (state_i + M1 < R) - WELLRNG19937 = case_5; - return (STATE[state_i] ^ (newVM2Over & BITMASK)); -} - -static unsigned int case_4 (void){ - // state_i+M3 >= R - z0 = (VRm1 & MASKL) | (VRm2 & MASKU); - z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1); - z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3Over); - newV1 = z1 ^ z2; - newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1); - state_i--; - if (state_i + M3 < R) - WELLRNG19937 = case_6; - return (STATE[state_i] ^ (newVM2 & BITMASK)); -} - -static unsigned int case_5 (void){ - // state_i+M2 >= R - z0 = (VRm1 & MASKL) | (VRm2 & MASKU); - z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1); - z2 = MAT3POS (9, VM2Over) ^ MAT0POS (1, VM3Over); - newV1 = z1 ^ z2; - newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1); - state_i--; - if (state_i + M2 < R) - WELLRNG19937 = case_4; - return (STATE[state_i] ^ (newVM2Over & BITMASK)); -} - -static unsigned int case_6 (void){ - // 2 <= state_i <= (R - M3 - 1) - z0 = (VRm1 & MASKL) | (VRm2 & MASKU); - z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1); - z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3); - newV1 = z1 ^ z2; - newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1); - state_i--; - if (state_i == 1) - WELLRNG19937 = case_2; - return (STATE[state_i] ^ (newVM2 & BITMASK)); -} - -// end WELL RNG code - - float EQ13toFloat(int d) { return ( float(d)/float(1<<2)); diff --git a/common/random.h b/common/random.h new file mode 100644 index 000000000..0e7316007 --- /dev/null +++ b/common/random.h @@ -0,0 +1,67 @@ +#ifndef __random_h__ +#define __random_h__ + +#include +#include + +/* This uses mt19937 seeded with the std::random_device + * The idea is to have this be included as a member of another class + * so mocking out for testing is easier + * If you need to reseed random.Reseed() + * Eventually this should be derived from an abstract base class + */ + +namespace EQEmu { + class Random { + public: + // AKA old MakeRandomInt + const int Int(int low, int high) + { + if (low > high) + std::swap(low, high); + return std::uniform_int_distribution(low, high)(m_gen); // [low, high] + } + + // AKA old MakeRandomFloat + const double Real(double low, double high) + { + if (low > high) + std::swap(low, high); + return std::uniform_real_distribution(low, high)(m_gen); // [low, high) + } + + // example Roll(50) would have a 50% success rate + // Roll(100) 100%, etc + // valid values 0-100 (well, higher works too but ...) + const bool Roll(const int required) + { + return Int(0, 99) < required; + } + + // valid values 0.0 - 1.0 + const bool Roll(const double required) + { + return Real(0.0, 1.0) <= required; + } + + void Reseed() + { + // We could do the seed_seq thing here too if we need better seeding + // but that is mostly overkill for us, so just seed once + std::random_device rd; + m_gen.seed(rd()); + } + + Random() + { + Reseed(); + } + + private: + std::mt19937 m_gen; + }; +} + + +#endif /* !__random_h__ */ + diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 9883c059d..bc0a86fa8 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -389,7 +389,7 @@ void Client::GenerateKey() '6', '7', '8', '9' }; - key.append((const char*)&key_selection[MakeRandomInt(0, 35)], 1); + key.append((const char*)&key_selection[random.Int(0, 35)], 1); count++; } } diff --git a/loginserver/client.h b/loginserver/client.h index 3248aefb5..c1b44dc6f 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -22,6 +22,7 @@ #include "../common/opcodemgr.h" #include "../common/eq_stream_type.h" #include "../common/eq_stream_factory.h" +#include "../common/random.h" #ifndef WIN32 #include "eq_crypto_api.h" #endif @@ -129,6 +130,8 @@ public: * Gets the connection for this client. */ EQStream *GetConnection() { return connection; } + + EQEmu::Random random; private: EQStream *connection; ClientVersion version; diff --git a/world/adventure.cpp b/world/adventure.cpp index 80b1dcaca..b6db3d6d0 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -4,6 +4,7 @@ #include "../common/rulesys.h" #include "../common/misc_functions.h" #include "../common/string_util.h" +#include "../common/random.h" #include "adventure.h" #include "adventure_manager.h" #include "worlddb.h" @@ -14,6 +15,7 @@ extern ZSList zoneserver_list; extern ClientList client_list; extern AdventureManager adventure_manager; +extern EQEmu::Random emu_random; Adventure::Adventure(AdventureTemplate *t) { @@ -392,8 +394,8 @@ void Adventure::MoveCorpsesToGraveyard() for (auto iter = dbid_list.begin(); iter != dbid_list.end(); ++iter) { - float x = GetTemplate()->graveyard_x + MakeRandomFloat(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius); - float y = GetTemplate()->graveyard_y + MakeRandomFloat(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius); + float x = GetTemplate()->graveyard_x + emu_random.Real(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius); + float y = GetTemplate()->graveyard_y + emu_random.Real(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius); float z = GetTemplate()->graveyard_z; query = StringFormat("UPDATE character_corpses " diff --git a/world/adventure_manager.cpp b/world/adventure_manager.cpp index aeee8e3c5..47ea42c51 100644 --- a/world/adventure_manager.cpp +++ b/world/adventure_manager.cpp @@ -3,6 +3,7 @@ #include "../common/string_util.h" #include "../common/servertalk.h" #include "../common/rulesys.h" +#include "../common/random.h" #include "adventure.h" #include "adventure_manager.h" #include "worlddb.h" @@ -14,6 +15,7 @@ extern ZSList zoneserver_list; extern ClientList client_list; +extern EQEmu::Random emu_random; AdventureManager::AdventureManager() { @@ -325,7 +327,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data) if(eligible_adventures.size() > 0) { ea_iter = eligible_adventures.begin(); - int c_index = MakeRandomInt(0, (eligible_adventures.size()-1)); + int c_index = emu_random.Int(0, (eligible_adventures.size()-1)); for(int i = 0; i < c_index; ++i) { ++ea_iter; diff --git a/world/client.cpp b/world/client.cpp index f3f1a78c8..0f9b92abf 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -15,6 +15,7 @@ #include "../common/extprofile.h" #include "../common/string_util.h" #include "../common/clientversions.h" +#include "../common/random.h" #include "client.h" #include "worlddb.h" @@ -61,6 +62,7 @@ std::vector character_create_race_class_combos; extern ZSList zoneserver_list; extern LoginServerList loginserverlist; extern ClientList client_list; +extern EQEmu::Random emu_random; extern uint32 numclients; extern volatile bool RunLoops; @@ -519,7 +521,7 @@ bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) { char cons[48]="bcdfghjklmnpqrstvwxzybcdgklmnprstvwbcdgkpstrkd"; char rndname[17]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; char paircons[33]="ngrkndstshthphsktrdrbrgrfrclcr"; - int rndnum=MakeRandomInt(0, 75),n=1; + int rndnum=emu_random.Int(0, 75),n=1; bool dlc=false; bool vwl=false; bool dbl=false; @@ -540,18 +542,18 @@ bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) { rndname[0]=vowels[rndnum]; vwl=true; } - int namlen=MakeRandomInt(5, 10); + int namlen=emu_random.Int(5, 10); for (int i=n;i46) { // pick a cons pair if (i>namlen-3) // last 2 chars in name? { // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng" - rndnum=MakeRandomInt(0, 7)*2; + rndnum=emu_random.Int(0, 7)*2; } else { // pick any from the set @@ -569,12 +571,12 @@ bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) { } else { // select a vowel - rndname[i]=vowels[MakeRandomInt(0, 16)]; + rndname[i]=vowels[emu_random.Int(0, 16)]; } vwl=!vwl; if (!dbl && !dlc) { // one chance at double letters in name - if (!MakeRandomInt(0, i+9)) // chances decrease towards end of name + if (!emu_random.Int(0, i+9)) // chances decrease towards end of name { rndname[i+1]=rndname[i]; dbl=true; @@ -831,7 +833,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { QueuePacket(outapp); safe_delete(outapp); - int MailKey = MakeRandomInt(1, INT_MAX); + int MailKey = emu_random.Int(1, INT_MAX); database.SetMailKey(charid, GetIP(), MailKey); @@ -1242,8 +1244,8 @@ void Client::ZoneUnavail() { bool Client::GenPassKey(char* key) { char* passKey=nullptr; - *passKey += ((char)('A'+((int)MakeRandomInt(0, 25)))); - *passKey += ((char)('A'+((int)MakeRandomInt(0, 25)))); + *passKey += ((char)('A'+((int)emu_random.Int(0, 25)))); + *passKey += ((char)('A'+((int)emu_random.Int(0, 25)))); memcpy(key, passKey, strlen(passKey)); return true; } diff --git a/world/net.cpp b/world/net.cpp index ee1158520..44107e39b 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -69,6 +69,7 @@ #include "../common/emu_tcp_server.h" #include "../common/patches/patches.h" +#include "../common/random.h" #include "zoneserver.h" #include "console.h" #include "login_server.h" @@ -97,6 +98,7 @@ UCSConnection UCSLink; QueryServConnection QSLink; LauncherList launcher_list; AdventureManager adventure_manager; +EQEmu::Random emu_random; volatile bool RunLoops = true; uint32 numclients = 0; uint32 numzones = 0; diff --git a/world/zonelist.cpp b/world/zonelist.cpp index c97010aa8..c6c1043f5 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -24,10 +24,12 @@ #include "world_config.h" #include "../common/servertalk.h" #include "../common/string_util.h" +#include "../common/random.h" extern uint32 numzones; extern bool holdzones; extern ConsoleList console_list; +extern EQEmu::Random emu_random; void CatchSignal(int sig_num); ZSList::ZSList() @@ -565,7 +567,7 @@ void ZSList::RebootZone(const char* ip1,uint16 port,const char* ip2, uint32 skip safe_delete(tmp); return; } - uint32 z = MakeRandomInt(0, y-1); + uint32 z = emu_random.Int(0, y-1); ServerPacket* pack = new ServerPacket(ServerOP_ZoneReboot, sizeof(ServerZoneReboot_Struct)); ServerZoneReboot_Struct* s = (ServerZoneReboot_Struct*) pack->pBuffer; diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 8f5da2eaa..a904b9707 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -329,7 +329,7 @@ bool Mob::CheckWillAggro(Mob *mob) { || ( fv == FACTION_THREATENLY - && MakeRandomInt(0,99) < THREATENLY_ARRGO_CHANCE - heroicCHA_mod + && zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod) ) ) ) @@ -1254,7 +1254,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) { return true; //1: The mob has a default 25% chance of being allowed a resistance check against the charm. - if (MakeRandomInt(0, 99) > RuleI(Spells, CharmBreakCheckChance)) + if (zone->random.Int(0, 99) > RuleI(Spells, CharmBreakCheckChance)) return true; if (RuleB(Spells, CharismaCharmDuration)) @@ -1273,7 +1273,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) { //3: At maxed ability, Total Domination has a 50% chance of preventing the charm break that otherwise would have occurred. int16 TotalDominationBonus = caster->aabonuses.CharmBreakChance + caster->spellbonuses.CharmBreakChance + caster->itembonuses.CharmBreakChance; - if (MakeRandomInt(0, 99) < TotalDominationBonus) + if (zone->random.Int(0, 99) < TotalDominationBonus) return true; } diff --git a/zone/attack.cpp b/zone/attack.cpp index 65c3fd9d1..825e90b58 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -339,7 +339,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c // Did we hit? // - float tohit_roll = MakeRandomFloat(0, 100); + float tohit_roll = zone->random.Real(0, 100); mlog(COMBAT__TOHIT, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll); @@ -415,7 +415,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) //Live AA - HightenedAwareness int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind; - if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){ + if (BlockBehindChance && zone->random.Roll(BlockBehindChance)) { bBlockFromRear = true; if (spellbonuses.BlockBehind || itembonuses.BlockBehind) @@ -508,7 +508,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) } if(damage > 0){ - roll = MakeRandomFloat(0,100); + roll = zone->random.Real(0,100); if(roll <= RollTable[0]){ damage = -3; } @@ -674,7 +674,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac if (acfail>100) acfail=100; } - if (acfail<=0 || MakeRandomInt(0, 100)>acfail) { + if (acfail<=0 || zone->random.Int(0, 100)>acfail) { float acreduction=1; int acrandom=300; if (database.GetVariable("ACreduction", tmp, 9)) @@ -693,7 +693,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac damage -= (int32) (GetAC() * acreduction/100.0f); } if (acrandom>0) { - damage -= (myac * MakeRandomInt(0, acrandom) / 10000); + damage -= (myac * zone->random.Int(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); @@ -721,8 +721,8 @@ 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); + float mit_roll = zone->random.Real(0, mit_rating); + float atk_roll = zone->random.Real(0, atk_rating); if (atk_roll > mit_roll) { float a_diff = atk_roll - mit_roll; @@ -771,8 +771,8 @@ int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, 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); + float mit_roll = zone->random.Real(0, mit_rating); + float atk_roll = zone->random.Real(0, atk_rating); if (atk_roll > mit_roll) { float a_diff = atk_roll - mit_roll; @@ -1272,7 +1272,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if(RuleB(Combat, UseIntervalAC)) damage = max_hit; else - damage = MakeRandomInt(min_hit, max_hit); + damage = zone->random.Int(min_hit, max_hit); damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); @@ -1296,9 +1296,9 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b } else { //we hit, try to avoid it other->AvoidDamage(this, damage); other->MeleeMitigation(this, damage, min_hit, opts); - if(damage > 0) + if(damage > 0) CommonOutgoingHitSuccess(other, damage, skillinuse); - + mlog(COMBAT__DAMAGE, "Final damage after all reductions: %d", damage); } @@ -1314,7 +1314,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b OffhandRiposteFail *= -1; //Live uses a negative value for this. if (OffhandRiposteFail && - (OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) { + (OffhandRiposteFail > 99 || zone->random.Roll(OffhandRiposteFail))) { damage = 0; // Counts as a miss slippery_attack = true; } else @@ -1330,7 +1330,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b 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 && (MakeRandomInt(0, 100) < bonusStrikeThrough)) { + 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; @@ -1843,7 +1843,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool if(RuleB(Combat, UseIntervalAC)) damage = (max_dmg+eleBane); else - damage = MakeRandomInt((min_dmg+eleBane),(max_dmg+eleBane)); + damage = zone->random.Int((min_dmg+eleBane),(max_dmg+eleBane)); //check if we're hitting above our max or below it. @@ -3438,17 +3438,16 @@ bool Client::CheckDoubleAttack(bool tripleAttack) { chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers. } - if((MakeRandomFloat(0, 1) < chance)) + if(zone->random.Roll(chance)) return true; return false; } bool Client::CheckDoubleRangedAttack() { - int32 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack; - if(chance && (MakeRandomInt(0, 100) < chance)) + if(chance && zone->random.Roll(chance)) return true; return false; @@ -3465,7 +3464,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons mlog(COMBAT__DAMAGE, "Avoiding %d damage due to invulnerability.", damage); damage = -5; } - + if( spell_id != SPELL_UNKNOWN || attacker == nullptr ) avoidable = false; @@ -3632,7 +3631,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons } } - if (stun_chance && MakeRandomInt(0, 99) < stun_chance) { + 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; @@ -3645,18 +3644,18 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons // frontal stun check for ogres/bonuses if (((GetBaseRace() == OGRE && IsClient()) || - (frontal_stun_resist && MakeRandomInt(0, 99) < frontal_stun_resist)) && + (frontal_stun_resist && zone->random.Roll(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 (stun_resist && zone->random.Roll(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 + Stun(zone->random.Int(0, 2) * 1000); // 0-2 seconds } } } else { @@ -3937,7 +3936,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) { for (int i = 0; i < MAX_PROCS; i++) { if (IsValidSpell(DefensiveProcs[i].spellID)) { float chance = ProcChance * (static_cast(DefensiveProcs[i].chance)/100.0f); - if ((MakeRandomFloat(0, 1) <= chance)) { + if (zone->random.Roll(chance)) { ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); CheckNumHitsRemaining(NUMHIT_DefensiveSpellProcs,0,DefensiveProcs[i].base_spellID); } @@ -3999,7 +3998,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on 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 (zone->random.Roll(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)", @@ -4037,7 +4036,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on 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 (zone->random.Roll(APC)) { if (aug->Proc.Level > ourlevel) { if (IsPet()) { Mob *own = GetOwner(); @@ -4090,7 +4089,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, if (!rangedattk) { // Perma procs (AAs) if (PermaProcs[i].spellID != SPELL_UNKNOWN) { - if (MakeRandomInt(0, 99) < PermaProcs[i].chance) { // TODO: Do these get spell bonus? + if (zone->random.Roll(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); @@ -4105,7 +4104,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, // Spell procs (buffs) if (SpellProcs[i].spellID != SPELL_UNKNOWN) { float chance = ProcChance * (static_cast(SpellProcs[i].chance) / 100.0f); - if (MakeRandomFloat(0, 1) <= chance) { + if (zone->random.Roll(chance)) { mlog(COMBAT__PROCS, "Spell proc %d procing spell %d (%.2f percent chance)", i, SpellProcs[i].spellID, chance); @@ -4121,7 +4120,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, // ranged spell procs (buffs) if (RangedProcs[i].spellID != SPELL_UNKNOWN) { float chance = ProcChance * (static_cast(RangedProcs[i].chance) / 100.0f); - if (MakeRandomFloat(0, 1) <= chance) { + if (zone->random.Roll(chance)) { mlog(COMBAT__PROCS, "Ranged proc %d procing spell %d (%.2f percent chance)", i, RangedProcs[i].spellID, chance); @@ -4189,7 +4188,7 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage) critChance /= 100; - if(MakeRandomFloat(0, 1) < critChance) + if(zone->random.Roll(critChance)) { critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 damage = (damage * critMod) / 100; @@ -4228,7 +4227,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack int32 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0]; if (SlayRateBonus) { float slayChance = static_cast(SlayRateBonus) / 10000.0f; - if (MakeRandomFloat(0, 1) < slayChance) { + if (zone->random.Roll(slayChance)) { int32 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1]; damage = (damage * SlayDmgBonus * 2.25) / 100; if (GetGender() == 1) // female @@ -4299,12 +4298,12 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack critChance /= 100; - if(MakeRandomFloat(0, 1) < critChance) + if(zone->random.Roll(critChance)) { uint32 critMod = 200; bool crip_success = false; int32 CripplingBlowChance = GetCrippBlowChance(); - + //Crippling Blow Chance: The percent value of the effect is applied //to the your Chance to Critical. (ie You have 10% chance to critical and you //have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow. @@ -4312,7 +4311,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack if (!IsBerserk() && !IsBerskerSPA) critChance *= float(CripplingBlowChance)/100.0f; - if ((IsBerserk() || IsBerskerSPA) || MakeRandomFloat(0, 1) < critChance) { + if ((IsBerserk() || IsBerskerSPA) || zone->random.Roll(critChance)) { critMod = 400; crip_success = true; } @@ -4322,7 +4321,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack damage = damage * critMod / 100; bool deadlySuccess = false; - if (deadlyChance && MakeRandomFloat(0, 1) < static_cast(deadlyChance) / 100.0f) { + if (deadlyChance && zone->random.Roll(static_cast(deadlyChance) / 100.0f)) { if (BehindMob(defender, GetX(), GetY())) { damage *= deadlyMod; deadlySuccess = true; @@ -4358,7 +4357,7 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){ uint32 FB_Dmg = aabonuses.FinishingBlow[1] + spellbonuses.FinishingBlow[1] + itembonuses.FinishingBlow[1]; - + uint32 FB_Level = 0; FB_Level = aabonuses.FinishingBlowLvl[0]; if (FB_Level < spellbonuses.FinishingBlowLvl[0]) @@ -4369,7 +4368,7 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) //Proc Chance value of 500 = 5% uint32 ProcChance = (aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0])/10; - if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= MakeRandomInt(0, 1000))){ + if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= zone->random.Int(0, 1000))){ entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); DoSpecialAttackDamage(defender, skillinuse, FB_Dmg, 1, -1, 10, false, false); return true; @@ -4396,7 +4395,7 @@ void Mob::DoRiposte(Mob* defender) { defender->itembonuses.DoubleRiposte; //Live AA - Double Riposte - if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { + if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) { mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance); defender->Attack(this, MainPrimary, true); if (HasDied()) return; @@ -4407,7 +4406,7 @@ void Mob::DoRiposte(Mob* defender) { DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1]; - if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { + if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) { mlog(COMBAT__ATTACKS, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance); if (defender->GetClass() == MONK) @@ -4510,7 +4509,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui uint16 proc_spell_id = 0; float ProcMod = 0; float chance = 0; - + if (IsDefensive) chance = on->GetSkillProcChances(ReuseTime, hand); else @@ -4519,16 +4518,14 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (spellbonuses.LimitToSkill[skill]){ for(int e = 0; e < MAX_SKILL_PROCS; e++){ - - if (CanProc && + if (CanProc && (!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e])) || (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e]))) { base_spell_id = spellbonuses.SkillProc[e]; base_spell_id = 0; ProcMod = 0; - + for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[base_spell_id].effectid[i] == SE_SkillProc) { proc_spell_id = spells[base_spell_id].base[i]; ProcMod = static_cast(spells[base_spell_id].base2[i]); @@ -4538,7 +4535,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); - if (MakeRandomFloat(0, 1) <= final_chance) { + if (zone->random.Roll(final_chance)) { ExecWeaponProc(nullptr, proc_spell_id, on); CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs,0, base_spell_id); CanProc = false; @@ -4558,8 +4555,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (itembonuses.LimitToSkill[skill]){ CanProc = true; for(int e = 0; e < MAX_SKILL_PROCS; e++){ - - if (CanProc && + if (CanProc && (!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e])) || (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e]))) { base_spell_id = itembonuses.SkillProc[e]; @@ -4567,7 +4563,6 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui ProcMod = 0; for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[base_spell_id].effectid[i] == SE_SkillProc) { proc_spell_id = spells[base_spell_id].base[i]; ProcMod = static_cast(spells[base_spell_id].base2[i]); @@ -4577,7 +4572,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); - if (MakeRandomFloat(0, 1) <= final_chance) { + if (zone->random.Roll(final_chance)) { ExecWeaponProc(nullptr, proc_spell_id, on); CanProc = false; break; @@ -4602,8 +4597,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui uint32 slot = 0; for(int e = 0; e < MAX_SKILL_PROCS; e++){ - - if (CanProc && + if (CanProc && (!Success && aabonuses.SkillProc[e]) || (Success && aabonuses.SkillProcSuccess[e])){ int aaid = aabonuses.SkillProc[e]; @@ -4630,7 +4624,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); - if (MakeRandomFloat(0, 1) <= final_chance) { + if (zone->random.Roll(final_chance)) { ExecWeaponProc(nullptr, proc_spell_id, on); CanProc = false; break; @@ -4651,62 +4645,58 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) { uint32 weapon_speed; float ProcChance = 0; - + if (!ReuseTime && hand) { - weapon_speed = GetWeaponSpeedbyHand(hand); - ProcChance = static_cast(weapon_speed) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f); - if (hand != MainPrimary) ProcChance /= 2; } - else + else ProcChance = static_cast(ReuseTime) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f); return ProcChance; } 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. - - /* 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. + + /*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. + + 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; + 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(); //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%; - - if (BreakChance < 1) - BreakChance = 1; - if (MakeRandomInt(0, 99) < BreakChance) { + if (BreakChance < 1) + BreakChance = 1; + + if (zone->random.Roll(BreakChance)) { if (!TryFadeEffect(spellbonuses.Root[1])) { BuffFadeBySlot(spellbonuses.Root[1]); @@ -4727,7 +4717,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) for(uint32 slot = 0; slot < buff_max; slot++) { if(slot == spellbonuses.MeleeRune[1] && spellbonuses.MeleeRune[0] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)){ int melee_rune_left = buffs[slot].melee_rune; - + if(melee_rune_left > damage) { melee_rune_left -= damage; diff --git a/zone/bot.cpp b/zone/bot.cpp index 496ddc7ae..9ae33318a 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -775,49 +775,49 @@ void Bot::GenerateAppearance() { // Randomize facial appearance int iFace = 0; if(this->GetRace() == 2) { // Barbarian w/Tatoo - iFace = MakeRandomInt(0, 79); + iFace = zone->random.Int(0, 79); } else { - iFace = MakeRandomInt(0, 7); + iFace = zone->random.Int(0, 7); } int iHair = 0; int iBeard = 0; int iBeardColor = 1; if(this->GetRace() == 522) { - iHair = MakeRandomInt(0, 8); - iBeard = MakeRandomInt(0, 11); - iBeardColor = MakeRandomInt(0, 3); + iHair = zone->random.Int(0, 8); + iBeard = zone->random.Int(0, 11); + iBeardColor = zone->random.Int(0, 3); } else if(this->GetGender()) { - iHair = MakeRandomInt(0, 2); + iHair = zone->random.Int(0, 2); if(this->GetRace() == 8) { // Dwarven Females can have a beard - if(MakeRandomInt(1, 100) < 50) { + if(zone->random.Int(1, 100) < 50) { iFace += 10; } } } else { - iHair = MakeRandomInt(0, 3); - iBeard = MakeRandomInt(0, 5); - iBeardColor = MakeRandomInt(0, 19); + 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) { - iHairColor = MakeRandomInt(0, 3); + iHairColor = zone->random.Int(0, 3); } else { - iHairColor = MakeRandomInt(0, 19); + iHairColor = zone->random.Int(0, 19); } - uint8 iEyeColor1 = (uint8)MakeRandomInt(0, 9); + uint8 iEyeColor1 = (uint8)zone->random.Int(0, 9); uint8 iEyeColor2 = 0; if(this->GetRace() == 522) { - iEyeColor1 = iEyeColor2 = (uint8)MakeRandomInt(0, 11); + iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11); } - else if(MakeRandomInt(1, 100) > 96) { - iEyeColor2 = MakeRandomInt(0, 9); + else if(zone->random.Int(1, 100) > 96) { + iEyeColor2 = zone->random.Int(0, 9); } else { iEyeColor2 = iEyeColor1; @@ -827,9 +827,9 @@ void Bot::GenerateAppearance() { int iTattoo = 0; int iDetails = 0; if(this->GetRace() == 522) { - iHeritage = MakeRandomInt(0, 6); - iTattoo = MakeRandomInt(0, 7); - iDetails = MakeRandomInt(0, 7); + iHeritage = zone->random.Int(0, 6); + iTattoo = zone->random.Int(0, 7); + iDetails = zone->random.Int(0, 7); } this->luclinface = iFace; @@ -3098,7 +3098,7 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) { chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers. } - if((MakeRandomFloat(0, 1) < chance)) + if((zone->random.Real(0, 1) < chance)) return true; return false; @@ -3148,7 +3148,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if(RuleB(Combat, UseIntervalAC)) damage = max_hit; else - damage = MakeRandomInt(min_hit, max_hit); + damage = zone->random.Int(min_hit, max_hit); if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) { damage = 0; @@ -3203,7 +3203,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if (damage > 0) CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); - if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && MakeRandomInt(0, 99) < 25){ + if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && zone->random.Int(0, 99) < 25){ SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff); other->Stun(100); } @@ -3483,7 +3483,7 @@ void Bot::AI_Process() { meleeDistance = meleeDistance * .30; } else { - meleeDistance *= (float)MakeRandomFloat(.50, .85); + meleeDistance *= (float)zone->random.Real(.50, .85); } bool atArcheryRange = IsArcheryRange(GetTarget()); @@ -3616,7 +3616,7 @@ void Bot::AI_Process() { if (GetTarget() && flurrychance) { - if(MakeRandomInt(0, 100) < flurrychance) + if(zone->random.Int(0, 100) < flurrychance) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); Attack(GetTarget(), MainPrimary, false); @@ -3633,7 +3633,7 @@ void Bot::AI_Process() { wpn->GetItem()->ItemType == ItemType2HBlunt || wpn->GetItem()->ItemType == ItemType2HPiercing ) { - if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus) + if(zone->random.Int(0, 100) < ExtraAttackChanceBonus) { Attack(GetTarget(), MainPrimary, false); } @@ -3678,7 +3678,7 @@ void Bot::AI_Process() { int32 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; - float random = MakeRandomFloat(0, 1); + float random = zone->random.Real(0, 1); if (random < DualWieldProbability){ // Max 78% of DW @@ -3912,7 +3912,7 @@ void Bot::PetAIProcess() { if (botPet->GetTarget()) // Do we still have a target? { // We're a pet so we re able to dual attack - int32 RandRoll = MakeRandomInt(0, 99); + int32 RandRoll = zone->random.Int(0, 99); if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) { if(botPet->Attack(botPet->GetTarget(), MainPrimary)) @@ -3945,7 +3945,7 @@ void Bot::PetAIProcess() { //aa_chance += botPet->GetOwner()->GetAA(aaCompanionsAlacrity) * 3; - if (MakeRandomInt(1, 100) < aa_chance) + if (zone->random.Int(1, 100) < aa_chance) Flurry(nullptr); } @@ -3955,12 +3955,12 @@ void Bot::PetAIProcess() { if(botPet->GetOwner()->GetLevel() >= 24) { float DualWieldProbability = (botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f; - DualWieldProbability -= MakeRandomFloat(0, 1); + DualWieldProbability -= zone->random.Real(0, 1); if(DualWieldProbability < 0){ botPet->Attack(botPet->GetTarget(), MainSecondary); if (botPet->CanThisClassDoubleAttack()) { - int32 RandRoll = MakeRandomInt(0, 99); + int32 RandRoll = zone->random.Int(0, 99); if (RandRoll < (botPet->GetLevel() + 20)) { botPet->Attack(botPet->GetTarget(), MainSecondary); @@ -6213,7 +6213,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if(RuleB(Combat, UseIntervalAC)) damage = max_hit; else - damage = MakeRandomInt(min_hit, max_hit); + damage = zone->random.Int(min_hit, max_hit); 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, GetLevel()); @@ -6258,7 +6258,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b OffhandRiposteFail *= -1; //Live uses a negative value for this. if (OffhandRiposteFail && - (OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) { + (OffhandRiposteFail > 99 || (zone->random.Int(0, 100) < OffhandRiposteFail))) { damage = 0; // Counts as a miss slippery_attack = true; } else @@ -6274,7 +6274,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b 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 && (MakeRandomInt(0, 100) < bonusStrikeThrough)) { + 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; @@ -6623,7 +6623,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) { if(type == focusTriggerOnCast) { - if(MakeRandomInt(0, 100) <= base1){ + if(zone->random.Int(0, 100) <= base1){ value = base2; } @@ -6646,7 +6646,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) { if(type == focusBlockNextSpell) { - if(MakeRandomInt(1, 100) <= base1) + if(zone->random.Int(1, 100) <= base1) value = 1; } break; @@ -6670,7 +6670,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time); GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod); - if(MakeRandomFloat(0, 1) <= ProcChance) + if(zone->random.Real(0, 1) <= ProcChance) value = focus_id; else @@ -7147,7 +7147,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel value = focus_spell.base[i]; } else { - value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]); + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } break; @@ -7165,7 +7165,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel value = focus_spell.base[i]; } else { - value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]); + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } break; @@ -7183,7 +7183,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel value = focus_spell.base[i]; } else { - value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]); + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } break; @@ -7273,7 +7273,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel { if(bottype == BotfocusTriggerOnCast) - if(MakeRandomInt(0, 100) <= focus_spell.base[i]) + if(zone->random.Int(0, 100) <= focus_spell.base[i]) value = focus_spell.base2[i]; else @@ -7293,7 +7293,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel { if(bottype == BotfocusBlockNextSpell) { - if(MakeRandomInt(1, 100) <= focus_spell.base[i]) + if(zone->random.Int(1, 100) <= focus_spell.base[i]) value = 1; } break; @@ -7313,7 +7313,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]); - if(MakeRandomFloat(0, 1) <= ProcChance) + if(zone->random.Real(0, 1) <= ProcChance) value = focus_id; else @@ -7503,7 +7503,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) //Live AA - HightenedAwareness int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind; - if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){ + if (BlockBehindChance && (BlockBehindChance > zone->random.Int(1, 100))){ bBlockFromRear = true; if (spellbonuses.BlockBehind || itembonuses.BlockBehind) @@ -7595,7 +7595,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if(damage > 0) { - roll = MakeRandomFloat(0,100); + roll = zone->random.Real(0,100); if(roll <= RollTable[0]){ damage = -3; } @@ -7662,7 +7662,7 @@ bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) uint32 damage = aabonuses.FinishingBlow[1]; uint16 levelreq = aabonuses.FinishingBlowLvl[0]; - if(defender->GetLevel() <= levelreq && (chance >= MakeRandomInt(0, 1000))){ + if(defender->GetLevel() <= levelreq && (chance >= zone->random.Int(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); @@ -7690,7 +7690,7 @@ void Bot::DoRiposte(Mob* defender) { defender->GetSpellBonuses().GiveDoubleRiposte[0] + defender->GetItemBonuses().GiveDoubleRiposte[0]; - if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { + if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { mlog(COMBAT__ATTACKS, "Preforming a double riposte (%d percent chance)", DoubleRipChance); defender->Attack(this, MainPrimary, true); @@ -7700,7 +7700,7 @@ void Bot::DoRiposte(Mob* defender) { //Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill] DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[1]; - if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { + if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { if (defender->GetClass() == MONK) defender->MonkSpecialAttack(this, defender->GetAABonuses().GiveDoubleRiposte[2]); else if (defender->IsBot()) @@ -7766,7 +7766,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int kb_chance = 25; kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100; - if (MakeRandomInt(0, 99) < kb_chance) + 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. } @@ -7807,7 +7807,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { //Live AA - Seized Opportunity int FrontalBSChance = itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance; - if (FrontalBSChance && (FrontalBSChance > MakeRandomInt(0, 100))) + if (FrontalBSChance && (FrontalBSChance > zone->random.Int(0, 100))) bCanFrontalBS = true; } @@ -7821,7 +7821,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { !other->CastToNPC()->IsEngaged() && // not aggro other->GetHP()<=32000 && other->IsNPC() - && MakeRandomFloat(0, 99) < chance // chance + && zone->random.Real(0, 99) < chance // chance ) { entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); RogueAssassinate(other); @@ -7832,12 +7832,12 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max // Check for double attack with main hand assuming maxed DA Skill (MS) - if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA + if(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA { if(other->GetHP() > 0) RogueBackstab(other,false,ReuseTime); - if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100)) + if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100)) RogueBackstab(other,false,ReuseTime); } } @@ -7851,11 +7851,11 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { 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(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA + if(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA if(other->GetHP() > 0) RogueBackstab(other,true, ReuseTime); - if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100)) + if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100)) RogueBackstab(other,false,ReuseTime); } } @@ -7929,7 +7929,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) if(RuleB(Combat, UseIntervalAC)) ndamage = max_hit; else - ndamage = MakeRandomInt(min_hit, max_hit); + ndamage = zone->random.Int(min_hit, max_hit); } } @@ -8036,7 +8036,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { canBash = true; } - if(!canBash || MakeRandomInt(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. + 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 { @@ -8117,7 +8117,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else - dmg = MakeRandomInt(1, GetBashDamage()); + dmg = zone->random.Int(1, GetBashDamage()); } } @@ -8164,7 +8164,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { //Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. while(AtkRounds > 0) { - if (GetTarget() && (AtkRounds == 1 || MakeRandomInt(0,100) < 75)){ + if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0,100) < 75)){ DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , reuse, true); } AtkRounds--; @@ -8192,7 +8192,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else - dmg = MakeRandomInt(1, GetKickDamage()); + dmg = zone->random.Int(1, GetKickDamage()); } } @@ -8215,18 +8215,18 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { //Live AA - Technique of Master Wu uint32 bDoubleSpecialAttack = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; - if( bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > MakeRandomInt(0,100))) { + if( bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0,100))) { int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick }; - MonkSpecialAttack(target, MonkSPA[MakeRandomInt(0,4)]); + MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]); int TripleChance = 25; if (bDoubleSpecialAttack > 100) TripleChance += TripleChance*(100-bDoubleSpecialAttack)/100; - if(TripleChance > MakeRandomInt(0,100)) { - MonkSpecialAttack(target, MonkSPA[MakeRandomInt(0,4)]); + if(TripleChance > zone->random.Int(0,100)) { + MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]); } } @@ -8259,7 +8259,7 @@ bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { // 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. float AttackerChance = 0.20f + ((float)(rangerLevel - 51) * 0.005f); - float DefenderChance = (float)MakeRandomFloat(0.00f, 1.00f); + float DefenderChance = (float)zone->random.Real(0.00f, 1.00f); if(AttackerChance > DefenderChance) { mlog(COMBAT__ATTACKS, "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 @@ -8734,14 +8734,14 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) chance = 100; - if (MakeRandomInt(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)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) { - ratio = MakeRandomInt(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. + 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. Critical = true; } @@ -8820,7 +8820,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (spellbonuses.CriticalHealDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); - if(chance && (MakeRandomInt(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. } @@ -8851,7 +8851,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (spellbonuses.CriticalRegenDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); - if(chance && (MakeRandomInt(0,99) < chance)) + if(chance && (zone->random.Int(0,99) < chance)) return (value * 2); } @@ -8950,7 +8950,7 @@ 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 * MakeRandomInt(1, 100) / 100; + int32 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell if(mana_back > cost) mana_back = cost; @@ -8963,7 +8963,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { // WildcardX float PercentManaReduction = 0; float SpecializeSkill = GetSpecializeSkillValue(spell_id); - int SuccessChance = MakeRandomInt(0, 100); + int SuccessChance = zone->random.Int(0, 100); float bonus = 1.0; switch(GetAA(aaSpellCastingMastery)) @@ -9015,7 +9015,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { if(focus_redux > 0) { - PercentManaReduction += MakeRandomFloat(1, (double)focus_redux); + PercentManaReduction += zone->random.Real(1, (double)focus_redux); } cost -= (cost * (PercentManaReduction / 100)); @@ -15580,7 +15580,7 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl return false; if (iChance < 100) { - uint8 tmp = MakeRandomInt(1, 100); + uint8 tmp = zone->random.Int(1, 100); if (tmp > iChance) return false; } diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 4917ed953..a5be7341e 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -13,7 +13,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { return false; if (iChance < 100) { - if (MakeRandomInt(0, 100) > iChance){ + if (zone->random.Int(0, 100) > iChance){ return false; } } @@ -485,7 +485,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { if(botClass == PALADIN) stunChance = 50; - if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (MakeRandomInt(1, 100) <= stunChance)) { + if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) { botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target); } } @@ -1843,7 +1843,7 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) { result = std::string("SumEarth"); else if(botCaster->GetLevel() < 30) { // Under level 30 - int counter = MakeRandomInt(0, 3); + int counter = zone->random.Int(0, 3); switch(counter) { case 0: @@ -1865,7 +1865,7 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) { } else { // Over level 30 - int counter = MakeRandomInt(0, 4); + int counter = zone->random.Int(0, 4); switch(counter) { case 0: diff --git a/zone/client.cpp b/zone/client.cpp index e4f2c823a..f67328ae9 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2328,7 +2328,7 @@ bool Client::CheckIncreaseSkill(SkillUseTypes skillid, Mob *against_who, int cha if(Chance < 1) Chance = 1; // Make it always possible - if(MakeRandomFloat(0, 99) < Chance) + if(zone->random.Real(0, 99) < Chance) { SetSkill(skillid, GetRawSkill(skillid) + 1); _log(SKILLS__GAIN, "Skill %d at value %d successfully gain with %.4f%%chance (mod %d)", skillid, skillval, Chance, chancemodi); @@ -2356,7 +2356,7 @@ void Client::CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill) { int32 Chance = 5 + ((TeacherSkill - LangSkill)/10); // greater chance to learn if teacher's skill is much higher than yours Chance = (Chance * RuleI(Character, SkillUpModifier)/100); - if(MakeRandomFloat(0,100) < Chance) { // if they make the roll + if(zone->random.Real(0,100) < Chance) { // if they make the roll IncreaseLanguageSkill(langid); // increase the language skill by 1 _log(SKILLS__GAIN, "Language %d at value %d successfully gain with %.4f%%chance", langid, LangSkill, Chance); } @@ -4904,7 +4904,7 @@ int Client::LDoNChest_SkillCheck(NPC *target, int skill) chance = 100.0f - base_difficulty; } - float d100 = (float)MakeRandomFloat(0, 100); + float d100 = (float)zone->random.Real(0, 100); if(d100 <= chance) return 1; @@ -7608,9 +7608,9 @@ void Client::GarbleMessage(char *message, uint8 variance) const char alpha_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; // only change alpha characters for now for (size_t i = 0; i < strlen(message); i++) { - uint8 chance = (uint8)MakeRandomInt(0, 115); // variation just over worst possible scrambling + uint8 chance = (uint8)zone->random.Int(0, 115); // variation just over worst possible scrambling if (isalpha(message[i]) && (chance <= variance)) { - uint8 rand_char = (uint8)MakeRandomInt(0,51); // choose a random character from the alpha list + uint8 rand_char = (uint8)zone->random.Int(0,51); // choose a random character from the alpha list message[i] = alpha_list[rand_char]; } } @@ -7728,7 +7728,7 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui // If our result is truncated, then double a mob's value every once and a while to equal what they would have got else { - if (MakeRandomInt(0, 100) < faction_mod) + if (zone->random.Int(0, 100) < faction_mod) npc_value[i] *= 2; } } @@ -7821,11 +7821,11 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) } // If no primary faction or biggest influence is your faction hit if (primaryfaction <= 0 || lowestvalue == tmpFactionValue) { - merchant->Say_StringID(MakeRandomInt(WONT_SELL_DEEDS1, WONT_SELL_DEEDS6)); + merchant->Say_StringID(zone->random.Int(WONT_SELL_DEEDS1, WONT_SELL_DEEDS6)); } else if (lowestvalue == fmod.race_mod) { // race biggest // Non-standard race (ex. illusioned to wolf) if (GetRace() > PLAYER_RACE_COUNT) { - messageid = MakeRandomInt(1, 3); // these aren't sequential StringIDs :( + messageid = zone->random.Int(1, 3); // these aren't sequential StringIDs :( switch (messageid) { case 1: messageid = WONT_SELL_NONSTDRACE1; @@ -7842,7 +7842,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) } merchant->Say_StringID(messageid); } else { // normal player races - messageid = MakeRandomInt(1, 4); + messageid = zone->random.Int(1, 4); switch (messageid) { case 1: messageid = WONT_SELL_RACE1; @@ -7863,7 +7863,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) merchant->Say_StringID(messageid, itoa(GetRace())); } } else if (lowestvalue == fmod.class_mod) { - merchant->Say_StringID(MakeRandomInt(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass())); + merchant->Say_StringID(zone->random.Int(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass())); } return; } @@ -7966,7 +7966,7 @@ void Client::TryItemTick(int slot) if(zone->tick_items.count(iid) > 0) { - if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(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 <= EmuConstants::EQUIPMENT_END) ) { ItemInst* e_inst = (ItemInst*)inst; parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); @@ -7985,7 +7985,7 @@ void Client::TryItemTick(int slot) if(zone->tick_items.count(iid) > 0) { - if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) ) + if( GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) ) { ItemInst* e_inst = (ItemInst*)a_inst; parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e2884e738..c4885252b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2953,7 +2953,7 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) if ((PrimaryWeapon && PrimaryWeapon->GetItem()->ItemType == ItemType1HPiercing) || (SecondaryWeapon && SecondaryWeapon->GetItem()->ItemType == ItemType1HPiercing)) { float SuccessChance = (GetSkill(SkillApplyPoison) + GetLevel()) / 400.0f; - double ChanceRoll = MakeRandomFloat(0, 1); + double ChanceRoll = zone->random.Real(0, 1); CheckIncreaseSkill(SkillApplyPoison, nullptr, 10); @@ -3642,14 +3642,14 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app) return; } - int RandomChance = MakeRandomInt(0, 100); + int RandomChance = zone->random.Int(0, 100); int ChanceToAttack = 0; if (GetLevel() > GetTarget()->GetLevel()) - ChanceToAttack = MakeRandomInt(0, 15); + ChanceToAttack = zone->random.Int(0, 15); else - ChanceToAttack = MakeRandomInt(((this->GetTarget()->GetLevel() - this->GetLevel()) * 10) - 5, ((this->GetTarget()->GetLevel() - this->GetLevel()) * 10)); + ChanceToAttack = zone->random.Int(((this->GetTarget()->GetLevel() - this->GetLevel()) * 10) - 5, ((this->GetTarget()->GetLevel() - this->GetLevel()) * 10)); if (ChanceToAttack < 0) ChanceToAttack = -ChanceToAttack; @@ -3668,7 +3668,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app) if (RandomChance < ChanceToBeg) { - brs->Amount = MakeRandomInt(1, 10); + brs->Amount = zone->random.Int(1, 10); // This needs some work to determine how much money they can beg, based on skill level etc. if (CurrentSkill < 50) { @@ -4550,7 +4550,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) delta_heading = ppu->delta_heading; if(IsTracking() && ((x_pos!=ppu->x_pos) || (y_pos!=ppu->y_pos))){ - if(MakeRandomFloat(0, 100) < 70)//should be good + if(zone->random.Real(0, 100) < 70)//should be good CheckIncreaseSkill(SkillTracking, nullptr, -20); } @@ -5252,16 +5252,16 @@ void Client::Handle_OP_DisarmTraps(const EQApplicationPacket *app) if (trap && trap->detected) { int uskill = GetSkill(SkillDisarmTraps); - if ((MakeRandomInt(0, 49) + uskill) >= (MakeRandomInt(0, 49) + trap->skill)) + if ((zone->random.Int(0, 49) + uskill) >= (zone->random.Int(0, 49) + trap->skill)) { Message(MT_Skills, "You disarm a trap."); trap->disarmed = true; trap->chkarea_timer.Disable(); - trap->respawn_timer.Start((trap->respawn_time + MakeRandomInt(0, trap->respawn_var)) * 1000); + trap->respawn_timer.Start((trap->respawn_time + zone->random.Int(0, trap->respawn_var)) * 1000); } else { - if (MakeRandomInt(0, 99) < 25){ + if (zone->random.Int(0, 99) < 25){ Message(MT_Skills, "You set off the trap while trying to disarm it!"); trap->Trigger(this); } @@ -5622,7 +5622,7 @@ void Client::Handle_OP_FeignDeath(const EQApplicationPacket *app) secfeign = 0; uint16 totalfeign = primfeign + secfeign; - if (MakeRandomFloat(0, 160) > totalfeign) { + if (zone->random.Real(0, 160) > totalfeign) { SetFeigned(false); entity_list.MessageClose_StringID(this, false, 200, 10, STRING_FEIGNFAILED, GetName()); } @@ -7886,7 +7886,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) p_timers.Start(pTimerHide, reuse - 1); float hidechance = ((GetSkill(SkillHide) / 250.0f) + .25) * 100; - float random = MakeRandomFloat(0, 100); + float random = zone->random.Real(0, 100); CheckIncreaseSkill(SkillHide, nullptr, 5); if (random < hidechance) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); @@ -7910,7 +7910,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) Mob *evadetar = GetTarget(); if (!auto_attack && (evadetar && evadetar->CheckAggro(this) && evadetar->IsNPC())) { - if (MakeRandomInt(0, 260) < (int)GetSkill(SkillHide)) { + if (zone->random.Int(0, 260) < (int)GetSkill(SkillHide)) { msg->string_id = EVADE_SUCCESS; RogueEvade(evadetar); } @@ -9293,11 +9293,11 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app) int mendhp = GetMaxHP() / 4; int currenthp = GetHP(); - if (MakeRandomInt(0, 199) < (int)GetSkill(SkillMend)) { + if (zone->random.Int(0, 199) < (int)GetSkill(SkillMend)) { int criticalchance = spellbonuses.CriticalMend + itembonuses.CriticalMend + aabonuses.CriticalMend; - if (MakeRandomInt(0, 99) < criticalchance){ + if (zone->random.Int(0, 99) < criticalchance){ mendhp *= 2; Message_StringID(4, MEND_CRITICAL); } @@ -9312,7 +9312,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) && (MakeRandomInt(GetSkill(SkillMend), 100) < 75) && (MakeRandomInt(1, 3) == 1)) + if ((GetSkill(SkillMend) <= 75) && (zone->random.Int(GetSkill(SkillMend), 100) < 75) && (zone->random.Int(1, 3) == 1)) { SetHP(currenthp > mendhp ? (GetHP() - mendhp) : 1); SendHPUpdate(); @@ -11213,7 +11213,7 @@ void Client::Handle_OP_RandomReq(const EQApplicationPacket *app) randLow = 0; randHigh = 100; } - randResult = MakeRandomInt(randLow, randHigh); + randResult = zone->random.Int(randLow, randHigh); EQApplicationPacket* outapp = new EQApplicationPacket(OP_RandomReply, sizeof(RandomReply_Struct)); RandomReply_Struct* rr = (RandomReply_Struct*)outapp->pBuffer; @@ -11703,7 +11703,7 @@ void Client::Handle_OP_SenseTraps(const EQApplicationPacket *app) if (trap && trap->skill > 0) { int uskill = GetSkill(SkillSenseTraps); - if ((MakeRandomInt(0, 99) + uskill) >= (MakeRandomInt(0, 99) + trap->skill*0.75)) + if ((zone->random.Int(0, 99) + uskill) >= (zone->random.Int(0, 99) + trap->skill*0.75)) { float xdif = trap->x - GetX(); float ydif = trap->y - GetY(); @@ -12446,7 +12446,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app) // 1199 I don't have time for that now. etc if (!tmp->CastToNPC()->IsMerchantOpen()) { - tmp->Say_StringID(MakeRandomInt(1199, 1202)); + tmp->Say_StringID(zone->random.Int(1199, 1202)); action = 0; } @@ -12501,7 +12501,7 @@ void Client::Handle_OP_Sneak(const EQApplicationPacket *app) CheckIncreaseSkill(SkillSneak, nullptr, 5); } float hidechance = ((GetSkill(SkillSneak) / 300.0f) + .25) * 100; - float random = MakeRandomFloat(0, 99); + float random = zone->random.Real(0, 99); if (!was && random < hidechance) { sneaking = true; } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index c2e3ae1f3..0b99b1c2a 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -436,7 +436,7 @@ bool Client::Process() { if (auto_attack_target && flurrychance) { - if(MakeRandomInt(0, 99) < flurrychance) + if(zone->random.Int(0, 99) < flurrychance) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); Attack(auto_attack_target, MainPrimary, false); @@ -453,7 +453,7 @@ bool Client::Process() { wpn->GetItem()->ItemType == ItemType2HBlunt || wpn->GetItem()->ItemType == ItemType2HPiercing ) { - if(MakeRandomInt(0, 99) < ExtraAttackChanceBonus) + if(zone->random.Int(0, 99) < ExtraAttackChanceBonus) { Attack(auto_attack_target, MainPrimary, false); } @@ -498,7 +498,7 @@ bool Client::Process() { int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; - float random = MakeRandomFloat(0, 1); + float random = zone->random.Real(0, 1); CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10); if (random < DualWieldProbability){ // Max 78% of DW if(CheckAAEffect(aaEffectRampage)) { @@ -1003,7 +1003,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required) continue; - handychance = MakeRandomInt(0, merlist.size() + tmp_merlist.size() - 1); + handychance = zone->random.Int(0, merlist.size() + tmp_merlist.size() - 1); item = database.GetItem(ml.item); if (item) { @@ -1079,7 +1079,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { zone->tmpmerchanttable[npcid] = tmp_merlist; if (merch != nullptr && handyitem) { char handy_id[8] = { 0 }; - int greeting = MakeRandomInt(0, 4); + int greeting = zone->random.Int(0, 4); int greet_id = 0; switch (greeting) { case 1: @@ -1640,7 +1640,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app) // welcome message if (pTrainer && pTrainer->IsNPC()) { - pTrainer->Say_StringID(MakeRandomInt(1204, 1207), GetCleanName()); + pTrainer->Say_StringID(zone->random.Int(1204, 1207), GetCleanName()); } } @@ -1667,7 +1667,7 @@ void Client::OPGMEndTraining(const EQApplicationPacket *app) // goodbye message if (pTrainer->IsNPC()) { - pTrainer->Say_StringID(MakeRandomInt(1208, 1211), GetCleanName()); + pTrainer->Say_StringID(zone->random.Int(1208, 1211), GetCleanName()); } } diff --git a/zone/command.cpp b/zone/command.cpp index 453c58ec9..1f4d76498 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5003,157 +5003,157 @@ void command_randomfeatures(Client *c, const Seperator *sep) uint32 DrakkinDetails = 0xFFFFFFFF; // Set some common feature settings - EyeColor1 = MakeRandomInt(0, 9); - EyeColor2 = MakeRandomInt(0, 9); - LuclinFace = MakeRandomInt(0, 7); + EyeColor1 = zone->random.Int(0, 9); + EyeColor2 = zone->random.Int(0, 9); + LuclinFace = zone->random.Int(0, 7); // Adjust all settings based on the min and max for each feature of each race and gender switch (Race) { case 1: // Human - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); if (Gender == 0) { BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 2: // Barbarian - HairColor = MakeRandomInt(0, 19); - LuclinFace = MakeRandomInt(0, 87); + HairColor = zone->random.Int(0, 19); + LuclinFace = zone->random.Int(0, 87); if (Gender == 0) { BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 3: // Erudite if (Gender == 0) { - BeardColor = MakeRandomInt(0, 19); - Beard = MakeRandomInt(0, 5); - LuclinFace = MakeRandomInt(0, 57); + BeardColor = zone->random.Int(0, 19); + Beard = zone->random.Int(0, 5); + LuclinFace = zone->random.Int(0, 57); } if (Gender == 1) { - LuclinFace = MakeRandomInt(0, 87); + LuclinFace = zone->random.Int(0, 87); } break; case 4: // WoodElf - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); + HairStyle = zone->random.Int(0, 3); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 5: // HighElf - HairColor = MakeRandomInt(0, 14); + HairColor = zone->random.Int(0, 14); if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); BeardColor = HairColor; } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 6: // DarkElf - HairColor = MakeRandomInt(13, 18); + HairColor = zone->random.Int(13, 18); if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); BeardColor = HairColor; } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 7: // HalfElf - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); BeardColor = HairColor; } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 8: // Dwarf - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); BeardColor = HairColor; if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - LuclinFace = MakeRandomInt(0, 17); + HairStyle = zone->random.Int(0, 2); + LuclinFace = zone->random.Int(0, 17); } break; case 9: // Troll - EyeColor1 = MakeRandomInt(0, 10); - EyeColor2 = MakeRandomInt(0, 10); + EyeColor1 = zone->random.Int(0, 10); + EyeColor2 = zone->random.Int(0, 10); if (Gender == 1) { - HairStyle = MakeRandomInt(0, 3); - HairColor = MakeRandomInt(0, 23); + HairStyle = zone->random.Int(0, 3); + HairColor = zone->random.Int(0, 23); } break; case 10: // Ogre if (Gender == 1) { - HairStyle = MakeRandomInt(0, 3); - HairColor = MakeRandomInt(0, 23); + HairStyle = zone->random.Int(0, 3); + HairColor = zone->random.Int(0, 23); } break; case 11: // Halfling - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); if (Gender == 0) { BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 12: // Gnome - HairColor = MakeRandomInt(0, 24); + HairColor = zone->random.Int(0, 24); if (Gender == 0) { BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 128: // Iksar case 130: // VahShir break; case 330: // Froglok - LuclinFace = MakeRandomInt(0, 9); + LuclinFace = zone->random.Int(0, 9); case 522: // Drakkin - HairColor = MakeRandomInt(0, 3); + HairColor = zone->random.Int(0, 3); BeardColor = HairColor; - EyeColor1 = MakeRandomInt(0, 11); - EyeColor2 = MakeRandomInt(0, 11); - LuclinFace = MakeRandomInt(0, 6); - DrakkinHeritage = MakeRandomInt(0, 6); - DrakkinTattoo = MakeRandomInt(0, 7); - DrakkinDetails = MakeRandomInt(0, 7); + 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 = MakeRandomInt(0, 12); - HairStyle = MakeRandomInt(0, 8); + Beard = zone->random.Int(0, 12); + HairStyle = zone->random.Int(0, 8); } if (Gender == 1) { - Beard = MakeRandomInt(0, 3); - HairStyle = MakeRandomInt(0, 7); + Beard = zone->random.Int(0, 3); + HairStyle = zone->random.Int(0, 7); } break; default: @@ -10443,6 +10443,7 @@ void command_distance(Client *c, const Seperator *sep) { void command_cvs(Client *c, const Seperator *sep) { + c->Message(0, "%f %d", zone->random.Real(0.0f, 1.0f), zone->random.Int(0, 100)); if(c) { ServerPacket *pack = new ServerPacket(ServerOP_ClientVersionSummary, sizeof(ServerRequestClientVersionSummary_Struct)); diff --git a/zone/effects.cpp b/zone/effects.cpp index 0bface8b7..5c542d16d 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -55,30 +55,25 @@ int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { else value -= target->GetFcDamageAmtIncoming(this, spell_id)/spells[spell_id].buffduration; } - - value += dmg*GetSpellFocusDMG()/100; + + value += dmg*GetSpellFocusDMG()/100; if (AI_HasSpellsEffects()){ int16 chance = 0; int ratio = 0; if (spells[spell_id].buffduration == 0) { - chance += spellbonuses.CriticalSpellChance + spellbonuses.FrenziedDevastation; - - if (chance && MakeRandomInt(1,100) <= chance){ - + + if (chance && zone->random.Roll(chance)) { ratio += spellbonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncNoStack; value += (value*ratio)/100; entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_BLAST, GetCleanName(), itoa(-value)); } } else { - chance += spellbonuses.CriticalDoTChance; - - if (chance && MakeRandomInt(1,100) <= chance){ - + if (chance && zone->random.Roll(chance)) { ratio += spellbonuses.DotCritDmgIncrease; value += (value*ratio)/100; } @@ -119,14 +114,14 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) chance = 100; - if (MakeRandomInt(1,100) <= chance){ + if (zone->random.Roll(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)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) { - ratio += MakeRandomInt(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed) + else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Roll(RuleI(Spells, WizCritChance)))) { + ratio += zone->random.Int(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed) Critical = true; } @@ -193,22 +188,16 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { if (spellbonuses.CriticalDotDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay); - + value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100); - if (chance > 0 && (MakeRandomInt(1, 100) <= chance)) { - + if (chance > 0 && (zone->random.Roll(chance))) { int32 ratio = 200; ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease; - - value = value_BaseEffect*ratio/100; - - value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100; - + value = value_BaseEffect*ratio/100; + 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; - + 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); @@ -216,7 +205,7 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { if (extra_dmg) { int duration = CalcBuffDuration(this, this, spell_id); if (duration > 0) - extra_dmg /= duration; + extra_dmg /= duration; } value -= extra_dmg; @@ -224,25 +213,20 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { return value; } - value = value_BaseEffect; - - value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, 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) + + value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, 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); if (extra_dmg) { int duration = CalcBuffDuration(this, this, spell_id); if (duration > 0) - extra_dmg /= duration; - } - + extra_dmg /= duration; + } + value -= extra_dmg; return value; @@ -275,28 +259,26 @@ int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { //Scale all NPC spell healing via SetSpellFocusHeal(value) - value += value*GetSpellFocusHeal()/100; + value += value*GetSpellFocusHeal()/100; if (target) { - value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); + value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); value += value*target->GetHealRate(spell_id, this)/100; } //Allow for critical heal chance if NPC is loading spell effect bonuses. if (AI_HasSpellsEffects()){ - if(spells[spell_id].buffduration < 1) { - - if(spellbonuses.CriticalHealChance && (MakeRandomInt(0,99) < spellbonuses.CriticalHealChance)) { - value = value*2; + if(spellbonuses.CriticalHealChance && (zone->random.Roll(spellbonuses.CriticalHealChance))) { + value = value*2; entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetCleanName(), itoa(value)); } } - else if(spellbonuses.CriticalHealOverTime && (MakeRandomInt(0,99) < spellbonuses.CriticalHealOverTime)) { - value = value*2; + else if(spellbonuses.CriticalHealOverTime && (zone->random.Roll(spellbonuses.CriticalHealOverTime))) { + value = value*2; } } - + return value; } @@ -326,7 +308,7 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (spellbonuses.CriticalHealDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); - if(chance && (MakeRandomInt(0,99) < chance)) { + if(chance && (zone->random.Roll(chance))) { Critical = true; modifier = 2; //At present time no critical heal amount modifier SPA exists. } @@ -360,7 +342,7 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (spellbonuses.CriticalRegenDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); - if(chance && (MakeRandomInt(0,99) < chance)) + if(chance && zone->random.Roll(chance)) return (value * 2); } @@ -374,12 +356,12 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int16 FrenziedDevastation = itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation; if (FrenziedDevastation && IsPureNukeSpell(spell_id)) - cost *= 2; - + cost *= 2; + // 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) { - int16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100; + int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell if(mana_back > cost) mana_back = cost; @@ -392,7 +374,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) // WildcardX float PercentManaReduction = 0; float SpecializeSkill = GetSpecializeSkillValue(spell_id); - int SuccessChance = MakeRandomInt(0, 100); + int SuccessChance = zone->random.Int(0, 100); float bonus = 1.0; switch(GetAA(aaSpellCastingMastery)) @@ -444,7 +426,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) if(focus_redux > 0) { - PercentManaReduction += MakeRandomFloat(1, (double)focus_redux); + PercentManaReduction += zone->random.Real(1, (double)focus_redux); } cost -= (cost * (PercentManaReduction / 100)); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 0e8b10a8e..62fa1dd70 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1521,7 +1521,7 @@ XS(XS__ChooseRandom) if (items < 1) Perl_croak(aTHX_ "Usage: ChooseRandom(... list ...)"); - int index = MakeRandomInt(0, items-1); + int index = zone->random.Int(0, items-1); SV *tmp = ST(0); ST(0) = ST(index); diff --git a/zone/entity.cpp b/zone/entity.cpp index cae20c3ce..fd3d79f1f 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -628,7 +628,7 @@ void EntityList::AddCorpse(Corpse *corpse, uint32 in_id) void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) { npc->SetID(GetFreeID()); - npc->SetMerchantProbability((uint8) MakeRandomInt(0, 99)); + npc->SetMerchantProbability((uint8) zone->random.Int(0, 99)); parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); uint16 emoteid = npc->GetEmoteID(); @@ -1570,7 +1570,7 @@ Client *EntityList::GetRandomClient(float x, float y, float z, float Distance, C if (ClientsInRange.empty()) return nullptr; - return ClientsInRange[MakeRandomInt(0, ClientsInRange.size() - 1)]; + return ClientsInRange[zone->random.Int(0, ClientsInRange.size() - 1)]; } Corpse *EntityList::GetCorpseByOwner(Client *client) @@ -2890,7 +2890,7 @@ void EntityList::ClearFeignAggro(Mob *targ) it->second->RemoveFromHateList(targ); if (targ->IsClient()) { - if (it->second->GetLevel() >= 35 && MakeRandomInt(1, 100) <= 60) + if (it->second->GetLevel() >= 35 && zone->random.Roll(60)) it->second->AddFeignMemory(targ->CastToClient()); else targ->CastToClient()->RemoveXTarget(it->second, false); @@ -4505,7 +4505,7 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count) selection.push_back(j); while (selection.size() > 0 && count > 0) { - int k = MakeRandomInt(0, selection.size() - 1); + int k = zone->random.Int(0, selection.size() - 1); counts[selection[k]]++; count--; selection.erase(selection.begin() + k); @@ -4687,6 +4687,6 @@ Mob *EntityList::GetTargetForVirus(Mob *spreader, int range) if(TargetsInRange.size() == 0) return nullptr; - return TargetsInRange[MakeRandomInt(0, TargetsInRange.size() - 1)]; + return TargetsInRange[zone->random.Int(0, TargetsInRange.size() - 1)]; } diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index 47fc53a96..25d514cfe 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -186,8 +186,8 @@ void Mob::CalculateNewFearpoint() { int ran = 250 - (loop*2); loop++; - ranx = GetX()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1); - rany = GetY()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1); + ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); + rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); ranz = FindGroundZ(ranx,rany); if (ranz == -999999) continue; diff --git a/zone/forage.cpp b/zone/forage.cpp index cbb6550db..7e2f7d457 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -83,7 +83,7 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) { ret = 0; - uint32 rindex = MakeRandomInt(1, chancepool); + uint32 rindex = zone->random.Int(1, chancepool); for(int i = 0; i < index; i++) { if(rindex <= chance[i]) { @@ -136,7 +136,7 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, if (index <= 0) return 0; - uint32 random = MakeRandomInt(1, chancepool); + uint32 random = zone->random.Int(1, chancepool); for (int i = 0; i < index; i++) { if (random > chance[i]) @@ -258,18 +258,18 @@ void Client::GoFish() fishing_skill = 100+((fishing_skill-100)/2); } - if (MakeRandomInt(0,175) < fishing_skill) { + if (zone->random.Int(0,175) < fishing_skill) { uint32 food_id = 0; //25% chance to fish an item. - if (MakeRandomInt(0, 399) <= fishing_skill ) { + if (zone->random.Int(0, 399) <= fishing_skill ) { uint32 npc_id = 0; uint8 npc_chance = 0; food_id = database.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance); //check for add NPC if(npc_chance > 0 && npc_id) { - if(npc_chance < MakeRandomInt(0, 99)) { + if(npc_chance < zone->random.Int(0, 99)) { const NPCType* tmp = database.GetNPCType(npc_id); if(tmp != nullptr) { NPC* npc = new NPC(tmp, nullptr, GetX()+3, GetY(), GetZ(), GetHeading(), FlyMode3); @@ -289,7 +289,7 @@ void Client::GoFish() DeleteItemInInventory(bslot, 1, true); //do we need client update? if(food_id == 0) { - int index = MakeRandomInt(0, MAX_COMMON_FISH_IDS-1); + int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1); food_id = common_fish_ids[index]; } @@ -324,11 +324,11 @@ void Client::GoFish() else { //chance to use bait when you dont catch anything... - if (MakeRandomInt(0, 4) == 1) { + if (zone->random.Int(0, 4) == 1) { DeleteItemInInventory(bslot, 1, true); //do we need client update? Message_StringID(MT_Skills, FISHING_LOST_BAIT); //You lost your bait! } else { - if (MakeRandomInt(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it + if (zone->random.Int(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it //TODO: check for & consume an alcoholic beverage from inventory when this triggers, and set it as a rule that's disabled by default Message_StringID(MT_Skills, FISHING_SPILL_BEER); //You spill your beer while bringing in your line. else @@ -341,7 +341,7 @@ void Client::GoFish() //chance to break fishing pole... //this is potentially exploitable in that they can fish //and then swap out items in primary slot... too lazy to fix right now - if (MakeRandomInt(0, 49) == 1) { + if (zone->random.Int(0, 49) == 1) { Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke! DeleteItemInInventory(MainPrimary, 0, true); } @@ -370,18 +370,18 @@ void Client::ForageItem(bool guarantee) { }; // these may need to be fine tuned, I am just guessing here - if (guarantee || MakeRandomInt(0,199) < skill_level) { + if (guarantee || zone->random.Int(0,199) < skill_level) { uint32 foragedfood = 0; uint32 stringid = FORAGE_NOEAT; - if (MakeRandomInt(0,99) <= 25) { + if (zone->random.Roll(25)) { foragedfood = database.GetZoneForage(m_pp.zone_id, skill_level); } //not an else in case theres no DB food if(foragedfood == 0) { uint8 index = 0; - index = MakeRandomInt(0, MAX_COMMON_FOOD_IDS-1); + index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1); foragedfood = common_food_ids[index]; } @@ -438,7 +438,7 @@ void Client::ForageItem(bool guarantee) { } int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems; - if(!guarantee && MakeRandomInt(0,99) < ChanceSecondForage) { + if(!guarantee && zone->random.Roll(ChanceSecondForage)) { Message_StringID(MT_Skills, FORAGE_MASTERY); ForageItem(true); } diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 4c4290232..2e64f092f 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -485,10 +485,10 @@ Mob *HateList::GetRandom() } auto iterator = list.begin(); - int random = MakeRandomInt(0, count - 1); + int random = zone->random.Int(0, count - 1); for (int i = 0; i < random; i++) ++iterator; - + return (*iterator)->ent; } diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 121dad8c5..c5fda890e 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -49,15 +49,15 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite if (lts->mincash == lts->maxcash) cash = lts->mincash; else - cash = MakeRandomInt(lts->mincash, lts->maxcash); + cash = zone->random.Int(lts->mincash, lts->maxcash); if (cash != 0) { if (lts->avgcoin != 0) { //this is some crazy ass stuff... and makes very little sense... dont use it, k? uint32 mincoin = (uint32) (lts->avgcoin * 0.75 + 1); uint32 maxcoin = (uint32) (lts->avgcoin * 1.25 + 1); - *copper = MakeRandomInt(mincoin, maxcoin); - *silver = MakeRandomInt(mincoin, maxcoin); - *gold = MakeRandomInt(mincoin, maxcoin); + *copper = zone->random.Int(mincoin, maxcoin); + *silver = zone->random.Int(mincoin, maxcoin); + *gold = zone->random.Int(mincoin, maxcoin); if(*copper > cash) { *copper = cash; } cash -= *copper; if(*silver>(cash/10)) { *silver = (cash/10); } @@ -92,7 +92,7 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite float drop_chance = 0.0f; if(ltchance > 0.0 && ltchance < 100.0) { - drop_chance = MakeRandomFloat(0.0, 100.0); + drop_chance = zone->random.Real(0.0, 100.0); } if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance < ltchance)) { @@ -118,7 +118,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml uint8 limit = 0; // Start at a random point in itemlist. - uint32 item = MakeRandomInt(0, lds->NumEntries-1); + uint32 item = zone->random.Int(0, lds->NumEntries-1); // Main loop. for (uint32 i=0; iNumEntries;) { @@ -137,7 +137,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml float drop_chance = 0.0; if(thischance != 100.0) - drop_chance = MakeRandomFloat(0.0, 100.0); + drop_chance = zone->random.Real(0.0, 100.0); #if EQDEBUG>=11 LogFile->write(EQEMuLog::Debug, "Drop chance for npc: %s, this chance:%f, drop roll:%f", npc->GetName(), thischance, drop_chance); @@ -282,7 +282,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge eslot = MaterialPrimary; } else if (foundslot == MainSecondary - && (GetOwner() != nullptr || (GetLevel() >= 13 && MakeRandomInt(0,99) < NPC_DW_CHANCE) || (item2->Damage==0)) && + && (GetOwner() != nullptr || (GetLevel() >= 13 && 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/merc.cpp b/zone/merc.cpp index b2793db73..21c5092c9 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -170,49 +170,49 @@ void Merc::GenerateAppearance() { // Randomize facial appearance int iFace = 0; if(this->GetRace() == 2) { // Barbarian w/Tatoo - iFace = MakeRandomInt(0, 79); + iFace = zone->random.Int(0, 79); } else { - iFace = MakeRandomInt(0, 7); + iFace = zone->random.Int(0, 7); } int iHair = 0; int iBeard = 0; int iBeardColor = 1; if(this->GetRace() == 522) { - iHair = MakeRandomInt(0, 8); - iBeard = MakeRandomInt(0, 11); - iBeardColor = MakeRandomInt(0, 3); + iHair = zone->random.Int(0, 8); + iBeard = zone->random.Int(0, 11); + iBeardColor = zone->random.Int(0, 3); } else if(this->GetGender()) { - iHair = MakeRandomInt(0, 2); + iHair = zone->random.Int(0, 2); if(this->GetRace() == 8) { // Dwarven Females can have a beard - if(MakeRandomInt(1, 100) < 50) { + if(zone->random.Roll(50)) { iFace += 10; } } } else { - iHair = MakeRandomInt(0, 3); - iBeard = MakeRandomInt(0, 5); - iBeardColor = MakeRandomInt(0, 19); + 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) { - iHairColor = MakeRandomInt(0, 3); + iHairColor = zone->random.Int(0, 3); } else { - iHairColor = MakeRandomInt(0, 19); + iHairColor = zone->random.Int(0, 19); } - uint8 iEyeColor1 = (uint8)MakeRandomInt(0, 9); + uint8 iEyeColor1 = (uint8)zone->random.Int(0, 9); uint8 iEyeColor2 = 0; if(this->GetRace() == 522) { - iEyeColor1 = iEyeColor2 = (uint8)MakeRandomInt(0, 11); + iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11); } - else if(MakeRandomInt(1, 100) > 96) { - iEyeColor2 = MakeRandomInt(0, 9); + else if(zone->random.Int(1, 100) > 96) { + iEyeColor2 = zone->random.Int(0, 9); } else { iEyeColor2 = iEyeColor1; @@ -222,9 +222,9 @@ void Merc::GenerateAppearance() { int iTattoo = 0; int iDetails = 0; if(this->GetRace() == 522) { - iHeritage = MakeRandomInt(0, 6); - iTattoo = MakeRandomInt(0, 7); - iDetails = MakeRandomInt(0, 7); + iHeritage = zone->random.Int(0, 6); + iTattoo = zone->random.Int(0, 7); + iDetails = zone->random.Int(0, 7); } this->luclinface = iFace; @@ -1523,7 +1523,7 @@ void Merc::AI_Process() { meleeDistance = meleeDistance * .30; } else { - meleeDistance *= (float)MakeRandomFloat(.50, .85); + meleeDistance *= (float)zone->random.Real(.50, .85); } if(IsMercCaster() && GetLevel() > 12) { if(IsMercCasterCombatRange(GetTarget())) @@ -1624,7 +1624,7 @@ void Merc::AI_Process() { if (GetTarget() && flurrychance) { - if(MakeRandomInt(0, 100) < flurrychance) + if(zone->random.Roll(flurrychance)) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); Attack(GetTarget(), MainPrimary, false); @@ -1635,7 +1635,7 @@ void Merc::AI_Process() { int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; if (GetTarget() && ExtraAttackChanceBonus) { - if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus) + if(zone->random.Roll(ExtraAttackChanceBonus)) { Attack(GetTarget(), MainPrimary, false); } @@ -1669,10 +1669,8 @@ void Merc::AI_Process() { int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; - float random = MakeRandomFloat(0, 1); - // Max 78% of DW - if (random < DualWieldProbability) + if (zone->random.Roll(DualWieldProbability)) { Attack(GetTarget(), MainSecondary); // Single attack with offhand @@ -1934,7 +1932,7 @@ bool EntityList::Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance, return false; if (iChance < 100) { - int8 tmp = MakeRandomInt(1, 100); + int8 tmp = zone->random.Int(1, 100); if (tmp > iChance) return false; } @@ -2030,7 +2028,7 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { return false; if (iChance < 100) { - if (MakeRandomInt(0, 100) > iChance){ + if (zone->random.Int(0, 100) > iChance){ return false; } } @@ -2315,14 +2313,14 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { if(selectedMercSpell.spellid == 0 && !tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned()) { uint8 stunChance = 15; - if(MakeRandomInt(1, 100) <= stunChance) { + if(zone->random.Roll(stunChance)) { selectedMercSpell = GetBestMercSpellForStun(this); } } if(selectedMercSpell.spellid == 0) { uint8 lureChance = 25; - if(MakeRandomInt(1, 100) <= lureChance) { + if(zone->random.Roll(lureChance)) { selectedMercSpell = GetBestMercSpellForNukeByTargetResists(this, tar); } } @@ -2742,14 +2740,14 @@ int32 Merc::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals. - if (MakeRandomInt(1,100) <= chance){ + if (zone->random.Roll(chance)) { Critical = true; ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease; ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack; } - else if (GetClass() == CASTERDPS && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) { - ratio = MakeRandomInt(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. + else if (GetClass() == CASTERDPS && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Roll(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. Critical = true; } @@ -2833,7 +2831,7 @@ int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (spellbonuses.CriticalHealDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); - if(chance && (MakeRandomInt(0,99) < chance)) { + if(chance && zone->random.Roll(chance)) { Critical = true; modifier = 2; //At present time no critical heal amount modifier SPA exists. } @@ -2864,7 +2862,7 @@ int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (spellbonuses.CriticalRegenDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); - if(chance && (MakeRandomInt(0,99) < chance)) + if(chance && zone->random.Roll(chance)) return (value * 2); } @@ -2876,7 +2874,7 @@ 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) { - int16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100; + int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell if(mana_back > cost) mana_back = cost; @@ -2893,7 +2891,7 @@ int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost) if(focus_redux > 0) { - PercentManaReduction += MakeRandomFloat(1, (double)focus_redux); + PercentManaReduction += zone->random.Real(1, (double)focus_redux); } cost -= (cost * (PercentManaReduction / 100)); @@ -3825,17 +3823,17 @@ MercSpell Merc::GetBestMercSpellForAENuke(Merc* caster, Mob* tar) { } //check of we even want to cast an AE nuke - if(MakeRandomInt(1, 100) <= initialCastChance) { + if(zone->random.Roll(initialCastChance)) { result = GetBestMercSpellForAERainNuke(caster, tar); //check if we have a spell & allow for other AE nuke types - if(result.spellid == 0 && MakeRandomInt(1, 100) <= castChanceFalloff) { + if(result.spellid == 0 && zone->random.Roll(castChanceFalloff)) { result = GetBestMercSpellForPBAENuke(caster, tar); //check if we have a spell & allow for other AE nuke types - if(result.spellid == 0 && MakeRandomInt(1, 100) <= castChanceFalloff) { + if(result.spellid == 0 && zone->random.Roll(castChanceFalloff)) { result = GetBestMercSpellForTargetedAENuke(caster, tar); } @@ -3879,7 +3877,7 @@ MercSpell Merc::GetBestMercSpellForTargetedAENuke(Merc* caster, Mob* tar) { && !IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { uint8 numTargets = 0; if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) { - if(numTargets >= numTargetsCheck && MakeRandomInt(1, 100) <= castChance) { + if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) { result.spellid = mercSpellListItr->spellid; result.stance = mercSpellListItr->stance; result.type = mercSpellListItr->type; @@ -3929,7 +3927,7 @@ MercSpell Merc::GetBestMercSpellForPBAENuke(Merc* caster, Mob* tar) { if(IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { uint8 numTargets = 0; if(CheckAENuke(caster, caster, mercSpellListItr->spellid, numTargets)) { - if(numTargets >= numTargetsCheck && MakeRandomInt(1, 100) <= castChance) { + if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) { result.spellid = mercSpellListItr->spellid; result.stance = mercSpellListItr->stance; result.type = mercSpellListItr->type; @@ -3976,7 +3974,7 @@ MercSpell Merc::GetBestMercSpellForAERainNuke(Merc* caster, Mob* tar) { for(std::list::iterator 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) && MakeRandomInt(1, 100) <= castChance && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { + if(IsAERainNukeSpell(mercSpellListItr->spellid) && zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { uint8 numTargets = 0; if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) { if(numTargets >= numTargetsCheck) { @@ -4015,7 +4013,7 @@ MercSpell Merc::GetBestMercSpellForNuke(Merc* caster) { for(std::list::iterator 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) - && MakeRandomInt(1, 100) <= castChance && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { + && zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { result.spellid = mercSpellListItr->spellid; result.stance = mercSpellListItr->stance; result.type = mercSpellListItr->type; @@ -4447,7 +4445,7 @@ bool Merc::CheckConfidence() { ConfidenceLossChance = 25 - ( 5 * (GetTierID() - 1)); } - if(MakeRandomInt(0 ,100) < ConfidenceLossChance) { + if(zone->random.Roll(ConfidenceLossChance)) { result = false; } @@ -4593,7 +4591,7 @@ void Merc::DoClassAttacks(Mob *target) { break; case TANK:{ if(level >= RuleI(Combat, NPCBashKickLevel)){ - if(MakeRandomInt(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. + if(zone->random.Int(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference. { DoAnim(animKick); int32 dmg = 0; @@ -4606,7 +4604,7 @@ void Merc::DoClassAttacks(Mob *target) { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else - dmg = MakeRandomInt(1, GetKickDamage()); + dmg = zone->random.Int(1, GetKickDamage()); } } @@ -4628,7 +4626,7 @@ void Merc::DoClassAttacks(Mob *target) { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else - dmg = MakeRandomInt(1, GetBashDamage()); + dmg = zone->random.Int(1, GetBashDamage()); } } @@ -4756,7 +4754,7 @@ const char* Merc::GetRandomName(){ bool valid = false; while(!valid) { - int rndnum=MakeRandomInt(0, 75),n=1; + int rndnum=zone->random.Int(0, 75),n=1; bool dlc=false; bool vwl=false; bool dbl=false; @@ -4777,18 +4775,18 @@ const char* Merc::GetRandomName(){ rndname[0]=vowels[rndnum]; vwl=true; } - int namlen=MakeRandomInt(5, 10); + int namlen=zone->random.Int(5, 10); for (int i=n;irandom.Int(0, 62); if (rndnum>46) { // pick a cons pair if (i>namlen-3) // last 2 chars in name? { // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng" - rndnum=MakeRandomInt(0, 7)*2; + rndnum=zone->random.Int(0, 7)*2; } else { // pick any from the set @@ -4806,12 +4804,12 @@ const char* Merc::GetRandomName(){ } else { // select a vowel - rndname[i]=vowels[MakeRandomInt(0, 16)]; + rndname[i]=vowels[zone->random.Int(0, 16)]; } vwl=!vwl; if (!dbl && !dlc) { // one chance at double letters in name - if (!MakeRandomInt(0, i+9)) // chances decrease towards end of name + if (!zone->random.Int(0, i+9)) // chances decrease towards end of name { rndname[i+1]=rndname[i]; dbl=true; @@ -6367,4 +6365,4 @@ uint32 Merc::CalcUpkeepCost(uint32 templateID , uint8 level, uint8 currency_type } return cost; -} \ No newline at end of file +} diff --git a/zone/mob.cpp b/zone/mob.cpp index e56f3839c..7e58cb037 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2356,7 +2356,7 @@ uint32 Mob::RandomTimer(int min,int max) { int r = 14000; if(min != 0 && max != 0 && min < max) { - r = MakeRandomInt(min, max); + r = zone->random.Int(min, max); } return r; } @@ -2753,7 +2753,7 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) { if(IsClient()) twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id); - if(twinproc_chance && (MakeRandomInt(0,99) < twinproc_chance)) + if(twinproc_chance && zone->random.Roll(twinproc_chance)) twinproc = true; if (IsBeneficialSpell(spell_id)) { @@ -3082,7 +3082,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) { if(!target || !IsValidSpell(spell_id)) return false; - + int spell_trig = 0; // Count all the percentage chances to trigger for all effects for(int i = 0; i < EFFECT_COUNT; i++) @@ -3098,7 +3098,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) { if (spells[spell_id].effectid[i] == SE_SpellTrigger) { - if(MakeRandomInt(0, trig_chance) <= spells[spell_id].base[i]) + if(zone->random.Int(0, trig_chance) <= spells[spell_id].base[i]) { // If we trigger an effect then its over. if (IsValidSpell(spells[spell_id].base2[i])){ @@ -3118,7 +3118,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) // if the chances don't add to 100, then each effect gets a chance to fire, chance for no trigger as well. else { - if(MakeRandomInt(0, 100) <= spells[spell_id].base[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); @@ -3223,7 +3223,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) if (focus > 0) { - if(MakeRandomInt(0, 100) <= focus) + 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); @@ -3242,7 +3242,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) int32 focus = CalcFocusEffect(focusTwincast, buffs[i].spellid, spell_id); if(focus > 0) { - if(MakeRandomInt(0, 100) <= focus) + if(zone->random.Roll(focus)) { SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff); } @@ -4023,7 +4023,7 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) { if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level) { - if(MakeRandomInt(0,99) < spells[spell_id].base[i]) + 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); } } @@ -4038,17 +4038,17 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) 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])) + if(zone->random.Roll(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])) + if(zone->random.Roll(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])) + if(zone->random.Roll(static_cast(spellbonuses.SpellOnKill[i + 1]))) SpellFinished(spellbonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } @@ -4065,19 +4065,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(MakeRandomInt(0, 99) < static_cast(aabonuses.SpellOnDeath[i + 1])) { + if(zone->random.Roll(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])) { + if(zone->random.Roll(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])) { + if(zone->random.Roll(static_cast(spellbonuses.SpellOnDeath[i + 1]))) { SpellFinished(spellbonuses.SpellOnDeath[i], this, 10, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff); } } @@ -4240,7 +4240,7 @@ bool Mob::TryReflectSpell(uint32 spell_id) int chance = itembonuses.reflect_chance + spellbonuses.reflect_chance + aabonuses.reflect_chance; - if(chance && MakeRandomInt(0, 99) < chance) + if(chance && zone->random.Roll(chance)) return true; return false; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 30f435dfa..d041ac884 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -57,7 +57,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { return false; if (iChance < 100) { - if (MakeRandomInt(0, 100) >= iChance) + if (zone->random.Int(0, 100) >= iChance) return false; } @@ -94,7 +94,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { 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. + && (AIspells[i].time_cancast + (zone->random.Int(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time. ) { #if MobAI_DEBUG_Spells >= 21 @@ -126,7 +126,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { } case SpellType_Root: { Mob *rootee = GetHateRandom(); - if (rootee && !rootee->IsRooted() && MakeRandomInt(0, 99) < 50 + if (rootee && !rootee->IsRooted() && zone->random.Roll(50) && rootee->DontRootMeBefore() < Timer::GetCurrentTime() && rootee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 ) { @@ -165,7 +165,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { } case SpellType_InCombatBuff: { - if(MakeRandomInt(0, 99) < 50) + if(zone->random.Roll(50)) { AIDoSpellCast(i, tar, mana_cost); return true; @@ -184,7 +184,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { case SpellType_Slow: case SpellType_Debuff: { Mob * debuffee = GetHateRandom(); - if (debuffee && manaR >= 10 && MakeRandomInt(0, 99 < 70) && + if (debuffee && manaR >= 10 && zone->random.Roll(70) && debuffee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) { if (!checked_los) { if (!CheckLosFN(debuffee)) @@ -198,7 +198,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { } case SpellType_Nuke: { if ( - manaR >= 10 && MakeRandomInt(0, 99) < 70 + manaR >= 10 && zone->random.Roll(70) && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 ) { if(!checked_los) { @@ -212,7 +212,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { break; } case SpellType_Dispel: { - if(MakeRandomInt(0, 99) < 15) + if(zone->random.Roll(15)) { if(!checked_los) { if(!CheckLosFN(tar)) @@ -228,7 +228,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { break; } case SpellType_Mez: { - if(MakeRandomInt(0, 99) < 20) + if(zone->random.Roll(20)) { Mob * mezTar = nullptr; mezTar = entity_list.GetTargetForMez(this); @@ -244,7 +244,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { case SpellType_Charm: { - if(!IsPet() && MakeRandomInt(0, 99) < 20) + if(!IsPet() && zone->random.Roll(20)) { Mob * chrmTar = GetHateRandom(); if(chrmTar && chrmTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) @@ -258,7 +258,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { case SpellType_Pet: { //keep mobs from recasting pets when they have them. - if (!IsPet() && !GetPetID() && MakeRandomInt(0, 99) < 25) { + if (!IsPet() && !GetPetID() && zone->random.Roll(25)) { AIDoSpellCast(i, tar, mana_cost); return true; } @@ -266,7 +266,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { } case SpellType_Lifetap: { if (GetHPRatio() <= 95 - && MakeRandomInt(0, 99) < 50 + && zone->random.Roll(50) && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 ) { if(!checked_los) { @@ -282,7 +282,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { case SpellType_Snare: { if ( !tar->IsRooted() - && MakeRandomInt(0, 99) < 50 + && zone->random.Roll(50) && tar->DontSnareMeBefore() < Timer::GetCurrentTime() && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 ) { @@ -300,7 +300,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { } case SpellType_DOT: { if ( - MakeRandomInt(0, 99) < 60 + zone->random.Roll(60) && tar->DontDotMeBefore() < Timer::GetCurrentTime() && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 ) { @@ -369,7 +369,7 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float return false; if (iChance < 100) { - uint8 tmp = MakeRandomInt(0, 99); + uint8 tmp = zone->random.Int(0, 99); if (tmp >= iChance) return false; } @@ -687,7 +687,7 @@ void Client::AI_SpellCast() } else { - uint32 idx = MakeRandomInt(0, (valid_spells.size()-1)); + uint32 idx = zone->random.Int(0, (valid_spells.size()-1)); spell_to_cast = valid_spells[idx]; slot_to_use = slots[idx]; } @@ -875,7 +875,7 @@ void Client::AI_Process() if (flurrychance) { - if(MakeRandomInt(0, 100) < flurrychance) + if(zone->random.Roll(flurrychance)) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); Attack(GetTarget(), MainPrimary, false); @@ -892,7 +892,7 @@ void Client::AI_Process() wpn->GetItem()->ItemType == ItemType2HBlunt || wpn->GetItem()->ItemType == ItemType2HPiercing ) { - if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus) + if(zone->random.Roll(ExtraAttackChanceBonus)) { Attack(GetTarget(), MainPrimary, false); } @@ -931,7 +931,7 @@ void Client::AI_Process() int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; - if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability) + if(zone->random.Roll(DualWieldProbability)) { Attack(GetTarget(), MainSecondary); if(CheckDoubleAttack()) @@ -1191,7 +1191,7 @@ void Mob::AI_Process() { //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); + 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... @@ -1215,7 +1215,7 @@ void Mob::AI_Process() { int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0); flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance); - if (MakeRandomInt(0, 99) < flurry_chance) { + if (zone->random.Roll(flurry_chance)) { ExtraAttackOptions opts; int cur = GetSpecialAbilityParam(SPECATK_FLURRY, 2); if (cur > 0) @@ -1257,7 +1257,7 @@ void Mob::AI_Process() { int16 flurry_chance = owner->aabonuses.PetFlurry + owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry; - if (flurry_chance && (MakeRandomInt(0, 99) < flurry_chance)) + if (flurry_chance && zone->random.Roll(flurry_chance)) Flurry(nullptr); } } @@ -1266,7 +1266,7 @@ void Mob::AI_Process() { { int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0); rampage_chance = rampage_chance > 0 ? rampage_chance : 20; - if(MakeRandomInt(0, 99) < rampage_chance) { + if(zone->random.Roll(rampage_chance)) { ExtraAttackOptions opts; int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2); if(cur > 0) { @@ -1305,7 +1305,7 @@ void Mob::AI_Process() { { int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0); rampage_chance = rampage_chance > 0 ? rampage_chance : 20; - if(MakeRandomInt(0, 99) < rampage_chance) { + if(zone->random.Roll(rampage_chance)) { ExtraAttackOptions opts; int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2); if(cur > 0) { @@ -1349,13 +1349,12 @@ void Mob::AI_Process() { //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) + if(zone->random.Roll(DualWieldProbability)) { Attack(target, MainSecondary); if (CanThisClassDoubleAttack()) { - int32 RandRoll = MakeRandomInt(0, 99); - if (RandRoll < (GetLevel() + 20)) + if (zone->random.Roll(GetLevel() + 20)) { Attack(target, MainSecondary); } @@ -1619,12 +1618,12 @@ void NPC::AI_DoMovement() { ) { float movedist = roambox_distance*roambox_distance; - float movex = MakeRandomFloat(0, movedist); + float movex = zone->random.Real(0, movedist); float movey = movedist - movex; movex = sqrtf(movex); movey = sqrtf(movey); - movex *= MakeRandomInt(0, 1) ? 1 : -1; - movey *= MakeRandomInt(0, 1) ? 1 : -1; + movex *= zone->random.Int(0, 1) ? 1 : -1; + movey *= zone->random.Int(0, 1) ? 1 : -1; roambox_movingto_x = GetX() + movex; roambox_movingto_y = GetY() + movey; //Try to calculate new coord using distance. @@ -1635,9 +1634,9 @@ void NPC::AI_DoMovement() { //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); + roambox_movingto_x = zone->random.Real(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); + roambox_movingto_y = zone->random.Real(roambox_min_y+1,roambox_max_y-1); } mlog(AI__WAYPOINTS, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)", @@ -1879,7 +1878,7 @@ void Mob::AI_Event_NoLongerEngaged() { if (minLastFightingDelayMoving == maxLastFightingDelayMoving) pLastFightingDelayMoving += minLastFightingDelayMoving; else - pLastFightingDelayMoving += MakeRandomInt(minLastFightingDelayMoving, maxLastFightingDelayMoving); + 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()){ diff --git a/zone/npc.cpp b/zone/npc.cpp index 17ab9ed48..034be8f75 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -293,7 +293,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float 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)); + std::advance(trap_list_iter, zone->random.Int(0, trap_list.size() - 1)); LDoNTrapTemplate* tt = (*trap_list_iter); if(tt) { @@ -550,10 +550,10 @@ void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_ } void NPC::AddCash() { - copper = MakeRandomInt(1, 100); - silver = MakeRandomInt(1, 50); - gold = MakeRandomInt(1, 10); - platinum = MakeRandomInt(1, 5); + copper = zone->random.Int(1, 100); + silver = zone->random.Int(1, 50); + gold = zone->random.Int(1, 10); + platinum = zone->random.Int(1, 5); } void NPC::RemoveCash() { @@ -1372,7 +1372,7 @@ void NPC::PickPocket(Client* thief) { return; } - if(MakeRandomInt(0, 100) > 95){ + if(zone->random.Roll(5)) { AddToHateList(thief, 50); Say("Stop thief!"); thief->Message(13, "You are noticed trying to steal!"); @@ -1401,7 +1401,7 @@ void NPC::PickPocket(Client* thief) { 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); + bool steal_item = (zone->random.Roll(50) || no_coin); if (steal_item) { ItemList::iterator cur,end; @@ -1431,7 +1431,7 @@ void NPC::PickPocket(Client* thief) { } if (x > 0) { - int random = MakeRandomInt(0, x-1); + int random = zone->random.Int(0, x-1); inst = database.CreateItem(steal_items[random], charges[random]); if (inst) { @@ -1466,7 +1466,7 @@ void NPC::PickPocket(Client* thief) { } if (!steal_item) //Steal money { - uint32 amt = MakeRandomInt(1, (steal_skill/25)+1); + uint32 amt = zone->random.Int(1, (steal_skill/25)+1); int steal_type = 0; if (!money[0]) { @@ -1481,7 +1481,7 @@ void NPC::PickPocket(Client* thief) { } } - if (MakeRandomInt(0, 100) <= stealchance) + if (zone->random.Roll(stealchance)) { switch (steal_type) { @@ -1962,7 +1962,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) void NPC::LevelScale() { - uint8 random_level = (MakeRandomInt(level, maxlevel)); + uint8 random_level = (zone->random.Int(level, maxlevel)); float scaling = (((random_level / (float)level) - 1) * (scalerate / 100.0f)); @@ -2449,4 +2449,4 @@ void NPC::DepopSwarmPets() } } } -} \ No newline at end of file +} diff --git a/zone/object.cpp b/zone/object.cpp index 0201434c0..b1acc53c9 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -441,8 +441,8 @@ void Object::RandomSpawn(bool send_packet) { if(!m_ground_spawn) return; - m_data.x = MakeRandomFloat(m_min_x, m_max_x); - m_data.y = MakeRandomFloat(m_min_y, m_max_y); + m_data.x = zone->random.Real(m_min_x, m_max_x); + m_data.y = zone->random.Real(m_min_y, m_max_y); respawn_timer.Disable(); if(send_packet) { diff --git a/zone/pathing.cpp b/zone/pathing.cpp index c860913fe..3bf02115e 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -1344,7 +1344,7 @@ PathNode* PathManager::FindPathNodeByCoordinates(float x, float y, float z) int PathManager::GetRandomPathNode() { - return MakeRandomInt(0, Head.PathNodeCount - 1); + return zone->random.Int(0, Head.PathNodeCount - 1); } diff --git a/zone/pets.cpp b/zone/pets.cpp index cf9ecab8c..052a44bea 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -109,7 +109,7 @@ const char *GetRandPetName() "Zibann","Zibarer","Zibartik","Zibekn","Zibn","Zibobn","Zobaner","Zobann", "Zobarn","Zober","Zobn","Zonanab","Zonaner","Zonann","Zonantik","Zonarer", "Zonartik","Zonobn","Zonobtik","Zontik","Ztik" }; - int r = MakeRandomInt(0, (sizeof(petnames)/sizeof(const char *))-1); + int r = zone->random.Int(0, (sizeof(petnames)/sizeof(const char *))-1); printf("Pet being created: %s\n",petnames[r]); // DO NOT COMMENT THIS OUT! return petnames[r]; } diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 8d8562157..bf7192107 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -109,7 +109,7 @@ uint32 Spawn2::resetTimer() if (variance_ != 0) { int var_over_2 = (variance_ * 1000) / 2; - rspawn = MakeRandomInt(rspawn - var_over_2, rspawn + var_over_2); + rspawn = zone->random.Int(rspawn - var_over_2, rspawn + var_over_2); //put a lower bound on it, not a lot of difference below 100, so set that as the bound. if(rspawn < 100) @@ -126,7 +126,7 @@ uint32 Spawn2::despawnTimer(uint32 despawn_timer) if (variance_ != 0) { int var_over_2 = (variance_ * 1000) / 2; - dspawn = MakeRandomInt(dspawn - var_over_2, dspawn + var_over_2); + dspawn = zone->random.Int(dspawn - var_over_2, dspawn + var_over_2); //put a lower bound on it, not a lot of difference below 100, so set that as the bound. if(dspawn < 100) diff --git a/zone/spawngroup.cpp b/zone/spawngroup.cpp index 81d6c5d51..6943d9349 100644 --- a/zone/spawngroup.cpp +++ b/zone/spawngroup.cpp @@ -25,8 +25,10 @@ #include "zonedb.h" #include "../common/misc_functions.h" #include "../common/string_util.h" +#include "zone.h" extern EntityList entity_list; +extern Zone* zone; SpawnEntry::SpawnEntry( uint32 in_NPCType, int in_chance, uint8 in_npc_spawn_limit ) { NPCType = in_NPCType; @@ -77,7 +79,7 @@ uint32 SpawnGroup::GetNPCType() { int32 roll = 0; - roll = MakeRandomInt(0, totalchance-1); + roll = zone->random.Int(0, totalchance-1); cur = possible.begin(); end = possible.end(); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index cf6a83c80..767efc410 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -138,9 +138,9 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, who->MeleeMitigation(this, max_damage, min_damage); - if(max_damage > 0) + if(max_damage > 0) CommonOutgoingHitSuccess(who, max_damage, skill); - + } who->AddToHateList(this, hate, 0, false); @@ -155,17 +155,17 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int kb_chance = 25; kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100; - if (MakeRandomInt(0, 99) < kb_chance) + 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); - + if (max_damage > 0 && HasSkillProcSuccess()) TrySkillProc(who, skill, ReuseTime*1000, true); - + if(max_damage == -3 && !who->HasDied()) DoRiposte(who); } @@ -256,7 +256,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { if(RuleB(Combat, UseIntervalAC)) ht = dmg = GetBashDamage(); else - ht = dmg = MakeRandomInt(1, GetBashDamage()); + ht = dmg = zone->random.Int(1, GetBashDamage()); } } @@ -295,8 +295,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 || MakeRandomInt(0,100) < 75)){ + if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , ReuseTime, true); } AtkRounds--; @@ -333,7 +332,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { if(RuleB(Combat, UseIntervalAC)) ht = dmg = GetKickDamage(); else - ht = dmg = MakeRandomInt(1, GetKickDamage()); + ht = dmg = zone->random.Int(1, GetKickDamage()); } } @@ -348,18 +347,18 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { //Live AA - Technique of Master Wu int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; if (wuchance) { - if (wuchance >= 100 || wuchance > MakeRandomInt(0, 99)) { + if (wuchance >= 100 || zone->random.Roll(wuchance)) { int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick }; int extra = 1; // always 1/4 of the double attack chance, 25% at rank 5 (100/4) - if (wuchance / 4 > MakeRandomInt(0, 99)) + if (zone->random.Roll(wuchance / 4)) extra++; // They didn't add a string ID for this. std::string msg = StringFormat("The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); // live uses 400 here -- not sure if it's the best for all clients though SendColoredText(400, msg); while (extra) { - MonkSpecialAttack(GetTarget(), MonkSPA[MakeRandomInt(0, 4)]); + MonkSpecialAttack(GetTarget(), MonkSPA[zone->random.Int(0, 4)]); extra--; } } @@ -484,7 +483,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) if(RuleB(Combat, UseIntervalAC)) ht = ndamage = max_dmg; else - ht = ndamage = MakeRandomInt(min_dmg, max_dmg); + ht = ndamage = zone->random.Int(min_dmg, max_dmg); } else{ ht = max_dmg; @@ -525,15 +524,14 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { //Live AA - Seized Opportunity int FrontalBSChance = itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance; - if (FrontalBSChance && (FrontalBSChance > MakeRandomInt(0, 100))) + if (FrontalBSChance && zone->random.Roll(FrontalBSChance)) bCanFrontalBS = true; } - - if (bIsBehind || bCanFrontalBS){ // Player is behind other OR can do Frontal Backstab - if (bCanFrontalBS) + if (bIsBehind || bCanFrontalBS){ // Player is behind other OR can do Frontal Backstab + if (bCanFrontalBS) CastToClient()->Message(0,"Your fierce attack is executed with such grace, your target did not see it coming!"); - + RogueBackstab(other,false,ReuseTime); if (level > 54) { if(IsClient() && CastToClient()->CheckDoubleAttack(false)) @@ -541,14 +539,14 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { if(other->GetHP() > 0) RogueBackstab(other,false,ReuseTime); - if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100)) + if (tripleChance && other->GetHP() > 0 && zone->random.Roll(tripleChance)) RogueBackstab(other,false,ReuseTime); } } - + if(IsClient()) CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); - + } //Live AA - Chaotic Backstab else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { @@ -562,7 +560,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { if(other->GetHP() > 0) RogueBackstab(other,true, ReuseTime); - if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100)) + if (tripleChance && other->GetHP() > 0 && zone->random.Roll(tripleChance)) RogueBackstab(other,false,ReuseTime); } @@ -640,7 +638,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) if(RuleB(Combat, UseIntervalAC)) ndamage = max_hit; else - ndamage = MakeRandomInt(min_hit, max_hit); + ndamage = zone->random.Int(min_hit, max_hit); } } } @@ -793,7 +791,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 && MakeRandomInt(0,99) > ChanceAvoidConsume)){ + if (!ChanceAvoidConsume || (ChanceAvoidConsume < 100 && zone->random.Int(0,99) > ChanceAvoidConsume)){ DeleteItemInInventory(ammo_slot, 1, true); mlog(COMBAT__RANGED, "Consumed one arrow from slot %d", ammo_slot); } else { @@ -920,11 +918,10 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite bool dobonus = false; if(GetClass() == RANGER && GetLevel() > 50){ - int bonuschance = RuleI(Combat, ArcheryBonusChance); bonuschance = mod_archery_bonus_chance(bonuschance, RangeWeapon); - if( !RuleB(Combat, UseArcheryBonusRoll) || (MakeRandomInt(1, 100) < bonuschance)){ + if( !RuleB(Combat, UseArcheryBonusRoll) || zone->random.Roll(bonuschance)){ if(RuleB(Combat, ArcheryBonusRequiresStationary)){ if(other->IsNPC() && !other->IsMoving() && !other->IsRooted()) dobonus = true; @@ -949,7 +946,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if(RuleB(Combat, UseIntervalAC)) TotalDmg = MaxDmg; else - TotalDmg = MakeRandomInt(1, MaxDmg); + TotalDmg = zone->random.Int(1, MaxDmg); int minDmg = 1; if(GetLevel() > 25){ @@ -1193,9 +1190,9 @@ void NPC::RangedAttack(Mob* other) if(ammo) SendItemAnimation(other, ammo, SkillArchery); - else + else ProjectileAnimation(other, 0,false,0,0,0,0,GetAmmoIDfile(),skillinuse); - + FaceTarget(other); if (!other->CheckHitChance(this, skillinuse, MainRange, GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2))) @@ -1211,17 +1208,17 @@ void NPC::RangedAttack(Mob* other) if(WDmg > 0 || ADmg > 0) { mlog(COMBAT__RANGED, "Ranged attack hit %s.", other->GetName()); - + int32 MaxDmg = max_dmg * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types int32 MinDmg = min_dmg * RuleR(Combat, ArcheryNPCMultiplier); if(RuleB(Combat, UseIntervalAC)) TotalDmg = MaxDmg; else - TotalDmg = MakeRandomInt(MinDmg, MaxDmg); + TotalDmg = zone->random.Int(MinDmg, MaxDmg); TotalDmg += TotalDmg * GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3) / 100; //Damage modifier - + other->AvoidDamage(this, TotalDmg, false); other->MeleeMitigation(this, TotalDmg, MinDmg); if (TotalDmg > 0) @@ -1262,7 +1259,7 @@ uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) { if(RuleB(Combat, UseIntervalAC)) TotalDmg = MaxDmg; else - TotalDmg = MakeRandomInt(1, MaxDmg); + TotalDmg = zone->random.Int(1, MaxDmg); minDmg = 1; if(GetLevel() > 25){ @@ -1680,7 +1677,7 @@ void NPC::DoClassAttacks(Mob *target) { } case WARRIOR: case WARRIORGM:{ if(level >= RuleI(Combat, NPCBashKickLevel)){ - if(MakeRandomInt(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. + if(zone->random.Roll(75)) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference. DoAnim(animKick); int32 dmg = 0; @@ -1692,7 +1689,7 @@ void NPC::DoClassAttacks(Mob *target) { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else - dmg = MakeRandomInt(1, GetKickDamage()); + dmg = zone->random.Int(1, GetKickDamage()); } } @@ -1713,7 +1710,7 @@ void NPC::DoClassAttacks(Mob *target) { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else - dmg = MakeRandomInt(1, GetBashDamage()); + dmg = zone->random.Int(1, GetBashDamage()); } } @@ -1740,8 +1737,8 @@ void NPC::DoClassAttacks(Mob *target) { reuse = FrenzyReuseTime * 1000; - while(AtkRounds > 0) { - if (GetTarget() && (AtkRounds == 1 || MakeRandomInt(0,100) < 75)){ + while(AtkRounds > 0) { + if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, -1 , reuse, true); } AtkRounds--; @@ -1766,7 +1763,7 @@ void NPC::DoClassAttacks(Mob *target) { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else - dmg = MakeRandomInt(1, GetKickDamage()); + dmg = zone->random.Int(1, GetKickDamage()); } } @@ -1791,7 +1788,7 @@ void NPC::DoClassAttacks(Mob *target) { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else - dmg = MakeRandomInt(1, GetBashDamage()); + dmg = zone->random.Int(1, GetBashDamage()); } } @@ -1900,7 +1897,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else - dmg = MakeRandomInt(1, GetBashDamage()); + dmg = zone->random.Int(1, GetBashDamage()); } } @@ -1937,7 +1934,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) //Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. while(AtkRounds > 0) { - if (GetTarget() && (AtkRounds == 1 || MakeRandomInt(0,100) < 75)){ + if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , ReuseTime, true); } AtkRounds--; @@ -1964,7 +1961,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else - dmg = MakeRandomInt(1, GetKickDamage()); + dmg = zone->random.Int(1, GetKickDamage()); } } @@ -1984,17 +1981,17 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) //Live AA - Technique of Master Wu int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; if (wuchance) { - if (wuchance >= 100 || wuchance > MakeRandomInt(0, 99)) { + if (wuchance >= 100 || zone->random.Roll(wuchance)) { int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick }; int extra = 1; - if (wuchance / 4 > MakeRandomInt(0, 99)) + if (zone->random.Roll(wuchance / 4)) extra++; // They didn't add a string ID for this. std::string msg = StringFormat("The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); // live uses 400 here -- not sure if it's the best for all clients though SendColoredText(400, msg); while (extra) { - MonkSpecialAttack(ca_target, MonkSPA[MakeRandomInt(0, 4)]); + MonkSpecialAttack(ca_target, MonkSPA[zone->random.Int(0, 4)]); extra--; } } @@ -2046,7 +2043,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) { int32 newhate = 0; float tauntchance = 50.0f; - + if(always_succeed) tauntchance = 101.0f; @@ -2078,7 +2075,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) { tauntchance /= 100.0f; - if (tauntchance > MakeRandomFloat(0, 1)) { + if (tauntchance > zone->random.Real(0, 1)) { if (hate_top && hate_top != this){ newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1; who->CastToNPC()->AddToHateList(this, newhate); @@ -2100,7 +2097,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) { if (HasSkillProcs()) TrySkillProc(who, SkillTaunt, TauntReuseTime*1000); - + if (Success && HasSkillProcSuccess()) TrySkillProc(who, SkillTaunt, TauntReuseTime*1000, true); } @@ -2134,7 +2131,7 @@ void Mob::InstillDoubt(Mob *who) { //target's counters value -= target->GetLevel()*4 + who->GetWIS()/4; - if (MakeRandomInt(0,99) < value) { + if (zone->random.Roll(value)) { //temporary hack... //cast fear on them... should prolly be a different spell //and should be un-resistable. @@ -2143,7 +2140,7 @@ void Mob::InstillDoubt(Mob *who) { } else { Message_StringID(4,NOT_SCARING); //Idea from WR: - /* if (target->IsNPC() && MakeRandomInt(0,99) < 10 ) { + /* if (target->IsNPC() && zone->random.Int(0,99) < 10 ) { entity_list.MessageClose(target, false, 50, MT_NPCRampage, "%s lashes out in anger!",target->GetName()); //should we actually do this? and the range is completely made up, unconfirmed entity_list.AEAttack(target, 50); @@ -2151,12 +2148,12 @@ void Mob::InstillDoubt(Mob *who) { } } -uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { +uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { //Only works on YOUR target. - if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() + if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && (skillInUse == SkillArchery) && (GetTarget() == defender)) { - - uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1]; + + uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1]; uint8 HeadShot_Level = 0; //Get Highest Headshot Level HeadShot_Level = aabonuses.HSLevel; if (HeadShot_Level < spellbonuses.HSLevel) @@ -2164,9 +2161,9 @@ uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { else if (HeadShot_Level < itembonuses.HSLevel) HeadShot_Level = itembonuses.HSLevel; - if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){ + if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){ float ProcChance = GetSpecialProcChances(MainRange); - if(ProcChance > MakeRandomFloat(0,1)) + if(zone->random.Roll(ProcChance)) return HeadShot_Dmg; } } @@ -2195,7 +2192,7 @@ float Mob::GetSpecialProcChances(uint16 hand) } else { /*PRE 2014 CHANGE Dev Quote - "Elidroth SOE:Proc chance is a function of your base hardcapped Dexterity / 35 + Heroic Dexterity / 25.” Kayen: Most reports suggest a ~ 6% chance to Headshot which consistent with above.*/ - + ProcChance = (static_cast(mydex/35) + static_cast(itembonuses.HeroicDEX / 25))/100.0f; } @@ -2206,9 +2203,9 @@ uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 Reuse if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && (skillInUse == SkillBackstab || skillInUse == SkillThrowing)) { - + uint32 Assassinate_Dmg = aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1]; - + uint8 Assassinate_Level = 0; //Get Highest Headshot Level Assassinate_Level = aabonuses.AssassinateLevel; if (Assassinate_Level < spellbonuses.AssassinateLevel) @@ -2226,13 +2223,13 @@ 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) ProcChance = GetSpecialProcChances(MainRange); else ProcChance = GetAssassinateProcChances(ReuseTime); - if(ProcChance > MakeRandomFloat(0,1)) + if(zone->random.Roll(ProcChance)) return Assassinate_Dmg; } } @@ -2252,7 +2249,7 @@ float Mob::GetAssassinateProcChances(uint16 ReuseTime) if (RuleB(Combat, AdjustSpecialProcPerMinute)) { ProcChance = (static_cast(ReuseTime*1000) * - RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f); + RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f); ProcBonus += (10 + (static_cast(mydex/10) + static_cast(itembonuses.HeroicDEX /10)))/100.0f; ProcChance += ProcChance * ProcBonus / 100.0f; @@ -2314,7 +2311,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes } } - ApplySpecialAttackMod(skillinuse, max_hit, min_hit); + ApplySpecialAttackMod(skillinuse, max_hit, min_hit); min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; if(max_hit < min_hit) @@ -2323,8 +2320,8 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if(RuleB(Combat, UseIntervalAC)) damage = max_hit; else - damage = MakeRandomInt(min_hit, max_hit); - + damage = zone->random.Int(min_hit, max_hit); + if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) { damage = 0; } else { @@ -2362,7 +2359,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int kb_chance = 25; kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100; - if (MakeRandomInt(0, 99) < kb_chance) + if (zone->random.Roll(kb_chance)) SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff); } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index d3ef1145d..59526fbbc 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -455,7 +455,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(IsClient()) { - if(MakeRandomInt(0, 99) < RuleI(Spells, SuccorFailChance)) { //2% Fail chance by default + if(zone->random.Roll(RuleI(Spells, SuccorFailChance))) { //2% Fail chance by default if(IsClient()) { CastToClient()->Message_StringID(MT_SpellFailure,SUCCOR_FAIL); @@ -710,9 +710,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (IsClient()) stun_resist += aabonuses.StunResist; - if (stun_resist <= 0 || MakeRandomInt(0,99) >= stun_resist) { + if (stun_resist <= 0 || zone->random.Int(0,99) >= stun_resist) { mlog(COMBAT__HITS, "Stunned. We had %d percent resist chance.", stun_resist); - + if (caster->IsClient()) effect_value += effect_value*caster->CastToClient()->GetFocusEffect(focusFcStunTimeMod, spell_id)/100; @@ -1033,8 +1033,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #endif if(!spellbonuses.AntiGate){ - if(MakeRandomInt(0, 99) < effect_value) - Gate(); + if(zone->random.Roll(effect_value)) + Gate(); else caster->Message_StringID(MT_SpellFailure,GATE_FAIL); } @@ -1475,16 +1475,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #endif int wipechance = spells[spell_id].base[i]; int bonus = 0; - + if (caster){ - bonus = caster->spellbonuses.IncreaseChanceMemwipe + - caster->itembonuses.IncreaseChanceMemwipe + + bonus = caster->spellbonuses.IncreaseChanceMemwipe + + caster->itembonuses.IncreaseChanceMemwipe + caster->aabonuses.IncreaseChanceMemwipe; } wipechance += wipechance*bonus/100; - - if(MakeRandomInt(0, 99) < wipechance) + + if(zone->random.Roll(wipechance)) { if(IsAIControlled()) { @@ -1597,7 +1597,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(IsClient()) { - if (MakeRandomInt(0, 99) > spells[spell_id].base[i]) { + if (zone->random.Int(0, 99) > spells[spell_id].base[i]) { CastToClient()->SetFeigned(false); entity_list.MessageClose_StringID(this, false, 200, 10, STRING_FEIGNFAILED, GetName()); } @@ -2187,7 +2187,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Fading Memories"); #endif - if(MakeRandomInt(0, 99) < spells[spell_id].base[i] ) { + if(zone->random.Roll(spells[spell_id].base[i])) { if(caster && caster->IsClient()) caster->CastToClient()->Escape(); @@ -2711,11 +2711,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) } }else{ int32 newhate = GetHateAmount(caster) + effect_value; - if (newhate < 1) + if (newhate < 1) SetHate(caster,1); - else + else SetHate(caster,newhate); - } + } } break; } @@ -2724,9 +2724,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (buffslot >= 0) break; - if(!spells[spell_id].uninterruptable && IsCasting() && MakeRandomInt(0, 100) <= spells[spell_id].base[i]) + if(!spells[spell_id].uninterruptable && IsCasting() && zone->random.Roll(spells[spell_id].base[i])) InterruptSpell(); - + break; } @@ -2742,17 +2742,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); break; } - + case SE_ApplyEffect: { if (caster && IsValidSpell(spells[spell_id].base2[i])){ - - if(MakeRandomInt(0, 100) <= spells[spell_id].base[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); } break; } - + case SE_SpellTrigger: { if (!SE_SpellTrigger_HasCast) { @@ -3209,7 +3208,7 @@ snare has both of them negative, yet their range should work the same: break; } case 123: // added 2/6/04 - result = MakeRandomInt(ubase, abs(max)); + result = zone->random.Int(ubase, abs(max)); break; case 124: // check sign @@ -3573,16 +3572,16 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste int wipechance = spells[spell_id].base[i]; int bonus = 0; - + if (caster){ - bonus = caster->spellbonuses.IncreaseChanceMemwipe + - caster->itembonuses.IncreaseChanceMemwipe + + bonus = caster->spellbonuses.IncreaseChanceMemwipe + + caster->itembonuses.IncreaseChanceMemwipe + caster->aabonuses.IncreaseChanceMemwipe; } - + wipechance += wipechance*bonus/100; - - if(MakeRandomInt(0, 99) < wipechance) + + if(zone->random.Roll(wipechance)) { if(IsAIControlled()) { @@ -3602,16 +3601,14 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste } 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 (MakeRandomInt(0, 99) < RuleI(Spells, RootBreakCheckChance)){ - + 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) + if(resist_check == 100) break; else if(!TryFadeEffect(slot)) @@ -3623,11 +3620,10 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste case SE_Fear: { - if (MakeRandomInt(0, 99) < RuleI(Spells, FearBreakCheckChance)){ - + if (zone->random.Roll(RuleI(Spells, FearBreakCheckChance))) { float resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster); - if(resist_check == 100) + if(resist_check == 100) break; else if(!TryFadeEffect(slot)) @@ -3664,7 +3660,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste break_chance -= (2 * (((double)GetSkill(SkillDivination) + ((double)GetLevel() * 3.0)) / 650.0)); } - if(MakeRandomFloat(0.0, 100.0) < break_chance) + if(zone->random.Real(0.0, 100.0) < break_chance) { BuffModifyDurationBySpellID(spell_id, 3); } @@ -3684,7 +3680,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste { if(IsCasting()) { - if(MakeRandomInt(0, 100) <= spells[spell_id].base[i]) + if(zone->random.Roll(spells[spell_id].base[i])) { InterruptSpell(); } @@ -4582,11 +4578,9 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) case SE_TriggerOnCast: if(type == focusTriggerOnCast){ - if(MakeRandomInt(0, 100) <= base1){ + if(zone->random.Roll(base1)) { value = base2; - } - - else{ + } else { value = 0; LimitFailure = true; } @@ -4600,7 +4594,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) case SE_BlockNextSpellFocus: if(type == focusBlockNextSpell){ - if(MakeRandomInt(1, 100) <= base1) + if(zone->random.Roll(base1)) value = 1; } break; @@ -4955,7 +4949,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo value = focus_spell.base[i]; } else { - value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]); + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } break; @@ -4974,7 +4968,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo value = focus_spell.base[i]; } else { - value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]); + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } break; @@ -4993,7 +4987,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo value = focus_spell.base[i]; } else { - value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]); + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } } break; @@ -5062,7 +5056,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_TriggerOnCast: if(type == focusTriggerOnCast){ - if(MakeRandomInt(1, 100) <= focus_spell.base[i]) + if(zone->random.Roll(focus_spell.base[i])) value = focus_spell.base2[i]; else value = 0; @@ -5071,7 +5065,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_BlockNextSpellFocus: if(type == focusBlockNextSpell){ - if(MakeRandomInt(1, 100) <= focus_spell.base[i]) + if(zone->random.Roll(focus_spell.base[i])) value = 1; } break; @@ -5219,12 +5213,9 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (TempItem && TempItem->Focus.Effect > 0 && IsValidSpell(TempItem->Focus.Effect)) { proc_spellid = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id); - if (IsValidSpell(proc_spellid)){ - ProcChance = GetSympatheticProcChances(spell_id, spells[TempItem->Focus.Effect].base[0], TempItem->ProcRate); - - if(MakeRandomFloat(0, 1) <= ProcChance) + if(zone->random.Roll(ProcChance)) SympatheticProcList.push_back(proc_spellid); } } @@ -5240,14 +5231,10 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { { const 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)){ - ProcChance = GetSympatheticProcChances(spell_id, spells[TempItemAug->Focus.Effect].base[0], TempItemAug->ProcRate); - - if(MakeRandomFloat(0, 1) <= ProcChance) + if(zone->random.Roll(ProcChance)) SympatheticProcList.push_back(proc_spellid); } } @@ -5275,8 +5262,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (IsValidSpell(proc_spellid)){ ProcChance = GetSympatheticProcChances(spell_id, spells[focusspellid].base[0]); - - if(MakeRandomFloat(0, 1) <= ProcChance) + if(zone->random.Roll(ProcChance)) SympatheticProcList.push_back(proc_spellid); } } @@ -5302,10 +5288,8 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { proc_spellid = CalcAAFocus(type, aa_AA, spell_id); if (IsValidSpell(proc_spellid)){ - ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1)); - - if(MakeRandomFloat(0, 1) <= ProcChance) + if(zone->random.Roll(ProcChance)) SympatheticProcList.push_back(proc_spellid); } } @@ -5313,7 +5297,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (SympatheticProcList.size() > 0) { - uint8 random = MakeRandomInt(0, SympatheticProcList.size()-1); + uint8 random = zone->random.Int(0, SympatheticProcList.size()-1); int FinalSympatheticProc = SympatheticProcList[random]; SympatheticProcList.clear(); return FinalSympatheticProc; @@ -5672,7 +5656,7 @@ bool Mob::TryDivineSave() */ int32 SuccessChance = aabonuses.DivineSaveChance[0] + itembonuses.DivineSaveChance[0] + spellbonuses.DivineSaveChance[0]; - if (SuccessChance && MakeRandomInt(0, 100) <= SuccessChance) + if (SuccessChance && zone->random.Roll(SuccessChance)) { SetHP(1); @@ -5731,7 +5715,7 @@ bool Mob::TryDeathSave() { if (SuccessChance > 95) SuccessChance = 95; - if(SuccessChance >= MakeRandomInt(0, 100)) { + if(zone->random.Roll(SuccessChance)) { if(spellbonuses.DeathSave[0] == 2) HealAmt = RuleI(Spells, DivineInterventionHeal); //8000HP is how much LIVE Divine Intervention max heals @@ -5762,7 +5746,7 @@ bool Mob::TryDeathSave() { if (SuccessChance > 95) SuccessChance = 95; - if(SuccessChance >= MakeRandomInt(0, 100)) { + if(zone->random.Roll(SuccessChance)) { if(spellbonuses.DeathSave[0] == 2) HealAmt = RuleI(Spells, DivineInterventionHeal); @@ -6064,7 +6048,7 @@ bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){ else if (dispel_chance < 10) dispel_chance = 10; - if (MakeRandomInt(0,99) < dispel_chance) + if (zone->random.Roll(dispel_chance)) return true; else return false; diff --git a/zone/spells.cpp b/zone/spells.cpp index 3bdc3557e..b051dfdca 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -178,7 +178,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, if(IsClient()){ int chance = CastToClient()->GetFocusEffect(focusFcMute, spell_id); - if (MakeRandomInt(0,99) < chance){ + if (zone->random.Roll(chance)) { Message_StringID(13, SILENCED_STRING); if(IsClient()) CastToClient()->SendSpellBarEnable(spell_id); @@ -697,7 +697,7 @@ bool Client::CheckFizzle(uint16 spell_id) specialize = specialize * 1.3; break; } - if(((specialize/6.0f) + 15.0f) < MakeRandomFloat(0, 100)) { + if(((specialize/6.0f) + 15.0f) < zone->random.Real(0, 100)) { specialize *= SPECIALIZE_FIZZLE / 200.0f; } else { specialize = 0.0f; @@ -739,7 +739,7 @@ bool Client::CheckFizzle(uint16 spell_id) } */ - float fizzle_roll = MakeRandomFloat(0, 100); + float fizzle_roll = zone->random.Real(0, 100); mlog(SPELLS__CASTING, "Check Fizzle %s spell %d fizzlechance: %0.2f%% diff: %0.2f roll: %0.2f", GetName(), spell_id, fizzlechance, diff, fizzle_roll); @@ -1028,7 +1028,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, mlog(SPELLS__CASTING, "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)); - if(!spells[spell_id].uninterruptable && MakeRandomFloat(0, 100) > channelchance) { + if(!spells[spell_id].uninterruptable && zone->random.Real(0, 100) > channelchance) { mlog(SPELLS__CASTING_ERR, "Casting of %d canceled: interrupted.", spell_id); InterruptSpell(); return; @@ -1044,7 +1044,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, // first check for component reduction if(IsClient()) { int reg_focus = CastToClient()->GetFocusEffect(focusReagentCost,spell_id); - if(MakeRandomInt(1, 100) <= reg_focus) { + if(zone->random.Roll(reg_focus)) { mlog(SPELLS__CASTING, "Spell %d: Reagent focus item prevented reagent consumption (%d chance)", spell_id, reg_focus); } else { if(reg_focus > 0) @@ -4204,7 +4204,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use { IsFear = true; int fear_resist_bonuses = CalcFearResistChance(); - if(MakeRandomInt(0, 99) < fear_resist_bonuses) + if(zone->random.Roll(fear_resist_bonuses)) { mlog(SPELLS__RESISTS, "Resisted spell in fear resistance, had %d chance to resist", fear_resist_bonuses); return 0; @@ -4215,14 +4215,14 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use //Check for Spell Effect specific resistance chances (ie AA Mental Fortitude) int se_resist_bonuses = GetSpellEffectResistChance(spell_id); - if(se_resist_bonuses && (MakeRandomInt(0, 99) < se_resist_bonuses)) + if(se_resist_bonuses && zone->random.Roll(se_resist_bonuses)) { return 0; } // Check for Chance to Resist Spell bonuses (ie Sanctification Discipline) int resist_bonuses = CalcResistChanceBonus(); - if(resist_bonuses && (MakeRandomInt(0, 99) < resist_bonuses)) + if(resist_bonuses && zone->random.Roll(resist_bonuses)) { mlog(SPELLS__RESISTS, "Resisted spell in sanctification, had %d chance to resist", resist_bonuses); return 0; @@ -4448,7 +4448,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use } //Finally our roll - int roll = MakeRandomInt(0, 200); + int roll = zone->random.Int(0, 200); if(roll > resist_chance) { return 100; @@ -4665,7 +4665,7 @@ void Mob::Stun(int duration) if(IsValidSpell(casting_spell_id) && !spells[casting_spell_id].uninterruptable) { int persistent_casting = spellbonuses.PersistantCasting + itembonuses.PersistantCasting + aabonuses.PersistantCasting; - if(MakeRandomInt(0,99) > persistent_casting) + if(zone->random.Int(0,99) > persistent_casting) InterruptSpell(); } @@ -5548,4 +5548,4 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust) ++iter; } -} \ No newline at end of file +} diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index fd9f5a632..58774f4b1 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -923,7 +923,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { _log(TRADESKILLS__TRACE, "...Current skill: %d , Trivial: %d , Success chance: %f percent", user_skill , spec->trivial , chance); _log(TRADESKILLS__TRACE, "...Bonusstat: %d , INT: %d , WIS: %d , DEX: %d , STR: %d", bonusstat , GetINT() , GetWIS() , GetDEX() , GetSTR()); - float res = MakeRandomFloat(0, 99); + float res = zone->random.Real(0, 99); int aa_chance = 0; //AA modifiers @@ -1057,7 +1057,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { chance = mod_tradeskill_chance(chance, spec); - if (((spec->tradeskill==75) || GetGM() || (chance > res)) || MakeRandomInt(0, 99) < aa_chance){ + if (((spec->tradeskill==75) || GetGM() || (chance > res)) || zone->random.Roll(aa_chance)) { success_modifier = 1; if(over_trivial < 0) @@ -1127,7 +1127,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { uint8 sc = 0; while(itr != spec->salvage.end()) { for(sc = 0; sc < itr->second; sc++) - if(MakeRandomInt(0,99) < SalvageChance) + if(zone->random.Roll(SalvageChance)) SummonItem(itr->first, 1); ++itr; } @@ -1153,7 +1153,7 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float //In stage2 the only thing that matters is your current unmodified skill. //If you want to customize here you probbably need to implement your own //formula instead of tweaking the below one. - if (chance_stage1 > MakeRandomFloat(0, 99)) { + if (chance_stage1 > zone->random.Real(0, 99)) { if (current_raw_skill < 15) { //Always succeed chance_stage2 = 100; @@ -1168,7 +1168,7 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float chance_stage2 = mod_tradeskill_skillup(chance_stage2); - if (chance_stage2 > MakeRandomFloat(0, 99)) { + if (chance_stage2 > zone->random.Real(0, 99)) { //Only if stage1 and stage2 succeeded you get a skillup. SetSkill(tradeskill, current_raw_skill + 1); diff --git a/zone/trap.cpp b/zone/trap.cpp index 44c177118..7d412d7cb 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -144,7 +144,7 @@ void Trap::Trigger(Mob* trigger) { if ((tmp = database.GetNPCType(effectvalue))) { - NPC* new_npc = new NPC(tmp, 0, x-5+MakeRandomInt(0, 10), y-5+MakeRandomInt(0, 10), z-5+MakeRandomInt(0, 10), MakeRandomInt(0, 249), FlyMode3); + NPC* new_npc = new NPC(tmp, 0, x-5+zone->random.Int(0, 10), y-5+zone->random.Int(0, 10), z-5+zone->random.Int(0, 10), zone->random.Int(0, 249), FlyMode3); new_npc->AddLootTable(); entity_list.AddNPC(new_npc); new_npc->AddToHateList(trigger,1); @@ -165,7 +165,7 @@ void Trap::Trigger(Mob* trigger) { if ((tmp = database.GetNPCType(effectvalue))) { - NPC* new_npc = new NPC(tmp, 0, x-2+MakeRandomInt(0, 5), y-2+MakeRandomInt(0, 5), z-2+MakeRandomInt(0, 5), MakeRandomInt(0, 249), FlyMode3); + NPC* new_npc = new NPC(tmp, 0, x-2+zone->random.Int(0, 5), y-2+zone->random.Int(0, 5), z-2+zone->random.Int(0, 5), zone->random.Int(0, 249), FlyMode3); new_npc->AddLootTable(); entity_list.AddNPC(new_npc); new_npc->AddToHateList(trigger,1); @@ -185,10 +185,10 @@ void Trap::Trigger(Mob* trigger) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer; - int dmg = MakeRandomInt(effectvalue, effectvalue2); + int dmg = zone->random.Int(effectvalue, effectvalue2); trigger->SetHP(trigger->GetHP() - dmg); a->damage = dmg; - a->sequence = MakeRandomInt(0, 1234567); + a->sequence = zone->random.Int(0, 1234567); a->source = GetHiddenTrigger()!=nullptr ? GetHiddenTrigger()->GetID() : trigger->GetID(); a->spellid = 0; a->target = trigger->GetID(); @@ -197,7 +197,7 @@ void Trap::Trigger(Mob* trigger) safe_delete(outapp); } } - respawn_timer.Start((respawn_time + MakeRandomInt(0, respawn_var)) * 1000); + respawn_timer.Start((respawn_time + zone->random.Int(0, respawn_var)) * 1000); chkarea_timer.Disable(); disarmed = true; } @@ -250,7 +250,7 @@ Mob* EntityList::GetTrapTrigger(Trap* trap) { if ((xdiff*xdiff + ydiff*ydiff) <= maxdist && zdiff < trap->maxzdiff) { - if (MakeRandomInt(0,100) < trap->chance) + if (zone->random.Roll(trap->chance)) return(cur); else savemob = cur; diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 908f0f946..410e76f3f 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -270,7 +270,7 @@ void NPC::CalculateNewWaypoint() if(closest.size() != 0) { iter = closest.begin(); - std::advance(iter, MakeRandomInt(0, closest.size() - 1)); + std::advance(iter, zone->random.Int(0, closest.size() - 1)); cur_wp = (*iter).index; } @@ -278,7 +278,7 @@ void NPC::CalculateNewWaypoint() } case 2: //random { - cur_wp = MakeRandomInt(0, Waypoints.size() - 1); + cur_wp = zone->random.Int(0, Waypoints.size() - 1); if(cur_wp == old_wp) { if(cur_wp == (Waypoints.size() - 1)) @@ -339,7 +339,7 @@ void NPC::CalculateNewWaypoint() if(closest.size() != 0) { iter = closest.begin(); - std::advance(iter, MakeRandomInt(0, closest.size() - 1)); + std::advance(iter, zone->random.Int(0, closest.size() - 1)); cur_wp = (*iter).index; } break; @@ -412,13 +412,13 @@ void NPC::SetWaypointPause() switch (pausetype) { case 0: //Random Half - AIwalking_timer->Start((cur_wp_pause - MakeRandomInt(0, cur_wp_pause-1)/2)*1000); + AIwalking_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); break; case 2: //Random Full - AIwalking_timer->Start(MakeRandomInt(0, cur_wp_pause-1)*1000); + AIwalking_timer->Start(zone->random.Int(0, cur_wp_pause-1)*1000); break; } } diff --git a/zone/zone.cpp b/zone/zone.cpp index 9b42bfb68..257d8e5a7 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1300,13 +1300,13 @@ void Zone::ChangeWeather() return; } - int chance = MakeRandomInt(0, 3); + int chance = zone->random.Int(0, 3); uint8 rainchance = zone->newzone_data.rain_chance[chance]; uint8 rainduration = zone->newzone_data.rain_duration[chance]; uint8 snowchance = zone->newzone_data.snow_chance[chance]; uint8 snowduration = zone->newzone_data.snow_duration[chance]; uint32 weathertimer = 0; - uint16 tmpweather = MakeRandomInt(0, 100); + uint16 tmpweather = zone->random.Int(0, 100); uint8 duration = 0; uint8 tmpOldWeather = zone->zone_weather; bool changed = false; @@ -1315,7 +1315,7 @@ void Zone::ChangeWeather() { if(rainchance > 0 || snowchance > 0) { - uint8 intensity = MakeRandomInt(1, 10); + uint8 intensity = zone->random.Int(1, 10); if((rainchance > snowchance) || (rainchance == snowchance)) { //It's gunna rain! diff --git a/zone/zone.h b/zone/zone.h index 2d74c9f17..40c3a8d11 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -22,6 +22,7 @@ #include "../common/linked_list.h" #include "../common/rulesys.h" #include "../common/types.h" +#include "../common/random.h" #include "qglobals.h" #include "spawn2.h" #include "spawngroup.h" @@ -253,6 +254,9 @@ public: void UpdateHotzone(); std::unordered_map tick_items; + // random object that provides random values for the zone + EQEmu::Random random; + //MODDING HOOKS void mod_init(); void mod_repop(); @@ -310,7 +314,7 @@ private: Timer* Instance_Warning_timer; LinkedList client_auth_list; QGlobalCache *qGlobals; - + Timer hotzone_timer; }; From 6f867ebca304d74ce8624c2bc0bc7eb2424ae7f1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 1 Dec 2014 19:50:05 -0500 Subject: [PATCH 75/96] Add license info --- common/random.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/common/random.h b/common/random.h index 0e7316007..ef2b3ef73 100644 --- a/common/random.h +++ b/common/random.h @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2014 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 __random_h__ #define __random_h__ @@ -62,6 +80,5 @@ namespace EQEmu { }; } - #endif /* !__random_h__ */ From 24ea7a0d45a85c219a59e5e10ca936c41ea15503 Mon Sep 17 00:00:00 2001 From: Trevius Date: Mon, 1 Dec 2014 19:54:01 -0600 Subject: [PATCH 76/96] Mercenaries now spawn as the same Gender and Size of the Merchant they are purchased from. Mercenaries now spawn with randomized facial features when purchased. Setting a lastname for NPCs will now override any hard coded lastname (such as GM Trainers). --- changelog.txt | 6 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2014_12_01_mercs_table_update.sql | 1 + zone/client_packet.cpp | 2 +- zone/command.cpp | 185 +----- zone/entity.cpp | 10 +- zone/merc.cpp | 237 +++----- zone/merc.h | 4 +- zone/mob.cpp | 555 ++++++++++++------ zone/mob.h | 2 + zone/zonedb.cpp | 83 +-- zone/zonedb.h | 1 + 13 files changed, 549 insertions(+), 540 deletions(-) create mode 100644 utils/sql/git/required/2014_12_01_mercs_table_update.sql diff --git a/changelog.txt b/changelog.txt index e3de59b35..d8ed052ab 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/01/2014 == +Trevius: Mercenaries now spawn as the same Gender and Size of the Merchant they are purchased from. +Trevius: Mercenaries now spawn with randomized facial features when purchased. +Trevius: Setting a lastname for NPCs will now override any hard coded lastname (such as GM Trainers). + +Required SQL: utils/sql/git/required/2014_12_01_mercs_table_update.sql == 11/28/2014 == Trevius: Fixed a zone crash related to numhits for spells. diff --git a/common/version.h b/common/version.h index 88131e9be..43b4f8b10 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 9058 +#define CURRENT_BINARY_DATABASE_VERSION 9059 #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 039b0135a..8291465a4 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -312,6 +312,7 @@ 9056|2014_11_08_RaidMembers.sql|SHOW COLUMNS FROM `raid_members` LIKE 'groupid'|missing|unsigned 9057|2014_11_13_spells_new_updates.sql|SHOW COLUMNS FROM `spells_new` LIKE 'disallow_sit'|empty| 9058|2014_11_26_InventoryTableUpdate.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornamenticon'|empty| +9059|2014_11_30_mercs_table_update.sql|SHOW COLUMNS FROM `mercs` LIKE 'MercSize'|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/2014_12_01_mercs_table_update.sql b/utils/sql/git/required/2014_12_01_mercs_table_update.sql new file mode 100644 index 000000000..e5dc895f9 --- /dev/null +++ b/utils/sql/git/required/2014_12_01_mercs_table_update.sql @@ -0,0 +1 @@ +ALTER TABLE `mercs` ADD `MercSize` float( 0 ) NOT NULL DEFAULT '5' AFTER `Gender`; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e2884e738..adb3b4464 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9619,7 +9619,7 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app) TakeMoneyFromPP(cost, true); } - // 0 is approved hire request + // approved hire request SendMercMerchantResponsePacket(0); } else diff --git a/zone/command.cpp b/zone/command.cpp index 453c58ec9..f4c2c8e91 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -4985,189 +4985,10 @@ void command_randomfeatures(Client *c, const Seperator *sep) c->Message(0,"Error: This command requires a target"); else { - uint16 Race = target->GetRace(); - if (Race <= 12 || Race == 128 || Race == 130 || Race == 330 || Race == 522) { - - uint8 Gender = target->GetGender(); - uint8 Texture = 0xFF; - uint8 HelmTexture = 0xFF; - uint8 HairColor = 0xFF; - uint8 BeardColor = 0xFF; - uint8 EyeColor1 = 0xFF; - uint8 EyeColor2 = 0xFF; - uint8 HairStyle = 0xFF; - uint8 LuclinFace = 0xFF; - uint8 Beard = 0xFF; - uint32 DrakkinHeritage = 0xFFFFFFFF; - uint32 DrakkinTattoo = 0xFFFFFFFF; - uint32 DrakkinDetails = 0xFFFFFFFF; - - // Set some common feature settings - EyeColor1 = MakeRandomInt(0, 9); - EyeColor2 = MakeRandomInt(0, 9); - LuclinFace = MakeRandomInt(0, 7); - - // Adjust all settings based on the min and max for each feature of each race and gender - switch (Race) - { - case 1: // Human - HairColor = MakeRandomInt(0, 19); - if (Gender == 0) { - BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - } - break; - case 2: // Barbarian - HairColor = MakeRandomInt(0, 19); - LuclinFace = MakeRandomInt(0, 87); - if (Gender == 0) { - BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - } - break; - case 3: // Erudite - if (Gender == 0) { - BeardColor = MakeRandomInt(0, 19); - Beard = MakeRandomInt(0, 5); - LuclinFace = MakeRandomInt(0, 57); - } - if (Gender == 1) { - LuclinFace = MakeRandomInt(0, 87); - } - break; - case 4: // WoodElf - HairColor = MakeRandomInt(0, 19); - if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - } - break; - case 5: // HighElf - HairColor = MakeRandomInt(0, 14); - if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); - BeardColor = HairColor; - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - } - break; - case 6: // DarkElf - HairColor = MakeRandomInt(13, 18); - if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); - BeardColor = HairColor; - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - } - break; - case 7: // HalfElf - HairColor = MakeRandomInt(0, 19); - if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); - BeardColor = HairColor; - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - } - break; - case 8: // Dwarf - HairColor = MakeRandomInt(0, 19); - BeardColor = HairColor; - if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - LuclinFace = MakeRandomInt(0, 17); - } - break; - case 9: // Troll - EyeColor1 = MakeRandomInt(0, 10); - EyeColor2 = MakeRandomInt(0, 10); - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 3); - HairColor = MakeRandomInt(0, 23); - } - break; - case 10: // Ogre - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 3); - HairColor = MakeRandomInt(0, 23); - } - break; - case 11: // Halfling - HairColor = MakeRandomInt(0, 19); - if (Gender == 0) { - BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - } - break; - case 12: // Gnome - HairColor = MakeRandomInt(0, 24); - if (Gender == 0) { - BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); - } - if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - } - break; - case 128: // Iksar - case 130: // VahShir - break; - case 330: // Froglok - LuclinFace = MakeRandomInt(0, 9); - case 522: // Drakkin - HairColor = MakeRandomInt(0, 3); - BeardColor = HairColor; - EyeColor1 = MakeRandomInt(0, 11); - EyeColor2 = MakeRandomInt(0, 11); - LuclinFace = MakeRandomInt(0, 6); - DrakkinHeritage = MakeRandomInt(0, 6); - DrakkinTattoo = MakeRandomInt(0, 7); - DrakkinDetails = MakeRandomInt(0, 7); - if (Gender == 0) { - Beard = MakeRandomInt(0, 12); - HairStyle = MakeRandomInt(0, 8); - } - if (Gender == 1) { - Beard = MakeRandomInt(0, 3); - HairStyle = MakeRandomInt(0, 7); - } - break; - default: - break; - } - - target->SendIllusionPacket(Race, Gender, Texture, HelmTexture, HairColor, BeardColor, - EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF, - DrakkinHeritage, DrakkinTattoo, DrakkinDetails); - - c->Message(0,"NPC Features Randomized"); - } + if (target->RandomizeFeatures()) + c->Message(0,"Features Randomized"); else - c->Message(0,"This command requires a Playable Race as the Target"); + c->Message(0,"This command requires a Playable Race as the target"); } } diff --git a/zone/entity.cpp b/zone/entity.cpp index cae20c3ce..f0e077e78 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -658,10 +658,12 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue) { - if (merc) { + if (merc) + { merc->SetID(GetFreeID()); - if (SendSpawnPacket) { + if (SendSpawnPacket) + { if (dontqueue) { // Send immediately EQApplicationPacket *outapp = new EQApplicationPacket(); @@ -673,12 +675,10 @@ void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue) // Queue the packet NewSpawn_Struct *ns = new NewSpawn_Struct; memset(ns, 0, sizeof(NewSpawn_Struct)); - merc->FillSpawnStruct(ns, merc); + merc->FillSpawnStruct(ns, 0); AddToSpawnQueue(merc->GetID(), &ns); safe_delete(ns); } - - //parse->EventMERC(EVENT_SPAWN, merc, nullptr, "", 0); } merc_list.insert(std::pair(merc->GetID(), merc)); diff --git a/zone/merc.cpp b/zone/merc.cpp index b2793db73..5593c3e50 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -62,7 +62,7 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading) skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)r,GetLevel()); } - GetMercSize(); + size = d->size; CalcBonuses(); SetHP(GetMaxHP()); @@ -112,131 +112,66 @@ void Merc::CalcBonuses() rooted = FindType(SE_Root); } -void Merc::GetMercSize() { +float Merc::GetDefaultSize() { float MercSize = GetSize(); - switch(this->GetRace()) { - case 1: // Humans have no race bonus - break; - case 2: // Barbarian - MercSize = 7.0; - break; - case 3: // Erudite - break; - case 4: // Wood Elf - MercSize = 5.0; - break; - case 5: // High Elf - break; - case 6: // Dark Elf - MercSize = 5.0; - break; - case 7: // Half Elf - MercSize = 5.5; - break; - case 8: // Dwarf - MercSize = 4.0; - break; - case 9: // Troll - MercSize = 8.0; - break; - case 10: // Ogre - MercSize = 9.0; - break; - case 11: // Halfling - MercSize = 3.5; - break; - case 12: // Gnome - MercSize = 3.0; - break; - case 128: // Iksar - break; - case 130: // Vah Shir - MercSize = 7.0; - break; - case 330: // Froglok - MercSize = 5.0; - break; - case 522: // Drakkin - MercSize = 5.0; - break; + switch(this->GetRace()) + { + case 1: // Humans + MercSize = 6.0; + break; + case 2: // Barbarian + MercSize = 7.0; + break; + case 3: // Erudite + MercSize = 6.0; + break; + case 4: // Wood Elf + MercSize = 5.0; + break; + case 5: // High Elf + MercSize = 6.0; + break; + case 6: // Dark Elf + MercSize = 5.0; + break; + case 7: // Half Elf + MercSize = 5.5; + break; + case 8: // Dwarf + MercSize = 4.0; + break; + case 9: // Troll + MercSize = 8.0; + break; + case 10: // Ogre + MercSize = 9.0; + break; + case 11: // Halfling + MercSize = 3.5; + break; + case 12: // Gnome + MercSize = 3.0; + break; + case 128: // Iksar + MercSize = 6.0; + break; + case 130: // Vah Shir + MercSize = 7.0; + break; + case 330: // Froglok + MercSize = 5.0; + break; + case 522: // Drakkin + MercSize = 5.0; + break; + default: + MercSize = 6.0; + break; } - this->size = MercSize; -} - -void Merc::GenerateAppearance() { - // Randomize facial appearance - int iFace = 0; - if(this->GetRace() == 2) { // Barbarian w/Tatoo - iFace = MakeRandomInt(0, 79); - } - else { - iFace = MakeRandomInt(0, 7); - } - - int iHair = 0; - int iBeard = 0; - int iBeardColor = 1; - if(this->GetRace() == 522) { - iHair = MakeRandomInt(0, 8); - iBeard = MakeRandomInt(0, 11); - iBeardColor = MakeRandomInt(0, 3); - } - else if(this->GetGender()) { - iHair = MakeRandomInt(0, 2); - if(this->GetRace() == 8) { // Dwarven Females can have a beard - if(MakeRandomInt(1, 100) < 50) { - iFace += 10; - } - } - } - else { - iHair = MakeRandomInt(0, 3); - iBeard = MakeRandomInt(0, 5); - iBeardColor = MakeRandomInt(0, 19); - } - - int iHairColor = 0; - if(this->GetRace() == 522) { - iHairColor = MakeRandomInt(0, 3); - } - else { - iHairColor = MakeRandomInt(0, 19); - } - - uint8 iEyeColor1 = (uint8)MakeRandomInt(0, 9); - uint8 iEyeColor2 = 0; - if(this->GetRace() == 522) { - iEyeColor1 = iEyeColor2 = (uint8)MakeRandomInt(0, 11); - } - else if(MakeRandomInt(1, 100) > 96) { - iEyeColor2 = MakeRandomInt(0, 9); - } - else { - iEyeColor2 = iEyeColor1; - } - - int iHeritage = 0; - int iTattoo = 0; - int iDetails = 0; - if(this->GetRace() == 522) { - iHeritage = MakeRandomInt(0, 6); - iTattoo = MakeRandomInt(0, 7); - iDetails = MakeRandomInt(0, 7); - } - - this->luclinface = iFace; - this->hairstyle = iHair; - this->beard = iBeard; - this->beardcolor = iBeardColor; - this->haircolor = iHairColor; - this->eyecolor1 = iEyeColor1; - this->eyecolor2 = iEyeColor2; - this->drakkin_heritage = iHeritage; - this->drakkin_tattoo = iTattoo; - this->drakkin_details = iDetails; + return MercSize; } int Merc::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) @@ -1258,7 +1193,6 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.guildrank = 0; ns->spawn.showhelm = 1; ns->spawn.flymode = 0; - ns->spawn.size = 0; ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse ns->spawn.IsMercenary = 1; @@ -4940,22 +4874,37 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, } snprintf(npc_type->name, 64, "%s", c->GetMercInfo().merc_name); } - uint8 gender = 0; - if(merchant_id > 0) { + + npc_type->race = merc_template->RaceID; + + // Use the Gender and Size of the Merchant if possible + uint8 tmpgender = 0; + float tmpsize = 6.0f; + if(merchant_id > 0) + { NPC* tar = entity_list.GetNPCByID(merchant_id); - if(tar) { - gender = Mob::GetDefaultGender(npc_type->race, tar->GetGender()); + if(tar) + { + tmpgender = tar->GetGender(); + tmpsize = tar->GetSize(); } + else + { + tmpgender = Mob::GetDefaultGender(npc_type->race, c->GetMercInfo().Gender); + } + } - else { - gender = c->GetMercInfo().Gender; + else + { + tmpgender = c->GetMercInfo().Gender; + tmpsize = c->GetMercInfo().MercSize; } - sprintf(npc_type->lastname, "%s's %s", c->GetName(), "Mercenary"); - npc_type->gender = gender; + sprintf(npc_type->lastname, "%s's Mercenary", c->GetName()); + npc_type->gender = tmpgender; + npc_type->size = tmpsize; npc_type->loottable_id = 0; // Loottable has to be 0, otherwise we'll be leavin' some corpses! npc_type->npc_id = 0; //NPC ID has to be 0, otherwise db gets all confuzzled. - npc_type->race = merc_template->RaceID; npc_type->class_ = merc_template->ClassID; npc_type->maxlevel = 0; //We should hard-set this to override scalerate's functionality in the NPC class when it is constructed. @@ -4975,6 +4924,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, snprintf(merc->name, 64, "%s", c->GetMercInfo().merc_name); merc->SetSuspended(c->GetMercInfo().IsSuspended); merc->gender = c->GetMercInfo().Gender; + merc->size = c->GetMercInfo().MercSize; merc->SetHP(c->GetMercInfo().hp <= 0 ? merc->GetMaxHP() : c->GetMercInfo().hp); merc->SetMana(c->GetMercInfo().hp <= 0 ? merc->GetMaxMana() : c->GetMercInfo().mana); merc->SetEndurance(c->GetMercInfo().endurance); @@ -4989,6 +4939,11 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, merc->drakkin_tattoo = c->GetMercInfo().drakkinTattoo; merc->drakkin_details = c->GetMercInfo().drakkinDetails; } + else + { + // Give Random Features to newly hired Mercs + merc->RandomizeFeatures(false, true); + } if(merc->GetMercID()) { database.LoadMercBuffs(merc); @@ -5008,7 +4963,8 @@ void Merc::UpdateMercInfo(Client *c) { snprintf(c->GetMercInfo().merc_name, 64, "%s", name); c->GetMercInfo().mercid = GetMercID(); c->GetMercInfo().IsSuspended = IsSuspended(); - c->GetMercInfo().Gender = gender; + c->GetMercInfo().Gender = GetGender(); + c->GetMercInfo().MercSize = GetSize(); c->GetMercInfo().hp = GetHP(); c->GetMercInfo().mana = GetMana(); c->GetMercInfo().endurance = GetEndurance(); @@ -5558,6 +5514,11 @@ void Client::SpawnMercOnZone() { Message(7, "Mercenary Debug: SpawnMercOnZone Suspended Merc."); } } + else + { + // No Merc Hired + SendClearMercInfo(); + } } void Client::SendMercTimer(Merc* merc) { @@ -5604,10 +5565,7 @@ void Client::SpawnMerc(Merc* merc, bool setMaxStats) { SetMerc(merc); merc->Unsuspend(setMaxStats); merc->SetStance(GetMercInfo().Stance); - GetMercInfo().SuspendedTime = 0; - //SendMercTimer(merc); - if (MERC_DEBUG > 0) Message(7, "Mercenary Debug: SpawnMerc Success."); @@ -5666,7 +5624,6 @@ bool Client::MercOnlyOrNoGroup() { bool Merc::Unsuspend(bool setMaxStats) { Client* mercOwner = nullptr; - bool loaded = false; if(GetMercOwner()) { mercOwner = GetMercOwner(); @@ -5694,12 +5651,8 @@ bool Merc::Unsuspend(bool setMaxStats) { if(!mercOwner->GetPTimers().Expired(&database, pTimerMercSuspend, false)) mercOwner->GetPTimers().Clear(&database, pTimerMercSuspend); - MercJoinClientGroup(); - - if(loaded) + if (MercJoinClientGroup()) { - LoadMercSpells(); - if(setMaxStats) { SetHP(GetMaxHP()); @@ -6073,7 +6026,7 @@ void Client::SetMerc(Merc* newmerc) { GetMercInfo().IsSuspended = newmerc->IsSuspended(); GetMercInfo().SuspendedTime = 0; GetMercInfo().Gender = newmerc->GetGender(); - //GetMercInfo().State = newmerc->GetStance(); + GetMercInfo().State = newmerc->IsSuspended() ? MERC_STATE_SUSPENDED : MERC_STATE_NORMAL; snprintf(GetMercInfo().merc_name, 64, "%s", newmerc->GetName()); if (MERC_DEBUG > 0) Message(7, "Mercenary Debug: SetMerc New Merc."); diff --git a/zone/merc.h b/zone/merc.h index eca59ba24..fdcdbec49 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -332,9 +332,7 @@ private: int GroupLeadershipAAHealthRegeneration(); int GroupLeadershipAAOffenseEnhancement(); - void GetMercSize(); - void GenerateAppearance(); - + float GetDefaultSize(); bool LoadMercSpells(); bool CheckStance(int16 stance); diff --git a/zone/mob.cpp b/zone/mob.cpp index e56f3839c..830217ef4 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -739,7 +739,8 @@ 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_) { case TRIBUTE_MASTER: @@ -817,70 +818,78 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns) { // 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; - } + // Set default Last Names for certain Classes if not defined + if (strlen(ns->spawn.lastName) == 0) + { + 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(ns2->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(ns2->spawn.lastName, "Mercenary liaison"); + break; + default: + strcpy(ns2->spawn.lastName, ns->spawn.lastName); + break; + } + } + else + { + strcpy(ns2->spawn.lastName, ns->spawn.lastName); + } memset(&app->pBuffer[sizeof(Spawn_Struct)-7], 0xFF, 7); } @@ -941,7 +950,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) } ns->spawn.guildrank = 0xFF; - ns->spawn.size = size; + 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 @@ -1387,147 +1396,150 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture, uint16 BaseRace = GetBaseRace(); - if (in_race == 0) { - this->race = BaseRace; + if (in_race == 0) + { + 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(); - } + 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; + { + race = in_race; + if (in_gender == 0xFF) + gender = GetDefaultGender(race, gender); + else + gender = in_gender; + } - 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; + if (in_texture == 0xFF) + { + if (IsPlayerRace(in_race)) + texture = 0xFF; else - this->helmtexture = GetHelmTexture(); + texture = GetTexture(); } else - this->helmtexture = in_helmtexture; + { + texture = in_texture; + } + + if (in_helmtexture == 0xFF) + { + if (IsPlayerRace(in_race)) + helmtexture = 0xFF; + else if (in_texture != 0xFF) + helmtexture = in_texture; + else + helmtexture = GetHelmTexture(); + } + else + { + helmtexture = in_helmtexture; + } if (in_haircolor == 0xFF) - this->haircolor = GetHairColor(); + haircolor = GetHairColor(); else - this->haircolor = in_haircolor; + haircolor = in_haircolor; if (in_beardcolor == 0xFF) - this->beardcolor = GetBeardColor(); + beardcolor = GetBeardColor(); else - this->beardcolor = in_beardcolor; + beardcolor = in_beardcolor; if (in_eyecolor1 == 0xFF) - this->eyecolor1 = GetEyeColor1(); + eyecolor1 = GetEyeColor1(); else - this->eyecolor1 = in_eyecolor1; + eyecolor1 = in_eyecolor1; if (in_eyecolor2 == 0xFF) - this->eyecolor2 = GetEyeColor2(); + eyecolor2 = GetEyeColor2(); else - this->eyecolor2 = in_eyecolor2; + eyecolor2 = in_eyecolor2; if (in_hairstyle == 0xFF) - this->hairstyle = GetHairStyle(); + hairstyle = GetHairStyle(); else - this->hairstyle = in_hairstyle; + hairstyle = in_hairstyle; if (in_luclinface == 0xFF) - this->luclinface = GetLuclinFace(); + luclinface = GetLuclinFace(); else - this->luclinface = in_luclinface; + luclinface = in_luclinface; if (in_beard == 0xFF) - this->beard = GetBeard(); + beard = GetBeard(); else - this->beard = in_beard; + beard = in_beard; - this->aa_title = 0xFF; + aa_title = in_aa_title; if (in_drakkin_heritage == 0xFFFFFFFF) - this->drakkin_heritage = GetDrakkinHeritage(); + drakkin_heritage = GetDrakkinHeritage(); else - this->drakkin_heritage = in_drakkin_heritage; + drakkin_heritage = in_drakkin_heritage; if (in_drakkin_tattoo == 0xFFFFFFFF) - this->drakkin_tattoo = GetDrakkinTattoo(); + drakkin_tattoo = GetDrakkinTattoo(); else - this->drakkin_tattoo = in_drakkin_tattoo; + drakkin_tattoo = in_drakkin_tattoo; if (in_drakkin_details == 0xFFFFFFFF) - this->drakkin_details = GetDrakkinDetails(); + drakkin_details = GetDrakkinDetails(); else - this->drakkin_details = in_drakkin_details; + drakkin_details = in_drakkin_details; if (in_size <= 0.0f) - this->size = GetSize(); + size = GetSize(); else - this->size = in_size; + 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(); + // Reset features to Base from the Player Profile + if (IsClient() && in_race == 0) + { + race = CastToClient()->GetBaseRace(); + gender = CastToClient()->GetBaseGender(); + texture = 0xFF; + helmtexture = 0xFF; + haircolor = CastToClient()->GetBaseHairColor(); + beardcolor = CastToClient()->GetBaseBeardColor(); + eyecolor1 = CastToClient()->GetBaseEyeColor(); + eyecolor2 = CastToClient()->GetBaseEyeColor(); + hairstyle = CastToClient()->GetBaseHairStyle(); + luclinface = CastToClient()->GetBaseFace(); + beard = CastToClient()->GetBaseBeard(); + aa_title = 0xFF; + drakkin_heritage = CastToClient()->GetBaseHeritage(); + drakkin_tattoo = CastToClient()->GetBaseTattoo(); + drakkin_details = CastToClient()->GetBaseDetails(); switch(race){ case OGRE: - this->size = 9; + size = 9; break; case TROLL: - this->size = 8; + size = 8; break; case VAHSHIR: case BARBARIAN: - this->size = 7; + size = 7; break; case HALF_ELF: case WOOD_ELF: case DARK_ELF: case FROGLOK: - this->size = 5; + size = 5; break; case DWARF: - this->size = 4; + size = 4; break; case HALFLING: case GNOME: - this->size = 3; + size = 3; break; default: - this->size = 6; + size = 6; break; } } @@ -1535,39 +1547,250 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture, 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(); + is->spawnid = 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; + is->race = race; + is->gender = gender; + is->texture = texture; + is->helmtexture = helmtexture; + is->haircolor = haircolor; + is->beardcolor = beardcolor; + is->beard = beard; + is->eyecolor1 = eyecolor1; + is->eyecolor2 = eyecolor2; + is->hairstyle = hairstyle; + is->face = luclinface; + is->drakkin_heritage = drakkin_heritage; + is->drakkin_tattoo = drakkin_tattoo; + is->drakkin_details = drakkin_details; + is->size = 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); + race, gender, texture, helmtexture, haircolor, beardcolor, eyecolor1, eyecolor2, hairstyle, luclinface, drakkin_heritage, drakkin_tattoo, drakkin_details, size); } +bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) +{ + if (IsPlayerRace(GetRace())) + { + uint8 Gender = GetGender(); + uint8 Texture = 0xFF; + uint8 HelmTexture = 0xFF; + uint8 HairColor = 0xFF; + uint8 BeardColor = 0xFF; + uint8 EyeColor1 = 0xFF; + uint8 EyeColor2 = 0xFF; + uint8 HairStyle = 0xFF; + uint8 LuclinFace = 0xFF; + uint8 Beard = 0xFF; + uint32 DrakkinHeritage = 0xFFFFFFFF; + uint32 DrakkinTattoo = 0xFFFFFFFF; + uint32 DrakkinDetails = 0xFFFFFFFF; + + // Set some common feature settings + EyeColor1 = MakeRandomInt(0, 9); + EyeColor2 = MakeRandomInt(0, 9); + LuclinFace = MakeRandomInt(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 = MakeRandomInt(0, 19); + if (Gender == 0) { + BeardColor = HairColor; + HairStyle = MakeRandomInt(0, 3); + Beard = MakeRandomInt(0, 5); + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + } + break; + case 2: // Barbarian + HairColor = MakeRandomInt(0, 19); + LuclinFace = MakeRandomInt(0, 87); + if (Gender == 0) { + BeardColor = HairColor; + HairStyle = MakeRandomInt(0, 3); + Beard = MakeRandomInt(0, 5); + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + } + break; + case 3: // Erudite + if (Gender == 0) { + BeardColor = MakeRandomInt(0, 19); + Beard = MakeRandomInt(0, 5); + LuclinFace = MakeRandomInt(0, 57); + } + if (Gender == 1) { + LuclinFace = MakeRandomInt(0, 87); + } + break; + case 4: // WoodElf + HairColor = MakeRandomInt(0, 19); + if (Gender == 0) { + HairStyle = MakeRandomInt(0, 3); + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + } + break; + case 5: // HighElf + HairColor = MakeRandomInt(0, 14); + if (Gender == 0) { + HairStyle = MakeRandomInt(0, 3); + LuclinFace = MakeRandomInt(0, 37); + BeardColor = HairColor; + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + } + break; + case 6: // DarkElf + HairColor = MakeRandomInt(13, 18); + if (Gender == 0) { + HairStyle = MakeRandomInt(0, 3); + LuclinFace = MakeRandomInt(0, 37); + BeardColor = HairColor; + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + } + break; + case 7: // HalfElf + HairColor = MakeRandomInt(0, 19); + if (Gender == 0) { + HairStyle = MakeRandomInt(0, 3); + LuclinFace = MakeRandomInt(0, 37); + BeardColor = HairColor; + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + } + break; + case 8: // Dwarf + HairColor = MakeRandomInt(0, 19); + BeardColor = HairColor; + if (Gender == 0) { + HairStyle = MakeRandomInt(0, 3); + Beard = MakeRandomInt(0, 5); + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + LuclinFace = MakeRandomInt(0, 17); + } + break; + case 9: // Troll + EyeColor1 = MakeRandomInt(0, 10); + EyeColor2 = MakeRandomInt(0, 10); + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 3); + HairColor = MakeRandomInt(0, 23); + } + break; + case 10: // Ogre + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 3); + HairColor = MakeRandomInt(0, 23); + } + break; + case 11: // Halfling + HairColor = MakeRandomInt(0, 19); + if (Gender == 0) { + BeardColor = HairColor; + HairStyle = MakeRandomInt(0, 3); + Beard = MakeRandomInt(0, 5); + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + } + break; + case 12: // Gnome + HairColor = MakeRandomInt(0, 24); + if (Gender == 0) { + BeardColor = HairColor; + HairStyle = MakeRandomInt(0, 3); + Beard = MakeRandomInt(0, 5); + } + if (Gender == 1) { + HairStyle = MakeRandomInt(0, 2); + } + break; + case 128: // Iksar + case 130: // VahShir + break; + case 330: // Froglok + LuclinFace = MakeRandomInt(0, 9); + case 522: // Drakkin + HairColor = MakeRandomInt(0, 3); + BeardColor = HairColor; + EyeColor1 = MakeRandomInt(0, 11); + EyeColor2 = MakeRandomInt(0, 11); + LuclinFace = MakeRandomInt(0, 6); + DrakkinHeritage = MakeRandomInt(0, 6); + DrakkinTattoo = MakeRandomInt(0, 7); + DrakkinDetails = MakeRandomInt(0, 7); + if (Gender == 0) { + Beard = MakeRandomInt(0, 12); + HairStyle = MakeRandomInt(0, 8); + } + if (Gender == 1) { + Beard = MakeRandomInt(0, 3); + HairStyle = MakeRandomInt(0, 7); + } + break; + default: + break; + } + + if (set_variables) + { + haircolor = HairColor; + beardcolor = BeardColor; + eyecolor1 = EyeColor1; + eyecolor2 = EyeColor2; + hairstyle = HairStyle; + luclinface = LuclinFace; + beard = Beard; + drakkin_heritage = DrakkinHeritage; + drakkin_tattoo = DrakkinTattoo; + drakkin_details = DrakkinDetails; + } + + if (send_illusion) + { + SendIllusionPacket(GetRace(), Gender, Texture, HelmTexture, HairColor, BeardColor, + EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF, DrakkinHeritage, + DrakkinTattoo, DrakkinDetails); + } + + return true; + } + return false; +} + + +bool Mob::IsPlayerRace(uint16 in_race) { + + if ((in_race >= HUMAN && in_race <= GNOME) || in_race == IKSAR || in_race == VAHSHIR || in_race == FROGLOK || in_race == DRAKKIN) + { + return true; + } + + return false; +} + + 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 (Mob::IsPlayerRace(in_race) || 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; + // Male default for PC Races + return 0; } else return in_gender; diff --git a/zone/mob.h b/zone/mob.h index 0e04c43b1..18f61281f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -497,6 +497,7 @@ public: //Util static uint32 RandomTimer(int min, int max); static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF); + static bool IsPlayerRace(uint16 in_race); uint16 GetSkillByItemType(int ItemType); uint8 GetItemTypeBySkill(SkillUseTypes skill); virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr); @@ -577,6 +578,7 @@ public: 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 = -1.0f); + bool RandomizeFeatures(bool send_illusion = true, bool set_variables = true); virtual void Stun(int duration); virtual void UnStun(); inline void Silence(bool newval) { silenced = newval; } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 1f520ed88..17b5ff508 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2100,7 +2100,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client bool ZoneDatabase::LoadMercInfo(Client *client) { std::string query = StringFormat("SELECT MercID, Slot, Name, TemplateID, SuspendedTime, " - "IsSuspended, TimerRemaining, Gender, StanceID, HP, Mana, " + "IsSuspended, TimerRemaining, Gender, MercSize, StanceID, HP, Mana, " "Endurance, Face, LuclinHairStyle, LuclinHairColor, " "LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, LuclinBeard, " "DrakkinHeritage, DrakkinTattoo, DrakkinDetails " @@ -2126,21 +2126,22 @@ bool ZoneDatabase::LoadMercInfo(Client *client) { client->GetMercInfo(slot).IsSuspended = atoi(row[5]) == 1 ? true : false; client->GetMercInfo(slot).MercTimerRemaining = atoi(row[6]); client->GetMercInfo(slot).Gender = atoi(row[7]); + client->GetMercInfo(slot).MercSize = atof(row[8]); client->GetMercInfo(slot).State = 5; - client->GetMercInfo(slot).Stance = atoi(row[8]); - client->GetMercInfo(slot).hp = atoi(row[9]); - client->GetMercInfo(slot).mana = atoi(row[10]); - client->GetMercInfo(slot).endurance = atoi(row[11]); - client->GetMercInfo(slot).face = atoi(row[12]); - client->GetMercInfo(slot).luclinHairStyle = atoi(row[13]); - client->GetMercInfo(slot).luclinHairColor = atoi(row[14]); - client->GetMercInfo(slot).luclinEyeColor = atoi(row[15]); - client->GetMercInfo(slot).luclinEyeColor2 = atoi(row[16]); - client->GetMercInfo(slot).luclinBeardColor = atoi(row[17]); - client->GetMercInfo(slot).luclinBeard = atoi(row[18]); - client->GetMercInfo(slot).drakkinHeritage = atoi(row[19]); - client->GetMercInfo(slot).drakkinTattoo = atoi(row[20]); - client->GetMercInfo(slot).drakkinDetails = atoi(row[21]); + client->GetMercInfo(slot).Stance = atoi(row[9]); + client->GetMercInfo(slot).hp = atoi(row[10]); + client->GetMercInfo(slot).mana = atoi(row[11]); + client->GetMercInfo(slot).endurance = atoi(row[12]); + client->GetMercInfo(slot).face = atoi(row[13]); + client->GetMercInfo(slot).luclinHairStyle = atoi(row[14]); + client->GetMercInfo(slot).luclinHairColor = atoi(row[15]); + client->GetMercInfo(slot).luclinEyeColor = atoi(row[16]); + client->GetMercInfo(slot).luclinEyeColor2 = atoi(row[17]); + client->GetMercInfo(slot).luclinBeardColor = atoi(row[18]); + client->GetMercInfo(slot).luclinBeard = atoi(row[19]); + client->GetMercInfo(slot).drakkinHeritage = atoi(row[20]); + client->GetMercInfo(slot).drakkinTattoo = atoi(row[21]); + client->GetMercInfo(slot).drakkinDetails = atoi(row[22]); } return true; @@ -2154,7 +2155,7 @@ bool ZoneDatabase::LoadCurrentMerc(Client *client) { return false; std::string query = StringFormat("SELECT MercID, Name, TemplateID, SuspendedTime, " - "IsSuspended, TimerRemaining, Gender, StanceID, HP, " + "IsSuspended, TimerRemaining, Gender, MercSize, StanceID, HP, " "Mana, Endurance, Face, LuclinHairStyle, LuclinHairColor, " "LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, " "LuclinBeard, DrakkinHeritage, DrakkinTattoo, DrakkinDetails " @@ -2178,20 +2179,21 @@ bool ZoneDatabase::LoadCurrentMerc(Client *client) { client->GetMercInfo(slot).IsSuspended = atoi(row[4]) == 1? true: false; client->GetMercInfo(slot).MercTimerRemaining = atoi(row[5]); client->GetMercInfo(slot).Gender = atoi(row[6]); - client->GetMercInfo(slot).State = atoi(row[7]); - client->GetMercInfo(slot).hp = atoi(row[8]); - client->GetMercInfo(slot).mana = atoi(row[9]); - client->GetMercInfo(slot).endurance = atoi(row[10]); - client->GetMercInfo(slot).face = atoi(row[11]); - client->GetMercInfo(slot).luclinHairStyle = atoi(row[12]); - client->GetMercInfo(slot).luclinHairColor = atoi(row[13]); - client->GetMercInfo(slot).luclinEyeColor = atoi(row[14]); - client->GetMercInfo(slot).luclinEyeColor2 = atoi(row[15]); - client->GetMercInfo(slot).luclinBeardColor = atoi(row[16]); - client->GetMercInfo(slot).luclinBeard = atoi(row[17]); - client->GetMercInfo(slot).drakkinHeritage = atoi(row[18]); - client->GetMercInfo(slot).drakkinTattoo = atoi(row[19]); - client->GetMercInfo(slot).drakkinDetails = atoi(row[20]); + client->GetMercInfo(slot).MercSize = atof(row[7]); + client->GetMercInfo(slot).State = atoi(row[8]); + client->GetMercInfo(slot).hp = atoi(row[9]); + client->GetMercInfo(slot).mana = atoi(row[10]); + client->GetMercInfo(slot).endurance = atoi(row[11]); + client->GetMercInfo(slot).face = atoi(row[12]); + client->GetMercInfo(slot).luclinHairStyle = atoi(row[13]); + client->GetMercInfo(slot).luclinHairColor = atoi(row[14]); + client->GetMercInfo(slot).luclinEyeColor = atoi(row[15]); + client->GetMercInfo(slot).luclinEyeColor2 = atoi(row[16]); + client->GetMercInfo(slot).luclinBeardColor = atoi(row[17]); + client->GetMercInfo(slot).luclinBeard = atoi(row[18]); + client->GetMercInfo(slot).drakkinHeritage = atoi(row[19]); + client->GetMercInfo(slot).drakkinTattoo = atoi(row[20]); + client->GetMercInfo(slot).drakkinDetails = atoi(row[21]); } return true; @@ -2209,19 +2211,19 @@ bool ZoneDatabase::SaveMerc(Merc *merc) { std::string query = StringFormat("INSERT INTO mercs " "(OwnerCharacterID, Slot, Name, TemplateID, " "SuspendedTime, IsSuspended, TimerRemaining, " - "Gender, StanceID, HP, Mana, Endurance, Face, " + "Gender, MercSize, StanceID, HP, Mana, Endurance, Face, " "LuclinHairStyle, LuclinHairColor, LuclinEyeColor, " "LuclinEyeColor2, LuclinBeardColor, LuclinBeard, " "DrakkinHeritage, DrakkinTattoo, DrakkinDetails) " "VALUES('%u', '%u', '%s', '%u', '%u', '%u', '%u', " - "'%u', '%u', '%u', '%u', '%u', '%i', '%i', '%i', " + "'%u', '%u', '%f', '%u', '%u', '%u', '%i', '%i', '%i', " "'%i', '%i', '%i', '%i', '%i', '%i', '%i')", merc->GetMercCharacterID(), owner->GetNumMercs(), merc->GetCleanName(), merc->GetMercTemplateID(), owner->GetMercInfo().SuspendedTime, merc->IsSuspended(), owner->GetMercInfo().MercTimerRemaining, merc->GetGender(), - merc->GetStance(), merc->GetHP(), merc->GetMana(), - merc->GetEndurance(), merc->GetLuclinFace(), + merc->GetSize(), merc->GetStance(), merc->GetHP(), + merc->GetMana(), merc->GetEndurance(), merc->GetLuclinFace(), merc->GetHairStyle(), merc->GetHairColor(), merc->GetEyeColor1(), merc->GetEyeColor2(), merc->GetBeardColor(), merc->GetBeard(), merc->GetDrakkinHeritage(), @@ -2245,7 +2247,7 @@ bool ZoneDatabase::SaveMerc(Merc *merc) { // Update existing merc record std::string query = StringFormat("UPDATE mercs SET OwnerCharacterID = '%u', Slot = '%u', " "Name = '%s', TemplateID = '%u', SuspendedTime = '%u', " - "IsSuspended = '%u', TimerRemaining = '%u', Gender = '%u', " + "IsSuspended = '%u', TimerRemaining = '%u', Gender = '%u', MercSize = '%f', " "StanceID = '%u', HP = '%u', Mana = '%u', Endurance = '%u', " "Face = '%i', LuclinHairStyle = '%i', LuclinHairColor = '%i', " "LuclinEyeColor = '%i', LuclinEyeColor2 = '%i', LuclinBeardColor = '%i', " @@ -2254,11 +2256,12 @@ bool ZoneDatabase::SaveMerc(Merc *merc) { merc->GetMercCharacterID(), owner->GetMercSlot(), merc->GetCleanName(), merc->GetMercTemplateID(), owner->GetMercInfo().SuspendedTime, merc->IsSuspended(), owner->GetMercInfo().MercTimerRemaining, - merc->GetGender(), merc->GetStance(), merc->GetHP(), merc->GetMana(), - merc->GetEndurance(), merc->GetLuclinFace(), merc->GetHairStyle(), - merc->GetHairColor(), merc->GetEyeColor1(), merc->GetEyeColor2(), - merc->GetBeardColor(), merc->GetBeard(), merc->GetDrakkinHeritage(), - merc->GetDrakkinTattoo(), merc->GetDrakkinDetails(), merc->GetMercID()); + merc->GetGender(), merc->GetSize(), merc->GetStance(), merc->GetHP(), + merc->GetMana(), merc->GetEndurance(), merc->GetLuclinFace(), + merc->GetHairStyle(), merc->GetHairColor(), merc->GetEyeColor1(), + merc->GetEyeColor2(), merc->GetBeardColor(), merc->GetBeard(), + merc->GetDrakkinHeritage(), merc->GetDrakkinTattoo(), merc->GetDrakkinDetails(), + merc->GetMercID()); auto results = database.QueryDatabase(query); if (!results.Success()) { diff --git a/zone/zonedb.h b/zone/zonedb.h index 5adc893ff..1c103074a 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -181,6 +181,7 @@ struct MercInfo { bool IsSuspended; uint32 MercTimerRemaining; uint8 Gender; + float MercSize; int32 State; uint32 Stance; int32 hp; From 52eb4d2d4e06238aa6e8d6cb9bf84a14bf198b26 Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 2 Dec 2014 00:07:09 -0600 Subject: [PATCH 77/96] Fixed Mercenary Depop Crash in Windows. --- zone/merc.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/zone/merc.cpp b/zone/merc.cpp index 5593c3e50..c94616eab 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -5930,7 +5930,7 @@ Merc* Client::GetMerc() { if(GetMercID() == 0) { if (MERC_DEBUG > 0) - //Message(7, "Mercenary Debug: GetMerc 0."); + Message(7, "Mercenary Debug: GetMerc 0."); return (nullptr); } @@ -5950,9 +5950,6 @@ Merc* Client::GetMerc() { Message(7, "Mercenary Debug: GetMerc Owner Mismatch."); return (nullptr); } - - if (MERC_DEBUG > 0) - //Message(7, "Mercenary Debug: GetMerc Success."); return (tmp); } From 70dd4471563abe283ac8ede9362a20cf1ca59704 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 2 Dec 2014 03:42:35 -0500 Subject: [PATCH 78/96] Fix for error introduced in projectile update for throwing/archery to do hit chance check 2x resulting in much greater chance to miss. --- zone/special_attacks.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index cf6a83c80..8b6f11d96 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -828,6 +828,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite this function is then run again to do the damage portion */ bool LaunchProjectile = false; + bool ProjectileImpact = false; bool ProjectileMiss = false; if (RuleB(Combat, ProjectileDmgOnImpact)){ @@ -844,6 +845,8 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (!RangeWeapon && !Ammo && range_id && ammo_id){ + ProjectileImpact = true; + if (weapon_damage == 0) ProjectileMiss = true; //This indicates that MISS was originally calculated. @@ -865,7 +868,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else if (AmmoItem) SendItemAnimation(other, AmmoItem, SkillArchery); - if (ProjectileMiss || !other->CheckHitChance(this, SkillArchery, MainPrimary, chance_mod)) { + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillArchery, MainPrimary, chance_mod))) { mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ @@ -1382,6 +1385,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite this function is then run again to do the damage portion */ bool LaunchProjectile = false; + bool ProjectileImpact = false; bool ProjectileMiss = false; if (RuleB(Combat, ProjectileDmgOnImpact)){ @@ -1391,6 +1395,8 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else{ if (!RangeWeapon && range_id){ + ProjectileImpact = true; + if (weapon_damage == 0) ProjectileMiss = true; //This indicates that MISS was originally calculated. @@ -1408,7 +1414,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else if (AmmoItem) SendItemAnimation(other, AmmoItem, SkillThrowing); - if (ProjectileMiss || !other->CheckHitChance(this, SkillThrowing, MainPrimary, chance_mod)){ + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillThrowing, MainPrimary, chance_mod))){ mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ TryProjectileAttack(other, AmmoItem, SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); From 525eb518f661fe7cbe89b0aebfce406c539d1685 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 2 Dec 2014 13:44:23 -0500 Subject: [PATCH 79/96] Crash fix, this check got removed accidentally --- zone/special_attacks.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index cf6a83c80..671968350 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -596,6 +596,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = wpn->GetAugment(i); + if(aug) { backstab_dmg += aug->GetItem()->BackstabDmg; } From 9636ef34996b8b9645f2530b54ef582b84a38fcb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 2 Dec 2014 14:09:14 -0500 Subject: [PATCH 80/96] Update to new random functions --- zone/mob.cpp | 124 +++++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 34da067e5..13a2eb06b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1590,157 +1590,157 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) uint32 DrakkinDetails = 0xFFFFFFFF; // Set some common feature settings - EyeColor1 = MakeRandomInt(0, 9); - EyeColor2 = MakeRandomInt(0, 9); - LuclinFace = MakeRandomInt(0, 7); + EyeColor1 = zone->random.Int(0, 9); + EyeColor2 = zone->random.Int(0, 9); + 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 = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); if (Gender == 0) { BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 2: // Barbarian - HairColor = MakeRandomInt(0, 19); - LuclinFace = MakeRandomInt(0, 87); + HairColor = zone->random.Int(0, 19); + LuclinFace = zone->random.Int(0, 87); if (Gender == 0) { BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 3: // Erudite if (Gender == 0) { - BeardColor = MakeRandomInt(0, 19); - Beard = MakeRandomInt(0, 5); - LuclinFace = MakeRandomInt(0, 57); + BeardColor = zone->random.Int(0, 19); + Beard = zone->random.Int(0, 5); + LuclinFace = zone->random.Int(0, 57); } if (Gender == 1) { - LuclinFace = MakeRandomInt(0, 87); + LuclinFace = zone->random.Int(0, 87); } break; case 4: // WoodElf - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); + HairStyle = zone->random.Int(0, 3); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 5: // HighElf - HairColor = MakeRandomInt(0, 14); + HairColor = zone->random.Int(0, 14); if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); BeardColor = HairColor; } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 6: // DarkElf - HairColor = MakeRandomInt(13, 18); + HairColor = zone->random.Int(13, 18); if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); BeardColor = HairColor; } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 7: // HalfElf - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - LuclinFace = MakeRandomInt(0, 37); + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); BeardColor = HairColor; } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 8: // Dwarf - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); BeardColor = HairColor; if (Gender == 0) { - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); - LuclinFace = MakeRandomInt(0, 17); + HairStyle = zone->random.Int(0, 2); + LuclinFace = zone->random.Int(0, 17); } break; case 9: // Troll - EyeColor1 = MakeRandomInt(0, 10); - EyeColor2 = MakeRandomInt(0, 10); + EyeColor1 = zone->random.Int(0, 10); + EyeColor2 = zone->random.Int(0, 10); if (Gender == 1) { - HairStyle = MakeRandomInt(0, 3); - HairColor = MakeRandomInt(0, 23); + HairStyle = zone->random.Int(0, 3); + HairColor = zone->random.Int(0, 23); } break; case 10: // Ogre if (Gender == 1) { - HairStyle = MakeRandomInt(0, 3); - HairColor = MakeRandomInt(0, 23); + HairStyle = zone->random.Int(0, 3); + HairColor = zone->random.Int(0, 23); } break; case 11: // Halfling - HairColor = MakeRandomInt(0, 19); + HairColor = zone->random.Int(0, 19); if (Gender == 0) { BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 12: // Gnome - HairColor = MakeRandomInt(0, 24); + HairColor = zone->random.Int(0, 24); if (Gender == 0) { BeardColor = HairColor; - HairStyle = MakeRandomInt(0, 3); - Beard = MakeRandomInt(0, 5); + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); } if (Gender == 1) { - HairStyle = MakeRandomInt(0, 2); + HairStyle = zone->random.Int(0, 2); } break; case 128: // Iksar case 130: // VahShir break; case 330: // Froglok - LuclinFace = MakeRandomInt(0, 9); + LuclinFace = zone->random.Int(0, 9); case 522: // Drakkin - HairColor = MakeRandomInt(0, 3); + HairColor = zone->random.Int(0, 3); BeardColor = HairColor; - EyeColor1 = MakeRandomInt(0, 11); - EyeColor2 = MakeRandomInt(0, 11); - LuclinFace = MakeRandomInt(0, 6); - DrakkinHeritage = MakeRandomInt(0, 6); - DrakkinTattoo = MakeRandomInt(0, 7); - DrakkinDetails = MakeRandomInt(0, 7); + 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 = MakeRandomInt(0, 12); - HairStyle = MakeRandomInt(0, 8); + Beard = zone->random.Int(0, 12); + HairStyle = zone->random.Int(0, 8); } if (Gender == 1) { - Beard = MakeRandomInt(0, 3); - HairStyle = MakeRandomInt(0, 7); + Beard = zone->random.Int(0, 3); + HairStyle = zone->random.Int(0, 7); } break; default: From 804421095ad878349bed459bf87f4f073c429cec Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Dec 2014 16:55:43 -0500 Subject: [PATCH 81/96] Fix DB manifest --- utils/sql/db_update_manifest.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 8291465a4..2af5e6e90 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -312,7 +312,7 @@ 9056|2014_11_08_RaidMembers.sql|SHOW COLUMNS FROM `raid_members` LIKE 'groupid'|missing|unsigned 9057|2014_11_13_spells_new_updates.sql|SHOW COLUMNS FROM `spells_new` LIKE 'disallow_sit'|empty| 9058|2014_11_26_InventoryTableUpdate.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornamenticon'|empty| -9059|2014_11_30_mercs_table_update.sql|SHOW COLUMNS FROM `mercs` LIKE 'MercSize'|empty| +9059|2014_12_01_mercs_table_update.sql|SHOW COLUMNS FROM `mercs` LIKE 'MercSize'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not @@ -331,4 +331,4 @@ # not_empty = If the query is not empty # 4 = Text to match # -# \ No newline at end of file +# From fc282f86c03c70fd1718c5ef0d28faf9fbba0df8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Dec 2014 17:04:26 -0500 Subject: [PATCH 82/96] Rework raid invite handling, shouldn't break rsay being invited to raid anymore --- zone/client_packet.cpp | 51 +++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index adb3b4464..537f7126b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10617,37 +10617,28 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) case RaidCommandInviteIntoExisting: case RaidCommandInvite: { Client *i = entity_list.GetClientByName(ri->player_name); - if (i){ - Group *g = i->GetGroup(); - if (g){ - if (g->IsLeader(i) == false) - Message(13, "You can only invite an ungrouped player or group leader to join your raid."); - else{ - //This sends an "invite" to the client in question. - EQApplicationPacket* 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); - - rg->parameter = 0; - rg->action = 20; - i->QueuePacket(outapp); - safe_delete(outapp); - } - } - else{ - //This sends an "invite" to the client in question. - EQApplicationPacket* 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); - - rg->parameter = 0; - rg->action = 20; - i->QueuePacket(outapp); - safe_delete(outapp); - } + if (!i) + break; + Group *g = i->GetGroup(); + // These two messages should be generated by the client I think, just do this for now + if (i->HasRaid()) { + Message(13, "%s is already in a raid.", i->GetName()); + break; } + if (g && !g->IsLeader(i)) { + Message(13, "You can only invite an ungrouped player or group leader to join your raid."); + break; + } + //This sends an "invite" to the client in question. + EQApplicationPacket* 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); + + rg->parameter = 0; + rg->action = 20; + i->QueuePacket(outapp); + safe_delete(outapp); break; } case RaidCommandAcceptInvite: { From 052b41fbb2e3063616b5862eb05118e0694a7be7 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 4 Dec 2014 02:40:51 -0500 Subject: [PATCH 83/96] Ranged attacks will now much more accurately calculate max distance server side via accounting for differences in attacker/target size. This fixes a very common issue of player hitting range attack and nothing happening due to server improperly calculating max range. --- changelog.txt | 4 +++ zone/mob.h | 1 + zone/special_attacks.cpp | 58 +++++++++++++++++++++++++++++++++------- zone/string_ids.h | 3 ++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/changelog.txt b/changelog.txt index d8ed052ab..e72fc04a3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/04/2014 == +Kayen: Ranged attacks will now more accurately check MAX firing range, fixing the issue where you would +hit ranged attack and nothing would happpen due to incorrect server side range checks. + == 12/01/2014 == Trevius: Mercenaries now spawn as the same Gender and Size of the Merchant they are purchased from. Trevius: Mercenaries now spawn with randomized facial features when purchased. diff --git a/zone/mob.h b/zone/mob.h index 18f61281f..6135c6571 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -737,6 +737,7 @@ public: void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } + float GetRangeDistTargetSizeMod(Mob* other); bool CanDoSpecialAttack(Mob *other); bool Flurry(ExtraAttackOptions *opts); bool Rampage(ExtraAttackOptions *opts); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 1ecf10934..632a2dad1 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -765,15 +765,16 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { } } - float range = RangeItem->Range + AmmoItem->Range + 5.0f; //Fudge it a little, client will let you hit something at 0 0 0 when you are at 205 0 0 + float range = RangeItem->Range + AmmoItem->Range + GetRangeDistTargetSizeMod(GetTarget()); mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range); range *= range; - if(DistNoRootNoZ(*GetTarget()) > range) { + if(DistNoRoot(*GetTarget()) > range) { mlog(COMBAT__RANGED, "Ranged attack out of range... client should catch this. (%f > %f).\n", DistNoRootNoZ(*GetTarget()), range); - //target is out of range, client does a message + Message_StringID(13,TARGET_OUT_OF_RANGE);//Client enforces range and sends the message, this is a backup just incase. return; } - else if(DistNoRootNoZ(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ + else if(DistNoRoot(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ + Message_StringID(15,RANGED_TOO_CLOSE);//Client enforces range and sends the message, this is a backup just incase. return; } @@ -1128,6 +1129,45 @@ void Mob::ProjectileAttack() SetProjectileAttack(false); } +float Mob::GetRangeDistTargetSizeMod(Mob* other) +{ + /* + Range is enforced client side, therefore these numbers do not need to be 100% accurate just close enough to + prevent any exploitation. The range mod changes in some situations depending on if size is from spawn or from SendIllusionPacket changes. + At present time only calculate from spawn (it is no consistent what happens to the calc when changing it after spawn). + */ + if (!other) + return 0.0f; + + float tsize = other->GetSize(); + + if (GetSize() > tsize) + tsize = GetSize(); + + float mod = 0.0f; + /*These are correct numbers if mob size is changed via #size (Don't know why it matters but it does) + if (tsize < 7) + mod = 16.0f; + else if (tsize >=7 && tsize <= 20) + mod = 16.0f + (0.6f * (tsize - 6.0f)); + else if (tsize >=20 && tsize <= 60) + mod = 25.0f + (1.25f * (tsize - 20.0f)); + else + mod = 75.0f; + */ + + if (tsize < 10) + mod = 18.0f; + else if (tsize >=10 && tsize < 15) + mod = 20.0f + (4.0f * (tsize - 10.0f)); + else if (tsize >=15 && tsize <= 20) + 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. +} + void NPC::RangedAttack(Mob* other) { @@ -1333,16 +1373,16 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 } } - int range = item->Range +50/*Fudge it a little, client will let you hit something at 0 0 0 when you are at 205 0 0*/; + float range = item->Range + GetRangeDistTargetSizeMod(GetTarget()); mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range); range *= range; - if(DistNoRootNoZ(*GetTarget()) > range) { + if(DistNoRoot(*GetTarget()) > range) { mlog(COMBAT__RANGED, "Throwing attack out of range... client should catch this. (%f > %f).\n", DistNoRootNoZ(*GetTarget()), range); - //target is out of range, client does a message + Message_StringID(13,TARGET_OUT_OF_RANGE);//Client enforces range and sends the message, this is a backup just incase. return; } - else if(DistNoRootNoZ(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ - return; + else if(DistNoRoot(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ + Message_StringID(15,RANGED_TOO_CLOSE);//Client enforces range and sends the message, this is a backup just incase. } if(!IsAttackAllowed(GetTarget()) || diff --git a/zone/string_ids.h b/zone/string_ids.h index e1e1bc7b3..ef758dba6 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -396,7 +396,8 @@ #define SONG_ENDS_OTHER 12688 //%1's song ends. #define SONG_ENDS_ABRUPTLY_OTHER 12689 //%1's song ends abruptly. #define DIVINE_AURA_NO_ATK 12695 //You can't attack while invulnerable! -#define TRY_ATTACKING_SOMEONE 12696 //Try attacking someone other than yourself, it's more productive. +#define TRY_ATTACKING_SOMEONE 12696 //Try attacking someone other than yourself, it's more productive +#define RANGED_TOO_CLOSE 12698 //Your target is too close to use a ranged weapon! #define BACKSTAB_WEAPON 12874 //You need a piercing weapon as your primary weapon in order to backstab #define MORE_SKILLED_THAN_I 12931 //%1 tells you, 'You are more skilled than I! What could I possibly teach you?' #define SURNAME_EXISTS 12939 //You already have a surname. Operation failed. From af42af786935195f8b75278d85c80559630357d1 Mon Sep 17 00:00:00 2001 From: Trevius Date: Thu, 4 Dec 2014 02:13:01 -0600 Subject: [PATCH 84/96] Initial addition of the RoF2 client from May 10th 2013 (currently available on Steam as the F2P client). RoF2 is disabled by default, but you can enable by editing /common/patches/patches.cpp (see comments) --- changelog.txt | 2 + common/CMakeLists.txt | 14 +- common/eq_dictionary.h | 2 +- common/patches/patches.cpp | 4 +- common/patches/rof2.cpp | 5673 +++++++++++++++++ common/patches/rof2.h | 37 + common/patches/rof2_constants.h | 216 + common/patches/rof2_itemfields.h | 439 ++ common/patches/rof2_ops.h | 173 + common/patches/rof2_structs.h | 4922 ++++++++++++++ utils/patches/patch_RoF2.conf | 660 ++ .../scripts/opcode_scripts/conf_to_oplist.pl | 66 + utils/scripts/opcode_scripts/opcodelist.txt | 1671 +++++ .../scripts/opcode_scripts/oplist_to_conf.pl | 88 + utils/scripts/opcode_scripts/patch_NEW.conf | 661 ++ utils/scripts/opcode_scripts/patch_OLD.conf | 661 ++ 16 files changed, 15286 insertions(+), 3 deletions(-) create mode 100644 common/patches/rof2.cpp create mode 100644 common/patches/rof2.h create mode 100644 common/patches/rof2_constants.h create mode 100644 common/patches/rof2_itemfields.h create mode 100644 common/patches/rof2_ops.h create mode 100644 common/patches/rof2_structs.h create mode 100644 utils/patches/patch_RoF2.conf create mode 100644 utils/scripts/opcode_scripts/conf_to_oplist.pl create mode 100644 utils/scripts/opcode_scripts/opcodelist.txt create mode 100644 utils/scripts/opcode_scripts/oplist_to_conf.pl create mode 100644 utils/scripts/opcode_scripts/patch_NEW.conf create mode 100644 utils/scripts/opcode_scripts/patch_OLD.conf diff --git a/changelog.txt b/changelog.txt index e72fc04a3..e24dcd59d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 12/04/2014 == Kayen: Ranged attacks will now more accurately check MAX firing range, fixing the issue where you would hit ranged attack and nothing would happpen due to incorrect server side range checks. +Trevius: Initial addition of the RoF2 client from May 10th 2013 (currently available on Steam as the F2P client). +Trevius: RoF2 is disabled by default, but you can enable by editing /common/patches/patches.cpp (see comments) == 12/01/2014 == Trevius: Mercenaries now spawn as the same Gender and Size of the Merchant they are purchased from. diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 01fcd6df8..be495e9b7 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -72,6 +72,7 @@ SET(common_sources patches/sod.cpp patches/sof.cpp patches/rof.cpp + patches/rof2.cpp patches/titanium.cpp patches/underfoot.cpp SocketLib/Base64.cpp @@ -216,6 +217,11 @@ SET(common_headers 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_ops.h + patches/rof2_structs.h patches/titanium.h patches/titanium_constants.h patches/titanium_itemfields.h @@ -269,6 +275,11 @@ SOURCE_GROUP(Patches FILES patches/rof_ops.h patches/rof_constants.h patches/rof_structs.h + patches/rof2.h + patches/rof2_itemfields.h + patches/rof2_ops.h + patches/rof2_constants.h + patches/rof2_structs.h patches/titanium.h patches/titanium_itemfields.h patches/titanium_ops.h @@ -284,6 +295,7 @@ SOURCE_GROUP(Patches FILES patches/sod.cpp patches/sof.cpp patches/rof.cpp + patches/rof2.cpp patches/titanium.cpp patches/underfoot.cpp ) @@ -335,7 +347,7 @@ ADD_LIBRARY(common ${common_sources} ${common_headers}) IF(UNIX) ADD_DEFINITIONS(-fPIC) SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) - SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0) + SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0) ENDIF(UNIX) diff --git a/common/eq_dictionary.h b/common/eq_dictionary.h index c08809a12..8ef38c77c 100644 --- a/common/eq_dictionary.h +++ b/common/eq_dictionary.h @@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/patches/sod_constants.h" #include "../common/patches/underfoot_constants.h" #include "../common/patches/rof_constants.h" -//#include "../common/patches/rof2_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!! *** diff --git a/common/patches/patches.cpp b/common/patches/patches.cpp index 212042210..d35ded9ba 100644 --- a/common/patches/patches.cpp +++ b/common/patches/patches.cpp @@ -8,7 +8,7 @@ #include "sof.h" #include "sod.h" #include "rof.h" -//#include "rof2.h" +#include "rof2.h" void RegisterAllPatches(EQStreamIdentifier &into) { Client62::Register(into); @@ -17,6 +17,7 @@ void RegisterAllPatches(EQStreamIdentifier &into) { SoD::Register(into); Underfoot::Register(into); RoF::Register(into); + // Uncomment the line below to enable RoF2 Client //RoF2::Register(into); } @@ -27,5 +28,6 @@ void ReloadAllPatches() { SoD::Reload(); Underfoot::Reload(); RoF::Reload(); + // Uncomment the line below to enable RoF2 Client //RoF2::Reload(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp new file mode 100644 index 000000000..372da9b07 --- /dev/null +++ b/common/patches/rof2.cpp @@ -0,0 +1,5673 @@ +#include "../debug.h" +#include "rof2.h" +#include "../opcodemgr.h" +#include "../logsys.h" +#include "../eq_stream_ident.h" +#include "../crc32.h" + +#include "../eq_packet_structs.h" +#include "../misc_functions.h" +#include "../string_util.h" +#include "../item.h" +#include "rof2_structs.h" +#include "../rulesys.h" + +#include +#include + +namespace RoF2 +{ + static const char *name = "RoF2"; + static OpcodeManager *opcodes = nullptr; + static Strategy struct_strategy; + + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + + // server to client inventory location converters + static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot); + static inline structs::MainInvItemSlotStruct ServerToRoF2MainInvSlot(uint32 ServerSlot); + static inline uint32 ServerToRoF2CorpseSlot(uint32 ServerCorpse); + + // client to server inventory location converters + static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot); + static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot); + static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse); + + void Register(EQStreamIdentifier &into) + { + //create our opcode manager if we havent already + if (opcodes == nullptr) { + //TODO: get this file name from the config file + std::string opfile = "patch_"; + opfile += name; + opfile += ".conf"; + //load up the opcode manager. + //TODO: figure out how to support shared memory with multiple patches... + opcodes = new RegularOpcodeManager(); + if (!opcodes->LoadOpcodes(opfile.c_str())) { + _log(NET__OPCODES, "Error loading opcodes file %s. Not registering patch %s.", opfile.c_str(), name); + return; + } + } + + //ok, now we have what we need to register. + + EQStream::Signature signature; + std::string pname; + + //register our world signature. + pname = std::string(name) + "_world"; + signature.ignore_eq_opcode = 0; + signature.first_length = sizeof(structs::LoginInfo_Struct); + signature.first_eq_opcode = opcodes->EmuToEQ(OP_SendLoginInfo); + into.RegisterPatch(signature, pname.c_str(), &opcodes, &struct_strategy); + + //register our zone signature. + pname = std::string(name) + "_zone"; + signature.ignore_eq_opcode = opcodes->EmuToEQ(OP_AckPacket); + 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(NET__IDENTIFY, "Registered patch %s", name); + } + + void Reload() + { + //we have a big problem to solve here when we switch back to shared memory + //opcode managers because we need to change the manager pointer, which means + //we need to go to every stream and replace it's manager. + + if (opcodes != nullptr) { + //TODO: get this file name from the config file + std::string opfile = "patch_"; + opfile += name; + opfile += ".conf"; + if (!opcodes->ReloadOpcodes(opfile.c_str())) { + _log(NET__OPCODES, "Error reloading opcodes file %s for patch %s.", opfile.c_str(), name); + return; + } + _log(NET__OPCODES, "Reloaded opcodes for patch %s", name); + } + } + + Strategy::Strategy() : StructStrategy() + { + //all opcodes default to passthrough. +#include "ss_register.h" +#include "rof_ops.h" + } + + std::string Strategy::Describe() const + { + std::string r; + r += "Patch "; + r += name; + return(r); + } + + const EQClientVersion Strategy::ClientVersion() const + { + return EQClientRoF2; + } + +#include "ss_define.h" + +// ENCODE methods + ENCODE(OP_Action) + { + ENCODE_LENGTH_EXACT(Action_Struct); + SETUP_DIRECT_ENCODE(Action_Struct, structs::ActionAlt_Struct); + + OUT(target); + OUT(source); + OUT(level); + eq->unknown06 = 0; + eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f; + eq->bard_focus_id = emu->bard_focus_id; + eq->knockback_angle = emu->sequence; + eq->unknown22 = 0; + OUT(type); + eq->damage = 0; + eq->unknown31 = 0; + OUT(spell); + eq->level2 = eq->level; + eq->effect_flag = emu->buff_unknown; + eq->unknown39 = 14; + eq->unknown43 = 0; + eq->unknown44 = 17; + eq->unknown45 = 0; + eq->unknown46 = -1; + eq->unknown50 = 0; + eq->unknown54 = 0; + + FINISH_ENCODE(); + } + + ENCODE(OP_AdventureMerchantSell) + { + ENCODE_LENGTH_EXACT(Adventure_Sell_Struct); + SETUP_DIRECT_ENCODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); + + eq->unknown000 = 1; + OUT(npcid); + eq->slot = ServerToRoF2MainInvSlot(emu->slot); + OUT(charges); + OUT(sell_price); + + FINISH_ENCODE(); + } + + ENCODE(OP_AltCurrency) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *emu_buffer = in->pBuffer; + uint32 opcode = *((uint32*)emu_buffer); + + 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); + structs::AltCurrencyPopulate_Struct *out_populate = (structs::AltCurrencyPopulate_Struct*)outapp->pBuffer; + + out_populate->opcode = populate->opcode; + out_populate->count = populate->count; + for (uint32 i = 0; i < populate->count; ++i) { + out_populate->entries[i].currency_number = populate->entries[i].currency_number; + out_populate->entries[i].unknown00 = populate->entries[i].unknown00; + out_populate->entries[i].currency_number2 = populate->entries[i].currency_number2; + out_populate->entries[i].item_id = populate->entries[i].item_id; + out_populate->entries[i].item_icon = populate->entries[i].item_icon; + out_populate->entries[i].stack_size = populate->entries[i].stack_size; + out_populate->entries[i].display = ((populate->entries[i].stack_size > 0) ? 1 : 0); + } + + dest->FastQueuePacket(&outapp, ack_req); + } + else { + EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); + memcpy(outapp->pBuffer, emu_buffer, sizeof(AltCurrencyUpdate_Struct)); + dest->FastQueuePacket(&outapp, ack_req); + } + + //dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_AltCurrencySell) + { + ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); + SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); + + OUT(merchant_entity_id); + eq->slot_id = ServerToRoF2Slot(emu->slot_id); + OUT(charges); + OUT(cost); + + FINISH_ENCODE(); + } + + ENCODE(OP_Animation) + { + ENCODE_LENGTH_EXACT(Animation_Struct); + SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct); + + OUT(spawnid); + OUT(value); + OUT(action); + + FINISH_ENCODE(); + } + + ENCODE(OP_ApplyPoison) + { + ENCODE_LENGTH_EXACT(ApplyPoison_Struct); + SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); + + eq->inventorySlot = ServerToRoF2MainInvSlot(emu->inventorySlot); + OUT(success); + + FINISH_ENCODE(); + } + + ENCODE(OP_AugmentInfo) + { + ENCODE_LENGTH_EXACT(AugmentInfo_Struct); + SETUP_DIRECT_ENCODE(AugmentInfo_Struct, structs::AugmentInfo_Struct); + + OUT(itemid); + OUT(window); + strn0cpy(eq->augment_info, emu->augment_info, 64); + + FINISH_ENCODE(); + } + + ENCODE(OP_Barter) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + char *Buffer = (char *)in->pBuffer; + + uint32 SubAction = VARSTRUCT_DECODE_TYPE(uint32, Buffer); + + if (SubAction != Barter_BuyerAppearance) + { + dest->FastQueuePacket(&in, ack_req); + + return; + } + + unsigned char *__emu_buffer = in->pBuffer; + + in->size = 80; + + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + char Name[64]; + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, SubAction); + uint32 EntityID = VARSTRUCT_DECODE_TYPE(uint32, Buffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, EntityID); + uint8 Toggle = VARSTRUCT_DECODE_TYPE(uint8, Buffer); + VARSTRUCT_DECODE_STRING(Name, Buffer); + VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + OutBuffer = (char *)in->pBuffer + 72; + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, Toggle); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_BazaarSearch) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + char *Buffer = (char *)in->pBuffer; + + uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer); + + if (SubAction != BazaarSearchResults) + { + dest->FastQueuePacket(&in, ack_req); + return; + } + + unsigned char *__emu_buffer = in->pBuffer; + + BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer; + + int EntryCount = in->size / sizeof(BazaarSearchResults_Struct); + + if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0) + { + _log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct)); + delete in; + return; + } + + in->size = EntryCount * sizeof(structs::BazaarSearchResults_Struct); + in->pBuffer = new unsigned char[in->size]; + + memset(in->pBuffer, 0, in->size); + + structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *)in->pBuffer; + + for (int i = 0; i < EntryCount; ++i, ++emu, ++eq) + { + OUT(Beginning.Action); + OUT(SellerID); + memcpy(eq->SellerName, emu->SellerName, sizeof(eq->SellerName)); + OUT(NumItems); + OUT(ItemID); + OUT(SerialNumber); + memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName)); + OUT(Cost); + OUT(ItemStat); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_BeginCast) + { + SETUP_DIRECT_ENCODE(BeginCast_Struct, structs::BeginCast_Struct); + + OUT(spell_id); + OUT(caster_id); + OUT(cast_time); + + FINISH_ENCODE(); + } + + ENCODE(OP_BlockedBuffs) + { + ENCODE_LENGTH_EXACT(BlockedBuffs_Struct); + SETUP_DIRECT_ENCODE(BlockedBuffs_Struct, structs::BlockedBuffs_Struct); + + for (uint32 i = 0; i < BLOCKED_BUFF_COUNT; ++i) + eq->SpellID[i] = emu->SpellID[i]; + + // -1 for the extra 10 added in RoF2. We should really be encoding for the older clients, not RoF2, but + // we can sort that out later. + + for (uint32 i = BLOCKED_BUFF_COUNT; i < structs::BLOCKED_BUFF_COUNT; ++i) + eq->SpellID[i] = -1; + + OUT(Count); + OUT(Pet); + OUT(Initialise); + OUT(Flags); + + FINISH_ENCODE(); + } + + ENCODE(OP_Buff) + { + ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); + SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Live); + + 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); + if (emu->bufffade == 1) + eq->bufffade = 1; + else + eq->bufffade = 2; + + // Bit of a hack. OP_Buff appears to add/remove the buff while OP_BuffCreate adds/removes the actual buff icon + EQApplicationPacket *outapp = nullptr; + if (eq->bufffade == 1) + { + outapp = new EQApplicationPacket(OP_BuffCreate, 29); + outapp->WriteUInt32(emu->entityid); + outapp->WriteUInt32(0x0271); // Unk + outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? + outapp->WriteUInt16(1); // 1 buff in this packet + outapp->WriteUInt32(emu->slotid); + outapp->WriteUInt32(0xffffffff); // SpellID (0xffff to remove) + outapp->WriteUInt32(0); // Duration + outapp->WriteUInt32(0); // ? + outapp->WriteUInt8(0); // Caster name + outapp->WriteUInt8(0); // Terminating byte + } + FINISH_ENCODE(); + + if (outapp) + dest->FastQueuePacket(&outapp); // Send the OP_BuffCreate to remove the buff + } + + ENCODE(OP_BuffCreate) + { + SETUP_VAR_ENCODE(BuffIcon_Struct); + + uint32 sz = 12 + (17 * emu->count); + __packet->size = sz; + __packet->pBuffer = new unsigned char[sz]; + memset(__packet->pBuffer, 0, sz); + + __packet->WriteUInt32(emu->entity_id); + __packet->WriteUInt32(0); // PlayerID ? + __packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff) + __packet->WriteUInt16(emu->count); + + for (uint16 i = 0; i < emu->count; ++i) + { + uint16 buffslot = emu->entries[i].buff_slot; + // Not sure if this is needs amending for RoF2 yet. + if (emu->entries[i].buff_slot >= 25) + { + buffslot += 17; + } + + __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->entries[i].spell_id); + __packet->WriteUInt32(emu->entries[i].tics_remaining); + __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown + __packet->WriteString(""); + } + __packet->WriteUInt8(!emu->all_buffs); // Unknown + + FINISH_ENCODE(); + } + + ENCODE(OP_CancelTrade) + { + ENCODE_LENGTH_EXACT(CancelTrade_Struct); + SETUP_DIRECT_ENCODE(CancelTrade_Struct, structs::CancelTrade_Struct); + + OUT(fromid); + OUT(action); + + FINISH_ENCODE(); + } + + ENCODE(OP_CastSpell) + { + ENCODE_LENGTH_EXACT(CastSpell_Struct); + SETUP_DIRECT_ENCODE(CastSpell_Struct, structs::CastSpell_Struct); + + if (emu->slot == 10) + eq->slot = 13; + else + OUT(slot); + + OUT(spell_id); + eq->inventoryslot = ServerToRoF2Slot(emu->inventoryslot); + //OUT(inventoryslot); + OUT(target_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_ChannelMessage) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sender); + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->targetname); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->language); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->chan_num); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->skill_in_language); + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->message); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint16, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_CharInventory) + { + //consume the packet + EQApplicationPacket *in = *p; + + *p = nullptr; + + if (in->size == 0) { + + in->size = 4; + in->pBuffer = new uchar[in->size]; + + *((uint32 *)in->pBuffer) = 0; + + 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) { + + _log(NET__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; + + in->pBuffer = new uchar[4]; + *(uint32 *)in->pBuffer = ItemCount; + in->size = 4; + + for (int r = 0; r < ItemCount; r++, eq++) { + + uint32 Length = 0; + + 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(NET__ERROR, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + } + } + + delete[] __emu_buffer; + + //_log(NET__ERROR, "Sending inventory to client"); + //_hex(NET__ERROR, in->pBuffer, in->size); + + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_ClickObjectAction) + { + ENCODE_LENGTH_EXACT(ClickObjectAction_Struct); + SETUP_DIRECT_ENCODE(ClickObjectAction_Struct, structs::ClickObjectAction_Struct); + + OUT(drop_id); + eq->unknown04 = -1; + eq->unknown08 = -1; + OUT(type); + OUT(icon); + eq->unknown16 = 0; + OUT_str(object_name); + + FINISH_ENCODE(); + } + + ENCODE(OP_ClientUpdate) + { + ENCODE_LENGTH_EXACT(PlayerPositionUpdateServer_Struct); + SETUP_DIRECT_ENCODE(PlayerPositionUpdateServer_Struct, structs::PlayerPositionUpdateServer_Struct); + + OUT(spawn_id); + OUT(x_pos); + OUT(delta_x); + OUT(delta_y); + OUT(z_pos); + OUT(delta_heading); + OUT(y_pos); + OUT(delta_z); + OUT(animation); + OUT(heading); + + FINISH_ENCODE(); + } + + ENCODE(OP_Consider) + { + ENCODE_LENGTH_EXACT(Consider_Struct); + SETUP_DIRECT_ENCODE(Consider_Struct, structs::Consider_Struct); + + OUT(playerid); + OUT(targetid); + OUT(faction); + OUT(level); + OUT(pvpcon); + + FINISH_ENCODE(); + } + + 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); + eq->sequence = emu->sequence; + + FINISH_ENCODE(); + } + + ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } + + ENCODE(OP_DeleteItem) + { + ENCODE_LENGTH_EXACT(DeleteItem_Struct); + SETUP_DIRECT_ENCODE(DeleteItem_Struct, structs::DeleteItem_Struct); + + eq->from_slot = ServerToRoF2Slot(emu->from_slot); + eq->to_slot = ServerToRoF2Slot(emu->to_slot); + OUT(number_in_stack); + + FINISH_ENCODE(); + } + + ENCODE(OP_DeleteSpawn) + { + ENCODE_LENGTH_EXACT(DeleteSpawn_Struct); + SETUP_DIRECT_ENCODE(DeleteSpawn_Struct, structs::DeleteSpawn_Struct); + + OUT(spawn_id); + eq->unknown04 = 1; // Observed + + FINISH_ENCODE(); + } + + ENCODE(OP_DisciplineUpdate) + { + ENCODE_LENGTH_EXACT(Disciplines_Struct); + SETUP_DIRECT_ENCODE(Disciplines_Struct, structs::Disciplines_Struct); + + memcpy(&eq->values, &emu->values, sizeof(Disciplines_Struct)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzCompass) + { + 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) + { + OUT(entries[i].x); + OUT(entries[i].y); + OUT(entries[i].z); + } + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionEndsWarning) + { + ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); + SETUP_DIRECT_ENCODE(ExpeditionExpireWarning, structs::ExpeditionExpireWarning); + + OUT(minutes_remaining); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionInfo) + { + ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); + + OUT(max_players); + eq->unknown004 = 785316192; + eq->unknown008 = 435601; + strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strncpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionList) + { + SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct); + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + uint32 client_id = 0; + uint8 null_term = 0; + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&emu->count, sizeof(uint32)); + for (uint32 i = 0; i < emu->count; ++i) + { + ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition)); + ss.write((const char*)&null_term, sizeof(char)); + ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event)); + ss.write((const char*)&null_term, sizeof(char)); + } + + __packet->size = ss.str().length(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzJoinExpeditionConfirm) + { + ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); + SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); + + strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strncpy(eq->player_name, emu->player_name, sizeof(eq->player_name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzLeaderStatus) + { + SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct); + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + uint32 client_id = 0; + uint8 null_term = 0; + + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write(emu->leader_name, strlen(emu->leader_name)); + ss.write((const char*)&null_term, sizeof(char)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32));//1 + ss.write((const char*)&client_id, sizeof(uint32)); + + __packet->size = ss.str().length(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzMemberList) + { + SETUP_VAR_ENCODE(ExpeditionMemberList_Struct); + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + + uint32 client_id = 0; + uint8 null_term = 0; + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&emu->count, sizeof(uint32)); + for (uint32 i = 0; i < emu->count; ++i) + { + ss.write(emu->entries[i].name, strlen(emu->entries[i].name)); + ss.write((const char*)&null_term, sizeof(char)); + ss.write((const char*)&emu->entries[i].status, sizeof(char)); + } + + __packet->size = ss.str().length(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + + FINISH_ENCODE(); + } + + ENCODE(OP_ExpansionInfo) + { + ENCODE_LENGTH_EXACT(ExpansionInfo_Struct); + SETUP_DIRECT_ENCODE(ExpansionInfo_Struct, structs::ExpansionInfo_Struct); + + OUT(Expansions); + + FINISH_ENCODE(); + } + + ENCODE(OP_GMLastName) + { + ENCODE_LENGTH_EXACT(GMLastName_Struct); + SETUP_DIRECT_ENCODE(GMLastName_Struct, structs::GMLastName_Struct); + + OUT_str(name); + OUT_str(gmname); + OUT_str(lastname); + for (int i = 0; i<4; i++) + { + eq->unknown[i] = emu->unknown[i]; + } + + FINISH_ENCODE(); + } + + ENCODE(OP_GMTrainSkillConfirm) + { + ENCODE_LENGTH_EXACT(GMTrainSkillConfirm_Struct); + SETUP_DIRECT_ENCODE(GMTrainSkillConfirm_Struct, structs::GMTrainSkillConfirm_Struct); + + OUT(SkillID); + OUT(Cost); + OUT(NewSkill); + OUT_str(TrainerName); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroundSpawn) + { + // We are not encoding the spawn_id field here, but it doesn't appear to matter. + // + EQApplicationPacket *in = *p; + *p = nullptr; + + Object_Struct *emu = (Object_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + in->size = strlen(emu->object_name) + sizeof(Object_Struct)-1; + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->object_name); + VARSTRUCT_ENCODE_TYPE(uint16, OutBuffer, emu->zone_id); + VARSTRUCT_ENCODE_TYPE(uint16, OutBuffer, emu->zone_instance); + 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(float, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 1); // Need to add emu->size to struct + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); + VARSTRUCT_ENCODE_TYPE(int32, OutBuffer, emu->object_type); // Unknown, observed 0x00000014 + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_GroupCancelInvite) + { + ENCODE_LENGTH_EXACT(GroupCancel_Struct); + SETUP_DIRECT_ENCODE(GroupCancel_Struct, structs::GroupCancel_Struct); + + memcpy(eq->name1, emu->name1, sizeof(eq->name1)); + memcpy(eq->name2, emu->name2, sizeof(eq->name2)); + OUT(toggle); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroupFollow) + { + ENCODE_LENGTH_EXACT(GroupGeneric_Struct); + SETUP_DIRECT_ENCODE(GroupGeneric_Struct, structs::GroupFollow_Struct); + + memcpy(eq->name1, emu->name1, sizeof(eq->name1)); + memcpy(eq->name2, emu->name2, sizeof(eq->name2)); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroupFollow2) + { + ENCODE_LENGTH_EXACT(GroupGeneric_Struct); + SETUP_DIRECT_ENCODE(GroupGeneric_Struct, structs::GroupFollow_Struct); + + memcpy(eq->name1, emu->name1, sizeof(eq->name1)); + memcpy(eq->name2, emu->name2, sizeof(eq->name2)); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroupInvite) + { + ENCODE_LENGTH_EXACT(GroupGeneric_Struct); + SETUP_DIRECT_ENCODE(GroupGeneric_Struct, structs::GroupInvite_Struct); + + memcpy(eq->invitee_name, emu->name1, sizeof(eq->invitee_name)); + memcpy(eq->inviter_name, emu->name2, sizeof(eq->inviter_name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroupUpdate) + { + //_log(NET__ERROR, "OP_GroupUpdate"); + EQApplicationPacket *in = *p; + GroupJoin_Struct *gjs = (GroupJoin_Struct*)in->pBuffer; + + //_log(NET__ERROR, "Received outgoing OP_GroupUpdate with action code %i", gjs->action); + if ((gjs->action == groupActLeave) || (gjs->action == groupActDisband)) + { + if ((gjs->action == groupActDisband) || !strcmp(gjs->yourname, gjs->membername)) + { + //_log(NET__ERROR, "Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); + + EQApplicationPacket *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)); + memcpy(ggs->name2, gjs->membername, sizeof(ggs->name1)); + dest->FastQueuePacket(&outapp); + + // Make an empty GLAA packet to clear out their useable GLAAs + // + outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + + dest->FastQueuePacket(&outapp); + delete in; + return; + } + //if(gjs->action == groupActLeave) + // _log(NET__ERROR, "Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); + + EQApplicationPacket *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)); + memcpy(ggs->name2, gjs->membername, sizeof(ggs->name2)); + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + dest->FastQueuePacket(&outapp); + + delete in; + return; + } + + if (in->size == sizeof(GroupUpdate2_Struct)) + { + // Group Update2 + //_log(NET__ERROR, "Struct is GroupUpdate2"); + + unsigned char *__emu_buffer = in->pBuffer; + GroupUpdate2_Struct *gu2 = (GroupUpdate2_Struct*)__emu_buffer; + + //_log(NET__ERROR, "Yourname is %s", gu2->yourname); + + int MemberCount = 1; + int PacketLength = 8 + strlen(gu2->leadersname) + 1 + 22 + strlen(gu2->yourname) + 1; + + for (int i = 0; i < 5; ++i) + { + //_log(NET__ERROR, "Membername[%i] is %s", i, gu2->membername[i]); + if (gu2->membername[i][0] != '\0') + { + PacketLength += (22 + strlen(gu2->membername[i]) + 1); + ++MemberCount; + } + } + + //_log(NET__ERROR, "Leadername is %s", gu2->leadersname); + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); + + char *Buffer = (char *)outapp->pBuffer; + + // Header + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Think this should be SpawnID, but it doesn't seem to matter + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, MemberCount); + VARSTRUCT_ENCODE_STRING(Buffer, gu2->leadersname); + + // Leader + // + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_STRING(Buffer, gu2->yourname); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + //VARSTRUCT_ENCODE_STRING(Buffer, ""); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x46); // Observed 0x41 and 0x46 here + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); + + int MemberNumber = 1; + + for (int i = 0; i < 5; ++i) + { + if (gu2->membername[i][0] == '\0') + continue; + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, MemberNumber++); + VARSTRUCT_ENCODE_STRING(Buffer, gu2->membername[i]); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + //VARSTRUCT_ENCODE_STRING(Buffer, ""); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x41); // Observed 0x41 and 0x46 here + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Low byte is Main Assist Flag + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); + } + + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + dest->FastQueuePacket(&outapp); + + outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + + GroupLeadershipAAUpdate_Struct *GLAAus = (GroupLeadershipAAUpdate_Struct*)outapp->pBuffer; + + GLAAus->NPCMarkerID = gu2->NPCMarkerID; + memcpy(&GLAAus->LeaderAAs, &gu2->leader_aas, sizeof(GLAAus->LeaderAAs)); + + dest->FastQueuePacket(&outapp); + delete in; + + return; + + } + //_log(NET__ERROR, "Generic GroupUpdate, yourname = %s, membername = %s", gjs->yourname, gjs->membername); + ENCODE_LENGTH_EXACT(GroupJoin_Struct); + SETUP_DIRECT_ENCODE(GroupJoin_Struct, structs::GroupJoin_Struct); + + memcpy(eq->membername, emu->membername, sizeof(eq->membername)); + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + GroupLeadershipAAUpdate_Struct *GLAAus = (GroupLeadershipAAUpdate_Struct*)outapp->pBuffer; + + GLAAus->NPCMarkerID = emu->NPCMarkerID; + + memcpy(&GLAAus->LeaderAAs, &emu->leader_aas, sizeof(GLAAus->LeaderAAs)); + //_hex(NET__ERROR, __packet->pBuffer, __packet->size); + + FINISH_ENCODE(); + + dest->FastQueuePacket(&outapp); + } + + ENCODE(OP_GuildMemberList) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + Internal_GuildMembers_Struct *emu = (Internal_GuildMembers_Struct *)in->pBuffer; + + //make a new EQ buffer. + uint32 pnl = strlen(emu->player_name); + uint32 length = sizeof(structs::GuildMembers_Struct) + pnl + + emu->count*sizeof(structs::GuildMemberEntry_Struct) + + emu->name_length + emu->note_length; + in->pBuffer = new uint8[length]; + in->size = length; + //no memset since we fill every byte. + + uint8 *buffer; + buffer = in->pBuffer; + + //easier way to setup GuildMembers_Struct + //set prefix name + strcpy((char *)buffer, emu->player_name); + buffer += pnl; + *buffer = '\0'; + buffer++; + + // Guild ID + buffer += sizeof(uint32); + + //add member count. + *((uint32 *)buffer) = htonl(emu->count); + buffer += sizeof(uint32); + + if (emu->count > 0) { + Internal_GuildMemberEntry_Struct *emu_e = emu->member; + const char *emu_name = (const char *)(__emu_buffer + + sizeof(Internal_GuildMembers_Struct)+ //skip header + emu->count * sizeof(Internal_GuildMemberEntry_Struct) //skip static length member data + ); + const char *emu_note = (emu_name + + emu->name_length + //skip name contents + emu->count //skip string terminators + ); + + structs::GuildMemberEntry_Struct *e = (structs::GuildMemberEntry_Struct *) buffer; + + uint32 r; + for (r = 0; r < emu->count; r++, emu_e++) { + + //the order we set things here must match the struct + + //nice helper macro +#define SlideStructString(field, str) \ + { \ + int sl = strlen(str); \ + memcpy(e->field, str, sl+1); \ + e = (structs::GuildMemberEntry_Struct *) ( ((uint8 *)e) + sl ); \ + str += sl + 1; \ + } +#define PutFieldN(field) e->field = htonl(emu_e->field) + + SlideStructString(name, emu_name); + PutFieldN(level); + PutFieldN(banker); + PutFieldN(class_); + + /* Translate older ranks to new values */ + 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 + default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE + } + + PutFieldN(time_last_on); + PutFieldN(tribute_enable); + e->unknown01 = 0; + PutFieldN(total_tribute); + PutFieldN(last_tribute); + e->unknown_one = htonl(1); + SlideStructString(public_note, emu_note); + e->zoneinstance = 0; + e->zone_id = htons(emu_e->zone_id); + e->unknown_one2 = htonl(1); + e->unknown04 = 0; + +#undef SlideStructString +#undef PutFieldN + + e++; + } + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_GuildMemberUpdate) + { + SETUP_DIRECT_ENCODE(GuildMemberUpdate_Struct, structs::GuildMemberUpdate_Struct); + + OUT(GuildID); + memcpy(eq->MemberName, emu->MemberName, sizeof(eq->MemberName)); + OUT(ZoneID); + OUT(InstanceID); + OUT(LastSeen); + eq->Unknown76 = 0; + + FINISH_ENCODE(); + } + + ENCODE(OP_GuildsList) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + uint32 NumberOfGuilds = in->size / 64; + uint32 PacketSize = 68; // 64 x 0x00 + a uint32 that I am guessing is the highest guild ID in use. + + unsigned char *__emu_buffer = in->pBuffer; + + char *InBuffer = (char *)__emu_buffer; + + uint32 HighestGuildID = 0; + + for (unsigned int i = 0; i < NumberOfGuilds; ++i) + { + if (InBuffer[0]) + { + PacketSize += (5 + strlen(InBuffer)); + HighestGuildID = i - 1; + } + InBuffer += 64; + } + + PacketSize++; // Appears to be an extra 0x00 at the very end. + + in->size = PacketSize; + in->pBuffer = new unsigned char[in->size]; + + InBuffer = (char *)__emu_buffer; + + char *OutBuffer = (char *)in->pBuffer; + + // Init the first 64 bytes to zero, as per live. + // + memset(OutBuffer, 0, 64); + + OutBuffer += 64; + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, HighestGuildID); + + for (unsigned int i = 0; i < NumberOfGuilds; ++i) + { + if (InBuffer[0]) + { + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, i - 1); + VARSTRUCT_ENCODE_STRING(OutBuffer, InBuffer); + } + InBuffer += 64; + } + + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0x00); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_HPUpdate) + { + SETUP_DIRECT_ENCODE(SpawnHPUpdate_Struct, structs::SpawnHPUpdate_Struct); + + OUT(spawn_id); + OUT(cur_hp); + OUT(max_hp); + + FINISH_ENCODE(); + } + + ENCODE(OP_Illusion) + { + ENCODE_LENGTH_EXACT(Illusion_Struct); + SETUP_DIRECT_ENCODE(Illusion_Struct, structs::Illusion_Struct); + + OUT(spawnid); + OUT_str(charname); + OUT(race); + OUT(unknown006[0]); + OUT(unknown006[1]); + OUT(gender); + OUT(texture); + OUT(helmtexture); + OUT(face); + OUT(hairstyle); + OUT(haircolor); + OUT(beard); + OUT(beardcolor); + OUT(size); + OUT(drakkin_heritage); + OUT(drakkin_tattoo); + OUT(drakkin_details); + eq->unknown316 = -1; // Observed + + FINISH_ENCODE(); + } + + /*ENCODE(OP_InspectAnswer) + { + ENCODE_LENGTH_EXACT(InspectResponse_Struct); + SETUP_DIRECT_ENCODE(InspectResponse_Struct, structs::InspectResponse_Struct); + + OUT(TargetID); + OUT(playerid); + + int r; + for (r = 0; r < 21; r++) { + strn0cpy(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r])); + } + // Swap last 2 slots for Arrow and Power Source + strn0cpy(eq->itemnames[21], emu->itemnames[22], sizeof(eq->itemnames[21])); + strn0cpy(eq->unknown_zero, emu->itemnames[21], sizeof(eq->unknown_zero)); + + int k; + for (k = 0; k < 21; k++) { + OUT(itemicons[k]); + } + // Swap last 2 slots for Arrow and Power Source + eq->itemicons[21] = emu->itemicons[22]; + eq->unknown_zero2 = emu->itemicons[21]; + strn0cpy(eq->text, emu->text, sizeof(eq->text)); + + FINISH_ENCODE(); + }*/ + + ENCODE(OP_InspectBuffs) + { + ENCODE_LENGTH_EXACT(InspectBuffs_Struct); + SETUP_DIRECT_ENCODE(InspectBuffs_Struct, structs::InspectBuffs_Struct); + + // we go over the internal 25 instead of the packet's since no entry is 0, which it will be already + for (int i = 0; i < BUFF_COUNT; i++) { + OUT(spell_id[i]); + OUT(tics_remaining[i]); + } + + FINISH_ENCODE(); + } + + ENCODE(OP_InspectRequest) + { + ENCODE_LENGTH_EXACT(Inspect_Struct); + SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); + + OUT(TargetID); + OUT(PlayerID); + + FINISH_ENCODE(); + } + + ENCODE(OP_InterruptCast) + { + ENCODE_LENGTH_EXACT(InterruptCast_Struct); + SETUP_DIRECT_ENCODE(InterruptCast_Struct, structs::InterruptCast_Struct); + + OUT(spawnid); + OUT(messageid); + + FINISH_ENCODE(); + } + + ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } + + ENCODE(OP_ItemPacket) + { + //consume the packet + 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); + + uint32 length; + char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); + + if (!serialized) { + _log(NET__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); + + delete[] __emu_buffer; + safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_ItemVerifyReply) + { + ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); + SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); + + eq->slot = ServerToRoF2Slot(emu->slot); + OUT(spell); + OUT(target); + + FINISH_ENCODE(); + } + + ENCODE(OP_LeadershipExpUpdate) + { + SETUP_DIRECT_ENCODE(LeadershipExpUpdate_Struct, structs::LeadershipExpUpdate_Struct); + + OUT(group_leadership_exp); + OUT(group_leadership_points); + OUT(raid_leadership_exp); + OUT(raid_leadership_points); + + FINISH_ENCODE(); + } + + ENCODE(OP_LogServer) + { + ENCODE_LENGTH_EXACT(LogServer_Struct); + SETUP_DIRECT_ENCODE(LogServer_Struct, structs::LogServer_Struct); + + strncpy(eq->worldshortname, emu->worldshortname, sizeof(eq->worldshortname)); + + //OUT(enablevoicemacros); // These two are lost, but must be one of the 1s in unknown[249] + //OUT(enablemail); + OUT(enable_pvp); + OUT(enable_FV); + + eq->unknown016 = 1; + eq->unknown020[0] = 1; + + eq->unknown249[0] = 1; + eq->unknown249[1] = 1; + eq->unknown249[8] = 1; + eq->unknown249[9] = 1; + eq->unknown249[12] = 1; + eq->unknown249[14] = 1; + eq->unknown249[15] = 1; + eq->unknown249[16] = 1; + + eq->unknown276[0] = 1.0f; + eq->unknown276[1] = 1.0f; + eq->unknown276[6] = 1.0f; + + FINISH_ENCODE(); + } + + ENCODE(OP_LootItem) + { + ENCODE_LENGTH_EXACT(LootingItem_Struct); + SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); + + OUT(lootee); + OUT(looter); + eq->slot_id = ServerToRoF2CorpseSlot(emu->slot_id); + OUT(auto_loot); + + FINISH_ENCODE(); + } + + ENCODE(OP_ManaChange) + { + ENCODE_LENGTH_EXACT(ManaChange_Struct); + SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct); + + OUT(new_mana); + OUT(stamina); + OUT(spell_id); + eq->unknown16 = -1; // Self Interrupt/Success = -1, Fizzle = 1, Other Interrupt = 2? + + FINISH_ENCODE(); + } + + ENCODE(OP_MercenaryDataResponse) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + MercenaryMerchantList_Struct *emu = (MercenaryMerchantList_Struct *)__emu_buffer; + + char *Buffer = (char *)in->pBuffer; + + int PacketSize = sizeof(structs::MercenaryMerchantList_Struct) - 4 + emu->MercTypeCount * 4; + PacketSize += (sizeof(structs::MercenaryListEntry_Struct) - sizeof(structs::MercenaryStance_Struct)) * emu->MercCount; + + uint32 r; + uint32 k; + for (r = 0; r < emu->MercCount; r++) + { + PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->Mercs[r].StanceCount; + } + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); + Buffer = (char *)outapp->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercTypeCount); + + for (r = 0; r < emu->MercTypeCount; r++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercGrades[r]); + } + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercCount); + + for (r = 0; r < emu->MercCount; r++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercID); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercSubType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].PurchaseCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].UpkeepCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].Status); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyUpkeep); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyType); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->Mercs[r].MercUnk01); + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->Mercs[r].TimeLeft); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MerchantSlot); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercUnk02); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].StanceCount); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercUnk03); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->Mercs[r].MercUnk04); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // MercName + for (k = 0; k < emu->Mercs[r].StanceCount; k++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].Stances[k].StanceIndex); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].Stances[k].Stance); + } + } + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_MercenaryDataUpdate) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + MercenaryDataUpdate_Struct *emu = (MercenaryDataUpdate_Struct *)__emu_buffer; + + char *Buffer = (char *)in->pBuffer; + + EQApplicationPacket *outapp; + + uint32 PacketSize = 0; + + // There are 2 different sized versions of this packet depending if a merc is hired or not + if (emu->MercStatus >= 0) + { + PacketSize += sizeof(structs::MercenaryDataUpdate_Struct) + (sizeof(structs::MercenaryData_Struct) - sizeof(structs::MercenaryStance_Struct)) * emu->MercCount; + + uint32 r; + uint32 k; + for (r = 0; r < emu->MercCount; r++) + { + PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->MercData[r].StanceCount; + PacketSize += strlen(emu->MercData[r].MercName); // Null Terminator size already accounted for in the struct + } + + outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, PacketSize); + Buffer = (char *)outapp->pBuffer; + + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercStatus); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercCount); + + for (r = 0; r < emu->MercCount; r++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MercID); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MercType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MercSubType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].PurchaseCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].UpkeepCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].Status); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyUpkeep); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyType); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->MercData[r].MercUnk01); + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercData[r].TimeLeft); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MerchantSlot); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MercUnk02); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].StanceCount); + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercData[r].MercUnk03); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->MercData[r].MercUnk04); + //VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // MercName + VARSTRUCT_ENCODE_STRING(Buffer, emu->MercData[r].MercName); + for (k = 0; k < emu->MercData[r].StanceCount; k++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].Stances[k].StanceIndex); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].Stances[k].Stance); + } + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); // MercUnk05 + } + } + else + { + PacketSize += sizeof(structs::NoMercenaryHired_Struct); + + outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, PacketSize); + Buffer = (char *)outapp->pBuffer; + + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercStatus); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercCount); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); + } + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_MoveItem) + { + ENCODE_LENGTH_EXACT(MoveItem_Struct); + SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); + + eq->from_slot = ServerToRoF2Slot(emu->from_slot); + eq->to_slot = ServerToRoF2Slot(emu->to_slot); + OUT(number_in_stack); + + FINISH_ENCODE(); + } + + ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } + + ENCODE(OP_NewZone) + { + SETUP_DIRECT_ENCODE(NewZone_Struct, structs::NewZone_Struct); + + OUT_str(char_name); + OUT_str(zone_short_name); + OUT_str(zone_long_name); + OUT(ztype); + int r; + for (r = 0; r < 4; r++) { + OUT(fog_red[r]); + OUT(fog_green[r]); + OUT(fog_blue[r]); + OUT(fog_minclip[r]); + OUT(fog_maxclip[r]); + } + OUT(gravity); + OUT(time_type); + for (r = 0; r < 4; r++) { + OUT(rain_chance[r]); + } + for (r = 0; r < 4; r++) { + OUT(rain_duration[r]); + } + for (r = 0; r < 4; r++) { + OUT(snow_chance[r]); + } + for (r = 0; r < 4; r++) { + OUT(snow_duration[r]); + } + for (r = 0; r < 32; r++) { + eq->unknown537[r] = 0xFF; //observed + } + OUT(sky); + OUT(zone_exp_multiplier); + OUT(safe_y); + OUT(safe_x); + OUT(safe_z); + OUT(max_z); + OUT(underworld); + OUT(minclip); + OUT(maxclip); + OUT_str(zone_short_name2); + OUT(zone_id); + OUT(zone_instance); + OUT(SuspendBuffs); + + eq->FogDensity = emu->fog_density; + + /*fill in some unknowns with observed values, hopefully it will help */ + eq->unknown800 = -1; + eq->unknown844 = 600; + eq->unknown880 = 50; + eq->unknown884 = 10; + eq->unknown888 = 1; + eq->unknown889 = 0; + eq->unknown890 = 1; + eq->unknown891 = 0; + eq->unknown892 = 0; + eq->unknown893 = 0; + eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off + eq->unknown895 = 0; + eq->unknown896 = 180; + eq->unknown900 = 180; + eq->unknown904 = 180; + eq->unknown908 = 2; + eq->unknown912 = 2; + eq->unknown932 = -1; // Set from PoK Example + eq->unknown936 = -1; // Set from PoK Example + eq->unknown944 = 1.0; // Set from PoK Example + + FINISH_ENCODE(); + } + + ENCODE(OP_OnLevelMessage) + { + ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); + SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); + + // This packet is variable sized now, but forcing it to the old packet size for now. + eq->Title_Count = 128; + memcpy(eq->Title, emu->Title, sizeof(eq->Title)); + eq->Text_Count = 4096; + memcpy(eq->Text, emu->Text, sizeof(eq->Text)); + OUT(Buttons); + OUT(Duration); + OUT(PopupID); + OUT(NegativeID); + // These two field names are used if Buttons == 1. We should add an interface to them via Perl. + eq->ButtonName0_Count = 25; + OUT_str(ButtonName0); + eq->ButtonName1_Count = 25; + OUT_str(ButtonName1); + + FINISH_ENCODE(); + } + + /* + ENCODE(OP_OpenNewTasksWindow) + { + AvailableTaskHeader_Struct* __emu_AvailableTaskHeader; + AvailableTaskData1_Struct* __emu_AvailableTaskData1; + AvailableTaskData2_Struct* __emu_AvailableTaskData2; + AvailableTaskTrailer_Struct* __emu_AvailableTaskTrailer; + + structs::AvailableTaskHeader_Struct* __eq_AvailableTaskHeader; + structs::AvailableTaskData1_Struct* __eq_AvailableTaskData1; + structs::AvailableTaskData2_Struct* __eq_AvailableTaskData2; + structs::AvailableTaskTrailer_Struct* __eq_AvailableTaskTrailer; + + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + + __emu_AvailableTaskHeader = (AvailableTaskHeader_Struct*)__emu_buffer; + + // For each task, SoF has an extra uint32 and what appears to be space for a null terminated string. + // + in->size = in->size + (__emu_AvailableTaskHeader->TaskCount * 5); + + in->pBuffer = new unsigned char[in->size]; + + unsigned char *__eq_buffer = in->pBuffer; + + __eq_AvailableTaskHeader = (structs::AvailableTaskHeader_Struct*)__eq_buffer; + + char *__eq_ptr, *__emu_Ptr; + + // Copy Header + // + // + + __eq_AvailableTaskHeader->TaskCount = __emu_AvailableTaskHeader->TaskCount; + __eq_AvailableTaskHeader->unknown1 = __emu_AvailableTaskHeader->unknown1; + __eq_AvailableTaskHeader->TaskGiver = __emu_AvailableTaskHeader->TaskGiver; + + __emu_Ptr = (char *) __emu_AvailableTaskHeader + sizeof(AvailableTaskHeader_Struct); + __eq_ptr = (char *) __eq_AvailableTaskHeader + sizeof(structs::AvailableTaskHeader_Struct); + + for(uint32 i=0; i<__emu_AvailableTaskHeader->TaskCount; i++) { + + __emu_AvailableTaskData1 = (AvailableTaskData1_Struct*)__emu_Ptr; + __eq_AvailableTaskData1 = (structs::AvailableTaskData1_Struct*)__eq_ptr; + + __eq_AvailableTaskData1->TaskID = __emu_AvailableTaskData1->TaskID; + // This next unknown seems to affect the colour of the task title. 0x3f80000 is what I have seen + // in RoF2 packets. Changing it to 0x3f000000 makes the title red. + __eq_AvailableTaskData1->unknown1 = 0x3f800000; + __eq_AvailableTaskData1->TimeLimit = __emu_AvailableTaskData1->TimeLimit; + __eq_AvailableTaskData1->unknown2 = __emu_AvailableTaskData1->unknown2; + + __emu_Ptr += sizeof(AvailableTaskData1_Struct); + __eq_ptr += sizeof(structs::AvailableTaskData1_Struct); + + strcpy(__eq_ptr, __emu_Ptr); // Title + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + + strcpy(__eq_ptr, __emu_Ptr); // Description + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + + __eq_ptr[0] = 0; + __eq_ptr += strlen(__eq_ptr) + 1; + + __emu_AvailableTaskData2 = (AvailableTaskData2_Struct*)__emu_Ptr; + __eq_AvailableTaskData2 = (structs::AvailableTaskData2_Struct*)__eq_ptr; + + __eq_AvailableTaskData2->unknown1 = __emu_AvailableTaskData2->unknown1; + __eq_AvailableTaskData2->unknown2 = __emu_AvailableTaskData2->unknown2; + __eq_AvailableTaskData2->unknown3 = __emu_AvailableTaskData2->unknown3; + __eq_AvailableTaskData2->unknown4 = __emu_AvailableTaskData2->unknown4; + + __emu_Ptr += sizeof(AvailableTaskData2_Struct); + __eq_ptr += sizeof(structs::AvailableTaskData2_Struct); + + strcpy(__eq_ptr, __emu_Ptr); // Unknown string + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + + strcpy(__eq_ptr, __emu_Ptr); // Unknown string + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + + __emu_AvailableTaskTrailer = (AvailableTaskTrailer_Struct*)__emu_Ptr; + __eq_AvailableTaskTrailer = (structs::AvailableTaskTrailer_Struct*)__eq_ptr; + + __eq_AvailableTaskTrailer->ItemCount = __emu_AvailableTaskTrailer->ItemCount; + __eq_AvailableTaskTrailer->unknown1 = __emu_AvailableTaskTrailer->unknown1; + __eq_AvailableTaskTrailer->unknown2 = __emu_AvailableTaskTrailer->unknown2; + __eq_AvailableTaskTrailer->StartZone = __emu_AvailableTaskTrailer->StartZone; + + __emu_Ptr += sizeof(AvailableTaskTrailer_Struct); + __eq_ptr += sizeof(structs::AvailableTaskTrailer_Struct); + + strcpy(__eq_ptr, __emu_Ptr); // Unknown string + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + */ + + ENCODE(OP_PetBuffWindow) + { + // The format of the RoF2 packet is identical to the OP_BuffCreate packet. + + SETUP_VAR_ENCODE(PetBuff_Struct); + + uint32 sz = 12 + (17 * emu->buffcount); + __packet->size = sz; + __packet->pBuffer = new unsigned char[sz]; + memset(__packet->pBuffer, 0, sz); + + __packet->WriteUInt32(emu->petid); + __packet->WriteUInt32(0); // PlayerID ? + __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) + { + if (emu->spellid[i]) + { + __packet->WriteUInt32(i); + __packet->WriteUInt32(emu->spellid[i]); + __packet->WriteUInt32(emu->ticsremaining[i]); + __packet->WriteUInt32(0); // Unknown + __packet->WriteString(""); + } + } + __packet->WriteUInt8(0); // Unknown + + FINISH_ENCODE(); + } + + ENCODE(OP_PlayerProfile) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + PlayerProfile_Struct *emu = (PlayerProfile_Struct *)__emu_buffer; + + uint32 PacketSize = 40000; // Calculate this later + + EQApplicationPacket *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 + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + + outapp->WriteUInt8(emu->gender); // Gender + outapp->WriteUInt32(emu->race); // Race + outapp->WriteUInt8(emu->class_); // Class + outapp->WriteUInt8(emu->level); // Level + outapp->WriteUInt8(emu->level); // Level1 + + + outapp->WriteUInt32(5); // Bind count + + for (int r = 0; r < 5; r++) + { + outapp->WriteUInt32(emu->binds[r].zoneId); + outapp->WriteFloat(emu->binds[r].x); + outapp->WriteFloat(emu->binds[r].y); + outapp->WriteFloat(emu->binds[r].z); + outapp->WriteFloat(emu->binds[r].heading); + } + + outapp->WriteUInt32(emu->deity); + outapp->WriteUInt32(emu->intoxication); + + outapp->WriteUInt32(10); // Unknown count + + for (int r = 0; r < 10; r++) + { + outapp->WriteUInt32(0); // Unknown + } + + outapp->WriteUInt32(22); // Equipment count + + for (int r = 0; r < 9; r++) + { + outapp->WriteUInt32(emu->item_material[r]); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + // Write zeroes for the next 13 equipment slots + + for (int r = 0; r < 13; r++) + { + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(9); // Equipment2 count + + for (int r = 0; r < 9; r++) + { + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(9); // Tint Count + + for (int r = 0; r < 7; r++) + { + outapp->WriteUInt32(emu->item_tint[r].color); + } + // Write zeroes for extra two tint values + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + + outapp->WriteUInt32(9); // Tint2 Count + + for (int r = 0; r < 7; r++) + { + outapp->WriteUInt32(emu->item_tint[r].color); + } + // Write zeroes for extra two tint values + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + + outapp->WriteUInt8(emu->haircolor); + outapp->WriteUInt8(emu->beardcolor); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt8(emu->eyecolor1); + outapp->WriteUInt8(emu->eyecolor2); + outapp->WriteUInt8(emu->hairstyle); + outapp->WriteUInt8(emu->beard); + outapp->WriteUInt8(emu->face); + + // Think there should be an extra byte before the drakkin stuff (referred to as oldface in client) + // Then one of the five bytes following the drakkin stuff needs removing. + + outapp->WriteUInt32(emu->drakkin_heritage); + outapp->WriteUInt32(emu->drakkin_tattoo); + outapp->WriteUInt32(emu->drakkin_details); + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteFloat(5.0f); // Height ? + + outapp->WriteFloat(3.0f); // Unknown + outapp->WriteFloat(2.5f); // Unknown + outapp->WriteFloat(5.5f); // Unknown + + outapp->WriteUInt32(0); // Primary ? + outapp->WriteUInt32(0); // Secondary ? + + outapp->WriteUInt32(emu->points); // Unspent skill points + outapp->WriteUInt32(emu->mana); + outapp->WriteUInt32(emu->cur_hp); + + outapp->WriteUInt32(emu->STR); + outapp->WriteUInt32(emu->STA); + outapp->WriteUInt32(emu->CHA); + outapp->WriteUInt32(emu->DEX); + outapp->WriteUInt32(emu->INT); + outapp->WriteUInt32(emu->AGI); + outapp->WriteUInt32(emu->WIS); + + 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 + + outapp->WriteUInt32(300); // AA Count + + for (uint32 r = 0; r < MAX_PP_AA_ARRAY; r++) + { + outapp->WriteUInt32(emu->aa_array[r].AA); + outapp->WriteUInt32(emu->aa_array[r].value); + outapp->WriteUInt32(0); + } + + // Fill the other 60 AAs with zeroes + + for (uint32 r = 0; r < structs::MAX_PP_AA_ARRAY - MAX_PP_AA_ARRAY; r++) + { + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(structs::MAX_PP_SKILL); + + for (uint32 r = 0; r < structs::MAX_PP_SKILL; r++) + { + outapp->WriteUInt32(emu->skills[r]); + } + + // deprecated + // Write zeroes for the rest of the skills + /* + for(uint32 r = 0; r < structs::MAX_PP_SKILL - MAX_PP_SKILL; r++) + { + outapp->WriteUInt32(emu->skills[r]); + } + */ + + outapp->WriteUInt32(25); // Unknown count + + for (uint32 r = 0; r < 25; r++) + { + outapp->WriteUInt32(0); // Unknown + } + + outapp->WriteUInt32(structs::MAX_PP_DISCIPLINES); // Discipline count + + for (uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) + { + outapp->WriteUInt32(emu->disciplines.values[r]); + } + + // Write zeroes for the rest of the disciplines + for (uint32 r = 0; r < structs::MAX_PP_DISCIPLINES - MAX_PP_DISCIPLINES; r++) + { + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(20); // Timestamp count + + for (uint32 r = 0; r < 20; r++) + { + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(MAX_RECAST_TYPES); // Timestamp count + + for (uint32 r = 0; r < MAX_RECAST_TYPES; r++) + { + outapp->WriteUInt32(emu->recastTimers[r]); + } + + outapp->WriteUInt32(100); // Timestamp2 count + + for (uint32 r = 0; r < 100; r++) + { + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(structs::MAX_PP_SPELLBOOK); // Spellbook slots + + for (uint32 r = 0; r < MAX_PP_SPELLBOOK; r++) + { + outapp->WriteUInt32(emu->spell_book[r]); + } + // zeroes for the rest of the spellbook slots + for (uint32 r = 0; r < structs::MAX_PP_SPELLBOOK - MAX_PP_SPELLBOOK; r++) + { + outapp->WriteUInt32(0xFFFFFFFFU); + } + + outapp->WriteUInt32(structs::MAX_PP_MEMSPELL); // Memorised spell slots + + for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) + { + outapp->WriteUInt32(emu->mem_spells[r]); + } + // zeroes for the rest of the slots + for (uint32 r = 0; r < structs::MAX_PP_MEMSPELL - MAX_PP_MEMSPELL; r++) + { + outapp->WriteUInt32(0xFFFFFFFFU); + } + + outapp->WriteUInt32(13); // Unknown count + + for (uint32 r = 0; r < 13; r++) + { + outapp->WriteUInt32(0); // Unknown + } + + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(structs::BUFF_COUNT); + + //*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*/ uint32 duration; + //*018*/ uint8 level; + //*019*/ uint32 spellid; + //*023*/ uint32 counters; + //*027*/ uint8 unknown0028[53]; + //*080*/ + + for (uint32 r = 0; r < BUFF_COUNT; r++) + { + float instrument_mod = 0.0f; + uint8 slotid = emu->buffs[r].slotid; + 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; + player_id = 0x000717fd; + } + else + { + slotid = 0; + } + outapp->WriteUInt8(0); // Had this as slot, but always appears to be 0 on live. + 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->WriteUInt32(0); + outapp->WriteUInt8(0); + outapp->WriteUInt32(emu->buffs[r].counters); // Appears twice ? + + for (uint32 j = 0; j < 44; ++j) + outapp->WriteUInt8(0); // Unknown + } + + for (uint32 r = 0; r < structs::BUFF_COUNT - BUFF_COUNT; r++) + { + // 80 bytes of zeroes + for (uint32 j = 0; j < 20; ++j) + outapp->WriteUInt32(0); + + } + + outapp->WriteUInt32(emu->platinum); + outapp->WriteUInt32(emu->gold); + outapp->WriteUInt32(emu->silver); + outapp->WriteUInt32(emu->copper); + + outapp->WriteUInt32(emu->platinum_cursor); + outapp->WriteUInt32(emu->gold_cursor); + outapp->WriteUInt32(emu->silver_cursor); + outapp->WriteUInt32(emu->copper_cursor); + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(0); // This is the cooldown timer for the monk 'Mend' skill. Client will add 6 minutes to this value the first time the + // player logs in. After that it will honour whatever value we send here. + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(emu->thirst_level); + outapp->WriteUInt32(emu->hunger_level); + + outapp->WriteUInt32(emu->aapoints_spent); + + outapp->WriteUInt32(5); // AA Points count ?? + outapp->WriteUInt32(1234); // AA Points assigned + outapp->WriteUInt32(0); // AA Points in General ? + outapp->WriteUInt32(0); // AA Points in Class ? + outapp->WriteUInt32(0); // AA Points in Archetype ? + outapp->WriteUInt32(0); // AA Points in Special ? + outapp->WriteUInt32(emu->aapoints); // AA Points unspent + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(structs::MAX_PLAYER_BANDOLIER); + + for (uint32 r = 0; r < EmuConstants::BANDOLIERS_COUNT; r++) + { + outapp->WriteString(emu->bandoliers[r].name); + + for (uint32 j = 0; j < EmuConstants::BANDOLIER_SIZE; ++j) + { + outapp->WriteString(emu->bandoliers[r].items[j].item_name); + outapp->WriteUInt32(emu->bandoliers[r].items[j].item_id); + outapp->WriteUInt32(emu->bandoliers[r].items[j].icon); + } + } + + for (uint32 r = 0; r < structs::MAX_PLAYER_BANDOLIER - EmuConstants::BANDOLIERS_COUNT; r++) + { + outapp->WriteString(""); + + for (uint32 j = 0; j < EmuConstants::BANDOLIER_SIZE; ++j) + { + outapp->WriteString(""); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + } + + outapp->WriteUInt32(structs::MAX_POTIONS_IN_BELT); + + for (uint32 r = 0; r < EmuConstants::POTION_BELT_SIZE; r++) + { + outapp->WriteString(emu->potionbelt.items[r].item_name); + outapp->WriteUInt32(emu->potionbelt.items[r].item_id); + outapp->WriteUInt32(emu->potionbelt.items[r].icon); + } + + for (uint32 r = 0; r < structs::MAX_POTIONS_IN_BELT - EmuConstants::POTION_BELT_SIZE; r++) + { + outapp->WriteString(""); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + outapp->WriteSInt32(-1); // Unknown; + outapp->WriteSInt32(123); // HP Total ? + 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 + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(20); // Unknown - Expansion count ? + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->endurance); + outapp->WriteUInt32(0); // Unknown - Observed 0x7cde - This is also seen in guild packets sent to this character. + outapp->WriteUInt32(0); // Unknown - Observed 0x64 + + outapp->WriteUInt32(64); // Name Length + + uint32 CurrentPosition = outapp->GetWritePosition(); + + outapp->WriteString(emu->name); + + outapp->SetWritePosition(CurrentPosition + 64); + + outapp->WriteUInt32(32); // Last Name Length + + CurrentPosition = outapp->GetWritePosition(); + + outapp->WriteString(emu->last_name); + + outapp->SetWritePosition(CurrentPosition + 32); + + outapp->WriteUInt32(emu->birthday); + outapp->WriteUInt32(emu->birthday); // Account start date ? + outapp->WriteUInt32(emu->lastlogin); + outapp->WriteUInt32(emu->timePlayedMin); + outapp->WriteUInt32(emu->timeentitledonaccount); + outapp->WriteUInt32(0x0007ffff); // Expansion bitmask + + outapp->WriteUInt32(structs::MAX_PP_LANGUAGE); + + for (uint32 r = 0; r < MAX_PP_LANGUAGE; r++) + { + outapp->WriteUInt8(emu->languages[r]); + } + + for (uint32 r = 0; r < structs::MAX_PP_LANGUAGE - MAX_PP_LANGUAGE; r++) + { + outapp->WriteUInt8(0); + } + + outapp->WriteUInt16(emu->zone_id); + outapp->WriteUInt16(emu->zoneInstance); + + outapp->WriteFloat(emu->y); + outapp->WriteFloat(emu->x); + outapp->WriteFloat(emu->z); + outapp->WriteFloat(emu->heading); + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(emu->pvp); + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(emu->gm); + + outapp->WriteUInt32(emu->guild_id); + outapp->WriteUInt8(0); // Unknown - observed 1 in a live packet. + outapp->WriteUInt32(0); // Unknown - observed 1 in a live packet. + outapp->WriteUInt8(0); // Unknown - observed 1 in a live packet. + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt64(emu->exp); + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(emu->platinum_bank); + outapp->WriteUInt32(emu->gold_bank); + outapp->WriteUInt32(emu->silver_bank); + outapp->WriteUInt32(emu->copper_bank); + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(42); // The meaning of life ? + + for (uint32 r = 0; r < 42; r++) + { + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + } + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(emu->career_tribute_points); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->tribute_points); + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(EmuConstants::TRIBUTE_SIZE); + + for (uint32 r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) + { + outapp->WriteUInt32(emu->tributes[r].tribute); + outapp->WriteUInt32(emu->tributes[r].tier); + } + + outapp->WriteUInt32(10); // Guild Tribute Count ? + + for (uint32 r = 0; r < 10; r++) + { + outapp->WriteUInt32(0xffffffff); + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + // Block of 121 unknown bytes + for (uint32 r = 0; r < 121; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->currentRadCrystals); + outapp->WriteUInt32(emu->careerRadCrystals); + outapp->WriteUInt32(emu->currentEbonCrystals); + outapp->WriteUInt32(emu->careerEbonCrystals); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + // Unknown String ? + outapp->WriteUInt32(64); // Unknown + for (uint32 r = 0; r < 64; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + // Unknown String ? + outapp->WriteUInt32(64); // Unknown + for (uint32 r = 0; r < 64; r++) + outapp->WriteUInt8(0); // Unknown + + // Unknown String ? + outapp->WriteUInt32(64); // Unknown + for (uint32 r = 0; r < 64; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + // Block of 320 unknown bytes + for (uint32 r = 0; r < 320; r++) + outapp->WriteUInt8(0); // Unknown + + // Block of 343 unknown bytes + for (uint32 r = 0; r < 343; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(emu->leadAAActive); + + outapp->WriteUInt32(6); // Count ... of LDoN stats ? + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->ldon_points_guk); + outapp->WriteUInt32(emu->ldon_points_mir); + outapp->WriteUInt32(emu->ldon_points_mmc); + outapp->WriteUInt32(emu->ldon_points_ruj); + outapp->WriteUInt32(emu->ldon_points_tak); + + outapp->WriteUInt32(emu->ldon_points_available); + + outapp->WriteDouble(emu->group_leadership_exp); + outapp->WriteDouble(emu->raid_leadership_exp); + + outapp->WriteUInt32(emu->group_leadership_points); + outapp->WriteUInt32(emu->raid_leadership_points); + + outapp->WriteUInt32(64); // Group of 64 int32s follow Group/Raid Leadership abilities ? + + for (uint32 r = 0; r < MAX_LEADERSHIP_AA_ARRAY; r++) + outapp->WriteUInt32(emu->leader_abilities.ranks[r]); + + for (uint32 r = 0; r < 64 - MAX_LEADERSHIP_AA_ARRAY; r++) + outapp->WriteUInt32(0); // Unused/unsupported Leadership abilities + + outapp->WriteUInt32(emu->air_remaining); // ? + + // PVP Stats + + outapp->WriteUInt32(emu->PVPKills); + outapp->WriteUInt32(emu->PVPDeaths); + outapp->WriteUInt32(emu->PVPCurrentPoints); + outapp->WriteUInt32(emu->PVPCareerPoints); + outapp->WriteUInt32(emu->PVPBestKillStreak); + outapp->WriteUInt32(emu->PVPWorstDeathStreak); + outapp->WriteUInt32(emu->PVPCurrentKillStreak); + + // Last PVP Kill + + outapp->WriteString(emu->PVPLastKill.Name); + outapp->WriteUInt32(emu->PVPLastKill.Level); + outapp->WriteUInt32(emu->PVPLastKill.Race); + outapp->WriteUInt32(emu->PVPLastKill.Class); + outapp->WriteUInt32(emu->PVPLastKill.Zone); + outapp->WriteUInt32(emu->PVPLastKill.Time); + outapp->WriteUInt32(emu->PVPLastKill.Points); + + // Last PVP Death + + outapp->WriteString(emu->PVPLastDeath.Name); + outapp->WriteUInt32(emu->PVPLastDeath.Level); + outapp->WriteUInt32(emu->PVPLastDeath.Race); + outapp->WriteUInt32(emu->PVPLastDeath.Class); + outapp->WriteUInt32(emu->PVPLastDeath.Zone); + outapp->WriteUInt32(emu->PVPLastDeath.Time); + outapp->WriteUInt32(emu->PVPLastDeath.Points); + + outapp->WriteUInt32(emu->PVPNumberOfKillsInLast24Hours); + + // Last 50 Kills + outapp->WriteUInt32(50); + for (uint32 r = 0; r < 50; ++r) + { + outapp->WriteString(emu->PVPRecentKills[r].Name); + outapp->WriteUInt32(emu->PVPRecentKills[r].Level); + outapp->WriteUInt32(emu->PVPRecentKills[r].Race); + outapp->WriteUInt32(emu->PVPRecentKills[r].Class); + outapp->WriteUInt32(emu->PVPRecentKills[r].Zone); + outapp->WriteUInt32(emu->PVPRecentKills[r].Time); + outapp->WriteUInt32(emu->PVPRecentKills[r].Points); + } + + outapp->WriteUInt32(emu->expAA); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(emu->groupAutoconsent); + outapp->WriteUInt8(emu->raidAutoconsent); + outapp->WriteUInt8(emu->guildAutoconsent); + + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(emu->level); // Level3 ? + + outapp->WriteUInt8(emu->showhelm); + + outapp->WriteUInt32(emu->RestTimer); + + outapp->WriteUInt32(1024); // Unknown Count + + // Block of 1024 unknown bytes + outapp->WriteUInt8(31); // Unknown + + for (uint32 r = 0; r < 1023; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + // Think we need 1 byte of padding at the end + + outapp->WriteUInt8(0); // Unknown + + _log(NET__STRUCTS, "Player Profile Packet is %i bytes", outapp->GetWritePosition()); + + unsigned char *NewBuffer = new unsigned char[outapp->GetWritePosition()]; + memcpy(NewBuffer, outapp->pBuffer, outapp->GetWritePosition()); + safe_delete_array(outapp->pBuffer); + outapp->pBuffer = NewBuffer; + outapp->size = outapp->GetWritePosition(); + outapp->SetWritePosition(4); + outapp->WriteUInt32(outapp->size - 9); + + CRC32::SetEQChecksum(outapp->pBuffer, outapp->size - 1, 8); + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + return; + } + + ENCODE(OP_RaidJoin) + { + EQApplicationPacket *inapp = *p; + 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)); + structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer; + + general->action = 8; + general->parameter = 1; + strn0cpy(general->leader_name, raid_create->leader_name, 64); + strn0cpy(general->player_name, raid_create->leader_name, 64); + + dest->FastQueuePacket(&outapp_create); + delete[] __emu_buffer; + } + + ENCODE(OP_RaidUpdate) + { + EQApplicationPacket *inapp = *p; + *p = nullptr; + unsigned char * __emu_buffer = inapp->pBuffer; + RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer; + + if (raid_gen->action == 0) // raid add has longer length than other raid updates + { + RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; + + EQApplicationPacket *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; + add_member->raidGen.parameter = in_add_member->raidGen.parameter; + strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64); + strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64); + add_member->_class = in_add_member->_class; + add_member->level = in_add_member->level; + add_member->isGroupLeader = in_add_member->isGroupLeader; + add_member->flags[0] = in_add_member->flags[0]; + add_member->flags[1] = in_add_member->flags[1]; + add_member->flags[2] = in_add_member->flags[2]; + add_member->flags[3] = in_add_member->flags[3]; + add_member->flags[4] = in_add_member->flags[4]; + dest->FastQueuePacket(&outapp); + } + 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); + structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer; + + outmotd->general.action = inmotd->general.action; + strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64); + strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1); + dest->FastQueuePacket(&outapp); + } + 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)); + structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer; + + outlaa->action = inlaa->action; + strn0cpy(outlaa->player_name, inlaa->player_name, 64); + strn0cpy(outlaa->leader_name, inlaa->leader_name, 64); + memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct)); + dest->FastQueuePacket(&outapp); + } + else + { + RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer; + + EQApplicationPacket *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); + raid_general->action = in_raid_general->action; + raid_general->parameter = in_raid_general->parameter; + dest->FastQueuePacket(&outapp); + } + + delete[] __emu_buffer; + } + + ENCODE(OP_ReadBook) + { + ENCODE_LENGTH_ATLEAST(BookText_Struct); + SETUP_DIRECT_ENCODE(BookText_Struct, structs::BookRequest_Struct); + + if (emu->window == 0xFF) + eq->window = 0xFFFFFFFF; + else + eq->window = emu->window; + OUT(type); + OUT(invslot); + strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); + + FINISH_ENCODE(); + } + + ENCODE(OP_RecipeAutoCombine) + { + ENCODE_LENGTH_EXACT(RecipeAutoCombine_Struct); + SETUP_DIRECT_ENCODE(RecipeAutoCombine_Struct, structs::RecipeAutoCombine_Struct); + + OUT(object_type); + OUT(some_id); + eq->container_slot = ServerToRoF2Slot(emu->unknown1); + structs::ItemSlotStruct RoF2Slot; + RoF2Slot.SlotType = 8; // Observed + RoF2Slot.Unknown02 = 0; + RoF2Slot.MainSlot = 0xffff; + RoF2Slot.SubSlot = 0xffff; + RoF2Slot.AugSlot = 0xffff; + RoF2Slot.Unknown01 = 0; + eq->unknown_slot = RoF2Slot; + OUT(recipe_id); + OUT(reply_code); + + FINISH_ENCODE(); + } + + ENCODE(OP_RemoveBlockedBuffs) { ENCODE_FORWARD(OP_BlockedBuffs); } + + ENCODE(OP_RequestClientZoneChange) + { + ENCODE_LENGTH_EXACT(RequestClientZoneChange_Struct); + SETUP_DIRECT_ENCODE(RequestClientZoneChange_Struct, structs::RequestClientZoneChange_Struct); + + OUT(zone_id); + OUT(instance_id); + OUT(y); + OUT(x); + OUT(z); + OUT(heading); + eq->type = 0x0b; + eq->unknown004 = 0xffffffff; + eq->unknown172 = 0x0168b500; + + FINISH_ENCODE(); + } + + ENCODE(OP_RespondAA) + { + SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); + + 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->aa_spent_general = 0; + eq->aa_spent_archetype = 0; + eq->aa_spent_class = 0; + eq->aa_spent_special = 0; + + 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; + } + + FINISH_ENCODE(); + } + + ENCODE(OP_RezzRequest) + { + SETUP_DIRECT_ENCODE(Resurrect_Struct, structs::Resurrect_Struct); + + OUT(zone_id); + OUT(instance_id); + OUT(y); + OUT(x); + OUT(z); + OUT_str(your_name); + OUT_str(rezzer_name); + OUT(spellid); + OUT_str(corpse_name); + OUT(action); + + FINISH_ENCODE(); + } + + 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)); + + // 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) + { + 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->unknown037 = 1; // Introduced during HoT + OUT(prereq_skill); + eq->unknown045 = 1; // New Mar 21 2012 - Seen 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); + 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); + } + } + + _hex(NET__ERROR, eq, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + + FINISH_ENCODE(); + } + + ENCODE(OP_SendCharInfo) + { + ENCODE_LENGTH_EXACT(CharacterSelect_Struct); + SETUP_VAR_ENCODE(CharacterSelect_Struct); + + //EQApplicationPacket *packet = *p; + //const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer; + + int char_count; + int namelen = 0; + for (char_count = 0; char_count < 10; char_count++) { + if (emu->name[char_count][0] == '\0') + break; + if (strcmp(emu->name[char_count], "") == 0) + break; + namelen += strlen(emu->name[char_count]); + } + + int total_length = sizeof(structs::CharacterSelect_Struct) + + char_count * sizeof(structs::CharacterSelectEntry_Struct) + + namelen; + + ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length); + + //unsigned char *eq_buffer = new unsigned char[total_length]; + //structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer; + + eq->char_count = char_count; + //eq->total_chars = 10; + + unsigned char *bufptr = (unsigned char *)eq->entries; + int r; + for (r = 0; r < char_count; r++) { + { //pre-name section... + structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr; + memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1); + } + //adjust for name. + bufptr += strlen(emu->name[r]); + { //post-name section... + structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr; + eq2->class_ = emu->class_[r]; + eq2->race = emu->race[r]; + eq2->level = emu->level[r]; + eq2->class_2 = emu->class_[r]; + eq2->race2 = emu->race[r]; + eq2->zone = emu->zone[r]; + eq2->instance = 0; + eq2->gender = emu->gender[r]; + eq2->face = emu->face[r]; + int k; + for (k = 0; k < _MaterialCount; k++) { + eq2->equip[k].equip0 = emu->equip[r][k]; + eq2->equip[k].equip1 = 0; + eq2->equip[k].equip2 = 0; + eq2->equip[k].itemid = 0; + eq2->equip[k].equip3 = emu->equip[r][k]; + eq2->equip[k].color.color = emu->cs_colors[r][k].color; + } + eq2->u15 = 0xff; + eq2->u19 = 0xFF; + eq2->drakkin_tattoo = emu->drakkin_tattoo[r]; + eq2->drakkin_details = emu->drakkin_details[r]; + eq2->deity = emu->deity[r]; + eq2->primary = emu->primary[r]; + eq2->secondary = emu->secondary[r]; + eq2->haircolor = emu->haircolor[r]; + eq2->beardcolor = emu->beardcolor[r]; + eq2->eyecolor1 = emu->eyecolor1[r]; + eq2->eyecolor2 = emu->eyecolor2[r]; + eq2->hairstyle = emu->hairstyle[r]; + eq2->beard = emu->beard[r]; + eq2->char_enabled = 1; + eq2->tutorial = emu->tutorial[r]; + eq2->drakkin_heritage = emu->drakkin_heritage[r]; + eq2->unknown1 = 0; + eq2->gohome = emu->gohome[r]; + eq2->LastLogin = 1212696584; + eq2->unknown2 = 0; + } + bufptr += sizeof(structs::CharacterSelectEntry_Struct); + } + + FINISH_ENCODE(); + } + + ENCODE(OP_SendMembership) + { + ENCODE_LENGTH_EXACT(Membership_Struct); + SETUP_DIRECT_ENCODE(Membership_Struct, structs::Membership_Struct); + + eq->membership = emu->membership; + eq->races = emu->races; + eq->classes = emu->classes; + eq->entrysize = 22; + for (int i = 0; i<21; i++) + { + eq->entries[i] = emu->entries[i]; + } + eq->entries[21] = 0; + + FINISH_ENCODE(); + } + + ENCODE(OP_SendZonepoints) + { + SETUP_VAR_ENCODE(ZonePoints); + ALLOC_VAR_ENCODE(structs::ZonePoints, sizeof(structs::ZonePoints) + sizeof(structs::ZonePoint_Entry) * (emu->count + 1)); + + eq->count = emu->count; + for (uint32 i = 0; i < emu->count; ++i) + { + eq->zpe[i].iterator = emu->zpe[i].iterator; + eq->zpe[i].x = emu->zpe[i].x; + eq->zpe[i].y = emu->zpe[i].y; + eq->zpe[i].z = emu->zpe[i].z; + eq->zpe[i].heading = emu->zpe[i].heading; + eq->zpe[i].zoneid = emu->zpe[i].zoneid; + eq->zpe[i].zoneinstance = emu->zpe[i].zoneinstance; + } + + FINISH_ENCODE(); + } + + ENCODE(OP_SetGuildRank) + { + ENCODE_LENGTH_EXACT(GuildSetRank_Struct); + SETUP_DIRECT_ENCODE(GuildSetRank_Struct, structs::GuildSetRank_Struct); + + eq->GuildID = emu->Unknown00; + + /* Translate older ranks to new values */ + 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 + default: { eq->Rank = emu->Rank; break; } + } + + memcpy(eq->MemberName, emu->MemberName, sizeof(eq->MemberName)); + OUT(Banker); + eq->Unknown76 = 1; + + FINISH_ENCODE(); + } + + ENCODE(OP_ShopPlayerBuy) + { + ENCODE_LENGTH_EXACT(Merchant_Sell_Struct); + SETUP_DIRECT_ENCODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct); + + OUT(npcid); + OUT(playerid); + OUT(itemslot); + OUT(quantity); + OUT(price); + + FINISH_ENCODE(); + } + + ENCODE(OP_ShopPlayerSell) + { + ENCODE_LENGTH_EXACT(Merchant_Purchase_Struct); + SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); + + OUT(npcid); + eq->itemslot = ServerToRoF2MainInvSlot(emu->itemslot); + //OUT(itemslot); + OUT(quantity); + OUT(price); + + FINISH_ENCODE(); + } + + ENCODE(OP_ShopRequest) + { + ENCODE_LENGTH_EXACT(Merchant_Click_Struct); + SETUP_DIRECT_ENCODE(Merchant_Click_Struct, structs::Merchant_Click_Struct); + + OUT(npcid); + OUT(playerid); + OUT(command); + OUT(rate); + eq->unknown01 = 3; // Not sure what these values do yet, but list won't display without them + eq->unknown02 = 2592000; + + FINISH_ENCODE(); + } + + ENCODE(OP_SkillUpdate) + { + ENCODE_LENGTH_EXACT(SkillUpdate_Struct); + SETUP_DIRECT_ENCODE(SkillUpdate_Struct, structs::SkillUpdate_Struct); + + OUT(skillId); + OUT(value); + eq->unknown08 = 1; // Observed + eq->unknown09 = 80; // Observed + eq->unknown10 = 136; // Observed + eq->unknown11 = 54; // Observed + + FINISH_ENCODE(); + } + + ENCODE(OP_SomeItemPacketMaybe) + { + // This Opcode is not named very well. It is used for the animation of arrows leaving the player's bow + // and flying to the target. + // + + ENCODE_LENGTH_EXACT(Arrow_Struct); + SETUP_DIRECT_ENCODE(Arrow_Struct, structs::Arrow_Struct); + + OUT(src_y); + OUT(src_x); + OUT(src_z); + OUT(velocity); + OUT(launch_angle); + OUT(tilt); + OUT(arc); + OUT(source_id); + OUT(target_id); + OUT(item_id); + + eq->unknown070 = 175; // This needs to be set to something, else we get a 1HS animation instead of ranged. + + OUT(item_type); + OUT(skill); + + strncpy(eq->model_name, emu->model_name, sizeof(eq->model_name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_SpawnAppearance) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *emu_buffer = in->pBuffer; + + SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer; + + if (sas->type != AT_Size) + { + dest->FastQueuePacket(&in, ack_req); + return; + } + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct)); + + ChangeSize_Struct *css = (ChangeSize_Struct *)outapp->pBuffer; + + css->EntityID = sas->spawn_id; + css->Size = (float)sas->parameter; + css->Unknown08 = 0; + css->Unknown12 = 1.0f; + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_SpawnDoor) + { + SETUP_VAR_ENCODE(Door_Struct); + int door_count = __packet->size / sizeof(Door_Struct); + int total_length = door_count * sizeof(structs::Door_Struct); + ALLOC_VAR_ENCODE(structs::Door_Struct, total_length); + + int r; + for (r = 0; r < door_count; r++) { + strncpy(eq[r].name, emu[r].name, sizeof(eq[r].name)); + eq[r].xPos = emu[r].xPos; + eq[r].yPos = emu[r].yPos; + eq[r].zPos = emu[r].zPos; + eq[r].heading = emu[r].heading; + eq[r].incline = emu[r].incline; + eq[r].size = emu[r].size; + eq[r].doorId = emu[r].doorId; + eq[r].opentype = emu[r].opentype; + eq[r].state_at_spawn = emu[r].state_at_spawn; + eq[r].invert_state = emu[r].invert_state; + eq[r].door_param = emu[r].door_param; + eq[r].unknown0080 = 0; + eq[r].unknown0081 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0082 = 0; + eq[r].unknown0083 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0084 = 0; + eq[r].unknown0085 = 0; + eq[r].unknown0086 = 0; + } + + FINISH_ENCODE(); + } + + ENCODE(OP_Stun) + { + ENCODE_LENGTH_EXACT(Stun_Struct); + SETUP_DIRECT_ENCODE(Stun_Struct, structs::Stun_Struct); + + OUT(duration); + eq->unknown005 = 163; + eq->unknown006 = 67; + + FINISH_ENCODE(); + } + + ENCODE(OP_TargetBuffs) { ENCODE_FORWARD(OP_BuffCreate); } + + ENCODE(OP_TaskDescription) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_TaskDescription, in->size + 1); + // Set the Write pointer as we don't know what has been done with the packet before we get it. + in->SetReadPosition(0); + // Copy the header + for (int i = 0; i < 5; ++i) + outapp->WriteUInt32(in->ReadUInt32()); + + // Copy Title + while (uint8 c = in->ReadUInt8()) + outapp->WriteUInt8(c); + outapp->WriteUInt8(0); + + outapp->WriteUInt32(in->ReadUInt32()); // Duration + outapp->WriteUInt32(in->ReadUInt32()); // Unknown + uint32 StartTime = in->ReadUInt32(); + outapp->WriteUInt32(time(nullptr) - StartTime); // RoF2 has elapsed time here rather than starttime + + // Copy the rest of the packet verbatim + uint32 BytesLeftToCopy = in->size - in->GetReadPosition(); + memcpy(outapp->pBuffer + outapp->GetWritePosition(), in->pBuffer + in->GetReadPosition(), BytesLeftToCopy); + + delete in; + dest->FastQueuePacket(&outapp, ack_req); + } + + ENCODE(OP_TaskHistoryReply) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + // First we need to calculate the length of the new packet + in->SetReadPosition(4); + uint32 ActivityCount = in->ReadUInt32(); + + uint32 Text1Length = 0; + uint32 Text2Length = 0; + uint32 Text3Length = 0; + + uint32 OutboundPacketSize = 8; + + for (uint32 i = 0; i < ActivityCount; ++i) + { + Text1Length = 0; + Text2Length = 0; + Text3Length = 0; + + in->ReadUInt32(); // Activity type + + // Skip past Text1 + while (in->ReadUInt8()) + ++Text1Length; + + // Skip past Text2 + while (in->ReadUInt8()) + ++Text2Length; + + in->ReadUInt32(); + in->ReadUInt32(); + in->ReadUInt32(); + uint32 ZoneID = in->ReadUInt32(); + in->ReadUInt32(); + + // Skip past Text3 + while (in->ReadUInt8()) + ++Text3Length; + + char ZoneNumber[10]; + + sprintf(ZoneNumber, "%i", ZoneID); + + OutboundPacketSize += (24 + Text1Length + 1 + Text2Length + Text3Length + 1 + 7 + (strlen(ZoneNumber) * 2)); + } + + in->SetReadPosition(0); + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_TaskHistoryReply, OutboundPacketSize); + + outapp->WriteUInt32(in->ReadUInt32()); // Task index + outapp->WriteUInt32(in->ReadUInt32()); // Activity count + + for (uint32 i = 0; i < ActivityCount; ++i) + { + Text1Length = 0; + Text2Length = 0; + Text3Length = 0; + + outapp->WriteUInt32(in->ReadUInt32()); // ActivityType + + // Copy Text1 + while (uint8 c = in->ReadUInt8()) + outapp->WriteUInt8(c); + + outapp->WriteUInt8(0); // Text1 has a null terminator + + uint32 CurrentPosition = in->GetReadPosition(); + + // Determine Length of Text2 + while (in->ReadUInt8()) + ++Text2Length; + + outapp->WriteUInt32(Text2Length); + + in->SetReadPosition(CurrentPosition); + + // Copy Text2 + while (uint8 c = in->ReadUInt8()) + outapp->WriteUInt8(c); + + outapp->WriteUInt32(in->ReadUInt32()); // Goalcount + in->ReadUInt32(); + in->ReadUInt32(); + uint32 ZoneID = in->ReadUInt32(); + in->ReadUInt32(); + + char ZoneNumber[10]; + + sprintf(ZoneNumber, "%i", ZoneID); + + outapp->WriteUInt32(2); + outapp->WriteUInt8(0x2d); // "-" + outapp->WriteUInt8(0x31); // "1" + + outapp->WriteUInt32(2); + outapp->WriteUInt8(0x2d); // "-" + outapp->WriteUInt8(0x31); // "1" + outapp->WriteString(ZoneNumber); + + outapp->WriteUInt32(0); + + // Copy Tex3t + while (uint8 c = in->ReadUInt8()) + outapp->WriteUInt8(c); + + outapp->WriteUInt8(0); // Text3 has a null terminator + + outapp->WriteUInt8(0x31); // "1" + outapp->WriteString(ZoneNumber); + } + + delete in; + dest->FastQueuePacket(&outapp, ack_req); + } + + ENCODE(OP_Track) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + Track_Struct *emu = (Track_Struct *)__emu_buffer; + + int EntryCount = in->size / sizeof(Track_Struct); + + if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0) + { + _log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct)); + delete in; + return; + } + + int PacketSize = 2; + + for (int i = 0; i < EntryCount; ++i, ++emu) + PacketSize += (12 + strlen(emu->name)); + + emu = (Track_Struct *)__emu_buffer; + + in->size = PacketSize; + in->pBuffer = new unsigned char[in->size]; + + char *Buffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, EntryCount); + + for (int i = 0; i < EntryCount; ++i, ++emu) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->entityid); + VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->distance); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + VARSTRUCT_ENCODE_STRING(Buffer, emu->name); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->GroupMember); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_Trader) + { + if ((*p)->size == sizeof(ClickTrader_Struct)) + { + ENCODE_LENGTH_EXACT(ClickTrader_Struct); + SETUP_DIRECT_ENCODE(ClickTrader_Struct, structs::ClickTrader_Struct); + + eq->Code = emu->Code; + // Live actually has 200 items now, but 80 is the most our internal struct supports + for (uint32 i = 0; i < 200; i++) + { + strncpy(eq->items[i].SerialNumber, "0000000000000000", sizeof(eq->items[i].SerialNumber)); + eq->items[i].Unknown18 = 0; + if (i < 80) { + eq->ItemCost[i] = emu->ItemCost[i]; + } + else { + eq->ItemCost[i] = 0; + } + } + + FINISH_ENCODE(); + } + else if ((*p)->size == sizeof(Trader_ShowItems_Struct)) + { + ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct); + SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct); + + eq->Code = emu->Code; + strncpy(eq->SerialNumber, "0000000000000000", sizeof(eq->SerialNumber)); + eq->TraderID = emu->TraderID; + eq->Stacksize = 0; + eq->Price = 0; + + FINISH_ENCODE(); + } + else if ((*p)->size == sizeof(TraderStatus_Struct)) + { + ENCODE_LENGTH_EXACT(TraderStatus_Struct); + SETUP_DIRECT_ENCODE(TraderStatus_Struct, structs::TraderStatus_Struct); + + eq->Code = emu->Code; + + FINISH_ENCODE(); + } + else if ((*p)->size == sizeof(TraderBuy_Struct)) + { + ENCODE_FORWARD(OP_TraderBuy); + } + } + + ENCODE(OP_TraderBuy) + { + ENCODE_LENGTH_EXACT(TraderBuy_Struct); + SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct); + + OUT(Action); + OUT(Price); + OUT(TraderID); + memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName)); + OUT(ItemID); + OUT(Quantity); + OUT(AlreadySold); + + FINISH_ENCODE(); + } + + ENCODE(OP_TributeInfo) + { + ENCODE_LENGTH_ATLEAST(TributeAbility_Struct); + SETUP_VAR_ENCODE(TributeAbility_Struct); + ALLOC_VAR_ENCODE(structs::TributeAbility_Struct, sizeof(structs::TributeAbility_Struct) + strlen(emu->name) + 1); + + OUT(tribute_id); + OUT(tier_count); + + for (uint32 i = 0; i < MAX_TRIBUTE_TIERS; ++i) + { + eq->tiers[i].level = emu->tiers[i].level; + eq->tiers[i].tribute_item_id = emu->tiers[i].tribute_item_id; + eq->tiers[i].cost = emu->tiers[i].cost; + } + + eq->unknown128 = 0; + + strcpy(eq->name, emu->name); + + FINISH_ENCODE(); + } + + ENCODE(OP_TributeItem) + { + ENCODE_LENGTH_EXACT(TributeItem_Struct); + SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); + + eq->slot = ServerToRoF2Slot(emu->slot); + OUT(quantity); + OUT(tribute_master_id); + OUT(tribute_points); + + FINISH_ENCODE(); + } + + ENCODE(OP_VetRewardsAvaliable) + { + EQApplicationPacket *inapp = *p; + unsigned char * __emu_buffer = inapp->pBuffer; + + uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward)); + *p = nullptr; + + EQApplicationPacket *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) + { + structs::VeteranReward *vr = (structs::VeteranReward*)data; + InternalVeteranReward *ivr = (InternalVeteranReward*)old_data; + + vr->claim_count = ivr->claim_count; + vr->claim_id = ivr->claim_id; + vr->number_available = ivr->number_available; + for (int x = 0; x < 8; ++x) + { + vr->items[x].item_id = ivr->items[x].item_id; + strncpy(vr->items[x].item_name, ivr->items[x].item_name, sizeof(vr->items[x].item_name)); + vr->items[x].charges = ivr->items[x].charges; + } + + old_data += sizeof(InternalVeteranReward); + data += sizeof(structs::VeteranReward); + } + + dest->FastQueuePacket(&outapp_create); + delete inapp; + } + + ENCODE(OP_WearChange) + { + ENCODE_LENGTH_EXACT(WearChange_Struct); + SETUP_DIRECT_ENCODE(WearChange_Struct, structs::WearChange_Struct); + + OUT(spawn_id); + OUT(material); + OUT(unknown06); + OUT(elite_material); + OUT(hero_forge_model); + OUT(unknown18); + OUT(color.color); + OUT(wear_slot_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_WhoAllResponse) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + char *InBuffer = (char *)in->pBuffer; + + WhoAllReturnStruct *wars = (WhoAllReturnStruct*)InBuffer; + + int Count = wars->playercount; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); + + char *OutBuffer = (char *)outapp->pBuffer; + + // The struct fields were moved around a bit, so adjust values before copying + wars->unknown44[0] = Count; + wars->unknown52 = 0; + + memcpy(OutBuffer, InBuffer, sizeof(WhoAllReturnStruct)); + + OutBuffer += sizeof(WhoAllReturnStruct); + InBuffer += sizeof(WhoAllReturnStruct); + + for (int i = 0; i < Count; ++i) + { + uint32 x; + + x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + + InBuffer += 4; + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0xffffffff); + + char Name[64]; + + VARSTRUCT_DECODE_STRING(Name, InBuffer); // Char Name + VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + + x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + + VARSTRUCT_DECODE_STRING(Name, InBuffer); // Guild Name + VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + + for (int j = 0; j < 7; ++j) + { + x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + } + + VARSTRUCT_DECODE_STRING(Name, InBuffer); // Account + VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + + x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + } + + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + dest->FastQueuePacket(&outapp); + delete in; + } + + ENCODE(OP_ZoneChange) + { + ENCODE_LENGTH_EXACT(ZoneChange_Struct); + SETUP_DIRECT_ENCODE(ZoneChange_Struct, structs::ZoneChange_Struct); + + memcpy(eq->char_name, emu->char_name, sizeof(emu->char_name)); + OUT(zoneID); + OUT(instanceID); + OUT(y); + OUT(x); + OUT(z) + OUT(zone_reason); + OUT(success); + + FINISH_ENCODE(); + } + + ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } + + ENCODE(OP_ZonePlayerToBind) + { + ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct); + + ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer; + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + + unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)]; + structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1; + unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)]; + structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2; + + zph->x = zps->x; + zph->y = zps->y; + zph->z = zps->z; + zph->heading = zps->heading; + zph->bind_zone_id = 0; + zph->bind_instance_id = zps->bind_instance_id; + strncpy(zph->zone_name, zps->zone_name, sizeof(zph->zone_name)); + + zpf->unknown021 = 1; + zpf->unknown022 = 0; + zpf->unknown023 = 0; + zpf->unknown024 = 0; + + ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name))); + ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct)); + + delete[] buffer1; + delete[] buffer2; + delete[](*p)->pBuffer; + + (*p)->pBuffer = new unsigned char[ss.str().size()]; + (*p)->size = ss.str().size(); + + memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size()); + dest->FastQueuePacket(&(*p)); + } + + ENCODE(OP_ZoneServerInfo) + { + SETUP_DIRECT_ENCODE(ZoneServerInfo_Struct, ZoneServerInfo_Struct); + + OUT_str(ip); + OUT(port); + + FINISH_ENCODE(); + } + + ENCODE(OP_ZoneSpawns) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + Spawn_Struct *emu = (Spawn_Struct *)__emu_buffer; + + //determine and verify length + int entrycount = in->size / sizeof(Spawn_Struct); + if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) { + _log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct)); + delete in; + return; + } + + //_log(NET__STRUCTS, "Spawn name is [%s]", emu->name); + + emu = (Spawn_Struct *)__emu_buffer; + + //_log(NET__STRUCTS, "Spawn packet size is %i, entries = %i", in->size, entrycount); + + char *Buffer = (char *)in->pBuffer, *BufferStart; + + int r; + int k; + for (r = 0; r < entrycount; r++, emu++) { + + int PacketSize = 206; + + PacketSize += strlen(emu->name); + PacketSize += strlen(emu->lastName); + + emu->title[0] = 0; + emu->suffix[0] = 0; + + if (strlen(emu->title)) + PacketSize += strlen(emu->title) + 1; + + if (strlen(emu->suffix)) + PacketSize += strlen(emu->suffix) + 1; + + bool ShowName = 1; + if (emu->bodytype >= 66) + { + emu->race = 127; + emu->bodytype = 11; + emu->gender = 0; + ShowName = 0; + } + + float SpawnSize = emu->size; + if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + { + PacketSize += 60; + + if (emu->size == 0) + { + emu->size = 6; + SpawnSize = 6; + } + } + else + PacketSize += 216; + + if (SpawnSize == 0) + { + SpawnSize = 3; + } + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); + Buffer = (char *)outapp->pBuffer; + BufferStart = Buffer; + 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? + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + + structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer; + + Bitfields->gender = emu->gender; + Bitfields->ispet = emu->is_pet; + Bitfields->afk = emu->afk; + Bitfields->anon = emu->anon; + Bitfields->gm = emu->gm; + Bitfields->sneak = 0; + Bitfields->lfg = emu->lfg; + Bitfields->invis = emu->invis; + Bitfields->linkdead = 0; + Bitfields->showhelm = emu->showhelm; + Bitfields->trader = 0; + Bitfields->targetable = 1; + Bitfields->targetable_with_hotkey = (emu->IsMercenary ? 0 : 1); + Bitfields->showname = ShowName; + + // Not currently found + // Bitfields->statue = 0; + // Bitfields->buyer = 0; + + Buffer += sizeof(structs::Spawn_Struct_Bitfields); + + uint8 OtherData = 0; + + if (strlen(emu->title)) + OtherData = OtherData | 16; + + if (strlen(emu->suffix)) + OtherData = OtherData | 32; + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); + + 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); + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->curHp); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->haircolor); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->beardcolor); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->eyecolor1); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->eyecolor2); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->hairstyle); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->beard); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_heritage); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_tattoo); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details); + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); // unknown8 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown9 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown10 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // unknown11 + + VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->size); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->face); + VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->walkspeed); + VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->runspeed); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->race); + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // ShowEQ calls this 'Holding' + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->deity); + if (emu->NPC) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xFFFFFFFF); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); + } + else + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildID); + + /* Translate older ranks to new values */ + 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; } // + } + } + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->class_); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // pvp + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->StandState); // standstate + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->light); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->flymode); + + VARSTRUCT_ENCODE_STRING(Buffer, emu->lastName); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle ?? + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC ? 0 : 1); // unknown - Must be 1 for guild name to be shown abover players head. + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown + + 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, 0); // unknown15 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19 + + 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) + { + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color); + } + } + + structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; + + for (k = 0; k < 9; k++) { + Equipment[k].equip0 = emu->equipment[k]; + Equipment[k].equip1 = 0; + Equipment[k].equip2 = 0; + Equipment[k].equip3 = 0; + Equipment[k].itemId = 0; + } + + Buffer += (sizeof(structs::EquipStruct) * 9); + } + else + { + 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, 0); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary]); + 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]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + } + + structs::Spawn_Struct_Position *Position = (structs::Spawn_Struct_Position*)Buffer; + + Position->y = emu->y; + Position->deltaZ = emu->deltaZ; + Position->deltaX = emu->deltaX; + Position->x = emu->x; + Position->heading = emu->heading; + Position->deltaHeading = emu->deltaHeading; + Position->z = emu->z; + Position->animation = emu->animation; + Position->deltaY = emu->deltaY; + + Buffer += sizeof(structs::Spawn_Struct_Position); + + if (strlen(emu->title)) + { + VARSTRUCT_ENCODE_STRING(Buffer, emu->title); + } + + if (strlen(emu->suffix)) + { + VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix); + } + + Buffer += 8; + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->IsMercenary); + VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000"); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); + // 29 zero bytes follow + Buffer += 29; + if (Buffer != (BufferStart + PacketSize)) + { + _log(NET__ERROR, "SPAWN ENCODE LOGIC PROBLEM: Buffer pointer is now %i from end", Buffer - (BufferStart + PacketSize)); + } + //_log(NET__ERROR, "Sending zone spawn for %s packet is %i bytes", emu->name, outapp->size); + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + dest->FastQueuePacket(&outapp, ack_req); + } + + delete in; + } + +// DECODE methods + DECODE(OP_AdventureMerchantSell) + { + DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); + SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); + + IN(npcid); + emu->slot = RoF2ToServerMainInvSlot(eq->slot); + IN(charges); + IN(sell_price); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_AltCurrencySell) + { + DECODE_LENGTH_EXACT(structs::AltCurrencySellItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); + + IN(merchant_entity_id); + emu->slot_id = RoF2ToServerSlot(eq->slot_id); + IN(charges); + IN(cost); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_AltCurrencySellSelection) + { + DECODE_LENGTH_EXACT(structs::AltCurrencySelectItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct); + + IN(merchant_entity_id); + emu->slot_id = RoF2ToServerSlot(eq->slot_id); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ApplyPoison) + { + DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); + SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); + + emu->inventorySlot = RoF2ToServerMainInvSlot(eq->inventorySlot); + IN(success); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_AugmentInfo) + { + DECODE_LENGTH_EXACT(structs::AugmentInfo_Struct); + SETUP_DIRECT_DECODE(AugmentInfo_Struct, structs::AugmentInfo_Struct); + + IN(itemid); + IN(window); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_AugmentItem) + { + DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); + SETUP_DIRECT_DECODE(AugmentItem_Struct, structs::AugmentItem_Struct); + + emu->container_slot = RoF2ToServerSlot(eq->container_slot); + emu->augment_slot = RoF2ToServerSlot(eq->augment_slot); + emu->container_index = eq->container_index; + emu->augment_index = eq->augment_index; + emu->dest_inst_id = eq->dest_inst_id; + emu->augment_action = eq->augment_action; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_BazaarSearch) + { + char *Buffer = (char *)__packet->pBuffer; + + uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer); + + if ((SubAction != BazaarInspectItem) || (__packet->size != sizeof(structs::NewBazaarInspect_Struct))) + return; + + SETUP_DIRECT_DECODE(NewBazaarInspect_Struct, structs::NewBazaarInspect_Struct); + MEMSET_IN(structs::NewBazaarInspect_Struct); + + IN(Beginning.Action); + memcpy(emu->Name, eq->Name, sizeof(emu->Name)); + IN(SerialNumber); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_BlockedBuffs) + { + DECODE_LENGTH_EXACT(structs::BlockedBuffs_Struct); + SETUP_DIRECT_DECODE(BlockedBuffs_Struct, structs::BlockedBuffs_Struct); + + for (uint32 i = 0; i < BLOCKED_BUFF_COUNT; ++i) + emu->SpellID[i] = eq->SpellID[i]; + + IN(Count); + IN(Pet); + IN(Initialise); + IN(Flags); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Buff) + { + DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct_Live); + SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Live); + + IN(entityid); + //IN(slot); + IN(level); + IN(effect); + IN(spellid); + IN(duration); + IN(slotid); + IN(bufffade); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_BuffRemoveRequest) + { + // This is to cater for the fact that short buff box buffs start at 30 as opposed to 25 in prior clients. + // + DECODE_LENGTH_EXACT(structs::BuffRemoveRequest_Struct); + SETUP_DIRECT_DECODE(BuffRemoveRequest_Struct, structs::BuffRemoveRequest_Struct); + + emu->SlotID = (eq->SlotID < 42) ? eq->SlotID : (eq->SlotID - 17); + + IN(EntityID); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_CastSpell) + { + DECODE_LENGTH_EXACT(structs::CastSpell_Struct); + SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); + + if (eq->slot == 13) + emu->slot = 10; + else + IN(slot); + + IN(spell_id); + emu->inventoryslot = RoF2ToServerSlot(eq->inventoryslot); + //IN(inventoryslot); + IN(target_id); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ChannelMessage) + { + unsigned char *__eq_buffer = __packet->pBuffer; + + char *InBuffer = (char *)__eq_buffer; + + char Sender[64]; + char Target[64]; + + VARSTRUCT_DECODE_STRING(Sender, InBuffer); + VARSTRUCT_DECODE_STRING(Target, InBuffer); + + InBuffer += 4; + + uint32 Language = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + uint32 Channel = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + + InBuffer += 5; + + uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + + __packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + __packet->pBuffer = new unsigned char[__packet->size]; + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; + + strn0cpy(emu->targetname, Target, sizeof(emu->targetname)); + strn0cpy(emu->sender, Target, sizeof(emu->sender)); + emu->language = Language; + emu->chan_num = Channel; + emu->skill_in_language = Skill; + strcpy(emu->message, InBuffer); + + delete[] __eq_buffer; + } + + DECODE(OP_CharacterCreate) + { + DECODE_LENGTH_EXACT(structs::CharCreate_Struct); + SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); + + IN(gender); + IN(race); + IN(class_); + IN(deity); + IN(start_zone); + IN(haircolor); + IN(beard); + IN(beardcolor); + IN(hairstyle); + IN(face); + IN(eyecolor1); + IN(eyecolor2); + IN(drakkin_heritage); + IN(drakkin_tattoo); + IN(drakkin_details); + IN(STR); + IN(STA); + IN(AGI); + IN(DEX); + IN(WIS); + IN(INT); + IN(CHA); + IN(tutorial); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ClientUpdate) + { + // for some odd reason, there is an extra byte on the end of this on occasion.. + DECODE_LENGTH_ATLEAST(structs::PlayerPositionUpdateClient_Struct); + SETUP_DIRECT_DECODE(PlayerPositionUpdateClient_Struct, structs::PlayerPositionUpdateClient_Struct); + + IN(spawn_id); + IN(sequence); + IN(x_pos); + IN(y_pos); + IN(z_pos); + IN(heading); + IN(delta_x); + IN(delta_y); + IN(delta_z); + IN(delta_heading); + IN(animation); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Consider) + { + DECODE_LENGTH_EXACT(structs::Consider_Struct); + SETUP_DIRECT_DECODE(Consider_Struct, structs::Consider_Struct); + + IN(playerid); + IN(targetid); + IN(faction); + IN(level); + //emu->cur_hp = 1; + //emu->max_hp = 2; + //emu->pvpcon = 0; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ConsiderCorpse) { DECODE_FORWARD(OP_Consider); } + + DECODE(OP_Consume) + { + DECODE_LENGTH_EXACT(structs::Consume_Struct); + SETUP_DIRECT_DECODE(Consume_Struct, structs::Consume_Struct); + + emu->slot = RoF2ToServerSlot(eq->slot); + IN(auto_consumed); + IN(type); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Damage) + { + DECODE_LENGTH_EXACT(structs::CombatDamage_Struct); + SETUP_DIRECT_DECODE(CombatDamage_Struct, structs::CombatDamage_Struct); + + IN(target); + IN(source); + IN(type); + IN(spellid); + IN(damage); + emu->sequence = eq->sequence; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DeleteItem) + { + DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); + SETUP_DIRECT_DECODE(DeleteItem_Struct, structs::DeleteItem_Struct); + + emu->from_slot = RoF2ToServerSlot(eq->from_slot); + emu->to_slot = RoF2ToServerSlot(eq->to_slot); + IN(number_in_stack); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_EnvDamage) + { + DECODE_LENGTH_EXACT(structs::EnvDamage2_Struct); + SETUP_DIRECT_DECODE(EnvDamage2_Struct, structs::EnvDamage2_Struct); + + IN(id); + IN(damage); + IN(dmgtype); + emu->constant = 0xFFFF; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_FaceChange) + { + DECODE_LENGTH_EXACT(structs::FaceChange_Struct); + SETUP_DIRECT_DECODE(FaceChange_Struct, structs::FaceChange_Struct); + + IN(haircolor); + IN(beardcolor); + IN(eyecolor1); + IN(eyecolor2); + IN(hairstyle); + IN(beard); + IN(face); + IN(drakkin_heritage); + IN(drakkin_tattoo); + IN(drakkin_details); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_FindPersonRequest) + { + DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct); + SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct); + + IN(npc_id); + IN(client_pos.x); + IN(client_pos.y); + IN(client_pos.z); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GMLastName) + { + DECODE_LENGTH_EXACT(structs::GMLastName_Struct); + SETUP_DIRECT_DECODE(GMLastName_Struct, structs::GMLastName_Struct); + + memcpy(emu->name, eq->name, sizeof(emu->name)); + memcpy(emu->gmname, eq->gmname, sizeof(emu->gmname)); + memcpy(emu->lastname, eq->lastname, sizeof(emu->lastname)); + for (int i = 0; i<4; i++) + { + emu->unknown[i] = eq->unknown[i]; + } + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupCancelInvite) + { + DECODE_LENGTH_EXACT(structs::GroupCancel_Struct); + SETUP_DIRECT_DECODE(GroupCancel_Struct, structs::GroupCancel_Struct); + + memcpy(emu->name1, eq->name1, sizeof(emu->name1)); + memcpy(emu->name2, eq->name2, sizeof(emu->name2)); + IN(toggle); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupDisband) + { + //EQApplicationPacket *in = __packet; + //_log(NET__ERROR, "Received incoming OP_Disband"); + //_hex(NET__ERROR, in->pBuffer, in->size); + DECODE_LENGTH_EXACT(structs::GroupGeneric_Struct); + SETUP_DIRECT_DECODE(GroupGeneric_Struct, structs::GroupGeneric_Struct); + + memcpy(emu->name1, eq->name1, sizeof(emu->name1)); + memcpy(emu->name2, eq->name2, sizeof(emu->name2)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupFollow) + { + //EQApplicationPacket *in = __packet; + //_log(NET__ERROR, "Received incoming OP_GroupFollow"); + //_hex(NET__ERROR, in->pBuffer, in->size); + DECODE_LENGTH_EXACT(structs::GroupFollow_Struct); + SETUP_DIRECT_DECODE(GroupGeneric_Struct, structs::GroupFollow_Struct); + + memcpy(emu->name1, eq->name1, sizeof(emu->name1)); + memcpy(emu->name2, eq->name2, sizeof(emu->name2)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupFollow2) + { + //EQApplicationPacket *in = __packet; + //_log(NET__ERROR, "Received incoming OP_GroupFollow2"); + //_hex(NET__ERROR, in->pBuffer, in->size); + DECODE_LENGTH_EXACT(structs::GroupFollow_Struct); + SETUP_DIRECT_DECODE(GroupGeneric_Struct, structs::GroupFollow_Struct); + + memcpy(emu->name1, eq->name1, sizeof(emu->name1)); + memcpy(emu->name2, eq->name2, sizeof(emu->name2)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupInvite) + { + //EQApplicationPacket *in = __packet; + //_log(NET__ERROR, "Received incoming OP_GroupInvite"); + //_hex(NET__ERROR, in->pBuffer, in->size); + DECODE_LENGTH_EXACT(structs::GroupInvite_Struct); + SETUP_DIRECT_DECODE(GroupGeneric_Struct, structs::GroupInvite_Struct); + + memcpy(emu->name1, eq->invitee_name, sizeof(emu->name1)); + memcpy(emu->name2, eq->inviter_name, sizeof(emu->name2)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupInvite2) + { + //_log(NET__ERROR, "Received incoming OP_GroupInvite2. Forwarding"); + DECODE_FORWARD(OP_GroupInvite); + } + + DECODE(OP_GuildDemote) + { + DECODE_LENGTH_EXACT(structs::GuildDemoteStruct); + SETUP_DIRECT_DECODE(GuildDemoteStruct, structs::GuildDemoteStruct); + + strn0cpy(emu->target, eq->target, sizeof(emu->target)); + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + // IN(rank); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GuildRemove) + { + DECODE_LENGTH_EXACT(structs::GuildCommand_Struct); + SETUP_DIRECT_DECODE(GuildCommand_Struct, structs::GuildCommand_Struct); + + strn0cpy(emu->othername, eq->othername, sizeof(emu->othername)); + strn0cpy(emu->myname, eq->myname, sizeof(emu->myname)); + IN(guildeqid); + IN(officer); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GuildStatus) + { + DECODE_LENGTH_EXACT(structs::GuildStatus_Struct); + SETUP_DIRECT_DECODE(GuildStatus_Struct, structs::GuildStatus_Struct); + + memcpy(emu->Name, eq->Name, sizeof(emu->Name)); + + FINISH_DIRECT_DECODE(); + } + + /*DECODE(OP_InspectAnswer) + { + DECODE_LENGTH_EXACT(structs::InspectResponse_Struct); + SETUP_DIRECT_DECODE(InspectResponse_Struct, structs::InspectResponse_Struct); + + IN(TargetID); + IN(playerid); + + int r; + for (r = 0; r < 21; r++) { + strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->itemnames[r])); + } + // Swap last 2 slots for Arrow and Power Source + strn0cpy(emu->itemnames[22], eq->itemnames[21], sizeof(emu->itemnames[22])); + strn0cpy(emu->itemnames[21], eq->unknown_zero, sizeof(emu->itemnames[21])); + strn0cpy(emu->unknown_zero, eq->unknown_zero, sizeof(emu->unknown_zero)); + + int k; + for (k = 0; k < 21; k++) { + IN(itemicons[k]); + } + // Swap last 2 slots for Arrow and Power Source + emu->itemicons[22] = eq->itemicons[21]; + emu->itemicons[21] = eq->unknown_zero2; + emu->unknown_zero2 = eq->unknown_zero2; + strn0cpy(emu->text, eq->text, sizeof(emu->text)); + //emu->unknown1772 = 0; + + FINISH_DIRECT_DECODE(); + }*/ + + DECODE(OP_InspectRequest) + { + DECODE_LENGTH_EXACT(structs::Inspect_Struct); + SETUP_DIRECT_DECODE(Inspect_Struct, structs::Inspect_Struct); + + IN(TargetID); + IN(PlayerID); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ItemLinkClick) + { + DECODE_LENGTH_EXACT(structs::ItemViewRequest_Struct); + SETUP_DIRECT_DECODE(ItemViewRequest_Struct, structs::ItemViewRequest_Struct); + MEMSET_IN(ItemViewRequest_Struct); + + IN(item_id); + int r; + for (r = 0; r < 5; r++) { + IN(augments[r]); + } + // Max Augs is now 6, but no code to support that many yet + IN(link_hash); + IN(icon); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ItemVerifyRequest) + { + DECODE_LENGTH_EXACT(structs::ItemVerifyRequest_Struct); + SETUP_DIRECT_DECODE(ItemVerifyRequest_Struct, structs::ItemVerifyRequest_Struct); + + emu->slot = RoF2ToServerSlot(eq->slot); + IN(target); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_LoadSpellSet) + { + DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); + SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); + + for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i) + { + if (eq->spell[i] == 0) + emu->spell[i] = 0xFFFFFFFF; + else + emu->spell[i] = eq->spell[i]; + } + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_LootItem) + { + DECODE_LENGTH_EXACT(structs::LootingItem_Struct); + SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); + + IN(lootee); + IN(looter); + emu->slot_id = RoF2ToServerCorpseSlot(eq->slot_id); + IN(auto_loot); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_MoveItem) + { + DECODE_LENGTH_EXACT(structs::MoveItem_Struct); + SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); + + //_log(NET__ERROR, "Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot); + _log(NET__ERROR, "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); + emu->from_slot = RoF2ToServerSlot(eq->from_slot); + emu->to_slot = RoF2ToServerSlot(eq->to_slot); + IN(number_in_stack); + + _hex(NET__ERROR, eq, sizeof(structs::MoveItem_Struct)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_PetCommands) + { + DECODE_LENGTH_EXACT(structs::PetCommand_Struct); + SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); + + switch (eq->command) + { + case 0x00: + emu->command = 0x04; // Health + break; + case 0x01: + emu->command = 0x10; // Leader + break; + case 0x02: + emu->command = 0x07; // Attack + break; + case 0x04: + emu->command = 0x08; // Follow + break; + case 0x05: + emu->command = 0x05; // Guard + break; + case 0x06: + emu->command = 0x09; // Sit. Needs work. This appears to be a toggle between Sit/Stand now. + break; + case 0x0c: + emu->command = 0x0b; // Taunt + break; + case 0x0f: + emu->command = 0x0c; // Hold + break; + case 0x10: + emu->command = 0x1b; // Hold on + break; + case 0x11: + emu->command = 0x1c; // Hold off + break; + case 0x1c: + emu->command = 0x01; // Back + break; + case 0x1d: + emu->command = 0x02; // Leave/Go Away + break; + default: + emu->command = eq->command; + } + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_RaidInvite) + { + DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct); + + // This is a switch on the RaidGeneral action + switch (*(uint32 *)__packet->pBuffer) { + case 35: { // raidMOTD + // we don't have a nice macro for this + structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer; + __eq_buffer->motd[1023] = '\0'; + size_t motd_size = strlen(__eq_buffer->motd) + 1; + __packet->size = sizeof(RaidMOTD_Struct) + motd_size; + __packet->pBuffer = new unsigned char[__packet->size]; + RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer; + structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer; + strn0cpy(emu->general.player_name, eq->general.player_name, 64); + strn0cpy(emu->motd, eq->motd, motd_size); + IN(general.action); + IN(general.parameter); + FINISH_DIRECT_DECODE(); + break; + } + case 36: { // raidPlayerNote unhandled + break; + } + default: { + DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct); + SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct); + strn0cpy(emu->leader_name, eq->leader_name, 64); + strn0cpy(emu->player_name, eq->player_name, 64); + IN(action); + IN(parameter); + FINISH_DIRECT_DECODE(); + break; + } + } + } + + DECODE(OP_ReadBook) + { + DECODE_LENGTH_EXACT(structs::BookRequest_Struct); + SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); + + IN(type); + IN(invslot); + emu->window = (uint8)eq->window; + strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_RecipeAutoCombine) + { + DECODE_LENGTH_EXACT(structs::RecipeAutoCombine_Struct); + SETUP_DIRECT_DECODE(RecipeAutoCombine_Struct, structs::RecipeAutoCombine_Struct); + + IN(object_type); + IN(some_id); + emu->unknown1 = RoF2ToServerSlot(eq->container_slot); + IN(recipe_id); + IN(reply_code); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_RemoveBlockedBuffs) { DECODE_FORWARD(OP_BlockedBuffs); } + + DECODE(OP_RezzAnswer) + { + DECODE_LENGTH_EXACT(structs::Resurrect_Struct); + SETUP_DIRECT_DECODE(Resurrect_Struct, structs::Resurrect_Struct); + + IN(zone_id); + IN(instance_id); + IN(y); + IN(x); + IN(z); + memcpy(emu->your_name, eq->your_name, sizeof(emu->your_name)); + memcpy(emu->rezzer_name, eq->rezzer_name, sizeof(emu->rezzer_name)); + IN(spellid); + memcpy(emu->corpse_name, eq->corpse_name, sizeof(emu->corpse_name)); + IN(action); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Save) + { + DECODE_LENGTH_EXACT(structs::Save_Struct); + SETUP_DIRECT_DECODE(Save_Struct, structs::Save_Struct); + + memcpy(emu->unknown00, eq->unknown00, sizeof(emu->unknown00)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_SetServerFilter) + { + DECODE_LENGTH_EXACT(structs::SetServerFilter_Struct); + SETUP_DIRECT_DECODE(SetServerFilter_Struct, structs::SetServerFilter_Struct); + + int r; + for (r = 0; r < 29; r++) { + // Size 40 in RoF2 + IN(filters[r]); + } + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ShopPlayerBuy) + { + DECODE_LENGTH_EXACT(structs::Merchant_Sell_Struct); + SETUP_DIRECT_DECODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct); + + IN(npcid); + IN(playerid); + IN(itemslot); + IN(quantity); + IN(price); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ShopPlayerSell) + { + DECODE_LENGTH_EXACT(structs::Merchant_Purchase_Struct); + SETUP_DIRECT_DECODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); + + IN(npcid); + emu->itemslot = RoF2ToServerMainInvSlot(eq->itemslot); + //IN(itemslot); + IN(quantity); + IN(price); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ShopRequest) + { + DECODE_LENGTH_EXACT(structs::Merchant_Click_Struct); + SETUP_DIRECT_DECODE(Merchant_Click_Struct, structs::Merchant_Click_Struct); + + IN(npcid); + IN(playerid); + IN(command); + IN(rate); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Trader) + { + uint32 psize = __packet->size; + if (psize == sizeof(structs::ClickTrader_Struct)) + { + DECODE_LENGTH_EXACT(structs::ClickTrader_Struct); + SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::ClickTrader_Struct); + MEMSET_IN(ClickTrader_Struct); + + emu->Code = eq->Code; + // Live actually has 200 items now, but 80 is the most our internal struct supports + for (uint32 i = 0; i < 80; i++) + { + emu->SerialNumber[i] = 0; // eq->SerialNumber[i]; + emu->ItemCost[i] = eq->ItemCost[i]; + } + + FINISH_DIRECT_DECODE(); + } + else if (psize == sizeof(structs::Trader_ShowItems_Struct)) + { + DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct); + SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct); + MEMSET_IN(Trader_ShowItems_Struct); + + emu->Code = eq->Code; + emu->TraderID = eq->TraderID; + + FINISH_DIRECT_DECODE(); + } + else if (psize == sizeof(structs::TraderStatus_Struct)) + { + DECODE_LENGTH_EXACT(structs::TraderStatus_Struct); + SETUP_DIRECT_DECODE(TraderStatus_Struct, structs::TraderStatus_Struct); + MEMSET_IN(TraderStatus_Struct); + + emu->Code = eq->Code; + + FINISH_DIRECT_DECODE(); + } + } + + DECODE(OP_TraderBuy) + { + DECODE_LENGTH_EXACT(structs::TraderBuy_Struct); + SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct); + MEMSET_IN(TraderBuy_Struct); + + IN(Action); + IN(Price); + IN(TraderID); + memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName)); + IN(ItemID); + IN(Quantity); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_TradeSkillCombine) + { + DECODE_LENGTH_EXACT(structs::NewCombine_Struct); + SETUP_DIRECT_DECODE(NewCombine_Struct, structs::NewCombine_Struct); + + int16 slot_id = RoF2ToServerSlot(eq->container_slot); + if (slot_id == 4000) { + slot_id = legacy::SLOT_TRADESKILL; // 1000 + } + emu->container_slot = slot_id; + emu->guildtribute_slot = RoF2ToServerSlot(eq->guildtribute_slot); // this should only return INVALID_INDEX until implemented -U + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_TributeItem) + { + DECODE_LENGTH_EXACT(structs::TributeItem_Struct); + SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); + + emu->slot = RoF2ToServerSlot(eq->slot); + IN(quantity); + IN(tribute_master_id); + IN(tribute_points); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_WhoAllRequest) + { + DECODE_LENGTH_EXACT(structs::Who_All_Struct); + SETUP_DIRECT_DECODE(Who_All_Struct, structs::Who_All_Struct); + + memcpy(emu->whom, eq->whom, sizeof(emu->whom)); + IN(wrace); + IN(wclass); + IN(lvllow); + IN(lvlhigh); + IN(gmlookup); + IN(guildid); + IN(type); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ZoneChange) + { + DECODE_LENGTH_EXACT(structs::ZoneChange_Struct); + SETUP_DIRECT_DECODE(ZoneChange_Struct, structs::ZoneChange_Struct); + + memcpy(emu->char_name, eq->char_name, sizeof(emu->char_name)); + IN(zoneID); + IN(instanceID); + IN(y); + IN(x); + IN(z) + IN(zone_reason); + IN(success); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ZoneEntry) + { + DECODE_LENGTH_EXACT(structs::ClientZoneEntry_Struct); + SETUP_DIRECT_DECODE(ClientZoneEntry_Struct, structs::ClientZoneEntry_Struct); + + memcpy(emu->char_name, eq->char_name, sizeof(emu->char_name)); + + FINISH_DIRECT_DECODE(); + } + +// file scope helper methods + uint32 NextItemInstSerialNumber = 1; + uint32 MaxInstances = 2000000000; + + static inline int32 GetNextItemInstSerialNumber() + { + if (NextItemInstSerialNumber >= MaxInstances) + NextItemInstSerialNumber = 1; + else + NextItemInstSerialNumber++; + + return NextItemInstSerialNumber; + } + + char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, 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(NET__ERROR, "Serialize called for: %s", item->Name); + + RoF2::structs::ItemSerializationHeader hdr; + + //sprintf(hdr.unknown000, "06e0002Y1W00"); + + snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%012d", item->ID); + + hdr.stacksize = stackable ? charges : 1; + hdr.unknown004 = 0; + + structs::ItemSlotStruct slot_id = ServerToRoF2Slot(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.unknown013 = 0xffff; + 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.unknown028 = 0; + hdr.last_cast_time = ((item->RecastDelay > 1) ? 1212693140 : 0); + hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); + hdr.inst_nodrop = inst->IsInstNoDrop() ? 1 : 0; + hdr.unknown044 = 0; + hdr.unknown048 = 0; + hdr.unknown052 = 0; + hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; + ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); + + if (item->EvolvingLevel > 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.Activated = 1; + evotop.evomaxlevel = 7; + ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); + } + //ORNAMENT IDFILE / ICON + uint16 ornaIcon = 0; + if (inst->GetOrnamentationAug(ornamentationAugtype)) { + const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + //Mainhand + ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + //Offhand + ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + //Icon + ornaIcon = aug_weap->Icon; + } + else 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)); + ornaIcon = inst->GetOrnamentationIcon(); + } + else { + ss.write((const char*)&null_term, sizeof(uint8)); //no mh + ss.write((const char*)&null_term, sizeof(uint8));//no of + } + + RoF2::structs::ItemSerializationHeaderFinish hdrf; + hdrf.ornamentIcon = ornaIcon; + hdrf.unknown061 = 0; + hdrf.unknown062 = 0; + hdrf.unknowna1 = 0xffffffff; + hdrf.unknowna2 = 0; + hdrf.unknown063 = 0; + hdrf.unknowna3 = 0; + hdrf.unknowna4 = 0xffffffff; + hdrf.unknowna5 = 0; + hdrf.ItemClass = item->ItemClass; + 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)); + } + + 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)); + } + + 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((const char*)&null_term, sizeof(uint8)); + //_log(NET__ERROR, "ItemBody struct is %i bytes", sizeof(RoF2::structs::ItemBodyStruct)); + RoF2::structs::ItemBodyStruct ibs; + memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); + + ibs.id = item->ID; + ibs.weight = item->Weight; + ibs.norent = item->NoRent; + ibs.nodrop = item->NoDrop; + ibs.attune = item->Attuneable; + ibs.size = item->Size; + ibs.slots = SwapBits21and22(item->Slots); + ibs.price = item->Price; + ibs.icon = item->Icon; + ibs.unknown1 = 1; + ibs.unknown2 = 1; + ibs.BenefitFlag = item->BenefitFlag; + ibs.tradeskills = item->Tradeskills; + ibs.CR = item->CR; + ibs.DR = item->DR; + ibs.PR = item->PR; + ibs.MR = item->MR; + ibs.FR = item->FR; + ibs.SVCorruption = item->SVCorruption; + ibs.AStr = item->AStr; + ibs.ASta = item->ASta; + ibs.AAgi = item->AAgi; + ibs.ADex = item->ADex; + ibs.ACha = item->ACha; + ibs.AInt = item->AInt; + ibs.AWis = item->AWis; + + ibs.HP = item->HP; + ibs.Mana = item->Mana; + ibs.Endur = item->Endur; + ibs.AC = item->AC; + ibs.regen = item->Regen; + ibs.mana_regen = item->ManaRegen; + ibs.end_regen = item->EnduranceRegen; + ibs.Classes = item->Classes; + ibs.Races = item->Races; + ibs.Deity = item->Deity; + ibs.SkillModValue = item->SkillModValue; + ibs.SkillModMax = 0xffffffff; + ibs.SkillModType = (int8)(item->SkillModType); + ibs.SkillModExtra = 0; + ibs.BaneDmgRace = item->BaneDmgRace; + ibs.BaneDmgBody = item->BaneDmgBody; + ibs.BaneDmgRaceAmt = item->BaneDmgRaceAmt; + 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.RecSkill = item->RecSkill; + ibs.BardType = item->BardType; + ibs.BardValue = item->BardValue; + ibs.Light = item->Light; + ibs.Delay = item->Delay; + ibs.ElemDmgType = item->ElemDmgType; + ibs.ElemDmgAmt = item->ElemDmgAmt; + ibs.Range = item->Range; + ibs.Damage = item->Damage; + ibs.Color = item->Color; + ibs.Prestige = 0; + ibs.ItemType = item->ItemType; + ibs.Material = item->Material; + ibs.unknown7 = 0; + ibs.EliteMaterial = item->EliteMaterial; + ibs.unknown_RoF23 = 0; + ibs.unknown_RoF24 = 0; + ibs.SellRate = item->SellRate; + ibs.CombatEffects = item->CombatEffects; + ibs.Shielding = item->Shielding; + ibs.StunResist = item->StunResist; + ibs.StrikeThrough = item->StrikeThrough; + ibs.ExtraDmgSkill = item->ExtraDmgSkill; + ibs.ExtraDmgAmt = item->ExtraDmgAmt; + ibs.SpellShield = item->SpellShield; + ibs.Avoidance = item->Avoidance; + ibs.Accuracy = item->Accuracy; + ibs.CharmFileID = item->CharmFileID; + ibs.FactionAmt1 = item->FactionAmt1; + ibs.FactionMod1 = item->FactionMod1; + ibs.FactionAmt2 = item->FactionAmt2; + ibs.FactionMod2 = item->FactionMod2; + ibs.FactionAmt3 = item->FactionAmt3; + ibs.FactionMod3 = item->FactionMod3; + ibs.FactionAmt4 = item->FactionAmt4; + ibs.FactionMod4 = item->FactionMod4; + + ss.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((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + //_log(NET__ERROR, "ItemBody secondary struct is %i bytes", sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + RoF2::structs::ItemSecondaryBodyStruct isbs; + memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + + isbs.augtype = item->AugType; + isbs.augdistiller = 65535; + isbs.augrestrict = item->AugRestrict; + + for (int x = AUG_BEGIN; x < EmuConstants::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]; + } + + // Increased to 6 max aug slots + isbs.augslots[5].type = 0; + isbs.augslots[5].visible = 1; + isbs.augslots[5].unknown = 0; + + isbs.ldonpoint_type = item->PointType; + isbs.ldontheme = item->LDoNTheme; + isbs.ldonprice = item->LDoNPrice; + isbs.ldonsellbackrate = item->LDoNSellBackRate; + isbs.ldonsold = item->LDoNSold; + + isbs.bagtype = item->BagType; + isbs.bagslots = item->BagSlots; + isbs.bagsize = item->BagSize; + isbs.wreduction = item->BagWR; + + isbs.book = item->Book; + isbs.booktype = item->BookType; + + 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)); + } + + //_log(NET__ERROR, "ItemBody tertiary struct is %i bytes", sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + RoF2::structs::ItemTertiaryBodyStruct itbs; + memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + + itbs.loregroup = item->LoreGroup; + itbs.artifact = item->ArtifactFlag; + itbs.summonedflag = item->SummonedFlag; + itbs.favor = item->Favor; + itbs.fvnodrop = item->FVNoDrop; + itbs.dotshield = item->DotShielding; + itbs.atk = item->Attack; + itbs.haste = item->Haste; + itbs.damage_shield = item->DamageShield; + itbs.guildfavor = item->GuildFavor; + itbs.augdistil = item->AugDistiller; + itbs.unknown3 = 0xffffffff; + itbs.unknown4 = 0; + itbs.no_pet = item->NoPet; + itbs.unknown5 = 0; + + itbs.potion_belt_enabled = item->PotionBelt; + itbs.potion_belt_slots = item->PotionBeltSlots; + itbs.stacksize = stackable ? item->StackSize : 0; + itbs.no_transfer = item->NoTransfer; + itbs.expendablearrow = item->ExpendableArrow; + + itbs.unknown8 = 0; + itbs.unknown9 = 0; + itbs.unknown10 = 0; + itbs.unknown11 = 0; + itbs.unknown12 = 0; + itbs.unknown13 = 0; + itbs.unknown14 = 0; + + ss.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + + // Effect Structures Broken down to allow variable length strings for effect names + int32 effect_unknown = 0; + + //_log(NET__ERROR, "ItemBody Click effect struct is %i bytes", sizeof(RoF2::structs::ClickEffectStruct)); + RoF2::structs::ClickEffectStruct ices; + memset(&ices, 0, sizeof(RoF2::structs::ClickEffectStruct)); + + ices.effect = item->Click.Effect; + ices.level2 = item->Click.Level2; + ices.type = item->Click.Type; + ices.level = item->Click.Level; + ices.max_charges = item->MaxCharges; + ices.cast_time = item->CastTime; + ices.recast = item->RecastDelay; + ices.recast_type = item->RecastType; + + 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((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + + //_log(NET__ERROR, "ItemBody proc effect struct is %i bytes", sizeof(RoF2::structs::ProcEffectStruct)); + RoF2::structs::ProcEffectStruct ipes; + memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); + + ipes.effect = item->Proc.Effect; + ipes.level2 = item->Proc.Level2; + ipes.type = item->Proc.Type; + ipes.level = item->Proc.Level; + ipes.procrate = item->ProcRate; + + 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((const char*)&effect_unknown, sizeof(int32)); // unknown5 + + //_log(NET__ERROR, "ItemBody worn effect struct is %i bytes", sizeof(RoF2::structs::WornEffectStruct)); + RoF2::structs::WornEffectStruct iwes; + memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); + + iwes.effect = item->Worn.Effect; + iwes.level2 = item->Worn.Level2; + iwes.type = item->Worn.Type; + iwes.level = item->Worn.Level; + + 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((const char*)&effect_unknown, sizeof(int32)); // unknown6 + + RoF2::structs::WornEffectStruct ifes; + memset(&ifes, 0, sizeof(RoF2::structs::WornEffectStruct)); + + ifes.effect = item->Focus.Effect; + ifes.level2 = item->Focus.Level2; + ifes.type = item->Focus.Type; + ifes.level = item->Focus.Level; + + 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((const char*)&effect_unknown, sizeof(int32)); // unknown6 + + RoF2::structs::WornEffectStruct ises; + memset(&ises, 0, sizeof(RoF2::structs::WornEffectStruct)); + + ises.effect = item->Scroll.Effect; + ises.level2 = item->Scroll.Level2; + ises.type = item->Scroll.Type; + ises.level = item->Scroll.Level; + + 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((const char*)&effect_unknown, sizeof(int32)); // unknown6 + + // Bard Effect? + RoF2::structs::WornEffectStruct ibes; + memset(&ibes, 0, sizeof(RoF2::structs::WornEffectStruct)); + + ibes.effect = 0xffffffff; + ibes.level2 = 0; + ibes.type = 0; + ibes.level = 0; + //ibes.unknown6 = 0xffffffff; + + ss.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)); + } + else */ + ss.write((const char*)&null_term, sizeof(uint8)); + + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + // End of Effects + + //_log(NET__ERROR, "ItemBody Quaternary effect struct is %i bytes", sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + RoF2::structs::ItemQuaternaryBodyStruct iqbs; + memset(&iqbs, 0, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + + iqbs.scriptfileid = item->ScriptFileID; + iqbs.quest_item = item->QuestItemFlag; + iqbs.Power = 0; + iqbs.Purity = item->Purity; + iqbs.unknown16 = 0; + iqbs.BackstabDmg = item->BackstabDmg; + iqbs.DSMitigation = item->DSMitigation; + iqbs.HeroicStr = item->HeroicStr; + iqbs.HeroicInt = item->HeroicInt; + iqbs.HeroicWis = item->HeroicWis; + iqbs.HeroicAgi = item->HeroicAgi; + iqbs.HeroicDex = item->HeroicDex; + iqbs.HeroicSta = item->HeroicSta; + iqbs.HeroicCha = item->HeroicCha; + iqbs.HeroicMR = item->HeroicMR; + iqbs.HeroicFR = item->HeroicFR; + iqbs.HeroicCR = item->HeroicCR; + iqbs.HeroicDR = item->HeroicDR; + iqbs.HeroicPR = item->HeroicPR; + iqbs.HeroicSVCorrup = item->HeroicSVCorrup; + iqbs.HealAmt = item->HealAmt; + iqbs.SpellDmg = item->SpellDmg; + iqbs.clairvoyance = item->Clairvoyance; + iqbs.unknown28 = 0; + + + // Begin RoF2 Test + iqbs.unknown_TEST1 = 0; + // End RoF2 Test + + iqbs.unknown30 = 0; + iqbs.unknown39 = 1; + + iqbs.subitem_count = 0; + + char *SubSerializations[10]; // + + uint32 SubLengths[10]; + + for (int x = SUB_BEGIN; x < EmuConstants::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 >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::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 - 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 - 2500) * 10) + 2530 + x + 1); + SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::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(RoF2::structs::ItemQuaternaryBodyStruct)); + + for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + + if (SubSerializations[x]) { + + ss.write((const char*)&x, sizeof(uint32)); + + ss.write(SubSerializations[x], SubLengths[x]); + + safe_delete_array(SubSerializations[x]); + } + } + + char* item_serial = new char[ss.tellp()]; + memset(item_serial, 0, ss.tellp()); + memcpy(item_serial, ss.str().c_str(), ss.tellp()); + + *length = ss.tellp(); + return item_serial; + } + + static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot) + { + structs::ItemSlotStruct RoF2Slot; + RoF2Slot.SlotType = INVALID_INDEX; + RoF2Slot.Unknown02 = NOT_USED; + RoF2Slot.MainSlot = INVALID_INDEX; + RoF2Slot.SubSlot = INVALID_INDEX; + RoF2Slot.AugSlot = INVALID_INDEX; + RoF2Slot.Unknown01 = NOT_USED; + + uint32 TempSlot = 0; + + if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // Main Inventory and Cursor + RoF2Slot.SlotType = maps::MapPossessions; + RoF2Slot.MainSlot = ServerSlot; + + if (ServerSlot == MainPowerSource) + RoF2Slot.MainSlot = slots::MainPowerSource; + + else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory + RoF2Slot.MainSlot += 3; + + else if (ServerSlot >= MainAmmo) // (> 20) + RoF2Slot.MainSlot += 1; + } + + /*else if (ServerSlot < 51) { // Cursor Buffer + RoF2Slot.SlotType = maps::MapLimbo; + RoF2Slot.MainSlot = ServerSlot - 31; + }*/ + + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) { // (> 250 && < 341) + RoF2Slot.SlotType = maps::MapPossessions; + TempSlot = ServerSlot - 1; + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + + if (RoF2Slot.MainSlot >= slots::MainGeneral9) // (> 30) + RoF2Slot.MainSlot = slots::MainCursor; + } + + else if (ServerSlot >= EmuConstants::TRIBUTE_BEGIN && ServerSlot <= EmuConstants::TRIBUTE_END) { // Tribute + RoF2Slot.SlotType = maps::MapTribute; + RoF2Slot.MainSlot = ServerSlot - EmuConstants::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; + + if (TempSlot > 30) { // (> 30) + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::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; + + if (TempSlot > 30) { // (> 30) + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::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; + + if (TempSlot > 30) { + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + } + + /* + // OLD CODE: + if (TempSlot > 99) { + if (TempSlot > 100) + RoF2Slot.MainSlot = int((TempSlot - 100) / 10); + + else + RoF2Slot.MainSlot = 0; + + RoF2Slot.SubSlot = TempSlot - (100 + RoF2Slot.MainSlot); + } + */ + } + + else if (ServerSlot >= EmuConstants::WORLD_BEGIN && ServerSlot <= EmuConstants::WORLD_END) { + RoF2Slot.SlotType = maps::MapWorld; + TempSlot = ServerSlot - EmuConstants::WORLD_BEGIN; + RoF2Slot.MainSlot = TempSlot; + } + + _log(NET__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); + + return RoF2Slot; + } + + static inline structs::MainInvItemSlotStruct ServerToRoF2MainInvSlot(uint32 ServerSlot) + { + structs::MainInvItemSlotStruct RoF2Slot; + RoF2Slot.MainSlot = INVALID_INDEX; + RoF2Slot.SubSlot = INVALID_INDEX; + RoF2Slot.AugSlot = INVALID_INDEX; + RoF2Slot.Unknown01 = NOT_USED; + + uint32 TempSlot = 0; + + if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // (< 52) + RoF2Slot.MainSlot = ServerSlot; + + if (ServerSlot == MainPowerSource) + RoF2Slot.MainSlot = slots::MainPowerSource; + + else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory + RoF2Slot.MainSlot += 3; + + else if (ServerSlot >= MainAmmo) // Ammo and Personl Inventory + RoF2Slot.MainSlot += 1; + + /*else if (ServerSlot >= MainCursor) { // Cursor + RoF2Slot.MainSlot = slots::MainCursor; + + if (ServerSlot > 30) + RoF2Slot.SubSlot = (ServerSlot + 3) - 33; + }*/ + } + + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::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); + } + + _log(NET__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); + + return RoF2Slot; + } + + static inline uint32 ServerToRoF2CorpseSlot(uint32 ServerCorpse) + { + //uint32 RoF2Corpse; + return (ServerCorpse + 1); + } + + static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot) + { + 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; + + else if (RoF2Slot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory + TempSlot = RoF2Slot.MainSlot - 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 + + // The slot range of 0 - client_max is cross-utilized between player inventory and corpse inventory. + // In the case of RoF2, player inventory is addressed as 0 - 33 and corpse inventory is addressed as 23 - 56. + // We 'could' assign the two new inventory slots as 9997 and 9998, and then work around their bag + // slot assignments, but doing so may disrupt our ability to utilize the corpse looting range properly. + + // 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 // Worn Slots + TempSlot = RoF2Slot.MainSlot; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + + ServerSlot = TempSlot; + } + + else if (RoF2Slot.SlotType == maps::MapBank) { + TempSlot = EmuConstants::BANK_BEGIN; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + + else + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoF2Slot.SlotType == maps::MapSharedBank) { + TempSlot = EmuConstants::SHARED_BANK_BEGIN; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + + else + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoF2Slot.SlotType == maps::MapTrade) { + TempSlot = EmuConstants::TRADE_BEGIN; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + // OLD CODE: + //TempSlot += 100 + (RoF2Slot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot; + + else + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoF2Slot.SlotType == maps::MapWorld) { + TempSlot = EmuConstants::WORLD_BEGIN; + + if (RoF2Slot.MainSlot >= SUB_BEGIN) + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + } + + /*else if (RoF2Slot.SlotType == maps::MapLimbo) { // Cursor Buffer + TempSlot = 31; + + if (RoF2Slot.MainSlot >= 0) + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + }*/ + + else if (RoF2Slot.SlotType == maps::MapGuildTribute) { + ServerSlot = INVALID_INDEX; + } + + _log(NET__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); + + return ServerSlot; + } + + static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct 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; + + else if (RoF2Slot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory + TempSlot = RoF2Slot.MainSlot - 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 + + // Same as above + }*/ + + else if (RoF2Slot.MainSlot >= slots::MainAmmo) // Main Inventory and Ammo Slots + TempSlot = RoF2Slot.MainSlot - 1; + + else + TempSlot = RoF2Slot.MainSlot; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + + ServerSlot = TempSlot; + } + + _log(NET__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); + + return ServerSlot; + } + + static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse) + { + //uint32 ServerCorpse; + return (RoF2Corpse - 1); + } +} +// end namespace RoF2 diff --git a/common/patches/rof2.h b/common/patches/rof2.h new file mode 100644 index 000000000..b39849048 --- /dev/null +++ b/common/patches/rof2.h @@ -0,0 +1,37 @@ +#ifndef RoF2_H_ +#define RoF2_H_ + +#include "../struct_strategy.h" + +class EQStreamIdentifier; + +namespace RoF2 { + + //these are the only public member of this namespace. + extern void Register(EQStreamIdentifier &into); + extern void Reload(); + + + + //you should not directly access anything below.. + //I just dont feel like making a seperate header for it. + + class Strategy : public StructStrategy { + public: + Strategy(); + + protected: + + virtual std::string Describe() const; + virtual const EQClientVersion ClientVersion() const; + + //magic macro to declare our opcode processors + #include "ss_declare.h" + #include "rof2_ops.h" + }; + +}; + + + +#endif /*RoF2_H_*/ diff --git a/common/patches/rof2_constants.h b/common/patches/rof2_constants.h new file mode 100644 index 000000000..1f8ff1a52 --- /dev/null +++ b/common/patches/rof2_constants.h @@ -0,0 +1,216 @@ +/* +EQEMu: Everquest Server Emulator + +Copyright (C) 2001-2014 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 RoF2_CONSTANTS_H_ +#define RoF2_CONSTANTS_H_ + +#include "../types.h" + +namespace RoF2 { + namespace maps { + 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; + } + + 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; + } + + namespace consts { + 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; + + // 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 GENERAL_BEGIN = slots::MainGeneral1; + static const int16 GENERAL_END = slots::MainGeneral10; + static const uint16 GENERAL_SIZE = slots::_MainGeneralCount; + 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_BAG_BEGIN = 351; + static const int16 CURSOR_BAG_END_OFFSET = 9; + static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; + + 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; + + 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; + + 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; + + static const int16 WORLD_BEGIN = 4000; + static const int16 WORLD_END = 4009; + + 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 uint16 ITEM_COMMON_SIZE = 6; + static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test) + + static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances + static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance + static const uint32 POTION_BELT_SIZE = 5; + } + + 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; + } + +}; //end namespace 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 ) + +*/ diff --git a/common/patches/rof2_itemfields.h b/common/patches/rof2_itemfields.h new file mode 100644 index 000000000..ccba333b5 --- /dev/null +++ b/common/patches/rof2_itemfields.h @@ -0,0 +1,439 @@ +/* + + +These fields must be in the order of how they are serialized! + + + +*/ +#define NEW_TRY +#ifdef NEW_TRY +//* 000 */ I(ItemClass) // Leave this one off on purpose +/* 001 */ S(Name) +/* 002 */ S(Lore) +//* 003 */ C("")//lorefile - Newly Added - Field is Null +/* 004 */ S(IDFile) +/* 005 */ I(ID) +/* 006 */ I(Weight) +/* 007 */ I(NoRent) +/* 008 */ I(NoDrop) +/* 009 */ I(Size) +/* 010 */ I(Slots) +/* 011 */ I(Price) +/* 012 */ I(Icon) +/* 013 */ C("0")//UNK013 +/* 014 */ C("0")//UNK014 +/* 015 */ I(BenefitFlag) +/* 016 */ I(Tradeskills) +/* 017 */ I(CR) +/* 018 */ I(DR) +/* 019 */ I(PR) +/* 020 */ I(MR) +/* 021 */ I(FR) +/* 022 */ C("0")//svcorruption - Newly Added +/* 023 */ I(AStr) +/* 024 */ I(ASta) +/* 025 */ I(AAgi) +/* 026 */ I(ADex) +/* 027 */ I(ACha) +/* 028 */ I(AInt) +/* 029 */ I(AWis) +/* 030 */ I(HP) +/* 031 */ I(Mana) +/* 032 */ I(Endur) //endur - Relocated +/* 033 */ I(AC) +/* 034 */ I(Classes)//classes - Relocated +/* 035 */ I(Races)//races - Relocated +/* 036 */ I(Deity) +/* 037 */ I(SkillModValue) +/* 038 */ C("0")//UNK038 - Default is 0 +/* 039 */ I(SkillModType) +/* 040 */ I(BaneDmgRace) +/* 041 */ I(BaneDmgBody)//banedmgbody - Relocated +/* 042 */ I(BaneDmgRaceAmt)//banedmgraceamt - Relocated +/* 043 */ I(BaneDmgAmt)//banedmgamt - Relocated +/* 044 */ I(Magic) +/* 045 */ I(CastTime_) +/* 046 */ I(ReqLevel) +/* 047 */ I(RecLevel)//reclevel - Relocated +/* 048 */ I(RecSkill)//recskill - Relocated +/* 049 */ I(BardType) +/* 050 */ I(BardValue) +/* 051 */ I(Light) +/* 052 */ I(Delay) +/* 053 */ I(ElemDmgType) +/* 054 */ I(ElemDmgAmt) +/* 055 */ I(Range) +/* 056 */ I(Damage) +/* 057 */ I(Color) +/* 058 */ I(ItemType) +/* 059 */ I(Material) +/* 060 */ C("0")//UNK060 - Default is 0 +/* 061 */ C("0")//UNK061 - Default is 0 +/* 062 */ F(SellRate) +/* 063 */ I(CombatEffects) +/* 064 */ I(Shielding) +/* 065 */ I(StunResist) +/* 066 */ I(StrikeThrough) +/* 067 */ I(ExtraDmgSkill) +/* 068 */ I(ExtraDmgAmt) +/* 069 */ I(SpellShield) +/* 070 */ I(Avoidance) +/* 071 */ I(Accuracy) +/* 072 */ I(CharmFileID) +/* 073 */ I(FactionMod1)//Swapped these so Faction Amt comes after each Faction Mod +/* 074 */ I(FactionAmt1)//Swapped these so Faction Amt comes after each Faction Mod +/* 075 */ I(FactionMod2)//Swapped these so Faction Amt comes after each Faction Mod +/* 076 */ I(FactionAmt2)//Swapped these so Faction Amt comes after each Faction Mod +/* 077 */ I(FactionMod3)//Swapped these so Faction Amt comes after each Faction Mod +/* 078 */ I(FactionAmt3)//Swapped these so Faction Amt comes after each Faction Mod +/* 079 */ I(FactionMod4)//Swapped these so Faction Amt comes after each Faction Mod +/* 080 */ I(FactionAmt4)//Swapped these so Faction Amt comes after each Faction Mod +/* 081 */ S(CharmFile) +/* 082 */ I(AugType) +/* 083 */ I(AugRestrict)//augrestrict - Relocated +/* 084 */ I(AugDistiller)//augdistiller - Relocated +/* 085 */ I(AugSlotType[0]) +/* 086 */ I(AugSlotVisible[0])//augslot1visible - Default 1 +/* 087 */ C("0")//augslot1unk2 - Newly Added - Default 0 +/* 088 */ I(AugSlotType[1]) +/* 089 */ I(AugSlotVisible[1]) +/* 090 */ C("0")//augslot2unk2 - Newly Added +/* 091 */ I(AugSlotType[2]) +/* 092 */ I(AugSlotVisible[2]) +/* 093 */ C("0")//augslot3unk2 - Newly Added +/* 094 */ I(AugSlotType[3]) +/* 095 */ I(AugSlotVisible[3]) +/* 096 */ C("0")//augslot4unk2 - Newly Added +/* 097 */ I(AugSlotType[4]) +/* 098 */ I(AugSlotVisible[4]) +/* 099 */ C("0")//augslot5unk2 - Newly Added +/* 100 */ I(PointType)//pointtype - Relocated +/* 101 */ I(LDoNTheme) +/* 102 */ I(LDoNPrice) +/* 103 */ C("70")//UNK098 - Newly Added - Default 70, but some are set to 0 +/* 104 */ I(LDoNSold) +/* 105 */ I(BagType) +/* 106 */ I(BagSlots) +/* 107 */ I(BagSize) +/* 108 */ I(BagWR) +/* 109 */ I(Book) +/* 110 */ I(BookType) +/* 111 */ S(Filename) +/* 112 */ I(LoreGroup) +/* 113 */ I(ArtifactFlag) +/* 114 */ C("0")//I(PendingLoreFlag)?//UNK109 - Default 0, but a few are 1 +/* 115 */ I(Favor) +/* 116 */ I(GuildFavor)//guildfavor - Relocated +/* 117 */ I(FVNoDrop) +/* 118 */ I(DotShielding) +/* 119 */ I(Attack) +/* 120 */ I(Regen) +/* 121 */ I(ManaRegen) +/* 122 */ I(EnduranceRegen) +/* 123 */ I(Haste) +/* 124 */ I(DamageShield) +/* 125 */ C("-1") //UNK120 - Default is -1 +/* 126 */ C("0") //UNK121 - Default is 0 +/* 127 */ I(Attuneable) +/* 128 */ I(NoPet) +/* 129 */ C("0") //UNK124 - Default 0, but a few are 1 +/* 130 */ I(PotionBelt) +/* 131 */ C("0") //potionbeltslots - Default 0, but a few are 1 +/* 132 */ I(StackSize) +/* 133 */ I(NoTransfer) +/* 134 */ I(Stackable)//UNK129 - Default is 0, but some are much higher +/* 135 */ I(QuestItemFlag)//questitemflag - Default is 0 (off), flag on = 1 +/* 136 */ C("0")//UNK131 - Default is 0, but there is an item set to 1 +/* 137 */ C("0")//UNK132 - Default is 0? 0000000000000000000? +/* 138 */ I(Click.Effect) +/* 139 */ I(Click.Type) +/* 140 */ I(Click.Level2) +/* 141 */ I(Click.Level) +/* 142 */ I(MaxCharges)//maxcharges - Relocated +/* 143 */ I(CastTime_)//casttime - Relocated - Note Duplicate Entries for CastTime_ and none for CastTime +/* 144 */ I(RecastDelay)//recastdelay - Relocated +/* 145 */ I(RecastType)//recasttype - Relocated +/* 146 */ C("0")//clickunk5 - Newly Added - Default is 0 +/* 147 */ C("")//clickname - Newly Added - Default is Null +/* 148 */ C("-1")//clickunk7 - Newly Added - Default is -1, but some set to 0 and some much higher +/* 149 */ I(Proc.Effect) +/* 150 */ I(Proc.Type) +/* 151 */ I(Proc.Level2) +/* 152 */ I(Proc.Level) +/* 153 */ C("0")//procunk1 - Newly Added - Default is 0, but some set to -1 and 1 +/* 154 */ C("0")//procunk2 - Newly Added - Default is 0 +/* 155 */ C("0")//procunk3 - Newly Added - Default is 0 +/* 156 */ C("0")//procunk4 - Newly Added - Default is 0 +/* 157 */ I(ProcRate)//procrate - Relocated +/* 158 */ C("")//procname - Newly Added - Default is Null +/* 159 */ C("-1")//procunk7 - Newly Added - Default is -1, but some set to 0 +/* 160 */ I(Worn.Effect) +/* 161 */ I(Worn.Type) +/* 162 */ I(Worn.Level2) +/* 163 */ I(Worn.Level) +/* 164 */ C("0")//wornunk1 - Newly Added - Default is 0 +/* 165 */ C("0")//wornunk2 - Newly Added - Default is 0 +/* 166 */ C("0")//wornunk3 - Newly Added - Default is 0 +/* 167 */ C("0")//wornunk4 - Newly Added - Default is 0 +/* 168 */ C("0")//wornunk5 - Newly Added - Default is 0 +/* 169 */ C("")//wornname - Newly Added - Default is Null +/* 170 */ C("-1")//wornunk7 - Newly Added - Default is -1, but some set to 0 +/* 171 */ I(Focus.Effect) +/* 172 */ I(Focus.Type) +/* 173 */ I(Focus.Level2) +/* 174 */ I(Focus.Level) +/* 175 */ C("0")//focusunk1 - Newly Added - Default is 0 +/* 176 */ C("0")//focusunk2 - Newly Added - Default is 0 +/* 177 */ C("0")//focusunk3 - Newly Added - Default is 0 +/* 178 */ C("0")//focusunk4 - Newly Added - Default is 0 +/* 179 */ C("0")//focusunk5 - Newly Added - Default is 0 +/* 180 */ C("")//focusname - Newly Added - Default is Null +/* 181 */ C("-1")//focusunk7 - Newly Added - Default is -1, but some set to 0 +/* 182 */ I(Scroll.Effect) +/* 183 */ I(Scroll.Type) +/* 184 */ I(Scroll.Level2) +/* 185 */ I(Scroll.Level) +/* 186 */ C("0")//scrollunk1 - Renumber this*** +/* 187 */ C("0")//scrollunk2 - Newly Added - Default is 0 +/* 188 */ C("0")//scrollunk3 - Newly Added - Default is 0 +/* 189 */ C("0")//scrollunk4 - Newly Added - Default is 0 +/* 190 */ C("0")//scrollunk5 - Newly Added - Default is 0 +/* 191 */ C("")//scrollname - Newly Added - Default is Null +/* 192 */ C("-1")//scrollunk7 - Newly Added - Default is -1, but some set to 0 +/* 193 */ C("0")//UNK193 - Default is 0 +/* 194 */ C("0")//purity - Newly Added - Default is 0, but some go up to 75 +/* 195 */ C("0")//dsmitigation - Newly Added - Default is 0, but some are up to 2 +/* 196 */ C("0")//heroic_str - Newly Added - Default is 0 +/* 197 */ C("0")//heroic_int - Newly Added - Default is 0 +/* 198 */ C("0")//heroic_wis - Newly Added - Default is 0 +/* 199 */ C("0")//heroic_agi - Newly Added - Default is 0 +/* 200 */ C("0")//heroic_dex - Newly Added - Default is 0 +/* 201 */ C("0")//heroic_sta - Newly Added - Default is 0 +/* 202 */ C("0")//heroic_cha - Newly Added - Default is 0 +/* 203 */ C("0")//HeroicSvPoison - Newly Added - Default is 0 +/* 204 */ C("0")//HeroicSvMagic - Newly Added - Default is 0 +/* 205 */ C("0")//HeroicSvFire - Newly Added - Default is 0 +/* 206 */ C("0")//HeroicSvDisease - Newly Added - Default is 0 +/* 207 */ C("0")//HeroicSvCold - Newly Added - Default is 0 +/* 208 */ C("0")//HeroicSvCorruption - Newly Added - Default is 0 +/* 209 */ C("0")//healamt - Newly Added - Default is 0, but some are up to 9 +/* 210 */ C("0")//spelldmg - Newly Added - Default is 0, but some are up to 9 +/* 211 */ C("0")//clairvoyance - Newly Added - Default is 0, but some are up to 10 +/* 212 */ C("0")//backstabdmg - Newly Added - Default is 0, but some are up to 65 +//* 213 */ C("0")//evolvinglevel - Newly Added - Default is 0, but some are up to 7 +//* 214 */ C("0")//MaxPower - Newly Added +//* 215 */ C("0")//Power - Newly Added + +//This doesn't appear to be used /* 102 */ S(verified)//verified +//This doesn't appear to be used /* 102 */ S(serialized)//created +//Unsure where this goes right now (or if it is even used) /* 108 */ I(SummonedFlag) + +#else +/* 000 */ //I(ItemClass) Leave this one off on purpose +/* 001 */ S(Name) +/* 002 */ S(Lore) +/* 003 */ C("") //LoreFile? +/* 003 */ S(IDFile) +/* 004 */ I(ID) +/* 005 */ I(Weight) +/* 006 */ I(NoRent) +/* 007 */ I(NoDrop) +/* 008 */ I(Size) +/* 009 */ I(Slots) +/* 010 */ I(Price) +/* 011 */ I(Icon) +/* 013 */ C("0") +/* 014 */ C("0") +/* 014 */ I(BenefitFlag) +/* 015 */ I(Tradeskills) +/* 016 */ I(CR) +/* 017 */ I(DR) +/* 018 */ I(PR) +/* 019 */ I(MR) +/* 020 */ I(FR) + C("0") //svcorruption +/* 021 */ I(AStr) +/* 022 */ I(ASta) +/* 023 */ I(AAgi) +/* 024 */ I(ADex) +/* 025 */ I(ACha) +/* 026 */ I(AInt) +/* 027 */ I(AWis) +/* 028 */ I(HP) +/* 029 */ I(Mana) + I(Endur) +/* 030 */ I(AC) +/* 052 */ I(Classes) +/* 053 */ I(Races) +/* 031 */ I(Deity) +/* 032 */ I(SkillModValue) +/* 033 */ C("0") +/* 034 */ I(SkillModType) +/* 035 */ I(BaneDmgRace) +/* 037 */ I(BaneDmgBody) +/* 036 */ I(BaneDmgRaceAmt) +/* 036 */ I(BaneDmgAmt) +/* 038 */ I(Magic) +/* 039 */ I(CastTime_) +/* 040 */ I(ReqLevel) +/* 045 */ I(RecLevel) +/* 046 */ I(RecSkill) +/* 041 */ I(BardType) +/* 042 */ I(BardValue) +/* 043 */ I(Light) +/* 044 */ I(Delay) +/* 047 */ I(ElemDmgType) +/* 048 */ I(ElemDmgAmt) +/* 049 */ I(Range) +/* 050 */ I(Damage) +/* 051 */ I(Color) +/* 056 */ I(ItemType) +/* 057 */ I(Material) +/* 060 */ C("0") +/* 061 */ C("0") +/* 058 */ F(SellRate) +/* 063 */ I(CombatEffects) +/* 064 */ I(Shielding) +/* 065 */ I(StunResist) +/* 059 */ //C("0") +/* 061 */ //C("0") +/* 066 */ I(StrikeThrough) +/* 067 */ I(ExtraDmgSkill) +/* 068 */ I(ExtraDmgAmt) +/* 069 */ I(SpellShield) +/* 070 */ I(Avoidance) +/* 071 */ I(Accuracy) +/* 072 */ I(CharmFileID) +/* 073 */ I(FactionMod1) +/* 077 */ I(FactionAmt1) +/* 074 */ I(FactionMod2) +/* 078 */ I(FactionAmt2) +/* 075 */ I(FactionMod3) +/* 079 */ I(FactionAmt3) +/* 076 */ I(FactionMod4) +/* 080 */ I(FactionAmt4) +/* 081 */ S(CharmFile) +/* 082 */ I(AugType) +/* 082 */ I(AugRestrict) +/* 082 */ I(AugDistiller) +/* 083 */ I(AugSlotType[0]) +/* 084 */ I(AugSlotVisible[0]) +/* 084 */ I(AugSlotUnk2[0]) +/* 085 */ I(AugSlotType[1]) +/* 086 */ I(AugSlotVisible[1]) +/* 086 */ I(AugSlotUnk2[1]) +/* 087 */ I(AugSlotType[2]) +/* 088 */ I(AugSlotVisible[2]) +/* 088 */ I(AugSlotUnk2[2]) +/* 089 */ I(AugSlotType[3]) +/* 090 */ I(AugSlotVisible[3]) +/* 090 */ I(AugSlotUnk2[3]) +/* 091 */ I(AugSlotType[4]) +/* 092 */ I(AugSlotVisible[4]) +/* 092 */ I(AugSlotUnk2[4]) +/* 093 */ I(PointType) +/* 093 */ I(LDoNTheme) +/* 094 */ I(LDoNPrice) +/* 094 */ C("0") +/* 095 */ I(LDoNSold) +/* 096 */ I(BagType) +/* 097 */ I(BagSlots) +/* 098 */ I(BagSize) +/* 099 */ I(BagWR) +/* 100 */ I(Book) +/* 101 */ I(BookType) +/* 102 */ S(Filename) +/* 105 */ I(LoreGroup) +/* 106 */ //I(PendingLoreFlag) +/* 107 */ I(ArtifactFlag) +/* 094 */ C("0") +/* 108 */ //I(SummonedFlag) +/* 109 */ I(Favor) +/* 121 */ I(GuildFavor) +/* 110 */ I(FVNoDrop) +/* 112 */ I(DotShielding) +/* 113 */ I(Attack) +/* 114 */ I(Regen) +/* 115 */ I(ManaRegen) +/* 116 */ I(EnduranceRegen) +/* 117 */ I(Haste) +/* 118 */ I(DamageShield) +/* 120 */ C("0") +/* 121 */ C("0") +/* 125 */ I(Attuneable) +/* 126 */ I(NoPet) +/* 124 */ C("0") +/* 129 */ I(PotionBelt) +/* 130 */ I(PotionBeltSlots) +/* 131 */ I(StackSize) +/* 132 */ I(NoTransfer) +/* 129 */ C("0") +/* 132 */ I(QuestItemFlag) +/* 131 */ C("0") +/* 132 */ C("00000000000000000000000000000000000000") +/* 134 */ I(Click.Effect) +/* 135 */ I(Click.Type) +/* 136 */ I(Click.Level2) +/* 137 */ I(Click.Level) +/* 055 */ I(MaxCharges) +/* 060 */ I(CastTime) +/* 119 */ I(RecastDelay) +/* 120 */ I(RecastType) +/* 138 */ C("0") //clickunk5 (prolly ProcRate) +/* 138 */ C("") //clickunk6 +/* 138 */ C("-1") //clickunk7 +/* 139 */ I(Proc.Effect) +/* 140 */ I(Proc.Type) +/* 141 */ I(Proc.Level2) +/* 142 */ I(Proc.Level) +/* 143 */ C("0") //procunk1 (prolly MaxCharges) +/* 143 */ C("0") //procunk2 (prolly CastTime) +/* 143 */ C("0") //procunk3 (prolly RecastDelay) +/* 143 */ C("0") //procunk4 (prolly RecastType) +/* 062 */ I(ProcRate) +/* 143 */ C("") //procunk6 +/* 143 */ C("-1") //procunk7 +/* 144 */ I(Worn.Effect) +/* 145 */ I(Worn.Type) +/* 146 */ I(Worn.Level2) +/* 147 */ I(Worn.Level) +/* 143 */ C("0") //wornunk1 (prolly MaxCharges) +/* 143 */ C("0") //wornunk2 (prolly CastTime) +/* 143 */ C("0") //wornunk3 (prolly RecastDelay) +/* 143 */ C("0") //wornunk4 (prolly RecastType) +/* 143 */ C("0") //wornunk5 (prolly ProcRate) +/* 143 */ C("") //wornunk6 +/* 143 */ C("-1") //wornunk7 +/* 149 */ I(Focus.Effect) +/* 150 */ I(Focus.Type) +/* 151 */ I(Focus.Level2) +/* 152 */ I(Focus.Level) +/* 143 */ C("0") //focusunk1 (prolly MaxCharges) +/* 143 */ C("0") //focusunk2 (prolly CastTime) +/* 143 */ C("0") //focusunk3 (prolly RecastDelay) +/* 143 */ C("0") //focusunk4 (prolly RecastType) +/* 143 */ C("0") //focusunk5 (prolly ProcRate) +/* 143 */ C("") //focusunk6 +/* 143 */ C("-1") //focusunk7 +/* 154 */ I(Scroll.Effect) +/* 155 */ I(Scroll.Type) +/* 156 */ I(Scroll.Level2) +/* 157 */ I(Scroll.Level) +/* 143 */ C("0") //scrollunk1 (prolly MaxCharges) +/* 143 */ C("0") //scrollunk2 (prolly CastTime) +/* 143 */ C("0") //scrollunk3 (prolly RecastDelay) +/* 143 */ C("0") //scrollunk4 (prolly RecastType) +/* 143 */ C("0") //scrollunk5 (prolly ProcRate) +/* 143 */ C("") //scrollunk6 +/* 143 */ C("-1") //scrollunk7 +/* 193 */ C("0") //Power Source Capacity +/* 194 */ C("0") //purity + +#endif + +#undef I +#undef C +#undef S +#undef F + diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h new file mode 100644 index 000000000..fbdd20575 --- /dev/null +++ b/common/patches/rof2_ops.h @@ -0,0 +1,173 @@ +// out-going packets that require an ENCODE translation: +// Begin RoF2 Encodes + +// incoming packets that require a DECODE translation: +// Begin RoF2 Decodes + + +// End RoF2 Encodes/Decodes + +// These require Encodes/Decodes for RoF, so they do for RoF2 as well +// Begin RoF Encodes +E(OP_Action) +E(OP_AdventureMerchantSell) +E(OP_AltCurrency) +E(OP_AltCurrencySell) +E(OP_Animation) +E(OP_ApplyPoison) +E(OP_AugmentInfo) +E(OP_Barter) +E(OP_BazaarSearch) +E(OP_BeginCast) +E(OP_BlockedBuffs) +E(OP_Buff) +E(OP_BuffCreate) +E(OP_CancelTrade) +E(OP_CastSpell) +E(OP_ChannelMessage) +E(OP_CharInventory) +E(OP_ClickObjectAction) +E(OP_ClientUpdate) +E(OP_Consider) +E(OP_Damage) +E(OP_DeleteCharge) +E(OP_DeleteItem) +E(OP_DeleteSpawn) +E(OP_DisciplineUpdate) +E(OP_DzCompass) +E(OP_DzExpeditionEndsWarning) +E(OP_DzExpeditionInfo) +E(OP_DzExpeditionList) +E(OP_DzJoinExpeditionConfirm) +E(OP_DzLeaderStatus) +E(OP_DzMemberList) +E(OP_ExpansionInfo) +E(OP_GMLastName) +E(OP_GMTrainSkillConfirm) +E(OP_GroundSpawn) +E(OP_GroupCancelInvite) +E(OP_GroupFollow) +E(OP_GroupFollow2) +E(OP_GroupInvite) +E(OP_GroupUpdate) +E(OP_GuildMemberList) +E(OP_GuildMemberUpdate) +E(OP_GuildsList) +E(OP_HPUpdate) +E(OP_Illusion) +E(OP_InspectBuffs) +E(OP_InspectRequest) +E(OP_InterruptCast) +E(OP_ItemLinkResponse) +E(OP_ItemPacket) +E(OP_ItemVerifyReply) +E(OP_LeadershipExpUpdate) +E(OP_LogServer) +E(OP_LootItem) +E(OP_ManaChange) +E(OP_MercenaryDataResponse) +E(OP_MercenaryDataUpdate) +E(OP_MoveItem) +E(OP_NewSpawn) +E(OP_NewZone) +E(OP_OnLevelMessage) +//E(OP_OpenNewTasksWindow) +E(OP_PetBuffWindow) +E(OP_PlayerProfile) +E(OP_RaidJoin) +E(OP_RaidUpdate) +E(OP_ReadBook) +E(OP_RecipeAutoCombine) +E(OP_RemoveBlockedBuffs) +E(OP_RequestClientZoneChange) +E(OP_RespondAA) +E(OP_RezzRequest) +E(OP_SendAATable) +E(OP_SendCharInfo) +E(OP_SendMembership) +E(OP_SendZonepoints) +E(OP_SetGuildRank) +E(OP_ShopPlayerBuy) +E(OP_ShopPlayerSell) +E(OP_ShopRequest) +E(OP_SkillUpdate) +E(OP_SomeItemPacketMaybe) +E(OP_SpawnAppearance) +E(OP_SpawnDoor) +E(OP_Stun) +E(OP_TargetBuffs) +E(OP_TaskDescription) +E(OP_TaskHistoryReply) +E(OP_Track) +E(OP_Trader) +E(OP_TraderBuy) +E(OP_TributeInfo) +E(OP_TributeItem) +E(OP_VetRewardsAvaliable) +E(OP_WearChange) +E(OP_WhoAllResponse) +E(OP_ZoneChange) +E(OP_ZoneEntry) +E(OP_ZonePlayerToBind) +E(OP_ZoneServerInfo) +E(OP_ZoneSpawns) +// Begin RoF Decodes +D(OP_AdventureMerchantSell) +D(OP_AltCurrencySell) +D(OP_AltCurrencySellSelection) +D(OP_ApplyPoison) +D(OP_AugmentInfo) +D(OP_AugmentItem) +D(OP_BazaarSearch) +D(OP_BlockedBuffs) +D(OP_Buff) +D(OP_BuffRemoveRequest) +D(OP_CastSpell) +D(OP_ChannelMessage) +D(OP_CharacterCreate) +D(OP_ClientUpdate) +D(OP_Consider) +D(OP_ConsiderCorpse) +D(OP_Consume) +D(OP_Damage) +D(OP_DeleteItem) +D(OP_EnvDamage) +D(OP_FaceChange) +D(OP_FindPersonRequest) +D(OP_GMLastName) +D(OP_GroupCancelInvite) +D(OP_GroupDisband) +D(OP_GroupFollow) +D(OP_GroupFollow2) +D(OP_GroupInvite) +D(OP_GroupInvite2) +D(OP_GuildDemote) +D(OP_GuildRemove) +D(OP_GuildStatus) +D(OP_InspectRequest) +D(OP_ItemLinkClick) +D(OP_ItemVerifyRequest) +D(OP_LoadSpellSet) +D(OP_LootItem) +D(OP_MoveItem) +D(OP_PetCommands) +D(OP_RaidInvite) +D(OP_ReadBook) +D(OP_RecipeAutoCombine) +D(OP_RemoveBlockedBuffs) +D(OP_RezzAnswer) +D(OP_Save) +D(OP_SetServerFilter) +D(OP_ShopPlayerBuy) +D(OP_ShopPlayerSell) +D(OP_ShopRequest) +D(OP_Trader) +D(OP_TraderBuy) +D(OP_TradeSkillCombine) +D(OP_TributeItem) +D(OP_WhoAllRequest) +D(OP_ZoneChange) +D(OP_ZoneEntry) +// End RoF Encodes/Decodes +#undef E +#undef D diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h new file mode 100644 index 000000000..b75faee91 --- /dev/null +++ b/common/patches/rof2_structs.h @@ -0,0 +1,4922 @@ +#ifndef RoF2_STRUCTS_H_ +#define RoF2_STRUCTS_H_ + +namespace RoF2 { + namespace structs { + +/* +** Compiler override to ensure +** byte aligned structures +*/ +#pragma pack(1) + +struct LoginInfo_Struct { +/*000*/ char login_info[64]; +/*064*/ uint8 unknown064[124]; +/*188*/ uint8 zoning; // 01 if zoning, 00 if not +/*189*/ uint8 unknown189[275]; +/*488*/ +}; + +struct EnterWorld_Struct { +/*000*/ char name[64]; +/*064*/ uint32 tutorial; // 01 on "Enter Tutorial", 00 if not +/*068*/ uint32 return_home; // 01 on "Return Home", 00 if not +}; + +//New For SoF +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 +/*002*/ int16 Unknown02; +/*004*/ int16 MainSlot; +/*006*/ int16 SubSlot; +/*008*/ int16 AugSlot; // 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; +/*006*/ int16 Unknown01; +/*008*/ +}; + +/* Name Approval Struct */ +/* Len: */ +/* Opcode: 0x8B20*/ +struct NameApproval +{ + char name[64]; + uint32 race; + uint32 class_; + uint32 deity; +}; + +/* +** Entity identification struct +** Size: 4 bytes +** OPCodes: OP_DeleteSpawn, OP_Assist +*/ +struct EntityId_Struct +{ +/*00*/ uint32 entity_id; +/*04*/ +}; + +struct Duel_Struct +{ + uint32 duel_initiator; + uint32 duel_target; +}; + +struct DuelResponse_Struct +{ + uint32 target_id; + uint32 entity_id; + uint32 unknown; +}; + +//Adventure stuff,not a net one,just one for our use +static const uint32 ADVENTURE_COLLECT = 0; +static const uint32 ADVENTURE_MASSKILL = 1; +static const uint32 ADVENTURE_NAMED = 2; +static const uint32 ADVENTURE_RESCUE = 3; + +static const uint32 BUFF_COUNT = 42; // was 25 +static const uint32 BLOCKED_BUFF_COUNT = 30; // was 20 + +static const uint32 MAX_PLAYER_TRIBUTES = 5; +static const uint32 MAX_TRIBUTE_TIERS = 10; +static const uint32 TRIBUTE_NONE = 0xFFFFFFFF; + +static const uint32 MAX_PLAYER_BANDOLIER = 20; +static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4; + +static const uint32 MAX_POTIONS_IN_BELT = 5; + +static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16; +static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16; +static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY); + +static const uint32 MAX_NUMBER_GUILDS = 1500; + +// Used primarily in the Player Profile: +static const uint32 MAX_PP_LANGUAGE = 32; // was 25 +static const uint32 MAX_PP_SPELLBOOK = 720; // was 480 +static const uint32 MAX_PP_MEMSPELL = 16; // was 12 +static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size +static const uint32 MAX_PP_AA_ARRAY = 300; +static const uint32 MAX_PP_DISCIPLINES = 200; // was 100 +static const uint32 MAX_GROUP_MEMBERS = 6; +static const uint32 MAX_RECAST_TYPES = 20; + +struct AdventureInfo { + uint32 QuestID; + uint32 NPCID; + bool in_use; + uint32 status; + bool ShowCompass; + uint32 Objetive;// can be item to collect,mobs to kill,boss to kill and someone to rescue. + uint32 ObjetiveValue;// number of items,or number of needed mob kills. + char text[512]; + uint8 type; + uint32 minutes; + uint32 points; + float x; + float y; + uint32 zoneid; + uint32 zonedungeonid; +}; +/////////////////////////////////////////////////////////////////////////////// + + +/* +** Color_Struct +** Size: 4 bytes +** Used for convenience +** Merth: Gave struct a name so gcc 2.96 would compile +** +*/ +struct Color_Struct +{ + union + { + struct + { + uint8 blue; + uint8 green; + uint8 red; + uint8 use_tint; // if there's a tint this is FF + } rgb; + uint32 color; + }; +}; + +struct CharSelectEquip { + //totally guessed; + uint32 equip0; + uint32 equip1; + uint32 equip2; + uint32 itemid; + uint32 equip3; + Color_Struct color; +}; + +struct CharacterSelectEntry_Struct { +/*0000*/ char name[1]; // Name null terminated +/*0000*/ uint8 class_; +/*0000*/ uint32 race; +/*0000*/ uint8 level; +/*0000*/ uint8 class_2; +/*0000*/ uint32 race2; +/*0000*/ uint16 zone; +/*0000*/ uint16 instance; +/*0000*/ uint8 gender; +/*0000*/ uint8 face; +/*0000*/ CharSelectEquip equip[9]; +/*0000*/ uint8 u15; // Seen FF +/*0000*/ uint8 u19; // Seen FF +/*0000*/ uint32 drakkin_tattoo; +/*0000*/ uint32 drakkin_details; +/*0000*/ uint32 deity; +/*0000*/ uint32 primary; +/*0000*/ uint32 secondary; +/*0000*/ uint8 haircolor; +/*0000*/ uint8 beardcolor; +/*0000*/ uint8 eyecolor1; +/*0000*/ uint8 eyecolor2; +/*0000*/ uint8 hairstyle; +/*0000*/ uint8 beard; +/*0000*/ uint8 char_enabled; +/*0000*/ uint8 tutorial; // Seen 1 for new char or 0 for existing +/*0000*/ uint32 drakkin_heritage; +/*0000*/ uint8 unknown1; // Seen 0 +/*0000*/ uint8 gohome; // Seen 0 for new char and 1 for existing +/*0000*/ uint32 LastLogin; +/*0000*/ uint8 unknown2; // Seen 0 +}; + +/* +** Character Selection Struct +** +*/ +struct CharacterSelect_Struct { +/*000*/ uint32 char_count; //number of chars in this packet +/*004*/ CharacterSelectEntry_Struct entries[0]; +}; + +struct Membership_Entry_Struct +{ +/*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300 +/*004*/ uint32 bitwise_entry; // Seen 16 to 65536 - Skips 4096 +/*008*/ +}; + +struct Membership_Setting_Struct +{ +/*000*/ uint32 setting_index; // 0, 1, or 2 +/*004*/ uint32 setting_id; // 0 to 21 +/*008*/ int32 setting_value; // All can be 0, 1, or -1 +/*012*/ +}; + +struct Membership_Details_Struct +{ +/*0000*/ uint32 membership_setting_count; // Seen 66 +/*0016*/ Membership_Setting_Struct settings[66]; +/*0012*/ uint32 race_entry_count; // Seen 15 +/*1044*/ Membership_Entry_Struct membership_races[15]; +/*0012*/ uint32 class_entry_count; // Seen 15 +/*1044*/ Membership_Entry_Struct membership_classes[15]; +/*1044*/ uint32 exit_url_length; // Length of the exit_url string (0 for none) +/*1048*/ //char exit_url[42]; // Upgrade to Silver or Gold Membership URL +/*1048*/ uint32 exit_url_length2; // Length of the exit_url2 string (0 for none) +/*0000*/ //char exit_url2[49]; // Upgrade to Gold Membership URL +}; + +struct Membership_Struct +{ +/*000*/ uint32 membership; // Seen 2 on Gold Account +/*004*/ uint32 races; // Seen ff ff 01 00 +/*008*/ uint32 classes; // Seen ff ff 01 01 +/*012*/ uint32 entrysize; // Seen 22 +/*016*/ int32 entries[22]; // Most -1, 1, and 0 for Gold Status +/*104*/ +}; + + +/* +* Visible equiptment. +* Size: 20 Octets +*/ +struct EquipStruct { +/*00*/ uint32 equip0; +/*04*/ uint32 equip1; +/*08*/ uint32 equip2; +/*12*/ uint32 itemId; +/*16*/ uint32 equip3; // Same as equip0? +/*20*/ +}; + + +/* +** Generic Spawn Struct +** Length: 897 Octets +** Used in: +** spawnZoneStruct +** dbSpawnStruct +** petStruct +** newSpawnStruct +*/ +/* +showeq -> eqemu +sed -e 's/_t//g' -e 's/seto_0xFF/set_to_0xFF/g' +*/ + +struct Spawn_Struct_Bitfields +{ +/*00*/ unsigned gender:2; // Gender (0=male, 1=female, 2=monster) +/*02*/ unsigned ispet:1; // Guessed based on observing live spawns +/*03*/ unsigned afk:1; // 0=no, 1=afk +/*04*/ unsigned anon:2; // 0=normal, 1=anon, 2=roleplay +/*06*/ unsigned gm:1; +/*06*/ unsigned sneak:1; +/*08*/ unsigned lfg:1; +/*09*/ unsigned unknown09:1; +/*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which +/*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below +/*12*/ unsigned invis2:1; // This one also make the NPC/PC invis +/*13*/ unsigned invis3:1; // This one also make the NPC/PC invis +/*14*/ unsigned invis4:1; // This one also make the NPC/PC invis +/*15*/ unsigned invis6:1; // This one also make the NPC/PC invis +/*16*/ unsigned invis7:1; // This one also make the NPC/PC invis +/*17*/ unsigned invis8:1; // This one also make the NPC/PC invis +/*18*/ unsigned invis9:1; // This one also make the NPC/PC invis +/*19*/ unsigned invis10:1; // This one also make the NPC/PC invis +/*20*/ unsigned invis11:1; // This one also make the NPC/PC invis +/*21*/ unsigned invis12:1; // This one also make the NPC/PC invis +/*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF2 +/*23*/ unsigned showhelm:1; +/*24*/ unsigned unknown24:1; // Prefixes name with ! +/*25*/ unsigned trader:1; +/*26*/ unsigned unknown26:1; +/*27*/ unsigned targetable:1; +/*28*/ unsigned targetable_with_hotkey:1; +/*29*/ unsigned showname:1; +/*30*/ unsigned unknown30:1; +/*30*/ unsigned untargetable:1; // Untargetable with mouse + /* + // Unknown in RoF2 + unsigned betabuffed:1; + unsigned buyer:1; + unsigned buyer:1; + */ +}; + +/* +struct Spawn_Struct_Position +{ + signed padding0000:12; + signed y:19; + signed padding0001:1; + + signed deltaX:13; // change in x + signed deltaHeading:10;// change in heading + signed padding0008:9; + + signed deltaY:13; + signed z:19; + + signed x:19; + signed animation:10; // animation + signed padding0016:3; + + signed heading:12; + signed deltaZ:13; // change in z + signed padding0020:7; +}; +*/ + +struct Spawn_Struct_Position +{ + signed padding0000:12; + signed y:19; + signed padding0001:1; + + signed deltaZ:13; // change in z + signed deltaX:13; // change in x + signed padding0008:6; + + signed x:19; + signed heading:12; + signed padding0016:1; + + signed deltaHeading:10;// change in heading + signed z:19; + signed padding0020:3; + + signed animation:10; // animation + signed deltaY:13; + signed padding0023:9; +}; + +struct Spawn_Struct +{ +// Note this struct is not used as such, it is here for reference. As the struct is variable sized, the packets +// are constructed in Live.cpp +// +/*0000*/ char name[1]; //name[64]; +/*0000*/ //uint8 nullterm1; // hack to null terminate name +/*0064*/ uint32 spawnId; +/*0068*/ uint8 level; +/*0069*/ float unknown1; +/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse + Spawn_Struct_Bitfields Bitfields; +/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable +/*0000*/ float unknown3; // seen -1 +/*0000*/ float unknown4; +/*0000*/ float size; +/*0000*/ uint8 face; +/*0000*/ float walkspeed; +/*0000*/ float runspeed; +/*0000*/ uint32 race; +/*0000*/ uint8 showname; // for body types - was charProperties +/*0000*/ uint32 bodytype; +/*0000*/ //uint32 bodytype2; // this is only present if charProperties==2 + // are there more than two possible properties? +/*0000*/ uint8 curHp; +/*0000*/ uint8 haircolor; +/*0000*/ uint8 beardcolor; +/*0000*/ uint8 eyecolor1; +/*0000*/ uint8 eyecolor2; +/*0000*/ uint8 hairstyle; +/*0000*/ uint8 beard; +/*0000*/ uint32 drakkin_heritage; +/*0000*/ uint32 drakkin_tattoo; +/*0000*/ uint32 drakkin_details; +/*0000*/ uint8 statue; // was holding +/*0000*/ uint32 deity; +/*0000*/ uint32 guildID; +/*0000*/ uint32 guildrank; // 0=member, 1=officer, 2=leader, -1=not guilded +/*0000*/ uint8 class_; +/*0000*/ uint8 pvp; // 0 = normal name color, 2 = PVP name color +/*0000*/ uint8 StandState; // stand state - 0x64 for normal animation +/*0000*/ uint8 light; +/*0000*/ uint8 flymode; +/*0000*/ uint8 equip_chest2; +/*0000*/ uint8 unknown9; +/*0000*/ uint8 unknown10; +/*0000*/ uint8 helm; +/*0000*/ char lastName[1]; +/*0000*/ //uint8 lastNameNull; //hack! +/*0000*/ uint32 aatitle; // 0=none, 1=general, 2=archtype, 3=class was AARank +/*0000*/ uint8 unknown12; +/*0000*/ uint32 petOwnerId; +/*0000*/ uint8 unknown13; +/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed +/*0000*/ uint32 unknown15; +/*0000*/ uint32 unknown16; +/*0000*/ uint32 unknown17; +/*0000*/ //uint8 unknownRoF23; +/*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 + }; + +// 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*/ //char title[0]; // only read if(hasTitleOrSuffix & 4) +/*0000*/ //char suffix[0]; // only read if(hasTitleOrSuffix & 8) + char unknown20[8]; + uint8 IsMercenary; // If NPC == 1 and this == 1, then the NPC name is Orange. +/*0000*/ char unknown21[55]; +}; + + +/* +** Generic Spawn Struct +** Fields from old struct not yet found: +** uint8 traptype; // 65 is disarmable trap, 66 and 67 are invis triggers/traps +** uint8 is_pet; // 0=no, 1=yes +** uint8 afk; // 0=no, 1=afk +** uint8 is_npc; // 0=no, 1=yes +** uint8 max_hp; // (name prolly wrong)takes on the value 100 for players, 100 or 110 for NPCs and 120 for PC corpses... +** uint8 guildrank; // 0=normal, 1=officer, 2=leader +** uint8 eyecolor2; //not sure, may be face +** uint8 aaitle; // 0=none, 1=general, 2=archtype, 3=class +*/ + +/* +** New Spawn +** Length: 176 Bytes +** OpCode: 4921 +*/ +struct NewSpawn_Struct +{ + struct Spawn_Struct spawn; // Spawn Information +}; + + +/* +** Client Zone Entry struct +** Length: 68 Octets +** OpCode: ZoneEntryCode (when direction == client) +*/ +struct ClientZoneEntry_Struct { +/*00*/ uint32 unknown00; // ***Placeholder +/*04*/ char char_name[64]; // Player firstname [32] +/*68*/ uint32 unknown68; +/*72*/ uint32 unknown72; +}; + + +/* +** Server Zone Entry Struct +** Length: 452 Bytes +** OPCodes: OP_ServerZoneEntry +** +*/ +struct ServerZoneEntry_Struct //Adjusted from SEQ Everquest.h Struct +{ + struct NewSpawn_Struct player; +}; + + +//New Zone Struct - Size: 948 +struct NewZone_Struct { +/*0000*/ char char_name[64]; // Character Name +/*0064*/ char zone_short_name[32]; // Zone Short Name +/*0096*/ char unknown0096[96]; +/*0192*/ char zone_long_name[278]; // Zone Long Name +/*0470*/ uint8 ztype; // Zone type (usually FF) +/*0471*/ uint8 fog_red[4]; // Zone fog (red) +/*0475*/ uint8 fog_green[4]; // Zone fog (green) +/*0479*/ uint8 fog_blue[4]; // Zone fog (blue) +/*0483*/ uint8 unknown323; +/*0484*/ float fog_minclip[4]; +/*0500*/ float fog_maxclip[4]; +/*0516*/ float gravity; +/*0520*/ uint8 time_type; +/*0521*/ uint8 rain_chance[4]; +/*0525*/ uint8 rain_duration[4]; +/*0529*/ uint8 snow_chance[4]; +/*0533*/ uint8 snow_duration[4]; +/*0537*/ uint8 unknown537[33]; +/*0570*/ uint8 sky; // Sky Type +/*0571*/ uint8 unknown571[13]; // ***Placeholder +/*0584*/ float zone_exp_multiplier; // Experience Multiplier +/*0588*/ float safe_y; // Zone Safe Y +/*0592*/ float safe_x; // Zone Safe X +/*0596*/ float safe_z; // Zone Safe Z +/*0600*/ float min_z; // Guessed - NEW - Seen 0 +/*0604*/ float max_z; // Guessed +/*0608*/ float underworld; // Underworld, min z (Not Sure?) +/*0612*/ float minclip; // Minimum View Distance +/*0616*/ float maxclip; // Maximum View DIstance +/*0620*/ uint8 unknown620[84]; // ***Placeholder +/*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version. +/*0800*/ int32 unknown800; //seen -1 +/*0804*/ char unknown804[40]; // +/*0844*/ int32 unknown844; //seen 600 +/*0848*/ int32 unknown848; +/*0852*/ uint16 zone_id; +/*0854*/ uint16 zone_instance; +/*0856*/ char unknown856[20]; +/*0876*/ uint32 SuspendBuffs; +/*0880*/ uint32 unknown880; // Seen 50 +/*0884*/ uint32 unknown884; // Seen 10 +/*0888*/ uint8 unknown888; // Seen 1 +/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj) +/*0890*/ uint8 unknown890; // Seen 1 +/*0891*/ uint8 unknown891; // Seen 0 +/*0892*/ uint8 unknown892; // Seen 0 +/*0893*/ uint8 unknown893; // Seen 0 - 00 +/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off +/*0895*/ uint8 unknown895; // Seen 0 - 00 +/*0896*/ uint32 unknown896; // Seen 180 +/*0900*/ uint32 unknown900; // Seen 180 +/*0904*/ uint32 unknown904; // Seen 180 +/*0908*/ uint32 unknown908; // Seen 2 +/*0912*/ uint32 unknown912; // Seen 2 +/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16 +/*0920*/ uint32 unknown920; // Seen 0 +/*0924*/ uint32 unknown924; // Seen 0 +/*0928*/ uint32 unknown928; // Seen 0 +/*0932*/ int32 unknown932; // Seen -1 +/*0936*/ int32 unknown936; // Seen -1 +/*0940*/ uint32 unknown940; // Seen 0 +/*0944*/ float unknown944; // Seen 1.0 +/*0948*/ +}; + + +/* +** Memorize Spell Struct +** Length: 16 Bytes +** +*/ +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; +}; + +/* +** Make Charmed Pet +** Length: 12 Bytes +** +*/ +struct Charm_Struct { +/*00*/ uint32 owner_id; +/*04*/ uint32 pet_id; +/*08*/ uint32 command; // 1: make pet, 0: release pet +/*12*/ +}; + +struct InterruptCast_Struct +{ + uint32 spawnid; + uint32 messageid; + //char message[0]; +}; + +struct DeleteSpell_Struct +{ +/*000*/int16 spell_slot; +/*002*/uint8 unknowndss002[2]; +/*004*/uint8 success; +/*005*/uint8 unknowndss006[3]; +/*008*/ +}; + +struct ManaChange_Struct +{ + uint32 new_mana; // New Mana AMount + uint32 stamina; + uint32 spell_id; + uint32 unknown12; + uint32 unknown16; +}; + +struct SwapSpell_Struct +{ + uint32 from_slot; + uint32 to_slot; +}; + +struct BeginCast_Struct +{ +/*000*/ uint32 spell_id; +/*004*/ uint16 caster_id; +/*006*/ uint32 cast_time; // in miliseconds +/*010*/ +}; + +struct CastSpell_Struct +{ +/*00*/ uint32 slot; +/*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]; +/*44*/ +}; + +/* +** SpawnAppearance_Struct +** Changes client appearance for all other clients in zone +** Size: 8 bytes +** Used in: OP_SpawnAppearance +** +*/ +struct SpawnAppearance_Struct +{ +/*0000*/ uint16 spawn_id; // ID of the spawn +/*0002*/ uint16 type; // Values associated with the type +/*0004*/ uint32 parameter; // Type of data sent +/*0008*/ +}; + +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*/ uint32 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*/ uint32 duration; +/*016*/ uint32 unknown016; +/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages +/*024*/ uint32 counters; +/*028*/ uint8 unknown0028[60]; +/*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*/ uint32 duration; +/*020*/ uint32 playerId; // Global player ID? +/*024*/ uint32 num_hits; +/*028*/ uint8 unknown0028[64]; +/*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*/ uint32 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; +/*04*/ uint32 EntityID; +/*08*/ +}; + +#if 0 +// not in use +struct BuffIconEntry_Struct { +/*000*/ uint32 buff_slot; +/*004*/ uint32 spell_id; +/*008*/ uint32 tics_remaining; +/*012*/ uint32 num_hits; +// char name[0]; caster name is also here sometimes +// uint8 unknownend; 1 when single, 0 when all opposite of all_buffs? +}; + +// not in use +struct BuffIcon_Struct { +/*000*/ uint32 entity_id; +/*004*/ uint32 unknown004; +/*008*/ uint8 all_buffs; // 1 when updating all buffs, 0 when doing one +/*009*/ uint16 count; +/*011*/ BuffIconEntry_Struct entires[0]; +}; +#endif + +struct GMTrainee_Struct +{ + /*000*/ uint32 npcid; + /*004*/ uint32 playerid; + /*008*/ uint32 skills[PACKET_SKILL_ARRAY_SIZE]; + /*408*/ uint8 unknown408[40]; + /*448*/ +}; + +struct GMTrainEnd_Struct +{ + /*000*/ uint32 npcid; + /*004*/ uint32 playerid; + /*008*/ +}; + +struct GMSkillChange_Struct { +/*000*/ uint16 npcid; +/*002*/ uint8 unknown1[2]; // something like PC_ID, but not really. stays the same thru the session though +/*002*/ uint16 skillbank; // 0 if normal skills, 1 if languages +/*002*/ uint8 unknown2[2]; +/*008*/ uint16 skill_id; +/*010*/ uint8 unknown3[2]; +/*012*/ +}; + +struct GMTrainSkillConfirm_Struct { // SoF+ only +/*000*/ uint32 SkillID; +/*004*/ uint32 Cost; +/*008*/ uint8 NewSkill; // Set to 1 for 'You have learned the basics' message. +/*009*/ char TrainerName[64]; +/*073*/ uint8 Unknown073[3]; +/*076*/ +}; + +struct ConsentResponse_Struct { + char grantname[64]; + char ownername[64]; + uint8 permission; + char zonename[64]; +}; + +/* +** Name Generator Struct +** Length: 72 bytes +** OpCode: 0x0290 +*/ +struct NameGeneration_Struct +{ +/*0000*/ uint32 race; +/*0004*/ uint32 gender; +/*0008*/ char name[64]; +/*0072*/ +}; + +/* +** Character Creation struct +** Length: 96 Bytes +*/ +struct CharCreate_Struct +{ +/*0000*/ uint32 gender; +/*0004*/ uint32 race; +/*0008*/ uint32 class_; +/*0012*/ uint32 deity; +/*0016*/ uint32 start_zone; +/*0020*/ uint32 haircolor; +/*0024*/ uint32 beard; +/*0028*/ uint32 beardcolor; +/*0032*/ uint32 hairstyle; +/*0036*/ uint32 face; +/*0040*/ uint32 eyecolor1; +/*0044*/ uint32 eyecolor2; +/*0048*/ uint32 drakkin_heritage; +/*0052*/ uint32 drakkin_tattoo; +/*0056*/ uint32 drakkin_details; +/*0060*/ uint32 STR; +/*0064*/ uint32 STA; +/*0068*/ uint32 AGI; +/*0073*/ uint32 DEX; +/*0076*/ uint32 WIS; +/*0080*/ uint32 INT; +/*0084*/ uint32 CHA; +/*0088*/ uint32 tutorial; +/*0092*/ uint32 unknown0092; +/*0096*/ +}; + +/* +** Character Creation struct +** Length: 0 Bytes +** OpCode: 0x +*/ +struct CharCreate_Struct_Temp //Size is now 0 +{ +}; + +/* + *Used in PlayerProfile + */ +struct AA_Array +{ + uint32 AA; + uint32 value; + uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live +}; + +struct Disciplines_Struct { + uint32 values[MAX_PP_DISCIPLINES]; +}; + + + +struct Tribute_Struct { + uint32 tribute; + uint32 tier; +}; + +struct BandolierItem_Struct { + char item_name[1]; // Variable Length + uint32 item_id; + uint32 icon; +}; + +//len = 72 +struct BandolierItem_Struct_Old { + uint32 item_id; + uint32 icon; + char item_name[64]; +}; + +//len = 320 +enum { //bandolier item positions + bandolierMainHand = 0, + bandolierOffHand, + bandolierRange, + bandolierAmmo +}; +struct Bandolier_Struct { + char name[1]; // Variable Length + BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS]; +}; + +struct Bandolier_Struct_Old { + char name[32]; + BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS]; +}; + +struct PotionBelt_Struct { + BandolierItem_Struct items[MAX_POTIONS_IN_BELT]; +}; + +struct GroupLeadershipAA_Struct { + union { + struct { + uint32 groupAAMarkNPC; + uint32 groupAANPCHealth; + uint32 groupAADelegateMainAssist; + uint32 groupAADelegateMarkNPC; + uint32 groupAA4; + uint32 groupAA5; + uint32 groupAAInspectBuffs; + uint32 groupAA7; + uint32 groupAASpellAwareness; + uint32 groupAAOffenseEnhancement; + uint32 groupAAManaEnhancement; + uint32 groupAAHealthEnhancement; + uint32 groupAAHealthRegeneration; + uint32 groupAAFindPathToPC; + uint32 groupAAHealthOfTargetsTarget; + uint32 groupAA15; + }; + uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + }; +}; + +struct RaidLeadershipAA_Struct { + union { + struct { + uint32 raidAAMarkNPC; + uint32 raidAANPCHealth; + uint32 raidAADelegateMainAssist; + uint32 raidAADelegateMarkNPC; + uint32 raidAA4; + uint32 raidAA5; + uint32 raidAA6; + uint32 raidAASpellAwareness; + uint32 raidAAOffenseEnhancement; + uint32 raidAAManaEnhancement; + uint32 raidAAHealthEnhancement; + uint32 raidAAHealthRegeneration; + uint32 raidAAFindPathToPC; + uint32 raidAAHealthOfTargetsTarget; + uint32 raidAA14; + uint32 raidAA15; + }; + uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + }; +}; + +struct LeadershipAA_Struct { + union { + struct { + GroupLeadershipAA_Struct group; + RaidLeadershipAA_Struct raid; + }; + uint32 ranks[MAX_LEADERSHIP_AA_ARRAY]; + }; +}; + + /** +* A bind point. +* Size: 20 Octets +*/ +struct BindStruct { + /*000*/ uint32 zoneId; + /*004*/ float x; + /*008*/ float y; + /*012*/ float z; + /*016*/ float heading; + /*020*/ +}; + + +// Player Profile - Variable Length as of Oct 12 2012 patch +struct PlayerProfile_Struct +{ +/*00000*/ uint32 checksum; // +/*00004*/ uint32 checksum_size; // Value = ( Packet Size - 9 ) +/*00008*/ uint8 checksum_byte; // +/*00009*/ uint8 unknown_rof1[3]; // +/*00012*/ uint32 unknown_rof2; // +/*00016*/ uint8 gender; // Player Gender - 0 Male, 1 Female +/*00017*/ uint32 race; // Player race +/*00021*/ uint8 class_; // Player class +/*00022*/ uint8 level; // Level of player +/*00023*/ uint8 level1; // Level of player (again?) +/*00024*/ uint32 bind_count; // Seen 5 +/*00028*/ BindStruct binds[5]; // Bind points (primary is first) 5 fields = 100 bytes +/*00128*/ uint32 deity; // deity +/*00132*/ uint32 unknown_rof3; // Maybe Drakkin Heritage? +/*00136*/ uint32 unknown4_count; // Seen 10 +/*00140*/ uint32 unknown_rof4[10]; // Seen all 0s +/*00180*/ uint32 equip_count; // Seen 22 +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 + // 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 + } equip; + /*00184*/ EquipStruct equipment[22]; +}; +/*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 +/*00848*/ uint32 tint_count2; // Seen 9 +/*00852*/ Color_Struct item_tint2[9]; // RR GG BB 00 +/*00888*/ uint8 haircolor; // Player hair color +/*00889*/ uint8 beardcolor; // Player beard color +/*00890*/ uint32 unknown_rof5; // +/*00894*/ uint8 eyecolor1; // Player left eye color +/*00895*/ uint8 eyecolor2; // Player right eye color +/*00896*/ uint8 hairstyle; // Player hair style +/*00897*/ uint8 beard; // Player beard type +/*00898*/ uint8 face; // Player face +/*00899*/ uint32 drakkin_heritage; // +/*00903*/ uint32 drakkin_tattoo; // +/*00907*/ uint32 drakkin_details; // +/*00911*/ uint8 unknown_rof6; // +/*00912*/ int8 unknown_rof7; // seen -1 +/*00913*/ uint8 unknown_rof8; // +/*00914*/ uint8 unknown_rof9; // +/*00915*/ uint8 unknown_rof10; // Seen 1 or 0 (on a female?) +/*00916*/ float height; // Seen 7.0 (barb), 5.0 (woodelf), 5.5 (halfelf) +/*00920*/ float unknown_rof11; // Seen 3.0 +/*00924*/ float unknown_rof12; // Seen 2.5 +/*00928*/ float unknown_rof13; // Seen 5.5 +/*00932*/ uint32 primary; // Seen 10528 +/*00936*/ uint32 secondary; // Seen 10006 +/*00940*/ uint32 points; // Unspent Practice points - RELOCATED??? +/*00944*/ uint32 mana; // Current mana +/*00948*/ uint32 cur_hp; // Current HP without +HP equipment +/*00952*/ uint32 STR; // Strength - 6e 00 00 00 - 110 +/*00956*/ uint32 STA; // Stamina - 73 00 00 00 - 115 +/*00960*/ uint32 CHA; // Charisma - 37 00 00 00 - 55 +/*00964*/ uint32 DEX; // Dexterity - 50 00 00 00 - 80 +/*00968*/ uint32 INT; // Intelligence - 3c 00 00 00 - 60 +/*00972*/ uint32 AGI; // Agility - 5f 00 00 00 - 95 +/*00976*/ uint32 WIS; // Wisdom - 46 00 00 00 - 70 +/*00980*/ uint32 unknown_rof14[7]; // Probably base resists? +/*01008*/ uint32 aa_count; // Seen 300 +/*01012*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [300] 3600 bytes - AAs 12 bytes each +/*04612*/ uint32 skill_count; // Seen 100 +/*04616*/ uint32 skills[MAX_PP_SKILL]; // [100] 400 bytes - List of skills +/*05016*/ uint32 unknown15_count; // Seen 25 +/*05020*/ uint32 unknown_rof15[25]; // Most are 255 or 0 +/*05120*/ uint32 discipline_count; // Seen 200 +/*05124*/ Disciplines_Struct disciplines; // [200] 800 bytes Known disciplines +/*05924*/ uint32 timestamp_count; // Seen 20 +/*05928*/ uint32 timestamps[20]; // Unknown Unix Timestamps - maybe recast related? +/*06008*/ uint32 recast_count; // Seen 20 +/*06012*/ uint32 recastTimers[MAX_RECAST_TYPES];// [20] 80 bytes - Timers (UNIX Time of last use) +/*06092*/ uint32 timestamp2_count; // Seen 100 +/*06096*/ uint32 timestamps2[100]; // Unknown Unix Timestamps - maybe Skill related? +/*06496*/ uint32 spell_book_count; // Seen 720 +/*06500*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes] +/*09380*/ uint32 mem_spell_count; // Seen 16 +/*09384*/ int32 mem_spells[MAX_PP_MEMSPELL]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s +/*09448*/ uint32 unknown16_count; // Seen 13 +/*09452*/ uint32 unknown_rof16[13]; // Possibly spell or buff related +/*09504*/ uint8 unknown_rof17; // Seen 0 or 8 +/*09505*/ uint32 buff_count; // Seen 42 +/*09509*/ SpellBuff_Struct buffs[BUFF_COUNT]; // [42] 3360 bytes - Buffs currently on the player (42 Max) - (Each Size 80) +/*12869*/ uint32 platinum; // Platinum Pieces on player +/*12873*/ uint32 gold; // Gold Pieces on player +/*12877*/ uint32 silver; // Silver Pieces on player +/*12881*/ uint32 copper; // Copper Pieces on player +/*12885*/ uint32 platinum_cursor; // Platinum Pieces on cursor +/*12889*/ uint32 gold_cursor; // Gold Pieces on cursor +/*12893*/ uint32 silver_cursor; // Silver Pieces on cursor +/*12897*/ uint32 copper_cursor; // Copper Pieces on cursor +/*12901*/ uint32 intoxication; // Alcohol level (in ticks till sober?) - Position Guessed +/*12905*/ uint32 toxicity; // Potion Toxicity (15=too toxic, each potion adds 3) - Position Guessed +/*12909*/ uint32 unknown_rof19; // +/*12913*/ uint32 thirst_level; // Drink (ticks till next drink) - Position Guessed +/*12917*/ uint32 hunger_level; // Food (ticks till next eat) - Position Guessed +/*12921*/ uint32 aapoints_spent; // Number of spent AA points +/*12925*/ uint32 aapoint_count; // Seen 5 - Unsure what this is exactly +/*12929*/ uint32 aapoints_assigned; // Number of Assigned AA points - Seen 206 (total of the 4 fields below) +/*12933*/ uint32 aa_spent_general; // Seen 63 +/*12937*/ uint32 aa_spent_archetype; // Seen 40 +/*12941*/ uint32 aa_spent_class; // Seen 103 +/*12945*/ uint32 aa_spent_special; // Seen 0 +/*12949*/ uint32 aapoints; // Unspent AA points - Seen 1 +/*12953*/ uint16 unknown_rof20; // +/*12955*/ uint32 bandolier_count; // Seen 20 +/*12959*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [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 +/*13752*/ int32 hp_total; // Guessed - Seen 20 on level 1 new mage +/*13756*/ int32 endurance_total; // Guessed - Seen 20 on level 1 new mage +/*13760*/ int32 mana_total; // Guessed - Only seen on casters so far - Matches above field if caster +/*13764*/ uint32 unknown_rof22[12]; // Same for all seen PPs - 48 bytes: +/* +19 00 00 00 19 00 00 00 19 00 00 00 0f 00 00 00 +0f 00 00 00 0f 00 00 00 0f 00 00 00 1f 85 eb 3e +33 33 33 3f 08 00 00 00 02 00 00 00 01 00 00 00 +*/ +/*13812*/ uint32 unknown_rof23; // Seen 5, 19, and 20 in examples +/*13816*/ uint32 unknown_rof24[4]; // +/*13832*/ uint32 unknown_rof25[2]; // Seen random numbers from 0 to 2165037 +/*13840*/ uint32 unknown_rof26; // Seen 106 +//END SUB-STRUCT used for shrouding. +/*13844*/ uint32 name_str_len; // Seen 64 +/*13848*/ char name[64]; // Name of player - 19960 for Live 1180 difference +/*13912*/ uint32 last_name_str_len; // Seen 32 +/*13916*/ char last_name[32]; // Last name of player +/*13948*/ uint32 birthday; // character birthday +/*13952*/ uint32 account_startdate; // Date the Account was started +/*13956*/ uint32 lastlogin; // character last save time +/*13960*/ uint32 timePlayedMin; // time character played +/*13964*/ uint32 timeentitledonaccount; +/*13968*/ uint32 expansions; // Bitmask for expansions ff 7f 00 00 - SoD +/*13972*/ uint32 language_count; // Seen 32 +/*13976*/ uint8 languages[MAX_PP_LANGUAGE]; // [32] 32 bytes - List of languages +/*14008*/ uint16 zone_id; // see zones.h +/*14010*/ uint16 zoneInstance; // Instance id +/*14012*/ float y; // Players y position (NOT positive about this switch) +/*14016*/ float x; // Players x position +/*14020*/ float z; // Players z position +/*14024*/ float heading; // Players heading +/*14028*/ uint32 air_remaining; // Air supply (seconds) +/*14032*/ int32 unknown_rof28; // Seen -1 +/*14036*/ uint8 unknown_rof29[10]; // +/*14046*/ uint32 unknown_rof30; // Random large number or 0 +/*14050*/ uint32 unknown_rof31; // +/*14054*/ uint32 unknown32_count; // Seen 5 +/*14058*/ uint8 unknown_rof32[29]; // +/*14087*/ uint32 unknown33_count; // Seen 32 for melee/hybrid and 21 for druid, 34 for mage +/*14091*/ uint32 unknown_rof33[64]; // Struct contains 2 ints, so double 32 count (Variable Sized) +// Position Varies after this point - Really starts varying at Bandolier names, but if no names set it starts here +/*00000*/ int32 unknown_rof34; // Seen -1 +/*00000*/ int32 unknown_rof35; // Seen -1 +/*00000*/ uint8 unknown_rof36[18]; // +/*00000*/ uint32 unknown37_count; // Seen 5 +/*00000*/ int32 unknown_rof37[10]; // Alternates -1 and 0 - Struct contains 2 ints +/*00000*/ uint32 unknown38_count; // Seen 10 +/*00000*/ int32 unknown_rof38[20]; // Alternates -1 and 0 - Struct contains 2 ints +/*00000*/ uint8 unknown_rof39[137]; // +/*00000*/ float unknown_rof40; // Seen 1.0 +/*00000*/ uint32 unknown_rof41[9]; // +/*00000*/ uint32 unknown_rof42; // Seen 0 or 1 +/*00000*/ uint32 unknown_string1_count; // Seen 64 +/*00000*/ char unknown_string1[64]; // +/*00000*/ uint8 unknown_rof43[30]; // +/*00000*/ uint32 unknown_string2_count; // Seen 64 +/*00000*/ char unknown_string2[64]; // +/*00000*/ uint32 unknown_string3_count; // Seen 64 +/*00000*/ char unknown_string3[64]; // +/*00000*/ uint32 unknown_rof44; // Seen 0 or 50 +/*00000*/ uint8 unknown_rof45[663]; // +/*00000*/ uint32 char_id; // Guessed based on char creation date and values +/*00000*/ uint8 unknown_rof46; // Seen 0 or 1 +/*00000*/ uint32 unknown_rof47; // Seen 6 +/*00000*/ uint32 unknown_rof48[13]; // Seen all 0s or some mix of ints and float? +/*00000*/ uint32 unknown_rof49; // Seen 64 +/*00000*/ uint8 unknown_rof50[256]; // Seen mostly 0s, but one example had a 2 in the middle +/*00000*/ uint32 unknown_rof51; // Seen 100 or 0 +/*00000*/ uint8 unknown_rof52[82]; // +/*00000*/ uint32 unknown_rof53; // Seen 50 + +uint8 unknown_rof54[1325]; // Unknown Section + +// Bottom of Struct: +/*00000*/ uint8 groupAutoconsent; // 0=off, 1=on +/*00000*/ uint8 raidAutoconsent; // 0=off, 1=on +/*00000*/ uint8 guildAutoconsent; // 0=off, 1=on +/*00000*/ uint8 unknown_rof55; // Seen 1 +/*00000*/ uint32 level3; // SoF looks at the level here to determine how many leadership AA you can bank. +/*00000*/ uint32 showhelm; // 0=no, 1=yes +/*00000*/ uint32 RestTimer; +/*00000*/ uint8 unknown_rof56; +/*00000*/ uint32 unknown_rof57; // Seen 49 +/*00000*/ uint8 unknown_rof58[1045]; // Seen all 0s + +/* +///////////////////// - Haven't identified the below fields in the PP yet +uint8 pvp; // 1=pvp, 0=not pvp +uint8 anon; // 2=roleplay, 1=anon, 0=not anon +uint8 gm; // 0=no, 1=yes (guessing!) +uint32 guild_id; // guildid +uint8 guildrank; // 0=member, 1=officer, 2=guildleader -1=no guild +uint32 guildbanker; +uint32 available_slots; +uint32 endurance; // Current endurance +uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 bytes Each * 16 = 64 bytes +uint32 abilitySlotRefresh; +/////////////////////// + +uint32 platinum_bank; // Platinum Pieces in Bank +uint32 gold_bank; // Gold Pieces in Bank +uint32 silver_bank; // Silver Pieces in Bank +uint32 copper_bank; // Copper Pieces in Bank +uint32 platinum_shared; // Shared platinum pieces + +uint32 autosplit; // 0 = off, 1 = on + +char groupMembers[MAX_GROUP_MEMBERS][64];// 384 all the members in group, including self +char groupLeader[64]; // Leader of the group ? +uint32 entityid; + +uint32 leadAAActive; // 0 = leader AA off, 1 = leader AA on +int32 ldon_points_guk; // Earned GUK points +int32 ldon_points_mir; // Earned MIR points +int32 ldon_points_mmc; // Earned MMC points +int32 ldon_points_ruj; // Earned RUJ points +int32 ldon_points_tak; // Earned TAK points +int32 ldon_points_available;// Available LDON points +float tribute_time_remaining;// Time remaining on tribute (millisecs) +uint32 career_tribute_points;// Total favor points for this char +uint32 tribute_points; // Current tribute points +uint32 tribute_active; // 0 = off, 1=on +Tribute_Struct tributes[MAX_PLAYER_TRIBUTES]; // [40] Current tribute loadout +double group_leadership_exp; // Current group lead exp points +double raid_leadership_exp; // Current raid lead AA exp points +uint32 group_leadership_points; // Unspent group lead AA points +uint32 raid_leadership_points; // Unspent raid lead AA points +LeadershipAA_Struct leader_abilities; // [128]Leader AA ranks 19332 + +uint32 PVPKills; +uint32 PVPDeaths; +uint32 PVPCurrentPoints; +uint32 PVPCareerPoints; +uint32 PVPBestKillStreak; +uint32 PVPWorstDeathStreak; +uint32 PVPCurrentKillStreak; +PVPStatsEntry_Struct PVPLastKill; // size 88 +PVPStatsEntry_Struct PVPLastDeath; // size 88 +uint32 PVPNumberOfKillsInLast24Hours; +PVPStatsEntry_Struct PVPRecentKills[50]; // size 4400 - 88 each +uint32 expAA; // Exp earned in current AA point +uint32 currentRadCrystals; // Current count of radiant crystals +uint32 careerRadCrystals; // Total count of radiant crystals ever +uint32 currentEbonCrystals; // Current count of ebon crystals +uint32 careerEbonCrystals; // Total count of ebon crystals ever +*/ + +}; + +/* +** Client Target Struct +** Length: 2 Bytes +** OpCode: 6221 +*/ +struct ClientTarget_Struct { +/*000*/ uint32 new_target; // Target ID +}; + +/* +** Target Rejection Struct +** Length: 12 Bytes +** OpCode: OP_TargetReject +*/ +struct TargetReject_Struct { +/*00*/ uint8 unknown00[12]; +}; + +struct PetCommand_Struct { +/*00*/ uint32 command; +/*04*/ uint32 unknown04; +/*08*/ uint32 unknown08; +}; + +/* +** Delete Spawn +** Length: 5 Bytes +** OpCode: OP_DeleteSpawn +*/ +struct DeleteSpawn_Struct +{ +/*00*/ uint32 spawn_id; // Spawn ID to delete +/*04*/ uint8 unknown04; // Seen 1 +/*05*/ +}; + +/* +** Channel Message received or sent +** Length: 144 Bytes + Variable Length + 1 +** OpCode: OP_ChannelMessage +** +*/ +struct ChannelMessage_Struct +{ +/*000*/ char targetname[64]; // Tell recipient +/*064*/ char sender[64]; // The senders name (len might be wrong) +/*128*/ uint32 language; // Language +/*132*/ uint32 chan_num; // Channel +/*136*/ uint32 cm_unknown4[2]; // ***Placeholder +/*144*/ uint32 skill_in_language; // The players skill in this language? might be wrong +/*148*/ char message[0]; // Variable length message +}; + +/* +** Special Message +** Length: 4 Bytes + Variable Text Length + 1 +** OpCode: OP_SpecialMesg +** +*/ +/* + Theres something wrong with this... example live packet: +Server->Client: [ Opcode: OP_SpecialMesg (0x0fab) Size: 244 ] + 0: 01 02 00 0A 00 00 00 09 - 05 00 00 42 61 72 73 74 | ...........Barst + 16: 72 65 20 53 6F 6E 67 77 - 65 61 76 65 72 00 7C F9 | re Songweaver.|. + 32: FF FF 84 FF FF FF 03 00 - 00 00 47 72 65 65 74 69 | ..........Greeti + +*/ +struct SpecialMesg_Struct +{ +/*00*/ char header[3]; // 04 04 00 <-- for #emote style msg +/*03*/ uint32 msg_type; // Color of text (see MT_*** below) +/*07*/ uint32 target_spawn_id; // Who is it being said to? +/*11*/ char sayer[1]; // Who is the source of the info - Was 1 +/*12*/ uint8 unknown12[12]; +/*24*/ char message[128]; // What is being said? - was 128 +}; + +/* +** When somebody changes what they're wearing +** or give a pet a weapon (model changes) +** Length: 19 Bytes +*/ +struct WearChange_Struct{ +/*000*/ uint16 spawn_id; +/*002*/ uint32 material; +/*006*/ uint32 unknown06; +/*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; +/*026*/ uint8 wear_slot_id; +/*027*/ +}; + +/* +** Type: Bind Wound Structure +** Length: 8 Bytes +*/ +//Fixed for 7-14-04 patch +struct BindWound_Struct +{ +/*000*/ uint16 to; // TargetID +/*002*/ uint16 unknown2; // ***Placeholder +/*004*/ uint16 type; +/*006*/ uint16 unknown6; +}; + + +/* +** Type: Zone Change Request (before hand) +** Length: 88 bytes +** OpCode: a320 +*/ + +struct ZoneChange_Struct { +/*000*/ char char_name[64]; // Character Name +/*064*/ uint16 zoneID; +/*066*/ uint16 instanceID; +/*068*/ uint32 Unknown068; +/*072*/ uint32 Unknown072; +/*076*/ float y; +/*080*/ float x; +/*084*/ float z; +/*088*/ uint32 zone_reason; //0x0A == death, I think +/*092*/ int32 success; // =0 client->server, =1 server->client, -X=specific error +/*096*/ uint32 Unknown096; // Not sure the extra 4 bytes goes here or earlier in the struct. +/*100*/ +}; + +struct RequestClientZoneChange_Struct { +/*000*/ uint16 zone_id; +/*002*/ uint16 instance_id; +/*004*/ uint32 unknown004; +/*008*/ float y; +/*012*/ float x; +/*016*/ float z; +/*020*/ float heading; +/*024*/ uint32 type; //unknown... values +/*032*/ uint8 unknown032[144]; +/*172*/ uint32 unknown172; +/*176*/ +}; + +struct Animation_Struct { +/*00*/ uint16 spawnid; +/*02*/ uint8 value; +/*03*/ uint8 action; +/*04*/ +}; + +// solar: this is what causes the caster to animate and the target to +// get the particle effects around them when a spell is cast +// also causes a buff icon +struct Action_Struct +{ +/*00*/ uint16 target; // id of target +/*02*/ uint16 source; // id of caster +/*04*/ uint16 level; // level of caster - Seen 0 +/*06*/ uint32 unknown06; +/*10*/ float instrument_mod; +/*14*/ uint32 bard_focus_id; // seen 0 +/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again +/*22*/ uint32 unknown22; +/*26*/ uint8 type; +/*27*/ uint32 damage; +/*31*/ uint16 unknown31; +/*33*/ uint32 spell; // spell id being cast +/*37*/ uint8 level2; // level of caster again? Or maybe the castee +/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time? +/*39*/ +}; + +// Starting with 2/21/2006, OP_Actions seem to come in pairs, duplicating +// themselves, with the second one with slightly more information. Maybe this +// has to do with buff blocking?? +struct ActionAlt_Struct +{ +/*00*/ uint16 target; // id of target +/*02*/ uint16 source; // id of caster +/*04*/ uint16 level; // level of caster - Seen 0 +/*06*/ uint32 unknown06; +/*10*/ float instrument_mod; +/*14*/ uint32 bard_focus_id; // seen 0 +/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again +/*22*/ uint32 unknown22; +/*26*/ uint8 type; +/*27*/ uint32 damage; +/*31*/ uint16 unknown31; +/*33*/ uint32 spell; // spell id being cast +/*37*/ uint8 level2; // level of caster again? Or maybe the castee +/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time? +/*39*/ uint32 unknown39; // New field to Underfoot - Seen 14 +/*43*/ uint8 unknown43; // New field to Underfoot - Seen 0 +/*44*/ uint8 unknown44; // New field to Underfoot - Seen 17 +/*45*/ uint8 unknown45; // New field to Underfoot - Seen 0 +/*46*/ int32 unknown46; // New field to Underfoot - Seen -1 +/*50*/ uint32 unknown50; // New field to Underfoot - Seen 0 +/*54*/ uint16 unknown54; // New field to Underfoot - Seen 0 +/*56*/ +}; + +// solar: this is what prints the You have been struck. and the regular +// melee messages like You try to pierce, etc. It's basically the melee +// and spell damage message +struct CombatDamage_Struct +{ +/* 00 */ uint16 target; +/* 02 */ uint16 source; +/* 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] +/* 30 */ +}; + + +/* +** Consider Struct +** Length: 20 Bytes +*/ +struct Consider_Struct{ +/*000*/ uint32 playerid; // PlayerID +/*004*/ uint32 targetid; // TargetID +/*008*/ uint32 faction; // Faction +/*012*/ uint32 level; // Level +/*016*/ uint8 pvpcon; // Pvp con flag 0/1 +/*017*/ uint8 unknown017[3]; // +/*020*/ +}; + +/* +** Spawn Death Blow +** Length: 32 Bytes +** OpCode: 0114 +*/ +struct Death_Struct +{ +/*000*/ uint32 spawn_id; +/*004*/ uint32 killer_id; +/*008*/ uint32 corpseid; // was corpseid +/*012*/ uint32 attack_skill; // was type +/*016*/ uint32 spell_id; +/*020*/ uint32 bindzoneid; //bindzoneid? +/*024*/ uint32 damage; +/*028*/ uint32 unknown028; +}; + +struct BecomeCorpse_Struct { + uint32 spawn_id; + float y; + float x; + float z; +}; + +struct ZonePlayerToBind_Struct { +/*000*/ uint16 bind_zone_id; +/*002*/ uint16 bind_instance_id; +/*004*/ float x; +/*008*/ float y; +/*012*/ float z; +/*016*/ float heading; +/*020*/ char zone_name[1]; // Or "Bind Location" +/*000*/ uint8 unknown021; // Seen 1 - Maybe 0 would be to force a rezone and 1 is just respawn +/*000*/ uint32 unknown022; // Seen 32 or 59 +/*000*/ uint32 unknown023; // Seen 0 +/*000*/ uint32 unknown024; // Seen 21 or 43 +}; + +struct ZonePlayerToBindHeader_Struct +{ + /*000*/ uint16 bind_zone_id; + /*002*/ uint16 bind_instance_id; + /*004*/ float x; + /*008*/ float y; + /*012*/ float z; + /*016*/ float heading; + /*020*/ char zone_name[1]; // Or "Bind Location" +}; + +struct ZonePlayerToBindFooter_Struct +{ + /*000*/ uint8 unknown021; // Seen 1 - Maybe 0 would be to force a rezone and 1 is just respawn + /*000*/ uint32 unknown022; // Seen 32 or 59 + /*000*/ uint32 unknown023; // Seen 0 + /*000*/ uint32 unknown024; // Seen 21 or 43 +}; + +typedef struct { +/*000*/ uint32 bind_number; // Number of this bind in the iteration +/*004*/ uint32 bind_zone_id; // ID of the zone for this bind point or resurect point +/*008*/ float x; // X loc for this bind point +/*012*/ float y; // Y loc for this bind point +/*016*/ float z; // Z loc for this bind point +/*020*/ float heading; // Heading for this bind point +/*024*/ char bind_zone_name[1]; // Or "Bind Location" or "Resurrect" +/*000*/ uint8 validity; // 0 = valid choice, 1 = not a valid choice at this time (resurrection) +} RespawnOptions_Struct; + +struct RespawnWindow_Struct { +/*000*/ uint32 unknown000; // Seen 0 +/*004*/ uint32 time_remaining; // Total time before respawn in milliseconds +/*008*/ uint32 unknown008; // Seen 0 +/*012*/ uint32 total_binds; // Total Bind Point Options? - Seen 2 +/*016*/ RespawnOptions_Struct bind_points; +// First bind point is "Bind Location" and the last one is "Ressurect" +}; + + +/* +** Spawn position update - Size: 22 +** Struct sent from server->client to update position of +** another spawn's position update in zone (whether NPC or PC) +** +*/ +struct PlayerPositionUpdateServer_Struct +{ + uint16 spawn_id; + uint16 spawnId2; + signed padding0004:12; + signed y_pos:19; // y coord + unsigned padding:1; + signed delta_z:13; // change in z + signed delta_x:13; // change in x + signed padding0008:6; + signed x_pos:19; // x coord + unsigned heading:12; // heading + signed padding0016:1; + signed delta_heading:10; // change in heading + signed z_pos:19; // z coord + signed padding0020:3; + signed animation:10; // animation + signed delta_y:13; // change in y + signed padding0024:9; +}; + +/* +** Player position update - Size: 40 +** Struct sent from client->server to update +** player position on server +** +*/ +struct PlayerPositionUpdateClient_Struct +{ + uint16 sequence; // increments one each packet - Verified + uint16 spawn_id; // Player's spawn id + uint8 unknown0004[6]; // ***Placeholder + float delta_x; // Change in x + unsigned heading:12; // Directional heading + unsigned padding0040:20; // ***Placeholder + float x_pos; // x coord (2nd loc value) + float delta_z; // Change in z + float z_pos; // z coord (3rd loc value) + float y_pos; // y coord (1st loc value) + unsigned animation:10; // ***Placeholder + unsigned padding0024:22; // animation + float delta_y; // Change in y + signed delta_heading:10; // change in heading + unsigned padding0041:22; // ***Placeholder +}; + +/* +** Spawn HP Update +** Length: 10 Bytes +** OpCode: OP_HPUpdate +*/ +struct SpawnHPUpdate_Struct +{ +/*00*/ int16 spawn_id; +/*02*/ uint32 cur_hp; +/*06*/ int32 max_hp; +/*10*/ +}; + +/* +** SendExpZonein +** Length: 152 Bytes +** OpCode: OP_SendExpZonein +*/ +struct SendExpZonein_Struct +{ +/*0000*/ uint16 spawn_id; // ID of the spawn +/*0002*/ uint16 type; // Values associated with the type +/*0004*/ uint32 parameter; // Type of data sent +/*0008*/ uint32 exp; // Current experience ratio from 0 to 330 +/*0012*/ uint32 expAA; +/*0016*/ uint8 unknown0016[4]; +/*0020*/ char name[64]; +/*0084*/ char last_name[64]; +/*00148*/ uint32 unknown132; +/*00152*/ +}; + +/* +** SendExpZonein +** Length: 0 Bytes +** OpCode: OP_SendExpZonein +*/ +//struct SendExpZonein_Struct {}; + +struct SpawnHPUpdate_Struct2 +{ +/*01*/ int16 spawn_id; +/*00*/ uint8 hp; +}; +/* +** Stamina +** Length: 8 Bytes +** OpCode: 5721 +*/ +struct Stamina_Struct { +/*00*/ uint32 food; // (low more hungry 127-0) +/*02*/ uint32 water; // (low more thirsty 127-0) +}; + +/* +** Level Update +** Length: 12 Bytes +*/ +struct LevelUpdate_Struct +{ +/*00*/ uint32 level; // New level +/*04*/ uint32 level_old; // Old level +/*08*/ uint32 exp; // Current Experience +}; + +/* +** Experience Update +** Length: 14 Bytes +** OpCode: 9921 +*/ +struct ExpUpdate_Struct +{ +/*0000*/ uint32 exp; // Current experience ratio from 0 to 330 +/*0004*/ uint32 aaxp; // @BP ?? +}; + +/* +** Item Packet Struct - Works on a variety of opcodes +** Packet Types: See ItemPacketType enum +** +*/ +enum ItemPacketType +{ + ItemPacketViewLink = 0x00, + ItemPacketTradeView = 0x65, + ItemPacketLoot = 0x66, + ItemPacketTrade = 0x67, + ItemPacketCharInventory = 0x69, + ItemPacketSummonItem = 0x6A, + ItemPacketTributeItem = 0x6C, + ItemPacketMerchant = 0x64, + ItemPacketWorldContainer = 0x6B +}; +struct ItemPacket_Struct +{ +/*00*/ ItemPacketType PacketType; +/*04*/ char SerializedItem[1]; //was 1 +/*xx*/ +}; + +struct BulkItemPacket_Struct +{ +/*00*/ char SerializedItem[0]; +/*xx*/ +}; + +struct Consume_Struct +{ +/*000*/ ItemSlotStruct 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 +/*024*/ +}; + +struct ItemNamePacket_Struct { +/*000*/ uint32 item_id; +/*004*/ uint32 unkown004; +/*008*/ char name[64]; +/*072*/ +}; + +// Length: 16 +struct ItemProperties_Struct_Old { + +/*000*/ uint8 unknown01[2]; +/*002*/ uint8 charges; +/*003*/ uint8 unknown02[13]; +/*016*/ +}; + +// Length: 8 +struct ItemProperties_Struct { + +/*000*/ uint8 unknown01[4]; +/*004*/ uint8 charges; +/*005*/ uint8 unknown02[3]; +/*008*/ +}; + +struct DeleteItem_Struct { +/*0000*/ ItemSlotStruct from_slot; +/*0012*/ ItemSlotStruct to_slot; +/*0024*/ uint32 number_in_stack; +/*0028*/ +}; + +struct MoveItem_Struct { +/*0000*/ ItemSlotStruct from_slot; +/*0012*/ ItemSlotStruct to_slot; +/*0024*/ uint32 number_in_stack; +/*0028*/ +}; + +// +// from_slot/to_slot +// -1 - destroy +// 0 - cursor +// 1 - inventory +// 2 - bank +// 3 - trade +// 4 - shared bank +// +// cointype +// 0 - copeer +// 1 - silver +// 2 - gold +// 3 - platinum +// +static const uint32 COINTYPE_PP = 3; +static const uint32 COINTYPE_GP = 2; +static const uint32 COINTYPE_SP = 1; +static const uint32 COINTYPE_CP = 0; + +struct MoveCoin_Struct +{ + int32 from_slot; + int32 to_slot; + int32 cointype1; + int32 cointype2; + int32 amount; +}; +struct TradeCoin_Struct{ + uint32 trader; + uint8 slot; + uint16 unknown5; + uint8 unknown7; + uint32 amount; +}; +struct TradeMoneyUpdate_Struct{ + uint32 trader; + uint32 type; + uint32 amount; +}; +/* +** Surname struct +** Size: 100 bytes +*/ +struct Surname_Struct +{ +/*0000*/ char name[64]; +/*0064*/ uint32 unknown0064; +/*0068*/ char lastname[32]; +/*0100*/ +}; + +struct GuildsListEntry_Struct { + char name[64]; +}; + +struct GuildsList_Struct { + uint8 head[64]; // First on guild list seems to be empty... + GuildsListEntry_Struct Guilds[MAX_NUMBER_GUILDS]; +}; + +struct GuildUpdate_Struct { + uint32 guildID; + GuildsListEntry_Struct entry; +}; + +/* +** Money Loot +** Length: 22 Bytes +** OpCode: 5020 +*/ +struct moneyOnCorpseStruct { +/*0000*/ uint8 response; // 0 = someone else is, 1 = OK, 2 = not at this time +/*0001*/ uint8 unknown1; // = 0x5a +/*0002*/ uint8 unknown2; // = 0x40 +/*0003*/ uint8 unknown3; // = 0 +/*0004*/ uint32 platinum; // Platinum Pieces +/*0008*/ uint32 gold; // Gold Pieces + +/*0012*/ uint32 silver; // Silver Pieces +/*0016*/ uint32 copper; // Copper Pieces +}; + +struct LootingItem_Struct { +/*000*/ uint32 lootee; +/*004*/ uint32 looter; +/*008*/ uint16 slot_id; +/*010*/ uint16 unknown10; +/*012*/ uint32 auto_loot; +/*016*/ uint32 unknown16; +/*020*/ +}; + +struct GuildManageStatus_Struct{ + uint32 guildid; + uint32 oldrank; + uint32 newrank; + char name[64]; +}; +// Guild invite, remove +struct GuildJoin_Struct{ +/*000*/ uint32 guild_id; +/*004*/ uint32 unknown04; +/*008*/ uint32 level; +/*012*/ uint32 class_; +/*016*/ uint32 rank;//0 member, 1 officer, 2 leader +/*020*/ uint32 zoneid; +/*024*/ uint32 unknown24; +/*028*/ char name[64]; +/*092*/ +}; +struct GuildInviteAccept_Struct { + char inviter[64]; + char newmember[64]; + uint32 response; + uint32 guildeqid; +}; +struct GuildManageRemove_Struct { + uint32 guildeqid; + char member[64]; +}; +struct GuildCommand_Struct { +/*000*/ char othername[64]; +/*064*/ char myname[64]; +/*128*/ uint16 guildeqid; +/*130*/ uint8 unknown[2]; // for guildinvite all 0's, for remove 0=0x56, 2=0x02 +/*132*/ uint32 officer; +/*136*/ uint32 unknown136; // New in RoF2 +/*140*/ +}; + +// Opcode OP_GMZoneRequest +// Size = 88 bytes +struct GMZoneRequest_Struct { +/*0000*/ char charname[64]; +/*0064*/ uint32 zone_id; +/*0068*/ float x; +/*0072*/ float y; +/*0076*/ float z; +/*0080*/ char unknown0080[4]; +/*0084*/ uint32 success; // 0 if command failed, 1 if succeeded? +/*0088*/ +// /*072*/ int8 success; // =0 client->server, =1 server->client, -X=specific error +// /*073*/ uint8 unknown0073[3]; // =0 ok, =ffffff error +}; + +struct GMSummon_Struct { +/* 0*/ char charname[64]; +/* 30*/ char gmname[64]; +/* 60*/ uint32 success; +/* 61*/ uint32 zoneID; +/*92*/ int32 y; +/*96*/ int32 x; +/*100*/ int32 z; +/*104*/ uint32 unknown2; // E0 E0 56 00 +}; + +struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet +/* 0*/ char charname[64]; + +/* 64*/ char gmname[64]; +/* 128*/ uint32 success; +/* 132*/ uint32 zoneID; + +/*136*/ int32 y; +/*140*/ int32 x; +/*144*/ int32 z; +/*148*/ uint32 unknown2; // E0 E0 56 00 +}; + +struct GMLastName_Struct { +/*000*/ char name[64]; +/*064*/ char gmname[64]; +/*128*/ char lastname[64]; +/*192*/ uint16 unknown[4]; // 0x00, 0x00, 0x01, 0x00 = Update the clients +/*200*/ uint32 unknown200[8]; +/*232*/ +}; + +struct OnLevelMessage_Struct { +/*0000*/ uint32 Title_Count; +/*0000*/ char Title[128]; +/*0000*/ uint32 Text_Count; +/*0000*/ char Text[4096]; +/*0000*/ uint32 ButtonName0_Count; +/*0000*/ char ButtonName0[25]; // If Buttons = 1, these two are the text for the left and right buttons respectively +/*0000*/ uint32 ButtonName1_Count; +/*0000*/ char ButtonName1[25]; +/*0000*/ uint8 Buttons; +/*0000*/ uint8 Unknown4275; // Something to do with audio controls +/*0000*/ uint32 Duration; +/*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button +/*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button +/*0000*/ uint32 Unknown4288; +/*0000*/ uint8 Unknown4276; +/*0000*/ uint8 Unknown4277; +/*0000*/ +}; + +//Combat Abilities +struct CombatAbility_Struct { + uint32 m_target; //the ID of the target mob + uint32 m_atk; + uint32 m_skill; +}; + +//Instill Doubt +struct Instill_Doubt_Struct { + uint8 i_id; + uint8 ia_unknown; + uint8 ib_unknown; + uint8 ic_unknown; + uint8 i_atk; + + uint8 id_unknown; + uint8 ie_unknown; + uint8 if_unknown; + uint8 i_type; + uint8 ig_unknown; + uint8 ih_unknown; + uint8 ii_unknown; +}; + +struct GiveItem_Struct { + uint16 to_entity; + int16 to_equipSlot; + uint16 from_entity; + int16 from_equipSlot; +}; + +struct RandomReq_Struct { + uint32 low; + uint32 high; +}; + +/* solar: 9/23/03 reply to /random command; struct from Zaphod */ +struct RandomReply_Struct { +/* 00 */ uint32 low; +/* 04 */ uint32 high; +/* 08 */ uint32 result; +/* 12 */ char name[64]; +/* 76 */ +}; + +/* +** LFG_Appearance_Struct +** Packet sent to clients to notify when someone in zone toggles LFG flag +** Size: 8 bytes +** Used in: OP_LFGAppearance +** +*/ +struct LFG_Appearance_Struct +{ +/*0000*/ uint32 spawn_id; // ID of the client +/*0004*/ uint8 lfg; // 1=LFG, 0=Not LFG +/*0005*/ char unknown0005[3]; // +/*0008*/ +}; + + +// EverQuest Time Information: +// 72 minutes per EQ Day +// 3 minutes per EQ Hour +// 6 seconds per EQ Tick (2 minutes EQ Time) +// 3 seconds per EQ Minute + +struct TimeOfDay_Struct { + uint8 hour; + uint8 minute; + uint8 day; + uint8 month; + uint16 year; +/*0006*/ uint16 unknown0016; // Placeholder +/*0008*/ +}; + +// Darvik: shopkeeper structs +struct Merchant_Click_Struct { +/*000*/ uint32 npcid; // Merchant NPC's entity id +/*004*/ uint32 playerid; +/*008*/ uint32 command; // 1=open, 0=cancel/close +/*012*/ float rate; // cost multiplier, dosent work anymore +/*016*/ int32 unknown01; // Seen 3 from Server or -1 from Client +/*020*/ int32 unknown02; // Seen 2592000 from Server or -1 from Client +/*024*/ +}; +/* +Unknowns: +0 is e7 from 01 to // MAYBE SLOT IN PURCHASE +1 is 03 +2 is 00 +3 is 00 +4 is ?? +5 is ?? +6 is 00 from a0 to +7 is 00 from 3f to */ +/* +0 is F6 to 01 +1 is CE CE +4A 4A +00 00 +00 E0 +00 CB +00 90 +00 3F +*/ + +struct Merchant_Sell_Struct { +/*000*/ uint32 npcid; // Merchant NPC's entity id +/*004*/ uint32 playerid; // Player's entity id +/*008*/ uint32 itemslot; // Merchant Slot / Item Instance ID +/*012*/ uint32 unknown12; +/*016*/ uint32 quantity; // Already sold +/*020*/ uint32 unknown20; +/*024*/ uint32 price; +/*028*/ uint32 unknown28; // Normally 0, but seen 84 c5 63 00 as well +/*032*/ +}; + +struct Merchant_Purchase_Struct { +/*000*/ uint32 npcid; // Merchant NPC's entity id +/*004*/ MainInvItemSlotStruct itemslot; +/*012*/ uint32 quantity; +/*016*/ uint32 price; +/*020*/ +}; + +struct Merchant_DelItem_Struct{ +/*000*/ uint32 npcid; // Merchant NPC's entity id +/*004*/ uint32 playerid; // Player's entity id +/*008*/ uint32 itemslot; +}; + +struct AltCurrencyDefinition_Struct { + uint32 id; + uint32 item_id; +}; + +//One packet i didn't include here is the alt currency merchant window. +//it works much like the adventure merchant window +//it is formated like: dbstringid|1|dbstringid|count +//ex for a blank crowns window you would send: +//999999|1|999999|0 +//any items come after in much the same way adventure merchant items do except there is no theme included + +//Server -> Client +//Populates the initial Alternate Currency Window +struct AltCurrencyPopulateEntry_Struct +{ +/*000*/ uint32 currency_number; // corresponds to a dbstr id as well, the string matches what shows up in the "alternate currency" tab. +/*004*/ uint32 unknown00; // always 1 +/*008*/ uint32 currency_number2; // always same as currency number +/*012*/ uint32 item_id; // appears to be the item id +/*016*/ uint32 item_icon; // actual icon +/*020*/ uint32 stack_size; // most are set to 1000, the stack size for the item; should match db i think or there will be problems. +/*024*/ uint8 display; // If set to 0, will not display by default. +/*025*/ +}; + +struct AltCurrencyPopulate_Struct { +/*000*/ uint32 opcode; // 8 for populate +/*004*/ uint32 count; // number of entries +/*008*/ AltCurrencyPopulateEntry_Struct entries[0]; +}; + +//Server -> Client +//Updates the value of a specific Alternate Currency +struct AltCurrencyUpdate_Struct { +/*000*/ uint32 opcode; //7 for update +/*004*/ char name[64]; //name of client (who knows why just do it) +/*068*/ uint32 currency_number; //matches currency_number from populate entry +/*072*/ uint32 unknown072; //always 1 +/*076*/ uint32 amount; //new amount +/*080*/ uint32 unknown080; //seen 0 +/*084*/ uint32 unknown084; //seen 0 +}; + +//Client -> Server +//When an item is selected while the alt currency merchant window is open +struct AltCurrencySelectItem_Struct { +/*000*/ uint32 merchant_entity_id; +/*004*/ //uint32 slot_id; + ItemSlotStruct slot_id; +/*008*/ uint32 unknown008; +/*012*/ uint32 unknown012; +/*016*/ uint32 unknown016; +/*020*/ uint32 unknown020; +/*024*/ uint32 unknown024; +/*028*/ uint32 unknown028; +/*032*/ uint32 unknown032; +/*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*/ uint32 unknown068; +/*072*/ uint32 unknown072; +/*076*/ uint32 unknown076; +}; + +//Server -> Client +//As setup it makes it so that item can't be sold to the merchant. +//eg: "I will give you no doubloons for a cloth cap." +//Probably also sends amounts somewhere +struct AltCurrencySelectItemReply_Struct { +/*000*/ uint32 unknown000; +/*004*/ uint8 unknown004; //0xff +/*005*/ uint8 unknown005; //0xff +/*006*/ uint8 unknown006; //0xff +/*007*/ uint8 unknown007; //0xff +/*008*/ char item_name[64]; +/*072*/ uint32 unknown074; +/*076*/ uint32 cost; +/*080*/ uint32 unknown080; +/*084*/ uint32 unknown084; +}; + +//Client -> Server +//Requests purchase of a specific item from the vendor +struct AltCurrencyPurchaseItem_Struct { +/*000*/ uint32 merchant_entity_id; +/*004*/ uint32 item_id; +/*008*/ uint32 unknown008; //1 +}; + +//Client -> Server +//Reclaims / Create currency button pushed. +struct AltCurrencyReclaim_Struct { +/*000*/ uint32 currency_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 count; +/*012*/ uint32 reclaim_flag; //1 = this is reclaim +}; + +struct AltCurrencySellItem_Struct { +/*000*/ uint32 merchant_entity_id; +/*004*/ //uint32 slot_id; + ItemSlotStruct slot_id; +/*008*/ uint32 charges; +/*012*/ uint32 cost; +}; + +struct Adventure_Purchase_Struct { +/*000*/ uint32 some_flag; //set to 1 generally... +/*004*/ uint32 npcid; +/*008*/ uint32 itemid; +/*012*/ uint32 variable; +}; + +struct Adventure_Sell_Struct { +/*000*/ uint32 unknown000; //0x01 - Stack Size/Charges? +/*004*/ uint32 npcid; +/*008*/ MainInvItemSlotStruct slot; +/*016*/ uint32 charges; +/*020*/ uint32 sell_price; +/*024*/ +}; + +struct AdventurePoints_Update_Struct { +/*000*/ uint32 ldon_available_points; // Total available points +/*004*/ uint8 unkown_apu004[20]; +/*024*/ uint32 ldon_guk_points; // Earned Deepest Guk points +/*028*/ uint32 ldon_mirugal_points; // Earned Mirugal' Mebagerie points +/*032*/ uint32 ldon_mistmoore_points; // Earned Mismoore Catacombs Points +/*036*/ uint32 ldon_rujarkian_points; // Earned Rujarkian Hills points +/*040*/ uint32 ldon_takish_points; // Earned Takish points +/*044*/ uint8 unknown_apu042[216]; +}; + + +struct AdventureFinish_Struct{ + uint32 win_lose;//Cofruben: 00 is a lose,01 is win. + uint32 points; +}; +//OP_AdventureRequest +struct AdventureRequest_Struct{ + uint32 risk;//1 normal,2 hard. + uint32 entity_id; +}; +struct AdventureRequestResponse_Struct{ + uint32 unknown000; + char text[2048]; + uint32 timetoenter; + uint32 timeleft; + uint32 risk; + float x; + float y; + float z; + uint32 showcompass; + uint32 unknown2080; +}; + +//this is mostly right but something is off that causes the client to crash sometimes +//I don't really care enough about the feature to work on it anymore though. +struct AdventureLeaderboardEntry_Struct +{ +/*004*/ char name[64]; +/*008*/ uint32 success; +/*012*/ uint32 failure; +/*016*/ +}; + +struct AdventureLeaderboard_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ uint32 success; +/*012*/ uint32 failure; +/*016*/ uint32 our_rank; +/*020*/ +}; + +/*struct Item_Shop_Struct { + uint16 merchantid; + uint8 itemtype; + Item_Struct item; + uint8 iss_unknown001[6]; +};*/ + +struct Illusion_Struct { // Was size: 336 +/*000*/ uint32 spawnid; +/*004*/ char charname[64]; +/*068*/ uint16 race; +/*070*/ char unknown006[2]; // Weird green name +/*072*/ uint8 gender; +/*073*/ uint8 texture; +/*074*/ uint8 unknown074; +/*075*/ uint8 unknown075; +/*076*/ uint8 helmtexture; +/*077*/ uint8 unknown077; +/*078*/ uint8 unknown078; +/*079*/ uint8 unknown079; +/*080*/ uint32 face; +/*084*/ uint8 hairstyle; // Some Races don't change Hair Style Properly in SoF +/*085*/ uint8 haircolor; +/*086*/ uint8 beard; +/*087*/ uint8 beardcolor; +/*088*/ float size; +/*092*/ uint8 unknown092[148]; +/*240*/ uint32 unknown240; // Removes armor? +/*244*/ uint32 drakkin_heritage; +/*248*/ uint32 drakkin_tattoo; +/*252*/ uint32 drakkin_details; +/*256*/ uint8 unknown256[60]; // This and below are new to RoF2 +/*316*/ int32 unknown316; // Seen -1 +/*320*/ uint8 unknown320[16]; +/*336*/ +}; + +struct ZonePoint_Entry { //32 octets +/*0000*/ uint32 iterator; +/*0004*/ float y; +/*0008*/ float x; +/*0012*/ float z; +/*0016*/ float heading; +/*0020*/ uint16 zoneid; +/*0022*/ uint16 zoneinstance; // LDoN instance +/*0024*/ uint32 unknown024; +/*0028*/ uint32 unknown028; +/*0032*/ +}; + +struct ZonePoints { +/*0000*/ uint32 count; +/*0004*/ struct ZonePoint_Entry zpe[0]; // Always add one extra to the end after all zonepoints +//*0xxx*/ uint8 unknown0xxx[24]; //New from SEQ +}; + +struct SkillUpdate_Struct { +/*00*/ uint32 skillId; +/*04*/ uint32 value; +/*08*/ uint8 unknown08; // Seen 1 +/*09*/ uint8 unknown09; // Seen 80 +/*10*/ uint8 unknown10; // Seen 136 +/*11*/ uint8 unknown11; // Seen 54 +/*12*/ +}; + +struct ZoneUnavail_Struct { + //This actually varies, but... + char zonename[16]; + int16 unknown[4]; +}; + +struct GroupInvite_Struct { +/*0000*/ char invitee_name[64]; +/*0064*/ char inviter_name[64]; +/*0128*/ uint32 unknown0128; +/*0132*/ uint32 unknown0132; +/*0136*/ uint32 unknown0136; +/*0140*/ uint32 unknown0140; +/*0144*/ uint32 unknown0144; +/*0148*/ +}; + +struct GroupGeneric_Struct { +/*0000*/ char name1[64]; +/*0064*/ char name2[64]; +/*0128*/ uint32 unknown0128; +/*0132*/ uint32 unknown0132; +/*0136*/ uint32 unknown0136; +/*0140*/ uint32 unknown0140; +/*0144*/ uint32 unknown0144; +/*0148*/ +}; + +struct GroupCancel_Struct { +/*000*/ char name1[64]; +/*064*/ char name2[64]; +/*128*/ uint8 unknown128[20]; +/*148*/ uint32 toggle; +/*152*/ +}; + +struct GroupUpdate_Struct { +/*0000*/ uint32 action; +/*0004*/ char yourname[64]; +/*0068*/ char membername[5][64]; +/*0388*/ char leadersname[64]; +/*0452*/ +}; + +struct GroupUpdate2_Struct { +/*0000*/ uint32 action; +/*0004*/ char yourname[64]; +/*0068*/ char membername[5][64]; +/*0388*/ char leadersname[64]; +/*0452*/ GroupLeadershipAA_Struct leader_aas; +/*0516*/ uint8 unknown[252]; // Titanium uses [188] here +/*0768*/ +}; + +struct GroupUpdate_Struct_Live { // New for Live +/*0000*/ uint32 groupid; // Guess - Matches unknown0136 from GroupFollow_Struct +/*0004*/ uint32 totalmembers; // Guess +/*0000*/ //uint32 leadersname[0]; // Group Leader Name Null Terminated +/*0008*/ //GroupMembers_Struct groupmembers; +}; + +struct GroupMembers_Struct { // New for Live +/*0000*/ uint32 membernumber; // Guess - number of member in the group (0 to 5?) +/*0000*/ //char membername[0]; // Member Name Null Terminated +/*0000*/ uint8 unknown001[3]; // Seen 0 +/*0000*/ uint32 memberlevel; // Guess +/*0000*/ uint8 unknown002[11]; // Seen 0 +}; + +struct GroupJoin_Struct_Live { // New for Live +/*0000*/ uint32 unknown0000; // Matches unknown0136 from GroupFollow_Struct +/*0004*/ uint32 action; +/*0008*/ uint8 unknown0008[5]; // Seen 0 +/*0013*/ //char membername[0]; // Null Terminated? +/*0000*/ uint8 unknown0013[3]; // Seen 0 +/*0000*/ uint32 unknown0016; // Matches unknown0132 from GroupFollow_Struct +/*0000*/ uint8 unknown0020[11]; // Seen 0 +}; + +struct GroupJoin_Struct { +/*000*/ char unknown000[64]; +/*064*/ char membername[64]; +/*128*/ uint8 unknown128[20]; // Leadership AA ? +/*148*/ +}; + +struct GroupFollow_Struct { // Live Follow Struct +/*0000*/ char name1[64]; // inviter +/*0064*/ char name2[64]; // invitee +/*0128*/ uint32 unknown0128; // Seen 0 +/*0132*/ uint32 unknown0132; // Group ID or member level? +/*0136*/ uint32 unknown0136; // Maybe Voice Chat Channel or Group ID? +/*0140*/ uint32 unknown0140; // Seen 0 +/*0144*/ uint32 unknown0144; // Seen 0 +/*0148*/ uint32 unknown0148; +/*0152*/ +}; + +struct InspectBuffs_Struct { +/*000*/ uint32 spell_id[BUFF_COUNT]; +/*168*/ uint32 tics_remaining[BUFF_COUNT]; +}; + +struct LFG_Struct { +/*000*/ uint32 unknown000; +/*004*/ uint32 value; // 0x00 = off 0x01 = on +/*008*/ uint32 unknown008; +/*012*/ uint32 unknown012; +/*016*/ char name[64]; +}; + +struct FaceChange_Struct { +/*000*/ uint8 haircolor; +/*001*/ uint8 beardcolor; +/*002*/ uint8 eyecolor1; +/*003*/ uint8 eyecolor2; +/*004*/ uint8 hairstyle; +/*005*/ uint8 beard; +/*006*/ uint8 face; +/*007*/ uint8 unknown007; +/*008*/ uint32 drakkin_heritage; +/*012*/ uint32 drakkin_tattoo; +/*016*/ uint32 drakkin_details; +/*020*/ uint32 unknown020; +/*024*/ +}; +//there are only 10 faces for barbs changing woad just +//increase the face value by ten so if there were 8 woad +//designs then there would be 80 barb faces + +/* +** Trade request from one client to another +** Used to initiate a trade +** Size: 8 bytes +** Used in: OP_TradeRequest +*/ +struct TradeRequest_Struct { +/*00*/ uint32 to_mob_id; +/*04*/ uint32 from_mob_id; +/*08*/ +}; + +struct TradeAccept_Struct { +/*00*/ uint32 from_mob_id; +/*04*/ uint32 unknown4; //seems to be garbage +/*08*/ +}; + +/* +** Cancel Trade struct +** Sent when a player cancels a trade +** Size: 8 bytes +** Used In: OP_CancelTrade +** +*/ +struct CancelTrade_Struct { +/*00*/ uint32 fromid; +/*04*/ uint32 action; +/*08*/ +}; + +struct PetitionUpdate_Struct { + uint32 petnumber; // Petition Number + uint32 color; // 0x00 = green, 0x01 = yellow, 0x02 = red + uint32 status; + time_t senttime; // 4 has to be 0x1F + char accountid[32]; + char gmsenttoo[64]; + int32 quetotal; + char charname[64]; +}; + +struct Petition_Struct { + uint32 petnumber; + uint32 urgency; + char accountid[32]; + char lastgm[32]; + uint32 zone; + //char zone[32]; + char charname[64]; + uint32 charlevel; + uint32 charclass; + uint32 charrace; + uint32 unknown; + //time_t senttime; // Time? + uint32 checkouts; + uint32 unavail; + //uint8 unknown5[4]; + time_t senttime; + uint32 unknown2; + char petitiontext[1024]; + char gmtext[1024]; +}; + + +struct Who_All_Struct { // 156 length total +/*000*/ char whom[64]; +/*088*/ uint8 unknown088[64]; +/*064*/ uint32 wrace; // FF FF = no race +/*068*/ uint32 wclass; // FF FF = no class +/*072*/ uint32 lvllow; // FF FF = no numbers +/*076*/ uint32 lvlhigh; // FF FF = no numbers +/*080*/ uint32 gmlookup; // FF FF = not doing /who all gm +/*084*/ uint32 guildid; // Also used for Buyer/Trader/LFG +/*152*/ uint32 type; // 0 = /who 3 = /who all +/*156*/ +}; + +struct Stun_Struct { // 8 bytes total +/*000*/ uint32 duration; // Duration of stun +/*004*/ uint8 unknown004; // seen 0 +/*005*/ uint8 unknown005; // seen 163 +/*006*/ uint8 unknown006; // seen 67 +/*007*/ uint8 unknown007; // seen 0 +/*008*/ +}; + +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 +/*20*/ uint32 augment_index; // Seen 0 +/*24*/ ItemSlotStruct 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*/ +}; + +// OP_Emote +struct Emote_Struct { +/*0000*/ uint32 unknown01; +/*0004*/ char message[1024]; // was 1024 +/*1028*/ +}; + +// Inspect +struct Inspect_Struct { + uint32 TargetID; + uint32 PlayerID; +}; + +//OP_InspectAnswer - Size: 1860 +struct InspectResponse_Struct{ +/*000*/ uint32 TargetID; +/*004*/ uint32 playerid; +/*008*/ char itemnames[23][64]; +/*1480*/uint32 itemicons[23]; +/*1572*/char text[288]; // Max number of chars in Inspect Window appears to be 254 +/*1860*/ +}; + +//OP_SetDataRate +struct SetDataRate_Struct { + float newdatarate; +}; + +//OP_SetServerFilter +struct SetServerFilter_Struct { + uint32 filters[35]; //see enum eqFilterType [31] +}; + +//Op_SetServerFilterAck +struct SetServerFilterAck_Struct { + uint8 blank[8]; +}; +struct IncreaseStat_Struct{ + /*0000*/ uint8 unknown0; + /*0001*/ uint8 str; + /*0002*/ uint8 sta; + /*0003*/ uint8 agi; + /*0004*/ uint8 dex; + /*0005*/ uint8 int_; + /*0006*/ uint8 wis; + /*0007*/ uint8 cha; + /*0008*/ uint8 fire; + /*0009*/ uint8 cold; + /*0010*/ uint8 magic; + /*0011*/ uint8 poison; + /*0012*/ uint8 disease; + /*0013*/ char unknown13[116]; + /*0129*/ uint8 str2; + /*0130*/ uint8 sta2; + /*0131*/ uint8 agi2; + /*0132*/ uint8 dex2; + /*0133*/ uint8 int_2; + /*0134*/ uint8 wis2; + /*0135*/ uint8 cha2; + /*0136*/ uint8 fire2; + /*0137*/ uint8 cold2; + /*0138*/ uint8 magic2; + /*0139*/ uint8 poison2; + /*0140*/ uint8 disease2; +}; + +struct GMName_Struct { + char oldname[64]; + char gmname[64]; + char newname[64]; + uint8 badname; + uint8 unknown[3]; +}; + +struct GMDelCorpse_Struct { + char corpsename[64]; + char gmname[64]; + uint8 unknown; +}; + +struct GMKick_Struct { + char name[64]; + char gmname[64]; + uint8 unknown; +}; + + +struct GMKill_Struct { + char name[64]; + char gmname[64]; + uint8 unknown; +}; + + +struct GMEmoteZone_Struct { + char text[512]; +}; + +// The BookText_Struct is not used in SoF and later clients. +// The BookRequest_Struct is used instead for both request and reply. +// +struct BookText_Struct { + uint8 window; // where to display the text (0xFF means new window) + uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly + char booktext[1]; // Variable Length - was 1 +}; +// This is the request to read a book. +// This is just a "text file" on the server +// or in our case, the 'name' column in our books table. +struct BookRequest_Struct { +/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window). +/*0004*/ uint16 invslot; // Is the slot, but the RoF2 conversion causes it to fail. Turned to 0 since it isnt required anyway. +/*0008*/ uint32 unknown006; // Seen FFFFFFFF +/*0010*/ uint16 unknown008; // seen 0000 +/*0012*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others +/*0016*/ uint32 unknown0012; +/*0020*/ uint16 unknown0016; +/*0022*/ char txtfile[8194]; +}; + +/* +** Object/Ground Spawn struct +** Used for Forges, Ovens, ground spawns, items dropped to ground, etc +** Size: Variable +** OpCodes: OP_CreateObject +** +*/ +struct Object_Struct { +/*00*/ uint32 object_count; // Iteration count in the object list +/*00*/ char object_name[1]; // Name of object, usually something like IT63_ACTORDEF +/*00*/ uint16 zone_id; // Redudant, but: Zone the object appears in +/*00*/ uint16 zone_instance; // +/*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 size; // Size - default 1 +/*00*/ float z; // z coord +/*00*/ float x; // x coord +/*00*/ float y; // y coord +/*00*/ int32 object_type; // Type of object, not directly translated to OP_OpenObject +}; +// object_type - 01 = generic drop, 02 = armor, 19 = weapon +// 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject + +/* +** Click Object Struct +** Client clicking on zone object (forge, groundspawn, etc) +** Size: 8 bytes +** Last Updated: Oct-17-2003 +** +*/ +struct ClickObject_Struct { +/*00*/ uint32 drop_id; // Appears to use the Object Count field now +/*04*/ uint32 player_id; +/*08*/ +}; + +struct Shielding_Struct { + uint32 target_id; +}; + +/* +** Click Object Acknowledgement Struct +** Response to client clicking on a World Container (ie, forge) +** +*/ +struct ClickObjectAction_Struct { +/*00*/ //uint32 player_id; // Appears to have been removed +/*00*/ uint32 drop_id; // Appears to use the object_count field now +/*04*/ int32 unknown04; // Seen -1 +/*08*/ int32 unknown08; // Seen -1 +/*08*/ //uint32 open; // 1=opening, 0=closing - Removed? +/*12*/ uint32 type; // See object.h, "Object Types" +/*16*/ uint32 unknown16; // +/*20*/ uint32 icon; // Icon to display for tradeskill containers +/*24*/ uint32 unknown24; // +/*28*/ char object_name[64]; // Object name to display +/*92*/ +}; + +/* +** This is different now, mostly unknown +** +*/ +struct CloseContainer_Struct { +/*00*/ uint32 player_id; // Entity Id of player who clicked object +/*04*/ uint32 drop_id; // Zone-specified unique object identifier +/*08*/ uint32 open; // 1=opening, 0=closing +/*12*/ uint32 unknown12[12]; +}; + +/* +** Generic Door Struct +** Length: 52 Octets +** Used in: +** cDoorSpawnsStruct(f721) +** +*/ +struct Door_Struct +{ +/*0000*/ char name[32]; // Filename of Door // Was 10char long before... added the 6 in the next unknown to it: Daeken M. BlackBlade +/*0032*/ float yPos; // y loc +/*0036*/ float xPos; // x loc +/*0040*/ float zPos; // z loc +/*0044*/ float heading; +/*0048*/ uint32 incline; // rotates the whole door +/*0052*/ uint32 size; // 100 is normal, smaller number = smaller model +/*0054*/ uint8 unknown0054[4]; // 00 00 00 00 +/*0060*/ uint8 doorId; // door's id # +/*0061*/ uint8 opentype; +/*0062*/ uint8 state_at_spawn; +/*0063*/ uint8 invert_state; // if this is 1, the door is normally open +/*0064*/ uint32 door_param; // normally ff ff ff ff (-1) +/*0068*/ uint32 unknown0068; // 00 00 00 00 +/*0072*/ uint32 unknown0072; // 00 00 00 00 +/*0076*/ uint8 unknown0076[4]; // New for RoF2 +/*0080*/ uint8 unknown0080; // seen 1 or 0 +/*0081*/ uint8 unknown0081; // seen 1 (always?) +/*0082*/ uint8 unknown0082; // seen 0 (always?) +/*0083*/ uint8 unknown0083; // seen 1 (always?) +/*0084*/ uint8 unknown0084; // seen 0 (always?) +/*0085*/ uint8 unknown0085; // seen 1 or 0 or rarely 2C or 90 or ED or 2D or A1 +/*0086*/ uint8 unknown0086; // seen 0 or rarely FF or FE or 10 or 5A or 82 +/*0087*/ uint8 unknown0087; // seen 0 or rarely 02 or 7C +/*0088*/ uint8 unknown0088[8]; // mostly 0s, the last 3 bytes are something tho +/*0096*/ +}; + +struct DoorSpawns_Struct { + struct Door_Struct doors[0]; +}; + +/* + OP Code: Op_ClickDoor + Size: 16 +*/ +struct ClickDoor_Struct { +/*000*/ uint8 doorid; +/*001*/ uint8 unknown001; // This may be some type of action setting +/*002*/ uint8 unknown002; // This is sometimes set after a lever is closed +/*003*/ uint8 unknown003; // Seen 0 +/*004*/ uint8 picklockskill; +/*005*/ uint8 unknown005[3]; +/*008*/ uint32 item_id; +/*012*/ uint16 player_id; +/*014*/ uint8 unknown014[2]; +/*016*/ +}; + +struct MoveDoor_Struct { + uint8 doorid; + uint8 action; +}; + + +struct BecomeNPC_Struct { + uint32 id; + int32 maxlevel; +}; + +struct Underworld_Struct { + float speed; + float y; + float x; + float z; +}; + +struct Resurrect_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint16 zone_id; +/*006*/ uint16 instance_id; +/*008*/ float y; +/*012*/ float x; +/*016*/ float z; +/*020*/ uint32 unknown020; +/*024*/ char your_name[64]; +/*088*/ uint32 unknown088; +/*092*/ char rezzer_name[64]; +/*156*/ uint32 spellid; +/*160*/ char corpse_name[64]; +/*224*/ uint32 action; +/*228*/ uint32 unknown228; +/*232*/ +}; + +struct SetRunMode_Struct { + uint8 mode; //01=run 00=walk + uint8 unknown[3]; +}; + +// EnvDamage is EnvDamage2 without a few bytes at the end. +// Size: 37 bytes +struct EnvDamage2_Struct { +/*0000*/ uint32 id; +/*0004*/ uint16 unknown4; +/*0006*/ uint32 damage; +/*0010*/ float unknown10; // New to Underfoot - Seen 1 +/*0014*/ uint8 unknown14[12]; +/*0026*/ uint8 dmgtype; // FA = Lava; FC = Falling +/*0027*/ uint8 unknown27[4]; +/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66 +/*0033*/ uint16 constant; // Always FFFF +/*0035*/ uint16 unknown35; +/*0037*/ +}; + +//Bazaar Stuff + +enum { + BazaarTrader_StartTraderMode = 1, + BazaarTrader_EndTraderMode = 2, + BazaarTrader_UpdatePrice = 3, + BazaarTrader_EndTransaction = 4, + BazaarSearchResults = 7, + BazaarWelcome = 9, + BazaarBuyItem = 10, + BazaarTrader_ShowItems = 11, + BazaarSearchDone = 12, + BazaarTrader_CustomerBrowsing = 13, + BazaarInspectItem = 18, + BazaarSearchDone2 = 19, + BazaarTrader_StartTraderMode2 = 22 +}; + +enum { + BazaarPriceChange_Fail = 0, + BazaarPriceChange_UpdatePrice = 1, + BazaarPriceChange_RemoveItem = 2, + BazaarPriceChange_AddItem = 3 +}; + +struct BazaarWindowStart_Struct { + uint8 Action; + uint8 Unknown001; + uint16 Unknown002; +}; + + +struct BazaarWelcome_Struct { + BazaarWindowStart_Struct Beginning; + uint32 Traders; + uint32 Items; + uint8 Unknown012[8]; +}; + +struct BazaarSearch_Struct { + BazaarWindowStart_Struct Beginning; + uint32 TraderID; + uint32 Class_; + uint32 Race; + uint32 ItemStat; + uint32 Slot; + uint32 Type; + char Name[64]; + uint32 MinPrice; + uint32 MaxPrice; + uint32 Minlevel; + uint32 MaxLlevel; +}; +struct BazaarInspect_Struct{ + uint32 ItemID; + uint32 Unknown004; + char Name[64]; +}; + +struct NewBazaarInspect_Struct { +/*000*/ BazaarWindowStart_Struct Beginning; +/*004*/ char Name[64]; +/*068*/ uint32 Unknown068; +/*072*/ int32 SerialNumber; +/*076*/ uint32 Unknown076; +/*080*/ uint32 SellerID; +/*084*/ uint32 Unknown084; +}; + +struct BazaarReturnDone_Struct{ + uint32 Type; + uint32 TraderID; + uint32 Unknown008; + uint32 Unknown012; + uint32 Unknown016; +}; + +struct BazaarSearchResults_Struct { +/*000*/ BazaarWindowStart_Struct Beginning; +/*004*/ uint32 SellerID; +/*008*/ char SellerName[64]; +/*072*/ uint32 NumItems; +/*076*/ uint32 ItemID; +/*080*/ uint32 SerialNumber; +/*084*/ uint32 Unknown084; +/*088*/ char ItemName[64]; +/*152*/ uint32 Cost; +/*156*/ uint32 ItemStat; +/*160*/ +}; + +struct ServerSideFilters_Struct { +uint8 clientattackfilters; // 0) No, 1) All (players) but self, 2) All (players) but group +uint8 npcattackfilters; // 0) No, 1) Ignore NPC misses (all), 2) Ignore NPC Misses + Attacks (all but self), 3) Ignores NPC Misses + Attacks (all but group) +uint8 clientcastfilters; // 0) No, 1) Ignore PC Casts (all), 2) Ignore PC Casts (not directed towards self) +uint8 npccastfilters; // 0) No, 1) Ignore NPC Casts (all), 2) Ignore NPC Casts (not directed towards self) +}; + +/* +** Client requesting item statistics +** Size: 52 bytes +** Used In: OP_ItemLinkClick +** Last Updated: 01/03/2012 +** +*/ +struct ItemViewRequest_Struct { +/*000*/ uint32 item_id; +/*004*/ uint32 augments[6]; +/*028*/ uint32 link_hash; +/*032*/ uint32 unknown028; //seems to always be 4 on SoF client +/*036*/ char unknown032[12]; //probably includes loregroup & evolving info. see Client::MakeItemLink() in zone/inventory.cpp:469 +/*048*/ uint16 icon; +/*050*/ char unknown046[2]; +/*052*/ +}; + +/* + * Client to server packet + */ +struct PickPocket_Struct { +// Size 18 + uint32 to; + uint32 from; + uint16 myskill; + uint8 type; // -1 you are being picked, 0 failed , 1 = plat, 2 = gold, 3 = silver, 4 = copper, 5 = item + uint8 unknown1; // 0 for response, unknown for input + uint32 coin; + uint8 lastsix[2]; +}; +/* + * Server to client packet + */ + +struct sPickPocket_Struct { + // Size 28 = coin/fail + uint32 to; + uint32 from; + uint32 myskill; + uint32 type; + uint32 coin; + char itemname[64]; +}; + + +struct LogServer_Struct { +// Op_Code OP_LOGSERVER +/*000*/ uint32 unknown000; +/*004*/ uint8 enable_pvp; +/*005*/ uint8 unknown005; +/*006*/ uint8 unknown006; +/*007*/ uint8 unknown007; +/*008*/ uint8 enable_FV; +/*009*/ uint8 unknown009; +/*010*/ uint8 unknown010; +/*011*/ uint8 unknown011; +/*012*/ uint32 unknown012; // htonl(1) on live +/*016*/ uint32 unknown016; // htonl(1) on live +/*020*/ uint8 unknown020[12]; +/*032*/ uint32 unknown032; +/*036*/ char worldshortname[32]; +/*068*/ uint8 unknown068[181]; +/*249*/ uint8 unknown249[27]; +/*276*/ float unknown276[7]; +/*304*/ uint8 unknown304[256]; +/*560*/ + +/* Currently lost + uint8 enablevoicemacros; + uint8 enablemail; +*/ +}; + +struct ApproveWorld_Struct { +// Size 544 +// Op_Code OP_ApproveWorld + uint8 unknown544[544]; +}; + +struct ClientError_Struct +{ +/*00001*/ char type; +/*00001*/ char unknown0001[69]; +/*00069*/ char character_name[64]; +/*00134*/ char unknown134[192]; +/*00133*/ char message[31994]; +/*32136*/ +}; + +struct MobHealth +{ + /*0000*/ uint8 hp; //health percent + /*0001*/ uint16 id;//mobs id +}; + +struct Track_Struct { + uint16 entityid; + uint16 y; + uint16 x; + uint16 z; +}; + +struct Tracking_Struct { + Track_Struct Entrys[0]; +}; + +// Looks like new tracking structures - Opcode: 0x57a7 +struct Tracking_Struct_New { + uint16 totalcount; // Total Count of mobs within tracking range + Track_Struct Entrys[0]; +}; + +struct Track_Struct_New { + uint16 entityid; // Entity ID + uint16 unknown002; // 00 00 + uint32 unknown004; // + uint8 level; // level of mob + uint8 unknown009; // 01 maybe type of mob? player/npc? + char name[1]; // name of mob +}; + + +/* +** ZoneServerInfo_Struct +** Zone server information +** Size: 130 bytes +** Used In: OP_ZoneServerInfo +** +*/ +struct ZoneServerInfo_Struct +{ +/*0000*/ char ip[128]; +/*0128*/ uint16 port; +}; + +struct WhoAllPlayer{ + uint32 formatstring; + uint32 pidstring; + int32 unknown64; // Seen -1 + char* name; + uint32 rankstring; + char* guild; + uint32 unknown80[2]; + uint32 zonestring; + uint32 zone; + uint32 class_; + uint32 level; + uint32 race; + char* account; + uint32 unknown100; +}; + +struct WhoAllReturnStruct { + uint32 id; + uint32 playerineqstring; + char line[27]; + uint8 unknown35; // 0A + uint32 unknown36; // Seen 208243456 + uint32 playersinzonestring; + uint32 unknown52; // Same as playercount? + uint32 unknown44[2]; // 0s + uint32 unknown56; // Same as playercount? + uint32 playercount; // Player Count in the who list + struct WhoAllPlayer player[0]; +}; + +// The following four structs are the WhoAllPlayer struct above broken down +// for use in World ClientList::SendFriendsWho to accomodate the user of variable +// length strings within the struct above. + +struct WhoAllPlayerPart1 { + uint32 FormatMSGID; + uint32 Unknown04; + uint32 Unknown08; + char Name[1]; +}; + +struct WhoAllPlayerPart2 { + uint32 RankMSGID; + char Guild[1]; +}; + +struct WhoAllPlayerPart3 { + uint32 Unknown80[2]; + uint32 ZoneMSGID; + uint32 Zone; + uint32 Class_; + uint32 Level; + uint32 Race; + char Account[1]; +}; + +struct WhoAllPlayerPart4 { + uint32 Unknown100; +}; + +struct TraderItemSerial_Struct { + char SerialNumber[17]; + uint8 Unknown18; +}; + +struct Trader_Struct { +/*0000*/ uint32 Code; +/*0004*/ TraderItemSerial_Struct items[200]; +/*3604*/ uint32 ItemCost[200]; +/*4404*/ +}; + +struct ClickTrader_Struct { +/*0000*/ uint32 Code; +/*0004*/ TraderItemSerial_Struct items[200]; +/*3604*/ uint32 ItemCost[200]; +/*4404*/ +}; + +struct GetItems_Struct { + uint32 items[200]; +}; + +struct BecomeTrader_Struct { + uint32 id; + uint32 code; +}; + +struct Trader_ShowItems_Struct { +/*000*/ uint32 Code; +/*004*/ char SerialNumber[17]; +/*021*/ uint8 Unknown21; +/*022*/ uint16 TraderID; +/*026*/ uint32 Stacksize; +/*030*/ uint32 Price; +/*032*/ +}; + +struct TraderStatus_Struct { +/*000*/ uint32 Code; +/*004*/ uint32 Uknown04; +/*008*/ uint32 Uknown08; +/*012*/ +}; + +struct TraderBuy_Struct { +/*000*/ uint32 Action; +/*004*/ uint32 Unknown004; +/*008*/ uint32 Price; +/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price. +/*016*/ uint32 TraderID; +/*020*/ char ItemName[64]; +/*084*/ uint32 Unknown076; +/*088*/ uint32 ItemID; +/*092*/ uint32 AlreadySold; +/*096*/ uint32 Quantity; +/*100*/ uint32 Unknown092; +/*104*/ +}; + +struct TraderItemUpdate_Struct{ + uint32 unknown0; + uint32 traderid; + uint8 fromslot; + uint8 toslot; //7? + uint16 charges; +}; + +struct MoneyUpdate_Struct{ + int32 platinum; + int32 gold; + int32 silver; + int32 copper; +}; + +//struct MoneyUpdate_Struct +//{ +//*0000*/ uint32 spawn_id; // ***Placeholder +//*0004*/ uint32 cointype; // Coin Type +//*0008*/ uint32 amount; // Amount +//*0012*/ +//}; + + +struct TraderDelItem_Struct{ + uint32 slotid; + uint32 quantity; + uint32 unknown; +}; + +struct TraderClick_Struct{ + uint32 traderid; + uint32 unknown4[2]; + uint32 approval; +}; + +struct FormattedMessage_Struct{ + uint32 unknown0; + uint32 string_id; + uint32 type; + char message[0]; +//*0???*/ uint8 unknown0[8]; // ***Placeholder +}; +struct SimpleMessage_Struct{ + uint32 string_id; + uint32 color; + uint32 unknown8; +}; + +// Size: 52 + strings +// Other than the strings, all of this packet is network byte order (reverse from normal) +struct GuildMemberEntry_Struct { + char name[1]; // variable length + uint32 level; + uint32 banker; // 1=yes, 0=no + uint32 class_; + uint32 rank; + uint32 time_last_on; + uint32 tribute_enable; + uint32 unknown01; // Seen 0 + uint32 total_tribute; // total guild tribute donated, network byte order + uint32 last_tribute; // unix timestamp + uint32 unknown_one; // unknown, set to 1 + char public_note[1]; // variable length. + uint16 zoneinstance; // Seen 0s or -1 in RoF2 + uint16 zone_id; // Seen 0s or -1 in RoF2 + uint32 unknown_one2; // unknown, set to 1 + uint32 unknown04; // Seen 0 +}; + +//just for display purposes, this is not actually used in the message encoding other than for size. +struct GuildMembers_Struct { + char player_name[1]; // variable length. + uint32 guildid; // Was unknown02 - network byte order + uint32 count; // network byte order + GuildMemberEntry_Struct member[0]; +}; + +struct GuildMOTD_Struct{ +/*0000*/ uint32 unknown0; +/*0004*/ char name[64]; +/*0068*/ char setby_name[64]; +/*0132*/ uint32 unknown132; +/*0136*/ char motd[0]; //was 512 +}; + +struct GuildURL_Struct{ +/*0000*/ uint32 unknown0; //index? seen server send 0 w/ the Guild URL, followed by 1 with nothing. +/*0004*/ uint32 unknown4; +/*0008*/ uint32 unknown8; //seen 7 +/*0012*/ char setby_name[64]; +/*0076*/ uint32 unknown132; //seen 0xc7de +/*0136*/ char url[4040]; +}; + +struct GuildStatus_Struct +{ +/*000*/ char Name[64]; +/*064*/ uint8 Unknown064[76]; +}; + +struct GuildMemberUpdate_Struct { +/*00*/ uint32 GuildID; +/*04*/ char MemberName[64]; +/*68*/ uint16 ZoneID; +/*70*/ uint16 InstanceID; //speculated +/*72*/ uint32 LastSeen; //unix timestamp +/*76*/ uint32 Unknown76; +/*80*/ +}; + +struct GuildMemberLevelUpdate_Struct { +/*00*/ uint32 guild_id; +/*04*/ char member_name[64]; +/*68*/ uint32 level; //not sure +}; + +struct GuildUpdate_PublicNote { + uint32 unknown0; + char name[64]; + char target[64]; + char note[100]; //we are cutting this off at 100, actually around 252 +}; + +struct GuildDemoteStruct { +/*000*/ char name[64]; +/*064*/ char target[64]; +/*128*/ uint32 rank; // New in RoF2 +/*132*/ +}; + +struct GuildRemoveStruct { +/*000*/ char target[64]; +/*064*/ char name[64]; +/*128*/ uint32 GuildID; // Was unknown128 +/*132*/ uint32 leaderstatus; +/*136*/ uint32 unknown136; // New in RoF2 +/*140*/ +}; + +struct GuildMakeLeader { + char name[64]; + char target[64]; +}; + +// Server -> Client +// Update a guild members rank and banker status +struct GuildSetRank_Struct +{ +/*00*/ uint32 GuildID; // Was Unknown00 +/*04*/ uint32 Rank; +/*08*/ char MemberName[64]; +/*72*/ uint32 Banker; +/*76*/ uint32 Unknown76; // Seen 1 - Maybe Banker? +/*80*/ +}; + +struct BugStruct{ +/*0000*/ char chartype[64]; +/*0064*/ char name[96]; +/*0160*/ char ui[128]; +/*0288*/ float x; +/*0292*/ float y; +/*0296*/ float z; +/*0300*/ float heading; +/*0304*/ uint32 unknown304; +/*0308*/ uint32 type; +/*0312*/ char unknown312[2144]; +/*2456*/ char bug[1024]; +/*3480*/ char placeholder[2]; +/*3482*/ char system_info[4098]; +}; +struct Make_Pet_Struct { //Simple struct for getting pet info + uint8 level; + uint8 class_; + uint16 race; + uint8 texture; + uint8 pettype; + float size; + uint8 type; + uint32 min_dmg; + uint32 max_dmg; +}; +struct Ground_Spawn{ + float max_x; + float max_y; + float min_x; + float min_y; + float max_z; + float heading; + char name[16]; + uint32 item; + uint32 max_allowed; + uint32 respawntimer; +}; +struct Ground_Spawns { + struct Ground_Spawn spawn[50]; //Assigned max number to allow +}; +struct PetitionBug_Struct{ + uint32 petition_number; + uint32 unknown4; + char accountname[64]; + uint32 zoneid; + char name[64]; + uint32 level; + uint32 class_; + uint32 race; + uint32 unknown152[3]; + uint32 time; + uint32 unknown168; + 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; + uint32 approve; +}; +struct ZoneInSendName_Struct { + uint32 unknown0; + char name[64]; + char name2[64]; + uint32 unknown132; +}; +struct ZoneInSendName_Struct2 { + uint32 unknown0; + char name[64]; + uint32 unknown68[145]; +}; + +struct StartTribute_Struct { + uint32 client_id; + uint32 tribute_master_id; + uint32 response; +}; + +struct TributeLevel_Struct { + uint32 level; //backwards byte order! + uint32 tribute_item_id; //backwards byte order! + uint32 cost; //backwards byte order! +}; + +struct TributeAbility_Struct { +/*000*/ uint32 tribute_id; //backwards byte order! +/*004*/ uint32 tier_count; //backwards byte order! +/*008*/ TributeLevel_Struct tiers[MAX_TRIBUTE_TIERS]; +/*128*/ uint32 unknown128; // New to RoF2 +/*132*/ char name[0]; +}; + +struct GuildTributeAbility_Struct { + uint32 guild_id; + TributeAbility_Struct ability; +}; + +struct SelectTributeReq_Struct { + uint32 client_id; //? maybe action ID? + uint32 tribute_id; + uint32 unknown8; //seen E3 00 00 00 +}; + +struct SelectTributeReply_Struct { + uint32 client_id; //echoed from request. + uint32 tribute_id; + char desc[0]; +}; + +struct TributeInfo_Struct { + uint32 active; //0 == inactive, 1 == active + uint32 tributes[MAX_PLAYER_TRIBUTES]; //-1 == NONE + uint32 tiers[MAX_PLAYER_TRIBUTES]; //all 00's + uint32 tribute_master_id; +}; + +struct TributeItem_Struct +{ +/*00*/ ItemSlotStruct slot; +/*12*/ uint32 quantity; +/*16*/ uint32 tribute_master_id; +/*20*/ int32 tribute_points; +/*24*/ +}; + +struct TributePoint_Struct { + int32 tribute_points; + uint32 unknown04; + int32 career_tribute_points; + uint32 unknown12; +}; + +struct TributeMoney_Struct { + uint32 platinum; + uint32 tribute_master_id; + int32 tribute_points; +}; + + +struct Split_Struct +{ + uint32 platinum; + uint32 gold; + uint32 silver; + uint32 copper; +}; + + +/* +** New Combine Struct +** Client requesting to perform a tradeskill combine +** Size: 24 bytes +** 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 -U) +/*24*/ +}; + + +//client requesting favorite recipies +struct TradeskillFavorites_Struct { + uint32 object_type; + uint32 some_id; + uint32 favorite_recipes[500]; +}; + +//search request +struct RecipesSearch_Struct { + uint32 object_type; //same as in favorites + uint32 some_id; //same as in favorites + uint32 mintrivial; + uint32 maxtrivial; + char query[56]; + uint32 unknown4; //is set to 00 03 00 00 + uint32 unknown5; //is set to 4C DD 12 00 +/*80*/ +}; + +//one sent for each item, from server in reply to favorites or search +struct RecipeReply_Struct { + uint32 object_type; + uint32 some_id; //same as in favorites + uint32 component_count; + uint32 recipe_id; + uint32 trivial; + char recipe_name[64]; +/*84*/ +}; + +//received and sent back as an ACK with different reply_code +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 +/*32*/ uint32 recipe_id; +/*36*/ uint32 reply_code; +/*40*/ +}; + +struct LevelAppearance_Struct { //Sends a little graphic on level up + uint32 spawn_id; + uint32 parm1; + uint32 value1a; + uint32 value1b; + uint32 parm2; + uint32 value2a; + uint32 value2b; + uint32 parm3; + uint32 value3a; + uint32 value3b; + uint32 parm4; + uint32 value4a; + uint32 value4b; + uint32 parm5; + uint32 value5a; + uint32 value5b; +/*64*/ +}; +struct MerchantList{ + uint32 id; + uint32 slot; + uint32 item; +}; +struct TempMerchantList{ + uint32 npcid; + uint32 slot; + uint32 item; + uint32 charges; //charges/quantity + uint32 origslot; +}; + + +struct FindPerson_Point { + float y; + float x; + float z; +}; + +struct FindPersonRequest_Struct { +/*00*/ uint32 unknown00; +/*04*/ uint32 npc_id; +/*08*/ uint32 unknown08; +/*12*/ uint32 unknown12; +/*16*/ FindPerson_Point client_pos; +/*28*/ uint32 unknown28; +/*32*/ uint32 unknown32; +/*36*/ uint32 unknown36; +}; + +//variable length packet of points +struct FindPersonResult_Struct { + FindPerson_Point dest; + FindPerson_Point path[0]; //last element must be the same as dest +}; + +struct MobRename_Struct { +/*000*/ char old_name[64]; +/*064*/ char old_name_again[64]; //not sure what the difference is +/*128*/ char new_name[64]; +/*192*/ uint32 unknown192; //set to 0 +/*196*/ uint32 unknown196; //set to 1 +/*200*/ +}; + +struct PlayMP3_Struct { + char filename[0]; +}; + +//this is for custom title display in the skill window +struct TitleEntry_Struct { + uint32 skill_id; + uint32 skill_value; + char title[1]; +}; + +struct Titles_Struct { + uint32 title_count; + TitleEntry_Struct titles[0]; +}; + +//this is for title selection by the client +struct TitleListEntry_Struct { + uint32 unknown0; //title ID + char prefix[1]; //variable length, null terminated + char postfix[1]; //variable length, null terminated +}; + +struct TitleList_Struct { + uint32 title_count; + TitleListEntry_Struct titles[0]; //list of title structs + //uint32 unknown_ending; seen 0x7265, 0 +}; + +struct SetTitle_Struct { + uint32 is_suffix; //guessed: 0 = prefix, 1 = suffix + uint32 title_id; +}; + +struct SetTitleReply_Struct { + uint32 is_suffix; //guessed: 0 = prefix, 1 = suffix + char title[32]; + uint32 entity_id; +}; + + +#if 0 +// Old struct not used by Task System implementation but left for reference +struct TaskDescription_Struct { +/*000*/ uint32 activity_count; //not right. +/*004*/ uint32 taskid; +/*008*/ uint8 unk; +/*009*/ uint32 id3; +/*013*/ uint32 unknown13; +/*017*/ char name[1]; //variable length, 0 terminated +/*018*/ uint32 unknown18; +/*022*/ uint32 unknown22; +/*026*/ uint32 unknown26; +/*030*/ char desc[1]; //variable length, 0 terminated +/*031*/ uint32 reward_count; //not sure +/*035*/ uint8 unknown31; +/*036*/ uint32 unknown31; +/*040*/ uint32 unknown35; +/*044*/ uint16 unknown39; +/*046*/ char reward_link[1]; //variable length, 0 terminated +/*047*/ uint32 unknown43; //maybe crystal count? +/*051*/ +}; +#endif + +struct TaskMemberList_Struct { +/*00*/ uint32 gopher_id; +/*04*/ uint32 unknown04; +/*08*/ uint32 member_count; //1 less than the number of members +/*12*/ char list_pointer[0]; +/* list is of the form: + char member_name[1] //null terminated string + uint8 task_leader //boolean flag +*/ +}; + +#if 0 +// Struct not used by Task System implentation but left for reference (current for RoF2) +struct TaskActivity_Struct { +/*000*/ uint32 TaskSequenceNumber; +/*004*/ uint32 unknown2; +/*008*/ uint32 TaskID; +/*012*/ uint32 ActivityID; +/*016*/ uint32 unknown3; +/*020*/ uint32 ActivityType; +/*024*/ uint32 Optional; +/*028*/ uint8 unknown5; +/*032*/ char Text1[1]; // Variable length - Null terminated +/*000*/ uint32 Text2Len; // Lenth of the following string +/*000*/ char Text2[1]; // Variable length - not Null terminated +/*000*/ uint32 GoalCount; +/*000*/ uint32 String1Len; // Lenth of the following string - Seen 2 +/*000*/ char String1[1]; // Numeric String - Seen "-1" - not Null terminated +/*000*/ uint32 String2Len; // Lenth of the following string - Seen 2 +/*000*/ char String2[1]; // Numeric String - Seen "-1" - not Null terminated +/*000*/ char ZoneIDString1[1]; // Numeric String - Seen "398" - Null terminated +/*000*/ uint32 unknown7; // Seen 0 +/*000*/ char Text3[1]; // Variable length - Null terminated +/*000*/ uint32 DoneCount; +/*000*/ uint8 unknown9; // Seen 1 +/*000*/ char ZoneIDString2[1]; // Numeric String - Seen "398" - Null terminated +}; + +struct TaskHistoryEntry_Struct { + uint32 task_id; + char name[1]; + uint32 completed_time; +}; +struct TaskHistory_Struct { + uint32 completed_count; + TaskHistoryEntry_Struct entries[0]; +}; +#endif + +struct AcceptNewTask_Struct { + uint32 unknown00; + uint32 task_id; //set to 0 for 'decline' + uint32 task_master_id; //entity ID +}; + +//was all 0's from client, server replied with same op, all 0's +struct CancelTask_Struct { + uint32 SequenceNumber; + uint32 unknown4; // Only seen 0x00000002 +}; + +#if 0 +// old struct, not used by Task System implementation but left for reference. +struct AvaliableTask_Struct { + uint32 task_index; //no idea, seen 0x1 + uint32 task_master_id; //entity ID + uint32 task_id; + uint32 unknown012; + uint32 activity_count; //not sure, seen 2 + char desc[1]; //variable length, 0 terminated + uint32 reward_platinum;//not sure on these + uint32 reward_gold; + uint32 reward_silver; + uint32 reward_copper; + char some_name[1]; //variable length, 0 terminated + uint8 unknown1; + uint32 unknown2; //0xFFFFFFFF + uint32 unknown3; //0xFFFFFFFF + uint32 unknown4; //seen 0x16 + uint8 unknown5; +}; +#endif + + +// Many of the Task System packets contain variable length strings, as well as variable numbers +// of records, hence splitting them into multiple structs (header, middle, trailer) etc. +// +struct AvailableTaskHeader_Struct { + uint32 TaskCount; + uint32 unknown1; + uint32 TaskGiver; +}; + +struct AvailableTaskData1_Struct { + uint32 TaskID; + uint32 unknown1; + uint32 TimeLimit; + uint32 unknown2; +}; + +struct AvailableTaskData2_Struct { + uint32 unknown1,unknown2,unknown3,unknown4; +}; + +struct AvailableTaskTrailer_Struct { + uint32 ItemCount; + uint32 unknown1, unknown2; + uint32 StartZone; +}; + +struct TaskDescriptionHeader_Struct { + uint32 SequenceNumber; // The order the tasks appear in the journal. 0 for first task, 1 for second, etc. + uint32 TaskID; + uint32 unknown2; + uint32 unknown3; + uint8 unknown4; +}; + +struct TaskDescriptionData1_Struct { + uint32 Duration; + uint32 unknown2; + uint32 StartTime; +}; + +struct TaskDescriptionData2_Struct { + uint32 RewardCount; // ?? + uint32 unknown1; + uint32 unknown2; + uint16 unknown3; + //uint8 unknown4; +}; + +struct TaskDescriptionTrailer_Struct { + //uint16 unknown1; // 0x0012 + uint32 Points; +}; + +struct TaskActivityHeader_Struct { + uint32 TaskSequenceNumber; + uint32 unknown2; // Seen 0x00000002 + uint32 TaskID; + uint32 ActivityID; + uint32 unknown3; + uint32 ActivityType; + uint32 Optional; + uint32 unknown5; +}; + +struct TaskActivityData1_Struct { + uint32 GoalCount; + uint32 unknown1; // 0xffffffff + uint32 unknown2; // 0xffffffff + uint32 ZoneID; // seen 0x36 + uint32 unknown3; +}; + +struct TaskActivityTrailer_Struct { + uint32 DoneCount; + uint32 unknown1; // Seen 1 +}; + +// The Short_Struct is sent for tasks that are hidden and act as a placeholder +struct TaskActivityShort_Struct { + uint32 TaskSequenceNumber; + uint32 unknown2; // Seen 0x00000002 + uint32 TaskID; + uint32 ActivityID; + uint32 unknown3; + uint32 ActivityType; // 0xffffffff for the short packet + uint32 unknown4; +}; + +struct TaskActivityComplete_Struct { + uint32 TaskIndex; + uint32 unknown2; // 0x00000002 + uint32 unknown3; + uint32 ActivityID; + uint32 unknown4; // 0x00000001 + uint32 unknown5; // 0x00000001 +}; + +#if 0 +// This is a dupe of the CancelTask struct +struct TaskComplete_Struct { + uint32 unknown00; // 0x00000000 + uint32 unknown04; // 0x00000002 +}; +#endif + +struct TaskHistoryRequest_Struct { + uint32 TaskIndex; // This is the sequence the task was sent in the Completed Tasks packet. +}; + +struct TaskHistoryReplyHeader_Struct { + uint32 TaskID; + uint32 ActivityCount; +}; + +struct TaskHistoryReplyData1_Struct { + uint32 ActivityType; +}; + +struct TaskHistoryReplyData2_Struct { + uint32 GoalCount; + uint32 unknown04; // 0xffffffff + uint32 unknown08; // 0xffffffff + uint32 ZoneID; + uint32 unknown16; +}; + +struct BankerChange_Struct { +/*00*/ uint32 platinum; +/*04*/ uint32 gold; +/*08*/ uint32 silver; +/*12*/ uint32 copper; +/*16*/ uint32 platinum_bank; +/*20*/ uint32 gold_bank; +/*24*/ uint32 silver_bank; +/*28*/ uint32 copper_bank; +/*32*/ +}; + +struct LeadershipExpUpdate_Struct { +/*00*/ double group_leadership_exp; +/*08*/ uint32 group_leadership_points; +/*12*/ uint32 Unknown12; +/*16*/ double raid_leadership_exp; +/*24*/ uint32 raid_leadership_points; +}; + +struct UpdateLeadershipAA_Struct { +/*00*/ uint32 ability_id; +/*04*/ uint32 new_rank; +/*08*/ uint32 unknown08; +/*12*/ +}; + +/** +* Leadership AA update +* Length: 32 Octets +* OpCode: LeadExpUpdate +*/ +struct leadExpUpdateStruct { + /*0000*/ uint32 unknown0000; // All zeroes? + /*0004*/ uint32 group_leadership_exp; // Group leadership exp value + /*0008*/ uint32 group_leadership_points; // Unspent group points + /*0012*/ uint32 unknown0012; // Type? + /*0016*/ uint32 unknown0016; // All zeroes? + /*0020*/ uint32 raid_leadership_exp; // Raid leadership exp value + /*0024*/ uint32 raid_leadership_points; // Unspent raid points + /*0028*/ uint32 unknown0028; +}; + +struct RaidGeneral_Struct { +/*00*/ uint32 action; +/*04*/ char player_name[64]; +/*68*/ uint32 unknown68; +/*72*/ char leader_name[64]; +/*136*/ uint32 parameter; +}; + +struct RaidAddMember_Struct { +/*000*/ RaidGeneral_Struct raidGen; //param = (group num-1); 0xFFFFFFFF = no group +/*136*/ uint8 _class; +/*137*/ uint8 level; +/*138*/ uint8 isGroupLeader; +/*139*/ uint8 flags[5]; //no idea if these are needed... +}; + +struct RaidMOTD_Struct { +/*000*/ RaidGeneral_Struct general; // leader_name and action only used +/*140*/ char motd[0]; // max size 1024, but reply is variable +}; + +struct RaidLeadershipUpdate_Struct { +/*000*/ uint32 action; +/*004*/ char player_name[64]; +/*068*/ uint32 Unknown068; +/*072*/ char leader_name[64]; +/*136*/ GroupLeadershipAA_Struct group; //unneeded +/*200*/ RaidLeadershipAA_Struct raid; +/*264*/ char Unknown264[128]; +}; + +struct RaidAdd_Struct { +/*000*/ uint32 action; //=0 +/*004*/ char player_name[64]; //should both be the player's name +/*068*/ char leader_name[64]; +/*132*/ uint8 _class; +/*133*/ uint8 level; +/*134*/ uint8 has_group; +/*135*/ uint8 unknown135; //seems to be 0x42 or 0 +}; + +struct RaidCreate_Struct { +/*00*/ uint32 action; //=8 +/*04*/ char leader_name[64]; +/*68*/ uint32 leader_id; +}; + +struct RaidMemberInfo_Struct { +/*00*/ uint8 group_number; +/*01*/ char member_name[1]; //dyanmic length, null terminated '\0' +/*00*/ uint8 unknown00; +/*01*/ uint8 _class; +/*02*/ uint8 level; +/*03*/ uint8 is_raid_leader; +/*04*/ uint8 is_group_leader; +/*05*/ uint8 main_tank; //not sure +/*06*/ uint8 unknown06[5]; //prolly more flags +}; + +struct RaidDetails_Struct { +/*000*/ uint32 action; //=6,20 +/*004*/ char leader_name[64]; +/*068*/ uint32 unknown68[4]; +/*084*/ LeadershipAA_Struct abilities; //ranks in backwards byte order +/*128*/ uint8 unknown128[142]; +/*354*/ uint32 leader_id; +}; + +struct RaidMembers_Struct { +/*000*/ RaidDetails_Struct details; +/*358*/ uint32 member_count; //including leader +/*362*/ RaidMemberInfo_Struct members[1]; +/*...*/ RaidMemberInfo_Struct empty; //seem to have an extra member with a 0 length name on the end +}; + +struct DynamicWall_Struct { +/*00*/ char name[32]; +/*32*/ float y; +/*36*/ float x; +/*40*/ float z; +/*44*/ uint32 something; +/*48*/ uint32 unknown48; //0 +/*52*/ uint32 one_hundred; //0x64 +/*56*/ uint32 unknown56; //0 +/*60*/ uint32 something2; +/*64*/ int32 unknown64; //-1 +/*68*/ uint32 unknown68; //0 +/*72*/ uint32 unknown72; //0 +/*76*/ uint32 unknown76; //0x100 +/*80*/ +}; + +enum { //bandolier actions + BandolierCreate = 0, + BandolierRemove = 1, + BandolierSet = 2 +}; + +struct BandolierCreate_Struct { +/*00*/ uint32 action; //0 for create +/*04*/ uint8 number; +/*05*/ char name[32]; +/*37*/ uint16 unknown37; //seen 0x93FD +/*39*/ uint8 unknown39; //0 +}; + +struct BandolierDelete_Struct { +/*00*/ uint32 action; +/*04*/ uint8 number; +/*05*/ uint8 unknown05[35]; +}; + +struct BandolierSet_Struct { +/*00*/ uint32 action; +/*04*/ uint8 number; +/*05*/ uint8 unknown05[35]; +}; + +struct Arrow_Struct { +/*000*/ float src_y; +/*004*/ float src_x; +/*008*/ float src_z; +/*012*/ uint8 unknown012[12]; +/*024*/ float velocity; //4 is normal, 20 is quite fast +/*028*/ float launch_angle; //0-450ish, not sure the units, 140ish is straight +/*032*/ float tilt; //on the order of 125 +/*036*/ uint8 unknown036[8]; +/*044*/ float arc; +/*048*/ uint32 source_id; +/*052*/ uint32 target_id; //entity ID +/*056*/ uint32 item_id; +/*060*/ uint32 unknown060; +/*064*/ uint32 unknown064; +/*068*/ uint8 unknown068; +/*069*/ uint8 unknown069; +/*070*/ uint8 unknown070; +/*071*/ uint8 item_type; +/*072*/ uint8 skill; +/*073*/ uint8 unknown073[16]; +/*089*/ char model_name[27]; +/*116*/ +}; + +//made a bunch of trivial structs for stuff for opcode finder to use +struct Consent_Struct { + char name[1]; //always at least a null - was 1 +}; + +struct AdventureMerchant_Struct { + uint32 unknown_flag; //seems to be 1 + uint32 entity_id; +}; + +// OP_Save - Size: 484 +struct Save_Struct { +/*000*/ uint8 unknown00[192]; +/*192*/ uint8 unknown0192[176]; +/*368*/ uint8 unknown0368[116]; +/*484*/ +}; + +struct GMToggle_Struct { + uint8 unknown0[64]; + uint32 toggle; +}; + +struct ColoredText_Struct { + uint32 color; + char msg[1]; //was 1 +/*0???*/ uint8 paddingXXX[3]; // always 0's +}; + +struct UseAA_Struct { + uint32 begin; + uint32 ability; + uint32 end; +}; + +struct AA_Ability { +/*00*/ uint32 skill_id; +/*04*/ uint32 base1; +/*08*/ uint32 base2; +/*12*/ uint32 slot; +/*16*/ +}; + +struct SendAA_Struct { +/*0000*/ uint32 id; +/*0004*/ uint8 unknown004; // uint32 unknown004; set to 1. +/*0005*/ int32 hotkey_sid; +/*0009*/ int32 hotkey_sid2; +/*0013*/ uint32 title_sid; +/*0017*/ uint32 desc_sid; +/*0021*/ uint32 class_type; +/*0025*/ uint32 cost; +/*0029*/ uint32 seq; +/*0033*/ uint32 current_level; //1s, MQ2 calls this AARankRequired +/*0037*/ uint32 unknown037; // Introduced during HoT +/*0041*/ uint32 prereq_skill; //is < 0, abs() is category # +/*0045*/ uint32 unknown045; // New Mar 21 2012 - Seen 1 +/*0049*/ uint32 prereq_minpoints; //min points in the prereq +/*0053*/ uint32 type; +/*0057*/ uint32 spellid; +/*0061*/ uint32 unknown057; // Introduced during HoT - Seen 1 - Maybe account status or enable/disable AA? +/*0065*/ uint32 spell_type; +/*0069*/ uint32 spell_refresh; +/*0073*/ uint16 classes; +/*0075*/ uint16 berserker; //seems to be 1 if its a berserker ability +/*0077*/ uint32 max_level; +/*0081*/ uint32 last_id; +/*0085*/ uint32 next_id; +/*0089*/ uint32 cost2; +/*0093*/ uint8 unknown80[7]; +/*0100*/ uint32 aa_expansion; +/*0104*/ uint32 special_category; +/*0108*/ uint32 unknown0096; +/*0112*/ uint32 total_abilities; +/*0116*/ AA_Ability abilities[0]; +}; + +struct AA_List { + SendAA_Struct* aa[0]; +}; + +struct AA_Action { +/*00*/ uint32 action; +/*04*/ uint32 ability; +/*08*/ uint32 unknown08; +/*12*/ uint32 exp_value; +/*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; +/*08*/ uint8 aaxp_percent; //% of exp that goes to AAs +/*09*/ uint8 unknown09[3]; //live doesn't always zero these, so they arnt part of aaxp_percent +/*12*/ +}; + +struct AltAdvStats_Struct { +/*000*/ uint32 experience; +/*004*/ uint16 unspent; +/*006*/ uint16 unknown006; +/*008*/ uint8 percentage; +/*009*/ uint8 unknown009[3]; +/*012*/ +}; + +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*/ +}; + +struct AATable_Struct { +/*00*/ uint32 aa_spent; // Total AAs Spent +/*04*/ uint32 aapoints_assigned; // Number of Assigned AA points - Seen 206 (total of the 4 fields below) +/*08*/ uint32 aa_spent_general; // Seen 63 +/*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]; +}; + +struct Weather_Struct { + uint32 val1; //generall 0x000000FF + uint32 type; //0x31=rain, 0x02=snow(i think), 0 = normal + uint32 mode; +}; + +struct ZoneInUnknown_Struct { + uint32 val1; + uint32 val2; + uint32 val3; +}; + +struct MobHealth_Struct { + uint16 entity_id; + uint8 hp; +}; + +struct AnnoyingZoneUnknown_Struct { + uint32 entity_id; + uint32 value; //always 4 +}; + +struct LoadSpellSet_Struct { + uint8 spell[12]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0 + uint32 unknown; //Seen 12 - Maybe a gem count? +}; + +struct BlockedBuffs_Struct +{ +/*000*/ int32 SpellID[BLOCKED_BUFF_COUNT]; +/*120*/ uint32 Count; +/*124*/ uint8 Pet; +/*125*/ uint8 Initialise; +/*126*/ uint16 Flags; +}; + +//Size 24 Bytes +struct WorldObfuscator_Struct { +/*000*/ uint32 var1; +/*004*/ uint32 Unknown1; +/*008*/ uint32 Unknown2; +/*012*/ uint32 Unknown3; +/*016*/ uint32 var2; +/*020*/ uint32 Unknown4; +/*024*/ +}; + +struct ExpansionInfo_Struct { +/*000*/ char Unknown000[64]; +/*064*/ uint32 Expansions; +}; + +struct ApplyPoison_Struct { + MainInvItemSlotStruct inventorySlot; + uint32 success; +}; + +struct ItemVerifyRequest_Struct { +/*000*/ ItemSlotStruct slot; +/*012*/ uint32 target; // Target Entity ID +/*016*/ +}; + +struct ItemVerifyReply_Struct { +/*000*/ ItemSlotStruct slot; +/*012*/ uint32 spell; // Spell ID to cast if different than item effect +/*016*/ uint32 target; // Target Entity ID +/*020*/ +}; + + +struct RoF2SlotStruct +{ + uint8 Bank; + uint16 MainSlot; + uint16 SubSlot; +}; + +struct ItemSerializationHeader +{ +/*000*/ char unknown000[13]; // New for HoT. Looks like a string. +/*017*/ uint32 stacksize; +/*021*/ uint32 unknown004; +/*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 +/*032*/ uint32 price; +/*036*/ uint32 merchant_slot; //1 if not a merchant item +/*040*/ uint32 scaled_value; //0 +/*044*/ uint32 instance_id; //unique instance id if not merchant item, else is merchant slot +/*048*/ uint32 unknown028; //0 +/*052*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0 +/*056*/ uint32 charges; //Total Charges an item has (-1 for unlimited) +/*060*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items) +/*064*/ uint32 unknown044; // 0 +/*068*/ uint32 unknown048; // 0 +/*072*/ uint32 unknown052; // 0 + uint8 isEvolving; +}; + +struct EvolvingItem { + uint8 unknown001; + uint8 unknown002; + uint8 unknown003; + uint8 unknown004; + int32 evoLevel; + double progress; + uint8 Activated; + int32 evomaxlevel; + uint8 unknown005[4]; +}; + +struct ItemSerializationHeaderFinish +{ + uint16 ornamentIcon; +/*081*/ uint8 unknown061; // 0 - Add Evolving Item struct if this isn't set to 0? +/*082*/ uint8 unknown062; // 0 +/*083*/ uint32 unknowna1; // 0xffffffff +/*087*/ uint32 unknowna2; // 0 +/*091*/ uint8 unknown063; // 0 +/*092*/ uint32 unknowna3; // 0 +/*096*/ uint32 unknowna4; // 0xffffffff +/*100*/ uint32 unknowna5; // 0 +/*104*/ uint8 ItemClass; //0, 1, or 2 +/*105*/ +}; + +struct ItemBodyStruct +{ + uint32 id; + int32 weight; // Seen an item on Live with -0.1 weight + uint8 norent; + uint8 nodrop; + uint8 attune; + uint8 size; + uint32 slots; + uint32 price; + uint32 icon; + uint8 unknown1; + uint8 unknown2; + uint32 BenefitFlag; + uint8 tradeskills; + int8 CR; + int8 DR; + int8 PR; + int8 MR; + int8 FR; + int8 SVCorruption; + int8 AStr; + int8 ASta; + int8 AAgi; + int8 ADex; + int8 ACha; + int8 AInt; + int8 AWis; + int32 HP; + int32 Mana; + uint32 Endur; + int32 AC; + int32 regen; + int32 mana_regen; + int32 end_regen; + uint32 Classes; + uint32 Races; + uint32 Deity; + int32 SkillModValue; + int32 SkillModMax; // Max skill point modification + int32 SkillModType; + uint32 SkillModExtra; // Adds a "+value" after the mod percentage + uint32 BaneDmgRace; + uint32 BaneDmgBody; + uint32 BaneDmgRaceAmt; + int32 BaneDmgAmt; + uint8 Magic; + int32 CastTime_; + uint32 ReqLevel; + uint32 RecLevel; + uint32 RecSkill; + uint32 BardType; + int32 BardValue; + uint8 Light; + uint8 Delay; + uint8 ElemDmgType; + uint8 ElemDmgAmt; + uint8 Range; + uint32 Damage; + uint32 Color; + uint32 Prestige; // New to March 21 2012 client + uint8 ItemType; + uint32 Material; + uint32 unknown7; + uint32 EliteMaterial; + uint32 unknown_RoF23; // New to March 21 2012 client + uint32 unknown_RoF24; // New to December 10th 2012 client - NEW + float SellRate; + int32 CombatEffects; + int32 Shielding; + int32 StunResist; + int32 StrikeThrough; + int32 ExtraDmgSkill; + int32 ExtraDmgAmt; + int32 SpellShield; + int32 Avoidance; + int32 Accuracy; + uint32 CharmFileID; + uint32 FactionMod1; + int32 FactionAmt1; + uint32 FactionMod2; + int32 FactionAmt2; + uint32 FactionMod3; + int32 FactionAmt3; + uint32 FactionMod4; + int32 FactionAmt4; +}; + +struct AugSlotStruct +{ + uint32 type; + uint8 visible; + uint8 unknown; +}; + +struct ItemSecondaryBodyStruct +{ + uint32 augtype; + // swapped augrestrict and augdistiller positions + // (this swap does show the proper augment restrictions in Item Information window now) + // unsure what the purpose of augdistiller is at this time -U 3/17/2014 + uint32 augdistiller; // New to December 10th 2012 client - NEW + uint32 augrestrict; + AugSlotStruct augslots[6]; + + uint32 ldonpoint_type; + uint32 ldontheme; + uint32 ldonprice; + uint32 ldonsellbackrate; + uint32 ldonsold; + + uint8 bagtype; + uint8 bagslots; + uint8 bagsize; + uint8 wreduction; + + uint8 book; + uint8 booktype; + //int32 filename; filename is either 0xffffffff/0x00000000 or the null term string ex: CREWizardNote\0 +}; + +struct ItemTertiaryBodyStruct +{ + int32 loregroup; + uint8 artifact; + uint8 summonedflag; + uint32 favor; + uint8 fvnodrop; + int32 dotshield; + int32 atk; + int32 haste; + int32 damage_shield; + uint32 guildfavor; + uint32 augdistil; + int32 unknown3; // 0xffffffff + uint32 unknown4; + uint8 no_pet; + uint8 unknown5; + + uint8 potion_belt_enabled; + uint32 potion_belt_slots; + + uint32 stacksize; + uint8 no_transfer; + uint16 expendablearrow; + + uint32 unknown8; + uint32 unknown9; + uint32 unknown10; + uint32 unknown11; + uint8 unknown12; + uint8 unknown13; + uint8 unknown14; +}; + +struct ClickEffectStruct +{ + int32 effect; + uint8 level2; + uint32 type; + uint8 level; + int32 max_charges; + int32 cast_time; + uint32 recast; + int32 recast_type; + uint32 clickunk5; + //uint8 effect_string; + //int32 clickunk7; +}; + +struct ProcEffectStruct +{ + uint32 effect; + uint8 level2; + uint32 type; + uint8 level; + uint32 unknown1; // poison? + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + uint32 procrate; + //uint8 effect_string; + //uint32 unknown5; +}; + +struct WornEffectStruct //worn, focus and scroll effect +{ + uint32 effect; + uint8 level2; + uint32 type; + uint8 level; + uint32 unknown1; + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + uint32 unknown5; + //uint8 effect_string; + //uint32 unknown6; +}; + +struct ItemQuaternaryBodyStruct +{ + uint32 scriptfileid; + uint8 quest_item; + uint32 Power; // Enables "Power" percentage field used by Power Sources + uint32 Purity; + uint8 unknown16; // RoF2 + 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; + 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; + uint8 unknown22; + uint32 unknown23; + uint32 unknown24; + uint32 unknown25; + float unknown26; + float unknown27; + uint32 unknown_RoF26; // 0 New to March 21 2012 client + uint32 unknown28; // 0xffffffff + uint16 unknown29; + uint32 unknown30; // 0xffffffff + uint16 unknown31; + uint32 unknown32; + float unknown33; + uint32 unknown34; + uint32 unknown35; + uint32 unknown36; + uint32 unknown37; + uint32 unknown_RoF27; + uint32 unknown_RoF28; + + // Begin RoF2 Test + uint8 unknown_TEST1; + // End RoF2 Test + + uint8 unknown38; // 0 + uint8 unknown39; // 1 + uint32 subitem_count; +}; + +struct AugmentInfo_Struct +{ +/*000*/ uint32 itemid; // id of the solvent needed +/*004*/ uint32 window; // window to display the information in +/*008*/ char augment_info[64]; // total packet length 76, all the rest were always 00 +/*072*/ uint32 unknown072; +}; + +struct VeteranRewardItem +{ +/*000*/ uint32 item_id; +/*004*/ uint32 charges; +/*008*/ char item_name[64]; +}; + +struct VeteranReward +{ +/*000*/ uint32 claim_id; +/*004*/ uint32 number_available; +/*008*/ uint32 claim_count; +/*012*/ VeteranRewardItem items[8]; +}; + +struct ExpeditionEntryHeader_Struct +{ +/*000*/ uint32 unknown000; +/*000*/ uint32 number_of_entries; +}; + +struct ExpeditionJoinPrompt_Struct +{ +/*000*/ uint32 clientid; +/*004*/ uint32 unknown004; +/*008*/ char player_name[64]; +/*072*/ char expedition_name[64]; +}; + +struct ExpeditionExpireWarning +{ +/*000*/ uint32 clientid; +/*004*/ uint32 unknown004; +/*008*/ uint32 minutes_remaining; +}; + +struct ExpeditionInfo_Struct +{ +/*000*/ uint32 clientid; +/*004*/ uint32 unknown004; +/*008*/ uint32 unknown008; +/*012*/ uint32 max_players; +/*016*/ char expedition_name[128]; +/*142*/ char leader_name[64]; +}; + +struct ExpeditionCompassEntry_Struct +{ +/*000*/ float unknown000; //seen *((uint32*)) = 1584791871 +/*004*/ uint32 enabled; //guess +/*008*/ uint32 unknown008; //seen 1019 +/*012*/ float y; +/*016*/ float x; +/*020*/ float z; +}; + +struct ExpeditionCompass_Struct +{ +/*000*/ uint32 clientid; +/*004*/ uint32 count; +/*008*/ ExpeditionCompassEntry_Struct entries[0]; +}; + +struct MaxCharacters_Struct +{ +/*000*/ uint32 max_chars; // Seen 4 on Silver Account (4 chars max) +/*004*/ uint32 unknown004; // Seen 0 +/*008*/ uint32 unknown008; // Seen 0 +}; + +// Used by MercenaryListEntry_Struct +struct MercenaryStance_Struct { +/*0000*/ uint32 StanceIndex; // Index of this stance (sometimes reverse reverse order - 3, 2, 1, 0 for 4 stances etc) +/*0004*/ uint32 Stance; // From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc +}; +// Used by MercenaryMerchantList_Struct +struct MercenaryListEntry_Struct { +/*0000*/ uint32 MercID; // ID unique to each type of mercenary (probably a DB id) +/*0004*/ uint32 MercType; // From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300) +/*0008*/ uint32 MercSubType; // From dbstr_us.txt - 330020105^23^Race: Guktan
Type: Healer
Confidence: High
Proficiency: Apprentice, Tier V... +/*0012*/ uint32 PurchaseCost; // Purchase Cost (in gold) +/*0016*/ uint32 UpkeepCost; // Upkeep Cost (in gold) +/*0020*/ uint32 Status; // Required Account Status (Free = 0, Silver = 1, Gold = 2) at merchants - Seen 0 (suspended) or 1 (unsuspended) on hired mercs ? +/*0024*/ uint32 AltCurrencyCost; // Alternate Currency Purchase Cost? (all seen costs show N/A Bayle Mark) - Seen 0 +/*0028*/ uint32 AltCurrencyUpkeep; // Alternate Currency Upkeep Cost? (all seen costs show 1 Bayle Mark) - Seen 1 +/*0032*/ uint32 AltCurrencyType; // Alternate Currency Type? - 19^17^Bayle Mark^0 - Seen 19 +/*0036*/ uint8 MercUnk01; // Unknown (always see 0) +/*0037*/ int32 TimeLeft; // Unknown (always see -1 at merchant) - Seen 900000 (15 minutes in ms for newly hired merc) +/*0041*/ uint32 MerchantSlot; // Merchant Slot? Increments, but not always by 1 - May be for Merc Window Options (Seen 5, 36, 1 for active mercs)? +/*0045*/ uint32 MercUnk02; // Unknown (normally see 1, but sometimes 2 or 0) +/*0049*/ uint32 StanceCount; // Iterations of MercenaryStance_Struct - Normally 2 to 4 seen +/*0053*/ int32 MercUnk03; // Unknown (always 0 at merchant) - Seen on active merc: 93 a4 03 77, b8 ed 2f 26, 88 d5 8b c3, and 93 a4 ad 77 +/*0057*/ uint8 MercUnk04; // Seen 1 +/*0058*/ char MercName[1]; // Null Terminated Mercenary Name (00 at merchants) +/*0000*/ MercenaryStance_Struct Stances[1]; // Count Varies - From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc +}; + +// Sent by the server when browsing the Mercenary Merchant +struct MercenaryMerchantList_Struct { +/*0000*/ uint32 MercTypeCount; // Number of Merc Types to follow +/*0004*/ uint32 MercTypes[1]; // Count varies, but hard set to 3 max for now - From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300) +/*0016*/ uint32 MercCount; // Number of MercenaryInfo_Struct to follow +/*0020*/ MercenaryListEntry_Struct Mercs[0]; // Data for individual mercenaries in the Merchant List +}; + +// OP_MercenaryDataRequest +// Right clicking merchant - shop request +struct MercenaryMerchantShopRequest_Struct { +/*0000*/ uint32 MercMerchantID; // Entity ID of the Mercenary Merchant +/*0004*/ +}; + +// Used by MercenaryDataUpdate_Struct +struct MercenaryData_Struct { +/*0000*/ uint32 MercID; // ID unique to each type of mercenary (probably a DB id) - (if 1, do not send MercenaryData_Struct - No merc hired) +/*0004*/ uint32 MercType; // From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300) +/*0008*/ uint32 MercSubType; // From dbstr_us.txt - 330020105^23^Race: Guktan
Type: Healer
Confidence: High
Proficiency: Apprentice, Tier V... +/*0012*/ uint32 PurchaseCost; // Purchase Cost (in gold) +/*0016*/ uint32 UpkeepCost; // Upkeep Cost (in gold) +/*0020*/ uint32 Status; // Required Account Status (Free = 0, Silver = 1, Gold = 2) at merchants - Seen 0 (suspended) or 1 (unsuspended) on hired mercs ? +/*0024*/ uint32 AltCurrencyCost; // Alternate Currency Purchase Cost? (all seen costs show N/A Bayle Mark) - Seen 0 +/*0028*/ uint32 AltCurrencyUpkeep; // Alternate Currency Upkeep Cost? (all seen costs show 1 Bayle Mark) - Seen 1 +/*0032*/ uint32 AltCurrencyType; // Alternate Currency Type? - 19^17^Bayle Mark^0 - Seen 19 +/*0036*/ uint8 MercUnk01; // Unknown (always see 0) +/*0037*/ int32 TimeLeft; // Unknown (always see -1 at merchant) - Seen 900000 (15 minutes in ms for newly hired merc) +/*0041*/ uint32 MerchantSlot; // Merchant Slot? Increments, but not always by 1 - May be for Merc Window Options (Seen 5, 36, 1 for active mercs)? +/*0045*/ uint32 MercUnk02; // Unknown (normally see 1, but sometimes 2 or 0) +/*0049*/ uint32 StanceCount; // Iterations of MercenaryStance_Struct - Normally 2 to 4 seen +/*0053*/ int32 MercUnk03; // Unknown (always 0 at merchant) - Seen on active merc: 93 a4 03 77, b8 ed 2f 26, 88 d5 8b c3, and 93 a4 ad 77 +/*0057*/ uint8 MercUnk04; // Seen 1 +/*0058*/ char MercName[1]; // Null Terminated Mercenary Name (00 at merchants) +/*0000*/ MercenaryStance_Struct Stances[1]; // Count Varies, but hard set to 2 for now - From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc (1 to 9 as of April 2012) +/*0000*/ uint32 MercUnk05; // Seen 1 - Extra Merc Data field that differs from MercenaryListEntry_Struct +// MercUnk05 may be a field that is at the end of the packet only, even if multiple mercs are listed (haven't seen examples of multiple mercs owned at once) +}; + +// Should be named OP_MercenaryDataResponse, but the current opcode using that name should be renamed first +// Size varies if mercenary is hired or if browsing Mercenary Merchant +// This may also be the response for Client->Server 0x0327 (size 0) packet On Live as of April 2 2012 +struct MercenaryDataUpdate_Struct { +/*0000*/ int32 MercStatus; // Seen 0 with merc and -1 with no merc hired +/*0004*/ uint32 MercCount; // Seen 1 with 1 merc hired and 0 with no merc hired +/*0008*/ MercenaryData_Struct MercData[0]; // Data for individual mercenaries in the Merchant List +}; + +// Size 12 and sent on Zone-In if no mercenary is currently hired and when merc is dismissed +// (Same packet as MercAssign_Struct?) +struct NoMercenaryHired_Struct { +/*0000*/ int32 MercStatus; // Seen -1 with no merc hired +/*0004*/ uint32 MercCount; // Seen 0 with no merc hired +/*0008*/ uint32 MercID; // Seen 1 when no merc is hired - ID unique to each type of mercenary +/*0012*/ +}; + +// OP_MercenaryAssign (Same packet as NoMercenaryHired_Struct?) +// Not actually Merc related - This is actually a weapon equp packet +struct MercenaryAssign_Struct { +/*0000*/ uint32 MercEntityID; // Seen 0 (no merc spawned) or 615843841 and 22779137 +/*0004*/ uint32 MercUnk01; // +/*0008*/ uint32 MercUnk02; // +/*0012*/ +}; + +// OP_MercenaryTimer +// Sent on Zone-In, or after Dismissing, Suspending, or Unsuspending Mercs +struct MercenaryStatus_Struct { +/*0000*/ uint32 MercEntityID; // Seen 0 (no merc spawned) or 615843841 and 22779137 +/*0004*/ uint32 UpdateInterval; // Seen 900000 - Matches from 0x6537 packet (15 minutes in ms?) +/*0008*/ uint32 MercUnk01; // Seen 180000 - 3 minutes in milleseconds? Maybe next update interval? +/*0012*/ uint32 MercState; // Seen 5 (normal) or 1 (suspended) +/*0016*/ uint32 SuspendedTime; // Seen 0 (not suspended) or c9 c2 64 4f (suspended on Sat Mar 17 11:58:49 2012) - Unix Timestamp +/*0020*/ +}; + +// Sent from the client when using the Mercenary Window +struct MercenaryCommand_Struct { +/*0000*/ uint32 MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (dismiss merc), 5 (normal state), 36 (zone in with merc) +/*0004*/ int32 Option; // Seen -1 (zone in with no merc), 0 (setting to passive stance), 1 (normal or setting to balanced stance) +/*0008*/ +}; + +// Requesting to suspend or unsuspend merc +struct SuspendMercenary_Struct { +/*0000*/ uint8 SuspendMerc; // Seen 30 (48) for suspending or unsuspending +/*0001*/ +}; + +// Response to suspend merc with timestamp +struct SuspendMercenaryResponse_Struct { +/*0000*/ uint32 SuspendTime; // Unix Timestamp - Seen a9 11 78 4f +/*0004*/ +}; + +// Sent by client when requesting to view Mercenary info or Hire a Mercenary +struct MercenaryMerchantRequest_Struct { +/*0000*/ uint32 MercID; // Seen 399 and 400 for merc ID +/*0004*/ uint32 MercUnk01; // Seen 1 +/*0008*/ uint32 MercMerchantID; // Entity ID for Mercenary Merchant +/*0012*/ uint32 MercUnk02; // Seen 65302016 (00 6e e4 03) - (probably actually individual uint8 fields), but seen as DWORD in Seeds client. +/*0016*/ +}; + +// Sent by Server in response to requesting to view Mercenary info or Hire a Mercenary +struct MercenaryMerchantResponse_Struct { +/*0000*/ uint32 ResponseType; +/*0004*/ +}; + + }; //end namespace structs +}; //end namespace RoF2 + +#endif /*RoF2_STRUCTS_H_*/ diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf new file mode 100644 index 000000000..589c47468 --- /dev/null +++ b/utils/patches/patch_RoF2.conf @@ -0,0 +1,660 @@ +# ShowEQ Import Notes: +# ZERO THE FILE first +# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf +# Unknown Mapping: +# OP_Action2 -> OP_Damage +# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake +# Name Differences: +# OP_CancelInvite -> OP_GroupCancelInvite +# OP_GMFind -> OP_FindPersonRequest +# OP_CommonMessage -> OP_ChannelMessage + +OP_Unknown=0x0000 +OP_ExploreUnknown=0x0000 # used for unknown explorer + +# world packets +# Required to reach Char Select: +OP_SendLoginInfo=0x7a09 +OP_ApproveWorld=0x7499 +OP_LogServer=0x7ceb +OP_SendCharInfo=0x00d2 +OP_ExpansionInfo=0x590d +OP_GuildsList=0x0000 +OP_EnterWorld=0x578f +OP_PostEnterWorld=0x6259 +OP_World_Client_CRC1=0x12cc +OP_World_Client_CRC2=0x0f13 +OP_SendSpellChecksum=0x0000 +OP_SendSkillCapsChecksum=0x0000 + +# Character Select Related: +OP_SendMaxCharacters=0x5475 +OP_SendMembership=0x7acc +OP_SendMembershipDetails=0x057b +OP_CharacterCreateRequest=0x6773 +OP_CharacterCreate=0x6bbf +OP_DeleteCharacter=0x1808 +OP_RandomNameGenerator=0x5954 +OP_ApproveName=0x56a2 +OP_MOTD=0x0c22 +OP_SetChatServer=0x1bc5 +OP_SetChatServer2=0x7eec +OP_ZoneServerInfo=0x4c44 +OP_WorldComplete=0x4493 +OP_WorldUnknown001=0x2301 +OP_FloatListThing=0x46c6 + +# Reasons for Disconnect: +OP_ZoneUnavail=0x4cb4 +OP_WorldClientReady=0x23c1 +OP_CharacterStillInZone=0x0000 +OP_WorldChecksumFailure=0x0000 +OP_WorldLoginFailed=0x0000 +OP_WorldLogout=0x0000 +OP_WorldLevelTooHigh=0x0000 +OP_CharInacessable=0x0000 +OP_UserCompInfo=0x0000 +OP_SendExeChecksum=0x0000 +OP_SendBaseDataChecksum=0x0000 + +# Zone in opcodes +OP_AckPacket=0x471d +OP_ZoneEntry=0x5089 +OP_ReqNewZone=0x7887 +OP_NewZone=0x1795 +OP_ZoneSpawns=0x5237 +OP_PlayerProfile=0x6506 +OP_TimeOfDay=0x5070 +OP_LevelUpdate=0x1eec +OP_Stamina=0x2a79 +OP_RequestClientZoneChange=0x3fcf +OP_ZoneChange=0x2d18 +OP_LockoutTimerInfo=0x0000 +OP_ZoneServerReady=0x0000 +OP_ZoneInUnknown=0x0000 +OP_LogoutReply=0x0000 +OP_PreLogoutReply=0x0000 + +# Required to fully log in +OP_SpawnAppearance=0x0971 +OP_ChangeSize=0x4707 +OP_TributeUpdate=0x5961 +OP_TributeTimer=0x073d +OP_SendTributes=0x729b +OP_SendGuildTributes=0x1877 +OP_TributeInfo=0x4254 +OP_Weather=0x661e +OP_ReqClientSpawn=0x35fa +OP_SpawnDoor=0x7291 +OP_GroundSpawn=0x6fca +OP_SendZonepoints=0x69a4 +OP_BlockedBuffs=0x3033 +OP_RemoveBlockedBuffs=0x0de7 +OP_ClearBlockedBuffs=0x34cb +OP_WorldObjectsSent=0x5ae2 +OP_SendExpZonein=0x5f8e +OP_SendAATable=0x66b5 +OP_RespondAA=0x7a27 +OP_UpdateAA=0x66f0 +OP_SendAAStats=0x43c8 +OP_AAExpUpdate=0x7d14 +OP_ExpUpdate=0x20ed +OP_HPUpdate=0x2828 +OP_ManaChange=0x43af +OP_TGB=0x0876 +OP_SpecialMesg=0x0083 +OP_GuildMemberList=0x12a6 +OP_GuildMOTD=0x3e13 +OP_CharInventory=0x5ca6 +OP_WearChange=0x7994 +OP_ClientUpdate=0x7dfc +OP_ClientReady=0x345d +OP_SetServerFilter=0x444d + +# Guild Opcodes - Disabled until crashes are resolved in RoF +OP_GetGuildMOTD=0x36e0 +OP_GetGuildMOTDReply=0x4f1f +OP_GuildMemberUpdate=0x69b9 +OP_GuildInvite=0x7099 +OP_GuildRemove=0x1444 +OP_GuildPeace=0x67e3 +OP_SetGuildMOTD=0x0b0b +OP_GuildList=0x507a +OP_GuildWar=0x1ffb +OP_GuildLeader=0x7e09 +OP_GuildDelete=0x3708 +OP_GuildInviteAccept=0x7053 +OP_GuildDemote=0x2d4e +OP_GuildPromote=0x0000 +OP_GuildPublicNote=0x5053 +OP_GuildManageBanker=0x748f +OP_GuildBank=0x5134 +OP_SetGuildRank=0x0b9c +OP_GuildUpdateURLAndChannel=0x2958 +OP_GuildStatus=0x7326 +OP_GuildCreate=0x1dc8 +OP_GuildMemberLevelUpdate=0x0000 # Unused? +OP_ZoneGuildList=0x0000 # Unused? +OP_GetGuildsList=0x0000 # Unused? +OP_LFGuild=0x0000 +OP_GuildManageRemove=0x0000 +OP_GuildManageAdd=0x0000 +OP_GuildManageStatus=0x0000 + +# GM/Guide Opcodes +OP_GMServers=0x08c1 +OP_GMBecomeNPC=0x3ae1 +OP_GMZoneRequest=0x62ac +OP_GMZoneRequest2=0x7e1a +OP_GMGoto=0x7d8e +OP_GMSearchCorpse=0x357c +OP_GMHideMe=0x79c5 +OP_GMDelCorpse=0x607e +OP_GMApproval=0x6db5 +OP_GMToggle=0x2097 +OP_GMSummon=0x486f +OP_GMEmoteZone=0x1cfd +OP_GMEmoteWorld=0x458e +OP_GMFind=0x4a8f +OP_GMKick=0x26a7 +OP_GMKill=0x51d3 +OP_GMNameChange=0x035f +OP_GMLastName=0x46ce + +# Misc Opcodes +OP_InspectRequest=0x57bc +OP_InspectAnswer=0x71ac +OP_InspectMessageUpdate=0x4d25 +OP_BeginCast=0x318f +OP_ColoredText=0x0000 +OP_ConsentResponse=0x384a +OP_MemorizeSpell=0x217c +OP_SwapSpell=0x0efa +OP_CastSpell=0x1287 +OP_Consider=0x742b +OP_FormattedMessage=0x1024 +OP_SimpleMessage=0x213f +OP_Buff=0x659c +OP_Illusion=0x312a +OP_MoneyOnCorpse=0x5f44 +OP_RandomReply=0x106b +OP_DenyResponse=0x2382 +OP_SkillUpdate=0x004c +OP_GMTrainSkillConfirm=0x66dd +OP_RandomReq=0x7b10 +OP_Death=0x6517 +OP_GMTraining=0x1966 +OP_GMEndTraining=0x4d6b +OP_GMTrainSkill=0x2a85 +OP_Animation=0x7177 +OP_Begging=0x6703 +OP_Consent=0x1fd1 +OP_ConsentDeny=0x7a45 +OP_AutoFire=0x241e +OP_PetCommands=0x0159 +OP_DeleteSpell=0x52e5 +OP_Surname=0x0423 +OP_ClearSurname=0x7d23 +OP_FaceChange=0x5578 +OP_SenseHeading=0x260a +OP_Action=0x744c +OP_ConsiderCorpse=0x5204 +OP_HideCorpse=0x49e1 +OP_CorpseDrag=0x0904 +OP_CorpseDrop=0x7037 +OP_Bug=0x73f4 +OP_Feedback=0x5602 +OP_Report=0x1414 +OP_Damage=0x6f15 +OP_ChannelMessage=0x2b2d +OP_Assist=0x4478 +OP_AssistGroup=0x27f8 +OP_MoveCoin=0x0bcf +OP_ZonePlayerToBind=0x0ecb +OP_KeyRing=0x6857 +OP_WhoAllRequest=0x65ab +OP_WhoAllResponse=0x7c88 +OP_FriendsWho=0x3956 +OP_ConfirmDelete=0x43a3 +OP_Logout=0x4ac6 +OP_Rewind=0x1745 +OP_TargetCommand=0x58e2 +OP_Hide=0x67fe +OP_Jump=0x2060 +OP_Camp=0x28ec +OP_Emote=0x373b +OP_SetRunMode=0x009f +OP_BankerChange=0x383c +OP_TargetMouse=0x075d +OP_MobHealth=0x37b1 +OP_InitialMobHealth=0x0000 # Unused? +OP_TargetHoTT=0x0272 +OP_XTargetResponse=0x672f +OP_XTargetRequest=0x45be +OP_XTargetAutoAddHaters=0x792c +OP_TargetBuffs=0x4f4b +OP_BuffCreate=0x3377 +OP_BuffRemoveRequest=0x64f2 +OP_DeleteSpawn=0x7280 +OP_AutoAttack=0x109d +OP_AutoAttack2=0x3526 +OP_Consume=0x4b70 +OP_MoveItem=0x32ee +OP_DeleteItem=0x18ad +OP_DeleteCharge=0x01b8 +OP_ItemPacket=0x368e +OP_ItemLinkResponse=0x633c +OP_ItemLinkClick=0x4cef +OP_ItemPreview=0x6b5c +OP_NewSpawn=0x6097 +OP_Track=0x17e5 +OP_TrackTarget=0x0029 +OP_TrackUnknown=0x4577 +OP_ClickDoor=0x3a8f +OP_MoveDoor=0x08e8 +OP_RemoveAllDoors=0x700c +OP_EnvDamage=0x51fd +OP_BoardBoat=0x4211 +OP_Forage=0x5306 +OP_LeaveBoat=0x7617 +OP_ControlBoat=0x0ae7 +OP_SafeFallSuccess=0x2219 +OP_RezzComplete=0x760d +OP_RezzRequest=0x3c21 +OP_RezzAnswer=0x701c +OP_Shielding=0x48c1 +OP_RequestDuel=0x3af1 +OP_MobRename=0x2c57 +OP_AugmentItem=0x661b +OP_WeaponEquip1=0x34a7 +OP_WeaponEquip2=0x559a +OP_WeaponUnequip2=0x2d25 +OP_ApplyPoison=0x31e6 +OP_Save=0x4a39 +OP_TestBuff=0x7cb8 +OP_CustomTitles=0x100e +OP_Split=0x3a54 +OP_YellForHelp=0x4e56 +OP_LoadSpellSet=0x261d +OP_Bandolier=0x7677 +OP_PotionBelt=0x1a3e +OP_DuelResponse=0x6a46 +OP_DuelResponse2=0x68d3 +OP_SaveOnZoneReq=0x600d +OP_ReadBook=0x72df +OP_Dye=0x23b9 +OP_InterruptCast=0x048c +OP_AAAction=0x424e +OP_LeadershipExpToggle=0x6c55 +OP_LeadershipExpUpdate=0x2797 +OP_PurchaseLeadershipAA=0x0026 +OP_UpdateLeadershipAA=0x026 +OP_MarkNPC=0x5a58 +OP_MarkRaidNPC=0x74bd #unimplemented +OP_ClearNPCMarks=0x2003 +OP_ClearRaidNPCMarks=0x20d3 #unimplemented +OP_DelegateAbility=0x76b8 +OP_SetGroupTarget=0x2814 +OP_Charm=0x5d92 +OP_Stun=0x36a4 +OP_SendFindableNPCs=0x3897 +OP_FindPersonRequest=0x5cea +OP_FindPersonReply=0x7e58 +OP_Sound=0x1a30 +OP_PetBuffWindow=0x5882 +OP_LevelAppearance=0x3bc9 +OP_Translocate=0x6580 +OP_Sacrifice=0x1821 +OP_PopupResponse=0x214a +OP_OnLevelMessage=0x4fd0 +OP_AugmentInfo=0x0afb +OP_Petition=0x5f03 +OP_SomeItemPacketMaybe=0x747c +OP_PVPStats=0x6f4b +OP_PVPLeaderBoardRequest=0x3707 +OP_PVPLeaderBoardReply=0x25b7 +OP_PVPLeaderBoardDetailsRequest=0x15a9 +OP_PVPLeaderBoardDetailsReply=0x04aa +OP_RestState=0x00f +OP_RespawnWindow=0x28bc +OP_LDoNButton=0x5327 +OP_SetStartCity=0x6326 +OP_VoiceMacroIn=0x17fd +OP_VoiceMacroOut=0x409a +OP_ItemViewUnknown=0x2289 +OP_VetRewardsAvaliable=0x590e +OP_VetClaimRequest=0x1126 +OP_VetClaimReply=0x16d4 +OP_DisciplineUpdate=0x759e +OP_DisciplineTimer=0x6989 +OP_BecomeCorpse=0x0000 # Unused? +OP_Action2=0x0000 # Unused? +OP_MobUpdate=0x2c84 +OP_NPCMoveUpdate=0x189c +OP_CameraEffect=0x127f +OP_SpellEffect=0x5936 +OP_RemoveNimbusEffect=0xc693 +OP_AltCurrency=0x7121 +OP_AltCurrencyMerchantRequest=0x6b6d +OP_AltCurrencyMerchantReply=0x74ec +OP_AltCurrencyPurchase=0x61cb +OP_AltCurrencySell=0x0165 +OP_AltCurrencySellSelection=0x5409 +OP_AltCurrencyReclaim=0x532a +OP_CrystalCountUpdate=0x467f +OP_CrystalCreate=0x7aee +OP_CrystalReclaim=0x2439 +OP_Untargetable=0x053c +OP_IncreaseStats=0x70a3 +OP_Weblink=0x18d3 +OP_OpenContainer=0x0000 +OP_Marquee=0x0000 +OP_ItemRecastDelay=0x08a6 +#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U + +OP_DzQuit=0xb2e3 +OP_DzListTimers=0x7b68 +OP_DzAddPlayer=0x4701 +OP_DzRemovePlayer=0x1abc +OP_DzSwapPlayer=0x405b +OP_DzMakeLeader=0x543d +OP_DzPlayerList=0x14c6 +OP_DzJoinExpeditionConfirm=0x7f4b +OP_DzJoinExpeditionReply=0x1950 +OP_DzExpeditionInfo=0x9119 +OP_DzExpeditionList=0x205f +OP_DzMemberStatus=0x32f0 +OP_DzLeaderStatus=0x3de9 +OP_DzExpeditionEndsWarning=0x5189 +OP_DzMemberList=0x5ae4 +OP_DzCompass=0x3e0e +OP_DzChooseZone=0x0000 + +# New Opcodes +OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? +OP_ManaUpdate=0x3791 +OP_EnduranceUpdate=0x5f42 +OP_MobManaUpdate=0x2404 +OP_MobEnduranceUpdate=0x1c81 + +# Mercenary Opcodes +OP_MercenaryDataUpdateRequest=0x7b89 +OP_MercenaryDataUpdate=0x61a4 +OP_MercenaryDataRequest=0x11c1 +OP_MercenaryDataResponse=0x72ce +OP_MercenaryHire=0x7169 +OP_MercenaryDismiss=0x6e83 +OP_MercenaryTimerRequest=0x31e4 +OP_MercenaryTimer=0x0763 +OP_MercenaryUnknown1=0x5d26 +OP_MercenaryCommand=0x27f2 +OP_MercenarySuspendRequest=0x4407 +OP_MercenarySuspendResponse=0x6f03 +OP_MercenaryUnsuspendResponse=0x27a0 + +# Looting +OP_LootRequest=0x0adf +OP_EndLootRequest=0x30f7 +OP_LootItem=0x4dc9 +OP_LootComplete=0x55c4 + +# bazaar trader stuff: +OP_BazaarSearch=0x39d6 +OP_TraderDelItem=0x0000 +OP_BecomeTrader=0x61b3 +OP_TraderShop=0x31df +OP_Trader=0x4ef5 +OP_TraderBuy=0x0000 +OP_Barter=0x243a +OP_ShopItem=0x0000 +OP_BazaarInspect=0x0000 +OP_Bazaar=0x0000 +OP_TraderItemUpdate=0x0000 + +# pc/npc trading +OP_TradeRequest=0x77b5 +OP_TradeAcceptClick=0x69e2 +OP_TradeRequestAck=0x14bf +OP_TradeCoins=0x4206 +OP_FinishTrade=0x3993 +OP_CancelTrade=0x354c +OP_TradeMoneyUpdate=0x68c2 +OP_MoneyUpdate=0x640c +OP_TradeBusy=0x5505 + +# Sent after canceling trade or after closing tradeskill object +OP_FinishWindow=0x7349 +OP_FinishWindow2=0x40ef + +# Sent on Live for what seems to be item existance verification +# Ex. Before Right Click Effect happens from items +OP_ItemVerifyRequest=0x097b +OP_ItemVerifyReply=0x2115 + +# merchant stuff +OP_ShopPlayerSell=0x1901 +OP_ShopRequest=0x4fed +OP_ShopEnd=0x30a8 +OP_ShopEndConfirm=0x3196 +OP_ShopPlayerBuy=0x04c +OP_ShopDelItem=0x724f + +# tradeskill stuff: +OP_ClickObject=0x4aa1 +OP_ClickObjectAction=0x0c1e +OP_ClearObject=0x7a11 +OP_RecipeDetails=0x40d7 +OP_RecipesFavorite=0x5c74 +OP_RecipesSearch=0x1db6 +OP_RecipeReply=0x6e02 +OP_RecipeAutoCombine=0x6261 +OP_TradeSkillCombine=0x579a + +# Tribute Packets: +OP_OpenGuildTributeMaster=0x378d +OP_OpenTributeMaster=0x7666 +OP_SelectTribute=0x79fc +OP_TributeItem=0x4f3e +OP_TributeMoney=0x58fb +OP_TributeToggle=0x241d +OP_TributePointUpdate=0x5300 +OP_TributeNPC=0x0000 +OP_GuildTributeInfo=0x0000 +OP_OpenTributeReply=0x0000 +OP_GuildTributeStatus=0x0000 + +# Adventure packets: +OP_LeaveAdventure=0x5d18 +OP_AdventureFinish=0x400f +OP_AdventureInfoRequest=0x3cb0 +OP_AdventureInfo=0x4c54 +OP_AdventureRequest=0x2c6c +OP_AdventureDetails=0x5648 +OP_AdventureData=0x7171 +OP_AdventureUpdate=0x1b01 +OP_AdventureMerchantRequest=0x6922 +OP_AdventureMerchantResponse=0x3e47 +OP_AdventureMerchantPurchase=0x5b72 +OP_AdventureMerchantSell=0x2f9b +OP_AdventurePointsUpdate=0x65c3 +OP_AdventureStatsRequest=0x5a62 +OP_AdventureStatsReply=0x2370 +OP_AdventureLeaderboardRequest=0x7093 +OP_AdventureLeaderboardReply=0x7f79 + +# Group Opcodes +OP_GroupDisband=0x4c10 +OP_GroupInvite=0x1649 +OP_GroupFollow=0x05ce +OP_GroupUpdate=0x3abb +OP_GroupUpdateB=0x6194 +OP_GroupCancelInvite=0x0000 +OP_GroupAcknowledge=0x7323 +OP_GroupDelete=0x0f6c +OP_CancelInvite=0x32c2 +OP_GroupFollow2=0x2a50 +OP_GroupInvite2=0x6c65 +OP_GroupDisbandYou=0x1ae5 +OP_GroupDisbandOther=0x74da +OP_GroupLeaderChange=0x21b4 +OP_GroupRoles=0x70e2 +OP_GroupMakeLeader=0x4229 +OP_DoGroupLeadershipAbility=0x1fb5 +OP_GroupLeadershipAAUpdate=0x02cf +OP_GroupMentor=0x5892 +OP_InspectBuffs=0x486c + +# LFG/LFP Opcodes +OP_LFGCommand=0x6060 +OP_LFGGetMatchesRequest=0x0340 +OP_LFGGetMatchesResponse=0x5048 +OP_LFPGetMatchesRequest=0x4d7d +OP_LFPGetMatchesResponse=0x22c6 +OP_LFPCommand=0x49a9 +OP_LFGAppearance=0x0000 +OP_LFGResponse=0x0000 + +# Raid Opcodes +OP_RaidInvite=0x55ac +OP_RaidUpdate=0x3973 +OP_RaidJoin=0x0000 + +# Button-push commands +OP_Taunt=0x2703 +OP_CombatAbility=0x3eba +OP_SenseTraps=0x02af +OP_PickPocket=0x39e8 +OP_DisarmTraps=0x78bf +OP_Disarm=0x5ec8 +OP_Sneak=0x5d55 +OP_Fishing=0x1e2a +OP_InstillDoubt=0x640e +OP_FeignDeath=0x52fa +OP_Mend=0x0ecf +OP_Bind_Wound=0x0386 +OP_LDoNOpen=0x3d5c + +# Task packets +OP_TaskDescription=0x083 +OP_TaskActivity=0x3714 +OP_CompletedTasks=0x4eba +OP_TaskActivityComplete=0x5e19 +OP_AcceptNewTask=0x0a23 +OP_CancelTask=0x08d3 +OP_TaskMemberList=0x5727 +OP_OpenNewTasksWindow=0x48a2 +OP_AvaliableTask=0x36e8 +OP_TaskHistoryRequest=0x5f1c +OP_TaskHistoryReply=0x3d05 +OP_DeclineAllTasks=0x0000 + +# Title opcodes +OP_NewTitlesAvailable=0x0d32 +OP_RequestTitles=0x6344 +OP_SendTitleList=0x2d08 +OP_SetTitle=0x6527 +OP_SetTitleReply=0x4c21 + +# mail opcodes +OP_Command=0x0000 +OP_MailboxHeader=0x0000 +OP_MailHeader=0x0000 +OP_MailBody=0x0000 +OP_NewMail=0x0000 +OP_SentConfirm=0x0000 + +########### Below this point should not be needed ########### + +# This section are all unknown in Titanium +OP_ForceFindPerson=0x0000 +OP_LocInfo=0x0000 +OP_ReloadUI=0x0000 +OP_ItemName=0x0000 +OP_ItemLinkText=0x0000 +OP_MultiLineMsg=0x0000 +OP_MendHPUpdate=0x0000 +OP_TargetReject=0x0000 +OP_SafePoint=0x0000 +OP_ApproveZone=0x0000 +OP_ZoneComplete=0x0000 +OP_ClientError=0x0000 +OP_DumpName=0x0000 +OP_Heartbeat=0x0000 +OP_CrashDump=0x0000 +OP_LoginComplete=0x0000 + +# discovered opcodes not yet used: +OP_PickLockSuccess=0x0000 +OP_PlayMP3=0x0000 +OP_ReclaimCrystals=0x0000 +OP_DynamicWall=0x0000 +OP_OpenDiscordMerchant=0x0000 +OP_DiscordMerchantInventory=0x0000 +OP_GiveMoney=0x0000 +OP_RequestKnowledgeBase=0x0000 +OP_KnowledgeBase=0x0000 +OP_SlashAdventure=0x0000 # /adventure +OP_BecomePVPPrompt=0x0000 +OP_MoveLogRequest=0x0000 # gone I think +OP_MoveLogDisregard=0x0000 # gone I think + +# named unknowns, to make looking for real unknown easier +OP_AnnoyingZoneUnknown=0x0000 +OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members +OP_QueryResponseThing=0x0000 + + +# realityincarnate: these are just here to stop annoying several thousand byte packet dumps +#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum +#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum + +# Petition Opcodes +OP_PetitionSearch=0x0000 search term for petition +OP_PetitionSearchResults=0x0000 (list of?) matches from search +OP_PetitionSearchText=0x0000 text results of search + +OP_PetitionUpdate=0x0000 +OP_PetitionCheckout=0x0000 +OP_PetitionCheckIn=0x0000 +OP_PetitionQue=0x0000 +OP_PetitionUnCheckout=0x0000 +OP_PetitionDelete=0x0000 +OP_DeletePetition=0x0000 +OP_PetitionResolve=0x0000 +OP_PDeletePetition=0x0000 +OP_PetitionBug=0x0000 +OP_PetitionRefresh=0x0000 +OP_PetitionCheckout2=0x0000 +OP_PetitionViewPetition=0x0000 + +# Login opcodes +OP_SessionReady=0x0000 +OP_Login=0x0000 +OP_ServerListRequest=0x0000 +OP_PlayEverquestRequest=0x0000 +OP_PlayEverquestResponse=0x0000 +OP_ChatMessage=0x0000 +OP_LoginAccepted=0x0000 +OP_ServerListResponse=0x0000 +OP_Poll=0x0000 +OP_EnterChat=0x0000 +OP_PollResponse=0x0000 + +# raw opcodes +OP_RAWSessionRequest=0x0000 +OP_RAWSessionResponse=0x0000 +OP_RAWCombined=0x0000 +OP_RAWSessionDisconnect=0x0000 +OP_RAWKeepAlive=0x0000 +OP_RAWSessionStatRequest=0x0000 +OP_RAWSessionStatResponse=0x0000 +OP_RAWPacket=0x0000 +OP_RAWFragment=0x0000 +OP_RAWOutOfOrderAck=0x0000 +OP_RAWAck=0x0000 +OP_RAWAppCombined=0x0000 +OP_RAWOutOfSession=0x0000 + +# we need to document the differences between these packets to make identifying them easier +OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs +OP_InitialHPUpdate=0x0000 \ No newline at end of file diff --git a/utils/scripts/opcode_scripts/conf_to_oplist.pl b/utils/scripts/opcode_scripts/conf_to_oplist.pl new file mode 100644 index 000000000..f79de1093 --- /dev/null +++ b/utils/scripts/opcode_scripts/conf_to_oplist.pl @@ -0,0 +1,66 @@ +#!/usr/bin/perl + +# File Name: conf_to_oplist.pl +# Converts a Patch File into the Opcode List with Opcode Names for the Spreadsheet. + +# Directions to use this script: +# 1. Paste the contents of the current patch file in the patch_OLD.conf file. +# 2. Run this script using "perl conf_to_oplist.pl" +# 3. This updates the opcodelist.txt with the values from the Patch File. + + +$stopmessage = "Failed to open file"; +open OpcodeFile, "<", "opcodelist.txt" or die $stopmessage; +open PatchFile, "<", "patch_OLD.conf" or die $stopmessage; + +my @OpcodeList = ; +my @PatchFile = ; +my %PatchHash = (); + +foreach $line (@PatchFile) +{ + @equalssplit = split(/=/, $line); + $ArraySize = @equalssplit; + if ($ArraySize > 1) + { + @OpcodeArray = split(//, $equalssplit[1]); + $CurOpcode = $OpcodeArray[0].$OpcodeArray[1].$OpcodeArray[2].$OpcodeArray[3].$OpcodeArray[4].$OpcodeArray[5]; + $CurOpcode = lc($CurOpcode); + # Opcode Name => Opcode + $PatchHash{ $CurOpcode } = $equalssplit[0]; + } +} + +close(OpcodeFile); +close(PatchFile); + +# Clear out file contents +open OpcodeResultFile, ">", "opcodelist.txt" or die $stopmessage; +print OpcodeResultFile ""; +close(OpcodeResultFile); + +open OpcodeResultFile, ">>", "opcodelist.txt" or die $stopmessage; + +while( my ($k, $v) = each %$PatchFile ) +{ + #print OpcodeResultFile "key: $k, value: $v.\n"; +} + + +$TabSpace = " "; # Tab +foreach $line (@OpcodeList) +{ + @LineSplit = split(//, $line); + $CurOpcode = $LineSplit[0].$LineSplit[1].$LineSplit[2].$LineSplit[3].$LineSplit[4].$LineSplit[5]; + $CurOpcode = lc($CurOpcode); + $OpcodeName = ""; # Tab + if ($PatchHash{$CurOpcode}) + { + $NameKey = $PatchHash{$CurOpcode}; + $OpcodeName = $NameKey; + } + $CurLine = $CurOpcode.$TabSpace.$OpcodeName."\n"; + print OpcodeResultFile $CurLine; +} + +close(OpcodeResultFile); diff --git a/utils/scripts/opcode_scripts/opcodelist.txt b/utils/scripts/opcode_scripts/opcodelist.txt new file mode 100644 index 000000000..6ef0916f9 --- /dev/null +++ b/utils/scripts/opcode_scripts/opcodelist.txt @@ -0,0 +1,1671 @@ +RoF2 Built May 10 2013 23:30:08 +0x04d6 +0x5efd +0x0cc1 +0x2c3d +0x7b25 +0x4f44 +0x7592 +0x2b1c +0x1fd1 OP_Consent +0x15a5 +0x3c7e +0x6262 +0x471d OP_AckPacket +0x64a8 +0x7c06 +0x2c5e +0x24ab +0x19b5 +0x72fa +0x0770 +0x4cef OP_ItemLinkClick +0x08c1 OP_GMServers +0x318f OP_BeginCast +0x5ec8 OP_Disarm +0x6ae3 +0x2b2d OP_ChannelMessage +0x1cb1 +0x5070 OP_TimeOfDay +0x7dfc OP_ClientUpdate +0x35ea +0x3b9a +0x148d +0x345d OP_ClientReady +0x5ae2 OP_WorldObjectsSent +0x03a4 +0x69e2 OP_TradeAcceptClick +0x354c OP_CancelTrade +0x3993 OP_FinishTrade +0x165b +0x2b95 +0x6fe2 +0x42fd +0x25d7 +0x7436 +0x4206 OP_TradeCoins +0x14bf OP_TradeRequestAck +0x7349 OP_FinishWindow +0x71fd +0x0b9c OP_SetGuildRank +0x0f7d +0x1bd3 +0x5053 OP_GuildPublicNote +0x01f9 +0x2c84 OP_MobUpdate +0x279d +0x5a94 +0x579a OP_TradeSkillCombine +0x56b1 +0x0f25 +0x3c14 +0x0c16 +0x4a8f OP_GMFind +0x2ad6 +0x0160 +0x7852 +0x41bf +0x40dd +0x3ec6 +0x6af4 +0x6d9d +0x2538 +0x0017 +0x017 +0x691a +0x0520 +0x200f +0x65ab OP_WhoAllRequest +0x674b +0x6a02 +0x0e48 +0x12a6 OP_GuildMemberList +0x0eae +0x2921 +0x7056 +0x507a OP_GuildList +0x6279 +0x5a26 +0x5b51 +0x0bad +0x59ad +0x2264 +0x004c OP_SkillUpdate +0x04c OP_ShopPlayerBuy +0x0ddd +0x4101 +0x5f03 OP_Petition +0x3de3 +0x1901 OP_ShopPlayerSell +0x791b +0x3a5d +0x7013 +0x47f1 +0x6506 OP_PlayerProfile +0x30a8 OP_ShopEnd +0x724f OP_ShopDelItem +0x5829 +0x1ce1 +0x47d6 +0x07cf +0x40c9 +0x38d4 +0x7eb9 +0x1e2c +0x3ae1 OP_GMBecomeNPC +0x4849 +0x376b +0x1e2a OP_Fishing +0x1eec OP_LevelUpdate +0x4958 +0x20ed OP_ExpUpdate +0x3ed4 +0x701c OP_RezzAnswer +0x640e OP_InstillDoubt +0x0ecf OP_Mend +0x09d3 +0x70a3 OP_IncreaseStats +0x178e +0x27e8 +0x61f8 +0x4322 +0x3f84 +0x40ef OP_FinishWindow2 +0x166c +0x106b OP_RandomReply +0x5bfd +0x11c8 +0x1753 +0x009f OP_SetRunMode +0x09f +0x4ae6 +0x3dbf +0x0399 +0x5c89 +0x012c +0x381c +0x4b36 +0x36d5 +0x5f21 +0x56f7 +0x46b1 +0x357c OP_GMSearchCorpse +0x2422 +0x084e +0x67e3 OP_GuildPeace +0x0f83 +0x4577 OP_TrackUnknown +0x5d55 OP_Sneak +0x67fe OP_Hide +0x12e5 +0x2c7a +0x600d OP_SaveOnZoneReq +0x16ce +0x46ce OP_GMLastName +0x1ffb OP_GuildWar +0x6718 +0x2f3e +0x7e09 OP_GuildLeader +0x5ce4 +0x5bcc +0x551d +0x6dbc +0x2219 OP_SafeFallSuccess +0x2686 +0x2022 +0x1c53 +0x33a2 +0x3541 +0x582e +0x3cba +0x190c +0x5067 +0x46d2 +0x49cf +0x1b0c + +0x31e6 OP_ApplyPoison +0x4211 OP_BoardBoat +0x7617 OP_LeaveBoat +0x4466 +0x1287 OP_CastSpell +0x5467 OP_ManaChange +0x43af OP_ManaChange +0x6a0d +0x217c OP_MemorizeSpell +0x260a OP_SenseHeading +0x5886 +0x7e8c +0x1a37 +0x0b6f +0x62ca +0x34a4 +0x6c83 +0x5d10 +0x21a0 +0x3537 +0x2acd +0x7c6d +0x6618 + + + +0x6c65 OP_GroupInvite2 +0x32c2 OP_CancelInvite +0x2a50 OP_GroupFollow2 +0x2060 OP_Jump +0x31f4 +0x4420 +0x1256 +0x4d38 +0x50f5 +0x79c5 OP_GMHideMe +0x2fab +0x57a5 +0x32a4 +0x590d OP_ExpansionInfo +0x6f15 OP_Damage +0x42ea +0x3091 +0x6b5a +0x3234 +0x30b4 +0x51fd OP_EnvDamage +0x15f4 +0x1808 OP_DeleteCharacter +0x1795 OP_NewZone +0x7887 OP_ReqNewZone +0x2414 +0x2eb3 +0x3db3 +0x4008 + +0x373b OP_Emote +0x7280 OP_DeleteSpawn +0x4bc2 +0x15bb +0x4fed OP_ShopRequest +0x0c2f +0x4aa1 OP_ClickObject +0x6fca OP_GroundSpawn +0x1045 +0x2a9e +0x2523 +0x6213 +0x4a39 OP_Save +0x0797 +0x35fa OP_ReqClientSpawn +0x5f8e OP_SendExpZonein +0x4c10 OP_GroupDisband +0x747c OP_SomeItemPacketMaybe +0x744c OP_Action +0x00d2 OP_SendCharInfo +0x0d2 +0x11d4 +0x6bbf OP_CharacterCreate +0x6517 OP_Death +0x19f6 +0x360f +0x1951 +0x51d3 OP_GMKill +0x26a7 OP_GMKick +0x7d8e OP_GMGoto +0x475e +0x5253 +0x3c79 +0x5065 +0x0337 +0x2ded +0x777b +0x4434 +0x0e90 +0x57da +0x150e +0x1ba8 +0x70eb +0x0adf OP_LootRequest +0x30f7 OP_EndLootRequest +0x5f44 OP_MoneyOnCorpse +0x3d54 +0x482d +0x58b2 +0x7361 +0x604f +0x3d87 +0x6909 +0x4f73 +0x0a0f +0x56a2 OP_ApproveName +0x69e6 +0x3a8f OP_ClickDoor +0x08e8 OP_MoveDoor +0x7dd1 +0x5c66 +0x312a OP_Illusion +0x2807 +0x4fe2 +0x2f2e +0x5824 +0x6661 +0x4742 +0x4d02 +0x2105 +0x19e9 +0x2268 +0x7994 OP_WearChange +0x0386 OP_Bind_Wound +0x5306 OP_Forage +0x0971 OP_SpawnAppearance +0x7099 OP_GuildInvite +0x7053 OP_GuildInviteAccept +0x1444 OP_GuildRemove +0x3708 OP_GuildDelete +0x7b22 +0x610f +0x324a +0x2889 +0x6f2a +0x2998 +0x700c OP_RemoveAllDoors +0x1966 OP_GMTraining +0x4d6b OP_GMEndTraining +0x6e8d +0x2b41 +0x4dc9 OP_LootItem +0x7177 OP_Animation +0x650e +0x2d18 OP_ZoneChange +0x707b +0x0803 +0x3fc3 +0x7326 OP_GuildStatus +0x0804 +0x3f86 +0x6d20 +0x04a3 +0x4714 +0x6703 OP_Begging +0x0ae7 OP_ControlBoat +0x27d7 +0x3c21 OP_RezzRequest +0x6f22 +0x32ee OP_MoveItem +0x0bcf OP_MoveCoin +0x2452 +0x0186 +0x0522 +0x3a54 OP_Split +0x659c OP_Buff +0x225b + +0x12cc OP_World_Client_CRC1 +0x661e OP_Weather +0x742b OP_Consider +0x102e +0x0f13 OP_World_Client_CRC2 +0x6944 +0x2703 OP_Taunt +0x5602 OP_Feedback +0x68c2 OP_TradeMoneyUpdate +0x07f7 +0x3fe7 +0x43a0 +0x314c +0x4b70 OP_Consume +0x2a79 OP_Stamina +0x402e +0x750e +0x0927 +0x36a4 OP_Stun +0x2b03 +0x68d3 OP_DuelResponse2 +0x6a46 OP_DuelResponse +0x5237 OP_ZoneSpawns +0x3eba OP_CombatAbility +0x109d OP_AutoAttack +0x075d OP_TargetMouse +0x05d2 +0x2a85 OP_GMTrainSkill +0x43a3 OP_ConfirmDelete +0x6c57 +0x3906 +0x55c4 OP_LootComplete +0x3196 OP_ShopEndConfirm +0x18ad OP_DeleteItem +0x01b8 OP_DeleteCharge +0x01d7 +0x4d28 +0x4fd9 +0x02c6 +0x3e30 +0x3fcf OP_RequestClientZoneChange +0x4e0e +0x1dee +0x62ac OP_GMZoneRequest +0x4ac6 OP_Logout +0x3526 OP_AutoAttack2 +0x7ceb OP_LogServer +0x0423 OP_Surname +0x3956 OP_FriendsWho +0x45dc +0x35e0 +0x173e +0x4853 +0x393b +0x0efa OP_SwapSpell +0x3588 +0x26e9 +0x4e56 OP_YellForHelp +0x2551 +0x38c8 +0x7499 OP_ApproveWorld +0x603a +0x7b10 OP_RandomReq +0x208f +0x607e OP_GMDelCorpse +0x1821 OP_Sacrifice +0x30d6 +0x760d OP_RezzComplete +0x4dd5 +0x0fe8 +0x6e5c +0x2228 +0x21bc +0x78c3 +0x3e57 +0x69d0 +0x1e3a +0x1a30 OP_Sound +0x61a0 +0x048c OP_InterruptCast +0x6e80 +0x3d29 +0x5d92 OP_Charm +0x0159 OP_PetCommands +0x486e +0x579e +0x49b3 +0x6db5 OP_GMApproval +0x4759 +0x0c22 OP_MOTD +0x2097 OP_GMToggle +0x72f7 +0x640c OP_MoneyUpdate +0x51e5 +0x1802 +0x5de1 +0x2e0c +0x58e2 OP_TargetCommand +0x444d OP_SetServerFilter +0x4478 OP_Assist +0x2a21 +0x7e59 +0x0b0b OP_SetGuildMOTD +0x3e13 OP_GuildMOTD +0x7a11 OP_ClearObject +0x6580 OP_Translocate +0x28ec OP_Camp +0x61b3 OP_BecomeTrader +0x31af +0x0876 OP_TGB +0x4ee1 +0x7e92 +0x7d14 OP_AAExpUpdate + +0x5578 OP_FaceChange +0x1a80 +0x42ff +0x7c2d +0x2c57 OP_MobRename +0x6dab +0x4568 +0x7776 +0x5029 +0x696c +0x23b9 OP_Dye +0x5204 OP_ConsiderCorpse +0x213f OP_SimpleMessage +0x1024 OP_FormattedMessage +0x2ce5 +0x5cc9 +0x3358 +0x52e5 OP_DeleteSpell +0x48c1 OP_Shielding +0x6f14 +0x1414 OP_Report +0x0e1c +0x1219 +0x6857 OP_KeyRing +0x55ac OP_RaidInvite +0x3973 OP_RaidUpdate +0x56fe +0x7f2d +0x31df OP_TraderShop +0x4ef5 OP_Trader +0x735d +0x019b +0x5930 +0x2d73 +0x39d6 OP_BazaarSearch +0x6a96 +0x424e OP_AAAction +0x7a27 OP_RespondAA +0x5eca +0x70c6 +0x0dd4 +0x4598 +0x19b6 +0x728a +0x5232 +0x77bd +0x70c0 +0x633c OP_ItemLinkResponse +0x63eb +0x4765 +0x6290 +0x1db6 OP_RecipesSearch +0x6e02 OP_RecipeReply +0x40d7 OP_RecipeDetails +0x6261 OP_RecipeAutoCombine +0x4015 OP_SetGroupLeadershipAbilities +0x6eae OP_SetRaidLeadershipAbilities +0x1fb5 OP_DoGroupLeadershipAbility +0x5a58 OP_MarkNPC +0x74bd OP_MarkRaidNPC +0x6c55 OP_LeadershipExpToggle +0x0026 OP_PurchaseLeadershipAA +0x026 OP_UpdateLeadershipAA +0x2814 OP_SetGroupTarget +0x4c9d OP_SetRaidTarget +0x76b8 OP_DelegateAbility +0x2b33 OP_DelegateRaidAbility +0x4786 OP_SenseNPCData +0x0eb4 OP_DelegateFailed +0x486c OP_InspectBuffs +0x0272 OP_TargetHoTT +0x2003 OP_ClearNPCMarks +0x20d3 OP_ClearRaidNPCMarks +0x1c89 +0x4ee2 +0x2797 OP_LeadershipExpUpdate +0x6da5 OP_ClearLeadershipAbilities +0x0ca6 +0x7717 +0x509d +0x6bee +0x0b04 +0x6097 OP_NewSpawn +0x758c +0x2b10 +0x4d09 +0x0083 OP_SpecialMesg +0x083 OP_TaskDescription +0x3714 OP_TaskActivity +0x08d3 OP_CancelTask +0x39f0 +0x5f7a OP_ItemScriptAdjustment +0x006a +0x06a +0x7465 +0x31c0 +0x14ba +0x25e0 +0x62a0 +0x407a +0x7c88 OP_WhoAllResponse +0x51b8 +0x578c +0x1197 +0x2dd3 +0x333a +0x2925 +0x37b1 OP_MobHealth +0x7314 +0x2404 OP_MobManaUpdate +0x5f5e +0x1c81 OP_MobEnduranceUpdate +0x4a78 +0x37a2 +0x5565 +0x2d09 +0x3141 +0x695e +0x0029 OP_TrackTarget +0x029 +0x1612 +0x3e69 +0x5c59 +0x7e1a OP_GMZoneRequest2 +0x24d9 +0x5089 OP_ZoneEntry +0x61db +0x542f +0x2006 +0x52fa OP_FeignDeath +0x39e8 OP_PickPocket +0x7c2e +0x2cdd +0x5e3a +0x4214 +0x2828 OP_HPUpdate +0x14b8 +0x3791 OP_ManaUpdate +0x0698 +0x5f42 OP_EnduranceUpdate +0x7eb5 +0x73f4 OP_Bug +0x69a4 OP_SendZonepoints +0x57bc OP_InspectRequest +0x71ac OP_InspectAnswer +0x4229 OP_GroupMakeLeader +0x54f7 +0x322b +0x3264 +0x202c +0x29ae +0x7a09 OP_SendLoginInfo +0x5206 +0x7fd2 +0x6259 OP_PostEnterWorld +0x0f70 +0x00d1 +0x0d1 +0x1eac +0x1b54 +0x5e23 +0x7910 +0x152e +0x7555 +0x05ce OP_GroupFollow +0x1649 OP_GroupInvite +0x6110 +0x0641 +0x578f OP_EnterWorld +0x6cb8 +0x6ef5 +0x4c44 OP_ZoneServerInfo +0x4cb4 OP_ZoneUnavail +0x74fb +0xbe6b +0x5ac7 +0x6281 +0x1bc5 OP_SetChatServer +0x48c8 +0x677b +0x6820 +0x2623 +0x69b9 OP_GuildMemberUpdate +0x2dcb +0x5e04 +0x1d3c +0x6060 OP_LFGCommand +0x0340 OP_LFGGetMatchesRequest +0x49a9 OP_LFPCommand +0x4d7d OP_LFPGetMatchesRequest +0x5048 OP_LFGGetMatchesResponse +0x22c6 OP_LFPGetMatchesResponse +0x499e +0x2d4e OP_GuildDemote +0x2009 +0x3b26 +0x69d4 +0x40b1 +0x587d +0x3747 +0x7a66 +0x2f03 +0x01ed +0x36e0 OP_GetGuildMOTD +0x4f1f OP_GetGuildMOTDReply +0x6087 +0x5f92 +0x439a +0x4334 +0x13c2 +0x7cb8 OP_TestBuff +0x17e5 OP_Track +0x5265 +0x1440 +0x7a4b +0x0648 +0x2529 +0x486f OP_GMSummon +0x458e OP_GMEmoteWorld +0x2549 +0x1cfd OP_GMEmoteZone +0x5ca6 OP_CharInventory +0x2710 +0x7291 OP_SpawnDoor +0x7afc +0x1f65 +0x3ddd +0x85fc +0x72df OP_ReadBook +0x3af1 OP_RequestDuel +0x52f7 +0x77b5 OP_TradeRequest +0x70f2 +0x207d +0x384a OP_ConsentResponse +0x5505 OP_TradeBusy +0x0c1e OP_ClickObjectAction +0x51eb +0x466b +0x41a3 +0x0682 +0x1242 +0x261d OP_LoadSpellSet +0x32a6 +0x2c6c OP_AdventureRequest +0x39e5 +0x5648 OP_AdventureDetails +0x5327 OP_LDoNButton +0x4524 +0x5954 OP_RandomNameGenerator +0x327d +0x2945 +0x33d7 +0x2651 +0x3b86 +0x0c6c +0x24d4 +0x4441 +0x4e42 +0x50d8 +0x1afb +0x6bd4 +0x3cb0 OP_AdventureInfoRequest +0x4c54 OP_AdventureInfo +0x7171 OP_AdventureData +0x35e8 +0x7d49 +0x1848 +0x2599 +0x0dab +0x6493 +0x34f2 +0x7d40 +0x0e00 +0x1cf3 +0x71f4 +0x5d18 OP_LeaveAdventure +0x4e25 +0x50c2 +0x400f OP_AdventureFinish +0x6368 +0x6192 +0x3aa4 +0x502e +0x1b01 OP_AdventureUpdate +0x0f24 +0x1015 +0x23a6 +0x5a74 +0x037a +0x7a45 OP_ConsentDeny +0x71bc +0x2382 OP_DenyResponse +0x02a0 +0x1126 OP_VetClaimRequest +0x0668 +0x16d4 OP_VetClaimReply +0x5cea OP_FindPersonRequest +0x0cc3 +0x7e58 OP_FindPersonReply +0x9be3 OP_PickLock +0x0438 +0x3d5c OP_LDoNOpen +0x15e7 +0x368e OP_ItemPacket +0x7331 +0x4936 +0x2c4e +0x78bf OP_DisarmTraps +0x02af OP_SenseTraps +0x65c3 OP_AdventurePointsUpdate +0x0dcb +0x661b OP_AugmentItem +0x5f68 +0x5278 +0x6b53 +0x5dd1 +0x559a OP_WeaponEquip2 +0x2d25 OP_WeaponUnequip2 +0x23c1 OP_WorldClientReady +0x5a62 OP_AdventureStatsRequest +0x7093 OP_AdventureLeaderboardRequest +0x2370 OP_AdventureStatsReply +0x7f79 OP_AdventureLeaderboardReply +0x4eb3 +0x3377 OP_BuffCreate +0x5882 OP_PetBuffWindow +0x4f4b OP_TargetBuffs +0x5961 OP_TributeUpdate +0x4f3e OP_TributeItem +0x5300 OP_TributePointUpdate +0x729b OP_SendTributes +0x4254 OP_TributeInfo +0x79fc OP_SelectTribute +0x073d OP_TributeTimer +0x08bf +0x7697 +0x4b65 +0x51ae +0x51a9 +0x7666 OP_OpenTributeMaster +0x4290 +0x759e OP_DisciplineUpdate +0x01c6 +0x6989 OP_DisciplineTimer +0x58fb OP_TributeMoney +0x7422 +0x0d25 +0x4de1 +0x46d0 +0x4f50 +0x2ddc +0x7441 +0x6a12 +0x29a8 +0x3f7f +0x150b +0x11e3 +0x1ad3 +0x59ca +0x4701 OP_DzAddPlayer +0x1abc OP_DzRemovePlayer +0x405b OP_DzSwapPlayer +0x543d OP_DzMakeLeader +0x14c6 OP_DzPlayerList +0x7f4b OP_DzJoinExpeditionConfirm +0x1950 OP_DzJoinExpeditionReply +0x64b5 +0x0398 +0x7b68 OP_DzListTimers +0x4f7e +0x9119 OP_DzExpeditionInfo +0x205f OP_DzExpeditionList +0xb2e3 OP_DzQuit +0x32f0 OP_DzMemberStatus +0x3de9 OP_DzLeaderStatus +0x5ae4 OP_DzMemberList +0x4d6e +0x4fd0 OP_OnLevelMessage +0x575b +0x7e94 +0x5189 OP_DzExpeditionEndsWarning +0x383c OP_BankerChange +0x791e +0x5c74 OP_RecipesFavorite +0x71b1 +0x20ab +0x025f +0x214a OP_PopupResponse +0x08a6 OP_ItemRecastDelay +0x15a9 OP_PVPLeaderBoardDetailsRequest +0x3707 OP_PVPLeaderBoardRequest +0x04aa OP_PVPLeaderBoardDetailsReply +0x25b7 OP_PVPLeaderBoardReply +0x071f +0x2dee +0x4e62 +0x0c91 +0x18d3 OP_Weblink +0x6f4b OP_PVPStats +0x4b15 +0x6755 +0x5c32 +0x5770 +0x7425 +0x5eed +0x574e +0x11b4 +0x4ed6 +0x0d9f +0x7d23 OP_ClearSurname +0x3fb0 +0xc693 OP_RemoveNimbusEffect +0x7b1e +0x20ae +0x0727 +0x3771 +0x7fe0 +0x4d5e +0x1877 OP_SendGuildTributes +0x649f +0x5f3f +0x5bcb +0x43d2 +0x49ea +0x378d OP_OpenGuildTributeMaster +0x7f8e +0x02bc +0x7dd2 +0x7c1d +0x7a41 +0x7db5 +0x7eec OP_SetChatServer2 +0x0904 OP_CorpseDrag +0x7037 OP_CorpseDrop +0x5e19 OP_TaskActivityComplete +0x4e32 +0x241d OP_TributeToggle +0x756a +0x7745 +0x039d +0x0f50 + +0x66b5 OP_SendAATable +0x0afb OP_AugmentInfo +0x10f6 +0x1013 + +0x6344 OP_RequestTitles +0x2d08 OP_SendTitleList +0x3719 +0x7a48 +0x0a23 OP_AcceptNewTask +0x705b +0x3bc9 OP_LevelAppearance +0x60ef +0x1619 +0x17fd OP_VoiceMacroIn +0x409a OP_VoiceMacroOut +0x4493 OP_WorldComplete +0x6527 OP_SetTitle +0x4c21 OP_SetTitleReply +0x127f OP_CameraEffect +0x0d32 OP_NewTitlesAvailable +0x34a7 OP_WeaponEquip1 +0x34cd +0x5936 OP_SpellEffect +0x241e OP_AutoFire +0x66f0 OP_UpdateAA +0x100e OP_CustomTitles +0x6b65 +0x12f5 +0x7677 OP_Bandolier +0x688f +0x7adf +0x0ed4 +0x243a OP_Barter +0x1a6a +0x5623 +0x43c8 OP_SendAAStats +0x655e +0x1a3e OP_PotionBelt +0x6326 OP_SetStartCity +0x7485 +0x5416 +0x3282 +0x3752 +0x425b +0x27c8 +0x2b19 +0x70ce +0x3165 +0x786b +0x0f26 +0x3500 +0x3d04 +0x5134 OP_GuildBank +0x0521 +0x7850 +0x108b +0x5671 +0x6d2b +0x732f +0x748f OP_GuildManageBanker +0x6858 +0x5e74 +0x3f35 +0x35e9 +0x2056 +0x6922 OP_AdventureMerchantRequest +0x5b72 OP_AdventureMerchantPurchase +0x2f9b OP_AdventureMerchantSell +0x3e47 OP_AdventureMerchantResponse +0x0b7d +0x2818 +0x35bd +0x51df +0x1ff7 +0x3926 +0x6265 +0x4ab0 +0x5e6c +0x1350 +0x6288 +0x7348 +0x48a2 OP_OpenNewTasksWindow +0x3010 +0x45db +0x36e8 OP_AvaliableTask +0x4865 +0x322e +0x7582 +0x5727 OP_TaskMemberList +0x6646 +0x37f2 +0x3444 +0x5ffc +0x5cb5 +0x0119 +0x35b5 +0x6cc6 +0x4926 +0x1b1d +0x7299 +0x0bf1 +0x08b4 +0x7f7a +0x3dab +0x1e7d +0x610a +0x04c8 +0x4811 +0x609e +0x65f0 +0x467f OP_CrystalCountUpdate +0x7aee OP_CrystalCreate +0x2439 OP_CrystalReclaim +0x39c1 +0x555e +0x7c9c +0x2c94 +0x2fc2 +0x2067 +0x059e +0x7f74 +0x68b2 +0x6f2b +0x01d6 +0x5182 +0x1da2 +0x5147 +0x51f8 +0x11f3 +0x0d07 +0x272f +0x413f +0x5968 +0x3e0e OP_DzCompass +0x282a +0x035f OP_GMNameChange +0x4013 +0x0e2f +0x099e +0x4eba OP_CompletedTasks +0x5f1c OP_TaskHistoryRequest +0x3d05 OP_TaskHistoryReply +0x2b8e +0x66d6 +0x0143 +0x6a5d +0x6e61 +0x2b0f +0x46c6 OP_FloatListThing +0x3a8d +0x15e5 +0x7d89 +0x4085 +0x1507 +0x5d93 +0x1669 +0x4664 +0x312d +0x2215 +0x1745 OP_Rewind +0x0cf1 +0x6567 +0x4405 +0x72d8 +0xaaba +0x27f8 OP_AssistGroup +0x7cfb +0x1a32 +0x14fd +0x77bb +0x36d1 +0x6193 +0x184c +0x3c47 +0x4e0b +0x7c15 +0x2ec3 OP_ShroudSelectionWindow +0x2b37 OP_ShroudRequestStats +0x6c04 OP_ShroudRespondStats +0x1cd0 OP_ShroudSelect +0x79da +0x7806 +0x541d OP_ShroudProgress +0x3823 +0x6562 OP_Shroud +0x4b25 +0x2507 +0x3acc +0x006e +0x06e +0x0728 +0x66cd +0x3c54 +0x2e8d +0x4eea +0x5a67 +0x3d20 +0x649c +0x21a6 +0x28bc OP_RespawnWindow +0x0ecb OP_ZonePlayerToBind +0x08d8 +0x7b71 +0x1115 +0x18cb +0x34f4 +0x5f08 +0x5bd2 +0x5052 +0x5e69 +0x2ccc +0x655c +0x6773 OP_CharacterCreateRequest +0x590e OP_VetRewardsAvaliable +0x6b0b +0x555a +0x7786 +0x67e8 +0x6381 +0x5628 +0xb52f +0x6084 +0x2958 OP_GuildUpdateURLAndChannel +0x2301 OP_WorldUnknown001 +0x610b +0x6f8b +0x4d25 OP_InspectMessageUpdate +0x3033 OP_BlockedBuffs +0x0de7 OP_RemoveBlockedBuffs +0x30e5 +0x618c +0x58e6 +0x1456 +0x053c OP_Untargetable +0x71da +0x333f +0x49bc +0x64f2 OP_BuffRemoveRequest +0x6b3d +0x34cb OP_ClearBlockedBuffs +0x5646 +0x7d13 +0x15e0 +0x5710 +0x172b +0x1888 +0x2956 +0x6a68 +0x7631 +0x298e +0x003c +0x03c +0x0b0f +0x5a72 +0x0767 +0x2f1a +0x6c7a +0x1660 +0x344f +0x028b +0x6eea +0x7707 +0x3fb2 +0x289e +0x3342 +0x5892 OP_GroupMentor +0x189c OP_NPCMoveUpdate +0x097b OP_ItemVerifyRequest +0x2115 OP_ItemVerifyReply +0x6411 +0x6471 +0x134a +0x1304 +0x5a79 +0x2dde +0x7d50 +0x1d47 +0x10ec +0x000f +0x00f OP_RestState +0x0f +0x465b +0x2289 OP_ItemViewUnknown +0x023b +0x4223 +0x7261 +0x2af9 +0x19aa +0x66dd OP_GMTrainSkillConfirm +0x4b64 +0x319e +0x1af3 +0x449c +0x8582 #OP_LoginUnknown1 +0x4b8d #OP_LoginUnknown2 +0x298d +0x06c8 +0x4f93 +0x412d +0x001f +0x01f +0x60f6 +0x1a9e +0x798e +0x17b7 +0x3042 +0x61bd +0x1f6e +0x65a6 +0x740d +0x48da +0x20d9 +0x5258 +0x1b5d +0x49f4 +0x7aa9 +0xb350 +0x6e2a +0x5d4e +0x6e4d +0x4ffc +0x1d15 +0x6f23 +0x2296 +0x765b +0x2e01 +0x26dd +0x72d3 +0x6981 +0x3b30 +0x14ac +0x0d92 +0x0001 +0x001 +0x01 +0x09bb +0x9e18 +0x0d9d +0x7f2b +0x3651 +0x645d +0x3af2 +0x4377 +0x39c9 +0x4924 +0x1e50 +0x4683 +0x0276 +0x6dec +0x56c9 +0x3ee6 +0x7121 OP_AltCurrency +0x62ab +0x5d88 +0x05f0 OP_MercenaryAssign +0x6b6d OP_AltCurrencyMerchantRequest +0x61cb OP_AltCurrencyPurchase +0x0165 OP_AltCurrencySell +0x74ec OP_AltCurrencyMerchantReply +0x5409 OP_AltCurrencySellSelection +0x3788 +0x40b6 +0x27a2 +0x532a OP_AltCurrencyReclaim +0x3899 +0x7567 +0x4820 +0x0339 +0x0c12 +0x074d +0x47ba +0x55c8 +0x4c89 +0x18b7 +0x2950 +0x44cb +0x4477 +0x6146 +0x40cf +0x2405 +0x49e2 +0x2aff +0x0bfa +0x26c0 +0x7d39 +0x259f +0x086b +0x6dc1 +0x6f80 +0x042e +0x2ad4 +0x317b +0x73ac +0x18d7 +0x5b8b +0x5c83 +0x1f51 +0x62f7 +0x1c46 +0x2a44 +0x3e7a +0x4374 +0x3b23 +0x1df4 +0x3ed8 +0x4b50 +0x36eb +0x65c7 +0x5620 +0x587e +0x3897 OP_SendFindableNPCs +0x7e62 +0x67ae +0x74f4 +0x4613 +0x2a92 +0x6d6e +0x2c01 +0x1243 +0x133e +0x67fc +0x49e1 OP_HideCorpse +0x0e44 +0x239a +0x1a0a +0x398f +0x1ff4 +0x88a1 +0x74da OP_GroupDisbandOther +0x21b4 OP_GroupLeaderChange +0x62b7 +0x4ced +0x3abb OP_GroupUpdate +0x0f6c OP_GroupDelete +0x0cbc +0x6194 OP_GroupUpdateB +0x7fe6 +0x04d0 +0x7323 OP_GroupAcknowledge +0x1ae5 OP_GroupDisbandYou +0x4d9f +0x70e2 OP_GroupRoles +0x6875 +0x6298 +0x02cf OP_GroupLeadershipAAUpdate +0x22b8 OP_MercenarySuspend2 +0x7bff +0x5512 +0x2b57 +0x1380 +0x2bcb +0x7b89 OP_MercenaryDataUpdateRequest +0x61a4 OP_MercenaryDataUpdate +0x11c1 OP_MercenaryDataRequest +0x72ce OP_MercenaryDataResponse +0x7169 OP_MercenaryHire +0x6e83 OP_MercenaryDismiss +0x31e4 OP_MercenaryTimerRequest +0x0763 OP_MercenaryTimer +0x78f6 +0x1b37 +0x27f2 OP_MercenaryCommand +0x5df8 +0x4333 +0x69ca +0x6e9f +0x4407 OP_MercenarySuspendRequest +0x6f03 OP_MercenarySuspendResponse +0x27a0 OP_MercenaryUnsuspendResponse +0x5f88 +0x2749 +0x038f +0x0e52 +0x20b9 +0x5d26 OP_MercenaryUnknown1 +0x69e7 +0x66b9 +0x0b72 +0x7e6f +0x29ec +0x6248 +0x702b +0x2b4f +0x6e6d +0x1e9f +0x5bd5 +0x4b7f +0x1490 +0x075e +0x4263 +0x1eba +0x4a74 +0x0a37 +0x3289 +0x3171 +0x0114 +0x5148 +0x76c3 +0x09bf +0x356f +0x77a7 +0x479a +0x209f +0x54e6 +0x6c3e +0xee80 +0x40e5 +0x76d9 +0x1dc8 OP_GuildCreate +0x794a +0x35c5 +0x137d +0x004a +0x04a +0x29b4 +0x18f1 +0x17fc +0x4707 OP_ChangeSize +0x3e15 +0x7248 +0x57c6 +0x7679 +0x6c8b +0x14c3 +0x3a02 +0x7900 +0x5688 +0x3a58 +0x75dd +0x39e1 +0x47cb +0x171e +0xdab0 +0x618f +0x27b1 +0x3d0c +0x0d2a +0x8c30 +0x2b42 +0x17f8 +0x1665 +0x059d +0x72c9 +0x675d +0x28e0 +0x61df +0x3ef8 +0x4d59 +0x3763 +0x672f OP_XTargetResponse +0x45be OP_XTargetRequest +0x792c OP_XTargetAutoAddHaters +0x66bf +0x66df +0x2aa7 +0x76c6 +0x6032 +0x3e00 +0x0c13 +0x0a59 +0x393a +0x45ed +0x507f +0x68ba +0x5a63 +0x6fd0 +0x63fd +0x4f09 +0x485d +0x3968 +0x69e1 +0x3d94 +0x0351 +0x5f0a +0x36be +0x59f9 +0x7075 +0x6ee6 +0x2691 +0x3c8b +0x01df +0x218c +0x233b +0x2cf7 +0x1097 +0x1baf +0x6f35 +0x1228 +0x1cef +0x7d28 +0x087f +0x1967 +0x6917 +0x613d +0x37d9 +0x58c7 +0x21ec +0x3424 +0x2036 +0x7ad1 +0x01c3 +0x626e +0x711a +0x5b41 +0x21ba +0x2933 +0x050c +0x51e3 +0x64a3 +0x3146 +0x2aa6 +0x16df +0x2698 +0x21ea +0x796c +0x7bb1 +0x6af6 +0x499a +0x3c44 +0x3cbc +0x6561 +0x12f7 +0x6292 +0x3de0 +0x1409 +0x4604 +0x0ca1 +0x754e +0x4f2b +0x6995 +0x3745 +0x789b +0xcadf +0x4abe +0x6014 +0x7fff +0x6228 +0x10e0 +0x7452 +0x6d9f +0x7f80 +0xb07f +0x6b5c OP_ItemPreview +0x02b4 +0x3bd3 +0x3036 +0x5c3f +0x433d +0x78e2 +0x543f +0x58b4 +0x2563 +0x1820 +0x40be +0x62d6 +0x0d68 +0x6d10 +0x3a32 +0x2fed +0x1303 +0x49df +0x3e24 +0x2b35 +0x0910 +0x3849 +0x6873 +0x15e2 +0x2d85 +0x39bb +0x42e9 +0x6860 +0x15a8 +0x52b5 +0x3311 +0x58df +0x2a7f +0x6573 +0x7a4d +0x7497 +0x1fcc +0x7c23 +0x2d28 +0x5dab +0x005a +0x05a +0x4506 +0x046d +0x36db +0x5a40 +0x4cd9 +0x63d7 +0x48d4 +0x035d +0x11f5 +0x7b84 +0x4f05 +0x7369 +0x7b32 +0x4fe6 +0x6cd0 +0x6770 +0x5c24 +0x063a +0x0d93 +0x4c2a +0x2235 +0x7b95 +0x6a1f +0x46f0 +0x2de2 +0xadd7 +0x2cc6 +0x7db7 +0x7588 +0x4957 +0x6a98 + +0x057b OP_SendMembershipDetails +0x7acc OP_SendMembership +0x431f +0x42c4 +0x05a8 +0x5475 OP_SendMaxCharacters +0x4ad2 +0x03d9 +0x771e +0x2a34 +0x7273 +0x1c9e +0x5f17 +0x37a9 +0x6530 +0x3157 +0x1f5e +0x2bc8 +0x593a +0x1643 +0x16bc +0x1781 +0x53d3 +0x5369 +0x25b3 +0x2fa0 +0x73a9 +0x1595 +0x6b6f +0x65f2 +0x3562 +0x309d +0x4efa +0x1da9 +0x6678 +0x16e8 diff --git a/utils/scripts/opcode_scripts/oplist_to_conf.pl b/utils/scripts/opcode_scripts/oplist_to_conf.pl new file mode 100644 index 000000000..0d808707d --- /dev/null +++ b/utils/scripts/opcode_scripts/oplist_to_conf.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl + +# File Name: oplist_to_conf.pl +# Converts the Opcode List with Opcode Names from the Spreadsheet into a Patch File. + +# Directions to use this script: +# 1. Copy the opcodes and opcode names columns from the opcode spreadsheet +# for the columns you want to create a new .conf file from into the file. +# 2. Remove the header row entries in the newly created text file and save it. +# 3. Paste the contents of the current patch file in the patch_OLD.conf file. +# 4. Run this script using "perl oplist_to_conf.pl" +# 5. This creates a new .conf file named patch_NEW.conf +# 6. Rename patch_NEW.conf to the desired name and you are all done + + +$stopmessage = "Failed to open file"; +# Open the text file that contains the opcode and opcode name rows for a single client from the opcode list spreadsheet +open OpcodeFile, "<", "opcodelist.txt" or die $stopmessage; +# Open the .conf file to copy from +open PatchFile, "<", "patch_OLD.conf" or die $stopmessage; + +# Read these files into arrays for looping and close the files +my @OpcodeList = ; +my @PatchFile = ; +close(OpcodeFile); +close(PatchFile); + +# Open the new/destination .conf file and clear out file contents +open OpcodeResultFile, ">", "patch_NEW.conf" or die $stopmessage; +print OpcodeResultFile ""; +# Close out the newly cleared .conf file +close(OpcodeResultFile); + +# Open the new/destination .conf file again for appending +open OpcodeResultFile, ">>", "patch_NEW.conf" or die $stopmessage; + +my %PatchHash = (); + +foreach $line (@OpcodeList) +{ + @equalssplit = split(/ /, $line); + $ArraySize = @equalssplit; + if ($ArraySize > 1) + { + my $CurOpcode = ""; + my $CurOpcodeName = ""; + @OpcodeArray = split(//, $equalssplit[0]); + if ($equalssplit[1] =~ /^OP_(.*)/i) + { + $CurOpcodeName = "OP_".$1; + } + foreach $Letter (@OpcodeArray) + { + if ($Letter =~ /[A-Za-z0-9]/) + { + $CurOpcode .= $Letter; + } + } + if ($CurOpcode && $CurOpcodeName) + { + $CurOpcode = lc($CurOpcode); + $PatchHash{ $CurOpcodeName } = $CurOpcode; + #print $CurOpcodeName."=". $CurOpcode."\n"; + } + } +} + +$TabSpace = " "; # Tab +foreach $line (@PatchFile) +{ + $CurLine = $line; + if ($line =~ /^OP_([^\=]+)=([^\s]+)(.*)/i) + { + $NewOpcode = "0x0000"; + $OpcodeName = "OP_".$1; + + if ($PatchHash{$OpcodeName}) + { + $NewOpcode = $PatchHash{$OpcodeName}; + } + + $CurLine = $OpcodeName."=".$NewOpcode.$3."\n"; + } + print OpcodeResultFile $CurLine; +} + + +close(OpcodeResultFile); diff --git a/utils/scripts/opcode_scripts/patch_NEW.conf b/utils/scripts/opcode_scripts/patch_NEW.conf new file mode 100644 index 000000000..148d00ba9 --- /dev/null +++ b/utils/scripts/opcode_scripts/patch_NEW.conf @@ -0,0 +1,661 @@ +# ShowEQ Import Notes: +# ZERO THE FILE first +# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf +# Unknown Mapping: +# OP_Action2 -> OP_Damage +# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake +# Name Differences: +# OP_CancelInvite -> OP_GroupCancelInvite +# OP_GMFind -> OP_FindPersonRequest +# OP_CommonMessage -> OP_ChannelMessage + +OP_Unknown=0x0000 +OP_ExploreUnknown=0x0000 used for unknown explorer + +# world packets +# Required to reach Char Select: +OP_SendLoginInfo=0x7a09 +OP_ApproveWorld=0x7499 +OP_LogServer=0x7ceb +OP_SendCharInfo=0x00d2 +OP_ExpansionInfo=0x590d +OP_GuildsList=0x0000 +OP_EnterWorld=0x578f +OP_PostEnterWorld=0x6259 +OP_World_Client_CRC1=0x12cc +OP_World_Client_CRC2=0x0f13 +OP_SendSpellChecksum=0x0000 +OP_SendSkillCapsChecksum=0x0000 + +# Character Select Related: +OP_SendMaxCharacters=0x5475 +OP_SendMembership=0x7acc +OP_SendMembershipDetails=0x057b +OP_CharacterCreateRequest=0x6773 +OP_CharacterCreate=0x6bbf +OP_DeleteCharacter=0x1808 +OP_RandomNameGenerator=0x5954 +OP_ApproveName=0x56a2 +OP_MOTD=0x0c22 +OP_SetChatServer=0x1bc5 +OP_SetChatServer2=0x7eec +OP_ZoneServerInfo=0x4c44 +OP_WorldComplete=0x4493 +OP_WorldUnknown001=0x2301 +OP_FloatListThing=0x46c6 + +# Reasons for Disconnect: +OP_ZoneUnavail=0x4cb4 +OP_WorldClientReady=0x23c1 +OP_CharacterStillInZone=0x0000 +OP_WorldChecksumFailure=0x0000 +OP_WorldLoginFailed=0x0000 +OP_WorldLogout=0x0000 +OP_WorldLevelTooHigh=0x0000 +OP_CharInacessable=0x0000 +OP_UserCompInfo=0x0000 +OP_SendExeChecksum=0x0000 +OP_SendBaseDataChecksum=0x0000 + +# Zone in opcodes +OP_AckPacket=0x471d +OP_ZoneEntry=0x5089 +OP_ReqNewZone=0x7887 +OP_NewZone=0x1795 +OP_ZoneSpawns=0x5237 +OP_PlayerProfile=0x6506 +OP_TimeOfDay=0x5070 +OP_LevelUpdate=0x1eec +OP_Stamina=0x2a79 +OP_RequestClientZoneChange=0x3fcf +OP_ZoneChange=0x2d18 +OP_LockoutTimerInfo=0x0000 +OP_ZoneServerReady=0x0000 +OP_ZoneInUnknown=0x0000 +OP_LogoutReply=0x0000 +OP_PreLogoutReply=0x0000 + +# Required to fully log in +OP_SpawnAppearance=0x0971 +OP_ChangeSize=0x4707 +OP_TributeUpdate=0x5961 +OP_TributeTimer=0x073d +OP_SendTributes=0x729b +OP_SendGuildTributes=0x1877 +OP_TributeInfo=0x4254 +OP_Weather=0x661e +OP_ReqClientSpawn=0x35fa +OP_SpawnDoor=0x7291 +OP_GroundSpawn=0x6fca +OP_SendZonepoints=0x69a4 +OP_BlockedBuffs=0x3033 +OP_RemoveBlockedBuffs=0x0de7 +OP_ClearBlockedBuffs=0x34cb +OP_WorldObjectsSent=0x5ae2 +OP_SendExpZonein=0x5f8e +OP_SendAATable=0x66b5 +OP_RespondAA=0x7a27 +OP_UpdateAA=0x66f0 +OP_SendAAStats=0x43c8 +OP_AAExpUpdate=0x7d14 +OP_ExpUpdate=0x20ed +OP_HPUpdate=0x2828 +OP_ManaChange=0x43af +OP_TGB=0x0876 +OP_SpecialMesg=0x0083 +OP_GuildMemberList=0x12a6 +OP_GuildMOTD=0x3e13 +OP_CharInventory=0x5ca6 +OP_WearChange=0x7994 +OP_ClientUpdate=0x7dfc +OP_ClientReady=0x345d # 0x422d +OP_SetServerFilter=0x444d + +# Guild Opcodes - Disabled until crashes are resolved in RoF +OP_GetGuildMOTD=0x36e0 # Was 0x35dc +OP_GetGuildMOTDReply=0x4f1f # Was 0x4586 +OP_GuildMemberUpdate=0x69b9 # Was 0x5643 +OP_GuildInvite=0x7099 +OP_GuildRemove=0x1444 +OP_GuildPeace=0x67e3 +OP_SetGuildMOTD=0x0b0b +OP_GuildList=0x507a +OP_GuildWar=0x1ffb +OP_GuildLeader=0x7e09 +OP_GuildDelete=0x3708 +OP_GuildInviteAccept=0x7053 +OP_GuildDemote=0x2d4e +OP_GuildPromote=0x0000 +OP_GuildPublicNote=0x5053 +OP_GuildManageBanker=0x748f # Was 0x0737 +OP_GuildBank=0x5134 # Was 0x10c3 +OP_SetGuildRank=0x0b9c +OP_GuildUpdateURLAndChannel=0x2958 +OP_GuildStatus=0x7326 +OP_GuildCreate=0x1dc8 # or maybe 0x086e +OP_GuildMemberLevelUpdate=0x0000 # Unused? +OP_ZoneGuildList=0x0000 # Unused? +OP_GetGuildsList=0x0000 # Unused? +OP_LFGuild=0x0000 +OP_GuildManageRemove=0x0000 +OP_GuildManageAdd=0x0000 +OP_GuildManageStatus=0x0000 + +# GM/Guide Opcodes +OP_GMServers=0x08c1 +OP_GMBecomeNPC=0x3ae1 +OP_GMZoneRequest=0x62ac +OP_GMZoneRequest2=0x7e1a +OP_GMGoto=0x7d8e +OP_GMSearchCorpse=0x357c +OP_GMHideMe=0x79c5 +OP_GMDelCorpse=0x607e +OP_GMApproval=0x6db5 +OP_GMToggle=0x2097 +OP_GMSummon=0x486f # Was 0x684f +OP_GMEmoteZone=0x1cfd # Was 0x0655 +OP_GMEmoteWorld=0x458e # Was 0x1935 +OP_GMFind=0x4a8f +OP_GMKick=0x26a7 +OP_GMKill=0x51d3 +OP_GMNameChange=0x035f # Was 0x4434 +OP_GMLastName=0x46ce # Was 0x3077 + +# Misc Opcodes +OP_InspectRequest=0x57bc +OP_InspectAnswer=0x71ac +OP_InspectMessageUpdate=0x4d25 +OP_BeginCast=0x318f +OP_ColoredText=0x0000 +OP_ConsentResponse=0x384a +OP_MemorizeSpell=0x217c +OP_SwapSpell=0x0efa +OP_CastSpell=0x1287 +OP_Consider=0x742b +OP_FormattedMessage=0x1024 +OP_SimpleMessage=0x213f +OP_Buff=0x659c +OP_Illusion=0x312a +OP_MoneyOnCorpse=0x5f44 +OP_RandomReply=0x106b +OP_DenyResponse=0x2382 +OP_SkillUpdate=0x004c +OP_GMTrainSkillConfirm=0x66dd # 0x3960 +OP_RandomReq=0x7b10 +OP_Death=0x6517 +OP_GMTraining=0x1966 +OP_GMEndTraining=0x4d6b +OP_GMTrainSkill=0x2a85 +OP_Animation=0x7177 +OP_Begging=0x6703 +OP_Consent=0x1fd1 +OP_ConsentDeny=0x7a45 +OP_AutoFire=0x241e +OP_PetCommands=0x0159 +OP_DeleteSpell=0x52e5 +OP_Surname=0x0423 +OP_ClearSurname=0x7d23 +OP_FaceChange=0x5578 +OP_SenseHeading=0x260a +OP_Action=0x744c +OP_ConsiderCorpse=0x5204 +OP_HideCorpse=0x49e1 +OP_CorpseDrag=0x0904 +OP_CorpseDrop=0x7037 +OP_Bug=0x73f4 +OP_Feedback=0x5602 +OP_Report=0x1414 +OP_Damage=0x6f15 +OP_ChannelMessage=0x2b2d +OP_Assist=0x4478 +OP_AssistGroup=0x27f8 +OP_MoveCoin=0x0bcf +OP_ZonePlayerToBind=0x0ecb +OP_KeyRing=0x6857 +OP_WhoAllRequest=0x65ab +OP_WhoAllResponse=0x7c88 +OP_FriendsWho=0x3956 +OP_ConfirmDelete=0x43a3 +OP_Logout=0x4ac6 +OP_Rewind=0x1745 +OP_TargetCommand=0x58e2 +OP_Hide=0x67fe +OP_Jump=0x2060 +OP_Camp=0x28ec +OP_Emote=0x373b +OP_SetRunMode=0x009f +OP_BankerChange=0x383c +OP_TargetMouse=0x075d +OP_MobHealth=0x37b1 +OP_InitialMobHealth=0x0000 # Unused? +OP_TargetHoTT=0x0272 +OP_XTargetResponse=0x672f +OP_XTargetRequest=0x45be +OP_XTargetAutoAddHaters=0x792c +OP_TargetBuffs=0x4f4b +OP_BuffCreate=0x3377 +OP_BuffRemoveRequest=0x64f2 +OP_DeleteSpawn=0x7280 +OP_AutoAttack=0x109d +OP_AutoAttack2=0x3526 +OP_Consume=0x4b70 +OP_MoveItem=0x32ee +OP_DeleteItem=0x18ad +OP_DeleteCharge=0x01b8 +OP_ItemPacket=0x368e +OP_ItemLinkResponse=0x633c +OP_ItemLinkClick=0x4cef +OP_ItemPreview=0x6b5c +OP_NewSpawn=0x6097 +OP_Track=0x17e5 +OP_TrackTarget=0x0029 +OP_TrackUnknown=0x4577 +OP_ClickDoor=0x3a8f +OP_MoveDoor=0x08e8 +OP_RemoveAllDoors=0x700c +OP_EnvDamage=0x51fd +OP_BoardBoat=0x4211 +OP_Forage=0x5306 +OP_LeaveBoat=0x7617 +OP_ControlBoat=0x0ae7 +OP_SafeFallSuccess=0x2219 +OP_RezzComplete=0x760d +OP_RezzRequest=0x3c21 +OP_RezzAnswer=0x701c +OP_Shielding=0x48c1 +OP_RequestDuel=0x3af1 +OP_MobRename=0x2c57 +OP_AugmentItem=0x661b # Was 0x37cb +OP_WeaponEquip1=0x34a7 +OP_WeaponEquip2=0x559a # Was 0x6022 +OP_WeaponUnequip2=0x2d25 # Was 0x0110 +OP_ApplyPoison=0x31e6 +OP_Save=0x4a39 +OP_TestBuff=0x7cb8 # Was 0x3772 +OP_CustomTitles=0x100e +OP_Split=0x3a54 +OP_YellForHelp=0x4e56 +OP_LoadSpellSet=0x261d +OP_Bandolier=0x7677 +OP_PotionBelt=0x1a3e # Was 0x4d3b +OP_DuelResponse=0x6a46 +OP_DuelResponse2=0x68d3 +OP_SaveOnZoneReq=0x600d +OP_ReadBook=0x72df +OP_Dye=0x23b9 +OP_InterruptCast=0x048c +OP_AAAction=0x424e +OP_LeadershipExpToggle=0x6c55 +OP_LeadershipExpUpdate=0x2797 +OP_PurchaseLeadershipAA=0x0026 +OP_UpdateLeadershipAA=0x026 +OP_MarkNPC=0x5a58 +OP_MarkRaidNPC=0x74bd #unimplemented +OP_ClearNPCMarks=0x2003 +OP_ClearRaidNPCMarks=0x20d3 #unimplemented +OP_DelegateAbility=0x76b8 +OP_SetGroupTarget=0x2814 +OP_Charm=0x5d92 +OP_Stun=0x36a4 +OP_SendFindableNPCs=0x3897 +OP_FindPersonRequest=0x5cea +OP_FindPersonReply=0x7e58 +OP_Sound=0x1a30 +OP_PetBuffWindow=0x5882 +OP_LevelAppearance=0x3bc9 +OP_Translocate=0x6580 +OP_Sacrifice=0x1821 +OP_PopupResponse=0x214a +OP_OnLevelMessage=0x4fd0 +OP_AugmentInfo=0x0afb +OP_Petition=0x5f03 +OP_SomeItemPacketMaybe=0x747c +OP_PVPStats=0x6f4b # Unsure +OP_PVPLeaderBoardRequest=0x3707 +OP_PVPLeaderBoardReply=0x25b7 +OP_PVPLeaderBoardDetailsRequest=0x15a9 +OP_PVPLeaderBoardDetailsReply=0x04aa +OP_RestState=0x00f +OP_RespawnWindow=0x28bc +OP_LDoNButton=0x5327 +OP_SetStartCity=0x6326 # Was 0x2d1b +OP_VoiceMacroIn=0x17fd +OP_VoiceMacroOut=0x409a +OP_ItemViewUnknown=0x2289 +OP_VetRewardsAvaliable=0x590e +OP_VetClaimRequest=0x1126 +OP_VetClaimReply=0x16d4 +OP_DisciplineUpdate=0x759e # Was 0x2f05 +OP_DisciplineTimer=0x6989 # Was 0x5e3f +OP_BecomeCorpse=0x0000 # Unused? +OP_Action2=0x0000 # Unused? +OP_MobUpdate=0x2c84 +OP_NPCMoveUpdate=0x189c +OP_CameraEffect=0x127f +OP_SpellEffect=0x5936 +OP_RemoveNimbusEffect=0xc693 +OP_AltCurrency=0x7121 +OP_AltCurrencyMerchantRequest=0x6b6d +OP_AltCurrencyMerchantReply=0x74ec +OP_AltCurrencyPurchase=0x61cb +OP_AltCurrencySell=0x0165 +OP_AltCurrencySellSelection=0x5409 +OP_AltCurrencyReclaim=0x532a +OP_CrystalCountUpdate=0x467f # Was 0x3f60 +OP_CrystalCreate=0x7aee # Was 0x5a82 +OP_CrystalReclaim=0x2439 # Was 0x7616 +OP_Untargetable=0x053c +OP_IncreaseStats=0x70a3 +OP_Weblink=0x18d3 +#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U +OP_OpenContainer=0x0000 +OP_Marquee=0x0000 + +OP_DzQuit=0xb2e3 +OP_DzListTimers=0x7b68 +OP_DzAddPlayer=0x4701 +OP_DzRemovePlayer=0x1abc +OP_DzSwapPlayer=0x405b +OP_DzMakeLeader=0x543d +OP_DzPlayerList=0x14c6 +OP_DzJoinExpeditionConfirm=0x7f4b +OP_DzJoinExpeditionReply=0x1950 +OP_DzExpeditionInfo=0x9119 +OP_DzExpeditionList=0x205f +OP_DzMemberStatus=0x32f0 +OP_DzLeaderStatus=0x3de9 +OP_DzExpeditionEndsWarning=0x5189 +OP_DzMemberList=0x5ae4 +OP_DzCompass=0x3e0e # Was 0x4f09 +OP_DzChooseZone=0x0000 # Maybe 0x29d6 + +# New Opcodes +OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? +OP_ManaUpdate=0x3791 +OP_EnduranceUpdate=0x5f42 +OP_MobManaUpdate=0x2404 +OP_MobEnduranceUpdate=0x1c81 + +# Mercenary Opcodes +OP_MercenaryDataUpdateRequest=0x7b89 +OP_MercenaryDataUpdate=0x61a4 +OP_MercenaryDataRequest=0x11c1 +OP_MercenaryDataResponse=0x72ce +OP_MercenaryHire=0x7169 +OP_MercenaryDismiss=0x6e83 +OP_MercenaryTimerRequest=0x31e4 +OP_MercenaryTimer=0x0763 +OP_MercenaryUnknown1=0x5d26 +OP_MercenaryCommand=0x27f2 +OP_MercenarySuspendRequest=0x4407 +OP_MercenarySuspendResponse=0x6f03 +OP_MercenaryUnsuspendResponse=0x27a0 + +# Looting +OP_LootRequest=0x0adf +OP_EndLootRequest=0x30f7 +OP_LootItem=0x4dc9 +OP_LootComplete=0x55c4 + +# bazaar trader stuff: +OP_BazaarSearch=0x39d6 +OP_TraderDelItem=0x0000 +OP_BecomeTrader=0x61b3 +OP_TraderShop=0x31df +OP_Trader=0x4ef5 # Was 0x6790 +OP_TraderBuy=0x0000 +OP_Barter=0x243a +OP_ShopItem=0x0000 +OP_BazaarInspect=0x0000 +OP_Bazaar=0x0000 +OP_TraderItemUpdate=0x0000 + +# pc/npc trading +OP_TradeRequest=0x77b5 +OP_TradeAcceptClick=0x69e2 +OP_TradeRequestAck=0x14bf +OP_TradeCoins=0x4206 +OP_FinishTrade=0x3993 +OP_CancelTrade=0x354c +OP_TradeMoneyUpdate=0x68c2 +OP_MoneyUpdate=0x640c +OP_TradeBusy=0x5505 + +# Sent after canceling trade or after closing tradeskill object +OP_FinishWindow=0x7349 +OP_FinishWindow2=0x40ef + +# Sent on Live for what seems to be item existance verification +# Ex. Before Right Click Effect happens from items +OP_ItemVerifyRequest=0x097b +OP_ItemVerifyReply=0x2115 + +# merchant stuff +OP_ShopPlayerSell=0x1901 +OP_ShopRequest=0x4fed +OP_ShopEnd=0x30a8 +OP_ShopEndConfirm=0x3196 +OP_ShopPlayerBuy=0x04c +OP_ShopDelItem=0x724f + +# tradeskill stuff: +OP_ClickObject=0x4aa1 +OP_ClickObjectAction=0x0c1e +OP_ClearObject=0x7a11 +OP_RecipeDetails=0x40d7 +OP_RecipesFavorite=0x5c74 +OP_RecipesSearch=0x1db6 +OP_RecipeReply=0x6e02 +OP_RecipeAutoCombine=0x6261 +OP_TradeSkillCombine=0x579a + +# Tribute Packets: +OP_OpenGuildTributeMaster=0x378d +OP_OpenTributeMaster=0x7666 # Was 0x40f5 +OP_SelectTribute=0x79fc +OP_TributeItem=0x4f3e +OP_TributeMoney=0x58fb # Was 0x6fed +OP_TributeToggle=0x241d +OP_TributePointUpdate=0x5300 +OP_TributeNPC=0x0000 +OP_GuildTributeInfo=0x0000 +OP_OpenTributeReply=0x0000 +OP_GuildTributeStatus=0x0000 + +# Adventure packets: +OP_LeaveAdventure=0x5d18 +OP_AdventureFinish=0x400f +OP_AdventureInfoRequest=0x3cb0 +OP_AdventureInfo=0x4c54 +OP_AdventureRequest=0x2c6c +OP_AdventureDetails=0x5648 +OP_AdventureData=0x7171 +OP_AdventureUpdate=0x1b01 +OP_AdventureMerchantRequest=0x6922 # Was 654d +OP_AdventureMerchantResponse=0x3e47 # Was 7949 +OP_AdventureMerchantPurchase=0x5b72 # Was 155a +OP_AdventureMerchantSell=0x2f9b # Was 389c +OP_AdventurePointsUpdate=0x65c3 # Was 7589 +OP_AdventureStatsRequest=0x5a62 +OP_AdventureStatsReply=0x2370 +OP_AdventureLeaderboardRequest=0x7093 +OP_AdventureLeaderboardReply=0x7f79 + +# Group Opcodes +OP_GroupDisband=0x4c10 +OP_GroupInvite=0x1649 +OP_GroupFollow=0x05ce +OP_GroupUpdate=0x3abb +OP_GroupUpdateB=0x6194 +OP_GroupCancelInvite=0x0000 +OP_GroupAcknowledge=0x7323 +OP_GroupDelete=0x0f6c +OP_CancelInvite=0x32c2 +OP_GroupFollow2=0x2a50 +OP_GroupInvite2=0x6c65 +OP_GroupDisbandYou=0x1ae5 +OP_GroupDisbandOther=0x74da +OP_GroupLeaderChange=0x21b4 +OP_GroupRoles=0x70e2 +OP_GroupMakeLeader=0x4229 +OP_DoGroupLeadershipAbility=0x1fb5 +OP_GroupLeadershipAAUpdate=0x02cf +OP_GroupMentor=0x5892 +OP_InspectBuffs=0x486c + +# LFG/LFP Opcodes +OP_LFGCommand=0x6060 +OP_LFGGetMatchesRequest=0x0340 +OP_LFGGetMatchesResponse=0x5048 +OP_LFPGetMatchesRequest=0x4d7d +OP_LFPGetMatchesResponse=0x22c6 +OP_LFPCommand=0x49a9 +OP_LFGAppearance=0x0000 +OP_LFGResponse=0x0000 + +# Raid Opcodes +OP_RaidInvite=0x55ac +OP_RaidUpdate=0x3973 +OP_RaidJoin=0x0000 + +# Button-push commands +OP_Taunt=0x2703 +OP_CombatAbility=0x3eba +OP_SenseTraps=0x02af # Was 0x2ee0 +OP_PickPocket=0x39e8 +OP_DisarmTraps=0x78bf +OP_Disarm=0x5ec8 +OP_Sneak=0x5d55 +OP_Fishing=0x1e2a +OP_InstillDoubt=0x640e +OP_FeignDeath=0x52fa +OP_Mend=0x0ecf +OP_Bind_Wound=0x0386 +OP_LDoNOpen=0x3d5c + +# Task packets +OP_TaskDescription=0x083 +OP_TaskActivity=0x3714 +OP_CompletedTasks=0x4eba +OP_TaskActivityComplete=0x5e19 +OP_AcceptNewTask=0x0a23 +OP_CancelTask=0x08d3 +OP_TaskMemberList=0x5727 # Was 0x1656 +OP_OpenNewTasksWindow=0x48a2 # Was 0x11de +OP_AvaliableTask=0x36e8 # Was 0x2377 +OP_TaskHistoryRequest=0x5f1c +OP_TaskHistoryReply=0x3d05 +OP_DeclineAllTasks=0x0000 + +# Title opcodes +OP_NewTitlesAvailable=0x0d32 +OP_RequestTitles=0x6344 +OP_SendTitleList=0x2d08 +OP_SetTitle=0x6527 +OP_SetTitleReply=0x4c21 + +# mail opcodes +OP_Command=0x0000 +OP_MailboxHeader=0x0000 +OP_MailHeader=0x0000 +OP_MailBody=0x0000 +OP_NewMail=0x0000 +OP_SentConfirm=0x0000 + +########### Below this point should not be needed ########### + +# This section are all unknown in Titanium +OP_ForceFindPerson=0x0000 +OP_LocInfo=0x0000 +OP_ReloadUI=0x0000 +OP_ItemName=0x0000 +OP_ItemLinkText=0x0000 +OP_MultiLineMsg=0x0000 +OP_MendHPUpdate=0x0000 +OP_TargetReject=0x0000 +OP_SafePoint=0x0000 +OP_ApproveZone=0x0000 +OP_ZoneComplete=0x0000 +OP_ClientError=0x0000 +OP_DumpName=0x0000 +OP_Heartbeat=0x0000 +OP_CrashDump=0x0000 +OP_LoginComplete=0x0000 + +# discovered opcodes not yet used: +OP_PickLockSuccess=0x0000 +OP_PlayMP3=0x0000 +OP_ReclaimCrystals=0x0000 +OP_DynamicWall=0x0000 +OP_OpenDiscordMerchant=0x0000 +OP_DiscordMerchantInventory=0x0000 +OP_GiveMoney=0x0000 +OP_RequestKnowledgeBase=0x0000 +OP_KnowledgeBase=0x0000 +OP_SlashAdventure=0x0000 # /adventure +OP_BecomePVPPrompt=0x0000 +OP_MoveLogRequest=0x0000 # gone I think +OP_MoveLogDisregard=0x0000 # gone I think + +# named unknowns, to make looking for real unknown easier +OP_AnnoyingZoneUnknown=0x0000 +OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members +OP_QueryResponseThing=0x0000 + + +# realityincarnate: these are just here to stop annoying several thousand byte packet dumps +#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum +#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum + +# Petition Opcodes +OP_PetitionSearch=0x0000 search term for petition +OP_PetitionSearchResults=0x0000 (list of?) matches from search +OP_PetitionSearchText=0x0000 text results of search + +OP_PetitionUpdate=0x0000 +OP_PetitionCheckout=0x0000 +OP_PetitionCheckIn=0x0000 +OP_PetitionQue=0x0000 +OP_PetitionUnCheckout=0x0000 +OP_PetitionDelete=0x0000 +OP_DeletePetition=0x0000 +OP_PetitionResolve=0x0000 +OP_PDeletePetition=0x0000 +OP_PetitionBug=0x0000 +OP_PetitionRefresh=0x0000 +OP_PetitionCheckout2=0x0000 +OP_PetitionViewPetition=0x0000 + +# Login opcodes +OP_SessionReady=0x0000 +OP_Login=0x0000 +OP_ServerListRequest=0x0000 +OP_PlayEverquestRequest=0x0000 +OP_PlayEverquestResponse=0x0000 +OP_ChatMessage=0x0000 +OP_LoginAccepted=0x0000 +OP_ServerListResponse=0x0000 +OP_Poll=0x0000 +OP_EnterChat=0x0000 +OP_PollResponse=0x0000 + +# raw opcodes +OP_RAWSessionRequest=0x0000 +OP_RAWSessionResponse=0x0000 +OP_RAWCombined=0x0000 +OP_RAWSessionDisconnect=0x0000 +OP_RAWKeepAlive=0x0000 +OP_RAWSessionStatRequest=0x0000 +OP_RAWSessionStatResponse=0x0000 +OP_RAWPacket=0x0000 +OP_RAWFragment=0x0000 +OP_RAWOutOfOrderAck=0x0000 +OP_RAWAck=0x0000 +OP_RAWAppCombined=0x0000 +OP_RAWOutOfSession=0x0000 + +# we need to document the differences between these packets to make identifying them easier +OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs +OP_InitialHPUpdate=0x0000 + +OP_ItemRecastDelay=0x08a6 diff --git a/utils/scripts/opcode_scripts/patch_OLD.conf b/utils/scripts/opcode_scripts/patch_OLD.conf new file mode 100644 index 000000000..4bc1f9097 --- /dev/null +++ b/utils/scripts/opcode_scripts/patch_OLD.conf @@ -0,0 +1,661 @@ +# ShowEQ Import Notes: +# ZERO THE FILE first +# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf +# Unknown Mapping: +# OP_Action2 -> OP_Damage +# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake +# Name Differences: +# OP_CancelInvite -> OP_GroupCancelInvite +# OP_GMFind -> OP_FindPersonRequest +# OP_CommonMessage -> OP_ChannelMessage + +OP_Unknown=0x0000 +OP_ExploreUnknown=0x0000 used for unknown explorer + +# world packets +# Required to reach Char Select: +OP_SendLoginInfo=0x7a09 +OP_ApproveWorld=0x7499 +OP_LogServer=0x7ceb +OP_SendCharInfo=0x00d2 +OP_ExpansionInfo=0x590d +OP_GuildsList=0x7056 +OP_EnterWorld=0x0641 +OP_PostEnterWorld=0x6259 +OP_World_Client_CRC1=0x12cc +OP_World_Client_CRC2=0x0f13 +OP_SendSpellChecksum=0x0000 +OP_SendSkillCapsChecksum=0x0000 + +# Character Select Related: +OP_SendMaxCharacters=0x05a8 +OP_SendMembership=0x057b +OP_SendMembershipDetails=0x6a98 +OP_CharacterCreateRequest=0x655c +OP_CharacterCreate=0x6bbf +OP_DeleteCharacter=0x1808 +OP_RandomNameGenerator=0x5954 +OP_ApproveName=0x56a2 +OP_MOTD=0x0c22 +OP_SetChatServer=0x1bc5 +OP_SetChatServer2=0x7db5 +OP_ZoneServerInfo=0x6ef5 +OP_WorldComplete=0x4493 +OP_WorldUnknown001=0x2958 +OP_FloatListThing=0x46c6 + +# Reasons for Disconnect: +OP_ZoneUnavail=0x4c44 +OP_WorldClientReady=0x23c1 +OP_CharacterStillInZone=0x0000 +OP_WorldChecksumFailure=0x0000 +OP_WorldLoginFailed=0x0000 +OP_WorldLogout=0x0000 +OP_WorldLevelTooHigh=0x0000 +OP_CharInacessable=0x0000 +OP_UserCompInfo=0x0000 +OP_SendExeChecksum=0x0000 +OP_SendBaseDataChecksum=0x0000 + +# Zone in opcodes +OP_AckPacket=0x471d +OP_ZoneEntry=0x5089 +OP_ReqNewZone=0x7887 +OP_NewZone=0x1795 +OP_ZoneSpawns=0x5237 +OP_PlayerProfile=0x6506 +OP_TimeOfDay=0x5070 +OP_LevelUpdate=0x1eec +OP_Stamina=0x2a79 +OP_RequestClientZoneChange=0x3fcf +OP_ZoneChange=0x2d18 +OP_LockoutTimerInfo=0x0000 +OP_ZoneServerReady=0x0000 +OP_ZoneInUnknown=0x0000 +OP_LogoutReply=0x0000 +OP_PreLogoutReply=0x0000 + +# Required to fully log in +OP_SpawnAppearance=0x0971 +OP_ChangeSize=0x4707 +OP_TributeUpdate=0x5961 +OP_TributeTimer=0x073d +OP_SendTributes=0x729b +OP_SendGuildTributes=0x4d5e +OP_TributeInfo=0x4254 +OP_Weather=0x661e +OP_ReqClientSpawn=0x35fa +OP_SpawnDoor=0x7291 +OP_GroundSpawn=0x6fca +OP_SendZonepoints=0x69a4 +OP_BlockedBuffs=0x4d25 +OP_RemoveBlockedBuffs=0x3033 +OP_ClearBlockedBuffs=0x6b3d +OP_WorldObjectsSent=0x5ae2 +OP_SendExpZonein=0x5f8e +OP_SendAATable=0x66b5 +OP_RespondAA=0x7a27 +OP_UpdateAA=0x66f0 +OP_SendAAStats=0x43c8 +OP_AAExpUpdate=0x7e92 +OP_ExpUpdate=0x20ed +OP_HPUpdate=0x2828 +OP_ManaChange=0x1287 +OP_TGB=0x0000 +OP_SpecialMesg=0x0000 +OP_GuildMemberList=0x0e48 +OP_GuildMOTD=0x3e13 +OP_CharInventory=0x5ca6 +OP_WearChange=0x7994 +OP_ClientUpdate=0x7dfc +OP_ClientReady=0x345d # 0x422d +OP_SetServerFilter=0x444d + +# Guild Opcodes - Disabled until crashes are resolved in RoF +OP_GetGuildMOTD=0x36e0 # Was 0x35dc +OP_GetGuildMOTDReply=0x4f1f # Was 0x4586 +OP_GuildMemberUpdate=0x69b9 # Was 0x5643 +OP_GuildInvite=0x7099 +OP_GuildRemove=0x1444 +OP_GuildPeace=0x084e +OP_SetGuildMOTD=0x0b0b +OP_GuildList=0x0000 +OP_GuildWar=0x46ce +OP_GuildLeader=0x2f3e +OP_GuildDelete=0x3708 +OP_GuildInviteAccept=0x7053 +OP_GuildDemote=0x2d4e +OP_GuildPromote=0x0000 +OP_GuildPublicNote=0x5053 +OP_GuildManageBanker=0x748f # Was 0x0737 +OP_GuildBank=0x5134 # Was 0x10c3 +OP_SetGuildRank=0x0b9c +OP_GuildUpdateURLAndChannel=0x6084 +OP_GuildStatus=0x7326 +OP_GuildCreate=0x1dc8 # or maybe 0x086e +OP_GuildMemberLevelUpdate=0x0000 # Unused? +OP_ZoneGuildList=0x0000 # Unused? +OP_GetGuildsList=0x0000 # Unused? +OP_LFGuild=0x0000 +OP_GuildManageRemove=0x0000 +OP_GuildManageAdd=0x0000 +OP_GuildManageStatus=0x0000 + +# GM/Guide Opcodes +OP_GMServers=0x08c1 +OP_GMBecomeNPC=0x3ae1 +OP_GMZoneRequest=0x62ac +OP_GMZoneRequest2=0x7e1a +OP_GMGoto=0x7d8e +OP_GMSearchCorpse=0x46b1 +OP_GMHideMe=0x79c5 +OP_GMDelCorpse=0x607e +OP_GMApproval=0x6db5 +OP_GMToggle=0x2097 +OP_GMSummon=0x486f # Was 0x684f +OP_GMEmoteZone=0x1cfd # Was 0x0655 +OP_GMEmoteWorld=0x458e # Was 0x1935 +OP_GMFind=0x4a8f +OP_GMKick=0x26a7 +OP_GMKill=0x51d3 +OP_GMNameChange=0x035f # Was 0x4434 +OP_GMLastName=0x16ce # Was 0x3077 + +# Misc Opcodes +OP_InspectRequest=0x57bc +OP_InspectAnswer=0x71ac +OP_InspectMessageUpdate=0x6f8b +OP_BeginCast=0x318f +OP_ColoredText=0x0000 +OP_ConsentResponse=0x384a +OP_MemorizeSpell=0x6a0d +OP_SwapSpell=0x0efa +OP_CastSpell=0x4466 +OP_Consider=0x742b +OP_FormattedMessage=0x1024 +OP_SimpleMessage=0x213f +OP_Buff=0x3a54 +OP_Illusion=0x312a +OP_MoneyOnCorpse=0x5f44 +OP_RandomReply=0x106b +OP_DenyResponse=0x2382 +OP_SkillUpdate=0x2264 +OP_GMTrainSkillConfirm=0x19aa # 0x3960 +OP_RandomReq=0x7b10 +OP_Death=0x6517 +OP_GMTraining=0x1966 +OP_GMEndTraining=0x4d6b +OP_GMTrainSkill=0x2a85 +OP_Animation=0x7177 +OP_Begging=0x6703 +OP_Consent=0x1fd1 +OP_ConsentDeny=0x7a45 +OP_AutoFire=0x241e +OP_PetCommands=0x0159 +OP_DeleteSpell=0x52e5 +OP_Surname=0x0423 +OP_ClearSurname=0x7d23 +OP_FaceChange=0x5578 +OP_SenseHeading=0x217c +OP_Action=0x744c +OP_ConsiderCorpse=0x5204 +OP_HideCorpse=0x67fc +OP_CorpseDrag=0x7eec +OP_CorpseDrop=0x0904 +OP_Bug=0x73f4 +OP_Feedback=0x5602 +OP_Report=0x1414 +OP_Damage=0x6f15 +OP_ChannelMessage=0x2b2d +OP_Assist=0x4478 +OP_AssistGroup=0x27f8 +OP_MoveCoin=0x0bcf +OP_ZonePlayerToBind=0x0ecb +OP_KeyRing=0x6857 +OP_WhoAllRequest=0x65ab +OP_WhoAllResponse=0x407a +OP_FriendsWho=0x3956 +OP_ConfirmDelete=0x43a3 +OP_Logout=0x4ac6 +OP_Rewind=0x1745 +OP_TargetCommand=0x58e2 +OP_Hide=0x5d55 +OP_Jump=0x2060 +OP_Camp=0x28ec +OP_Emote=0x373b +OP_SetRunMode=0x009f +OP_BankerChange=0x383c +OP_TargetMouse=0x075d +OP_MobHealth=0x2dd3 +OP_InitialMobHealth=0x0000 # Unused? +OP_TargetHoTT=0x486c +OP_XTargetResponse=0x4d59 +OP_XTargetRequest=0x3763 +OP_XTargetAutoAddHaters=0x672f +OP_TargetBuffs=0x4f4b +OP_BuffCreate=0x3377 +OP_BuffRemoveRequest=0x49bc +OP_DeleteSpawn=0x7280 +OP_AutoAttack=0x109d +OP_AutoAttack2=0x3526 +OP_Consume=0x4b70 +OP_MoveItem=0x32ee +OP_DeleteItem=0x18ad +OP_DeleteCharge=0x01b8 +OP_ItemPacket=0x368e +OP_ItemLinkResponse=0x70c0 +OP_ItemLinkClick=0x4cef +OP_ItemPreview=0x7f80 +OP_NewSpawn=0x0b04 +OP_Track=0x17e5 +OP_TrackTarget=0x0029 +OP_TrackUnknown=0x0f83 +OP_ClickDoor=0x3a8f +OP_MoveDoor=0x08e8 +OP_RemoveAllDoors=0x700c +OP_EnvDamage=0x51fd +OP_BoardBoat=0x31e6 +OP_Forage=0x5306 +OP_LeaveBoat=0x4211 +OP_ControlBoat=0x0ae7 +OP_SafeFallSuccess=0x6dbc +OP_RezzComplete=0x760d +OP_RezzRequest=0x3c21 +OP_RezzAnswer=0x701c +OP_Shielding=0x48c1 +OP_RequestDuel=0x3af1 +OP_MobRename=0x2c57 +OP_AugmentItem=0x661b # Was 0x37cb +OP_WeaponEquip1=0x34a7 +OP_WeaponEquip2=0x559a # Was 0x6022 +OP_WeaponUnequip2=0x2d25 # Was 0x0110 +OP_ApplyPoison=0x1b0c +OP_Save=0x4a39 +OP_TestBuff=0x7cb8 # Was 0x3772 +OP_CustomTitles=0x100e +OP_Split=0x0522 +OP_YellForHelp=0x4e56 +OP_LoadSpellSet=0x261d +OP_Bandolier=0x7677 +OP_PotionBelt=0x1a3e # Was 0x4d3b +OP_DuelResponse=0x6a46 +OP_DuelResponse2=0x68d3 +OP_SaveOnZoneReq=0x2c7a +OP_ReadBook=0x72df +OP_Dye=0x23b9 +OP_InterruptCast=0x048c +OP_AAAction=0x424e +OP_LeadershipExpToggle=0x74bd +OP_LeadershipExpUpdate=0x4ee2 +OP_PurchaseLeadershipAA=0x6c55 +OP_UpdateLeadershipAA=0x0026 +OP_MarkNPC=0x5a58 +OP_MarkRaidNPC=0x0000 #unimplemented +OP_ClearNPCMarks=0x0272 +OP_ClearRaidNPCMarks=0x0000 #unimplemented +OP_DelegateAbility=0x4c9d +OP_SetGroupTarget=0x026 +OP_Charm=0x5d92 +OP_Stun=0x36a4 +OP_SendFindableNPCs=0x587e +OP_FindPersonRequest=0x5cea +OP_FindPersonReply=0x7e58 +OP_Sound=0x1a30 +OP_PetBuffWindow=0x5882 +OP_LevelAppearance=0x3bc9 +OP_Translocate=0x6580 +OP_Sacrifice=0x1821 +OP_PopupResponse=0x214a +OP_OnLevelMessage=0x4fd0 +OP_AugmentInfo=0x0afb +OP_Petition=0x4101 +OP_SomeItemPacketMaybe=0x747c +OP_PVPStats=0x6f4b # Unsure +OP_PVPLeaderBoardRequest=0x3707 +OP_PVPLeaderBoardReply=0x25b7 +OP_PVPLeaderBoardDetailsRequest=0x15a9 +OP_PVPLeaderBoardDetailsReply=0x04aa +OP_RestState=0x000f +OP_RespawnWindow=0x28bc +OP_LDoNButton=0x5327 +OP_SetStartCity=0x6326 # Was 0x2d1b +OP_VoiceMacroIn=0x17fd +OP_VoiceMacroOut=0x409a +OP_ItemViewUnknown=0x465b +OP_VetRewardsAvaliable=0x6773 +OP_VetClaimRequest=0x1126 +OP_VetClaimReply=0x16d4 +OP_DisciplineUpdate=0x759e # Was 0x2f05 +OP_DisciplineTimer=0x6989 # Was 0x5e3f +OP_BecomeCorpse=0x0000 # Unused? +OP_Action2=0x0000 # Unused? +OP_MobUpdate=0x2c84 +OP_NPCMoveUpdate=0x5892 +OP_CameraEffect=0x127f +OP_SpellEffect=0x5936 +OP_RemoveNimbusEffect=0xc693 +OP_AltCurrency=0x3ee6 +OP_AltCurrencyMerchantRequest=0x05f0 +OP_AltCurrencyMerchantReply=0x0165 +OP_AltCurrencyPurchase=0x6b6d +OP_AltCurrencySell=0x61cb +OP_AltCurrencySellSelection=0x74ec +OP_AltCurrencyReclaim=0x27a2 +OP_CrystalCountUpdate=0x467f # Was 0x3f60 +OP_CrystalCreate=0x7aee # Was 0x5a82 +OP_CrystalReclaim=0x2439 # Was 0x7616 +OP_Untargetable=0x1456 +OP_IncreaseStats=0x70a3 +OP_Weblink=0x18d3 +#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U +OP_OpenContainer=0x0000 +OP_Marquee=0x0000 + +OP_DzQuit=0xb2e3 +OP_DzListTimers=0x7b68 +OP_DzAddPlayer=0x4701 +OP_DzRemovePlayer=0x1abc +OP_DzSwapPlayer=0x405b +OP_DzMakeLeader=0x543d +OP_DzPlayerList=0x14c6 +OP_DzJoinExpeditionConfirm=0x7f4b +OP_DzJoinExpeditionReply=0x1950 +OP_DzExpeditionInfo=0x9119 +OP_DzExpeditionList=0x205f +OP_DzMemberStatus=0x32f0 +OP_DzLeaderStatus=0x3de9 +OP_DzExpeditionEndsWarning=0x5189 +OP_DzMemberList=0x0000 +OP_DzCompass=0x3e0e # Was 0x4f09 +OP_DzChooseZone=0x0000 # Maybe 0x29d6 + +# New Opcodes +OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? +OP_ManaUpdate=0x3791 +OP_EnduranceUpdate=0x5f42 +OP_MobManaUpdate=0x2925 +OP_MobEnduranceUpdate=0x7314 + +# Mercenary Opcodes +OP_MercenaryDataUpdateRequest=0x2bcb +OP_MercenaryDataUpdate=0x7b89 +OP_MercenaryDataRequest=0x61a4 +OP_MercenaryDataResponse=0x11c1 +OP_MercenaryHire=0x72ce +OP_MercenaryDismiss=0x7169 +OP_MercenaryTimerRequest=0x6e83 +OP_MercenaryTimer=0x31e4 +OP_MercenaryUnknown1=0x20b9 +OP_MercenaryCommand=0x1b37 +OP_MercenarySuspendRequest=0x6e9f +OP_MercenarySuspendResponse=0x4407 +OP_MercenaryUnsuspendResponse=0x6f03 + +# Looting +OP_LootRequest=0x0adf +OP_EndLootRequest=0x30f7 +OP_LootItem=0x4dc9 +OP_LootComplete=0x55c4 + +# bazaar trader stuff: +OP_BazaarSearch=0x39d6 +OP_TraderDelItem=0x0000 +OP_BecomeTrader=0x61b3 +OP_TraderShop=0x5eca +OP_Trader=0x4ef5 # Was 0x6790 +OP_TraderBuy=0x0000 +OP_Barter=0x243a +OP_ShopItem=0x0000 +OP_BazaarInspect=0x0000 +OP_Bazaar=0x0000 +OP_TraderItemUpdate=0x0000 + +# pc/npc trading +OP_TradeRequest=0x77b5 +OP_TradeAcceptClick=0x69e2 +OP_TradeRequestAck=0x14bf +OP_TradeCoins=0x4206 +OP_FinishTrade=0x3993 +OP_CancelTrade=0x354c +OP_TradeMoneyUpdate=0x68c2 +OP_MoneyUpdate=0x640c +OP_TradeBusy=0x5505 + +# Sent after canceling trade or after closing tradeskill object +OP_FinishWindow=0x7349 +OP_FinishWindow2=0x40ef + +# Sent on Live for what seems to be item existance verification +# Ex. Before Right Click Effect happens from items +OP_ItemVerifyRequest=0x189c +OP_ItemVerifyReply=0x097b + +# merchant stuff +OP_ShopPlayerSell=0x3de3 +OP_ShopRequest=0x4fed +OP_ShopEnd=0x30a8 +OP_ShopEndConfirm=0x3196 +OP_ShopPlayerBuy=0x004c +OP_ShopDelItem=0x724f + +# tradeskill stuff: +OP_ClickObject=0x4aa1 +OP_ClickObjectAction=0x0c1e +OP_ClearObject=0x7a11 +OP_RecipeDetails=0x6e02 +OP_RecipesFavorite=0x5c74 +OP_RecipesSearch=0x6290 +OP_RecipeReply=0x1db6 +OP_RecipeAutoCombine=0x40d7 +OP_TradeSkillCombine=0x579a + +# Tribute Packets: +OP_OpenGuildTributeMaster=0x49ea +OP_OpenTributeMaster=0x7666 # Was 0x40f5 +OP_SelectTribute=0x79fc +OP_TributeItem=0x4f3e +OP_TributeMoney=0x58fb # Was 0x6fed +OP_TributeToggle=0x4e32 +OP_TributePointUpdate=0x5300 +OP_TributeNPC=0x0000 +OP_GuildTributeInfo=0x0000 +OP_OpenTributeReply=0x0000 +OP_GuildTributeStatus=0x0000 + +# Adventure packets: +OP_LeaveAdventure=0x5d18 +OP_AdventureFinish=0x400f +OP_AdventureInfoRequest=0x3cb0 +OP_AdventureInfo=0x4c54 +OP_AdventureRequest=0x2c6c +OP_AdventureDetails=0x5648 +OP_AdventureData=0x7171 +OP_AdventureUpdate=0x1b01 +OP_AdventureMerchantRequest=0x6922 # Was 654d +OP_AdventureMerchantResponse=0x3e47 # Was 7949 +OP_AdventureMerchantPurchase=0x5b72 # Was 155a +OP_AdventureMerchantSell=0x2f9b # Was 389c +OP_AdventurePointsUpdate=0x65c3 # Was 7589 +OP_AdventureStatsRequest=0x5a62 +OP_AdventureStatsReply=0x2370 +OP_AdventureLeaderboardRequest=0x7093 +OP_AdventureLeaderboardReply=0x7f79 + +# Group Opcodes +OP_GroupDisband=0x4c10 +OP_GroupInvite=0x1649 +OP_GroupFollow=0x05ce +OP_GroupUpdate=0x4ced +OP_GroupUpdateB=0x0cbc +OP_GroupCancelInvite=0x0000 +OP_GroupAcknowledge=0x04d0 +OP_GroupDelete=0x3abb +OP_CancelInvite=0x32c2 +OP_GroupFollow2=0x2a50 +OP_GroupInvite2=0x6c65 +OP_GroupDisbandYou=0x7323 +OP_GroupDisbandOther=0x88a1 +OP_GroupLeaderChange=0x74da +OP_GroupRoles=0x4d9f +OP_GroupMakeLeader=0x4229 +OP_DoGroupLeadershipAbility=0x6eae +OP_GroupLeadershipAAUpdate=0x6298 +OP_GroupMentor=0x3342 +OP_InspectBuffs=0x0000 + +# LFG/LFP Opcodes +OP_LFGCommand=0x6060 +OP_LFGGetMatchesRequest=0x0340 +OP_LFGGetMatchesResponse=0x5048 +OP_LFPGetMatchesRequest=0x4d7d +OP_LFPGetMatchesResponse=0x22c6 +OP_LFPCommand=0x49a9 +OP_LFGAppearance=0x0000 +OP_LFGResponse=0x0000 + +# Raid Opcodes +OP_RaidInvite=0x3973 +OP_RaidUpdate=0x56fe +OP_RaidJoin=0x0000 + +# Button-push commands +OP_Taunt=0x2703 +OP_CombatAbility=0x3eba +OP_SenseTraps=0x02af # Was 0x2ee0 +OP_PickPocket=0x39e8 +OP_DisarmTraps=0x0000 +OP_Disarm=0x5ec8 +OP_Sneak=0x4577 +OP_Fishing=0x1e2a +OP_InstillDoubt=0x640e +OP_FeignDeath=0x52fa +OP_Mend=0x0ecf +OP_Bind_Wound=0x0386 +OP_LDoNOpen=0x3d5c + +# Task packets +OP_TaskDescription=0x0083 +OP_TaskActivity=0x083 +OP_CompletedTasks=0x4eba +OP_TaskActivityComplete=0x7037 +OP_AcceptNewTask=0x0a23 +OP_CancelTask=0x3714 +OP_TaskMemberList=0x5727 # Was 0x1656 +OP_OpenNewTasksWindow=0x48a2 # Was 0x11de +OP_AvaliableTask=0x36e8 # Was 0x2377 +OP_TaskHistoryRequest=0x5f1c +OP_TaskHistoryReply=0x3d05 +OP_DeclineAllTasks=0x0000 + +# Title opcodes +OP_NewTitlesAvailable=0x0d32 +OP_RequestTitles=0x6344 +OP_SendTitleList=0x2d08 +OP_SetTitle=0x6527 +OP_SetTitleReply=0x4c21 + +# mail opcodes +OP_Command=0x0000 +OP_MailboxHeader=0x0000 +OP_MailHeader=0x0000 +OP_MailBody=0x0000 +OP_NewMail=0x0000 +OP_SentConfirm=0x0000 + +########### Below this point should not be needed ########### + +# This section are all unknown in Titanium +OP_ForceFindPerson=0x0000 +OP_LocInfo=0x0000 +OP_ReloadUI=0x0000 +OP_ItemName=0x0000 +OP_ItemLinkText=0x0000 +OP_MultiLineMsg=0x0000 +OP_MendHPUpdate=0x0000 +OP_TargetReject=0x0000 +OP_SafePoint=0x0000 +OP_ApproveZone=0x0000 +OP_ZoneComplete=0x0000 +OP_ClientError=0x0000 +OP_DumpName=0x0000 +OP_Heartbeat=0x0000 +OP_CrashDump=0x0000 +OP_LoginComplete=0x0000 + +# discovered opcodes not yet used: +OP_PickLockSuccess=0x0000 +OP_PlayMP3=0x0000 +OP_ReclaimCrystals=0x0000 +OP_DynamicWall=0x0000 +OP_OpenDiscordMerchant=0x0000 +OP_DiscordMerchantInventory=0x0000 +OP_GiveMoney=0x0000 +OP_RequestKnowledgeBase=0x0000 +OP_KnowledgeBase=0x0000 +OP_SlashAdventure=0x0000 # /adventure +OP_BecomePVPPrompt=0x0000 +OP_MoveLogRequest=0x0000 # gone I think +OP_MoveLogDisregard=0x0000 # gone I think + +# named unknowns, to make looking for real unknown easier +OP_AnnoyingZoneUnknown=0x0000 +OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members +OP_QueryResponseThing=0x0000 + + +# realityincarnate: these are just here to stop annoying several thousand byte packet dumps +#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum +#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum + +# Petition Opcodes +OP_PetitionSearch=0x0000 search term for petition +OP_PetitionSearchResults=0x0000 (list of?) matches from search +OP_PetitionSearchText=0x0000 text results of search + +OP_PetitionUpdate=0x0000 +OP_PetitionCheckout=0x0000 +OP_PetitionCheckIn=0x0000 +OP_PetitionQue=0x0000 +OP_PetitionUnCheckout=0x0000 +OP_PetitionDelete=0x0000 +OP_DeletePetition=0x0000 +OP_PetitionResolve=0x0000 +OP_PDeletePetition=0x0000 +OP_PetitionBug=0x0000 +OP_PetitionRefresh=0x0000 +OP_PetitionCheckout2=0x0000 +OP_PetitionViewPetition=0x0000 + +# Login opcodes +OP_SessionReady=0x0000 +OP_Login=0x0000 +OP_ServerListRequest=0x0000 +OP_PlayEverquestRequest=0x0000 +OP_PlayEverquestResponse=0x0000 +OP_ChatMessage=0x0000 +OP_LoginAccepted=0x0000 +OP_ServerListResponse=0x0000 +OP_Poll=0x0000 +OP_EnterChat=0x0000 +OP_PollResponse=0x0000 + +# raw opcodes +OP_RAWSessionRequest=0x0000 +OP_RAWSessionResponse=0x0000 +OP_RAWCombined=0x0000 +OP_RAWSessionDisconnect=0x0000 +OP_RAWKeepAlive=0x0000 +OP_RAWSessionStatRequest=0x0000 +OP_RAWSessionStatResponse=0x0000 +OP_RAWPacket=0x0000 +OP_RAWFragment=0x0000 +OP_RAWOutOfOrderAck=0x0000 +OP_RAWAck=0x0000 +OP_RAWAppCombined=0x0000 +OP_RAWOutOfSession=0x0000 + +# we need to document the differences between these packets to make identifying them easier +OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs +OP_InitialHPUpdate=0x0000 + +OP_ItemRecastDelay=0x08a6 From 36c945a77c29cf4c5d9ec71c9fa1edd14cddcaab Mon Sep 17 00:00:00 2001 From: Trevius Date: Thu, 4 Dec 2014 23:06:43 -0600 Subject: [PATCH 85/96] Updated a large number of RoF2 opcodes. --- common/eq_dictionary.cpp | 66 ++++++------ utils/patches/patch_RoF2.conf | 130 ++++++++++++------------ utils/scripts/opcode_scripts/.gitignore | 3 + 3 files changed, 101 insertions(+), 98 deletions(-) create mode 100644 utils/scripts/opcode_scripts/.gitignore diff --git a/common/eq_dictionary.cpp b/common/eq_dictionary.cpp index f85d3110f..3756ca8fe 100644 --- a/common/eq_dictionary.cpp +++ b/common/eq_dictionary.cpp @@ -539,7 +539,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*Underfoot*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*RoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*NPC*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*Merc*/ EmuConstants::MAP_POSSESSIONS_SIZE, @@ -554,7 +554,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_BANK_SIZE, /*Underfoot*/ EmuConstants::MAP_BANK_SIZE, /*RoF*/ EmuConstants::MAP_BANK_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -569,7 +569,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*Underfoot*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*RoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -584,7 +584,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_TRADE_SIZE, /*Underfoot*/ EmuConstants::MAP_TRADE_SIZE, /*RoF*/ EmuConstants::MAP_TRADE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_TRADE_SIZE, /*NPC*/ 4, /*Merc*/ 4, @@ -599,7 +599,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_WORLD_SIZE, /*Underfoot*/ EmuConstants::MAP_WORLD_SIZE, /*RoF*/ EmuConstants::MAP_WORLD_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_WORLD_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -614,7 +614,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_LIMBO_SIZE, /*Underfoot*/ EmuConstants::MAP_LIMBO_SIZE, /*RoF*/ EmuConstants::MAP_LIMBO_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_LIMBO_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -629,7 +629,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_TRIBUTE_SIZE, /*Underfoot*/ EmuConstants::MAP_TRIBUTE_SIZE, /*RoF*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -644,7 +644,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -659,7 +659,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -674,7 +674,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_MERCHANT_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_MERCHANT_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -689,7 +689,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_DELETED_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_DELETED_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -704,7 +704,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ SoD::consts::MAP_CORPSE_SIZE, /*Underfoot*/ Underfoot::consts::MAP_CORPSE_SIZE, /*RoF*/ RoF::consts::MAP_CORPSE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ RoF2::consts::MAP_CORPSE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -719,7 +719,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_BAZAAR_SIZE, /*Underfoot*/ EmuConstants::MAP_BAZAAR_SIZE, /*RoF*/ EmuConstants::MAP_BAZAAR_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_BAZAAR_SIZE, /*NPC*/ 0, // this may need to be 'EmuConstants::MAP_BAZAAR_SIZE' if offline client traders respawn as an npc /*Merc*/ 0, @@ -734,7 +734,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ SoD::consts::MAP_INSPECT_SIZE, /*Underfoot*/ Underfoot::consts::MAP_INSPECT_SIZE, /*RoF*/ RoF::consts::MAP_INSPECT_SIZE, -/*RoF2*/ 0, +/*RoF2*/ RoF2::consts::MAP_INSPECT_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -749,7 +749,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_REAL_ESTATE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_REAL_ESTATE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -764,7 +764,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -779,7 +779,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -794,7 +794,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -809,7 +809,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -824,7 +824,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_ALT_STORAGE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_ALT_STORAGE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -839,7 +839,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_ARCHIVED_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_ARCHIVED_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -854,7 +854,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_MAIL_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_MAIL_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -869,7 +869,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -884,7 +884,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ NOT_USED, /*Underfoot*/ NOT_USED, /*RoF*/ EmuConstants::MAP_KRONO_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_KRONO_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -899,7 +899,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_OTHER_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_OTHER_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -1012,7 +1012,7 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) { /*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*Underfoot*/ Underfoot::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*RoF2*/ false, +/*RoF2*/ RoF2::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*NPC*/ false, /*Merc*/ false, @@ -1033,7 +1033,7 @@ bool EQLimits::AllowsClickCastFromBag(uint32 version) { /*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG, /*Underfoot*/ Underfoot::limits::ALLOWS_CLICK_CAST_FROM_BAG, /*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*RoF2*/ false, +/*RoF2*/ RoF2::limits::ALLOWS_CLICK_CAST_FROM_BAG, /*NPC*/ false, /*Merc*/ false, @@ -1054,7 +1054,7 @@ uint16 EQLimits::ItemCommonSize(uint32 version) { /*SoD*/ EmuConstants::ITEM_COMMON_SIZE, /*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE, /*RoF*/ EmuConstants::ITEM_COMMON_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::ITEM_COMMON_SIZE, /*NPC*/ EmuConstants::ITEM_COMMON_SIZE, /*Merc*/ EmuConstants::ITEM_COMMON_SIZE, @@ -1074,7 +1074,7 @@ uint16 EQLimits::ItemContainerSize(uint32 version) { /*SoD*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE, /*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::ITEM_CONTAINER_SIZE, /*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE, @@ -1094,7 +1094,7 @@ bool EQLimits::CoinHasWeight(uint32 version) { /*SoD*/ SoD::limits::COIN_HAS_WEIGHT, /*Underfoot*/ Underfoot::limits::COIN_HAS_WEIGHT, /*RoF*/ RoF::limits::COIN_HAS_WEIGHT, -/*RoF2*/ true, +/*RoF2*/ RoF::limits::COIN_HAS_WEIGHT, /*NPC*/ true, /*Merc*/ true, @@ -1114,7 +1114,7 @@ uint32 EQLimits::BandoliersCount(uint32 version) { /*SoD*/ EmuConstants::BANDOLIERS_COUNT, /*Underfoot*/ EmuConstants::BANDOLIERS_COUNT, /*RoF*/ EmuConstants::BANDOLIERS_COUNT, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::BANDOLIERS_COUNT, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -1134,7 +1134,7 @@ uint32 EQLimits::BandolierSize(uint32 version) { /*SoD*/ EmuConstants::BANDOLIER_SIZE, /*Underfoot*/ EmuConstants::BANDOLIER_SIZE, /*RoF*/ EmuConstants::BANDOLIER_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::BANDOLIER_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -1154,7 +1154,7 @@ uint32 EQLimits::PotionBeltSize(uint32 version) { /*SoD*/ EmuConstants::POTION_BELT_SIZE, /*Underfoot*/ EmuConstants::POTION_BELT_SIZE, /*RoF*/ EmuConstants::POTION_BELT_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::POTION_BELT_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 589c47468..8c15c59c6 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -100,9 +100,9 @@ OP_SendAAStats=0x43c8 OP_AAExpUpdate=0x7d14 OP_ExpUpdate=0x20ed OP_HPUpdate=0x2828 -OP_ManaChange=0x43af +OP_ManaChange=0x5467 OP_TGB=0x0876 -OP_SpecialMesg=0x0083 +OP_SpecialMesg=0x083 OP_GuildMemberList=0x12a6 OP_GuildMOTD=0x3e13 OP_CharInventory=0x5ca6 @@ -119,7 +119,7 @@ OP_GuildInvite=0x7099 OP_GuildRemove=0x1444 OP_GuildPeace=0x67e3 OP_SetGuildMOTD=0x0b0b -OP_GuildList=0x507a +OP_GuildList=0x6279 OP_GuildWar=0x1ffb OP_GuildLeader=0x7e09 OP_GuildDelete=0x3708 @@ -132,7 +132,7 @@ OP_GuildBank=0x5134 OP_SetGuildRank=0x0b9c OP_GuildUpdateURLAndChannel=0x2958 OP_GuildStatus=0x7326 -OP_GuildCreate=0x1dc8 +OP_GuildCreate=0x76d9 OP_GuildMemberLevelUpdate=0x0000 # Unused? OP_ZoneGuildList=0x0000 # Unused? OP_GetGuildsList=0x0000 # Unused? @@ -166,7 +166,7 @@ OP_InspectRequest=0x57bc OP_InspectAnswer=0x71ac OP_InspectMessageUpdate=0x4d25 OP_BeginCast=0x318f -OP_ColoredText=0x0000 +OP_ColoredText=0x43af OP_ConsentResponse=0x384a OP_MemorizeSpell=0x217c OP_SwapSpell=0x0efa @@ -179,8 +179,8 @@ OP_Illusion=0x312a OP_MoneyOnCorpse=0x5f44 OP_RandomReply=0x106b OP_DenyResponse=0x2382 -OP_SkillUpdate=0x004c -OP_GMTrainSkillConfirm=0x66dd +OP_SkillUpdate=0x04c +OP_GMTrainSkillConfirm=0x4b64 OP_RandomReq=0x7b10 OP_Death=0x6517 OP_GMTraining=0x1966 @@ -194,7 +194,7 @@ OP_AutoFire=0x241e OP_PetCommands=0x0159 OP_DeleteSpell=0x52e5 OP_Surname=0x0423 -OP_ClearSurname=0x7d23 +OP_ClearSurname=0x3fb0 OP_FaceChange=0x5578 OP_SenseHeading=0x260a OP_Action=0x744c @@ -212,19 +212,19 @@ OP_AssistGroup=0x27f8 OP_MoveCoin=0x0bcf OP_ZonePlayerToBind=0x0ecb OP_KeyRing=0x6857 -OP_WhoAllRequest=0x65ab -OP_WhoAllResponse=0x7c88 +OP_WhoAllRequest=0x674b +OP_WhoAllResponse=0x51b8 OP_FriendsWho=0x3956 OP_ConfirmDelete=0x43a3 OP_Logout=0x4ac6 OP_Rewind=0x1745 OP_TargetCommand=0x58e2 OP_Hide=0x67fe -OP_Jump=0x2060 +OP_Jump=0x31f4 OP_Camp=0x28ec OP_Emote=0x373b OP_SetRunMode=0x009f -OP_BankerChange=0x383c +OP_BankerChange=0x791e OP_TargetMouse=0x075d OP_MobHealth=0x37b1 OP_InitialMobHealth=0x0000 # Unused? @@ -243,7 +243,7 @@ OP_MoveItem=0x32ee OP_DeleteItem=0x18ad OP_DeleteCharge=0x01b8 OP_ItemPacket=0x368e -OP_ItemLinkResponse=0x633c +OP_ItemLinkResponse=0x70c0 OP_ItemLinkClick=0x4cef OP_ItemPreview=0x6b5c OP_NewSpawn=0x6097 @@ -297,7 +297,7 @@ OP_DelegateAbility=0x76b8 OP_SetGroupTarget=0x2814 OP_Charm=0x5d92 OP_Stun=0x36a4 -OP_SendFindableNPCs=0x3897 +OP_SendFindableNPCs=0x7e62 OP_FindPersonRequest=0x5cea OP_FindPersonReply=0x7e58 OP_Sound=0x1a30 @@ -305,23 +305,23 @@ OP_PetBuffWindow=0x5882 OP_LevelAppearance=0x3bc9 OP_Translocate=0x6580 OP_Sacrifice=0x1821 -OP_PopupResponse=0x214a -OP_OnLevelMessage=0x4fd0 +OP_PopupResponse=0x08a6 +OP_OnLevelMessage=0x4d6e OP_AugmentInfo=0x0afb -OP_Petition=0x5f03 +OP_Petition=0x3de3 OP_SomeItemPacketMaybe=0x747c -OP_PVPStats=0x6f4b -OP_PVPLeaderBoardRequest=0x3707 -OP_PVPLeaderBoardReply=0x25b7 -OP_PVPLeaderBoardDetailsRequest=0x15a9 -OP_PVPLeaderBoardDetailsReply=0x04aa -OP_RestState=0x00f +OP_PVPStats=0x4b15 +OP_PVPLeaderBoardRequest=0x04aa +OP_PVPLeaderBoardReply=0x071f +OP_PVPLeaderBoardDetailsRequest=0x3707 +OP_PVPLeaderBoardDetailsReply=0x25b7 +OP_RestState=0x000f OP_RespawnWindow=0x28bc OP_LDoNButton=0x5327 OP_SetStartCity=0x6326 OP_VoiceMacroIn=0x17fd OP_VoiceMacroOut=0x409a -OP_ItemViewUnknown=0x2289 +OP_ItemViewUnknown=0x465b OP_VetRewardsAvaliable=0x590e OP_VetClaimRequest=0x1126 OP_VetClaimReply=0x16d4 @@ -330,43 +330,43 @@ OP_DisciplineTimer=0x6989 OP_BecomeCorpse=0x0000 # Unused? OP_Action2=0x0000 # Unused? OP_MobUpdate=0x2c84 -OP_NPCMoveUpdate=0x189c +OP_NPCMoveUpdate=0x5892 OP_CameraEffect=0x127f OP_SpellEffect=0x5936 -OP_RemoveNimbusEffect=0xc693 -OP_AltCurrency=0x7121 -OP_AltCurrencyMerchantRequest=0x6b6d -OP_AltCurrencyMerchantReply=0x74ec -OP_AltCurrencyPurchase=0x61cb -OP_AltCurrencySell=0x0165 -OP_AltCurrencySellSelection=0x5409 -OP_AltCurrencyReclaim=0x532a +OP_RemoveNimbusEffect=0x7b1e +OP_AltCurrency=0x62ab +OP_AltCurrencyMerchantRequest=0x61cb +OP_AltCurrencyMerchantReply=0x5409 +OP_AltCurrencyPurchase=0x0165 +OP_AltCurrencySell=0x74ec +OP_AltCurrencySellSelection=0x3788 +OP_AltCurrencyReclaim=0x3899 OP_CrystalCountUpdate=0x467f OP_CrystalCreate=0x7aee OP_CrystalReclaim=0x2439 OP_Untargetable=0x053c OP_IncreaseStats=0x70a3 -OP_Weblink=0x18d3 +OP_Weblink=0x6f4b OP_OpenContainer=0x0000 OP_Marquee=0x0000 -OP_ItemRecastDelay=0x08a6 +OP_ItemRecastDelay=0x15a9 #OP_OpenInventory=0x0000 # Likely does not exist in RoF -U -OP_DzQuit=0xb2e3 -OP_DzListTimers=0x7b68 -OP_DzAddPlayer=0x4701 -OP_DzRemovePlayer=0x1abc -OP_DzSwapPlayer=0x405b -OP_DzMakeLeader=0x543d -OP_DzPlayerList=0x14c6 -OP_DzJoinExpeditionConfirm=0x7f4b -OP_DzJoinExpeditionReply=0x1950 -OP_DzExpeditionInfo=0x9119 -OP_DzExpeditionList=0x205f -OP_DzMemberStatus=0x32f0 -OP_DzLeaderStatus=0x3de9 -OP_DzExpeditionEndsWarning=0x5189 -OP_DzMemberList=0x5ae4 +OP_DzQuit=0x205f +OP_DzListTimers=0x0398 +OP_DzAddPlayer=0x59ca +OP_DzRemovePlayer=0x4701 +OP_DzSwapPlayer=0x1abc +OP_DzMakeLeader=0x405b +OP_DzPlayerList=0x543d +OP_DzJoinExpeditionConfirm=0x14c6 +OP_DzJoinExpeditionReply=0x7f4b +OP_DzExpeditionInfo=0x4f7e +OP_DzExpeditionList=0x9119 +OP_DzMemberStatus=0xb2e3 +OP_DzLeaderStatus=0x32f0 +OP_DzExpeditionEndsWarning=0x7e94 +OP_DzMemberList=0x3de9 OP_DzCompass=0x3e0e OP_DzChooseZone=0x0000 @@ -428,15 +428,15 @@ OP_FinishWindow2=0x40ef # Sent on Live for what seems to be item existance verification # Ex. Before Right Click Effect happens from items -OP_ItemVerifyRequest=0x097b -OP_ItemVerifyReply=0x2115 +OP_ItemVerifyRequest=0x189c +OP_ItemVerifyReply=0x097b # merchant stuff -OP_ShopPlayerSell=0x1901 +OP_ShopPlayerSell=0x0000 OP_ShopRequest=0x4fed OP_ShopEnd=0x30a8 OP_ShopEndConfirm=0x3196 -OP_ShopPlayerBuy=0x04c +OP_ShopPlayerBuy=0x0ddd OP_ShopDelItem=0x724f # tradeskill stuff: @@ -444,7 +444,7 @@ OP_ClickObject=0x4aa1 OP_ClickObjectAction=0x0c1e OP_ClearObject=0x7a11 OP_RecipeDetails=0x40d7 -OP_RecipesFavorite=0x5c74 +OP_RecipesFavorite=0x71b1 OP_RecipesSearch=0x1db6 OP_RecipeReply=0x6e02 OP_RecipeAutoCombine=0x6261 @@ -484,16 +484,16 @@ OP_AdventureLeaderboardReply=0x7f79 # Group Opcodes OP_GroupDisband=0x4c10 -OP_GroupInvite=0x1649 -OP_GroupFollow=0x05ce +OP_GroupInvite=0x6110 +OP_GroupFollow=0x1649 OP_GroupUpdate=0x3abb OP_GroupUpdateB=0x6194 OP_GroupCancelInvite=0x0000 OP_GroupAcknowledge=0x7323 OP_GroupDelete=0x0f6c -OP_CancelInvite=0x32c2 -OP_GroupFollow2=0x2a50 -OP_GroupInvite2=0x6c65 +OP_CancelInvite=0x2a50 +OP_GroupFollow2=0x2060 +OP_GroupInvite2=0x32c2 OP_GroupDisbandYou=0x1ae5 OP_GroupDisbandOther=0x74da OP_GroupLeaderChange=0x21b4 @@ -501,7 +501,7 @@ OP_GroupRoles=0x70e2 OP_GroupMakeLeader=0x4229 OP_DoGroupLeadershipAbility=0x1fb5 OP_GroupLeadershipAAUpdate=0x02cf -OP_GroupMentor=0x5892 +OP_GroupMentor=0x3342 OP_InspectBuffs=0x486c # LFG/LFP Opcodes @@ -535,12 +535,12 @@ OP_Bind_Wound=0x0386 OP_LDoNOpen=0x3d5c # Task packets -OP_TaskDescription=0x083 -OP_TaskActivity=0x3714 +OP_TaskDescription=0x3714 +OP_TaskActivity=0x08d3 OP_CompletedTasks=0x4eba OP_TaskActivityComplete=0x5e19 OP_AcceptNewTask=0x0a23 -OP_CancelTask=0x08d3 +OP_CancelTask=0x39f0 OP_TaskMemberList=0x5727 OP_OpenNewTasksWindow=0x48a2 OP_AvaliableTask=0x36e8 @@ -657,4 +657,4 @@ OP_RAWOutOfSession=0x0000 # we need to document the differences between these packets to make identifying them easier OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs -OP_InitialHPUpdate=0x0000 \ No newline at end of file +OP_InitialHPUpdate=0x0000 diff --git a/utils/scripts/opcode_scripts/.gitignore b/utils/scripts/opcode_scripts/.gitignore new file mode 100644 index 000000000..4104a1572 --- /dev/null +++ b/utils/scripts/opcode_scripts/.gitignore @@ -0,0 +1,3 @@ +# Input and Output txt and conf files. +*.txt +*.conf From 48be7c508db94da6aa4d8b0081a8ead7c4878e8e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 02:48:54 -0500 Subject: [PATCH 86/96] OP_PlayMP3 for SoF --- utils/patches/patch_SoF.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index fc0c716e1..17765b77f 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -544,7 +544,7 @@ OP_PickLockSuccess=0x0000 # OP_VetRewardsAvaliable=0x044b # OP_VetClaimRequest=0x7503 OP_VetClaimReply=0x01e1 -OP_PlayMP3=0x0000 # +OP_PlayMP3=0x0d1c # OP_ReclaimCrystals=0x0000 # OP_CrystalCountUpdate=0x64C1 # OP_DynamicWall=0x0000 # From 921433f998ed924c25713d127e4768fcb72c7174 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 5 Dec 2014 03:47:41 -0500 Subject: [PATCH 87/96] Range attack clean up, prevent possible nullptr checks. --- zone/special_attacks.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index e3721a6a0..928353149 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -676,7 +676,8 @@ void Mob::RogueAssassinate(Mob* other) void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //conditions to use an attack checked before we are called - + if (!other) + return; //make sure the attack and ranged timers are up //if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow if(!CanDoubleAttack && ((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check()))) { @@ -716,7 +717,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { return; } - mlog(COMBAT__RANGED, "Shooting %s with bow %s (%d) and arrow %s (%d)", GetTarget()->GetName(), RangeItem->Name, RangeItem->ID, AmmoItem->Name, AmmoItem->ID); + mlog(COMBAT__RANGED, "Shooting %s with bow %s (%d) and arrow %s (%d)", other->GetName(), RangeItem->Name, RangeItem->ID, AmmoItem->Name, AmmoItem->ID); //look for ammo in inventory if we only have 1 left... if(Ammo->GetCharges() == 1) { @@ -766,17 +767,18 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { float range = RangeItem->Range + AmmoItem->Range + GetRangeDistTargetSizeMod(GetTarget()); mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range); range *= range; - if(DistNoRoot(*GetTarget()) > range) { - mlog(COMBAT__RANGED, "Ranged attack out of range... client should catch this. (%f > %f).\n", DistNoRootNoZ(*GetTarget()), range); + float dist = DistNoRoot(*other); + if(dist > range) { + mlog(COMBAT__RANGED, "Ranged attack out of range... client should catch this. (%f > %f).\n", dist, range); Message_StringID(13,TARGET_OUT_OF_RANGE);//Client enforces range and sends the message, this is a backup just incase. return; } - else if(DistNoRoot(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ + else if(dist < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ Message_StringID(15,RANGED_TOO_CLOSE);//Client enforces range and sends the message, this is a backup just incase. return; } - if(!IsAttackAllowed(GetTarget()) || + if(!IsAttackAllowed(other) || IsCasting() || IsSitting() || (DivineAura() && !GetGM()) || @@ -788,7 +790,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { } //Shoots projectile and/or applies the archery damage - DoArcheryAttackDmg(GetTarget(), RangeWeapon, Ammo,0,0,0,0,0,0, AmmoItem, ammo_slot); + DoArcheryAttackDmg(other, RangeWeapon, Ammo,0,0,0,0,0,0, AmmoItem, ammo_slot); //EndlessQuiver AA base1 = 100% Chance to avoid consumption arrow. int ChanceAvoidConsume = aabonuses.ConsumeProjectile + itembonuses.ConsumeProjectile + spellbonuses.ConsumeProjectile; @@ -1322,7 +1324,8 @@ uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) { void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 //conditions to use an attack checked before we are called - + if (!other) + return; //make sure the attack and ranged timers are up //if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow if((!CanDoubleAttack && (attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check()))) { @@ -1348,7 +1351,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - mlog(COMBAT__RANGED, "Throwing %s (%d) at %s", item->Name, item->ID, GetTarget()->GetName()); + mlog(COMBAT__RANGED, "Throwing %s (%d) at %s", item->Name, item->ID, other->GetName()); if(RangeWeapon->GetCharges() == 1) { //first check ammo @@ -1370,19 +1373,20 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 } } - float range = item->Range + GetRangeDistTargetSizeMod(GetTarget()); + float range = item->Range + GetRangeDistTargetSizeMod(other); mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range); range *= range; - if(DistNoRoot(*GetTarget()) > range) { - mlog(COMBAT__RANGED, "Throwing attack out of range... client should catch this. (%f > %f).\n", DistNoRootNoZ(*GetTarget()), range); + float dist = DistNoRoot(*other); + if(dist > range) { + mlog(COMBAT__RANGED, "Throwing attack out of range... client should catch this. (%f > %f).\n", dist, range); Message_StringID(13,TARGET_OUT_OF_RANGE);//Client enforces range and sends the message, this is a backup just incase. return; } - else if(DistNoRoot(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ + else if(dist < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ Message_StringID(15,RANGED_TOO_CLOSE);//Client enforces range and sends the message, this is a backup just incase. } - if(!IsAttackAllowed(GetTarget()) || + if(!IsAttackAllowed(other) || IsCasting() || IsSitting() || (DivineAura() && !GetGM()) || @@ -1393,7 +1397,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - DoThrowingAttackDmg(GetTarget(), RangeWeapon, item); + DoThrowingAttackDmg(other, RangeWeapon, item); //consume ammo DeleteItemInInventory(ammo_slot, 1, true); From f6bddb9502747efbde62a3fef4944be8ec32e4ea Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 13:23:37 -0500 Subject: [PATCH 88/96] OP_IncreaseStats for SoF --- utils/patches/patch_SoD.conf | 1 - utils/patches/patch_SoF.conf | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index 338ee82e7..764d93a4d 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -580,7 +580,6 @@ OP_MultiLineMsg=0x0000 # OP_MendHPUpdate=0x0000 # OP_TargetReject=0x0000 # OP_SafePoint=0x0000 # -OP_IncreaseStats=0x0000 # OP_ApproveZone=0x0000 # OP_ZoneComplete=0x0000 # OP_ClientError=0x0000 # diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 17765b77f..1380540e5 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -530,7 +530,7 @@ OP_MultiLineMsg=0x0000 # OP_MendHPUpdate=0x0000 # OP_TargetReject=0x0000 # OP_SafePoint=0x0000 # -OP_IncreaseStats=0x0000 # +OP_IncreaseStats=0x5ecb # OP_ApproveZone=0x0000 # OP_ZoneComplete=0x0000 # OP_ClientError=0x0000 # From e65bf63e513282de88ea1c8d5f5941185628656c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 13:56:20 -0500 Subject: [PATCH 89/96] Fix OP_GMEmoteWorld for SoD --- utils/patches/patch_SoD.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index 764d93a4d..e700939a0 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -158,7 +158,7 @@ OP_GMApproval=0x72fa # C OP_GMToggle=0x7566 # C OP_GMSummon=0x596d # C OP_GMEmoteZone=0x3e7c # C -OP_GMEmoteWorld=0x3e7c # C +OP_GMEmoteWorld=0x5298 # C OP_GMFind=0x6e27 # C OP_GMKick=0x799c # C OP_GMKill=0x6685 # C From 26589835e524138b484e8cad01764b720896399a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 14:00:51 -0500 Subject: [PATCH 90/96] OP_PVPStats for Underfoot --- utils/patches/patch_Underfoot.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/patches/patch_Underfoot.conf b/utils/patches/patch_Underfoot.conf index 56838da65..adaf5fc05 100644 --- a/utils/patches/patch_Underfoot.conf +++ b/utils/patches/patch_Underfoot.conf @@ -315,7 +315,7 @@ OP_OnLevelMessage=0x24cb # C OP_AugmentInfo=0x31b1 # C OP_Petition=0x31d1 # C OP_SomeItemPacketMaybe=0x2c27 # C -OP_PVPStats=0x0000 # +OP_PVPStats=0x5272 # OP_PVPLeaderBoardRequest=0x4973 # C OP_PVPLeaderBoardReply=0x3842 # C OP_PVPLeaderBoardDetailsRequest=0x6c75 # C From e2bc79401b456385630b208b95f898503293ac0b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 14:13:05 -0500 Subject: [PATCH 91/96] OP_ShroudClearAA for RoF, UF, and SoF This should actually be usable to just straight clear AA data --- utils/patches/patch_RoF.conf | 1 + utils/patches/patch_SoF.conf | 1 + utils/patches/patch_Underfoot.conf | 1 + 3 files changed, 3 insertions(+) diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 027eac161..0866bf073 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -94,6 +94,7 @@ OP_ClearBlockedBuffs=0x5d3c OP_WorldObjectsSent=0x7fa8 OP_SendExpZonein=0x25ab OP_SendAATable=0x7791 +OP_ShroudClearAA=0x422e OP_RespondAA=0x379d OP_UpdateAA=0x504f OP_SendAAStats=0x3d1c diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 1380540e5..7da699a75 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -85,6 +85,7 @@ OP_TaskActivity=0x2E60 #SEQ 12/04/08 OP_CompletedTasks=0x75AC #Derision 2009 OP_Weather=0x70A5 #SEQ 12/04/08 OP_SendAATable=0x6F05 #Trevius 12/20/08 +OP_ShroudClearAA=0x71b9 OP_UpdateAA=0x45D2 #Trevius 12/20/08 OP_RespondAA=0x4426 #Trevius 12/20/08 OP_ReqClientSpawn=0x014C #SEQ 12/04/08 diff --git a/utils/patches/patch_Underfoot.conf b/utils/patches/patch_Underfoot.conf index adaf5fc05..736d0a576 100644 --- a/utils/patches/patch_Underfoot.conf +++ b/utils/patches/patch_Underfoot.conf @@ -88,6 +88,7 @@ OP_TaskActivity=0x31f3 # C OP_CompletedTasks=0x687f # C OP_Weather=0x4658 # V OP_SendAATable=0x6ef9 # V +OP_ShroudClearAA=0x2cd4 OP_UpdateAA=0x7bf6 # V OP_RespondAA=0x1fbd # C 0x2bad OP_ReqClientSpawn=0x69cd # V From 7cb1a2e7e42800ab4b7d486f328a8ff6333228d9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 14:29:54 -0500 Subject: [PATCH 92/96] OP_DzChooseZone for RoF and UF --- utils/patches/patch_RoF.conf | 2 +- utils/patches/patch_SoD.conf | 2 +- utils/patches/patch_Underfoot.conf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 0866bf073..16973c202 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -368,7 +368,7 @@ OP_DzLeaderStatus=0x4021 OP_DzExpeditionEndsWarning=0x32eb OP_DzMemberList=0x348f OP_DzCompass=0x0e01 # Was 0x4f09 -OP_DzChooseZone=0x0000 # Maybe 0x29d6 +OP_DzChooseZone=0x6e5e # Maybe 0x29d6 # New Opcodes OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index e700939a0..f42231238 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -369,7 +369,7 @@ OP_DzExpeditionEndsWarning=0x1879 OP_DzExpeditionList=0x3657 OP_DzMemberList=0x74e4 OP_DzCompass=0x35d3 -OP_DzChooseZone=0xd8a +OP_DzChooseZone=0x0d8a #0x1d99 was grouped with these too but I don't really know it's purpose. # New Opcodes diff --git a/utils/patches/patch_Underfoot.conf b/utils/patches/patch_Underfoot.conf index 736d0a576..842f5a259 100644 --- a/utils/patches/patch_Underfoot.conf +++ b/utils/patches/patch_Underfoot.conf @@ -374,7 +374,7 @@ OP_DzExpeditionEndsWarning=0x6ac2 OP_DzExpeditionList=0x70d8 OP_DzMemberList=0x15c4 OP_DzCompass=0x01cb -OP_DzChooseZone=0x0000 +OP_DzChooseZone=0x65e1 # New Opcodes OP_SpawnPositionUpdate=0x4656 # C From 4e257d43b2999e1884ac0791be43ded3a3bea303 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 14:40:41 -0500 Subject: [PATCH 93/96] OP_CrystalCreate and OP_CrystalReclaim for SoF --- utils/patches/patch_SoF.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 7da699a75..9e434bb65 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -548,6 +548,8 @@ OP_VetClaimReply=0x01e1 OP_PlayMP3=0x0d1c # OP_ReclaimCrystals=0x0000 # OP_CrystalCountUpdate=0x64C1 # +OP_CrystalCreate=0x65e2 +OP_CrystalReclaim=0x0730 OP_DynamicWall=0x0000 # OP_OpenDiscordMerchant=0x0000 # OP_DiscordMerchantInventory=0x0000 # From 2d070ff1c0bdec2e6d0ec7ef8d07c0e2916a494e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 15:59:03 -0500 Subject: [PATCH 94/96] OP_Untargetable for SoF --- utils/patches/patch_SoF.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 9e434bb65..7b0c41ad2 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -332,6 +332,7 @@ OP_InspectMessageUpdate=0x67e9 # C OP_OpenInventory=0x66c8 OP_OpenContainer=0x10e3 OP_Marquee=0x2f75 +OP_Untargetable=0x3e36 #expedition OP_DzQuit=0x20d6 From a201a3e837ee4fd49384892bac29cab83aea7409 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Dec 2014 16:26:55 -0500 Subject: [PATCH 95/96] Added Shroud ops for UF --- utils/patches/patch_Underfoot.conf | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/utils/patches/patch_Underfoot.conf b/utils/patches/patch_Underfoot.conf index 842f5a259..2b1c41dd9 100644 --- a/utils/patches/patch_Underfoot.conf +++ b/utils/patches/patch_Underfoot.conf @@ -376,6 +376,16 @@ OP_DzMemberList=0x15c4 OP_DzCompass=0x01cb OP_DzChooseZone=0x65e1 +#shroud +OP_ShroudSelectionWindow=0x72ad +OP_ShroudRequestStats=0x488b +OP_ShroudRespondStats=0x1910 +OP_ShroudSelect=0x45d7 +OP_ShroudSelectCancel=0x666d +OP_ShroudProgress=0x6016 # This clears current progress and sets +OP_ShroudProgress2=0x66b4 # This just sets progress +OP_Shroud=0x1643 + # New Opcodes OP_SpawnPositionUpdate=0x4656 # C OP_ManaUpdate=0x0433 # C From 60563aead61198050b3f569f534310ebc3fc9373 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 5 Dec 2014 19:33:25 -0500 Subject: [PATCH 96/96] Added MapKrono entry to RoF2::InventoryMaps enumeration --- common/patches/rof2_constants.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/patches/rof2_constants.h b/common/patches/rof2_constants.h index 1f8ff1a52..596ffa7e7 100644 --- a/common/patches/rof2_constants.h +++ b/common/patches/rof2_constants.h @@ -50,6 +50,7 @@ namespace RoF2 { MapArchived, MapMail, MapGuildTrophyTribute, + MapKrono, MapOther, _MapCount } InventoryMaps;