From e4fc6aad5aea339266cbb4d4d22f57dfdb47ad62 Mon Sep 17 00:00:00 2001 From: Emagi Date: Sun, 20 Oct 2024 09:35:41 -0400 Subject: [PATCH] Zone ruleset_id support for most rules --- .../AltAdvancement/AltAdvancement.cpp | 20 +++--- source/WorldServer/Bots/BotBrain.cpp | 2 +- source/WorldServer/Combat.cpp | 48 ++++++------- source/WorldServer/Combat.h | 6 -- source/WorldServer/Commands/Commands.cpp | 68 +++++++++---------- source/WorldServer/Entity.cpp | 26 +++---- source/WorldServer/GroundSpawn.cpp | 4 +- source/WorldServer/Housing/HousingPackets.cpp | 2 +- source/WorldServer/Items/Items.cpp | 18 +++-- source/WorldServer/Items/Loot.cpp | 6 +- source/WorldServer/NPC.cpp | 2 +- source/WorldServer/NPC_AI.cpp | 16 ++--- source/WorldServer/Player.cpp | 8 +-- source/WorldServer/Rules/Rules.cpp | 21 +++--- source/WorldServer/Spawn.cpp | 34 ++++++---- source/WorldServer/Spawn.h | 1 + source/WorldServer/SpellProcess.cpp | 2 +- source/WorldServer/World.cpp | 2 +- source/WorldServer/client.cpp | 64 +++++++++-------- source/WorldServer/client.h | 1 + source/WorldServer/zoneserver.cpp | 30 ++++---- 21 files changed, 196 insertions(+), 185 deletions(-) diff --git a/source/WorldServer/AltAdvancement/AltAdvancement.cpp b/source/WorldServer/AltAdvancement/AltAdvancement.cpp index 32678d4..c48115f 100644 --- a/source/WorldServer/AltAdvancement/AltAdvancement.cpp +++ b/source/WorldServer/AltAdvancement/AltAdvancement.cpp @@ -536,7 +536,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("class_tab_title", classes.GetClassNameCase(classes.GetSecondaryBaseClass(client->GetPlayer()->GetAdventureClass())).c_str()); packet->setDataByName("class_tree_node_id", node_id[AA_CLASS]); - packet->setDataByName("class_max_aa", rule_manager.GetGlobalRule(R_Player, MaxClassAA)->GetInt32()); + packet->setDataByName("class_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxClassAA)->GetInt32()); int32 class_id = TreeNodeList[node_id[AA_CLASS]]->AAtreeID; class_id = classid[node_id[AA_CLASS]]; packet->setDataByName("class_id", classid[node_id[AA_CLASS]]); @@ -630,7 +630,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("subclass_tab_title", classes.GetClassNameCase(client->GetPlayer()->GetAdventureClass()).c_str()); packet->setDataByName("subclass_tree_node_id", node_id[AA_SUBCLASS]); - packet->setDataByName("subclass_max_aa", rule_manager.GetGlobalRule(R_Player, MaxSubclassAA)->GetInt32()); + packet->setDataByName("subclass_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxSubclassAA)->GetInt32()); int32 unknown3 = TreeNodeList[node_id[AA_SUBCLASS]]->AAtreeID; packet->setDataByName("subclass_id", classid[node_id[AA_SUBCLASS]]); @@ -745,7 +745,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("shadows_tab_title", "Shadows"); packet->setDataByName("shadows_tree_node_id", node_id[AA_SHADOW]); - packet->setDataByName("shadows_max_aa", rule_manager.GetGlobalRule(R_Player, MaxShadowsAA)->GetInt32()); + packet->setDataByName("shadows_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxShadowsAA)->GetInt32()); packet->setDataByName("shadows_id", classid[node_id[AA_SHADOW]]); packet->setDataByName("shadows_eof_req", 0); packet->setArrayLengthByName("shadows_num_items", shadows_num_items, 0); @@ -848,7 +848,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("heroic_tab_title", "Heroic"); packet->setDataByName("heroic_tree_node_id", node_id[AA_HEROIC]); - packet->setDataByName("heroic_max_aa", rule_manager.GetGlobalRule(R_Player, MaxHeroicAA)->GetInt32()); + packet->setDataByName("heroic_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxHeroicAA)->GetInt32()); packet->setDataByName("heroic_id", classid[node_id[AA_HEROIC]]); packet->setDataByName("heroic_eof_req", 0); packet->setArrayLengthByName("heroic_num_items", heroic_num_items, 0); @@ -956,7 +956,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("tradeskill_tab_title", "Tradeskill"); packet->setDataByName("tradeskill_tree_node_id", node_id[AA_TRADESKILL]); - packet->setDataByName("tradeskill_max_aa", rule_manager.GetGlobalRule(R_Player, MaxTradeskillAA)->GetInt32()); + packet->setDataByName("tradeskill_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxTradeskillAA)->GetInt32()); packet->setDataByName("tradeskill_id", classid[node_id[AA_TRADESKILL]]); packet->setDataByName("tradeskill_eof_req", 0); packet->setArrayLengthByName("tradeskill_num_items", tradeskill_num_items, 0); @@ -1048,7 +1048,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("prestige_tab_title", "Prestige"); packet->setDataByName("prestige_tree_node_id", node_id[AA_PRESTIGE]); - packet->setDataByName("prestige_max_aa", rule_manager.GetGlobalRule(R_Player, MaxPrestigeAA)->GetInt32()); + packet->setDataByName("prestige_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxPrestigeAA)->GetInt32()); packet->setDataByName("prestige_id", classid[node_id[AA_PRESTIGE]]); packet->setDataByName("prestige_eof_req", 0); packet->setArrayLengthByName("prestige_num_items", prestige_num_items, 0); @@ -1151,7 +1151,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { packet->setDataByName("tradeskillprestige_tab_title", "Tradeskill Prestige"); } packet->setDataByName("tradeskillprestige_tree_node_id", node_id[AA_TRADESKILL_PRESTIGE]); - packet->setDataByName("tradeskillprestige_max_aa", rule_manager.GetGlobalRule(R_Player, MaxPrestigeAA)->GetInt32()); + packet->setDataByName("tradeskillprestige_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxPrestigeAA)->GetInt32()); packet->setDataByName("tradeskillprestige_id", classid[node_id[AA_TRADESKILL_PRESTIGE]]); packet->setDataByName("tradeskillprestige_eof_req", 0); packet->setArrayLengthByName("tradeskillprestige_num_items", tradeskillprestige_num_items, 0); @@ -1245,7 +1245,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("dragon_tab_title", "Dragon"); packet->setDataByName("dragon_tree_node_id", node_id[AA_DRAGON]); - packet->setDataByName("dragon_max_aa", rule_manager.GetGlobalRule(R_Player, MaxDragonAA)->GetInt32()); + packet->setDataByName("dragon_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxDragonAA)->GetInt32()); packet->setDataByName("dragon_id", classid[node_id[AA_DRAGON]]); packet->setDataByName("dragon_eof_req", 0); packet->setArrayLengthByName("dragon_num_items", dragon_num_items, 0); @@ -1324,7 +1324,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("dragonclass_tab_title", classes.GetClassNameCase(client->GetPlayer()->GetAdventureClass()).c_str()); packet->setDataByName("dragonclass_tree_node_id", node_id[AA_DRAGONCLASS]); - packet->setDataByName("dragonclass_max_aa", rule_manager.GetGlobalRule(R_Player, MaxDragonAA)->GetInt32()); + packet->setDataByName("dragonclass_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxDragonAA)->GetInt32()); packet->setDataByName("dragonclass_id", classid[node_id[AA_DRAGONCLASS]]); packet->setDataByName("dragonclass_eof_req", 0); packet->setArrayLengthByName("dragonclass_num_items", dragonclass_num_items, 0); @@ -1402,7 +1402,7 @@ void MasterAAList::DisplayAA(Client* client,int8 newtemplate,int8 changemode) { index = 0; packet->setDataByName("farseas_tab_title", "Farseas"); packet->setDataByName("farseas_tree_node_id", node_id[AA_FARSEAS]); - packet->setDataByName("farseas_max_aa", rule_manager.GetGlobalRule(R_Player, MaxDragonAA)->GetInt32()); + packet->setDataByName("farseas_max_aa", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxDragonAA)->GetInt32()); packet->setDataByName("farseas_id", classid[node_id[AA_FARSEAS]]); packet->setDataByName("farseas_eof_req", 0); packet->setArrayLengthByName("farseas_num_items", farseas_num_items, 0); diff --git a/source/WorldServer/Bots/BotBrain.cpp b/source/WorldServer/Bots/BotBrain.cpp index 69d19b0..f6e6600 100644 --- a/source/WorldServer/Bots/BotBrain.cpp +++ b/source/WorldServer/Bots/BotBrain.cpp @@ -50,7 +50,7 @@ void BotBrain::Think() { float distance = GetBody()->GetDistance(target); // If out of melee range then move closer - if (distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) + if (distance > rule_manager.GetZoneRule(GetBody()->GetZoneID(), R_Combat, MaxCombatRange)->GetFloat()) MoveCloser(target); } } diff --git a/source/WorldServer/Combat.cpp b/source/WorldServer/Combat.cpp index 78e2141..774bc0b 100644 --- a/source/WorldServer/Combat.cpp +++ b/source/WorldServer/Combat.cpp @@ -125,7 +125,7 @@ bool Entity::AttackAllowed(Entity* target, float distance, bool range_attack) { return false; } - if(rule_manager.GetGlobalRule(R_Combat, LockedEncounterNoAttack)->GetBool()) { + if(rule_manager.GetZoneRule(GetZoneID(), R_Combat, LockedEncounterNoAttack)->GetBool()) { if(target->IsNPC() && (target->GetLockedNoLoot() == ENCOUNTER_STATE_LOCKED || target->GetLockedNoLoot() == ENCOUNTER_STATE_OVERMATCHED) && !attacker->IsEngagedBySpawnID(target->GetID())) { return false; @@ -138,14 +138,14 @@ bool Entity::AttackAllowed(Entity* target, float distance, bool range_attack) { if (attacker->IsPlayer() && target->IsPlayer()) { - bool pvp_allowed = rule_manager.GetGlobalRule(R_PVP, AllowPVP)->GetBool(); + bool pvp_allowed = rule_manager.GetZoneRule(GetZoneID(), R_PVP, AllowPVP)->GetBool(); if (!pvp_allowed) { LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: pvp is not allowed"); return false; } else { - sint32 pvpLevelRange = rule_manager.GetGlobalRule(R_PVP, LevelRange)->GetSInt32(); + sint32 pvpLevelRange = rule_manager.GetZoneRule(GetZoneID(), R_PVP, LevelRange)->GetSInt32(); int32 attackerLevel = attacker->GetLevel(); int32 defenderLevel = target->GetLevel(); if ((sint32)abs((sint32)attackerLevel - (sint32)defenderLevel) > pvpLevelRange) @@ -186,7 +186,7 @@ bool Entity::AttackAllowed(Entity* target, float distance, bool range_attack) { } } else if (distance != 0) { - if(distance >= rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) { + if(distance >= rule_manager.GetZoneRule(GetZoneID(), R_Combat, MaxCombatRange)->GetFloat()) { LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: distance is beyond melee range"); return false; } @@ -808,7 +808,7 @@ int8 Entity::DetermineHit(Spawn* victim, int8 type, int8 damage_type, float ToHi LogWrite(COMBAT__DEBUG, 9, "Combat", "SpellResist: resistibility %f, bonus %f", lua_spell->spell->GetSpellData()->resistibility, bonus); // Here we take into account Subjugation, Disruption and Ordination (debuffs) if(lua_spell->spell->GetSpellData()->mastery_skill) { - int32 master_skill_reduce = rule_manager.GetGlobalRule(R_Spells, MasterSkillReduceSpellResist)->GetInt32(); + int32 master_skill_reduce = rule_manager.GetZoneRule(GetZoneID(), R_Spells, MasterSkillReduceSpellResist)->GetInt32(); if(master_skill_reduce < 1) master_skill_reduce = 25; if(IsPlayer() && lua_spell->spell->GetSpellData()->spell_book_type == SPELL_BOOK_TYPE_TRADESKILL && @@ -1230,7 +1230,7 @@ float Entity::CalculateMitigation(int8 type, int8 damage_type, int16 effective_l else effective_level_attacker = 1; - int32 effective_mit_cap = effective_level_victim * rule_manager.GetGlobalRule(R_Combat, EffectiveMitigationCapLevel)->GetInt32(); + int32 effective_mit_cap = effective_level_victim * rule_manager.GetZoneRule(GetZoneID(), R_Combat, EffectiveMitigationCapLevel)->GetInt32(); float max_mit = (float)GetInfoStruct()->get_max_mitigation(); if(max_mit == 0.0f) max_mit = effective_level_victim * 100.0f; @@ -1268,26 +1268,26 @@ float Entity::CalculateMitigation(int8 type, int8 damage_type, int16 effective_l } if(for_pvp) { - mit_to_use += effective_level_victim * rule_manager.GetGlobalRule(R_Combat, MitigationLevelEffectivenessMax)->GetInt32(); + mit_to_use += effective_level_victim * rule_manager.GetZoneRule(GetZoneID(), R_Combat, MitigationLevelEffectivenessMax)->GetInt32(); } if(mit_to_use > effective_mit_cap) { mit_to_use = effective_mit_cap; } float level_diff = ((float)effective_level_victim / (float)effective_level_attacker); - if(level_diff > rule_manager.GetGlobalRule(R_Combat, MitigationLevelEffectivenessMax)->GetFloat()) { - level_diff = rule_manager.GetGlobalRule(R_Combat, MitigationLevelEffectivenessMax)->GetFloat(); + if(level_diff > rule_manager.GetZoneRule(GetZoneID(), R_Combat, MitigationLevelEffectivenessMax)->GetFloat()) { + level_diff = rule_manager.GetZoneRule(GetZoneID(), R_Combat, MitigationLevelEffectivenessMax)->GetFloat(); } - else if(level_diff < rule_manager.GetGlobalRule(R_Combat, MitigationLevelEffectivenessMax)->GetFloat()) { - level_diff = rule_manager.GetGlobalRule(R_Combat, MitigationLevelEffectivenessMin)->GetFloat(); + else if(level_diff < rule_manager.GetZoneRule(GetZoneID(), R_Combat, MitigationLevelEffectivenessMax)->GetFloat()) { + level_diff = rule_manager.GetZoneRule(GetZoneID(), R_Combat, MitigationLevelEffectivenessMin)->GetFloat(); } float mit_percentage = ((float)mit_to_use / max_mit) * level_diff; - if(!for_pvp && mit_percentage > rule_manager.GetGlobalRule(R_Combat, MaxMitigationAllowed)->GetFloat()) { - mit_percentage = rule_manager.GetGlobalRule(R_Combat, MaxMitigationAllowed)->GetFloat(); + if(!for_pvp && mit_percentage > rule_manager.GetZoneRule(GetZoneID(), R_Combat, MaxMitigationAllowed)->GetFloat()) { + mit_percentage = rule_manager.GetZoneRule(GetZoneID(), R_Combat, MaxMitigationAllowed)->GetFloat(); } - else if(for_pvp && mit_percentage > rule_manager.GetGlobalRule(R_Combat, MaxMitigationAllowedPVP)->GetFloat()) { - mit_percentage = rule_manager.GetGlobalRule(R_Combat, MaxMitigationAllowedPVP)->GetFloat(); + else if(for_pvp && mit_percentage > rule_manager.GetZoneRule(GetZoneID(), R_Combat, MaxMitigationAllowedPVP)->GetFloat()) { + mit_percentage = rule_manager.GetZoneRule(GetZoneID(), R_Combat, MaxMitigationAllowedPVP)->GetFloat(); } return mit_percentage; @@ -1356,13 +1356,13 @@ void Entity::AddHate(Entity* attacker, sint32 hate) { } bool Entity::CheckFizzleSpell(LuaSpell* spell) { - if(!spell || !rule_manager.GetGlobalRule(R_Spells, EnableFizzleSpells)->GetInt8() + if(!spell || !rule_manager.GetZoneRule(GetZoneID(), R_Spells, EnableFizzleSpells)->GetInt8() || spell->spell->GetSpellData()->can_fizzle == false) return false; - float fizzleMaxSkill = rule_manager.GetGlobalRule(R_Spells, FizzleMaxSkill)->GetFloat(); - float baseFizzle = rule_manager.GetGlobalRule(R_Spells, DefaultFizzleChance)->GetFloat()/100.0f; // 10% - float skillObtained = rule_manager.GetGlobalRule(R_Spells, FizzleDefaultSkill)->GetFloat(); // default of .2f so we don't go over the threshold if no skill + float fizzleMaxSkill = rule_manager.GetZoneRule(GetZoneID(), R_Spells, FizzleMaxSkill)->GetFloat(); + float baseFizzle = rule_manager.GetZoneRule(GetZoneID(), R_Spells, DefaultFizzleChance)->GetFloat()/100.0f; // 10% + float skillObtained = rule_manager.GetZoneRule(GetZoneID(), R_Spells, FizzleDefaultSkill)->GetFloat(); // default of .2f so we don't go over the threshold if no skill Skill* skill = GetSkillByID(spell->spell->GetSpellData()->mastery_skill, false); if(skill && spell->spell->GetSpellData()->min_class_skill_req > 0) { @@ -1397,7 +1397,7 @@ bool Entity::CheckInterruptSpell(Entity* attacker) { //originally base of 30 percent chance to continue casting if attacked //modified to 50% and added global rule, 30% was too small at starting levels - int8 percent = rule_manager.GetGlobalRule(R_Spells, NoInterruptBaseChance)->GetInt32(); + int8 percent = rule_manager.GetZoneRule(GetZoneID(), R_Spells, NoInterruptBaseChance)->GetInt32(); float focus_skill_with_bonus = CalculateSkillWithBonus("Focus", ITEM_STAT_FOCUS, true); @@ -1464,13 +1464,13 @@ void Entity::HandleDeathExperienceDebt(Spawn* killer) float ruleDebt = 0.0f; if(killer && killer->IsPlayer()) - ruleDebt = rule_manager.GetGlobalRule(R_Combat, PVPDeathExperienceDebt)->GetFloat()/100.0f; + ruleDebt = rule_manager.GetZoneRule(GetZoneID(), R_Combat, PVPDeathExperienceDebt)->GetFloat()/100.0f; else - ruleDebt = rule_manager.GetGlobalRule(R_Combat, DeathExperienceDebt)->GetFloat()/100.0f; + ruleDebt = rule_manager.GetZoneRule(GetZoneID(), R_Combat, DeathExperienceDebt)->GetFloat()/100.0f; if(ruleDebt > 0.0f) { - bool groupDebt = rule_manager.GetGlobalRule(R_Combat, GroupExperienceDebt)->GetBool(); + bool groupDebt = rule_manager.GetZoneRule(GetZoneID(), R_Combat, GroupExperienceDebt)->GetBool(); if(groupDebt && ((Player*)this)->GetGroupMemberInfo()) { world.GetGroupManager()->GroupLock(__FUNCTION__, __LINE__); @@ -1594,7 +1594,7 @@ void Player::ProcessCombat() { } } } - else if(distance <= rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) { + else if(distance <= rule_manager.GetZoneRule(GetZoneID(), R_Combat, MaxCombatRange)->GetFloat()) { // We are doing melee auto attacks and are within range // Check to see if we can attack the target diff --git a/source/WorldServer/Combat.h b/source/WorldServer/Combat.h index 627aae1..f56a11b 100644 --- a/source/WorldServer/Combat.h +++ b/source/WorldServer/Combat.h @@ -24,12 +24,6 @@ #include "NPC_AI.h" #include "MutexList.h" -#define COMBAT_NORMAL_FIGHTER 0 -#define COMBAT_ADD_FIGHTER 1 -#define COMBAT_REMOVE_FIGHTER 2 -// replace with rule rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat() -//#define MAX_COMBAT_RANGE 3 - class ZoneServer; class SpellProcess; class LuaSpell; diff --git a/source/WorldServer/Commands/Commands.cpp b/source/WorldServer/Commands/Commands.cpp index c433bc8..f6b4b43 100644 --- a/source/WorldServer/Commands/Commands.cpp +++ b/source/WorldServer/Commands/Commands.cpp @@ -2352,7 +2352,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie break; } int16 tier_up = player->GetTierUp(spell->GetSpellTier()); - if (rule_manager.GetGlobalRule(R_Spells, RequirePreviousTierScribe)->GetInt8() && !player->HasSpell(spell->GetSpellID(), tier_up, false, true)) + if (rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, RequirePreviousTierScribe)->GetInt8() && !player->HasSpell(spell->GetSpellID(), tier_up, false, true)) client->SimpleMessage(CHANNEL_COLOR_RED, "You have not scribed the required previous version of this ability."); else if (!player->HasSpell(spell->GetSpellID(), spell->GetSpellTier(), true)) { old_slot = player->GetSpellSlot(spell->GetSpellID()); @@ -2549,7 +2549,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie if (spawn->IsNPC()) show_bubble = false; client->GetCurrentZone()->HandleChatMessage(client->GetPlayer(), 0, CHANNEL_SAY, tmp, HEAR_SPAWN_DISTANCE, 0, show_bubble, client->GetPlayer()->GetCurrentLanguage()); - if(spawn->IsPlayer() == false && spawn->Alive() && spawn->GetDistance(client->GetPlayer()) < rule_manager.GetGlobalRule(R_Spawn, HailDistance)->GetInt32()){ + if(spawn->IsPlayer() == false && spawn->Alive() && spawn->GetDistance(client->GetPlayer()) < rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spawn, HailDistance)->GetInt32()){ if(spawn->IsNPC() && ((NPC*)spawn)->EngagedInCombat()) spawn->GetZone()->CallSpawnScript(spawn, SPAWN_SCRIPT_HAILED_BUSY, client->GetPlayer()); else @@ -2563,7 +2563,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie } if(spawn->GetZone()->CallSpawnScript(spawn, SPAWN_SCRIPT_HAILED, client->GetPlayer()) && pauseRunback) - spawn->PauseMovement(rule_manager.GetGlobalRule(R_Spawn, HailMovementPause)->GetInt32()); + spawn->PauseMovement(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spawn, HailMovementPause)->GetInt32()); else if(spawn->IsNPC() && pauseRunback) ((NPC*)spawn)->ClearRunback(); } @@ -3034,11 +3034,11 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie } if(cmdTarget && cmdTarget->IsEntity()){ - if (cmdTarget->GetDistance(client->GetPlayer()) <= rule_manager.GetGlobalRule(R_Loot, LootRadius)->GetFloat()){ - if (!rule_manager.GetGlobalRule(R_Loot, AutoDisarmChest)->GetBool() && command->handler == COMMAND_DISARM ) + if (cmdTarget->GetDistance(client->GetPlayer()) <= rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Loot, LootRadius)->GetFloat()){ + if (!rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Loot, AutoDisarmChest)->GetBool() && command->handler == COMMAND_DISARM ) client->OpenChest(cmdTarget, true); else - client->LootSpawnRequest(cmdTarget, rule_manager.GetGlobalRule(R_Loot, AutoDisarmChest)->GetBool()); + client->LootSpawnRequest(cmdTarget, rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Loot, AutoDisarmChest)->GetBool()); if (!(cmdTarget)->HasLoot()){ if (((Entity*)cmdTarget)->IsNPC()) client->GetCurrentZone()->RemoveDeadSpawn(cmdTarget); @@ -7012,7 +7012,7 @@ void Commands::Command_Inventory(Client* client, Seperator* sep, EQ2_RemoteComma } else if(sep->arg[2][0] && strncasecmp("swap_equip", sep->arg[0], 10) == 0 && sep->IsNumber(1) && sep->IsNumber(2)) { - if(client->GetPlayer()->EngagedInCombat() && rule_manager.GetGlobalRule(R_Player, AllowPlayerEquipCombat)->GetInt8() == 0) { + if(client->GetPlayer()->EngagedInCombat() && rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, AllowPlayerEquipCombat)->GetInt8() == 0) { client->SimpleMessage(CHANNEL_COLOR_RED, "You may not swap items while in combat."); } else { @@ -7250,7 +7250,7 @@ void Commands::Command_LastName(Client* client, Seperator* sep) if (sep && sep->arg[0]) { if (!client->GetPlayer()->get_character_flag(CF_ENABLE_CHANGE_LASTNAME)){ - client->Message(CHANNEL_COLOR_YELLOW, "You must be atleast level %i to change your last name.", rule_manager.GetGlobalRule(R_Player, MinLastNameLevel)->GetInt8()); + client->Message(CHANNEL_COLOR_YELLOW, "You must be atleast level %i to change your last name.", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MinLastNameLevel)->GetInt8()); return; } client->RemovePendingLastName(); @@ -7265,13 +7265,13 @@ void Commands::Command_LastName(Client* client, Seperator* sep) } if (!valid_name) { - client->Message(CHANNEL_COLOR_YELLOW, "Your last name can only contain letters.", rule_manager.GetGlobalRule(R_Player, MinLastNameLevel)->GetInt8()); + client->Message(CHANNEL_COLOR_YELLOW, "Your last name can only contain letters.", rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MinLastNameLevel)->GetInt8()); return; } string last_name = (string)sep->arg[0]; - int8 max_length = rule_manager.GetGlobalRule(R_Player, MaxLastNameLength)->GetInt8(); - int8 min_length = rule_manager.GetGlobalRule(R_Player, MinLastNameLength)->GetInt8(); + int8 max_length = rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxLastNameLength)->GetInt8(); + int8 min_length = rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MinLastNameLength)->GetInt8(); if (last_name.length() <= max_length && last_name.length() >= min_length){ client->SetPendingLastName(last_name); client->SendLastNameConfirmation(); @@ -11272,15 +11272,15 @@ void Commands::Command_Weather(Client* client, Seperator* sep) } else if( strncasecmp(value, "reset", strlen(value)) == 0 ) { - zsZone->SetWeatherType(rule_manager.GetGlobalRule(R_Zone, WeatherType)->GetInt8()); - zsZone->SetWeatherFrequency(rule_manager.GetGlobalRule(R_Zone, WeatherChangeFrequency)->GetInt32()); - zsZone->SetWeatherMinSeverity(rule_manager.GetGlobalRule(R_Zone, MinWeatherSeverity)->GetFloat()); - zsZone->SetWeatherMaxSeverity(rule_manager.GetGlobalRule(R_Zone, MaxWeatherSeverity)->GetFloat()); + zsZone->SetWeatherType(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Zone, WeatherType)->GetInt8()); + zsZone->SetWeatherFrequency(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Zone, WeatherChangeFrequency)->GetInt32()); + zsZone->SetWeatherMinSeverity(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Zone, MinWeatherSeverity)->GetFloat()); + zsZone->SetWeatherMaxSeverity(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Zone, MaxWeatherSeverity)->GetFloat()); zsZone->SetCurrentWeather(zsZone->GetWeatherMinSeverity()); zsZone->SetWeatherPattern(1); - zsZone->SetWeatherChance(rule_manager.GetGlobalRule(R_Zone, WeatherChangeChance)->GetInt8()); - zsZone->SetWeatherChangeAmount(rule_manager.GetGlobalRule(R_Zone, WeatherChangePerInterval)->GetFloat()); - zsZone->SetWeatherDynamicOffset(rule_manager.GetGlobalRule(R_Zone, WeatherDynamicMaxOffset)->GetFloat()); + zsZone->SetWeatherChance(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Zone, WeatherChangeChance)->GetInt8()); + zsZone->SetWeatherChangeAmount(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Zone, WeatherChangePerInterval)->GetFloat()); + zsZone->SetWeatherDynamicOffset(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Zone, WeatherDynamicMaxOffset)->GetFloat()); zsZone->SetWeatherLastChangedTime(Timer::GetUnixTimeStamp() - zsZone->GetWeatherFrequency()); zsZone->ProcessWeather(); } @@ -11627,9 +11627,9 @@ void Commands::Command_AchievementAdd(Client* client, Seperator* sep) { void Commands::Command_Editor(Client* client, Seperator* sep) { PacketStruct* packet = configReader.getStruct("WS_ChoiceWindow", client->GetVersion()); if (packet) { - string url = string(rule_manager.GetGlobalRule(R_World, EditorURL)->GetString()); + string url = string(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_World, EditorURL)->GetString()); - if (rule_manager.GetGlobalRule(R_World, EditorOfficialServer)->GetBool()) { + if (rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_World, EditorOfficialServer)->GetBool()) { char command[255]; url = "browser " + url; int32 spawn_id = 0; @@ -11661,7 +11661,7 @@ void Commands::Command_Editor(Client* client, Seperator* sep) { packet->setDataByName("accept_command", command); } - else if (rule_manager.GetGlobalRule(R_World, EditorIncludeID)->GetBool()) { + else if (rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_World, EditorIncludeID)->GetBool()) { char command[255]; url = "browser " + url; if (client->GetPlayer()->GetTarget()) @@ -12042,40 +12042,40 @@ void Commands::Command_CurePlayer(Client* client, Seperator* sep) if(str == "arcane") { type = EFFECT_CURE_TYPE_ARCANE; // cure arcane spell missing in DB? - if(use_spells && rule_manager.GetGlobalRule(R_Spells, CureArcaneSpellID)->GetInt32()) { - entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetGlobalRule(R_Spells, CureArcaneSpellID)->GetInt32()); // cure noxious + if(use_spells && rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureArcaneSpellID)->GetInt32()) { + entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureArcaneSpellID)->GetInt32()); // cure noxious } } else if(str == "trauma") { type = EFFECT_CURE_TYPE_TRAUMA; // cure trauma spell missing in DB? - if(use_spells && rule_manager.GetGlobalRule(R_Spells, CureTraumaSpellID)->GetInt32()) { - entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetGlobalRule(R_Spells, CureTraumaSpellID)->GetInt32()); // cure noxious + if(use_spells && rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureTraumaSpellID)->GetInt32()) { + entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureTraumaSpellID)->GetInt32()); // cure noxious } } else if(str == "noxious") { type = EFFECT_CURE_TYPE_NOXIOUS; - if(use_spells && rule_manager.GetGlobalRule(R_Spells, CureNoxiousSpellID)->GetInt32()) { - entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetGlobalRule(R_Spells, CureNoxiousSpellID)->GetInt32()); // cure noxious + if(use_spells && rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureNoxiousSpellID)->GetInt32()) { + entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureNoxiousSpellID)->GetInt32()); // cure noxious } } else if(str == "curse") { type = EFFECT_CURE_TYPE_CURSE; - if(use_spells && rule_manager.GetGlobalRule(R_Spells, CureCurseSpellID)->GetInt32()) { - entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetGlobalRule(R_Spells, CureCurseSpellID)->GetInt32()); // cure curse + if(use_spells && rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureCurseSpellID)->GetInt32()) { + entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureCurseSpellID)->GetInt32()); // cure curse } } else if(str == "magic") { type = EFFECT_CURE_TYPE_MAGIC; - if(use_spells && rule_manager.GetGlobalRule(R_Spells, CureMagicSpellID)->GetInt32()) { - entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetGlobalRule(R_Spells, CureMagicSpellID)->GetInt32()); // cure magic + if(use_spells && rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureMagicSpellID)->GetInt32()) { + entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureMagicSpellID)->GetInt32()); // cure magic } } if(use_spells) { // check if any of the specific cure types are available, if not then check the base cures - if(!entry && rule_manager.GetGlobalRule(R_Spells, CureSpellID)->GetInt32()) { - entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetGlobalRule(R_Spells, CureSpellID)->GetInt32()); // cure + if(!entry && rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureSpellID)->GetInt32()) { + entry = client->GetPlayer()->GetSpellBookSpell(rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Spells, CureSpellID)->GetInt32()); // cure } if(entry && entry->spell_id) { @@ -12353,7 +12353,7 @@ void Commands::Command_Target(Client* client, Seperator* sep) { Entity* player = (Entity*)client->GetPlayer(); Spawn* res = nullptr; if(sep && sep->arg[0] && player->GetZone()) { - float max_distance = rule_manager.GetGlobalRule(R_Player, MaxTargetCommandDistance)->GetFloat(); + float max_distance = rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MaxTargetCommandDistance)->GetFloat(); if(max_distance < 1.0f) { max_distance = 10.0f; diff --git a/source/WorldServer/Entity.cpp b/source/WorldServer/Entity.cpp index e3636b7..0fa247a 100644 --- a/source/WorldServer/Entity.cpp +++ b/source/WorldServer/Entity.cpp @@ -781,7 +781,7 @@ void Entity::GetWeaponDamage(Item* item, int32* low_damage, int32* high_damage) int32 selected_high_dmg = item->weapon_info->damage_high3; if(IsPlayer()) { - float skillMultiplier = rule_manager.GetGlobalRule(R_Player, LevelMasterySkillMultiplier)->GetFloat(); + float skillMultiplier = rule_manager.GetZoneRule(GetZoneID(), R_Player, LevelMasterySkillMultiplier)->GetFloat(); if(skillMultiplier <= 0.0f) { skillMultiplier = 1.0f; } @@ -919,12 +919,12 @@ void Entity::UpdateWeapons() { int32 Entity::GetStrengthDamage() { int32 str_offset = 1; if(IsNPC()) { - str_offset = rule_manager.GetGlobalRule(R_Combat, StrengthNPC)->GetInt32(); + str_offset = rule_manager.GetZoneRule(GetZoneID(), R_Combat, StrengthNPC)->GetInt32(); if(str_offset < 1) str_offset = 1; } else { - str_offset = rule_manager.GetGlobalRule(R_Combat, StrengthOther)->GetInt32(); + str_offset = rule_manager.GetZoneRule(GetZoneID(), R_Combat, StrengthOther)->GetInt32(); if(str_offset < 1) str_offset = 1; @@ -1343,7 +1343,7 @@ void Entity::SetMaxSpeed(float val){ float Entity::CalculateSkillStatChance(char* skillName, int16 item_stat, float max_cap, float modifier, bool add_to_skill) { float skillAndItemsChance = 0.0f; - float maxBonusCap = (float)GetLevel()*rule_manager.GetGlobalRule(R_Combat, MaxSkillBonusByLevel)->GetFloat(); + float maxBonusCap = (float)GetLevel()*rule_manager.GetZoneRule(GetZoneID(), R_Combat, MaxSkillBonusByLevel)->GetFloat(); Skill* skill = GetSkillByName(skillName, false); if(skill){ MStats.lock(); @@ -1398,7 +1398,7 @@ float Entity::CalculateSkillWithBonus(char* skillName, int16 item_stat, bool cha } float Entity::GetRuleSkillMaxBonus() { - return (float)GetLevel()*rule_manager.GetGlobalRule(R_Combat, MaxSkillBonusByLevel)->GetFloat(); + return (float)GetLevel()*rule_manager.GetZoneRule(GetZoneID(), R_Combat, MaxSkillBonusByLevel)->GetFloat(); } void Entity::CalculateBonuses(){ @@ -1468,7 +1468,7 @@ void Entity::CalculateBonuses(){ info->set_cur_mitigation(info->get_mitigation_base()); - int32 calc_mit_cap = effective_level * rule_manager.GetGlobalRule(R_Combat, CalculatedMitigationCapLevel)->GetInt32(); + int32 calc_mit_cap = effective_level * rule_manager.GetZoneRule(GetZoneID(), R_Combat, CalculatedMitigationCapLevel)->GetInt32(); info->set_max_mitigation(calc_mit_cap); int16 mit_percent = (int16)(CalculateMitigation() * 1000.0f); @@ -1656,7 +1656,7 @@ void Entity::CalculateApplyWeight() { int32 coin_gold = GetInfoStruct()->get_coin_gold(); int32 coin_plat = GetInfoStruct()->get_coin_plat(); - float weight_per_stone = rule_manager.GetGlobalRule(R_Player, CoinWeightPerStone)->GetFloat(); + float weight_per_stone = rule_manager.GetZoneRule(GetZoneID(), R_Player, CoinWeightPerStone)->GetFloat(); if(weight_per_stone < 0.0f) { weight_per_stone = 0.0f; } @@ -1683,8 +1683,8 @@ void Entity::CalculateApplyWeight() { ((Player*)this)->SetCharSheetChanged(true); } int32 max_weight = 0; - float weight_str_multiplier = rule_manager.GetGlobalRule(R_Player, MaxWeightStrengthMultiplier)->GetFloat(); - int32 base_weight = rule_manager.GetGlobalRule(R_Player, BaseWeight)->GetInt32(); + float weight_str_multiplier = rule_manager.GetZoneRule(GetZoneID(), R_Player, MaxWeightStrengthMultiplier)->GetFloat(); + int32 base_weight = rule_manager.GetZoneRule(GetZoneID(), R_Player, BaseWeight)->GetInt32(); if(weight_str_multiplier < 0.0f) { weight_str_multiplier = 0.0f; } @@ -1701,7 +1701,7 @@ void Entity::CalculateApplyWeight() { void Entity::SetRegenValues(int16 effective_level) { - bool classicRegen = rule_manager.GetGlobalRule(R_Spawn, ClassicRegen)->GetBool(); + bool classicRegen = rule_manager.GetZoneRule(GetZoneID(), R_Spawn, ClassicRegen)->GetBool(); bool override_ = (IsPlayer() && !GetInfoStruct()->get_engaged_encounter()); if(!GetInfoStruct()->get_hp_regen_override()) @@ -2934,9 +2934,9 @@ float Entity::GetHighestSnare() { // For simplicity this will return the highest snare value, which is actually the lowest value float ret = 1.0f; float weight_diff = 0.0f; - if (IsPlayer() && rule_manager.GetGlobalRule(R_Player, WeightInflictsSpeed)->GetBool()) { - float weight_pct_impact = rule_manager.GetGlobalRule(R_Player, WeightPercentImpact)->GetFloat(); - float weight_pct_cap = rule_manager.GetGlobalRule(R_Player, WeightPercentCap)->GetFloat(); + if (IsPlayer() && rule_manager.GetZoneRule(GetZoneID(), R_Player, WeightInflictsSpeed)->GetBool()) { + float weight_pct_impact = rule_manager.GetZoneRule(GetZoneID(), R_Player, WeightPercentImpact)->GetFloat(); + float weight_pct_cap = rule_manager.GetZoneRule(GetZoneID(), R_Player, WeightPercentCap)->GetFloat(); if(weight_pct_impact > 1.0f) { weight_pct_impact = 1.0f; } diff --git a/source/WorldServer/GroundSpawn.cpp b/source/WorldServer/GroundSpawn.cpp index 88be140..75e99a7 100644 --- a/source/WorldServer/GroundSpawn.cpp +++ b/source/WorldServer/GroundSpawn.cpp @@ -138,7 +138,7 @@ void GroundSpawn::ProcessHarvest(Client* client) { int16 totalSkill = skill->current_val; int32 skillID = master_item_list.GetItemStatIDByName(collection_skill); - int16 max_skill_req_groundspawn = rule_manager.GetGlobalRule(R_Player, MinSkillMultiplierValue)->GetInt16(); + int16 max_skill_req_groundspawn = rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MinSkillMultiplierValue)->GetInt16(); if(max_skill_req_groundspawn < 1) // can't be 0 max_skill_req_groundspawn = 1; @@ -278,7 +278,7 @@ void GroundSpawn::ProcessHarvest(Client* client) { else LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest nothing..."); - float node_maxskill_multiplier = rule_manager.GetGlobalRule(R_Player, HarvestSkillUpMultiplier)->GetFloat(); + float node_maxskill_multiplier = rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, HarvestSkillUpMultiplier)->GetFloat(); if(node_maxskill_multiplier <= 0.0f) { node_maxskill_multiplier = 1.0f; } diff --git a/source/WorldServer/Housing/HousingPackets.cpp b/source/WorldServer/Housing/HousingPackets.cpp index 9b30783..3f817eb 100644 --- a/source/WorldServer/Housing/HousingPackets.cpp +++ b/source/WorldServer/Housing/HousingPackets.cpp @@ -12,7 +12,7 @@ extern RuleManager rule_manager; void ClientPacketFunctions::SendHousePurchase(Client* client, HouseZone* hz, int32 spawnID) { PacketStruct* packet = configReader.getStruct("WS_PlayerHousePurchase", client->GetVersion()); if (packet) { - int8 disable_alignment_req = rule_manager.GetGlobalRule(R_Player, DisableHouseAlignmentRequirement)->GetInt8(); + int8 disable_alignment_req = rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, DisableHouseAlignmentRequirement)->GetInt8(); packet->setDataByName("house_name", hz->name.c_str()); packet->setDataByName("house_id", hz->id); packet->setDataByName("spawn_id", spawnID); diff --git a/source/WorldServer/Items/Items.cpp b/source/WorldServer/Items/Items.cpp index 76d7114..f5cbf01 100644 --- a/source/WorldServer/Items/Items.cpp +++ b/source/WorldServer/Items/Items.cpp @@ -856,7 +856,8 @@ ItemStatsValues* MasterItemList::CalculateItemBonuses(Item* item, Entity* entity { int32 diff = item->details.recommended_level - effective_level; float tmpValue = (float)value; - value = (sint32)(float)(tmpValue / (1.0f + ((float)diff * rule_manager.GetGlobalRule(R_Player, MentorItemDecayRate)->GetFloat()))); + int32 zone_id = entity->GetZone() ? entity->GetZone()->GetZoneID() : 0; + value = (sint32)(float)(tmpValue / (1.0f + ((float)diff * rule_manager.GetZoneRule(zone_id, R_Player, MentorItemDecayRate)->GetFloat()))); } } @@ -1850,7 +1851,8 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16 packet->setSubstructDataByName("header_info", "unique_id", details.unique_id); packet->setSubstructDataByName("header_info", "icon", GetIcon(packet->GetVersion())); - if(rule_manager.GetGlobalRule(R_World, DisplayItemTiers)->GetBool()) { + int32 zone_id = player->GetZone() ? player->GetZone()->GetZoneID() : 0; + if(rule_manager.GetZoneRule(zone_id, R_World, DisplayItemTiers)->GetBool()) { packet->setSubstructDataByName("header_info", "tier", details.tier); } packet->setSubstructDataByName("header_info", "flags", generic_info.item_flags); @@ -1894,7 +1896,8 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16 { int32 diff = details.recommended_level - effective_level; float tmpValue = (float)statValue; - statValue = (sint32)(float)(tmpValue / (1.0f + ((float)diff * rule_manager.GetGlobalRule(R_Player, MentorItemDecayRate)->GetFloat()))); + int32 zone_id = player->GetZone() ? player->GetZone()->GetZoneID() : 0; + statValue = (sint32)(float)(tmpValue / (1.0f + ((float)diff * rule_manager.GetZoneRule(zone_id, R_Player, MentorItemDecayRate)->GetFloat()))); } } @@ -2395,7 +2398,8 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16 // either don't require previous tier or check that we have the lower tier spells potentially int32 tier_up = player->GetTierUp(skill_info->spell_tier); - if (!rule_manager.GetGlobalRule(R_Spells, RequirePreviousTierScribe)->GetInt8() || player->HasSpell(skill_info->spell_id, tier_up, false, true)) + int32 zone_id = player->GetZone() ? player->GetZone()->GetZoneID() : 0; + if (!rule_manager.GetZoneRule(zone_id, R_Spells, RequirePreviousTierScribe)->GetInt8() || player->HasSpell(skill_info->spell_id, tier_up, false, true)) packet->setDataByName("require_previous", 1, 0); // membership required //packet->setDataByName("unknown_1188_2_MJ", 1, 1); @@ -3820,7 +3824,8 @@ void PlayerItemList::AddItemToPacket(PacketStruct* packet, Player* player, Item* packet->setSubstructArrayDataByName("items", "item_level", item->details.recommended_level , 0, i); - if(rule_manager.GetGlobalRule(R_World, DisplayItemTiers)->GetBool()) { + int32 zone_id = player->GetZone() ? player->GetZone()->GetZoneID() : 0; + if(rule_manager.GetZoneRule(zone_id, R_World, DisplayItemTiers)->GetBool()) { packet->setSubstructArrayDataByName("items", "tier", item->details.tier, 0, i); } @@ -4392,7 +4397,8 @@ EQ2Packet* EquipmentItemList::serialize(int16 version, Player* player){ packet->setSubstructArrayDataByName("items", "count", item->details.count, 0, i); // item level needed here - if(rule_manager.GetGlobalRule(R_World, DisplayItemTiers)->GetBool()) { + int32 zone_id = player->GetZone() ? player->GetZone()->GetZoneID() : 0; + if(rule_manager.GetZoneRule(zone_id, R_World, DisplayItemTiers)->GetBool()) { packet->setSubstructArrayDataByName("items", "tier", item->details.tier, 0, i); } packet->setSubstructArrayDataByName("items", "num_slots", item->details.num_slots, 0, i); diff --git a/source/WorldServer/Items/Loot.cpp b/source/WorldServer/Items/Loot.cpp index 112b714..ecc92fe 100644 --- a/source/WorldServer/Items/Loot.cpp +++ b/source/WorldServer/Items/Loot.cpp @@ -40,7 +40,7 @@ extern RuleManager rule_manager; NPC* Entity::DropChest() { // Check to see if treasure chests are disabled in the rules - if (rule_manager.GetGlobalRule(R_World, TreasureChestDisabled)->GetBool()) + if (rule_manager.GetZoneRule(GetZoneID(), R_World, TreasureChestDisabled)->GetBool()) return 0; if(GetChestDropTime()) { @@ -66,8 +66,8 @@ NPC* Entity::DropChest() { // heading needs to be GetHeading() - 180 so the chest faces the proper way chest->SetHeading(GetHeading() - 180); // Set the primary command to loot and the secondary to disarm - chest->AddPrimaryEntityCommand("loot", rule_manager.GetGlobalRule(R_Loot, LootRadius)->GetFloat(), "loot", "", 0, 0); - chest->AddSecondaryEntityCommand("Disarm", rule_manager.GetGlobalRule(R_Loot, LootRadius)->GetFloat(), "Disarm", "", 0, 0); + chest->AddPrimaryEntityCommand("loot", rule_manager.GetZoneRule(GetZoneID(), R_Loot, LootRadius)->GetFloat(), "loot", "", 0, 0); + chest->AddSecondaryEntityCommand("Disarm", rule_manager.GetZoneRule(GetZoneID(), R_Loot, LootRadius)->GetFloat(), "Disarm", "", 0, 0); // 32 = loot icon for the mouse chest->SetIcon(32); // 1 = show the right click menu diff --git a/source/WorldServer/NPC.cpp b/source/WorldServer/NPC.cpp index c892840..e9cf623 100644 --- a/source/WorldServer/NPC.cpp +++ b/source/WorldServer/NPC.cpp @@ -345,7 +345,7 @@ void NPC::InCombat(bool val){ } } - int8 ruleAutoLockEncounter = rule_manager.GetGlobalRule(R_World, AutoLockEncounter)->GetInt8(); + int8 ruleAutoLockEncounter = rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_World, AutoLockEncounter)->GetInt8(); in_combat = val; if(val){ LogWrite(NPC__DEBUG, 3, "NPC", "'%s' engaged in combat with '%s'", this->GetName(), ( GetTarget() ) ? GetTarget()->GetName() : "Unknown" ); diff --git a/source/WorldServer/NPC_AI.cpp b/source/WorldServer/NPC_AI.cpp index ff89588..b062a93 100644 --- a/source/WorldServer/NPC_AI.cpp +++ b/source/WorldServer/NPC_AI.cpp @@ -395,7 +395,7 @@ vector* Brain::GetHateList() { void Brain::MoveCloser(Spawn* target) { if (target && m_body->GetFollowTarget() != target) - m_body->SetFollowTarget(target, rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()); + m_body->SetFollowTarget(target, rule_manager.GetZoneRule(m_body->GetZone() ? m_body->GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat()); if (m_body->GetFollowTarget() && !m_body->following) { m_body->CalculateRunningLocation(true); @@ -478,7 +478,7 @@ bool Brain::CheckBuffs() { } void Brain::ProcessMelee(Entity* target, float distance) { - if(distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) + if(distance > rule_manager.GetZoneRule(m_body->GetZone() ? m_body->GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat()) MoveCloser((Spawn*)target); else { if (target) { @@ -581,12 +581,12 @@ bool Brain::CheckLootAllowed(Entity* entity) { LogWrite(LOOT__INFO, 0, "Loot", "%s: CheckLootAllowed failed, looter spawn id %u does not match received %s(%u)", GetBody()->GetName(), m_body->GetLooterSpawnID(), entity->GetName(), entity->GetID()); return false; } - if (rule_manager.GetGlobalRule(R_Loot, AllowChestUnlockByDropTime)->GetInt8() - && m_body->GetChestDropTime() > 0 && Timer::GetCurrentTime2() >= m_body->GetChestDropTime() + (rule_manager.GetGlobalRule(R_Loot, ChestUnlockedTimeDrop)->GetInt32() * 1000)) { + if (rule_manager.GetZoneRule(m_body->GetZone() ? m_body->GetZone()->GetZoneID() : 0, R_Loot, AllowChestUnlockByDropTime)->GetInt8() + && m_body->GetChestDropTime() > 0 && Timer::GetCurrentTime2() >= m_body->GetChestDropTime() + (rule_manager.GetZoneRule(m_body->GetZone() ? m_body->GetZone()->GetZoneID() : 0, R_Loot, ChestUnlockedTimeDrop)->GetInt32() * 1000)) { return true; } - if (rule_manager.GetGlobalRule(R_Loot, AllowChestUnlockByTrapTime)->GetInt8() - && m_body->GetTrapOpenedTime() > 0 && Timer::GetCurrentTime2() >= m_body->GetChestDropTime() + (rule_manager.GetGlobalRule(R_Loot, ChestUnlockedTimeTrap)->GetInt32() * 1000)) { + if (rule_manager.GetZoneRule(m_body->GetZone() ? m_body->GetZone()->GetZoneID() : 0, R_Loot, AllowChestUnlockByTrapTime)->GetInt8() + && m_body->GetTrapOpenedTime() > 0 && Timer::GetCurrentTime2() >= m_body->GetChestDropTime() + (rule_manager.GetZoneRule(m_body->GetZone() ? m_body->GetZone()->GetZoneID() : 0, R_Loot, ChestUnlockedTimeTrap)->GetInt32() * 1000)) { return true; } if ((m_body->GetLootMethod() == GroupLootMethod::METHOD_LOTTO || m_body->GetLootMethod() == GroupLootMethod::METHOD_NEED_BEFORE_GREED) && m_body->HasSpawnLootWindowCompleted(entity->GetID())) { @@ -770,7 +770,7 @@ void CombatPetBrain::Think() { float distance = GetBody()->GetDistance(target); // If out of melee range then move closer - if (distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) + if (distance > rule_manager.GetZoneRule(m_body->GetZone() ? m_body->GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat()) MoveCloser((Spawn*)target); } @@ -802,7 +802,7 @@ void NonCombatPetBrain::Think() { float distance = GetBody()->GetDistance(target); // If out of melee range then move closer - if (distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) + if (distance > rule_manager.GetZoneRule(m_body->GetZone() ? m_body->GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat()) MoveCloser((Spawn*)target); } diff --git a/source/WorldServer/Player.cpp b/source/WorldServer/Player.cpp index b1f59ff..b4eb6ee 100644 --- a/source/WorldServer/Player.cpp +++ b/source/WorldServer/Player.cpp @@ -826,13 +826,13 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal packet->setDataByName("coins_plat", info_struct->get_coin_plat());// dov confirmed Skill* skill = player->GetSkillByName("Swimming", false); - float breath_modifier = rule_manager.GetGlobalRule(R_Player, SwimmingSkillMinBreathLength)->GetFloat(); + float breath_modifier = rule_manager.GetZoneRule(player->GetZone() ? player->GetZone()->GetZoneID() : 0, R_Player, SwimmingSkillMinBreathLength)->GetFloat(); if(skill) { int32 max_val = 450; if(skill->max_val > 0) max_val = skill->max_val; float diff = (float)(skill->current_val + player->GetStat(ITEM_STAT_SWIMMING)) / (float)max_val; - float max_breath_mod = rule_manager.GetGlobalRule(R_Player, SwimmingSkillMaxBreathLength)->GetFloat(); + float max_breath_mod = rule_manager.GetZoneRule(player->GetZone() ? player->GetZone()->GetZoneID() : 0, R_Player, SwimmingSkillMaxBreathLength)->GetFloat(); float diff_mod = max_breath_mod * diff; if(diff_mod > max_breath_mod) breath_modifier = max_breath_mod; @@ -6835,7 +6835,7 @@ bool Player::CanSeeInvis(Entity* target) else if (target->IsInvis() && HasSeeInvisSpell()) return true; - sint32 radius = rule_manager.GetGlobalRule(R_PVP, InvisPlayerDiscoveryRange)->GetSInt32(); + sint32 radius = rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_PVP, InvisPlayerDiscoveryRange)->GetSInt32(); if (radius == 0) // radius of 0 is always seen return true; @@ -7512,7 +7512,7 @@ void Player::CalculatePlayerHPPower(int16 new_level) { bool Player::IsAllowedCombatEquip(int8 slot, bool send_message) { bool rule_pass = true; - if(EngagedInCombat() && rule_manager.GetGlobalRule(R_Player, AllowPlayerEquipCombat)->GetInt8() == 0) { + if(EngagedInCombat() && rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Player, AllowPlayerEquipCombat)->GetInt8() == 0) { switch(slot) { case EQ2_PRIMARY_SLOT: case EQ2_SECONDARY_SLOT: diff --git a/source/WorldServer/Rules/Rules.cpp b/source/WorldServer/Rules/Rules.cpp index 9055da9..3b0f8b3 100644 --- a/source/WorldServer/Rules/Rules.cpp +++ b/source/WorldServer/Rules/Rules.cpp @@ -513,17 +513,18 @@ bool RuleManager::SetZoneRuleSet(int32 zone_id, int32 rule_set_id) { Rule * RuleManager::GetZoneRule(int32 zone_id, int32 category, int32 type) { Rule *ret = 0; - /* we never want to return null so MAKE SURE the rule exists. if this assertion fails then the server admin must fix the problem */ - assert(rules.count(category) > 0); - assert(rules[category].count(type) > 0); - /* first try to get the zone rule */ - m_zone_rule_sets.readlock(__FUNCTION__, __LINE__); - if (zone_rule_sets.count(zone_id) > 0) - ret = zone_rule_sets[zone_id]->GetRule(category, type); - m_zone_rule_sets.releasereadlock(__FUNCTION__, __LINE__); - - return ret ? ret : rules[category][type]; + if(zone_id) { + m_zone_rule_sets.readlock(__FUNCTION__, __LINE__); + if (zone_rule_sets.count(zone_id) > 0) + ret = zone_rule_sets[zone_id]->GetRule(category, type); + m_zone_rule_sets.releasereadlock(__FUNCTION__, __LINE__); + } + if(!ret) { + ret = GetGlobalRule(category, type); + } + + return ret; } void RuleManager::ClearZoneRuleSets() { diff --git a/source/WorldServer/Spawn.cpp b/source/WorldServer/Spawn.cpp index bf54dbd..92a7f50 100644 --- a/source/WorldServer/Spawn.cpp +++ b/source/WorldServer/Spawn.cpp @@ -1388,6 +1388,10 @@ ZoneServer* Spawn::GetZone(){ return zone; } +int32 Spawn::GetZoneID(){ + return zone ? zone->GetZoneID() : 0; +} + void Spawn::SetZone(ZoneServer* in_zone, int32 version){ zone = in_zone; @@ -2366,7 +2370,7 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) { int8 classicFlags = 0; // radius of 0 is always seen, -1 is never seen (unless items/spells override), larger than 0 is a defined radius to restrict visibility - sint32 radius = rule_manager.GetGlobalRule(R_PVP, InvisPlayerDiscoveryRange)->GetSInt32(); + sint32 radius = rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_PVP, InvisPlayerDiscoveryRange)->GetSInt32(); if (radius != 0 && (Spawn*)spawn != this && this->IsPlayer() && !spawn->CanSeeInvis((Entity*)this)) spawnHiddenFromClient = true; @@ -3097,20 +3101,20 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){ float dist = GetDistance(followTarget, true); if ((!EngagedInCombat() && m_followDistance > 0 && dist <= m_followDistance) || - (dist <= rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat())) { + (dist <= rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat())) { ClearRunningLocations(); CalculateRunningLocation(true); } else if (loc) { float distance = GetDistance(followTarget, loc->x, loc->y, loc->z); if ( (!EngagedInCombat() && m_followDistance > 0 && distance > m_followDistance) || - ( EngagedInCombat() && distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat())) { - MoveToLocation(followTarget, rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat(), true, loc->mapped); + ( EngagedInCombat() && distance > rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat())) { + MoveToLocation(followTarget, rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat(), true, loc->mapped); CalculateRunningLocation(); } } else { - MoveToLocation(followTarget, rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat(), false); + MoveToLocation(followTarget, rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat(), false); CalculateRunningLocation(); } } @@ -3374,7 +3378,7 @@ void Spawn::RunToLocation(float x, float y, float z, float following_x, float fo return; } - if(!IsWidget() && (!EngagedInCombat() || GetDistance(GetTarget()) > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat())) + if(!IsWidget() && (!EngagedInCombat() || GetDistance(GetTarget()) > rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat())) FaceTarget(x, z); SetPos(&appearance.pos.X2, x, false); SetPos(&appearance.pos.Z2, z, false); @@ -3665,7 +3669,7 @@ void Spawn::CalculateRunningLocation(bool stop){ if (continueElseIf && GetZone() && GetTarget() != NULL && EngagedInCombat()) { - if (GetDistance(GetTarget()) > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) + if (GetDistance(GetTarget()) > rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Combat, MaxCombatRange)->GetFloat()) { if ((IsFlyingCreature() || IsWaterCreature() || InWater()) && CheckLoS(GetTarget())) AddRunningLocation(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetSpeed(), 0, false); @@ -3953,7 +3957,7 @@ void Spawn::CheckEncounterState(Entity* victim, bool test_auto_lock) { attacker->GetInfoStruct()->set_engaged_encounter(1); } - int8 skip_loot_gray_mob_flag = rule_manager.GetGlobalRule(R_Loot, SkipLootGrayMob)->GetInt8(); + int8 skip_loot_gray_mob_flag = rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Loot, SkipLootGrayMob)->GetInt8(); int8 difficulty = attacker->GetArrowColor(victim->GetLevel()); @@ -4751,7 +4755,7 @@ bool Spawn::IsWaterCreature() void Spawn::SetFlyingCreature() { - if(!IsEntity() || !rule_manager.GetGlobalRule(R_Spawn, UseHardCodeFlyingModelType)->GetInt8()) + if(!IsEntity() || !rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Spawn, UseHardCodeFlyingModelType)->GetInt8()) return; if(((Entity*)this)->GetInfoStruct()->get_flying_type() > 0) // DB spawn npc flag already set @@ -4771,7 +4775,7 @@ void Spawn::SetFlyingCreature() { } void Spawn::SetWaterCreature() { - if(!IsEntity() || !rule_manager.GetGlobalRule(R_Spawn, UseHardCodeWaterModelType)->GetInt8()) + if(!IsEntity() || !rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Spawn, UseHardCodeWaterModelType)->GetInt8()) return; if(((Entity*)this)->GetInfoStruct()->get_water_type() > 0) // DB spawn npc flag already set @@ -5049,13 +5053,13 @@ bool Spawn::HasLootWindowCompleted() { void Spawn::StartLootTimer(Spawn* looter) { if (!IsLootTimerRunning()) { - int32 loot_timer_time = rule_manager.GetGlobalRule(R_Loot, LootDistributionTime)->GetInt32() * 1000; - if(rule_manager.GetGlobalRule(R_Loot, AllowChestUnlockByDropTime)->GetBool() && loot_timer_time > rule_manager.GetGlobalRule(R_Loot, ChestUnlockedTimeDrop)->GetInt32()*1000) { - loot_timer_time = (rule_manager.GetGlobalRule(R_Loot, ChestUnlockedTimeDrop)->GetInt32()*1000) / 2; + int32 loot_timer_time = rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Loot, LootDistributionTime)->GetInt32() * 1000; + if(rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Loot, AllowChestUnlockByDropTime)->GetBool() && loot_timer_time > rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Loot, ChestUnlockedTimeDrop)->GetInt32()*1000) { + loot_timer_time = (rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Loot, ChestUnlockedTimeDrop)->GetInt32()*1000) / 2; } - if(rule_manager.GetGlobalRule(R_Loot, AllowChestUnlockByTrapTime)->GetBool() && loot_timer_time > rule_manager.GetGlobalRule(R_Loot, ChestUnlockedTimeTrap)->GetInt32()*1000) { - loot_timer_time = (rule_manager.GetGlobalRule(R_Loot, ChestUnlockedTimeTrap)->GetInt32()*1000) / 2; + if(rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Loot, AllowChestUnlockByTrapTime)->GetBool() && loot_timer_time > rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Loot, ChestUnlockedTimeTrap)->GetInt32()*1000) { + loot_timer_time = (rule_manager.GetZoneRule(GetZone() ? GetZone()->GetZoneID() : 0, R_Loot, ChestUnlockedTimeTrap)->GetInt32()*1000) / 2; } if(loot_timer_time < 1000) { diff --git a/source/WorldServer/Spawn.h b/source/WorldServer/Spawn.h index 373f265..28d9d32 100644 --- a/source/WorldServer/Spawn.h +++ b/source/WorldServer/Spawn.h @@ -1047,6 +1047,7 @@ public: void SetLastAttacker(Spawn* spawn); bool TakeDamage(int32 damage); ZoneServer* GetZone(); + int32 GetZoneID(); virtual void SetZone(ZoneServer* in_zone, int32 version=0); void SetFactionID(int32 val) { faction_id = val; } int32 GetFactionID(){ diff --git a/source/WorldServer/SpellProcess.cpp b/source/WorldServer/SpellProcess.cpp index cc67b35..18e9492 100644 --- a/source/WorldServer/SpellProcess.cpp +++ b/source/WorldServer/SpellProcess.cpp @@ -743,7 +743,7 @@ void SpellProcess::SendFinishedCast(LuaSpell* spell, Client* client){ Spawn* target = client->GetPlayer()->GetZone()->GetSpawnByID(spell->initial_target); if(target) { float distance = client->GetPlayer()->GetDistance(target); - if(distance <= rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) { + if(distance <= rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Combat, MaxCombatRange)->GetFloat()) { client->GetPlayer()->InCombat(true, false); client->GetPlayer()->SetRangeAttack(false); } diff --git a/source/WorldServer/World.cpp b/source/WorldServer/World.cpp index 7e862a4..f84875e 100644 --- a/source/WorldServer/World.cpp +++ b/source/WorldServer/World.cpp @@ -581,7 +581,7 @@ void ZoneList::Remove(ZoneServer* zone) { MZoneList.releasewritelock(__FUNCTION__, __LINE__); ZoneServer* alternativeZone = Get(zoneName, false, false); - if(!alternativeZone && !rule_manager.GetGlobalRule(R_World, MemoryCacheZoneMaps)->GetBool()) { + if(!alternativeZone && !rule_manager.GetZoneRule(zone->GetZoneID(), R_World, MemoryCacheZoneMaps)->GetBool()) { world.RemoveMaps(std::string(zoneName)); } } diff --git a/source/WorldServer/client.cpp b/source/WorldServer/client.cpp index 65ba1be..a92a952 100644 --- a/source/WorldServer/client.cpp +++ b/source/WorldServer/client.cpp @@ -684,7 +684,7 @@ void Client::HandlePlayerRevive(int32 point_id) safe_delete(packet); } - if(rule_manager.GetGlobalRule(R_Combat, EnableSpiritShards)->GetBool()) + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_Combat, EnableSpiritShards)->GetBool()) { NPC* shard = player->InstantiateSpiritShard(origX, origY, origZ, origHeading, origGridID, originalZone); @@ -841,7 +841,7 @@ void Client::SendCharInfo() { } //Allow this player to change their last name if they meet the level requirement - if (!player->get_character_flag(CF_ENABLE_CHANGE_LASTNAME) && player->GetLevel() >= rule_manager.GetGlobalRule(R_Player, MinLastNameLevel)->GetInt8()) + if (!player->get_character_flag(CF_ENABLE_CHANGE_LASTNAME) && player->GetLevel() >= rule_manager.GetZoneRule(GetCurrentZoneID(), R_Player, MinLastNameLevel)->GetInt8()) player->set_character_flag(CF_ENABLE_CHANGE_LASTNAME); safe_delete(items); @@ -1229,9 +1229,9 @@ bool Client::HandlePacket(EQApplicationPacket* app) { if (!camp_timer) { int16 camp_time = 20; // default if rule cannot be found if (GetAdminStatus() >= 100) - camp_time = rule_manager.GetGlobalRule(R_World, GMCampTimer)->GetInt16(); + camp_time = rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, GMCampTimer)->GetInt16(); else - camp_time = rule_manager.GetGlobalRule(R_World, PlayerCampTimer)->GetInt16(); + camp_time = rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, PlayerCampTimer)->GetInt16(); PacketStruct* response = configReader.getStruct("WS_Camp", GetVersion()); if (response) { @@ -2337,7 +2337,7 @@ bool Client::HandlePacket(EQApplicationPacket* app) { HouseZone* hz = world.GetHouseZone(house_id); if (hz) { bool got_bank_money = BankHasCoin(hz->cost_coin); - int8 disable_alignment_req = rule_manager.GetGlobalRule(R_Player, DisableHouseAlignmentRequirement)->GetInt8(); + int8 disable_alignment_req = rule_manager.GetZoneRule(GetCurrentZoneID(), R_Player, DisableHouseAlignmentRequirement)->GetInt8(); std::vector houses = world.GetAllPlayerHouses(GetCharacterID()); if (houses.size() > 24) { @@ -3721,7 +3721,7 @@ bool Client::Process(bool zone_process) { LogWrite(CCLIENT__DEBUG, 1, "Client", "%s, ProcessQuestUpdates", __FUNCTION__, __LINE__); ProcessQuestUpdates(); } - int32 queue_timer_delay = rule_manager.GetGlobalRule(R_Client, QuestQueueTimer)->GetInt32(); + int32 queue_timer_delay = rule_manager.GetZoneRule(GetCurrentZoneID(), R_Client, QuestQueueTimer)->GetInt32(); if(queue_timer_delay < 10) { queue_timer_delay = 10; } @@ -3770,12 +3770,12 @@ bool Client::Process(bool zone_process) { enabled_player_pos_timer = true; if(!underworld_cooldown_timer.Enabled() || (underworld_cooldown_timer.Enabled() && underworld_cooldown_timer.Check())) { bool underworld = false; - if(rule_manager.GetGlobalRule(R_Zone, UseMapUnderworldCoords)->GetBool()) { + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_Zone, UseMapUnderworldCoords)->GetBool()) { if(GetCurrentZone()->GetUnderWorld() != -1000000.0f) { if(GetPlayer()->GetY() < GetCurrentZone()->GetUnderWorld()) underworld = true; } - else if(GetPlayer()->GetMap() && GetPlayer()->GetMap()->GetMinY() != 9999999.0f && GetPlayer()->GetY() < (GetPlayer()->GetMap()->GetMinY() + rule_manager.GetGlobalRule(R_Zone, MapUnderworldCoordOffset)->GetFloat())) { + else if(GetPlayer()->GetMap() && GetPlayer()->GetMap()->GetMinY() != 9999999.0f && GetPlayer()->GetY() < (GetPlayer()->GetMap()->GetMinY() + rule_manager.GetZoneRule(GetCurrentZoneID(), R_Zone, MapUnderworldCoordOffset)->GetFloat())) { underworld = true; } } @@ -4113,6 +4113,10 @@ ZoneServer* Client::GetCurrentZone() { return current_zone; } +int32 Client::GetCurrentZoneID() { + return current_zone ? current_zone->GetZoneID() : 0; +} + int8 Client::GetMessageChannelColor(int8 channel_type) { if (GetVersion() >= 973 && GetVersion() <= 1000) { if (channel_type == CHANNEL_LOOT) @@ -4672,7 +4676,7 @@ bool Client::TryZoneInstance(int32 zoneID, bool zone_coords_valid) { instance_zone = zone_list.GetByLowestPopulation(zoneID); if (instance_zone) { // Check the current population against the max population, if greater or equal start a new version - if (instance_zone->GetClientCount() >= rule_manager.GetGlobalRule(R_Zone, MaxPlayers)->GetInt32()) + if (instance_zone->GetClientCount() >= rule_manager.GetZoneRule(GetCurrentZoneID(), R_Zone, MaxPlayers)->GetInt32()) instance_zone = zone_list.GetByInstanceID(0, zoneID); } else @@ -4804,7 +4808,7 @@ bool Client::CheckZoneAccess(const char* zoneName) { LogWrite(CCLIENT__DEBUG, 0, "Client", "Access Requirements: status %i, level %i - %i, req >= %i version", zoneMinStatus, zoneMinLevel, zoneMaxLevel, zoneMinVersion); // use ZoneLevelOverrideStatus in both min_level and max_level checks - sint16 ZoneLevelOverrideStatus = rule_manager.GetGlobalRule(R_Zone, MinZoneLevelOverrideStatus)->GetSInt16(); + sint16 ZoneLevelOverrideStatus = rule_manager.GetZoneRule(GetCurrentZoneID(), R_Zone, MinZoneLevelOverrideStatus)->GetSInt16(); if ((zoneMinVersion > 0) && (GetVersion() < zoneMinVersion)) { @@ -4839,7 +4843,7 @@ bool Client::CheckZoneAccess(const char* zoneName) { { LogWrite(CCLIENT__DEBUG, 0, "Client", "Zone MinStatus of %i challenge...", zoneMinStatus); - sint16 ZoneAccessOverrideStatus = rule_manager.GetGlobalRule(R_Zone, MinZoneAccessOverrideStatus)->GetSInt16(); + sint16 ZoneAccessOverrideStatus = rule_manager.GetZoneRule(GetCurrentZoneID(), R_Zone, MinZoneAccessOverrideStatus)->GetSInt16(); if (ZoneAccessOverrideStatus && ZoneAccessOverrideStatus > GetAdminStatus()) { LogWrite(CCLIENT__DEBUG, 0, "Client", "Player denied access to zone '%s' (status req: %i)", zoneName, GetAdminStatus()); @@ -5263,7 +5267,7 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) { safe_delete(command_packet); } - if (!player->get_character_flag(CF_ENABLE_CHANGE_LASTNAME) && new_level >= rule_manager.GetGlobalRule(R_Player, MinLastNameLevel)->GetInt8()) + if (!player->get_character_flag(CF_ENABLE_CHANGE_LASTNAME) && new_level >= rule_manager.GetZoneRule(GetCurrentZoneID(), R_Player, MinLastNameLevel)->GetInt8()) player->set_character_flag(CF_ENABLE_CHANGE_LASTNAME); SendNewAdventureSpells(); @@ -5303,7 +5307,7 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) { player_skills->SetSkillCapsByType(SKILL_TYPE_ARMOR, new_skill_cap); player_skills->SetSkillCapsByType(SKILL_TYPE_SHIELD, new_skill_cap); - if(rule_manager.GetGlobalRule(R_Player, AutoSkillUpBaseSkills)->GetBool()) { + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_Player, AutoSkillUpBaseSkills)->GetBool()) { //SKILL_TYPE_ARMOR/SKILL_TYPE_SHIELD always has the same current / max values player_skills->SetSkillValuesByType(SKILL_TYPE_ARMOR, new_skill_cap, false); player_skills->SetSkillValuesByType(SKILL_TYPE_SHIELD, new_skill_cap, false); @@ -5312,7 +5316,7 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) { player_skills->SetSkillCapsByType(SKILL_TYPE_CLASS, new_skill_cap); player_skills->SetSkillCapsByType(SKILL_TYPE_WEAPON, new_skill_cap); - if(rule_manager.GetGlobalRule(R_Player, AutoSkillUpBaseSkills)->GetBool()) { + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_Player, AutoSkillUpBaseSkills)->GetBool()) { //SKILL_TYPE_CLASS/SKILL_TYPE_WEAPON always has the same current/max values player_skills->SetSkillValuesByType(SKILL_TYPE_CLASS, new_skill_cap, false); player_skills->SetSkillValuesByType(SKILL_TYPE_WEAPON, new_skill_cap, false); @@ -6045,7 +6049,7 @@ void Client::OpenChest(Spawn* entity, bool attemptDisarm) if (disarmSkill->CheckDisarmSkill(entity->GetLevel(), chest_difficulty) < 1) { CastGroupOrSelf(entity && entity->IsEntity() ? (Entity*)entity : 0, nextTrap.spell_id, nextTrap.spell_tier, - rule_manager.GetGlobalRule(R_Loot, ChestTriggerRadiusGroup)->GetFloat()); + rule_manager.GetZoneRule(GetCurrentZoneID(), R_Loot, ChestTriggerRadiusGroup)->GetFloat()); Message(CHANNEL_NARRATIVE, "You trigger the trap on %s!", modelName.c_str()); } else @@ -6059,7 +6063,7 @@ void Client::OpenChest(Spawn* entity, bool attemptDisarm) else // no disarm skill, always fail { CastGroupOrSelf(entity && entity->IsEntity() ? (Entity*)entity : 0, nextTrap.spell_id, nextTrap.spell_tier, - rule_manager.GetGlobalRule(R_Loot, ChestTriggerRadiusGroup)->GetFloat()); + rule_manager.GetZoneRule(GetCurrentZoneID(), R_Loot, ChestTriggerRadiusGroup)->GetFloat()); Message(CHANNEL_NARRATIVE, "You trigger the trap on %s!", modelName.c_str()); } } @@ -8491,7 +8495,7 @@ void Client::SendBuyMerchantList(bool sell) { else tmp_level = item->generic_info.tradeskill_default_level; packet->setArrayDataByName("level", tmp_level, i); - if(rule_manager.GetGlobalRule(R_World, DisplayItemTiers)->GetBool()) { + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, DisplayItemTiers)->GetBool()) { packet->setArrayDataByName("tier", item->details.tier, i); } packet->setArrayDataByName("item_id2", item->details.item_id, i); @@ -8687,7 +8691,7 @@ void Client::SendSellMerchantList(bool sell) { tmp_level = item->generic_info.tradeskill_default_level; packet->setArrayDataByName("level", item->details.recommended_level, i); - if(rule_manager.GetGlobalRule(R_World, DisplayItemTiers)->GetBool()) { + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, DisplayItemTiers)->GetBool()) { packet->setArrayDataByName("tier", item->details.tier, i); } packet->setArrayDataByName("item_id2", item->details.item_id, i); @@ -8769,7 +8773,7 @@ void Client::SendBuyBackList(bool sell) { else tmp_level = master_item->generic_info.tradeskill_default_level; packet->setArrayDataByName("level", tmp_level, i); - if(rule_manager.GetGlobalRule(R_World, DisplayItemTiers)->GetBool()) { + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, DisplayItemTiers)->GetBool()) { packet->setArrayDataByName("tier", master_item->details.tier, i); } packet->setArrayDataByName("item_id2", master_item->details.item_id, i); @@ -8841,7 +8845,7 @@ void Client::SendRepairList() { packet->setArrayDataByName("level", tmp_level, i);*/ packet->setArrayDataByName("level", item->generic_info.adventure_default_level, i); - if(rule_manager.GetGlobalRule(R_World, DisplayItemTiers)->GetBool()) { + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, DisplayItemTiers)->GetBool()) { packet->setArrayDataByName("tier", item->details.tier, i); } packet->setArrayDataByName("item_id2", item->details.item_id, i); @@ -8892,7 +8896,7 @@ void Client::ShowLottoWindow() { Spawn* spawn = GetMerchantTransaction(); if (spawn) { - int32 item_id = rule_manager.GetGlobalRule(R_World, GamblingTokenItemID)->GetInt32(); + int32 item_id = rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, GamblingTokenItemID)->GetInt32(); if (!item_id) { LogWrite(WORLD__ERROR, 0, "World", "No GamblingTokenItemID rule set!"); @@ -8927,7 +8931,7 @@ void Client::ShowLottoWindow() { packet->setArrayDataByName("icon", item->GetIcon(GetVersion())); packet->setArrayDataByName("level", item->generic_info.adventure_default_level); - if(rule_manager.GetGlobalRule(R_World, DisplayItemTiers)->GetBool()) { + if(rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, DisplayItemTiers)->GetBool()) { packet->setArrayDataByName("tier", item->details.tier); } packet->setArrayDataByName("item_id2", item->details.item_id); @@ -10246,7 +10250,7 @@ void Client::BeginWaypoint(const char* waypoint_name, float x, float y, float z) void Client::InspectPlayer(Player* player_to_inspect) { int source_pvp_alignment = GetPlayer()->GetPVPAlignment(); int target_pvp_alignment = player_to_inspect->GetPVPAlignment(); - bool pvp_allowed = rule_manager.GetGlobalRule(R_PVP, AllowPVP)->GetBool(); + bool pvp_allowed = rule_manager.GetZoneRule(GetCurrentZoneID(), R_PVP, AllowPVP)->GetBool(); if(pvp_allowed == true){ if(source_pvp_alignment != target_pvp_alignment){ @@ -11317,16 +11321,16 @@ void Client::SavePlayerImages() { LogWrite(CCLIENT__DEBUG, 0, "Client", "Saving %s image for player %s (%u)", (incoming_paperdoll.image_type == PAPERDOLL_TYPE_FULL ? "paperdoll" : "headshot"), GetPlayer()->GetName(), GetCharacterID()); // Save the paperdoll image if the server allows it - if (incoming_paperdoll.image_type == PAPERDOLL_TYPE_FULL && rule_manager.GetGlobalRule(R_World, SavePaperdollImage)->GetBool()) + if (incoming_paperdoll.image_type == PAPERDOLL_TYPE_FULL && rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, SavePaperdollImage)->GetBool()) database.SaveCharacterPicture(GetCharacterID(), incoming_paperdoll.image_type, incoming_paperdoll.image_bytes, incoming_paperdoll.current_size_bytes); if (incoming_paperdoll.image_type == PAPERDOLL_TYPE_HEAD) { // Save the head shot if the server allows it - if (rule_manager.GetGlobalRule(R_World, SaveHeadshotImage)->GetBool()) + if (rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, SaveHeadshotImage)->GetBool()) database.SaveCharacterPicture(GetCharacterID(), incoming_paperdoll.image_type, incoming_paperdoll.image_bytes, incoming_paperdoll.current_size_bytes); // Send the head shot to the login server - if (rule_manager.GetGlobalRule(R_World, SendPaperdollImagesToLogin)->GetBool()) { + if (rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, SendPaperdollImagesToLogin)->GetBool()) { int32 size = incoming_paperdoll.current_size_bytes + CHARPICSTRUCT_MINSIZE; ServerPacket* packet = new ServerPacket(ServerOP_CharacterPicture, size); memset(packet->pBuffer, 0, size); @@ -11450,7 +11454,7 @@ bool Client::HandleNewLogin(int32 account_id, int32 access_code) GetPlayer()->vis_changed = false; GetPlayer()->info_changed = false; - bool pvp_allowed = rule_manager.GetGlobalRule(R_PVP, AllowPVP)->GetBool(); + bool pvp_allowed = rule_manager.GetZoneRule(GetCurrentZoneID(), R_PVP, AllowPVP)->GetBool(); if (pvp_allowed) this->GetPlayer()->SetAttackable(1); MDeletePlayer.writelock(__FUNCTION__, __LINE__); @@ -12360,7 +12364,7 @@ void Client::AwardCoins(int64 total_coins, std::string reason) void Client::TriggerSpellSave() { - int32 interval = rule_manager.GetGlobalRule(R_Spells, PlayerSpellSaveStateWaitInterval)->GetInt32(); + int32 interval = rule_manager.GetZoneRule(GetCurrentZoneID(), R_Spells, PlayerSpellSaveStateWaitInterval)->GetInt32(); // default to not have some bogus value in the rule if(interval < 1) interval = 100; @@ -12376,7 +12380,7 @@ void Client::TriggerSpellSave() int32 elapsed_time = save_spell_state_timer.GetElapsedTime(); save_spell_state_time_bucket += elapsed_time; - int32 save_wait_cap = rule_manager.GetGlobalRule(R_Spells, PlayerSpellSaveStateCap)->GetInt32(); + int32 save_wait_cap = rule_manager.GetZoneRule(GetCurrentZoneID(), R_Spells, PlayerSpellSaveStateCap)->GetInt32(); // default to not have some bogus value in the rule if(save_wait_cap < interval) @@ -12739,7 +12743,7 @@ bool Client::CheckConsumptionAllowed(int16 slot, bool send_message) { void Client::StartLinkdeadTimer() { if(!linkdead_timer) { - int32 LD_Timer = rule_manager.GetGlobalRule(R_World, LinkDeadTimer)->GetInt32(); + int32 LD_Timer = rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, LinkDeadTimer)->GetInt32(); LogWrite(CCLIENT__DEBUG, 0, "Client", "Starting linkdead timer for %s (timer %u seconds)", GetPlayer()->GetName(), (LD_Timer/1000)); linkdead_timer = new Timer(LD_Timer); linkdead_timer->Enable(); diff --git a/source/WorldServer/client.h b/source/WorldServer/client.h index 805a35b..cffb112 100644 --- a/source/WorldServer/client.h +++ b/source/WorldServer/client.h @@ -222,6 +222,7 @@ public: bool CheckZoneAccess(const char* zoneName); ZoneServer* GetCurrentZone(); + int32 GetCurrentZoneID(); void SetCurrentZoneByInstanceID(int32 id, int32 zoneid); //void SetCurrentZoneByInstanceID(instanceid, zoneid); void SetCurrentZone(int32 id); diff --git a/source/WorldServer/zoneserver.cpp b/source/WorldServer/zoneserver.cpp index 247a5fe..1eef0d2 100644 --- a/source/WorldServer/zoneserver.cpp +++ b/source/WorldServer/zoneserver.cpp @@ -378,12 +378,12 @@ void ZoneServer::CancelThreads() { void ZoneServer::InitWeather() { - weather_enabled = rule_manager.GetGlobalRule(R_Zone, WeatherEnabled)->GetBool(); + weather_enabled = rule_manager.GetZoneRule(GetZoneID(), R_Zone, WeatherEnabled)->GetBool(); if( weather_enabled && isWeatherAllowed()) { string tmp; // set up weather system when zone starts up - weather_type = rule_manager.GetGlobalRule(R_Zone, WeatherType)->GetInt8(); + weather_type = rule_manager.GetZoneRule(GetZoneID(), R_Zone, WeatherType)->GetInt8(); switch(weather_type) { case 3: tmp = "Chaotic"; break; @@ -393,14 +393,14 @@ void ZoneServer::InitWeather() } LogWrite(ZONE__DEBUG, 0, "Zone", "%s: Setting up '%s' weather", zone_name, tmp.c_str()); - weather_frequency = rule_manager.GetGlobalRule(R_Zone, WeatherChangeFrequency)->GetInt32(); + weather_frequency = rule_manager.GetZoneRule(GetZoneID(), R_Zone, WeatherChangeFrequency)->GetInt32(); LogWrite(ZONE__DEBUG, 1, "Zone", "%s: Change weather every %u seconds", zone_name, weather_frequency); - weather_change_chance = rule_manager.GetGlobalRule(R_Zone, WeatherChangeChance)->GetInt8(); + weather_change_chance = rule_manager.GetZoneRule(GetZoneID(), R_Zone, WeatherChangeChance)->GetInt8(); LogWrite(ZONE__DEBUG, 1, "Zone", "%s: Chance of weather change: %i%%", zone_name, weather_change_chance); - weather_min_severity = rule_manager.GetGlobalRule(R_Zone, MinWeatherSeverity)->GetFloat(); - weather_max_severity = rule_manager.GetGlobalRule(R_Zone, MaxWeatherSeverity)->GetFloat(); + weather_min_severity = rule_manager.GetZoneRule(GetZoneID(), R_Zone, MinWeatherSeverity)->GetFloat(); + weather_max_severity = rule_manager.GetZoneRule(GetZoneID(), R_Zone, MaxWeatherSeverity)->GetFloat(); LogWrite(ZONE__DEBUG, 1, "Zone", "%s: Weather Severity min/max is %.2f - %.2f", zone_name, weather_min_severity, weather_max_severity); // Allow a random roll to determine if weather should start out severe or calm if( MakeRandomInt(1, 100) > 50) @@ -415,12 +415,12 @@ void ZoneServer::InitWeather() } LogWrite(ZONE__DEBUG, 1, "Zone", "%s: Weather Severity set to %.2f, pattern: %i", zone_name, weather_current_severity, weather_pattern); - weather_change_amount = rule_manager.GetGlobalRule(R_Zone, WeatherChangePerInterval)->GetFloat(); + weather_change_amount = rule_manager.GetZoneRule(GetZoneID(), R_Zone, WeatherChangePerInterval)->GetFloat(); LogWrite(ZONE__DEBUG, 1, "Zone", "%s: Weather change by %.2f each interval", zone_name, weather_change_amount); if( weather_type > 0 ) { - weather_dynamic_offset = rule_manager.GetGlobalRule(R_Zone, WeatherDynamicMaxOffset)->GetFloat(); + weather_dynamic_offset = rule_manager.GetZoneRule(GetZoneID(), R_Zone, WeatherDynamicMaxOffset)->GetFloat(); LogWrite(ZONE__DEBUG, 1, "Zone", "%s: Weather Max Offset changes no more than %.2f each interval", zone_name, weather_dynamic_offset); } else @@ -428,7 +428,7 @@ void ZoneServer::InitWeather() SetRain(weather_current_severity); weather_last_changed_time = Timer::GetUnixTimeStamp(); - weatherTimer.Start(rule_manager.GetGlobalRule(R_Zone, WeatherTimer)->GetInt32()); + weatherTimer.Start(rule_manager.GetZoneRule(GetZoneID(), R_Zone, WeatherTimer)->GetInt32()); } } void ZoneServer::DeleteSpellProcess(){ @@ -1072,7 +1072,7 @@ void ZoneServer::AddEnemyList(NPC* npc){ if(faction_id <= 9) return; - if(!rule_manager.GetGlobalRule(R_Faction, AllowFactionBasedCombat)->GetBool()) { + if(!rule_manager.GetZoneRule(GetZoneID(), R_Faction, AllowFactionBasedCombat)->GetBool()) { LogWrite(FACTION__WARNING, 0, "Faction", "Faction Combat is DISABLED via R_Faction::AllowFactionBasedCombat rule!"); return; } @@ -2705,7 +2705,7 @@ void ZoneServer::AddLoot(NPC* npc, Spawn* killer, GroupLootMethod loot_method, i if(killer) { npc->SetLootMethod(loot_method, item_rarity, group_id); - int8 skip_loot_gray_mob_flag = rule_manager.GetGlobalRule(R_Loot, SkipLootGrayMob)->GetInt8(); + int8 skip_loot_gray_mob_flag = rule_manager.GetZoneRule(GetZoneID(), R_Loot, SkipLootGrayMob)->GetInt8(); if(skip_loot_gray_mob_flag) { Player* player = 0; if(killer->IsPlayer()) @@ -5946,8 +5946,8 @@ EQ2Packet* ZoneServer::GetZoneInfoPacket(Client* client){ safe_delete(slides); } - if(rule_manager.GetGlobalRule(R_Zone, UseMapUnderworldCoords)->GetBool() && client->GetPlayer()->GetMap()) { - packet->setDataByName("underworld", client->GetPlayer()->GetMap()->GetMinY() + rule_manager.GetGlobalRule(R_Zone, MapUnderworldCoordOffset)->GetFloat()); + if(rule_manager.GetZoneRule(GetZoneID(), R_Zone, UseMapUnderworldCoords)->GetBool() && client->GetPlayer()->GetMap()) { + packet->setDataByName("underworld", client->GetPlayer()->GetMap()->GetMinY() + rule_manager.GetZoneRule(GetZoneID(), R_Zone, MapUnderworldCoordOffset)->GetFloat()); } else { packet->setDataByName("underworld", underworld); @@ -6524,7 +6524,7 @@ void ZoneServer::CheckLocationGrids() { grid->players.Put(player, true); bool show_enter_location_popup = true; - bool discovery_enabled = rule_manager.GetGlobalRule(R_World, EnablePOIDiscovery)->GetBool(); + bool discovery_enabled = rule_manager.GetZoneRule(GetZoneID(), R_World, EnablePOIDiscovery)->GetBool(); if( grid->discovery && discovery_enabled && !player->DiscoveredLocation(grid->id) ) { @@ -7085,7 +7085,7 @@ void ZoneServer::ProcessAggroChecks(Spawn* spawn) { if (spawn->GetFactionID() < 1 || spawn->EngagedInCombat()) return; // If faction based combat is not allowed then no need to run the loops so just return out - if(!rule_manager.GetGlobalRule(R_Faction, AllowFactionBasedCombat)->GetBool()) + if(!rule_manager.GetZoneRule(GetZoneID(), R_Faction, AllowFactionBasedCombat)->GetBool()) return; if (spawn && spawn->IsNPC() && spawn->Alive())