void removeAdds() { for (std::vector<uint64>::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) { Creature* creature = ObjectAccessor::GetCreature(*me, *itr); if (creature && creature->IsAlive()) { creature->GetMotionMaster()->Clear(true); me->DealDamage(creature, creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); creature->RemoveCorpse(); } } adds.clear(); for (std::vector<uint64>::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) { Creature* creature = ObjectAccessor::GetCreature(*me, *itr); if (creature && creature->IsAlive()) { creature->GetMotionMaster()->Clear(true); me->DealDamage(creature, creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); creature->RemoveCorpse(); } } assassins.clear(); }
void MovementInform(uint32 uiType, uint32 uiPointId) { if (uiType != POINT_MOTION_TYPE || !instance) return; switch (uiPointId) { case 1: { Creature* boss = me->GetMap()->GetCreature(instance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); if (boss) { CAST_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok = true; CAST_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = false; // sacrifice health transfer if ((boss->GetHealth() + me->GetHealth()) >= boss->GetMaxHealth()) boss->SetFullHealth(); else boss->SetHealth(boss->GetHealth() + me->GetHealth()); me->Kill(me); } } break; } }
void SpellHit(Unit *caster, const SpellEntry *entry) { if (caster == m_creature) return; Creature *pOtherBoss = GetOtherBoss(); if (entry->Id != SPELL_HEAL_BROTHER || !pOtherBoss) return; // add health so we keep same percentage for both brothers uint32 mytotal = m_creature->GetMaxHealth(), histotal = pOtherBoss->GetMaxHealth(); float mult = ((float)mytotal) / ((float)histotal); if (mult < 1) mult = 1.0f/mult; #define HEAL_BROTHER_AMOUNT 30000.0f uint32 largerAmount = (uint32)((HEAL_BROTHER_AMOUNT * mult) - HEAL_BROTHER_AMOUNT); uint32 myh = m_creature->GetHealth(); uint32 hish = pOtherBoss->GetHealth(); if (mytotal > histotal) { uint32 h = m_creature->GetHealth()+largerAmount; m_creature->SetHealth(std::min(mytotal, h)); } else { uint32 h = pOtherBoss->GetHealth()+largerAmount; pOtherBoss->SetHealth(std::min(histotal, h)); } }
Creature* GetChainHealTarget() { if (HealthBelowPct(85)) return m_creature; if (pGuard1 && pGuard1->isAlive() && (pGuard1->GetHealth()*100 <= pGuard1->GetMaxHealth() * 75)) return pGuard1; if (pGuard2 && pGuard2->isAlive() && (pGuard2->GetHealth()*100 <= pGuard2->GetMaxHealth() * 75)) return pGuard2; return NULL; }
void UpdateAI(const uint32 diff) { if (!EventBegun) return; if (EndEventTimer) { if (EndEventTimer <= diff) { if (DeathCount > 3) { if (instance) { if (Creature* VoiceTrigger = (Unit::GetCreature(*me, instance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); instance->SetData(DATA_ILLIDARICOUNCILEVENT, DONE); //me->SummonCreature(AKAMAID, 746.466980f, 304.394989f, 311.90208f, 6.272870f, TEMPSUMMON_DEAD_DESPAWN, 0); } me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return; } Creature* pMember = (Unit::GetCreature(*me, Council[DeathCount])); if (pMember && pMember->isAlive()) pMember->DealDamage(pMember, pMember->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); ++DeathCount; EndEventTimer = 1500; } else EndEventTimer -= diff; } if (CheckTimer) { if (CheckTimer <= diff) { uint8 EvadeCheck = 0; for (uint8 i = 0; i < 4; ++i) { if (Council[i]) { if (Creature* Member = (Unit::GetCreature((*me), Council[i]))) { // This is the evade/death check. if (Member->isAlive() && !Member->getVictim()) ++EvadeCheck; //If all members evade, we reset so that players can properly reset the event else if (!Member->isAlive()) // If even one member dies, kill the rest, set instance data, and kill self. { EndEventTimer = 1000; CheckTimer = 0; return; } } } } if (EvadeCheck > 3) Reset(); CheckTimer = 2000; } else CheckTimer -= diff; } }
void ControllerAI::ResetEvent(bool finished) { if (!instance) return; Creature* pCreature = NULL; if (pCreature = me->FindNearestCreature(CREATURE_SEARING_GAZE_TARGET, 100.0f)) pCreature->DespawnOrUnsummon(); if (pCreature = me->FindNearestCreature(CREATURE_SHADOW_ORB, 100.0f)) pCreature->DespawnOrUnsummon(); for (uint8 i = 0; i < 2; ++i) { if (pCreature = me->GetCreature((*me), instance->GetData64(DATA_LIGHTNING_TRIGGER_LEFT+i))) { if (finished) pCreature->DealDamage(pCreature, pCreature->GetHealth()); else pCreature->RemoveAurasDueToSpell(SPELL_VISUAL_LIGHTNING_TRIGGER); } } if (!finished) { ActivateOrSwitchBossGO(BOSS_ALL, BOSS_GO_STATE_NOTHING); me->CastSpell(me, SPELL_KILL_TRIBUNAL_ADD, true); Reset(); } }
void MeleeHitCount() { if(m_uiMeleeCounter >= 25 && !m_bCracking1) // 25, 50, 75? { m_creature->GenericTextEmote("Viscidus begins to crack.", NULL, false); m_bCracking1 = true; } else if(m_uiMeleeCounter >= 50 && !m_bCracking2) { m_creature->GenericTextEmote("Viscidus looks ready to shatter.", NULL, false); m_bCracking2 = true; m_bSummoned = false; } else if(m_uiMeleeCounter >= 75 && !m_bExploded) { if (!m_bExploded) { // if Viscidus has less than 5% hp he should // die since every glob is 5% hp if (HealthBelowPct(5)) { KillViscidus(); return; } m_bCanDoDamage = false; m_bExploded = true; m_creature->RemoveAllAuras(AuraRemoveMode::AURA_REMOVE_BY_DEFAULT); m_creature->CastSpell(m_creature, SPELL_VISCIDUS_EXPLODE,true); m_creature->GenericTextEmote("Viscidus explodes.", NULL, false); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // Clear the target to prevent him from rotating. m_creature->SetTargetGuid(ObjectGuid()); // Save his health m_health = m_creature->GetHealth(); // Summon another Viscidus that we blow up. This to // avoid the raid killing the original if we set his // health to zero to blow him up. float x, y, z; m_creature->GetPosition(x, y, z); Creature* pSummoned = m_creature->SummonCreature(m_creature->GetEntry(), x, y, z, m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 2200, false); if (pSummoned) { pSummoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pSummoned->SetObjectScale(m_creature->GetObjectScale()); pSummoned->UpdateModelData(); m_creature->DealDamage(pSummoned, pSummoned->GetHealth() + 1, nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, true); } m_uiSetInvisTimer = 100; m_uiGlobSpawnTimer = 4000; // slight delay before we spawn the adds m_uiSetVisibleTimer = 17000; // adjust so that he spawns slightly after all globs despawned } } }
bool ShatteringStomp(uint32 i, Spell* pSpell) { if( !pSpell->u_caster ) return false; Unit* _unit = pSpell->u_caster; Creature* golem = NULL; for(unordered_set<Object*>::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); itr++) { if( (*itr) && (*itr)->IsCreature() ) { golem = TO_CREATURE((*itr)); if( golem->isAlive() && golem->creature_info && golem->creature_info->Id == MOLTEN_GOLEM_ENTRY ) { uint32 spellid = pSpell->m_spellInfo->Id == 59529 ? 59527 : 52429; Creature* Golem = TO_CREATURE( (*itr) ); Golem->CastSpell( Golem, spellid, true ); for( uint8 i=0; i<7; i++ ) Golem->SchoolImmunityList[i] = 0; _unit->DealDamage( Golem, Golem->GetHealth(),0,0,0); } } } return true; }
void UpdateAI(const uint32 diff) { if (!EventBegun) return; if (EndEventTimer) { if (EndEventTimer <= diff) { if (DeathCount > 1) { if (m_pInstance) m_pInstance->SetData(TYPE_VALKIRIES, DONE); m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return; } Creature* pMember = m_creature->GetMap()->GetCreature(Valkyrias[DeathCount]); if (pMember && pMember->isAlive()) pMember->DealDamage(pMember, pMember->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); ++DeathCount; EndEventTimer = 1500; }else EndEventTimer -= diff; } if (CheckTimer) { if (CheckTimer <= diff) { uint8 EvadeCheck = 0; for(uint8 i = 0; i < 2; ++i) { if (Valkyrias[i]) { if (Creature* Member = m_creature->GetMap()->GetCreature(Valkyrias[i])) { // This is the evade/death check. if (Member->isAlive() && !Member->SelectHostileTarget()) ++EvadeCheck; //If all members evade, we reset so that players can properly reset the event else if (!Member->isAlive()) //If even one member dies, kill the rest, set instance data, and kill self. { EndEventTimer = 1000; CheckTimer = 0; return; } } } } if (EvadeCheck > 1) Reset(); CheckTimer = 2000; }else CheckTimer -= diff; } }
void CheckDamage() { Creature* target = GetHitCreature(); if (!target || target->GetEntry() != NPC_DARK_RUNE_GUARDIAN) return; if (GetHitDamage() >= int32(target->GetHealth())) target->AI()->SetData(DATA_IRON_DWARF_MEDIUM_RARE, 1); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if (Fireball_Timer <= diff) { if (Unit* pVictim = SelectUnit(SELECT_TARGET_RANDOM,0)) DoCast(pVictim, DUNGEON_MODE(SPELL_FIREBALL, SPELL_FIREBALL_H), true); Fireball_Timer = urand(4000,7000); } else Fireball_Timer -= diff; if (flight) // phase 1 - the flight { Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) { flight = false; BellowingRoar_Timer = 6000; ConeOfFire_Timer = 12000; me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); me->GetMotionMaster()->Clear(); if (Unit* pVictim = SelectUnit(SELECT_TARGET_NEAREST,0)) me->AI()->AttackStart(pVictim); DoStartMovement(me->getVictim()); DoScriptText(EMOTE, me); return; } else Fly_Timer -= diff; if (Turn_Timer <= diff) { uint32 waypoint = (Fly_Timer/10000)%2; if (!me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); Turn_Timer = 10000; } else Turn_Timer -= diff; } else // phase 2 - land fight { if (ConeOfFire_Timer <= diff) { DoCast(me, DUNGEON_MODE(SPELL_CONE_OF_FIRE, SPELL_CONE_OF_FIRE_H)); ConeOfFire_Timer = 12000; Fireball_Timer = 4000; } else ConeOfFire_Timer -= diff; if (IsHeroic()) if (BellowingRoar_Timer <= diff) { DoCast(me, SPELL_BELLOWING_ROAR); BellowingRoar_Timer = 45000; } else BellowingRoar_Timer -= diff; DoMeleeAttackIfReady(); } }
bool Projectile::OnCollideActor(Actor* actor) { if (actor->GetType () == "monster" || actor->GetType () == "player") { Creature * a = static_cast<Creature*>(actor); a->SetHealth (a->GetHealth () - blow_); } return false; }
void DamageTaken(Unit* who, uint32& damage) { if(magmaw == NULL) return; magmaw->SetHealth(magmaw->GetHealth()-damage); damage = 0; }
static bool HandleNpcInfoCommand(ChatHandler* handler, const char* /*args*/) { Creature* target = handler->getSelectedCreature(); if (!target) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } uint32 faction = target->getFaction(); uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS); uint32 displayid = target->GetDisplayId(); uint32 nativeid = target->GetNativeDisplayId(); uint32 Entry = target->GetEntry(); CreatureInfo const* cInfo = target->GetCreatureInfo(); int64 curRespawnDelay = target->GetRespawnTimeEx() - time(NULL); if (curRespawnDelay < 0) curRespawnDelay = 0; std::string curRespawnDelayStr = secsToTimeString( uint64(curRespawnDelay), true); std::string defRespawnDelayStr = secsToTimeString( target->GetRespawnDelay(), true); handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), faction, npcflags, Entry, displayid, nativeid); handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); handler->PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); handler->PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction()); handler->PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(), curRespawnDelayStr.c_str()); handler->PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->lootid, cInfo->pickpocketLootId, cInfo->SkinLootId); handler->PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId()); handler->PSendSysMessage(LANG_NPCINFO_PHASEMASK, target->GetPhaseMask()); handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); handler->PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); if ((npcflags & UNIT_NPC_FLAG_VENDOR)) { handler->SendSysMessage(LANG_NPCINFO_VENDOR); } if ((npcflags & UNIT_NPC_FLAG_TRAINER)) { handler->SendSysMessage(LANG_NPCINFO_TRAINER); } return true; }
void AxesCleanup() { for (uint8 i = 0; i < 2; ++i) { Creature* pAxe = m_creature->GetMap()->GetCreature(m_aAxeGuid[i]); if (pAxe && pAxe->isAlive()) pAxe->DealDamage(pAxe, pAxe->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); m_aAxeGuid[i].Clear(); } }
void PhaseChange() { if (m_uiPhase == PHASE_SINGLE) { if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 25*m_uiPhaseCounter) { if (!m_uiPhaseCounter) { // final phase m_uiPhase = PHASE_FINAL; m_uiFrenzyTimer = 16*IN_MILISECONDS; m_uiSaberLashTimer = 20*IN_MILISECONDS; } else { m_uiPhase = PHASE_TOTEM; m_uiShockTimer = 10*IN_MILISECONDS; m_uiTotemTimer = 12*IN_MILISECONDS; DoScriptText(SAY_SPLIT, m_creature); m_creature->CastSpell(m_creature, SPELL_TRANSFIGURE_TO_TROLL, false); } } } else { Creature* pSpiritLynx = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_SPIRIT_LYNX)); if (m_creature->GetHealth()*10 < m_creature->GetMaxHealth() || (pSpiritLynx && pSpiritLynx->GetHealth()*10 < pSpiritLynx->GetMaxHealth())) { m_uiPhase = PHASE_SINGLE; DoScriptText(SAY_MERGE, m_creature); uint32 uiSpellId; switch(m_uiPhaseCounter) { case 3: uiSpellId = SPELL_TRANSFORM_TO_LYNX_75; break; case 2: uiSpellId = SPELL_TRANSFORM_TO_LYNX_50; break; case 1: uiSpellId = SPELL_TRANSFORM_TO_LYNX_25; break; } m_creature->CastSpell(m_creature, uiSpellId, false); if (pSpiritLynx) pSpiritLynx->ForcedDespawn(); m_uiFrenzyTimer = 16*IN_MILISECONDS; m_uiSaberLashTimer = 20*IN_MILISECONDS; } } }
void Reset() override { Initialize(); Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); if (Pet && Pet->IsAlive()) Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); SummonedPet.Clear(); instance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); }
void ShatterRemainingCrystals() { if (m_lCrystalGuids.empty()) return; for (GUIDList::const_iterator itr = m_lCrystalGuids.begin(); itr != m_lCrystalGuids.end(); ++itr) { //Creature* pCrystal = m_creature->GetMap()->GetCreature(FelCrystals[i]); Creature* pCrystal = m_creature->GetMap()->GetCreature(*itr); if (pCrystal && pCrystal->isAlive()) pCrystal->DealDamage(pCrystal, pCrystal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } }
void ShatterRemainingCrystals() { if (Crystals.empty()) return; //for(uint8 i = 0; i < CRYSTALS_NUMBER; ++i) for(std::list<uint64>::iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) { //Creature* pCrystal = ((Creature*)Unit::GetUnit(*m_creature, FelCrystals[i])); Creature* pCrystal = ((Creature*)Unit::GetUnit(*m_creature, *itr)); if (pCrystal && pCrystal->isAlive()) pCrystal->DealDamage(pCrystal, pCrystal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } }
void JustDied(Unit* /*who*/) { for (int ni=0; ni<3; ++ni) { Creature* sent = nearby[ni]; if (!sent) continue; if (sent->isDead()) continue; uint32 h = sent->GetHealth() + (sent->GetMaxHealth() / 2); if (h > sent->GetMaxHealth()) h = sent->GetMaxHealth(); sent->SetHealth(h); CAST_AI(aqsentinelAI, sent->AI())->GainSentinelAbility(ability); } }
void DamageTaken(Unit* /*done_by*/, uint32 &damage) { Creature *pOtherBoss = GetOtherBoss(); if (pOtherBoss) { float dPercent = ((float)damage) / ((float)m_creature->GetMaxHealth()); int odmg = (int)(dPercent * ((float)pOtherBoss->GetMaxHealth())); int ohealth = pOtherBoss->GetHealth()-odmg; pOtherBoss->SetHealth(ohealth > 0 ? ohealth : 0); if (ohealth <= 0) { pOtherBoss->SetDeathState(JUST_DIED); pOtherBoss->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } } }
void Reset() { LeechingThrow_Timer = 20000; TheBeastWithin_Timer = 30000; Multishot_Timer = 15000; Pet_Timer = 10000; pet = false; Creature* Pet = Unit::GetCreature(*me, SummonedPet); if (Pet && Pet->IsAlive()) Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); SummonedPet = 0; if (pInstance) pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); }
void UpdateAI(const uint32 diff) { if (!VorpilGUID) { m_creature->Kill(m_creature); return; } if (move <= diff) { Creature *Vorpil = Unit::GetCreature(*m_creature, VorpilGUID); if (!Vorpil) { VorpilGUID = 0; return; } if (sacrificed) { m_creature->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), Vorpil); Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth()/25); DoCast(m_creature, SPELL_SHADOW_NOVA, true); m_creature->Kill(m_creature); return; } m_creature->GetMotionMaster()->MoveFollow(Vorpil,0,0); if (m_creature->IsWithinDist(Vorpil, 3)) { DoCast(m_creature, SPELL_SACRIFICE, false); sacrificed = true; move = 500; return; } if (!Vorpil->isInCombat() || Vorpil->isDead()) { m_creature->Kill(m_creature); return; } move = 1000; } else move -= diff; }
void DoEndEvent() { if (!m_pInstance || m_bEventEnd) return; // Prevent further handling for next council uiMember death m_bEventEnd = true; // Kill all the other council members for (unsigned int i : aCouncilMember) { Creature* pMember = m_pInstance->GetSingleCreatureFromStorage(i); if (pMember && pMember->isAlive()) pMember->DealDamage(pMember, pMember->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } // Self kill the voice trigger and the controller if (Creature* pVoiceTrigger = m_pInstance->GetSingleCreatureFromStorage(NPC_COUNCIL_VOICE)) pVoiceTrigger->DealDamage(pVoiceTrigger, pVoiceTrigger->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); m_creature->DealDamage(m_creature, m_creature->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); }
void boss_attumen::boss_attumenAI::UpdateAI(const uint32 diff) { if (ResetTimer) { if (ResetTimer <= diff) { ResetTimer = 0; Unit *pMidnight = Unit::GetUnit(*me, Midnight); if (pMidnight) { pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); pMidnight->SetVisible(true); } Midnight = 0; me->SetVisible(false); me->Kill(me); } } else ResetTimer -= diff; //Return since we have no target if (!UpdateVictim()) return; if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) return; if (CleaveTimer <= diff) { DoCast(me->getVictim(), SPELL_SHADOWCLEAVE); CleaveTimer = urand(10000, 15000); } else CleaveTimer -= diff; if (CurseTimer <= diff) { DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); CurseTimer = 30000; } else CurseTimer -= diff; if (RandomYellTimer <= diff) { DoScriptText(RAND(SAY_RANDOM1, SAY_RANDOM2), me); RandomYellTimer = urand(30000, 60000); } else RandomYellTimer -= diff; if (me->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID) { if (ChargeTimer <= diff) { Unit *pTarget = NULL; std::list<HostileReference *> t_list = me->getThreatManager().getThreatList(); std::vector<Unit *> target_list; for (std::list<HostileReference *>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); if (pTarget && !pTarget->IsWithinDist(me, ATTACK_DISTANCE, false)) target_list.push_back(pTarget); pTarget = NULL; } if (target_list.size()) pTarget = *(target_list.begin()+rand()%target_list.size()); DoCast(pTarget, SPELL_BERSERKER_CHARGE); ChargeTimer = 20000; } else ChargeTimer -= diff; } else { if (HealthBelowPct(25)) { Creature *pMidnight = Unit::GetCreature(*me, Midnight); if (pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT) { CAST_AI(boss_midnight::boss_midnightAI, (pMidnight->AI()))->Mount(me); me->SetHealth(pMidnight->GetHealth()); DoResetThreat(); } } } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (!m_bDrainingCrystal) { uint32 uiMaxPowerMana = m_creature->GetMaxPower(POWER_MANA); if (uiMaxPowerMana && ((m_creature->GetPower(POWER_MANA)*100 / uiMaxPowerMana) < 10)) { if (m_uiDrainLifeTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_DRAIN_LIFE) == CAST_OK) m_uiDrainLifeTimer = 10000; } } else m_uiDrainLifeTimer -= uiDiff; // Heroic only if (!m_bIsRegularMode) { if (m_uiDrainManaTimer < uiDiff) { Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1); if (!pTarget) pTarget = m_creature->getVictim(); if (DoCastSpellIfCan(pTarget, SPELL_DRAIN_MANA) == CAST_OK) m_uiDrainManaTimer = 10000; } else m_uiDrainManaTimer -= uiDiff; } } if (m_uiFelExplosionTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_FEL_EXPLOSION) == CAST_OK) m_uiFelExplosionTimer = 2000; } else m_uiFelExplosionTimer -= uiDiff; // If below 10% mana, start recharging uiMaxPowerMana = m_creature->GetMaxPower(POWER_MANA); if (uiMaxPowerMana && ((m_creature->GetPower(POWER_MANA)*100 / uiMaxPowerMana) < 10)) { if (m_uiDrainCrystalTimer < uiDiff) { SelectNearestCrystal(); if (m_bIsRegularMode) m_uiDrainCrystalTimer = urand(20000, 25000); else m_uiDrainCrystalTimer = urand(10000, 15000); } else m_uiDrainCrystalTimer -= uiDiff; } DoMeleeAttackIfReady(); } else // if m_bDrainingCrystal { if (m_bIsDraining) { if (m_uiEmpowerTimer < uiDiff) { m_bIsDraining = false; m_bDrainingCrystal = false; DoScriptText(SAY_EMPOWERED, m_creature); Creature* CrystalChosen = m_creature->GetMap()->GetCreature(m_crystalGuid); if (CrystalChosen && CrystalChosen->isAlive()) // Use Deal Damage to kill it, not SetDeathState. CrystalChosen->DealDamage(CrystalChosen, CrystalChosen->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); m_crystalGuid.Clear(); m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); } else m_uiEmpowerTimer -= uiDiff; } } }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (!m_bDrainingCrystal) { if (m_creature->GetPower(POWER_MANA) * 100 / m_creature->GetMaxPower(POWER_MANA) < 10) { if (m_uiDrainLifeTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_DRAIN_LIFE : SPELL_DRAIN_LIFE_H) == CAST_OK) m_uiDrainLifeTimer = 10000; } } else m_uiDrainLifeTimer -= uiDiff; // Heroic only if (!m_bIsRegularMode) { if (m_uiDrainManaTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_DRAIN_MANA, SELECT_FLAG_POWER_MANA)) { if (DoCastSpellIfCan(pTarget, SPELL_DRAIN_MANA) == CAST_OK) m_uiDrainManaTimer = 10000; } } else m_uiDrainManaTimer -= uiDiff; } if (m_uiDrainCrystalTimer < uiDiff) { if (DoSelectNearestCrystal()) m_uiDrainCrystalTimer = m_bIsRegularMode ? urand(20000, 25000) : urand(10000, 15000); } else m_uiDrainCrystalTimer -= uiDiff; } if (m_uiFelExplosionTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_FEL_EXPLOSION) == CAST_OK) m_uiFelExplosionTimer = 2000; } else m_uiFelExplosionTimer -= uiDiff; DoMeleeAttackIfReady(); } else { if (m_uiManaRageTimer) { if (m_uiManaRageTimer <= uiDiff) { DoScriptText(SAY_EMPOWERED, m_creature); ManaRageComplete(); // Kill the drained crystal Creature* pCrystalChosen = m_creature->GetMap()->GetCreature(m_crystalGuid); if (pCrystalChosen && pCrystalChosen->isAlive()) pCrystalChosen->DealDamage(pCrystalChosen, pCrystalChosen->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); m_uiManaRageTimer = 0; } else m_uiManaRageTimer -= uiDiff; } } }
//============================================================================== void GameServer::tick() { /*float dt = (time_.elapsed() - lastTime_) * 0.001f;*/ lastTime_ = time_.elapsed(); /*if (actors_.size() < 100 && !testingStageActive_) { GenMonsters_(); }*/ auto collideWithGrid = [=](Actor* actor, EActorDirection direction) { auto& p = *actor; float x = p.GetPosition().x; float y = p.GetPosition().y; bool collided = false; if ((levelMap_.GetCell(x + 0.49f, y - 0.51f) != '.' || levelMap_.GetCell(x + 0.49f, y + 0.49f) != '.') && levelMap_.GetCell(x - slideThreshold_+ 0.5f, y) == '.' && (direction == EActorDirection::NORTH || direction == EActorDirection::SOUTH)) { p.SetPosition(Vector2(x - slideThreshold_+ 0.0001f, p.GetPosition().y)); } if (levelMap_.GetCell(x + slideThreshold_- 0.5f, y) == '.' &&((levelMap_.GetCell(x - 0.5f, y - 0.51f) != '.' || levelMap_.GetCell(x - 0.5f, y + 0.49f) != '.') && (direction == EActorDirection::NORTH || direction == EActorDirection::SOUTH))) { p.SetPosition(Vector2(x + slideThreshold_- 0.0001f, p.GetPosition().y)); } if (levelMap_.GetCell(x, y - slideThreshold_ + 0.5f) == '.' && (levelMap_.GetCell(x - 0.51f, y + 0.49f) != '.' || levelMap_.GetCell(x + 0.49f, y + 0.49f) != '.') && (direction == EActorDirection::EAST || direction == EActorDirection::WEST)) { p.SetPosition(Vector2(p.GetPosition().x, y - slideThreshold_+ 0.0001f)); } if ((levelMap_.GetCell(x + 0.49f, y - 0.5f) != '.' || levelMap_.GetCell(x - 0.51f, y - 0.5f) != '.') && levelMap_.GetCell(x, y + slideThreshold_- 0.5f) == '.' && (direction == EActorDirection::EAST || direction == EActorDirection::WEST)) { p.SetPosition(Vector2(p.GetPosition().x, y + slideThreshold_ - 0.001f)); } if (levelMap_.GetCell(x + 0.5f, y) != '.') { p.SetPosition(Vector2(round(x + 0.5f) - 0.5f, p.GetPosition().y)); collided = true; } if (levelMap_.GetCell(x - 0.51f, y) != '.') { p.SetPosition(Vector2(round(x - 0.5f) + 0.5f, p.GetPosition().y)); collided = true; } if (levelMap_.GetCell(x, y + 0.5f) != '.') { p.SetPosition(Vector2(p.GetPosition().x, round(y + 0.5f) - 0.5f)); collided = true; } if (levelMap_.GetCell(x, y - 0.51f) != '.') { p.SetPosition(Vector2(p.GetPosition().x, round(y - 0.5f) + 0.5f)); collided = true; } if (collided) { actor->OnCollideWorld(); } }; for (Actor* actor: actors_) { if (actor->GetType() == EActorType::MONSTER) { Monster* monster = dynamic_cast<Monster*>(actor); Creature* target = monster->target; float distance2; Vector2 m_pos = actor->GetPosition(); if (target && target != nullptr) { Vector2 t_pos = target->GetPosition(); distance2 = Sqr(m_pos.x - t_pos.x) + Sqr(m_pos.y - t_pos.y); if (distance2 < 25) { if (abs(m_pos.x - t_pos.x - 1.0f) < playerVelocity_ && m_pos.x - t_pos.x - 1.0f != 0) { monster->SetPosition(Vector2(t_pos.x + 1.0f, m_pos.y)); monster->SetDirection(EActorDirection::NONE); } if (abs(m_pos.y - t_pos.y + 1.0f) < playerVelocity_ && m_pos.y - t_pos.y + 1.0f != 0) { monster->SetPosition(Vector2(m_pos.x, t_pos.y - 1.0f)); monster->SetDirection(EActorDirection::NONE); } if (m_pos.x < t_pos.x - 1.0f) { monster->SetDirection(EActorDirection::EAST); } else if (m_pos.x > t_pos.x + 1.0f) { monster->SetDirection(EActorDirection::WEST); } else if (m_pos.y < t_pos.y - 1.0f) { monster->SetDirection(EActorDirection::SOUTH); } else if (m_pos.y > t_pos.y + 1.0f) { monster->SetDirection(EActorDirection::NORTH); } } } if (!target || target == nullptr || distance2 >= 5) { for (Actor* tar : actors_) { if (tar != monster) { bool b = false; if (tar->GetType() != EActorType::ITEM && tar->GetType () != EActorType::PROJECTILE) { Creature* m = dynamic_cast<Creature*>(tar); QStringList str = monster->Flags.filter("HATE"); for (QString hate: str) { if (Hates[hate] == m->GetRace()) { b = true; break; } } if (b) { Vector2 t_pos = tar->GetPosition(); distance2 = Sqr(m_pos.x - t_pos.x) + Sqr(m_pos.y - t_pos.y); // Dasha told 5^2 is a protocol defined const if (distance2 < 25) { monster->target = m; break; } } } } } } } if (actor->GetType() == EActorType::MONSTER || actor->GetType() == EActorType::PLAYER) { Creature* monster = dynamic_cast<Creature*>(actor); if (monster->GetHealth() <= 0) { KillActor_(actor); break; } } } for (Actor* actor: actors_) { if (!actor || actor == nullptr) { break; } auto v = directionToVector[static_cast<unsigned>(actor->GetDirection())] ; actor->SetVelocity(v); float dt = playerVelocity_; Vector2 old_pos = actor->GetPosition(); Vector2 new_pos = old_pos + v * (dt + 0.001); Vector2 old_pos2 = old_pos + v * 0.51; levelMap_.RemoveActor(actor); EActorDirection d = actor->GetDirection(); float x = new_pos.x; float y = new_pos.y; if (levelMap_.GetCell(old_pos2.x, old_pos2.y) != '#' && d != EActorDirection::NONE && (((levelMap_.GetCell(x - slideThreshold_+ 0.5f, y) == '.' && levelMap_.GetCell(x + slideThreshold_- 0.5f, y) == '.') && (d == EActorDirection::NORTH || d == EActorDirection::SOUTH)) || ((levelMap_.GetCell(x, y - slideThreshold_+ 0.5f) == '.' && levelMap_.GetCell(x, y + slideThreshold_- 0.5f) == '.') && (d == EActorDirection::EAST || d == EActorDirection::WEST)))) { if (levelMap_.GetCell(new_pos.x, new_pos.y) == '.') { if (!actor->Update(dt) && actor->GetType () == EActorType::PROJECTILE) { static_cast<Projectile*>(actor)->death = true; } collideWithGrid(actor, d); } else if (levelMap_.GetCell(x , y) != '.' && playerVelocity_ >= 1) { bool b = false; for (float i = 0.01; i <= dt; i += 0.01) { new_pos = old_pos + v * i + v * 0.5f; if (levelMap_.GetCell(new_pos.x, new_pos.y) == '#' && !b) { actor->Update(i - 0.01); b = true; } } } else { if (actor->GetType () == EActorType::PROJECTILE) { static_cast<Projectile*>(actor)->death = true; } } } else { if (actor && actor != nullptr) { if (actor->GetType () == EActorType::PROJECTILE) { static_cast<Projectile*>(actor)->death = true; } else { actor->OnCollideWorld(); } } } if (actor->GetType() == EActorType::PLAYER) { Player* player = dynamic_cast<Player*>(actor); if (player->GetHealth() < player->GetMaxHealth()) { player->SetHealth(player->GetHealth() + 1); } } if (actor->GetType() == EActorType::MONSTER) { Monster* monster = dynamic_cast<Monster*>(actor); Creature* target = monster->target; if (target && target->GetHealth() > 0) { Vector2 m_pos = actor->GetPosition(); Vector2 t_pos = target->GetPosition(); float distance2 = Sqr(m_pos.x - t_pos.x) + Sqr(m_pos.y - t_pos.y); if (distance2 <= Sqr(pickUpRadius_)) { events_ << monster->atack(target); events_ << target->atack(monster); } } } for (Actor* neighbour : actors_) { if (actor == nullptr || neighbour == nullptr || actor == neighbour || neighbour->GetType() == EActorType::ITEM || (actor->GetType() == EActorType::PROJECTILE && neighbour->GetType() == EActorType::PROJECTILE)) { break; } Box box0(neighbour->GetPosition(), 0.9f, 0.9f); Box box1(actor->GetPosition(), 0.9f, 0.9f); if (box0.Intersect(box1)) { actor->OnCollideActor(neighbour); neighbour->OnCollideActor(actor); if (actor->GetType() == EActorType::PROJECTILE) { static_cast<Projectile*>(actor)->death = true; if (neighbour->GetType () == EActorType::MONSTER) { Monster* monster = dynamic_cast<Monster*>(neighbour); if (monster->GetHealth () <= 0) { GetItems(monster); } } } else if (neighbour->GetType() == EActorType::PROJECTILE) { static_cast<Projectile*>(neighbour)->death = true; if (actor->GetType() == EActorType::MONSTER) { Monster* monster = dynamic_cast<Monster*>(actor); if (monster->GetHealth () <= 0) { GetItems(monster); } } } else if (neighbour->GetType() != EActorType::ITEM) { actor->SetPosition(old_pos); } } } if (actor->GetType() == EActorType::PROJECTILE && static_cast<Projectile*>(actor)->death) { QVariantMap ans1; ans1["radius"] = 1.0f; ans1["x"] = actor->GetPosition ().x; ans1["y"] = actor->GetPosition ().y; QVariantMap ans; ans["explode"] = ans1; events_ << ans; idToActor_.erase(actor->GetId()); actors_.erase(std::remove(actors_.begin(), actors_.end(), actor), actors_.end()); delete actor; actor = nullptr; } else { levelMap_.IndexActor(actor); } } QVariantMap tickMessage; tickMessage["tick"] = tick_; tickMessage["events"] = events_; events_.clear(); emit broadcastMessage(QString(QJsonDocument::fromVariant(tickMessage).toJson())); tick_++; }
//============================================================================== void GameServer::HandleUse_(const QVariantMap& request, QVariantMap& response) { auto sid = request["sid"].toByteArray(); Player* p = sidToPlayer_[sid]; if (!request["id"].toInt()) { WriteResult_(response, EFEMPResult::BAD_ID); return; } int id = request["id"].toInt(); Item* item = dynamic_cast<Item*>(idToActor_[request["id"].toInt()]); if (item) { if (request.find("x") == request.end() && request.find("y") == request.end()) { if (item->GetSubtype() != "consumable") { WriteResult_(response, EFEMPResult::BAD_ID); return; } else { p->SetHealth(p->GetHealth() + item->bonuses[EStatConst::HP]["value"].toFloat()); WriteResult_(response, EFEMPResult::OK); return; } } if ((item != p->GetSlot(left_hand) || item != p->GetSlot(right_hand)) && (p->GetSlot(left_hand) != 0 || p->GetSlot(right_hand)!= 0 ) && id != FistId_) { WriteResult_(response, EFEMPResult::BAD_SLOT); return; } WriteResult_ (response, EFEMPResult::OK); return; } if (!request["x"].toFloat() || !request["y"].toFloat()) { WriteResult_(response, EFEMPResult::BAD_PLACING); return; } for (Actor* actor : actors_) { if (actor->GetType() != EActorType::ITEM && actor->GetType() != EActorType::PROJECTILE) { Creature* target = static_cast<Creature*>(actor); if ((p->GetId() != target->GetId()) && (target->GetHealth() > 0)) { Vector2 player_pos = p->GetPosition(); Vector2 target_pos = target->GetPosition(); float distance2 = Sqr(player_pos.x - target_pos.x) + Sqr(player_pos.y - target_pos.y); if (distance2 <= Sqr(pickUpRadius_)) { QVariantMap a = p->atack(target, id); events_ << a; if (target->GetHealth() <= 0) { GetItems(target); p->SetExperience(p->GetExperience () + 300); int lev = p->GetLevel(); p->SetLevel (p->GetExperience() / 1000); if (lev < p->GetLevel()) { p->AddStat (); p->UpdateStat(); } } else { a = target->atack(p); events_ << a; } WriteResult_(response, EFEMPResult::OK); return; } } } } }
void UpdateAI(const uint32 uiDiff) override { if (!pEntered) // should also be in phase zero { float x,y,z; m_creature->GetClosePoint(x, y, z, m_creature->GetObjectBoundingRadius(), 15.0f, 0.0f); if (Creature* pTemp = m_creature->SummonCreature(NPC_HEAD, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0)) HeadGUID = pTemp->GetObjectGuid(); pEntered = true; m_uiPhase = PHASE_ONE; } Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_HEAD); if (!m_pInstance) return; if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; switch (m_uiPhase) { case PHASE_ONE: { // he gets his head if (!m_creature->HasAura(SPELL_HEAD)) DoCast(m_creature,SPELL_HEAD,false); if (((m_creature->GetHealth()*100) / (m_creature->GetMaxHealth())) <= 1) m_uiPhase = PHASE_TWO; if (m_uiCleave_Timer <= uiDiff) { m_creature->CastSpell(m_creature->getVictim(),SPELL_CLEAVE_PROC,false); m_uiCleave_Timer = 5000; }else m_uiCleave_Timer -= uiDiff; DoMeleeAttackIfReady(); break; } case PHASE_TWO: { if (m_creature->HasAura(SPELL_HEAD)) { m_creature->RemoveAurasDueToSpell(SPELL_HEAD); // visual of head flying off body ( really head flying at target which in this case needs to be the head npc ) DoCast(pHead,SPELL_SEND_HEAD,true); } ApplyRegenAuras(); if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) if (pHead && pHead->GetTypeId() == TYPEID_UNIT && pHead->AI()) pHead->AI()->AttackStart(pTarget); if ((pHead->GetHealth()*100) / (pHead->GetMaxHealth()) <= 66) /*|| (m_creature->GetHealth()*100) / (m_creature->GetMaxHealth()) <= 100)*/ { RemoveRegenAuras(); m_uiPhase = PHASE_THREE; } break; } case PHASE_THREE: { // give him his head back ( the head will target and cast spell send head at the body will look like head flying back on to body if (!m_creature->HasAura(SPELL_HEAD)) DoCast(m_creature,SPELL_HEAD,false); if (((m_creature->GetHealth()*100) / (m_creature->GetMaxHealth())) <= 1) m_uiPhase = PHASE_FOUR; if (m_uiConflageration_Timer <= uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { DoScriptText(SAY_CONFLAGRATION,m_creature); pTarget->CastSpell(pTarget,SPELL_CONFLAGRATION,false); } m_uiConflageration_Timer = 15000; }else m_uiConflageration_Timer -= uiDiff; DoMeleeAttackIfReady(); break; } case PHASE_FOUR: { if (m_creature->HasAura(SPELL_HEAD)) { m_creature->RemoveAurasDueToSpell(SPELL_HEAD); // visual of head flying off body ( really head flying at target which in this case needs to be the head npc ) DoCast(pHead,SPELL_SEND_HEAD,true); } ApplyRegenAuras(); if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) if (pHead->AI()) pHead->AI()->AttackStart(pTarget); if ((pHead->GetHealth()*100) / (pHead->GetMaxHealth()) <= 33) /*|| (m_creature->GetHealth()*100) / (m_creature->GetMaxHealth()) <= 100)*/ { RemoveRegenAuras(); m_uiPhase = PHASE_FIVE; } break; } case PHASE_FIVE: { if (!m_creature->HasAura(SPELL_HEAD)) DoCast(m_creature,SPELL_HEAD,false); if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) if (pHead->AI()) pHead->AI()->AttackStart(pTarget); if (m_uiPumpkinSprout_Timer <= uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { DoScriptText(SAY_SPROUTING_PUMPKINS,m_creature); m_creature->CastSpell(pTarget,SPELL_SUMMON_PUMPKIN,false); } m_uiPumpkinSprout_Timer = 30000; }else m_uiPumpkinSprout_Timer -= uiDiff; if (m_uiConflageration_Timer <= uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { DoScriptText(SAY_CONFLAGRATION,m_creature); pTarget->CastSpell(pTarget,SPELL_CONFLAGRATION,false); } m_uiConflageration_Timer = 15000; }else m_uiConflageration_Timer -= uiDiff; if (((m_creature->GetHealth()*100) / (m_creature->GetMaxHealth())) <= 1) { m_uiPhase = PHASE_FOUR; DoCast(pHead,SPELL_SEND_HEAD,true); } DoMeleeAttackIfReady(); break; //default: break; } } }