void RandomMovementGenerator<Creature>::Initialize(Creature &creature)
{
    if (!creature.isAlive())
        return;

    if (creature.canFly() && !(creature.canWalk() &&
        creature.IsAtGroundLevel()))
        creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);
    else
        creature.AddSplineFlag(SPLINEFLAG_WALKMODE);

    creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
    _setRandomLocation(creature);
}
Example #2
0
void WaypointMovementGenerator<Creature>::InitTraveller(Creature &unit, const WaypointData &node)
{
    node.run ? unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING):
        unit.AddUnitMovementFlag(MOVEMENTFLAG_WALKING);

    unit.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
    unit.SetUInt32Value(UNIT_FIELD_BYTES_1, 0);

    // TODO: make this part of waypoint node, so that creature can walk when desired?
    if (unit.canFly())
        unit.SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02);

    unit.addUnitState(UNIT_STAT_ROAMING);
}
Example #3
0
bool RandomCircleMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{   
    if (creature.hasUnitState(UNIT_STAT_NOT_MOVE | UNIT_STAT_ON_VEHICLE))
    {
        i_nextMoveTime.Update(i_nextMoveTime.GetExpiry());  // Expire the timer
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
        return true;
    }

    i_nextMoveTime.Update(diff);

    if (!creature.IsStopped() && !creature.canFly())
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);

    if (creature.IsStopped())
        creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

    if (!IsActive(creature))                        // force stop processing (movement can move out active zone with cleanup movegens list)
    {
        Interrupt(creature);
        return true;
    }

    if (m_splineMap.empty())
    {
        Reset(creature);
        return true;
    }

    if (i_nextMoveTime.Passed())
    {
        if (m_splineMap.find(i_wpId) == m_splineMap.end())
        {
            Reset(creature);
            return true;
        }
        SplineWayPointMap::iterator wp = m_splineMap.find(i_wpId);
        //rellocate but not send
        creature.Relocate(wp->second->x, wp->second->y, wp->second->z, wp->second->o); 
        if (i_wpId == 29) // not last wp
        {
            Initialize(creature);
            return true;
        }
        i_wpId++;
        i_nextMoveTime.Reset(500);
    }
    return true;
}
Example #4
0
void AssistanceMovementGenerator::Initialize(Creature& unit)
{
    if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT | UNIT_STAT_CAN_NOT_MOVE))
        return;

    if (!unit.IsStopped())
        unit.StopMoving();

    unit.addUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE);
    Movement::MoveSplineInit init(unit, "AssistanceMovementGenerator::Initialize");
    init.MoveTo(i_x, i_y, i_z, (_options & (MOVE_PATHFINDING | MOVE_FORCE_DESTINATION)));
    init.SetWalk(true);
    init.SetVelocity(unit.GetFleeingSpeed());
    init.Launch();
}
void FollowMovementGenerator<Creature>::Initialize(Creature &owner)
{
    owner.addUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
    _updateWalkMode(owner);
    _updateSpeed(owner);

    _setTargetLocation(owner);

    float x,y,z;
    i_destinationHolder.GetDestination(x,y,z);

    if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly() &&
        !(((Creature*)&owner)->canWalk() && ((Creature*)&owner)->IsAtGroundLevel(x,y,z)))
        owner.AddSplineFlag(SPLINEFLAG_UNKNOWN7);
}
void
TargetedMovementGenerator::_setTargetLocation(Creature &owner, float offset)
{
    if( !&i_target || !&owner )
        return;

    if( owner.hasUnitState(UNIT_STAT_ROOT) || owner.hasUnitState(UNIT_STAT_STUNDED) )
        return;

    float x, y, z;
    i_target.GetContactPoint( &owner, x, y, z );
    Traveller<Creature> traveller(owner);
    i_destinationHolder.SetDestination(traveller, x, y, z, offset);
    owner.addUnitState(UNIT_STAT_CHASE);
}
Example #7
0
 void SpawnAdds()
 {
     Creature *pCreature = NULL;
     for (uint8 i = 0; i < 4; ++i)
     {
         pCreature = me->SummonCreature(SpiritInfo[i].entry, SpiritInfo[i].x, SpiritInfo[i].y, SpiritInfo[i].z, SpiritInfo[i].orient, TEMPSUMMON_DEAD_DESPAWN, 0);
         if (pCreature)
         {
             pCreature->CastSpell(pCreature, SPELL_SPIRIT_AURA, true);
             pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
             pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
             pCreature->addUnitState(UNIT_STAT_STUNNED);
             SpiritGUID[i] = pCreature->GetGUID();
         }
     }
 }
bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if (creature.hasUnitState(UNIT_STAT_NOT_MOVE))
    {
        i_nextMoveTime.Update(i_nextMoveTime.GetExpiry());  // Expire the timer
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
        return true;
    }

    i_nextMoveTime.Update(diff);

    if (i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly())
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);

    if (!i_destinationHolder.HasArrived() && creature.IsStopped())
        creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

    CreatureTraveller traveller(creature);

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

        if (i_nextMoveTime.Passed())
        {
            float x,y,z;
            if(i_destinationHolder.HasDestination())
                i_destinationHolder.GetLocationNowNoMicroMovement(x,y,z);
            else
                creature.GetPosition(x,y,z);

            if (creature.canFly() && !(creature.canWalk() && creature.IsAtGroundLevel(x,y,z)))
                creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);
            else
                creature.AddSplineFlag(SPLINEFLAG_WALKMODE);

            _setRandomLocation(creature);
        }
        else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST+2.5f))
        {
            creature.AddSplineFlag(SPLINEFLAG_WALKMODE);
            _setRandomLocation(creature);
        }
    }
    return true;
}
bool
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if(!&creature)
        return true;
    if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
        return true;
    i_nextMoveTime.Update(diff);
#ifdef USE_INTERPOLATION
    CreatureTraveller traveller(creature);
    i_destinationHolder.UpdateTraveller(traveller, diff, false);
