diff --git a/README.md b/README.md index c562503..160760c 100644 --- a/README.md +++ b/README.md @@ -11,5 +11,5 @@ extract Devil's Dust from Devilstrand. I'll leave the rest for you to discover. # Acknowledgement This is my first mod for RimWorld and it was created in about a week, not least thanks to the -kind people in [#rimworld-modding](https://discord.gg/0kEwljX6FiCur2uN). Especially I want to thank erdelf, NotFood, Mehni, ChJees, spdskatr, Swenzi, Xen, Why_is_that, Alistaire and probably other whom I forgot. So thank you. Without this wouldn't have been done in so little time. +kind people in [#rimworld-modding](https://discord.gg/0kEwljX6FiCur2uN). Especially I want to thank erdelf, NotFood, Mehni, ChJees, spdskatr, Swenzi, Xen, Why_is_that, Alistaire and probably other whom I forgot. So thank you. Without this wouldn't have been done in so little time. And also thank you to Marnador for his RimWorld Font. diff --git a/Source/CompExplosive.cs b/Source/CompExplosive.cs new file mode 100644 index 0000000..e8536f3 --- /dev/null +++ b/Source/CompExplosive.cs @@ -0,0 +1,176 @@ +using System; +using UnityEngine; +using Verse; +using Verse.Sound; +using RimWorld; + +namespace Autarky +{ + public class CompExplosive : ThingComp + { + // + // Fields + // + public bool wickStarted; + + protected Sustainer wickSoundSustainer; + + public bool detonated; + + private Thing instigator; + + protected int wickTicksLeft; + + // + // Properties + // + private bool CanEverExplodeFromDamage { + get { + if (this.Props.chanceNeverExplodeFromDamage < 1E-05f) { + return true; + } + Rand.PushState (); + Rand.Seed = this.parent.thingIDNumber.GetHashCode (); + bool result = Rand.Value < this.Props.chanceNeverExplodeFromDamage; + Rand.PopState (); + return result; + } + } + + public CompProperties_Explosive Props { + get { + return (CompProperties_Explosive)this.props; + } + } + + protected int StartWickThreshold { + get { + return Mathf.RoundToInt (this.Props.startWickHitPointsPercent * (float)this.parent.MaxHitPoints); + } + } + + // + // Methods + // + public override void CompTick () + { + if (this.wickStarted) { + if (this.wickSoundSustainer == null) { + this.StartWickSustainer (); + } + else { + this.wickSoundSustainer.Maintain (); + } + this.wickTicksLeft--; + if (this.wickTicksLeft <= 0) { + this.Detonate (this.parent.MapHeld); + } + } + } + + protected void Detonate (Map map) + { + if (this.detonated) { + return; + } + this.detonated = true; + if (!this.parent.SpawnedOrAnyParentSpawned) { + return; + } + if (map == null) { + Log.Warning ("Tried to detonate CompExplosive in a null map."); + return; + } + CompProperties_Explosive props = this.Props; + float num = props.explosiveRadius; + if (this.parent.stackCount > 1 && props.explosiveExpandPerStackcount > 0f) { + num += Mathf.Sqrt ((float)(this.parent.stackCount - 1) * props.explosiveExpandPerStackcount); + } + if (props.explosionEffect != null) { + Effecter effecter = props.explosionEffect.Spawn (); + effecter.Trigger (new TargetInfo (this.parent.PositionHeld, map, false), new TargetInfo (this.parent.PositionHeld, map, false)); + effecter.Cleanup (); + } + ThingDef postExplosionSpawnThingDef = props.postExplosionSpawnThingDef; + float postExplosionSpawnChance = props.postExplosionSpawnChance; + int postExplosionSpawnThingCount = props.postExplosionSpawnThingCount; + GenExplosion.DoExplosion (this.parent.PositionHeld, map, num, props.explosiveDamageType, this.instigator ?? this.parent, null, null, null, postExplosionSpawnThingDef, postExplosionSpawnChance, postExplosionSpawnThingCount, props.applyDamageToExplosionCellsNeighbors, props.preExplosionSpawnThingDef, props.preExplosionSpawnChance, props.preExplosionSpawnThingCount); + if (!this.parent.Destroyed) + { + this.parent.Kill(null); + } + } + + public override void PostDraw () + { + if (this.wickStarted) { + this.parent.Map.overlayDrawer.DrawOverlay (this.parent, OverlayTypes.BurningWick); + } + } + + public override void PostExposeData () + { + base.PostExposeData (); + Scribe_References.Look (ref this.instigator, "instigator", false); + Scribe_Values.Look (ref this.wickStarted, "wickStarted", false, false); + Scribe_Values.Look (ref this.wickTicksLeft, "wickTicksLeft", 0, false); + Scribe_Values.Look (ref this.detonated, "detonated", false, false); + } + + public override void PostPostApplyDamage (DamageInfo dinfo, float totalDamageDealt) + { + if (!this.CanEverExplodeFromDamage) { + return; + } + if (!this.parent.Destroyed) { + if (this.wickStarted && dinfo.Def == DamageDefOf.Stun) { + this.StopWick (); + } + else if (!this.wickStarted && this.parent.HitPoints <= this.StartWickThreshold && dinfo.Def.externalViolence) { + this.StartWick (dinfo.Instigator); + } + } + } + + public override void PostPreApplyDamage (DamageInfo dinfo, out bool absorbed) + { + absorbed = false; + if (this.CanEverExplodeFromDamage) { + if (dinfo.Def.externalViolence && dinfo.Amount >= this.parent.HitPoints) { + if (this.parent.MapHeld != null) { + this.Detonate (this.parent.MapHeld); + absorbed = true; + } + } + else if (!this.wickStarted && this.Props.startWickOnDamageTaken != null && dinfo.Def == this.Props.startWickOnDamageTaken) { + this.StartWick (dinfo.Instigator); + } + } + } + + public void StartWick (Thing instigator = null) + { + if (this.wickStarted) { + return; + } + this.instigator = instigator; + this.wickStarted = true; + this.wickTicksLeft = this.Props.wickTicks.RandomInRange; + this.StartWickSustainer (); + GenExplosion.NotifyNearbyPawnsOfDangerousExplosive (this.parent, this.Props.explosiveDamageType, null); + } + + private void StartWickSustainer () + { + SoundDefOf.MetalHitImportant.PlayOneShot (new TargetInfo (this.parent.Position, this.parent.Map, false)); + SoundInfo info = SoundInfo.InMap (this.parent, MaintenanceType.PerTick); + this.wickSoundSustainer = SoundDefOf.HissSmall.TrySpawnSustainer (info); + } + + public void StopWick () + { + this.wickStarted = false; + this.instigator = null; + } + } +} \ No newline at end of file diff --git a/Source/CompProperties_Explosive.cs b/Source/CompProperties_Explosive.cs new file mode 100644 index 0000000..de2be7e --- /dev/null +++ b/Source/CompProperties_Explosive.cs @@ -0,0 +1,52 @@ +using System; +using Verse; +using RimWorld; + +namespace Autarky +{ + public class CompProperties_Explosive : CompProperties + { + // + // Fields + // + public float explosiveRadius = 1.9f; + + public float explosiveExpandPerStackcount; + + public EffecterDef explosionEffect; + + public DamageDef startWickOnDamageTaken; + + public float startWickHitPointsPercent = 0.2f; + + public IntRange wickTicks = new IntRange (140, 150); + + public float wickScale = 1f; + + public float chanceNeverExplodeFromDamage; + + public int preExplosionSpawnThingCount = 1; + + public DamageDef explosiveDamageType = DamageDefOf.Bomb; + + public ThingDef postExplosionSpawnThingDef; + + public float postExplosionSpawnChance; + + public int postExplosionSpawnThingCount = 1; + + public bool applyDamageToExplosionCellsNeighbors; + + public ThingDef preExplosionSpawnThingDef; + + public float preExplosionSpawnChance; + + // + // Constructors + // + public CompProperties_Explosive () + { + this.compClass = typeof(CompExplosive); + } + } +} \ No newline at end of file