rearranged core files
--HG-- branch : trunk
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "MapManager.h"
|
||||
#include "Opcodes.h"
|
||||
#include "ConfusedMovementGenerator.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "VMapFactory.h"
|
||||
|
||||
#ifdef MAP_BASED_RAND_GEN
|
||||
#define rand_norm() unit.rand_norm()
|
||||
#define urand(a,b) unit.urand(a,b)
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Initialize(T &unit)
|
||||
{
|
||||
const float wander_distance = 11;
|
||||
float x,y,z;
|
||||
x = unit.GetPositionX();
|
||||
y = unit.GetPositionY();
|
||||
z = unit.GetPositionZ();
|
||||
|
||||
Map const* map = unit.GetBaseMap();
|
||||
|
||||
i_nextMove = 1;
|
||||
|
||||
bool is_water_ok, is_land_ok;
|
||||
_InitSpecific(unit, is_water_ok, is_land_ok);
|
||||
|
||||
VMAP::IVMapManager *vMaps = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
|
||||
for (uint8 idx = 0; idx <= MAX_CONF_WAYPOINTS; ++idx)
|
||||
{
|
||||
const bool isInLoS = vMaps->isInLineOfSight(unit.GetMapId(), x, y, z + 2.0f, i_waypoints[idx][0], i_waypoints[idx][1], z + 2.0f);
|
||||
if (isInLoS)
|
||||
{
|
||||
const float wanderX = wander_distance*rand_norm() - wander_distance/2;
|
||||
const float wanderY = wander_distance*rand_norm() - wander_distance/2;
|
||||
i_waypoints[idx][0] = x + wanderX;
|
||||
i_waypoints[idx][1] = y + wanderY;
|
||||
}
|
||||
else
|
||||
{
|
||||
i_waypoints[idx][0] = x;
|
||||
i_waypoints[idx][1] = y;
|
||||
}
|
||||
|
||||
// prevent invalid coordinates generation
|
||||
Trinity::NormalizeMapCoord(i_waypoints[idx][0]);
|
||||
Trinity::NormalizeMapCoord(i_waypoints[idx][1]);
|
||||
|
||||
bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z);
|
||||
// if generated wrong path just ignore
|
||||
if ((is_water && !is_water_ok) || (!is_water && !is_land_ok))
|
||||
{
|
||||
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
|
||||
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
|
||||
}
|
||||
|
||||
unit.UpdateGroundPositionZ(i_waypoints[idx][0],i_waypoints[idx][1],z);
|
||||
i_waypoints[idx][2] = z;
|
||||
}
|
||||
|
||||
unit.SetUInt64Value(UNIT_FIELD_TARGET, 0);
|
||||
unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
|
||||
unit.CastStop();
|
||||
unit.StopMoving();
|
||||
unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
unit.addUnitState(UNIT_STAT_CONFUSED);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
ConfusedMovementGenerator<Creature>::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok)
|
||||
{
|
||||
is_water_ok = creature.canSwim();
|
||||
is_land_ok = creature.canWalk();
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
ConfusedMovementGenerator<Player>::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok)
|
||||
{
|
||||
is_water_ok = true;
|
||||
is_land_ok = true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Reset(T &unit)
|
||||
{
|
||||
i_nextMove = 1;
|
||||
i_nextMoveTime.Reset(0);
|
||||
i_destinationHolder.ResetUpdate();
|
||||
unit.StopMoving();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||
{
|
||||
if (!&unit)
|
||||
return true;
|
||||
|
||||
if (unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
|
||||
return true;
|
||||
|
||||
if (i_nextMoveTime.Passed())
|
||||
{
|
||||
// currently moving, update location
|
||||
Traveller<T> traveller(unit);
|
||||
if (i_destinationHolder.UpdateTraveller(traveller, diff))
|
||||
{
|
||||
if (i_destinationHolder.HasArrived())
|
||||
{
|
||||
// arrived, stop and wait a bit
|
||||
unit.clearUnitState(UNIT_STAT_MOVE);
|
||||
|
||||
i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
|
||||
i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// waiting for next move
|
||||
i_nextMoveTime.Update(diff);
|
||||
if (i_nextMoveTime.Passed())
|
||||
{
|
||||
// start moving
|
||||
assert(i_nextMove <= MAX_CONF_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];
|
||||
Traveller<T> traveller(unit);
|
||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Finalize(T &unit)
|
||||
{
|
||||
unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
|
||||
unit.clearUnitState(UNIT_STAT_CONFUSED);
|
||||
if (unit.GetTypeId() == TYPEID_UNIT && unit.getVictim())
|
||||
unit.SetUInt64Value(UNIT_FIELD_TARGET, unit.getVictim()->GetGUID());
|
||||
}
|
||||
|
||||
template void ConfusedMovementGenerator<Player>::Initialize(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Initialize(Creature &creature);
|
||||
template void ConfusedMovementGenerator<Player>::Finalize(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Finalize(Creature &creature);
|
||||
template void ConfusedMovementGenerator<Player>::Reset(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Reset(Creature &creature);
|
||||
template bool ConfusedMovementGenerator<Player>::Update(Player &player, const uint32 &diff);
|
||||
template bool ConfusedMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff);
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_CONFUSEDGENERATOR_H
|
||||
#define TRINITY_CONFUSEDGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "DestinationHolder.h"
|
||||
#include "Traveller.h"
|
||||
|
||||
#define MAX_CONF_WAYPOINTS 24
|
||||
|
||||
template<class T>
|
||||
class ConfusedMovementGenerator
|
||||
: public MovementGeneratorMedium< T, ConfusedMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
explicit ConfusedMovementGenerator() : i_nextMoveTime(0) {}
|
||||
|
||||
void Initialize(T &);
|
||||
void Finalize(T &);
|
||||
void Reset(T &);
|
||||
bool Update(T &, const uint32 &);
|
||||
|
||||
bool GetDestination(float &x, float &y, float &z) const
|
||||
{
|
||||
if (i_destinationHolder.HasArrived()) return false;
|
||||
i_destinationHolder.GetDestination(x,y,z);
|
||||
return true;
|
||||
}
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; }
|
||||
private:
|
||||
void _InitSpecific(T &, bool &, bool &);
|
||||
TimeTracker i_nextMoveTime;
|
||||
float i_waypoints[MAX_CONF_WAYPOINTS+1][3];
|
||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
||||
uint32 i_nextMove;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "MapManager.h"
|
||||
#include "FleeingMovementGenerator.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
#define MIN_QUIET_DISTANCE 28.0f
|
||||
#define MAX_QUIET_DISTANCE 43.0f
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::_setTargetLocation(T &owner)
|
||||
{
|
||||
if (!&owner)
|
||||
return;
|
||||
|
||||
if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
|
||||
return;
|
||||
|
||||
if (!_setMoveData(owner))
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
if (!_getPoint(owner, x, y, z))
|
||||
return;
|
||||
|
||||
owner.addUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING);
|
||||
Traveller<T> traveller(owner);
|
||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool FleeingMovementGenerator<Creature>::GetDestination(float &x, float &y, float &z) const
|
||||
{
|
||||
if (i_destinationHolder.HasArrived())
|
||||
return false;
|
||||
|
||||
i_destinationHolder.GetDestination(x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool FleeingMovementGenerator<Player>::GetDestination(float & /*x*/, float & /*y*/, float & /*z*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
|
||||
{
|
||||
if (!&owner)
|
||||
return false;
|
||||
|
||||
x = owner.GetPositionX();
|
||||
y = owner.GetPositionY();
|
||||
z = owner.GetPositionZ();
|
||||
|
||||
float temp_x, temp_y, angle = 0;
|
||||
const Map * _map = owner.GetBaseMap();
|
||||
//primitive path-finding
|
||||
for (uint8 i = 0; i < 18; ++i)
|
||||
{
|
||||
if (i_only_forward && i > 2)
|
||||
break;
|
||||
|
||||
float distance = 5.0f;
|
||||
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
angle = i_cur_angle;
|
||||
break;
|
||||
case 1:
|
||||
angle = i_cur_angle;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 2:
|
||||
angle = i_cur_angle;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 3:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
break;
|
||||
case 4:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
break;
|
||||
case 5:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 6:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 7:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
break;
|
||||
case 8:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
break;
|
||||
case 9:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 10:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 11:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 12:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 13:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 14:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 15:
|
||||
angle = i_cur_angle + M_PI*3/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 16:
|
||||
angle = i_cur_angle - M_PI*3/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 17:
|
||||
angle = i_cur_angle + M_PI;
|
||||
distance /= 2;
|
||||
break;
|
||||
}
|
||||
temp_x = x + distance * cos(angle);
|
||||
temp_y = y + distance * sin(angle);
|
||||
Trinity::NormalizeMapCoord(temp_x);
|
||||
Trinity::NormalizeMapCoord(temp_y);
|
||||
if (owner.IsWithinLOS(temp_x,temp_y,z))
|
||||
{
|
||||
bool is_water_now = _map->IsInWater(x,y,z);
|
||||
|
||||
if (is_water_now && _map->IsInWater(temp_x,temp_y,z))
|
||||
{
|
||||
x = temp_x;
|
||||
y = temp_y;
|
||||
return true;
|
||||
}
|
||||
float new_z = _map->GetHeight(temp_x,temp_y,z,true);
|
||||
|
||||
if (new_z <= INVALID_HEIGHT)
|
||||
continue;
|
||||
|
||||
bool is_water_next = _map->IsInWater(temp_x,temp_y,new_z);
|
||||
|
||||
if ((is_water_now && !is_water_next && !is_land_ok) || (!is_water_now && is_water_next && !is_water_ok))
|
||||
continue;
|
||||
|
||||
if (!(new_z - z) || distance / fabs(new_z - z) > 1.0f)
|
||||
{
|
||||
float new_z_left = _map->GetHeight(temp_x + 1.0f*cos(angle+M_PI/2),temp_y + 1.0f*sin(angle+M_PI/2),z,true);
|
||||
float new_z_right = _map->GetHeight(temp_x + 1.0f*cos(angle-M_PI/2),temp_y + 1.0f*sin(angle-M_PI/2),z,true);
|
||||
if (fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f)
|
||||
{
|
||||
x = temp_x;
|
||||
y = temp_y;
|
||||
z = new_z;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
i_nextCheckTime.Reset(urand(500,1000));
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::_setMoveData(T &owner)
|
||||
{
|
||||
float cur_dist_xyz = owner.GetDistance(i_caster_x, i_caster_y, i_caster_z);
|
||||
|
||||
if (i_to_distance_from_caster > 0.0f)
|
||||
{
|
||||
if ((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) ||
|
||||
// if we reach lower distance
|
||||
(i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) ||
|
||||
// if we can't be close
|
||||
(i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) ||
|
||||
// if we reach bigger distance
|
||||
(cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far
|
||||
(i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE))
|
||||
// if we leave 'quiet zone'
|
||||
{
|
||||
// we are very far or too close, stopping
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
i_nextCheckTime.Reset(urand(500,1000));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// now we are running, continue
|
||||
i_last_distance_from_caster = cur_dist_xyz;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
float cur_dist;
|
||||
float angle_to_caster;
|
||||
|
||||
Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID);
|
||||
|
||||
if (fright)
|
||||
{
|
||||
cur_dist = fright->GetDistance(&owner);
|
||||
if (cur_dist < cur_dist_xyz)
|
||||
{
|
||||
i_caster_x = fright->GetPositionX();
|
||||
i_caster_y = fright->GetPositionY();
|
||||
i_caster_z = fright->GetPositionZ();
|
||||
angle_to_caster = fright->GetAngle(&owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_dist = cur_dist_xyz;
|
||||
angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_dist = cur_dist_xyz;
|
||||
angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI;
|
||||
}
|
||||
|
||||
// if we too close may use 'path-finding' else just stop
|
||||
i_only_forward = cur_dist >= MIN_QUIET_DISTANCE/3;
|
||||
|
||||
//get angle and 'distance from caster' to run
|
||||
float angle;
|
||||
|
||||
if (i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time
|
||||
{
|
||||
angle = rand_norm()*(1.0f - cur_dist/MIN_QUIET_DISTANCE) * M_PI/3 + rand_norm()*M_PI*2/3;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE;
|
||||
i_only_forward = true;
|
||||
}
|
||||
else if (cur_dist < MIN_QUIET_DISTANCE)
|
||||
{
|
||||
angle = M_PI/6 + rand_norm()*M_PI*2/3;
|
||||
i_to_distance_from_caster = cur_dist*2/3 + rand_norm()*(MIN_QUIET_DISTANCE - cur_dist*2/3);
|
||||
}
|
||||
else if (cur_dist > MAX_QUIET_DISTANCE)
|
||||
{
|
||||
angle = rand_norm()*M_PI/3 + M_PI*2/3;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = rand_norm()*M_PI;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
|
||||
}
|
||||
|
||||
int8 sign = rand_norm() > 0.5f ? 1 : -1;
|
||||
i_cur_angle = sign*angle + angle_to_caster;
|
||||
|
||||
// current distance
|
||||
i_last_distance_from_caster = cur_dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Initialize(T &owner)
|
||||
{
|
||||
if (!&owner)
|
||||
return;
|
||||
|
||||
_Init(owner);
|
||||
owner.CastStop();
|
||||
owner.addUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING);
|
||||
owner.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
|
||||
owner.SetUInt64Value(UNIT_FIELD_TARGET, 0);
|
||||
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
|
||||
if (Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID))
|
||||
{
|
||||
i_caster_x = fright->GetPositionX();
|
||||
i_caster_y = fright->GetPositionY();
|
||||
i_caster_z = fright->GetPositionZ();
|
||||
}
|
||||
else
|
||||
{
|
||||
i_caster_x = owner.GetPositionX();
|
||||
i_caster_y = owner.GetPositionY();
|
||||
i_caster_z = owner.GetPositionZ();
|
||||
}
|
||||
|
||||
i_only_forward = true;
|
||||
i_cur_angle = 0.0f;
|
||||
i_last_distance_from_caster = 0.0f;
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
FleeingMovementGenerator<Creature>::_Init(Creature &owner)
|
||||
{
|
||||
if (!&owner)
|
||||
return;
|
||||
|
||||
is_water_ok = owner.canSwim();
|
||||
is_land_ok = owner.canWalk();
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
FleeingMovementGenerator<Player>::_Init(Player &)
|
||||
{
|
||||
is_water_ok = true;
|
||||
is_land_ok = true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Finalize(T &owner)
|
||||
{
|
||||
owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
|
||||
owner.clearUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING);
|
||||
if (owner.GetTypeId() == TYPEID_UNIT && owner.getVictim())
|
||||
owner.SetUInt64Value(UNIT_FIELD_TARGET, owner.getVictim()->GetGUID());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Reset(T &owner)
|
||||
{
|
||||
Initialize(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
|
||||
{
|
||||
if (!&owner || !owner.isAlive())
|
||||
return false;
|
||||
if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
|
||||
return true;
|
||||
|
||||
Traveller<T> traveller(owner);
|
||||
|
||||
i_nextCheckTime.Update(time_diff);
|
||||
|
||||
if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || !i_destinationHolder.HasDestination())
|
||||
{
|
||||
_setTargetLocation(owner);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i_destinationHolder.UpdateTraveller(traveller, time_diff))
|
||||
{
|
||||
i_destinationHolder.ResetUpdate(50);
|
||||
if (i_nextCheckTime.Passed() && i_destinationHolder.HasArrived())
|
||||
{
|
||||
_setTargetLocation(owner);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template void FleeingMovementGenerator<Player>::Initialize(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Initialize(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::_setMoveData(Player &);
|
||||
template bool FleeingMovementGenerator<Creature>::_setMoveData(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::_getPoint(Player &, float &, float &, float &);
|
||||
template bool FleeingMovementGenerator<Creature>::_getPoint(Creature &, float &, float &, float &);
|
||||
template void FleeingMovementGenerator<Player>::_setTargetLocation(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::_setTargetLocation(Creature &);
|
||||
template void FleeingMovementGenerator<Player>::Finalize(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Finalize(Creature &);
|
||||
template void FleeingMovementGenerator<Player>::Reset(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Reset(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::Update(Player &, const uint32 &);
|
||||
template bool FleeingMovementGenerator<Creature>::Update(Creature &, const uint32 &);
|
||||
|
||||
void TimedFleeingMovementGenerator::Finalize(Unit &owner)
|
||||
{
|
||||
owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
|
||||
owner.clearUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING);
|
||||
if (Unit* victim = owner.getVictim())
|
||||
{
|
||||
if (owner.isAlive())
|
||||
{
|
||||
owner.AttackStop();
|
||||
owner.ToCreature()->AI()->AttackStart(victim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TimedFleeingMovementGenerator::Update(Unit & owner, const uint32 & time_diff)
|
||||
{
|
||||
if (!owner.isAlive())
|
||||
return false;
|
||||
|
||||
if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
|
||||
return true;
|
||||
|
||||
i_totalFleeTime.Update(time_diff);
|
||||
if (i_totalFleeTime.Passed())
|
||||
return false;
|
||||
|
||||
// This calls grant-parent Update method hiden by FleeingMovementGenerator::Update(Creature &, const uint32 &) version
|
||||
// This is done instead of casting Unit& to Creature& and call parent method, then we can use Unit directly
|
||||
return MovementGeneratorMedium< Creature, FleeingMovementGenerator<Creature> >::Update(owner, time_diff);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_FLEEINGMOVEMENTGENERATOR_H
|
||||
#define TRINITY_FLEEINGMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "DestinationHolder.h"
|
||||
#include "Traveller.h"
|
||||
|
||||
template<class T>
|
||||
class FleeingMovementGenerator
|
||||
: public MovementGeneratorMedium< T, FleeingMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
FleeingMovementGenerator(uint64 fright) : i_frightGUID(fright), i_nextCheckTime(0) {}
|
||||
|
||||
void Initialize(T &);
|
||||
void Finalize(T &);
|
||||
void Reset(T &);
|
||||
bool Update(T &, const uint32 &);
|
||||
bool GetDestination(float &x, float &y, float &z) const;
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
void _setTargetLocation(T &owner);
|
||||
bool _getPoint(T &owner, float &x, float &y, float &z);
|
||||
bool _setMoveData(T &owner);
|
||||
void _Init(T &);
|
||||
|
||||
bool is_water_ok :1;
|
||||
bool is_land_ok :1;
|
||||
bool i_only_forward:1;
|
||||
|
||||
float i_caster_x;
|
||||
float i_caster_y;
|
||||
float i_caster_z;
|
||||
float i_last_distance_from_caster;
|
||||
float i_to_distance_from_caster;
|
||||
float i_cur_angle;
|
||||
uint64 i_frightGUID;
|
||||
TimeTracker i_nextCheckTime;
|
||||
|
||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
||||
};
|
||||
|
||||
class TimedFleeingMovementGenerator
|
||||
: public FleeingMovementGenerator<Creature>
|
||||
{
|
||||
public:
|
||||
TimedFleeingMovementGenerator(uint64 fright, uint32 time) :
|
||||
FleeingMovementGenerator<Creature>(fright),
|
||||
i_totalFleeTime(time) {}
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return TIMED_FLEEING_MOTION_TYPE; }
|
||||
bool Update(Unit &, const uint32 &);
|
||||
void Finalize(Unit &);
|
||||
|
||||
private:
|
||||
TimeTracker i_totalFleeTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "HomeMovementGenerator.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "Traveller.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
void
|
||||
HomeMovementGenerator<Creature>::Initialize(Creature & owner)
|
||||
{
|
||||
float x, y, z;
|
||||
owner.GetHomePosition(x, y, z, ori);
|
||||
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
owner.addUnitState(UNIT_STAT_EVADE);
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
void
|
||||
HomeMovementGenerator<Creature>::Reset(Creature &)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
modifyTravelTime(travel_time);
|
||||
owner.clearUnitState(UNIT_STAT_ALL_STATE);
|
||||
}
|
||||
|
||||
bool
|
||||
HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff)
|
||||
{
|
||||
CreatureTraveller traveller(owner);
|
||||
i_destinationHolder.UpdateTraveller(traveller, time_diff);
|
||||
|
||||
if (time_diff > i_travel_timer)
|
||||
{
|
||||
owner.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
|
||||
// restore orientation of not moving creature at returning to home
|
||||
if (owner.GetDefaultMovementType() == IDLE_MOTION_TYPE)
|
||||
{
|
||||
//sLog.outDebug("Entering HomeMovement::GetDestination(z,y,z)");
|
||||
owner.SetOrientation(ori);
|
||||
WorldPacket packet;
|
||||
owner.BuildHeartBeatMsg(&packet);
|
||||
owner.SendMessageToSet(&packet, false);
|
||||
}
|
||||
|
||||
owner.clearUnitState(UNIT_STAT_EVADE);
|
||||
owner.AI()->JustReachedHome();
|
||||
return false;
|
||||
}
|
||||
|
||||
i_travel_timer -= time_diff;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_HOMEMOVEMENTGENERATOR_H
|
||||
#define TRINITY_HOMEMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "DestinationHolder.h"
|
||||
#include "Traveller.h"
|
||||
|
||||
class Creature;
|
||||
|
||||
template < class T >
|
||||
class HomeMovementGenerator;
|
||||
|
||||
template <>
|
||||
class HomeMovementGenerator<Creature>
|
||||
: public MovementGeneratorMedium< Creature, HomeMovementGenerator<Creature> >
|
||||
{
|
||||
public:
|
||||
|
||||
HomeMovementGenerator() {}
|
||||
~HomeMovementGenerator() {}
|
||||
|
||||
void Initialize(Creature &);
|
||||
void Finalize(Creature &) {}
|
||||
void Reset(Creature &);
|
||||
bool Update(Creature &, const uint32 &);
|
||||
void modifyTravelTime(uint32 travel_time) { i_travel_timer = travel_time; }
|
||||
MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; }
|
||||
|
||||
bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
|
||||
|
||||
private:
|
||||
void _setTargetLocation(Creature &);
|
||||
DestinationHolder< Traveller<Creature> > i_destinationHolder;
|
||||
|
||||
float ori;
|
||||
uint32 i_travel_timer;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "IdleMovementGenerator.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "Creature.h"
|
||||
|
||||
IdleMovementGenerator si_idleMovement;
|
||||
|
||||
// StopMoving is needed to make unit stop if its last movement generator expires
|
||||
// But it should not be sent otherwise there are many redundent packets
|
||||
void IdleMovementGenerator::Initialize(Unit &owner)
|
||||
{
|
||||
if (owner.hasUnitState(UNIT_STAT_MOVE))
|
||||
owner.StopMoving();
|
||||
}
|
||||
|
||||
void
|
||||
IdleMovementGenerator::Reset(Unit& owner)
|
||||
{
|
||||
if (owner.hasUnitState(UNIT_STAT_MOVE))
|
||||
owner.StopMoving();
|
||||
}
|
||||
|
||||
void RotateMovementGenerator::Initialize(Unit& owner)
|
||||
{
|
||||
if (owner.hasUnitState(UNIT_STAT_MOVE))
|
||||
owner.StopMoving();
|
||||
|
||||
if (owner.getVictim())
|
||||
owner.SetInFront(owner.getVictim());
|
||||
|
||||
owner.addUnitState(UNIT_STAT_ROTATING);
|
||||
|
||||
owner.AttackStop();
|
||||
}
|
||||
|
||||
bool RotateMovementGenerator::Update(Unit& owner, const uint32& diff)
|
||||
{
|
||||
float angle = owner.GetOrientation();
|
||||
if (m_direction == ROTATE_DIRECTION_LEFT)
|
||||
{
|
||||
angle += (float)diff * M_PI * 2 / m_maxDuration;
|
||||
while (angle >= M_PI * 2) angle -= M_PI * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle -= (float)diff * M_PI * 2 / m_maxDuration;
|
||||
while (angle < 0) angle += M_PI * 2;
|
||||
}
|
||||
owner.SetOrientation(angle);
|
||||
owner.SendMovementFlagUpdate(); // this is a hack. we do not have anything correct to send in the beginning
|
||||
|
||||
if (m_duration > diff)
|
||||
m_duration -= diff;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RotateMovementGenerator::Finalize(Unit &unit)
|
||||
{
|
||||
unit.clearUnitState(UNIT_STAT_ROTATING);
|
||||
if (unit.GetTypeId() == TYPEID_UNIT)
|
||||
unit.ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0);
|
||||
}
|
||||
|
||||
void
|
||||
DistractMovementGenerator::Initialize(Unit& owner)
|
||||
{
|
||||
owner.addUnitState(UNIT_STAT_DISTRACTED);
|
||||
}
|
||||
|
||||
void
|
||||
DistractMovementGenerator::Finalize(Unit& owner)
|
||||
{
|
||||
owner.clearUnitState(UNIT_STAT_DISTRACTED);
|
||||
}
|
||||
|
||||
bool
|
||||
DistractMovementGenerator::Update(Unit& /*owner*/, const uint32& time_diff)
|
||||
{
|
||||
if (time_diff > m_timer)
|
||||
return false;
|
||||
|
||||
m_timer -= time_diff;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
AssistanceDistractMovementGenerator::Finalize(Unit &unit)
|
||||
{
|
||||
unit.clearUnitState(UNIT_STAT_DISTRACTED);
|
||||
unit.ToCreature()->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_IDLEMOVEMENTGENERATOR_H
|
||||
#define TRINITY_IDLEMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
|
||||
class IdleMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
|
||||
void Initialize(Unit &);
|
||||
void Finalize(Unit &) { }
|
||||
void Reset(Unit &);
|
||||
bool Update(Unit &, const uint32 &) { return true; }
|
||||
MovementGeneratorType GetMovementGeneratorType() { return IDLE_MOTION_TYPE; }
|
||||
};
|
||||
|
||||
extern IdleMovementGenerator si_idleMovement;
|
||||
|
||||
class RotateMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : m_duration(time), m_maxDuration(time), m_direction(direction) {}
|
||||
|
||||
void Initialize(Unit& owner);
|
||||
void Finalize(Unit& owner);
|
||||
void Reset(Unit& owner) { Initialize(owner); }
|
||||
bool Update(Unit& owner, const uint32& time_diff);
|
||||
MovementGeneratorType GetMovementGeneratorType() { return ROTATE_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
uint32 m_duration, m_maxDuration;
|
||||
RotateDirection m_direction;
|
||||
};
|
||||
|
||||
class DistractMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
explicit DistractMovementGenerator(uint32 timer) : m_timer(timer) {}
|
||||
|
||||
void Initialize(Unit& owner);
|
||||
void Finalize(Unit& owner);
|
||||
void Reset(Unit& owner) { Initialize(owner); }
|
||||
bool Update(Unit& owner, const uint32& time_diff);
|
||||
MovementGeneratorType GetMovementGeneratorType() { return DISTRACT_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
uint32 m_timer;
|
||||
};
|
||||
|
||||
class AssistanceDistractMovementGenerator : public DistractMovementGenerator
|
||||
{
|
||||
public:
|
||||
AssistanceDistractMovementGenerator(uint32 timer) :
|
||||
DistractMovementGenerator(timer) {}
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_DISTRACT_MOTION_TYPE; }
|
||||
void Finalize(Unit& unit);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
|
||||
MovementGenerator::~MovementGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_MOVEMENTGENERATOR_H
|
||||
#define TRINITY_MOVEMENTGENERATOR_H
|
||||
|
||||
#include "Platform/Define.h"
|
||||
#include "Policies/Singleton.h"
|
||||
#include "Dynamic/ObjectRegistry.h"
|
||||
#include "Dynamic/FactoryHolder.h"
|
||||
#include "Common.h"
|
||||
#include "MotionMaster.h"
|
||||
|
||||
class Unit;
|
||||
|
||||
class MovementGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~MovementGenerator();
|
||||
|
||||
virtual void Initialize(Unit &) = 0;
|
||||
virtual void Finalize(Unit &) = 0;
|
||||
|
||||
virtual void Reset(Unit &) = 0;
|
||||
|
||||
virtual bool Update(Unit &, const uint32 &time_diff) = 0;
|
||||
|
||||
virtual MovementGeneratorType GetMovementGeneratorType() = 0;
|
||||
|
||||
virtual void unitSpeedChanged() { }
|
||||
|
||||
virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; }
|
||||
};
|
||||
|
||||
template<class T, class D>
|
||||
class MovementGeneratorMedium : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
void Initialize(Unit &u)
|
||||
{
|
||||
//u->AssertIsType<T>();
|
||||
(static_cast<D*>(this))->Initialize(*((T*)&u));
|
||||
}
|
||||
void Finalize(Unit &u)
|
||||
{
|
||||
//u->AssertIsType<T>();
|
||||
(static_cast<D*>(this))->Finalize(*((T*)&u));
|
||||
}
|
||||
void Reset(Unit &u)
|
||||
{
|
||||
//u->AssertIsType<T>();
|
||||
(static_cast<D*>(this))->Reset(*((T*)&u));
|
||||
}
|
||||
bool Update(Unit &u, const uint32 &time_diff)
|
||||
{
|
||||
//u->AssertIsType<T>();
|
||||
return (static_cast<D*>(this))->Update(*((T*)&u), time_diff);
|
||||
}
|
||||
public:
|
||||
// will not link if not overridden in the generators
|
||||
void Initialize(T &u);
|
||||
void Finalize(T &u);
|
||||
void Reset(T &u);
|
||||
bool Update(T &u, const uint32 &time_diff);
|
||||
};
|
||||
|
||||
struct SelectableMovement : public FactoryHolder<MovementGenerator,MovementGeneratorType>
|
||||
{
|
||||
SelectableMovement(MovementGeneratorType mgt) : FactoryHolder<MovementGenerator,MovementGeneratorType>(mgt) {}
|
||||
};
|
||||
|
||||
template<class REAL_MOVEMENT>
|
||||
struct MovementGeneratorFactory : public SelectableMovement
|
||||
{
|
||||
MovementGeneratorFactory(MovementGeneratorType mgt) : SelectableMovement(mgt) {}
|
||||
|
||||
MovementGenerator* Create(void *) const;
|
||||
};
|
||||
|
||||
typedef FactoryHolder<MovementGenerator,MovementGeneratorType> MovementGeneratorCreator;
|
||||
typedef FactoryHolder<MovementGenerator,MovementGeneratorType>::FactoryHolderRegistry MovementGeneratorRegistry;
|
||||
typedef FactoryHolder<MovementGenerator,MovementGeneratorType>::FactoryHolderRepository MovementGeneratorRepository;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_MOVEMENTGENERATOR_IMPL_H
|
||||
#define TRINITY_MOVEMENTGENERATOR_IMPL_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
|
||||
template<class MOVEMENT_GEN>
|
||||
inline MovementGenerator*
|
||||
MovementGeneratorFactory<MOVEMENT_GEN>::Create(void * /*data*/) const
|
||||
{
|
||||
return (new MOVEMENT_GEN());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "PointMovementGenerator.h"
|
||||
#include "Errors.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "World.h"
|
||||
|
||||
//----- Point Movement Generator
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::Initialize(T &unit)
|
||||
{
|
||||
unit.StopMoving();
|
||||
Traveller<T> traveller(unit);
|
||||
// knockback effect has UNIT_STAT_JUMPING set,so if here we disable sentmonstermove there will be creature position sync problem between client and server
|
||||
i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z, true /* !unit.hasUnitState(UNIT_STAT_JUMPING)*/);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool PointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||
{
|
||||
if (!&unit)
|
||||
return false;
|
||||
|
||||
if (unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
|
||||
{
|
||||
if (unit.hasUnitState(UNIT_STAT_CHARGING))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
Traveller<T> traveller(unit);
|
||||
|
||||
i_destinationHolder.UpdateTraveller(traveller, diff);
|
||||
|
||||
if (i_destinationHolder.HasArrived())
|
||||
{
|
||||
unit.clearUnitState(UNIT_STAT_MOVE);
|
||||
arrived = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>:: Finalize(T &unit)
|
||||
{
|
||||
if (unit.hasUnitState(UNIT_STAT_CHARGING))
|
||||
unit.clearUnitState(UNIT_STAT_CHARGING | UNIT_STAT_JUMPING);
|
||||
if (arrived) // without this crash!
|
||||
MovementInform(unit);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::MovementInform(T & /*unit*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <> void PointMovementGenerator<Creature>::MovementInform(Creature &unit)
|
||||
{
|
||||
if (id == EVENT_FALL_GROUND)
|
||||
{
|
||||
unit.setDeathState(JUST_DIED);
|
||||
unit.SetFlying(true);
|
||||
}
|
||||
unit.AI()->MovementInform(POINT_MOTION_TYPE, id);
|
||||
}
|
||||
|
||||
template void PointMovementGenerator<Player>::Initialize(Player&);
|
||||
template bool PointMovementGenerator<Player>::Update(Player &, const uint32 &diff);
|
||||
template void PointMovementGenerator<Player>::MovementInform(Player&);
|
||||
template void PointMovementGenerator<Player>::Finalize(Player&);
|
||||
|
||||
template void PointMovementGenerator<Creature>::Initialize(Creature&);
|
||||
template bool PointMovementGenerator<Creature>::Update(Creature&, const uint32 &diff);
|
||||
template void PointMovementGenerator<Creature>::Finalize(Creature&);
|
||||
|
||||
void AssistanceMovementGenerator::Finalize(Unit &unit)
|
||||
{
|
||||
unit.ToCreature()->SetNoCallAssistance(false);
|
||||
unit.ToCreature()->CallAssistance();
|
||||
if (unit.isAlive())
|
||||
unit.GetMotionMaster()->MoveSeekAssistanceDistract(sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_POINTMOVEMENTGENERATOR_H
|
||||
#define TRINITY_POINTMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "DestinationHolder.h"
|
||||
#include "Traveller.h"
|
||||
#include "FollowerReference.h"
|
||||
|
||||
template<class T>
|
||||
class PointMovementGenerator
|
||||
: public MovementGeneratorMedium< T, PointMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
PointMovementGenerator(uint32 _id, float _x, float _y, float _z) : id(_id),
|
||||
i_x(_x), i_y(_y), i_z(_z), i_nextMoveTime(0), arrived(false) {}
|
||||
|
||||
void Initialize(T &);
|
||||
void Finalize(T &unit);
|
||||
void Reset(T &unit){unit.StopMoving();}
|
||||
bool Update(T &, const uint32 &diff);
|
||||
|
||||
void MovementInform(T &);
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; }
|
||||
|
||||
bool GetDestination(float& x, float& y, float& z) const { x=i_x; y=i_y; z=i_z; return true; }
|
||||
private:
|
||||
uint32 id;
|
||||
float i_x,i_y,i_z;
|
||||
TimeTracker i_nextMoveTime;
|
||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
||||
bool arrived;
|
||||
};
|
||||
|
||||
class AssistanceMovementGenerator
|
||||
: public PointMovementGenerator<Creature>
|
||||
{
|
||||
public:
|
||||
AssistanceMovementGenerator(float _x, float _y, float _z) :
|
||||
PointMovementGenerator<Creature>(0, _x, _y, _z) {}
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_MOTION_TYPE; }
|
||||
void Finalize(Unit &);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "MapManager.h"
|
||||
#include "RandomMovementGenerator.h"
|
||||
#include "Traveller.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "Map.h"
|
||||
#include "Util.h"
|
||||
#include "CreatureGroups.h"
|
||||
|
||||
#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV"
|
||||
|
||||
template<>
|
||||
bool
|
||||
RandomMovementGenerator<Creature>::GetDestination(float &x, float &y, float &z) const
|
||||
{
|
||||
if (i_destinationHolder.HasArrived())
|
||||
return false;
|
||||
|
||||
i_destinationHolder.GetDestination(x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MAP_BASED_RAND_GEN
|
||||
#define rand_norm() creature.rand_norm()
|
||||
#endif
|
||||
|
||||
template<>
|
||||
void
|
||||
RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
|
||||
{
|
||||
float X,Y,Z,z,nx,ny,nz,ori,dist;
|
||||
|
||||
creature.GetHomePosition(X, Y, Z, ori);
|
||||
|
||||
z = creature.GetPositionZ();
|
||||
Map const* map = creature.GetBaseMap();
|
||||
|
||||
// For 2D/3D system selection
|
||||
//bool is_land_ok = creature.canWalk();
|
||||
//bool is_water_ok = creature.canSwim();
|
||||
bool is_air_ok = creature.canFly();
|
||||
|
||||
for (uint32 i = 0; ; ++i)
|
||||
{
|
||||
|
||||
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 (i == 5)
|
||||
{
|
||||
nz = Z;
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
continue; // 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)
|
||||
continue; // let's forget this bad coords where a z cannot be find and retry at next tick
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
//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.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
}
|
||||
|
||||
//Call for creature group update
|
||||
if (creature.GetFormation() && creature.GetFormation()->getLeader() == &creature)
|
||||
{
|
||||
creature.GetFormation()->LeaderMoveTo(nx, ny, nz);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
RandomMovementGenerator<Creature>::Initialize(Creature &creature)
|
||||
{
|
||||
if (!creature.isAlive())
|
||||
return;
|
||||
|
||||
if (!wander_distance)
|
||||
wander_distance = creature.GetRespawnRadius();
|
||||
|
||||
if (irand(0,RUNNING_CHANCE_RANDOMMV) > 0)
|
||||
creature.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
_setRandomLocation(creature);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
RandomMovementGenerator<Creature>::Reset(Creature &creature)
|
||||
{
|
||||
Initialize(creature);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
RandomMovementGenerator<Creature>::Finalize(Creature & /*creature*/){}
|
||||
|
||||
template<>
|
||||
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 | UNIT_STAT_MOVE);
|
||||
|
||||
if (!i_destinationHolder.HasArrived() && creature.IsStopped())
|
||||
creature.addUnitState(UNIT_STAT_ROAMING);
|
||||
|
||||
CreatureTraveller traveller(creature);
|
||||
|
||||
if (i_destinationHolder.UpdateTraveller(traveller, diff, true))
|
||||
{
|
||||
if (i_nextMoveTime.Passed())
|
||||
{
|
||||
if (irand(0,RUNNING_CHANCE_RANDOMMV) > 0)
|
||||
creature.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
_setRandomLocation(creature);
|
||||
}
|
||||
else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(),PET_FOLLOW_DIST+2.5f))
|
||||
{
|
||||
creature.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
_setRandomLocation(creature);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_RANDOMMOTIONGENERATOR_H
|
||||
#define TRINITY_RANDOMMOTIONGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "DestinationHolder.h"
|
||||
#include "Traveller.h"
|
||||
|
||||
template<class T>
|
||||
class RandomMovementGenerator
|
||||
: public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
// Wander dist is related on db spawn dist. So what if we wanna set eandom movement on summoned creature?!
|
||||
RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) {}
|
||||
|
||||
void _setRandomLocation(T &);
|
||||
void Initialize(T &);
|
||||
void Finalize(T &);
|
||||
void Reset(T &);
|
||||
bool Update(T &, const uint32 &);
|
||||
bool GetDestination(float &x, float &y, float &z) const;
|
||||
void UpdateMapPosition(uint32 mapid, float &x ,float &y, float &z)
|
||||
{
|
||||
i_destinationHolder.GetLocationNow(mapid, x,y,z);
|
||||
}
|
||||
MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; }
|
||||
private:
|
||||
TimeTrackerSmall i_nextMoveTime;
|
||||
|
||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
||||
float wander_distance;
|
||||
uint32 i_nextMove;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ByteBuffer.h"
|
||||
#include "TargetedMovementGenerator.h"
|
||||
#include "Errors.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "World.h"
|
||||
|
||||
#define SMALL_ALPHA 0.05f
|
||||
|
||||
#include <cmath>
|
||||
/*
|
||||
struct StackCleaner
|
||||
{
|
||||
Creature &i_creature;
|
||||
StackCleaner(Creature &creature) : i_creature(creature) {}
|
||||
void Done(void) { i_creature.StopMoving(); }
|
||||
~StackCleaner()
|
||||
{
|
||||
i_creature->Clear();
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
template<class T>
|
||||
TargetedMovementGenerator<T>::TargetedMovementGenerator(Unit &target, float offset, float angle)
|
||||
: TargetedMovementGeneratorBase(target)
|
||||
, i_offset(offset), i_angle(angle), i_recalculateTravel(false)
|
||||
{
|
||||
target.GetPosition(i_targetX, i_targetY, i_targetZ);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
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())
|
||||
{
|
||||
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))
|
||||
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);
|
||||
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);
|
||||
owner.addUnitState(UNIT_STAT_CHASE);
|
||||
i_destinationHolder.StartTravel(traveller);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
TargetedMovementGenerator<T>::Initialize(T &owner)
|
||||
{
|
||||
if (owner.isInCombat())
|
||||
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
TargetedMovementGenerator<T>::Finalize(T &owner)
|
||||
{
|
||||
owner.clearUnitState(UNIT_STAT_CHASE);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
TargetedMovementGenerator<T>::Reset(T &owner)
|
||||
{
|
||||
Initialize(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
|
||||
{
|
||||
if (!i_target.isValid() || !i_target->IsInWorld())
|
||||
return false;
|
||||
|
||||
if (!&owner || !owner.isAlive())
|
||||
return true;
|
||||
|
||||
if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED))
|
||||
return true;
|
||||
|
||||
// prevent movement while casting spells with cast time or channel time
|
||||
if (owner.hasUnitState(UNIT_STAT_CASTING))
|
||||
{
|
||||
if (!owner.IsStopped())
|
||||
owner.StopMoving();
|
||||
return true;
|
||||
}
|
||||
|
||||
// prevent crash after creature killed pet
|
||||
if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
|
||||
return true;
|
||||
|
||||
Traveller<T> traveller(owner);
|
||||
|
||||
if (!i_destinationHolder.HasDestination())
|
||||
_setTargetLocation(owner);
|
||||
else if (owner.IsStopped() && !i_destinationHolder.HasArrived())
|
||||
{
|
||||
owner.addUnitState(UNIT_STAT_CHASE);
|
||||
i_destinationHolder.StartTravel(traveller);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i_destinationHolder.UpdateTraveller(traveller, time_diff))
|
||||
{
|
||||
// put targeted movement generators on a higher priority
|
||||
//if (owner.GetObjectSize())
|
||||
//i_destinationHolder.ResetUpdate(50);
|
||||
|
||||
// target moved
|
||||
if (i_targetX != i_target->GetPositionX() || i_targetY != i_target->GetPositionY()
|
||||
|| i_targetZ != i_target->GetPositionZ())
|
||||
{
|
||||
if (_setTargetLocation(owner) || !owner.hasUnitState(UNIT_STAT_FOLLOW))
|
||||
owner.SetInFront(i_target.getTarget());
|
||||
i_target->GetPosition(i_targetX, i_targetY, i_targetZ);
|
||||
}
|
||||
|
||||
if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
|
||||
{
|
||||
i_recalculateTravel = false;
|
||||
//Angle update will take place into owner.StopMoving()
|
||||
owner.SetInFront(i_target.getTarget());
|
||||
|
||||
owner.StopMoving();
|
||||
if (owner.IsWithinMeleeRange(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
|
||||
owner.Attack(i_target.getTarget(),true);
|
||||
}
|
||||
}
|
||||
|
||||
// Implemented for PetAI to handle resetting flags when pet owner reached
|
||||
if (i_destinationHolder.HasArrived())
|
||||
MovementInform(owner);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Unit*
|
||||
TargetedMovementGenerator<T>::GetTarget() const
|
||||
{
|
||||
return i_target.getTarget();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void TargetedMovementGenerator<T>::MovementInform(T & /*unit*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <> void TargetedMovementGenerator<Creature>::MovementInform(Creature &unit)
|
||||
{
|
||||
// Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
|
||||
unit.AI()->MovementInform(TARGETED_MOTION_TYPE, i_target.getTarget()->GetGUIDLow());
|
||||
}
|
||||
|
||||
template void TargetedMovementGenerator<Player>::MovementInform(Player&); // Not implemented for players
|
||||
template TargetedMovementGenerator<Player>::TargetedMovementGenerator(Unit &target, float offset, float angle);
|
||||
template TargetedMovementGenerator<Creature>::TargetedMovementGenerator(Unit &target, float offset, float angle);
|
||||
template bool TargetedMovementGenerator<Player>::_setTargetLocation(Player &);
|
||||
template bool TargetedMovementGenerator<Creature>::_setTargetLocation(Creature &);
|
||||
template void TargetedMovementGenerator<Player>::Initialize(Player &);
|
||||
template void TargetedMovementGenerator<Creature>::Initialize(Creature &);
|
||||
template void TargetedMovementGenerator<Player>::Finalize(Player &);
|
||||
template void TargetedMovementGenerator<Creature>::Finalize(Creature &);
|
||||
template void TargetedMovementGenerator<Player>::Reset(Player &);
|
||||
template void TargetedMovementGenerator<Creature>::Reset(Creature &);
|
||||
template bool TargetedMovementGenerator<Player>::Update(Player &, const uint32 &);
|
||||
template bool TargetedMovementGenerator<Creature>::Update(Creature &, const uint32 &);
|
||||
template Unit* TargetedMovementGenerator<Player>::GetTarget() const;
|
||||
template Unit* TargetedMovementGenerator<Creature>::GetTarget() const;
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_TARGETEDMOVEMENTGENERATOR_H
|
||||
#define TRINITY_TARGETEDMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "DestinationHolder.h"
|
||||
#include "Traveller.h"
|
||||
#include "FollowerReference.h"
|
||||
|
||||
class TargetedMovementGeneratorBase
|
||||
{
|
||||
public:
|
||||
TargetedMovementGeneratorBase(Unit &target) { i_target.link(&target, this); }
|
||||
void stopFollowing() { }
|
||||
protected:
|
||||
FollowerReference i_target;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class TargetedMovementGenerator
|
||||
: public MovementGeneratorMedium< T, TargetedMovementGenerator<T> >, public TargetedMovementGeneratorBase
|
||||
{
|
||||
public:
|
||||
TargetedMovementGenerator(Unit &target, float offset = 0, float angle = 0);
|
||||
~TargetedMovementGenerator() {}
|
||||
|
||||
void Initialize(T &);
|
||||
void Finalize(T &);
|
||||
void Reset(T &);
|
||||
bool Update(T &, const uint32 &);
|
||||
MovementGeneratorType GetMovementGeneratorType() { return TARGETED_MOTION_TYPE; }
|
||||
|
||||
void MovementInform(T &);
|
||||
|
||||
Unit* GetTarget() const;
|
||||
|
||||
bool GetDestination(float &x, float &y, float &z) const
|
||||
{
|
||||
if (i_destinationHolder.HasArrived() || !i_destinationHolder.HasDestination()) return false;
|
||||
i_destinationHolder.GetDestination(x,y,z);
|
||||
return true;
|
||||
}
|
||||
|
||||
void unitSpeedChanged() { i_recalculateTravel=true; }
|
||||
private:
|
||||
|
||||
bool _setTargetLocation(T &);
|
||||
|
||||
float i_offset;
|
||||
float i_angle;
|
||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
||||
bool i_recalculateTravel;
|
||||
float i_targetX, i_targetY, i_targetZ;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,682 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
//Basic headers
|
||||
#include "WaypointMovementGenerator.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
//Extended headers
|
||||
#include "ObjectMgr.h"
|
||||
#include "World.h"
|
||||
#include "MapManager.h" // for flightmaster grid preloading
|
||||
//Creature-specific headers
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureGroups.h"
|
||||
//Player-specific
|
||||
#include "Player.h"
|
||||
|
||||
template<class T>
|
||||
void
|
||||
WaypointMovementGenerator<T>::Initialize(T & /*u*/){}
|
||||
|
||||
template<>
|
||||
void
|
||||
WaypointMovementGenerator<Creature>::Finalize(Creature & /*u*/){}
|
||||
|
||||
template<>
|
||||
void
|
||||
WaypointMovementGenerator<Player>::Finalize(Player & /*u*/){}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
WaypointMovementGenerator<T>::MovementInform(T & /*unit*/){}
|
||||
|
||||
template<>
|
||||
void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
|
||||
{
|
||||
unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool WaypointMovementGenerator<Creature>::GetDestination(float &x, float &y, float &z) const
|
||||
{
|
||||
if (i_destinationHolder.HasArrived())
|
||||
return false;
|
||||
|
||||
i_destinationHolder.GetDestination(x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool WaypointMovementGenerator<Player>::GetDestination(float & /*x*/, float & /*y*/, float & /*z*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
void WaypointMovementGenerator<Creature>::Reset(Creature & /*unit*/)
|
||||
{
|
||||
StopedByPlayer = true;
|
||||
i_nextMoveTime.Reset(0);
|
||||
}
|
||||
|
||||
template<>
|
||||
void WaypointMovementGenerator<Player>::Reset(Player & /*unit*/){}
|
||||
|
||||
template<>
|
||||
void WaypointMovementGenerator<Creature>::InitTraveller(Creature &unit, const WaypointData &node)
|
||||
{
|
||||
node.run ? unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE):
|
||||
unit.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
WaypointMovementGenerator<Creature>::Initialize(Creature &u)
|
||||
{
|
||||
u.StopMoving();
|
||||
//i_currentNode = -1; // uint32, become 0 in the first update
|
||||
//i_nextMoveTime.Reset(0);
|
||||
StopedByPlayer = false;
|
||||
if (!path_id)
|
||||
path_id = u.GetWaypointPath();
|
||||
waypoints = sWaypointMgr->GetPath(path_id);
|
||||
i_currentNode = 0;
|
||||
if (waypoints && waypoints->size())
|
||||
{
|
||||
node = waypoints->front();
|
||||
Traveller<Creature> traveller(u);
|
||||
InitTraveller(u, *node);
|
||||
i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z);
|
||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
||||
|
||||
//Call for creature group update
|
||||
if (u.GetFormation() && u.GetFormation()->getLeader() == &u)
|
||||
u.GetFormation()->LeaderMoveTo(node->x, node->y, node->z);
|
||||
}
|
||||
else
|
||||
node = NULL;
|
||||
}
|
||||
|
||||
template<>
|
||||
void WaypointMovementGenerator<Player>::InitTraveller(Player & /*unit*/, const WaypointData & /*node*/){}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
WaypointMovementGenerator<T>::Update(T & /*unit*/, const uint32 & /*diff*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff)
|
||||
{
|
||||
if (!&unit)
|
||||
return true;
|
||||
|
||||
if (!path_id)
|
||||
return false;
|
||||
|
||||
// Waypoint movement can be switched on/off
|
||||
// This is quite handy for escort quests and other stuff
|
||||
if (unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
|
||||
return true;
|
||||
|
||||
// Clear the generator if the path doesn't exist
|
||||
if (!waypoints || !waypoints->size())
|
||||
return false;
|
||||
|
||||
Traveller<Creature> traveller(unit);
|
||||
|
||||
i_nextMoveTime.Update(diff);
|
||||
i_destinationHolder.UpdateTraveller(traveller, diff, true);
|
||||
|
||||
if (i_nextMoveTime.GetExpiry() < TIMEDIFF_NEXT_WP)
|
||||
{
|
||||
if (unit.IsStopped())
|
||||
{
|
||||
if (StopedByPlayer)
|
||||
{
|
||||
assert(node);
|
||||
InitTraveller(unit, *node);
|
||||
i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z);
|
||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
||||
StopedByPlayer = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i_currentNode == waypoints->size() - 1) // If that's our last waypoint
|
||||
{
|
||||
if (repeating) // If the movement is repeating
|
||||
i_currentNode = 0; // Start moving all over again
|
||||
else
|
||||
{
|
||||
unit.SetHomePosition(node->x, node->y, node->z, unit.GetOrientation());
|
||||
unit.GetMotionMaster()->Initialize();
|
||||
return false; // Clear the waypoint movement
|
||||
}
|
||||
}
|
||||
else
|
||||
++i_currentNode;
|
||||
|
||||
node = waypoints->at(i_currentNode);
|
||||
InitTraveller(unit, *node);
|
||||
i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z);
|
||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
||||
|
||||
//Call for creature group update
|
||||
if (unit.GetFormation() && unit.GetFormation()->getLeader() == &unit)
|
||||
unit.GetFormation()->LeaderMoveTo(node->x, node->y, node->z);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Determine waittime
|
||||
if (node->delay)
|
||||
i_nextMoveTime.Reset(node->delay);
|
||||
|
||||
//note: disable "start" for mtmap
|
||||
if (node->event_id && urand(0,99) < node->event_chance)
|
||||
unit.GetMap()->ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL/*, false*/);
|
||||
|
||||
i_destinationHolder.ResetTravelTime();
|
||||
MovementInform(unit);
|
||||
unit.UpdateWaypointID(i_currentNode);
|
||||
unit.clearUnitState(UNIT_STAT_ROAMING);
|
||||
unit.Relocate(node->x, node->y, node->z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unit.IsStopped() && !i_destinationHolder.HasArrived())
|
||||
{
|
||||
if (!StopedByPlayer)
|
||||
{
|
||||
i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
|
||||
i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
|
||||
StopedByPlayer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template void WaypointMovementGenerator<Player>::Initialize(Player &);
|
||||
template bool WaypointMovementGenerator<Player>::Update(Player &, const uint32 &);
|
||||
template void WaypointMovementGenerator<Player>::MovementInform(Player &);
|
||||
|
||||
//----------------------------------------------------//
|
||||
void FlightPathMovementGenerator::LoadPath(Player &)
|
||||
{
|
||||
objmgr.GetTaxiPathNodes(i_pathId, i_path,i_mapIds);
|
||||
}
|
||||
|
||||
uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
|
||||
{
|
||||
if (i_currentNode >= i_mapIds.size())
|
||||
return i_mapIds.size();
|
||||
|
||||
uint32 curMapId = i_mapIds[i_currentNode];
|
||||
for (uint32 i = i_currentNode; i < i_mapIds.size(); ++i)
|
||||
{
|
||||
if (i_mapIds[i] != curMapId)
|
||||
return i;
|
||||
}
|
||||
|
||||
return i_mapIds.size();
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::Initialize(Player &player)
|
||||
{
|
||||
player.getHostileRefManager().setOnlineOfflineState(false);
|
||||
player.addUnitState(UNIT_STAT_IN_FLIGHT);
|
||||
player.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
||||
LoadPath(player);
|
||||
Traveller<Player> traveller(player);
|
||||
// do not send movement, it was sent already
|
||||
i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false);
|
||||
|
||||
player.SendMonsterMoveByPath(GetPath(), GetCurrentNode(), GetPathAtMapEnd());
|
||||
|
||||
// Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will
|
||||
// be reinitialized for each flightmaster at the end of each spline (or stop) in the flight.
|
||||
|
||||
uint32 nodeCount = i_mapIds.size(); // Get the number of nodes in the path. i_path and i_mapIds are the
|
||||
// same size when loaded in ObjectMgr::GetTaxiPathNodes, called from LoadPath()
|
||||
|
||||
m_endMapId = i_mapIds[nodeCount -1]; // Get the map ID from the last node
|
||||
m_preloadTargetNode = nodeCount / 2; // Split the number of nodes in half to preload the flightmaster half-way through the flight
|
||||
m_endGridX = i_path[nodeCount -1].x; // Get the X position from the last node
|
||||
m_endGridY = i_path[nodeCount -1].y; // Get tye Y position from the last node
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::Finalize(Player & player)
|
||||
{
|
||||
player.clearUnitState(UNIT_STAT_IN_FLIGHT);
|
||||
|
||||
float x, y, z;
|
||||
i_destinationHolder.GetLocationNow(player.GetBaseMap(), x, y, z);
|
||||
player.SetPosition(x, y, z, player.GetOrientation());
|
||||
}
|
||||
|
||||
bool FlightPathMovementGenerator::Update(Player &player, const uint32 &diff)
|
||||
{
|
||||
if (MovementInProgress())
|
||||
{
|
||||
Traveller<Player> traveller(player);
|
||||
if (i_destinationHolder.UpdateTraveller(traveller, diff))
|
||||
{
|
||||
i_destinationHolder.ResetUpdate(FLIGHT_TRAVEL_UPDATE);
|
||||
if (i_destinationHolder.HasArrived())
|
||||
{
|
||||
uint32 curMap = i_mapIds[i_currentNode];
|
||||
++i_currentNode;
|
||||
if (MovementInProgress())
|
||||
{
|
||||
DEBUG_LOG("loading node %u for player %s", i_currentNode, player.GetName());
|
||||
if (i_mapIds[i_currentNode] == curMap)
|
||||
{
|
||||
// do not send movement, it was sent already
|
||||
i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false);
|
||||
}
|
||||
|
||||
// check if it's time to preload the flightmaster grid at path end
|
||||
if (i_currentNode == m_preloadTargetNode)
|
||||
PreloadEndGrid();
|
||||
|
||||
return true;
|
||||
}
|
||||
//else HasArrived()
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
// we have arrived at the end of the path
|
||||
return false;
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
|
||||
{
|
||||
if (i_mapIds.empty())
|
||||
return;
|
||||
|
||||
uint32 map0 = i_mapIds[0];
|
||||
for (size_t i = 1; i < i_mapIds.size(); ++i)
|
||||
{
|
||||
if (i_mapIds[i] != map0)
|
||||
{
|
||||
i_currentNode = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::PreloadEndGrid()
|
||||
{
|
||||
// used to preload the final grid where the flightmaster is
|
||||
Map *endMap = MapManager::Instance().FindMap(m_endMapId);
|
||||
|
||||
// Load the grid
|
||||
if (endMap)
|
||||
{
|
||||
sLog.outDetail("Preloading flightmaster at grid (%f, %f) for map %u", m_endGridX, m_endGridY, m_endMapId);
|
||||
endMap->LoadGrid(m_endGridX, m_endGridY);
|
||||
}
|
||||
else
|
||||
sLog.outDetail("Unable to determine map to preload flightmaster grid");
|
||||
}
|
||||
|
||||
//
|
||||
// Unique1's ASTAR Pathfinding Code... For future use & reference...
|
||||
//
|
||||
|
||||
#ifdef __PATHFINDING__
|
||||
|
||||
int GetFCost(int to, int num, int parentNum, float *gcost); // Below...
|
||||
|
||||
int ShortenASTARRoute(short int *pathlist, int number)
|
||||
{ // Wrote this to make the routes a little smarter (shorter)... No point looping back to the same places... Unique1
|
||||
short int temppathlist[MAX_PATHLIST_NODES];
|
||||
int count = 0;
|
||||
// int count2 = 0;
|
||||
int temp, temp2;
|
||||
int link;
|
||||
int upto = 0;
|
||||
|
||||
for (temp = number; temp >= 0; temp--)
|
||||
{
|
||||
qboolean shortened = qfalse;
|
||||
|
||||
for (temp2 = 0; temp2 < temp; temp2++)
|
||||
{
|
||||
for (link = 0; link < nodes[pathlist[temp]].enodenum; link++)
|
||||
{
|
||||
if (nodes[pathlist[temp]].links[link].flags & PATH_BLOCKED)
|
||||
continue;
|
||||
|
||||
//if ((bot->client->ps.eFlags & EF_TANK) && nodes[bot->current_node].links[link].flags & PATH_NOTANKS) //if this path is blocked, skip it
|
||||
// continue;
|
||||
|
||||
//if (nodes[nodes[pathlist[temp]].links[link].targetNode].origin[2] > nodes[pathlist[temp]].origin[2] + 32)
|
||||
// continue;
|
||||
|
||||
if (nodes[pathlist[temp]].links[link].targetNode == pathlist[temp2])
|
||||
{ // Found a shorter route...
|
||||
//if (OrgVisible(nodes[pathlist[temp2]].origin, nodes[pathlist[temp]].origin, -1))
|
||||
{
|
||||
temppathlist[count] = pathlist[temp2];
|
||||
temp = temp2;
|
||||
++count;
|
||||
shortened = qtrue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shortened)
|
||||
{
|
||||
temppathlist[count] = pathlist[temp];
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
upto = count;
|
||||
|
||||
for (temp = 0; temp < count; temp++)
|
||||
{
|
||||
pathlist[temp] = temppathlist[upto];
|
||||
--upto;
|
||||
}
|
||||
|
||||
G_Printf("ShortenASTARRoute: Path size reduced from %i to %i nodes...n", number, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
CreatePathAStar
|
||||
This function uses the A* pathfinding algorithm to determine the
|
||||
shortest path between any two nodes.
|
||||
It's fairly complex, so I'm not really going to explain it much.
|
||||
Look up A* and binary heaps for more info.
|
||||
pathlist stores the ideal path between the nodes, in reverse order,
|
||||
and the return value is the number of nodes in that path
|
||||
===========================================================================
|
||||
*/
|
||||
int CreatePathAStar(gentity_t *bot, int from, int to, short int *pathlist)
|
||||
{
|
||||
//all the data we have to hold...since we can't do dynamic allocation, has to be MAX_NODES
|
||||
//we can probably lower this later - eg, the open list should never have more than at most a few dozen items on it
|
||||
short int openlist[MAX_NODES+1]; //add 1 because it's a binary heap, and they don't use 0 - 1 is the first used index
|
||||
float gcost[MAX_NODES];
|
||||
int fcost[MAX_NODES];
|
||||
char list[MAX_NODES]; //0 is neither, 1 is open, 2 is closed - char because it's the smallest data type
|
||||
short int parent[MAX_NODES];
|
||||
|
||||
short int numOpen = 0;
|
||||
short int atNode, temp, newnode=-1;
|
||||
qboolean found = qfalse;
|
||||
int count = -1;
|
||||
float gc;
|
||||
int i, u, v, m;
|
||||
vec3_t vec;
|
||||
|
||||
//clear out all the arrays
|
||||
memset(openlist, 0, sizeof(short int)*(MAX_NODES+1));
|
||||
memset(fcost, 0, sizeof(int)*MAX_NODES);
|
||||
memset(list, 0, sizeof(char)*MAX_NODES);
|
||||
memset(parent, 0, sizeof(short int)*MAX_NODES);
|
||||
memset(gcost, -1, sizeof(float)*MAX_NODES);
|
||||
|
||||
//make sure we have valid data before calculating everything
|
||||
if ((from == NODE_INVALID) || (to == NODE_INVALID) || (from >= MAX_NODES) || (to >= MAX_NODES) || (from == to))
|
||||
return -1;
|
||||
|
||||
openlist[1] = from; //add the starting node to the open list
|
||||
++numOpen;
|
||||
gcost[from] = 0; //its f and g costs are obviously 0
|
||||
fcost[from] = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (numOpen != 0) //if there are still items in the open list
|
||||
{
|
||||
//pop the top item off of the list
|
||||
atNode = openlist[1];
|
||||
list[atNode] = 2; //put the node on the closed list so we don't check it again
|
||||
--numOpen;
|
||||
|
||||
openlist[1] = openlist[numOpen+1]; //move the last item in the list to the top position
|
||||
v = 1;
|
||||
|
||||
//this while loop reorders the list so that the new lowest fcost is at the top again
|
||||
while (1)
|
||||
{
|
||||
u = v;
|
||||
if ((2*u+1) < numOpen) //if both children exist
|
||||
{
|
||||
if (fcost[openlist[u]] >= fcost[openlist[2*u]])
|
||||
v = 2*u;
|
||||
if (fcost[openlist[v]] >= fcost[openlist[2*u+1]])
|
||||
v = 2*u+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((2*u) < numOpen) //if only one child exists
|
||||
{
|
||||
if (fcost[openlist[u]] >= fcost[openlist[2*u]])
|
||||
v = 2*u;
|
||||
}
|
||||
}
|
||||
|
||||
if (u != v) //if they're out of order, swap this item with its parent
|
||||
{
|
||||
temp = openlist[u];
|
||||
openlist[u] = openlist[v];
|
||||
openlist[v] = temp;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < nodes[atNode].enodenum; ++i) //loop through all the links for this node
|
||||
{
|
||||
newnode = nodes[atNode].links[i].targetNode;
|
||||
|
||||
//if this path is blocked, skip it
|
||||
if (nodes[atNode].links[i].flags & PATH_BLOCKED)
|
||||
continue;
|
||||
//if this path is blocked, skip it
|
||||
if (bot->client && (bot->client->ps.eFlags & EF_TANK) && nodes[atNode].links[i].flags & PATH_NOTANKS)
|
||||
continue;
|
||||
//skip any unreachable nodes
|
||||
if (bot->client && (nodes[newnode].type & NODE_ALLY_UNREACHABLE) && (bot->client->sess.sessionTeam == TEAM_ALLIES))
|
||||
continue;
|
||||
if (bot->client && (nodes[newnode].type & NODE_AXIS_UNREACHABLE) && (bot->client->sess.sessionTeam == TEAM_AXIS))
|
||||
continue;
|
||||
|
||||
if (list[newnode] == 2) //if this node is on the closed list, skip it
|
||||
continue;
|
||||
|
||||
if (list[newnode] != 1) //if this node is not already on the open list
|
||||
{
|
||||
openlist[++numOpen] = newnode; //add the new node to the open list
|
||||
list[newnode] = 1;
|
||||
parent[newnode] = atNode; //record the node's parent
|
||||
|
||||
if (newnode == to) //if we've found the goal, don't keep computing paths!
|
||||
break; //this will break the 'for' and go all the way to 'if (list[to] == 1)'
|
||||
|
||||
//store it's f cost value
|
||||
fcost[newnode] = GetFCost(to, newnode, parent[newnode], gcost);
|
||||
|
||||
//this loop re-orders the heap so that the lowest fcost is at the top
|
||||
m = numOpen;
|
||||
while (m != 1) //while this item isn't at the top of the heap already
|
||||
{
|
||||
//if it has a lower fcost than its parent
|
||||
if (fcost[openlist[m]] <= fcost[openlist[m/2]])
|
||||
{
|
||||
temp = openlist[m/2];
|
||||
openlist[m/2] = openlist[m];
|
||||
openlist[m] = temp; //swap them
|
||||
m /= 2;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else //if this node is already on the open list
|
||||
{
|
||||
gc = gcost[atNode];
|
||||
VectorSubtract(nodes[newnode].origin, nodes[atNode].origin, vec);
|
||||
gc += VectorLength(vec); //calculate what the gcost would be if we reached this node along the current path
|
||||
|
||||
if (gc < gcost[newnode]) //if the new gcost is less (ie, this path is shorter than what we had before)
|
||||
{
|
||||
parent[newnode] = atNode; //set the new parent for this node
|
||||
gcost[newnode] = gc; //and the new g cost
|
||||
|
||||
for (i = 1; i < numOpen; ++i) //loop through all the items on the open list
|
||||
{
|
||||
if (openlist[i] == newnode) //find this node in the list
|
||||
{
|
||||
//calculate the new fcost and store it
|
||||
fcost[newnode] = GetFCost(to, newnode, parent[newnode], gcost);
|
||||
|
||||
//reorder the list again, with the lowest fcost item on top
|
||||
m = i;
|
||||
while (m != 1)
|
||||
{
|
||||
//if the item has a lower fcost than it's parent
|
||||
if (fcost[openlist[m]] < fcost[openlist[m/2]])
|
||||
{
|
||||
temp = openlist[m/2];
|
||||
openlist[m/2] = openlist[m];
|
||||
openlist[m] = temp; //swap them
|
||||
m /= 2;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
break; //exit the 'for' loop because we already changed this node
|
||||
} //if
|
||||
} //for
|
||||
} //if (gc < gcost[newnode])
|
||||
} //if (list[newnode] != 1) --> else
|
||||
} //for (loop through links)
|
||||
} //if (numOpen != 0)
|
||||
else
|
||||
{
|
||||
found = qfalse; //there is no path between these nodes
|
||||
break;
|
||||
}
|
||||
|
||||
if (list[to] == 1) //if the destination node is on the open list, we're done
|
||||
{
|
||||
found = qtrue;
|
||||
break;
|
||||
}
|
||||
} //while (1)
|
||||
|
||||
if (found == qtrue) //if we found a path
|
||||
{
|
||||
//G_Printf("%s - path found!n", bot->client->pers.netname);
|
||||
count = 0;
|
||||
|
||||
temp = to; //start at the end point
|
||||
while (temp != from) //travel along the path (backwards) until we reach the starting point
|
||||
{
|
||||
pathlist[count++] = temp; //add the node to the pathlist and increment the count
|
||||
temp = parent[temp]; //move to the parent of this node to continue the path
|
||||
}
|
||||
|
||||
pathlist[count++] = from; //add the beginning node to the end of the pathlist
|
||||
|
||||
#ifdef __BOT_SHORTEN_ROUTING__
|
||||
count = ShortenASTARRoute(pathlist, count); // This isn't working... Dunno why.. Unique1
|
||||
#endif //__BOT_SHORTEN_ROUTING__
|
||||
}
|
||||
else
|
||||
{
|
||||
//G_Printf("^1*** ^4BOT DEBUG^5: (CreatePathAStar) There is no route between node ^7%i^5 and node ^7%i^5.n", from, to);
|
||||
count = CreateDumbRoute(from, to, pathlist);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
#ifdef __BOT_SHORTEN_ROUTING__
|
||||
count = ShortenASTARRoute(pathlist, count); // This isn't working... Dunno why.. Unique1
|
||||
#endif //__BOT_SHORTEN_ROUTING__
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
return count; //return the number of nodes in the path, -1 if not found
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
GetFCost
|
||||
Utility function used by A* pathfinding to calculate the
|
||||
cost to move between nodes towards a goal. Using the A*
|
||||
algorithm F = G + H, G here is the distance along the node
|
||||
paths the bot must travel, and H is the straight-line distance
|
||||
to the goal node.
|
||||
Returned as an int because more precision is unnecessary and it
|
||||
will slightly speed up heap access
|
||||
===========================================================================
|
||||
*/
|
||||
int GetFCost(int to, int num, int parentNum, float *gcost)
|
||||
{
|
||||
float gc = 0;
|
||||
float hc = 0;
|
||||
vec3_t v;
|
||||
|
||||
if (gcost[num] == -1)
|
||||
{
|
||||
if (parentNum != -1)
|
||||
{
|
||||
gc = gcost[parentNum];
|
||||
VectorSubtract(nodes[num].origin, nodes[parentNum].origin, v);
|
||||
gc += VectorLength(v);
|
||||
}
|
||||
gcost[num] = gc;
|
||||
}
|
||||
else
|
||||
gc = gcost[num];
|
||||
|
||||
VectorSubtract(nodes[to].origin, nodes[num].origin, v);
|
||||
hc = VectorLength(v);
|
||||
|
||||
return (int)(gc + hc);
|
||||
}
|
||||
#endif //__PATHFINDING__
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_WAYPOINTMOVEMENTGENERATOR_H
|
||||
#define TRINITY_WAYPOINTMOVEMENTGENERATOR_H
|
||||
|
||||
/** @page PathMovementGenerator is used to generate movements
|
||||
* of waypoints and flight paths. Each serves the purpose
|
||||
* of generate activities so that it generates updated
|
||||
* packets for the players.
|
||||
*/
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "DestinationHolder.h"
|
||||
#include "WaypointManager.h"
|
||||
#include "Path.h"
|
||||
#include "Traveller.h"
|
||||
|
||||
#include "Player.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#define FLIGHT_TRAVEL_UPDATE 100
|
||||
#define STOP_TIME_FOR_PLAYER 3 * MINUTE * IN_MILISECONDS // 3 Minutes
|
||||
#define TIMEDIFF_NEXT_WP 250
|
||||
|
||||
template<class T, class P = Path>
|
||||
class PathMovementBase
|
||||
{
|
||||
public:
|
||||
PathMovementBase() : i_currentNode(0) {}
|
||||
virtual ~PathMovementBase() {};
|
||||
|
||||
bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
|
||||
|
||||
void LoadPath(T &);
|
||||
void ReloadPath(T &);
|
||||
uint32 GetCurrentNode() const { return i_currentNode; }
|
||||
|
||||
protected:
|
||||
uint32 i_currentNode;
|
||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
||||
P i_path;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
|
||||
class WaypointMovementGenerator
|
||||
: public MovementGeneratorMedium< T, WaypointMovementGenerator<T> >, public PathMovementBase<T>
|
||||
{
|
||||
public:
|
||||
WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) :
|
||||
i_nextMoveTime(0), path_id(_path_id), repeating(_repeating), StopedByPlayer(false), node(NULL) {}
|
||||
|
||||
void Initialize(T &);
|
||||
void Finalize(T &);
|
||||
void MovementInform(T &);
|
||||
void InitTraveller(T &, const WaypointData &);
|
||||
void GeneratePathId(T &);
|
||||
void Reset(T &unit);
|
||||
bool Update(T &, const uint32 &);
|
||||
bool GetDestination(float &x, float &y, float &z) const;
|
||||
MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
WaypointData *node;
|
||||
uint32 path_id;
|
||||
TimeTrackerSmall i_nextMoveTime;
|
||||
WaypointPath *waypoints;
|
||||
bool repeating, StopedByPlayer;
|
||||
};
|
||||
|
||||
/** FlightPathMovementGenerator generates movement of the player for the paths
|
||||
* and hence generates ground and activities for the player.
|
||||
*/
|
||||
class FlightPathMovementGenerator
|
||||
: public MovementGeneratorMedium< Player, FlightPathMovementGenerator >,
|
||||
public PathMovementBase<Player>
|
||||
{
|
||||
uint32 i_pathId;
|
||||
std::vector<uint32> i_mapIds;
|
||||
public:
|
||||
explicit FlightPathMovementGenerator(uint32 id, uint32 startNode = 0) : i_pathId(id) { i_currentNode = startNode; }
|
||||
void Initialize(Player &);
|
||||
void Finalize(Player &);
|
||||
void Reset(Player &) {}
|
||||
bool Update(Player &, const uint32 &);
|
||||
MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; }
|
||||
|
||||
void LoadPath(Player &);
|
||||
void ReloadPath(Player &) { /* don't reload flight path */ }
|
||||
|
||||
Path& GetPath() { return i_path; }
|
||||
uint32 GetPathAtMapEnd() const;
|
||||
bool HasArrived() const { return (i_currentNode >= i_path.Size()); }
|
||||
void SetCurrentNodeAfterTeleport();
|
||||
void SkipCurrentNode() { ++i_currentNode; }
|
||||
bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
|
||||
|
||||
private:
|
||||
// storage for preloading the flightmaster grid at end
|
||||
// before reaching final waypoint
|
||||
uint32 m_endMapId;
|
||||
uint32 m_preloadTargetNode;
|
||||
float m_endGridX;
|
||||
float m_endGridY;
|
||||
void PreloadEndGrid();
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user