Ejemplo n.º 1
0
void FollowMovementGenerator<Player>::Initialize(Player& owner)
{
    owner.addUnitState(UNIT_STAT_FOLLOW | UNIT_STAT_FOLLOW_MOVE);
    _updateSpeed(owner);
    _setTargetLocation(owner, true);
}
bool TargetedMovementGeneratorMedium<T, D>::Update(T& owner, const uint32& time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner.IsAlive())
        return true;

    if (owner.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED))
        return true;

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCast(false, false,  true) || owner.HasUnitState(UNIT_STATE_CASTING))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    if (!owner.HasAuraType(SPELL_AURA_MOD_INVISIBILITY) && !owner.CanSeeOrDetect(i_target.getTarget(), true))
    {
        owner.AttackStop();
        if (owner.GetOwner())
            owner.GetMotionMaster()->MoveFollow(owner.GetOwner(), PET_FOLLOW_DIST, owner.GetFollowAngle());
        else
            owner.StopMoving();

        return true;
    }

    // prevent crash after creature killed pet
    if (!owner.HasUnitState(UNIT_STATE_FOLLOW) && owner.getVictim() != i_target.getTarget())
        return true;

    if (i_path && i_path->getPathType() & PATHFIND_NOPATH)
    {
        if (Creature* me = owner.ToCreature())
        {
            if (m_evadeTimer <= time_diff)
            {
                if (me->AI())
                    me->AI()->EnterEvadeMode();
            }
            else
                m_evadeTimer -= time_diff;
        }
        return true;
    }

    bool targetMoved = false;
    i_recheckDistance.Update(time_diff);
    if (i_recheckDistance.Passed())
    {
        i_recheckDistance.Reset(this->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE ? 50 : 100);
        G3D::Vector3 dest = owner.movespline->FinalDestination();
        targetMoved = RequiresNewPosition(owner, dest.x, dest.y, dest.z);
    }

    if (m_speedChanged || targetMoved)
        _setTargetLocation(owner, targetMoved);

    if (owner.movespline->Finalized())
    {
        if (i_angle == 0.f && !owner.HasInArc(0.01f, i_target.getTarget()))
            owner.SetInFront(i_target.getTarget());

        if (!i_targetReached)
        {
            i_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }

    // Implemented for PetAI to handle resetting flags when pet owner reached
    if (owner.movespline->Finalized())
        MovementInform(owner);

    return true;
}
void ChaseMovementGenerator<Creature>::Initialize(Creature& owner)
{
    owner.SetWalk(false, false);                            // Chase movement is running
    owner.addUnitState(UNIT_STAT_CHASE | UNIT_STAT_CHASE_MOVE);
    _setTargetLocation(owner, true);
}
Ejemplo n.º 4
0
void ChaseMovementGenerator<Creature>::Initialize(Creature& owner)
{
    owner.SetWalk(false, false);                            // Chase movement is running
    owner.addUnitState(UNIT_STAT_CHASE);                    // _MOVE set in _SetTargetLocation after required checks
    _setTargetLocation(owner, true);
}
Ejemplo n.º 5
0
bool TargetedMovementGeneratorMedium<T, D>::Update(T& owner, const uint32& time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner.isAlive())
        return true;

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    if (this->GetMovementGeneratorType() == CHASE_MOTION_TYPE && owner.hasUnitState(UNIT_STAT_NO_COMBAT_MOVEMENT))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCasted(false, false,  true))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    bool targetMoved = false;
    i_recheckDistance.Update(time_diff);
    if (i_recheckDistance.Passed())
    {
        i_recheckDistance.Reset(100);

        // More distance let have better performance, less distance let have more sensitive reaction at target move.
        float allowed_dist = owner.GetObjectBoundingRadius() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);
        G3D::Vector3 dest = owner.movespline->FinalDestination();

        if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->CanFly())
            targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist);
        else
            targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist);

        // If we have a following angle, the followed object isn't targeting us and its orientation changed a lot -- @Rikub
        if (!targetMoved && i_angle && i_target->GetTargetGuid() != owner.GetObjectGuid()
            && fabs(i_target->GetOrientation() - i_targetAngle) > M_PI_F / 3) // => 120° arc
        {
            i_targetAngle = i_target->GetOrientation();
            targetMoved = true;
        }
    }

    if (m_speedChanged || targetMoved)
        _setTargetLocation(owner, targetMoved);

    if (owner.movespline->Finalized())
    {
        if (!owner.HasInArc(0.01f, i_target.getTarget()))
            owner.SetInFront(i_target.getTarget());

        if (!i_targetReached)
        {
            i_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }
    return true;
}
void ChaseMovementGenerator<Player>::Initialize(Player &owner)
{
    owner.AddUnitState(UNIT_STATE_CHASE|UNIT_STATE_CHASE_MOVE);
    _setTargetLocation(owner);
}
void FollowMovementGenerator<Creature>::Initialize(Creature &owner)
{
    owner.AddUnitState(UNIT_STATE_FOLLOW|UNIT_STATE_FOLLOW_MOVE);
    _updateSpeed(owner);
    _setTargetLocation(owner);
}
Ejemplo n.º 8
0
void
HomeMovementGenerator<Creature>::Initialize(Creature & owner)
{
    owner.RemoveSplineFlag(SPLINEFLAG_WALKMODE);
    _setTargetLocation(owner);
}
Ejemplo n.º 9
0
void
HomeMovementGenerator<Creature>::Initialize(Creature & owner)
{
    owner.RemoveMonsterMoveFlag(MONSTER_MOVE_WALK);
    _setTargetLocation(owner);
}
Ejemplo n.º 10
0
bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner || !owner->IsAlive())
        return false;

    if (owner->HasUnitState(UNIT_STATE_NOT_MOVE))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner->HasUnitState(UNIT_STATE_CASTING))
    {
        if (!owner->IsStopped())
            owner->StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    bool targetMoved = false;
    i_recheckDistance.Update(time_diff);
    if (i_recheckDistance.Passed())
    {
        i_recheckDistance.Reset(100);
        //More distance let have better performance, less distance let have more sensitive reaction at target move.
        float allowed_dist = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE);
        G3D::Vector3 dest = owner->movespline->FinalDestination();

        if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly())
            targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist);
        else
            targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist);
    }

    if (evadeTimer)
    {
        if (evadeTimer <= time_diff)
        {
            if ((failedCounter >= 30) && (owner->GetTypeId() == TYPEID_UNIT) && owner->IsAIEnabled)
                owner->ToCreature()->AI()->EnterEvadeMode();

            failedCounter = 0;
            evadeTimer = 0;
        }
        else
            evadeTimer -= time_diff;
    }

    if (i_recalculateTravel || targetMoved)
        _setTargetLocation(owner, targetMoved);

    if (owner->movespline->Finalized())
    {
        static_cast<D*>(this)->MovementInform(owner);
        if (i_angle == 0.f && !owner->HasInArc(0.01f, i_target.getTarget()))
            owner->SetInFront(i_target.getTarget());

        if (!i_targetReached)
        {
            i_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }

    return true;
}
bool TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!&owner || !owner.isAlive())
        return true;

    if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED))
        return true;

    // prevent movement while casting spells with cast time or channel time
    if (owner.hasUnitState(UNIT_STAT_CASTING))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
        return true;

    if (i_path && (i_path->getPathType() & PATHFIND_NOPATH))
        return true;

    Traveller<T> traveller(owner);

    if (!i_destinationHolder.HasDestination())
        _setTargetLocation(owner);

    if (i_destinationHolder.UpdateTraveller(traveller, time_diff, i_recalculateTravel || owner.IsStopped()))
    {
        // put targeted movement generators on a higher priority
        if (owner.GetObjectSize())
            i_destinationHolder.ResetUpdate(100);

        float dist = owner.GetCombatReach() + sWorld.getRate(RATE_TARGET_POS_RECALCULATION_RANGE);

        float x,y,z;
        i_target->GetPosition(x, y, z);
        PathNode next_point(x, y, z);

        bool targetMoved = false, needNewDest = false;
        if (i_path)
        {
            PathNode end_point = i_path->getEndPosition();
            next_point = i_path->getNextPosition();

            needNewDest = i_destinationHolder.HasArrived() && !inRange(next_point, i_path->getActualEndPosition(), dist, dist);

            // GetClosePoint() will always return a point on the ground, so we need to
            // handle the difference in elevation when the creature is flying
            if (owner.GetTypeId() == TYPEID_UNIT && owner.ToCreature()->canFly())
                targetMoved = i_target->GetDistanceSqr(end_point.x, end_point.y, end_point.z) >= dist * dist;
            else
                targetMoved = i_target->GetDistance2d(end_point.x, end_point.y) >= dist;
        }

        // target moved
		if (!i_path || targetMoved || needNewDest || i_recalculateTravel || owner.IsStopped())
        {
            // (re)calculate path
            _setTargetLocation(owner);

            next_point = i_path->getNextPosition();

            // Set new Angle For Map::
            owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));
         }
        // Update the Angle of the target only for Map::, no need to send packet for player
        else if (!i_angle && !owner.HasInArc(0.01f, next_point.x, next_point.y))
           owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));

        if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
        {
            i_recalculateTravel = false;
            //Angle update will take place into owner.StopMoving()
	    owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));

            owner.StopMoving();
            if (owner.IsWithinMeleeRange(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
                owner.Attack(i_target.getTarget(), true);
        }
    }

    // Implemented for PetAI to handle resetting flags when pet owner reached
    if (i_destinationHolder.HasArrived())
        MovementInform(owner);

    return true;
}
bool TargetedMovementGeneratorMedium<T, D>::Update(T& owner, const uint32& time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner.isAlive())
        return true;

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCasted(false, false, true, true))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    if (this->GetMovementGeneratorType() == CHASE_MOTION_TYPE && owner.hasUnitState(UNIT_STAT_NO_COMBAT_MOVEMENT))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCasted(false, false,  true))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    bool targetMoved = false;
    i_recheckDistance.Update(time_diff);
    if (i_recheckDistance.Passed())
    {
        i_recheckDistance.Reset(this->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE ? 50 : 100);
        G3D::Vector3 dest = owner.movespline->FinalDestination();
        targetMoved = RequiresNewPosition(owner, dest.x, dest.y, dest.z);
    }

    if (m_speedChanged || targetMoved)
        _setTargetLocation(owner, targetMoved);

    if (owner.movespline->Finalized())
    {
        if (i_angle == 0.f && !owner.HasInArc(i_target.getTarget(), 0.01f))
            owner.SetInFront(i_target.getTarget());

        if (!i_targetReached)
        {
            i_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }
    return true;
}
bool TargetedMovementGeneratorMedium<T,D>::DoUpdate(T* owner, uint32 time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner || !owner->isAlive())
        return false;

    if (owner->HasUnitState(UNIT_STATE_NOT_MOVE))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner->HasUnitState(UNIT_STATE_CASTING))
    {
        if (!owner->IsStopped())
            owner->StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // Check whether pet got send to cast a spell
    if (i_spell)
    {
        SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i_spell);
        Spell* spell = new Spell(owner->ToUnit(), spellInfo, TRIGGERED_NONE);
        SpellCastResult result = spell->CheckPetCast(i_target.getTarget());
        if (result == SPELL_CAST_OK)
        {
            spell->prepare(&(spell->m_targets));
            // Reset i_spell here to prevent chaincasting.
            i_spell = 0;
        }
        else
        {
            spell->finish(false);
            delete spell;
        }
    }

    bool targetMoved = false;
    i_recheckDistance.Update(time_diff);
    if (i_recheckDistance.Passed())
    {
        i_recheckDistance.Reset(100);
        //More distance let have better performance, less distance let have more sensitive reaction at target move.
        float allowed_dist = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE);
        G3D::Vector3 dest = owner->movespline->FinalDestination();

        targetMoved = !(i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist) && i_target->IsWithinLOS(dest.x, dest.y, dest.z));
    }

    if (i_recalculateTravel || targetMoved)
        _setTargetLocation(owner, targetMoved);

    if (owner->movespline->Finalized())
    {
        static_cast<D*>(this)->MovementInform(owner);
        if (i_angle == 0.f && !owner->HasInArc(0.01f, i_target.getTarget()))
            owner->SetInFront(i_target.getTarget());

        if (!i_targetReached)
        {
            i_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }

    return true;
}
Ejemplo n.º 14
0
bool TargetedMovementGeneratorMedium<T, D>::Update(T& owner, const uint32& time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner.isAlive())
        return true;

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCasted(false, false,  true))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    i_recheckDistance.Update(time_diff);
    if (i_recheckDistance.Passed())
    {
        i_recheckDistance.Reset(100);

        //More distance let have better performance, less distance let have more sensitive reaction at target move.
        float allowed_dist = owner.GetObjectBoundingRadius() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);
        G3D::Vector3 dest = owner.movespline->FinalDestination();

        bool targetMoved = false;
        if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->CanFly())
            targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist);
        else
            targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist);

        if (targetMoved)
            _setTargetLocation(owner);
    }

    if (owner.movespline->Finalized())
    {
        if (i_angle == 0.f && !owner.HasInArc(0.01f, i_target.getTarget()))
            owner.SetInFront(i_target.getTarget());

        if (!i_targetReached)
        {
            i_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }
    else
    {
        if (i_recalculateTravel)
            _setTargetLocation(owner);
    }
    return true;
}
bool
TargetedMovementGenerator<T>::Update(T &owner, const uint32 time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!&owner || !owner.isAlive())
        return true;

    if (owner.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED))
        return true;

    // prevent movement while casting spells with cast time or channel time
    if (owner.HasUnitState(UNIT_STAT_CASTING))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (!owner.HasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
        return true;

    Traveller<T> traveller(owner);

    if (!i_destinationHolder.HasDestination())
        _setTargetLocation(owner);
    else if (owner.IsStopped() && !i_destinationHolder.HasArrived())
    {
        owner.AddUnitState(UNIT_STAT_CHASE);
        i_destinationHolder.StartTravel(traveller);
        return true;
    }

    if (i_destinationHolder.UpdateTraveller(traveller, time_diff))
    {
        // put targeted movement generators on a higher priority
        //if (owner.GetObjectSize())
        //i_destinationHolder.ResetUpdate(50);

        // target moved
        if (i_targetX != i_target->GetPositionX() || i_targetY != i_target->GetPositionY()
            || i_targetZ != i_target->GetPositionZ())
        {
            if (_setTargetLocation(owner) || !owner.HasUnitState(UNIT_STAT_FOLLOW))
                owner.SetInFront(i_target.getTarget());
            i_target->GetPosition(i_targetX, i_targetY, i_targetZ);
        }

        if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
        {
            i_recalculateTravel = false;
            //Angle update will take place into owner.StopMoving()
            owner.SetInFront(i_target.getTarget());

            owner.StopMoving();
            if (owner.IsWithinMeleeRange(i_target.getTarget()) && !owner.HasUnitState(UNIT_STAT_FOLLOW))
                owner.Attack(i_target.getTarget(), true);
        }
    }

    // Implemented for PetAI to handle resetting flags when pet owner reached
    if (i_destinationHolder.HasArrived())
        MovementInform(owner);

    return true;
}
Ejemplo n.º 16
0
bool
TargetedMovementGenerator::Update(Creature &owner, const uint32 & time_diff)
{
    if( !&owner || !owner.isAlive() || !&i_target )
        return true;
    if( owner.hasUnitState(UNIT_STAT_ROOT) || owner.hasUnitState(UNIT_STAT_STUNDED) || owner.hasUnitState(UNIT_STAT_FLEEING))
        return true;
    if( !owner.isInCombat() && !owner.hasUnitState(UNIT_STAT_FOLLOW) )
    {
        //owner.AIM_Initialize();   This case must be the one, when a creature aggroed you. By Initalized a new AI, we prevented to Ai::_stopAttack() to be executed properly.
        return true;
    }

    // prevent crash after creature killed pet
    if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != &i_target)
        return true;

    Traveller<Creature> traveller(owner);

    if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
    {
        // put targeted movement generators on a higher priority
        if (owner.GetObjectSize())
            i_destinationHolder.ResetUpdate(50);

        float  dist = i_target.GetObjectSize() + owner.GetObjectSize() + OBJECT_CONTACT_DISTANCE;

        // try to counter precision differences
        if( i_destinationHolder.GetDistanceFromDestSq(i_target) > dist * dist + 0.1)
            _setTargetLocation(owner, 0);
        else if ( !owner.HasInArc( 0.1f, &i_target ) )
        {
            owner.SetInFront(&i_target);
            if( i_target.GetTypeId() == TYPEID_PLAYER )
                owner.SendUpdateToPlayer( (Player*)&i_target );
        }
        if( !owner.IsStopped() && i_destinationHolder.HasArrived())
        {
            owner.StopMoving();
            if(owner.canReachWithAttack(&i_target) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
                owner.Attack(&i_target);
        }
    }
    /*

         //SpellEntry* spellInfo;
        if( reach )
        {
            if( owner.GetDistance2dSq( &i_target ) > 0.0f )
            {
                DEBUG_LOG("MOVEMENT : Distance = %f",owner.GetDistance2dSq( &i_target ));
                owner.addUnitState(UNIT_STAT_CHASE);
                _setTargetLocation(owner, 0);
            }
            else if ( !owner.HasInArc( 0.0f, &i_target ) )
            {
                DEBUG_LOG("MOVEMENT : Orientation = %f",owner.GetAngle(&i_target));
                owner.SetInFront(&i_target);
                if( i_target.GetTypeId() == TYPEID_PLAYER )
                    owner.SendUpdateToPlayer( (Player*)&i_target );
            }
            if( !owner.isInCombat() )
            {
                owner.AIM_Initialize();
                return;
            }
        }
        else if( i_target.isAlive() )
        {
            if( !owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.isInCombat() )
            {
                if( spellInfo = owner.reachWithSpellAttack( &i_target ) )
                {
                    _spellAtack(owner, spellInfo);
                    return;
                }
            }
            if( owner.GetDistance2dSq( &i_target ) > 0.0f )
            {
                DEBUG_LOG("MOVEMENT : Distance = %f",owner.GetDistance2dSq( &i_target ));
                owner.addUnitState(UNIT_STAT_CHASE);
                _setTargetLocation(owner, 0);
            }
        }
        else if( !i_targetedHome )
        {
            if( !owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.isInCombat() && (spellInfo = owner.reachWithSpellAttack(&i_target)) )
            {
                _spellAtack(owner, spellInfo);
                return;
            }
            _setTargetLocation(owner, 0);
            if(reach)
            {
                if( reach && owner.canReachWithAttack(&i_target) )
                {
                    owner.StopMoving();
                    if(!owner.hasUnitState(UNIT_STAT_FOLLOW))
                        owner.Attack(&i_target);
                    owner.clearUnitState(UNIT_STAT_CHASE);
                    DEBUG_LOG("UNIT IS THERE");
                }
                else
                {
                    _setTargetLocation(owner, 0);
                    DEBUG_LOG("Continue to chase");
                }
            }
        }*/
    return true;
}
Ejemplo n.º 17
0
void HomeMovementGenerator<Creature>::Initialize(Creature & owner)
{
    _setTargetLocation(owner);
}
bool TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!&owner || !owner.isAlive())
        return true;

    if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED))
        return true;

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCasted(false, false,  true) || owner.hasUnitState(UNIT_STAT_CASTING))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    if (!owner.HasAuraType(SPELL_AURA_MOD_INVISIBILITY) && !owner.canSeeOrDetect(i_target.getTarget(), true))
    {
        owner.AttackStop();
        if (owner.GetOwner())
            owner.GetMotionMaster()->MoveFollow(owner.GetOwner(), PET_FOLLOW_DIST, owner.GetFollowAngle());
        else
            owner.StopMoving();

        return true;
    }

    // prevent crash after creature killed pet
    if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
        return true;

    if (m_usePathfinding)
    {
        if (i_path && (i_path->getPathType() & PATHFIND_NOPATH))
            return true;

        Traveller<T> traveller(owner);

        if (!i_destinationHolder.HasDestination())
            _setTargetLocation(owner);

        if (i_destinationHolder.UpdateTraveller(traveller, time_diff, i_recalculateTravel || owner.IsStopped()))
        {
            // put targeted movement generators on a higher priority
            if (owner.GetCombatReach())
                i_destinationHolder.ResetUpdate(100);

            float x,y,z;
            i_target->GetPosition(x, y, z);
            PathNode next_point(x, y, z);

            bool targetMoved = false, needNewDest = false;
            bool forceRecalc = i_recalculateTravel || owner.IsStopped();
            if (i_path && !forceRecalc)
            {
                PathNode end_point = i_path->getEndPosition();
                next_point = i_path->getNextPosition();

                //More distance let have better performance, less distance let have more sensitive reaction at target move.
                float dist = owner.GetCombatReach() + sWorld.getRate(RATE_TARGET_POS_RECALCULATION_RANGE);

                needNewDest = i_destinationHolder.HasArrived() && (!i_path->inRange(next_point, i_path->getActualEndPosition(), dist, dist) || !owner.IsWithinLOSInMap(i_target.getTarget()));

                if (!needNewDest)
                {
                    // GetClosePoint() will always return a point on the ground, so we need to
                    // handle the difference in elevation when the creature is flying
                    if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
                        targetMoved = i_target->GetDistanceSqr(end_point.x, end_point.y, end_point.z) > dist*dist;
                    else
                        targetMoved = i_target->GetDistance2d(end_point.x, end_point.y) > dist;
                }
            }

            // target moved
            if (!i_path || targetMoved || needNewDest || forceRecalc)
            {
                // (re)calculate path
                _setTargetLocation(owner);

                next_point = i_path->getNextPosition();

                // Set new Angle For Map::
                owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));
            }
            // Update the Angle of the target only for Map::, no need to send packet for player
            else if (!i_angle && !owner.HasInArc(0.01f, next_point.x, next_point.y))
                owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));

            if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
            {
                i_recalculateTravel = false;
                //Angle update will take place into owner.StopMoving()
                owner.SetInFront(i_target.getTarget());

                owner.StopMoving();
                if (owner.IsWithinMeleeRange(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
                    owner.Attack(i_target.getTarget(), true);
            }
        }
    }
    else
    {
        Traveller<T> traveller(owner);

        if (!i_destinationHolder.HasDestination())
        {
            _setTargetLocation(owner);
        }
        else if (owner.IsStopped() && !i_destinationHolder.HasArrived())
        {
            owner.addUnitState(UNIT_STAT_CHASE);
            i_destinationHolder.StartTravel(traveller);
            return true;
        }

        if (i_destinationHolder.UpdateTraveller(traveller, time_diff))
        {
            // target moved
            if (i_targetX != i_target->GetPositionX() || i_targetY != i_target->GetPositionY()
                || i_targetZ != i_target->GetPositionZ())
            {
                if (_setTargetLocation(owner) || !owner.hasUnitState(UNIT_STAT_FOLLOW))
                    owner.SetInFront(i_target.getTarget());
                i_target->GetPosition(i_targetX, i_targetY, i_targetZ);
            }

            if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
            {
                i_recalculateTravel = false;
                //Angle update will take place into owner.StopMoving()
                owner.SetInFront(i_target.getTarget());

                owner.StopMoving();
                if (owner.IsWithinMeleeRange(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
                    owner.Attack(i_target.getTarget(),true);
            }
        }
    }

    // Implemented for PetAI to handle resetting flags when pet owner reached
    if (i_destinationHolder.HasArrived())
        MovementInform(owner);

    return true;
}
void ChaseMovementGenerator<Creature>::Initialize(Creature &owner)
{
    owner.SetWalk(false);
    owner.AddUnitState(UNIT_STATE_CHASE|UNIT_STATE_CHASE_MOVE);
    _setTargetLocation(owner);
}
Ejemplo n.º 20
0
bool TargetedMovementGeneratorMedium<T,D>::DoUpdate(T* owner, uint32 time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner || !owner->IsAlive())
        return false;

    if (owner->HasUnitState(UNIT_STATE_NOT_MOVE))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner->HasUnitState(UNIT_STATE_CASTING))
    {
		bool stop = true;
		if (Spell* spell = owner->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
			if (!(spell->GetSpellInfo()->ChannelInterruptFlags & (AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING)) && !(spell->GetSpellInfo()->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT))
				stop = false;

		if (stop)
		{
			// Xinef: delay distance recheck in case of succeeding casts
			i_recheckDistance.Reset(300);
			if (!owner->IsStopped())
				owner->StopMoving();

			return true;
		}
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

	i_recheckDistanceForced.Update(time_diff);
	if (i_recheckDistanceForced.Passed())
	{
		i_recheckDistanceForced.Reset(2500);
		lastOwnerXYZ.Relocate(-5000.0f, -5000.0f, -5000.0f);
	}

    i_recheckDistance.Update(time_diff);
    if (i_recheckDistance.Passed())
    {
        i_recheckDistance.Reset(50);
        //More distance let have better performance, less distance let have more sensitive reaction at target move.
        float allowed_dist_sq = i_target->GetObjectSize() + owner->GetObjectSize() + MELEE_RANGE - 0.5f;

		// xinef: if offset is negative (follow distance is smaller than just object sizes), reduce minimum allowed distance which is based purely on object sizes
		if (i_offset < 0.0f)
		{
			allowed_dist_sq += i_offset;
			allowed_dist_sq = std::max<float>(0.0f, allowed_dist_sq);
		}

		allowed_dist_sq *= allowed_dist_sq;

        G3D::Vector3 dest = owner->movespline->FinalDestination();
        if (owner->movespline->onTransport)
            if (TransportBase* transport = owner->GetDirectTransport())
                transport->CalculatePassengerPosition(dest.x, dest.y, dest.z);

        float dist = (dest - G3D::Vector3(i_target->GetPositionX(),i_target->GetPositionY(),i_target->GetPositionZ())).squaredLength();
        float targetMoveDistSq = i_target->GetExactDistSq(&lastTargetXYZ);
        if (dist >= allowed_dist_sq || (!i_offset && targetMoveDistSq >= 1.5f*1.5f))
            if (targetMoveDistSq >= 0.1f*0.1f || owner->GetExactDistSq(&lastOwnerXYZ) >= 0.1f*0.1f)
                _setTargetLocation(owner, false);
    }

    if (owner->movespline->Finalized())
    {
        static_cast<D*>(this)->MovementInform(owner);
        if (i_angle == 0.f && !owner->HasInArc(0.01f, i_target.getTarget()))
            owner->SetInFront(i_target.getTarget());

        if (!i_targetReached)
        {
            i_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }
    else
    {
        if (i_recalculateTravel)
            _setTargetLocation(owner, false);
    }
    return true;
}
Ejemplo n.º 21
0
void ChaseMovementGenerator<Player>::Initialize(Player& owner)
{
    owner.addUnitState(UNIT_STAT_CHASE);                    // _MOVE set in _SetTargetLocation after required checks
    _setTargetLocation(owner, true);
}
Ejemplo n.º 22
0
bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner.isAlive())
        return true;

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE | UNIT_STAT_ON_VEHICLE))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCasted(false, false,  true))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    Traveller<T> traveller(owner);

    if (!i_destinationHolder.HasDestination())
        _setTargetLocation(owner);
    if (owner.IsStopped() && !i_destinationHolder.HasArrived())
    {
        D::_addUnitStateMove(owner);
        float x,y,z;
        i_destinationHolder.GetLocationNowNoMicroMovement(x,y,z);
        if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly() &&
            !(((Creature*)&owner)->canWalk() && ((Creature*)&owner)->IsAtGroundLevel(x,y,z)))
            ((Creature&)owner).AddSplineFlag(SPLINEFLAG_UNKNOWN7);

        i_destinationHolder.StartTravel(traveller);
        return true;
    }

    if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
    {
        if (!IsActive(owner))                               // force stop processing (movement can move out active zone with cleanup movegens list)
            return true;                                    // not expire now, but already lost

        // put targeted movement generators on a higher priority
        if (owner.GetObjectBoundingRadius())
            i_destinationHolder.ResetUpdate(50);

        float dist = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);

        //More distance let have better performance, less distance let have more sensitive reaction at target move.

        // try to counter precision differences
        if (i_destinationHolder.GetDistance3dFromDestSq(*i_target.getTarget()) >= dist * dist)
        {
            owner.SetInFront(i_target.getTarget());         // Set new Angle For Map::
            _setTargetLocation(owner);                      //Calculate New Dest and Send data To Player
        }
        // Update the Angle of the target only for Map::, no need to send packet for player
        else if (!i_angle && !owner.HasInArc(0.01f, i_target.getTarget()))
            owner.SetInFront(i_target.getTarget());

        if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
        {
            i_recalculateTravel = false;
            //Angle update will take place into owner.StopMoving()
            owner.SetInFront(i_target.getTarget());

            owner.StopMoving();
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }
    return true;
}
Ejemplo n.º 23
0
void FollowMovementGenerator<Creature>::Initialize(Creature& owner)
{
    owner.addUnitState(UNIT_STAT_FOLLOW);                   // _MOVE set in _SetTargetLocation after required checks
    _updateSpeed(owner);
    _setTargetLocation(owner, true);
}
Ejemplo n.º 24
0
void HomeMovementGenerator<Creature>::Initialize(Creature & owner)
{
    owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
    owner.AddUnitState(UNIT_STAT_EVADE);
    _setTargetLocation(owner);
}
Ejemplo n.º 25
0
void
HomeMovementGenerator<Creature>::Initialize(Creature & owner)
{
    owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
    _setTargetLocation(owner);
}
Ejemplo n.º 26
0
bool TargetedMovementGeneratorMedium<T, D>::Update(T& owner, const uint32& time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE) || (owner.IsInUnitState(UNIT_ACTION_CHASE) && owner.hasUnitState(UNIT_STAT_NO_COMBAT_MOVEMENT)))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCasted(false, false,  true))
    {
        if (!owner.IsStopped())
        {
            // some spells should be able to be cast while moving
            // maybe some attribute? here, check the entry of creatures useing these spells
            switch(owner.GetEntry())
            {
                case 36633: // Ice Sphere (Lich King)
                case 37562: // Volatile Ooze and Gas Cloud (Putricide)
                case 37697:
                    break;
                default:
                    owner.StopMoving();
                    break;
            }
        }
        if (owner.IsStopped())
            return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        if (i_targetSearchingTimer >= TARGET_NOT_ACCESSIBLE_MAX_TIMER)
            return false;
        else
        {
            i_targetSearchingTimer += 5 * time_diff;
            return true;
        }
    }

    if (!i_target->isInAccessablePlaceFor(&owner))
        return true;

    bool targetMoved = false;

    i_recheckDistance.Update(time_diff);
    if (i_recheckDistance.Passed())
    {
        i_recheckDistance.Reset(RECHECK_DISTANCE_TIMER);

        //More distance let have better performance, less distance let have more sensitive reaction at target move.
        //float allowed_dist = owner.GetObjectBoundingRadius() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);

        float allowed_dist = 0.0f;
        bool targetIsVictim = owner.getVictim() && owner.getVictim()->GetObjectGuid() == i_target->GetObjectGuid();
        if (targetIsVictim)
            allowed_dist = owner.GetMeleeAttackDistance(owner.getVictim()) + owner.GetObjectBoundingRadius();
        else
            allowed_dist = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);

        if (allowed_dist < owner.GetObjectBoundingRadius())
            allowed_dist = owner.GetObjectBoundingRadius();

        G3D::Vector3 dest = owner.movespline->FinalDestination();

        if (owner.GetTypeId() == TYPEID_UNIT && (((Creature*)&owner)->CanFly() || ((Creature*)&owner)->IsLevitating()))
            targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist);
        else
            targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist);

        if (targetIsVictim && owner.GetTypeId() == TYPEID_UNIT && !((Creature*)&owner)->IsPet())
        {
            if ((!owner.getVictim() || !owner.getVictim()->isAlive()) && owner.movespline->Finalized())
                return false;

            if (!i_offset && owner.movespline->Finalized() && !owner.CanReachWithMeleeAttack(owner.getVictim())
                && !i_target->m_movementInfo.HasMovementFlag(MOVEFLAG_PENDINGSTOP))
            {
                if (i_targetSearchingTimer >= TARGET_NOT_ACCESSIBLE_MAX_TIMER)
                {
                    return false;
                }
                else
                {
                    i_targetSearchingTimer += RECHECK_DISTANCE_TIMER;
                    targetMoved = true;
                }
            }
            else
                i_targetSearchingTimer = 0;
        }
        else
            i_targetSearchingTimer = 0;
    }

    if (m_speedChanged || targetMoved)
        _setTargetLocation(owner, true);

    if (m_speedChanged || targetMoved)
        _setTargetLocation(owner, targetMoved);

    if (owner.movespline->Finalized())
    {
        if (fabs(i_angle) < M_NULL_F && !owner.HasInArc(0.01f, i_target.getTarget()))
            owner.SetInFront(i_target.getTarget());

        if (!i_targetReached)
        {
            i_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }
    return true;
};
void ChaseMovementGenerator<Player>::Initialize(Player& owner)
{
    owner.AddUnitState(UNIT_STATE_CHASE);                    // _MOVE set in _SetTargetLocation after required checks
    _setTargetLocation(owner, true);
    m_evadeTimer = urand(4000, 8000);
}
bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_diff)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

    if (!owner.isAlive())
        return true;

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (owner.IsNonMeleeSpellCasted(false, false,  true))
    {
        if (!owner.IsStopped())
            owner.StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    if (i_path && (i_path->getPathType() & PATHFIND_NOPATH))
        return true;

    Traveller<T> traveller(owner);

    if (!i_destinationHolder.HasDestination())
        _setTargetLocation(owner);

    if (i_destinationHolder.UpdateTraveller(traveller, time_diff, i_recalculateTravel || owner.IsStopped()))
    {
        if (!IsActive(owner))                               // force stop processing (movement can move out active zone with cleanup movegens list)
            return true;                                    // not expire now, but already lost

        // put targeted movement generators on a higher priority
        if (owner.GetObjectBoundingRadius())
            i_destinationHolder.ResetUpdate(100);

        //More distance let have better performance, less distance let have more sensitive reaction at target move.
        float dist = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + sWorld.getConfig(RATE_TARGET_POS_RECALCULATION_RANGE);

        float x,y,z;
        i_target->GetPosition(x, y, z);
        PathNode next_point(x, y, z);

        bool targetMoved = false, needNewDest = false;
        if (i_path)
        {
            PathNode end_point = i_path->getEndPosition();
            next_point = i_path->getNextPosition();

            needNewDest = i_destinationHolder.HasArrived() && !inRange(next_point, i_path->getActualEndPosition(), dist, 2*dist);

            // GetClosePoint() will always return a point on the ground, so we need to
            // handle the difference in elevation when the creature is flying
            if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
                targetMoved = i_target->GetDistanceSqr(end_point.x, end_point.y, end_point.z) >= dist*dist;
            else
                targetMoved = i_target->GetDistance2d(end_point.x, end_point.y) >= dist;
        }

        if (!i_path || targetMoved || needNewDest || i_recalculateTravel || owner.IsStopped())
        {
            // (re)calculate path
            _setTargetLocation(owner);

            next_point = i_path->getNextPosition();

            // Set new Angle For Map::
            owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));
        }
        // Update the Angle of the target only for Map::, no need to send packet for player
        else if (!i_angle && !owner.HasInArc(0.01f, next_point.x, next_point.y))
            owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));

        if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
        {
            i_recalculateTravel = false;

            //Angle update will take place into owner.StopMoving()
            owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));

            owner.StopMoving();
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }
    return true;
}