void PointMovementGenerator<T>::Initialize(T &unit)
{
    unit.StopMoving();
    Traveller<T> traveller(unit);

    // OLD: knockback effect has UNIT_STAT_JUMPING set, so if here we disable sentmonstermove there will be creature position sync problem between client and server
    // NEW: reactivated this check - UNIT_STAT_JUMPING is only used in MoveJump, which sends its own packet
	//i_destinationHolder.SetDestination(traveller, i_x, i_y, i_z, !m_usePathfinding);
	
	if (m_usePathfinding)
	{
		PathInfo path(&unit, i_x, i_y, i_z);
		PointPath pointPath = path.getFullPath();
		
		float speed = traveller.Speed() * 0.001f; // in ms
		uint32 traveltime = uint32(pointPath.GetTotalLength() / speed);
		if (unit.GetTypeId() != TYPEID_UNIT)
			unit.SetUnitMovementFlags(SPLINEFLAG_WALKING);
		unit.SendMonsterMoveByPath(pointPath, 1, pointPath.size(), traveltime);

		 PathNode p = pointPath[pointPath.size()-1];
		 i_destinationHolder.SetDestination(traveller, p.x, p.y, p.z, false);
	}
	else
       i_destinationHolder.SetDestination(traveller, i_x, i_y, i_z, /*true*/ !unit.HasUnitState(UNIT_STAT_JUMPING));
}
예제 #2
0
void PointMovementGenerator<T>::Initialize(T& unit)
{
    if (!unit.IsStopped())
        unit.StopMoving();

    unit.addUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE);

    Traveller<T> traveller(unit);

    if (m_usePathfinding)
    {
        PathInfo path(&unit, i_x, i_y, i_z);
        PointPath pointPath = path.getFullPath();

        float speed = traveller.Speed() * 0.001f;           // in ms
        uint32 traveltime = uint32(pointPath.GetTotalLength() / speed);
        SplineFlags flags = (unit.GetTypeId() == TYPEID_UNIT) ? ((Creature*)&unit)->GetSplineFlags() : SPLINEFLAG_WALKMODE;
        unit.SendMonsterMoveByPath(pointPath, 1, pointPath.size(), flags, traveltime);

        PathNode p = pointPath[pointPath.size() - 1];
        i_destinationHolder.SetDestination(traveller, p.x, p.y, p.z, false);
    }
    else
        i_destinationHolder.SetDestination(traveller, i_x, i_y, i_z, true);

    if (unit.GetTypeId() == TYPEID_UNIT && ((Creature*)&unit)->CanFly())
        ((Creature&)unit).AddSplineFlag(SPLINEFLAG_FLYING);
}
예제 #3
0
void
HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
{
    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
        return;

    float x, y, z;

    // at apply we can select more nice return points base at current movegen
    if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner,x,y,z))
        owner.GetRespawnCoord(x, y, z);

    CreatureTraveller traveller(owner);
    i_destinationHolder.SetDestination(traveller, x, y, z, false);

    PathInfo path(&owner, x, y, z);
    PointPath pointPath = path.getFullPath();

    float speed = traveller.Speed() * 0.001f; // in ms
    uint32 traveltime = uint32(pointPath.GetTotalLength() / speed);
    modifyTravelTime(traveltime);

    owner.SendMonsterMoveByPath(pointPath, 1, pointPath.size(), owner.GetSplineFlags(), traveltime);
    owner.clearUnitState(UNIT_STAT_ALL_STATE);
}
void
HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
{
    if (!&owner)
        return;

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

    float x, y, z;
    owner.GetHomePosition(x, y, z, ori);

    CreatureTraveller traveller(owner);

    i_destinationHolder.SetDestination(traveller, x, y, z, false);

    PathInfo path(&owner, x, y, z, true);
    PointPath pointPath = path.getFullPath();

    float speed = traveller.Speed() * 0.001f; // in ms
    uint32 traveltime = uint32(pointPath.GetTotalLength() / speed);
    modifyTravelTime(traveltime);
    owner.SendMonsterMoveByPath(pointPath, 1, pointPath.size(), traveltime);

    owner.clearUnitState(UNIT_STAT_ALL_STATE);
}
예제 #5
0
        static bool HandleMmapPathCommand(ChatHandler* handler, const char* args)
        {
            if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()))
            {
                handler->PSendSysMessage("NavMesh not loaded for current map.");
                return true;
            }

            handler->PSendSysMessage("mmap path:");

            // units
            Player* player = handler->GetSession()->GetPlayer();
            Unit* target = handler->getSelectedUnit();
            if (!player || !target)
            {
                handler->PSendSysMessage("Invalid target/source selection.");
                return true;
            }

            char* para = strtok((char*)args, " ");

            bool useStraightPath = false;
            if (para && strcmp(para, "true") == 0)
                useStraightPath = true;

            // unit locations
            float x, y, z;
            player->GetPosition(x, y, z);

            // path
            PathInfo path(target, x, y, z, useStraightPath);
            PointPath pointPath = path.getFullPath();
            handler->PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName());
            handler->PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath");
            handler->PSendSysMessage("length %i type %u", pointPath.size(), path.getPathType());

            PathNode start = path.getStartPosition();
            PathNode next = path.getNextPosition();
            PathNode end = path.getEndPosition();
            PathNode actualEnd = path.getActualEndPosition();

            handler->PSendSysMessage("start      (%.3f, %.3f, %.3f)", start.x, start.y, start.z);
            handler->PSendSysMessage("next       (%.3f, %.3f, %.3f)", next.x, next.y, next.z);
            handler->PSendSysMessage("end        (%.3f, %.3f, %.3f)", end.x, end.y, end.z);
            handler->PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z);

            if (!player->isGameMaster())
                handler->PSendSysMessage("Enable GM mode to see the path points.");

            // this entry visible only to GM's with "gm on"
            static const uint32 WAYPOINT_NPC_ENTRY = 1;
            for (uint32 i = 0; i < pointPath.size(); ++i)
                player->SummonCreature(WAYPOINT_NPC_ENTRY, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000);

            return true;
        }
