Index: src/game/ConfusedMovementGenerator.h =================================================================== --- src/game/ConfusedMovementGenerator.h (revision 5137) +++ src/game/ConfusedMovementGenerator.h (working copy) @@ -16,8 +16,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef MANGOS_RANDOMMOTIONGENERATOR_H -#define MANGOS_RANDOMMOTIONGENERATOR_H +#ifndef MANGOS_CONFUSEDMOVEMENTGENERATOR_H +#define MANGOS_CONFUSEDMOVEMENTGENERATOR_H #include "MovementGenerator.h" #include "DestinationHolder.h" Index: src/game/FearedMovementGenerator.cpp =================================================================== --- src/game/FearedMovementGenerator.cpp (revision 0) +++ src/game/FearedMovementGenerator.cpp (revision 0) @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2005,2006,2007 MaNGOS + * + * 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 "FearedMovementGenerator.h" +#include "Creature.h" + +#define FEAR_MAX_TRIES 6 +#define FEAR_MAX_STEPS 12 +#define FEAR_MAX_FEAR_ANGLE 45 +#define FEAR_STEP_DIST 3 +#define FEAR_MIN_STEP_DIST 15 +#define FEAR_MAX_STEP_DIST 25 +#define FEAR_GOOD_DIST 26 +#define FEAR_MAX_DIST 40 + +template +void FearedMovementGenerator::Initialize(T &unit) +{ + unit.StopMoving(); + unit.setMoveRunFlag(true); + _InitSpecific(unit, is_water_ok, is_land_ok); + ReinitDestination(unit); +} + +template +void FearedMovementGenerator::Finalize(T &) +{ +} + +template +void FearedMovementGenerator::Reset(T &unit) +{ + timeTracker.Reset(0); + i_destinationHolder.ResetUpdate(); + unit.StopMoving(); + unit.setMoveRunFlag(true); + _InitSpecific(unit, is_water_ok, is_land_ok); + ReinitDestination(unit); +} + +template +bool FearedMovementGenerator::Update(T &unit, const uint32 &diff) +{ + if(!&unit) + return true; + + if(unit.hasUnitState(UNIT_STAT_ROOT) || unit.hasUnitState(UNIT_STAT_STUNDED)) + return true; + timeTracker.Update(diff); + Traveller traveller(unit); + i_destinationHolder.UpdateTraveller(traveller, diff, false); + if( timeTracker.Passed() ) + { + if( i_destinationHolder.HasArrived() ) + { + unit.StopMoving(); + unit.setMoveRunFlag(true); + if (destSteps) + { + GenerateMovement(unit); + timeTracker.Reset( i_destinationHolder.GetTotalTravelTime() ); + } + else + timeTracker.Reset(urand(700,1000)); + } + } + return true; +} + +template +void FearedMovementGenerator::ReinitDestination(T &unit) +{ + destSteps = FEAR_MAX_STEPS; + if (caster) + { + baseX = caster->GetPositionX(); + baseY = caster->GetPositionY(); + baseZ = caster->GetPositionZ(); + } + else + { + baseX = unit.GetPositionX(); + baseY = unit.GetPositionX(); + baseZ = unit.GetPositionX(); + } +} + +template +void FearedMovementGenerator::SetNoMovement(float &dX, float &dY, float &dZ, T &unit) +{ + dX = unit.GetPositionX(); + dY = unit.GetPositionY(); + dZ = unit.GetPositionZ(); +} + +template +void FearedMovementGenerator::SetMovement(float &dX, float &dY, float &dZ, T &unit, float angle, float distance) +{ + uint32 mapid = unit.GetMapId(); + + dX = unit.GetPositionX() + cosf(angle) * distance; + dY = unit.GetPositionY() + sinf(angle) * distance; + dZ = unit.GetPositionZ(); + + dZ = MapManager::Instance().GetBaseMap(mapid)->GetHeight(dX,dY,dZ,true); + if(dZ > INVALID_HEIGHT) + dZ = dZ + 0.05f; //just to be sure that we are not a few pixel under the surface +} + +template +float FearedMovementGenerator::ComputeAngle(float x, float y) +{ + float angle = x*x + y*y; + if (angle != 0) + angle = sqrt(angle); + if (angle != 0) + angle = atan2(x/angle, y/angle); + return angle; +} + +template +float FearedMovementGenerator::ComputeUnitAngle(T &unit) +{ + return ComputeAngle(unit.GetPositionX() - baseX, unit.GetPositionY() - baseY); +} + +template +float FearedMovementGenerator::GetRandAngle(int start, int end) +{ + return (urand(start, end)*M_PI)/180; +} + +template +float FearedMovementGenerator::GetFearedDist(float dX, float dY) +{ + return sqrt((dX-baseX)*(dX-baseX)+(dY-baseY)*(dY-baseY)); +} + +template +float FearedMovementGenerator::GetFearedDist(float dX, float dY, float dZ) +{ + return sqrt((dX-baseX)*(dX-baseX)+(dY-baseY)*(dY-baseY)+(dZ-baseZ)*(dZ-baseZ)); +} + +template +bool FearedMovementGenerator::IsFearedAngleOk(float angle) +{ + bool angleOk = false; + if (angle >= 0 && angle < 90) + { + if (angle <= FEAR_MAX_FEAR_ANGLE) + angleOk=true; + } + else if (angle >= 90 && angle < 180) + { + angle -=90; + if (angle >= FEAR_MAX_FEAR_ANGLE) + angleOk=true; + } + else if (angle >= -90 && angle < 0) + { + angle +=90; + if (angle >= FEAR_MAX_FEAR_ANGLE) + angleOk=true; + } + else if (angle >= -180 && angle < 90) + { + angle +=180; + if (angle <= FEAR_MAX_FEAR_ANGLE) + angleOk=true; + } + return angleOk; +} + +template +bool FearedMovementGenerator::IsDestOk(float dX, float dY, float dZ, T &unit) +{ + uint32 mapid = unit.GetMapId(); + bool is_water = false; + float heightAngle = 0; + float fearedDist = GetFearedDist(dX, dY); + float realFearedDist = GetFearedDist(dX, dY, dZ); + //make sure the distances are big enoughf and not waste useless divisions + if ( + (dZ-unit.GetPositionZ() <= -1 || dZ-unit.GetPositionZ() >= 1) && + (fearedDist <= -1 || fearedDist >= 1) + ) + { + heightAngle = ComputeAngle(fearedDist, dZ-unit.GetPositionZ()); + heightAngle = (heightAngle*180)/M_PI; + } + is_water = MapManager::Instance().GetBaseMap(mapid)->IsInWater(dX, dY, dZ); + return (unit.IsWithinLOS(dX, dY, dZ) && + (realFearedDist <= FEAR_MAX_DIST) && + IsFearedAngleOk(heightAngle) && + !((is_water && !is_water_ok) || (!is_water && !is_land_ok))); +} + +template +void FearedMovementGenerator::RandomizeDestination(T &unit) +{ + if (!destSteps) + return; + else + --destSteps; + + bool destOK = false; + float unitAngle = ComputeUnitAngle(unit); + float randMultiplier = 0.0f; + float randAngle = 0.0f; + float tmpDist = 0.0f; + + float lastdX = 0.0f, lastdY = 0.0f, lastdZ = 0.0f; + + int tries = FEAR_MAX_TRIES; + + do + { + if (tries-- == 0) + { + SetNoMovement(destX, destY, destZ, unit); + destSteps = 0; + break; + } + + randAngle = (urand(0, 1)?(-1):(1)); + + if(destSteps % 2) + { + randAngle *= GetRandAngle(45, 90); + randMultiplier = urand(FEAR_STEP_DIST, FEAR_MIN_STEP_DIST) + FEAR_STEP_DIST; + } + else + { + if (tries >= FEAR_MAX_TRIES/2) + randAngle *= GetRandAngle(0, 60); + else if (tries >= FEAR_MAX_TRIES/4) + randAngle *= GetRandAngle(45, 90); + else + randAngle *= GetRandAngle(90, 180); + if (tries >= FEAR_MAX_TRIES/2) + randMultiplier = urand(FEAR_MIN_STEP_DIST, FEAR_MAX_STEP_DIST); + else + randMultiplier = urand(FEAR_STEP_DIST, FEAR_MIN_STEP_DIST); + } + randAngle += unitAngle; + + destOK = false; + for (tmpDist = FEAR_STEP_DIST; tmpDist <= randMultiplier; tmpDist += FEAR_STEP_DIST) + { + SetMovement(lastdX, lastdY, lastdZ, unit, randAngle, tmpDist); + destOK = IsDestOk(lastdX, lastdY, lastdZ, unit); + if (!destOK) + { + if (tmpDist > FEAR_STEP_DIST) + destOK = true; + break; + } + else + { + destX = lastdX; + destY = lastdY; + destZ = lastdZ; + } + } + }while(!destOK); +} + +template +void FearedMovementGenerator::GenerateMovement(T &unit) +{ + RandomizeDestination(unit); + Traveller traveller(unit); + i_destinationHolder.SetDestination(traveller, destX, destY, destZ); +} + +template<> +void +FearedMovementGenerator::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok) +{ + is_water_ok = creature.isCanSwimOrFly(); + is_land_ok = creature.isCanWalkOrFly(); +} + +template<> +void +FearedMovementGenerator::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok) +{ + is_water_ok = true; + is_land_ok = true; +} + +template void FearedMovementGenerator::Initialize(Player &player); +template void FearedMovementGenerator::Initialize(Creature &creature); +template void FearedMovementGenerator::Finalize(Player &player); +template void FearedMovementGenerator::Finalize(Creature &player); +template void FearedMovementGenerator::Reset(Player &player); +template void FearedMovementGenerator::Reset(Creature &creature); +template bool FearedMovementGenerator::Update(Player &player, const uint32 &diff); +template bool FearedMovementGenerator::Update(Creature &creature, const uint32 &diff); Index: src/game/FearedMovementGenerator.h =================================================================== --- src/game/FearedMovementGenerator.h (revision 0) +++ src/game/FearedMovementGenerator.h (revision 0) @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2005,2006,2007 MaNGOS + * + * 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 MANGOS_FEAREDMOVEMENTGENERATOR_H +#define MANGOS_FEAREDMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" + +template +class MANGOS_DLL_SPEC FearedMovementGenerator : public MovementGeneratorMedium< T, FearedMovementGenerator > +{ + public: + FearedMovementGenerator(const Unit &, Unit *_caster) : caster(_caster), timeTracker(0), + baseX(0.0f), baseY(0.0f), baseZ(0.0f), + destSteps(0), destX(0.0f), destY(0.0f), destZ(0.0f) {} + void Initialize(T &); + void Finalize(T &); + void Reset(T &unit); + bool Update(T &, const uint32 &diff); + MovementGeneratorType GetMovementGeneratorType() { return FEARED_MOTION_TYPE; } + + private: + DestinationHolder< Traveller > i_destinationHolder; + Unit *caster; + TimeTracker timeTracker; + + bool is_water_ok; + bool is_land_ok; + void _InitSpecific(T &, bool &, bool &); + + uint32 destSteps; + float baseX, baseY, baseZ; + void ReinitDestination(T &unit); + + float destX, destY, destZ; + void SetNoMovement(float &dX, float &dY, float &dZ, T &unit); + void SetMovement(float &dX, float &dY, float &dZ, T &unit, float angle, float distance); + float ComputeAngle(float x, float y); + float ComputeUnitAngle(T &unit); + float GetRandAngle(int start, int end); + float GetFearedDist(float dX, float dY); + float GetFearedDist(float dX, float dY, float dZ); + bool IsFearedAngleOk(float angle); + bool IsDestOk(float dX, float dY, float dZ, T &unit); + void RandomizeDestination(T &unit); + + void GenerateMovement(T &unit); +}; + +#endif Index: src/game/FleeMovementGenerator.cpp =================================================================== --- src/game/FleeMovementGenerator.cpp (revision 0) +++ src/game/FleeMovementGenerator.cpp (revision 0) @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2005,2006,2007 MaNGOS + * + * 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 "FleeMovementGenerator.h" +#include "Creature.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +#define FLEE_MAX_CALL_DISTANCE 3 +#define FLEE_MAX_DISTANCE 20 + +template +bool FleeMovementGenerator::Update(T &unit, const uint32 &diff) +{ + if(!&unit) + return true; + + if(unit.hasUnitState(UNIT_STAT_ROOT) || unit.hasUnitState(UNIT_STAT_STUNDED)) + return true; + timeTracker.Update(diff); + Traveller traveller(unit); + i_destinationHolder.UpdateTraveller(traveller, diff, false); + if( timeTracker.Passed() ) + { + if( i_destinationHolder.HasArrived() ) + { + unit.StopMoving(); + unit.setMoveRunFlag(true); + if (FindNextPosition(unit)) + timeTracker.Reset( i_destinationHolder.GetTotalTravelTime() ); + else + return false; + } + } + return true; +} + +template +void FleeMovementGenerator::Initialize(T &unit) +{ + unit.StopMoving(); + FindSafePosition(unit); +} + +template +void FleeMovementGenerator::Finalize(T &) +{ +} + +template +void FleeMovementGenerator::Reset(T &unit) +{ + unit.StopMoving(); + FindSafePosition(unit); +} + +template +void FleeMovementGenerator::GetTargets(Creature*unit, float range, std::list&targets) +{ + CellPair p(MaNGOS::ComputeCellPair(unit->GetPositionX(), unit->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + { + MaNGOS::AnyAssistCreatureInRangeCheck u_check(unit, unit, range); + MaNGOS::UnitListSearcher searcher(targets, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(unit->GetMapId(), unit)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(unit->GetMapId(), unit)); + } + + for(std::list::iterator tIter = targets.begin(); tIter != targets.end();) + { + if(!unit->IsWithinLOSInMap(*tIter)) + { + std::list::iterator tIter2 = tIter; + ++tIter; + targets.erase(tIter2); + } + else + ++tIter; + } +} + +template +void FleeMovementGenerator::GetTargets(Player*unit, float range, std::list&targets) +{ + CellPair p(MaNGOS::ComputeCellPair(unit->GetPositionX(), unit->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + { + MaNGOS::AnyAssistCreatureInRangeCheck u_check(unit, unit, range); + MaNGOS::UnitListSearcher searcher(targets, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(unit->GetMapId(), unit)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(unit->GetMapId(), unit)); + } + + for(std::list::iterator tIter = targets.begin(); tIter != targets.end();) + { + if(!unit->IsWithinLOSInMap(*tIter)) + { + std::list::iterator tIter2 = tIter; + ++tIter; + targets.erase(tIter2); + } + else + ++tIter; + } +} + +template +Unit*FleeMovementGenerator::IsSafePosition(T&unit) +{ + std::list targets; + if (unit.GetTypeId() == TYPEID_UNIT) + GetTargets((Creature*)&unit, FLEE_MAX_CALL_DISTANCE, targets); + else + GetTargets((Player*)&unit, FLEE_MAX_CALL_DISTANCE, targets); + + // no appropriate targets + if(targets.empty()) + return NULL; + + // select random + uint32 rIdx = rand32(0,targets.size()-1); + std::list::const_iterator tIter = targets.begin(); + for(uint32 i = 0; i < rIdx; ++i) + ++tIter; + + // Set our target + (*tIter)->GetPosition(destX, destY, destZ); + + return (*tIter); +} + +template +bool FleeMovementGenerator::FindSafePosition(T&unit) +{ + destX = unit.GetPositionX(); + destY = unit.GetPositionY(); + destZ = unit.GetPositionZ(); + + std::list targets; + if (unit.GetTypeId() == TYPEID_UNIT) + GetTargets((Creature*)&unit, FLEE_MAX_DISTANCE, targets); + else + GetTargets((Player*)&unit, FLEE_MAX_DISTANCE, targets); + + // no appropriate targets + if(targets.empty()) + return false; + + // select random + uint32 rIdx = rand32(0,targets.size()-1); + std::list::const_iterator tIter = targets.begin(); + for(uint32 i = 0; i < rIdx; ++i) + ++tIter; + + // Set our target + (*tIter)->GetPosition(destX, destY, destZ); + + return true; +} + +template +bool FleeMovementGenerator::FindNextPosition(T&unit) +{ + nextPX = unit.GetPositionX(); + nextPY = unit.GetPositionY(); + nextPZ = unit.GetPositionZ(); + + if (nextPX == destX && + nextPY == destY && + nextPZ == destZ) + { + Creature*friendlyUnit = (Creature*)IsSafePosition(unit); + if (friendlyUnit) + { + /* + We reached to one of our friendly units. + Here we should call for asistance. + */ + if (unit.getVictim() && friendlyUnit->AI()) + friendlyUnit->AI()->AttackStart(unit.getVictim()); + return false; + } + else + { + if (!FindSafePosition(unit)) + return false; + } + } + nextPX = destX; + nextPY = destY; + nextPZ = destZ; + + Traveller traveller(unit); + i_destinationHolder.SetDestination(traveller, nextPX, nextPY, nextPZ); + return true; +} + +template void FleeMovementGenerator::Initialize(Player &); +template void FleeMovementGenerator::Finalize(Player &); +template bool FleeMovementGenerator::Update(Player &, const uint32 &); +template void FleeMovementGenerator::Initialize(Creature &); +template void FleeMovementGenerator::Finalize(Creature &); +template bool FleeMovementGenerator::Update(Creature &, const uint32 &); Index: src/game/FleeMovementGenerator.h =================================================================== --- src/game/FleeMovementGenerator.h (revision 0) +++ src/game/FleeMovementGenerator.h (revision 0) @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005,2006,2007 MaNGOS + * + * 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 MANGOS_FLEEMOVEMENTGENERATOR_H +#define MANGOS_FLEEMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" + +class Creature; + +template +class MANGOS_DLL_SPEC FleeMovementGenerator : public MovementGeneratorMedium< T, FleeMovementGenerator > +{ + public: + FleeMovementGenerator() : + destX(0), destY(0), destZ(0), + nextPX(0), nextPY(0), nextPZ(0), + timeTracker(0) {} + void Initialize(T &); + void Finalize(T &); + void Reset(T &unit); + bool Update(T &, const uint32 &diff); + MovementGeneratorType GetMovementGeneratorType() { return FLEE_MOTION_TYPE; } + private: + TimeTracker timeTracker; + float destX,destY,destZ; + float nextPX,nextPY,nextPZ; + void GetTargets(Creature*unit, float range, std::list&targets); + void GetTargets(Player*unit, float range, std::list&targets); + Unit*IsSafePosition(T&unit); + bool FindSafePosition(T&unit); + bool FindNextPosition(T&unit); + DestinationHolder< Traveller > i_destinationHolder; +}; + +#endif Index: src/game/GridNotifiers.h =================================================================== --- src/game/GridNotifiers.h (revision 5137) +++ src/game/GridNotifiers.h (working copy) @@ -652,6 +652,40 @@ return true; } + bool operator()(Player* u) + { + if(u == i_funit) + return false; + + // we don't need help from zombies :) + if( !u->isAlive() ) + return false; + + // only free creature + if( u->GetCharmerOrOwnerGUID() ) + return false; + + // skip fighting creature + if( u->isInCombat() ) + return false; + + // too far + if( !i_funit->IsWithinDistInMap(u, i_range) ) + return false; + + // skip non hostile to caster enemy creatures + if( !u->IsHostileTo(i_enemy) ) + return false; + + // only from same creature faction + if(u->getFaction() != i_funit->getFaction() ) + return false; + + if(!u->IsWithinLOSInMap(i_enemy) ) + return false; + + return true; + } private: Unit* const i_funit; Unit* const i_enemy; Index: src/game/Makefile.am =================================================================== --- src/game/Makefile.am (revision 5137) +++ src/game/Makefile.am (working copy) @@ -96,6 +96,8 @@ DuelHandler.cpp \ DynamicObject.cpp \ DynamicObject.h \ + FearedMovementGenerator.cpp \ + FearedMovementGenerator.h \ Formulas.h \ GameEvent.cpp \ GameEvent.h \ Index: src/game/MotionMaster.h =================================================================== --- src/game/MotionMaster.h (revision 5137) +++ src/game/MotionMaster.h (working copy) @@ -38,7 +38,10 @@ CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h TARGETED_MOTION_TYPE = 5, // TargetedMovementGenerator.h HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h - FLIGHT_MOTION_TYPE = 7 // WaypointMovementGenerator.h + FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h + POINT_MOTION_TYPE = 8, // PointMovementGenerator.h + FEARED_MOTION_TYPE = 9, // FearedMovementGenerator.h + FLEE_MOTION_TYPE = 10, // FleeMovementGenerator.h }; class MANGOS_DLL_SPEC MotionMaster : private std::stack Index: src/game/PointMovementGenerator.cpp =================================================================== --- src/game/PointMovementGenerator.cpp (revision 0) +++ src/game/PointMovementGenerator.cpp (revision 0) @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005,2006,2007 MaNGOS + * + * 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 "Creature.h" + +template +bool PointMovementGenerator::Update(T &unit, const uint32 &diff) +{ + if(!&unit) + return false; + + if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED)) + return true; + + Traveller traveller(unit); + + i_destinationHolder.UpdateTraveller(traveller, diff, false); + + if(i_destinationHolder.HasArrived()) + { + unit.StopMoving(); + return false; + } + + return true; +} + +template +void PointMovementGenerator::Initialize(T &unit) +{ + unit.StopMoving(); + Traveller traveller(unit); + i_destinationHolder.SetDestination(traveller,x,y,z); +} + +template +void PointMovementGenerator::Finalize(T &) +{ +} + +template void PointMovementGenerator::Initialize(Player &); +template void PointMovementGenerator::Finalize(Player &); +template bool PointMovementGenerator::Update(Player &, const uint32 &); +template void PointMovementGenerator::Initialize(Creature &); +template void PointMovementGenerator::Finalize(Creature &); +template bool PointMovementGenerator::Update(Creature &, const uint32 &); Index: src/game/PointMovementGenerator.h =================================================================== --- src/game/PointMovementGenerator.h (revision 0) +++ src/game/PointMovementGenerator.h (revision 0) @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005,2006,2007 MaNGOS + * + * 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 MANGOS_POINTMOVEMENTGENERATOR_H +#define MANGOS_POINTMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" + +class Creature; + +template +class MANGOS_DLL_SPEC PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator > +{ + public: + PointMovementGenerator(float _x, float _y, float _z) : + x(_x), y(_y), z(_z), i_nextMoveTime(0) {} + void Initialize(T &); + void Finalize(T &); + void Reset(T &unit) { unit.StopMoving(); } + bool Update(T &, const uint32 &diff); + MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; } + private: + TimeTracker i_nextMoveTime; + float x,y,z; + DestinationHolder< Traveller > i_destinationHolder; +}; + +#endif Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 5137) +++ src/game/SpellAuras.cpp (working copy) @@ -39,6 +39,7 @@ #include "Totem.h" #include "Creature.h" #include "ConfusedMovementGenerator.h" +#include "FearedMovementGenerator.h" #include "TargetedMovementGenerator.h" #include "Formulas.h" #include "BattleGround.h" @@ -464,7 +465,7 @@ caster->ModifyPower(powertype,-manaPerSecond); caster->ModifyPower(powertype,-manaPerSecondPerLevel); } - if(caster && m_target->isAlive() && m_target->HasFlag(UNIT_FIELD_FLAGS,(UNIT_STAT_FLEEING<<16))) + if(caster && m_target->isAlive() && m_target->HasFlag(UNIT_FIELD_FLAGS,(UNIT_STAT_FLEEING<<16)) && !m_target->HasAuraType(SPELL_AURA_MOD_FEAR)) { int q = rand() % 80; if(q == 8) m_fearMoveAngle += (float)(urand(45, 90)); @@ -2096,22 +2097,27 @@ { if( Apply ) { + if(Real) + m_target->StopMoving(); m_target->addUnitState(UNIT_STAT_FLEEING); m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); // only at real add aura if(Real) { - //FIX ME: we need Mutate to now not existed FleeMovementGenerator (see Aura::Update hack code) - // at this moment Idle instead - m_target->GetMotionMaster()->MovementExpired(false); - m_target->GetMotionMaster()->Idle(); - - // what is this for ? (doesn't work anyway) - /*WorldPacket data(SMSG_DEATH_NOTIFY_OBSOLETE, 9); - data.append(m_target->GetPackGUID()); - data << uint8(0x00); - m_target->SendMessageToSet(&data,true);*/ + m_target->GetMotionMaster()->MovementExpired(false); + if (m_target->GetTypeId() == TYPEID_UNIT) + m_target->GetMotionMaster()->Mutate(new FearedMovementGenerator(*((Creature*)m_target), GetCaster())); + else + { + m_target->GetMotionMaster()->Mutate(new FearedMovementGenerator(*((Player*)m_target), GetCaster())); + Player *player = (Player*)m_target; + + WorldPacket data(SMSG_DEATH_NOTIFY_OBSOLETE, 10); + data.append(player->GetPackGUID()); // target's viewpoint + data << uint8(0x00); // movement disabled + player->GetSession()->SendPacket(&data); + } } } else @@ -2122,28 +2128,34 @@ // only at real remove aura if(Real) { + m_target->StopMoving(); m_target->GetMotionMaster()->MovementExpired(false); if( m_target->GetTypeId() != TYPEID_PLAYER && m_target->isAlive() ) { - // restore appropriate movement generator - if(m_target->getVictim()) - m_target->GetMotionMaster()->Mutate(new TargetedMovementGenerator(*m_target->getVictim())); - else - m_target->GetMotionMaster()->Initialize(); - - // attack caster if can - Unit* caster = GetCaster(); - if(caster && caster != m_target->getVictim()) - if (((Creature*)m_target)->AI()) - ((Creature*)m_target)->AI()->AttackStart(caster); + if (!m_target->willBeDead()) + { + // restore appropriate movement generator + if(m_target->getVictim()) + m_target->GetMotionMaster()->Mutate(new TargetedMovementGenerator(*m_target->getVictim())); + else + m_target->GetMotionMaster()->Initialize(); + // attack caster if can + Unit* caster = GetCaster(); + if(caster && caster != m_target->getVictim()) + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackStart(caster); + } } - - // what is this for ? (doesn't work anyway) - /*WorldPacket data(SMSG_DEATH_NOTIFY_OBSOLETE, 9); - data.append(m_target->GetPackGUID()); - data << uint8(0x01); - m_target->SendMessageToSet(&data,true);*/ + else + { + Player *player = (Player*)m_target; + + WorldPacket data(SMSG_DEATH_NOTIFY_OBSOLETE, 10); + data.append(player->GetPackGUID()); // target's viewpoint + data << uint8(0x01); // movement enabled + player->GetSession()->SendPacket(&data); + } } } } Index: src/game/Traveller.h =================================================================== --- src/game/Traveller.h (revision 5137) +++ src/game/Traveller.h (working copy) @@ -78,7 +78,10 @@ template<> inline float Traveller::Speed() { - return PLAYER_FLIGHT_SPEED; + if (i_traveller.isInFlight()) + return PLAYER_FLIGHT_SPEED; + else + return i_traveller.GetSpeed(i_traveller.getMoveRunFlag() ? MOVE_RUN : MOVE_WALK); } template<> Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 5137) +++ src/game/Unit.cpp (working copy) @@ -153,6 +153,7 @@ m_state = 0; m_form = 0; m_deathState = ALIVE; + m_nextDeathState = ALIVE; for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) m_currentSpells[i] = NULL; @@ -7040,6 +7041,7 @@ void Unit::setDeathState(DeathState s) { + m_nextDeathState = s; if (s != ALIVE) { CombatStop(); @@ -8271,7 +8273,10 @@ void Unit::StopMoving() { - clearUnitState(UNIT_STAT_MOVING); + uint32 unitState = UNIT_STAT_MOVING; + if (HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_FLEEING)) + unitState &= (~UNIT_STAT_FLEEING); + clearUnitState(unitState); // send explicit stop packet SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(),0,true,0); Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 5137) +++ src/game/Unit.h (working copy) @@ -780,8 +780,11 @@ bool isAlive() const { return (m_deathState == ALIVE); }; bool isDead() const { return ( m_deathState == DEAD || m_deathState == CORPSE ); }; + bool willBeAlive() const { return (m_nextDeathState == ALIVE); }; + bool willBeDead() const { return ( m_nextDeathState == DEAD || m_nextDeathState == CORPSE ); }; DeathState getDeathState() { return m_deathState; }; virtual void setDeathState(DeathState s); // overwrited in Creature/Player/Pet + DeathState getNextDeathState() { return m_nextDeathState; }; uint64 const& GetOwnerGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMONEDBY); } uint64 GetPetGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMON); } @@ -1030,6 +1033,7 @@ Unit* m_attacking; DeathState m_deathState; + DeathState m_nextDeathState; AuraMap m_Auras;