diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 179b0fa288..fb791dc7cd 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -419,7 +419,6 @@
-
diff --git a/OpenRA.Mods.Common/Traits/Explodes.cs b/OpenRA.Mods.Common/Traits/Explodes.cs
index b73eca9587..3fd58b3dd3 100644
--- a/OpenRA.Mods.Common/Traits/Explodes.cs
+++ b/OpenRA.Mods.Common/Traits/Explodes.cs
@@ -17,16 +17,18 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
+ public enum ExplosionType { Footprint, CenterPosition }
+
[Desc("This actor explodes when killed.")]
public class ExplodesInfo : ITraitInfo, IRulesetLoaded, Requires
{
- [WeaponReference, FieldLoader.Require, Desc("Weapon to use for explosion if ammo/payload is loaded.")]
+ [WeaponReference, FieldLoader.Require, Desc("Default weapon to use for explosion if ammo/payload is loaded.")]
public readonly string Weapon = "UnitExplode";
- [WeaponReference, Desc("Weapon to use for explosion if no ammo/payload is loaded.")]
+ [WeaponReference, Desc("Fallback weapon to use for explosion if empty (no ammo/payload).")]
public readonly string EmptyWeapon = "UnitExplode";
- [Desc("Chance that the explosion will use Weapon if the actor has ammo/payload.")]
+ [Desc("Chance that the explosion will use Weapon instead of EmptyWeapon when exploding, provided the actor has ammo/payload.")]
public readonly int LoadedChance = 100;
[Desc("Chance that this actor will explode at all.")]
@@ -38,6 +40,10 @@ namespace OpenRA.Mods.Common.Traits
[Desc("DeathType(s) that trigger the explosion. Leave empty to always trigger an explosion.")]
public readonly HashSet DeathTypes = new HashSet();
+ [Desc("Possible values are CenterPosition (explosion at the actors' center) and ",
+ "Footprint (explosion on each occupied cell).")]
+ public readonly ExplosionType Type = ExplosionType.CenterPosition;
+
public WeaponInfo WeaponInfo { get; private set; }
public WeaponInfo EmptyWeaponInfo { get; private set; }
@@ -49,11 +55,11 @@ namespace OpenRA.Mods.Common.Traits
}
}
- public class Explodes : INotifyKilled, INotifyDamage
+ public class Explodes : INotifyKilled, INotifyDamage, INotifyCreated
{
readonly ExplodesInfo info;
-
readonly Health health;
+ BuildingInfo buildingInfo;
public Explodes(ExplodesInfo info, Actor self)
{
@@ -61,7 +67,12 @@ namespace OpenRA.Mods.Common.Traits
health = self.Trait();
}
- public void Killed(Actor self, AttackInfo e)
+ void INotifyCreated.Created(Actor self)
+ {
+ buildingInfo = self.Info.TraitInfoOrDefault();
+ }
+
+ void INotifyKilled.Killed(Actor self, AttackInfo e)
{
if (!self.IsInWorld)
return;
@@ -79,6 +90,15 @@ namespace OpenRA.Mods.Common.Traits
if (weapon.Report != null && weapon.Report.Any())
Game.Sound.Play(weapon.Report.Random(e.Attacker.World.SharedRandom), self.CenterPosition);
+ if (info.Type == ExplosionType.Footprint && buildingInfo != null)
+ {
+ var cells = FootprintUtils.UnpathableTiles(self.Info.Name, buildingInfo, self.Location);
+ foreach (var c in cells)
+ weapon.Impact(Target.FromPos(self.World.Map.CenterOfCell(c)), e.Attacker, Enumerable.Empty());
+
+ return;
+ }
+
// Use .FromPos since this actor is killed. Cannot use Target.FromActor
weapon.Impact(Target.FromPos(self.CenterPosition), e.Attacker, Enumerable.Empty());
}
@@ -90,7 +110,7 @@ namespace OpenRA.Mods.Common.Traits
return (shouldExplode && useFullExplosion) ? info.WeaponInfo : info.EmptyWeaponInfo;
}
- public void Damaged(Actor self, AttackInfo e)
+ void INotifyDamage.Damaged(Actor self, AttackInfo e)
{
if (info.DamageThreshold == 0)
return;
diff --git a/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderShroud.cs b/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderShroud.cs
index bbedbcfc7c..a49182845f 100644
--- a/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderShroud.cs
+++ b/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderShroud.cs
@@ -15,8 +15,6 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
- public enum VisibilityType { Footprint, CenterPosition, GroundPosition }
-
[Desc("The actor stays invisible under the shroud.")]
public class HiddenUnderShroudInfo : ITraitInfo, IDefaultVisibilityInfo
{
diff --git a/OpenRA.Mods.Common/Traits/Render/WithBuildingExplosion.cs b/OpenRA.Mods.Common/Traits/Render/WithBuildingExplosion.cs
deleted file mode 100644
index b31f1a1985..0000000000
--- a/OpenRA.Mods.Common/Traits/Render/WithBuildingExplosion.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-#region Copyright & License Information
-/*
- * Copyright 2007-2016 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 OpenRA.Effects;
-using OpenRA.Mods.Common.Effects;
-using OpenRA.Traits;
-
-namespace OpenRA.Mods.Common.Traits.Render
-{
- [Desc("Display explosions over the building footprint when it is destroyed.")]
- class WithBuildingExplosionInfo : ITraitInfo, Requires
- {
- [Desc("'Image' where Sequences are looked up.")]
- public readonly string Image = "explosion";
-
- [Desc("Explosion sequence names to use.")]
- [SequenceReference("Image")] public readonly string[] Sequences = { "building" };
-
- [Desc("Delay the explosions by this many ticks.")]
- public readonly int Delay = 0;
-
- [Desc("Custom palette name.")]
- [PaletteReference] public readonly string Palette = "effect";
-
- public object Create(ActorInitializer init) { return new WithBuildingExplosion(init.Self, this); }
- }
-
- class WithBuildingExplosion : INotifyKilled
- {
- readonly WithBuildingExplosionInfo info;
- readonly BuildingInfo buildingInfo;
-
- public WithBuildingExplosion(Actor self, WithBuildingExplosionInfo info)
- {
- this.info = info;
- buildingInfo = self.Info.TraitInfo();
- }
-
- public void Killed(Actor self, AttackInfo e)
- {
- var cells = FootprintUtils.UnpathableTiles(self.Info.Name, buildingInfo, self.Location);
-
- if (info.Delay > 0)
- self.World.AddFrameEndTask(w => w.Add(new DelayedAction(info.Delay, () => SpawnExplosions(self.World, cells))));
- else
- SpawnExplosions(self.World, cells);
- }
-
- void SpawnExplosions(World world, IEnumerable cells)
- {
- foreach (var c in cells)
- world.AddFrameEndTask(w => w.Add(new SpriteEffect(w.Map.CenterOfCell(c), w, info.Image, info.Sequences.Random(w.SharedRandom), info.Palette)));
- }
- }
-}
diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs
index 405ba38190..9a003670d4 100644
--- a/OpenRA.Mods.Common/TraitsInterfaces.cs
+++ b/OpenRA.Mods.Common/TraitsInterfaces.cs
@@ -19,6 +19,8 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
+ public enum VisibilityType { Footprint, CenterPosition, GroundPosition }
+
public enum AttackDelayType { Preparation, Attack }
public interface IQuantizeBodyOrientationInfo : ITraitInfo
diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
index 35d2495410..80c360ea8f 100644
--- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
+++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
@@ -542,6 +542,19 @@ namespace OpenRA.Mods.Common.UtilityCommands
RenameNodeKey(node, "LegacyBridgeLayer");
}
+ // Removed WithBuildingExplosion
+ if (engineVersion < 20161210)
+ {
+ if (node.Key == "WithBuildingExplosion")
+ {
+ node.Value.Nodes.Add(new MiniYamlNode("Type", "Footprint"));
+ node.Value.Nodes.Add(new MiniYamlNode("Weapon", "UnitExplodeSmall"));
+ node.Key = "Explodes";
+ Console.WriteLine("The trait WithBuildingExplosion has been removed and superseded by additional 'Explodes' functionality.");
+ Console.WriteLine("If you need a delayed building explosion, use 'Explodes' with 'Type: Footprint' and a cosmetic weapon with warhead delay.");
+ }
+ }
+
UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
}
diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml
index 79efc71355..f202f1c81b 100644
--- a/mods/cnc/rules/defaults.yaml
+++ b/mods/cnc/rules/defaults.yaml
@@ -563,9 +563,10 @@
DamagedSounds: xplos.aud
DestroyedSounds: crumble.aud
WithSpriteBody:
- WithBuildingExplosion:
- Sequences: building, building_napalm, med_frag, poof, small_building
- Delay: 1
+ Explodes:
+ Type: Footprint
+ Weapon: BuildingExplode
+ EmptyWeapon: BuildingExplode
CaptureNotification:
Notification: BuildingCaptured
NewOwnerVoice: no
@@ -650,7 +651,7 @@
-SelectionDecorations:
Tooltip:
GenericName: Field
- -WithBuildingExplosion:
+ -Explodes:
-Targetable:
-Demolishable:
RenderSprites:
diff --git a/mods/cnc/weapons/explosions.yaml b/mods/cnc/weapons/explosions.yaml
index 8de9366c31..54680def37 100644
--- a/mods/cnc/weapons/explosions.yaml
+++ b/mods/cnc/weapons/explosions.yaml
@@ -81,6 +81,14 @@ GrenadierExplode:
Warhead@3Smu: LeaveSmudge
SmudgeType: Crater
+BuildingExplode:
+ Warhead@1Eff: CreateEffect
+ Explosions: building, building_napalm, med_frag, poof, small_building
+ Delay: 1
+ Warhead@2Smu: LeaveSmudge
+ SmudgeType: Crater
+ Delay: 1
+
Napalm.Crate:
Warhead@1Dam: SpreadDamage
Spread: 170
diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml
index 1c4a8846dc..18a7091b96 100644
--- a/mods/d2k/rules/defaults.yaml
+++ b/mods/d2k/rules/defaults.yaml
@@ -332,8 +332,10 @@
DamagedSounds: EXPLSML1.WAV
DestroyedSounds: EXPLHG1.WAV
WithSpriteBody:
- WithBuildingExplosion:
- Sequences: building, self_destruct, large_explosion
+ Explodes:
+ Type: Footprint
+ Weapon: BuildingExplode
+ EmptyWeapon: BuildingExplode
RepairableBuilding:
PlayerExperience: 25
EmitInfantryOnSell:
diff --git a/mods/d2k/weapons/other.yaml b/mods/d2k/weapons/other.yaml
index 5d000c5ca3..3d307effb1 100644
--- a/mods/d2k/weapons/other.yaml
+++ b/mods/d2k/weapons/other.yaml
@@ -186,6 +186,10 @@ UnitExplodeLarge:
Explosions: large_explosion
ImpactSounds: EXPLLG2.WAV
+BuildingExplode:
+ Warhead@1Eff: CreateEffect
+ Explosions: building, self_destruct, large_explosion
+
grenade:
ReloadDelay: 50
Range: 4c0
diff --git a/mods/ra/rules/civilian.yaml b/mods/ra/rules/civilian.yaml
index cb8f2da866..ddad7f75cf 100644
--- a/mods/ra/rules/civilian.yaml
+++ b/mods/ra/rules/civilian.yaml
@@ -106,8 +106,6 @@ HOSP:
WithDeathAnimation:
DeathSequence: dead
UseDeathTypeSuffix: false
- WithBuildingExplosion:
- Delay: 1
ProvidesPrerequisite@buildingname:
GpsDot:
String: Hospital
@@ -330,8 +328,6 @@ MISS:
WithDeathAnimation:
DeathSequence: dead
UseDeathTypeSuffix: false
- WithBuildingExplosion:
- Delay: 1
ProvidesPrerequisite@buildingname:
BIO:
@@ -349,8 +345,6 @@ BIO:
WithDeathAnimation:
DeathSequence: dead
UseDeathTypeSuffix: false
- WithBuildingExplosion:
- Delay: 1
ProvidesPrerequisite@buildingname:
GpsDot:
String: Biohazard
diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml
index f6347c96af..13b5c8d31e 100644
--- a/mods/ra/rules/defaults.yaml
+++ b/mods/ra/rules/defaults.yaml
@@ -494,8 +494,10 @@
DamagedSounds: kaboom1.aud
DestroyedSounds: kaboom22.aud
WithSpriteBody:
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct, large_napalm
+ Explodes:
+ Type: Footprint
+ Weapon: BuildingExplode
+ EmptyWeapon: BuildingExplode
CaptureNotification:
ShakeOnDeath:
ProximityCaptor:
@@ -546,6 +548,9 @@
-AcceptsSupplies:
DrawLineToTarget:
RenderRangeCircle:
+ Explodes:
+ Weapon: SmallBuildingExplode
+ EmptyWeapon: SmallBuildingExplode
^Wall:
Inherits@1: ^ExistsInWorld
diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml
index d485a486c2..b16ba50ff3 100644
--- a/mods/ra/rules/structures.yaml
+++ b/mods/ra/rules/structures.yaml
@@ -84,8 +84,9 @@ GAP:
Amount: -60
MustBeDestroyed:
RequiredForShortGame: false
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
+ Explodes:
+ Weapon: SmallBuildingExplode
+ EmptyWeapon: SmallBuildingExplode
SPEN:
Inherits: ^Building
@@ -434,8 +435,6 @@ TSLA:
DetectCloaked:
Range: 8c0
ProvidesPrerequisite@buildingname:
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
AGUN:
Inherits: ^Defense
@@ -482,8 +481,6 @@ AGUN:
Amount: -50
DetectCloaked:
Range: 6c0
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
BodyOrientation:
UseClassicFacingFudge: True
@@ -566,8 +563,6 @@ PBOX:
Amount: -15
DetectCloaked:
Range: 6c0
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
HBOX:
Inherits: ^Defense
@@ -614,8 +609,6 @@ HBOX:
Power:
Amount: -15
-MustBeDestroyed:
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
GUN:
Inherits: ^Defense
@@ -652,8 +645,6 @@ GUN:
Amount: -40
DetectCloaked:
Range: 7c0
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
BodyOrientation:
UseClassicFacingFudge: True
@@ -692,8 +683,9 @@ FTUR:
DetectCloaked:
Range: 6c0
ProvidesPrerequisite@buildingname:
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
+ Explodes:
+ Weapon: BuildingExplode
+ EmptyWeapon: BuildingExplode
SAM:
Inherits: ^Defense
@@ -950,8 +942,6 @@ FACT:
WithDeathAnimation:
DeathSequence: dead
UseDeathTypeSuffix: false
- WithBuildingExplosion:
- Delay: 1
ProvidesPrerequisite@buildingname:
PROC:
@@ -1004,8 +994,6 @@ PROC:
WithDeathAnimation:
DeathSequence: dead
UseDeathTypeSuffix: false
- WithBuildingExplosion:
- Delay: 1
ProvidesPrerequisite@buildingname:
SILO:
@@ -1036,8 +1024,9 @@ SILO:
-EmitInfantryOnSell:
Power:
Amount: -10
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
+ Explodes:
+ Weapon: SmallBuildingExplode
+ EmptyWeapon: SmallBuildingExplode
HPAD:
Inherits: ^Building
@@ -1267,8 +1256,6 @@ POWR:
WithDeathAnimation:
DeathSequence: dead
UseDeathTypeSuffix: false
- WithBuildingExplosion:
- Delay: 1
APWR:
Inherits: ^Building
@@ -1308,8 +1295,6 @@ APWR:
WithDeathAnimation:
DeathSequence: dead
UseDeathTypeSuffix: false
- WithBuildingExplosion:
- Delay: 1
STEK:
Inherits: ^ScienceBuilding
@@ -1448,8 +1433,6 @@ KENN:
Power:
Amount: -10
ProvidesPrerequisite@buildingname:
- WithBuildingExplosion:
- Sequences: building, building_napalm, large_explosion, self_destruct
WithDecoration@primary:
RequiresSelection: true
Image: pips
diff --git a/mods/ra/weapons/explosions.yaml b/mods/ra/weapons/explosions.yaml
index 16a35867ce..153aaf2bfc 100644
--- a/mods/ra/weapons/explosions.yaml
+++ b/mods/ra/weapons/explosions.yaml
@@ -212,12 +212,16 @@ UnitExplodeSmall:
SmudgeType: Crater
InvalidTargets: Structure, Wall, Trees
-# Used to panic civilians which are emitted from a killed CivBuilding
CivBuildingExplosion:
- Warhead@1Dam: SpreadDamage
+ Warhead@1Dam: SpreadDamage # Used to panic civilians which are emitted from a killed CivBuilding
Spread: 64
Damage: 1
Delay: 1
+ Warhead@2Eff: CreateEffect
+ Explosions: building, building_napalm, large_explosion, self_destruct
+ Warhead@3Smu: LeaveSmudge
+ SmudgeType: Crater
+ InvalidTargets: Wall, Trees
ArtilleryExplode:
Warhead@1Dam: SpreadDamage
@@ -245,6 +249,20 @@ V2Explode:
Inherits: SCUD
-Report:
+BuildingExplode:
+ Warhead@1Eff: CreateEffect
+ Explosions: building, building_napalm, large_explosion, self_destruct, large_napalm
+ Warhead@2Smu: LeaveSmudge
+ SmudgeType: Crater
+ InvalidTargets: Wall, Trees
+
+SmallBuildingExplode:
+ Warhead@1Eff: CreateEffect
+ Explosions: building, building_napalm, large_explosion, self_destruct
+ Warhead@2Smu: LeaveSmudge
+ SmudgeType: Crater
+ InvalidTargets: Wall, Trees
+
BarrelExplode:
Warhead@1Dam: SpreadDamage
Spread: 426
diff --git a/mods/ts/rules/bridges.yaml b/mods/ts/rules/bridges.yaml
index 98cc31f891..4eb711f46a 100644
--- a/mods/ts/rules/bridges.yaml
+++ b/mods/ts/rules/bridges.yaml
@@ -14,6 +14,7 @@ CABHUT:
TargetTypes: C4
-SelectionDecorations:
-Demolishable:
+ -Explodes:
^LowBridgeRamp:
AlwaysVisible:
diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml
index 29ac068747..92e305909a 100644
--- a/mods/ts/rules/defaults.yaml
+++ b/mods/ts/rules/defaults.yaml
@@ -126,8 +126,10 @@
DamagedSounds: expnew01.aud
DestroyedSounds: crmble2.aud
WithSpriteBody:
- WithBuildingExplosion:
- Sequences: building, large_bang, large_brnl, verylarge_clsn, large_tumu
+ Explodes:
+ Weapon: BuildingExplosions
+ EmptyWeapon: BuildingExplosions
+ Type: Footprint
EngineerRepairable:
ShakeOnDeath:
AcceptsSupplies:
diff --git a/mods/ts/rules/shared-structures.yaml b/mods/ts/rules/shared-structures.yaml
index 75feddaa7a..51a3b9d09a 100644
--- a/mods/ts/rules/shared-structures.yaml
+++ b/mods/ts/rules/shared-structures.yaml
@@ -107,6 +107,8 @@ PROC:
FactionImages:
gdi: proc.gdi
nod: proc.nod
+ Explodes:
+ Weapon: TiberiumExplosion
GASILO:
Inherits: ^Building
@@ -150,6 +152,8 @@ GASILO:
Amount: -10
SelectionDecorations:
VisualBounds: 80, 48, -5, 0
+ Explodes:
+ Weapon: TiberiumExplosion
ANYPOWER:
AlwaysVisible:
diff --git a/mods/ts/weapons/explosions.yaml b/mods/ts/weapons/explosions.yaml
index 3b8c89ee11..3691a5c241 100644
--- a/mods/ts/weapons/explosions.yaml
+++ b/mods/ts/weapons/explosions.yaml
@@ -34,6 +34,13 @@ UnitExplodeSmall:
SmudgeType: SmallCrater
InvalidTargets: Building, Wall
+BuildingExplosions:
+ Warhead@1Eff: CreateEffect
+ Explosions: building, large_bang, large_brnl, verylarge_clsn, large_tumu
+ ExplosionPalette: effectalpha75
+ Warhead@2Smu: LeaveSmudge
+ SmudgeType: MediumCrater
+
CyborgExplode:
Warhead@1Eff: CreateEffect
Explosions: medium_bang