Skip to content

Commit

Permalink
Radioactivity code migrated to mod DLL.
Browse files Browse the repository at this point in the history
  • Loading branch information
jdj committed Jan 24, 2017
1 parent 25c3fd9 commit c1a416b
Show file tree
Hide file tree
Showing 7 changed files with 496 additions and 3 deletions.
5 changes: 4 additions & 1 deletion OpenRA.Mods.yupgi_alert/OpenRA.Mods.yupgi_alert.csproj
Expand Up @@ -71,11 +71,15 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Traits\DamagedByRadioactivity.cs" />
<Compile Include="Traits\DeployToTimedUpgrade.cs" />
<Compile Include="Traits\ExplodeWeapon.cs" />
<Compile Include="Traits\StructureChrono.cs" />
<Compile Include="Traits\SupportPowers\AttackOrderPower.cs" />
<Compile Include="Traits\Warheads\CreateRadioactivityWarhead.cs" />
<Compile Include="Traits\Warheads\FireClusterWarhead.cs" />
<Compile Include="Traits\Warheads\WarheadAS.cs" />
<Compile Include="Traits\World\RadioactivityLayer.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Activities\" />
Expand All @@ -86,7 +90,6 @@
<Folder Include="Traits\Conditions\" />
<Folder Include="Traits\Render\" />
<Folder Include="Traits\Widgets\" />
<Folder Include="Traits\World\" />
<Folder Include="UtilityCommands\" />
</ItemGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
69 changes: 69 additions & 0 deletions OpenRA.Mods.yupgi_alert/Traits/DamagedByRadioactivity.cs
@@ -0,0 +1,69 @@
#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 System.Linq;
using OpenRA.GameRules;
using OpenRA.Traits;
using OpenRA.Mods.Common.Traits;

namespace OpenRA.Mods.yupgi_alert.Traits
{
[Desc("This actor receives damage from the given weapon when in radioactive area.")]
class DamagedByRadioactivityInfo : UpgradableTraitInfo, Requires<HealthInfo>
{
[Desc("Related to amount of damage received per DamageInterval ticks. (Damage = DamageCoeff * RadioactivityLevel")]
[FieldLoader.Require] public readonly float DamageCoeff = 0;

This comment has been minimized.

Copy link
@GraionDilach

GraionDilach Jan 30, 2017

Contributor

Float values should never be used in game code due to danger of being computed differently between computers. Use percentage values as integers.

This comment has been minimized.

Copy link
@forcecore

forcecore Jan 30, 2017

Owner

Ah, that's why I never saw float! Thank you, I'll take care of it.


[Desc("Delay between receiving damage.")]
public readonly int DamageInterval = 0;

[Desc("Apply the damage using these damagetypes.")]
public readonly HashSet<string> DamageTypes = new HashSet<string>();

public override object Create(ActorInitializer init) { return new DamagedByRadioactivity(init.Self, this); }
}

class DamagedByRadioactivity : UpgradableTrait<DamagedByRadioactivityInfo>, ITick, ISync
{
readonly Health health;
readonly RadioactivityLayer raLayer;

[Sync] int damageTicks;

public DamagedByRadioactivity(Actor self, DamagedByRadioactivityInfo info) : base(info)
{
health = self.Trait<Health>();
raLayer = self.World.WorldActor.Trait<RadioactivityLayer>();
}

public void Tick(Actor self)
{
if (IsTraitDisabled || --damageTicks > 0)
return;

// Prevents harming cargo.
if (!self.IsInWorld)
return;

var level = raLayer.GetLevel(self.Location);
if (level <= 0)
return;

float dmg = Info.DamageCoeff * level;
if (dmg < 1.0f)
dmg = 1.0f; // cos we will be rounding this as int.

self.InflictDamage(self.World.WorldActor, new Damage((int) dmg, Info.DamageTypes));
damageTicks = Info.DamageInterval;
}
}
}
2 changes: 1 addition & 1 deletion OpenRA.Mods.yupgi_alert/Traits/DeployToTimedUpgrade.cs
Expand Up @@ -25,7 +25,7 @@
using OpenRA.Mods.Common.Traits.Render;
using OpenRA.Traits;

