153 lines
5.0 KiB
C#
153 lines
5.0 KiB
C#
using RimWorld;
|
|
using UnityEngine;
|
|
using Verse;
|
|
using System.Collections.Generic;
|
|
|
|
namespace ArachnaeSwarm
|
|
{
|
|
public interface IStructurePoints
|
|
{
|
|
float StructurePoints { get; }
|
|
float StructurePointsMax { get; }
|
|
float StructurePointsPercent { get; }
|
|
string Label { get; }
|
|
}
|
|
|
|
public class PowerArmorExtension : DefModExtension
|
|
{
|
|
public ThingDef buildingDef;
|
|
public float structurePointsMax = 500f;
|
|
}
|
|
|
|
[StaticConstructorOnStartup]
|
|
public class ARA_PowerArmor : Apparel, IStructurePoints
|
|
{
|
|
#region Properties
|
|
private PowerArmorExtension ext;
|
|
public PowerArmorExtension Ext => ext ??= def.GetModExtension<PowerArmorExtension>();
|
|
public override string Label => base.Label;
|
|
|
|
private float structurePoints = -1f;
|
|
public float StructurePointsMax => Ext?.structurePointsMax ?? 500f;
|
|
|
|
public float StructurePoints
|
|
{
|
|
get
|
|
{
|
|
if (structurePoints < 0)
|
|
{
|
|
structurePoints = StructurePointsMax;
|
|
}
|
|
return structurePoints;
|
|
}
|
|
set
|
|
{
|
|
structurePoints = Mathf.Clamp(value, 0, StructurePointsMax);
|
|
}
|
|
}
|
|
|
|
public float StructurePointsPercent => StructurePoints / StructurePointsMax;
|
|
|
|
public Building sourceBuilding;
|
|
#endregion
|
|
|
|
#region Data
|
|
public override void ExposeData()
|
|
{
|
|
base.ExposeData();
|
|
Scribe_Values.Look(ref structurePoints, "structurePoints", -1f);
|
|
Scribe_References.Look(ref sourceBuilding, "sourceBuilding");
|
|
}
|
|
#endregion
|
|
|
|
#region Gizmo
|
|
public override IEnumerable<Gizmo> GetWornGizmos()
|
|
{
|
|
foreach (var gizmo in base.GetWornGizmos())
|
|
{
|
|
yield return gizmo;
|
|
}
|
|
yield return new Gizmo_StructurePanel(this);
|
|
}
|
|
#endregion
|
|
|
|
#region State-Switching
|
|
public override void Notify_Unequipped(Pawn pawn)
|
|
{
|
|
base.Notify_Unequipped(pawn);
|
|
|
|
ThingDef buildingToSpawn = sourceBuilding?.def ?? Ext?.buildingDef;
|
|
|
|
if (buildingToSpawn == null)
|
|
{
|
|
Log.Error($"[ArachnaeSwarm] Power Armor {this.def.defName} unequipped, but has no buildingDef defined in its PowerArmorExtension or a source building.");
|
|
return;
|
|
}
|
|
|
|
Building building = (Building)ThingMaker.MakeThing(buildingToSpawn);
|
|
building.HitPoints = Mathf.RoundToInt(this.StructurePoints);
|
|
GenPlace.TryPlaceThing(building, pawn.Position, pawn.Map, ThingPlaceMode.Near);
|
|
}
|
|
#endregion
|
|
|
|
#region Damage Handling - THE FINAL, CORRECT IMPLEMENTATION
|
|
public override bool CheckPreAbsorbDamage(DamageInfo dinfo)
|
|
{
|
|
if (this.Wearer == null || !dinfo.Def.harmsHealth || dinfo.Amount <= 0.001f)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
float finalDamage = GetPostArmorDamage(ref dinfo);
|
|
|
|
if (finalDamage > 0)
|
|
{
|
|
this.StructurePoints -= finalDamage;
|
|
EffecterDefOf.DamageDiminished_Metal.SpawnAttached(this.Wearer, this.Wearer.Map, 1f);
|
|
|
|
if (this.StructurePoints <= 0)
|
|
{
|
|
Messages.Message("PowerArmorBroken".Translate(this.Label, this.Wearer.LabelShort), this, MessageTypeDefOf.NegativeEvent);
|
|
this.Destroy(DestroyMode.KillFinalize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EffecterDefOf.Deflect_Metal_Bullet.SpawnAttached(this.Wearer, this.Wearer.Map, 1f);
|
|
}
|
|
|
|
// By returning true, we tell the game the damage has been fully handled and should not proceed to the pawn.
|
|
return true;
|
|
}
|
|
|
|
private float GetPostArmorDamage(ref DamageInfo dinfo)
|
|
{
|
|
float amount = dinfo.Amount;
|
|
if (dinfo.Def.armorCategory != null)
|
|
{
|
|
StatDef armorRatingStat = dinfo.Def.armorCategory.armorRatingStat;
|
|
float armorRating = this.GetStatValue(armorRatingStat);
|
|
|
|
float armorPenetration = dinfo.ArmorPenetrationInt;
|
|
float num = Mathf.Max(armorRating - armorPenetration, 0f);
|
|
float value = Rand.Value;
|
|
float num2 = num * 0.5f;
|
|
float num3 = num;
|
|
if (value < num2)
|
|
{
|
|
amount = 0f;
|
|
}
|
|
else if (value < num3)
|
|
{
|
|
amount = GenMath.RoundRandom(amount / 2f);
|
|
if (dinfo.Def.armorCategory == DamageArmorCategoryDefOf.Sharp)
|
|
{
|
|
dinfo.Def = DamageDefOf.Blunt;
|
|
}
|
|
}
|
|
}
|
|
return amount;
|
|
}
|
|
#endregion
|
|
}
|
|
} |