diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index f42aa66..d9740b4 100644 Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ diff --git a/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml index d38dff5..329b3f2 100644 --- a/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml +++ b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml @@ -322,8 +322,8 @@ ARA_Ability_Smokepop - - 浓雾种将其腹部的大量白色压缩气体和阻燃泡沫一股脑喷射到空中,形成一大片足以遮蔽虫族身形的烟雾,并防止敌方使用火焰武器点燃虫族集群。 + + 浓雾种将其腹部的大量释放阿拉克涅信息素烟雾,吸引附近的阿拉克涅辅虫破土而出支援虫群。形成一大片足以遮蔽虫族身形的烟雾,并防止敌方使用火焰武器点燃虫族集群。 UI/Abilities/MechSmokepop 6000 false @@ -344,15 +344,22 @@ 0.25 营养值不足,需要进食 -
  • + +
  • + ARA_ReinforceGas + 5 + 2.0 10 + Explosion_Smoke Ability 15 + ARA_ReinforceGasCloud + 1 + 1
  • + + HediffWithComps + (0.6, 0.4, 0.8) + +
  • + 1200 + True +
  • +
  • +
  • + +
  • ArachnaeBase_Race_Acid
  • + + 1 + 0 + +
    + + + + ARA_Unburnable + + 不会着火. + HediffWithComps + +
  • + + 0 + +
  • +
    + +
  • + 1200 + True +
  • +
  • + + + \ No newline at end of file diff --git a/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml b/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml new file mode 100644 index 0000000..8f7d07a --- /dev/null +++ b/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml @@ -0,0 +1,43 @@ + + + + + Gas + + Gas + Gas + false + Normal + + Graphic_Gas + Transparent + + + + + + ARA_ReinforceGasCloud + + + Things/Gas/Puff + 2.6 + (1.0, 0.647, 0.0, 0.5) + + + + 15 + 20 + + 20 + + ArachnaeSwarm.OPToxicGas + +
  • + ARA_Unburnable + 0.1 + 240 +
  • + + + + \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Abilities/CompAbilityEffect_DRM_Deaddustpop.cs b/Source/ArachnaeSwarm/Abilities/CompAbilityEffect_DRM_Deaddustpop.cs new file mode 100644 index 0000000..4ed71b5 --- /dev/null +++ b/Source/ArachnaeSwarm/Abilities/CompAbilityEffect_DRM_Deaddustpop.cs @@ -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 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; + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 469912d..4d584b3 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -154,6 +154,7 @@ + @@ -164,6 +165,7 @@ + diff --git a/Source/ArachnaeSwarm/HediffComp_SpawnPawnOnRemoved.cs b/Source/ArachnaeSwarm/HediffComp_SpawnPawnOnRemoved.cs index a29f091..525595c 100644 --- a/Source/ArachnaeSwarm/HediffComp_SpawnPawnOnRemoved.cs +++ b/Source/ArachnaeSwarm/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 /// public class HediffCompProperties_SpawnPawnOnRemoved : HediffCompProperties { - public PawnKindDef pawnKindDef; + public List 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}."); + } } } diff --git a/Source/ArachnaeSwarm/OPToxicGas.cs b/Source/ArachnaeSwarm/OPToxicGas.cs new file mode 100644 index 0000000..6f85926 --- /dev/null +++ b/Source/ArachnaeSwarm/OPToxicGas.cs @@ -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(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 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.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(); + string result; + if (flag) + { + result = thingdef.GetModExtension().OPToxicHediff; + } + else + { + result = null; + } + return result; + } + + public static float OPToxicGetSev(ThingDef thingdef) + { + bool flag = thingdef.HasModExtension(); + float result; + if (flag) + { + result = thingdef.GetModExtension().OPToxicSeverity; + } + else + { + result = 0f; + } + return result; + } + + public static int OPToxicGetSevUpVal(ThingDef thingdef) + { + bool flag = thingdef.HasModExtension(); + int result; + if (flag) + { + result = thingdef.GetModExtension().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 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; + } + } +}