namespace OpenRA.Mods.yupgi_alert.Traits
namespace OpenRA.Mods.AS.Traits
{
public class DeployToTimedUpgradeInfo : ITraitInfo, Requires<UpgradeManagerInfo>
{
Expand Down
107 changes: 107 additions & 0 deletions OpenRA.Mods.yupgi_alert/Traits/ExplodeWeapon.cs
@@ -0,0 +1,107 @@
#region Copyright & License Information
/*
* Copyright 2015- OpenRA.Mods.AS Developers (see AUTHORS)
* This file is a part of a third-party plugin for 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.GameRules;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;


// Remark:
// While I'm modding latest stable version,
// UpgradableTrait is renamed to ConditionalTrait in bleed version of OpenRA.

namespace OpenRA.Mods.AS.Traits
{
[Desc("Explodes a weapon at the actor's position when enabled."
+ "Reload/burstdelays are used as explosion intervals.")]
public class ExplodeWeaponInfo : UpgradableTraitInfo, IRulesetLoaded
{
[WeaponReference, FieldLoader.Require]
[Desc("Has to be defined in weapons.yaml as well.")]
public readonly string Weapon = null;

public readonly bool ResetReloadWhenEnabled = true;

public WeaponInfo WeaponInfo { get; private set; }

[Desc("Explosion offset relative to actor's position.")]
public readonly WVec LocalOffset = WVec.Zero;

public override object Create(ActorInitializer init) { return new ExplodeWeapon(init.Self, this); }

void IRulesetLoaded<ActorInfo>.RulesetLoaded(Ruleset rules, ActorInfo info)
{
WeaponInfo weaponInfo;

var weaponToLower = Weapon.ToLowerInvariant();
if (!rules.Weapons.TryGetValue(weaponToLower, out weaponInfo))
throw new YamlException("Weapons Ruleset does not contain an entry '{0}'".F(weaponToLower));

WeaponInfo = weaponInfo;
}
}

class ExplodeWeapon : UpgradableTrait<ExplodeWeaponInfo>, ITick
{
readonly ExplodeWeaponInfo info;
readonly WeaponInfo weapon;
readonly BodyOrientation body;

int fireDelay;
int burst;

public ExplodeWeapon(Actor self, ExplodeWeaponInfo info)
: base(info)
{
this.info = info;

weapon = info.WeaponInfo;
burst = weapon.Burst;
body = self.TraitOrDefault<BodyOrientation>();
}

void ITick.Tick(Actor self)
{
if (IsTraitDisabled)
return;

if (--fireDelay < 0)
{
var localoffset = body != null
? body.LocalToWorld(info.LocalOffset.Rotate(body.QuantizeOrientation(self, self.Orientation)))
: info.LocalOffset;

weapon.Impact(Target.FromPos(self.CenterPosition + localoffset), self,
self.TraitsImplementing<IFirepowerModifier>().Select(a => a.GetFirepowerModifier()).ToArray());

if (--burst > 0)
fireDelay = weapon.BurstDelay;
else
{
var modifiers = self.TraitsImplementing<IReloadModifier>()
.Select(m => m.GetReloadModifier());
fireDelay = Util.ApplyPercentageModifiers(weapon.ReloadDelay, modifiers);
burst = weapon.Burst;
}
}
}

protected override void UpgradeEnabled(Actor self)
{
if (info.ResetReloadWhenEnabled)
{
burst = weapon.Burst;
fireDelay = 0;
}
}
}
}
2 changes: 1 addition & 1 deletion OpenRA.Mods.yupgi_alert/Traits/StructureChrono.cs
Expand Up @@ -21,7 +21,7 @@
using OpenRA.Primitives;
using OpenRA.Mods.Common;

namespace OpenRA.Mods.RA.Traits
namespace OpenRA.Mods.yupgi_alert.Traits
{
class StructureChronoInfo : ITraitInfo
{
Expand Down
111 changes: 111 additions & 0 deletions OpenRA.Mods.yupgi_alert/Traits/Warheads/CreateRadioactivityWarhead.cs
@@ -0,0 +1,111 @@
#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.GameRules;
using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
using OpenRA.Mods.Common.Warheads;
using OpenRA.Mods.yupgi_alert.Traits;

namespace OpenRA.Mods.yupgi_alert.Warheads
{
public class CreateRadioactivityWarhead : DamageWarhead, IRulesetLoaded<WeaponInfo>
{
[Desc("Range between falloff steps, in cells")]
public readonly int Spread = 1;

[Desc("Radioactivity level percentage at each range step")]
public readonly int[] Falloff = { 100, 37, 14, 5, 0 };

// Since radioactivity level is accumulative, we pre-compute this var from Falloff. (Lookup table)
private int[] FalloffDifference;

[Desc("Ranges at which each Falloff step is defined (in cells). Overrides Spread.")]
public int[] Range = null;

[Desc("Radio activity level per shot (Sievert?)")]
public int Level = 32;

[Desc("Radio activity saturates at this level, by this weapon.")]
// this means if the cell is affected by other stronger radioactive weapon, the level can go past this value.
// For details, have a look at RadioactivityLayers.cs:IncreaseLevel()
public int MaxLevel = 128;

[Desc("Half-life of the RA level, from this weapon, in ticks.")]
public int HalfLife = 15;

public void RulesetLoaded(Ruleset rules, WeaponInfo info)
{
if (Range != null)
{
if (Range.Length != 1 && Range.Length != Falloff.Length)
throw new YamlException("Number of range values must be 1 or equal to the number of Falloff values.");

for (var i = 0; i < Range.Length - 1; i++)
if (Range[i] > Range[i + 1])
throw new YamlException("Range values must be specified in an increasing order.");
}
else
Range = Exts.MakeArray(Falloff.Length, i => i * Spread);

// Compute FalloffDifference LUT.
FalloffDifference = new int[Falloff.Length];
for(var i = 0; i < FalloffDifference.Length-1; i++)
{
// with Falloff = { 100, 37, 14, 5, 0 }, you get
// { 63, 23, 9, 5, 0 }
FalloffDifference[i] = Falloff[i] - Falloff[i + 1];
}
FalloffDifference[FalloffDifference.Length - 1] = 0;
}

public override void DoImpact(WPos pos, Actor firedBy, IEnumerable<int> damageModifiers)
{
var world = firedBy.World;
var resLayer = world.WorldActor.Trait<RadioactivityLayer>();

if (world.LocalPlayer != null)
{
var devMode = world.LocalPlayer.PlayerActor.TraitOrDefault<DeveloperMode>();
if (devMode != null && devMode.ShowCombatGeometry)
{
WDist[] rng = Exts.MakeArray(Range.Length, i => WDist.FromCells(Range[i]));
world.WorldActor.Trait<WarheadDebugOverlay>().AddImpact(pos, rng, DebugOverlayColor);
}
}

// Accumulate radiation
var targetTile = world.Map.CellContaining(pos);
for (var i = Range.Length-1; i >=0; i--)
{
// Find affected cells, from outer Range down to inner range.
var affectedCells = world.Map.FindTilesInAnnulus(targetTile, 0, Range[i]);

var ra_layer = world.WorldActor.Trait<RadioactivityLayer>();

foreach (var cell in affectedCells)
{
var foff = FalloffDifference[i];
IncreaseRALevel(cell, foff, ra_layer);
}
}
}

// Increase radiation level of the cell at given pos, considering falloff
void IncreaseRALevel(CPos pos, int foff, RadioactivityLayer ra_layer)
{
// increase RA level of the cell by this amount.
int level = this.Level * foff / 100;
ra_layer.IncreaseLevel(pos, level, HalfLife, MaxLevel);
}
}
}

0 comments on commit c1a416b

Please sign in to comment.