Give husks the ability to crush

This commit is contained in:
Gustas
2022-10-01 15:47:23 +03:00
committed by Matthias Mailänder
parent 7638822e49
commit a691f2ebac
6 changed files with 65 additions and 5 deletions

View File

@@ -9,8 +9,10 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Activities;
using OpenRA.Mods.Common.Activities;
using OpenRA.Primitives;
using OpenRA.Traits;
@@ -18,13 +20,17 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Spawns remains of a husk actor with the correct facing.")]
public class HuskInfo : TraitInfo, IPositionableInfo, IFacingInfo, IActorPreviewInitInfo
public class HuskInfo : TraitInfo, IPositionableInfo, IFacingInfo, IActorPreviewInitInfo, IRulesetLoaded
{
public readonly HashSet<string> AllowedTerrain = new();
[Desc("Facing to use for actor previews (map editor, color picker, etc)")]
public readonly WAngle PreviewFacing = new(384);
[LocomotorReference]
[Desc("Used to define crushes. Locomotor must be defined on the World actor.")]
public readonly string Locomotor = null;
IEnumerable<ActorInit> IActorPreviewInitInfo.ActorPreviewInits(ActorInfo ai, ActorPreviewType type)
{
yield return new FacingInit(PreviewFacing);
@@ -47,6 +53,15 @@ namespace OpenRA.Mods.Common.Traits
// all places relevant for husks check IPositionable.CanEnterCell instead, so we can safely set this to true.
return true;
}
public LocomotorInfo LocomotorInfo { get; private set; }
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
if (string.IsNullOrEmpty(Locomotor))
return;
LocomotorInfo = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>().FirstOrDefault(li => li.Name == Locomotor);
}
}
public class Husk : IPositionable, IFacing, ISync, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld,
@@ -95,10 +110,7 @@ namespace OpenRA.Mods.Common.Traits
void INotifyCreated.Created(Actor self)
{
var distance = (finalPosition - CenterPosition).Length;
if (dragSpeed > 0 && distance > 0)
self.QueueActivity(new Drag(self, CenterPosition, finalPosition, distance / dragSpeed));
self.QueueActivity(new DragAndCrush(self, info.LocomotorInfo, dragSpeed, finalPosition));
notifyCenterPositionChanged = self.TraitsImplementing<INotifyCenterPositionChanged>().ToArray();
}
@@ -181,4 +193,39 @@ namespace OpenRA.Mods.Common.Traits
public HuskSpeedInit(int value)
: base(value) { }
}
public class DragAndCrush : Activity
{
readonly LocomotorInfo info;
public DragAndCrush(Actor self, LocomotorInfo info, int dragSpeed, WPos finalPosition)
{
this.info = info;
var distance = (finalPosition - self.CenterPosition).Length;
if (dragSpeed > 0 && distance > 0)
self.QueueActivity(new Drag(self, self.CenterPosition, finalPosition, distance / dragSpeed));
}
protected override void OnFirstRun(Actor self)
{
if (self.IsAtGroundLevel())
CrushAction(self, self.CenterPosition, (notifyCrushed) => notifyCrushed.OnCrush);
}
void CrushAction(Actor self, WPos position, Func<INotifyCrushed, Action<Actor, Actor, BitSet<CrushClass>>> action)
{
if (info == null || !info.Crushes.Any())
return;
var crushables = self.World.ActorMap.GetActorsAt(self.World.Map.CellContaining(position)).Where(a => a != self)
.SelectMany(a => a.TraitsImplementing<ICrushable>().Select(t => new TraitPair<ICrushable>(a, t)));
// Only crush actors that are on the ground level.
foreach (var crushable in crushables)
if (crushable.Trait.CrushableBy(crushable.Actor, self, info.Crushes) && crushable.Actor.IsAtGroundLevel())
foreach (var notifyCrushed in crushable.Actor.TraitsImplementing<INotifyCrushed>())
action(notifyCrushed)(crushable.Actor, self, info.Crushes);
}
}
}

View File

@@ -1069,6 +1069,7 @@
Inherits: ^CommonHuskDefaults
Husk:
AllowedTerrain: Clear, Rough, Road, Tiberium, BlueTiberium, Beach
Locomotor: tracked
Targetable:
RequiresForceFire: true
TargetTypes: Ground, Husk
@@ -1097,6 +1098,8 @@
^LightHusk:
Inherits: ^Husk
Husk:
Locomotor: wheeled
Health:
HP: 4000

View File

@@ -299,6 +299,7 @@
Inherits: ^Husk
Husk:
AllowedTerrain: Sand, Rock, Transition, Concrete, Spice, SpiceSand, SpiceBlobs, Dune
Locomotor: tank
Targetable:
TargetTypes: Ground, Vehicle
RequiresForceFire: true

View File

@@ -32,6 +32,8 @@ missile_tank.husk:
sonic_tank.husk:
Inherits: ^VehicleHusk
Husk:
Locomotor: vehicle
Tooltip:
Name: Sonic Tank (Destroyed)
TransformOnCapture:
@@ -39,6 +41,8 @@ sonic_tank.husk:
devastator.husk:
Inherits: ^VehicleHusk
Husk:
Locomotor: devastator
Health:
HP: 1250
Tooltip:

View File

@@ -1048,6 +1048,7 @@
Inherits@2: ^ClassicFacingSpriteActor
Husk:
AllowedTerrain: Clear, Rough, Road, Ore, Gems, Beach
Locomotor: tracked
WithIdleOverlay@Burns:
Image: fire
Sequence: 1

View File

@@ -26,6 +26,8 @@
4TNK.Husk:
Inherits: ^Husk
Husk:
Locomotor: heavytracked
Tooltip:
Name: Husk (Mammoth Tank)
ThrowsParticle@turret:
@@ -72,6 +74,8 @@ MCV.Husk:
MGG.Husk:
Inherits: ^Husk
Husk:
Locomotor: wheeled
Tooltip:
Name: Husk (Mobile Gap Generator)
ThrowsParticle@spinner: