Example #1
0
bool AIController::ProcessMessage(Unit &unit)
{
    std::vector<Message> messagesReceived = unit.GetMessages();
    if(!messagesReceived.empty() && unit.GetTarget()== NULL){

        float currentLenght = 0;
        float bestLenght = (messagesReceived[0].sender->GetPosition() - unit.GetPosition()).Length();
        Message closestMessage = messagesReceived[0];
        for(std::vector<Message>::iterator it = messagesReceived.begin(); it != messagesReceived.end(); ++it) {
                Message currentObject = *it;
                currentLenght = (currentObject.sender->GetPosition() - unit.GetPosition()).Length();
                if (currentLenght < bestLenght){
                    closestMessage = currentObject;
                    bestLenght = currentLenght;
                }
        }
        if(!closestMessage.content.compare("attack") && bestLenght < 400){
            unit.SetTarget(closestMessage.target);
            unit.SetNullDestination();
            unit.ClearMessages();
            return true;
        }
    }
    unit.ClearMessages();
    return false;

}
Example #2
0
void aiBehaviorAttackTarget::Update( Ogre::Any& owner, float dt )
{
	Unit* pUnit = Ogre::any_cast<Unit*>(owner);
	Unit* target = pUnit->GetAttackTarget();
	AnimatedComponent* anim = pUnit->GetAnim();
	
	if (target)
	{
		//³¯ÏòÄ¿±ê
		POS targetPos = target->GetPosition();
		targetPos.y = pUnit->GetPosition().y;
		pUnit->GetSceneNode()->lookAt(targetPos, Ogre::Node::TS_WORLD, FLOAT3::UNIT_Z);

		float fLastAttkTime = pUnit->GetLastAttackPastTime();
		fLastAttkTime += dt;
		float cooldown = pUnit->GetAttackInterval();

		pUnit->SetLastAttackPastTime(fLastAttkTime);

		//¹¥»÷ÀäÈ´
		if (fLastAttkTime >= cooldown)
		{
			anim->PlayAnimation(eAnimation_Attack, false);

			target->_OnAttacked(pUnit);
			pUnit->SetLastAttackPastTime(0);
		}
		else if(anim->IsAnimationOver())
		{
			anim->PlayAnimation(eAnimation_Idle, true);
		}
	}
}
            void RandomJump(SpellEffIndex effIndex)
            {
                PreventHitDefaultEffect(effIndex);
                Unit* target = GetHitUnit();

                if (!target)
                    return;

                uint8 roll = urand(0, 1);
                float angle = frand(0, M_PI);
                float SpeedXY = frand(10.0f, 30.0f);
                float SpeedZ = frand(10.0f, 15.0f);
                float x, y;

                if (!roll)
                {
                    target->GetPosition(x, y);
                    target->SetOrientation(angle);
                    target->KnockbackFrom(x, y, SpeedXY, SpeedZ);
                }
                else
                {
                    float dist = frand(10.0f, 30.0f);
                    target->GetNearPoint2D(x, y, dist, angle);
                    target->GetMotionMaster()->MoveJump(x, y, FLOR_COORD_Z, SpeedXY, SpeedZ);
                }
            }
Example #4
0
    // Wrapper to handle movement to the closest trigger
    void DoMoveToClosestTrigger(bool bGround)
    {
        if (!m_pInstance)
            return;

        Unit* pChosenTrigger = NULL;
        GuidList lTriggersList;
        float fX, fY, fZ;

        // get the list of wanted triggers
        m_pInstance->GetNightbaneTriggers(lTriggersList, bGround);

        // calculate the closest trigger from the list
        for (GuidList::const_iterator itr = lTriggersList.begin(); itr != lTriggersList.end(); ++itr)
        {
            if (Creature* pTrigger = m_creature->GetMap()->GetCreature(*itr))
            {
                if (!pChosenTrigger || m_creature->GetDistanceOrder(pTrigger, pChosenTrigger, false))
                    pChosenTrigger = pTrigger;
            }
        }

        // Move to trigger position
        if (pChosenTrigger)
        {
            pChosenTrigger->GetPosition(fX, fY, fZ);
            m_creature->GetMotionMaster()->MovePoint(bGround ? POINT_ID_GROUND : POINT_ID_AIR, fX, fY, fZ);
        }
    }
Example #5
0
Battle::Position Battle::Position::GetCorrect(const Unit & b, s32 head)
{
    Position result;

    result.first = Board::GetCell(head);

    if(result.first && b.isWide())
    {
	result.second = Board::GetCell(head, b.isReflect() ? RIGHT : LEFT);

	if(! result.second ||
	    (result.second != b.GetPosition().GetHead() && ! result.second->isPassable1(true)))
	{
	    result.second = Board::GetCell(head, b.isReflect() ? LEFT : RIGHT);

	    if(! result.second)
		result.second = Board::GetCell(head, b.isReflect() ? RIGHT : LEFT);

	    if(result.second)
		std::swap(result.first, result.second);
	    else
		DEBUG(DBG_BATTLE, DBG_WARN, "NULL pointer, " << b.String() << ", dst: " << head);
	}
    }

    return result;
}
 void ModDestHeight(SpellDestination& dest)
 {
     Unit* caster = GetCaster();
     Position pos = caster->GetPosition();
     pos.m_positionZ = caster->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), true, 100.0f);
     dest.Relocate(pos);
 }
