initial commit
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 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 Framework.GameMath;
|
||||
using Game.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
public class SplineChainMovementGenerator : IMovementGenerator
|
||||
{
|
||||
public SplineChainMovementGenerator(uint id, List<SplineChainLink> chain, bool walk = false)
|
||||
{
|
||||
_id = id;
|
||||
_chain = chain;
|
||||
_chainSize = (byte)chain.Count;
|
||||
_walk = walk;
|
||||
}
|
||||
public SplineChainMovementGenerator(SplineChainResumeInfo info)
|
||||
{
|
||||
_id = info.PointID;
|
||||
_chain = info.Chain;
|
||||
_chainSize = (byte)info.Chain.Count;
|
||||
_walk = info.IsWalkMode;
|
||||
finished = info.SplineIndex >= info.Chain.Count;
|
||||
_nextIndex = info.SplineIndex;
|
||||
_nextFirstWP = info.PointIndex;
|
||||
_msToNext = info.TimeToNext;
|
||||
}
|
||||
|
||||
uint SendPathSpline(Unit me, List<Vector3> wp)
|
||||
{
|
||||
int numWp = wp.Count;
|
||||
Contract.Assert(numWp > 1, "Every path must have source & destination");
|
||||
MoveSplineInit init = new MoveSplineInit(me);
|
||||
if (numWp > 2)
|
||||
init.MovebyPath(wp.ToArray());
|
||||
else
|
||||
init.MoveTo(wp[1], false, true);
|
||||
init.SetWalk(_walk);
|
||||
return (uint)init.Launch();
|
||||
}
|
||||
|
||||
void SendSplineFor(Unit me, int index, uint toNext)
|
||||
{
|
||||
Contract.Assert(index < _chainSize);
|
||||
Log.outDebug(LogFilter.Movement, "{0}: Sending spline for {1}.", me.GetGUID().ToString(), index);
|
||||
|
||||
SplineChainLink thisLink = _chain[index];
|
||||
uint actualDuration = SendPathSpline(me, thisLink.Points);
|
||||
if (actualDuration != thisLink.ExpectedDuration)
|
||||
{
|
||||
Log.outDebug(LogFilter.Movement, "{0}: Sent spline for {1}, duration is {2} ms. Expected was {3} ms (delta {4} ms). Adjusting.", me.GetGUID().ToString(), index, actualDuration, thisLink.ExpectedDuration, actualDuration - thisLink.ExpectedDuration);
|
||||
toNext = (uint)(actualDuration / thisLink.ExpectedDuration * toNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.outDebug(LogFilter.Movement, "{0}: Sent spline for {1}, duration is {2} ms.", me.GetGUID().ToString(), index, actualDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Initialize(Unit me)
|
||||
{
|
||||
if (_chainSize != 0)
|
||||
{
|
||||
if (_nextFirstWP != 0) // this is a resumed movegen that has to start with a partial spline
|
||||
{
|
||||
if (finished)
|
||||
return;
|
||||
SplineChainLink thisLink = _chain[_nextIndex];
|
||||
if (_nextFirstWP >= thisLink.Points.Count)
|
||||
{
|
||||
Log.outError(LogFilter.Movement, "{0}: Attempted to resume spline chain from invalid resume state ({1}, {2}).", me.GetGUID().ToString(), _nextIndex, _nextFirstWP);
|
||||
_nextFirstWP = (byte)(thisLink.Points.Count - 1);
|
||||
}
|
||||
List<Vector3> partial = new List<Vector3>();
|
||||
partial.AddRange(thisLink.Points.Skip(_nextFirstWP - 1).ToArray());
|
||||
SendPathSpline(me, partial);
|
||||
Log.outDebug(LogFilter.Movement, "{0}: Resumed spline chain generator from resume state.", me.GetGUID().ToString());
|
||||
++_nextIndex;
|
||||
if (_msToNext == 0)
|
||||
_msToNext = 1;
|
||||
_nextFirstWP = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_msToNext = Math.Max(_chain[_nextIndex].TimeToNext, 1u);
|
||||
SendSplineFor(me, _nextIndex, _msToNext);
|
||||
++_nextIndex;
|
||||
if (_nextIndex >= _chainSize)
|
||||
_msToNext = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.outError(LogFilter.Movement, "SplineChainMovementGenerator.Initialize - empty spline chain passed for {0}.", me.GetGUID().ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public override void Finalize(Unit me)
|
||||
{
|
||||
if (!finished)
|
||||
return;
|
||||
|
||||
Creature cMe = me.ToCreature();
|
||||
if (cMe && cMe.IsAIEnabled)
|
||||
cMe.GetAI().MovementInform(MovementGeneratorType.SplineChain, _id);
|
||||
}
|
||||
|
||||
public override bool Update(Unit me, uint diff)
|
||||
{
|
||||
if (finished)
|
||||
return false;
|
||||
|
||||
// _msToNext being zero here means we're on the final spline
|
||||
if (_msToNext == 0)
|
||||
{
|
||||
finished = me.moveSpline.Finalized();
|
||||
return !finished;
|
||||
}
|
||||
|
||||
if (_msToNext <= diff)
|
||||
{
|
||||
// Send next spline
|
||||
Log.outDebug(LogFilter.Movement, "{0}: Should send spline {1} ({2} ms late).", me.GetGUID().ToString(), _nextIndex, diff - _msToNext);
|
||||
_msToNext = Math.Max(_chain[_nextIndex].TimeToNext, 1u);
|
||||
SendSplineFor(me, _nextIndex, _msToNext);
|
||||
++_nextIndex;
|
||||
if (_nextIndex >= _chainSize)
|
||||
{
|
||||
// We have reached the final spline, once it finalizes we should also finalize the movegen (start checking on next update)
|
||||
_msToNext = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
_msToNext -= diff;
|
||||
return true;
|
||||
}
|
||||
|
||||
SplineChainResumeInfo GetResumeInfo(Unit me)
|
||||
{
|
||||
if (_nextIndex == 0)
|
||||
return new SplineChainResumeInfo(_id, _chain, _walk, 0, 0, _msToNext);
|
||||
if (me.moveSpline.Finalized())
|
||||
{
|
||||
if (_nextIndex < _chainSize)
|
||||
return new SplineChainResumeInfo(_id, _chain, _walk, _nextIndex, 0, 1u);
|
||||
else
|
||||
return new SplineChainResumeInfo();
|
||||
}
|
||||
return new SplineChainResumeInfo(_id, _chain, _walk, (byte)(_nextIndex - 1), (byte)(me.moveSpline._currentSplineIdx()), _msToNext);
|
||||
}
|
||||
|
||||
public override void Reset(Unit owner) { }
|
||||
|
||||
public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.SplineChain; }
|
||||
|
||||
uint _id;
|
||||
List<SplineChainLink> _chain = new List<SplineChainLink>();
|
||||
byte _chainSize;
|
||||
bool _walk;
|
||||
bool finished;
|
||||
byte _nextIndex;
|
||||
byte _nextFirstWP; // only used for resuming
|
||||
uint _msToNext;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user