#endif
    if( i_nextMoveTime.Passed() )
    {
        if( creature.IsStopped() )
        {
            assert( i_nextMove <= MAX_RAND_WAYPOINTS );
            const float x = i_waypoints[i_nextMove][0];
            const float y = i_waypoints[i_nextMove][1];
            const float z = i_waypoints[i_nextMove][2];
            creature.addUnitState(UNIT_STAT_ROAMING);
            CreatureTraveller traveller(creature);
            i_destinationHolder.SetDestination(traveller, x, y, z);
#ifndef USE_INTERPOLATION
            traveller.Relocation(x,y,z);
#endif
            i_nextMoveTime.Reset( i_destinationHolder.GetTotalTravelTime() );
        }
        else
        {
            creature.StopMoving();
            creature.setMoveRunFlag(!urand(0,10));

            ++i_nextMove;
            if( i_nextMove == MAX_RAND_WAYPOINTS )
            {
                i_nextMove = 0;
                i_nextMoveTime.Reset(urand(0, 3000-1));     // TODO: check the lower bound (it is probably too small)
            }
            else
            {
                i_nextMoveTime.Reset(urand(0, 7000-1));     // TODO: check the lower bound (it is probably too small)
            }
        }
    }
    return true;
}
Example #10
0
void RandomCircleMovementGenerator<Creature>::Initialize(Creature &creature)
{
    if (!creature.isAlive())
        return;

    if (creature.canFly() && !(creature.canWalk() &&
        creature.IsAtGroundLevel(creature.GetPositionX(), creature.GetPositionY(), creature.GetPositionZ())))
        creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);
    else
        creature.AddSplineFlag(SPLINEFLAG_WALKMODE);

    creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
    m_bClockWise = urand(0, 1) ? true : false;
    i_wpId = 0;
    fillSplineWayPoints(creature);
    SplineFlags flags = SplineFlags(SPLINEFLAG_FORWARD | SPLINEFLAG_UNKNOWN7 | SPLINEFLAG_FLYING | creature.GetSplineFlags());
    creature.SendSplineMove(&m_splineMap, SPLINETYPE_NORMAL, flags, 500, NULL);
}
void WaypointMovementGenerator<Creature>::StartMove(Creature& creature)
{
    if (!i_path || i_path->empty())
        return;

    if (Stopped(creature))
        return;

    if (!creature.isAlive() || creature.hasUnitState(UNIT_STAT_NOT_MOVE))
        return;

    WaypointPath::const_iterator currPoint = i_path->find(i_currentNode);
    BLIZZLIKE_ASSERT(currPoint != i_path->end());

    if (WaypointBehavior* behavior = currPoint->second.behavior)
    {
        if (behavior->model2 != 0)
            creature.SetDisplayId(behavior->model2);
        creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
    }

    if (m_isArrivalDone)
    {
        ++currPoint;
        if (currPoint == i_path->end())
            currPoint = i_path->begin();

        i_currentNode = currPoint->first;
    }

    m_isArrivalDone = false;

    creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

    WaypointNode const& nextNode = currPoint->second;;
    Movement::MoveSplineInit init(creature);
    init.MoveTo(nextNode.x, nextNode.y, nextNode.z, true);

    if (nextNode.orientation != 100 && nextNode.delay != 0)
        init.SetFacing(nextNode.orientation);
    creature.SetWalk(!creature.hasUnitState(UNIT_STAT_RUNNING_STATE) && !creature.IsLevitating(), false);
    init.Launch();
}
Example #12
0
bool
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
    {
        i_nextMoveTime.Update(i_nextMoveTime.GetExpiry());    // Expire the timer
        creature.clearUnitState(UNIT_STAT_ROAMING);
        return true;
    }

    i_nextMoveTime.Update(diff);

    if(i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly())
        creature.clearUnitState(UNIT_STAT_ROAMING);

    if(!i_destinationHolder.HasArrived() && creature.IsStopped())
        creature.addUnitState(UNIT_STAT_ROAMING);

    CreatureTraveller traveller(creature);

    if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) )
    {
        if(i_nextMoveTime.Passed())
        {
            if (creature.canFly())
                creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY);
            else if(irand(0,RUNNING_CHANCE_RANDOMMV) > 0)
                creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK);
            else                                            // run with 1/RUNNING_CHANCE_RANDOMMV chance
                creature.RemoveMonsterMoveFlag(MONSTER_MOVE_WALK);

            _setRandomLocation(creature);
        }
        else if(creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(),PET_FOLLOW_DIST+2.5f))
        {
           creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK);
           _setRandomLocation(creature);
        }
    }
    return true;
}
Example #13
0
bool
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if (creature.hasUnitState(UNIT_STAT_NOT_MOVE & ~UNIT_STAT_ON_VEHICLE))
    {
        i_nextMoveTime.Update(i_nextMoveTime.GetExpiry());  // Expire the timer
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);;
        return true;
    }

    i_nextMoveTime.Update(diff);

    if (i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly())
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);

    if (!i_destinationHolder.HasArrived() && creature.IsStopped())
        creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

    CreatureTraveller traveller(creature);

    if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true))
    {
        if (i_nextMoveTime.Passed())
        {
            if (creature.canFly())
                creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);
            else
                creature.AddSplineFlag(SPLINEFLAG_WALKMODE);

            _setRandomLocation(creature);
        }
        else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST+2.5f))
        {
            creature.AddSplineFlag(SPLINEFLAG_WALKMODE);
            _setRandomLocation(creature);
        }
    }
    return true;
}
Example #14
0
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
{
    const float angle = rand_norm_f() * (M_PI_F * 2.0f);
    const float range = rand_norm_f() * i_radius;

    float destX = i_x + range * cos(angle);
    float destY = i_y + range * sin(angle);
    float destZ = i_z + frand(-1, 1) * i_verticalZ;
    creature.UpdateAllowedPositionZ(destX, destY, destZ);

    creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

    Movement::MoveSplineInit init(creature);
    init.MoveTo(destX, destY, destZ, true);
    init.SetWalk(true);
    init.Launch();

    if (creature.CanFly())
        i_nextMoveTime.Reset(0);
    else
        i_nextMoveTime.Reset(urand(500, 10000));
}
bool
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
	if(!&creature)
		return true;

	i_nextMoveTime.Update(diff);

	if(i_nextMoveTime.Passed())
	{
		if(creature.IsStopped())
		{
			assert( i_nextMove <= MAX_RAND_WAYPOINTS );
			uint16 x = i_waypoints[i_nextMove][0];
			uint16 y = i_waypoints[i_nextMove][1];
			creature.addUnitState(UNIT_STATE_ROAMING);
			creature.SendMonsterMove(x, y, 0);
//			sLog.outDebug("****** RandomMovementGenerator<Creature>::Update *******");
			i_nextMoveTime.Reset(urand(10000, 12000-1));
		}
		else
		{
			creature.StopMoving();

			++i_nextMove;
			if(i_nextMove == MAX_RAND_WAYPOINTS)
			{
				i_nextMove = 0;
				i_nextMoveTime.Reset(urand(0, 3000-1));
			}
			else
			{
				i_nextMoveTime.Reset(urand(0, 7000-1));
			}
		}
	}
	return true;
}
Example #16
0
bool
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
    {
        i_nextMoveTime.Update(i_nextMoveTime.GetExpiry());    // Expire the timer
        creature.clearUnitState(UNIT_STAT_ROAMING);
        return true;
    }

    i_nextMoveTime.Update(diff);

    if(i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly())
        creature.clearUnitState(UNIT_STAT_ROAMING);

    if(!i_destinationHolder.HasArrived() && creature.IsStopped())
        creature.addUnitState(UNIT_STAT_ROAMING);

    CreatureTraveller traveller(creature);

    if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) )
    {
        if(i_nextMoveTime.Passed())
        {
            if (creature.canFly())
                creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
            else
                creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE);
            _setRandomLocation(creature);
        }
        else if(creature.isPet() && creature.GetOwner() && creature.GetDistance(creature.GetOwner()) > PET_FOLLOW_DIST+2.5f)
        {
           creature.SetUnitMovementFlags(MOVEMENTFLAG_NONE);
           _setRandomLocation(creature);
        }
    }
    return true;
}
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
{
    float destX = i_x;
    float destY = i_y;
    float destZ = i_z;

    creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

    // check if new random position is assigned, GetReachableRandomPosition may fail
    if (creature.GetMap()->GetReachableRandomPosition(&creature, destX, destY, destZ, i_radius))
    {
        Movement::MoveSplineInit init(creature);
        init.MoveTo(destX, destY, destZ, true);
        init.SetWalk(true);
        init.Launch();
        if (roll_chance_i(MOVEMENT_RANDOM_MMGEN_CHANCE_NO_BREAK))
            i_nextMoveTime.Reset(50);
        else
            i_nextMoveTime.Reset(urand(3000, 10000));       // Keep a short wait time
    }
    else
        i_nextMoveTime.Reset(50);                           // Retry later
    return;
}
void ChargeMovementGenerator<Creature>::Initialize(Creature &creature)
{
    if (!creature.isAlive())
        return;

    creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);

    if (m_start == m_end)
    {
        float dist = creature.GetDistance(m_path[m_end].x, m_path[m_end].y, m_path[m_end].z);
        float angle = creature.GetAngle(m_path[m_end].x, m_path[m_end].y);
        bool outdoor = creature.GetTerrain()->IsOutdoors(m_path[m_end].x, m_path[m_end].y, m_path[m_end].z);
        Coords pos = creature.GetPosition();
        float itr = 1;
        if(m_pointTime > 1000)
        {
            while(float(m_pointTime)/(float(dist+itr)/itr) <= 1000 && itr < dist)
                itr+=0.3f;
        }
        else itr = dist;

        for(float i = 1; i < dist; i+=itr)
        {
            m_path.resize(m_path.size()+1);
            m_path.set(m_end+1, m_path[m_end]);

            pos.x += cos(angle)*itr;
            pos.y += sin(angle)*itr;
            creature.UpdateGroundPositionZ(pos.x, pos.y, pos.z, outdoor ? 10.0f : 3.0f);
            m_path.set(m_end, pos);
            ++m_end;
        }
        m_pointTime = float(m_pointTime)/float((m_end - m_start) + 1);
        i_nextMoveTime.Reset(m_pointTime);
    }
}
void FollowMovementGenerator<Creature>::Initialize(Creature& owner)
{
    owner.addUnitState(UNIT_STAT_FOLLOW);                   // _MOVE set in _SetTargetLocation after required checks
    _updateSpeed(owner);
    _setTargetLocation(owner, true);
}
void WaypointMovementGenerator<Creature>::Initialize(Creature& creature)
{
    creature.addUnitState(UNIT_STAT_ROAMING);
    creature.clearUnitState(UNIT_STAT_WAYPOINT_PAUSED);
}
void WaypointMovementGenerator<Creature>::Reset(Creature& creature)
{
    creature.addUnitState(UNIT_STAT_ROAMING);
    StartMove(creature);
}
void WaypointMovementGenerator<Creature>::Initialize(Creature& creature)
{
    LoadPath(creature);
    creature.addUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE);
}
void FollowMovementGenerator<Creature>::initialize(Creature& owner)
{
    owner.addUnitState(UNIT_STAT_FOLLOW | UNIT_STAT_FOLLOW_MOVE);
    _updateSpeed(owner);
    _setTargetLocation(owner, true);
}
void WaypointMovementGenerator<Creature>::Reset(Creature &creature)
{
    SetStoppedByPlayer(false);
    i_nextMoveTime.Reset(0);
    creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
}
bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if (!&creature)
        return true;

    // Waypoint movement can be switched on/off
    // This is quite handy for escort quests and other stuff
    if (creature.hasUnitState(UNIT_STAT_NOT_MOVE))
    {
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
        return true;
    }

    // prevent a crash at empty waypoint path.
    if (!i_path || i_path->empty())
    {
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
        return true;
    }

    if (i_currentNode >= i_path->size())
    {
        sLog.outError("WaypointMovement currentNode (%u) is equal or bigger than path size (creature entry %u)", i_currentNode, creature.GetEntry());
        i_currentNode = 0;
    }

    CreatureTraveller traveller(creature);

    i_nextMoveTime.Update(diff);

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

    // creature has been stopped in middle of the waypoint segment
    if (!i_destinationHolder.HasArrived() && creature.IsStopped())
    {
        // Timer has elapsed, meaning this part controlled it
        if (i_nextMoveTime.Passed())
        {
            SetStoppedByPlayer(false);

            creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

            if (creature.canFly())
                creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);

            // Now we re-set destination to same node and start travel
            const WaypointNode &node = i_path->at(i_currentNode);
            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
        }
        else // if( !i_nextMoveTime.Passed())
        {
            // unexpected end of timer && creature stopped && not at end of segment
            if (!IsStoppedByPlayer())
            {
                // Put 30 seconds delay
                i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
                i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
                SetStoppedByPlayer(true);                   // Mark we did it
            }
        }
        return true;                                        // Abort here this update
    }

    if (creature.IsStopped())
    {
        if (!m_isArrivalDone)
        {
            if (i_path->at(i_currentNode).orientation != 100)
                creature.SetOrientation(i_path->at(i_currentNode).orientation);

            if (i_path->at(i_currentNode).script_id)
            {
                DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for creature %u (entry %u).", i_path->at(i_currentNode).script_id, i_currentNode, creature.GetDBTableGUIDLow(), creature.GetEntry());
                creature.GetMap()->ScriptsStart(sCreatureMovementScripts, i_path->at(i_currentNode).script_id, &creature, &creature);
            }

            // We have reached the destination and can process behavior
            if (WaypointBehavior *behavior = i_path->at(i_currentNode).behavior)
            {
                if (behavior->emote != 0)
                    creature.HandleEmote(behavior->emote);

                if (behavior->spell != 0)
                {
                    creature.CastSpell(&creature, behavior->spell, false);

                    if (!IsActive(creature))                // force stop processing (cast can change movegens list)
                        return true;                        // not expire now, but already lost
                }

                if (behavior->model1 != 0)
                    creature.SetDisplayId(behavior->model1);

                if (behavior->textid[0])
                {
                    // Not only one text is set
                    if (behavior->textid[1])
                    {
                        // Select one from max 5 texts (0 and 1 already checked)
                        int i = 2;
                        for(; i < MAX_WAYPOINT_TEXT; ++i)
                        {
                            if (!behavior->textid[i])
                                break;
                        }

                        creature.Say(behavior->textid[rand() % i], 0, 0);
                    }
                    else
                        creature.Say(behavior->textid[0], 0, 0);
                }
            }                                               // wpBehaviour found

            // Can only do this once for the node
            m_isArrivalDone = true;

            // Inform script
            MovementInform(creature);

            if (!IsActive(creature))                        // force stop processing (movement can move out active zone with cleanup movegens list)
                return true;                                // not expire now, but already lost

            // prevent a crash at empty waypoint path.
            if (!i_path || i_path->empty() || i_currentNode >= i_path->size())
            {
                creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
                return true;
            }
        }
    }                                                       // i_creature.IsStopped()

    // This is at the end of waypoint segment (incl. was previously stopped by player, extending the time)
    if (i_nextMoveTime.Passed())
    {
        // If stopped then begin a new move segment
        if (creature.IsStopped())
        {
            creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

            if (creature.canFly())
                creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);

            if (WaypointBehavior *behavior = i_path->at(i_currentNode).behavior)
            {
                if (behavior->model2 != 0)
                    creature.SetDisplayId(behavior->model2);

                creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
            }

            // behavior for "departure" of the current node is done
            m_isArrivalDone = false;

            // Proceed with increment current node and then send to the next destination
            ++i_currentNode;

            // Oops, end of the line so need to start from the beginning
            if (i_currentNode >= i_path->size())
                i_currentNode = 0;

            if (i_path->at(i_currentNode).orientation != 100)
                creature.SetOrientation(i_path->at(i_currentNode).orientation);

            const WaypointNode &node = i_path->at(i_currentNode);
            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
        }
        else
        {
            // If not stopped then stop it
            creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);

            SetStoppedByPlayer(false);

            // Set TimeTracker to waittime for the current node
            i_nextMoveTime.Reset(i_path->at(i_currentNode).delay);
        }
    }

    return true;
}
Example #26
0
void WaypointMovementGenerator<Creature>::Reset( Creature &u )
{
    b_StoppedByPlayer = false;
    i_nextMoveTime.Reset(0);
    u.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
}
Example #27
0
bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if (!&creature)
        return true;

    // Waypoint movement can be switched on/off
    // This is quite handy for escort quests and other stuff
    if (creature.hasUnitState(UNIT_STAT_NOT_MOVE))
    {
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
        return true;
    }

    // prevent a crash at empty waypoint path.
    if (!i_path || i_path->empty())
    {
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
        return true;
    }

    if (i_currentNode >= i_path->size())
        i_currentNode = 0;

    CreatureTraveller traveller(creature);

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

    // creature has been stopped in middle of the waypoint segment
    if (!i_destinationHolder.HasArrived() && creature.IsStopped())
    {
        // Timer has elapsed, meaning this part controlled it
        if (i_nextMoveTime.Passed())
        {
            SetStoppedByPlayer(false);

            creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

            if (creature.canFly())
                creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);

            // Now we re-set destination to same node and start travel
            const WaypointNode &node = i_path->at(i_currentNode);
            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
        }
        else // if( !i_nextMoveTime.Passed())
        {
            // unexpected end of timer && creature stopped && not at end of segment
            if (!IsStoppedByPlayer())
            {
                // Put 30 seconds delay
                i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
                i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
                SetStoppedByPlayer(true);                   // Mark we did it
            }
        }
        return true;                                        // Abort here this update
    }

    if (creature.IsStopped() && !i_hasDone) // creature is waiting on a waypoint and hasn't done the behavior yet
    {
        uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;

        if (i_path->at(idx).orientation != 100)
            creature.SetOrientation(i_path->at(idx).orientation);

        if (WaypointBehavior *behavior = i_path->at(idx).behavior)
        {
            if (behavior->emote != 0)
                creature.HandleEmote(behavior->emote);

            if (behavior->spell != 0)
            {
                creature.CastSpell(&creature, behavior->spell, false);

                if (!IsActive(creature))                // force stop processing (cast can change movegens list)
                    return true;                        // not expire now, but already lost
            }

            if (behavior->model1 != 0)
                creature.SetDisplayId(behavior->model1);

            if (behavior->textid[0])
            {
                // Not only one text is set
                if (behavior->textid[1])
                {
                    // Select one from max 5 texts (0 and 1 already checked)
                    int i = 2;
                    for(; i < MAX_WAYPOINT_TEXT; ++i)
                    {
                        if (!behavior->textid[i])
                            break;
                    }

                    creature.Say(behavior->textid[rand() % i], 0, 0);
                }
                else
                    creature.Say(behavior->textid[0], 0, 0);
            }
        } // behavior done

        i_hasDone = true;
        MovementInform(creature);

        if (!IsActive(creature))                        // force stop processing (movement can move out active zone with cleanup movegens list)
            return true;                                // not expire now, but already lost

        // prevent a crash at empty waypoint path.
        if (!i_path || i_path->empty() || i_currentNode >= i_path->size())
        {
            creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
            return true;
        }
    }                                                       // i_creature.IsStopped()

    // This is at the end of waypoint segment or has been stopped by player
    if (i_nextMoveTime.Passed())
    {
        // If stopped then begin a new move segment
        if (creature.IsStopped())
        {
            creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

            if (creature.canFly())
                creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);

            const WaypointNode &node = i_path->at(i_currentNode);
            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());

            uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;

            if (i_path->at(idx).orientation != 100)
                creature.SetOrientation(i_path->at(idx).orientation);

            if (WaypointBehavior *behavior = i_path->at(idx).behavior)
            {
                if (behavior->model2 != 0)
                    creature.SetDisplayId(behavior->model2);

                creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
            }
        }
        else
        {
            // If not stopped then stop it and set the reset of TimeTracker to waittime
            creature.StopMoving();
            SetStoppedByPlayer(false);

            i_nextMoveTime.Reset(i_path->at(i_currentNode).delay);
            ++i_currentNode;

            i_hasDone = false;

            if (i_currentNode >= i_path->size())
                i_currentNode = 0;
        }
    }
    return true;
}
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);
}
bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if(!&creature)
        return true;

    // Waypoint movement can be switched on/off
    // This is quite handy for escort quests and other stuff
    if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
        return true;

    // prevent a crash at empty waypoint path.
    if(!i_path || i_path->empty())
        return true;

    // i_path was modified by chat commands for example
    if(i_path->size() != i_hasDone.size())
        i_hasDone.resize(i_path->size());
    if(i_currentNode >= i_path->size())
        i_currentNode = 0;

    CreatureTraveller traveller(creature);

    i_nextMoveTime.Update(diff);
    i_destinationHolder.UpdateTraveller(traveller, diff, false, true);

    // creature has been stopped in middle of the waypoint segment
    if (!i_destinationHolder.HasArrived() && creature.IsStopped())
    {
        if( i_nextMoveTime.Passed()) // Timer has elapsed, meaning this part controlled it
        {
            SetStopedByPlayer(false);
            // Now we re-set destination to same node and start travel
            creature.addUnitState(UNIT_STAT_ROAMING);
            if (creature.canFly())
                creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
            const WaypointNode &node = i_path->at(i_currentNode);
            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
        }
        else // if( !i_nextMoveTime.Passed())
        {   // unexpected end of timer && creature stopped && not at end of segment
            if (!IsStopedByPlayer())
            {   // Put 30 seconds delay
                i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
                i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
                SetStopedByPlayer(true);                        // Mark we did it
            }
        }
        return true;    // Abort here this update
    }

    if( creature.IsStopped())
    {
        uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;

        if (!i_hasDone[idx])
        {
            if (i_path->at(idx).orientation !=100)
                creature.SetOrientation(i_path->at(idx).orientation);

            if(WaypointBehavior *behavior = i_path->at(idx).behavior)
            {
                if(behavior->emote != 0)
                    creature.SetUInt32Value(UNIT_NPC_EMOTESTATE,behavior->emote);
                if(behavior->spell != 0)
                    creature.CastSpell(&creature,behavior->spell, false);
                if(behavior->model1 != 0)
                    creature.SetDisplayId(behavior->model1);
                if(behavior->textid[0])
                {
                    // Not only one text is set
                    if( behavior->textid[1] )
                    {
                        // Select one from max 5 texts (0 and 1 laready checked)
                        int i = 2;
                        for( ; i < MAX_WAYPOINT_TEXT; ++i )
                            if( !behavior->textid[i] )
                                break;

                        creature.Say(behavior->textid[rand() % i], 0, 0);
                    }
                    else
                        creature.Say(behavior->textid[0], 0, 0);
                }

                i_hasDone[idx] = true;
                MovementInform(creature);
            }                                               // wpBehaviour found
        }                                                   // HasDone == false
    }                                                       // i_creature.IsStopped()

    if( i_nextMoveTime.Passed() ) // This is at the end of waypoint segment or has been stopped by player
    {
        if( creature.IsStopped() ) // If stopped then begin a new move segment
        {
            creature.addUnitState(UNIT_STAT_ROAMING);
            if (creature.canFly())
                creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
            const WaypointNode &node = i_path->at(i_currentNode);
            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
            uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;

            if (i_path->at(idx).orientation !=100)
                creature.SetOrientation(i_path->at(idx).orientation);

            if(WaypointBehavior *behavior = i_path->at(idx).behavior )
            {
                i_hasDone[idx] = false;
                if(behavior->model2 != 0)
                    creature.SetDisplayId(behavior->model2);

                creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
            }
        }
        else // If not stopped then stop it and set the reset of TimeTracker to waittime
        {
            creature.StopMoving();
            SetStopedByPlayer(false);
            i_nextMoveTime.Reset(i_path->at(i_currentNode).delay);
            ++i_currentNode;
            if( i_currentNode >= i_path->size() )
                i_currentNode = 0;
        }
    }
    return true;
}
Example #30
0
void
RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
{
    float X,Y,Z,z,nx,ny,nz,wander_distance,ori,dist;

    creature.GetRespawnCoord(X, Y, Z, &ori, &wander_distance);

    z = creature.GetPositionZ();
    uint32 mapid=creature.GetMapId();
    Map const* map = MapManager::Instance().GetBaseMap(mapid);

    // For 2D/3D system selection
    bool is_land_ok  = creature.canWalk();
    bool is_water_ok = creature.canSwim();
    bool is_air_ok   = creature.canFly();

    const float angle = rand_norm()*(M_PI*2);
    const float range = rand_norm()*wander_distance;
    const float distanceX = range * cos(angle);
    const float distanceY = range * sin(angle);

    nx = X + distanceX;
    ny = Y + distanceY;

    // prevent invalid coordinates generation 
    Trinity::NormalizeMapCoord(nx);
    Trinity::NormalizeMapCoord(ny);

    dist = (nx - X)*(nx - X) + (ny - Y)*(ny - Y);

    if (is_air_ok) // 3D system above ground and above water (flying mode)
    {
        const float distanceZ = rand_norm() * sqrtf(dist)/2; // Limit height change
        nz = Z + distanceZ;
        float tz = map->GetHeight(nx, ny, nz-2.0f, false); // Map check only, vmap needed here but need to alter vmaps checks for height.
        float wz = map->GetWaterLevel(nx, ny);
        if (tz >= nz || wz >= nz)
            return; // Problem here, we must fly above the ground and water, not under. Let's try on next tick
    }
    //else if (is_water_ok) // 3D system under water and above ground (swimming mode)
    else // 2D only
    {
        dist = dist>=100.0f ? 10.0f : sqrtf(dist); // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
        // The fastest way to get an accurate result 90% of the time.
        // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
        nz = map->GetHeight(nx,ny,Z+dist-2.0f,false); // Map check
        if (fabs(nz-Z)>dist)
        {
            nz = map->GetHeight(nx,ny,Z-2.0f,true); // Vmap Horizontal or above
            if (fabs(nz-Z)>dist)
            {
                nz = map->GetHeight(nx,ny,Z+dist-2.0f,true); // Vmap Higher
                if (fabs(nz-Z)>dist)
                    return; // let's forget this bad coords where a z cannot be find and retry at next tick
            }
        }
    }

    Traveller<Creature> traveller(creature);
    creature.SetOrientation(creature.GetAngle(nx,ny));
    i_destinationHolder.SetDestination(traveller, nx, ny, nz);
    creature.addUnitState(UNIT_STAT_ROAMING);
    if (is_air_ok)
    {
        i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
        creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
    }
    //else if (is_water_ok) // Swimming mode to be done with more than this check
    else
    {
        i_nextMoveTime.Reset(urand(500+i_destinationHolder.GetTotalTravelTime(),5000+i_destinationHolder.GetTotalTravelTime()));
        creature.SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE);
    }
}