While they may be only 'visual' in terms of influence/cell grid, they all do update CenterPosition, which is essentially the actual world position of the actor. 'Visual' would imply that it only affects the position where the actor is drawn, which is inaccurate. Furthermore, using the term 'Visual' here would make naming future methods/properties related to visual interpolation unnecessarily complicated, because that's where we might need a real 'Visual(Only)Position'.
127 lines
3.6 KiB
C#
127 lines
3.6 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
|
* This file is part of OpenRA, which is free software. It is made
|
|
* available to you 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. For more
|
|
* information, see COPYING.
|
|
*/
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using OpenRA.Activities;
|
|
using OpenRA.Mods.Cnc.Traits;
|
|
using OpenRA.Mods.Common.Traits;
|
|
using OpenRA.Traits;
|
|
|
|
namespace OpenRA.Mods.Cnc.Activities
|
|
{
|
|
public class Leap : Activity
|
|
{
|
|
readonly Mobile mobile;
|
|
readonly Mobile targetMobile;
|
|
readonly int speed;
|
|
readonly AttackLeap attack;
|
|
readonly EdibleByLeap edible;
|
|
readonly Target target;
|
|
|
|
CPos destinationCell;
|
|
SubCell destinationSubCell = SubCell.Any;
|
|
WPos destination, origin;
|
|
int length;
|
|
bool canceled = false;
|
|
bool jumpComplete = false;
|
|
int ticks = 0;
|
|
WPos targetPosition;
|
|
|
|
public Leap(Actor self, in Target target, Mobile mobile, Mobile targetMobile, int speed, AttackLeap attack, EdibleByLeap edible)
|
|
{
|
|
this.mobile = mobile;
|
|
this.targetMobile = targetMobile;
|
|
this.attack = attack;
|
|
this.target = target;
|
|
this.edible = edible;
|
|
this.speed = speed;
|
|
}
|
|
|
|
protected override void OnFirstRun(Actor self)
|
|
{
|
|
destinationCell = target.Actor.Location;
|
|
if (targetMobile != null)
|
|
destinationSubCell = targetMobile.ToSubCell;
|
|
|
|
origin = self.CenterPosition;
|
|
destination = self.World.Map.CenterOfSubCell(destinationCell, destinationSubCell);
|
|
length = Math.Max((origin - destination).Length / speed, 1);
|
|
|
|
// First check if we are still allowed to leap
|
|
// We need an extra boolean as using Cancel() in OnFirstRun doesn't work
|
|
canceled = !edible.GetLeapAtBy(self) || target.Type != TargetType.Actor;
|
|
|
|
IsInterruptible = false;
|
|
|
|
if (canceled)
|
|
return;
|
|
|
|
targetPosition = target.CenterPosition;
|
|
attack.GrantLeapCondition(self);
|
|
}
|
|
|
|
public override bool Tick(Actor self)
|
|
{
|
|
// Correct the visual position after we jumped
|
|
if (canceled || jumpComplete)
|
|
return true;
|
|
|
|
if (target.Type != TargetType.Invalid)
|
|
targetPosition = target.CenterPosition;
|
|
|
|
var position = length > 1 ? WPos.Lerp(origin, targetPosition, ticks, length - 1) : targetPosition;
|
|
mobile.SetCenterPosition(self, position);
|
|
|
|
// We are at the destination
|
|
if (++ticks >= length)
|
|
{
|
|
// Revoke the run condition
|
|
attack.IsAiming = false;
|
|
|
|
// Move to the correct subcells, if our target actor uses subcells
|
|
// (This does not update the visual position!)
|
|
mobile.SetLocation(destinationCell, destinationSubCell, destinationCell, destinationSubCell);
|
|
|
|
// Update movement which results in movementType set to MovementType.None.
|
|
// This is needed to prevent the move animation from playing.
|
|
mobile.UpdateMovement(self);
|
|
|
|
// Revoke the condition before attacking, as it is usually used to pause the attack trait
|
|
attack.RevokeLeapCondition(self);
|
|
attack.DoAttack(self, target);
|
|
|
|
jumpComplete = true;
|
|
QueueChild(mobile.LocalMove(self, position, self.World.Map.CenterOfSubCell(destinationCell, destinationSubCell)));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected override void OnLastRun(Actor self)
|
|
{
|
|
attack.RevokeLeapCondition(self);
|
|
base.OnLastRun(self);
|
|
}
|
|
|
|
protected override void OnActorDispose(Actor self)
|
|
{
|
|
attack.RevokeLeapCondition(self);
|
|
base.OnActorDispose(self);
|
|
}
|
|
|
|
public override IEnumerable<Target> GetTargets(Actor self)
|
|
{
|
|
yield return Target.FromPos(ticks < length / 2 ? origin : destination);
|
|
}
|
|
}
|
|
}
|