Example #7
0
void VehicleKit::Dismount(Unit* passenger, VehicleSeatEntry const* seatInfo)
{
    if (!passenger)
        return;

    float ox, oy, oz, oo;

    Unit* base = m_pBase->GetVehicle() ? m_pBase->GetVehicle()->GetBase() : m_pBase;
    base->GetPosition(ox, oy, oz);
    oo = base->GetOrientation();
    passenger->SetPosition(ox,oy,oz,oo,false);

    if (b_dstSet)
    {
        // parabolic traectory (catapults, explode, other effects). mostly set destination in DummyEffect.
        // destination Z not checked in this case! only limited on 8.0 delta. requred full correct set in spelleffects. 
        float speed = ((m_dst_speed > M_NULL_F) ? m_dst_speed : ((seatInfo && seatInfo->m_exitSpeed > M_NULL_F) ? seatInfo->m_exitSpeed : BASE_CHARGE_SPEED));
        float verticalSpeed = speed * sin(m_dst_elevation);
        float horisontalSpeed = speed * cos(m_dst_elevation);
        float moveTimeHalf =  verticalSpeed / ((seatInfo && seatInfo->m_exitGravity > 0.0f) ? seatInfo->m_exitGravity : Movement::gravity);
        float max_height = - Movement::computeFallElevation(moveTimeHalf,false,-verticalSpeed);

        passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x,m_dst_y,m_dst_z,passenger->GetOrientation(), horisontalSpeed, max_height, true);
    }
    else if (seatInfo)
    {
        // half-parabolic traectory (unmount)
        float horisontalSpeed = seatInfo->m_exitSpeed;

        if (horisontalSpeed < M_NULL_F)
            horisontalSpeed = BASE_CHARGE_SPEED;

        // may be under water
        base->GetClosePoint(m_dst_x, m_dst_y, m_dst_z, base->GetObjectBoundingRadius(), frand(2.0f, 3.0f), frand(M_PI_F/2.0f,3.0f*M_PI_F/2.0f), passenger);
        if (m_dst_z < oz)
            m_dst_z = oz;

        passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x, m_dst_y, m_dst_z + 0.1f, passenger->GetOrientation(), horisontalSpeed, 0.0f);
    }
    else
    {
        // jump from vehicle without seatInfo (? error case)
        base->GetClosePoint(m_dst_x, m_dst_y, m_dst_z, base->GetObjectBoundingRadius(), 2.0f, M_PI_F, passenger);
        passenger->UpdateAllowedPositionZ(m_dst_x, m_dst_y, m_dst_z);
        if (m_dst_z < oz)
            m_dst_z = oz;

        passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x, m_dst_y, m_dst_z + 0.1f, passenger->GetOrientation(), BASE_CHARGE_SPEED, 0.0f);
    }

    DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS,"VehicleKit::Dismount %s from %s (%f %f %f), destination point is %f %f %f",
        passenger->GetObjectGuid().GetString().c_str(),
        base->GetObjectGuid().GetString().c_str(),
        ox,oy,oz,
        m_dst_x,m_dst_y,m_dst_z);
    SetDestination();
}
Example #8
0
        void HandleBouncerSpikes()
        {
            Unit* caster = GetCaster();
            Vehicle* vehicle = caster->GetVehicleKit();
            if (!vehicle)
                return;

            for (uint8 i = 0; i < vehicle->GetAvailableSeatCount(); i++)
                if (Creature* summon = caster->SummonCreature(NPC_BOUNCER_SPIKE, caster->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 10000))
                    summon->EnterVehicle(caster, i);
        }
Example #9
0
/// Spell Target Handling for type 29: all object around the caster / object (so it seems)
void Spell::SpellTargetTypeTAOE(uint32 i, uint32 j)
{
	Unit* Target = m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget);
	if( Target == NULL )
		return;

	// tranquility
	if( u_caster != NULL && m_spellInfo->NameHash == SPELL_HASH_TRANQUILITY )
		m_targetUnits[i].push_back(u_caster->GetGUID());
	else
		FillAllTargetsInArea( (LocationVector&)Target->GetPosition(), i );
}
 void Reset()
 {
     Unit* target = me->FindNearestCreature(ENTRY_THROW_TARGET, 50);
     if (target)
     {
         DoCast(me, SPELL_SHADOW_AXE_DAMAGE);
         float x, y, z;
         target->GetPosition(x, y, z);
         me->GetMotionMaster()->MovePoint(0, x, y, z);
     }
     uiDespawnTimer = 7000;
 }
Example #11
0
 void Reset()
 {
     Unit *pTarget = m_creature->FindNearestCreature(ENTRY_THROW_TARGET,50);
     if (pTarget)
     {
         DoCast(m_creature, DUNGEON_MODE(SPELL_SHADOW_AXE_DAMAGE, H_SPELL_SHADOW_AXE_DAMAGE));
         float x,y,z;
         pTarget->GetPosition(x,y,z);
         m_creature->GetMotionMaster()->MovePoint(0,x,y,z);
     }
     Despawn_Timer = 7000;
 }
Example #12
0
void VehicleKit::Dismount(Unit* passenger, VehicleSeatEntry const* seatInfo)
{
    if (!passenger)
        return;

    float ox, oy, oz/*, oo*/; /* oo can be used, but not at the moment*/

    Unit* base = m_pBase->GetVehicle() ? m_pBase->GetVehicle()->GetBase() : m_pBase;

    base->GetPosition(ox, oy, oz);
    /*oo = base->GetOrientation();*/

    passenger->m_movementInfo = base->m_movementInfo;

    if (b_dstSet)
    {
        // parabolic traectory (catapults, explode, other effects). mostly set destination in DummyEffect.
        // destination Z not checked in this case! only limited on 8.0 delta. requred full correct set in spelleffects. 
        float speed = ((m_dst_speed > 0.0f) ? m_dst_speed : (seatInfo ? seatInfo->m_exitSpeed : 28.0f));
        float verticalSpeed = speed * sin(m_dst_elevation);
        float horisontalSpeed = speed * cos(m_dst_elevation);
        float moveTimeHalf =  verticalSpeed / ((seatInfo && seatInfo->m_exitGravity > 0.0f) ? seatInfo->m_exitGravity : Movement::gravity);
        float max_height = - Movement::computeFallElevation(moveTimeHalf,false,-verticalSpeed);

        passenger->MonsterMoveJump(m_dst_x, m_dst_y, m_dst_z,passenger->GetOrientation(), horisontalSpeed, max_height, false);

    }
    else if (seatInfo)
    {
        // half-parabolic traectory (unmount)
        float horisontalSpeed = seatInfo->m_exitSpeed;

        // may be under water
        base->GetClosePoint(m_dst_x, m_dst_y, m_dst_z, base->GetObjectBoundingRadius(), frand(2.0f, 3.0f), frand(M_PI_F/2.0f,3.0f*M_PI_F/2.0f));
        if (m_dst_z < oz)
            m_dst_z = oz;

        passenger->MonsterMoveJump(m_dst_x, m_dst_y, m_dst_z + 0.1f, passenger->GetOrientation(), horisontalSpeed, 0.0f, false);
    }
    else
    {
        // jump from vehicle without seatInfo (? error case)
        base->GetClosePoint(m_dst_x, m_dst_y, m_dst_z, base->GetObjectBoundingRadius(), 2.0f, M_PI_F);
        passenger->UpdateAllowedPositionZ(m_dst_x, m_dst_y, m_dst_z);
        if (m_dst_z < oz)
            m_dst_z = oz;

        passenger->MonsterMoveWithSpeed(m_dst_x, m_dst_y, m_dst_z + 0.1f, 28.0f);
    }

    SetDestination();
}
Example #13
0
/// Spell Target Handling for type 53: Target Area by Players CurrentSelection()
void Spell::SpellTargetTargetAreaSelectedUnit(uint32 i, uint32 j)
{
	Unit* Target = NULL;
	if(m_caster->IsInWorld())
	{
		if(p_caster)
			Target = m_caster->GetMapMgr()->GetUnit(p_caster->GetSelection());
		else
			Target = m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget);
	}

	if(!Target)
		return;

	FillAllTargetsInArea((LocationVector&)Target->GetPosition(), i);
}
        void SpellCast(float val)
        {
            if (_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->getNextTarget())
            {
                float comulativeperc = 0;
                Unit* target = NULL;
                for (uint8 i = 0; i < nrspells; i++)
                {
                    spells[i].casttime--;

                    if (m_spellcheck[i])
                    {
                        spells[i].casttime = spells[i].cooldown;
                        target = _unit->GetAIInterface()->getNextTarget();
                        switch (spells[i].targettype)
                        {
                            case TARGET_SELF:
                            case TARGET_VARIOUS:
                                _unit->CastSpell(_unit, spells[i].info, spells[i].instant);
                                break;
                            case TARGET_ATTACKING:
                                _unit->CastSpell(target, spells[i].info, spells[i].instant);
                                break;
                            case TARGET_DESTINATION:
                                _unit->CastSpellAoF(target->GetPosition(), spells[i].info, spells[i].instant);
                                break;
                        }

                        if (spells[i].speech != "")
                        {
                            _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str());
                            _unit->PlaySoundToSet(spells[i].soundid);
                        }

                        m_spellcheck[i] = false;
                        return;
                    }

                    if ((val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) || !spells[i].casttime)
                    {
                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
                        m_spellcheck[i] = true;
                    }
                    comulativeperc += spells[i].perctrigger;
                }
            }
        }
