/* * Copyright (C) 2005-2008 MaNGOS * * Copyright (C) 2008 Trinity * * 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" template void ConfusedMovementGenerator::Initialize(T &unit) { const float wander_distance=11; float x,y,z; x = unit.GetPositionX(); y = unit.GetPositionY(); z = unit.GetPositionZ(); uint32 mapid=unit.GetMapId(); Map const* map = MapManager::Instance().GetBaseMap(mapid); i_nextMove = 1; bool is_water_ok, is_land_ok; _InitSpecific(unit, is_water_ok, is_land_ok); for(unsigned int idx=0; idx < MAX_CONF_WAYPOINTS+1; ++idx) { 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; // 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.StopMoving(); unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); unit.addUnitState(UNIT_STAT_CONFUSED); } template<> void ConfusedMovementGenerator::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok) { is_water_ok = creature.canSwim(); is_land_ok = creature.canWalk(); } template<> void ConfusedMovementGenerator::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok) { is_water_ok = true; is_land_ok = true; } template void ConfusedMovementGenerator::Reset(T &unit) { i_nextMove = 1; i_nextMoveTime.Reset(0); i_destinationHolder.ResetUpdate(); unit.StopMoving(); } template bool ConfusedMovementGenerator::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 traveller(unit); if( i_destinationHolder.UpdateTraveller(traveller, diff, false)) { if( i_destinationHolder.HasArrived()) { // arrived, stop and wait a bit unit.StopMoving(); 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 traveller(unit); i_destinationHolder.SetDestination(traveller, x, y, z); } } return true; } template void ConfusedMovementGenerator::Finalize(T &unit) { unit.clearUnitState(UNIT_STAT_CONFUSED); } template void ConfusedMovementGenerator::Initialize(Player &player); template void ConfusedMovementGenerator::Initialize(Creature &creature); template void ConfusedMovementGenerator::Finalize(Player &player); template void ConfusedMovementGenerator::Finalize(Creature &creature); template void ConfusedMovementGenerator::Reset(Player &player); template void ConfusedMovementGenerator::Reset(Creature &creature); template bool ConfusedMovementGenerator::Update(Player &player, const uint32 &diff); template bool ConfusedMovementGenerator::Update(Creature &creature, const uint32 &diff);