虫烟
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.Sound;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompAbilityEffect_DRM_Deaddustpop : CompAbilityEffect
|
||||
{
|
||||
public new CompProperties_AbilityDRM_Deaddustpop Props
|
||||
{
|
||||
get
|
||||
{
|
||||
return (CompProperties_AbilityDRM_Deaddustpop)this.props;
|
||||
}
|
||||
}
|
||||
|
||||
private Pawn Pawn
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.parent.pawn;
|
||||
}
|
||||
}
|
||||
private List<IntVec3> AffectedCells(LocalTargetInfo target)
|
||||
{
|
||||
return GenRadial.RadialCellsAround(target.Cell, Props.smokeRadius, true).ToList();
|
||||
}
|
||||
|
||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||
{
|
||||
base.Apply(target, dest);
|
||||
GenExplosion.DoExplosion(
|
||||
center: target.Cell,
|
||||
map: this.parent.pawn.MapHeld,
|
||||
radius: this.Props.smokeRadius,
|
||||
damType: this.Props.damageDef,
|
||||
instigator: null,
|
||||
damAmount: this.Props.damageAmount,
|
||||
armorPenetration: this.Props.armorPenetration,
|
||||
// 明确命名关键参数,避免顺序错误
|
||||
postExplosionSpawnThingDef: this.Props.postExplosionSpawnThingDef,
|
||||
postExplosionSpawnChance: this.Props.postExplosionSpawnChance,
|
||||
postExplosionSpawnThingCount: this.Props.postExplosionSpawnThingCount,
|
||||
postExplosionGasType: this.Props.gasType,
|
||||
// 需要补充的参数(根据实际需求填写)
|
||||
flammabilityChanceCurve: null,
|
||||
overrideCells: this.AffectedCells(target), // 明确传递实际需要的值
|
||||
postExplosionSpawnSingleThingDef: null,
|
||||
preExplosionSpawnSingleThingDef: null
|
||||
);
|
||||
}
|
||||
public override void DrawEffectPreview(LocalTargetInfo target)
|
||||
{
|
||||
GenDraw.DrawRadiusRing(target.Cell, this.Props.smokeRadius);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CompProperties_AbilityDRM_Deaddustpop : CompProperties_AbilityEffect
|
||||
{
|
||||
public CompProperties_AbilityDRM_Deaddustpop()
|
||||
{
|
||||
this.compClass = typeof(CompAbilityEffect_DRM_Deaddustpop);
|
||||
}
|
||||
|
||||
public float smokeRadius;
|
||||
public SoundDef explosionSound;
|
||||
|
||||
public GasType gasType;
|
||||
|
||||
public DamageDef damageDef;
|
||||
|
||||
public float postExplosionSpawnChance = 0f;
|
||||
|
||||
public int postExplosionSpawnThingCount = 1;
|
||||
|
||||
public ThingDef postExplosionSpawnThingDef = null;
|
||||
|
||||
public int damageAmount = -1;
|
||||
|
||||
public float armorPenetration = -1f;
|
||||
}
|
||||
}
|
||||
@@ -154,6 +154,7 @@
|
||||
<Compile Include="CompPawnFlight.cs" />
|
||||
<Compile Include="CompProperties_PawnFlight.cs" />
|
||||
<Compile Include="HarmonyPatches.cs" />
|
||||
<Compile Include="OPToxicGas.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -164,6 +165,7 @@
|
||||
<Compile Include="Abilities\CompProperties_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\PawnFlyer_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\Verb_CastAbilityTrackingCharge.cs" />
|
||||
<Compile Include="Abilities\CompAbilityEffect_DRM_Deaddustpop.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="HediffComp_SpawnPawnOnRemoved.cs" />
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
@@ -9,7 +11,8 @@ namespace ArachnaeSwarm
|
||||
/// </summary>
|
||||
public class HediffCompProperties_SpawnPawnOnRemoved : HediffCompProperties
|
||||
{
|
||||
public PawnKindDef pawnKindDef;
|
||||
public List<PawnKindDef> pawnKindDefs; // 更改为列表
|
||||
public int spawnCount = 1; // 新增生成数量
|
||||
public float? fixedBiologicalAge; // 新增用于XML配置的固定生物年龄
|
||||
public FloatRange? biologicalAgeRange; // 新增用于XML配置的生物年龄范围
|
||||
|
||||
@@ -49,32 +52,43 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
base.CompPostPostRemoved();
|
||||
|
||||
if (this.Pawn == null || this.Pawn.Map == null || Props.pawnKindDef == null)
|
||||
if (this.Pawn == null || this.Pawn.Map == null || Props.pawnKindDefs.NullOrEmpty())
|
||||
{
|
||||
Log.Warning("ArachnaeSwarm: HediffComp_SpawnPawnOnRemoved tried to spawn a pawn but required data was missing (Pawn, Map, or pawnKindDef).");
|
||||
Log.Warning("ArachnaeSwarm: HediffComp_SpawnPawnOnRemoved tried to spawn a pawn but required data was missing (Pawn, Map, or pawnKindDefs).");
|
||||
return;
|
||||
}
|
||||
|
||||
Map map = this.Pawn.Map;
|
||||
IntVec3 loc = this.Pawn.Position;
|
||||
|
||||
Pawn newPawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(
|
||||
kind: Props.pawnKindDef,
|
||||
faction: this.casterFaction, // Use the stored faction
|
||||
context: PawnGenerationContext.NonPlayer,
|
||||
tile: -1,
|
||||
forceGenerateNewPawn: true,
|
||||
fixedBiologicalAge: Props.fixedBiologicalAge, // 使用XML配置的固定生物年龄
|
||||
biologicalAgeRange: Props.biologicalAgeRange // 使用XML配置的生物年龄范围
|
||||
));
|
||||
|
||||
if (newPawn != null)
|
||||
// If casterFaction is null, default to the player's faction
|
||||
if (this.casterFaction == null)
|
||||
{
|
||||
GenSpawn.Spawn(newPawn, loc, map, WipeMode.Vanish);
|
||||
this.casterFaction = Faction.OfPlayer;
|
||||
}
|
||||
else
|
||||
|
||||
for (int i = 0; i < Props.spawnCount; i++)
|
||||
{
|
||||
Log.Error($"ArachnaeSwarm: Failed to generate pawn of kind {Props.pawnKindDef.defName}.");
|
||||
PawnKindDef selectedPawnKindDef = Props.pawnKindDefs.RandomElement();
|
||||
|
||||
Pawn newPawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(
|
||||
kind: selectedPawnKindDef,
|
||||
faction: this.casterFaction, // Use the stored faction
|
||||
context: PawnGenerationContext.NonPlayer,
|
||||
tile: -1,
|
||||
forceGenerateNewPawn: true,
|
||||
fixedBiologicalAge: Props.fixedBiologicalAge, // 使用XML配置的固定生物年龄
|
||||
biologicalAgeRange: Props.biologicalAgeRange // 使用XML配置的生物年龄范围
|
||||
));
|
||||
|
||||
if (newPawn != null)
|
||||
{
|
||||
GenSpawn.Spawn(newPawn, loc, map, WipeMode.Vanish);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"ArachnaeSwarm: Failed to generate pawn of kind {selectedPawnKindDef.defName}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
187
Source/ArachnaeSwarm/OPToxicGas.cs
Normal file
187
Source/ArachnaeSwarm/OPToxicGas.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class OPToxicGas : Gas
|
||||
{
|
||||
public override void SpawnSetup(Map map, bool respawningAfterLoad)
|
||||
{
|
||||
base.SpawnSetup(map, true);
|
||||
this.destroyTick = Find.TickManager.TicksGame + this.def.gas.expireSeconds.RandomInRange.SecondsToTicks();
|
||||
}
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look<int>(ref this.destroyTick, "destroyTick", 0, false);
|
||||
}
|
||||
|
||||
protected override void Tick()
|
||||
{
|
||||
bool flag = this.destroyTick <= Find.TickManager.TicksGame;
|
||||
if (flag)
|
||||
{
|
||||
this.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
this.graphicRotation += this.graphicRotationSpeed;
|
||||
bool flag2 = !base.Destroyed && Find.TickManager.TicksGame % OPToxicDefGetValue.OPToxicGetSevUpVal(this.def) == 0;
|
||||
if (flag2)
|
||||
{
|
||||
Map map = base.Map;
|
||||
IntVec3 position = base.Position;
|
||||
List<Thing> thingList = position.GetThingList(map);
|
||||
bool flag3 = thingList.Count > 0;
|
||||
if (flag3)
|
||||
{
|
||||
for (int i = 0; i < thingList.Count; i++)
|
||||
{
|
||||
bool flag4 = thingList[i] is Pawn && !(thingList[i] as Pawn).RaceProps.IsMechanoid && thingList[i].Position == position;
|
||||
if (flag4)
|
||||
{
|
||||
this.DoOPToxicGas(this, thingList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DoOPToxicGas(Thing Gas, Thing targ)
|
||||
{
|
||||
Pawn pawn = targ as Pawn;
|
||||
bool flag = pawn != null && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Breathing);
|
||||
if (flag)
|
||||
{
|
||||
HediffDef namedSilentFail = DefDatabase<HediffDef>.GetNamedSilentFail(OPToxicDefGetValue.OPToxicGetHediff(Gas.def));
|
||||
bool flag2 = namedSilentFail != null;
|
||||
if (flag2)
|
||||
{
|
||||
Pawn_HealthTracker health = pawn.health;
|
||||
bool flag3 = health == null;
|
||||
Hediff hediff;
|
||||
if (flag3)
|
||||
{
|
||||
hediff = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
HediffSet hediffSet = health.hediffSet;
|
||||
hediff = ((hediffSet != null) ? hediffSet.GetFirstHediffOfDef(namedSilentFail, false) : null);
|
||||
}
|
||||
float num = 1f - pawn.GetStatValue(StatDefOf.ToxicResistance, true, -1);
|
||||
float num2 = OPToxicDefGetValue.OPToxicGetSev(Gas.def);
|
||||
bool flag4 = num2 < 0.01f;
|
||||
if (flag4)
|
||||
{
|
||||
num2 = 0.01f;
|
||||
}
|
||||
float num3 = Rand.Range(0.01f * num, num2 * num);
|
||||
bool flag5 = hediff != null && num3 > 0f;
|
||||
if (flag5)
|
||||
{
|
||||
hediff.Severity += num3;
|
||||
}
|
||||
else
|
||||
{
|
||||
Hediff hediff2 = HediffMaker.MakeHediff(namedSilentFail, pawn, null);
|
||||
hediff2.Severity = num3;
|
||||
pawn.health.AddHediff(hediff2, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OPToxicDefGetValue
|
||||
{
|
||||
public static string OPToxicGetHediff(ThingDef thingdef)
|
||||
{
|
||||
bool flag = thingdef.HasModExtension<OPToxicDefs>();
|
||||
string result;
|
||||
if (flag)
|
||||
{
|
||||
result = thingdef.GetModExtension<OPToxicDefs>().OPToxicHediff;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static float OPToxicGetSev(ThingDef thingdef)
|
||||
{
|
||||
bool flag = thingdef.HasModExtension<OPToxicDefs>();
|
||||
float result;
|
||||
if (flag)
|
||||
{
|
||||
result = thingdef.GetModExtension<OPToxicDefs>().OPToxicSeverity;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 0f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int OPToxicGetSevUpVal(ThingDef thingdef)
|
||||
{
|
||||
bool flag = thingdef.HasModExtension<OPToxicDefs>();
|
||||
int result;
|
||||
if (flag)
|
||||
{
|
||||
result = thingdef.GetModExtension<OPToxicDefs>().OPSevUpTickPeriod;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 120;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class OPToxicDefs : DefModExtension
|
||||
{
|
||||
public string OPToxicHediff;
|
||||
|
||||
public float OPToxicSeverity;
|
||||
|
||||
public int OPSevUpTickPeriod = 120;
|
||||
}
|
||||
|
||||
public class DamageWorker_OPToxic : DamageWorker
|
||||
{
|
||||
public override void ExplosionStart(Explosion explosion, List<IntVec3> cellsToAffect)
|
||||
{
|
||||
bool flag = this.def.explosionHeatEnergyPerCell > float.Epsilon;
|
||||
if (flag)
|
||||
{
|
||||
GenTemperature.PushHeat(explosion.Position, explosion.Map, this.def.explosionHeatEnergyPerCell * (float)cellsToAffect.Count);
|
||||
}
|
||||
FleckMaker.Static(explosion.Position, explosion.Map, FleckDefOf.ExplosionFlash, explosion.radius * 6f);
|
||||
FleckMaker.Static(explosion.Position, explosion.Map, FleckDefOf.ExplosionFlash, explosion.radius * 6f);
|
||||
this.ExplosionVisualEffectCenter(explosion);
|
||||
}
|
||||
|
||||
public override DamageWorker.DamageResult Apply(DamageInfo dinfo, Thing victim)
|
||||
{
|
||||
DamageWorker.DamageResult damageResult = new DamageWorker.DamageResult();
|
||||
bool flag = victim.def.category == ThingCategory.Pawn && victim.def.useHitPoints && dinfo.Def.harmsHealth;
|
||||
if (flag)
|
||||
{
|
||||
float amount = dinfo.Amount;
|
||||
damageResult.totalDamageDealt = (float)Mathf.Min(victim.HitPoints, GenMath.RoundRandom(amount));
|
||||
victim.HitPoints -= Mathf.RoundToInt(damageResult.totalDamageDealt);
|
||||
bool flag2 = victim.HitPoints <= 0;
|
||||
if (flag2)
|
||||
{
|
||||
victim.HitPoints = 0;
|
||||
victim.Kill(new DamageInfo?(dinfo), null);
|
||||
}
|
||||
}
|
||||
return damageResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user