Example #15
0
        void SpawnAdds()
        {
            for (uint8 i = 0; i < 30; ++i)
            {
                Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0);

                if (victim)
                {
                    Position pos;
                    victim->GetPosition(&pos);
                    me->GetRandomNearPosition(pos, float(urand(5, 80)));
                    me->SummonCreature(NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILLISECONDS);
                    me->GetRandomNearPosition(pos, float(urand(5, 80)));
                    me->SummonCreature(NPC_HEALTHY_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILLISECONDS);
                }
            }
        }
Example #16
0
void WorldSession::HandleTeleportToUnitOpcode(WorldPacket & recv_data)
{
	uint8 unk;
	Unit * target;
	recv_data >> unk;

	if(!_player->IsInWorld())
		return;

	if(!HasGMPermissions())
	{
		SendNotification("You do not have permission to use this function.");
		return;
	}

	if( (target = _player->GetMapMgr()->GetUnit(_player->GetSelection())) == NULL )
		return;

	_player->SafeTeleport(_player->GetMapId(), _player->GetInstanceID(), target->GetPosition());
}
Example #17
0
            void OnRemoveVehicle(constAuraEffectPtr /*aurEff*/, AuraEffectHandleModes mode)
            {
                PreventDefaultAction();
                Unit* caster = GetCaster();
                if (!caster)
                    return;

                Position exitPosition;
                exitPosition.m_positionX = 1750.0f;
                exitPosition.m_positionY = -7.5f + frand(-3.0f, 3.0f);
                exitPosition.m_positionZ = 457.9322f;

                caster->_ExitVehicle(&exitPosition);
                caster->RemoveAurasDueToSpell(GetId());

                Position oldPos;
                caster->GetPosition(&oldPos);
                caster->Relocate(exitPosition);
                caster->GetMotionMaster()->MoveFall();
                caster->Relocate(oldPos);
            }
Example #18
0
    void UpdateAI(const uint32 diff)
    {
        float x, y, z;
        me->GetPosition(x, y, z);

        if(z > WATER_Z)
            me->Relocate(x, y, WATER_Z, me->GetOrientation());

        if(!UpdateVictim())
            return;

        Unit *victim = me->getVictim();

        victim->GetPosition(x, y, z);
        if(z - 0.5f > WATER_Z)
        {
            EnterEvadeMode();
            return;
        }

        DoMeleeAttackIfReady();
    }
Example #19
0
            void IsSummonedBy(Unit* owner)
            {
                if (owner->GetTypeId() != TYPEID_UNIT)
                    return;
                Creature* creOwner = owner->ToCreature();
                DoCast(me, SPELL_COLDFLAME_PASSIVE, true);
                float x, y, z;
                // random target case
                if (!owner->HasAura(SPELL_BONE_STORM))
                {
                    // select any unit but not the tank (by owners threatlist)
                    Unit* target = creOwner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1, 40.0f, true);
                    if (!target)
                        target = creOwner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true); // or the tank if its solo
                    if (!target)
                    {
                        me->ForcedDespawn();
                        return;
                    }

                    target->GetPosition(x, y, z);
                    float scale = 70.0f / me->GetExactDist2d(x, y);
                    x = me->GetPositionX() + (x - me->GetPositionX()) * scale;
                    y = me->GetPositionY() + (y - me->GetPositionY()) * scale;
                }
                else
                {
                    me->GetPosition(x, y, z);
                    MarrowgarAI* marrowgarAI = CAST_AI(MarrowgarAI, creOwner->AI());
                    Position const* ownerPos = marrowgarAI->GetLastColdflamePosition();
                    float ang = me->GetAngle(ownerPos) - static_cast<float>(M_PI);
                    MapManager::NormalizeOrientation(ang);
                    x += 50.0f * cosf(ang);
                    y += 50.0f * sinf(ang);
                }
                me->GetMotionMaster()->MovePoint(POINT_TARGET_COLDFLAME, x, y, z);
                events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 400);
            }
