Move Shape from Health to new HitShape trait

Renamed Shape to Type
This commit is contained in:
reaperrr
2017-05-21 12:44:47 +02:00
parent c7c6cf864c
commit 43b55ae333
9 changed files with 87 additions and 51 deletions

View File

@@ -296,6 +296,7 @@
<Compile Include="Traits\Burns.cs" /> <Compile Include="Traits\Burns.cs" />
<Compile Include="Traits\ChangesTerrain.cs" /> <Compile Include="Traits\ChangesTerrain.cs" />
<Compile Include="Traits\Health.cs" /> <Compile Include="Traits\Health.cs" />
<Compile Include="Traits\HitShape.cs" />
<Compile Include="Traits\PowerTooltip.cs" /> <Compile Include="Traits\PowerTooltip.cs" />
<Compile Include="Traits\Render\VeteranProductionIconOverlay.cs" /> <Compile Include="Traits\Render\VeteranProductionIconOverlay.cs" />
<Compile Include="Traits\Capturable.cs" /> <Compile Include="Traits\Capturable.cs" />

View File

@@ -12,6 +12,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq;
using OpenRA.Effects; using OpenRA.Effects;
using OpenRA.GameRules; using OpenRA.GameRules;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -302,12 +303,9 @@ namespace OpenRA.Mods.Common.Projectiles
if (!info.ValidBounceBlockerStances.HasStance(victim.Owner.Stances[firedBy.Owner])) if (!info.ValidBounceBlockerStances.HasStance(victim.Owner.Stances[firedBy.Owner]))
continue; continue;
var healthInfo = victim.Info.TraitInfoOrDefault<HealthInfo>();
if (healthInfo == null)
continue;
// If the impact position is within any actor's HitShape, we have a direct hit // If the impact position is within any actor's HitShape, we have a direct hit
if (healthInfo.Shape.DistanceFromEdge(pos, victim).Length <= 0) var activeShapes = victim.TraitsImplementing<HitShape>().Where(Exts.IsTraitEnabled);
if (activeShapes.Any(i => i.Info.Type.DistanceFromEdge(pos, victim).Length <= 0))
return true; return true;
} }

View File

@@ -34,6 +34,7 @@ namespace OpenRA.Mods.Common.Traits
readonly HealthInfo healthInfo; readonly HealthInfo healthInfo;
readonly Lazy<BodyOrientation> coords; readonly Lazy<BodyOrientation> coords;
HitShape[] shapes;
IBlocksProjectiles[] allBlockers; IBlocksProjectiles[] allBlockers;
ITargetablePositions[] targetablePositions; ITargetablePositions[] targetablePositions;
@@ -48,6 +49,7 @@ namespace OpenRA.Mods.Common.Traits
void INotifyCreated.Created(Actor self) void INotifyCreated.Created(Actor self)
{ {
shapes = self.TraitsImplementing<HitShape>().ToArray();
allBlockers = self.TraitsImplementing<IBlocksProjectiles>().ToArray(); allBlockers = self.TraitsImplementing<IBlocksProjectiles>().ToArray();
targetablePositions = self.TraitsImplementing<ITargetablePositions>().ToArray(); targetablePositions = self.TraitsImplementing<ITargetablePositions>().ToArray();
} }
@@ -60,9 +62,6 @@ namespace OpenRA.Mods.Common.Traits
var wcr = Game.Renderer.WorldRgbaColorRenderer; var wcr = Game.Renderer.WorldRgbaColorRenderer;
var iz = 1 / wr.Viewport.Zoom; var iz = 1 / wr.Viewport.Zoom;
if (healthInfo != null)
healthInfo.Shape.DrawCombatOverlay(wr, wcr, self);
var blockers = allBlockers.Where(Exts.IsTraitEnabled).ToList(); var blockers = allBlockers.Where(Exts.IsTraitEnabled).ToList();
if (blockers.Count > 0) if (blockers.Count > 0)
{ {
@@ -75,6 +74,10 @@ namespace OpenRA.Mods.Common.Traits
TargetLineRenderable.DrawTargetMarker(wr, hc, hb); TargetLineRenderable.DrawTargetMarker(wr, hc, hb);
} }
var activeShapes = shapes.Where(Exts.IsTraitEnabled);
foreach (var s in activeShapes)
s.Info.Type.DrawCombatOverlay(wr, wcr, self);
var tc = Color.Lime; var tc = Color.Lime;
var enabledPositions = targetablePositions.Where(Exts.IsTraitEnabled); var enabledPositions = targetablePositions.Where(Exts.IsTraitEnabled);
var positions = enabledPositions.SelectMany(tp => tp.TargetablePositions(self)); var positions = enabledPositions.SelectMany(tp => tp.TargetablePositions(self));

