EverWrath/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
Kitzunu 913e65f97f
refactor(Core/Misc): fabs() to std::fabs() (#9790)
- prefer std functions over C functions
2021-12-31 20:41:00 -03:00

185 lines
6.3 KiB
C++

/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ConfusedMovementGenerator.h"
#include "Creature.h"
#include "MapMgr.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
#include "Player.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>::DoInitialize(T* unit)
{
unit->StopMoving();
float const wander_distance = 4;
float x = unit->GetPositionX();
float y = unit->GetPositionY();
float z = unit->GetPositionZ();
Map const* map = unit->GetMap();
bool is_water_ok, is_land_ok;
_InitSpecific(unit, is_water_ok, is_land_ok);
for (uint8 idx = 0; idx < MAX_CONF_WAYPOINTS + 1; ++idx)
{
float wanderX = x + (wander_distance * (float)rand_norm() - wander_distance / 2);
float wanderY = y + (wander_distance * (float)rand_norm() - wander_distance / 2);
// prevent invalid coordinates generation
Acore::NormalizeMapCoord(wanderX);
Acore::NormalizeMapCoord(wanderY);
float new_z = unit->GetMapHeight(wanderX, wanderY, z);
if (new_z <= INVALID_HEIGHT || std::fabs(z - new_z) > 3.0f) // pussywizard
{
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
continue;
}
else if (unit->IsWithinLOS(wanderX, wanderY, z))
{
bool is_water = map->IsInWater(unit->GetPhaseMask(), wanderX, wanderY, z, unit->GetCollisionHeight());
if ((is_water && !is_water_ok) || (!is_water && !is_land_ok))
{
//! Cannot use coordinates outside our InhabitType. Use the current or previous position.
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
continue;
}
}
else
{
//! Trying to access path outside line of sight. Skip this by using the current or previous position.
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
continue;
}
//unit->UpdateAllowedPositionZ(wanderX, wanderY, z);
//! Positions are fine - apply them to this waypoint
i_waypoints[idx][0] = wanderX;
i_waypoints[idx][1] = wanderY;
i_waypoints[idx][2] = new_z;
}
// Xinef: Call movement immediately to broadcast movement packet
// Xinef: Initial timer is set to 1 so update with 1
i_nextMove = urand(1, MAX_CONF_WAYPOINTS);
DoUpdate(unit, 1);
unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
unit->AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
}
template<>
void ConfusedMovementGenerator<Creature>::_InitSpecific(Creature* creature, bool& is_water_ok, bool& is_land_ok)
{
is_water_ok = creature->CanEnterWater();
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>::DoReset(T* unit)
{
DoInitialize(unit);
}
template<class T>
bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff)
{
if (unit->HasUnitState(UNIT_STATE_NOT_MOVE) || unit->IsMovementPreventedByCasting())
{
unit->StopMoving();
return true;
}
if (i_nextMoveTime.Passed())
{
// currently moving, update location
unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
if (unit->movespline->Finalized())
{
i_nextMove = urand(1, MAX_CONF_WAYPOINTS);
i_nextMoveTime.Reset(urand(600, 1200)); // Guessed
}
}
else
{
// waiting for next move
i_nextMoveTime.Update(diff);
if (i_nextMoveTime.Passed())
{
// start moving
unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
ASSERT(i_nextMove <= MAX_CONF_WAYPOINTS);
float x = i_waypoints[i_nextMove][0];
float y = i_waypoints[i_nextMove][1];
float z = i_waypoints[i_nextMove][2];
Movement::MoveSplineInit init(unit);
init.MoveTo(x, y, z, true);
init.Launch();
}
}
return true;
}
template<>
void ConfusedMovementGenerator<Player>::DoFinalize(Player* unit)
{
unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
unit->StopMoving();
}
template<>
void ConfusedMovementGenerator<Creature>::DoFinalize(Creature* unit)
{
unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
if (unit->GetVictim())
unit->SetTarget(unit->GetVictim()->GetGUID());
}
template void ConfusedMovementGenerator<Player>::DoInitialize(Player*);
template void ConfusedMovementGenerator<Creature>::DoInitialize(Creature*);
template void ConfusedMovementGenerator<Player>::DoReset(Player*);
template void ConfusedMovementGenerator<Creature>::DoReset(Creature*);
template bool ConfusedMovementGenerator<Player>::DoUpdate(Player*, uint32 diff);
template bool ConfusedMovementGenerator<Creature>::DoUpdate(Creature*, uint32 diff);