Rules.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <assert.h>
  17. #include "../../common/debug.h"
  18. #include "../../common/Log.h"
  19. #include "../../common/database.h"
  20. #include "Rules.h"
  21. extern RuleManager rule_manager;
  22. Rule::Rule() {
  23. category = 0;
  24. type = 0;
  25. strncpy(value, "", sizeof(value));
  26. strncpy(combined, "NONE", sizeof(combined));
  27. }
  28. Rule::Rule(int32 category, int32 type, const char *value, const char *combined) {
  29. this->category = category;
  30. this->type = type;
  31. strncpy(this->value, value, sizeof(this->value));
  32. strncpy(this->combined, combined, sizeof(this->combined));
  33. }
  34. Rule::Rule (Rule *rule_in) {
  35. category = rule_in->GetCategory();
  36. type = rule_in->GetType();
  37. strncpy(value, rule_in->GetValue(), sizeof(value));
  38. strncpy(combined, rule_in->GetCombined(), sizeof(combined));
  39. }
  40. Rule::~Rule() {
  41. }
  42. RuleSet::RuleSet() {
  43. id = 0;
  44. memset(name, 0, sizeof(name));
  45. m_rules.SetName("RuleSet::rules");
  46. }
  47. RuleSet::RuleSet(RuleSet *in_rule_set) {
  48. assert(in_rule_set);
  49. map<int32, map<int32, Rule *> > * in_rules = in_rule_set->GetRules();
  50. map<int32, map<int32, Rule *> >::iterator itr;
  51. map<int32, Rule *>::iterator itr2;
  52. Rule * rule;
  53. m_rules.SetName("RuleSet::rules");
  54. id = in_rule_set->GetID();
  55. strncpy(name, in_rule_set->GetName(), sizeof(name));
  56. for (itr = in_rules->begin(); itr != in_rules->end(); itr++) {
  57. for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++) {
  58. rule = itr2->second;
  59. rules[rule->GetCategory()][rule->GetType()] = new Rule(rule);
  60. }
  61. }
  62. }
  63. RuleSet::~RuleSet() {
  64. ClearRules();
  65. }
  66. void RuleSet::CopyRulesInto(RuleSet *in_rule_set) {
  67. assert(in_rule_set);
  68. map<int32, map<int32, Rule *> > * in_rules = in_rule_set->GetRules();
  69. map<int32, map<int32, Rule *> >::iterator itr;
  70. map<int32, Rule *>::iterator itr2;
  71. Rule * rule;
  72. ClearRules();
  73. m_rules.writelock(__FUNCTION__, __LINE__);
  74. for (itr = in_rules->begin(); itr != in_rules->end(); itr++) {
  75. for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++) {
  76. rule = itr2->second;
  77. rules[rule->GetCategory()][rule->GetType()] = new Rule(rule);
  78. }
  79. }
  80. m_rules.releasewritelock(__FUNCTION__, __LINE__);
  81. }
  82. void RuleSet::AddRule(Rule *rule) {
  83. int32 category, type;
  84. assert(rule);
  85. category = rule->GetCategory();
  86. type = rule->GetType();
  87. m_rules.writelock(__FUNCTION__, __LINE__);
  88. if (rules[category].count(type) == 0)
  89. rules[category][type] = rule;
  90. else
  91. rules[category][type]->SetValue(rule->GetValue());
  92. m_rules.releasewritelock(__FUNCTION__, __LINE__);
  93. }
  94. Rule * RuleSet::GetRule(int32 category, int32 type) {
  95. Rule *ret = 0;
  96. m_rules.readlock(__FUNCTION__, __LINE__);
  97. if (rules[category].count(type) > 0)
  98. ret = rules[category][type];
  99. m_rules.releasereadlock(__FUNCTION__, __LINE__);
  100. if (!ret)
  101. ret = rule_manager.GetBlankRule();
  102. LogWrite(RULESYS__DEBUG, 5, "Rules", "Rule: %s, Value: %s", ret->GetCombined(), ret->GetValue());
  103. return ret;
  104. }
  105. Rule * RuleSet::GetRule(const char *category, const char *type) {
  106. map<int32, map<int32, Rule *> >::iterator itr;
  107. map<int32, Rule *>::iterator itr2;
  108. char combined[256];
  109. Rule *ret = 0;
  110. snprintf(combined, sizeof(combined), "%s:%s", category, type);
  111. // Zero terminate ([max - 1] = 0) to prevent a warning/error
  112. combined[255] = 0;
  113. m_rules.readlock(__FUNCTION__, __LINE__);
  114. for (itr = rules.begin(); itr != rules.end(); itr++) {
  115. for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++) {
  116. if (!strcmp(itr2->second->GetCombined(), combined)) {
  117. ret = itr2->second;
  118. break;
  119. }
  120. }
  121. }
  122. m_rules.releasereadlock(__FUNCTION__, __LINE__);
  123. return ret;
  124. }
  125. void RuleSet::ClearRules() {
  126. map<int32, map<int32, Rule *> >::iterator itr;
  127. map<int32, Rule *>::iterator itr2;
  128. m_rules.writelock(__FUNCTION__, __LINE__);
  129. for (itr = rules.begin(); itr != rules.end(); itr++) {
  130. for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++)
  131. safe_delete(itr2->second);
  132. }
  133. rules.clear();
  134. m_rules.releasewritelock(__FUNCTION__, __LINE__);
  135. }
  136. RuleManager::RuleManager() {
  137. m_rule_sets.SetName("RuleManager::rule_sets");
  138. m_global_rule_set.SetName("RuleManager::global_rule_set");
  139. m_zone_rule_sets.SetName("RuleManager::zone_rule_sets");
  140. Init();
  141. }
  142. RuleManager::~RuleManager() {
  143. Flush();
  144. }
  145. void RuleManager::Init()
  146. {
  147. #define RULE_INIT(category, type, value) rules[category][type] = new Rule(category, type, value, #category ":" #type)
  148. /* CLIENT */
  149. RULE_INIT(R_Client, ShowWelcomeScreen, "0");
  150. RULE_INIT(R_Client, GroupSpellsTimer, "1000");
  151. /* FACTION */
  152. RULE_INIT(R_Faction, AllowFactionBasedCombat, "1");
  153. /* GUILD */
  154. RULE_INIT(R_Guild, MaxLevel, "50");
  155. RULE_INIT(R_Guild, MaxPlayers, "-1");
  156. /* PLAYER */
  157. RULE_INIT(R_Player, MaxLevel, "50");
  158. RULE_INIT(R_Player, MaxLevelOverrideStatus, "100");
  159. RULE_INIT(R_Player, VitalityAmount, ".5");
  160. RULE_INIT(R_Player, VitalityFrequency, "3600");
  161. RULE_INIT(R_Player, XPMultiplier, "1.0");
  162. RULE_INIT(R_Player, TSXPMultiplier, "1.0");
  163. RULE_INIT(R_Player, MaxAA, "320");
  164. RULE_INIT(R_Player, MaxClassAA, "100");
  165. RULE_INIT(R_Player, MaxSubclassAA, "100");
  166. RULE_INIT(R_Player, MaxShadowsAA, "70");
  167. RULE_INIT(R_Player, MaxHeroicAA, "50");
  168. RULE_INIT(R_Player, MaxTradeskillAA, "40");
  169. RULE_INIT(R_Player, MaxPrestigeAA, "25");
  170. RULE_INIT(R_Player, MaxTradeskillPrestigeAA, "25");
  171. RULE_INIT(R_Player, MinLastNameLevel, "20");
  172. RULE_INIT(R_Player, MaxLastNameLength, "20");
  173. RULE_INIT(R_Player, MinLastNameLength, "4");
  174. RULE_INIT(R_Player, DisableHouseAlignmentRequirement, "1");
  175. RULE_INIT(R_Player, MentorItemDecayRate, ".05"); // 5% per level lost when mentoring
  176. RULE_INIT(R_Player, TemporaryItemLogoutTime, "1800.0"); // time in seconds (double) for temporary item to decay after being logged out for a period of time, 30 min is the default
  177. RULE_INIT(R_Player, HeirloomItemShareExpiration, "172800.0"); // 2 days ('48 hours') in seconds
  178. RULE_INIT(R_Player, SwimmingSkillMinSpeed, "20");
  179. RULE_INIT(R_Player, SwimmingSkillMaxSpeed, "200");
  180. RULE_INIT(R_Player, SwimmingSkillMinBreathLength, "30");
  181. RULE_INIT(R_Player, SwimmingSkillMaxBreathLength, "1000");
  182. /* PVP */
  183. RULE_INIT(R_PVP, AllowPVP, "0");
  184. RULE_INIT(R_PVP, LevelRange, "4");
  185. RULE_INIT(R_PVP, InvisPlayerDiscoveryRange, "20"); // value > 0 sets radius inner to see, = 0 means always seen, -1 = never seen
  186. RULE_INIT(R_PVP, PVPMitigationModByLevel, "25"); // gives a bonus to mitigation for PVP combat to offset the percentage level * mod (default 25)
  187. /* COMBAT */
  188. RULE_INIT(R_Combat, MaxCombatRange, "4.0");
  189. RULE_INIT(R_Combat, DeathExperienceDebt, "50.00"); // divide by 100, 50/100 = .5% debt per pve death
  190. RULE_INIT(R_Combat, PVPDeathExperienceDebt, "25.00"); // divide by 100, 25/100 = .25% debt per pvp death
  191. RULE_INIT(R_Combat, GroupExperienceDebt, "0"); // set to 1 means we will share debt between the group
  192. RULE_INIT(R_Combat, ExperienceToDebt, "50.00"); // percentage of xp earned to debt vs obtained xp 50/100 = 50% to debt
  193. RULE_INIT(R_Combat, ExperienceDebtRecoveryPercent, "5.00"); // recovery percentage per period of time, 5/100 = 5% recovered (so if .5% debt, .5*.05 = .025, .5-.025=.475% debt left)
  194. RULE_INIT(R_Combat, ExperienceDebtRecoveryPeriod, "600"); // every 10 minutes (x*60 seconds) recover ExperienceDebtRecoveryPercent
  195. RULE_INIT(R_Combat, EnableSpiritShards, "1");
  196. RULE_INIT(R_Combat, SpiritShardSpawnScript, "SpawnScripts/Generic/SpiritShard.lua");
  197. RULE_INIT(R_Combat, ShardDebtRecoveryPercent, "25.00"); // recovered percentage of debt upon obtainig shard, 25/100 means 25%. If there is .5 DeathExperienceDebt, .5*25% = .125, .5 - .125 = .375
  198. RULE_INIT(R_Combat, ShardRecoveryByRadius, "1"); // allow shards to auto pick up by radius, not requiring to click/right click the shard
  199. RULE_INIT(R_Combat, EffectiveMitigationCapLevel, "80"); // level multiplier for max effective cap, level * 80 (default)
  200. RULE_INIT(R_Combat, CalculatedMitigationCapLevel, "100"); // The cap to calculate your mitigation from is [level*100].
  201. RULE_INIT(R_Combat, MitigationLevelEffectivenessMax, "1.5"); // ratio victim level / attacker level for max effectiveness, when victim is higher level cap can reach 1.5
  202. RULE_INIT(R_Combat, MitigationLevelEffectivenessMin, ".5"); // ratio victim level / attacker level for min effectiveness
  203. RULE_INIT(R_Combat, MaxMitigationAllowed, ".75"); // percentage max mitigation allowed, eg. 75% of damage can be mitigated max in PVE
  204. RULE_INIT(R_Combat, MaxMitigationAllowedPVP, ".75"); // percentage max mitigation allowed, eg. 75% of damage can be mitigated max in PVP
  205. RULE_INIT(R_Combat, StrengthNPC, "10"); // divider for strength NPC only str/x = additional dmg to low/high dmg
  206. RULE_INIT(R_Combat, StrengthOther, "25"); // divider for strength other than NPC str/x = additional dmg to low/high dmg
  207. /* SPAWN */
  208. RULE_INIT(R_Spawn, SpeedMultiplier, "300"); // note: this value was 1280 until 6/1/2009, then was 600 til Sep 2009, when it became 300...?
  209. RULE_INIT(R_Spawn, ClassicRegen, "0");
  210. RULE_INIT(R_Spawn, HailMovementPause, "5000"); // time in milliseconds the spawn is paused on hail
  211. RULE_INIT(R_Spawn, HailDistance, "5"); // max distance to hail a spawn/npc
  212. RULE_INIT(R_Spawn, UseHardCodeWaterModelType, "1"); // uses alternate method of setting water type by model type (hardcoded) versus relying on just DB
  213. RULE_INIT(R_Spawn, UseHardCodeFlyingModelType, "1"); // uses alternate method of setting flying type by model type (hardcoded) versus relying on just DB
  214. /* TIMER */
  215. /* UI */
  216. RULE_INIT(R_UI, MaxWhoResults, "20");
  217. RULE_INIT(R_UI, MaxWhoOverrideStatus, "200");
  218. /* WORLD */
  219. RULE_INIT(R_World, DefaultStartingZoneID, "1");
  220. RULE_INIT(R_World, EnablePOIDiscovery, "0");
  221. RULE_INIT(R_World, GamblingTokenItemID, "2");
  222. RULE_INIT(R_World, GuildAutoJoin, "0");
  223. RULE_INIT(R_World, GuildAutoJoinID, "1");
  224. RULE_INIT(R_World, GuildAutoJoinDefaultRankID, "7");
  225. RULE_INIT(R_World, MaxPlayers, "-1");
  226. RULE_INIT(R_World, MaxPlayersOverrideStatus, "100");
  227. RULE_INIT(R_World, ServerLocked, "0");
  228. RULE_INIT(R_World, ServerLockedOverrideStatus, "10");
  229. RULE_INIT(R_World, SyncZonesWithLogin, "1");
  230. RULE_INIT(R_World, SyncEquipWithLogin, "1");
  231. RULE_INIT(R_World, UseBannedIPsTable, "0");
  232. RULE_INIT(R_World, LinkDeadTimer, "120000"); // default: 2 minutes
  233. RULE_INIT(R_World, RemoveDisconnectedClientsTimer, "30000"); // default: 30 seconds
  234. RULE_INIT(R_World, PlayerCampTimer, "20"); // default: 20 seconds
  235. RULE_INIT(R_World, GMCampTimer, "1"); // default: 1 second
  236. RULE_INIT(R_World, AutoAdminPlayers, "0"); // default: No
  237. RULE_INIT(R_World, AutoAdminGMs, "0"); // default: No
  238. RULE_INIT(R_World, AutoAdminStatusValue, "10"); // default: 10 (CSR)
  239. RULE_INIT(R_World, DuskTime, "20:00"); // default: 8pm
  240. RULE_INIT(R_World, DawnTime, "8:00"); // default: 8am
  241. RULE_INIT(R_World, ThreadedLoad, "0"); // default: no threaded loading
  242. RULE_INIT(R_World, TradeskillSuccessChance, "87.0"); // default: 87% chance of success while crafting
  243. RULE_INIT(R_World, TradeskillCritSuccessChance, "2.0"); // default: 2% chance of critical success while crafting
  244. RULE_INIT(R_World, TradeskillFailChance, "10.0"); // default: 10% chance of failure while crafting
  245. RULE_INIT(R_World, TradeskillCritFailChance, "1.0"); // default: 1% chance of critical failure while crafting
  246. RULE_INIT(R_World, TradeskillEventChance, "15.0"); // default: 15% chance of a tradeskill event while crafting
  247. RULE_INIT(R_World, EditorURL, "www.eq2emulator.net"); // default: www.eq2emulator.net
  248. RULE_INIT(R_World, EditorIncludeID, "0"); // default: 0 (0 = disabled, 1 = enabled)
  249. RULE_INIT(R_World, EditorOfficialServer, "0"); // default: 0 (0 = disabled, 1 = enabled)
  250. RULE_INIT(R_World, SavePaperdollImage, "1"); // default: true
  251. RULE_INIT(R_World, SaveHeadshotImage, "1"); // default: true
  252. RULE_INIT(R_World, SendPaperdollImagesToLogin, "1"); // default: true
  253. RULE_INIT(R_World, TreasureChestDisabled, "0"); // default: false
  254. RULE_INIT(R_World, StartingZoneLanguages, "0"); // default: 0 (0 = Live Like, 1 = Starting City Based)
  255. RULE_INIT(R_World, StartingZoneRuleFlag, "0"); // default: 0 - match any options available, just based on version/other fields (will not force qc/outpost)
  256. // 1 - force split zones on alignment/deity despite client selection (queens colony/overlord outpost)
  257. // 2 - (isle of refuge)
  258. // 4 - send to 'new' starting zones, won't support old clients
  259. // 5+ - send to new and old starting zones as needed
  260. RULE_INIT(R_World, EnforceRacialAlignment, "1");
  261. //INSERT INTO `ruleset_details`(`id`, `ruleset_id`, `rule_category`, `rule_type`, `rule_value`, `description`) VALUES (NULL, '1', 'R_World', '', '', '')
  262. /* ZONE */
  263. RULE_INIT(R_Zone, MaxPlayers, "100");
  264. RULE_INIT(R_Zone, MinZoneLevelOverrideStatus, "1");
  265. RULE_INIT(R_Zone, MinZoneAccessOverrideStatus, "100");
  266. RULE_INIT(R_Zone, WeatherEnabled, "1"); // default: 1 (0 = disabled, 1 = enabled)
  267. RULE_INIT(R_Zone, WeatherType, "0"); // default: 1 (0 = normal, 1 = dynamic, 2 = random, 3 = chaotic)
  268. RULE_INIT(R_Zone, MinWeatherSeverity, "0.0"); // default: 0.0 or no weather
  269. RULE_INIT(R_Zone, MaxWeatherSeverity, "1.0"); // default: 1.0 or hard rain (range 0.0 - 1.0, rain starts at 0.75)
  270. RULE_INIT(R_Zone, WeatherChangeFrequency, "300"); // default: 5 minutes
  271. RULE_INIT(R_Zone, WeatherChangePerInterval, "0.02"); // default: 0.02 (slight changes)
  272. RULE_INIT(R_Zone, WeatherChangeChance, "20"); // default: 20% (in whole percents)
  273. RULE_INIT(R_Zone, WeatherDynamicMaxOffset, "0.08"); // default: 0.08 - dynamic weather changes can only change this max amount
  274. RULE_INIT(R_Zone, SpawnUpdateTimer, "50"); // default: 50ms - how often to check for spawn update sends
  275. RULE_INIT(R_Zone, CheckAttackNPC, "2000"); // default: 2 seconds, how often to for NPCs to attack eachother
  276. RULE_INIT(R_Zone, CheckAttackPlayer, "2000"); // default: 2 seconds, how often to check for NPCs to attack players
  277. RULE_INIT(R_Zone, HOTime, "10.0"); // default: 10 seconds, time to complete the HO wheel before it expires
  278. /* ZONE TIMERS */
  279. RULE_INIT(R_Zone, RegenTimer, "6000");
  280. RULE_INIT(R_Zone, ClientSaveTimer, "60000");
  281. RULE_INIT(R_Zone, ShutdownDelayTimer, "120000");
  282. RULE_INIT(R_Zone, WeatherTimer, "60000"); // default: 1 minute
  283. RULE_INIT(R_Zone, SpawnDeleteTimer, "30000"); // default: 30 seconds, how long a spawn pointer is held onto after being removed from the world before deleting it
  284. RULE_INIT(R_Zone, UseMapUnderworldCoords, "1"); // use maps lowest Y coordinate to establish underworld markers
  285. RULE_INIT(R_Zone, MapUnderworldCoordOffset, "-200.0"); // adds (or in the case of negative value subtracts) so that the underworld marker is lower when map is using its lowest Y coordinate
  286. RULE_INIT(R_Loot, LootRadius, "5.0");
  287. RULE_INIT(R_Loot, AutoDisarmChest, "1");
  288. RULE_INIT(R_Loot, ChestTriggerRadiusGroup, "10.0"); // radius at which chest will trigger against group members
  289. RULE_INIT(R_Loot, ChestUnlockedTimeDrop, "1200"); // time in seconds, 20 minutes by default, triggers only if AllowChestUnlockByDropTime is 1
  290. RULE_INIT(R_Loot, AllowChestUnlockByDropTime, "1"); // when set to 1 we will start a countdown timer to allow anyone to loot once ChestUnlockedTimeDrop elapsed
  291. RULE_INIT(R_Loot, ChestUnlockedTimeTrap, "600"); // time in seconds, 10 minutes by default
  292. RULE_INIT(R_Loot, AllowChestUnlockByTrapTime, "1"); // when set to 1 we will allow unlocking the chest to all players after the trap is triggered (or chest is open) and period ChestUnlockedTimeTrap elapsed
  293. RULE_INIT(R_Loot, SkipLootGrayMob, "1");
  294. RULE_INIT(R_Spells, NoInterruptBaseChance, "50");
  295. RULE_INIT(R_Spells, EnableFizzleSpells, "1"); // enables/disables the 'fizzling' of spells based on can_fizzle in the spells table. This also enables increasing specialized skills for classes based on spells/abilities.
  296. RULE_INIT(R_Spells, DefaultFizzleChance, "10.0"); // default percentage x / 100, eg 10% is 10.0
  297. RULE_INIT(R_Spells, FizzleMaxSkill, "1.2"); // 1.0 is 100%, 1.2 is 120%, so you get 120% your max skill against a spell, no fizzle
  298. RULE_INIT(R_Spells, FizzleDefaultSkill, ".2"); // offset against MaxSkill to average out to 100%, default of .2f so we don't go over the threshold if no skill
  299. RULE_INIT(R_Spells, EnableCrossZoneGroupBuffs, "0"); // enables/disables allowing cross zone group buffs
  300. RULE_INIT(R_Spells, EnableCrossZoneTargetBuffs, "0"); // enables/disables allowing cross zone target buffs
  301. RULE_INIT(R_Spells, PlayerSpellSaveStateWaitInterval, "100"); // time in milliseconds we wait before performing a save when the spell save trigger is activated, allows additional actions to take place until the cap is hit
  302. RULE_INIT(R_Spells, PlayerSpellSaveStateCap, "1000"); // sets a maximum wait time before we queue a spell state save to the DB, given a lot can go on in a short period with players especially in combat, maybe good to have this at a higher interval.
  303. RULE_INIT(R_Spells, RequirePreviousTierScribe, "0"); // requires step up apprentice -> apprentice (handcrafted?) -> journeyman (handcrafted?) -> adept -> expert -> master
  304. RULE_INIT(R_Spells, CureSpellID, "110003"); // Base Cure spell that was used after they removed cure types
  305. RULE_INIT(R_Spells, CureCurseSpellID, "110004"); // Curse Spell ID in the spells database
  306. RULE_INIT(R_Spells, CureNoxiousSpellID, "110005"); // Noxious/Poison Spell ID in the spells database
  307. RULE_INIT(R_Spells, CureMagicSpellID, "210006"); // Magic/Elemental Spell ID in the spells database
  308. RULE_INIT(R_Spells, CureTraumaSpellID, "0"); // Trauma/Mental Spell ID in the spells database
  309. RULE_INIT(R_Spells, CureArcaneSpellID, "0"); // Arcane/Heat Spell ID in the spells database
  310. RULE_INIT(R_Spells, MinistrationSkillID, "366253016"); // ministration skill id used to map power reduction rule MinistrationPowerReductionMax
  311. RULE_INIT(R_Spells, MinistrationPowerReductionMax, "15.0"); // max percentage of power reduction for spells with ministration mastery skill (default is 15.0 for 15%)
  312. RULE_INIT(R_Spells, MinistrationPowerReductionSkill, "25"); // divides by integer value to establish how much skill req for higher power reduction
  313. RULE_INIT(R_Spells, MasterSkillReduceSpellResist, "25"); // divides by integer value to establish how much skill bonus for reducing spell resistance on target
  314. RULE_INIT(R_Expansion, GlobalExpansionFlag, "0");
  315. RULE_INIT(R_Expansion, GlobalHolidayFlag, "0");
  316. RULE_INIT(R_World, DatabaseVersion, "0");
  317. #undef RULE_INIT
  318. }
  319. void RuleManager::Flush(bool reinit)
  320. {
  321. map<int32, map<int32, Rule*> >::iterator itr;
  322. map<int32, Rule*>::iterator itr2;
  323. for (itr = rules.begin(); itr != rules.end(); itr++) {
  324. for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++)
  325. safe_delete(itr2->second);
  326. }
  327. rules.clear();
  328. ClearRuleSets();
  329. ClearZoneRuleSets();
  330. if (reinit)
  331. Init();
  332. }
  333. void RuleManager::LoadCodedDefaultsIntoRuleSet(RuleSet *rule_set) {
  334. map<int32, map<int32, Rule *> >::iterator itr;
  335. map<int32, Rule *>::iterator itr2;
  336. assert(rule_set);
  337. for (itr = rules.begin(); itr != rules.end(); itr++) {
  338. for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++)
  339. rule_set->AddRule(new Rule(itr2->second));
  340. }
  341. }
  342. bool RuleManager::AddRuleSet(RuleSet *rule_set) {
  343. bool ret = false;
  344. int32 id;
  345. assert(rule_set);
  346. id = rule_set->GetID();
  347. m_rule_sets.writelock(__FUNCTION__, __LINE__);
  348. if (rule_sets.count(id) == 0) {
  349. rule_sets[id] = rule_set;
  350. ret = true;
  351. }
  352. m_rule_sets.releasewritelock(__FUNCTION__, __LINE__);
  353. return ret;
  354. }
  355. int32 RuleManager::GetNumRuleSets() {
  356. int32 ret;
  357. m_rule_sets.readlock(__FUNCTION__, __LINE__);
  358. ret = rule_sets.size();
  359. m_rule_sets.releasereadlock(__FUNCTION__, __LINE__);
  360. return ret;
  361. }
  362. void RuleManager::ClearRuleSets() {
  363. map<int32, RuleSet *>::iterator itr;
  364. m_rule_sets.writelock(__FUNCTION__, __LINE__);
  365. for (itr = rule_sets.begin(); itr != rule_sets.end(); itr++)
  366. safe_delete(itr->second);
  367. rule_sets.clear();
  368. m_rule_sets.releasewritelock(__FUNCTION__, __LINE__);
  369. }
  370. bool RuleManager::SetGlobalRuleSet(int32 rule_set_id) {
  371. if (rule_sets.count(rule_set_id) == 0)
  372. return false;
  373. global_rule_set.CopyRulesInto(rule_sets[rule_set_id]);
  374. return true;
  375. }
  376. Rule * RuleManager::GetGlobalRule(int32 category, int32 type) {
  377. return global_rule_set.GetRule(category, type);
  378. }
  379. Rule * RuleManager::GetGlobalRule(const char* category, const char* type) {
  380. return global_rule_set.GetRule(category, type);
  381. }
  382. bool RuleManager::SetZoneRuleSet(int32 zone_id, int32 rule_set_id) {
  383. bool ret = true;
  384. RuleSet *rule_set;
  385. m_rule_sets.readlock(__FUNCTION__, __LINE__);
  386. if (rule_sets.count(rule_set_id) == 0)
  387. ret = false;
  388. rule_set = rule_sets[rule_set_id];
  389. if (ret) {
  390. m_zone_rule_sets.writelock(__FUNCTION__, __LINE__);
  391. zone_rule_sets[zone_id] = rule_set;
  392. m_zone_rule_sets.releasewritelock(__FUNCTION__, __LINE__);
  393. }
  394. m_rule_sets.releasereadlock(__FUNCTION__, __LINE__);
  395. return ret;
  396. }
  397. Rule * RuleManager::GetZoneRule(int32 zone_id, int32 category, int32 type) {
  398. Rule *ret = 0;
  399. /* we never want to return null so MAKE SURE the rule exists. if this assertion fails then the server admin must fix the problem */
  400. assert(rules.count(category) > 0);
  401. assert(rules[category].count(type) > 0);
  402. /* first try to get the zone rule */
  403. m_zone_rule_sets.readlock(__FUNCTION__, __LINE__);
  404. if (zone_rule_sets.count(zone_id) > 0)
  405. ret = zone_rule_sets[zone_id]->GetRule(category, type);
  406. m_zone_rule_sets.releasereadlock(__FUNCTION__, __LINE__);
  407. return ret ? ret : rules[category][type];
  408. }
  409. void RuleManager::ClearZoneRuleSets() {
  410. m_zone_rule_sets.writelock(__FUNCTION__, __LINE__);
  411. zone_rule_sets.clear();
  412. m_zone_rule_sets.releasewritelock(__FUNCTION__, __LINE__);
  413. }