View File

@@ -10,7 +10,6 @@
#endregion #endregion
using System.Linq; using System.Linq;
using OpenRA.Mods.Common.HitShapes;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
@@ -22,36 +21,6 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Trigger interfaces such as AnnounceOnKill?")] [Desc("Trigger interfaces such as AnnounceOnKill?")]
public readonly bool NotifyAppliedDamage = true; public readonly bool NotifyAppliedDamage = true;
[FieldLoader.LoadUsing("LoadShape")]
public readonly IHitShape Shape;
static object LoadShape(MiniYaml yaml)
{
IHitShape ret;
var shapeNode = yaml.Nodes.Find(n => n.Key == "Shape");
var shape = shapeNode != null ? shapeNode.Value.Value : string.Empty;
if (!string.IsNullOrEmpty(shape))
{
ret = Game.CreateObject<IHitShape>(shape + "Shape");
try
{
FieldLoader.Load(ret, shapeNode.Value);
}
catch (YamlException e)
{
throw new YamlException("HitShape {0}: {1}".F(shape, e.Message));
}
}
else
ret = new CircleShape();
ret.Initialize();
return ret;
}
public virtual object Create(ActorInitializer init) { return new Health(init, this); } public virtual object Create(ActorInitializer init) { return new Health(init, this); }
} }

View File

