diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index f9a4ea8..d9a6d41 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 6555cf4..2def29c 100644 --- a/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml +++ b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml @@ -31,6 +31,46 @@ + + ARA_TrapSpew + + 发射一排阿拉克涅休眠茧,其中装有阿拉克涅酸爆种,这些危险的虫族被唤醒后就会开始寻仇,匆匆了结自己的生命. + UI/Commands/EggSpew + 5000 + true + 300 + true + false + AcidSpray_Warmup + + Verb_CastAbility + 14.9 + 0.25 + AcidSpray_Resolve + + true + + + +
  • + ARA_Proj_StrongSludgeSpray + 8 + AcidSpray_Directional +
  • +
  • + ARA_Proj_Trap + 3 +
  • +
    +
    + + + ARA_Proj_Trap + + + Arachnae_Trap_ReleaseRandom + + ARA_TumorSpew diff --git a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceDroneSwarm.xml b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceDroneSwarm.xml index f6ea89c..03a781d 100644 --- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceDroneSwarm.xml +++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceDroneSwarm.xml @@ -131,6 +131,60 @@ + + ArachnaeBase_Race_Acidling + + 阿拉克涅辅虫之一,智力低下,一般被作为自杀式无人机打出,靠近敌人后就会引爆酸囊产生危险的酸性雾气。 + + HunterDroneConstant + 0.5 + + BeetleLikeWithClaw + +
  • + EusocialInsectAdult + 0 + Pawn_Spelopede_Pain + Pawn_Spelopede_Death + Pawn_Spelopede_Call + Pawn_Spelopede_Angry +
  • +
    +
    + + 6 + + +
  • + 4400 + 寿命 + 这种特殊的阿拉克涅辅虫从出生起就走在死亡的道路上了——它们的寿命就是如此短暂。 + true +
  • +
  • + 6 + ARA_AcidBurn + 40 + 0.5 + Explosion_Smoke + ARA_AcidGasCloud + 1 + 1 +
  • +
    + +
  • + + +
  • ARA_AcidCut
  • + + 6 + 2.6 + HeadAttackTool + true + +
    +
    ARA_AcidCut 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 index 1e6577a..c624340 100644 --- a/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml +++ b/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml @@ -40,4 +40,32 @@ + + + ARA_AcidGasCloud + + + Things/Gas/Puff + 2.6 + (0.56, 1, 0.03,0.5) + + + + 30 + 50 + + + 20 + + ArachnaeSwarm.OPToxicGas + +
  • + ARA_AcidCoverd + 0.1 + 240 +
  • +
    +
    + \ No newline at end of file diff --git a/1.6/1.6/Defs/Thing_building/ARA_ThingDefs_TrapReleaseRandom.xml b/1.6/1.6/Defs/Thing_building/ARA_ThingDefs_TrapReleaseRandom.xml new file mode 100644 index 0000000..5f22f6f --- /dev/null +++ b/1.6/1.6/Defs/Thing_building/ARA_ThingDefs_TrapReleaseRandom.xml @@ -0,0 +1,52 @@ + + + + Arachnae_Trap_ReleaseRandom + + 一种阿拉克涅休眠茧,内藏有休眠中的阿拉克涅虫族。如果靠太近则会唤醒其中的虫族。 + ArachnaeSwarm.Building_TrapReleaseRandom + + (1,1) + Building + PassThroughOnly + true + 0.20 + false + false + Normal + EatVegetarian + Filth_Slime + Buildings + + 20 + + + 10 + 4 + 1.0 + 50 + + + ArachnaeSwarm/Building/ARA_Tumor + Graphic_Single + 1.2 + + (0.3, 0.6, 0.3) + (0,0,-0.1) + + + + 3 + +
  • ArachnaeBase_Race_Acidling
  • +
  • ArachnaeBase_Race_Acid
  • +
    + + +
  • + 3 + (220,210,171,0) +
  • +
    +
    +
    diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml index c1cb40f..d324416 100644 --- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml +++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml @@ -22,4 +22,8 @@ 控制的虫族: 尚未绑定任何虫族。 + + {TRAP} 被 {PAWN} 触发! + {TRAP} 被触发! + \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 9b9f81d..a443725 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -1,5 +1,6 @@  - + Debug @@ -161,6 +162,7 @@ + @@ -192,6 +194,8 @@ + + diff --git a/Source/ArachnaeSwarm/Building_TrapReleaseRandom.cs b/Source/ArachnaeSwarm/Building_TrapReleaseRandom.cs new file mode 100644 index 0000000..89ae517 --- /dev/null +++ b/Source/ArachnaeSwarm/Building_TrapReleaseRandom.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using Verse; +using Verse.Sound; +using RimWorld; + +namespace ArachnaeSwarm; + +public class Building_TrapReleaseRandom : Building_TrapReleaseEntity +{ + // XML-assignable: number of pawns to spawn + public int countToSpawn = 1; + + // XML-assignable: list of PawnKindDefs to choose from randomly when spawning + public List pawnKinds = new List(); + + protected override int CountToSpawn => countToSpawn; + + protected override PawnKindDef PawnToSpawn => (pawnKinds == null || pawnKinds.Count == 0) ? PawnKindDefOf.Drone_Hunter : pawnKinds.RandomElement(); + + // Ensure spawned pawns use the building's faction when possible; otherwise spawn as wild (null faction) + protected override void SpringSub(Pawn p) + { + if (base.Spawned) + { + SoundStarter.PlayOneShot(SoundDefOf.DroneTrapSpring, new TargetInfo(base.Position, base.Map)); + if (base.Faction != Faction.OfPlayer) + { + // Show a localized message including the trap name and, if available, the pawn who triggered it. + if (p != null) + { + Messages.Message("MessageTrapSprung".Translate(this.Named("TRAP"), p.Named("PAWN")), new LookTargets(base.Position, base.Map), MessageTypeDefOf.NegativeEvent); + } + else + { + Messages.Message("MessageTrapSprung_NoInstigator".Translate(this.Named("TRAP")), new LookTargets(base.Position, base.Map), MessageTypeDefOf.NegativeEvent); + } + } + + for (int i = 0; i < CountToSpawn; i++) + { + PawnKindDef pawnToSpawn = PawnToSpawn; + + // Prefer the building's faction (usually the faction that built it). If none, pass null to produce a wild pawn. + Faction spawnFaction = this.Faction; + + float? fixedBiologicalAge = 0f; + float? fixedChronologicalAge = 0f; + Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest( + pawnToSpawn, + spawnFaction, + PawnGenerationContext.NonPlayer, + null, + forceGenerateNewPawn: false, + allowDead: false, + allowDowned: false, + canGeneratePawnRelations: true, + mustBeCapableOfViolence: false, + 1f, + forceAddFreeWarmLayerIfNeeded: false, + allowGay: true, + allowPregnant: false, + allowFood: true, + allowAddictions: true, + inhabitant: false, + certainlyBeenInCryptosleep: false, + forceRedressWorldPawnIfFormerColonist: false, + worldPawnFactionDoesntMatter: false, + 0f, + 0f, + null, + 1f, + null, + null, + null, + null, + null, + fixedBiologicalAge, + fixedChronologicalAge)); + + pawn.mindState.enemyTarget = p; + GenSpawn.Spawn(pawn, base.Position, base.Map); + } + } + } +} diff --git a/Source/ArachnaeSwarm/CompHunterExplosion.cs b/Source/ArachnaeSwarm/CompHunterExplosion.cs new file mode 100644 index 0000000..504d5f7 --- /dev/null +++ b/Source/ArachnaeSwarm/CompHunterExplosion.cs @@ -0,0 +1,123 @@ +using Verse; +using Verse.Sound; +using System.Collections.Generic; +using RimWorld; + +namespace ArachnaeSwarm; + +public class CompHunterExplosion : ThingComp +{ + private bool wickStarted; + + private int wickTicks; + + [Unsaved(false)] + private Sustainer wickSoundSustainer; + + [Unsaved(false)] + private OverlayHandle? overlayBurningWick; + + private CompProperties_HunterExplosion Props => (CompProperties_HunterExplosion)props; + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Values.Look(ref wickStarted, "wickStarted", defaultValue: false); + Scribe_Values.Look(ref wickTicks, "wickTicks", 0); + } + + public override void CompTickInterval(int delta) + { + if (!wickStarted && parent.IsHashIntervalTick(30, delta) && parent is Pawn { Spawned: not false, Downed: false } pawn && PawnUtility.EnemiesAreNearby(pawn, 9, passDoors: true, 1.5f)) + { + StartWick(); + } + } + + public override void CompTick() + { + if (wickStarted) + { + wickSoundSustainer.Maintain(); + wickTicks--; + if (wickTicks <= 0) + { + Detonate(); + } + } + } + + private void StartWick() + { + if (!wickStarted) + { + wickStarted = true; + overlayBurningWick = parent.Map.overlayDrawer.Enable(parent, OverlayTypes.BurningWick); + wickSoundSustainer = SoundDefOf.HissSmall.TrySpawnSustainer(SoundInfo.InMap(parent, MaintenanceType.PerTick)); + wickTicks = 120; + } + } + + public override void Notify_Killed(Map prevMap, DamageInfo? dinfo = null) + { + if (dinfo.HasValue) + { + Detonate(prevMap); + } + } + + private void Detonate(Map map = null) + { + IntVec3 position = parent.Position; + if (map == null) + { + map = parent.Map; + } + if (!parent.Destroyed) + { + parent.Destroy(); + } + GenExplosion.DoExplosion( + center: position, + map: map, + radius: Props.explosionRadius, + damType: Props.explosionDamageType, + instigator: parent, + damAmount: Props.explosionDamageAmount, + armorPenetration: Props.armorPenetration, + explosionSound: Props.explosionSound, + weapon: Props.weapon, + projectile: Props.projectile, + intendedTarget: Props.intendedTarget, + postExplosionSpawnThingDef: Props.postExplosionSpawnThingDef, + postExplosionSpawnChance: Props.postExplosionSpawnChance, + postExplosionSpawnThingCount: Props.postExplosionSpawnThingCount, + postExplosionGasType: Props.postExplosionGasType, + postExplosionGasRadiusOverride: Props.postExplosionGasRadiusOverride, + postExplosionGasAmount: Props.postExplosionGasAmount, + applyDamageToExplosionCellsNeighbors: Props.applyDamageToExplosionCellsNeighbors, + preExplosionSpawnThingDef: Props.preExplosionSpawnThingDef, + preExplosionSpawnChance: Props.preExplosionSpawnChance, + preExplosionSpawnThingCount: Props.preExplosionSpawnThingCount, + chanceToStartFire: Props.chanceToStartFire, + damageFalloff: Props.damageFalloff, + direction: Props.direction, + ignoredThings: Props.ignoredThings, + affectedAngle: Props.affectedAngle, + doVisualEffects: Props.doVisualEffects, + propagationSpeed: Props.propagationSpeed, + excludeRadius: Props.excludeRadius, + doSoundEffects: Props.doSoundEffects, + postExplosionSpawnThingDefWater: Props.postExplosionSpawnThingDefWater, + screenShakeFactor: Props.screenShakeFactor, + flammabilityChanceCurve: Props.flammabilityChanceCurve, + overrideCells: Props.overrideCells, + postExplosionSpawnSingleThingDef: Props.postExplosionSpawnSingleThingDef, + preExplosionSpawnSingleThingDef: Props.preExplosionSpawnSingleThingDef + ); + if (base.ParentHolder is Corpse corpse) + { + corpse.Destroy(); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/CompProperties_HunterExplosion.cs b/Source/ArachnaeSwarm/CompProperties_HunterExplosion.cs new file mode 100644 index 0000000..d4a03b4 --- /dev/null +++ b/Source/ArachnaeSwarm/CompProperties_HunterExplosion.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using RimWorld; +using Verse; + +namespace ArachnaeSwarm; + +public class CompProperties_HunterExplosion : CompProperties +{ + public float explosionRadius = 1.9f; + public DamageDef explosionDamageType; + public int explosionDamageAmount = 50; + public float armorPenetration = -1f; + public SoundDef explosionSound; + public ThingDef weapon; + public ThingDef projectile; + public Thing intendedTarget; + public ThingDef postExplosionSpawnThingDef; + public float postExplosionSpawnChance; + public int postExplosionSpawnThingCount = 1; + public GasType? postExplosionGasType; + public float? postExplosionGasRadiusOverride; + public int postExplosionGasAmount = 255; + public bool applyDamageToExplosionCellsNeighbors; + public ThingDef preExplosionSpawnThingDef; + public float preExplosionSpawnChance; + public int preExplosionSpawnThingCount = 1; + public float chanceToStartFire; + public bool damageFalloff; + public float? direction; + public List ignoredThings; + public FloatRange? affectedAngle; + public bool doVisualEffects = true; + public float propagationSpeed = 1f; + public float excludeRadius; + public bool doSoundEffects = true; + public ThingDef postExplosionSpawnThingDefWater; + public float screenShakeFactor = 1f; + public SimpleCurve flammabilityChanceCurve; + public List overrideCells; + public ThingDef postExplosionSpawnSingleThingDef; + public ThingDef preExplosionSpawnSingleThingDef; + + public CompProperties_HunterExplosion() + { + compClass = typeof(CompHunterExplosion); + } + + public override void ResolveReferences(ThingDef parentDef) + { + base.ResolveReferences(parentDef); + if (explosionDamageType == null) + { + explosionDamageType = DamageDefOf.Bomb; + } + } +} \ No newline at end of file