Meat kudzu (from anomoly) more killable, telegraphs better (#16107)
@@ -11,9 +11,6 @@ public sealed class GrowingKudzuComponent : Component
|
|||||||
[DataField("growthLevel")]
|
[DataField("growthLevel")]
|
||||||
public int GrowthLevel = 1;
|
public int GrowthLevel = 1;
|
||||||
|
|
||||||
[DataField("growthTickChance")]
|
|
||||||
public float GrowthTickChance = 1f;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The next time kudzu will try to tick its growth level.
|
/// The next time kudzu will try to tick its growth level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Content.Shared.Damage;
|
||||||
|
|
||||||
namespace Content.Server.Spreader;
|
namespace Content.Server.Spreader;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -11,4 +13,26 @@ public sealed class KudzuComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("spreadChance")]
|
[DataField("spreadChance")]
|
||||||
public float SpreadChance = 1f;
|
public float SpreadChance = 1f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much damage is required to reduce growth level
|
||||||
|
/// </summary>
|
||||||
|
[DataField("growthHealth")]
|
||||||
|
public float GrowthHealth = 10.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much damage is required to prevent growth
|
||||||
|
/// </summary>
|
||||||
|
[DataField("growthBlock")]
|
||||||
|
public float GrowthBlock = 20.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much the kudzu heals each tick
|
||||||
|
/// </summary>
|
||||||
|
[DataField("damageRecovery")]
|
||||||
|
public DamageSpecifier? DamageRecovery = null;
|
||||||
|
|
||||||
|
[DataField("growthTickChance")]
|
||||||
|
public float GrowthTickChance = 1f;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Spreader;
|
using Content.Shared.Spreader;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -9,6 +10,7 @@ public sealed class KudzuSystem : EntitySystem
|
|||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||||
|
|
||||||
private const string KudzuGroup = "kudzu";
|
private const string KudzuGroup = "kudzu";
|
||||||
|
|
||||||
@@ -19,6 +21,28 @@ public sealed class KudzuSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<KudzuComponent, SpreadNeighborsEvent>(OnKudzuSpread);
|
SubscribeLocalEvent<KudzuComponent, SpreadNeighborsEvent>(OnKudzuSpread);
|
||||||
SubscribeLocalEvent<GrowingKudzuComponent, EntityUnpausedEvent>(OnKudzuUnpaused);
|
SubscribeLocalEvent<GrowingKudzuComponent, EntityUnpausedEvent>(OnKudzuUnpaused);
|
||||||
SubscribeLocalEvent<SpreadGroupUpdateRate>(OnKudzuUpdateRate);
|
SubscribeLocalEvent<SpreadGroupUpdateRate>(OnKudzuUpdateRate);
|
||||||
|
SubscribeLocalEvent<KudzuComponent, DamageChangedEvent>(OnDamageChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDamageChanged(EntityUid uid, KudzuComponent component, DamageChangedEvent args)
|
||||||
|
{
|
||||||
|
// Every time we take any damage, we reduce growth depending on all damage over the growth impact
|
||||||
|
// So the kudzu gets slower growing the more it is hurt.
|
||||||
|
int growthDamage = (int) (args.Damageable.TotalDamage / component.GrowthHealth);
|
||||||
|
if (growthDamage > 0)
|
||||||
|
{
|
||||||
|
GrowingKudzuComponent? growing;
|
||||||
|
if (!TryComp<GrowingKudzuComponent>(uid, out growing))
|
||||||
|
{
|
||||||
|
growing = AddComp<GrowingKudzuComponent>(uid);
|
||||||
|
growing.GrowthLevel = 3;
|
||||||
|
}
|
||||||
|
growing.GrowthLevel = Math.Max(1, growing.GrowthLevel - growthDamage);
|
||||||
|
if (EntityManager.TryGetComponent<AppearanceComponent>(uid, out var appearance))
|
||||||
|
{
|
||||||
|
_appearance.SetData(uid, KudzuVisuals.GrowthLevel, growing.GrowthLevel, appearance);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnKudzuSpread(EntityUid uid, KudzuComponent component, ref SpreadNeighborsEvent args)
|
private void OnKudzuSpread(EntityUid uid, KudzuComponent component, ref SpreadNeighborsEvent args)
|
||||||
@@ -83,32 +107,55 @@ public sealed class KudzuSystem : EntitySystem
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
var query = EntityQueryEnumerator<GrowingKudzuComponent, AppearanceComponent>();
|
var query = EntityQueryEnumerator<GrowingKudzuComponent, KudzuComponent>();
|
||||||
var curTime = _timing.CurTime;
|
var curTime = _timing.CurTime;
|
||||||
|
|
||||||
while (query.MoveNext(out var uid, out var kudzu, out var appearance))
|
while (query.MoveNext(out var uid, out var grow, out var kudzu))
|
||||||
{
|
{
|
||||||
if (kudzu.NextTick > curTime)
|
if (grow.NextTick > curTime)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
kudzu.NextTick = curTime + TimeSpan.FromSeconds(0.5);
|
grow.NextTick = curTime + TimeSpan.FromSeconds(0.5);
|
||||||
|
|
||||||
if (!_robustRandom.Prob(kudzu.GrowthTickChance))
|
if (!_robustRandom.Prob(kudzu.GrowthTickChance))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
kudzu.GrowthLevel += 1;
|
if (TryComp<DamageableComponent>(uid, out var damage))
|
||||||
|
{
|
||||||
|
if (damage.TotalDamage > 1.0)
|
||||||
|
{
|
||||||
|
if (kudzu.DamageRecovery != null)
|
||||||
|
{
|
||||||
|
// This kudzu features healing, so Gradually heal
|
||||||
|
_damageable.TryChangeDamage(uid, kudzu.DamageRecovery, true);
|
||||||
|
}
|
||||||
|
if (damage.TotalDamage >= kudzu.GrowthBlock)
|
||||||
|
{
|
||||||
|
// Don't grow when quite damaged
|
||||||
|
if (_robustRandom.Prob(0.95f))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (kudzu.GrowthLevel >= 3)
|
grow.GrowthLevel += 1;
|
||||||
|
|
||||||
|
if (grow.GrowthLevel >= 3)
|
||||||
{
|
{
|
||||||
// why cache when you can simply cease to be? Also saves a bit of memory/time.
|
// why cache when you can simply cease to be? Also saves a bit of memory/time.
|
||||||
RemCompDeferred<GrowingKudzuComponent>(uid);
|
RemCompDeferred<GrowingKudzuComponent>(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
_appearance.SetData(uid, KudzuVisuals.GrowthLevel, kudzu.GrowthLevel, appearance);
|
if (EntityManager.TryGetComponent<AppearanceComponent>(uid, out var appearance))
|
||||||
|
{
|
||||||
|
_appearance.SetData(uid, KudzuVisuals.GrowthLevel, grow.GrowthLevel, appearance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,8 +70,8 @@
|
|||||||
Heat: 10
|
Heat: 10
|
||||||
- type: AtmosExposed
|
- type: AtmosExposed
|
||||||
- type: Kudzu
|
- type: Kudzu
|
||||||
- type: GrowingKudzu
|
|
||||||
growthTickChance: 0.3
|
growthTickChance: 0.3
|
||||||
|
- type: GrowingKudzu
|
||||||
- type: SlowContacts
|
- type: SlowContacts
|
||||||
walkSpeedModifier: 0.2
|
walkSpeedModifier: 0.2
|
||||||
sprintSpeedModifier: 0.2
|
sprintSpeedModifier: 0.2
|
||||||
@@ -119,10 +119,11 @@
|
|||||||
"/Audio/Weapons/slash.ogg"
|
"/Audio/Weapons/slash.ogg"
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Misc/fleshkudzu.rsi
|
sprite: Objects/Misc/fleshkudzu.rsi
|
||||||
state: base
|
state: kudzu_11
|
||||||
drawdepth: Overdoors
|
drawdepth: Overdoors
|
||||||
netsync: false
|
netsync: false
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
|
- type: KudzuVisuals
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
- type: Transform
|
- type: Transform
|
||||||
anchored: true
|
anchored: true
|
||||||
@@ -141,7 +142,7 @@
|
|||||||
thresholds:
|
thresholds:
|
||||||
- trigger:
|
- trigger:
|
||||||
!type:DamageTrigger
|
!type:DamageTrigger
|
||||||
damage: 10
|
damage: 40
|
||||||
behaviors:
|
behaviors:
|
||||||
- !type:DoActsBehavior
|
- !type:DoActsBehavior
|
||||||
acts: [ "Destruction" ]
|
acts: [ "Destruction" ]
|
||||||
@@ -154,6 +155,33 @@
|
|||||||
tags:
|
tags:
|
||||||
- Flesh
|
- Flesh
|
||||||
- type: Kudzu
|
- type: Kudzu
|
||||||
|
growthTickChance: 0.3
|
||||||
|
# Heals each time it manages to do a growth tick:
|
||||||
|
damageRecovery:
|
||||||
|
types:
|
||||||
|
Slash: -0.5
|
||||||
|
Heat: -1.0
|
||||||
|
Cold: -1.0
|
||||||
|
Blunt: -0.5 # Needs to be balanced (approx 3x) with vacuum damage to stall but not kill Kudzu
|
||||||
|
- type: Temperature
|
||||||
|
heatDamage:
|
||||||
|
types:
|
||||||
|
Heat: 10
|
||||||
|
coldDamage:
|
||||||
|
types:
|
||||||
|
Cold: 5 #per second, scales with temperature & other constants
|
||||||
|
- type: Barotrauma
|
||||||
|
damage:
|
||||||
|
types:
|
||||||
|
Blunt: 0.15 #per second, scales with pressure and other constants.
|
||||||
|
- type: Flammable
|
||||||
|
fireSpread: true
|
||||||
|
damage:
|
||||||
|
types:
|
||||||
|
Heat: 1
|
||||||
|
- type: GrowingKudzu
|
||||||
|
growthTickChance: 0.3
|
||||||
|
- type: AtmosExposed
|
||||||
- type: EdgeSpreader
|
- type: EdgeSpreader
|
||||||
- type: NodeContainer
|
- type: NodeContainer
|
||||||
nodes:
|
nodes:
|
||||||
@@ -174,3 +202,11 @@
|
|||||||
reagents:
|
reagents:
|
||||||
- ReagentId: Protein
|
- ReagentId: Protein
|
||||||
Quantity: 2
|
Quantity: 2
|
||||||
|
- type: Respirator
|
||||||
|
damage:
|
||||||
|
types:
|
||||||
|
Asphyxiation: 0.25
|
||||||
|
damageRecovery:
|
||||||
|
types:
|
||||||
|
Asphyxiation: -0.25
|
||||||
|
|
||||||
|
|||||||
BIN
Resources/Textures/Objects/Misc/fleshkudzu.rsi/kudzu_11.png
Normal file
|
After Width: | Height: | Size: 468 B |
BIN
Resources/Textures/Objects/Misc/fleshkudzu.rsi/kudzu_12.png
Normal file
|
After Width: | Height: | Size: 468 B |
BIN
Resources/Textures/Objects/Misc/fleshkudzu.rsi/kudzu_13.png
Normal file
|
After Width: | Height: | Size: 468 B |
BIN
Resources/Textures/Objects/Misc/fleshkudzu.rsi/kudzu_21.png
Normal file
|
After Width: | Height: | Size: 491 B |
BIN
Resources/Textures/Objects/Misc/fleshkudzu.rsi/kudzu_22.png
Normal file
|
After Width: | Height: | Size: 491 B |
BIN
Resources/Textures/Objects/Misc/fleshkudzu.rsi/kudzu_23.png
Normal file
|
After Width: | Height: | Size: 491 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
BIN
Resources/Textures/Objects/Misc/fleshkudzu.rsi/kudzu_32.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
Resources/Textures/Objects/Misc/fleshkudzu.rsi/kudzu_33.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
@@ -1,14 +1,38 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"copyright": "Created by EmoGarbage404 (github) for space-station-14",
|
"copyright": "Created by EmoGarbage404 & tom-leys (github) for space-station-14",
|
||||||
"size": {
|
"size": {
|
||||||
"x": 32,
|
"x": 32,
|
||||||
"y": 32
|
"y": 32
|
||||||
},
|
},
|
||||||
"states": [
|
"states": [
|
||||||
{
|
{
|
||||||
"name": "base"
|
"name": "kudzu_33"
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"name": "kudzu_32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kudzu_31"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kudzu_23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kudzu_22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kudzu_21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kudzu_13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kudzu_12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kudzu_11"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||