diff options
Diffstat (limited to 'src')
73 files changed, 1584 insertions, 1040 deletions
diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp index 654a07107dc..fa3b2466db9 100644 --- a/src/bindings/scripts/ScriptMgr.cpp +++ b/src/bindings/scripts/ScriptMgr.cpp @@ -646,10 +646,10 @@ void LoadDatabase() // Load EventAI Text outstring_log("TSCR: Loading EventAI Texts..."); - LoadTrinityStrings(TScriptDB,"eventai_texts",-1,1+(TEXT_SOURCE_RANGE)); + LoadTrinityStrings(TScriptDB,"creature_ai_texts",-1,1+(TEXT_SOURCE_RANGE)); // Gather Additional data from EventAI Texts - result = TScriptDB.PQuery("SELECT entry, sound, type, language, emote FROM eventai_texts"); + result = TScriptDB.PQuery("SELECT entry, sound, type, language, emote FROM creature_ai_texts"); outstring_log("TSCR: Loading EventAI Texts additional data..."); if (result) @@ -671,27 +671,27 @@ void LoadDatabase() if (i >= 0) { - error_db_log("TSCR: Entry %i in table `eventai_texts` is not a negative value.",i); + error_db_log("TSCR: Entry %i in table `creature_ai_texts` is not a negative value.",i); continue; } if (i <= TEXT_SOURCE_RANGE) { - error_db_log("TSCR: Entry %i in table `eventai_texts` is out of accepted entry range for table.",i); + error_db_log("TSCR: Entry %i in table `creature_ai_texts` is out of accepted entry range for table.",i); continue; } if (temp.SoundId) { if (!GetSoundEntriesStore()->LookupEntry(temp.SoundId)) - error_db_log("TSCR: Entry %i in table `eventai_texts` has soundId %u but sound does not exist.",i,temp.SoundId); + error_db_log("TSCR: Entry %i in table `creature_ai_texts` has soundId %u but sound does not exist.",i,temp.SoundId); } if (!GetLanguageDescByID(temp.Language)) - error_db_log("TSCR: Entry %i in table `eventai_texts` using Language %u but Language does not exist.",i,temp.Language); + error_db_log("TSCR: Entry %i in table `creature_ai_texts` using Language %u but Language does not exist.",i,temp.Language); if (temp.Type > CHAT_TYPE_BOSS_WHISPER) - error_db_log("TSCR: Entry %i in table `eventai_texts` has Type %u but this Chat Type does not exist.",i,temp.Type); + error_db_log("TSCR: Entry %i in table `creature_ai_texts` has Type %u but this Chat Type does not exist.",i,temp.Type); TextMap[i] = temp; ++count; @@ -706,7 +706,7 @@ void LoadDatabase() barGoLink bar(1); bar.step(); outstring_log(""); - outstring_log(">> Loaded 0 additional EventAI Texts data. DB table `eventai_texts` is empty."); + outstring_log(">> Loaded 0 additional EventAI Texts data. DB table `creature_ai_texts` is empty."); } // Load Script Text diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_reliquary_of_souls.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_reliquary_of_souls.cpp index 851c5f4c243..df58c705c17 100644 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_reliquary_of_souls.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_reliquary_of_souls.cpp @@ -366,9 +366,9 @@ struct TRINITY_DLL_DECL boss_essence_of_sufferingAI : public ScriptedAI { switch(rand()%2) { - case 0: DoScriptText(SUFF_SAY_SLAY1, m_creature); break; - case 1: DoScriptText(SUFF_SAY_SLAY2, m_creature); break; - case 2: DoScriptText(SUFF_SAY_SLAY3, m_creature); break; + case 0: DoScriptText(SUFF_SAY_SLAY1, m_creature); break; + case 1: DoScriptText(SUFF_SAY_SLAY2, m_creature); break; + case 2: DoScriptText(SUFF_SAY_SLAY3, m_creature); break; } } @@ -391,25 +391,30 @@ struct TRINITY_DLL_DECL boss_essence_of_sufferingAI : public ScriptedAI targets.resize(1); // Only need closest target. Unit* target = targets.front(); // Get the first target. target->CastSpell(m_creature, SPELL_FIXATE_TAUNT, true); + DoResetThreat(); + m_creature->AddThreat(target,1000000); } void UpdateAI(const uint32 diff) { + if(InCombat) + { + //Supposed to be cast on nearest target + if(FixateTimer < diff) + { + CastFixate(); + FixateTimer = 5000; + if(!(rand()%16)) + { + DoScriptText(SUFF_SAY_AGGRO, m_creature); + } + }else FixateTimer -= diff; + } + //Return since we have no target if (!UpdateVictim()) return; - //Supposed to be cast on nearest target - if(FixateTimer < diff) - { - CastFixate(); - FixateTimer = 5000; - if(!(rand()%16)) - { - DoScriptText(SUFF_SAY_AGGRO, m_creature); - } - }else FixateTimer -= diff; - if(EnrageTimer < diff) { DoCast(m_creature, SPELL_ENRAGE); @@ -419,7 +424,7 @@ struct TRINITY_DLL_DECL boss_essence_of_sufferingAI : public ScriptedAI if(SoulDrainTimer < diff) { - DoCast(m_creature->getVictim(), SPELL_SOUL_DRAIN); + DoCast(SelectUnit(SELECT_TARGET_RANDOM,0), SPELL_SOUL_DRAIN); SoulDrainTimer = 60000; }else SoulDrainTimer -= diff; diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp index 0e4cc9129db..00358be80f3 100644 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp @@ -145,7 +145,7 @@ struct TRINITY_DLL_DECL mob_ashtongue_sorcererAI : public ScriptedAI if(CheckTimer < diff) { - Unit* Shade = Unit::GetUnit((*m_creature), ShadeGUID); + Creature* Shade = Unit::GetCreature((*m_creature), ShadeGUID); if(Shade && Shade->isAlive() && m_creature->isAlive()) { if(m_creature->GetDistance2d(Shade) < 20) @@ -165,10 +165,13 @@ struct TRINITY_DLL_DECL mob_ashtongue_sorcererAI : public ScriptedAI struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI { - boss_shade_of_akamaAI(Creature* c) : ScriptedAI(c) + boss_shade_of_akamaAI(Creature* c) : ScriptedAI(c), summons(m_creature) { pInstance = ((ScriptedInstance*)c->GetInstanceData()); AkamaGUID = pInstance ? pInstance->GetData64(DATA_AKAMA_SHADE) : 0; + m_creature->setActive(true);//if view distance is too low + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); } ScriptedInstance* pInstance; @@ -189,30 +192,28 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI bool HasKilledAkama; bool reseting; bool GridSearcherSucceeded; + bool HasKilledAkamaAndReseting; + SummonList summons; void Reset() { reseting = true; + HasKilledAkamaAndReseting = false; GridSearcherSucceeded = false; - if(!Sorcerers.empty()) + Sorcerers.clear(); + summons.DespawnAll();//despawn all adds + + if(Creature* Akama = Unit::GetCreature(*m_creature, AkamaGUID)) { - for(std::list<uint64>::iterator itr = Sorcerers.begin(); itr != Sorcerers.end(); ++itr) + Akama->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//turn gossip on so players can restart the event + if(Akama->isDead()) { - if(Creature* Sorcerer = (Unit::GetCreature(*m_creature, *itr))) - if(Sorcerer->isAlive()) - { - Sorcerer->SetVisibility(VISIBILITY_OFF); - Sorcerer->Kill(Sorcerer); - } + Akama->Respawn();//respawn akama if dead + Akama->AI()->EnterEvadeMode(); } - Sorcerers.clear(); } - - if(Unit* Akama = Unit::GetUnit(*m_creature, AkamaGUID)) - Akama->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SorcererCount = 0; DeathCount = 0; @@ -236,42 +237,42 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI reseting = false; } + void JustSummoned(Creature *summon) {summons.Summon(summon);} + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - void MoveInLineOfSight(Unit *who) - { - if(!GridSearcherSucceeded) - { - FindChannelers(); - - if (!Channelers.empty()) + void MoveInLineOfSight(Unit *who) + { + if(!GridSearcherSucceeded) { - for(std::list<uint64>::iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - { - Creature* Channeler = NULL; - Channeler = (Unit::GetCreature(*m_creature, *itr)); + FindChannelers(); - if (Channeler) + if (!Channelers.empty()) + { + for(std::list<uint64>::iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) { - if (Channeler->isDead()) + Creature* Channeler = (Unit::GetCreature(*m_creature, *itr)); + if (Channeler) { - Channeler->RemoveCorpse(); - Channeler->Respawn(); - Channeler->InterruptNonMeleeSpells(true); - Channeler->RemoveAurasDueToSpell(SPELL_SHADE_SOUL_CHANNEL); - } + if (Channeler->isDead()) + { + Channeler->RemoveCorpse(); + Channeler->Respawn(); + Channeler->InterruptNonMeleeSpells(true); + Channeler->RemoveAurasDueToSpell(SPELL_SHADE_SOUL_CHANNEL); + } - if (Channeler->isAlive()) - { - Channeler->CastSpell(m_creature, SPELL_SHADE_SOUL_CHANNEL, true); - Channeler->CastSpell(m_creature, SPELL_SHADE_SOUL_CHANNEL_2, true); - Channeler->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - GridSearcherSucceeded = true; + if (Channeler->isAlive()) + { + Channeler->CastSpell(m_creature, SPELL_SHADE_SOUL_CHANNEL, true); + Channeler->CastSpell(m_creature, SPELL_SHADE_SOUL_CHANNEL_2, true); + Channeler->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + GridSearcherSucceeded = true; + } } } - } - }else error_log("SD2 ERROR: No Channelers are stored in the list. This encounter will not work properly"); - } - } + }else error_log("SD2 ERROR: No Channelers are stored in the list. This encounter will not work properly"); + } + } void Aggro(Unit* who) { } @@ -387,7 +388,10 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI { // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check if(m_creature->getThreatManager().getThreatList().size() < 2) + { EnterEvadeMode(); + return; + } if(DefenderTimer < diff) { @@ -399,7 +403,7 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI bool move = true; if(AkamaGUID) { - if(Unit* Akama = Unit::GetUnit(*m_creature, AkamaGUID)) + if(Creature* Akama = Unit::GetCreature(*m_creature, AkamaGUID)) { float x, y, z; Akama->GetPosition(x,y,z); @@ -424,7 +428,7 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI { if(AkamaGUID) { - Unit* Akama = Unit::GetUnit((*m_creature), AkamaGUID); + Creature* Akama = Unit::GetCreature((*m_creature), AkamaGUID); if(Akama && Akama->isAlive()) { IsBanished = false; @@ -449,31 +453,30 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI { if(AkamaGUID) { - Unit* Akama = Unit::GetUnit((*m_creature), AkamaGUID); + Creature* Akama = Unit::GetCreature((*m_creature), AkamaGUID); if(Akama && Akama->isAlive()) { //10 % less health every few seconds. m_creature->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); ReduceHealthTimer = 12000; } - else - { - HasKilledAkama = true; // Akama is dead or missing, we stop fighting and disappear - m_creature->SetVisibility(VISIBILITY_OFF); - m_creature->SetHealth(m_creature->GetMaxHealth()); - m_creature->RemoveAllAuras(); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } } }else ReduceHealthTimer -= diff; if(HasKilledAkama) { - if(ResetTimer < diff) - { - InCombat = false; - EnterEvadeMode(); // Reset a little while after killing Akama + if(!HasKilledAkamaAndReseting)//do not let players kill Shade if Akama is dead and Shade is waiting for ResetTimer!! event would bug + { + HasKilledAkamaAndReseting = true; + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + //m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->GetMotionMaster()->MoveTargetedHome(); } + if(ResetTimer < diff) + EnterEvadeMode();// Reset a little while after killing Akama, evade and respawn Akama else ResetTimer -= diff; } @@ -505,7 +508,17 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI ShadeHasDied = false; StartCombat = false; pInstance = ((ScriptedInstance*)c->GetInstanceData()); - ShadeGUID = pInstance ? pInstance->GetData64(DATA_SHADEOFAKAMA) : 0; + ShadeGUID = pInstance ? pInstance->GetData64(DATA_SHADEOFAKAMA) : NOT_STARTED; + m_creature->setActive(true); + EventBegun = false; + CastSoulRetrieveTimer = 0; + SoulRetrieveTimer = 0; + SummonBrokenTimer = 0; + EndingTalkCount = 0; + WayPointId = 0; + BrokenSummonIndex = 0; + BrokenList.clear(); + HasYelledOnce = false; } ScriptedInstance* pInstance; @@ -534,20 +547,12 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI DestructivePoisonTimer = 15000; LightningBoltTimer = 10000; CheckTimer = 2000; - CastSoulRetrieveTimer = 0; - SoulRetrieveTimer = 0; - SummonBrokenTimer = 0; - EndingTalkCount = 0; - WayPointId = 0; - BrokenSummonIndex = 0; - - BrokenList.clear(); - - EventBegun = false; - HasYelledOnce = false; - - m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has very very strange values - m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + if(!EventBegun) + { + m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has very very strange values + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } } void Aggro(Unit* who) {} @@ -589,7 +594,7 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI case 0: ++WayPointId; break; case 1: - if(Unit* Shade = Unit::GetUnit(*m_creature, ShadeGUID)) + if(Creature* Shade = Unit::GetCreature(*m_creature, ShadeGUID)) { m_creature->SetUInt64Value(UNIT_FIELD_TARGET, ShadeGUID); DoCast(Shade, SPELL_AKAMA_SOUL_RETRIEVE); @@ -603,6 +608,20 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI void JustDied(Unit* killer) { DoScriptText(SAY_DEATH, m_creature); + EventBegun = false; + ShadeHasDied = false; + StartCombat = false; + CastSoulRetrieveTimer = 0; + SoulRetrieveTimer = 0; + SummonBrokenTimer = 0; + EndingTalkCount = 0; + WayPointId = 0; + BrokenSummonIndex = 0; + BrokenList.clear(); + HasYelledOnce = false; + Creature* Shade = Unit::GetCreature((*m_creature), ShadeGUID); + if(Shade && Shade->isAlive()) + ((boss_shade_of_akamaAI*)Shade->AI())->HasKilledAkama = true; } void UpdateAI(const uint32 diff) @@ -650,7 +669,7 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI { if(ShadeGUID) { - Unit* Shade = Unit::GetUnit((*m_creature), ShadeGUID); + Creature* Shade = Unit::GetCreature((*m_creature), ShadeGUID); if(Shade && !Shade->isAlive()) { ShadeHasDied = true; @@ -658,6 +677,11 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI m_creature->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); m_creature->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z); } + if(Shade && Shade->isAlive()) + { + if(Shade->getThreatManager().getThreatList().size() < 2) + Shade->AI()->EnterEvadeMode(); + } } CheckTimer = 5000; }else CheckTimer -= diff; @@ -710,7 +734,7 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI { bool Yelled = false; for(std::list<uint64>::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if(Unit* pUnit = Unit::GetUnit(*m_creature, *itr)) + if(Creature* pUnit = Unit::GetCreature(*m_creature, *itr)) { if(!Yelled) { @@ -727,7 +751,7 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI if(!BrokenList.empty()) { for(std::list<uint64>::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if(Unit* pUnit = Unit::GetUnit(*m_creature, *itr)) + if(Creature* pUnit = Unit::GetCreature(*m_creature, *itr)) // This is the incorrect spell, but can't seem to find the right one. pUnit->CastSpell(pUnit, 39656, true); } @@ -738,7 +762,7 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI if(!BrokenList.empty()) { for(std::list<uint64>::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if(Unit* pUnit = Unit::GetUnit((*m_creature), *itr)) + if(Creature* pUnit = Unit::GetCreature((*m_creature), *itr)) pUnit->MonsterYell(SAY_BROKEN_FREE_02, LANG_UNIVERSAL, 0); } SoulRetrieveTimer = 0; @@ -751,7 +775,7 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI if(DestructivePoisonTimer < diff) { - Unit* Shade = Unit::GetUnit((*m_creature), ShadeGUID); + Creature* Shade = Unit::GetCreature((*m_creature), ShadeGUID); if (Shade && Shade->isAlive()) DoCast(Shade, SPELL_DESTRUCTIVE_POISON); DestructivePoisonTimer = 15000; diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp index 25e22f8f391..c5f7b402df6 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp @@ -43,7 +43,6 @@ struct TRINITY_DLL_DECL boss_anetheronAI : public hyjal_trashAI pInstance = ((ScriptedInstance*)c->GetInstanceData()); go = false; pos = 0; - Reset(); SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_SLEEP); if(TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) { @@ -61,6 +60,7 @@ struct TRINITY_DLL_DECL boss_anetheronAI : public hyjal_trashAI void Reset() { + damageTaken = 0; SwarmTimer = 45000; SleepTimer = 60000; AuraTimer = 5000; diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_archimonde.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_archimonde.cpp index b89a614389e..af842479ed1 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_archimonde.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_archimonde.cpp @@ -239,6 +239,7 @@ struct TRINITY_DLL_DECL boss_archimondeAI : public hyjal_trashAI pInstance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); DoomfireSpiritGUID = 0; + damageTaken = 0; WorldTreeGUID = 0; DrainNordrassilTimer = 0; diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp index 85948706145..fac53fbda02 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp @@ -34,7 +34,6 @@ struct TRINITY_DLL_DECL boss_azgalorAI : public hyjal_trashAI pInstance = ((ScriptedInstance*)c->GetInstanceData()); go = false; pos = 0; - Reset(); SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_HOWL_OF_AZGALOR); if(TempSpell) TempSpell->EffectRadiusIndex[0] = 12;//100yards instead of 50000?! @@ -52,6 +51,7 @@ struct TRINITY_DLL_DECL boss_azgalorAI : public hyjal_trashAI void Reset() { + damageTaken = 0; RainTimer = 20000; DoomTimer = 50000; HowlTimer = 30000; diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_kazrogal.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_kazrogal.cpp index 6bd24fca7a4..33c6ec44cf9 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_kazrogal.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_kazrogal.cpp @@ -31,7 +31,6 @@ struct TRINITY_DLL_DECL boss_kazrogalAI : public hyjal_trashAI pInstance = ((ScriptedInstance*)c->GetInstanceData()); go = false; pos = 0; - Reset(); SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_MARK); if(TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) { @@ -49,6 +48,7 @@ struct TRINITY_DLL_DECL boss_kazrogalAI : public hyjal_trashAI void Reset() { + damageTaken = 0; CleaveTimer = 5000; WarStompTimer = 15000; MarkTimer = 45000; diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp index b125668947c..ddf5e0ad715 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp @@ -37,7 +37,6 @@ struct TRINITY_DLL_DECL boss_rage_winterchillAI : public hyjal_trashAI pInstance = ((ScriptedInstance*)c->GetInstanceData()); go = false; pos = 0; - Reset(); } uint32 FrostArmorTimer; @@ -49,6 +48,7 @@ struct TRINITY_DLL_DECL boss_rage_winterchillAI : public hyjal_trashAI void Reset() { + damageTaken = 0; FrostArmorTimer = 37000; DecayTimer = 45000; NovaTimer = 15000; diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp index 74d283340b1..ed62e77b218 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp @@ -84,18 +84,34 @@ float InfernalPos[8][3]=//spawn points for the infernals in the horde base {5482.39, -2689.19, 1481.09} }; -float InfernalSPWP[10][3]=//spawn points for the infernals in the horde base used in the cleaning wave +float InfernalSPWP[26][4]=//spawn points for the infernals in the horde base used in the cleaning wave { - {5528.5, -2771.23, 1494.08}, - {5471.41, -2711.17, 1483.97}, - {5464.08, -2653.9, 1482.67}, - {5550.84, -2633.8, 1484.08}, - {5579.86, -2704.86, 1489.33}, - {5589.67, -2655.5, 1490.15}, - {5432.36, -2744.81, 1486.25}, - {5463.14, -2857.41, 1512.45}, - {5534.31, -2774.58, 1494.89}, - {5524.36, -2735.52, 1484.16} + {5490.96, -2718.72, 1482.96, 0.49773}, + {5449.51, -2723.32, 1485.69, 2.69685}, + {5520.83, -2624.68, 1483.82, 1.20459}, + {5558.28, -2629.26, 1485.76, 0.37992}, + {5567.97, -2758.69, 1494.10, 5.04125}, + {5384.90, -2793.47, 1503.90, 5.55412}, + {5495.33, -2814.06, 1501.56, 1.12055}, + {5472.63, -2929.39, 1538.31, 1.95777}, + {5334.72, -2952.29, 1534.34, 0.50869}, + {5398.36, -2872.46, 1512.38, 0.76787}, + {5514.39, -2768.63, 1492.30, 1.55721}, + {5598.91, -2703.75, 1495.64, 2.56644}, + {5467.80, -2655.93, 1482.27, 0.85819}, + {5399.83, -2985.24, 1545.04, 5.92559}, + {5232.13, -2967.05, 1553.09, 5.41351}, + {5272.02, -3082.52, 1567.09, 3.40681}, + {5343.26, -3120.71, 1582.92, 3.16727}, + {5371.26, -3175.24, 1587.41, 6.10466}, + {5434.67, -3177.91, 1579.25, 2.77850}, + {5237.39, -3149.25, 1593.59, 0.83855}, + {5202.15, -3016.64, 1566.28, 3.31256}, + {5302.54, -2914.37, 1528.53, 3.37146}, + {5439.04, -2834.81, 1508.80, 2.14231}, + {5421.33, -2771.04, 1494.28, 6.06223}, + {5549.76, -2692.93, 1482.68, 2.19414}, + {5459.78, -2755.71, 1490.68, 1.05139} }; float VeinPos[14][8]=//spawn points of the ancient gem veins @@ -116,6 +132,15 @@ float VeinPos[14][8]=//spawn points of the ancient gem veins {5441.54, -3321.59, 1651.55, 0.258306, 0, 0, 0.128794, 0.991671} //horde }; +float AllianceOverrunGargPos[5][4]=//gargoyle spawn points in the alliance overrun +{ + {5279.94, -2049.68, 1311.38, 0},//garg1 + {5289.15, -2219.06, 1291.12, 0},//garg2 + {5202.07, -2136.10, 1305.07, 2.8},//garg3 + {5071.52, -2425.63, 1454.48, 5.54},//garg4 + {5120.65, -2467.92, 1463.93, 2.54}//garg5 +}; + float AllianceFirePos[92][8]=//spawn points for the fire visuals (GO) in the alliance base { {5039.9, -1796.84, 1323.88, 2.59222, 0, 0, 0.962511, 0.271243}, @@ -1142,7 +1167,7 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) pUnit->setActive(true); } } - for(uint8 i = 0; i < 5; i++)//summon 5 abominations + for(uint8 i = 0; i < 3; i++)//summon 3 abominations { uint8 r = rand()%4; Creature* pUnit = m_creature->SummonCreature(ABOMINATION, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); @@ -1156,10 +1181,10 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) } for(uint8 i = 0; i < 5; i++)//summon 5 gargoyles { - uint8 r = rand()%4; - Creature* pUnit = m_creature->SummonCreature(GARGOYLE, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + Creature* pUnit = m_creature->SummonCreature(GARGOYLE, AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); if(pUnit) { + pUnit->SetHomePosition(AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3]); ((hyjal_trashAI*)pUnit->AI())->faction = Faction; ((hyjal_trashAI*)pUnit->AI())->IsOverrun = true; ((hyjal_trashAI*)pUnit->AI())->OverrunType = i; @@ -1171,6 +1196,42 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) for(uint8 i = 0; i < 65; i++)//summon fires m_creature->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); + for(uint8 i = 0; i < 26; i++)//summon infernals + { + Creature* pUnit = m_creature->SummonCreature(GIANT_INFERNAL, InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if(pUnit) + { + pUnit->SetHomePosition(InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3]); + ((hyjal_trashAI*)pUnit->AI())->faction = Faction; + ((hyjal_trashAI*)pUnit->AI())->IsOverrun = true; + ((hyjal_trashAI*)pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for(uint8 i = 0; i < 25; i++)//summon 25 ghouls + { + uint8 r = rand()%4; + Creature* pUnit = m_creature->SummonCreature(GHOUL, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if(pUnit) + { + ((hyjal_trashAI*)pUnit->AI())->faction = Faction; + ((hyjal_trashAI*)pUnit->AI())->IsOverrun = true; + ((hyjal_trashAI*)pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for(uint8 i = 0; i < 5; i++)//summon 5 abominations + { + uint8 r = rand()%4; + Creature* pUnit = m_creature->SummonCreature(ABOMINATION, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if(pUnit) + { + ((hyjal_trashAI*)pUnit->AI())->faction = Faction; + ((hyjal_trashAI*)pUnit->AI())->IsOverrun = true; + ((hyjal_trashAI*)pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } break; } }
\ No newline at end of file diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp index 3f6fd1044ff..ac15c8cc30e 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp @@ -17,7 +17,7 @@ float HordeWPs[8][3]=//basic waypoints from spawn to leader {5554.58, -2514.66, 1476.12}, {5554.16, -2567.23, 1479.90}, {5540.67, -2625.99, 1480.89}, - {5508.16, -2659.2, 1480.15}, + {5508.16, -2659.20, 1480.15},//random rush starts from here {5489.62, -2704.05, 1482.18}, {5457.04, -2726.26, 1485.10} }; @@ -36,7 +36,7 @@ float AllianceWPs[8][3]=//basic waypoints from spawn to leader float FrostWyrmWPs[3][3]=//waypoints for the frost wyrms in horde base { {5580.82, -2628.83, 1528.28}, - {5550.9, -2667.16, 1505.45}, + {5550.90, -2667.16, 1505.45}, {5459.64, -2725.91, 1484.83} }; @@ -54,7 +54,7 @@ float FlyPathWPs[3][3]=//waypoints for the gargoyls and frost wyrms in horde bas {5456.67, -2725.48, 1493.08} }; -float AllianceOverrunWP[36][3]=//waypoints in the alliance base used in the end in the cleaning wave +float AllianceOverrunWP[55][3]=//waypoints in the alliance base used in the end in the cleaning wave { {4976.37,-1708.02,1339.43},//0spawn {4994.83,-1725.52,1333.25},//1 start @@ -91,45 +91,52 @@ float AllianceOverrunWP[36][3]=//waypoints in the alliance base used in the end {4983.25, -1857.4, 1320.48},//32 {5015.94, -1821.24, 1321.86},//33 {5027.97, -1775.25, 1321.87},//34 - {5015.27, -1738.77, 1324.83}//35 + {5015.27, -1738.77, 1324.83},//35 + {5081.07, -1902.10, 1346.36},//36 abo start + {5107.65, -1912.03, 1356.49},//37 + {5132.83, -1927.07, 1362.42},//38 + {5147.78, -1954.41, 1365.98},//39 + {5164.96, -1966.48, 1367.04},//40 + {5189.04, -1961.06, 1367.90},//41 + {5212.27, -1975.30, 1365.58},//42 + {5221.82, -1994.18, 1364.97},//43 end1 + {5202.23, -1994.94, 1367.59},//44 end2 + {5279.94, -2049.68, 1311.38},//45 garg1 + {5289.15, -2219.06, 1291.12},//46 garg2 + {5202.07, -2136.10, 1305.07},//47 garg3 + {5071.52, -2425.63, 1454.48},//48 garg4 + {5120.65, -2467.92, 1463.93},//49 garg5 + {5283.04, -2043.26, 1300.11},//50 garg target1 + {5313.22, -2207.60, 1290.06},//51 garg target2 + {5180.41, -2121.87, 1292.62},//52 garg target3 + {5088.68, -2432.04, 1441.73},//53 garg target4 + {5111.26, -2454.73, 1449.63}//54 garg target5 }; -float HordeOverrunWP[33][3]=//waypoints in the horde base used in the end in the cleaning wave -{ - {5510.4815, -2676.7112, 1480.4314},// 0 spawn - {5528.5, -2771.23, 1494.08},// 1 infernal 1 - {5471.41, -2711.17, 1483.97},// 2 infernal 2 - {5464.08, -2653.9, 1482.67},// 3 infernal 3 - {5550.84, -2633.8, 1484.08},// 4 infernal 4 - {5579.86, -2704.86, 1489.33},// 5 infernal 5 - {5531.17, -2634.41, 1481.11},// 6 start - {5484.56, -2662.32, 1481.11},// 7 end - {5528.79, -2636.19, 1481.33},// 8 start - {5511.87, -2626.16, 1484.76},// 9 end - {5537.93, -2637.54, 1480.69},// 10 start - {5504.26, -2710.44, 1482.14},// 11 - {5449.92, -2724.51, 1485.69},// 12 - {5431.08, -2713.96, 1493.37},// 13 end - {5546.89, -2620.74, 1481.06},// 14 start - {5579.75, -2658.66, 1488.61},// 15 - {5598.45, -2692.56, 1493.59},// 16 end - {5550.96, -2624.63, 1482.94},// 17 start - {5578.7, -2656.13, 1488.69},// 18 - {5574.56, -2722.74, 1488.5},// 19 - {5590.46, -2746.81, 1495},// 20 - {5571.33, -2761.14, 1494.93},// 21 - {5546.45, -2770.83, 1495.33},// 22 - {5532.51, -2804.72, 1498.49},// 23 - {5492.97, -2760.9, 1489.16},// 24 - {5451.35, -2724.44, 1485.58},// 25 - {5430.23, -2714.38, 1493.51},// 26 end - {5535.67, -2627.69, 1480.87},// 27 start - {5485.75, -2667.97, 1480.64},// 28 - {5510.78, -2740.5, 1486.27},// 29 - {5559.93, -2710.97, 1483.59},// 30 - {5561.09, -2688.13, 1484.65},// 31 - {5556.73, -2676.17, 1482.58}// 32 end +float HordeOverrunWP[21][3]=//waypoints in the horde base used in the end in the cleaning wave +{ + {5490.72,-2702.94,1482.14},//0 start + {5469.77,-2741.34,1486.95}, + {5439.47,-2771.02,1494.59}, + {5408.85,-2811.92,1505.68}, + {5423.87,-2857.80,1515.55}, + {5428.19,-2898.15,1524.61}, + {5394.59,-2930.05,1528.23}, + {5351.11,-2935.80,1532.24}, + {5312.37,-2959.06,1536.21}, + {5264.93,-2989.80,1545.70}, + {5256.63,-3056.16,1559.24}, + {5267.32,-3119.55,1575.36}, + {5305.61,-3139.88,1586.38}, + {5330.56,-3135.37,1588.58}, + {5365.87,-3139.78,1583.96}, + {5389.39,-3163.57,1582.57},//15 end + {5500.86,-2669.89,1481.04},//16 start + {5472.08,-2715.14,1483.55}, + {5450.11,-2721.47,1485.61}, + {5433.25,-2712.93,1493.02},//19 end 1 + {5429.91,-2718.44,1493.42}//20 end 2 }; void hyjal_trashAI::Reset(){} @@ -151,7 +158,7 @@ hyjal_trashAI::hyjal_trashAI(Creature *c) : npc_escortAI(c) void hyjal_trashAI::DamageTaken(Unit *done_by, uint32 &damage) { - if(done_by->GetTypeId() == TYPEID_PLAYER) + if(done_by->GetTypeId() == TYPEID_PLAYER || (done_by->GetTypeId() == TYPEID_UNIT && ((Creature*)done_by)->isPet())) { damageTaken += damage; if(pInstance) @@ -167,12 +174,124 @@ void hyjal_trashAI::UpdateAI(const uint32 diff) { SetupOverrun = true; if(faction == 0) - { - for(uint8 i = 0; i < 4; i++) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + { + if(m_creature->GetEntry() == GARGOYLE) + { + switch(OverrunType) + { + case 0: + { + DummyTarget[0] = AllianceOverrunWP[50][0]; + DummyTarget[1] = AllianceOverrunWP[50][1]; + DummyTarget[2] = AllianceOverrunWP[50][2]; + } + break; + case 1: + { + DummyTarget[0] = AllianceOverrunWP[51][0]; + DummyTarget[1] = AllianceOverrunWP[51][1]; + DummyTarget[2] = AllianceOverrunWP[51][2]; + } + break; + case 2: + { + DummyTarget[0] = AllianceOverrunWP[52][0]; + DummyTarget[1] = AllianceOverrunWP[52][1]; + DummyTarget[2] = AllianceOverrunWP[52][2]; + } + break; + case 3: + { + DummyTarget[0] = AllianceOverrunWP[53][0]; + DummyTarget[1] = AllianceOverrunWP[53][1]; + DummyTarget[2] = AllianceOverrunWP[53][2]; + } + break; + case 4: + { + DummyTarget[0] = AllianceOverrunWP[54][0]; + DummyTarget[1] = AllianceOverrunWP[54][1]; + DummyTarget[2] = AllianceOverrunWP[54][2]; + } + break; + } + + } + if(m_creature->GetEntry() == ABOMINATION) + { + for(uint8 i = 0; i < 4; i++) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint( 4, AllianceOverrunWP[35][0]+irand(-3,3), AllianceOverrunWP[35][1]+irand(-3,3), AllianceOverrunWP[35][2]); + AddWaypoint( 5, AllianceOverrunWP[34][0]+irand(-3,3), AllianceOverrunWP[34][1]+irand(-3,3), AllianceOverrunWP[34][2]); + AddWaypoint( 6, AllianceOverrunWP[33][0]+irand(-3,3), AllianceOverrunWP[33][1]+irand(-3,3), AllianceOverrunWP[33][2]); + AddWaypoint( 7, AllianceOverrunWP[32][0]+irand(-3,3), AllianceOverrunWP[32][1]+irand(-3,3), AllianceOverrunWP[32][2]); + AddWaypoint( 8, AllianceOverrunWP[31][0]+irand(-3,3), AllianceOverrunWP[31][1]+irand(-3,3), AllianceOverrunWP[31][2]); + AddWaypoint( 9, AllianceOverrunWP[30][0]+irand(-3,3), AllianceOverrunWP[30][1]+irand(-3,3), AllianceOverrunWP[30][2]); + AddWaypoint(10, AllianceOverrunWP[29][0]+irand(-3,3), AllianceOverrunWP[29][1]+irand(-3,3), AllianceOverrunWP[29][2]); + AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); + AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); + AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); + AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); + AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); + AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); + AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); + AddWaypoint(18, AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2]); + m_creature->SetHomePosition(AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 18; + Start(true, true, true); + break; + case 1: + AddWaypoint( 4, AllianceOverrunWP[35][0]+irand(-3,3), AllianceOverrunWP[35][1]+irand(-3,3), AllianceOverrunWP[35][2]); + AddWaypoint( 5, AllianceOverrunWP[34][0]+irand(-3,3), AllianceOverrunWP[34][1]+irand(-3,3), AllianceOverrunWP[34][2]); + AddWaypoint( 6, AllianceOverrunWP[33][0]+irand(-3,3), AllianceOverrunWP[33][1]+irand(-3,3), AllianceOverrunWP[33][2]); + AddWaypoint( 7, AllianceOverrunWP[32][0]+irand(-3,3), AllianceOverrunWP[32][1]+irand(-3,3), AllianceOverrunWP[32][2]); + AddWaypoint( 8, AllianceOverrunWP[31][0]+irand(-3,3), AllianceOverrunWP[31][1]+irand(-3,3), AllianceOverrunWP[31][2]); + AddWaypoint( 9, AllianceOverrunWP[30][0]+irand(-3,3), AllianceOverrunWP[30][1]+irand(-3,3), AllianceOverrunWP[30][2]); + AddWaypoint(10, AllianceOverrunWP[29][0]+irand(-3,3), AllianceOverrunWP[29][1]+irand(-3,3), AllianceOverrunWP[29][2]); + AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); + AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); + AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); + AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); + AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); + AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); + AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); + AddWaypoint(18, AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2]); + m_creature->SetHomePosition(AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 18; + Start(true, true, true); + break; + default: + AddWaypoint( 4, AllianceOverrunWP[35][0]+irand(-3,3), AllianceOverrunWP[35][1]+irand(-3,3), AllianceOverrunWP[35][2]); + AddWaypoint( 5, AllianceOverrunWP[34][0]+irand(-3,3), AllianceOverrunWP[34][1]+irand(-3,3), AllianceOverrunWP[34][2]); + AddWaypoint( 6, AllianceOverrunWP[33][0]+irand(-3,3), AllianceOverrunWP[33][1]+irand(-3,3), AllianceOverrunWP[33][2]); + AddWaypoint( 7, AllianceOverrunWP[32][0]+irand(-3,3), AllianceOverrunWP[32][1]+irand(-3,3), AllianceOverrunWP[32][2]); + AddWaypoint( 8, AllianceOverrunWP[31][0]+irand(-3,3), AllianceOverrunWP[31][1]+irand(-3,3), AllianceOverrunWP[31][2]); + AddWaypoint( 9, AllianceOverrunWP[30][0]+irand(-3,3), AllianceOverrunWP[30][1]+irand(-3,3), AllianceOverrunWP[30][2]); + AddWaypoint(10, AllianceOverrunWP[29][0]+irand(-3,3), AllianceOverrunWP[29][1]+irand(-3,3), AllianceOverrunWP[29][2]); + AddWaypoint(11, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); + AddWaypoint(12, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); + AddWaypoint(13, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); + AddWaypoint(14, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); + AddWaypoint(15, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); + AddWaypoint(16, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); + AddWaypoint(17, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); + //m_creature->SetHomePosition(AllianceOverrunWP[0][0]+irand(-3,3), AllianceOverrunWP[0][1]+irand(-3,3), AllianceOverrunWP[0][2],0); + SetDespawnAtEnd(true); + LastOverronPos = 17; + Start(true, true, true); + break; + } + } if(m_creature->GetEntry() == GHOUL) { - switch(OverrunType)//0-19 ghouls, 20-24 abominations, 25-29 gargoyles + for(uint8 i = 0; i < 4; i++) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + switch(OverrunType) { case 0: AddWaypoint(4, AllianceOverrunWP[1][0]+irand(-3,3), AllianceOverrunWP[1][1]+irand(-3,3), AllianceOverrunWP[1][2]); @@ -252,81 +371,91 @@ void hyjal_trashAI::UpdateAI(const uint32 diff) Start(true, true, true); break; } + } + } + if(faction == 1) + { + if(m_creature->GetEntry() == GHOUL) + { + for(uint8 i = 0; i < 6; i++) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint( 5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); + AddWaypoint( 6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); + AddWaypoint( 7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); + AddWaypoint( 8, HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2]); + m_creature->SetHomePosition(HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 8; + Start(true, true, true); + break; + case 1: + AddWaypoint( 5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); + AddWaypoint( 6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); + AddWaypoint( 7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); + AddWaypoint( 8, HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2]); + m_creature->SetHomePosition(HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 8; + Start(true, true, true); + break; + default: + AddWaypoint( 5, HordeOverrunWP[0][0]+irand(-10,10), HordeOverrunWP[0][1]+irand(-10,10), HordeOverrunWP[0][2]); + AddWaypoint( 6, HordeOverrunWP[1][0]+irand(-10,10), HordeOverrunWP[1][1]+irand(-10,10), HordeOverrunWP[1][2]); + AddWaypoint( 7, HordeOverrunWP[2][0]+irand(-10,10), HordeOverrunWP[2][1]+irand(-10,10), HordeOverrunWP[2][2]); + AddWaypoint( 8, HordeOverrunWP[3][0]+irand(-10,10), HordeOverrunWP[3][1]+irand(-10,10), HordeOverrunWP[3][2]); + AddWaypoint( 9, HordeOverrunWP[4][0]+irand(-10,10), HordeOverrunWP[4][1]+irand(-10,10), HordeOverrunWP[4][2]); + AddWaypoint(10, HordeOverrunWP[5][0]+irand(-10,10), HordeOverrunWP[5][1]+irand(-10,10), HordeOverrunWP[5][2]); + AddWaypoint(11, HordeOverrunWP[6][0]+irand(-10,10), HordeOverrunWP[6][1]+irand(-10,10), HordeOverrunWP[6][2]); + AddWaypoint(12, HordeOverrunWP[7][0]+irand(-10,10), HordeOverrunWP[7][1]+irand(-10,10), HordeOverrunWP[7][2]); + AddWaypoint(13, HordeOverrunWP[8][0]+irand(-10,10), HordeOverrunWP[8][1]+irand(-10,10), HordeOverrunWP[8][2]); + AddWaypoint(14, HordeOverrunWP[9][0]+irand(-10,10), HordeOverrunWP[9][1]+irand(-10,10), HordeOverrunWP[9][2]); + AddWaypoint(15, HordeOverrunWP[10][0]+irand(-10,10), HordeOverrunWP[10][1]+irand(-10,10), HordeOverrunWP[10][2]); + AddWaypoint(16, HordeOverrunWP[11][0]+irand(-10,10), HordeOverrunWP[11][1]+irand(-10,10), HordeOverrunWP[11][2]); + AddWaypoint(17, HordeOverrunWP[12][0]+irand(-10,10), HordeOverrunWP[12][1]+irand(-10,10), HordeOverrunWP[12][2]); + AddWaypoint(18, HordeOverrunWP[13][0]+irand(-10,10), HordeOverrunWP[13][1]+irand(-10,10), HordeOverrunWP[13][2]); + AddWaypoint(19, HordeOverrunWP[14][0]+irand(-10,10), HordeOverrunWP[14][1]+irand(-10,10), HordeOverrunWP[14][2]); + AddWaypoint(20, HordeOverrunWP[15][0]+irand(-10,10), HordeOverrunWP[15][1]+irand(-10,10), HordeOverrunWP[15][2]); + //m_creature->SetHomePosition(AllianceOverrunWP[2][0]+irand(-10,10), AllianceOverrunWP[2][1]+irand(-10,10), AllianceOverrunWP[2][2],0); + SetDespawnAtEnd(true); + LastOverronPos = 20; + Start(true, true, true); + break; + } + } + if(m_creature->GetEntry() == ABOMINATION) + { + for(uint8 i = 0; i < 6; i++) + AddWaypoint(i, HordeWPs[i][0]+irand(-10,10), HordeWPs[i][1]+irand(-10,10), HordeWPs[i][2]); + switch(OverrunType) + { + case 0: + default: + AddWaypoint( 5, HordeOverrunWP[0][0]+irand(-10,10), HordeOverrunWP[0][1]+irand(-10,10), HordeOverrunWP[0][2]); + AddWaypoint( 6, HordeOverrunWP[1][0]+irand(-10,10), HordeOverrunWP[1][1]+irand(-10,10), HordeOverrunWP[1][2]); + AddWaypoint( 7, HordeOverrunWP[2][0]+irand(-10,10), HordeOverrunWP[2][1]+irand(-10,10), HordeOverrunWP[2][2]); + AddWaypoint( 8, HordeOverrunWP[3][0]+irand(-10,10), HordeOverrunWP[3][1]+irand(-10,10), HordeOverrunWP[3][2]); + AddWaypoint( 9, HordeOverrunWP[4][0]+irand(-10,10), HordeOverrunWP[4][1]+irand(-10,10), HordeOverrunWP[4][2]); + AddWaypoint(10, HordeOverrunWP[5][0]+irand(-10,10), HordeOverrunWP[5][1]+irand(-10,10), HordeOverrunWP[5][2]); + AddWaypoint(11, HordeOverrunWP[6][0]+irand(-10,10), HordeOverrunWP[6][1]+irand(-10,10), HordeOverrunWP[6][2]); + AddWaypoint(12, HordeOverrunWP[7][0]+irand(-10,10), HordeOverrunWP[7][1]+irand(-10,10), HordeOverrunWP[7][2]); + AddWaypoint(13, HordeOverrunWP[8][0]+irand(-10,10), HordeOverrunWP[8][1]+irand(-10,10), HordeOverrunWP[8][2]); + AddWaypoint(14, HordeOverrunWP[9][0]+irand(-10,10), HordeOverrunWP[9][1]+irand(-10,10), HordeOverrunWP[9][2]); + AddWaypoint(15, HordeOverrunWP[10][0]+irand(-10,10), HordeOverrunWP[10][1]+irand(-10,10), HordeOverrunWP[10][2]); + AddWaypoint(16, HordeOverrunWP[11][0]+irand(-10,10), HordeOverrunWP[11][1]+irand(-10,10), HordeOverrunWP[11][2]); + AddWaypoint(17, HordeOverrunWP[12][0]+irand(-10,10), HordeOverrunWP[12][1]+irand(-10,10), HordeOverrunWP[12][2]); + AddWaypoint(18, HordeOverrunWP[13][0]+irand(-10,10), HordeOverrunWP[13][1]+irand(-10,10), HordeOverrunWP[13][2]); + AddWaypoint(19, HordeOverrunWP[14][0]+irand(-10,10), HordeOverrunWP[14][1]+irand(-10,10), HordeOverrunWP[14][2]); + AddWaypoint(20, HordeOverrunWP[15][0]+irand(-10,10), HordeOverrunWP[15][1]+irand(-10,10), HordeOverrunWP[15][2]); + //m_creature->SetHomePosition(AllianceOverrunWP[2][0]+irand(-10,10), AllianceOverrunWP[2][1]+irand(-10,10), AllianceOverrunWP[2][2],0); + SetDespawnAtEnd(true); + LastOverronPos = 20; + Start(true, true, true); + break; + } } - //}else if(faction == 1 && m_creature->GetEntry() != GARGOYLE){ - // switch(OverrunType) - // { - // case 0:break;//infernal - // case 1: - // AddWaypoint(0, HordeOverrunWP[6][0], HordeOverrunWP[6][1], HordeOverrunWP[6][2]); - // AddWaypoint(1, HordeOverrunWP[7][0]+irand(-3,3), HordeOverrunWP[7][1]+irand(-3,3), HordeOverrunWP[7][2]); - // SetDespawnAtEnd(false); - // LastOverronPos = 1; - // Start(true, true, true); - // break; - // case 2: - // AddWaypoint(0, HordeOverrunWP[6][0], HordeOverrunWP[6][1], HordeOverrunWP[6][2]); - // AddWaypoint(1, HordeOverrunWP[7][0]+irand(-3,3), HordeOverrunWP[7][1]+irand(-3,3), HordeOverrunWP[7][2]); - // SetDespawnAtEnd(false); - // LastOverronPos = 1; - // Start(true, true, true); - // break; - // case 3: - // AddWaypoint(0, HordeOverrunWP[8][0], HordeOverrunWP[8][1], HordeOverrunWP[8][2]); - // AddWaypoint(1, HordeOverrunWP[9][0]+irand(-3,3), HordeOverrunWP[9][1]+irand(-3,3), HordeOverrunWP[9][2]); - // SetDespawnAtEnd(false); - // LastOverronPos = 1; - // Start(true, true, true); - // break; - // case 4: - // AddWaypoint(0, HordeOverrunWP[10][0], HordeOverrunWP[10][1], HordeOverrunWP[10][2]); - // AddWaypoint(1, HordeOverrunWP[11][0], HordeOverrunWP[11][1], HordeOverrunWP[11][2]); - // AddWaypoint(2, HordeOverrunWP[12][0], HordeOverrunWP[12][1], HordeOverrunWP[12][2]); - // AddWaypoint(3, HordeOverrunWP[13][0]+irand(-3,3), HordeOverrunWP[13][1]+irand(-3,3), HordeOverrunWP[13][2]); - // SetDespawnAtEnd(false); - // LastOverronPos = 3; - // Start(true, true, true); - // break; - // case 5: - // AddWaypoint(0, HordeOverrunWP[14][0], HordeOverrunWP[14][1], HordeOverrunWP[14][2]); - // AddWaypoint(1, HordeOverrunWP[15][0], HordeOverrunWP[15][1], HordeOverrunWP[15][2]); - // AddWaypoint(2, HordeOverrunWP[16][0]+irand(-3,3), HordeOverrunWP[16][1]+irand(-3,3), HordeOverrunWP[16][2]); - // SetDespawnAtEnd(false); - // LastOverronPos = 2; - // Start(true, true, true); - // break; - // case 6: - // AddWaypoint(0, HordeOverrunWP[17][0], HordeOverrunWP[17][1], HordeOverrunWP[17][2]); - // AddWaypoint(1, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); - // AddWaypoint(2, HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2]); - // AddWaypoint(3, HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2]); - // AddWaypoint(4, HordeOverrunWP[21][0], HordeOverrunWP[21][1], HordeOverrunWP[21][2]); - // AddWaypoint(5, HordeOverrunWP[22][0], HordeOverrunWP[22][1], HordeOverrunWP[22][2]); - // AddWaypoint(6, HordeOverrunWP[23][0], HordeOverrunWP[23][1], HordeOverrunWP[23][2]); - // AddWaypoint(7, HordeOverrunWP[24][0], HordeOverrunWP[24][1], HordeOverrunWP[24][2]); - // AddWaypoint(8, HordeOverrunWP[25][0], HordeOverrunWP[25][1], HordeOverrunWP[25][2]); - // AddWaypoint(9, HordeOverrunWP[26][0]+irand(-3,3), HordeOverrunWP[26][1]+irand(-3,3), HordeOverrunWP[26][2]); - // SetDespawnAtEnd(true); - // LastOverronPos = 9; - // Start(true, true, true); - // break; - // case 7: - // AddWaypoint(0, HordeOverrunWP[27][0], HordeOverrunWP[27][1], HordeOverrunWP[27][2]); - // AddWaypoint(1, HordeOverrunWP[28][0], HordeOverrunWP[28][1], HordeOverrunWP[28][2]); - // AddWaypoint(2, HordeOverrunWP[29][0], HordeOverrunWP[29][1], HordeOverrunWP[29][2]); - // AddWaypoint(3, HordeOverrunWP[30][0], HordeOverrunWP[30][1], HordeOverrunWP[30][2]); - // AddWaypoint(4, HordeOverrunWP[31][0], HordeOverrunWP[31][1], HordeOverrunWP[31][2]); - // AddWaypoint(5, HordeOverrunWP[32][0]+irand(-3,3), HordeOverrunWP[32][1]+irand(-3,3), HordeOverrunWP[32][2]); - // SetDespawnAtEnd(true); - // LastOverronPos = 5; - // Start(true, true, true); - // break; - // } - //}else if(faction == 1 && m_creature->GetEntry() == GARGOYLE){ - // AddWaypoint(0, 5536.65+irand(-80,+80), -2710.66+irand(-80,+80), 1504.45+irand(-5,+5)); - // SetDespawnAtEnd(false); - // LastOverronPos = 0; - // Start(false, true, true); } } } @@ -337,7 +466,7 @@ void hyjal_trashAI::JustDied(Unit *victim) if(IsEvent && !m_creature->isWorldBoss()) pInstance->SetData(DATA_TRASH, 0);//signal trash is dead - if((pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE && !m_creature->isWorldBoss()) || (damageTaken < m_creature->GetMaxHealth()/2 && m_creature->isWorldBoss())) + if((pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE && !m_creature->isWorldBoss()) || (damageTaken < m_creature->GetMaxHealth()/4 && m_creature->isWorldBoss())) m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);//no loot if(IsOverrun) @@ -351,6 +480,9 @@ void hyjal_trashAI::JustDied(Unit *victim) ((hyjal_trashAI*)pUnit->AI())->IsOverrun = true; ((hyjal_trashAI*)pUnit->AI())->OverrunType = OverrunType; ((hyjal_trashAI*)pUnit->AI())->SetupOverrun = true; + ((hyjal_trashAI*)pUnit->AI())->DummyTarget[0] = DummyTarget[0]; + ((hyjal_trashAI*)pUnit->AI())->DummyTarget[1] = DummyTarget[1]; + ((hyjal_trashAI*)pUnit->AI())->DummyTarget[2] = DummyTarget[2]; pUnit->setActive(true); pUnit->AI()->EnterEvadeMode(); } @@ -364,7 +496,7 @@ struct mob_giant_infernalAI : public hyjal_trashAI pInstance = ((ScriptedInstance*)c->GetInstanceData()); meteor = false;//call once! CanMove = false; - Delay = rand()%10000; + Delay = rand()%30000; m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_INVIS); @@ -402,19 +534,6 @@ struct mob_giant_infernalAI : public hyjal_trashAI if (target && target->isAlive()) m_creature->AddThreat(target,0.0); } - } - if (i == LastOverronPos && IsOverrun) - { - Creature* pUnit = m_creature->SummonCreature(17931, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 2*60*1000); - if(pUnit) - { - pUnit->SetVisibility(VISIBILITY_OFF); - pUnit->SetMaxHealth(10000000); - pUnit->SetHealth(10000000); - pUnit->setFaction(17772); - pUnit->Attack(m_creature, true); - m_creature->AddThreat(pUnit,0); - } } } @@ -542,15 +661,29 @@ struct mob_abominationAI : public hyjal_trashAI } if (i == LastOverronPos && IsOverrun) { - Creature* pUnit = m_creature->SummonCreature(17931, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 2*60*1000); - if(pUnit) + if(faction == 0 && LastOverronPos == 17)//alliance round { - pUnit->SetVisibility(VISIBILITY_OFF); - pUnit->SetMaxHealth(10000000); - pUnit->SetHealth(10000000); - pUnit->setFaction(17772); - pUnit->Attack(m_creature, true); - m_creature->AddThreat(pUnit,0); + Creature* pUnit = m_creature->SummonCreature(m_creature->GetEntry(),4928.48+irand(-10,10), -1526.38+irand(-10,10), 1326.83,0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if(pUnit) + { + ((hyjal_trashAI*)pUnit->AI())->faction = faction; + ((hyjal_trashAI*)pUnit->AI())->IsOverrun = true; + ((hyjal_trashAI*)pUnit->AI())->OverrunType = 2;//default + ((hyjal_trashAI*)pUnit->AI())->SetupOverrun = false; + pUnit->setActive(true); + } + } + if(faction == 1 && LastOverronPos == 20)//horde round + { + Creature* pUnit = m_creature->SummonCreature(m_creature->GetEntry(),5458.01+irand(-10,10),-2340.27+irand(-10,10),1459.60,0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if(pUnit) + { + ((hyjal_trashAI*)pUnit->AI())->faction = faction; + ((hyjal_trashAI*)pUnit->AI())->IsOverrun = true; + ((hyjal_trashAI*)pUnit->AI())->OverrunType = 10;//default + ((hyjal_trashAI*)pUnit->AI())->SetupOverrun = false; + pUnit->setActive(true); + } } } } @@ -619,9 +752,13 @@ struct mob_ghoulAI : public hyjal_trashAI bool go; uint32 FrenzyTimer; uint32 pos; + uint32 MoveTimer; + bool RandomMove; void Reset() { FrenzyTimer = 5000+rand()%5000; + MoveTimer = 2000; + RandomMove = false; } void WaypointReached(uint32 i) @@ -639,18 +776,13 @@ struct mob_ghoulAI : public hyjal_trashAI if (target && target->isAlive()) m_creature->AddThreat(target,0.0); } - } - if(faction == 0)//alliance round - { - } if (i == LastOverronPos && IsOverrun) { m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); - //m_creature->SetHomePosition(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation()); if(faction == 0 && LastOverronPos == 17)//alliance round { - Creature* pUnit = m_creature->SummonCreature(m_creature->GetEntry(),4928.48+irand(-10,10), -1526.38+irand(-10,10), 1326.83+irand(-10,10),0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + Creature* pUnit = m_creature->SummonCreature(m_creature->GetEntry(),4928.48+irand(-10,10), -1526.38+irand(-10,10), 1326.83,0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); if(pUnit) { ((hyjal_trashAI*)pUnit->AI())->faction = faction; @@ -660,6 +792,18 @@ struct mob_ghoulAI : public hyjal_trashAI pUnit->setActive(true); } } + if(faction == 1 && LastOverronPos == 20)//horde round + { + Creature* pUnit = m_creature->SummonCreature(m_creature->GetEntry(),5458.01+irand(-10,10), -2340.27+irand(-10,10), 1459.60,0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if(pUnit) + { + ((hyjal_trashAI*)pUnit->AI())->faction = faction; + ((hyjal_trashAI*)pUnit->AI())->IsOverrun = true; + ((hyjal_trashAI*)pUnit->AI())->OverrunType = 10;//default + ((hyjal_trashAI*)pUnit->AI())->SetupOverrun = false; + pUnit->setActive(true); + } + } } } @@ -697,7 +841,7 @@ struct mob_ghoulAI : public hyjal_trashAI { DoCast(m_creature,SPELL_FRENZY); FrenzyTimer = 15000+rand()%15000; - }else FrenzyTimer -= diff; + }else FrenzyTimer -= diff; if (!UpdateVictim()) return; @@ -1275,6 +1419,7 @@ struct mob_gargoyleAI : public hyjal_trashAI pInstance = ((ScriptedInstance*)c->GetInstanceData()); go = false; pos = 0; + DummyTarget[0] = 0;DummyTarget[1] = 0;DummyTarget[2] = 0; Reset(); } @@ -1283,7 +1428,7 @@ struct mob_gargoyleAI : public hyjal_trashAI uint32 pos; uint32 MoveTimer; float Zpos; - bool forcemove; + bool forcemove; void Reset() { @@ -1291,7 +1436,7 @@ struct mob_gargoyleAI : public hyjal_trashAI Zpos = 10.0; StrikeTimer = 2000+rand()%5000; MoveTimer = 0; - m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); } void WaypointReached(uint32 i) @@ -1318,14 +1463,12 @@ struct mob_gargoyleAI : public hyjal_trashAI void JustDied(Unit *victim) { - if(pInstance && IsEvent) - pInstance->SetData(DATA_TRASH, 0);//signal trash is dead - float x,y,z; m_creature->GetPosition(x,y,z); z = m_creature->GetMap()->GetVmapHeight(x, y, z, true); m_creature->GetMotionMaster()->MovePoint(0,x,y,z); m_creature->Relocate(x,y,z,0); + hyjal_trashAI::JustDied(victim); } void UpdateAI(const uint32 diff) @@ -1358,6 +1501,17 @@ struct mob_gargoyleAI : public hyjal_trashAI } } } + if(IsOverrun && !UpdateVictim()) + { + if(faction == 0)//alliance + { + if(StrikeTimer<diff) + { + m_creature->CastSpell(DummyTarget[0],DummyTarget[1],DummyTarget[2],SPELL_GARGOYLE_STRIKE,false); + StrikeTimer = 2000+rand()%1000; + }else StrikeTimer -= diff; + } + } if (!UpdateVictim()) return; if(m_creature->GetDistance(m_creature->getVictim()) >= 20 || forcemove) diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.h b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.h index 3ea12038436..1113ce4c8a2 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.h +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.h @@ -5,7 +5,7 @@ #include "def_hyjal.h" #include "../../../npc/npc_escortAI.h" -#define MINRAIDDAMAGE 1000000//minimal damage before trash can drop loot and reputation +#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies struct TRINITY_DLL_DECL hyjal_trashAI : public npc_escortAI { @@ -34,6 +34,7 @@ struct TRINITY_DLL_DECL hyjal_trashAI : public npc_escortAI uint8 faction; bool useFlyPath; uint32 damageTaken; + float DummyTarget[3]; //private: }; diff --git a/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp b/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp index 3951a2ba247..34943449b1e 100644 --- a/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp +++ b/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp @@ -125,8 +125,8 @@ struct TRINITY_DLL_DECL instance_gruuls_lair : public ScriptedInstance if(data == DONE) HandleGameObject(MaulgarDoor, true); Encounters[0] = data; break; case DATA_GRUULEVENT: - if(data == IN_PROGRESS) HandleGameObject(GruulDoor, true); - else HandleGameObject(GruulDoor, false); + if(data == IN_PROGRESS) HandleGameObject(GruulDoor, false); + else HandleGameObject(GruulDoor, true); Encounters[1] = data; break; } diff --git a/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp b/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp index 0364c132447..3a788d2e863 100644 --- a/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp +++ b/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp @@ -26,6 +26,18 @@ EndScriptData */ #define ENCOUNTERS 4 +enum +{ + SAY_BOSS_DIE_AD = -1033007, + SAY_BOSS_DIE_AS = -1033008, + + NPC_ASH = 3850, + NPC_ADA = 3849, + + GO_COURTYARD_DOOR = 18895, //door to open when talking to NPC's + GO_SORCERER_DOOR = 18972, //door to open when Fenrus the Devourer + GO_ARUGAL_DOOR = 18971 //door to open when Wolf Master Nandos +}; struct TRINITY_DLL_DECL instance_shadowfang_keep : public ScriptedInstance { instance_shadowfang_keep(Map *map) : ScriptedInstance(map) {Initialize();}; @@ -33,12 +45,18 @@ struct TRINITY_DLL_DECL instance_shadowfang_keep : public ScriptedInstance uint32 Encounter[ENCOUNTERS]; std::string str_data; + uint64 uiAshGUID; + uint64 uiAdaGUID; + uint64 DoorCourtyardGUID; uint64 DoorSorcererGUID; uint64 DoorArugalGUID; void Initialize() { + uiAshGUID = 0; + uiAdaGUID = 0; + DoorCourtyardGUID = 0; DoorSorcererGUID = 0; DoorArugalGUID = 0; @@ -63,13 +81,34 @@ struct TRINITY_DLL_DECL instance_shadowfang_keep : public ScriptedInstance return NULL; } + void OnCreatureCreate(Creature* pCreature, uint32 uiCreature) + { + switch(pCreature->GetEntry()) + { + case NPC_ASH: uiAshGUID = pCreature->GetGUID(); break; + case NPC_ADA: uiAdaGUID = pCreature->GetGUID(); break; + } + } + void OnObjectCreate(GameObject *go) { switch(go->GetEntry()) { - case 18895: DoorCourtyardGUID = go->GetGUID(); break; - case 18972: DoorSorcererGUID = go->GetGUID(); break; - case 18971: DoorArugalGUID = go->GetGUID(); break; + case GO_COURTYARD_DOOR: + DoorCourtyardGUID = go->GetGUID(); + if (Encounter[0] == DONE) + go->SetGoState(0); + break; + case GO_SORCERER_DOOR: + DoorSorcererGUID = go->GetGUID(); + if (Encounter[2] == DONE) + go->SetGoState(0); + break; + case GO_ARUGAL_DOOR: + DoorArugalGUID = go->GetGUID(); + if (Encounter[3] == DONE) + go->SetGoState(0); + break; } } @@ -87,6 +126,23 @@ struct TRINITY_DLL_DECL instance_shadowfang_keep : public ScriptedInstance go->SetGoState(state); } + void DoSpeech() + { + Player* pPlayer = GetPlayerInMap(); + + if (pPlayer) + { + Unit* pAda = Unit::GetUnit(*pPlayer,uiAdaGUID); + Unit* pAsh = Unit::GetUnit(*pPlayer,uiAshGUID); + + if (pAda && pAda->isAlive() && pAsh && pAsh->isAlive()) + { + DoScriptText(SAY_BOSS_DIE_AD,pAda); + DoScriptText(SAY_BOSS_DIE_AS,pAsh); + } + } + } + void SetData(uint32 type, uint32 data) { switch(type) @@ -97,6 +153,8 @@ struct TRINITY_DLL_DECL instance_shadowfang_keep : public ScriptedInstance Encounter[0] = data; break; case TYPE_RETHILGORE: + if (data == DONE) + DoSpeech(); Encounter[1] = data; break; case TYPE_FENRUS: @@ -160,8 +218,10 @@ struct TRINITY_DLL_DECL instance_shadowfang_keep : public ScriptedInstance loadStream >> Encounter[0] >> Encounter[1] >> Encounter[2] >> Encounter[3]; for(uint8 i = 0; i < ENCOUNTERS; ++i) + { if (Encounter[i] == IN_PROGRESS) Encounter[i] = NOT_STARTED; + } OUT_LOAD_INST_DATA_COMPLETE; } diff --git a/src/bindings/scripts/scripts/zone/shadowfang_keep/shadowfang_keep.cpp b/src/bindings/scripts/scripts/zone/shadowfang_keep/shadowfang_keep.cpp index 6c8f0939b5c..f4b49b5f524 100644 --- a/src/bindings/scripts/scripts/zone/shadowfang_keep/shadowfang_keep.cpp +++ b/src/bindings/scripts/scripts/zone/shadowfang_keep/shadowfang_keep.cpp @@ -35,7 +35,16 @@ EndContentData */ enum { - SAY_FREE = -1033000 + SAY_FREE_AS = -1033000, + SAY_OPEN_DOOR_AS = -1033001, + SAY_POST_DOOR_AS = -1033002, + SAY_FREE_AD = -1033003, + SAY_OPEN_DOOR_AD = -1033004, + SAY_POST1_DOOR_AD = -1033005, + SAY_POST2_DOOR_AD = -1033006, + + SPELL_UNLOCK = 6421, + NPC_ASH = 3850 }; #define GOSSIP_ITEM_DOOR "Thanks, I'll follow you to the door." @@ -45,16 +54,45 @@ struct TRINITY_DLL_DECL npc_shadowfang_prisonerAI : public npc_escortAI npc_shadowfang_prisonerAI(Creature *c) : npc_escortAI(c) { pInstance = ((ScriptedInstance*)c->GetInstanceData()); + uiNpcEntry = c->GetEntry(); } ScriptedInstance *pInstance; + uint32 uiNpcEntry; - void WaypointReached(uint32 i) + void WaypointReached(uint32 uiPoint) { - if( pInstance && i == 6) + switch(uiPoint) { - DoScriptText(SAY_FREE, m_creature); - pInstance->SetData(TYPE_FREE_NPC, DONE); + case 0: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_FREE_AS, m_creature); + else + DoScriptText(SAY_FREE_AD, m_creature); + break; + case 10: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_OPEN_DOOR_AS, m_creature); + else + DoScriptText(SAY_OPEN_DOOR_AD, m_creature); + break; + case 11: + if (uiNpcEntry == NPC_ASH) + DoCast(m_creature, SPELL_UNLOCK); + break; + case 12: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_POST_DOOR_AS, m_creature); + else + DoScriptText(SAY_POST1_DOOR_AD, m_creature); + + if (pInstance) + pInstance->SetData(TYPE_FREE_NPC, DONE); + break; + case 13: + if (uiNpcEntry != NPC_ASH) + DoScriptText(SAY_POST2_DOOR_AD, m_creature); + break; } } @@ -93,16 +131,12 @@ bool GossipSelect_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature, return true; } -/*###### -## AddSC -######*/ - void AddSC_shadowfang_keep() { Script *newscript; newscript = new Script; - newscript->Name="npc_shadowfang_prisoner"; + newscript->Name = "npc_shadowfang_prisoner"; newscript->pGossipHello = &GossipHello_npc_shadowfang_prisoner; newscript->pGossipSelect = &GossipSelect_npc_shadowfang_prisoner; newscript->GetAI = &GetAI_npc_shadowfang_prisoner; diff --git a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp index bcc6d9ccbfe..37697119a35 100644 --- a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp +++ b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp @@ -75,7 +75,7 @@ struct TRINITY_DLL_DECL npc_bartlebyAI : public ScriptedAI void Reset() { m_creature->setFaction(11); - m_creature->setEmoteState(7); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, 7); PlayerGUID = 0; } @@ -132,7 +132,7 @@ struct TRINITY_DLL_DECL npc_dashel_stonefistAI : public ScriptedAI void Reset() { m_creature->setFaction(11); - m_creature->setEmoteState(7); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, 7); } void DamageTaken(Unit *done_by, uint32 & damage) diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp index ca0711f1222..86b04b28753 100644 --- a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp @@ -301,7 +301,7 @@ struct TRINITY_DLL_DECL eye_of_cthunAI : public Scripted_NoMovementAI DoCast(m_creature,SPELL_RED_COLORATION); //Freeze animation - m_creature->setEmoteState(53); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, 53); //Darkbeam for 35 seconds PhaseTimer = 35000; @@ -351,7 +351,7 @@ struct TRINITY_DLL_DECL eye_of_cthunAI : public Scripted_NoMovementAI m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION); //Freeze animation - m_creature->setEmoteState(0); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, 0); //Eye Beam for 50 seconds @@ -397,7 +397,7 @@ struct TRINITY_DLL_DECL eye_of_cthunAI : public Scripted_NoMovementAI m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION); //Reset to normal emote state and prevent select and attack - m_creature->setEmoteState(0); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); //Remove Target field diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index a1120e8365e..37a876bb059 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -37,78 +37,78 @@ AggressorAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -AggressorAI::AggressorAI(Creature *c) : CreatureAI(c), i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +AggressorAI::AggressorAI(Creature *c) : CreatureAI(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) { } void AggressorAI::EnterEvadeMode() { - if( !i_creature.isAlive() ) + if( !m_creature->isAlive() ) { - DEBUG_LOG("Creature stopped attacking cuz his dead [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking cuz his dead [guid=%u]", m_creature->GetGUIDLow()); i_victimGuid = 0; - i_creature.CombatStop(); - i_creature.DeleteThreatList(); + m_creature->CombatStop(); + m_creature->DeleteThreatList(); return; } - Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid ); + Unit* victim = ObjectAccessor::GetUnit(*m_creature, i_victimGuid ); if( !victim ) { - DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", m_creature->GetGUIDLow()); } else if( !victim->isAlive() ) { - DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", m_creature->GetGUIDLow()); } else if( victim->HasStealthAura() ) { - DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", m_creature->GetGUIDLow()); } else if( victim->isInFlight() ) { - DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", m_creature->GetGUIDLow()); } else { - DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", m_creature->GetGUIDLow()); //i_state = STATE_LOOK_AT_VICTIM; //i_tracker.Reset(TIME_INTERVAL_LOOK); } - if(!i_creature.GetCharmerOrOwner()) + if(!m_creature->GetCharmerOrOwner()) { - i_creature.RemoveAllAuras(); + m_creature->RemoveAllAuras(); // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead - if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) - i_creature.GetMotionMaster()->MoveTargetedHome(); + if( m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) + m_creature->GetMotionMaster()->MoveTargetedHome(); } - else if (i_creature.GetOwner() && i_creature.GetOwner()->isAlive()) - i_creature.GetMotionMaster()->MoveFollow(i_creature.GetOwner(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + else if (m_creature->GetOwner() && m_creature->GetOwner()->isAlive()) + m_creature->GetMotionMaster()->MoveFollow(m_creature->GetOwner(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); - i_creature.DeleteThreatList(); + m_creature->DeleteThreatList(); i_victimGuid = 0; - i_creature.CombatStop(); - i_creature.SetLootRecipient(NULL); + m_creature->CombatStop(); + m_creature->SetLootRecipient(NULL); } void AggressorAI::UpdateAI(const uint32 /*diff*/) { - // update i_victimGuid if i_creature.getVictim() !=0 and changed + // update i_victimGuid if m_creature->getVictim() !=0 and changed if(!UpdateVictim()) return; - i_victimGuid = i_creature.getVictim()->GetGUID(); + i_victimGuid = m_creature->getVictim()->GetGUID(); - if( i_creature.isAttackReady() ) + if( m_creature->isAttackReady() ) { - if( i_creature.IsWithinMeleeRange(i_creature.getVictim())) + if( m_creature->IsWithinMeleeRange(m_creature->getVictim())) { - i_creature.AttackerStateUpdate(i_creature.getVictim()); - i_creature.resetAttackTimer(); + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); } } } diff --git a/src/game/AggressorAI.h b/src/game/AggressorAI.h index a2a0230939a..983498716e6 100644 --- a/src/game/AggressorAI.h +++ b/src/game/AggressorAI.h @@ -36,7 +36,7 @@ class TRINITY_DLL_DECL AggressorAI : public CreatureAI public: - AggressorAI(Creature *c); + explicit AggressorAI(Creature *c); void EnterEvadeMode(); @@ -44,7 +44,6 @@ class TRINITY_DLL_DECL AggressorAI : public CreatureAI static int Permissible(const Creature *); private: - Creature &i_creature; uint64 i_victimGuid; AggressorState i_state; TimeTracker i_tracker; diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index f63a550b7de..402fdd048c7 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -181,6 +181,7 @@ ChatCommand * ChatHandler::getCommandTable() { "creature", SEC_MODERATOR, false, &ChatHandler::HandleGoCreatureCommand, "", NULL }, { "object", SEC_MODERATOR, false, &ChatHandler::HandleGoObjectCommand, "", NULL }, { "trigger", SEC_MODERATOR, false, &ChatHandler::HandleGoTriggerCommand, "", NULL }, + { "ticket", SEC_MODERATOR, false, &ChatHandler::HandleGoTicketCommand, "", NULL }, { "graveyard", SEC_MODERATOR, false, &ChatHandler::HandleGoGraveyardCommand, "", NULL }, { "zonexy", SEC_MODERATOR, false, &ChatHandler::HandleGoZoneXYCommand, "", NULL }, { "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 7065c6dd0ed..d516d44c6a1 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -442,6 +442,7 @@ class ChatHandler bool HandleDeMorphCommand(const char* args); bool HandleGoCreatureCommand(const char* args); bool HandleGoObjectCommand(const char* args); + bool HandleGoTicketCommand(const char* args); bool HandleGoTriggerCommand(const char* args); bool HandleGoGraveyardCommand(const char* args); @@ -562,7 +563,6 @@ class ChatHandler GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry); // Utility methods for commands - void ShowTicket(uint64 guid, char const* text, char const* time); bool LookupPlayerSearchCommand(QueryResult* result, int32 limit); bool HandleBanListHelper(QueryResult* result); bool HandleBanHelper(BanMode mode,char const* args); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 7a4cac89408..71631e4bdbc 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -136,7 +136,7 @@ Unit(), lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0), m_lootMoney(0), m_lootRecipient(0), m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f), -m_gossipOptionLoaded(false), m_emoteState(0), +m_gossipOptionLoaded(false), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formation(NULL), m_summonMask(SUMMON_MASK_NONE) @@ -2237,12 +2237,17 @@ uint32 Creature::getLevelForTarget( Unit const* target ) const return level; } -std::string Creature::GetScriptName() +std::string Creature::GetAIName() const +{ + return ObjectMgr::GetCreatureTemplate(GetEntry())->AIName; +} + +std::string Creature::GetScriptName() const { return objmgr.GetScriptName(GetScriptId()); } -uint32 Creature::GetScriptId() +uint32 Creature::GetScriptId() const { return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptID; } diff --git a/src/game/Creature.h b/src/game/Creature.h index ce890c34902..0f12401bba8 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -560,8 +560,9 @@ class TRINITY_DLL_SPEC Creature : public Unit CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; } CreatureDataAddon const* GetCreatureAddon() const; - std::string GetScriptName(); - uint32 GetScriptId(); + std::string GetAIName() const; + std::string GetScriptName() const; + uint32 GetScriptId() const; void prepareGossipMenu( Player *pPlayer, uint32 gossipid = 0 ); void sendPreparedGossip( Player* player ); @@ -575,7 +576,6 @@ class TRINITY_DLL_SPEC Creature : public Unit GossipOption const* GetGossipOption( uint32 id ) const; void addGossipOption(GossipOption const& gso) { m_goptions.push_back(gso); } - void setEmoteState(uint8 emote) { m_emoteState = emote; }; void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } void TextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote = false) { MonsterTextEmote(textId,TargetGuid,IsBossEmote); } @@ -709,7 +709,6 @@ class TRINITY_DLL_SPEC Creature : public Unit bool m_gossipOptionLoaded; GossipOptionList m_goptions; - uint8 m_emoteState; uint32 m_summonMask; ReactStates m_reactState; // for AI, not charmInfo void RegenerateMana(); diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index e7043c6042f..fdd145737ab 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -167,3 +167,8 @@ void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) AttackStart(charmer->SelectNearestTarget()); } +/*void CreatureAI::AttackedBy( Unit* attacker ) +{ + if(!m_creature->getVictim()) + AttackStart(attacker); +}*/ diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index 11d5bd372fd..6d7026a9766 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -73,9 +73,9 @@ enum SelectAggroTarget class TRINITY_DLL_SPEC UnitAI { protected: - Unit *me; + Unit* const me; public: - UnitAI(Unit *u) : me(u) {} + explicit UnitAI(Unit *u) : me(u) {} virtual void AttackStart(Unit *); virtual void UpdateAI(const uint32 diff) = 0; @@ -95,9 +95,9 @@ class TRINITY_DLL_SPEC UnitAI class TRINITY_DLL_SPEC PlayerAI : public UnitAI { protected: - Player *me; + Player* const me; public: - PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {} + explicit PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {} void OnCharmed(bool apply); }; @@ -111,21 +111,26 @@ class TRINITY_DLL_SPEC SimpleCharmedAI : public PlayerAI class TRINITY_DLL_SPEC CreatureAI : public UnitAI { protected: - Creature *me; + Creature* const me; + Creature* const m_creature; bool UpdateVictim(); public: - CreatureAI(Creature *c) : UnitAI((Unit*)c), me(c) {} + explicit CreatureAI(Creature *c) : UnitAI((Unit*)c), me(c), m_creature(c) {} virtual ~CreatureAI() {} - // Called if IsVisible(Unit *who) is true at each *who move + ///== Reactions At ================================= + + // Called if IsVisible(Unit *who) is true at each *who move, reaction at visibility zone enter virtual void MoveInLineOfSight(Unit *); - // Called at stopping attack by any attacker + // Called for reaction at stopping attack at no attackers or targets virtual void EnterEvadeMode(); // Called at any Damage from any attacker (before damage apply) + // Note: it for recalculation damage or special reaction at damage + // for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) {} // Called when the creature is killed @@ -145,8 +150,8 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI // Called when spell hits a target virtual void SpellHitTarget(Unit* target, const SpellEntry*) {} - // Called when vitim entered water and creature can not enter water - virtual bool canReachByRangeAttack(Unit*) { return false; } + // Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc) + //virtual void AttackedBy(Unit* attacker); // Called when creature is spawned or respawned (for reseting variables) virtual void JustRespawned() {} @@ -160,6 +165,28 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI virtual void JustReachedHome() {} void DoZoneInCombat(Unit* pUnit = NULL); + + ///== Triggered Actions Requested ================== + + // Called when creature attack expected (if creature can and no have current victim) + // Note: for reaction at hostile action must be called AttackedBy function. + //virtual void AttackStart(Unit *) {} + + // Called at World update tick + //virtual void UpdateAI(const uint32 diff ) {} + + ///== State checks ================================= + + // Is unit visible for MoveInLineOfSight + //virtual bool IsVisible(Unit *) const { return false; } + + // Called when victim entered water and creature can not enter water + virtual bool canReachByRangeAttack(Unit*) { return false; } + + ///== Fields ======================================= + + // Pointer to controlled by AI creature + //Creature* const m_creature; }; struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature> diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp index 88384fd6f21..9250a254155 100644 --- a/src/game/CreatureAISelector.cpp +++ b/src/game/CreatureAISelector.cpp @@ -47,11 +47,8 @@ namespace FactorySelector if(CreatureAI* scriptedAI = Script->GetAI(creature)) return scriptedAI; - CreatureInfo const *cinfo = creature->GetCreatureInfo(); - assert(cinfo); - - // this seems to be useless - std::string ainame=cinfo->AIName; + // AIname in db + std::string ainame=creature->GetAIName(); if(!ai_factory && !ainame.empty()) ai_factory = ai_registry.GetRegistryItem( ainame.c_str() ); diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index daf5c74ca72..3c45fbdf9b3 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -34,14 +34,14 @@ int CreatureEventAI::Permissible(const Creature *creature) { - if( creature->GetCreatureInfo()->AIName == "EventAI" ) + if( creature->GetAIName() == "EventAI" ) return PERMIT_BASE_SPECIAL; return PERMIT_BASE_NO; } -CreatureEventAI::CreatureEventAI(Creature *c) : CreatureAI(c), m_creature(*c), InCombat(false) +CreatureEventAI::CreatureEventAI(Creature *c) : CreatureAI(c), InCombat(false) { - CreatureEventAI_Event_Map::iterator CreatureEvents = CreatureEAI_Mgr.GetCreatureEventAIMap().find(m_creature.GetEntry()); + CreatureEventAI_Event_Map::iterator CreatureEvents = CreatureEAI_Mgr.GetCreatureEventAIMap().find(m_creature->GetEntry()); if (CreatureEvents != CreatureEAI_Mgr.GetCreatureEventAIMap().end()) { std::vector<CreatureEventAI_Event>::iterator i; @@ -53,10 +53,10 @@ CreatureEventAI::CreatureEventAI(Creature *c) : CreatureAI(c), m_creature(*c), I if ((*i).event_flags & EFLAG_DEBUG_ONLY) continue; #endif - if(((*i).event_flags & (EFLAG_HEROIC | EFLAG_NORMAL)) && m_creature.GetMap()->IsDungeon() ) + if(((*i).event_flags & (EFLAG_HEROIC | EFLAG_NORMAL)) && m_creature->GetMap()->IsDungeon() ) { - if( (m_creature.GetMap()->IsHeroic() && (*i).event_flags & EFLAG_HEROIC) || - (!m_creature.GetMap()->IsHeroic() && (*i).event_flags & EFLAG_NORMAL)) + if( (m_creature->GetMap()->IsHeroic() && (*i).event_flags & EFLAG_HEROIC) || + (!m_creature->GetMap()->IsHeroic() && (*i).event_flags & EFLAG_NORMAL)) { //event flagged for instance mode CreatureEventAIList.push_back(CreatureEventAIHolder(*i)); @@ -67,10 +67,10 @@ CreatureEventAI::CreatureEventAI(Creature *c) : CreatureAI(c), m_creature(*c), I } //EventMap had events but they were not added because they must be for instance if (CreatureEventAIList.empty()) - sLog.outError("CreatureEventAI: CreatureId has events but no events added to list because of instance flags.", m_creature.GetEntry()); + sLog.outError("CreatureEventAI: CreatureId has events but no events added to list because of instance flags.", m_creature->GetEntry()); } else - sLog.outError("CreatureEventAI: EventMap for Creature %u is empty but creature is using CreatureEventAI.", m_creature.GetEntry()); + sLog.outError("CreatureEventAI: EventMap for Creature %u is empty but creature is using CreatureEventAI.", m_creature->GetEntry()); bEmptyList = CreatureEventAIList.empty(); Phase = 0; @@ -152,7 +152,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction pHolder.Time = urand(param3, param4); else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -172,17 +172,17 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } break; case EVENT_T_HP: { - if (!InCombat || !m_creature.GetMaxHealth()) + if (!InCombat || !m_creature->GetMaxHealth()) return false; - uint32 perc = (m_creature.GetHealth()*100) / m_creature.GetMaxHealth(); + uint32 perc = (m_creature->GetHealth()*100) / m_creature->GetMaxHealth(); if (perc > param1 || perc < param2) return false; @@ -197,17 +197,17 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } break; case EVENT_T_MANA: { - if (!InCombat || !m_creature.GetMaxPower(POWER_MANA)) + if (!InCombat || !m_creature->GetMaxPower(POWER_MANA)) return false; - uint32 perc = (m_creature.GetPower(POWER_MANA)*100) / m_creature.GetMaxPower(POWER_MANA); + uint32 perc = (m_creature->GetPower(POWER_MANA)*100) / m_creature->GetMaxPower(POWER_MANA); if (perc > param1 || perc < param2) return false; @@ -222,7 +222,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -243,7 +243,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -269,7 +269,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -286,7 +286,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -303,7 +303,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -314,10 +314,10 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction break; case EVENT_T_TARGET_HP: { - if (!InCombat || !m_creature.getVictim() || !m_creature.getVictim()->GetMaxHealth()) + if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxHealth()) return false; - uint32 perc = (m_creature.getVictim()->GetHealth()*100) / m_creature.getVictim()->GetMaxHealth(); + uint32 perc = (m_creature->getVictim()->GetHealth()*100) / m_creature->getVictim()->GetMaxHealth(); if (perc > param1 || perc < param2) return false; @@ -332,14 +332,14 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } break; case EVENT_T_TARGET_CASTING: { - if (!InCombat || !m_creature.getVictim() || !m_creature.getVictim()->IsNonMeleeSpellCasted(false, false, true)) + if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->IsNonMeleeSpellCasted(false, false, true)) return false; //Repeat Timers @@ -352,7 +352,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -379,7 +379,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -408,7 +408,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction pHolder.Time = urand(param3, param4); else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -435,7 +435,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -460,7 +460,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction else { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); pHolder.Enabled = false; } } @@ -475,7 +475,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction break; default: - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); break; } @@ -532,7 +532,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u target = owner; } } - else if (target = m_creature.getVictim()) + else if (target = m_creature->getVictim()) { if (target->GetTypeId() != TYPEID_PLAYER) { @@ -544,21 +544,21 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u } } - DoScriptText(temp, &m_creature, target); + DoScriptText(temp, m_creature, target); } } break; case ACTION_T_SET_FACTION: { if (param1) - m_creature.setFaction(param1); + m_creature->setFaction(param1); else { - if (CreatureInfo const* ci = GetCreatureTemplateStore(m_creature.GetEntry())) + if (CreatureInfo const* ci = GetCreatureTemplateStore(m_creature->GetEntry())) { //if no id provided, assume reset and then use default - if (m_creature.getFaction() != ci->faction_A) - m_creature.setFaction(ci->faction_A); + if (m_creature->getFaction() != ci->faction_A) + m_creature->setFaction(ci->faction_A); } } } @@ -574,29 +574,29 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u { //use default display if (ci->Modelid1) - m_creature.SetDisplayId(ci->Modelid1); + m_creature->SetDisplayId(ci->Modelid1); } } //if no param1, then use value from param2 (modelId) else - m_creature.SetDisplayId(param2); + m_creature->SetDisplayId(param2); } else - m_creature.DeMorph(); + m_creature->DeMorph(); } break; case ACTION_T_SOUND: - m_creature.PlayDirectSound(param1); + m_creature->PlayDirectSound(param1); break; case ACTION_T_EMOTE: - m_creature.HandleEmoteCommand(param1); + m_creature->HandleEmoteCommand(param1); break; case ACTION_T_RANDOM_SOUND: { uint32 temp = GetRandActionParam(rnd, param1, param2, param3); if (temp != uint32(0xffffffff)) - m_creature.PlayDirectSound( temp ); + m_creature->PlayDirectSound( temp ); } break; case ACTION_T_RANDOM_EMOTE: @@ -604,13 +604,13 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u uint32 temp = GetRandActionParam(rnd, param1, param2, param3); if (temp != uint32(0xffffffff)) - m_creature.HandleEmoteCommand(temp); + m_creature->HandleEmoteCommand(temp); } break; case ACTION_T_CAST: { Unit* target = GetTargetByType(param2, pActionInvoker); - Unit* caster = &m_creature; + Unit* caster = m_creature; if (!target) return; @@ -646,12 +646,12 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u //Melee current victim if flag not set if (!(param3 & CAST_NO_MELEE_IF_OOM)) { - if (m_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) { AttackDistance = 0; AttackAngle = 0; - m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); } } @@ -666,7 +666,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u } }else - sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature.GetEntry(), param1); + sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), param1); } } break; @@ -677,14 +677,14 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u Creature* pCreature = NULL; if (param3) - pCreature = m_creature.SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3); + pCreature = m_creature->SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3); else - pCreature = m_creature.SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + pCreature = m_creature->SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); if (!pCreature) { - sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature.GetEntry()); + sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature->GetEntry()); } else if (param2 != TARGET_T_SELF && target) pCreature->AI()->AttackStart(target); @@ -695,19 +695,19 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u Unit* target = GetTargetByType(param2, pActionInvoker); if (target) - m_creature.getThreatManager().modifyThreatPercent(target, param1); + m_creature->getThreatManager().modifyThreatPercent(target, param1); } break; case ACTION_T_THREAT_ALL_PCT: { Unit* Temp = NULL; - std::list<HostilReference*>::iterator i = m_creature.getThreatManager().getThreatList().begin(); - for (; i != m_creature.getThreatManager().getThreatList().end(); ++i) + std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (; i != m_creature->getThreatManager().getThreatList().end(); ++i) { - Temp = Unit::GetUnit(m_creature,(*i)->getUnitGuid()); + Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); if (Temp) - m_creature.getThreatManager().modifyThreatPercent(Temp, param1); + m_creature->getThreatManager().modifyThreatPercent(Temp, param1); } } break; @@ -724,7 +724,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u Unit* target = GetTargetByType(param3, pActionInvoker); if (target && target->GetTypeId() == TYPEID_PLAYER) - ((Player*)target)->CastedCreatureOrGO(param1, m_creature.GetGUID(), param2); + ((Player*)target)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2); } break; case ACTION_T_SET_UNIT_FIELD: @@ -768,11 +768,11 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u //Allow movement (create new targeted movement gen only if idle) if (CombatMovementEnabled) { - m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); } else { - m_creature.GetMotionMaster()->MoveIdle(); + m_creature->GetMotionMaster()->MoveIdle(); } } break; @@ -787,7 +787,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u if (Phase > 31) - sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature.GetEntry()); + sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature->GetEntry()); } break; case ACTION_T_EVADE: @@ -797,10 +797,10 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u break; case ACTION_T_FLEE: { - if(m_creature.HasAuraType(SPELL_AURA_PREVENTS_FLEEING)) + if(m_creature->HasAuraType(SPELL_AURA_PREVENTS_FLEEING)) break; TimetoFleeLeft = 8000; - m_creature.DoFleeToGetAssistance(); + m_creature->DoFleeToGetAssistance(); IsFleeing = true; } break; @@ -809,9 +809,9 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u Unit* Temp = NULL; if( pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER ) { - Temp = Unit::GetUnit(m_creature,pActionInvoker->GetGUID()); + Temp = Unit::GetUnit(*m_creature,pActionInvoker->GetGUID()); if( Temp ) - ((Player*)Temp)->GroupEventHappens(param1,&m_creature); + ((Player*)Temp)->GroupEventHappens(param1,m_creature); } } break; @@ -819,12 +819,12 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u { Unit* Temp = NULL; - std::list<HostilReference*>::iterator i = m_creature.getThreatManager().getThreatList().begin(); - for (; i != m_creature.getThreatManager().getThreatList().end(); ++i) + std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (; i != m_creature->getThreatManager().getThreatList().end(); ++i) { - Temp = Unit::GetUnit(m_creature,(*i)->getUnitGuid()); + Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); if (Temp && Temp->GetTypeId() == TYPEID_PLAYER) - ((Player*)Temp)->CastedCreatureOrGO(param1, m_creature.GetGUID(), param2); + ((Player*)Temp)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2); } } break; @@ -843,7 +843,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u if (CombatMovementEnabled) { - m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); } } break; @@ -861,7 +861,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u Phase = param1 + (rnd % (param2 - param1)); } else - sLog.outErrorDb( "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature.GetEntry()); + sLog.outErrorDb( "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature->GetEntry()); } break; case ACTION_T_SUMMON_ID: @@ -875,18 +875,18 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u if (i == CreatureEAI_Mgr.GetCreatureEventAISummonMap().end()) { - sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature.GetEntry()); + sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature->GetEntry()); return; } if ((*i).second.SpawnTimeSecs) - pCreature = m_creature.SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs); - else pCreature = m_creature.SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs); + else pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); if (!pCreature) { - sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature.GetEntry()); + sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature->GetEntry()); } else if (param2 != TARGET_T_SELF && target) pCreature->AI()->AttackStart(target); @@ -895,24 +895,24 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u case ACTION_T_KILLED_MONSTER: { //first attempt player who tapped creature - if (Player* pPlayer = m_creature.GetLootRecipient()) - pPlayer->RewardPlayerAndGroupAtEvent(param1, &m_creature); + if (Player* pPlayer = m_creature->GetLootRecipient()) + pPlayer->RewardPlayerAndGroupAtEvent(param1, m_creature); else { //if not available, use pActionInvoker Unit* pTarget = GetTargetByType(param2, pActionInvoker); if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself()) - pPlayer->RewardPlayerAndGroupAtEvent(param1, &m_creature); + pPlayer->RewardPlayerAndGroupAtEvent(param1, m_creature); } } break; case ACTION_T_SET_INST_DATA: { - InstanceData* pInst = (InstanceData*)m_creature.GetInstanceData(); + InstanceData* pInst = (InstanceData*)m_creature->GetInstanceData(); if (!pInst) { - sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", EventId, m_creature.GetEntry()); + sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", EventId, m_creature->GetEntry()); return; } @@ -924,14 +924,14 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u Unit* target = GetTargetByType(param2, pActionInvoker); if (!target) { - sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature.GetEntry()); + sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature->GetEntry()); return; } - InstanceData* pInst = (InstanceData*)m_creature.GetInstanceData(); + InstanceData* pInst = (InstanceData*)m_creature->GetInstanceData(); if (!pInst) { - sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", EventId, m_creature.GetEntry()); + sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", EventId, m_creature->GetEntry()); return; } @@ -940,37 +940,37 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u break; case ACTION_T_UPDATE_TEMPLATE: { - if (m_creature.GetEntry() == param1) + if (m_creature->GetEntry() == param1) { - sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature.GetEntry()); + sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature->GetEntry()); return; } - m_creature.UpdateEntry(param1, param2 ? HORDE : ALLIANCE); + m_creature->UpdateEntry(param1, param2 ? HORDE : ALLIANCE); } break; case ACTION_T_DIE: { - if (m_creature.isDead()) + if (m_creature->isDead()) { - sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", EventId, m_creature.GetEntry()); + sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", EventId, m_creature->GetEntry()); return; } - m_creature.DealDamage(&m_creature, m_creature.GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } break; case ACTION_T_ZONE_COMBAT_PULSE: { - if (!m_creature.isInCombat() || !m_creature.GetMap()->IsDungeon()) + if (!m_creature->isInCombat() || !m_creature->GetMap()->IsDungeon()) { - sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_ZONE_COMBAT_PULSE on creature out of combat or in non-dungeon map. Creature %d", EventId, m_creature.GetEntry()); + sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_ZONE_COMBAT_PULSE on creature out of combat or in non-dungeon map. Creature %d", EventId, m_creature->GetEntry()); return; } - DoZoneInCombat(&m_creature); + DoZoneInCombat(m_creature); } break; @@ -1034,7 +1034,7 @@ void CreatureEventAI::Reset() (*i).Enabled = true; } else - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature.GetEntry(), (*i).Event.event_id, (*i).Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type); } break; //default: @@ -1048,7 +1048,7 @@ void CreatureEventAI::Reset() void CreatureEventAI::JustReachedHome() { - m_creature.LoadCreaturesAddon(); + m_creature->LoadCreaturesAddon(); if (!bEmptyList) { @@ -1064,15 +1064,15 @@ void CreatureEventAI::JustReachedHome() void CreatureEventAI::EnterEvadeMode() { - m_creature.InterruptNonMeleeSpells(true); - m_creature.RemoveAllAuras(); - m_creature.DeleteThreatList(); - m_creature.CombatStop(); + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); - if (m_creature.isAlive()) - m_creature.GetMotionMaster()->MoveTargetedHome(); + if (m_creature->isAlive()) + m_creature->GetMotionMaster()->MoveTargetedHome(); - m_creature.SetLootRecipient(NULL); + m_creature->SetLootRecipient(NULL); InCombat = false; @@ -1154,7 +1154,7 @@ void CreatureEventAI::Aggro(Unit *who) (*i).Enabled = true; } else - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature.GetEntry(), (*i).Event.event_id, (*i).Event.event_type); + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type); break; //All normal events need to be re-enabled and their time set to 0 default: @@ -1174,7 +1174,7 @@ void CreatureEventAI::AttackStart(Unit *who) if (!who) return; - if (m_creature.Attack(who, MeleeEnabled)) + if (m_creature->Attack(who, MeleeEnabled)) { if (!InCombat) { @@ -1184,11 +1184,11 @@ void CreatureEventAI::AttackStart(Unit *who) if (CombatMovementEnabled) { - m_creature.GetMotionMaster()->MoveChase(who, AttackDistance, AttackAngle); + m_creature->GetMotionMaster()->MoveChase(who, AttackDistance, AttackAngle); } else { - m_creature.GetMotionMaster()->MoveIdle(); + m_creature->GetMotionMaster()->MoveIdle(); } } } @@ -1199,7 +1199,7 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who) return; //Check for OOC LOS Event - if (!bEmptyList && !m_creature.getVictim()) + if (!bEmptyList && !m_creature->getVictim()) { for (std::list<CreatureEventAIHolder>::iterator itr = CreatureEventAIList.begin(); itr != CreatureEventAIList.end(); ++itr) { @@ -1209,18 +1209,18 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who) float fMaxAllowedRange = (*itr).Event.event_param2; //if range is ok and we are actually in LOS - if (m_creature.IsWithinDistInMap(who, fMaxAllowedRange) && m_creature.IsWithinLOSInMap(who)) + if (m_creature->IsWithinDistInMap(who, fMaxAllowedRange) && m_creature->IsWithinLOSInMap(who)) { //if friendly event&&who is not hostile OR hostile event&&who is hostile - if (((*itr).Event.event_param1 && !m_creature.IsHostileTo(who)) || - ((!(*itr).Event.event_param1) && m_creature.IsHostileTo(who))) + if (((*itr).Event.event_param1 && !m_creature->IsHostileTo(who)) || + ((!(*itr).Event.event_param1) && m_creature->IsHostileTo(who))) ProcessEvent(*itr, who); } } } } - //if (m_creature.isCivilian() && m_creature.IsNeutralToAll()) + //if (m_creature->isCivilian() && m_creature->IsNeutralToAll()) // return; if(me->canStartAttack(who)) @@ -1253,7 +1253,7 @@ void CreatureEventAI::UpdateAI(const uint32 diff) bool Combat = InCombat ? UpdateVictim() : false; //Must return if creature isn't alive. Normally select hostil target and get victim prevent this - if (!m_creature.isAlive()) + if (!m_creature->isAlive()) return; if (IsFleeing) @@ -1316,9 +1316,9 @@ void CreatureEventAI::UpdateAI(const uint32 diff) case EVENT_T_RANGE: if (Combat) { - if (m_creature.IsWithinDistInMap(m_creature.getVictim(),(float)(*i).Event.event_param2)) + if (m_creature->IsWithinDistInMap(m_creature->getVictim(),(float)(*i).Event.event_param2)) { - if (m_creature.GetDistance(m_creature.getVictim()) >= (float)(*i).Event.event_param1) + if (m_creature->GetDistance(m_creature->getVictim()) >= (float)(*i).Event.event_param1) ProcessEvent(*i); } } @@ -1344,7 +1344,7 @@ void CreatureEventAI::UpdateAI(const uint32 diff) inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position) { //ThreatList m_threatlist; - std::list<HostilReference*>& m_threatlist = m_creature.getThreatManager().getThreatList(); + std::list<HostilReference*>& m_threatlist = m_creature->getThreatManager().getThreatList(); std::list<HostilReference*>::iterator i = m_threatlist.begin(); std::list<HostilReference*>::reverse_iterator r = m_threatlist.rbegin(); @@ -1356,17 +1356,17 @@ inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position case ATTACKING_TARGET_RANDOM: { advance ( i , position + (rand() % (m_threatlist.size() - position ) )); - return Unit::GetUnit(m_creature,(*i)->getUnitGuid()); + return Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); } case ATTACKING_TARGET_TOPAGGRO: { advance ( i , position); - return Unit::GetUnit(m_creature,(*i)->getUnitGuid()); + return Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); } case ATTACKING_TARGET_BOTTOMAGGRO: { advance ( r , position); - return Unit::GetUnit(m_creature,(*r)->getUnitGuid()); + return Unit::GetUnit(*m_creature,(*r)->getUnitGuid()); } } return NULL; @@ -1394,10 +1394,10 @@ inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoke switch (Target) { case TARGET_T_SELF: - return &m_creature; + return m_creature; break; case TARGET_T_HOSTILE: - return m_creature.getVictim(); + return m_creature->getVictim(); break; case TARGET_T_HOSTILE_SECOND_AGGRO: return SelectUnit(ATTACKING_TARGET_TOPAGGRO,1); @@ -1422,15 +1422,15 @@ inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoke Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) { - CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY())); + CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); Unit* pUnit = NULL; - MaNGOS::MostHPMissingInRange u_check(&m_creature, range, MinHPDiff); - MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange> searcher(&m_creature, pUnit, u_check); + MaNGOS::MostHPMissingInRange u_check(m_creature, range, MinHPDiff); + MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange> searcher(m_creature, pUnit, u_check); /* typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes; @@ -1439,40 +1439,40 @@ Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher); CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature.GetMap()); + cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature->GetMap()); return pUnit; } void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range) { - CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY())); + CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - MaNGOS::FriendlyCCedInRange u_check(&m_creature, range); - MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange> searcher(&m_creature, _list, u_check); + MaNGOS::FriendlyCCedInRange u_check(m_creature, range); + MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange> searcher(m_creature, _list, u_check); TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher); CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature.GetMap()); + cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap()); } void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid) { - CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY())); + CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - MaNGOS::FriendlyMissingBuffInRange u_check(&m_creature, range, spellid); - MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange> searcher(&m_creature, _list, u_check); + MaNGOS::FriendlyMissingBuffInRange u_check(m_creature, range, spellid); + MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange> searcher(m_creature, _list, u_check); TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher); CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature.GetMap()); + cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap()); } //********************************* diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index 74ea7a40a6a..83e925e1fd4 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -251,7 +251,7 @@ class TRINITY_DLL_SPEC CreatureEventAI : public CreatureAI { public: - CreatureEventAI(Creature *c); + explicit CreatureEventAI(Creature *c); ~CreatureEventAI() { CreatureEventAIList.clear(); @@ -284,12 +284,8 @@ class TRINITY_DLL_SPEC CreatureEventAI : public CreatureAI void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid); void DoFindFriendlyCC(std::list<Creature*>& _list, float range); - //Pointer to creature we are manipulating - Creature& m_creature; - //Bool for if we are in combat or not bool InCombat; - //Holder for events (stores enabled, time, and eventid) std::list<CreatureEventAIHolder> CreatureEventAIList; uint32 EventUpdateTime; //Time between event updates diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index 3e6c2822759..5ac08400804 100644 --- a/src/game/CreatureEventAIMgr.cpp +++ b/src/game/CreatureEventAIMgr.cpp @@ -544,6 +544,9 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() //Add to list m_CreatureEventAI_Event_Map[creature_id].push_back(temp); ++Count; + + if(cInfo->AIName == "") + const_cast<CreatureInfo*>(cInfo)->AIName = "EventAI"; } while (result->NextRow()); delete result; diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 7d3dea72ccf..e804cba5066 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1638,6 +1638,7 @@ struct WorldMapAreaEntry float x1; // 6 float x2; // 7 int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally) + // int32 dungeonMap_id; // 9 pointer to DungeonMap.dbc (owerride x1,x2,y1,y2 coordinates) }; struct WorldSafeLocsEntry diff --git a/src/game/GridStates.cpp b/src/game/GridStates.cpp index fa1c0a2b534..36092fbdc29 100644 --- a/src/game/GridStates.cpp +++ b/src/game/GridStates.cpp @@ -40,6 +40,7 @@ ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, c ObjectGridStoper stoper(grid); stoper.StopN(); grid.SetGridState(GRID_STATE_IDLE); + sLog.outDebug("Grid[%u,%u] on map %u moved to IDLE state", x, y, m.GetId()); } else { @@ -53,7 +54,7 @@ IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 &x, const ui { m.ResetGridExpiry(grid); grid.SetGridState(GRID_STATE_REMOVAL); - sLog.outDebug("Grid[%u,%u] on map %u moved to IDLE state", x, y, m.GetId()); + sLog.outDebug("Grid[%u,%u] on map %u moved to REMOVAL state", x, y, m.GetId()); } void diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index 09314d5e69f..710acede150 100644 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -33,22 +33,22 @@ int GuardAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -GuardAI::GuardAI(Creature *c) : CreatureAI(c), i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +GuardAI::GuardAI(Creature *c) : CreatureAI(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) { } void GuardAI::MoveInLineOfSight(Unit *u) { // Ignore Z for flying creatures - if ( !i_creature.canFly() && i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE ) + if ( !m_creature->canFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE ) return; - if( !i_creature.getVictim() && i_creature.canAttack(u) && - ( u->IsHostileToPlayers() || i_creature.IsHostileTo(u) /*|| u->getVictim() && i_creature.IsFriendlyTo(u->getVictim())*/ ) && - u->isInAccessiblePlaceFor(&i_creature)) + if( !m_creature->getVictim() && m_creature->canAttack(u) && + ( u->IsHostileToPlayers() || m_creature->IsHostileTo(u) /*|| u->getVictim() && m_creature->IsFriendlyTo(u->getVictim())*/ ) && + u->isInAccessiblePlaceFor(m_creature)) { - float attackRadius = i_creature.GetAttackDistance(u); - if(i_creature.IsWithinDistInMap(u,attackRadius)) + float attackRadius = m_creature->GetAttackDistance(u); + if(m_creature->IsWithinDistInMap(u,attackRadius)) { //Need add code to let guard support player AttackStart(u); @@ -59,81 +59,81 @@ void GuardAI::MoveInLineOfSight(Unit *u) void GuardAI::EnterEvadeMode() { - if( !i_creature.isAlive() ) + if( !m_creature->isAlive() ) { - DEBUG_LOG("Creature stopped attacking because he's dead [guid=%u]", i_creature.GetGUIDLow()); - i_creature.GetMotionMaster()->MoveIdle(); + DEBUG_LOG("Creature stopped attacking because he's dead [guid=%u]", m_creature->GetGUIDLow()); + m_creature->GetMotionMaster()->MoveIdle(); i_state = STATE_NORMAL; i_victimGuid = 0; - i_creature.CombatStop(); - i_creature.DeleteThreatList(); + m_creature->CombatStop(); + m_creature->DeleteThreatList(); return; } - Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid ); + Unit* victim = ObjectAccessor::GetUnit(*m_creature, i_victimGuid ); if( !victim ) { - DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", m_creature->GetGUIDLow()); } else if( !victim ->isAlive() ) { - DEBUG_LOG("Creature stopped attacking because victim is dead [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking because victim is dead [guid=%u]", m_creature->GetGUIDLow()); } else if( victim ->HasStealthAura() ) { - DEBUG_LOG("Creature stopped attacking because victim is using stealth [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking because victim is using stealth [guid=%u]", m_creature->GetGUIDLow()); } else if( victim ->isInFlight() ) { - DEBUG_LOG("Creature stopped attacking because victim is flying away [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking because victim is flying away [guid=%u]", m_creature->GetGUIDLow()); } else { - DEBUG_LOG("Creature stopped attacking because victim outran him [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking because victim outran him [guid=%u]", m_creature->GetGUIDLow()); } - i_creature.RemoveAllAuras(); - i_creature.DeleteThreatList(); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); i_victimGuid = 0; - i_creature.CombatStop(); + m_creature->CombatStop(); i_state = STATE_NORMAL; // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead - if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) - i_creature.GetMotionMaster()->MoveTargetedHome(); + if( m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) + m_creature->GetMotionMaster()->MoveTargetedHome(); } void GuardAI::UpdateAI(const uint32 /*diff*/) { - // update i_victimGuid if i_creature.getVictim() !=0 and changed + // update i_victimGuid if m_creature->getVictim() !=0 and changed if(!UpdateVictim()) return; - i_victimGuid = i_creature.getVictim()->GetGUID(); + i_victimGuid = m_creature->getVictim()->GetGUID(); - if( i_creature.isAttackReady() ) + if( m_creature->isAttackReady() ) { - if( i_creature.IsWithinMeleeRange(i_creature.getVictim())) + if( m_creature->IsWithinMeleeRange(m_creature->getVictim())) { - i_creature.AttackerStateUpdate(i_creature.getVictim()); - i_creature.resetAttackTimer(); + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); } } } bool GuardAI::IsVisible(Unit *pl) const { - return i_creature.GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_GUARDER) - && pl->isVisibleForOrDetect(&i_creature,true); + return m_creature->GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_GUARDER) + && pl->isVisibleForOrDetect(m_creature,true); } void GuardAI::JustDied(Unit *killer) { if(Player* pkiller = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) - i_creature.SendZoneUnderAttackMessage(pkiller); + m_creature->SendZoneUnderAttackMessage(pkiller); } diff --git a/src/game/GuardAI.h b/src/game/GuardAI.h index 3bc7ac35f8e..db1bfe0229d 100644 --- a/src/game/GuardAI.h +++ b/src/game/GuardAI.h @@ -36,7 +36,7 @@ class TRINITY_DLL_DECL GuardAI : public CreatureAI public: - GuardAI(Creature *c); + explicit GuardAI(Creature *c); void MoveInLineOfSight(Unit *); void EnterEvadeMode(); @@ -47,7 +47,6 @@ class TRINITY_DLL_DECL GuardAI : public CreatureAI static int Permissible(const Creature *); private: - Creature &i_creature; uint64 i_victimGuid; GuardState i_state; TimeTracker i_tracker; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index ac91f47bf95..1b8ec5eb836 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -905,7 +905,7 @@ void WorldSession::HandleGuildBankQuery( WorldPacket & recv_data ) uint8 unk; recv_data >> GoGuid >> unk; - if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; if (uint32 GuildId = GetPlayer()->GetGuildId()) @@ -929,7 +929,7 @@ void WorldSession::HandleGuildBankTabColon( WorldPacket & recv_data ) uint8 TabId,unk1; recv_data >> GoGuid >> TabId >> unk1; - if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; uint32 GuildId = GetPlayer()->GetGuildId(); @@ -958,7 +958,7 @@ void WorldSession::HandleGuildBankDeposit( WorldPacket & recv_data ) if (!money) return; - if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; uint32 GuildId = GetPlayer()->GetGuildId(); @@ -1006,7 +1006,7 @@ void WorldSession::HandleGuildBankWithdraw( WorldPacket & recv_data ) if (!money) return; - if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; uint32 GuildId = GetPlayer()->GetGuildId(); @@ -1108,7 +1108,7 @@ void WorldSession::HandleGuildBankDepositItem( WorldPacket & recv_data ) return; } - if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; uint32 GuildId = GetPlayer()->GetGuildId(); @@ -1563,7 +1563,7 @@ void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data ) recv_data >> GoGuid; recv_data >> TabId; - if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; uint32 GuildId = GetPlayer()->GetGuildId(); @@ -1620,7 +1620,7 @@ void WorldSession::HandleGuildBankModifyTab( WorldPacket & recv_data ) if(IconIndex.empty()) return; - if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; uint32 GuildId = GetPlayer()->GetGuildId(); diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 27aa29267df..aef5ea829c6 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -827,10 +827,23 @@ void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data ) _player->StoreItem( dest, pItem, true ); } -void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) { + CHECK_PACKET_SIZE(recvPacket, 8); + sLog.outDebug("WORLD: CMSG_BUY_BANK_SLOT"); + uint64 guid; + recvPacket >> guid; + + // cheating protection + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_BANKER); + if(!pCreature) + { + sLog.outDebug( "WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + uint32 slot = _player->GetByteValue(PLAYER_BYTES_2, 2); // next slot diff --git a/src/game/Language.h b/src/game/Language.h index 8217193ea50..28c0a81c879 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -807,24 +807,24 @@ enum TrinityStrings LANG_BG_AV_A_CAPTAIN_DEAD = 1232, // FREE IDS 1233-9999 - // Ticket Strings 2000-2029 - LANG_COMMAND_TICKETNEW = 2000, + // Ticket Strings 2000-2029 + LANG_COMMAND_TICKETNEW = 2000, LANG_COMMAND_TICKETUPDATED = 2001, - LANG_COMMAND_TICKETPLAYERABANDON = 2002, - LANG_COMMAND_TICKETCLOSED = 2003, - LANG_COMMAND_TICKETDELETED = 2004, - LANG_COMMAND_TICKETNOTEXIST = 2005, - LANG_COMMAND_TICKETCLOSEFIRST = 2006, - LANG_COMMAND_TICKETALREADYASSIGNED = 2007, - LANG_COMMAND_TICKETRELOAD = 2008, - LANG_COMMAND_TICKETSHOWLIST = 2009, + LANG_COMMAND_TICKETPLAYERABANDON = 2002, + LANG_COMMAND_TICKETCLOSED = 2003, + LANG_COMMAND_TICKETDELETED = 2004, + LANG_COMMAND_TICKETNOTEXIST = 2005, + LANG_COMMAND_TICKETCLOSEFIRST = 2006, + LANG_COMMAND_TICKETALREADYASSIGNED = 2007, + LANG_COMMAND_TICKETRELOAD = 2008, + LANG_COMMAND_TICKETSHOWLIST = 2009, LANG_COMMAND_TICKETSHOWONLINELIST = 2010, LANG_COMMAND_TICKETSHOWCLOSEDLIST = 2011, - LANG_COMMAND_TICKETASSIGNERROR_A = 2012, - LANG_COMMAND_TICKETASSIGNERROR_B = 2013, - LANG_COMMAND_TICKETNOTASSIGNED = 2014, - LANG_COMMAND_TICKETUNASSIGNSECURITY = 2015, - LANG_COMMAND_TICKETCANNOTCLOSE = 2016, + LANG_COMMAND_TICKETASSIGNERROR_A = 2012, + LANG_COMMAND_TICKETASSIGNERROR_B = 2013, + LANG_COMMAND_TICKETNOTASSIGNED = 2014, + LANG_COMMAND_TICKETUNASSIGNSECURITY = 2015, + LANG_COMMAND_TICKETCANNOTCLOSE = 2016, LANG_COMMAND_TICKETLISTGUID = 2017, LANG_COMMAND_TICKETLISTNAME = 2018, LANG_COMMAND_TICKETLISTAGE = 2019, @@ -833,7 +833,7 @@ enum TrinityStrings LANG_COMMAND_TICKETLISTMESSAGE = 2022, LANG_COMMAND_TICKETLISTCOMMENT = 2023, LANG_COMMAND_TICKETLISTADDCOMMENT = 2024, - + LANG_COMMAND_TICKETLISTAGECREATE = 2025, // Trinity strings 5000-9999 LANG_COMMAND_FREEZE = 5000, diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 831861c1ed8..452020e667b 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -293,6 +293,7 @@ bool ChatHandler::HandleGMTicketListCommand(const char* args) std::stringstream ss; ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); if(objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) { @@ -316,6 +317,7 @@ bool ChatHandler::HandleGMTicketListOnlineCommand(const char* args) std::stringstream ss; ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); if(objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) { @@ -338,6 +340,7 @@ bool ChatHandler::HandleGMTicketListClosedCommand(const char* args) std::stringstream ss; ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); if(objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) { @@ -365,6 +368,7 @@ bool ChatHandler::HandleGMTicketGetByIdCommand(const char* args) std::stringstream ss; ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str()); ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str()); if(objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) { @@ -395,6 +399,7 @@ bool ChatHandler::HandleGMTicketGetByNameCommand(const char* args) std::stringstream ss; ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str()); ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str()); if(objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) { diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 0377d299945..116fea3ac46 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -34,7 +34,7 @@ #include "SpellMgr.h" #include "PoolHandler.h" #include "AccountMgr.h" -//#include "GMTicketMgr.h" +#include "TicketMgr.h" #include "WaypointManager.h" #include "Util.h" #include <cctype> @@ -158,6 +158,48 @@ bool ChatHandler::HandleUnmuteCommand(const char* args) return true; } +bool ChatHandler::HandleGoTicketCommand(const char * args) +{ + if(!*args) + return false; + + char *cstrticket_id = strtok((char*)args, " "); + + if(!cstrticket_id) + return false; + + uint64 ticket_id = atoi(cstrticket_id); + if(!ticket_id) + return false; + + GM_Ticket *ticket = ticketmgr.GetGMTicket(ticket_id); + if(!ticket) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + float x, y, z; + int mapid; + + x = ticket->pos_x; + y = ticket->pos_y; + z = ticket->pos_z; + mapid = ticket->map; + + Player* _player = m_session->GetPlayer(); + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, 1, 0); + return true; +} + bool ChatHandler::HandleGoTriggerCommand(const char* args) { Player* _player = m_session->GetPlayer(); diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 09c95628921..97a684a2700 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -55,6 +55,9 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data ) recv_data >> mailbox; recv_data >> receiver; + if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + return; + // recheck CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+1+1+4+4+1+4+4+8+1); @@ -277,6 +280,10 @@ void WorldSession::HandleMarkAsRead(WorldPacket & recv_data ) uint64 mailbox; uint32 mailId; recv_data >> mailbox; + + if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + return; + recv_data >> mailId; Player *pl = _player; Mail *m = pl->GetMail(mailId); @@ -300,6 +307,10 @@ void WorldSession::HandleMailDelete(WorldPacket & recv_data ) uint32 mailId; recv_data >> mailbox; recv_data >> mailId; + + if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + return; + Player* pl = _player; pl->m_mailsUpdated = true; Mail *m = pl->GetMail(mailId); @@ -315,6 +326,10 @@ void WorldSession::HandleReturnToSender(WorldPacket & recv_data ) uint64 mailbox; uint32 mailId; recv_data >> mailbox; + + if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + return; + recv_data >> mailId; Player *pl = _player; Mail *m = pl->GetMail(mailId); @@ -419,6 +434,10 @@ void WorldSession::HandleTakeItem(WorldPacket & recv_data ) uint32 mailId; uint32 itemId; recv_data >> mailbox; + + if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + return; + recv_data >> mailId; recv_data >> itemId; // item guid low? Player* pl = _player; @@ -510,6 +529,10 @@ void WorldSession::HandleTakeMoney(WorldPacket & recv_data ) uint32 mailId; recv_data >> mailbox; recv_data >> mailId; + + if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + return; + Player *pl = _player; Mail* m = pl->GetMail(mailId); @@ -541,9 +564,8 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data ) uint64 mailbox; recv_data >> mailbox; - //GameObject* obj = ObjectAccessor::GetGameObject(_player, mailbox); - //if(!obj || !obj->IsMailBox()) - // return; + if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + return; Player* pl = _player; @@ -679,6 +701,9 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data ) recv_data >> mailbox >> mailId; + if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + return; + Player *pl = _player; Mail* m = pl->GetMail(mailId); diff --git a/src/game/Map.cpp b/src/game/Map.cpp index ac81b9c2a6d..d53c617e374 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -386,6 +386,8 @@ Map::EnsureGridCreated(const GridPair &p) Guard guard(*this); if(!getNGrid(p.x_coord, p.y_coord)) { + sLog.outDebug("Creating grid[%u,%u] for map %u instance %u", p.x_coord, p.y_coord, i_id, i_InstanceId); + setNGrid(new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld.getConfig(CONFIG_GRID_UNLOAD)), p.x_coord, p.y_coord); @@ -441,6 +443,8 @@ bool Map::EnsureGridLoaded(const Cell &cell) assert(grid != NULL); if( !isGridObjectDataLoaded(cell.GridX(), cell.GridY()) ) { + sLog.outDebug("Loading grid[%u,%u] for map %u instance %u", cell.GridX(), cell.GridY(), i_id, i_InstanceId); + ObjectGridLoader loader(*grid, this, cell); loader.LoadN(); @@ -1113,7 +1117,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool unloadAll) if(!unloadAll && ActiveObjectsNearGrid(x, y) ) return false; - DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id); + sLog.outDebug("Unloading grid[%u,%u] for map %u", x,y, i_id); ObjectGridUnloader unloader(*grid); @@ -1832,6 +1836,37 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const if (x > 1299.0f && x < 1839.0f && y > 10.0f && y < 440.0f) areaflag = 685; } break; + // The Makers' Perch (ground) and Makers' Overlook (ground and cave) + case 1335: // Sholazar Basin + // The Makers' Perch ground (fast box) + if (x > 6100.0f && x < 6250.0f && y > 5650.0f && y < 5800.0f) + { + // nice slow circle + if ((x-6183.0f)*(x-6183.0f)+(y-5717.0f)*(y-5717.0f) < 2500.0f) + areaflag = 2189; + } + // Makers' Overlook (ground and cave) + else if (x > 5634.48f && x < 5774.53f && y < 3475.0f && z > 300.0f) + { + if(y > 3380.26f || y > 3265.0f && z < 360.0f) areaflag = 2187; + } + break; + // The Makers' Perch (underground) + case 2147: // The Stormwright's Shelf (Sholazar Basin) + if (x > 6199.0f && x < 6283.0f && y > 5705.0f && y < 5817.0f && z < 38.0f) areaflag = 2189; break; + // Makers' Overlook (deep cave) + case 267: // Icecrown + if (x > 5684.0f && x < 5798.0f && y > 3035.0f && y < 3367.0f && z < 358.0f) areaflag = 2187; break; + // Wyrmrest Temple (Dragonblight) + case 1814: // Path of the Titans (Dragonblight) + case 1897: // The Dragon Wastes (Dragonblight) + // fast box + if (x > 3400.0f && x < 3700.0f && y > 130.0f && y < 420.0f) + { + // nice slow circle + if ((x-3546.87f)*(x-3546.87f)+(y-272.71f)*(y-272.71f) < 19600.0f) areaflag = 1791; + } + break; } return areaflag; diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index b299fbfd40a..51e684c5a6c 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -208,7 +208,7 @@ MotionMaster::MoveTargetedHome() DEBUG_LOG("Pet or controlled unit (Entry: %u GUID: %u) targeting home", i_owner->GetEntry(), i_owner->GetGUIDLow() ); - MoveFollow(i_owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE); + MoveFollow(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE); } else if(i_owner->GetTypeId() == TYPEID_UNIT) { @@ -242,7 +242,7 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle) { // ignore movement request if target not exist - if(!target) + if(!target || target == i_owner) return; i_owner->clearUnitState(UNIT_STAT_FOLLOW); @@ -268,7 +268,7 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot) { // ignore movement request if target not exist - if(!target) + if(!target || target == i_owner) return; i_owner->addUnitState(UNIT_STAT_FOLLOW); diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h index 626dd307ef3..d5c12d8c9a0 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -26,7 +26,7 @@ class TRINITY_DLL_DECL PassiveAI : public CreatureAI { public: - PassiveAI(Creature *c) : CreatureAI(c) {} + explicit PassiveAI(Creature *c) : CreatureAI(c) {} ~PassiveAI() {} void MoveInLineOfSight(Unit *) {} @@ -39,7 +39,7 @@ class TRINITY_DLL_DECL PassiveAI : public CreatureAI class TRINITY_DLL_DECL PossessedAI : public PassiveAI { public: - PossessedAI(Creature *c) : PassiveAI(c) {} + explicit PossessedAI(Creature *c) : PassiveAI(c) {} void AttackStart(Unit *target); void UpdateAI(const uint32); @@ -52,7 +52,7 @@ class TRINITY_DLL_DECL PossessedAI : public PassiveAI class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI { public: - NullCreatureAI(Creature *c) : PassiveAI(c) {} + explicit NullCreatureAI(Creature *c) : PassiveAI(c) {} void UpdateAI(const uint32) {} void EnterEvadeMode() {} @@ -61,7 +61,7 @@ class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI class TRINITY_DLL_DECL CritterAI : public PassiveAI { public: - CritterAI(Creature *c) : PassiveAI(c) {} + explicit CritterAI(Creature *c) : PassiveAI(c) {} void DamageTaken(Unit *done_by, uint32 & /*damage*/); void EnterEvadeMode(); diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp index d3e8397baaa..368edce0a53 100644 --- a/src/game/ObjectGridLoader.cpp +++ b/src/game/ObjectGridLoader.cpp @@ -311,10 +311,13 @@ ObjectGridStoper::Visit(CreatureMapType &m) // stop any fights at grid de-activation and remove dynobjects created at cast by creatures for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) { - iter->getSource()->CombatStop(); - iter->getSource()->DeleteThreatList(); iter->getSource()->RemoveAllDynObjects(); - iter->getSource()->AI()->EnterEvadeMode(); + if(iter->getSource()->isInCombat()) + { + iter->getSource()->CombatStop(); + iter->getSource()->DeleteThreatList(); + iter->getSource()->AI()->EnterEvadeMode(); + } } } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index efb5d0974ca..7096fa03dfa 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -161,6 +161,7 @@ ObjectMgr::~ObjectMgr() for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr) delete itr->second; + mGuildMap.clear(); for (CachePlayerInfoMap::iterator itr = m_mPlayerInfoMap.begin(); itr != m_mPlayerInfoMap.end(); ++itr) delete itr->second; @@ -590,6 +591,18 @@ void ObjectMgr::LoadCreatureTemplates() continue; } + if(heroicInfo->AIName && *heroicInfo->AIName) + { + sLog.outErrorDb("Heroic mode creature (Entry: %u) has `AIName`, but in any case will used normal mode creature (Entry: %u) AIName.",cInfo->HeroicEntry,i); + continue; + } + + if(heroicInfo->ScriptID) + { + sLog.outErrorDb("Heroic mode creature (Entry: %u) has `ScriptName`, but in any case will used normal mode creature (Entry: %u) ScriptName.",cInfo->HeroicEntry,i); + continue; + } + hasHeroicEntries.insert(i); heroicEntries.insert(cInfo->HeroicEntry); } @@ -4266,6 +4279,23 @@ void ObjectMgr::LoadInstanceTemplate() sLog.outString(); } +bool ObjectMgr::IsGameObjectOfTypeInRange(Player *player, uint64 guid, GameobjectTypes type) const +{ + if(GameObject *go = ObjectAccessor::GetGameObject(*player, guid)) + { + if(go->GetGoType() == type) + { + // TODO: find out how the client calculates the maximal usage distance to spellless working + // gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number + if (go->IsWithinDistInMap(player, 10.0f)) + return true; + sLog.outError("IsGameObjectOfTypeInRange: GameObject '%s' [GUID: %u] is too far away from player %s [GUID: %u] to be used by him (distance=%f, maximal 10 is allowed)", go->GetGOInfo()->name, + go->GetGUIDLow(), player->GetName(), player->GetGUIDLow(), go->GetDistance(player)); + } + } + return false; +} + GossipText const *ObjectMgr::GetGossipText(uint32 Text_ID) const { GossipTextMap::const_iterator itr = mGossipText.find(Text_ID); diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index ea73fb15715..56e1cbc2366 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -436,13 +436,7 @@ class ObjectMgr return mGameObjectForQuestSet.find(entry) != mGameObjectForQuestSet.end(); } - bool IsGuildVaultGameObject(Player *player, uint64 guid) const - { - if(GameObject *go = ObjectAccessor::GetGameObject(*player, guid)) - if(go->GetGoType() == GAMEOBJECT_TYPE_GUILD_BANK) - return true; - return false; - } + bool IsGameObjectOfTypeInRange(Player *player, uint64 guid, GameobjectTypes type) const; GossipText const* GetGossipText(uint32 Text_ID) const; diff --git a/src/game/OutdoorPvPObjectiveAI.h b/src/game/OutdoorPvPObjectiveAI.h index 5c68f45b082..dffd8885243 100644 --- a/src/game/OutdoorPvPObjectiveAI.h +++ b/src/game/OutdoorPvPObjectiveAI.h @@ -26,7 +26,7 @@ class Creature; class TRINITY_DLL_DECL OutdoorPvPObjectiveAI : public NullCreatureAI { public: - OutdoorPvPObjectiveAI(Creature *c); + explicit OutdoorPvPObjectiveAI(Creature *c); void MoveInLineOfSight(Unit *); diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index e723298565a..d1345b7079d 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -477,11 +477,7 @@ void Pet::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState(s); if(getDeathState()==CORPSE) { - //remove summoned pet (no corpse) - if(getPetType()==SUMMON_PET) - Remove(PET_SAVE_NOT_IN_SLOT); - // other will despawn at corpse desppawning (Pet::Update code) - else + if(getPetType() == HUNTER_PET) { // pet corpse non lootable and non skinnable SetUInt32Value( UNIT_DYNAMIC_FLAGS, 0x00 ); @@ -511,9 +507,8 @@ void Pet::Update(uint32 diff) { case CORPSE: { - if( m_deathTimer <= diff ) + if(getPetType() != HUNTER_PET || m_deathTimer <= diff ) { - assert(getPetType()!=SUMMON_PET && "Must be already removed."); Remove(PET_SAVE_NOT_IN_SLOT); //hunters' pets never get removed because of death, NEVER! return; } diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 3ba66bd57a0..88327978de9 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -38,7 +38,7 @@ int PetAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -PetAI::PetAI(Creature *c) : CreatureAI(c), i_pet(*c), i_tracker(TIME_INTERVAL_LOOK) +PetAI::PetAI(Creature *c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK) { m_AllySet.clear(); UpdateAllies(); @@ -51,46 +51,46 @@ void PetAI::EnterEvadeMode() bool PetAI::_needToStop() const { // This is needed for charmed creatures, as once their target was reset other effects can trigger threat - if(i_pet.isCharmed() && i_pet.getVictim() == i_pet.GetCharmer()) + if(m_creature->isCharmed() && m_creature->getVictim() == m_creature->GetCharmer()) return true; - return !i_pet.canAttack(i_pet.getVictim()); + return !m_creature->canAttack(m_creature->getVictim()); } void PetAI::_stopAttack() { - if( !i_pet.isAlive() ) + if( !m_creature->isAlive() ) { - DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_pet.GetGUIDLow()); - i_pet.GetMotionMaster()->Clear(); - i_pet.GetMotionMaster()->MoveIdle(); - i_pet.CombatStop(); - i_pet.getHostilRefManager().deleteReferences(); + DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", m_creature->GetGUIDLow()); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->CombatStop(); + m_creature->getHostilRefManager().deleteReferences(); return; } - Unit* owner = i_pet.GetCharmerOrOwner(); + Unit* owner = m_creature->GetCharmerOrOwner(); - if(owner && i_pet.GetCharmInfo() && i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) + if(owner && m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) { - i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); } else { - i_pet.clearUnitState(UNIT_STAT_FOLLOW); - i_pet.GetMotionMaster()->Clear(); - i_pet.GetMotionMaster()->MoveIdle(); + m_creature->clearUnitState(UNIT_STAT_FOLLOW); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); } - i_pet.AttackStop(); + m_creature->AttackStop(); } void PetAI::UpdateAI(const uint32 diff) { - if (!i_pet.isAlive()) + if (!m_creature->isAlive()) return; - Unit* owner = i_pet.GetCharmerOrOwner(); + Unit* owner = m_creature->GetCharmerOrOwner(); if(m_updateAlliesTimer <= diff) // UpdateAllies self set update timer @@ -98,12 +98,12 @@ void PetAI::UpdateAI(const uint32 diff) else m_updateAlliesTimer -= diff; - // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. - if( i_pet.getVictim() ) + // m_creature->getVictim() can't be used for check in case stop fighting, m_creature->getVictim() clear at Unit death etc. + if( m_creature->getVictim() ) { if( _needToStop() ) { - DEBUG_LOG("Pet AI stoped attacking [guid=%u]", i_pet.GetGUIDLow()); + DEBUG_LOG("Pet AI stoped attacking [guid=%u]", m_creature->GetGUIDLow()); _stopAttack(); return; } @@ -114,26 +114,26 @@ void PetAI::UpdateAI(const uint32 diff) { if(me->isInCombat()) _stopAttack(); - else if(owner && i_pet.GetCharmInfo()) //no victim + else if(owner && m_creature->GetCharmInfo()) //no victim { - if(owner->isInCombat() && !(i_pet.HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY))) + if(owner->isInCombat() && !(m_creature->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY))) AttackStart(owner->getAttackerForHelper()); - else if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !i_pet.hasUnitState(UNIT_STAT_FOLLOW)) - i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + else if(m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) + m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); } } if(!me->GetCharmInfo()) return; - if (i_pet.GetGlobalCooldown() == 0 && !i_pet.hasUnitState(UNIT_STAT_CASTING)) + if (m_creature->GetGlobalCooldown() == 0 && !m_creature->hasUnitState(UNIT_STAT_CASTING)) { bool inCombat = me->getVictim(); //Autocast - for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++) + for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); i++) { - uint32 spellID = i_pet.GetPetAutoSpellOnPos(i); + uint32 spellID = m_creature->GetPetAutoSpellOnPos(i); if (!spellID) continue; @@ -153,11 +153,11 @@ void PetAI::UpdateAI(const uint32 diff) continue; } - Spell *spell = new Spell(&i_pet, spellInfo, false, 0); + Spell *spell = new Spell(m_creature, spellInfo, false, 0); - if(inCombat && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim())) + if(inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim())) { - m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(i_pet.getVictim(), spell)); + m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(m_creature->getVictim(), spell)); continue; } else @@ -165,7 +165,7 @@ void PetAI::UpdateAI(const uint32 diff) bool spellUsed = false; for(std::set<uint64>::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) { - Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar); + Unit* Target = ObjectAccessor::GetUnit(*m_creature,*tar); //only buff targets that are in combat, unless the spell can only be cast while out of combat if(!Target) @@ -196,19 +196,19 @@ void PetAI::UpdateAI(const uint32 diff) SpellCastTargets targets; targets.setUnitTarget( target ); - if( !i_pet.HasInArc(M_PI, target) ) + if( !m_creature->HasInArc(M_PI, target) ) { - i_pet.SetInFront(target); + m_creature->SetInFront(target); if( target->GetTypeId() == TYPEID_PLAYER ) - i_pet.SendUpdateToPlayer( (Player*)target ); + m_creature->SendUpdateToPlayer( (Player*)target ); if(owner && owner->GetTypeId() == TYPEID_PLAYER) - i_pet.SendUpdateToPlayer( (Player*)owner ); + m_creature->SendUpdateToPlayer( (Player*)owner ); } - i_pet.AddCreatureSpellCooldown(spell->m_spellInfo->Id); - if(i_pet.isPet()) - ((Pet*)&i_pet)->CheckLearning(spell->m_spellInfo->Id); + m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id); + if(m_creature->isPet()) + ((Pet*)m_creature)->CheckLearning(spell->m_spellInfo->Id); spell->prepare(&targets); } @@ -222,7 +222,7 @@ void PetAI::UpdateAI(const uint32 diff) void PetAI::UpdateAllies() { - Unit* owner = i_pet.GetCharmerOrOwner(); + Unit* owner = m_creature->GetCharmerOrOwner(); Group *pGroup = NULL; m_updateAlliesTimer = 10*IN_MILISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance @@ -240,7 +240,7 @@ void PetAI::UpdateAllies() return; m_AllySet.clear(); - m_AllySet.insert(i_pet.GetGUID()); + m_AllySet.insert(m_creature->GetGUID()); if(pGroup) //add group { for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) diff --git a/src/game/PetAI.h b/src/game/PetAI.h index be38e03e13c..a346908ee0e 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -31,7 +31,7 @@ class TRINITY_DLL_DECL PetAI : public CreatureAI { public: - PetAI(Creature *c); + explicit PetAI(Creature *c); void EnterEvadeMode(); void JustDied(Unit* who) { _stopAttack(); } @@ -46,7 +46,6 @@ class TRINITY_DLL_DECL PetAI : public CreatureAI void UpdateAllies(); - Creature &i_pet; TimeTracker i_tracker; std::set<uint64> m_AllySet; uint32 m_updateAlliesTimer; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e8b7aa6c8d1..803f2b5ecef 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -9548,7 +9548,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++) { pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); - if( pBag ) + if( pBag && ItemCanGoIntoBag(pItem->GetProto(), pBag->GetProto())) { for(uint32 j = 0; j < pBag->GetBagSize(); j++) { @@ -9585,7 +9585,6 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const if (b_found) continue; - /* until proper implementation if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) { for(uint32 t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t) @@ -9600,7 +9599,6 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const } if (b_found) continue; - */ for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++) { @@ -14419,7 +14417,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff); _LoadGlyphAuras(); - // add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura) if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) m_deathState = DEAD; @@ -16455,18 +16452,19 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) } } - pet->SavePetToDB(mode); - // only if current pet in slot switch(pet->getPetType()) { case POSSESSED_PET: pet->RemoveCharmedOrPossessedBy(NULL); + break; default: - SetGuardian(pet, false); + pet->SavePetToDB(mode); break; } + SetGuardian(pet, false); + pet->CleanupsBeforeDelete(); pet->AddObjectToRemoveList(); pet->m_removed = true; @@ -18001,13 +17999,25 @@ bool Player::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList, bool return false; } - // player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting) - if((m_mover->m_invisibilityMask || u->m_invisibilityMask) && !m_mover->canDetectInvisibilityOf(u)) - if(!(u->GetTypeId()==TYPEID_PLAYER && !IsHostileTo(u) && IsGroupVisibleFor(((Player*)u)))) - return false; + // GM's can see everyone with invisibilitymask with less or equal security level + if(m_mover->m_invisibilityMask || u->m_invisibilityMask) + { + if(isGameMaster()) + { + if(u->GetTypeId() == TYPEID_PLAYER) + return ((Player*)u)->GetSession()->GetSecurity() <= GetSession()->GetSecurity(); + else + return true; + } + + // player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting) + if(!m_mover->canDetectInvisibilityOf(u)) + if(!(u->GetTypeId()==TYPEID_PLAYER && !IsHostileTo(u) && IsGroupVisibleFor(((Player*)u)))) + return false; + } // GM invisibility checks early, invisibility if any detectable, so if not stealth then visible - if(u->GetVisibility() == VISIBILITY_GROUP_STEALTH) + if(u->GetVisibility() == VISIBILITY_GROUP_STEALTH && !isGameMaster()) { // if player is dead then he can't detect anyone in any cases //do not know what is the use of this detect diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp index fea5666c9e0..f8f4a0f9f8a 100644 --- a/src/game/PlayerDump.cpp +++ b/src/game/PlayerDump.cpp @@ -26,7 +26,7 @@ #include "ObjectMgr.h" // Character Dump tables -#define DUMP_TABLE_COUNT 18 +#define DUMP_TABLE_COUNT 20 struct DumpTable { @@ -36,24 +36,27 @@ struct DumpTable static DumpTable dumpTables[DUMP_TABLE_COUNT] = { - { "characters", DTT_CHARACTER }, - { "character_queststatus", DTT_CHAR_TABLE }, - { "character_reputation", DTT_CHAR_TABLE }, - { "character_spell", DTT_CHAR_TABLE }, - { "character_spell_cooldown", DTT_CHAR_TABLE }, - { "character_action", DTT_CHAR_TABLE }, - { "character_aura", DTT_CHAR_TABLE }, - { "character_homebind", DTT_CHAR_TABLE }, - { "character_inventory", DTT_INVENTORY }, - { "mail", DTT_MAIL }, - { "mail_items", DTT_MAIL_ITEM }, - { "item_instance", DTT_ITEM }, - { "character_gifts", DTT_ITEM_GIFT }, - { "item_text", DTT_ITEM_TEXT }, - { "character_pet", DTT_PET }, - { "pet_aura", DTT_PET_TABLE }, - { "pet_spell", DTT_PET_TABLE }, - { "pet_spell_cooldown", DTT_PET_TABLE }, + { "characters", DTT_CHARACTER }, + { "character_achievement", DTT_CHAR_TABLE }, + { "character_achievement_progress", DTT_CHAR_TABLE }, + { "character_queststatus", DTT_CHAR_TABLE }, + { "character_reputation", DTT_CHAR_TABLE }, + { "character_spell", DTT_CHAR_TABLE }, + { "character_spell_cooldown", DTT_CHAR_TABLE }, + { "character_action", DTT_CHAR_TABLE }, + { "character_aura", DTT_CHAR_TABLE }, + { "character_homebind", DTT_CHAR_TABLE }, +// { "character_ticket", DTT_CHAR_TABLE }, + { "character_inventory", DTT_INVENTORY }, + { "mail", DTT_MAIL }, + { "mail_items", DTT_MAIL_ITEM }, + { "item_instance", DTT_ITEM }, + { "character_gifts", DTT_ITEM_GIFT }, + { "item_text", DTT_ITEM_TEXT }, + { "character_pet", DTT_PET }, + { "pet_aura", DTT_PET_TABLE }, + { "pet_spell", DTT_PET_TABLE }, + { "pet_spell_cooldown", DTT_PET_TABLE }, }; // Low level functions diff --git a/src/game/PlayerDump.h b/src/game/PlayerDump.h index 01f97718267..e3dfd192efb 100644 --- a/src/game/PlayerDump.h +++ b/src/game/PlayerDump.h @@ -29,10 +29,10 @@ enum DumpTableType { DTT_CHARACTER, // // characters - DTT_CHAR_TABLE, // // character_action, character_aura, character_homebind, - // character_queststatus, character_reputation, - // character_spell, character_spell_cooldown, character_ticket, - // character_tutorial + DTT_CHAR_TABLE, // // character_achievement, character_achievement_progress, + // character_action, character_aura, character_homebind, + // character_queststatus, character_reputation, character_spell, + // character_spell_cooldown, character_ticket, character_tutorial DTT_INVENTORY, // -> item guids collection // character_inventory diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp index 7c4d1a73eb6..30847405c9e 100644 --- a/src/game/ReactorAI.cpp +++ b/src/game/ReactorAI.cpp @@ -50,18 +50,18 @@ ReactorAI::IsVisible(Unit *) const void ReactorAI::UpdateAI(const uint32 /*time_diff*/) { - // update i_victimGuid if i_creature.getVictim() !=0 and changed + // update i_victimGuid if m_creature->getVictim() !=0 and changed if(!UpdateVictim()) return; - i_victimGuid = i_creature.getVictim()->GetGUID(); + i_victimGuid = m_creature->getVictim()->GetGUID(); - if( i_creature.isAttackReady() ) + if( m_creature->isAttackReady() ) { - if( i_creature.IsWithinMeleeRange(i_creature.getVictim())) + if( m_creature->IsWithinMeleeRange(m_creature->getVictim())) { - i_creature.AttackerStateUpdate(i_creature.getVictim()); - i_creature.resetAttackTimer(); + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); } } } @@ -69,49 +69,49 @@ ReactorAI::UpdateAI(const uint32 /*time_diff*/) void ReactorAI::EnterEvadeMode() { - if( !i_creature.isAlive() ) + if( !m_creature->isAlive() ) { - DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_creature.GetGUIDLow()); - i_creature.GetMotionMaster()->MovementExpired(); - i_creature.GetMotionMaster()->MoveIdle(); + DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", m_creature->GetGUIDLow()); + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->GetMotionMaster()->MoveIdle(); i_victimGuid = 0; - i_creature.CombatStop(); - i_creature.DeleteThreatList(); + m_creature->CombatStop(); + m_creature->DeleteThreatList(); return; } - Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid ); + Unit* victim = ObjectAccessor::GetUnit(*m_creature, i_victimGuid ); if( !victim ) { - DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", m_creature->GetGUIDLow()); } else if( victim->HasStealthAura() ) { - DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", m_creature->GetGUIDLow()); } else if( victim->isInFlight() ) { - DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", m_creature->GetGUIDLow()); } else { - DEBUG_LOG("Creature stopped attacking due to target %s [guid=%u]", victim->isAlive() ? "out run him" : "is dead", i_creature.GetGUIDLow()); + DEBUG_LOG("Creature stopped attacking due to target %s [guid=%u]", victim->isAlive() ? "out run him" : "is dead", m_creature->GetGUIDLow()); } - i_creature.RemoveAllAuras(); - i_creature.DeleteThreatList(); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); i_victimGuid = 0; - i_creature.CombatStop(); - i_creature.SetLootRecipient(NULL); + m_creature->CombatStop(); + m_creature->SetLootRecipient(NULL); - if(!i_creature.GetCharmerOrOwner()) + if(!m_creature->GetCharmerOrOwner()) { // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead - if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) - i_creature.GetMotionMaster()->MoveTargetedHome(); + if( m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) + m_creature->GetMotionMaster()->MoveTargetedHome(); } - else if (i_creature.GetOwner() && i_creature.GetOwner()->isAlive()) - i_creature.GetMotionMaster()->MoveFollow(i_creature.GetOwner(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + else if (m_creature->GetOwner() && m_creature->GetOwner()->isAlive()) + m_creature->GetMotionMaster()->MoveFollow(m_creature->GetOwner(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); } diff --git a/src/game/ReactorAI.h b/src/game/ReactorAI.h index 1cc7da43743..baed6a8e6e1 100644 --- a/src/game/ReactorAI.h +++ b/src/game/ReactorAI.h @@ -29,7 +29,7 @@ class TRINITY_DLL_DECL ReactorAI : public CreatureAI { public: - ReactorAI(Creature *c) : CreatureAI(c), i_creature(*c), i_victimGuid(0) {} + explicit ReactorAI(Creature *c) : CreatureAI(c), i_victimGuid(0) {} void MoveInLineOfSight(Unit *); void EnterEvadeMode(); @@ -39,7 +39,6 @@ class TRINITY_DLL_DECL ReactorAI : public CreatureAI static int Permissible(const Creature *); private: - Creature &i_creature; uint64 i_victimGuid; }; #endif diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 41d01772c50..d9aa5ffc2a1 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -380,6 +380,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi m_glyphIndex = 0; m_preCastSpell = 0; m_triggeredByAuraSpell = NULL; + m_spellAura = NULL; //Auto Shot & Shoot (wand) m_autoRepeat = IsAutoRepeatRangedSpell(m_spellInfo); @@ -938,6 +939,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) uint32 procAttacker = m_procAttacker; uint32 procVictim = m_procVictim; uint32 procEx = PROC_EX_NONE; + m_spellAura = NULL; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied if (missInfo==SPELL_MISS_NONE) // In case spell hit target, do all effect on that target DoSpellHitOnUnit(unit, mask); @@ -981,6 +983,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (m_canTrigger && missInfo != SPELL_MISS_REFLECT) caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo); + if (m_spellAura) + m_spellAura->SetProcDamage(addhealth); + int32 gain = unitTarget->ModifyHealth( int32(addhealth) ); unitTarget->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, m_spellInfo); @@ -1007,6 +1012,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (m_canTrigger && missInfo != SPELL_MISS_REFLECT) caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo); + if (m_spellAura) + m_spellAura->SetProcDamage(damageInfo.damage); + caster->DealSpellDamage(&damageInfo, true); // Judgement of Blood @@ -1186,7 +1194,9 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags[1] & 0x000020)) m_caster->CastSpell(unit, 41637, true, NULL, NULL, m_originalCasterGUID); } - unit->AddAura(Aur); + // Set aura only when successfully applied + if (unit->AddAura(Aur)) + m_spellAura = Aur; } t_effmask = effectMask& ~t_effmask; for(uint32 effectNumber=0;effectNumber<3;effectNumber++) @@ -1236,6 +1246,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) _duration = aur ? aur->GetAuraDuration() : -1; } triggeredAur->SetAuraDuration(_duration); + triggeredAur->SetPermanent(false); } } } @@ -2570,8 +2581,8 @@ void Spell::SendSpellCooldown() return; } - // have infinity cooldown but set at aura apply - if(m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) + // have infinity cooldown but set at aura apply // do not set cooldown for triggered spells (needed by reincarnation) + if(m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE || m_IsTriggeredSpell) return; _player->AddSpellAndCategoryCooldowns(m_spellInfo,m_CastItem ? m_CastItem->GetEntry() : 0, this); @@ -2813,6 +2824,10 @@ void Spell::SendSpellStart() uint32 castFlags = CAST_FLAG_UNKNOWN1; if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; + if ((m_caster->GetTypeId() == TYPEID_PLAYER || + (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isPet())) + && m_spellInfo->powerType != POWER_HEALTH ) + castFlags |= CAST_FLAG_POWER_LEFT_SELF; if(m_spellInfo->runeCostID) castFlags |= CAST_FLAG_UNKNOWN10; @@ -2833,23 +2848,8 @@ void Spell::SendSpellStart() m_targets.write(&data); - if ( castFlags & CAST_FLAG_UNKNOWN6 ) // predicted power? - data << uint32(0); - - if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list - { - uint8 v1 = 0;//m_runesState; - uint8 v2 = 0;//((Player*)m_caster)->GetRunesState(); - data << uint8(v1); // runes state before - data << uint8(v2); // runes state after - for(uint8 i = 0; i < MAX_RUNES; ++i) - { - uint8 m = (1 << i); - if(m & v1) // usable before... - if(!(m & v2)) // ...but on cooldown now... - data << uint8(0); // some unknown byte (time?) - } - } + if(castFlags & CAST_FLAG_POWER_LEFT_SELF) + data << uint32(m_caster->GetPower((Powers)m_spellInfo->powerType)); if ( castFlags & CAST_FLAG_AMMO ) WriteAmmoToPacket(&data); @@ -2870,11 +2870,14 @@ void Spell::SendSpellGo() uint32 castFlags = CAST_FLAG_UNKNOWN3; if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual + if ((m_caster->GetTypeId() == TYPEID_PLAYER || + (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isPet())) + && m_spellInfo->powerType != POWER_HEALTH ) + castFlags |= CAST_FLAG_POWER_LEFT_SELF; // should only be sent to self, but the current messaging doesn't make that possible if((m_caster->GetTypeId() == TYPEID_PLAYER) && (m_caster->getClass() == CLASS_DEATH_KNIGHT) && m_spellInfo->runeCostID) { castFlags |= CAST_FLAG_UNKNOWN10; // same as in SMSG_SPELL_START - castFlags |= CAST_FLAG_UNKNOWN6; // makes cooldowns visible castFlags |= CAST_FLAG_UNKNOWN7; // rune cooldowns list } @@ -2895,8 +2898,8 @@ void Spell::SendSpellGo() m_targets.write(&data); - if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk, predicted power? - data << uint32(0); + if(castFlags & CAST_FLAG_POWER_LEFT_SELF) + data << uint32(m_caster->GetPower((Powers)m_spellInfo->powerType)); if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list { @@ -3658,19 +3661,23 @@ SpellCastResult Spell::CheckCast(bool strict) } } - // caster state requirements - if(m_spellInfo->CasterAuraState && !m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraState), m_spellInfo, m_caster)) - return SPELL_FAILED_CASTER_AURASTATE; - if(m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraStateNot), m_spellInfo, m_caster)) - return SPELL_FAILED_CASTER_AURASTATE; + // caster state requirements + // not for triggered spells (needed by execute) + if (!m_IsTriggeredSpell) + { + if(m_spellInfo->CasterAuraState && !m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraState), m_spellInfo, m_caster)) + return SPELL_FAILED_CASTER_AURASTATE; + if(m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraStateNot), m_spellInfo, m_caster)) + return SPELL_FAILED_CASTER_AURASTATE; - if(m_spellInfo->casterAuraSpell && !m_caster->HasAura(m_spellInfo->casterAuraSpell)) - return SPELL_FAILED_CASTER_AURASTATE; - if(m_spellInfo->excludeCasterAuraSpell && m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell)) - return SPELL_FAILED_CASTER_AURASTATE; + if(m_spellInfo->casterAuraSpell && !m_caster->HasAura(m_spellInfo->casterAuraSpell)) + return SPELL_FAILED_CASTER_AURASTATE; + if(m_spellInfo->excludeCasterAuraSpell && m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell)) + return SPELL_FAILED_CASTER_AURASTATE; - if(reqCombat && m_caster->isInCombat() && IsNonCombatSpell(m_spellInfo)) - return SPELL_FAILED_AFFECTING_COMBAT; + if(reqCombat && m_caster->isInCombat() && IsNonCombatSpell(m_spellInfo)) + return SPELL_FAILED_AFFECTING_COMBAT; + } // cancel autorepeat spells if cast start when moving // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code) @@ -3684,9 +3691,8 @@ SpellCastResult Spell::CheckCast(bool strict) if(Unit *target = m_targets.getUnitTarget()) { - // target state requirements (not allowed state), apply to self also - if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot), m_spellInfo, m_caster)) + if(!m_IsTriggeredSpell && m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot), m_spellInfo, m_caster)) return SPELL_FAILED_TARGET_AURASTATE; if(m_spellInfo->targetAuraSpell && !target->HasAura(m_spellInfo->targetAuraSpell)) @@ -3698,7 +3704,7 @@ SpellCastResult Spell::CheckCast(bool strict) if(target != m_caster) { // target state requirements (apply to non-self only), to allow cast affects to self like Dirty Deeds - if(m_spellInfo->TargetAuraState && !target->HasAuraState(AuraState(m_spellInfo->TargetAuraState), m_spellInfo, m_caster)) + if(!m_IsTriggeredSpell && m_spellInfo->TargetAuraState && !target->HasAuraState(AuraState(m_spellInfo->TargetAuraState), m_spellInfo, m_caster)) return SPELL_FAILED_TARGET_AURASTATE; // Not allow casting on flying player @@ -4004,22 +4010,7 @@ SpellCastResult Spell::CheckCast(bool strict) { case SPELL_EFFECT_DUMMY: { - if(m_spellInfo->SpellIconID == 1648) // Execute - { - if(!m_targets.getUnitTarget()) - return SPELL_FAILED_BAD_TARGETS; - if (m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2) - { - bool found = false; - Unit::AuraEffectList const& stateAuras = m_caster->GetAurasByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); - for(Unit::AuraEffectList::const_iterator j = stateAuras.begin();j != stateAuras.end(); ++j) - if((*j)->isAffectedOnSpell(m_spellInfo)) - found=true; - if (!found) - return SPELL_FAILED_BAD_TARGETS; - } - } - else if (m_spellInfo->Id == 51582) // Rocket Boots Engaged + if (m_spellInfo->Id == 51582) // Rocket Boots Engaged { if(m_caster->IsInWater()) return SPELL_FAILED_ONLY_ABOVEWATER; @@ -4039,19 +4030,6 @@ SpellCastResult Spell::CheckCast(bool strict) } break; } - case SPELL_EFFECT_SCHOOL_DAMAGE: - { - // Hammer of Wrath - if(m_spellInfo->SpellVisual[0] == 7250) - { - if (!m_targets.getUnitTarget()) - return SPELL_FAILED_BAD_IMPLICIT_TARGETS; - - if(m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2) - return SPELL_FAILED_BAD_TARGETS; - } - break; - } case SPELL_EFFECT_LEARN_SPELL: { if (m_caster->GetTypeId() != TYPEID_PLAYER) diff --git a/src/game/Spell.h b/src/game/Spell.h index 45a3a123bae..f012fdff231 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -82,7 +82,7 @@ enum SpellCastFlags CAST_FLAG_UNKNOWN3 = 0x00000100, CAST_FLAG_UNKNOWN13 = 0x00000200, CAST_FLAG_UNKNOWN14 = 0x00000400, - CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk, trigger rune cooldown + CAST_FLAG_POWER_LEFT_SELF = 0x00000800, // wotlk CAST_FLAG_UNKNOWN15 = 0x00001000, CAST_FLAG_UNKNOWN16 = 0x00002000, CAST_FLAG_UNKNOWN17 = 0x00004000, @@ -517,6 +517,7 @@ class Spell Item* itemTarget; GameObject* gameObjTarget; int32 damage; + Aura * m_spellAura; // only used in DoAllEffectOnTarget // this is set in Spell Hit, but used in Apply Aura handler DiminishingLevels m_diminishLevel; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 5fedc013188..b9f440188d2 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -426,24 +426,22 @@ m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_aura // Aura is positive when it is casted by friend and at least one aura is positive // or when it is casted by enemy and at least one aura is negative bool swap=false; - if (!caster || caster==target) - m_positive=IsPositiveSpell(m_spellProto->Id); + if (!caster || caster==target) // caster == target - 1 negative effect is enough for aura to be negative + m_positive = false; else - { m_positive = !caster->IsHostileTo(m_target); - for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i) + for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i) + { + if (!(1<<i & GetEffectMask())) + continue; + if (m_positive == IsPositiveEffect(GetId(), i)) { - if (!(1<<i & GetEffectMask())) - continue; - if (m_positive == IsPositiveEffect(GetId(), i)) - { - swap = true; - break; - } + swap = true; + break; } - if (!swap) - m_positive=!m_positive; } + if (!swap) + m_positive=!m_positive; } Aura::~Aura() @@ -607,36 +605,48 @@ void Aura::Update(uint32 diff) m_duration -= diff; if (m_duration < 0) m_duration = 0; - m_timeCla -= diff; // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0 + if(m_timeCla > 0) + m_timeCla -= diff; if(m_timeCla <= 0) { if(Unit* caster = GetCaster()) { - Powers powertype = Powers(m_spellProto->powerType); - int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel(); - m_timeCla = 1000; - if (manaPerSecond) + if(int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel()) { - if(powertype==POWER_HEALTH) + m_timeCla = 1000; + + Powers powertype = Powers(m_spellProto->powerType); + if(powertype == POWER_HEALTH) { - if (caster->GetHealth()>manaPerSecond) + if (caster->GetHealth() > manaPerSecond) caster->ModifyHealth(-manaPerSecond); else + { m_target->RemoveAura(this); + return; + } } - else if (caster->GetPower(powertype)>=manaPerSecond) - caster->ModifyPower(powertype,-manaPerSecond); else - m_target->RemoveAura(this); + { + if (caster->GetPower(powertype) >= manaPerSecond) + caster->ModifyPower(powertype, -manaPerSecond); + else + { + m_target->RemoveAura(this); + return; + } + } } } } } - // Channeled aura required check distance from caster except in possessed cases - if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID() && !m_target->isPossessed()) + // Channeled aura required check distance from caster + if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID() + && !IsAreaAura() && !IsPersistent() // check for these is done in auraeffect + /* && !m_target->isPossessed()*/) { Unit* caster = GetCaster(); if(!caster) @@ -647,16 +657,18 @@ void Aura::Update(uint32 diff) // Get spell range float radius=-1.0f; SpellModOp mod; + // get part aura with lowest radius for (uint8 i=0;i<3;++i) { if (HasEffect(i) && m_spellProto->EffectRadiusIndex[i]) { - radius = caster->GetSpellRadiusForTarget(m_target, sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[i])); + float new_radius = caster->GetSpellRadiusForTarget(m_target, sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[i])); + if (radius < 0.0f || radius > new_radius) + radius = new_radius; mod = SPELLMOD_RADIUS; - break; } } - if (radius<0) + if (radius < 0.0f) { radius = caster->GetSpellMaxRangeForTarget(m_target, sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex)) ; mod = SPELLMOD_RANGE; @@ -672,16 +684,9 @@ void Aura::Update(uint32 diff) } } - for (uint8 i = 0; i<MAX_SPELL_EFFECTS;++i) + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (m_partAuras[i]) - { - if (m_partAuras[i]->IsAreaAura()) - ((AreaAuraEffect *) m_partAuras[i])->Update(diff); - else if(m_partAuras[i]->IsPersistent()) - ((PersistentAreaAuraEffect *) m_partAuras[i])->Update(diff); - else - m_partAuras[i]->Update(diff); - } + m_partAuras[i]->Update(diff); } void AuraEffect::Update(uint32 diff) @@ -764,28 +769,29 @@ void AreaAuraEffect::Update(uint32 diff) } else // aura at non-caster { - Unit * tmp_target = m_target; - Unit* caster = GetCaster(); - uint32 tmp_spellId = GetId(); - uint32 tmp_effIndex = GetEffIndex(); - uint64 tmp_guid = GetCasterGUID(); - // WARNING: the aura may get deleted during the update // DO NOT access its members after update! AuraEffect::Update(diff); + // Speedup - no need to do more checks + if (GetParentAura()->IsRemoved()) + return; + + // Caster may be deleted due to update + Unit* caster = GetCaster(); + // remove aura if out-of-range from caster (after teleport for example) // or caster is isolated or caster no longer has the aura // or caster is (no longer) friendly bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true); if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) || - !caster->HasAuraEffect(tmp_spellId, tmp_effIndex) || - caster->IsFriendlyTo(tmp_target) != needFriendly + !caster->HasAuraEffect(GetId(), m_effIndex) || + caster->IsFriendlyTo(m_target) != needFriendly ) { m_target->RemoveAura(GetParentAura()); } - else if (!caster->IsWithinDistInMap(tmp_target, m_radius)) + else if (!caster->IsWithinDistInMap(m_target, m_radius)) { if (needFriendly) { @@ -802,17 +808,17 @@ void AreaAuraEffect::Update(uint32 diff) m_removeTime = FRIENDLY_AA_REMOVE_TIME; if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group { - if(!tmp_target->IsInPartyWith(caster)) + if(!m_target->IsInPartyWith(caster)) m_target->RemoveAura(GetParentAura()); } else if( m_areaAuraType == AREA_AURA_RAID) { - if(!tmp_target->IsInRaidWith(caster)) + if(!m_target->IsInRaidWith(caster)) m_target->RemoveAura(GetParentAura()); } else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) { - if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) + if( m_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) m_target->RemoveAura(GetParentAura()); } } @@ -821,29 +827,21 @@ void AreaAuraEffect::Update(uint32 diff) void PersistentAreaAuraEffect::Update(uint32 diff) { - bool remove = false; - - // remove the aura if its caster or the dynamic object causing it was removed - // or if the target moves too far from the dynamic object - Unit *caster = GetCaster(); - if (caster) + if(Unit *caster = GetCaster()) { - DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex()); - if (dynObj) + if(DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex())) { - if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius())) - remove = true; + if(m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius())) + { + AuraEffect::Update(diff); + return; + } } - else - remove = true; } - else - remove = true; - - if(remove) - m_target->RemoveAura(GetParentAura()); - AuraEffect::Update(diff); + // remove the aura if its caster or the dynamic object causing it was removed + // or if the target moves too far from the dynamic object + m_target->RemoveAura(GetParentAura()); } void AuraEffect::ApplyModifier(bool apply, bool Real) @@ -1169,25 +1167,26 @@ void Aura::_RemoveAura() // Proc on aura remove (only spell flags for now) if (caster) { - uint32 ProcCaster, ProcVictim; - if (IsPositiveSpell(GetId())) - { - ProcCaster = PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL; - ProcVictim = PROC_FLAG_TAKEN_POSITIVE_SPELL; - } - else - { - ProcCaster = PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT; - ProcVictim = PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT; - } uint32 procEx=0; if (m_removeMode == AURA_REMOVE_BY_ENEMY_SPELL) procEx = PROC_EX_AURA_REMOVE_DESTROY; else if (m_removeMode == AURA_REMOVE_BY_EXPIRE || m_removeMode == AURA_REMOVE_BY_CANCEL) procEx = PROC_EX_AURA_REMOVE_EXPIRE; - else return; - - caster->ProcDamageAndSpell(m_target,ProcCaster, ProcVictim, procEx, m_procDamage, BASE_ATTACK, m_spellProto); + if (procEx) + { + uint32 ProcCaster, ProcVictim; + if (IsPositiveSpell(GetId())) + { + ProcCaster = PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL; + ProcVictim = PROC_FLAG_TAKEN_POSITIVE_SPELL; + } + else + { + ProcCaster = PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT; + ProcVictim = PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT; + } + caster->ProcDamageAndSpell(m_target,ProcCaster, ProcVictim, procEx, m_procDamage, BASE_ATTACK, m_spellProto); + } } } @@ -1208,11 +1207,10 @@ void Aura::SetStackAmount(uint8 stackAmount) // Reapply if amount change if (amount!=part->GetAmount()) { - bool Real = bool (part->m_spellmod); // Auras which are applying spellmod should have removed spellmods for real - part->ApplyModifier(false,Real); + part->ApplyModifier(false,true); part->SetAmount(amount); - part->ApplyModifier(true, Real); + part->ApplyModifier(true,true); } } } @@ -2267,6 +2265,12 @@ void AuraEffect::HandleAuraDummy(bool apply, bool Real) { switch(GetId()) { + // Haunting Spirits - perdiodic trigger demon + case 7057: + m_isPeriodic = true; + m_amplitude = irand (0, 60) + 30; + m_amplitude *= IN_MILISECONDS; + return; case 1515: // Tame beast // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness if( caster && m_target->CanHaveThreatList()) @@ -2425,8 +2429,9 @@ void AuraEffect::HandleAuraDummy(bool apply, bool Real) // Haunt if(m_spellProto->SpellFamilyFlags[1] & 0x40000) { + int32 bp0 = GetParentAura()->GetProcDamage() * m_amount / 100; if(caster) - caster->CastCustomSpell(caster, 48210, &m_currentBasePoints, 0, 0, true); + caster->CastCustomSpell(caster, 48210, &bp0, 0, 0, true, NULL, this); return; } break; @@ -3073,10 +3078,10 @@ void AuraEffect::HandleAuraTransform(bool apply, bool Real) if(GetMiscValue()==0) { // player applied only - if(m_target->GetTypeId()!=TYPEID_PLAYER) + if (m_target->GetTypeId()!=TYPEID_PLAYER) return; - switch(GetId()) + switch (GetId()) { // Orb of Deception case 16739: @@ -3152,16 +3157,19 @@ void AuraEffect::HandleAuraTransform(bool apply, bool Real) if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty()) m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); } - m_target->setTransForm(GetId()); } + // update active transform spell only not set or not overwriting negative by positive case + if (!m_target->getTransForm() || !IsPositiveSpell(GetId()) || IsPositiveSpell(m_target->getTransForm())) + m_target->setTransForm(GetId()); + // polymorph case - if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed()) + if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed()) { // for players, start regeneration after 1s (in polymorph fast regeneration case) // only if caster is Player (after patch 2.4.2) - if(IS_PLAYER_GUID(GetCasterGUID()) ) - ((Player*)m_target)->setRegenTimer(1000); + if (IS_PLAYER_GUID(GetCasterGUID()) ) + ((Player*)m_target)->setRegenTimer(1*IN_MILISECONDS); //dismount polymorphed target (after patch 2.4.2) if (m_target->IsMounted()) @@ -3170,20 +3178,20 @@ void AuraEffect::HandleAuraTransform(bool apply, bool Real) } else { + // ApplyModifier(true) will reapply it if need + m_target->setTransForm(0); + m_target->SetDisplayId(m_target->GetNativeDisplayId()); + + // re-aplly some from still active with preference negative cases Unit::AuraEffectList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM); - if(otherTransforms.empty()) - { - m_target->SetDisplayId(m_target->GetNativeDisplayId()); - m_target->setTransForm(0); - } - else + if (!otherTransforms.empty()) { // look for other transform auras AuraEffect* handledAura = *otherTransforms.begin(); for(Unit::AuraEffectList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i) { // negative auras are preferred - if(!IsPositiveSpell((*i)->GetSpellProto()->Id)) + if (!IsPositiveSpell((*i)->GetSpellProto()->Id)) { handledAura = *i; break; @@ -3193,9 +3201,9 @@ void AuraEffect::HandleAuraTransform(bool apply, bool Real) } // Dragonmaw Illusion (restore mount model) - if(GetId()==42016 && m_target->GetMountID()==16314) + if (GetId()==42016 && m_target->GetMountID()==16314) { - if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty()) + if (!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty()) { uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetMiscValue(); if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id)) @@ -3416,7 +3424,7 @@ void AuraEffect::HandleAuraModScale(bool apply, bool Real) ((Creature*)m_target)->AIM_Initialize(); if (((Creature*)m_target)->AI()) - ((Creature*)m_target)->AI()->AttackStart(caster); + ((Creature*)m_target)->AI()->AttackedBy(caster); } } } @@ -3572,7 +3580,7 @@ void AuraEffect::HandleAuraModPetTalentsPoints(bool Apply, bool Real) { ((Creature*)m_target)->AIM_Initialize(); if (((Creature*)m_target)->AI()) - ((Creature*)m_target)->AI()->AttackStart(caster); + ((Creature*)m_target)->AI()->AttackedBy(caster); } } } @@ -3813,18 +3821,8 @@ void AuraEffect::HandleAuraModSilence(bool apply, bool Real) m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++) - { - Spell* currentSpell = m_target->m_currentSpells[i]; - if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) - { - uint32 state = currentSpell->getState(); - // Stop spells on prepare or casting state - if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING ) - { - currentSpell->cancel(); - } - } - } + if (m_target->m_currentSpells[i] && m_target->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + m_target->InterruptSpell(i,false); // Stop spells on prepare or casting state switch (GetId()) { @@ -6172,6 +6170,18 @@ void AuraEffect::PeriodicTick() m_target->ModifyPower(pt, m_amount*3/5); break; } + case SPELL_AURA_DUMMY: + { + // Haunting Spirits + if (GetId() == 7057) + { + m_target->CastSpell((Unit*)NULL , m_amount , true); + m_amplitude = irand (0 , 60 ) + 30; + m_amplitude *= IN_MILISECONDS; + break; + } + break; + } // Here tick dummy auras case SPELL_AURA_PERIODIC_DUMMY: { diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index fb8120a01e6..bd8e9d00c3b 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -74,6 +74,8 @@ class TRINITY_DLL_SPEC Aura uint8 GetAuraCharges() const { return m_procCharges; } void SetAuraCharges(uint8 charges); bool DropAuraCharge(); + void SetProcDamage(uint32 val) { m_procDamage = val; } + uint32 GetProcDamage() const { return m_procDamage; } int8 GetStackAmount() const {return m_stackAmount;} void SetStackAmount(uint8 num); @@ -92,6 +94,7 @@ class TRINITY_DLL_SPEC Aura void SetNegative() { m_positive = false; } void SetPositive() { m_positive = true; } bool IsPermanent() const { return m_permanent; } + void SetPermanent(bool val) { m_permanent = val; } bool IsPassive() const { return m_isPassive; } bool IsDeathPersistent() const { return m_isDeathPersist; } @@ -159,6 +162,7 @@ class TRINITY_DLL_SPEC Aura bool m_updated:1; // Prevent remove aura by stack if set bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example }; + class TRINITY_DLL_SPEC AuraEffect { public: @@ -333,7 +337,7 @@ class TRINITY_DLL_SPEC AuraEffect uint32 GetEffIndex() const { return m_effIndex; } int32 GetBasePoints() const { return m_currentBasePoints; } int32 GetAuraAmplitude(){return m_amplitude;} - void Update(uint32 diff); + virtual void Update(uint32 diff); bool IsAreaAura() const { return m_isAreaAura; } bool IsPeriodic() const { return m_isPeriodic; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index d01e992ed90..053130fed90 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -448,12 +448,6 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE, m_spellInfo, m_caster)) damage += int32(damage*0.25f); } - // Haunt - else if (m_spellInfo->SpellFamilyFlags[1] & 0x40000) - { - m_currentBasePoints[1] = int32(damage * m_currentBasePoints[1] / 100); - } - // Conflagrate - consumes immolate if (m_spellInfo->TargetAuraState == AURA_STATE_IMMOLATE) { @@ -3358,7 +3352,7 @@ void Spell::EffectDispel(uint32 i) for (uint32 i=urand(0, list_size-1);i>0;--i) itr++; - if (GetDispelChance(this, (*itr)->GetCaster(), (*itr)->GetId())) + if (GetDispelChance((*itr)->GetCaster(), (*itr)->GetId())) { success_list.push_back(*itr); dispel_list.erase(itr); @@ -3489,8 +3483,7 @@ void Spell::EffectPickPocket(uint32 /*i*/) { // Reveal action + get attack m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); - if (((Creature*)unitTarget)->IsAIEnabled) - ((Creature*)unitTarget)->AI()->AttackStart(m_caster); + m_caster->CombatStart(unitTarget); } } } @@ -4132,6 +4125,14 @@ void Spell::SpellDamageWeaponDmg(uint32 i) if(m_caster->GetTypeId()==TYPEID_PLAYER) ((Player*)m_caster)->AddComboPoints(unitTarget, 1); } + // Fan of Knives + else if(m_spellInfo->SpellFamilyFlags[1] & 0x40000) + { + // 50% more damage with daggers + if (Item* item = ((Player*)m_caster)->GetWeaponForAttack(m_attackType)) + if (item->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER) + totalDamagePercentMod *= 1.5f; + } // Mutilate (for each hand) else if(m_spellInfo->SpellFamilyFlags[1] & 0x6) { @@ -4914,8 +4915,6 @@ void Spell::EffectScriptEffect(uint32 effIndex) flag96 familyFlag = aura->GetSpellProto()->SpellFamilyFlags; if (!(familyFlag[1] & 0x00000080 || familyFlag[0] & 0x0000C000)) continue; - // Refresh aura duration - aura->RefreshAura(); // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. if (familyFlag[0] & 0x4000) @@ -4944,9 +4943,13 @@ void Spell::EffectScriptEffect(uint32 effIndex) //{ // spellId = 53366; // 53366 Chimera Shot - Wyvern //} + + // Refresh aura duration + aura->RefreshAura(); + break; } if (spellId) - m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false); + m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, true); return; } default: @@ -5876,13 +5879,19 @@ void Spell::EffectDispelMechanic(uint32 i) Unit::AuraMap& Auras = unitTarget->GetAuras(); for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); iter++) + { if(GetAllSpellMechanicMask(iter->second->GetSpellProto()) & (1<<(mechanic))) + { dispel_list.push(iter->second); + } + } for(;dispel_list.size();dispel_list.pop()) { - if (GetDispelChance(this, dispel_list.front()->GetCaster(), dispel_list.front()->GetId())) - unitTarget->RemoveAura(dispel_list.front()->GetId(), dispel_list.front()->GetCasterGUID()); + if (GetDispelChance(dispel_list.front()->GetCaster(), dispel_list.front()->GetId())) + { + unitTarget->RemoveAura(dispel_list.front(), AURA_REMOVE_BY_ENEMY_SPELL); + } } } diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 0efc4cb0ee4..19a33dff75a 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -380,15 +380,11 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) return; // channeled spell case (it currently casted then) - if(IsChanneledSpell(spellInfo)) + if (IsChanneledSpell(spellInfo)) { - if(Spell* spell = _player->m_currentSpells[CURRENT_CHANNELED_SPELL]) - { - if(spell->m_spellInfo->Id==spellId) - { - spell->cancel(); - } - } + if (_player->m_currentSpells[CURRENT_CHANNELED_SPELL] && + _player->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spellId) + _player->InterruptSpell(CURRENT_CHANNELED_SPELL); return; } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7134dbb4dba..af8a04740f8 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -230,7 +230,7 @@ int32 GetSpellMaxDuration(SpellEntry const *spellInfo) return (du->Duration[2] == -1) ? -1 : abs(du->Duration[2]); } -bool GetDispelChance(Spell* spell, Unit* caster, uint32 spellId) +bool GetDispelChance(Unit* caster, uint32 spellId) { // we assume that aura dispel chance is 100% on start // need formula for level difference based chance @@ -239,7 +239,7 @@ bool GetDispelChance(Spell* spell, Unit* caster, uint32 spellId) if (caster) { if ( Player* modOwner = caster->GetSpellModOwner() ) - modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, spell); + modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance); } // Try dispel return !roll_chance_i(miss_chance); @@ -676,7 +676,23 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex, bool deep) { case SPELLMOD_COST: // dependent from bas point sign (negative -> positive) if(spellproto->CalculateSimpleValue(effIndex) > 0) - return false; + { + if (!deep) + { + bool negative = true; + for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i) + { + if (i != effIndex) + if (IsPositiveEffect(spellId, i, true)) + { + negative = false; + break; + } + } + if (negative) + return false; + } + } break; default: break; @@ -1158,7 +1174,7 @@ void SpellMgr::LoadSpellBonusess() sLog.outString( ">> Loaded %u extra spell bonus data", count); } -bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active) +bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active) { // No extra req need uint32 procEvent_procEx = PROC_EX_NONE; @@ -1195,7 +1211,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP // spellFamilyName is Ok need check for spellFamilyMask if present if(spellProcEvent->spellFamilyMask) { - if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0) + if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0) return false; active = true; // Spell added manualy -> so its active spell } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 5c55d9b93a2..41a6cf41cf3 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -152,7 +152,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId); inline float GetSpellRadiusForHostile(SpellRadiusEntry const *radius) { return (radius ? radius->radiusHostile : 0); } inline float GetSpellRadiusForFriend(SpellRadiusEntry const *radius) { return (radius ? radius->radiusFriend : 0); } uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell = NULL); -bool GetDispelChance(Spell* spell, Unit* caster, uint32 spellId); +bool GetDispelChance(Unit* caster, uint32 spellId); inline float GetSpellMinRangeForHostile(SpellRangeEntry const *range) { return (range ? range->minRangeHostile : 0); } inline float GetSpellMaxRangeForHostile(SpellRangeEntry const *range) { return (range ? range->maxRangeHostile : 0); } inline float GetSpellMinRangeForFriend(SpellRangeEntry const *range) { return (range ? range->minRangeFriend : 0); } @@ -715,7 +715,7 @@ class SpellMgr return NULL; } - static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active); + bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active); // Spell bonus data SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 3a95be1c3ef..f9d237b9d5e 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -697,21 +697,11 @@ void Player::UpdateManaRegen() power_regen_mp5 += GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 500.0f; } - // Bonus from some dummy auras - AuraEffectList const& mDummyAuras = GetAurasByType(SPELL_AURA_PERIODIC_DUMMY); - for(AuraEffectList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) - if((*i)->GetId() == 34074) // Aspect of the Viper - { - power_regen_mp5 += (*i)->GetAmount() * Intellect / 500.0f; - // Add regen bonus from level in this dummy - power_regen_mp5 += getLevel() * 35 / 100; - } - // Set regen rate in cast state apply only on spirit based regen int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); if (modManaRegenInterrupt > 100) modManaRegenInterrupt = 100; - SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); + SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, (power_regen_mp5 + power_regen) * modManaRegenInterrupt / 100.0f); SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, power_regen_mp5 + power_regen); } diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp index acf0dbc78ba..c87ad91ff90 100644 --- a/src/game/TemporarySummon.cpp +++ b/src/game/TemporarySummon.cpp @@ -176,10 +176,22 @@ void TempSummon::InitSummon(uint32 duration) if(m_type == TEMPSUMMON_MANUAL_DESPAWN) m_type = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; + Unit* owner = GetSummoner(); + if(owner) + { + if(owner->GetTypeId()==TYPEID_UNIT && ((Creature*)owner)->IsAIEnabled) + ((Creature*)owner)->AI()->JustSummoned(this); + + if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER && m_spells[0]) + { + setFaction(owner->getFaction()); + CastSpell(this, m_spells[0], false, 0, 0, m_summonerGUID); + } + } + if(!m_Properties) return; - Unit* owner = GetSummoner(); if(uint32 slot = m_Properties->Slot) { if(owner) @@ -194,18 +206,6 @@ void TempSummon::InitSummon(uint32 duration) } } - if(owner) - { - if(owner->GetTypeId()==TYPEID_UNIT && ((Creature*)owner)->IsAIEnabled) - ((Creature*)owner)->AI()->JustSummoned(this); - - if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER && m_spells[0]) - { - setFaction(owner->getFaction()); - CastSpell(this, m_spells[0], false, 0, 0, m_summonerGUID); - } - } - if(m_Properties->Faction) setFaction(m_Properties->Faction); } diff --git a/src/game/TicketHandler.cpp b/src/game/TicketHandler.cpp index ff920cab04b..f4af95bb169 100644 --- a/src/game/TicketHandler.cpp +++ b/src/game/TicketHandler.cpp @@ -60,6 +60,11 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data ) ticket->guid = ticketmgr.GenerateTicketID(); ticket->playerGuid = GetPlayer()->GetGUID(); ticket->message = ticketText; + ticket->createtime = time(NULL); + ticket->map = map; + ticket->pos_x = x; + ticket->pos_y = y; + ticket->pos_z = z; ticket->timestamp = time(NULL); ticket->closed = 0; ticket->assignedToGM = 0; @@ -188,4 +193,3 @@ void WorldSession::HandleGMTicketSystemStatusOpcode( WorldPacket & /*recv_data*/ // Send Packet SendPacket(&data); } - diff --git a/src/game/TicketMgr.cpp b/src/game/TicketMgr.cpp index 82079105aef..7335b3a3067 100644 --- a/src/game/TicketMgr.cpp +++ b/src/game/TicketMgr.cpp @@ -92,13 +92,9 @@ void TicketMgr::DeleteGMTicketPermanently(uint64 ticketGuid) for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();) { if((*i)->guid == ticketGuid) - { i = GM_TicketList.erase(i); - } else - { ++i; - } } // delete database record @@ -108,10 +104,9 @@ void TicketMgr::DeleteGMTicketPermanently(uint64 ticketGuid) void TicketMgr::LoadGMTickets() { - InitTicketID(); // Delete all out of object holder GM_TicketList.clear(); - QueryResult *result = CharacterDatabase.Query( "SELECT `guid`, `playerGuid`, `name`, `message`, `timestamp`, `closed`, `assignedto`, `comment` FROM `gm_tickets`" ); + QueryResult *result = CharacterDatabase.Query( "SELECT `guid`, `playerGuid`, `name`, `message`, `createtime`, `map`, `posX`, `posY`, `posZ`, `timestamp`, `closed`, `assignedto`, `comment` FROM `gm_tickets`" ); GM_Ticket *ticket; if(!result) @@ -126,10 +121,14 @@ void TicketMgr::LoadGMTickets() ticket->playerGuid = fields[1].GetUInt64(); ticket->name = fields[2].GetString(); ticket->message = fields[3].GetString(); - ticket->timestamp = fields[4].GetUInt32(); - ticket->closed = fields[5].GetUInt16(); - ticket->assignedToGM = fields[6].GetUInt64(); - ticket->comment = fields[7].GetString(); + ticket->createtime = fields[4].GetUInt64(); + ticket->pos_x = fields[5].GetFloat(); + ticket->pos_y = fields[6].GetFloat(); + ticket->pos_z = fields[7].GetFloat(); + ticket->timestamp = fields[8].GetUInt64(); + ticket->closed = fields[9].GetUInt64(); + ticket->assignedToGM = fields[10].GetUInt64(); + ticket->comment = fields[11].GetString(); AddGMTicket(ticket, true); @@ -172,11 +171,16 @@ void TicketMgr::SaveGMTicket(GM_Ticket* ticket) std::string msg = ticket->message; CharacterDatabase.escape_string(msg); std::stringstream ss; - ss << "REPLACE INTO `gm_tickets` (`guid`, `playerGuid`, `name`, `message`, `timestamp`, `closed`, `assignedto`, `comment`) VALUES('"; + ss << "REPLACE INTO `gm_tickets` (`guid`, `playerGuid`, `name`, `message`, `createtime`, `map`, `posX`, `posY`, `posZ`, `timestamp`, `closed`, `assignedto`, `comment`) VALUES('"; ss << ticket->guid << "', '"; ss << ticket->playerGuid << "', '"; ss << ticket->name << "', '"; ss << msg << "', '" ; + ss << ticket->createtime << "', '"; + ss << ticket->map << "', '"; + ss << ticket->pos_x << "', '"; + ss << ticket->pos_y << "', '"; + ss << ticket->pos_z << "', '"; ss << ticket->timestamp << "', '"; ss << ticket->closed << "', '"; ss << ticket->assignedToGM << "', '"; diff --git a/src/game/TicketMgr.h b/src/game/TicketMgr.h index a180268a552..491e6657f40 100644 --- a/src/game/TicketMgr.h +++ b/src/game/TicketMgr.h @@ -32,9 +32,14 @@ struct GM_Ticket uint64 guid; uint64 playerGuid; std::string name; + float pos_x; + float pos_y; + float pos_z; + uint32 map; std::string message; + uint64 createtime; uint64 timestamp; - uint16 closed; + uint64 closed; uint64 assignedToGM; std::string comment; }; @@ -45,7 +50,7 @@ typedef std::list<GM_Ticket*> GmTicketList class TicketMgr { public: - TicketMgr(){m_ticketid = 1;} //constructor + TicketMgr(){ InitTicketID();} //constructor ~TicketMgr(){} //destructor // Object Holder diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp index cc32d40fdae..4efced3bc3a 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -38,8 +38,9 @@ TotemAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -TotemAI::TotemAI(Creature *c) : CreatureAI(c), i_totem(static_cast<Totem&>(*c)), i_victimGuid(0) +TotemAI::TotemAI(Creature *c) : CreatureAI(c), i_victimGuid(0) { + assert(c->isTotem()); } void @@ -49,20 +50,20 @@ TotemAI::MoveInLineOfSight(Unit *) void TotemAI::EnterEvadeMode() { - i_totem.CombatStop(); + m_creature->CombatStop(); } void TotemAI::UpdateAI(const uint32 /*diff*/) { - if (i_totem.GetTotemType() != TOTEM_ACTIVE) + if (((Totem*)m_creature)->GetTotemType() != TOTEM_ACTIVE) return; - if (!i_totem.isAlive() || i_totem.IsNonMeleeSpellCasted(false)) + if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false)) return; // Search spell - SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_totem.GetSpell()); + SpellEntry const *spellInfo = sSpellStore.LookupEntry(((Totem*)m_creature)->GetSpell()); if (!spellInfo) return; @@ -73,17 +74,17 @@ TotemAI::UpdateAI(const uint32 /*diff*/) // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // pointer to appropriate target if found any - Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(i_totem, i_victimGuid) : NULL; + Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*m_creature, i_victimGuid) : NULL; // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if( !victim || - !victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) || - i_totem.IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(&i_totem,false) ) + !victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) || + m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,false) ) { victim = NULL; - Trinity::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range); - Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(&i_totem, victim, u_check); - i_totem.VisitNearbyObject(max_range, checker); + Trinity::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range); + Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(m_creature, victim, u_check); + m_creature->VisitNearbyObject(max_range, checker); } // If have target @@ -93,30 +94,23 @@ TotemAI::UpdateAI(const uint32 /*diff*/) i_victimGuid = victim->GetGUID(); // attack - i_totem.SetInFront(victim); // client change orientation by self - i_totem.CastSpell(victim, i_totem.GetSpell(), false); + m_creature->SetInFront(victim); // client change orientation by self + m_creature->CastSpell(victim, ((Totem*)m_creature)->GetSpell(), false); } else i_victimGuid = 0; } -bool -TotemAI::IsVisible(Unit *) const -{ - return false; -} - void TotemAI::AttackStart(Unit *) { // Sentry totem sends ping on attack - if (i_totem.GetEntry() == SENTRY_TOTEM_ENTRY && i_totem.GetOwner()->GetTypeId() == TYPEID_PLAYER) + if (m_creature->GetEntry() == SENTRY_TOTEM_ENTRY && m_creature->GetOwner()->GetTypeId() == TYPEID_PLAYER) { WorldPacket data(MSG_MINIMAP_PING, (8+4+4)); - data << i_totem.GetGUID(); - data << i_totem.GetPositionX(); - data << i_totem.GetPositionY(); - ((Player*)i_totem.GetOwner())->GetSession()->SendPacket(&data); + data << m_creature->GetGUID(); + data << m_creature->GetPositionX(); + data << m_creature->GetPositionY(); + ((Player*)m_creature->GetOwner())->GetSession()->SendPacket(&data); } } - diff --git a/src/game/TotemAI.h b/src/game/TotemAI.h index 9a19d2c99e5..003f5d5ca13 100644 --- a/src/game/TotemAI.h +++ b/src/game/TotemAI.h @@ -31,18 +31,16 @@ class TRINITY_DLL_DECL TotemAI : public CreatureAI { public: - TotemAI(Creature *c); + explicit TotemAI(Creature *c); void MoveInLineOfSight(Unit *); void AttackStart(Unit *); void EnterEvadeMode(); - bool IsVisible(Unit *) const; void UpdateAI(const uint32); static int Permissible(const Creature *); private: - Totem &i_totem; uint64 i_victimGuid; }; #endif diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f41637b6c75..1e403577dbd 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -574,30 +574,27 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa return 0; } - if(pVictim->GetTypeId() != TYPEID_PLAYER) + // no xp,health if type 8 /critters/ + if(pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) { - // no xp,health if type 8 /critters/ - if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) + // allow loot only if has loot_id in creature_template + if(damage >= pVictim->GetHealth()) { - // allow loot only if has loot_id in creature_template - if(damage >= pVictim->GetHealth()) - { - pVictim->setDeathState(JUST_DIED); - pVictim->SetHealth(0); + pVictim->setDeathState(JUST_DIED); + pVictim->SetHealth(0); - CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo(); - if(cInfo && cInfo->lootid) - pVictim->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo(); + if(cInfo && cInfo->lootid) + pVictim->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - // some critters required for quests - if(GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); - } - else - pVictim->ModifyHealth(- (int32)damage); - - return damage; + // some critters required for quests + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); } + else + pVictim->ModifyHealth(- (int32)damage); + + return damage; } DEBUG_LOG("DealDamageStart"); @@ -835,22 +832,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa pVictim->ModifyHealth(- (int32)damage); - if(damagetype != DOT) - { - if(!getVictim()) - /*{ - // if have target and damage pVictim just call AI reaction - if(pVictim != getVictim() && pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsAIEnabled) - ((Creature*)pVictim)->AI()->AttackedBy(this); - } - else*/ - { - // if not have main target then attack state with target (including AI call) - //start melee attacks only after melee hit - Attack(pVictim,(damagetype == DIRECT_DAMAGE)); - } - } - if(damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE) { //TODO: This is from procflag, I do not know which spell needs this @@ -2268,6 +2249,10 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex } } + // if damage pVictim call AI reaction + //if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) + // ((Creature*)pVictim)->AI()->AttackedBy(this); + return; } @@ -2295,6 +2280,10 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex --m_extraAttacks; } } + + // if damage pVictim call AI reaction + //if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) + // ((Creature*)pVictim)->AI()->AttackedBy(this); } MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const @@ -3300,7 +3289,7 @@ void Unit::_UpdateSpells( uint32 time ) if(!m_gameObj.empty()) { - std::list<GameObject*>::iterator ite1, dnext1; + GameObjectList::iterator ite1, dnext1; for (ite1 = m_gameObj.begin(); ite1 != m_gameObj.end(); ite1 = dnext1) { dnext1 = ite1; @@ -3477,40 +3466,16 @@ bool Unit::IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled, bool skip void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) { // generic spells are interrupted if they are not finished or delayed - Spell *spell = m_currentSpells[CURRENT_GENERIC_SPELL]; - if (spell && (!spell_id || spell->m_spellInfo->Id==spell_id)) - { - m_currentSpells[CURRENT_GENERIC_SPELL] = NULL; - - if ( (spell->getState() != SPELL_STATE_FINISHED) && - (withDelayed || spell->getState() != SPELL_STATE_DELAYED) ) - spell->cancel(); - spell->SetReferencedFromCurrent(false); - } + if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id==spell_id)) + InterruptSpell(CURRENT_GENERIC_SPELL,withDelayed); - spell = m_currentSpells[CURRENT_AUTOREPEAT_SPELL]; // autorepeat spells are interrupted if they are not finished or delayed - if (spell && (!spell_id || spell->m_spellInfo->Id==spell_id)) - { - m_currentSpells[CURRENT_AUTOREPEAT_SPELL] = NULL; - // send disable autorepeat packet in any case - if(GetTypeId()==TYPEID_PLAYER) - ((Player*)this)->SendAutoRepeatCancel(); - if ( (spell->getState() != SPELL_STATE_FINISHED) && - (withDelayed || spell->getState() != SPELL_STATE_DELAYED) ) - spell->cancel(); - spell->SetReferencedFromCurrent(false); - } + if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id==spell_id)) + InterruptSpell(CURRENT_AUTOREPEAT_SPELL,withDelayed); // channeled spells are interrupted if they are not finished, even if they are delayed - spell = m_currentSpells[CURRENT_CHANNELED_SPELL]; - if (spell && (!spell_id || spell->m_spellInfo->Id==spell_id)) - { - m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL; - if (spell->getState() != SPELL_STATE_FINISHED) - spell->cancel(); - spell->SetReferencedFromCurrent(false); - } + if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spell_id)) + InterruptSpell(CURRENT_CHANNELED_SPELL,true); } Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const @@ -3763,7 +3728,7 @@ bool Unit::AddAura(Aura *Aur) else foundAura->RefreshAura(); delete Aur; - return true; + return false; } } @@ -4075,7 +4040,7 @@ void Unit::RemoveAurasByTypeWithDispel(AuraType auraType, Spell * spell) { Aura * aur = (*iter)->GetParentAura(); ++iter; - if (GetDispelChance(spell, aur->GetCaster(), aur->GetId())) + if (GetDispelChance(aur->GetCaster(), aur->GetId())) { uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur, AURA_REMOVE_BY_ENEMY_SPELL); @@ -4375,6 +4340,15 @@ DynamicObject * Unit::GetDynObject(uint32 spellId) return NULL; } +GameObject* Unit::GetGameObject(uint32 spellId) const +{ + for (GameObjectList::const_iterator i = m_gameObj.begin(); i != m_gameObj.end();) + if ((*i)->GetSpellId() == spellId) + return *i; + + return NULL; +} + void Unit::AddGameObject(GameObject* gameObj) { assert(gameObj && gameObj->GetOwnerGUID()==0); @@ -4425,7 +4399,7 @@ void Unit::RemoveGameObject(uint32 spellid, bool del) { if(m_gameObj.empty()) return; - std::list<GameObject*>::iterator i, next; + GameObjectList::iterator i, next; for (i = m_gameObj.begin(); i != m_gameObj.end(); i = next) { next = i; @@ -4448,7 +4422,7 @@ void Unit::RemoveGameObject(uint32 spellid, bool del) void Unit::RemoveAllGameObjects() { // remove references to unit - for(std::list<GameObject*>::iterator i = m_gameObj.begin(); i != m_gameObj.end();) + for(GameObjectList::iterator i = m_gameObj.begin(); i != m_gameObj.end();) { (*i)->SetOwnerGUID(0); (*i)->SetRespawnTime(0); @@ -5197,7 +5171,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger if (dummySpell->SpellIconID == 2999) { if (effIndex!=0) - return true; + return false; AuraEffect *counter = GetAuraEffect(triggeredByAura->GetId(), 1); if (!counter) return true; @@ -5699,7 +5673,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger return false; // Only 0 aura can proc if (effIndex!=0) - return true; + return false; // Wrath crit if (procSpell->SpellFamilyFlags[0] & 0x1) { @@ -5827,8 +5801,10 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger case SPELLFAMILY_PALADIN: { // Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage) - if (dummySpell->SpellFamilyFlags[0]&0x8000000 && effIndex==0) + if (dummySpell->SpellFamilyFlags[0]&0x8000000) { + if (effIndex!=0) + return false; triggered_spell_id = 25742; float ap = GetTotalAttackPowerValue(BASE_ATTACK); int32 holy = SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) + @@ -7830,9 +7806,6 @@ bool Unit::Attack(Unit *victim, bool meleeAttack) //if(GetTypeId()==TYPEID_UNIT) // ((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ()); - //if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->IsAIEnabled) - // ((Creature*)m_attacking)->AI()->AttackedBy(this); - if(GetTypeId()==TYPEID_UNIT) { // should not let player enter combat by right clicking target @@ -9044,10 +9017,11 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint break; } } - coeff = (CastingTime / 3500.0f) * DotFactor; + // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells) + coeff = (CastingTime / 3500.0f) * DotFactor * 1.88f; } - float coeff2 = CalculateLevelPenalty(spellProto) * 1.88f * stack; + float coeff2 = CalculateLevelPenalty(spellProto)* stack; TakenTotal += TakenAdvertisedBenefit * coeff * coeff2; if(Player* modOwner = GetSpellModOwner()) { @@ -9070,7 +9044,7 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint // Rejuvenation, Regrowth, Lifebloom, or Wild Growth if (pVictim->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x50, 0x4000010, 0)) //increase healing by 20% - DoneTotalMod *= 1.2f; + TakenTotalMod *= 1.2f; } // Taken mods @@ -9096,11 +9070,11 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint if(damagetype==DOT) { // Healing over time taken percent - float minval_hot = GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT); + float minval_hot = pVictim->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT); if(minval_hot) TakenTotalMod *= (100.0f + minval_hot) / 100.0f; - float maxval_hot = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT); + float maxval_hot = pVictim->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT); if(maxval_hot) TakenTotalMod *= (100.0f + maxval_hot) / 100.0f; } @@ -11555,6 +11529,8 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag if (GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown) cooldown = i->spellProcEvent->cooldown; + uint32 procDebug = 0; + for (uint8 effIndex = 0; effIndex<MAX_SPELL_EFFECTS;++effIndex) { if (!(i->effMask & (1<<effIndex))) @@ -11589,18 +11565,27 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); if (!HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) continue; + if (procDebug & 1) + sLog.outError("Dummy aura of spell %d procs twice from one effect!",spellInfo->Id); + procDebug |= 1; break; } case SPELL_AURA_OBS_MOD_ENERGY: sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); if (!HandleObsModEnergyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) continue; + if (procDebug & 2) + sLog.outError("ObsModEnergy aura of spell %d procs twice from one effect!",spellInfo->Id); + procDebug |= 2; break; case SPELL_AURA_MOD_HASTE: { sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); if (!HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) continue; + if (procDebug & 4) + sLog.outError("Haste aura of spell %d procs twice from one effect!",spellInfo->Id); + procDebug |= 4; break; } case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: @@ -11608,6 +11593,9 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); if (!HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown)) continue; + if (procDebug & 8) + sLog.outError("OverrideClassScripts aura of spell %d procs twice from one effect!",spellInfo->Id); + procDebug |= 8; break; } case SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE: @@ -11834,8 +11822,8 @@ void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID) // attack caster if can Unit* caster = ObjectAccessor::GetObjectInWorld(casterGUID, (Unit*)NULL); - if(caster && caster != getVictim() && ((Creature*)this)->IsAIEnabled) - ((Creature*)this)->AI()->AttackStart(caster); + if(caster && ((Creature*)this)->AI()) + ((Creature*)this)->AI()->AttackedBy(caster); } } @@ -12297,7 +12285,7 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) return pet; } -bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura * aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ) +bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura * aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const *& spellProcEvent ) { SpellEntry const* spellProto = aura->GetSpellProto (); @@ -12315,7 +12303,7 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura * aura, SpellEntry co return false; // Check spellProcEvent data requirements - if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active)) + if(!spellmgr.IsSpellProcEventCanTriggeredBy(spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active)) return false; // In most cases req get honor or XP from kill @@ -12500,6 +12488,9 @@ void Unit::SetToNotify() void Unit::Kill(Unit *pVictim, bool durabilityLoss) { + // Prevent killing unit twice (and giving reward from kill twice) + if (!pVictim->isAlive()) + return; pVictim->SetHealth(0); // find player: owner of controlled `this` or `this` itself maybe diff --git a/src/game/Unit.h b/src/game/Unit.h index ace61563c0f..3e7a93bad1f 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1430,16 +1430,20 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); } void setTransForm(uint32 spellid) { m_transform = spellid;} uint32 getTransForm() const { return m_transform;} + + DynamicObject* GetDynObject(uint32 spellId, uint32 effIndex); + DynamicObject* GetDynObject(uint32 spellId); void AddDynObject(DynamicObject* dynObj); void RemoveDynObject(uint32 spellid); void RemoveDynObjectWithGUID(uint64 guid) { m_dynObjGUIDs.remove(guid); } void RemoveAllDynObjects(); + + GameObject* GetGameObject(uint32 spellId) const; void AddGameObject(GameObject* gameObj); void RemoveGameObject(GameObject* gameObj, bool del); void RemoveGameObject(uint32 spellid, bool del); void RemoveAllGameObjects(); - DynamicObject *GetDynObject(uint32 spellId, uint32 effIndex); - DynamicObject *GetDynObject(uint32 spellId); + uint32 CalculateDamage(WeaponAttackType attType, bool normalized); float GetAPMultiplier(WeaponAttackType attType, bool normalized); void ModifyAuraState(AuraState flag, bool apply); @@ -1582,7 +1586,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject typedef std::list<uint64> DynObjectGUIDs; DynObjectGUIDs m_dynObjGUIDs; - std::list<GameObject*> m_gameObj; + typedef std::list<GameObject*> GameObjectList; + GameObjectList m_gameObj; bool m_isSorted; uint32 m_transform; @@ -1618,7 +1623,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void SendAttackStop(Unit* victim); // only from AttackStop(Unit*) //void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*) - bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ); + bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const * procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const *& spellProcEvent ); bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleObsModEnergyAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); diff --git a/src/game/World.cpp b/src/game/World.cpp index ef1935f84a7..d9a22a4a4a2 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1546,6 +1546,7 @@ void World::SetInitialWorldSettings() } else { + sLog.SetLogDB(false); sLog.SetLogDBLater(false); } diff --git a/src/trinitycore/Master.cpp b/src/trinitycore/Master.cpp index 62446c4106c..a478f18daa9 100644 --- a/src/trinitycore/Master.cpp +++ b/src/trinitycore/Master.cpp @@ -464,8 +464,14 @@ bool Master::_StartDB() { // everything successful - set var to enable DB logging once startup finished. sLog.SetLogDBLater(true); + sLog.SetLogDB(false); sLog.SetRealmID(realmID); } + else + { + sLog.SetLogDBLater(false); + sLog.SetLogDB(false); + } ///- Clean the database before starting clearOnlineAccounts(); diff --git a/src/trinityrealm/Main.cpp b/src/trinityrealm/Main.cpp index bd318779f83..65596e35b21 100644 --- a/src/trinityrealm/Main.cpp +++ b/src/trinityrealm/Main.cpp @@ -187,6 +187,7 @@ extern int main(int argc, char **argv) { // everything successful - set var to enable DB logging once startup finished. sLog.SetLogDBLater(true); + sLog.SetLogDB(false); // ensure we've set realm to 0 (realmd realmid) sLog.SetRealmID(0); } @@ -271,6 +272,11 @@ extern int main(int argc, char **argv) // login db needs thread for logging sLog.SetLogDB(true); } + else + { + sLog.SetLogDB(false); + sLog.SetLogDBLater(false); + } ///- Wait for termination signal while (!stopEvent) |