Index: scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp =================================================================== --- scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp (revision 315) +++ scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp (working copy) @@ -26,6 +26,9 @@ #define SPELL_WHIRLWIND 40653 #define SPELL_CHAOS_BLAST 37675 // #define SPELL_INSIDIOUS_WHISPER 37676 // useless - dummy effect that can't be implemented +#define SPELL_WIPEWHIRLWIND 37641 +#define INNER_DEMON_ID 21857 // Temporary summon 5 demons in random players with aura +#define INNER_DEMON_AURA 37713 // Demonic Alignment aura #define SAY_AGGRO "Finally my banishment ends!" #define SAY_SWITCH_TO_DEMON "Be gone trifling elf. I'm in control now." @@ -58,6 +61,26 @@ #define DEMON_FORM 21845 +// BANISH PHASE +#define GREEN_BEAM 38909 +#define BANISH_EFFECT 37833 + +float add1SPlace[4] = +{ + 364.219208, -448.394073, 29.515247, 0.170111 +}; + +float add2SPlace[4] = +{ + 375.948334, -426.4744335, 29.524292, 4.982298 +}; + +float add3SPlace[4] = +{ + 396.755188, -433.087402, 30.189342, 3.782232 +}; + + //Original Leotheras the Blind AI struct MANGOS_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI { @@ -65,33 +88,68 @@ { pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; Demon = 0; + initialize(); EnterEvadeMode(); } + Creature *add1; + Creature *add2; + Creature *add3; + ScriptedInstance *pInstance; uint32 Whirlwind_Timer; uint32 ChaosBlast_Timer; uint32 Switch_Timer; + uint32 Wipe_Timer; + uint32 Wipe_Whirlwind_Timer; bool DemonForm; bool IsFinalForm; bool InCombat; + + bool spawned; + bool relased; + bool channeling[3]; + bool add1Dead; + bool add2Dead; + bool add3Dead; + uint64 Demon; + + + void initialize() + { + relased = false; + spawned = false; + relased = false; + for(uint8 i = 0; i < 3; ++i) + channeling[i] = false; + add1Dead = false; + add2Dead = false; + add3Dead = false; + + add1 = NULL; + add2 = NULL; + add3 = NULL; + } + void Reset() { - Whirlwind_Timer = 20000; + Whirlwind_Timer = 20000; ChaosBlast_Timer = 1000; Switch_Timer = 45000; + Wipe_Timer = 600000; + Wipe_Whirlwind_Timer = 15000; DemonForm = false; IsFinalForm = false; InCombat = false; - + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); - + //m_creature->RemoveAllAuras(); //m_creature->DeleteThreatList(); //m_creature->CombatStop(); @@ -105,6 +163,11 @@ void StartEvent() { + if(!relased) + { + m_creature->CombatStop(); + return; + } DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_AGGRO); @@ -174,6 +237,9 @@ if(pInstance) pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, 0); + + // ustawia wskazniki add1,add2,add3 na NULl, spawned = false itd. (bez tego po respawnie nie było by addów) + initialize(); } void AttackStart(Unit *who) @@ -185,7 +251,7 @@ { //Begin melee attack if we are within range DoStartMeleeAttack(who); - + if(!InCombat) StartEvent(); } @@ -211,9 +277,10 @@ } } } - +// VICTIMSTATE_DODGE void UpdateAI(const uint32 diff) { + banishPhase(); //Return since we have no target if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) return; @@ -237,6 +304,13 @@ DoPlaySoundToSet(m_creature, SOUND_SWITCH_TO_DEMON); DemonForm = true; + Unit* Spawn = NULL; + Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); + Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); + Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); + Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); + Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); + Switch_Timer = 60000; }else Switch_Timer -= diff; @@ -260,8 +334,25 @@ Switch_Timer = 45000; }else Switch_Timer -= diff; - } + //WIPE after 10 minutes + if(Wipe_Timer < diff) + { + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg * 10)); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg * 10)); + m_c reature->UpdateDamagePhysical(BASE_ATTACK); + Wipe_Timer = 60000; + if(Wipe_Whirlwind_Timer < diff) + { + DoCast(m_creature, SPELL_WIPEWHIRLWIND); + Wipe_Whirlwind_Timer = 20000; + ResetThreat(); + }else Wipe_Whirlwind_Timer -=diff; + }else Wipe_Timer -=diff; + + } + if(!IsFinalForm && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 15) { //at this point he divides himself in two parts @@ -284,6 +375,154 @@ m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); } } + + void ResetThreat() + { + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list::iterator i = m_threatlist.begin(); + for(i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + { + Unit* pUnit = NULL; + pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit) + { + m_creature->getThreatManager().modifyThreatPercent(pUnit, -100); + } + } + } + + void banishPhase() + { + // Banish Phase by Krz (just educational code ^_^) + // ---------- BANISH PHASE START ---------- + if(!spawned) + { + m_creature->ApplySpellImmune(BANISH_EFFECT,IMMUNITY_MECHANIC,MECHANIC_BANISH,false); // żeby mógł rzucić banisha - Ustawione na true podczas relase + add1 = m_creature->SummonCreature(21806, add1SPlace[0], add1SPlace[1],add1SPlace[2],add1SPlace[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,1000); + add2 = m_creature->SummonCreature(21806, add2SPlace[0], add2SPlace[1],add2SPlace[2],add2SPlace[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,1000); + add3 = m_creature->SummonCreature(21806, add3SPlace[0], add3SPlace[1],add3SPlace[2],add3SPlace[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,1000); + + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON); // DemonModel - Blizzlike banishment + DoCast(m_creature, BANISH_EFFECT); // selfCast banisha + spawned = true; + } + + // Zacznš castować tylko gdy nie sš w combacie (jak wejdš w combat to channeling[] = false, żeby w razie gdy zabijš cel to powrócš i znów wycastujš ten channeling spell + if(!add1 == NULL) + { + // odwróci je w stronę blinda - Visual bug... trzeba się odsunšc i wrócić, to wtedy będš odwrócone -_- + if(add1->GetPositionX() == add1SPlace[0] && + add1->GetPositionY() == add1SPlace[1] && + add1->GetPositionZ() == add1SPlace[2] && + add1->GetOrientation() != add1SPlace[3] ) + add1->SetOrientation(add1SPlace[3]); + + /* Unit *target = add1->getVictim(); + if(target) <- test, żeby addy castowały shocka tylko jak cel castuje ( pozniej przerobie na random.target@threatlist ale chcialem sprawdzic czy zadziala wykrywanie casta + if(target->m_currentSpells[3] || target->m_currentSpells[2] || target->m_currentSpells[1])//->getState() == 2 && target)//->getState() == 2 && target) + add1->CastSpell(add1->getVictim(), 39076, false); +*/ + + if(!channeling[0] && !add1->isInCombat()) + { + add1->CastSpell(m_creature,GREEN_BEAM,false); + channeling[0] = true; + } + if(add1->isInCombat() && channeling[0] == true) + { + channeling[0] = false; + add1->InterruptSpell(CURRENT_CHANNELED_SPELL, true); + + if(!add2 == NULL) + if(!add2->isInCombat()) + add2->getThreatManager().addThreat(add1->getVictim(),1); + if(!add3 == NULL) + if(!add3->isInCombat()) + add3->getThreatManager().addThreat(add1->getVictim(),1); + } + if(add1->GetHealth() == 0) + { + add1Dead = true; + add1 = NULL; + } + } + if(!add2 == NULL) + { + if(add2->GetPositionX() == add2SPlace[0] && + add2->GetPositionY() == add2SPlace[1] && + add2->GetPositionZ() == add2SPlace[2] && + add2->GetOrientation() != add2SPlace[3] ) + add2->SetOrientation(add2SPlace[3]); + + if(!channeling[1] && !add2->isInCombat()) + { + add2->CastSpell(m_creature,GREEN_BEAM,false); + channeling[1] = true; + } + if(add2->isInCombat() && channeling[1] == true) + { + channeling[1] = false; + add2->InterruptSpell(CURRENT_CHANNELED_SPELL, true); + + if(!add1 == NULL) + if(!add1->isInCombat()) + add1->getThreatManager().addThreat(add2->getVictim(),1); + if(!add3 == NULL) + if(!add3->isInCombat()) + add3->getThreatManager().addThreat(add2->getVictim(),1); + } + if(add2->GetHealth() == 0) + { + add2Dead = true; + add2 = NULL; + } + } + if(!add3 == NULL) + { + if(add3->GetPositionX() == add3SPlace[0] && + add3->GetPositionY() == add3SPlace[1] && + add3->GetPositionZ() == add3SPlace[2] && + add3->GetOrientation() != add3SPlace[3] ) + add3->SetOrientation(add3SPlace[3]); + + if(!channeling[2] && !add3->isInCombat()) + { + add3->CastSpell(m_creature,GREEN_BEAM,false); + channeling[2] = true; + } + if(add3->isInCombat() && channeling[2] == true) + { + channeling[2] = false; + add3->InterruptSpell(CURRENT_CHANNELED_SPELL, true); + + //zaatakuja wszystkie gdy 1 wejdzie w combat + if(!add1 == NULL) + if(!add1->isInCombat()) + add1->getThreatManager().addThreat(add3->getVictim(),1); + if(!add2 == NULL) + if(!add2->isInCombat()) + add2->getThreatManager().addThreat(add3->getVictim(),1); + + } + if(add3->GetHealth() == 0) + { + add3Dead = true; + add3 = NULL; + } + } + + if(add1Dead && add2Dead && add3Dead) + { + m_creature->RemoveAllAuras(); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); + m_creature->ApplySpellImmune(37546,IMMUNITY_MECHANIC,MECHANIC_BANISH,true); + relased = true; + add1Dead = false; + add2Dead = false; + add3Dead = false; + } +// ---------- BANISH PHASE END ---------- + } }; //Leotheras the Blind Demon Form AI