bool NavigationMesh::makeSpline(PointPath& path) {

	if( path.size() < 2 )
		return false;

	PointPath::iterator p0, p1, p2, p3;

	p0 = p1 = path.begin();
	++p1;
	Ogre::Vector3 pextra = *p0 - ((*p1 - *p0).normalise() * 0.5);
	path.push_front(pextra);

	p0 = p1 = path.end();
	--p1;
	--p0;
	--p0;
	pextra = *p1 + ((*p1 - *p0).normalise() * 0.5);
	path.push_back(pextra);

	int dotsPerUnit = 2;

	p0 = path.begin();

	p1 = p0; 
	++p1;

	p2 = p1; 
	++p2;

	p3 = p2; 
	++p3;


	while( p3 != path.end() ){

		int n = (*p1 - *p2).length() * dotsPerUnit;
		Ogre::Real step = 1.0/n;
		Ogre::Real s = step;

		for(int i = 1; i < n; ++i) {
			path.insert(p2, CatmullRollSpline(*p0, *p1, *p2, *p3, s));
			s += step;
		}

		p0 = p1;
		p1 = p2;
		++p2;
		++p3;

	}

	path.pop_front();
	path.pop_back();

	return true;
}
예제 #7
0
void
WaypointMovementGenerator<Creature>::MoveToNextNode(CreatureTraveller &traveller)
{
    Creature* owner = &(traveller.i_traveller);
    i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z, false);

    PathInfo sub_path(owner, node->x, node->y, node->z);
    PointPath pointPath = sub_path.getFullPath();

    float speed = traveller.Speed()*0.001f; // in ms
    uint32 traveltime = uint32(pointPath.GetTotalLength()/speed);
    owner->SendMonsterMoveByPath(pointPath, 1, pointPath.size(), traveltime);

    i_nextMoveTime.Reset(traveltime);
}
void WaypointMovementGenerator<Creature>::MoveToNextNode(CreatureTraveller &traveller)
{
    Creature* owner = &(traveller.i_traveller);
    const WaypointNode &node = i_path->at(i_currentNode);
    i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z, false);

    PathInfo sub_path(owner, node.x, node.y, node.z);
    PointPath myPath = sub_path.getFullPath();

    float speed = traveller.Speed()*0.001f; // in ms
    uint32 traveltime = uint32(myPath.GetTotalLength()/speed);
    owner->SendMonsterMoveByPath(myPath, 1, myPath.size(), owner->GetSplineFlags(), traveltime);

    i_nextMoveTime.Reset(traveltime);
}
bool NavigationMesh::buildPath(PointPath& path,
                               const Ogre::Vector3& startPos,
                               const Ogre::Vector3& endPos,
                               Cell* startCell,
                               Cell* endCell) {

    if (!startCell)
	startCell = findCell(startPos);

    if (!endCell)
	endCell = findCell(endPos);

    if (!startCell || !endCell) {
	cout << "Celdas no pertenecen a la rejilla" << endl;
	return false;
    }

    int startId = startCell->getId();
    int endId = endCell->getId();
    
    if (_graph[startId * _cellNumber + endId] == Ogre::Math::POS_INFINITY) {
	cout << "No se ha encontrado camino" << endl;
	return false;
    }

    CellPath cellPath;

    recoverPath(startId, endId, cellPath);

    path.clear();
	
    for(CellPath::iterator i = cellPath.begin(); i != cellPath.end(); ++i)
	path.push_back((*i)->getCenter());

    path.push_front(startPos);

    path.push_back(endPos);

    makeSpline(path);

    return true;
}
void PointMovementGenerator<T>::Initialize(T &unit)
{
    unit.StopMoving();
    Traveller<T> traveller(unit);

    if (m_usePathfinding)
    {
        PathInfo path(&unit, i_x, i_y, i_z);
        PointPath pointPath = path.getFullPath();

        float speed = traveller.Speed() * 0.001f; // in ms
        uint32 traveltime = uint32(pointPath.GetTotalLength() / speed);
        if (unit.GetTypeId() != TYPEID_UNIT)
            unit.SetUnitMovementFlags(SPLINEFLAG_WALKMODE);
        unit.SendMonsterMoveByPath(pointPath, 1, pointPath.size(), traveltime);

        PathNode p = pointPath[pointPath.size()-1];
        i_destinationHolder.SetDestination(traveller, p.x, p.y, p.z, false);
    }
    else
        i_destinationHolder.SetDestination(traveller, i_x, i_y, i_z, true);
}
bool TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return false;

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

    float x, y, z;
    Traveller<T> traveller(owner);
    if (i_destinationHolder.HasDestination() && !m_pathPointsSent)
    {
        if (i_destinationHolder.HasArrived())
        {
            // prevent redundant micro-movement
            if (!i_offset)
            {
                if (i_target->IsWithinMeleeRange(&owner))
                    return false;
            }
            else if (!i_angle && !owner.hasUnitState(UNIT_STAT_FOLLOW))
            {
                if (i_target->IsWithinDistInMap(&owner, i_offset))
                    return false;
            }
            else
            {
                if (i_target->IsWithinDistInMap(&owner, i_offset + 1.0f))
                    return false;
            }
        }
        else
        {
            bool stop = false;
            if (!i_offset)
            {
                if (i_target->IsWithinMeleeRange(&owner, 0.0f))
                    stop = true;
            }
            else if (!i_angle && !owner.hasUnitState(UNIT_STAT_FOLLOW))
            {
                if (i_target->IsWithinDist(&owner, i_offset * 0.8f))
                    stop = true;
            }

            if (stop)
            {
                owner.GetPosition(x, y, z);
                if (owner.GetTypeId() == TYPEID_UNIT && (owner.HasUnitMovementFlag(MOVEFLAG_CAN_FLY) || owner.IsInWater() || i_target->IsInWater()))
                    z = i_target->GetPositionZ();

                if(m_usePathfinding)
                {
                    bool newPathCalculated = true;

                    if (!i_path)
                        i_path = new PathInfo(&owner, x, y, z);
                    else
                        newPathCalculated = i_path->Update(x, y, z);

                    // nothing we can do here ...
                    if(i_path->getPathType() & PATHFIND_NOPATH)
                        return true;

                    PointPath pointPath = i_path->getFullPath();

                    if (i_destinationHolder.HasArrived() && m_pathPointsSent)
                        --m_pathPointsSent;

                    i_path->getNextPosition(x, y, z);
                    i_destinationHolder.SetDestination(traveller, x, y, z, false);

                    // send the path if:
                    //    we have brand new path
                    //    we have visited almost all of the previously sent points
                    //    movespeed has changed
                    //    the owner is stopped (caused by some movement effects)
                    if (newPathCalculated || m_pathPointsSent < 2 || i_recalculateTravel || owner.IsStopped())
                    {
                        // send 10 nodes, or send all nodes if there are less than 10 left
                        m_pathPointsSent = std::min<uint32>(10, pointPath.size() - 1);
                        uint32 endIndex = m_pathPointsSent + 1;

                        // dist to next node + world-unit length of the path
                        x -= owner.GetPositionX();
                        y -= owner.GetPositionY();
                        z -= owner.GetPositionZ();
                        float dist = sqrt(x*x + y*y + z*z) + pointPath.GetTotalLength(1, endIndex);

                        // calculate travel time, set spline, then send path
                        uint32 traveltime = uint32(dist / (traveller.Speed()*0.001f));

                        owner.SendMonsterMoveByPath(pointPath, 1, endIndex, traveltime);

                        return false;
                    }
                }
                else
                {
                    i_destinationHolder.SetDestination(traveller, x, y, z);
                    i_destinationHolder.StartTravel(traveller, false);
                    owner.StopMoving();
                    return false;
                }
            }
        }

        if (i_target->GetExactDistSq(i_targetX, i_targetY, i_targetZ) < 0.01f)
            return false;
    }

    if (!i_offset)
    {
        // to nearest random contact position
        i_target->GetRandomContactPoint(&owner, x, y, z, 0, MELEE_RANGE - 0.5f);
    }
    else if (!i_angle && !owner.hasUnitState(UNIT_STAT_FOLLOW))
    {
        // caster chase
        i_target->GetContactPoint(&owner, x, y, z, i_offset * urand(80, 95) * 0.01f);
    }
    else
    {
        // to at i_offset distance from target and i_angle from target facing
        i_target->GetClosePoint(x, y, z, owner.GetObjectSize(), i_offset,i_angle);
    }

    /*
        We MUST not check the distance difference and avoid setting the new location for smaller distances.
        By that we risk having far too many GetContactPoint() calls freezing the whole system.
        In TargetedMovementGenerator<T>::Update() we check the distance to the target and at
        some range we calculate a new position. The calculation takes some processor cycles due to vmaps.
        If the distance to the target it too large to ignore,
        but the distance to the new contact point is short enough to be ignored,
        we will calculate a new contact point each update loop, but will never move to it.
        The system will freeze.
        ralf

        //We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
        float  bothObjectSize = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE;
        if (i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize)
            return;
    */
    //i_destinationHolder.SetDestination(traveller, x, y, z);

    if(m_usePathfinding)
    {

        bool forceDest = false;
        // allow pets to cheat while generating paths as they should ALWAYS be able to reach thier target.
        if (owner.GetTypeId() == TYPEID_UNIT
                && owner.ToCreature()
                && owner.ToCreature()->isPet())
            forceDest = true;

        bool newPathCalculated = true;
        if (!i_path)
            i_path = new PathInfo(&owner, x, y, z, forceDest);
        else
            newPathCalculated = i_path->Update(x, y, z, forceDest);

        // nothing we can do here ...
        if (i_path->getPathType() & PATHFIND_NOPATH)
            return true;

        if (i_destinationHolder.HasArrived() && m_pathPointsSent)
            --m_pathPointsSent;

        i_path->getNextPosition(x, y, z);
        i_destinationHolder.SetDestination(traveller, x, y, z, false);

        // send the path if:
        //    we have brand new path
        //    we have visited almost all of the previously sent points
        //    movespeed has changed
        //    the owner is stopped (caused by some movement effects)
        if (newPathCalculated || m_pathPointsSent < 2 || i_recalculateTravel || owner.IsStopped())
        {
            PointPath pointPath = i_path->getFullPath();
            // send 10 nodes, or send all nodes if there are less than 10 left
            m_pathPointsSent = std::min<uint32>(10, pointPath.size() - 1);
            uint32 endIndex = m_pathPointsSent + 1;

            // dist to next node + world-unit length of the path
            x -= owner.GetPositionX();
            y -= owner.GetPositionY();
            z -= owner.GetPositionZ();
            float dist = sqrt(x*x + y*y + z*z) + pointPath.GetTotalLength(1, endIndex);

            // calculate travel time, set spline, then send path
            uint32 traveltime = uint32(dist / (traveller.Speed()*0.001f));

            owner.SendMonsterMoveByPath(pointPath, 1, endIndex, traveltime);
        }

        owner.addUnitState(UNIT_STAT_CHASE);
    }
    else
    {
        i_destinationHolder.SetDestination(traveller, x, y, z);
        owner.addUnitState(UNIT_STAT_CHASE);
        i_destinationHolder.StartTravel(traveller);
    }

}
bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
    if(!&unit)
        return true;

    // ignore in case other no reaction state
    if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_CONFUSED))
        return true;

    if (i_nextMoveTime.Passed())
    {
        // currently moving, update location
        unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
        Traveller<T> traveller(unit);
        if (i_destinationHolder.UpdateTraveller(traveller, diff, false))
        {
            if (!IsActive(unit))                            // force stop processing (movement can move out active zone with cleanup movegens list)
                return true;                                // not expire now, but already lost

            if (i_destinationHolder.HasArrived())
            {
                // arrived, stop and wait a bit
                unit.StopMoving();

                i_nextMoveTime.Reset(urand(800, 1500));
            }
        }
    }
    else
    {
        // waiting for next move
        i_nextMoveTime.Update(diff);
        if(i_nextMoveTime.Passed())
        {
            // start moving
            unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
            
            float x = i_x + 10.0f*(rand_norm_f() - 0.5f);
            float y = i_y + 10.0f*(rand_norm_f() - 0.5f);
            float z = i_z;

            unit.UpdateAllowedPositionZ(x, y, z);

            Traveller<T> traveller(unit);

            PathInfo path(&unit, x, y, z);
            if(!(path.getPathType() & PATHFIND_NORMAL))
            {
                i_nextMoveTime.Reset(urand(800, 1000));
                return true;
            }

            PointPath pointPath = path.getFullPath();

            float speed = traveller.Speed() * 0.001f; // in ms
            uint32 traveltime = uint32(pointPath.GetTotalLength() / speed);
            SplineFlags flags = (unit.GetTypeId() == TYPEID_UNIT) ? ((Creature*)&unit)->GetSplineFlags() : SPLINEFLAG_WALKMODE;
            unit.SendMonsterMoveByPath(pointPath, 1, std::min<uint32>(pointPath.size(), 5), flags, traveltime);

            PathNode p = pointPath[std::min<uint32>(pointPath.size()-1, 4)];
            // we do not really need it with mmaps active
            unit.UpdateAllowedPositionZ(p.x, p.y, p.z);
            i_destinationHolder.SetDestination(traveller, p.x, p.y, p.z, false);
        }
    }
    return true;
}
void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return;

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
        return;

    float x, y, z;

    // prevent redundant micro-movement for pets, other followers.
    if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
    {
        if (i_destinationHolder.HasDestination())
            return;

        owner.GetPosition(x, y, z);
    }
    else if (!i_offset)
    {
        // to nearest contact position
        i_target->GetContactPoint( &owner, x, y, z );
    }
    else
    {
        // to at i_offset distance from target and i_angle from target facing
        i_target->GetClosePoint(x, y, z, owner.GetObjectBoundingRadius(), i_offset, i_angle, &owner);
    }

    /*
        We MUST not check the distance difference and avoid setting the new location for smaller distances.
        By that we risk having far too many GetContactPoint() calls freezing the whole system.
        In TargetedMovementGenerator<T>::Update() we check the distance to the target and at
        some range we calculate a new position. The calculation takes some processor cycles due to vmaps.
        If the distance to the target it too large to ignore,
        but the distance to the new contact point is short enough to be ignored,
        we will calculate a new contact point each update loop, but will never move to it.
        The system will freeze.
        ralf

        //We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
        float  bothObjectSize = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + CONTACT_DISTANCE;
        if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
            return;
    */

    //ACE_High_Res_Timer timer = ACE_High_Res_Timer();
    //ACE_hrtime_t elapsed;
    //timer.start();

    bool forceDest = false;
    // allow pets following their master to cheat while generating paths
    if(owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->IsPet()
        && owner.hasUnitState(UNIT_STAT_FOLLOW))
        forceDest = true;

    bool newPathCalculated = true;
    if(!i_path)
        i_path = new PathInfo(&owner, x, y, z, false, forceDest);
    else
        newPathCalculated = i_path->Update(x, y, z, false, forceDest);

    //timer.stop();
    //timer.elapsed_microseconds(elapsed);
    //sLog.outDebug("Path found in %llu microseconds", elapsed);

    // nothing we can do here ...
    if(i_path->getPathType() & PATHFIND_NOPATH)
        return;

    PointPath pointPath = i_path->getFullPath();

    if (i_destinationHolder.HasArrived() && m_pathPointsSent)
        --m_pathPointsSent;

    Traveller<T> traveller(owner);
    i_path->getNextPosition(x, y, z);
    i_destinationHolder.SetDestination(traveller, x, y, z, false);

    // send the path if:
    //    we have brand new path
    //    we have visited almost all of the previously sent points
    //    movespeed has changed
    //    the owner is stopped (caused by some movement effects)
    if (newPathCalculated || m_pathPointsSent < 2 || i_recalculateTravel || owner.IsStopped())
    {
        // send 10 nodes, or send all nodes if there are less than 10 left
        m_pathPointsSent = std::min<uint32>(10, pointPath.size() - 1);
        uint32 endIndex = m_pathPointsSent + 1;

        // dist to next node + world-unit length of the path
        x -= owner.GetPositionX();
        y -= owner.GetPositionY();
        z -= owner.GetPositionZ();
        float dist = sqrt(x*x + y*y + z*z) + pointPath.GetTotalLength(1, endIndex);

        // calculate travel time, set spline, then send path
        uint32 traveltime = uint32(dist / (traveller.Speed()*0.001f));
        SplineFlags flags = (owner.GetTypeId() == TYPEID_UNIT) ? ((Creature*)&owner)->GetSplineFlags() : SPLINEFLAG_WALKMODE;
        owner.SendMonsterMoveByPath(pointPath, 1, endIndex, flags, traveltime);
    }

    D::_addUnitStateMove(owner);
    if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->CanFly())
        ((Creature&)owner).AddSplineFlag(SPLINEFLAG_FLYING);
}
예제 #14
0
void npc_toc_announcerAI::UpdateAI(const uint32 /*diff*/)
{
    // custom event step handling
    if (SpellTimer* stepTimer = m_TimerMgr->GetState(TIMER_PHASE_HANDLING))
    {
        uint32 cooldown = 0;
        ++encounterStage;

        switch(currentEncounter)
        {
            case TYPE_BEASTS:
            {
                switch(encounterStage)
                {
                    case 1:
                        DoScriptText(SAY_STAGE_0_01, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 22000;
                        break;
                    case 2:
                        DoScriptText(SAY_STAGE_0_02, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 4000;
                        break;
                    case 3:
                        SummonToCBoss(NPC_GORMOK, 0, 100);
                        cooldown = 1000;
                        break;
                    case 4:
                        if (encounterCreature)
                            encounterCreature->AI()->AttackStart(m_pInstance->GetRandomPlayerInMap());
                        cooldown = 5000;
                        break;
                    case 5:
                        if (m_pInstance->GetInstanceSide() == INSTANCE_SIDE_ALI)
                            DoScriptText(SAY_STAGE_0_03a, m_pInstance->GetCreature(NPC_WRYNN));
                        else
                            DoScriptText(SAY_STAGE_0_03h, m_pInstance->GetCreature(NPC_GARROSH));
                        cooldown = isHeroic ? 174000 : REALLY_BIG_COOLDOWN;
                        break;
                    case 6:
                        SummonToCBoss(NPC_DREADSCALE, NULL, 5100);
                        DoScriptText(SAY_STAGE_0_04, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 6000;
                        break;
                    case 7:
                        if (encounterCreature)
                            encounterCreature->AI()->AttackStart(m_pInstance->GetRandomPlayerInMap());
                        cooldown = 4000;
                        break;
                    case 8:
                    {
                        Player* randPlr = m_pInstance->GetRandomPlayerInMap();
                        if (!randPlr)
                            break;

                        encounterCreature2 = DoSpawnTocBoss(NPC_ACIDMAW, randPlr->GetPosition(), 0);
                        if (!encounterCreature2)
                            break;

                        encounterCreature2->CastSpell(encounterCreature2, SPELL_EMERGE_ACIDMAW, false);
                        cooldown = isHeroic ? 170000 + stepTimer->GetCustomValue() : REALLY_BIG_COOLDOWN;
                        break;
                    }
                    case 9:
                        SummonToCBoss(NPC_ICEHOWL, NULL, 3100);
                        DoScriptText(SAY_STAGE_0_05, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 4000;
                    case 10:
                        if (encounterCreature)
                            encounterCreature->AI()->AttackStart(m_pInstance->GetRandomPlayerInMap());
                        cooldown = isHeroic ? 176000 + stepTimer->GetCustomValue() : REALLY_BIG_COOLDOWN;
                        break;
                    case 11:
                        if (encounterCreature)
                            encounterCreature->GetTimerMgr()->AddSpellToQueue(SPELL_BERSERK_NB);
                        cooldown = REALLY_BIG_COOLDOWN;
                        break;
                    case 51: // outro
                        DoScriptText(SAY_STAGE_0_06, m_pInstance->GetCreature(NPC_TIRION));
                        break;
                }
                break;
            }
            case TYPE_JARAXXUS:
            {
                switch(encounterStage)
                {
                    case 1:
                    {
                        encounterCreature2 = m_pInstance->GetCreature(NPC_JARAXXUS);
                        if (encounterCreature2 && m_pInstance->GetData(TYPE_JARAXXUS) == FAIL)
                        {
                            encounterCreature2->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS);
                            encounterCreature2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                            encounterCreature2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
                            encounterCreature2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
                            ((ScriptedAI*)encounterCreature2->AI())->EnableAttack(true);
                            DoScriptText(SAY_STAGE_1_AGGRO, encounterCreature2);
                            encounterCreature2->AI()->AttackStart(m_pInstance->GetRandomPlayerInMap());
                            m_pInstance->SetData(TYPE_JARAXXUS, IN_PROGRESS);
                            cooldown = REALLY_BIG_COOLDOWN;
                        }
                        else
                        {
                            DoScriptText(SAY_STAGE_1_01, m_pInstance->GetCreature(NPC_TIRION));
                            SummonToCBoss(NPC_FIZZLEBANG);
                            cooldown = 2000;
                        }
                        break;
                    }
                    case 2:
                    {
                        if (!encounterCreature)
                            break;

                        encounterCreature->AddSplineFlag(SPLINEFLAG_WALKMODE);
                        encounterCreature->GetMotionMaster()->MovePoint(POINT_MOVE, SpawnLoc[LOC_FIZZLE_END], false);

                        uint32 timeToPoint = uint32(encounterCreature->GetPosition().GetDistance2d(SpawnLoc[LOC_FIZZLE_END])/0.0025f);

                        m_TimerMgr->Cooldown(TIMER_DOOR_HANDLER, timeToPoint);
                        cooldown = timeToPoint + 1000;
                        break;
                    }
                    case 3:
                        DoScriptText(SAY_STAGE_1_02, encounterCreature);
                        cooldown = 11000;
                        break;
                    case 4:
                    {
                        DoScriptText(SAY_STAGE_1_03, encounterCreature);
                        Coords sumPos = SpawnLoc[LOC_CENTER];
                        encounterCreature->SummonCreature(NPC_WILFRED_PORTAL_GROUND, sumPos, 1.5f*M_PI_F, TEMPSUMMON_TIMED_DESPAWN, 8000);
                        cooldown = 2000;
                        break;
                    }
                    case 5:
                    {
                        Coords sumPos = SpawnLoc[LOC_CENTER];
                        sumPos.z += 5.f;
                        if (!(encounterCreature2 = encounterCreature->SummonCreature(NPC_TRIGGER, sumPos, 1.5f*M_PI_F, TEMPSUMMON_TIMED_DESPAWN, 6000)))
                            break;

                        encounterCreature2->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.f);
                        encounterCreature2->CastSpell(encounterCreature2, SPELL_WILFRED_PORTAL, false);
                        cooldown = 3500;
                        break;
                    }
                    case 6:
                        DoScriptText(SAY_STAGE_1_04, encounterCreature);
                        if (!(encounterCreature2 = DoSpawnTocBoss(NPC_JARAXXUS, encounterCreature2->GetPosition(), encounterCreature->GetOrientation())))
                            break;

                        cooldown = 500;
                        break;
                    case 7:
                        encounterCreature2->GetMotionMaster()->MovePoint(0, SpawnLoc[LOC_JAROXXUS_END]);
                        cooldown = 2300;
                        break;
                    case 8:
                        encounterCreature2->SetFacingToObject(encounterCreature);
                        encounterCreature2->SetSummonPoint(encounterCreature->GetPositionX(), encounterCreature->GetPositionY(), encounterCreature->GetPositionZ(), encounterCreature->GetOrientation());
                        ((ScriptedAI*)encounterCreature2->AI())->SetCombatMovement(false);
                        cooldown = 8500;
                        break;
                    case 9:
                        DoScriptText(SAY_STAGE_1_05, encounterCreature2);
                        cooldown = 7000;
                        break;
                    case 10:
                        DoScriptText(SAY_STAGE_1_06, encounterCreature);
                        cooldown = 800;
                        break;
                    case 11:
                        encounterCreature2->CastSpell(encounterCreature, SPELL_FEL_LIGHTNING_IK, false);
                        cooldown = 2000;
                        break;
                    case 12:
                        DoScriptText(SAY_STAGE_1_07, m_pInstance->GetCreature(NPC_TIRION));
                        ((ScriptedAI*)encounterCreature2->AI())->SetCombatMovement(true);
                        cooldown = 5000;
                        break;
                    case 13:
                        encounterCreature2->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS);
                        encounterCreature2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                        encounterCreature2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
                        encounterCreature2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
                        ((ScriptedAI*)encounterCreature2->AI())->EnableAttack(true);
                        m_pInstance->SetData(TYPE_JARAXXUS, IN_PROGRESS);
                        DoScriptText(SAY_STAGE_1_AGGRO, encounterCreature2);
                        encounterCreature2->AI()->AttackStart(m_pInstance->GetRandomPlayerInMap());
                        cooldown = REALLY_BIG_COOLDOWN;
                        break;
                    case 51: //outro
                        DoScriptText(SAY_STAGE_1_08, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 15000;
                        break;
                    case 52:
                        DoScriptText(SAY_STAGE_1_09, m_pInstance->GetCreature(NPC_GARROSH));
                        cooldown = 10000;
                        break;
                    case 53:
                        DoScriptText(SAY_STAGE_1_10, m_pInstance->GetCreature(NPC_WRYNN));
                        cooldown = 7000;
                        break;
                    case 54:
                        DoScriptText(SAY_STAGE_1_11, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 5000;
                        break;
                    case 55:
                        break;
                }
                break;
            }
            case TYPE_CRUSADERS:
            {
                switch(encounterStage)
                {
                    case 1:
                        DoScriptText(SAY_STAGE_2_01, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 9000;
                        break;
                    case 2:
                        if (m_pInstance->GetInstanceSide() == INSTANCE_SIDE_ALI)
                            DoScriptText(SAY_STAGE_2_02h, m_pInstance->GetCreature(NPC_GARROSH));
                        else
                            DoScriptText(SAY_STAGE_2_02a, m_pInstance->GetCreature(NPC_WRYNN));
                        cooldown = 17000;
                        break;
                    case 3:
                        DoScriptText(SAY_STAGE_2_03, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 5000;
                        break;
                    case 4:
                    {
                        uint32 spawnMask = 0;
                        if (!(spawnMask = m_pInstance->GetData(TYPE_CHAMPION_SPAWN_MASK)))
                        {
                            typedef std::list<uint8> ChampionList;
                            ChampionList healerList, dpsList, finalList;

                            for(uint8 i = 0; i < CHAMPION_COUNT; ++i)
                            {
                                if (i == CHAMPION_R_DRUID  || i == CHAMPION_H_PALADIN || i == CHAMPION_R_SHAMAN || i == CHAMPION_D_PRIEST)
                                    healerList.push_back(i);
                                else
                                    dpsList.push_back(i);
                            }

                            for(uint8 h = 0; h < 2; ++h)
                            {
                                uint8 neededCount = h ? (is10Man ? 2 : 3) : (is10Man ? 4 : 7);
                                ChampionList& refList = h ? healerList : dpsList;
                                for (uint8 i = 0; i < neededCount; ++i)
                                {
                                    ChampionList::iterator itr = refList.begin();
                                    std::advance(itr, urand(0, refList.size()-1));
                                    finalList.push_back(*itr);
                                    refList.erase(itr);
                                }
                            }

                            for(ChampionList::iterator itr = finalList.begin(); itr != finalList.end(); ++itr)
                                spawnMask |= (1 << *itr);

                            m_pInstance->SetData(TYPE_CHAMPION_SPAWN_MASK, spawnMask);
                        }
                        encounterCreature = NULL;
                        encounterCreature2 = NULL;
                        AddNonCastTimer(TIMER_CUSTOM, 500, 2000);
                        cooldown = REALLY_BIG_COOLDOWN;
                        break;
                    }
                    case 5:
                    {
                        uint32 textId, npcId, faction;
                        if (m_pInstance->GetInstanceSide() == INSTANCE_SIDE_ALI)
                        {
                            textId = SAY_STAGE_2_04h;
                            npcId = NPC_GARROSH;
                            faction = FACTION_HORDE;
                        }
                        else
                        {
                            textId = SAY_STAGE_2_04a;
                            npcId = NPC_WRYNN;
                            faction = FACTION_ALLIANCE;
                        }

                        DoScriptText(textId, m_pInstance->GetCreature(npcId));
                        CreatureList ChampionList;
                        for(uint8 i = 0; i < CHAMPION_COUNT; ++i)
                            GetCreatureListWithEntryInGrid(ChampionList, m_creature, FChampIDs[i][faction], DEFAULT_VISIBILITY_INSTANCE);

                        stepTimer->SetValue(TIMER_VALUE_CUSTOM, 0);

                        for(CreatureList::iterator itr = ChampionList.begin(); itr != ChampionList.end(); ++itr)
                        {
                            Creature* champ = *itr;
                            if (!champ)
                                continue;

                            champ->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                            ((ScriptedAI*)champ->AI())->EnableAttack(true);
                        }

                        cooldown = REALLY_BIG_COOLDOWN;
                        break;
                    }
                    case 51: // outro
                        DoScriptText(SAY_STAGE_2_06, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 5000;
                        break;
                    case 52:
                    {
                        uint32 chestId = 0;
                        m_pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_CHAMPIONS);
                        if (getMSTimeDiff(stepTimer->GetCustomValue(), getMSTime() < 73000)) // kill under 60 seconds
                            m_pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_CHAMPIONS_MINUTE);

                        switch(m_dDifficulty)
                        {
                            case RAID_DIFFICULTY_10MAN_NORMAL: chestId = GO_CRUSADERS_CACHE_10; break;
                            case RAID_DIFFICULTY_25MAN_NORMAL: chestId = GO_CRUSADERS_CACHE_25; break;
                            case RAID_DIFFICULTY_10MAN_HEROIC: chestId = GO_CRUSADERS_CACHE_10_H; break;
                            case RAID_DIFFICULTY_25MAN_HEROIC: chestId = GO_CRUSADERS_CACHE_25_H; break;
                            default: break;
                        }
                        if (chestId)
                            m_creature->SummonGameobject(chestId, SpawnLoc[LOC_CENTER], M_PI_F*1.5f, 604800);
                        break;
                    }
                }
                break;
            }
            case TYPE_VALKIRIES:
            {
                switch(encounterStage)
                {
                    case 1:
                        DoScriptText(SAY_STAGE_3_01, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 12000;
                        break;
                    case 2:
                        SummonToCBoss(NPC_LIGHTBANE, NPC_DARKBANE);
                        for(uint8 i = 0; i < 4; ++i)
                            DoSpawnTocBoss(i/2 ? NPC_LIGHT_ESSENCE : NPC_DARK_ESSENCE, SpawnLoc[LOC_D_ESSENCE_1+i], 0);

                        cooldown = 2000;
                        break;
                    case 3:
                    {
                        if (!encounterCreature || !encounterCreature2)
                            break;

                        DoScriptText(SAY_STAGE_3_02, m_pInstance->GetCreature(NPC_TIRION));

                        uint32 travelTime[2];
                        for(uint8 second = 0; second < 2; ++second)
                        {
                            Creature* crt = second ? encounterCreature2 : encounterCreature;
                            ((ScriptedAI*)crt->AI())->EnableAttack(false);

                            PointPath path;
                            path.resize(3);
                            path.set(0, crt->GetPosition());
                            path.set(1, second ? SpawnLoc[LOC_D_VALKYR_1] : SpawnLoc[LOC_L_VALKYR_1]);
                            path.set(2, second ? SpawnLoc[LOC_D_VALKYR_2] : SpawnLoc[LOC_L_VALKYR_2]);
                            //path.set(3, second ? SpawnLoc[LOC_D_VALKYR_3] : SpawnLoc[LOC_L_VALKYR_3]);

                            travelTime[second] = path.GetTotalLength()/(crt->GetSpeed(MOVE_RUN)*0.001f);

                            crt->GetMotionMaster()->Clear(false, true);
                            crt->ChargeMonsterMove(path, SPLINETYPE_FACINGANGLE, crt->GetSplineFlags(), travelTime[second], M_PI_F*1.5f);
                        }
                        cooldown = (travelTime[0] > travelTime[1] ? travelTime[0] : travelTime[1]) + 5000;
                        break;
                    }
                    case 4:
                    {
                        for(uint8 second = 0; second < 2; ++second)
                        {
                            Creature* crt = second ? encounterCreature2 : encounterCreature;
                            ((ScriptedAI*)crt->AI())->EnableAttack(true);
                            crt->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                        }
                        cooldown = REALLY_BIG_COOLDOWN;
                        break;
                    }
                    case 51: // outro
                        if (m_pInstance->GetInstanceSide() == INSTANCE_SIDE_ALI)
                            DoScriptText(SAY_STAGE_3_03a, m_pInstance->GetCreature(NPC_WRYNN));
                        else
                            DoScriptText(SAY_STAGE_3_03h, m_pInstance->GetCreature(NPC_GARROSH));
                        cooldown = 5000;
                        break;
                    case 52:
                        break;
                }
                break;
            }
            case TYPE_LICH_KING:
            {
                switch(encounterStage)
                {
                    case 1:
                        DoScriptText(SAY_STAGE_4_01, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 19000;
                        break;
                    case 2:
                        encounterCreature = DoSpawnTocBoss(NPC_LICH_KING, SpawnLoc[LOC_BACKDOOR], M_PI_F*1.5f);
                        encounterCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.1f);
                        encounterCreature->SetVisibility(VISIBILITY_OFF);
                        m_pInstance->SetData(TYPE_LICH_KING, IN_PROGRESS);
                        cooldown = 500;
                        break;
                    case 3:
                        DoScriptText(SAY_STAGE_4_02, encounterCreature);
                        cooldown = 7000;
                        break;
                    case 4:
                        if (!(encounterCreature2 = DoSpawnTocBoss(NPC_TRIGGER, SpawnLoc[LOC_LICH_KING_S], M_PI_F*1.5f, false)))
                            break;

                        encounterCreature2->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.8f);
                        encounterCreature2->CastSpell(encounterCreature2, SPELL_LK_GATE, false);
                        cooldown = 4000;
                        break;
                    case 5:
                        encounterCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.f);
                        m_pInstance->instance->CreatureRelocation(encounterCreature, SpawnLoc[LOC_LICH_KING_S], M_PI_F*1.5f);
                        cooldown = 500;
                        break;
                    case 6:
                    {
                        PointPath path;
                        path.resize(2);
                        path.set(0, SpawnLoc[LOC_LICH_KING_S]);
                        path.set(1, SpawnLoc[LOC_LICH_KING_E]);

                        encounterCreature->GetMotionMaster()->Clear(false, true);
                        encounterCreature->GetMotionMaster()->MoveIdle();
                        encounterCreature->ChargeMonsterMove(path, SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, path.GetTotalLength()/0.0025f);
                        cooldown = 3000;
                        break;
                    }
                    case 7:
                        DoScriptText(SAY_STAGE_4_03, m_pInstance->GetCreature(NPC_TIRION));
                        cooldown = 8000;
                        break;
                    case 8:
                        DoScriptText(SAY_STAGE_4_04, encounterCreature);
                        encounterCreature->HandleEmote(EMOTE_ONESHOT_LAUGH);
                        cooldown = 13000;
                        break;
                    case 9:
                        encounterCreature->HandleEmote(EMOTE_ONESHOT_EXCLAMATION);
                        cooldown = 3000;
                        break;
                    case 10:
                        encounterCreature->HandleEmote(EMOTE_ONESHOT_KNEEL);
                        cooldown = 1000;
                        break;
                    case 11:
                        encounterCreature->CastSpell(encounterCreature, SPELL_LK_NOVA, false);
                        cooldown = 500;
                        break;
                    case 12:
                    {
                        encounterCreature->SetVisibility(VISIBILITY_OFF);
                        m_pInstance->instance->CreatureRelocation(encounterCreature, SpawnLoc[LOC_BACKDOOR], M_PI_F*1.5f);
                        encounterCreature->SendMonsterMove(SpawnLoc[LOC_BACKDOOR].x, SpawnLoc[LOC_BACKDOOR].y, SpawnLoc[LOC_BACKDOOR].z, SPLINETYPE_NORMAL, encounterCreature->GetSplineFlags(), 1);

                        Map::PlayerList const &PlayerList = m_pInstance->instance->GetPlayers();
                        if (!PlayerList.isEmpty())
                            for (Map::PlayerList::const_iterator iter = PlayerList.begin(); iter != PlayerList.end(); ++iter)
                                if (Player* plr = iter->getSource())
                                    plr->KnockBackFrom(plr, 2, 25);

                        if (GameObject* pFloor = m_pInstance->GetGameObject(GO_ARGENT_COLISEUM_FLOOR))
                        {
                            pFloor->TakenDamage(100, m_creature);
                            pFloor->TakenDamage(100, m_creature);
                        }
                        cooldown = 2000;
                        break;
                    }
                    case 13:
                        DoScriptText(SAY_STAGE_4_05, encounterCreature);
                        cooldown = 10000;
                        break;
                    case 14:
                    {
                        m_pInstance->SetData(TYPE_LICH_KING, DONE);
                        encounterCreature->ForcedDespawn();
                        if (GameObject* pFloor = m_pInstance->GetGameObject(GO_ARGENT_COLISEUM_FLOOR))
                            pFloor->Rebuild(m_creature);
                        break;
                    }
                }
                break;
            }
            case TYPE_ANUBARAK:
            {
                switch(encounterStage)
                {
                    case 51:
                        if (!(encounterCreature = DoSpawnTocBoss(NPC_OUTRO_TIRION, SpawnLoc[LOC_O_TIRION_S], 0)))
                            break;
                        if (!(encounterCreature2 = DoSpawnTocBoss(NPC_OUTRO_ARGENT_MAGE, SpawnLoc[LOC_O_MAGE_S], 0)))
                            break;

                        encounterCreature->GetMotionMaster()->MovePoint(0, SpawnLoc[LOC_O_TIRION_E], false);
                        encounterCreature2->GetMotionMaster()->MovePoint(0, SpawnLoc[LOC_O_MAGE_E], false);
                        cooldown = 10000;
                        break;
                    case 52:
                        DoScriptText(SAY_STAGE_4_06, encounterCreature);
                        cooldown = 15000;
                        break;
                    case 53:
                        if (!isHeroic || m_pInstance->GetData(TYPE_COUNTER) >= 50)
                            break;

                        DoScriptText(SAY_STAGE_4_07, encounterCreature);
                        cooldown = 5000;
                        break;
                    case 54:
                    {
                        uint32 chestId = 0;
                        uint32 attempts = m_pInstance->GetData(TYPE_COUNTER);
                        if (isInRange(1, attempts, 24))
                            chestId = is10Man ? GO_TRIBUTE_CHEST_10H_1 : GO_TRIBUTE_CHEST_25H_1;
                        else if (isInRange(25, attempts, 44))
                            chestId = is10Man ? GO_TRIBUTE_CHEST_10H_25 : GO_TRIBUTE_CHEST_25H_25;
                        else if (isInRange(45, attempts, 49))
                            chestId = is10Man ? GO_TRIBUTE_CHEST_10H_45 : GO_TRIBUTE_CHEST_25H_45;
                        else if (attempts == 50)
                            chestId = is10Man ? GO_TRIBUTE_CHEST_10H_50 : GO_TRIBUTE_CHEST_25H_50;
                        if (chestId)
                            m_creature->SummonGameobject(chestId, SpawnLoc[LOC_UNDERGROUND], 0, 604800);

                        break;
                    }
                }
                break;
            }
            default:
                break;
        }

        cat_log("toc_announcer: Phase updating: Handling current encounter %u in encounter stage %u and setting cooldown to %u", currentEncounter, encounterStage, cooldown);

        if (cooldown)
            stepTimer->Cooldown(cooldown);
        else
            Reset();
    }

    // open and closes doors
    if (SpellTimer* doorTimer = m_TimerMgr->GetState(TIMER_DOOR_HANDLER))
    {
        uint64 doorGuid = m_pInstance->GetData64(GO_MAIN_GATE_DOOR);
        if (!doorTimer->GetCustomValue())
        {
            m_pInstance->OpenDoor(doorGuid);
            doorTimer->SetValue(TIMER_VALUE_CUSTOM, true);
        }
        else
        {
            m_pInstance->CloseDoor(doorGuid);
            doorTimer->SetValue(TIMER_VALUE_DELETE_AT_FINISH, true);
        }
    }

    // runaway of announcer
    if (SpellTimer* runawayTimer = m_TimerMgr->GetState(TIMER_RUNAWAY))
    {
        if (GameObject* go = m_pInstance->GetGameObject(GO_GATE_EAST))
        {
            Coords coord = go->GetPosition();
            m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
            m_creature->SetSpeedRate(MOVE_RUN, 1.2f, true);
            m_creature->GetMotionMaster()->MovePoint(POINT_MOVE, coord.x, coord.y, coord.z, false);
        }
        runawayTimer->SetValue(TIMER_VALUE_DELETE_AT_FINISH, true);
    }

    // handling of custom timer in the event
    if (SpellTimer* customTimer = m_TimerMgr->GetState(TIMER_CUSTOM))
    {
        if (currentEncounter == TYPE_CRUSADERS)
        {
            uint32 timerCustom = customTimer->GetCustomValue();
            uint32 spawnMask = m_pInstance->GetData(TYPE_CHAMPION_SPAWN_MASK);
            uint8 faction = m_pInstance->GetInstanceSide() == INSTANCE_SIDE_ALI ? FACTION_HORDE : FACTION_ALLIANCE;

            const Coords Spawn1 = faction == FACTION_ALLIANCE ? SpawnLoc[LOC_FCH_A_SPAWN_1] : SpawnLoc[LOC_FCH_H_SPAWN_1];
            const Coords Spawn2 = faction == FACTION_ALLIANCE ? SpawnLoc[LOC_FCH_A_SPAWN_2] : SpawnLoc[LOC_FCH_H_SPAWN_2];
            const Coords Jump1 = faction == FACTION_ALLIANCE ? SpawnLoc[LOC_FCH_A_JUMP_1] : SpawnLoc[LOC_FCH_H_JUMP_1];
            const Coords Jump2 = faction == FACTION_ALLIANCE ? SpawnLoc[LOC_FCH_A_JUMP_2] : SpawnLoc[LOC_FCH_H_JUMP_2];
            Coords Location = faction == FACTION_ALLIANCE ? SpawnLoc[LOC_FCH_A_MOVE] : SpawnLoc[LOC_FCH_H_MOVE];

            if (encounterCreature2)
            {
                int32 champOrder = customValue-2;
                int32 x_coef = champOrder%2 ? 1 : -1;
                int32 y_coef = champOrder/2 - (is10Man ? 1 : 2);
                if (faction == FACTION_HORDE)
                {
                    x_coef *= -1;
                    y_coef *= -1;
                }
                Location.x += x_coef*2.5f;
                Location.y += y_coef*5.f;

                PointPath path;
                path.resize(2);
                //path.set(0, champOrder%2 ? Jump2 : Jump1);
                path.set(0, encounterCreature2->GetPosition());
                path.set(1, Location);

                uint32 travelTime = path.GetTotalLength()/0.0025f;
                encounterCreature2->GetMotionMaster()->Clear(false, true);
                encounterCreature2->ChargeMonsterMove(path, SPLINETYPE_FACINGANGLE, SPLINEFLAG_WALKMODE,
                travelTime, faction == FACTION_ALLIANCE ? M_PI_F : 0);
                encounterCreature2 = NULL;

                // if is last one set phase handler to travelTime
                if (timerCustom == CHAMPION_COUNT && !encounterCreature)
                {
                    customTimer->SetValue(TIMER_VALUE_DELETE_AT_FINISH, true);
                    m_TimerMgr->Cooldown(TIMER_PHASE_HANDLING, travelTime);
                    return;
                }
            }
            if (encounterCreature)
            {
                uint32 champOrder = customValue-1;
                const Coords& jump = champOrder%2 ? Jump2 : Jump1;
                encounterCreature->GetMotionMaster()->Clear(false, true);
                encounterCreature->GetMotionMaster()->MoveIdle();
                encounterCreature->TrajMonsterMove(jump.x, jump.y, jump.z, false, 80, 1000);
                encounterCreature2 = encounterCreature;
                encounterCreature = NULL;
            }
            for(uint8 i = timerCustom; i < CHAMPION_COUNT; ++i)
            {
                customTimer->SetValue(TIMER_VALUE_CUSTOM, i+1);
                if (spawnMask & (1 << i))
                {
                    const Coords& spawn = customValue%2 ? Spawn2 : Spawn1;
                    encounterCreature = DoSpawnTocBoss(FChampIDs[i][faction], spawn, 0);
                    ((ScriptedAI*)encounterCreature->AI())->EnableAttack(false);
                    break;
                }
            }
            ++customValue;
        }
        else
            customTimer->SetValue(TIMER_VALUE_DELETE_AT_FINISH, true);
    }
}