diff options
author | maximius <none@none> | 2009-08-07 12:12:42 -0700 |
---|---|---|
committer | maximius <none@none> | 2009-08-07 12:12:42 -0700 |
commit | fe3ba612d94b715bbbbac944418be1188ad66339 (patch) | |
tree | dcfba651a684cd3f896988e361240f91c4b1d80f /src | |
parent | be74be36f6d170fd11b2df2ebfc20a9c2e40584a (diff) |
*Emalon the Stormwatcher fully scripted, by Necroo (boss needs to be spawned and ScriptName needs to be updated)
*Added config options: DurabilityLoss.OnDeath and DurabilityLoss.InPvP, optimized Rate.RepairCost
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/scripts/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/bindings/scripts/ScriptMgr.cpp | 4 | ||||
-rw-r--r-- | src/bindings/scripts/VC80/80ScriptDev2.vcproj | 4 | ||||
-rw-r--r-- | src/bindings/scripts/VC90/90ScriptDev2.vcproj | 4 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/vault_of_archavon/boss_archavon.cpp | 62 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/vault_of_archavon/boss_emalon.cpp | 284 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/vault_of_archavon/def_vault_of_archavon.h | 9 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/vault_of_archavon/instance_vault_of_archavon.cpp | 103 | ||||
-rw-r--r-- | src/game/Player.cpp | 3 | ||||
-rw-r--r-- | src/game/Unit.cpp | 6 | ||||
-rw-r--r-- | src/game/World.cpp | 21 | ||||
-rw-r--r-- | src/game/World.h | 3 | ||||
-rw-r--r-- | src/trinitycore/trinitycore.conf.dist | 10 |
13 files changed, 478 insertions, 36 deletions
diff --git a/src/bindings/scripts/CMakeLists.txt b/src/bindings/scripts/CMakeLists.txt index dab90812b59..b67d7cfe4aa 100644 --- a/src/bindings/scripts/CMakeLists.txt +++ b/src/bindings/scripts/CMakeLists.txt @@ -484,6 +484,7 @@ SET(trinityscript_LIB_SRCS scripts/zone/obsidian_sanctum/def_obsidian_sanctum.h scripts/zone/vault_of_archavon/instance_vault_of_archavon.cpp scripts/zone/vault_of_archavon/boss_archavon.cpp + scripts/zone/vault_of_archavon/boss_emalon.cpp scripts/zone/vault_of_archavon/def_vault_of_archavon.h scripts/zone/wintergrasp/wintergrasp.cpp scripts/zone/ulduar/ulduar/boss_algalon.cpp diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp index 478c2b904f3..ae298061984 100644 --- a/src/bindings/scripts/ScriptMgr.cpp +++ b/src/bindings/scripts/ScriptMgr.cpp @@ -650,6 +650,8 @@ extern void AddSC_zuldrak(); //Dungeon //Vault of Archavon extern void AddSC_boss_archavon(); +extern void AddSC_boss_emalon(); +extern void AddSC_instance_archavon(); //Region extern void AddSC_wintergrasp(); @@ -1558,6 +1560,8 @@ void ScriptsInit(char const* cfg_file = "trinitycore.conf") //Dungeon //Vault of Archavon AddSC_boss_archavon(); + AddSC_boss_emalon(); + AddSC_instance_archavon(); //Region AddSC_wintergrasp(); diff --git a/src/bindings/scripts/VC80/80ScriptDev2.vcproj b/src/bindings/scripts/VC80/80ScriptDev2.vcproj index d1d41523d36..e5eeda086ff 100644 --- a/src/bindings/scripts/VC80/80ScriptDev2.vcproj +++ b/src/bindings/scripts/VC80/80ScriptDev2.vcproj @@ -2834,6 +2834,10 @@ > </File> <File + RelativePath="..\scripts\zone\vault_of_archavon\boss_emalon.cpp" + > + </File> + <File RelativePath="..\scripts\zone\vault_of_archavon\def_vault_of_archavon.h" > </File> diff --git a/src/bindings/scripts/VC90/90ScriptDev2.vcproj b/src/bindings/scripts/VC90/90ScriptDev2.vcproj index 04645271404..7fe459734ed 100644 --- a/src/bindings/scripts/VC90/90ScriptDev2.vcproj +++ b/src/bindings/scripts/VC90/90ScriptDev2.vcproj @@ -2835,6 +2835,10 @@ > </File> <File + RelativePath="..\scripts\zone\vault_of_archavon\boss_emalon.cpp" + > + </File> + <File RelativePath="..\scripts\zone\vault_of_archavon\def_vault_of_archavon.h" > </File> diff --git a/src/bindings/scripts/scripts/zone/vault_of_archavon/boss_archavon.cpp b/src/bindings/scripts/scripts/zone/vault_of_archavon/boss_archavon.cpp index d963024d69e..51e6df5e023 100644 --- a/src/bindings/scripts/scripts/zone/vault_of_archavon/boss_archavon.cpp +++ b/src/bindings/scripts/scripts/zone/vault_of_archavon/boss_archavon.cpp @@ -3,77 +3,77 @@ UPDATE `creature_template` SET `ScriptName`='boss_archavon' WHERE `entry`='31125 UPDATE `creature_template` SET `ScriptName`='mob_archavon_warder' WHERE `entry`='32353'; *** SQL END ***/ #include "precompiled.h" +#include "def_vault_of_archavon.h" -//These are patchwerk's yell -#define SAY_AGGRO1 -1533017 -#define SAY_AGGRO2 -1533018 -#define SAY_SLAY -1533019 -#define SAY_DEATH -1533020 - -#define EMOTE_BERSERK -1533021 -#define EMOTE_ENRAGE -1533022 +#define EMOTE_BERSERK -1590002 //Spells Archavon -#define SPELL_ROCK_SHARDS 58678 -#define SPELL_CRUSHING_LEAP HEROIC(58960,60894)//Instant (10-80yr range) -- Leaps at an enemy, inflicting 8000 Physical damage, knocking all nearby enemies away, and creating a cloud of choking debris. -#define SPELL_STOMP HEROIC(58663,60880) -#define SPELL_IMPALE HEROIC(58666,60882) //Lifts an enemy off the ground with a spiked fist, inflicting 47125 to 52875 Physical damage and 9425 to 10575 additional damage each second for 8 sec. -#define SPELL_BERSERK 47008 +#define SPELL_ROCK_SHARDS 58678 +#define SPELL_CRUSHING_LEAP HEROIC(58960,60894)//Instant (10-80yr range) -- Leaps at an enemy, inflicting 8000 Physical damage, knocking all nearby enemies away, and creating a cloud of choking debris. +#define SPELL_STOMP HEROIC(58663,60880) +#define SPELL_IMPALE HEROIC(58666,60882) //Lifts an enemy off the ground with a spiked fist, inflicting 47125 to 52875 Physical damage and 9425 to 10575 additional damage each second for 8 sec. +#define SPELL_BERSERK 47008 //Spells Archavon Warders -#define SPELL_ROCK_SHOWER HEROIC(60919,60923) -#define SPELL_SHIELD_CRUSH HEROIC(60897,60899) -#define SPELL_WHIRL HEROIC(60902,60916) +#define SPELL_ROCK_SHOWER HEROIC(60919,60923) +#define SPELL_SHIELD_CRUSH HEROIC(60897,60899) +#define SPELL_WHIRL HEROIC(60902,60916) //4 Warders spawned -#define ARCHAVON_WARDER 32353 //npc 32353 +#define ARCHAVON_WARDER 32353 //npc 32353 //Yell #define SAY_LEAP "Archavon the Stone Watcher lunges for $N!" //$N should be the target -#define EVENT_ROCK_SHARDS 1 //15s cd -#define EVENT_CHOKING_CLOUD 2 //30s cd +#define EVENT_ROCK_SHARDS 1 //15s cd +#define EVENT_CHOKING_CLOUD 2 //30s cd #define EVENT_STOMP 3 //45s cd #define EVENT_IMPALE 4 #define EVENT_BERSERK 5 //300s cd //mob -#define EVENT_ROCK_SHOWER 5 //set = 20s cd,unkown cd -#define EVENT_SHIELD_CRUSH 6 //set = 30s cd -#define EVENT_WHIRL 8 //set= 10s cd +#define EVENT_ROCK_SHOWER 5 //set = 20s cd,unkown cd +#define EVENT_SHIELD_CRUSH 6 //set = 30s cd +#define EVENT_WHIRL 8 //set= 10s cd struct TRINITY_DLL_DECL boss_archavonAI : public ScriptedAI { - boss_archavonAI(Creature *c) : ScriptedAI(c) {} + boss_archavonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + ScriptedInstance* pInstance; EventMap events; void Reset() { events.Reset(); - } - void KilledUnit(Unit* Victim) - { - if(!(rand()%5)) - DoScriptText(SAY_SLAY, me); + if(pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, NOT_STARTED); } + void KilledUnit(Unit* Victim){} + void JustDied(Unit* Killer) { - DoScriptText(SAY_DEATH, me); + if (pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, DONE); } void EnterCombat(Unit *who) { - DoScriptText((rand()%2) ? SAY_AGGRO1 : SAY_AGGRO2, me); DoZoneInCombat(); events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); events.ScheduleEvent(EVENT_STOMP, 45000); events.ScheduleEvent(EVENT_BERSERK, 300000); - } + if(pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, IN_PROGRESS); + } + // Below UpdateAI may need review/debug. void UpdateAI(const uint32 diff) { //Return since we have no target diff --git a/src/bindings/scripts/scripts/zone/vault_of_archavon/boss_emalon.cpp b/src/bindings/scripts/scripts/zone/vault_of_archavon/boss_emalon.cpp new file mode 100644 index 00000000000..80fe55ca996 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/vault_of_archavon/boss_emalon.cpp @@ -0,0 +1,284 @@ +#include "precompiled.h" +#include "def_vault_of_archavon.h" + +#define EMOTE_OVERCHARGE_TEMPEST_MINION -1590000 +#define EMOTE_MINION_RESPAWN -1590001 + +//Spells Emalon +#define SPELL_CHAIN_LIGHTNING HEROIC(64213,64215) +#define SPELL_LIGHTNING_NOVA HEROIC(64216,65279) +#define SPELL_OVERCHARGE 64218 +#define SPELL_BERSERK 47008 + +//Spells Tempest Minions +#define SPELL_OVERCHARGED 64217 +#define SPELL_OVERCHARGED_BLAST 64219 +#define SPELL_SHOCK 64363 + +//4 Warders spawned +#define TEMPEST_MINIONS 33998 + +#define EVENT_CHAIN_LIGHTNING 1 //5s cd +#define EVENT_OVERCHARGE 2 //45s cd +#define EVENT_LIGHTNING_NOVA 3 //40s cd +#define EVENT_BERSERK 4 //360s cd +#define EVENT_SHOCK 5 //20s cd + +struct Location +{ + float x, y, z, o; +}; + +static Location MinionLocation[]= +{ + -231.713,-281.96,91.466,1.53213, + -205.585,-281.549,91.4661,1.75204, + -205.651,-296.394,91.4661,1.69549, + -232.235,-296.433,91.4998,1.44417 +}; + +struct TRINITY_DLL_DECL boss_emalonAI : public ScriptedAI +{ + boss_emalonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + std::list<uint64> MinionList; + + void Reset() + { + events.Reset(); + DespawnAllMinions(); + SummonAllMinions(); + + if(pInstance) + pInstance->SetData(DATA_EMALON_EVENT, NOT_STARTED); + } + + void DespawnAllMinions() + { + if(!MinionList.empty()) + { + for(std::list<uint64>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); itr++) + { + Unit *Minion = Unit::GetUnit(*m_creature, (*itr)); + if(Minion) + Minion->RemoveFromWorld(); + } + } + + MinionList.clear(); + } + + void JustSummoned(Creature *Summoned) + { + MinionList.push_back(Summoned->GetGUID()); + if(Unit* target = m_creature->getVictim()) + Summoned->AI()->AttackStart(target); + } + + void SummonAllMinions() + { + if(MinionList.empty()) + for(uint8 i = 0; i < 4; i++) + SummonMinion(m_creature, MinionLocation[i].x, MinionLocation[i].y, MinionLocation[i].z, MinionLocation[i].o); + } + + static void SummonMinion(Creature *Summoner, float x, float y, float z, float o) + { + Summoner->SummonCreature(TEMPEST_MINIONS, x, y, z, o, TEMPSUMMON_DEAD_DESPAWN, 0); + } + + void KilledUnit(Unit* Victim){} + + void JustDied(Unit* Killer) + { + DespawnAllMinions(); + if (pInstance) + pInstance->SetData(DATA_EMALON_EVENT, DONE); + } + + void EnterCombat(Unit *who) + { + if(!MinionList.empty()) + { + for(std::list<uint64>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr) + { + Creature* Minion = (Unit::GetCreature(*m_creature, *itr)); + Minion->AI()->AttackStart(who); + } + } + + DoZoneInCombat(); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 5000); + events.ScheduleEvent(EVENT_OVERCHARGE, 45000); + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 30000); + events.ScheduleEvent(EVENT_BERSERK, 360000); + events.ScheduleEvent(EVENT_SHOCK, 20000); + + if(pInstance) + pInstance->SetData(DATA_EMALON_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if(!UpdateVictim()) + return; + + events.Update(diff); + + if(me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while(uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CHAIN_LIGHTNING: + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_CHAIN_LIGHTNING); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 20000); + return; + case EVENT_OVERCHARGE: + for(std::list<uint64>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr) + { + Creature* Minion = (Unit::GetCreature(*m_creature, *itr)); + if(Minion && Minion->isAlive() && !Minion->HasAura(SPELL_OVERCHARGED)) + { + Minion->CastSpell(me, SPELL_OVERCHARGED, true); + Minion->SetHealth(Minion->GetMaxHealth()); + DoScriptText(EMOTE_OVERCHARGE_TEMPEST_MINION, m_creature); + events.ScheduleEvent(EVENT_OVERCHARGE, 45000); + return; + } + } + case EVENT_LIGHTNING_NOVA: + DoCast(me->getVictim(), SPELL_LIGHTNING_NOVA); + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 25000); + return; + case EVENT_SHOCK: + for(std::list<uint64>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr) + { + Creature* Minion = (Unit::GetCreature(*m_creature, *itr)); + if(Minion && Minion->isAlive()) + { + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + Minion->CastSpell(target, SPELL_SHOCK, true); + events.ScheduleEvent(EVENT_SHOCK, 20000); + return; + } + } + } + case EVENT_BERSERK: + DoCast(m_creature, SPELL_BERSERK); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Mob Tempest Minions +######*/ +struct TRINITY_DLL_DECL mob_tempest_minionsAI : public ScriptedAI +{ + mob_tempest_minionsAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EmalonGUID = pInstance ? pInstance->GetData64(DATA_EMALON) : 0; + Emalon = Unit::GetCreature(*m_creature, EmalonGUID); + } + + ScriptedInstance* pInstance; + EventMap events; + uint64 EmalonGUID; + std::list<Creature*> MinionList; + Creature* Emalon; + uint32 SPELL_OVERCHARGED_Timer; + bool AlreadyOvercharged; + + void Reset() + { + events.Reset(); + AlreadyOvercharged = false; + SPELL_OVERCHARGED_Timer = 0; + } + + void EnterCombat(Unit *who) + { + DoZoneInCombat(); + if(Emalon) + Emalon->AI()->AttackStart(who); + } + + void JustDied(Unit* Killer) + { + m_creature->RemoveCorpse(); + m_creature->RemoveFromWorld(); + if(Emalon) + { + boss_emalonAI::SummonMinion(Emalon, Emalon->GetPositionX(), Emalon->GetPositionY(), Emalon->GetPositionZ(), Emalon->GetOrientation()); + DoScriptText(EMOTE_MINION_RESPAWN, m_creature); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if(!UpdateVictim()) + return; + + if(Aura *OverchargedAura = m_creature->GetAura(SPELL_OVERCHARGED)) + { + if(OverchargedAura->GetStackAmount() < 10) + { + if (SPELL_OVERCHARGED_Timer < diff) + { + DoCast(me, SPELL_OVERCHARGED); + SPELL_OVERCHARGED_Timer = 2000; + }else SPELL_OVERCHARGED_Timer -=diff; + } + else + { + if(OverchargedAura->GetStackAmount() == 10 && (AlreadyOvercharged == false)) + { + DoCast(me,SPELL_OVERCHARGED_BLAST); + AlreadyOvercharged = true; + } + } + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_tempest_minions(Creature *_Creature) +{ + return new mob_tempest_minionsAI (_Creature); +} + +CreatureAI* GetAI_boss_emalon(Creature *_Creature) +{ + return new boss_emalonAI (_Creature); +} + +void AddSC_boss_emalon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_emalon"; + newscript->GetAI = &GetAI_boss_emalon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_tempest_minions"; + newscript->GetAI = &GetAI_mob_tempest_minions; + newscript->RegisterSelf(); +} diff --git a/src/bindings/scripts/scripts/zone/vault_of_archavon/def_vault_of_archavon.h b/src/bindings/scripts/scripts/zone/vault_of_archavon/def_vault_of_archavon.h index f46ba447945..5b11d5729eb 100644 --- a/src/bindings/scripts/scripts/zone/vault_of_archavon/def_vault_of_archavon.h +++ b/src/bindings/scripts/scripts/zone/vault_of_archavon/def_vault_of_archavon.h @@ -1,4 +1,13 @@ #ifndef DEF_ARCHAVON_H #define DEF_ARCHAVON_H +enum +{ + DATA_ARCHAVON = 1, + DATA_EMALON = 2, + + DATA_ARCHAVON_EVENT = 3, + DATA_EMALON_EVENT = 4 +}; + #endif diff --git a/src/bindings/scripts/scripts/zone/vault_of_archavon/instance_vault_of_archavon.cpp b/src/bindings/scripts/scripts/zone/vault_of_archavon/instance_vault_of_archavon.cpp index dc725b2be66..e7f6f572a77 100644 --- a/src/bindings/scripts/scripts/zone/vault_of_archavon/instance_vault_of_archavon.cpp +++ b/src/bindings/scripts/scripts/zone/vault_of_archavon/instance_vault_of_archavon.cpp @@ -1,9 +1,112 @@ #include "precompiled.h" #include "def_vault_of_archavon.h" +#define NUMBER_OF_ENCOUNTERS 2 + struct TRINITY_DLL_DECL instance_archavon : public ScriptedInstance { instance_archavon(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + std::string strInstData; + uint64 Archavon; + uint64 Emalon; + uint32 Encounters[NUMBER_OF_ENCOUNTERS]; + + void Initialize() + { + Archavon = 0; + Emalon = 0; + + for(uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; i++) + Encounters[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i) + if(Encounters[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, bool add) + { + switch(creature->GetEntry()) + { + case 31125: Archavon = creature->GetGUID(); break; + case 33993: Emalon = creature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_ARCHAVON: return Archavon; + case DATA_EMALON: return Emalon; + } + return 0; + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_ARCHAVON_EVENT: return Encounters[0]; + case DATA_EMALON_EVENT: return Encounters[1]; + } + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch(identifier) + { + case DATA_ARCHAVON_EVENT: Encounters[0] = data; break; + case DATA_EMALON_EVENT: Encounters[1] = data; break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << Encounters[0] << " " << Encounters[1]; + + strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + std::string GetSaveData() + { + return strInstData; + } + + void Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + loadStream >> Encounters[0] >> Encounters[1]; + + for(uint8 i = 1; i < NUMBER_OF_ENCOUNTERS; ++i) + { + if (Encounters[i] == IN_PROGRESS) + Encounters[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + } }; InstanceData* GetInstanceData_instance_archavon(Map* map) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f648a5a3d3d..ed2f79f4b38 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -20,7 +20,6 @@ #include "Common.h" #include "Language.h" -#include "Config/ConfigEnv.h" #include "Database/DatabaseEnv.h" #include "Log.h" #include "Opcodes.h" @@ -4557,7 +4556,7 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g uint32 dmultiplier = dcost->multiplier[ItemSubClassToDurabilityMultiplierId(ditemProto->Class,ditemProto->SubClass)]; uint32 costs = uint32(LostDurability*dmultiplier*double(dQualitymodEntry->quality_mod)); - costs = uint32(costs * discountMod) * sConfig.GetFloatDefault("Rate.RepairCost", 1); + costs = uint32(costs * discountMod) * sWorld.getRate(RATE_REPAIRCOST); if (costs==0) //fix for ITEM_QUALITY_ARTIFACT costs = 1; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 58fe17783bc..bc43eefbb36 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -14016,10 +14016,10 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss) ((Player*)pVictim)->SetPvPDeath(player!=NULL); // only if not player and not controlled by player pet. And not at BG - if (durabilityLoss && !player && !((Player*)pVictim)->InBattleGround()) + if ( (durabilityLoss && !player && !((Player*)pVictim)->InBattleGround()) || ( player && sWorld.getConfig(CONFIG_DURABILITY_LOSS_IN_PVP) ) ) { - DEBUG_LOG("We are dead, loosing 10 percents durability"); - ((Player*)pVictim)->DurabilityLossAll(0.10f,false); + DEBUG_LOG("We are dead, losing %u percent durability", sWorld.getRate(RATE_DURABILITY_LOSS_ON_DEATH)); + ((Player*)pVictim)->DurabilityLossAll(sWorld.getRate(RATE_DURABILITY_LOSS_ON_DEATH),false); // durability lost message WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0); ((Player*)pVictim)->GetSession()->SendPacket(&data); diff --git a/src/game/World.cpp b/src/game/World.cpp index 4669590392c..450840f1714 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -469,6 +469,12 @@ void World::LoadConfigSettings(bool reload) rate_values[RATE_XP_KILL] = sConfig.GetFloatDefault("Rate.XP.Kill", 1.0f); rate_values[RATE_XP_QUEST] = sConfig.GetFloatDefault("Rate.XP.Quest", 1.0f); rate_values[RATE_XP_EXPLORE] = sConfig.GetFloatDefault("Rate.XP.Explore", 1.0f); + rate_values[RATE_REPAIRCOST] = sConfig.GetFloatDefault("Rate.RepairCost", 1.0f); + if(rate_values[RATE_REPAIRCOST] < 0.0f) + { + sLog.outError("Rate.RepairCost (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_REPAIRCOST]); + rate_values[RATE_REPAIRCOST] = 0.0f; + } rate_values[RATE_REPUTATION_GAIN] = sConfig.GetFloatDefault("Rate.Reputation.Gain", 1.0f); rate_values[RATE_REPUTATION_LOWLEVEL_KILL] = sConfig.GetFloatDefault("Rate.Reputation.LowLevel.Kill", 1.0f); rate_values[RATE_REPUTATION_LOWLEVEL_QUEST] = sConfig.GetFloatDefault("Rate.Reputation.LowLevel.Quest", 1.0f); @@ -520,6 +526,19 @@ void World::LoadConfigSettings(bool reload) rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = NOMINAL_MELEE_RANGE; } + rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = sConfig.GetFloatDefault("DurabilityLoss.OnDeath", 10.0f); + if(rate_values[RATE_DURABILITY_LOSS_ON_DEATH] < 0.0f) + { + sLog.outError("DurabilityLoss.OnDeath (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_ON_DEATH]); + rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f; + } + if(rate_values[RATE_DURABILITY_LOSS_ON_DEATH] > 100.0f) + { + sLog.outError("DurabilityLoss.OnDeath (%f) must be <=100. Using 100.0 instead.",rate_values[RATE_DURABILITY_LOSS_ON_DEATH]); + rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f; + } + rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = rate_values[RATE_DURABILITY_LOSS_ON_DEATH] / 100.0f; + rate_values[RATE_DURABILITY_LOSS_DAMAGE] = sConfig.GetFloatDefault("DurabilityLossChance.Damage",0.5f); if(rate_values[RATE_DURABILITY_LOSS_DAMAGE] < 0.0f) { @@ -547,6 +566,8 @@ void World::LoadConfigSettings(bool reload) ///- Read other configuration items from the config file + m_configs[CONFIG_DURABILITY_LOSS_IN_PVP] = sConfig.GetBoolDefault("DurabilityLoss.InPvP", false); + m_configs[CONFIG_COMPRESSION] = sConfig.GetIntDefault("Compression", 1); if(m_configs[CONFIG_COMPRESSION] < 1 || m_configs[CONFIG_COMPRESSION] > 9) { diff --git a/src/game/World.h b/src/game/World.h index 78d4c181b4a..d590a552f26 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -164,6 +164,7 @@ enum WorldConfigs CONFIG_SKILL_GAIN_DEFENSE, CONFIG_SKILL_GAIN_GATHERING, CONFIG_SKILL_GAIN_WEAPON, + CONFIG_DURABILITY_LOSS_IN_PVP, CONFIG_MAX_OVERSPEED_PINGS, CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY, CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL, @@ -279,6 +280,7 @@ enum Rates RATE_XP_KILL, RATE_XP_QUEST, RATE_XP_EXPLORE, + RATE_REPAIRCOST, RATE_REPUTATION_GAIN, RATE_REPUTATION_LOWLEVEL_KILL, RATE_REPUTATION_LOWLEVEL_QUEST, @@ -312,6 +314,7 @@ enum Rates RATE_CORPSE_DECAY_LOOTED, RATE_INSTANCE_RESET_TIME, RATE_TARGET_POS_RECALCULATION_RANGE, + RATE_DURABILITY_LOSS_ON_DEATH, RATE_DURABILITY_LOSS_DAMAGE, RATE_DURABILITY_LOSS_PARRY, RATE_DURABILITY_LOSS_ABSORB, diff --git a/src/trinitycore/trinitycore.conf.dist b/src/trinitycore/trinitycore.conf.dist index 44c1199c277..617d5baca62 100644 --- a/src/trinitycore/trinitycore.conf.dist +++ b/src/trinitycore/trinitycore.conf.dist @@ -1243,6 +1243,14 @@ Visibility.Distance.Grey.Object = 10 # Default: 0 - no decrease # 75 - in 2 times each 75 skill points # +# DurabilityLoss.InPvP +# If true, players take durability loss on death in PvP. +# Default: 0 (false) +# 1 (true) +# +# DurabilityLoss.OnDeath +# Durability loss percentage on death (10 - standard, 20 - double, 5 - half) +# # DurabilityLossChance.Damage # Chance lost one from equiped items durability point at damage apply or receive. # Default: 0.5 (100/0.5 = 200) Each 200 damage apply one from 19 possible equipped items @@ -1327,6 +1335,8 @@ SkillChance.Green = 25 SkillChance.Grey = 0 SkillChance.MiningSteps = 0 SkillChance.SkinningSteps = 0 +DurabilityLoss.InPvP = 0 +DurabilityLoss.OnDeath = 10 DurabilityLossChance.Damage = 0.5 DurabilityLossChance.Absorb = 0.5 DurabilityLossChance.Parry = 0.05 |