114 lines
2.5 KiB
C#
114 lines
2.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using OpenRa.Game.GameRules;
|
|
using OpenRa.Game.Graphics;
|
|
|
|
namespace OpenRa.Game.Traits
|
|
{
|
|
class Mobile : ITick, IOrder
|
|
{
|
|
public Actor self;
|
|
|
|
public int2 fromCell, destination;
|
|
public int2 toCell { get { return self.Location; } }
|
|
public int moveFraction, moveFractionTotal;
|
|
public int facing;
|
|
|
|
public Mobile(Actor self)
|
|
{
|
|
this.self = self;
|
|
fromCell = destination = self.Location;
|
|
}
|
|
|
|
public bool Turn(int desiredFacing)
|
|
{
|
|
if (facing == desiredFacing)
|
|
return false;
|
|
|
|
int df = (desiredFacing - facing + 32) % 32;
|
|
facing = (facing + (df > 16 ? 31 : 1)) % 32;
|
|
return true;
|
|
}
|
|
|
|
static float2[] fvecs = Util.MakeArray<float2>(32,
|
|
i => -float2.FromAngle(i / 16.0f * (float)Math.PI) * new float2(1f, 1.3f));
|
|
|
|
int GetFacing(float2 d)
|
|
{
|
|
if (float2.WithinEpsilon(d, float2.Zero, 0.001f))
|
|
return facing;
|
|
|
|
int highest = -1;
|
|
float highestDot = -1.0f;
|
|
|
|
for (int i = 0; i < fvecs.Length; i++)
|
|
{
|
|
float dot = float2.Dot(fvecs[i], d);
|
|
if (dot > highestDot)
|
|
{
|
|
highestDot = dot;
|
|
highest = i;
|
|
}
|
|
}
|
|
|
|
return highest;
|
|
}
|
|
|
|
void UpdateCenterLocation()
|
|
{
|
|
float fraction = (moveFraction > 0) ? (float)moveFraction / moveFractionTotal : 0f;
|
|
self.CenterLocation = new float2(12, 12) + 24 * float2.Lerp(fromCell, toCell, fraction);
|
|
}
|
|
|
|
public void Tick(Actor self, Game game, int dt)
|
|
{
|
|
Move(self, game, dt);
|
|
UpdateCenterLocation();
|
|
}
|
|
|
|
void Move(Actor self, Game game, int dt)
|
|
{
|
|
if (fromCell != toCell)
|
|
{
|
|
if (Turn(GetFacing(toCell - fromCell)))
|
|
return;
|
|
|
|
moveFraction += dt * ((UnitInfo.MobileInfo)self.unitInfo).Speed;
|
|
}
|
|
if (moveFraction < moveFractionTotal)
|
|
return;
|
|
|
|
moveFraction = 0;
|
|
moveFractionTotal = 0;
|
|
fromCell = toCell;
|
|
|
|
if (destination == toCell)
|
|
return;
|
|
|
|
List<int2> res = game.pathFinder.FindUnitPath(toCell, PathFinder.DefaultEstimator(destination));
|
|
if (res.Count != 0)
|
|
{
|
|
self.Location = res[res.Count - 1];
|
|
|
|
int2 dir = toCell - fromCell;
|
|
moveFractionTotal = (dir.X != 0 && dir.Y != 0) ? 2500 : 2000;
|
|
}
|
|
else
|
|
destination = toCell;
|
|
}
|
|
|
|
public Order Order(Actor self, Game game, int2 xy)
|
|
{
|
|
if (xy != toCell)
|
|
{
|
|
if (game.LocalPlayer == self.Owner)
|
|
game.PlaySound("ackno.r00", false);
|
|
return new MoveOrder(self, xy);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|