@@ -0,0 +1,59 @@
#region Copyright & License Information
/*
* Copyright 2007-2017 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.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.HitShapes;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Shape of actor for damage calculations.")]
public class HitShapeInfo : ConditionalTraitInfo
{
[FieldLoader.LoadUsing("LoadShape")]
public readonly IHitShape Type;
static object LoadShape(MiniYaml yaml)
{
IHitShape ret;
var shapeNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Type");
var shape = shapeNode != null ? shapeNode.Value.Value : string.Empty;
if (!string.IsNullOrEmpty(shape))
{
try
{
ret = Game.CreateObject<IHitShape>(shape + "Shape");
FieldLoader.Load(ret, shapeNode.Value);
}
catch (YamlException e)
{
throw new YamlException("HitShape {0}: {1}".F(shape, e.Message));
}
}
else
ret = new CircleShape();
ret.Initialize();
return ret;
}
public override object Create(ActorInitializer init) { return new HitShape(init.Self, this); }
}
public class HitShape : ConditionalTrait<HitShapeInfo>
{
public HitShape(Actor self, HitShapeInfo info)
: base(info) { }
}
}

View File

@@ -180,14 +180,14 @@ namespace OpenRA.Mods.Common
// TODO: Investigate caching this or moving it to ActorMapInfo // TODO: Investigate caching this or moving it to ActorMapInfo
public static WDist MinimumRequiredVictimScanRadius(Ruleset rules) public static WDist MinimumRequiredVictimScanRadius(Ruleset rules)
{ {
return rules.Actors.SelectMany(a => a.Value.TraitInfos<HealthInfo>()).Max(h => h.Shape.OuterRadius); return rules.Actors.SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius);
} }
// TODO: Investigate caching this or moving it to ActorMapInfo // TODO: Investigate caching this or moving it to ActorMapInfo
public static WDist MinimumRequiredBlockerScanRadius(Ruleset rules) public static WDist MinimumRequiredBlockerScanRadius(Ruleset rules)
{ {
return rules.Actors.Where(a => a.Value.HasTraitInfo<IBlocksProjectilesInfo>()) return rules.Actors.Where(a => a.Value.HasTraitInfo<IBlocksProjectilesInfo>())
.SelectMany(a => a.Value.TraitInfos<HealthInfo>()).Max(h => h.Shape.OuterRadius); .SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius);
} }
} }
} }

View File

@@ -10,6 +10,7 @@
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules; using OpenRA.GameRules;
using OpenRA.Mods.Common.Effects; using OpenRA.Mods.Common.Effects;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
@@ -88,12 +89,9 @@ namespace OpenRA.Mods.Common.Warheads
if (checkTargetType && !IsValidAgainst(victim, firedBy)) if (checkTargetType && !IsValidAgainst(victim, firedBy))
continue; continue;
var healthInfo = victim.Info.TraitInfoOrDefault<HealthInfo>(); // If the impact position is within any HitShape, we have a direct hit
if (healthInfo == null) var activeShapes = victim.TraitsImplementing<HitShape>().Where(Exts.IsTraitEnabled);
continue; if (activeShapes.Any(i => i.Info.Type.DistanceFromEdge(pos, victim).Length <= 0))
// If the impact position is within any actor's HitShape, we have a direct hit
if (healthInfo.Shape.DistanceFromEdge(pos, victim).Length <= 0)
return true; return true;
} }

View File

@@ -10,6 +10,7 @@
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules; using OpenRA.GameRules;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits; using OpenRA.Traits;
@@ -66,11 +67,17 @@ namespace OpenRA.Mods.Common.Warheads
foreach (var victim in hitActors) foreach (var victim in hitActors)
{ {
// Cannot be damaged without a Health trait
var healthInfo = victim.Info.TraitInfoOrDefault<HealthInfo>(); var healthInfo = victim.Info.TraitInfoOrDefault<HealthInfo>();
if (healthInfo == null) if (healthInfo == null)
continue; continue;
var distance = healthInfo.Shape.DistanceFromEdge(pos, victim); // Cannot be damaged without an active HitShape
var activeShapes = victim.TraitsImplementing<HitShape>().Where(Exts.IsTraitEnabled);
if (!activeShapes.Any())
continue;
var distance = activeShapes.Min(t => t.Info.Type.DistanceFromEdge(pos, victim));
var localModifiers = damageModifiers.Append(GetDamageFalloff(distance.Length)); var localModifiers = damageModifiers.Append(GetDamageFalloff(distance.Length));
DoImpact(victim, firedBy, localModifiers); DoImpact(victim, firedBy, localModifiers);

View File

@@ -11,6 +11,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
namespace OpenRA.Mods.Common namespace OpenRA.Mods.Common
@@ -45,9 +46,9 @@ namespace OpenRA.Mods.Common
foreach (var currActor in actorsInSquare) foreach (var currActor in actorsInSquare)
{ {
var actorWidth = 0; var actorWidth = 0;
var healthInfo = currActor.Info.TraitInfoOrDefault<HealthInfo>(); var shapes = currActor.TraitsImplementing<HitShape>().Where(Exts.IsTraitEnabled);
if (healthInfo != null) if (shapes.Any())
actorWidth = healthInfo.Shape.OuterRadius.Length; actorWidth = shapes.Max(h => h.Info.Type.OuterRadius.Length);
var projection = MinimumPointLineProjection(lineStart, lineEnd, currActor.CenterPosition); var projection = MinimumPointLineProjection(lineStart, lineEnd, currActor.CenterPosition);
var distance = (currActor.CenterPosition - projection).HorizontalLength; var distance = (currActor.CenterPosition - projection).HorizontalLength;