Files
OpenRA/OpenRA.Mods.Common/Traits/Explodes.cs
reaperrr c205afcf4d Add descriptions and LoadedChance to Explodes trait
'Chance' only allows to control whether the actor explodes at all.
'LoadedChance' allows to control how likely the actor will explode violently using Weapon, and otherwise falls back to EmptyWeapon.
2015-07-30 21:23:55 +02:00

76 lines
2.4 KiB
C#

#region Copyright & License Information
/*
* Copyright 2007-2015 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. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Mods.Common.Warheads;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("This actor explodes when killed.")]
public class ExplodesInfo : ITraitInfo
{
[WeaponReference, Desc("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.")]
public readonly string EmptyWeapon = "UnitExplode";
[Desc("Chance that the explosion will use Weapon if the actor has ammo/payload.")]
public readonly int LoadedChance = 100;
[Desc("Chance that this actor will explode at all.")]
public readonly int Chance = 100;
[Desc("DeathType(s) to apply upon explosion.")]
public readonly string[] DeathType = null;
public object Create(ActorInitializer init) { return new Explodes(this); }
}
public class Explodes : INotifyKilled
{
readonly ExplodesInfo info;
public Explodes(ExplodesInfo info) { this.info = info; }
public void Killed(Actor self, AttackInfo e)
{
if (!self.IsInWorld)
return;
if (self.World.SharedRandom.Next(100) > info.Chance)
return;
var warhead = e.Warhead as DamageWarhead;
if (info.DeathType != null && warhead != null && !info.DeathType.Intersect(warhead.DamageTypes).Any())
return;
var weaponName = ChooseWeaponForExplosion(self);
if (weaponName == null)
return;
var weapon = e.Attacker.World.Map.Rules.Weapons[weaponName.ToLowerInvariant()];
if (weapon.Report != null && weapon.Report.Any())
Sound.Play(weapon.Report.Random(e.Attacker.World.SharedRandom), self.CenterPosition);
// Use .FromPos since this actor is killed. Cannot use Target.FromActor
weapon.Impact(Target.FromPos(self.CenterPosition), e.Attacker, Enumerable.Empty<int>());
}
string ChooseWeaponForExplosion(Actor self)
{
var shouldExplode = self.TraitsImplementing<IExplodeModifier>().All(a => a.ShouldExplode(self));
var useFullExplosion = self.World.SharedRandom.Next(100) <= info.LoadedChance;
return (shouldExplode && useFullExplosion) ? info.Weapon : info.EmptyWeapon;
}
}
}