Example #20
0
 void CastSinisterReflection()
 {
     DoScriptText(RAND(SAY_KJ_REFLECTION1,SAY_KJ_REFLECTION2), me);
     for (uint8 i = 0; i < 4; ++i)
     {
         float x,y,z;
         Unit *pTarget = NULL;
         for (uint8 z = 0; z < 6; ++z)
         {
             pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
             if (!pTarget || !pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break;
         }
         if (pTarget)
         {
             pTarget->GetPosition(x,y,z);
             if (Creature* pSinisterReflection = me->SummonCreature(CREATURE_SINISTER_REFLECTION, x,y,z,0, TEMPSUMMON_CORPSE_DESPAWN, 0))
             {
                 pSinisterReflection->SetDisplayId(pTarget->GetDisplayId());
                 pSinisterReflection->AI()->AttackStart(pTarget);
             }
         }
     }
 }
Example #21
0
Unit::Unit(const Unit& unit)
{
	// Declare necessary variables
	Ball*	pBall;
	Ball*	pNewBall;

	// Initialize pimpl object
	_pPimpl = new UnitPimpl;
	assert(_pPimpl);

	// Get Unit Data
	this->SetPosition		(unit.GetPosition		());
	this->SetStartPoint		(unit.GetStartPoint		());
	this->SetCenterPoint	(unit.GetCenterPoint	());
	this->SetSize			(unit.GetSize			());

	// Get Ball Data
	pBall = unit.FirstBall();

	if (pBall == NULL)
	{
		return;
	}

	do
	{
		pNewBall = new Ball(*pBall);

		if (pNewBall == NULL)
		{
			continue;
		}

		this->InsertBall(pNewBall);
	}
	while ((pBall = unit.NextBall()) != NULL);
}
Example #22
0
            void OnRemoveVehicle(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
            {
                PreventDefaultAction();
                Unit* caster = GetCaster();
                if (!caster)
                    return;

                Position exitPosition;
                exitPosition.m_positionX = 1750.0f;
                exitPosition.m_positionY = -7.5f + frand(-3.0f, 3.0f);
                exitPosition.m_positionZ = 457.9322f;

                // Remove pending passengers before exiting vehicle - might cause an Uninstall
                GetTarget()->GetVehicleKit()->RemovePendingEventsForPassenger(caster);
                caster->_ExitVehicle(&exitPosition);
                caster->RemoveAurasDueToSpell(GetId());

                // Temporarily relocate player to vehicle exit dest serverside to send proper fall movement
                // beats me why blizzard sends these 2 spline packets one after another instantly
                Position oldPos = caster->GetPosition();
                caster->Relocate(exitPosition);
                caster->GetMotionMaster()->MoveFall();
                caster->Relocate(oldPos);
            }
TargetedMovementGenerator<T>::TargetedMovementGenerator(Unit &target, float offset, float angle, bool _usePathfinding):
    TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), m_usePathfinding(_usePathfinding), i_recalculateTravel(false), i_path(NULL), m_pathPointsSent(0)
{
    target.GetPosition(i_targetX, i_targetY, i_targetZ);
}
Example #24
0
void AI::BattleTurn(Arena & arena, const Unit & b, Actions & a)
{
    Board* board = Arena::GetBoard();

    // reset quality param for board
    board->Reset();

    // set quality for enemy troop
    board->SetEnemyQuality(b);

    const Unit* enemy = NULL;
    bool attack = false;

    if(b.isArchers() && !b.isHandFighting())
    {
	enemy = arena.GetEnemyMaxQuality(b.GetColor());
	if(BattleMagicTurn(arena, b, a, enemy)) return; /* repeat turn: correct spell ability */
	attack = true;
    }
    else
    if(b.isHandFighting())
    {
	enemy = AIGetEnemyAbroadMaxQuality(b);
	if(BattleMagicTurn(arena, b, a, enemy)) return; /* repeat turn: correct spell ability */
	attack = true;
    }
    else
    {
	s16 move = -1;

	if(b.Modes(SP_BERSERKER))
	{
	    const Indexes positions = board->GetNearestTroopIndexes(b.GetHeadIndex(), NULL);
	    if(positions.size()) move = *Rand::Get(positions);
	}
	else
	{
	    if(BattleMagicTurn(arena, b, a, NULL)) return; /* repeat turn: correct spell ability */

	    // set quality position from enemy
	    board->SetPositionQuality(b);

	    // get passable quality positions
	    const Indexes positions = board->GetPassableQualityPositions(b);
	    attack = true;

	    if(positions.size())
		move = AIAttackPosition(arena, b, positions);
	}

	if(Board::isValidIndex(move))
	{
	    if(b.isFly())
	    {
		enemy = AIGetEnemyAbroadMaxQuality(move, b.GetColor());
		if(BattleMagicTurn(arena, b, a, enemy)) return; /* repeat turn: correct spell ability */
	    	a.push_back(Battle::Command(MSG_BATTLE_MOVE, b.GetUID(), move));
		attack = true;
	    }
	    else
	    {
		Position dst = Position::GetCorrect(b, move);
		Indexes path = arena.GetPath(b, dst);

		if(path.empty())
		{
		    const u8 direction = b.GetPosition().GetHead()->GetPos().x > dst.GetHead()->GetPos().x ?
						RIGHT : LEFT;
		    // find near position
		    while(path.empty() &&
			Board::isValidDirection(dst.GetHead()->GetIndex(), direction))
		    {
			const s16 & pos = Board::GetIndexDirection(dst.GetHead()->GetIndex(), direction);
			if(b.GetHeadIndex() == pos) break;

			dst.Set(pos, b.isWide(), direction == RIGHT);
			path = arena.GetPath(b, dst);
		    }
		}

		if(path.size())
		{
		    if(b.isWide())
		    {
			const s16 & head = dst.GetHead()->GetIndex();
			const s16 & tail = dst.GetTail()->GetIndex();

			if(path.back() == head || path.back() == tail)
			{
			    enemy = AIGetEnemyAbroadMaxQuality(head, b.GetColor());

			    if(!enemy)
				enemy = AIGetEnemyAbroadMaxQuality(tail, b.GetColor());
			}
		    }

		    if(! enemy)
			enemy = AIGetEnemyAbroadMaxQuality(path.back(), b.GetColor());

	    	    a.push_back(Battle::Command(MSG_BATTLE_MOVE, b.GetUID(), path.back()));

		    // archers move and short attack only
		    attack = b.isArchers() ? false : true;
		}
	    }
	}
	else
	    enemy = AIGetEnemyAbroadMaxQuality(b);
    }

    if(enemy)
    {
	if(attack) a.push_back(Battle::Command(MSG_BATTLE_ATTACK, b.GetUID(), enemy->GetUID(), enemy->GetHeadIndex(), 0));
    }
    else
    {
	DEBUG(DBG_BATTLE, DBG_TRACE, "enemy: " << "is NULL" << ", board: " << board->AllUnitsInfo());
    }

    // end action
    a.push_back(Battle::Command(MSG_BATTLE_END_TURN, b.GetUID()));
}
Example #25
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        if(StormCount)
        {
            Unit* target = Unit::GetUnit(*m_creature, CloudGUID);
            if(!target || !target->isAlive())
            {
                EnterEvadeMode();
                return;
            }
            else if(Unit* Cyclone = Unit::GetUnit(*m_creature, CycloneGUID))
                Cyclone->CastSpell(target, 25160, true); // keep casting or...

            if(StormSequenceTimer < diff) {
                HandleStormSequence(target);
            }else StormSequenceTimer -= diff;
            return;
        }

        if (Enrage_Timer < diff) {
            DoYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL);
            DoPlaySoundToSet(m_creature, SOUND_ONENRAGE);
            m_creature->CastSpell(m_creature, SPELL_BERSERK, true);
            Enrage_Timer = 600000;
        }else Enrage_Timer -= diff;

        if (StaticDisruption_Timer < diff) {
            Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1);
            if(!target) target = m_creature->getVictim();
            TargetGUID = target->GetGUID();
            m_creature->CastSpell(target, SPELL_STATIC_DISRUPTION, false);
            m_creature->SetInFront(m_creature->getVictim());
            StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s

            /*if(float dist = m_creature->IsWithinDist3d(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 5.0f) dist = 5.0f;
            SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/
        }else StaticDisruption_Timer -= diff;

        if (GustOfWind_Timer < diff) {
            Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1);
            if(!target) target = m_creature->getVictim();
            DoCast(target, SPELL_GUST_OF_WIND);
            GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers)
        } else GustOfWind_Timer -= diff;

        if (CallLighting_Timer < diff) {
            DoCast(m_creature->getVictim(), SPELL_CALL_LIGHTNING);
            CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this
        } else CallLighting_Timer -= diff;

        if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000) {
            SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f);
            isRaining = true;
        }

        if (ElectricalStorm_Timer < diff) {
            Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true);
            if(!target)
            {
                EnterEvadeMode();
                return;
            }
            target->CastSpell(target, 44007, true);//cloud visual
            m_creature->CastSpell(target, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual
            float x,y,z;
            target->GetPosition(x,y,z);
            if (target)
            {
                target->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
                target->SendMonsterMove(x,y,m_creature->GetPositionZ()+15,0);
            }
            Unit *Cloud = m_creature->SummonTrigger(x, y, m_creature->GetPositionZ()+16, 0, 15000);
            if(Cloud)
            {
                CloudGUID = Cloud->GetGUID();
                Cloud->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
                Cloud->StopMoving();
                Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f);
                Cloud->setFaction(35);
                Cloud->SetMaxHealth(9999999);
                Cloud->SetHealth(9999999);
                Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            }
            ElectricalStorm_Timer = 60000; //60 seconds(bosskillers)
            StormCount = 1;
            StormSequenceTimer = 0;
        } else ElectricalStorm_Timer -= diff;

        if (SummonEagles_Timer < diff)
        {
            DoYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL);
            DoPlaySoundToSet(m_creature, SOUND_ONSUMMON);

            float x, y, z;
            m_creature->GetPosition(x, y, z);

            for (uint8 i = 0; i < 8; i++)
            {
                Unit* bird = Unit::GetUnit(*m_creature,BirdGUIDs[i]);
                if(!bird)//they despawned on die
                {
                    if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
                    {
                        x = target->GetPositionX() + 10 - rand()%20;
                        y = target->GetPositionY() + 10 - rand()%20;
                        z = target->GetPositionZ() + 6 + rand()%5 + 10;
                        if(z > 95) z = 95 - rand()%5;
                    }
                    Creature *pCreature = m_creature->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
                    if (pCreature)
                    {
                        pCreature->AddThreat(m_creature->getVictim(), 1.0f);
                        pCreature->AI()->AttackStart(m_creature->getVictim());
                        BirdGUIDs[i] = pCreature->GetGUID();
                    }
                }
            }
            SummonEagles_Timer = 999999;
        } else SummonEagles_Timer -= diff;

        DoMeleeAttackIfReady();
    }
Example #26
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        if (StormCount)
        {
            Unit* pTarget = Unit::GetUnit(*me, CloudGUID);
            if (!pTarget || !pTarget->IsAlive())
            {
                EnterEvadeMode();
                return;
            }
            else if (Unit* Cyclone = Unit::GetUnit(*me, CycloneGUID))
                Cyclone->CastSpell(pTarget, 25160, true); // keep casting or...

            if (StormSequenceTimer <= diff)
                HandleStormSequence(pTarget);
            else
                StormSequenceTimer -= diff;

            return;
        }

        if (Enrage_Timer <= diff)
        {
            me->MonsterYell(SAY_ONENRAGE, LANG_UNIVERSAL, 0);
            DoPlaySoundToSet(me, SOUND_ONENRAGE);
            DoCast(me, SPELL_BERSERK, true);
            Enrage_Timer = (diff - Enrage_Timer) + 600000;
        }
        else
            Enrage_Timer -= diff;

        if (StaticDisruption_Timer <= diff)
        {
            Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);
            if (!pTarget) pTarget = me->GetVictim();
            TargetGUID = pTarget->GetGUID();
            DoCast(pTarget, SPELL_STATIC_DISRUPTION, false);
            me->SetInFront(me->GetVictim());
            StaticDisruption_Timer = (diff - StaticDisruption_Timer) + (10 + rand() % 8) * 1000; // < 20s

            /*if (float dist = me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f) dist = 5.0f;
            SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/
        }
        else
            StaticDisruption_Timer -= diff;

        if (GustOfWind_Timer <= diff)
        {
            Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);
            if (!pTarget) pTarget = me->GetVictim();
            DoCast(pTarget, SPELL_GUST_OF_WIND);
            GustOfWind_Timer = (diff - GustOfWind_Timer) + (20 + rand() % 10) * 1000; //20 to 30 seconds(bosskillers)
        }
        else
            GustOfWind_Timer -= diff;

        if (CallLighting_Timer <= diff)
        {
            DoCastVictim( SPELL_CALL_LIGHTNING);
            CallLighting_Timer = (diff - CallLighting_Timer) + (12 + rand() % 5) * 1000; //totaly random timer. can't find any info on this
        }
        else
            CallLighting_Timer -= diff;

        if (!isRaining && ElectricalStorm_Timer < 8000 + urand(0, 5000))
        {
            SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f);
            isRaining = true;
        }

        if (ElectricalStorm_Timer <= diff)
        {
            Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true);
            if (!pTarget)
            {
                EnterEvadeMode();
                return;
            }
            pTarget->CastSpell(pTarget, SPELL_ELECTRICAL_STORM_VISUAL, true);//cloud visual
            DoCast(pTarget, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual

            float x, y, z;
            pTarget->GetPosition(x, y, z);
            pTarget->SetLevitate(true);
            Movement::MoveSplineInit init(*me);
            init.MoveTo(x, y, me->GetPositionZ() + 15.0f, true);
            init.Launch();
            Unit* Cloud = me->SummonTrigger(x, y, me->GetPositionZ() + 16, 0, 15000);
            if (Cloud)
            {
                CloudGUID = Cloud->GetGUID();
                Cloud->SetLevitate(true);
                Cloud->StopMoving();
                Cloud->SetObjectScale(1.0f);
                Cloud->setFaction(35);
                Cloud->SetMaxHealth(9999999);
                Cloud->SetHealth(9999999);
                Cloud->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            }
            ElectricalStorm_Timer = (diff - ElectricalStorm_Timer) + 60000; //60 seconds (bosskillers)
            StormCount = 1;
            StormSequenceTimer = 0;
        }
        else
            ElectricalStorm_Timer -= diff;

        if (SummonEagles_Timer <= diff)
        {
            if (urand(0, 1))
            {
                me->MonsterYell(SAY_ONSUMMON2, LANG_UNIVERSAL, 0);
                DoPlaySoundToSet(me, SOUND_ONSUMMON1);
            }
            else
            {
                me->MonsterYell(SAY_ONSUMMON2, LANG_UNIVERSAL, 0);
                DoPlaySoundToSet(me, SOUND_ONSUMMON2);
            }

            float x, y, z;
            me->GetPosition(x, y, z);

            for (uint8 i = 0; i < 8; ++i)
            {
                if (!Unit::GetUnit(*me, BirdGUIDs[i])) // they despawn on death
                {
                    if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
                    {
                        x = pTarget->GetPositionX() + irand(-10, 10);
                        y = pTarget->GetPositionY() + irand(-10, 10);
                        z = pTarget->GetPositionZ() + urand(16, 20);
                        if (z > 95)
                            z = 95 - urand(0, 5);
                    }

                    if (Creature* pCreature = me->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0))
                    {
                        pCreature->AddThreat(me->GetVictim(), 1.0f);
                        pCreature->AI()->AttackStart(me->GetVictim());
                        BirdGUIDs[i] = pCreature->GetGUID();
                    }
                }
            }
            SummonEagles_Timer = (diff - SummonEagles_Timer) + 999999;
        }
        else
            SummonEagles_Timer -= diff;

        DoMeleeAttackIfReady();
    }
Example #27
0
void ChargeMovementGenerator<T>::ComputePath(T& attacker, Unit& victim)
{
    Vector3 attackPos; // attacker position
    Vector3 victimPos; // victim position
    Vector3 chargeVect; // vector of the charge
    Vector3 victimSpd; // speed vector of victim
    float o;

    if (Transport* t = attacker.GetTransport())
        path.SetTransport(t);

    if (_speed == 0)
        _speed = attacker.GetSpeed(MOVE_RUN) * 4;
    if (_speed > 24.0f)
        _speed = 24.0f;

    attacker.GetPosition(attackPos.x, attackPos.y, attackPos.z);
    victim.GetPosition(victimPos.x, victimPos.y, victimPos.z);
    chargeVect = victimPos - attackPos;
    chargeVect = chargeVect.direction(); // unit vector

    // Base path is to current victim position
    path.calculate(victimPos.x, victimPos.y, victimPos.z, false);

    // Improved path to victim future estimated position
    if (Player* victimPlayer = victim.ToPlayer())
    {
        PlayerAnticheatInterface* data = victimPlayer->GetCheatData();
        if ((data->InterpolateMovement(victimPlayer->m_movementInfo, 1000, victimSpd.x, victimSpd.y, victimSpd.z, o)) &&
                (data->InterpolateMovement(victimPlayer->m_movementInfo, 0, victimPos.x, victimPos.y, victimPos.z, o)))
        {
            // Victim speed per sec.
            victimSpd -= victimPos;
            // We get only the component of the speed in the direction of charge vector
            float victimSpeed = victimSpd.dot(chargeVect); // dot product
            if (abs(victimSpeed) > 0.1f)
            {
                float currDistance = path.Length();
                uint32 pathTravelTime;
                // Equation when matching collision distance, to get collision time:
                // _speed * t = currDistance + victimSpeed * t
                // t = currDistance / (_speed - victimSpeed)
                if (_speed > 2 * victimSpeed) // we don't want to reach target if target speed is more than half charge speed
                    pathTravelTime = (uint32)(1000 * currDistance / (_speed - victimSpeed));
                else
                    pathTravelTime = (uint32)(1000 * 2 * currDistance / _speed);

                pathTravelTime *= 0.45f; // Attenuation factor (empirical)
                _interpolateDelay = (WorldTimer::getMSTime() - victimPlayer->m_movementInfo.time) + pathTravelTime;
                if (_interpolateDelay > 1500) _interpolateDelay = 1500;
                if (data->InterpolateMovement(victimPlayer->m_movementInfo, _interpolateDelay, victimPos.x, victimPos.y, victimPos.z, o))
                {
                    victim.UpdateAllowedPositionZ(victimPos.x, victimPos.y, victimPos.z);
                    path.calculate(victimPos.x, victimPos.y, victimPos.z, false);
                }
            }
            else
                path.UpdateForMelee(&victim, attacker.GetMeleeReach());
        }
    }
    else
    {
        // TODO: PvE victim position prediction?
        // Relocate last path point to hitbox rather than exact position of victim
        path.UpdateForMelee(&victim, attacker.GetMeleeReach());
    }
}
Example #28
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim() || Phase < PHASE_NORMAL)
            return;

        if (IsWaiting)
        {
            if (WaitTimer <= diff)
            {
                IsWaiting = false;
                ChangeTimers(false, 0);
            } else WaitTimer -= diff;
        }

        for (uint8 t = 0; t < ActiveTimers; ++t)
        {
            if (Timer[t] <= diff && !TimerIsDeactivated[t])
            {
                switch(t)
                {
                    case TIMER_SPEECH:
                        if (SpeechBegins)
                        {
                            SpeechBegins=false;
                            switch(Phase)
                            {
                                case PHASE_NORMAL:
                                    speechPhaseEnd=1;
                                    break;
                                case PHASE_DARKNESS:
                                    speechPhaseEnd=4;
                                    break;
                                case PHASE_ARMAGEDDON:
                                    speechPhaseEnd=7;
                                    break;
                                case PHASE_SACRIFICE:
                                    speechPhaseEnd=12;
                                    break;
                            }
                        }
                        if (Speeches[speechCount].timer < SpeechTimer)
                        {
                            SpeechTimer = 0;
                            if (pInstance)
                                if (Creature* pSpeechCreature = Unit::GetCreature(*me, pInstance->GetData64(Speeches[speechCount].pCreature)))
                                    DoScriptText(Speeches[speechCount].textid, pSpeechCreature);
                            if (speechCount == 12)
                                if (Creature* pAnveena =  Unit::GetCreature(*me, pInstance->GetData64(DATA_ANVEENA)))
                                    pAnveena->CastSpell(me, SPELL_SACRIFICE_OF_ANVEENA, false);
                                    //   ChangeTimers(true, 10000); // Kil should do an emote while screaming without attacking for 10 seconds
                            if (speechCount == speechPhaseEnd)
                                TimerIsDeactivated[TIMER_SPEECH]=true;
                            speechCount++;
                        }
                        SpeechTimer += diff;
                        break;
                    case TIMER_SOUL_FLAY:
                        if (!me->IsNonMeleeSpellCasted(false))
                        {
                            DoCast(me->getVictim(), SPELL_SOUL_FLAY_SLOW, false);
                            DoCast(me->getVictim(), SPELL_SOUL_FLAY, false);
                            Timer[TIMER_SOUL_FLAY] = 3500;
                        }
                        break;
                    case TIMER_LEGION_LIGHTNING:
                        if (!me->IsNonMeleeSpellCasted(false))
                        {
                            Unit* pRandomPlayer = NULL;

                            me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY);
                            for (uint8 z = 0; z < 6; ++z)
                            {
                                pRandomPlayer = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
                                if (!pRandomPlayer || !pRandomPlayer->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0))
                                    break;
                            }

                            if (pRandomPlayer)
                                DoCast(pRandomPlayer, SPELL_LEGION_LIGHTNING, false);
                            else
                                error_log("try to cast SPELL_LEGION_LIGHTNING on invalid target");

                            Timer[TIMER_LEGION_LIGHTNING] = (Phase == PHASE_SACRIFICE) ? 18000 : 30000; // 18 seconds in PHASE_SACRIFICE
                            Timer[TIMER_SOUL_FLAY] = 2500;
                        }
                        break;
                    case TIMER_FIRE_BLOOM:
                        if (!me->IsNonMeleeSpellCasted(false))
                        {
                            me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY);
                            DoCastAOE(SPELL_FIRE_BLOOM, false);
                            Timer[TIMER_FIRE_BLOOM] = (Phase == PHASE_SACRIFICE) ? 25000 : 40000; // 25 seconds in PHASE_SACRIFICE
                            Timer[TIMER_SOUL_FLAY] = 1000;
                        }
                        break;
                    case TIMER_SUMMON_SHILEDORB:
                        for (uint8 i = 1; i < Phase; ++i)
                        {
                            float sx, sy;
                            sx = ShieldOrbLocations[0][0] + sin(ShieldOrbLocations[i][0]);
                            sy = ShieldOrbLocations[0][1] + sin(ShieldOrbLocations[i][1]);
                            me->SummonCreature(CREATURE_SHIELD_ORB, sx, sy, SHIELD_ORB_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000);
                        }
                        Timer[TIMER_SUMMON_SHILEDORB] = urand(30000,60000); // 30-60seconds cooldown
                        Timer[TIMER_SOUL_FLAY] = 2000;
                        break;
                    case TIMER_SHADOW_SPIKE: //Phase 3
                        if (!me->IsNonMeleeSpellCasted(false))
                        {
                            CastSinisterReflection();
                            DoCastAOE(SPELL_SHADOW_SPIKE, false);
                            ChangeTimers(true, 30000);
                            Timer[TIMER_SHADOW_SPIKE] = 0;
                            TimerIsDeactivated[TIMER_SPEECH] = false;
                        }
                        break;
                    case TIMER_FLAME_DART: //Phase 3
                        DoCastAOE(SPELL_FLAME_DART, false);
                        Timer[TIMER_FLAME_DART] = 3000; //TODO Timer
                        break;
                    case TIMER_DARKNESS: //Phase 3
                        if (!me->IsNonMeleeSpellCasted(false))
                        {
                            // Begins to channel for 8 seconds, then deals 50'000 damage to all raid members.
                            if (!IsInDarkness)
                            {
                                DoScriptText(EMOTE_KJ_DARKNESS, me);
                                DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS, false);
                                ChangeTimers(true, 9000);
                                Timer[TIMER_DARKNESS] = 8750;
                                TimerIsDeactivated[TIMER_DARKNESS] = false;
                                if (Phase == PHASE_SACRIFICE)
                                    TimerIsDeactivated[TIMER_ARMAGEDDON] = false;
                                IsInDarkness = true;
                            }
                            else
                            {
                                Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(40000,70000);
                                IsInDarkness = false;
                                DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE);
                                DoScriptText(RAND(SAY_KJ_DARKNESS1,SAY_KJ_DARKNESS2,SAY_KJ_DARKNESS3), me);
                            }
                            Timer[TIMER_SOUL_FLAY] = 9000;
                        }
                        break;
                    case TIMER_ORBS_EMPOWER: //Phase 3
                        if (pInstance)
                            if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ)))
                            {
                                switch (Phase)
                                {
                                   case PHASE_SACRIFICE:
                                        CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(true);
                                        break;
                                    default:
                                        CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(false);
                                        break;
                                }
                            }
                        OrbActivated = true;
                        TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true;
                        break;
                    case TIMER_ARMAGEDDON: //Phase 4
                        Unit *pTarget = NULL;
                        for (uint8 z = 0; z < 6; ++z)
                        {
                            pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
                            if (!pTarget || !pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break;
                        }
                        if (pTarget)
                        {
                            float x, y, z;
                            pTarget->GetPosition(x, y, z);
                            me->SummonCreature(CREATURE_ARMAGEDDON_TARGET, x,y,z,0, TEMPSUMMON_TIMED_DESPAWN,15000);
                        }
                        Timer[TIMER_ARMAGEDDON] = 2000; // No, I'm not kidding
                        break;
                 }
            }
        }
        DoMeleeAttackIfReady();
        //Time runs over!
        for (uint8 i = 0; i < ActiveTimers; ++i)
            if (!TimerIsDeactivated[i])
            {
                Timer[i] -= diff;
                if (((int32)Timer[i]) < 0) Timer[i] = 0;
            }

        //Phase 3
        if (Phase <= PHASE_NORMAL && !IsInDarkness)
        {
            if (Phase == PHASE_NORMAL && HealthBelowPct(85))
            {
                Phase = PHASE_DARKNESS;
                ActiveTimers = 9;
                EnterNextPhase();
            }
            else return;
        }

        //Phase 4
        if (Phase <= PHASE_DARKNESS && !IsInDarkness)
        {
            if (Phase == PHASE_DARKNESS && HealthBelowPct(55))
            {
                Phase = PHASE_ARMAGEDDON;
                ActiveTimers = 10;
                EnterNextPhase();
            }
            else return;
        }

        //Phase 5 specific spells all we can
        if (Phase <= PHASE_ARMAGEDDON && !IsInDarkness)
        {
            if (Phase == PHASE_ARMAGEDDON && HealthBelowPct(25))
            {
                Phase = PHASE_SACRIFICE;
                EnterNextPhase();
            }
            else return;
        }
    }
TargetedMovementGenerator<T>::TargetedMovementGenerator(Unit &target, float offset, float angle)
: TargetedMovementGeneratorBase(target)
, i_offset(offset), i_angle(angle), i_recalculateTravel(false)
{
    target.GetPosition(i_targetX, i_targetY, i_targetZ);
}
Example #30
0
            void UpdateAI(uint32 diff) override
            {
                if (!UpdateVictim())
                    return;

                events.Update(diff);

                while (uint32 eventId = events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_STATIC_DISRUPTION:
                            {
                            Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
                            if (!target)
                                target = me->GetVictim();
                            if (target)
                            {
                                TargetGUID = target->GetGUID();
                                DoCast(target, SPELL_STATIC_DISRUPTION, false);
                                me->SetInFront(me->GetVictim());
                            }
                            /*if (float dist = me->IsWithinDist3d(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 5.0f) dist = 5.0f;
                            SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/
                            events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(10000, 18000));
                            break;
                            }
                        case EVENT_GUST_OF_WIND:
                            {
                                Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
                                if (!target)
                                    target = me->GetVictim();
                                if (target)
                                    DoCast(target, SPELL_GUST_OF_WIND);
                                events.ScheduleEvent(EVENT_GUST_OF_WIND, urand(20000, 30000));
                                break;
                            }
                        case EVENT_CALL_LIGHTNING:
                            DoCastVictim(SPELL_CALL_LIGHTNING);
                            events.ScheduleEvent(EVENT_CALL_LIGHTNING, urand(12000, 17000)); // totaly random timer. can't find any info on this
                            break;
                        case EVENT_ELECTRICAL_STORM:
                            {
                                Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true);
                                if (!target)
                                {
                                    EnterEvadeMode();
                                    return;
                                }
                                target->CastSpell(target, 44007, true); // cloud visual
                                DoCast(target, SPELL_ELECTRICAL_STORM, false); // storm cyclon + visual
                                float x, y, z;
                                target->GetPosition(x, y, z);
                                /// @todo: fix it in correct way, that causes player to can fly until logout
                                /*
                                if (target)
                                {
                                    target->SetDisableGravity(true);
                                    target->MonsterMoveWithSpeed(x, y, me->GetPositionZ()+15, 0);
                                }
                                */

                                Unit* Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000);
                                if (Cloud)
                                    {
                                        CloudGUID = Cloud->GetGUID();
                                        Cloud->SetDisableGravity(true);
                                        Cloud->StopMoving();
                                        Cloud->SetObjectScale(1.0f);
                                        Cloud->setFaction(35);
                                        Cloud->SetMaxHealth(9999999);
                                        Cloud->SetHealth(9999999);
                                        Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                                    }
                                StormCount = 1;
                                events.ScheduleEvent(EVENT_ELECTRICAL_STORM, 60000); // 60 seconds(bosskillers)
                                events.ScheduleEvent(EVENT_RAIN, urand(47000, 52000));
                                break;
                            }
                        case EVENT_RAIN:
                            if (!isRaining)
                            {
                                SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f);
                                isRaining = true;
                            }
                            else
                                events.ScheduleEvent(EVENT_RAIN, 1000);
                            break;
                        case EVENT_STORM_SEQUENCE:
                            {
                                Unit* target = ObjectAccessor::GetUnit(*me, CloudGUID);
                                if (!target || !target->IsAlive())
                                {
                                    EnterEvadeMode();
                                    return;
                                }
                                else if (Unit* Cyclone = ObjectAccessor::GetUnit(*me, CycloneGUID))
                                    Cyclone->CastSpell(target, SPELL_SAND_STORM, true); // keep casting or...
                                HandleStormSequence(target);
                                break;
                            }
                        case EVENT_SUMMON_EAGLES:
                            Talk(SAY_SUMMON);

                            float x, y, z;
                            me->GetPosition(x, y, z);

                            for (uint8 i = 0; i < 8; ++i)
                            {
                                Unit* bird = ObjectAccessor::GetUnit(*me, BirdGUIDs[i]);
                                if (!bird) //they despawned on die
                                {
                                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                                    {
                                        x = target->GetPositionX() + irand(-10, 10);
                                        y = target->GetPositionY() + irand(-10, 10);
                                        z = target->GetPositionZ() + urand(16, 20);
                                        if (z > 95)
                                            z = 95.0f - urand(0, 5);
                                    }
                                    Creature* creature = me->SummonCreature(NPC_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
                                    if (creature)
                                    {
                                        creature->AddThreat(me->GetVictim(), 1.0f);
                                        creature->AI()->AttackStart(me->GetVictim());
                                        BirdGUIDs[i] = creature->GetGUID();
                                    }
                                }
                            }
                            break;
                        case EVENT_ENRAGE:
                             Talk(SAY_ENRAGE);
                             DoCast(me, SPELL_BERSERK, true);
                            events.ScheduleEvent(EVENT_ENRAGE, 600000);
                            break;
                        default:
                            break;
                    }
                }

                DoMeleeAttackIfReady();
            }