杂七杂八
This commit is contained in:
Binary file not shown.
@@ -1,22 +1,18 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
|
||||
"WorkspaceRootPath": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\buildings\\building_arachnaegravengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_arachnaegravengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_ejectorgans\\compabilityeffect_ejectorgans.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_ejectorgans\\compabilityeffect_ejectorgans.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\building_comps\\ara_building_refuelingvat\\building_refuelingvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_building_refuelingvat\\building_refuelingvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_genestealer\\compabilityeffect_extractgene.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_genestealer\\compabilityeffect_extractgene.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\ara_hediffterrainspawn\\comphediffterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_hediffterrainspawn\\comphediffterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\compabilityeffect_randomhediff.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\compabilityeffect_randomhediff.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_terrainrestriction\\compabilityeffect_terrainrestriction .cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_terrainrestriction\\compabilityeffect_terrainrestriction .cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
@@ -26,7 +22,7 @@
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 2,
|
||||
"SelectedChildIndex": 1,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
@@ -34,54 +30,42 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "Building_RefuelingVat.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
|
||||
"RelativeDocumentMoniker": "Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
|
||||
"RelativeToolTip": "Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
|
||||
"ViewState": "AgIAAEQAAAAAAAAAAAAAAEABAAAQAAAAAAAAAA==",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "CompAbilityEffect_EjectOrgans.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_EjectOrgans\\CompAbilityEffect_EjectOrgans.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_EjectOrgans\\CompAbilityEffect_EjectOrgans.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_EjectOrgans\\CompAbilityEffect_EjectOrgans.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_EjectOrgans\\CompAbilityEffect_EjectOrgans.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAC4AAAAoAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-24T06:16:14.743Z",
|
||||
"WhenOpened": "2025-10-25T11:49:25.843Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "Building_ArachnaeGravEngine.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs",
|
||||
"RelativeDocumentMoniker": "Buildings\\Building_ArachnaeGravEngine.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs",
|
||||
"RelativeToolTip": "Buildings\\Building_ArachnaeGravEngine.cs",
|
||||
"ViewState": "AgIAAHwAAAAAAAAAAAAgwJcAAAAJAAAAAAAAAA==",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "CompAbilityEffect_ExtractGene.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
|
||||
"ViewState": "AgIAABEAAAAAAAAAAAAAwCgAAAApAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-24T02:30:45.288Z",
|
||||
"WhenOpened": "2025-10-25T11:49:07.979Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "CompHediffTerrainSpawn.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
|
||||
"RelativeDocumentMoniker": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
|
||||
"RelativeToolTip": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
|
||||
"ViewState": "AgIAAB0AAAAAAAAAAAAswE0AAABHAAAAAAAAAA==",
|
||||
"Title": "CompAbilityEffect_TerrainRestriction .cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_TerrainRestriction\\CompAbilityEffect_TerrainRestriction .cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_TerrainRestriction\\CompAbilityEffect_TerrainRestriction .cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_TerrainRestriction\\CompAbilityEffect_TerrainRestriction .cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_TerrainRestriction\\CompAbilityEffect_TerrainRestriction .cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAADwvwQAAAABAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-23T08:00:28.236Z",
|
||||
"WhenOpened": "2025-10-25T11:48:39.275Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "CompAbilityEffect_RandomHediff.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\CompAbilityEffect_RandomHediff.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs",
|
||||
"RelativeToolTip": "Abilities\\CompAbilityEffect_RandomHediff.cs",
|
||||
"ViewState": "AgIAALoAAAAAAAAAAAAqwNcAAAAZAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-22T06:34:08.063Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompAbilityEffect_EjectOrgans : CompAbilityEffect
|
||||
{
|
||||
// 定义免疫的 Hediff 列表
|
||||
private static readonly string[] ImmuneHediffs =
|
||||
{
|
||||
"ARA_HiveMindMaster",
|
||||
"ARA_HiveMindDrone",
|
||||
"ARA_HiveMindWorker"
|
||||
};
|
||||
|
||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||
{
|
||||
base.Apply(target, dest);
|
||||
|
||||
Pawn caster = parent.pawn;
|
||||
Pawn targetPawn = target.Pawn;
|
||||
|
||||
if (caster == null || targetPawn == null || targetPawn.Dead)
|
||||
return;
|
||||
|
||||
// 检查目标是否免疫
|
||||
if (IsTargetImmune(targetPawn))
|
||||
{
|
||||
Messages.Message("ARA_TargetBlacklisted".Translate(), targetPawn, MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
List<BodyPartRecord> partsToEject = new List<BodyPartRecord>();
|
||||
|
||||
// 遍历所有身体部位
|
||||
foreach (BodyPartRecord part in targetPawn.RaceProps.body.AllParts)
|
||||
{
|
||||
// 只检查有spawnThingOnRemoved且未缺失的部位
|
||||
if (!targetPawn.health.hediffSet.PartIsMissing(part) &&
|
||||
part.def.spawnThingOnRemoved != null)
|
||||
{
|
||||
partsToEject.Add(part);
|
||||
}
|
||||
}
|
||||
|
||||
if (partsToEject.Count == 0)
|
||||
return;
|
||||
|
||||
// 执行弹出
|
||||
foreach (BodyPartRecord part in partsToEject)
|
||||
{
|
||||
// 生成物品 - spawnThingOnRemoved 是 ThingDef 类型
|
||||
ThingDef thingDef = part.def.spawnThingOnRemoved;
|
||||
if (thingDef != null)
|
||||
{
|
||||
Thing thing = ThingMaker.MakeThing(thingDef);
|
||||
GenSpawn.Spawn(thing, caster.Position, caster.Map);
|
||||
}
|
||||
|
||||
// 标记部位缺失
|
||||
targetPawn.health.AddHediff(HediffDefOf.MissingBodyPart, part);
|
||||
}
|
||||
|
||||
Messages.Message("ARA_EjectedOrgans".Translate(targetPawn.LabelShort), MessageTypeDefOf.NeutralEvent);
|
||||
}
|
||||
|
||||
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
|
||||
{
|
||||
Pawn targetPawn = target.Pawn;
|
||||
if (targetPawn == null)
|
||||
return false;
|
||||
|
||||
// 检查目标是否免疫
|
||||
if (IsTargetImmune(targetPawn))
|
||||
{
|
||||
if (throwMessages)
|
||||
Messages.Message("ARA_TargetBlacklisted".Translate(), targetPawn, MessageTypeDefOf.RejectInput, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否有可弹出的器官
|
||||
if (!HasEjectableOrgans(targetPawn))
|
||||
{
|
||||
if (throwMessages)
|
||||
Messages.Message("ARA_NoEjectableOrgans".Translate(), targetPawn, MessageTypeDefOf.RejectInput, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.Valid(target, throwMessages);
|
||||
}
|
||||
|
||||
public override bool GizmoDisabled(out string reason)
|
||||
{
|
||||
Pawn caster = parent.pawn;
|
||||
if (caster == null || caster.Dead)
|
||||
{
|
||||
reason = "ARA_CasterDead".Translate();
|
||||
return true;
|
||||
}
|
||||
|
||||
reason = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查目标是否免疫器官弹出
|
||||
/// </summary>
|
||||
private bool IsTargetImmune(Pawn pawn)
|
||||
{
|
||||
if (pawn?.health?.hediffSet?.hediffs == null)
|
||||
return false;
|
||||
|
||||
foreach (Hediff hediff in pawn.health.hediffSet.hediffs)
|
||||
{
|
||||
if (hediff?.def != null)
|
||||
{
|
||||
string hediffDefName = hediff.def.defName;
|
||||
foreach (string immuneHediff in ImmuneHediffs)
|
||||
{
|
||||
if (hediffDefName == immuneHediff)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查目标是否有可弹出的器官
|
||||
/// </summary>
|
||||
private bool HasEjectableOrgans(Pawn pawn)
|
||||
{
|
||||
if (pawn?.RaceProps?.body?.AllParts == null)
|
||||
return false;
|
||||
|
||||
foreach (BodyPartRecord part in pawn.RaceProps.body.AllParts)
|
||||
{
|
||||
if (!pawn.health.hediffSet.PartIsMissing(part) &&
|
||||
part.def.spawnThingOnRemoved != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class CompProperties_AbilityEjectOrgans : CompProperties_AbilityEffect
|
||||
{
|
||||
public CompProperties_AbilityEjectOrgans()
|
||||
{
|
||||
compClass = typeof(CompAbilityEffect_EjectOrgans);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,7 @@
|
||||
<Compile Include="Abilities\ARA_AddExtraExp\CompProperties_AddExtraExp.cs" />
|
||||
<Compile Include="Abilities\ARA_DestroyOwnBodyPart\CompAbilityEffect_DestroyOwnBodyPart.cs" />
|
||||
<Compile Include="Abilities\ARA_DestroyOwnBodyPart\CompProperties_AbilityDestroyOwnBodyPart.cs" />
|
||||
<Compile Include="Abilities\ARA_EjectOrgans\CompAbilityEffect_EjectOrgans.cs" />
|
||||
<Compile Include="Abilities\ARA_Genestealer\CompAbilityEffect_ExtractGene.cs" />
|
||||
<Compile Include="Abilities\ARA_Genestealer\CompAbilityEffect_InjectGenes.cs" />
|
||||
<Compile Include="Abilities\ARA_Genestealer\CompProperties_AbilityInjectGenes.cs" />
|
||||
@@ -115,8 +116,12 @@
|
||||
<Compile Include="Building_Comps\ARA_Building_RefuelingVat\CompRefuelingVat.cs" />
|
||||
<Compile Include="Building_Comps\ARA_CompInteractiveProducer\CompResearchProducer.cs" />
|
||||
<Compile Include="Building_Comps\ARA_CompInteractiveProducer\JobDriver_StartResearchProduction.cs" />
|
||||
<Compile Include="Building_Comps\ARA_ForwardClearance\CompForwardClearance.cs" />
|
||||
<Compile Include="Building_Comps\ARA_ForwardClearance\CompProperties_ForwardClearance.cs" />
|
||||
<Compile Include="Building_Comps\ARA_ForwardClearance\PlaceWorker_ForwardClearance.cs" />
|
||||
<Compile Include="Building_Comps\ARA_ProductStorage\CompProductStorage.cs" />
|
||||
<Compile Include="Building_Comps\ARA_ProductStorage\CompProperties_ProductStorage.cs" />
|
||||
<Compile Include="Building_Comps\CompBreakdownDisabler.cs" />
|
||||
<Compile Include="EventSystem\CompOpenCustomUI.cs" />
|
||||
<Compile Include="EventSystem\Condition.cs" />
|
||||
<Compile Include="EventSystem\DebugActions.cs" />
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompForwardClearance : ThingComp
|
||||
{
|
||||
private bool isBlocked = false;
|
||||
private int lastCheckedTick = -99999;
|
||||
private const int CheckInterval = 60; // 每60tick检查一次
|
||||
|
||||
public CompProperties_ForwardClearance Props => (CompProperties_ForwardClearance)props;
|
||||
|
||||
public bool IsBlocked
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Find.TickManager.TicksGame - lastCheckedTick > CheckInterval)
|
||||
{
|
||||
CheckClearance();
|
||||
}
|
||||
return isBlocked;
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
CheckClearance();
|
||||
}
|
||||
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
if (Find.TickManager.TicksGame % CheckInterval == 0)
|
||||
{
|
||||
bool previousState = isBlocked;
|
||||
CheckClearance();
|
||||
|
||||
// 状态变化时发送信号
|
||||
if (isBlocked != previousState)
|
||||
{
|
||||
SendStateSignal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompTickRare()
|
||||
{
|
||||
base.CompTickRare();
|
||||
CheckClearance();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查前方是否有遮挡
|
||||
/// </summary>
|
||||
public void CheckClearance()
|
||||
{
|
||||
lastCheckedTick = Find.TickManager.TicksGame;
|
||||
bool newBlockedState = IsForwardBlocked(parent.Position, parent.Rotation, parent.Map, Props);
|
||||
|
||||
if (newBlockedState != isBlocked)
|
||||
{
|
||||
isBlocked = newBlockedState;
|
||||
SendStateSignal();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送状态信号
|
||||
/// </summary>
|
||||
private void SendStateSignal()
|
||||
{
|
||||
if (isBlocked)
|
||||
{
|
||||
parent.BroadcastCompSignal(Props.blockedSignal);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.BroadcastCompSignal(Props.clearSignal);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 静态方法:检查指定位置和朝向是否有遮挡
|
||||
/// </summary>
|
||||
public static bool IsForwardBlocked(IntVec3 position, Rot4 rotation, Map map, CompProperties_ForwardClearance props)
|
||||
{
|
||||
if (!position.InBounds(map))
|
||||
return false;
|
||||
|
||||
// 获取前方检查的单元格
|
||||
List<IntVec3> checkCells = GetForwardCells(position, rotation, props.checkDistance);
|
||||
|
||||
foreach (IntVec3 cell in checkCells)
|
||||
{
|
||||
if (!cell.InBounds(map))
|
||||
continue;
|
||||
|
||||
// 检查屋顶
|
||||
if (props.checkRoof && map.roofGrid.Roofed(cell))
|
||||
return true;
|
||||
|
||||
// 检查建筑
|
||||
if (props.checkBuildings)
|
||||
{
|
||||
foreach (Thing thing in map.thingGrid.ThingsListAt(cell))
|
||||
{
|
||||
if (thing.def.passability == Traversability.Impassable &&
|
||||
!thing.def.IsFrame && !thing.def.IsBlueprint)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查植物
|
||||
if (props.checkPlants)
|
||||
{
|
||||
Plant plant = cell.GetPlant(map);
|
||||
if (plant != null && plant.def.passability == Traversability.Impassable)
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查地形
|
||||
if (props.checkTerrain)
|
||||
{
|
||||
TerrainDef terrain = map.terrainGrid.TerrainAt(cell);
|
||||
if (terrain != null && terrain.passability == Traversability.Impassable)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取前方需要检查的单元格
|
||||
/// </summary>
|
||||
public static List<IntVec3> GetForwardCells(IntVec3 position, Rot4 rotation, int distance)
|
||||
{
|
||||
List<IntVec3> cells = new List<IntVec3>();
|
||||
|
||||
// 根据朝向确定检查方向
|
||||
IntVec3 direction = rotation.FacingCell;
|
||||
|
||||
for (int i = 1; i <= distance; i++)
|
||||
{
|
||||
IntVec3 checkCell = position + direction * i;
|
||||
cells.Add(checkCell);
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
public override string CompInspectStringExtra()
|
||||
{
|
||||
if (IsBlocked)
|
||||
{
|
||||
return "ForwardClearanceBlocked".Translate(Props.checkDistance);
|
||||
}
|
||||
return "ForwardClearanceClear".Translate(Props.checkDistance);
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Values.Look(ref isBlocked, "isBlocked", false);
|
||||
Scribe_Values.Look(ref lastCheckedTick, "lastCheckedTick", -99999);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompProperties_ForwardClearance : CompProperties
|
||||
{
|
||||
public int checkDistance = 5; // 检查距离(格数)
|
||||
public bool checkRoof = true; // 是否检查屋顶
|
||||
public bool checkBuildings = true; // 是否检查建筑
|
||||
public bool checkPlants = false; // 是否检查植物
|
||||
public bool checkTerrain = false; // 是否检查地形
|
||||
|
||||
// 信号定义
|
||||
public string blockedSignal = "ForwardBlocked";
|
||||
public string clearSignal = "ForwardClear";
|
||||
|
||||
public CompProperties_ForwardClearance()
|
||||
{
|
||||
compClass = typeof(CompForwardClearance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class PlaceWorker_ForwardClearance : PlaceWorker
|
||||
{
|
||||
private static List<IntVec3> forwardCells = new List<IntVec3>();
|
||||
|
||||
public override void DrawGhost(ThingDef def, IntVec3 center, Rot4 rot, Color ghostCol, Thing thing = null)
|
||||
{
|
||||
// 获取清除检查组件属性
|
||||
CompProperties_ForwardClearance compProps = def.GetCompProperties<CompProperties_ForwardClearance>();
|
||||
if (compProps == null) return;
|
||||
|
||||
// 获取前方检查的单元格
|
||||
forwardCells.Clear();
|
||||
forwardCells = CompForwardClearance.GetForwardCells(center, rot, compProps.checkDistance);
|
||||
|
||||
// 绘制检查区域
|
||||
Color cellColor = GetBlockedColor(center, rot, Find.CurrentMap, compProps);
|
||||
GenDraw.DrawFieldEdges(forwardCells, cellColor);
|
||||
|
||||
// 绘制方向指示器
|
||||
DrawDirectionIndicator(center, rot, cellColor);
|
||||
}
|
||||
|
||||
public override AcceptanceReport AllowsPlacing(BuildableDef def, IntVec3 center, Rot4 rot, Map map, Thing thingToIgnore = null, Thing thing = null)
|
||||
{
|
||||
// 将 BuildableDef 转换为 ThingDef 来获取组件属性
|
||||
ThingDef thingDef = def as ThingDef;
|
||||
if (thingDef == null) return true;
|
||||
|
||||
CompProperties_ForwardClearance compProps = thingDef.GetCompProperties<CompProperties_ForwardClearance>();
|
||||
if (compProps == null) return true;
|
||||
|
||||
// 检查前方是否有遮挡
|
||||
if (CompForwardClearance.IsForwardBlocked(center, rot, map, compProps))
|
||||
{
|
||||
return new AcceptanceReport("ForwardClearanceBlockedPlacement".Translate(compProps.checkDistance));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void PostPlace(Map map, BuildableDef def, IntVec3 loc, Rot4 rot)
|
||||
{
|
||||
// 将 BuildableDef 转换为 ThingDef 来获取组件属性
|
||||
ThingDef thingDef = def as ThingDef;
|
||||
if (thingDef == null) return;
|
||||
|
||||
CompProperties_ForwardClearance compProps = thingDef.GetCompProperties<CompProperties_ForwardClearance>();
|
||||
if (compProps == null) return;
|
||||
|
||||
// 放置后检查并发送警告
|
||||
if (CompForwardClearance.IsForwardBlocked(loc, rot, map, compProps))
|
||||
{
|
||||
Messages.Message("WarningForwardClearanceBlocked".Translate(def.LabelCap, compProps.checkDistance),
|
||||
MessageTypeDefOf.CautionInput, historical: false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据遮挡状态获取颜色
|
||||
/// </summary>
|
||||
private Color GetBlockedColor(IntVec3 center, Rot4 rot, Map map, CompProperties_ForwardClearance props)
|
||||
{
|
||||
if (CompForwardClearance.IsForwardBlocked(center, rot, map, props))
|
||||
{
|
||||
return Color.red;
|
||||
}
|
||||
return Color.green;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制方向指示器
|
||||
/// </summary>
|
||||
private void DrawDirectionIndicator(IntVec3 center, Rot4 rot, Color color)
|
||||
{
|
||||
Vector3 startPos = center.ToVector3Shifted();
|
||||
Vector3 direction = rot.FacingCell.ToVector3();
|
||||
Vector3 endPos = startPos + direction * 2f; // 2格长的方向线
|
||||
|
||||
// 使用正确的绘制方法
|
||||
Material lineMaterial = SolidColorMaterials.SimpleSolidColorMaterial(color);
|
||||
|
||||
// 绘制方向线
|
||||
GenDraw.DrawLineBetween(startPos, endPos, lineMaterial, 0.2f);
|
||||
|
||||
// 绘制方向箭头
|
||||
DrawDirectionArrow(endPos, direction, lineMaterial);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制方向箭头
|
||||
/// </summary>
|
||||
private void DrawDirectionArrow(Vector3 pos, Vector3 direction, Material material)
|
||||
{
|
||||
float arrowSize = 0.5f;
|
||||
Vector3 perpendicular = new Vector3(-direction.z, 0f, direction.x);
|
||||
|
||||
Vector3 arrowTip = pos + direction * arrowSize;
|
||||
Vector3 arrowLeft = pos - direction * arrowSize * 0.5f + perpendicular * arrowSize * 0.5f;
|
||||
Vector3 arrowRight = pos - direction * arrowSize * 0.5f - perpendicular * arrowSize * 0.5f;
|
||||
|
||||
GenDraw.DrawLineBetween(arrowTip, arrowLeft, material, 0.15f);
|
||||
GenDraw.DrawLineBetween(arrowTip, arrowRight, material, 0.15f);
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Source/ArachnaeSwarm/Building_Comps/CompBreakdownDisabler.cs
Normal file
162
Source/ArachnaeSwarm/Building_Comps/CompBreakdownDisabler.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompBreakdownDisabler : ThingComp
|
||||
{
|
||||
private CompBreakdownable breakdownable;
|
||||
private CompPowerTrader powerTrader;
|
||||
private CompRefuelable refuelable;
|
||||
private bool wasBrokenDown = false;
|
||||
|
||||
public CompProperties_BreakdownDisabler Props => (CompProperties_BreakdownDisabler)props;
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
|
||||
// 获取相关的组件
|
||||
breakdownable = parent.GetComp<CompBreakdownable>();
|
||||
powerTrader = parent.GetComp<CompPowerTrader>();
|
||||
refuelable = parent.GetComp<CompRefuelable>();
|
||||
|
||||
// 立即修复任何现有的损坏
|
||||
if (breakdownable != null && breakdownable.BrokenDown)
|
||||
{
|
||||
FixBreakdownImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
// 每 tick 检查是否需要修复
|
||||
if (breakdownable != null && breakdownable.BrokenDown && !wasBrokenDown)
|
||||
{
|
||||
FixBreakdownImmediately();
|
||||
}
|
||||
|
||||
wasBrokenDown = breakdownable?.BrokenDown ?? false;
|
||||
}
|
||||
|
||||
public override void CompTickRare()
|
||||
{
|
||||
base.CompTickRare();
|
||||
|
||||
// 每 250 ticks 检查一次(更高效)
|
||||
if (breakdownable != null && breakdownable.BrokenDown && !wasBrokenDown)
|
||||
{
|
||||
FixBreakdownImmediately();
|
||||
}
|
||||
|
||||
wasBrokenDown = breakdownable?.BrokenDown ?? false;
|
||||
}
|
||||
|
||||
public override void ReceiveCompSignal(string signal)
|
||||
{
|
||||
base.ReceiveCompSignal(signal);
|
||||
|
||||
// 监听损坏信号并立即修复
|
||||
if (signal == "Breakdown" && breakdownable != null)
|
||||
{
|
||||
FixBreakdownImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 立即修复损坏并消除所有影响
|
||||
/// </summary>
|
||||
private void FixBreakdownImmediately()
|
||||
{
|
||||
if (breakdownable == null) return;
|
||||
|
||||
// 记录修复前的状态
|
||||
bool wasPoweredOn = powerTrader?.PowerOn ?? true;
|
||||
float fuelAmount = refuelable?.Fuel ?? 0f;
|
||||
|
||||
// 调用修复方法
|
||||
breakdownable.Notify_Repaired();
|
||||
|
||||
// 恢复电力状态
|
||||
if (powerTrader != null)
|
||||
{
|
||||
// 确保电力交易器恢复正常
|
||||
if (wasPoweredOn && !powerTrader.PowerOn)
|
||||
{
|
||||
powerTrader.PowerOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复燃料状态
|
||||
if (refuelable != null)
|
||||
{
|
||||
refuelable.ConsumeFuel(0f); // 触发更新
|
||||
}
|
||||
|
||||
// 发送修复完成的信号
|
||||
parent.BroadcastCompSignal("Repaired");
|
||||
|
||||
// 记录日志(可选)
|
||||
if (Props.logRepairs)
|
||||
{
|
||||
Log.Message($"[BreakdownDisabler] Automatically repaired {parent.Label} at {parent.Position}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostDraw()
|
||||
{
|
||||
base.PostDraw();
|
||||
|
||||
// 可选:在修复时显示视觉反馈
|
||||
if (breakdownable != null && breakdownable.BrokenDown)
|
||||
{
|
||||
// 立即在下一次绘制前修复
|
||||
if (Find.TickManager.TicksGame % 10 == 0) // 每10 tick尝试修复一次
|
||||
{
|
||||
FixBreakdownImmediately();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string CompInspectStringExtra()
|
||||
{
|
||||
if (breakdownable != null && breakdownable.BrokenDown)
|
||||
{
|
||||
return "AutoRepairSystemActive".Translate();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
{
|
||||
if (breakdownable != null && breakdownable.BrokenDown)
|
||||
{
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "ForceAutoRepair".Translate(),
|
||||
defaultDesc = "ForceAutoRepairDesc".Translate(),
|
||||
icon = TexCommand.DesirePower,
|
||||
action = delegate
|
||||
{
|
||||
FixBreakdownImmediately();
|
||||
Messages.Message("ForcedAutoRepairComplete".Translate(parent.Label), parent, MessageTypeDefOf.PositiveEvent);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CompProperties_BreakdownDisabler : CompProperties
|
||||
{
|
||||
public bool logRepairs = false; // 是否在控制台记录修复日志
|
||||
public bool showVisualFeedback = true; // 是否显示视觉反馈
|
||||
|
||||
public CompProperties_BreakdownDisabler()
|
||||
{
|
||||
compClass = typeof(CompBreakdownDisabler);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,19 @@ namespace ArachnaeSwarm
|
||||
|
||||
// 自定义图形组件
|
||||
private Graphic customBaseGraphic; // 基座图形 - 始终静止
|
||||
private Graphic customOrbGraphic; // 球体图形 - 正常状态下浮动
|
||||
private Graphic customOrbGraphic; // 球体图形 - 正常状态下搏动
|
||||
private Graphic customCooldownGraphic; // 冷却球体图形 - 冷却状态下静止
|
||||
|
||||
// 渲染相关的变量
|
||||
private float orbFloatOffset = 0f;
|
||||
// 搏动相关的变量
|
||||
private float orbPulseScale = 1f; // 球体缩放比例
|
||||
private float orbPulseIntensity = 0f; // 搏动强度
|
||||
private int lastTick = -1;
|
||||
|
||||
// 记录初始缩放值
|
||||
private Vector2 baseInitialScale;
|
||||
private Vector2 orbInitialScale;
|
||||
private Vector2 cooldownInitialScale;
|
||||
|
||||
public ArachnaeGravEngineExtension ModExtension
|
||||
{
|
||||
get
|
||||
@@ -42,17 +48,18 @@ namespace ArachnaeSwarm
|
||||
if (customBaseGraphic == null)
|
||||
{
|
||||
string basePath = ModExtension?.baseTexPath ?? "ArachnaeSwarm/Building/ARA_HiveShip_Heart_Pedestal";
|
||||
baseInitialScale = ModExtension?.baseScale ?? Vector2.one * 3f;
|
||||
customBaseGraphic = GraphicDatabase.Get<Graphic_Single>(
|
||||
basePath,
|
||||
ShaderDatabase.Cutout,
|
||||
def.graphicData?.drawSize ?? Vector2.one * 3f,
|
||||
baseInitialScale,
|
||||
Color.white);
|
||||
}
|
||||
return customBaseGraphic;
|
||||
}
|
||||
}
|
||||
|
||||
// 球体图形 - 正常状态下浮动
|
||||
// 球体图形 - 正常状态下搏动
|
||||
private Graphic CustomOrbGraphic
|
||||
{
|
||||
get
|
||||
@@ -60,10 +67,11 @@ namespace ArachnaeSwarm
|
||||
if (customOrbGraphic == null)
|
||||
{
|
||||
string orbPath = ModExtension?.orbTexPath ?? "ArachnaeSwarm/Building/ARA_HiveShip_Heart";
|
||||
orbInitialScale = ModExtension?.orbScale ?? Vector2.one * 2f;
|
||||
customOrbGraphic = GraphicDatabase.Get<Graphic_Single>(
|
||||
orbPath,
|
||||
ShaderDatabase.Cutout,
|
||||
Vector2.one * 2f,
|
||||
orbInitialScale,
|
||||
Color.white);
|
||||
}
|
||||
return customOrbGraphic;
|
||||
@@ -78,10 +86,11 @@ namespace ArachnaeSwarm
|
||||
if (customCooldownGraphic == null)
|
||||
{
|
||||
string cooldownPath = ModExtension?.cooldownTexPath ?? "ArachnaeSwarm/Building/ARA_HiveShip_Heart_Cooldown";
|
||||
cooldownInitialScale = ModExtension?.cooldownScale ?? Vector2.one * 2f;
|
||||
customCooldownGraphic = GraphicDatabase.Get<Graphic_Single>(
|
||||
cooldownPath,
|
||||
ShaderDatabase.Cutout,
|
||||
Vector2.one * 2f, // 注意:这里应该和球体大小一致,而不是基座大小
|
||||
cooldownInitialScale,
|
||||
Color.white);
|
||||
}
|
||||
return customCooldownGraphic;
|
||||
@@ -110,19 +119,6 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
yield return gizmo;
|
||||
}
|
||||
|
||||
// 可以添加虫群特有的 gizmo
|
||||
if (DebugSettings.ShowDevGizmos)
|
||||
{
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "DEV: Spawn Arachnae Swarm",
|
||||
action = delegate
|
||||
{
|
||||
SpawnArachnaeSwarm();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 重写 GetFloatMenuOptions 方法,移除检查选项
|
||||
@@ -162,29 +158,16 @@ namespace ArachnaeSwarm
|
||||
text = text.Replace("GravEngineNotInspected".Translate() + "\n", "");
|
||||
}
|
||||
|
||||
// 添加虫群特有的信息
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
text += "\n";
|
||||
}
|
||||
text += "ArachnaeSwarmControl".Translate();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
// 虫群特有的方法
|
||||
private void SpawnArachnaeSwarm()
|
||||
{
|
||||
Messages.Message("ArachnaeSwarmActivated".Translate(), this, MessageTypeDefOf.PositiveEvent);
|
||||
}
|
||||
|
||||
// 完全重写 DrawAt 方法,实现自定义渲染系统
|
||||
protected override void DrawAt(Vector3 drawLoc, bool flip = false)
|
||||
{
|
||||
// 不调用基类的 DrawAt,完全自定义渲染
|
||||
|
||||
// 更新浮动效果
|
||||
UpdateFloatOffsets();
|
||||
// 更新搏动效果
|
||||
UpdatePulseEffect();
|
||||
|
||||
// 基础位置 - 底座始终静止
|
||||
Vector3 baseDrawPos = drawLoc;
|
||||
@@ -192,49 +175,75 @@ namespace ArachnaeSwarm
|
||||
|
||||
// 球体位置 - 根据状态决定
|
||||
Vector3 orbDrawPos = drawLoc;
|
||||
orbDrawPos.y += 0.03658537f; // 基础高度偏移
|
||||
orbDrawPos.z += 0.05f; // 球体稍微向前偏移,避免与底座重叠
|
||||
orbDrawPos.y += 0.05f; // 球体稍微向前偏移,避免与底座重叠
|
||||
orbDrawPos.z += 0.05f;
|
||||
|
||||
// 始终绘制底座
|
||||
CustomBaseGraphic.Draw(baseDrawPos, flip ? base.Rotation.Opposite : base.Rotation, this, 0f);
|
||||
|
||||
// 根据状态绘制球体
|
||||
if (Find.TickManager.TicksGame >= cooldownCompleteTick)
|
||||
{
|
||||
// 正常状态:球体浮动
|
||||
orbDrawPos.y += orbFloatOffset;
|
||||
CustomOrbGraphic.Draw(orbDrawPos, flip ? base.Rotation.Opposite : base.Rotation, this, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 冷却状态:球体静止,使用冷却贴图
|
||||
CustomCooldownGraphic.Draw(orbDrawPos, flip ? base.Rotation.Opposite : base.Rotation, this, 0f);
|
||||
}
|
||||
DrawPulsingOrb(orbDrawPos, flip ? base.Rotation.Opposite : base.Rotation, CustomOrbGraphic);
|
||||
}
|
||||
|
||||
// 更新浮动效果 - 只更新球体浮动
|
||||
private void UpdateFloatOffsets()
|
||||
// 绘制搏动的球体
|
||||
private void DrawPulsingOrb(Vector3 drawPos, Rot4 rotation, Graphic graphic)
|
||||
{
|
||||
// 计算搏动缩放,基于初始缩放
|
||||
Vector3 baseScale = new Vector3(orbInitialScale.x, 1f, orbInitialScale.y);
|
||||
Vector3 pulseScale = Vector3.one * orbPulseScale;
|
||||
Vector3 finalScale = Vector3.Scale(baseScale, pulseScale);
|
||||
|
||||
// 创建缩放矩阵
|
||||
Matrix4x4 matrix = Matrix4x4.TRS(drawPos, rotation.AsQuat, finalScale);
|
||||
|
||||
// 获取材质
|
||||
Material material = graphic.MatSingle;
|
||||
|
||||
// 绘制缩放后的球体
|
||||
Graphics.DrawMesh(MeshPool.plane10, matrix, material, 0);
|
||||
}
|
||||
|
||||
// 更新搏动效果 - 类似心脏搏动的放大缩小
|
||||
private void UpdatePulseEffect()
|
||||
{
|
||||
int currentTick = Find.TickManager.TicksGame;
|
||||
|
||||
if (currentTick != lastTick)
|
||||
{
|
||||
// 只在非冷却状态下更新球体浮动
|
||||
// 只在非冷却状态下更新球体搏动
|
||||
if (Find.TickManager.TicksGame >= cooldownCompleteTick)
|
||||
{
|
||||
// 球体浮动 - 上下浮动
|
||||
orbFloatOffset = Mathf.Sin((float)currentTick / 100f) * 0.1f;
|
||||
// 心脏搏动效果
|
||||
float time = (float)currentTick / 60f; // 控制搏动速度
|
||||
|
||||
// 使用更自然的搏动曲线
|
||||
// 快速收缩然后缓慢舒张,类似真实心跳
|
||||
float pulse = Mathf.Sin(time * 3f) * 0.5f + 0.5f; // 0到1的范围
|
||||
|
||||
// 应用非线性变换,使搏动更自然
|
||||
pulse = EaseInOutCubic(pulse);
|
||||
|
||||
// 计算缩放比例 (0.9到1.1的范围)
|
||||
orbPulseScale = 0.9f + pulse * 0.2f;
|
||||
|
||||
// 搏动强度用于可能的其他效果
|
||||
orbPulseIntensity = pulse;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 冷却状态下球体不浮动
|
||||
orbFloatOffset = 0f;
|
||||
// 冷却状态下球体不搏动,保持正常大小
|
||||
orbPulseScale = 1f;
|
||||
orbPulseIntensity = 0f;
|
||||
}
|
||||
|
||||
lastTick = currentTick;
|
||||
}
|
||||
}
|
||||
|
||||
// 缓动函数 - 使搏动更自然
|
||||
private float EaseInOutCubic(float x)
|
||||
{
|
||||
return x < 0.5f ? 4f * x * x * x : 1f - Mathf.Pow(-2f * x + 2f, 3f) / 2f;
|
||||
}
|
||||
|
||||
// 重写额外的绘制阶段(如果需要)
|
||||
public override void DrawExtraSelectionOverlays()
|
||||
{
|
||||
@@ -264,11 +273,16 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
// 扩展 ModExtension 定义,添加基座纹理路径
|
||||
// 扩展 ModExtension 定义,添加基座纹理路径和缩放参数
|
||||
public class ArachnaeGravEngineExtension : DefModExtension
|
||||
{
|
||||
public string baseTexPath; // 基座纹理路径 - 始终静止
|
||||
public string orbTexPath; // 球体纹理路径 - 正常状态下浮动
|
||||
public string orbTexPath; // 球体纹理路径 - 正常状态下搏动
|
||||
public string cooldownTexPath; // 冷却球体纹理路径 - 冷却状态下静止
|
||||
|
||||
// 新增:各部分的初始缩放比例
|
||||
public Vector2 baseScale = Vector2.one * 3f; // 基座默认缩放
|
||||
public Vector2 orbScale = Vector2.one * 2f; // 球体默认缩放
|
||||
public Vector2 cooldownScale = Vector2.one * 2f; // 冷却球体默认缩放
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user