Files
CypherCore/Source/Game/Movement/Generators/RandomMovement.cs
T

164 lines
5.5 KiB
C#

/*
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
*
* 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 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 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/>.
*/
using Framework.Constants;
using Game.Entities;
using System;
namespace Game.Movement
{
public class RandomMovementGenerator : MovementGeneratorMedium<Creature>
{
public RandomMovementGenerator(float spawnDist = 0.0f)
{
_timer = new TimeTracker();
_reference = new();
_wanderDistance = spawnDist;
Mode = MovementGeneratorMode.Default;
Priority = MovementGeneratorPriority.Normal;
Flags = MovementGeneratorFlags.InitializationPending;
BaseUnitState = UnitState.Roaming;
}
public override void DoInitialize(Creature owner)
{
RemoveFlag(MovementGeneratorFlags.InitializationPending | MovementGeneratorFlags.Transitory | MovementGeneratorFlags.Deactivated);
AddFlag(MovementGeneratorFlags.Initialized);
if (owner == null || !owner.IsAlive())
return;
_reference = owner.GetPosition();
owner.StopMoving();
if (_wanderDistance == 0)
_wanderDistance = owner.GetRespawnRadius();
_timer.Reset(0);
_path = null;
}
public override void DoReset(Creature owner)
{
RemoveFlag(MovementGeneratorFlags.Transitory | MovementGeneratorFlags.Deactivated);
DoInitialize(owner);
}
public override bool DoUpdate(Creature owner, uint diff)
{
if (!owner || !owner.IsAlive())
return true;
if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting())
{
AddFlag(MovementGeneratorFlags.Interrupted);
owner.StopMoving();
_path = null;
return true;
}
else
RemoveFlag(MovementGeneratorFlags.Interrupted);
_timer.Update(diff);
if ((HasFlag(MovementGeneratorFlags.SpeedUpdatePending) && !owner.MoveSpline.Finalized()) || (_timer.Passed() && owner.MoveSpline.Finalized()))
{
RemoveFlag(MovementGeneratorFlags.Transitory);
SetRandomLocation(owner);
}
return true;
}
public override void DoDeactivate(Creature owner)
{
AddFlag(MovementGeneratorFlags.Deactivated);
owner.ClearUnitState(UnitState.RoamingMove);
}
public override void DoFinalize(Creature owner, bool active, bool movementInform)
{
AddFlag(MovementGeneratorFlags.Finalized);
if (active)
{
owner.ClearUnitState(UnitState.RoamingMove);
owner.StopMoving();
// TODO: Research if this modification is needed, which most likely isnt
owner.SetWalk(false);
}
}
void SetRandomLocation(Creature owner)
{
if (owner == null)
return;
if (owner.HasUnitState(UnitState.NotMove | UnitState.LostControl) || owner.IsMovementPreventedByCasting())
{
AddFlag(MovementGeneratorFlags.Interrupted);
owner.StopMoving();
_path = null;
return;
}
Position position = new(_reference);
float distance = RandomHelper.FRand(0.0f, 1.0f) * _wanderDistance;
float angle = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f;
owner.MovePositionToFirstCollision(position, distance, angle);
uint resetTimer = RandomHelper.randChance(50) ? RandomHelper.URand(5000, 10000) : RandomHelper.URand(1000, 2000);
if (_path == null)
{
_path = new PathGenerator(owner);
_path.SetPathLengthLimit(30.0f);
}
bool result = _path.CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ());
if (!result || _path.GetPathType().HasAnyFlag(PathType.NoPath))
{
_timer.Reset(100);
return;
}
owner.AddUnitState(UnitState.RoamingMove);
MoveSplineInit init = new(owner);
init.MovebyPath(_path.GetPath());
init.SetWalk(true);
int traveltime = init.Launch();
_timer.Reset(traveltime + resetTimer);
// Call for creature group update
owner.SignalFormationMovement(position);
}
public override void UnitSpeedChanged() { AddFlag(MovementGeneratorFlags.SpeedUpdatePending); }
public override MovementGeneratorType GetMovementGeneratorType()
{
return MovementGeneratorType.Random;
}
PathGenerator _path;
TimeTracker _timer;
Position _reference;
float _wanderDistance;
}
}