diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 579171b..0795224 100644 Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 4c6332d..9b9f81d 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -193,6 +193,13 @@ + + + + + + + diff --git a/Source/ArachnaeSwarm/Morphable/Building_Morphable.cs b/Source/ArachnaeSwarm/Morphable/Building_Morphable.cs new file mode 100644 index 0000000..b18c04e --- /dev/null +++ b/Source/ArachnaeSwarm/Morphable/Building_Morphable.cs @@ -0,0 +1,30 @@ +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + public class Building_Morphable : Building + { + public override void Destroy(DestroyMode mode) + { + var comp = this.GetComp(); + if (comp != null && comp.StoredPawn != null) + { + Pawn pawn = comp.StoredPawn; + Map map = this.Map; + IntVec3 position = this.Position; + + // 在建筑消失前,先把Pawn生成出来 + GenSpawn.Spawn(pawn, position, map, WipeMode.Vanish); + PawnComponentsUtility.AddComponentsForSpawn(pawn); + + // 如果是被武力摧毁,给玩家一个提示 + if (mode == DestroyMode.KillFinalize) + { + Messages.Message("PawnTransformer_BuildingDestroyed".Translate(pawn.Named("PAWN"), this.Named("BUILDING")), pawn, MessageTypeDefOf.NegativeEvent); + } + } + base.Destroy(mode); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Morphable/CompAbilityEffect_Transform.cs b/Source/ArachnaeSwarm/Morphable/CompAbilityEffect_Transform.cs new file mode 100644 index 0000000..270d783 --- /dev/null +++ b/Source/ArachnaeSwarm/Morphable/CompAbilityEffect_Transform.cs @@ -0,0 +1,68 @@ +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + public class CompAbilityEffect_Transform : CompAbilityEffect + { + public new CompProperties_AbilityTransform Props => (CompProperties_AbilityTransform)props; + + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + Pawn pawn = parent.pawn; + + // 检查空间 + foreach (var cell in GenRadial.RadialCellsAround(pawn.Position, Props.buildingDef.Size.x / 2f, true)) + { + if (!cell.InBounds(pawn.Map) || !cell.Walkable(pawn.Map) || cell.GetEdifice(pawn.Map) != null) + { + Messages.Message("PawnTransformer_SpaceBlocked".Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.RejectInput, false); + // 重置技能冷却 + parent.StartCooldown(0); + return; + } + } + + // 执行转换 + IntVec3 position = pawn.Position; + Map map = pawn.Map; + + pawn.DeSpawn(DestroyMode.Vanish); + + Building building = (Building)GenSpawn.Spawn(Props.buildingDef, position, map, WipeMode.Vanish); + building.SetFaction(pawn.Faction); + + if (pawn.Name != null) + { + building.TryGetComp()?.TryAssignPawn(pawn); + } + + var container = building.GetComp(); + if (container != null) + { + container.GetDirectlyHeldThings().TryAdd(pawn); + } + + var newMorphComp = building.GetComp(); + if (newMorphComp != null) + { + newMorphComp.SetStoredPawn(pawn); + } + } + + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + // 这个技能只应该对自己释放 + if (target.Pawn != parent.pawn) + { + if (throwMessages) + { + Messages.Message("AbilityCannotBeUsedOnOthers".Translate(), MessageTypeDefOf.RejectInput, false); + } + return false; + } + return base.Valid(target, throwMessages); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Morphable/CompMorphable.cs b/Source/ArachnaeSwarm/Morphable/CompMorphable.cs new file mode 100644 index 0000000..d1a35ae --- /dev/null +++ b/Source/ArachnaeSwarm/Morphable/CompMorphable.cs @@ -0,0 +1,59 @@ +using RimWorld; +using System.Collections.Generic; +using Verse; +using Verse.AI; + +namespace ArachnaeSwarm +{ + public class CompMorphable : ThingComp + { + private Pawn storedPawn; + public Pawn StoredPawn => storedPawn; + + public void SetStoredPawn(Pawn pawn) + { + this.storedPawn = pawn; + } + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_References.Look(ref storedPawn, "storedPawn", false); + } + + public override IEnumerable CompGetGizmosExtra() + { + if (parent.Faction == Faction.OfPlayer && storedPawn != null) + { + yield return new Command_Action + { + defaultLabel = "恢复人形", + defaultDesc = "将此建筑恢复为人形。", + icon = TexCommand.ReleaseAnimals, // TODO: Replace with a proper icon + action = () => { TransformBackToPawn(); } + }; + } + } + + private void TransformBackToPawn() + { + Building building = (Building)this.parent; + Map map = building.Map; + + // 移除建筑 + building.DeSpawn(DestroyMode.Vanish); + + // 重新生成Pawn + GenSpawn.Spawn(storedPawn, building.Position, map, WipeMode.Vanish); + + // 重新初始化Pawn在地图上所需的组件 + PawnComponentsUtility.AddComponentsForSpawn(storedPawn); + + // 选中Pawn + if (Find.Selector.IsSelected(building)) + { + Find.Selector.Select(storedPawn); + } + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Morphable/CompProperties_AbilityTransform.cs b/Source/ArachnaeSwarm/Morphable/CompProperties_AbilityTransform.cs new file mode 100644 index 0000000..c727e1e --- /dev/null +++ b/Source/ArachnaeSwarm/Morphable/CompProperties_AbilityTransform.cs @@ -0,0 +1,15 @@ +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + public class CompProperties_AbilityTransform : CompProperties_AbilityEffect + { + public ThingDef buildingDef; + + public CompProperties_AbilityTransform() + { + compClass = typeof(CompAbilityEffect_Transform); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Morphable/CompProperties_Morphable.cs b/Source/ArachnaeSwarm/Morphable/CompProperties_Morphable.cs new file mode 100644 index 0000000..a656901 --- /dev/null +++ b/Source/ArachnaeSwarm/Morphable/CompProperties_Morphable.cs @@ -0,0 +1,13 @@ +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + public class CompProperties_Morphable : CompProperties + { + public CompProperties_Morphable() + { + compClass = typeof(CompMorphable); + } + } +} \ No newline at end of file