Ported .Net Core commits:
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
* 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.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
public class MoveSpline
|
||||
{
|
||||
public MoveSpline()
|
||||
{
|
||||
m_Id = 0;
|
||||
time_passed = 0;
|
||||
vertical_acceleration = 0.0f;
|
||||
initialOrientation = 0.0f;
|
||||
effect_start_time = 0;
|
||||
point_Idx = 0;
|
||||
point_Idx_offset = 0;
|
||||
onTransport = false;
|
||||
splineIsFacingOnly = false;
|
||||
splineflags.Flags = SplineFlag.Done;
|
||||
}
|
||||
|
||||
public void Initialize(MoveSplineInitArgs args)
|
||||
{
|
||||
splineflags = args.flags;
|
||||
facing = args.facing;
|
||||
m_Id = args.splineId;
|
||||
point_Idx_offset = args.path_Idx_offset;
|
||||
initialOrientation = args.initialOrientation;
|
||||
|
||||
time_passed = 0;
|
||||
vertical_acceleration = 0.0f;
|
||||
effect_start_time = 0;
|
||||
spell_effect_extra = args.spellEffectExtra;
|
||||
splineIsFacingOnly = args.path.Length == 2 && args.facing.type != MonsterMoveType.Normal && ((args.path[1] - args.path[0]).GetLength() < 0.1f);
|
||||
|
||||
// Check if its a stop spline
|
||||
if (args.flags.hasFlag(SplineFlag.Done))
|
||||
{
|
||||
spline.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
init_spline(args);
|
||||
|
||||
// init parabolic / animation
|
||||
// spline initialized, duration known and i able to compute parabolic acceleration
|
||||
if (args.flags.hasFlag(SplineFlag.Parabolic | SplineFlag.Animation | SplineFlag.FadeObject))
|
||||
{
|
||||
effect_start_time = (int)(Duration() * args.time_perc);
|
||||
if (args.flags.hasFlag(SplineFlag.Parabolic) && effect_start_time < Duration())
|
||||
{
|
||||
float f_duration = (float)TimeSpan.FromMilliseconds(Duration() - effect_start_time).TotalSeconds;
|
||||
vertical_acceleration = args.parabolic_amplitude * 8.0f / (f_duration * f_duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_spline(MoveSplineInitArgs args)
|
||||
{
|
||||
Spline.EvaluationMode[] modes = new Spline.EvaluationMode[2] { Spline.EvaluationMode.Linear, Spline.EvaluationMode.Catmullrom };
|
||||
if (args.flags.hasFlag(SplineFlag.Cyclic))
|
||||
{
|
||||
spline.init_cyclic_spline(args.path, args.path.Length, modes[Convert.ToInt32(args.flags.isSmooth())], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
spline.Init_Spline(args.path, args.path.Length, modes[Convert.ToInt32(args.flags.isSmooth())]);
|
||||
}
|
||||
|
||||
// init spline timestamps
|
||||
if (splineflags.hasFlag(SplineFlag.Falling))
|
||||
{
|
||||
FallInitializer init = new FallInitializer(spline.getPoint(spline.first()).Z);
|
||||
spline.initLengths(init);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommonInitializer init = new CommonInitializer(args.velocity);
|
||||
spline.initLengths(init);
|
||||
}
|
||||
|
||||
// TODO: what to do in such cases? problem is in input data (all points are at same coords)
|
||||
if (spline.length() < 1)
|
||||
{
|
||||
Log.outError(LogFilter.Unit, "MoveSpline.init_spline: zero length spline, wrong input data?");
|
||||
spline.set_length(spline.last(), spline.isCyclic() ? 1000 : 1);
|
||||
}
|
||||
point_Idx = spline.first();
|
||||
}
|
||||
|
||||
public int currentPathIdx()
|
||||
{
|
||||
int point = point_Idx_offset + point_Idx - spline.first() + (Finalized() ? 1 : 0);
|
||||
if (isCyclic())
|
||||
point = point % (spline.last() - spline.first());
|
||||
return point;
|
||||
}
|
||||
|
||||
public Vector3[] getPath() { return spline.getPoints(); }
|
||||
public int timePassed() { return time_passed; }
|
||||
|
||||
public int Duration() { return spline.length(); }
|
||||
public int _currentSplineIdx() { return point_Idx; }
|
||||
public uint GetId() { return m_Id; }
|
||||
public bool Finalized() { return splineflags.hasFlag(SplineFlag.Done); }
|
||||
void _Finalize()
|
||||
{
|
||||
splineflags.SetUnsetFlag(SplineFlag.Done);
|
||||
point_Idx = spline.last() - 1;
|
||||
time_passed = Duration();
|
||||
}
|
||||
public Vector4 computePosition(int time_point, int point_index)
|
||||
{
|
||||
float u = 1.0f;
|
||||
int seg_time = spline.length(point_index, point_index + 1);
|
||||
if (seg_time > 0)
|
||||
u = (time_point - spline.length(point_index)) / (float)seg_time;
|
||||
|
||||
Vector3 c;
|
||||
float orientation = initialOrientation;
|
||||
spline.Evaluate_Percent(point_index, u, out c);
|
||||
|
||||
if (splineflags.hasFlag(SplineFlag.Parabolic))
|
||||
computeParabolicElevation(time_point, ref c.Z);
|
||||
else if (splineflags.hasFlag(SplineFlag.Falling))
|
||||
computeFallElevation(time_point, ref c.Z);
|
||||
|
||||
if (splineflags.hasFlag(SplineFlag.Done) && facing.type != MonsterMoveType.Normal)
|
||||
{
|
||||
if (facing.type == MonsterMoveType.FacingAngle)
|
||||
orientation = facing.angle;
|
||||
else if (facing.type == MonsterMoveType.FacingSpot)
|
||||
orientation = (float)Math.Atan2(facing.f.Y - c.Y, facing.f.X - c.X);
|
||||
//nothing to do for MoveSplineFlag.Final_Target flag
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!splineflags.hasFlag(SplineFlag.OrientationFixed | SplineFlag.Falling | SplineFlag.Unknown0))
|
||||
{
|
||||
Vector3 hermite;
|
||||
spline.Evaluate_Derivative(point_Idx, u, out hermite);
|
||||
orientation = (float)Math.Atan2(hermite.Y, hermite.X);
|
||||
}
|
||||
|
||||
if (splineflags.hasFlag(SplineFlag.Backward))
|
||||
orientation = orientation - (float)Math.PI;
|
||||
}
|
||||
|
||||
return new Vector4(c.X, c.Y, c.Z, orientation);
|
||||
}
|
||||
public Vector4 ComputePosition()
|
||||
{
|
||||
return computePosition(time_passed, point_Idx);
|
||||
}
|
||||
public Vector4 ComputePosition(int time_offset)
|
||||
{
|
||||
int time_point = time_passed + time_offset;
|
||||
if (time_point >= Duration())
|
||||
return computePosition(Duration(), spline.last() - 1);
|
||||
if (time_point <= 0)
|
||||
return computePosition(0, spline.first());
|
||||
|
||||
// find point_index where spline.length(point_index) < time_point < spline.length(point_index + 1)
|
||||
int point_index = point_Idx;
|
||||
while (time_point >= spline.length(point_index + 1))
|
||||
++point_index;
|
||||
|
||||
while (time_point < spline.length(point_index))
|
||||
--point_index;
|
||||
|
||||
return computePosition(time_point, point_index);
|
||||
}
|
||||
public void computeParabolicElevation(int time_point, ref float el)
|
||||
{
|
||||
if (time_point > effect_start_time)
|
||||
{
|
||||
float t_passedf = MSToSec((uint)(time_point - effect_start_time));
|
||||
float t_durationf = MSToSec((uint)(Duration() - effect_start_time)); //client use not modified duration here
|
||||
if (spell_effect_extra.HasValue && spell_effect_extra.Value.ParabolicCurveId != 0)
|
||||
t_passedf *= Global.DB2Mgr.GetCurveValueAt(spell_effect_extra.Value.ParabolicCurveId, time_point / Duration());
|
||||
|
||||
el += (t_durationf - t_passedf) * 0.5f * vertical_acceleration * t_passedf;
|
||||
}
|
||||
}
|
||||
public void computeFallElevation(int time_point, ref float el)
|
||||
{
|
||||
float z_now = spline.getPoint(spline.first()).Z - computeFallElevation(MSToSec((uint)time_point), false);
|
||||
float final_z = FinalDestination().Z;
|
||||
el = Math.Max(z_now, final_z);
|
||||
}
|
||||
public static float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity = 0.0f)
|
||||
{
|
||||
float termVel;
|
||||
float result;
|
||||
|
||||
if (isSafeFall)
|
||||
termVel = SharedConst.terminalSafefallVelocity;
|
||||
else
|
||||
termVel = SharedConst.terminalVelocity;
|
||||
|
||||
if (start_velocity > termVel)
|
||||
start_velocity = termVel;
|
||||
|
||||
float terminal_time = (float)((isSafeFall ? SharedConst.terminal_safeFall_fallTime : SharedConst.terminal_fallTime) - start_velocity / SharedConst.gravity); // the time that needed to reach terminalVelocity
|
||||
|
||||
if (t_passed > terminal_time)
|
||||
{
|
||||
result = termVel * (t_passed - terminal_time) +
|
||||
start_velocity * terminal_time +
|
||||
(float)SharedConst.gravity * terminal_time * terminal_time * 0.5f;
|
||||
}
|
||||
else
|
||||
result = t_passed * (float)(start_velocity + t_passed * SharedConst.gravity * 0.5f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float MSToSec(uint ms)
|
||||
{
|
||||
return ms / 1000.0f;
|
||||
}
|
||||
|
||||
public void Interrupt() { splineflags.SetUnsetFlag(SplineFlag.Done); }
|
||||
public void updateState(int difftime)
|
||||
{
|
||||
do
|
||||
{
|
||||
_updateState(ref difftime);
|
||||
} while (difftime > 0);
|
||||
}
|
||||
UpdateResult _updateState(ref int ms_time_diff)
|
||||
{
|
||||
if (Finalized())
|
||||
{
|
||||
ms_time_diff = 0;
|
||||
return UpdateResult.Arrived;
|
||||
}
|
||||
|
||||
UpdateResult result = UpdateResult.None;
|
||||
int minimal_diff = Math.Min(ms_time_diff, segment_time_elapsed());
|
||||
time_passed += minimal_diff;
|
||||
ms_time_diff -= minimal_diff;
|
||||
|
||||
if (time_passed >= next_timestamp())
|
||||
{
|
||||
++point_Idx;
|
||||
if (point_Idx < spline.last())
|
||||
{
|
||||
result = UpdateResult.NextSegment;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spline.isCyclic())
|
||||
{
|
||||
point_Idx = spline.first();
|
||||
time_passed = time_passed % Duration();
|
||||
result = UpdateResult.NextCycle;
|
||||
}
|
||||
else
|
||||
{
|
||||
_Finalize();
|
||||
ms_time_diff = 0;
|
||||
result = UpdateResult.Arrived;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
int next_timestamp() { return spline.length(point_Idx + 1); }
|
||||
int segment_time_elapsed() { return next_timestamp() - time_passed; }
|
||||
public bool isCyclic() { return splineflags.hasFlag(SplineFlag.Cyclic); }
|
||||
public bool isFalling() { return splineflags.hasFlag(SplineFlag.Falling); }
|
||||
public bool Initialized() { return !spline.empty(); }
|
||||
public Vector3 FinalDestination() { return Initialized() ? spline.getPoint(spline.last()) : new Vector3(); }
|
||||
|
||||
#region Fields
|
||||
public MoveSplineInitArgs InitArgs;
|
||||
public Spline spline = new Spline();
|
||||
public FacingInfo facing;
|
||||
public MoveSplineFlag splineflags = new MoveSplineFlag();
|
||||
public bool onTransport;
|
||||
public bool splineIsFacingOnly;
|
||||
public uint m_Id;
|
||||
public int time_passed;
|
||||
public float vertical_acceleration;
|
||||
public float initialOrientation;
|
||||
public int effect_start_time;
|
||||
public int point_Idx;
|
||||
public int point_Idx_offset;
|
||||
public Optional<SpellEffectExtraData> spell_effect_extra;
|
||||
#endregion
|
||||
|
||||
public class CommonInitializer : Initializer
|
||||
{
|
||||
public CommonInitializer(float _velocity)
|
||||
{
|
||||
velocityInv = 1000f / _velocity;
|
||||
time = 1;
|
||||
}
|
||||
public float velocityInv;
|
||||
public int time;
|
||||
public int SetGetTime(Spline s, int i)
|
||||
{
|
||||
time += (int)(s.SegLength(i) * velocityInv);
|
||||
return time;
|
||||
}
|
||||
}
|
||||
public class FallInitializer : Initializer
|
||||
{
|
||||
public FallInitializer(float startelevation)
|
||||
{
|
||||
startElevation = startelevation;
|
||||
}
|
||||
float startElevation;
|
||||
public int SetGetTime(Spline s, int i)
|
||||
{
|
||||
return (int)(computeFallTime(startElevation - s.getPoint(i + 1).Z, false) * 1000.0f);
|
||||
}
|
||||
|
||||
float computeFallTime(float path_length, bool isSafeFall)
|
||||
{
|
||||
if (path_length < 0.0f)
|
||||
return 0.0f;
|
||||
|
||||
float time;
|
||||
if (isSafeFall)
|
||||
{
|
||||
if (path_length >= SharedConst.terminal_safeFall_length)
|
||||
time = (path_length - SharedConst.terminal_safeFall_length) / SharedConst.terminalSafefallVelocity + SharedConst.terminal_safeFall_fallTime;
|
||||
else
|
||||
time = (float)Math.Sqrt(2.0f * path_length / SharedConst.gravity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path_length >= SharedConst.terminal_length)
|
||||
time = (path_length - SharedConst.terminal_length) / SharedConst.terminalVelocity + SharedConst.terminal_fallTime;
|
||||
else
|
||||
time = (float)Math.Sqrt(2.0f * path_length / SharedConst.gravity);
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
}
|
||||
public enum UpdateResult
|
||||
{
|
||||
None = 0x01,
|
||||
Arrived = 0x02,
|
||||
NextCycle = 0x04,
|
||||
NextSegment = 0x08
|
||||
}
|
||||
}
|
||||
public interface Initializer
|
||||
{
|
||||
int SetGetTime(Spline s, int i);
|
||||
}
|
||||
|
||||
public class SplineChainLink
|
||||
{
|
||||
public SplineChainLink(Vector3[] points, uint expectedDuration, uint msToNext)
|
||||
{
|
||||
Points.AddRange(points);
|
||||
ExpectedDuration = expectedDuration;
|
||||
TimeToNext = msToNext;
|
||||
}
|
||||
|
||||
public SplineChainLink(uint expectedDuration, uint msToNext)
|
||||
{
|
||||
ExpectedDuration = expectedDuration;
|
||||
TimeToNext = msToNext;
|
||||
}
|
||||
|
||||
public List<Vector3> Points = new List<Vector3>();
|
||||
public uint ExpectedDuration;
|
||||
public uint TimeToNext;
|
||||
}
|
||||
|
||||
public class SplineChainResumeInfo
|
||||
{
|
||||
public SplineChainResumeInfo() { }
|
||||
public SplineChainResumeInfo(uint id, List<SplineChainLink> chain, bool walk, byte splineIndex, byte wpIndex, uint msToNext)
|
||||
{
|
||||
PointID = id;
|
||||
Chain = chain;
|
||||
IsWalkMode = walk;
|
||||
SplineIndex = splineIndex;
|
||||
PointIndex = wpIndex;
|
||||
TimeToNext = msToNext;
|
||||
}
|
||||
|
||||
public bool Empty() { return Chain.Empty(); }
|
||||
public void Clear() { Chain.Clear(); }
|
||||
|
||||
public uint PointID;
|
||||
public List<SplineChainLink> Chain = new List<SplineChainLink>();
|
||||
public bool IsWalkMode;
|
||||
public byte SplineIndex;
|
||||
public byte PointIndex;
|
||||
public uint TimeToNext;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user