This commit is contained in:
Tourswen
2025-11-30 14:39:22 +08:00
parent 14a2cf542c
commit 6a5c5bd9aa
60 changed files with 3121 additions and 670 deletions

View File

@@ -23,6 +23,9 @@ namespace WulaFallenEmpire
public int StoredCount => storedMechanoidCount;
public int MaxStorage => Props.maxStorageCapacity;
public bool IsCooldownActive => Find.TickManager.TicksGame - spawnTick < 24 * 2500; // 24小时冷却
// 新增:检查是否属于玩家派系
public bool IsPlayerFaction => this.Faction == Faction.OfPlayer;
// 生成初始单位(改为计数)
private void SpawnInitialUnits()
@@ -192,6 +195,10 @@ namespace WulaFallenEmpire
foreach (Gizmo g in base.GetGizmos())
yield return g;
// 新增:只有玩家派系才能看到和使用这些按钮
if (!IsPlayerFaction)
yield break;
// 回收附近机械族按钮
Command_Action recycleCommand = new Command_Action
{

View File

@@ -24,10 +24,24 @@ namespace WulaFallenEmpire
return _worldComponent;
}
}
private GlobalStorageWorldComponent _globalStorage;
private GlobalStorageWorldComponent GlobalStorage
{
get
{
if (_globalStorage == null)
{
_globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
}
return _globalStorage;
}
}
private bool used = false;
private int callTick = -1;
private bool calling = false;
private bool usedGlobalStorage = false; // 新增:标记是否使用了全局储存器
public bool CanCall => !used && !calling;
@@ -119,6 +133,7 @@ namespace WulaFallenEmpire
Scribe_Values.Look(ref used, "used", false);
Scribe_Values.Look(ref callTick, "callTick", -1);
Scribe_Values.Look(ref calling, "calling", false);
Scribe_Values.Look(ref usedGlobalStorage, "usedGlobalStorage", false);
}
public override void CompTick()
@@ -166,7 +181,11 @@ namespace WulaFallenEmpire
}
else
{
Messages.Message("WULA_SkyfallerIncoming".Translate(delay.ToStringTicksToPeriod()), parent, MessageTypeDefOf.ThreatBig);
// 修改:根据资源来源显示不同的消息
string messageKey = usedGlobalStorage ?
"WULA_SkyfallerIncomingFromGlobal" :
"WULA_SkyfallerIncoming";
Messages.Message(messageKey.Translate(delay.ToStringTicksToPeriod()), parent, MessageTypeDefOf.ThreatBig);
}
}
@@ -175,6 +194,7 @@ namespace WulaFallenEmpire
calling = false;
used = false;
callTick = -1;
usedGlobalStorage = false;
}
protected virtual void ExecuteSkyfallerCall()
@@ -187,14 +207,17 @@ namespace WulaFallenEmpire
return;
}
if (!HasEnoughMaterials())
// 修改:使用新的资源检查方法
var resourceCheck = CheckAndConsumeMaterials();
if (!resourceCheck.HasEnoughMaterials)
{
Log.Message($"[SkyfallerCaller] Aborting skyfaller call due to insufficient materials.");
ResetCall();
return;
}
ConsumeMaterials();
// 记录是否使用了全局储存器
usedGlobalStorage = resourceCheck.UsedGlobalStorage;
// 检查屋顶并处理
HandleRoofDestruction();
@@ -251,18 +274,106 @@ namespace WulaFallenEmpire
}
}
protected bool HasEnoughMaterials()
// 新增:资源检查结果结构
protected struct ResourceCheckResult
{
if (DebugSettings.godMode) return true;
public bool HasEnoughMaterials;
public bool UsedGlobalStorage;
public Dictionary<ThingDef, int> BeaconMaterials;
public Dictionary<ThingDef, int> GlobalMaterials;
}
// 修改:新的资源检查方法,优先检查信标附近,然后检查全局储存器
protected ResourceCheckResult CheckAndConsumeMaterials()
{
var result = new ResourceCheckResult
{
HasEnoughMaterials = false,
UsedGlobalStorage = false,
BeaconMaterials = new Dictionary<ThingDef, int>(),
GlobalMaterials = new Dictionary<ThingDef, int>()
};
if (DebugSettings.godMode)
{
result.HasEnoughMaterials = true;
return result;
}
var costList = CostList;
if (costList.NullOrEmpty())
{
return true;
result.HasEnoughMaterials = true;
return result;
}
var availableThings = new List<Thing>();
if (parent.Map == null) return false;
if (parent.Map == null)
{
return result;
}
// 第一步:收集信标附近的可用物资
var beaconMaterials = CollectBeaconMaterials();
result.BeaconMaterials = beaconMaterials;
// 第二步:检查信标附近物资是否足够
bool beaconHasEnough = true;
foreach (var cost in costList)
{
int availableInBeacon = beaconMaterials.ContainsKey(cost.thingDef) ? beaconMaterials[cost.thingDef] : 0;
if (availableInBeacon < cost.count)
{
beaconHasEnough = false;
break;
}
}
// 第三步:如果信标附近物资足够,只消耗信标附近的
if (beaconHasEnough)
{
ConsumeBeaconMaterials(beaconMaterials, costList);
result.HasEnoughMaterials = true;
result.UsedGlobalStorage = false;
return result;
}
// 第四步:如果信标附近物资不足,检查全局储存器
var globalMaterials = CheckGlobalStorageMaterials();
result.GlobalMaterials = globalMaterials;
bool globalHasEnough = true;
foreach (var cost in costList)
{
int availableInBeacon = beaconMaterials.ContainsKey(cost.thingDef) ? beaconMaterials[cost.thingDef] : 0;
int availableInGlobal = globalMaterials.ContainsKey(cost.thingDef) ? globalMaterials[cost.thingDef] : 0;
if (availableInBeacon + availableInGlobal < cost.count)
{
globalHasEnough = false;
break;
}
}
if (globalHasEnough)
{
// 先消耗信标附近的,不足部分从全局储存器扣除
ConsumeMixedMaterials(beaconMaterials, globalMaterials, costList);
result.HasEnoughMaterials = true;
result.UsedGlobalStorage = true;
return result;
}
// 两种来源加起来都不够
result.HasEnoughMaterials = false;
return result;
}
// 新增:收集信标附近的物资
private Dictionary<ThingDef, int> CollectBeaconMaterials()
{
var materials = new Dictionary<ThingDef, int>();
if (parent.Map == null) return materials;
foreach (Building_OrbitalTradeBeacon beacon in Building_OrbitalTradeBeacon.AllPowered(parent.Map))
{
@@ -274,46 +385,49 @@ namespace WulaFallenEmpire
Thing thing = thingList[i];
if (thing.def.EverHaulable)
{
availableThings.Add(thing);
if (materials.ContainsKey(thing.def))
{
materials[thing.def] += thing.stackCount;
}
else
{
materials[thing.def] = thing.stackCount;
}
}
}
}
}
availableThings = availableThings.Distinct().ToList();
return materials;
}
// 新增:检查全局储存器中的物资
private Dictionary<ThingDef, int> CheckGlobalStorageMaterials()
{
var materials = new Dictionary<ThingDef, int>();
if (GlobalStorage == null) return materials;
var costList = CostList;
if (costList.NullOrEmpty()) return materials;
foreach (var cost in costList)
{
int count = 0;
foreach (var thing in availableThings)
int globalCount = GlobalStorage.GetInputStorageCount(cost.thingDef);
if (globalCount > 0)
{
if (thing.def == cost.thingDef)
{
count += thing.stackCount;
}
}
if (count < cost.count)
{
return false;
materials[cost.thingDef] = globalCount;
}
}
return true;
return materials;
}
protected void ConsumeMaterials()
// 新增:只消耗信标附近的物资
private void ConsumeBeaconMaterials(Dictionary<ThingDef, int> beaconMaterials, List<ThingDefCountClass> costList)
{
if (DebugSettings.godMode) return;
var costList = CostList;
if (costList.NullOrEmpty())
{
return;
}
var tradeableThings = new List<Thing>();
if (parent.Map == null) return;
foreach (Building_OrbitalTradeBeacon beacon in Building_OrbitalTradeBeacon.AllPowered(parent.Map))
{
foreach (IntVec3 cell in beacon.TradeableCells)
@@ -329,13 +443,11 @@ namespace WulaFallenEmpire
}
}
}
tradeableThings = tradeableThings.Distinct().ToList();
foreach (var cost in costList)
{
int remaining = cost.count;
for (int i = tradeableThings.Count - 1; i >= 0; i--)
for (int i = tradeableThings.Count - 1; i >= 0 && remaining > 0; i--)
{
var thing = tradeableThings[i];
if (thing.def == cost.thingDef)
@@ -349,16 +461,123 @@ namespace WulaFallenEmpire
{
remaining -= thing.stackCount;
thing.Destroy();
}
if (remaining <= 0)
{
break;
tradeableThings.RemoveAt(i);
}
}
}
}
}
// 新增:混合消耗信标和全局储存器的物资
private void ConsumeMixedMaterials(Dictionary<ThingDef, int> beaconMaterials, Dictionary<ThingDef, int> globalMaterials, List<ThingDefCountClass> costList)
{
// 先消耗信标附近的物资
var tradeableThings = new List<Thing>();
foreach (Building_OrbitalTradeBeacon beacon in Building_OrbitalTradeBeacon.AllPowered(parent.Map))
{
foreach (IntVec3 cell in beacon.TradeableCells)
{
List<Thing> thingList = parent.Map.thingGrid.ThingsListAt(cell);
for (int i = 0; i < thingList.Count; i++)
{
Thing thing = thingList[i];
if (thing.def.EverHaulable)
{
tradeableThings.Add(thing);
}
}
}
}
// 对每种所需材料进行处理
foreach (var cost in costList)
{
int remaining = cost.count;
// 第一步:消耗信标附近的物资
for (int i = tradeableThings.Count - 1; i >= 0 && remaining > 0; i--)
{
var thing = tradeableThings[i];
if (thing.def == cost.thingDef)
{
if (thing.stackCount > remaining)
{
thing.SplitOff(remaining);
remaining = 0;
}
else
{
remaining -= thing.stackCount;
thing.Destroy();
tradeableThings.RemoveAt(i);
}
}
}
// 第二步:如果还有剩余,从全局储存器扣除
if (remaining > 0 && GlobalStorage != null)
{
GlobalStorage.RemoveFromInputStorage(cost.thingDef, remaining);
}
}
}
// 保留原有的 HasEnoughMaterials 方法用于 Gizmo 显示
protected bool HasEnoughMaterials()
{
if (DebugSettings.godMode) return true;
var costList = CostList;
if (costList.NullOrEmpty())
{
return true;
}
// 第一步:检查信标附近物资
var beaconMaterials = CollectBeaconMaterials();
bool beaconHasEnough = true;
foreach (var cost in costList)
{
int availableInBeacon = beaconMaterials.ContainsKey(cost.thingDef) ? beaconMaterials[cost.thingDef] : 0;
if (availableInBeacon < cost.count)
{
beaconHasEnough = false;
break;
}
}
if (beaconHasEnough) return true;
// 第二步:检查全局储存器(如果信标附近不够)
if (GlobalStorage == null) return false;
foreach (var cost in costList)
{
int availableInBeacon = beaconMaterials.ContainsKey(cost.thingDef) ? beaconMaterials[cost.thingDef] : 0;
int availableInGlobal = GlobalStorage.GetInputStorageCount(cost.thingDef);
if (availableInBeacon + availableInGlobal < cost.count)
{
return false;
}
}
return true;
}
// 原有的 ConsumeMaterials 方法现在只用于 God Mode 情况
protected void ConsumeMaterials()
{
if (DebugSettings.godMode) return;
// 在非 God Mode 下,这个方法不应该被调用
// 实际的消耗在 CheckAndConsumeMaterials 中处理
Log.Warning("[SkyfallerCaller] ConsumeMaterials called in non-God mode, this shouldn't happen");
}
// 其余方法保持不变...
private string GetCostString()
{
var costList = CostList;
@@ -379,6 +598,7 @@ namespace WulaFallenEmpire
calling = false;
used = false;
callTick = -1;
usedGlobalStorage = false;
Messages.Message("WULA_SkyfallerCallCancelled".Translate(), parent, MessageTypeDefOf.NeutralEvent);
}
@@ -451,6 +671,9 @@ namespace WulaFallenEmpire
sb.Append(costString);
}
// 新增:显示资源来源信息
sb.AppendLine().AppendLine().Append("WULA_ResourcePriorityInfo".Translate());
return sb.ToString();
}
@@ -501,7 +724,10 @@ namespace WulaFallenEmpire
int ticksLeft = callTick - Find.TickManager.TicksGame;
if (ticksLeft > 0)
{
sb.Append("WULA_SkyfallerArrivingIn".Translate(ticksLeft.ToStringTicksToPeriod()));
string messageKey = usedGlobalStorage ?
"WULA_SkyfallerArrivingInFromGlobal" :
"WULA_SkyfallerArrivingIn";
sb.Append(messageKey.Translate(ticksLeft.ToStringTicksToPeriod()));
}
}
else if (!used)

View File

@@ -83,22 +83,34 @@ namespace WulaFallenEmpire
}
}
private void PlayTransformEffects(IntVec3 position, Map map)
{
//// 播放转换视觉效果
//for (int i = 0; i < 3; i++)
//{
// MoteMaker.ThrowSmoke(position.ToVector3Shifted() + new Vector3(0, 0, 0.5f), map, 1.5f);
// MoteMaker.ThrowLightningGlow(position.ToVector3Shifted(), map, 2f);
//}
//// 播放音效
//SoundDefOf.PsychicPulseGlobal.PlayOneShot(new TargetInfo(position, map));
}
public void TransformToPawn()
{
if (Recycler == null || !parent.Spawned)
return;
Map map = parent.Map;
IntVec3 position = parent.Position;
Faction faction = parent.Faction;
// 记录建筑定义用于后续更新
ThingDef buildingDef = parent.def;
// 消耗存储的机械族
if (!Recycler.ConsumeMechanoids(Props.requiredCapacity))
{
Messages.Message("WULA_NotEnoughMechs".Translate(), MessageTypeDefOf.RejectInput);
return;
}
// 生成目标Pawn
PawnGenerationRequest request = new PawnGenerationRequest(
Props.targetPawnKind,
@@ -111,9 +123,8 @@ namespace WulaFallenEmpire
canGeneratePawnRelations: false,
mustBeCapableOfViolence: true
);
Pawn newPawn = PawnGenerator.GeneratePawn(request);
// 关键修改传递当前的机械族数量6个
var transformComp = newPawn.GetComp<CompTransformIntoBuilding>();
if (transformComp != null)
@@ -136,37 +147,24 @@ namespace WulaFallenEmpire
// 传递建筑定义和机械族数量
transformComp.SetRestoreData(parent.def, Props.requiredCapacity);
}
// 移除建筑
parent.DeSpawn(DestroyMode.Vanish);
// 生成Pawn
GenSpawn.Spawn(newPawn, position, map, WipeMode.Vanish);
// 选中新生成的Pawn
if (Find.Selector.IsSelected(parent))
{
Find.Selector.Select(newPawn);
}
Messages.Message("WULA_BuildingTransformedToPawn".Translate(parent.Label, newPawn.LabelCap, Props.requiredCapacity),
Messages.Message("WULA_BuildingTransformedToPawn".Translate(parent.Label, newPawn.LabelCap, Props.requiredCapacity),
MessageTypeDefOf.PositiveEvent);
// 播放转换效果
PlayTransformEffects(position, map);
}
private void PlayTransformEffects(IntVec3 position, Map map)
{
//// 播放转换视觉效果
//for (int i = 0; i < 3; i++)
//{
// MoteMaker.ThrowSmoke(position.ToVector3Shifted() + new Vector3(0, 0, 0.5f), map, 1.5f);
// MoteMaker.ThrowLightningGlow(position.ToVector3Shifted(), map, 2f);
//}
//// 播放音效
//SoundDefOf.PsychicPulseGlobal.PlayOneShot(new TargetInfo(position, map));
Log.Message($"[TransformSystem] Building -> Pawn transformation completed at {position}. Path grid updated.");
}
}
}

View File

@@ -77,7 +77,6 @@ namespace WulaFallenEmpire
// 显示恢复的机械族数量
sb.AppendLine();
sb.Append("WULA_RestoreMechCount".Translate(restoreMechCount));
// 显示目标建筑的最大存储容量
var recyclerProps = restoreBuildingDef.GetCompProperties<CompProperties_MechanoidRecycler>();
@@ -195,88 +194,6 @@ namespace WulaFallenEmpire
return false;
}
public void TransformToBuilding()
{
if (Pawn == null || !Pawn.Spawned)
return;
Map map = Pawn.Map;
IntVec3 desiredPosition = Pawn.Position;
Faction faction = Pawn.Faction;
// 确定要生成的建筑类型
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
if (buildingDef == null)
{
Messages.Message("WULA_CannotDetermineBuildingType".Translate(), MessageTypeDefOf.RejectInput);
return;
}
// 最终校验排除被转换的Pawn本身
string failReason;
if (!TransformValidationUtility.CanPlaceBuildingAt(buildingDef, desiredPosition, map, faction, Pawn, out failReason))
{
// 尝试寻找附近的位置
IntVec3 alternativePosition;
if (TryFindNearbyValidPosition(out alternativePosition, out failReason))
{
desiredPosition = alternativePosition;
Messages.Message("WULA_DeployingAtNearbyPosition".Translate(desiredPosition), MessageTypeDefOf.NeutralEvent);
}
else
{
Messages.Message("WULA_CannotDeployBuilding".Translate(failReason), MessageTypeDefOf.RejectInput);
return;
}
}
// 移除Pawn
Pawn.DeSpawn(DestroyMode.Vanish);
// 生成建筑
Building newBuilding = (Building)GenSpawn.Spawn(buildingDef, desiredPosition, map, WipeMode.Vanish);
newBuilding.SetFaction(faction);
// 关键修改:恢复机械族数量
var recycler = newBuilding as Building_MechanoidRecycler;
if (recycler != null)
{
recycler.SetMechanoidCount(restoreMechCount);
}
// 添加建筑转换组件
var transformComp = newBuilding.TryGetComp<CompTransformAtFullCapacity>();
if (transformComp == null)
{
// 动态添加组件
var compProps = new CompProperties_TransformAtFullCapacity
{
targetPawnKind = Pawn.kindDef
};
transformComp = new CompTransformAtFullCapacity();
transformComp.parent = newBuilding;
transformComp.props = compProps;
newBuilding.AllComps.Add(transformComp);
transformComp.Initialize(compProps);
}
// 选中新生成的建筑
if (Find.Selector.IsSelected(Pawn))
{
Find.Selector.Select(newBuilding);
}
Messages.Message("WULA_PawnDeployedAsBuilding".Translate(Pawn.LabelCap, newBuilding.Label, restoreMechCount),
MessageTypeDefOf.PositiveEvent);
// 播放转换效果
PlayTransformEffects(desiredPosition, map);
// 清除缓存
lastValidationResult = null;
lastValidationReason = null;
}
private void PlayTransformEffects(IntVec3 position, Map map)
{
// 播放转换视觉效果
@@ -298,5 +215,80 @@ namespace WulaFallenEmpire
lastValidationResult = null;
}
}
public void TransformToBuilding()
{
if (Pawn == null || !Pawn.Spawned)
return;
Map map = Pawn.Map;
IntVec3 desiredPosition = Pawn.Position;
Faction faction = Pawn.Faction;
// 确定要生成的建筑类型
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
if (buildingDef == null)
{
Messages.Message("WULA_CannotDetermineBuildingType".Translate(), MessageTypeDefOf.RejectInput);
return;
}
// 最终校验排除被转换的Pawn本身
string failReason;
if (!TransformValidationUtility.CanPlaceBuildingAt(buildingDef, desiredPosition, map, faction, Pawn, out failReason))
{
// 尝试寻找附近的位置
IntVec3 alternativePosition;
if (TryFindNearbyValidPosition(out alternativePosition, out failReason))
{
desiredPosition = alternativePosition;
Messages.Message("WULA_DeployingAtNearbyPosition".Translate(desiredPosition), MessageTypeDefOf.NeutralEvent);
}
else
{
Messages.Message("WULA_CannotDeployBuilding".Translate(failReason), MessageTypeDefOf.RejectInput);
return;
}
}
// 移除Pawn
Pawn.DeSpawn(DestroyMode.Vanish);
// 生成建筑
Building newBuilding = (Building)GenSpawn.Spawn(buildingDef, desiredPosition, map, WipeMode.Vanish);
newBuilding.SetFaction(faction);
// 关键修改:恢复机械族数量
var recycler = newBuilding as Building_MechanoidRecycler;
if (recycler != null)
{
recycler.SetMechanoidCount(restoreMechCount);
}
// 添加建筑转换组件
var transformComp = newBuilding.TryGetComp<CompTransformAtFullCapacity>();
if (transformComp == null)
{
// 动态添加组件
var compProps = new CompProperties_TransformAtFullCapacity
{
targetPawnKind = Pawn.kindDef
};
transformComp = new CompTransformAtFullCapacity();
transformComp.parent = newBuilding;
transformComp.props = compProps;
newBuilding.AllComps.Add(transformComp);
transformComp.Initialize(compProps);
}
// 选中新生成的建筑
if (Find.Selector.IsSelected(Pawn))
{
Find.Selector.Select(newBuilding);
}
Messages.Message("WULA_PawnDeployedAsBuilding".Translate(Pawn.LabelCap, newBuilding.Label, restoreMechCount),
MessageTypeDefOf.PositiveEvent);
// 播放转换效果
PlayTransformEffects(desiredPosition, map);
// 清除缓存
lastValidationResult = null;
lastValidationReason = null;
Log.Message($"[TransformSystem] Pawn -> Building transformation completed at {desiredPosition}. Path grid updated.");
}
}
}

View File

@@ -35,181 +35,10 @@ namespace WulaFallenEmpire
private static readonly Color CustomButtonTextNormalColor = new Color(0.9f, 0.9f, 0.9f, 1f);
private static readonly Color CustomButtonTextHoverColor = new Color(1f, 1f, 1f, 1f);
private static readonly Color CustomButtonTextDisabledColor = new Color(0.6f, 0.6f, 0.6f, 1f);
// 绘制单个选项 - 使用自定义样式
private void DrawSingleOption(Rect rect, EventOption option)
{
string reason;
bool conditionsMet = AreConditionsMet(option.conditions, out reason);
// 水平居中选项
float optionWidth = Mathf.Min(rect.width, Config.optionSize.x * (rect.width / Config.windowSize.x));
float optionX = rect.x + (rect.width - optionWidth) / 2;
Rect optionRect = new Rect(optionX, rect.y, optionWidth, rect.height);
// 保存原始状态
Color originalColor = GUI.color;
GameFont originalFont = Text.Font;
Color originalTextColor = GUI.contentColor;
TextAnchor originalAnchor = Text.Anchor;
try
{
// 设置文本居中
Text.Anchor = TextAnchor.MiddleCenter;
Text.Font = GameFont.Small;
if (conditionsMet)
{
// 启用状态的选项 - 使用自定义样式
if (option.useCustomColors)
{
// 使用选项自定义颜色
DrawCustomButtonWithColors(optionRect, option.label.Translate(), option);
}
else
{
// 使用默认自定义颜色
DrawCustomButton(optionRect, option.label.Translate(), isEnabled: true);
}
// 添加点击处理
if (Widgets.ButtonInvisible(optionRect))
{
HandleAction(option.optionEffects);
}
}
else
{
// 禁用状态的选项 - 使用自定义禁用样式
if (option.useCustomColors && option.disabledColor.HasValue)
{
// 使用选项自定义禁用颜色
DrawCustomButtonWithColors(optionRect, option.label.Translate(), option, isEnabled: false);
}
else
{
// 使用默认自定义禁用颜色
DrawCustomButton(optionRect, option.label.Translate(), isEnabled: false);
}
// 添加禁用提示
TooltipHandler.TipRegion(optionRect, GetDisabledReason(option, reason).Translate());
}
}
finally
{
// 恢复原始状态
GUI.color = originalColor;
Text.Font = originalFont;
GUI.contentColor = originalTextColor;
Text.Anchor = originalAnchor;
}
}
/// <summary>
/// 绘制自定义按钮(基础版本)
/// </summary>
private void DrawCustomButton(Rect rect, string label, bool isEnabled = true)
{
bool isMouseOver = Mouse.IsOver(rect);
// 确定按钮状态颜色
Color buttonColor, textColor;
if (!isEnabled)
{
// 禁用状态
buttonColor = CustomButtonDisabledColor;
textColor = CustomButtonTextDisabledColor;
}
else if (isMouseOver)
{
// 悬停状态
buttonColor = CustomButtonHoverColor;
textColor = CustomButtonTextHoverColor;
}
else
{
// 正常状态
buttonColor = CustomButtonNormalColor;
textColor = CustomButtonTextNormalColor;
}
// 绘制按钮背景
GUI.color = buttonColor;
Widgets.DrawBoxSolid(rect, buttonColor);
// 绘制边框
if (isEnabled)
{
Widgets.DrawBox(rect, 1);
}
else
{
// 禁用状态的边框更细更暗
Widgets.DrawBox(rect, 1);
}
// 绘制文本
GUI.color = textColor;
Text.Anchor = TextAnchor.MiddleCenter;
Widgets.Label(rect.ContractedBy(4f), label);
// 如果是禁用状态,添加删除线效果
if (!isEnabled)
{
GUI.color = new Color(0.6f, 0.6f, 0.6f, 0.8f);
Widgets.DrawLine(
new Vector2(rect.x + 10f, rect.center.y),
new Vector2(rect.xMax - 10f, rect.center.y),
GUI.color,
1f
);
}
}
/// <summary>
/// 绘制自定义按钮(使用选项自定义颜色)
/// </summary>
private void DrawCustomButtonWithColors(Rect rect, string label, EventOption option, bool isEnabled = true)
{
bool isMouseOver = Mouse.IsOver(rect);
// 确定按钮状态颜色
Color buttonColor, textColor;
if (!isEnabled)
{
// 禁用状态
buttonColor = option.disabledColor ?? CustomButtonDisabledColor;
textColor = option.textDisabledColor ?? CustomButtonTextDisabledColor;
}
else if (isMouseOver)
{
// 悬停状态
buttonColor = option.hoverColor ?? CustomButtonHoverColor;
textColor = option.textHoverColor ?? CustomButtonTextHoverColor;
}
else
{
// 正常状态
buttonColor = option.normalColor ?? CustomButtonNormalColor;
textColor = option.textColor ?? CustomButtonTextNormalColor;
}
// 绘制按钮背景
GUI.color = buttonColor;
Widgets.DrawBoxSolid(rect, buttonColor);
// 绘制边框
Widgets.DrawBox(rect);
// 绘制文本
GUI.color = textColor;
Text.Anchor = TextAnchor.MiddleCenter;
Widgets.Label(rect.ContractedBy(4f), label);
// 如果是禁用状态,添加删除线效果
if (!isEnabled)
{
GUI.color = new Color(0.6f, 0.6f, 0.6f, 0.8f);
Widgets.DrawLine(
new Vector2(rect.x + 10f, rect.center.y),
new Vector2(rect.xMax - 10f, rect.center.y),
GUI.color,
1f
);
}
}
// 滚动位置
private Vector2 descriptionScrollPosition = Vector2.zero;
private Vector2 optionsScrollPosition = Vector2.zero;
// 使用配置的窗口尺寸
public override Vector2 InitialSize
@@ -397,7 +226,7 @@ namespace WulaFallenEmpire
currentY += nameRect.height + Config.GetScaledMargin(Config.characterNameMargins.y, inRect);
}
// 4. 描述
// 4. 描述 - 修复滚动问题
if (Config.showDescriptions)
{
currentY += Config.GetScaledMargin(Config.descriptionsMargins.x, inRect);
@@ -414,13 +243,8 @@ namespace WulaFallenEmpire
Vector2 scaledDescriptionsPadding = Config.GetScaledDescriptionsPadding(descriptionRect);
Rect descriptionInnerRect = descriptionRect.ContractedBy(scaledDescriptionsPadding.y, scaledDescriptionsPadding.x);
// 使用可滚动的文本区域
float textHeight = Text.CalcHeight(selectedDescription, descriptionInnerRect.width);
Rect viewRect = new Rect(0, 0, descriptionInnerRect.width, Mathf.Max(textHeight, descriptionInnerRect.height));
Widgets.BeginScrollView(descriptionInnerRect, ref descriptionScrollPosition, viewRect);
Widgets.Label(new Rect(0, 0, viewRect.width, viewRect.height), selectedDescription);
Widgets.EndScrollView();
// 修复:使用正确的滚动视图设置,只显示纵向滚动条
DrawDescriptionScrollView(descriptionInnerRect, selectedDescription);
currentY += descriptionRect.height + Config.GetScaledMargin(Config.descriptionsMargins.y, inRect);
}
@@ -453,9 +277,227 @@ namespace WulaFallenEmpire
}
}
// 滚动位置
private Vector2 descriptionScrollPosition = Vector2.zero;
private Vector2 optionsScrollPosition = Vector2.zero;
/// <summary>
/// 修复的描述区域滚动视图 - 只显示纵向滚动条
/// </summary>
private void DrawDescriptionScrollView(Rect outRect, string text)
{
try
{
// 计算文本高度 - 使用outRect的宽度减去滚动条宽度来计算
float scrollbarWidth = 16f; // 滚动条的标准宽度
float textAreaWidth = outRect.width - scrollbarWidth;
// 确保文本区域宽度为正数
if (textAreaWidth <= 0)
textAreaWidth = outRect.width;
float textHeight = Text.CalcHeight(text, textAreaWidth);
// 创建视图矩形 - 宽度设置为文本区域宽度,高度为计算出的文本高度
Rect viewRect = new Rect(0f, 0f, textAreaWidth, Mathf.Max(textHeight, outRect.height));
// 开始滚动视图 - 只显示纵向滚动条
Widgets.BeginScrollView(outRect, ref descriptionScrollPosition, viewRect, false);
{
// 绘制文本 - 使用视图矩形的宽度确保文本正确换行
Rect textRect = new Rect(0f, 0f, viewRect.width, viewRect.height);
Widgets.Label(textRect, text);
}
Widgets.EndScrollView();
}
catch (Exception ex)
{
// 错误处理:如果滚动视图出现问题,回退到简单标签
Log.Warning($"[CustomDisplay] Error in description scroll view: {ex.Message}");
Widgets.Label(outRect, text);
}
}
// 绘制单个选项 - 使用自定义样式
private void DrawSingleOption(Rect rect, EventOption option)
{
string reason;
bool conditionsMet = AreConditionsMet(option.conditions, out reason);
// 水平居中选项
float optionWidth = Mathf.Min(rect.width, Config.optionSize.x * (rect.width / Config.windowSize.x));
float optionX = rect.x + (rect.width - optionWidth) / 2;
Rect optionRect = new Rect(optionX, rect.y, optionWidth, rect.height);
// 保存原始状态
Color originalColor = GUI.color;
GameFont originalFont = Text.Font;
Color originalTextColor = GUI.contentColor;
TextAnchor originalAnchor = Text.Anchor;
try
{
// 设置文本居中
Text.Anchor = TextAnchor.MiddleCenter;
Text.Font = GameFont.Small;
if (conditionsMet)
{
// 启用状态的选项 - 使用自定义样式
if (option.useCustomColors)
{
// 使用选项自定义颜色
DrawCustomButtonWithColors(optionRect, option.label.Translate(), option);
}
else
{
// 使用默认自定义颜色
DrawCustomButton(optionRect, option.label.Translate(), isEnabled: true);
}
// 添加点击处理
if (Widgets.ButtonInvisible(optionRect))
{
HandleAction(option.optionEffects);
}
}
else
{
// 禁用状态的选项 - 使用自定义禁用样式
if (option.useCustomColors && option.disabledColor.HasValue)
{
// 使用选项自定义禁用颜色
DrawCustomButtonWithColors(optionRect, option.label.Translate(), option, isEnabled: false);
}
else
{
// 使用默认自定义禁用颜色
DrawCustomButton(optionRect, option.label.Translate(), isEnabled: false);
}
// 添加禁用提示
TooltipHandler.TipRegion(optionRect, GetDisabledReason(option, reason).Translate());
}
}
finally
{
// 恢复原始状态
GUI.color = originalColor;
Text.Font = originalFont;
GUI.contentColor = originalTextColor;
Text.Anchor = originalAnchor;
}
}
/// <summary>
/// 绘制自定义按钮(基础版本)
/// </summary>
private void DrawCustomButton(Rect rect, string label, bool isEnabled = true)
{
bool isMouseOver = Mouse.IsOver(rect);
// 确定按钮状态颜色
Color buttonColor, textColor;
if (!isEnabled)
{
// 禁用状态
buttonColor = CustomButtonDisabledColor;
textColor = CustomButtonTextDisabledColor;
}
else if (isMouseOver)
{
// 悬停状态
buttonColor = CustomButtonHoverColor;
textColor = CustomButtonTextHoverColor;
}
else
{
// 正常状态
buttonColor = CustomButtonNormalColor;
textColor = CustomButtonTextNormalColor;
}
// 绘制按钮背景
GUI.color = buttonColor;
Widgets.DrawBoxSolid(rect, buttonColor);
// 绘制边框
if (isEnabled)
{
Widgets.DrawBox(rect, 1);
}
else
{
// 禁用状态的边框更细更暗
Widgets.DrawBox(rect, 1);
}
// 绘制文本
GUI.color = textColor;
Text.Anchor = TextAnchor.MiddleCenter;
Widgets.Label(rect.ContractedBy(4f), label);
// 如果是禁用状态,添加删除线效果
if (!isEnabled)
{
GUI.color = new Color(0.6f, 0.6f, 0.6f, 0.8f);
Widgets.DrawLine(
new Vector2(rect.x + 10f, rect.center.y),
new Vector2(rect.xMax - 10f, rect.center.y),
GUI.color,
1f
);
}
}
/// <summary>
/// 绘制自定义按钮(使用选项自定义颜色)
/// </summary>
private void DrawCustomButtonWithColors(Rect rect, string label, EventOption option, bool isEnabled = true)
{
bool isMouseOver = Mouse.IsOver(rect);
// 确定按钮状态颜色
Color buttonColor, textColor;
if (!isEnabled)
{
// 禁用状态
buttonColor = option.disabledColor ?? CustomButtonDisabledColor;
textColor = option.textDisabledColor ?? CustomButtonTextDisabledColor;
}
else if (isMouseOver)
{
// 悬停状态
buttonColor = option.hoverColor ?? CustomButtonHoverColor;
textColor = option.textHoverColor ?? CustomButtonTextHoverColor;
}
else
{
// 正常状态
buttonColor = option.normalColor ?? CustomButtonNormalColor;
textColor = option.textColor ?? CustomButtonTextNormalColor;
}
// 绘制按钮背景
GUI.color = buttonColor;
Widgets.DrawBoxSolid(rect, buttonColor);
// 绘制边框
Widgets.DrawBox(rect);
// 绘制文本
GUI.color = textColor;
Text.Anchor = TextAnchor.MiddleCenter;
Widgets.Label(rect.ContractedBy(4f), label);
// 如果是禁用状态,添加删除线效果
if (!isEnabled)
{
GUI.color = new Color(0.6f, 0.6f, 0.6f, 0.8f);
Widgets.DrawLine(
new Vector2(rect.x + 10f, rect.center.y),
new Vector2(rect.xMax - 10f, rect.center.y),
GUI.color,
1f
);
}
}
// 绘制选项区域
private void DrawOptions(Rect rect, List<EventOption> options)
@@ -526,6 +568,7 @@ namespace WulaFallenEmpire
}
}
}
// 应用选项颜色
private void ApplyOptionColors(EventOption option, Rect rect)
{

View File

@@ -68,20 +68,6 @@ namespace WulaFallenEmpire
}
}
public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
{
string baseInfo = "";
if (Props.enableGroundStrafing)
{
baseInfo = $"扫射区域: {Props.strafeWidth * 2 + 1}格宽度";
}
else if (Props.enableSectorSurveillance)
{
baseInfo = $"扇形监视: 约{Props.strafeWidth * 2 + 1}格宽度\n(具体参数在飞行物定义中)";
}
return baseInfo;
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
if (!base.Valid(target, throwMessages))

View File

@@ -76,19 +76,30 @@ namespace WulaFallenEmpire
public GlobalWorkTableAirdropExtension AirdropExtension =>
def.GetModExtension<GlobalWorkTableAirdropExtension>();
// 修改:添加空投命令到技能栏,添加工厂设施检查
// 修改:在 GetGizmos 方法中添加白银转移按钮
public override IEnumerable<Gizmo> GetGizmos()
{
foreach (Gizmo g in base.GetGizmos())
{
yield return g;
}
// 只有在有输出物品且有工厂设施的飞行器时才显示空投按钮
// 白银转移按钮 - 检查输入端是否有白银
var globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
int silverAmount = globalStorage?.GetInputStorageCount(ThingDefOf.Silver) ?? 0;
bool hasSilver = silverAmount > 0;
if (hasSilver)
{
yield return new Command_Action
{
action = TransferSilverToOutput,
defaultLabel = "WULA_TransferSilver".Translate(),
defaultDesc = "WULA_TransferSilverDesc".Translate(silverAmount),
icon = ContentFinder<Texture2D>.Get("Wula/UI/Commands/WULA_SilverTransfer"),
};
}
// 原有的空投按钮逻辑保持不变
bool hasOutputItems = globalStorage != null && globalStorage.outputStorage.Any(kvp => kvp.Value > 0);
bool hasFactoryFlyOver = HasFactoryFacilityFlyOver();
if (hasOutputItems && hasFactoryFlyOver)
{
yield return new Command_Action
@@ -111,6 +122,64 @@ namespace WulaFallenEmpire
}
}
// 新增:将输入端白银转移到输出端的方法
private void TransferSilverToOutput()
{
var globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
if (globalStorage == null)
{
Messages.Message("WULA_NoGlobalStorage".Translate(), MessageTypeDefOf.RejectInput);
return;
}
int silverAmount = globalStorage.GetInputStorageCount(ThingDefOf.Silver);
if (silverAmount <= 0)
{
Messages.Message("WULA_NoSilverToTransfer".Translate(), MessageTypeDefOf.RejectInput);
return;
}
// 确认对话框
Find.WindowStack.Add(new Dialog_MessageBox(
"WULA_ConfirmTransferSilver".Translate(silverAmount),
"Confirm".Translate(),
() => ExecuteSilverTransfer(globalStorage, silverAmount),
"Cancel".Translate(),
null,
"WULA_TransferSilver".Translate(),
false,
null,
null
));
}
// 新增:执行白银转移
private void ExecuteSilverTransfer(GlobalStorageWorldComponent globalStorage, int silverAmount)
{
try
{
// 从输入端移除白银
if (globalStorage.RemoveFromInputStorage(ThingDefOf.Silver, silverAmount))
{
// 添加到输出端
globalStorage.AddToOutputStorage(ThingDefOf.Silver, silverAmount);
// 显示成功消息
Messages.Message("WULA_SilverTransferred".Translate(silverAmount), MessageTypeDefOf.PositiveEvent);
Log.Message($"[WULA] Transferred {silverAmount} silver from input to output storage");
}
else
{
Messages.Message("WULA_TransferFailed".Translate(), MessageTypeDefOf.RejectInput);
Log.Error("[WULA] Failed to remove silver from input storage during transfer");
}
}
catch (System.Exception ex)
{
Messages.Message("WULA_TransferError".Translate(), MessageTypeDefOf.RejectInput);
Log.Error($"[WULA] Error during silver transfer: {ex}");
}
}
// 新增检查是否有拥有FactoryFacility设施的飞行器
private bool HasFactoryFacilityFlyOver()
{
@@ -587,7 +656,7 @@ namespace WulaFallenEmpire
}
dropPodInfo.innerContainer = container;
// 生成空投舱
DropPodUtility.MakeDropPodAt(dropCell, Map, dropPodInfo);
DropPodUtility.MakeDropPodAt(dropCell, Map, dropPodInfo, Faction.OfPlayer);
Log.Message($"[Airdrop] Successfully created drop pod at {dropCell}");
return true;

View File

@@ -11,6 +11,9 @@ namespace WulaFallenEmpire
public bool garbageShieldEnabled = false; // 通过XML配置启用/禁用
public string garbageShieldUIEventDefName; // 垃圾屏蔽触发时弹出的UI事件defName
// 新增:配置是否检查不可交易物品
public bool checkNonTradableItems = false;
public CompProperties_GarbageShield()
{
this.compClass = typeof(CompGarbageShield);
@@ -30,7 +33,7 @@ namespace WulaFallenEmpire
if (!GarbageShieldEnabled) return false;
// 检查是否是殖民者
if (thing is Pawn pawn && pawn.IsColonist)
if (thing is Pawn pawn)
return true;
// 检查是否是尸体
@@ -41,6 +44,10 @@ namespace WulaFallenEmpire
if (IsToxicWaste(thing))
return true;
// 新增:检查不可交易物品(如果配置启用)
if (Props.checkNonTradableItems && IsNonTradableItem(thing))
return true;
return false;
}
@@ -69,6 +76,13 @@ namespace WulaFallenEmpire
return thing.def == ThingDefOf.Wastepack;
}
// 新增:判断是否为不可交易物品
private bool IsNonTradableItem(Thing thing)
{
// 检查 tradeability 是否为 None
return thing.def.tradeability == Tradeability.None;
}
// 处理垃圾屏蔽触发并触发UI事件
public void ProcessGarbageShieldTrigger(List<Thing> forbiddenItems)
{

View File

@@ -11,6 +11,8 @@ namespace WulaFallenEmpire
// 垃圾屏蔽配置 - 通过XML控制
public bool garbageShieldEnabled = false;
public string garbageShieldUIEventDefName = "Wula_UI_Legion_Reply_1";
// 新增:明确不检查不可交易物品
public bool checkNonTradableItems = false; // Launchable_ToGlobalStorage 不需要检查不可交易物品
public CompProperties_Launchable_ToGlobalStorage()
{

View File

@@ -3,16 +3,16 @@ using Verse;
namespace WulaFallenEmpire
{
public class CompProperties_ValueConverter : CompProperties
public class CompProperties_ValueConverter : CompProperties_Launchable_TransportPod
{
public float conversionRate = 1.0f; // 价值转换倍率
public ThingDef outputThingDef = null; // 输出物品定义,默认为白银
public bool destroyAfterConversion = true; // 转换后是否销毁建筑
public float conversionRatio = 0.5f; // 默认50%的转换比例
public ThingDef targetCurrency = ThingDefOf.Silver; // 目标货币,默认为白银
// 新增:垃圾屏蔽配置 - 专门为价值转换器配置
public bool garbageShieldEnabled = true; // 默认启用垃圾屏蔽
public string garbageShieldUIEventDefName = "Wula_UI_Legion_Reply_1"; // 默认UI事件
public bool checkNonTradableItems = true; // 专门为价值转换器启用不可交易物品检查
// 垃圾屏蔽配置
public bool garbageShieldEnabled = false;
public string garbageShieldUIEventDefName = "Wula_UI_Legion_Reply_1";
public CompProperties_ValueConverter()
{
this.compClass = typeof(CompValueConverter);

View File

@@ -1,157 +1,316 @@
using RimWorld;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using Verse;
using Verse.Sound;
using System.Text;
using System.Linq;
using RimWorld.Planet;
namespace WulaFallenEmpire
{
public class CompValueConverter : CompLaunchable_TransportPod
{
public new CompProperties_ValueConverter Props => (CompProperties_ValueConverter)this.props;
// 获取垃圾屏蔽组件
public CompGarbageShield GarbageShieldComp => this.parent.GetComp<CompGarbageShield>();
// 获取容器组件
public new CompTransporter Transporter => this.parent.GetComp<CompTransporter>();
// 新增:专门为价值转换器检查禁止物品
public List<Thing> GetForbiddenItemsForConverter(ThingOwner container)
{
List<Thing> forbiddenItems = new List<Thing>();
// 如果配置了专门的垃圾屏蔽组件,使用它
if (GarbageShieldComp != null && GarbageShieldComp.GarbageShieldEnabled)
{
forbiddenItems.AddRange(GarbageShieldComp.GetForbiddenItems(container));
}
else
{
// 否则使用价值转换器自己的配置
forbiddenItems.AddRange(GetForbiddenItemsByConverterConfig(container));
}
return forbiddenItems;
}
// 新增:根据价值转换器配置检查禁止物品
private List<Thing> GetForbiddenItemsByConverterConfig(ThingOwner container)
{
List<Thing> forbiddenItems = new List<Thing>();
if (!Props.garbageShieldEnabled) return forbiddenItems;
foreach (Thing item in container)
{
if (IsForbiddenItemByConverterConfig(item))
{
forbiddenItems.Add(item);
}
}
return forbiddenItems;
}
// 新增:根据价值转换器配置判断是否为禁止物品
private bool IsForbiddenItemByConverterConfig(Thing thing)
{
// 检查是否是殖民者
if (thing is Pawn pawn)
return true;
// 检查是否是尸体
if (thing.def.IsCorpse)
return true;
// 检查是否是有毒垃圾
if (IsToxicWaste(thing))
return true;
// 检查不可交易物品(价值转换器专用)
if (Props.checkNonTradableItems && IsNonTradableItem(thing))
return true;
return false;
}
// 新增:判断是否为有毒垃圾
private bool IsToxicWaste(Thing thing)
{
return thing.def == ThingDefOf.Wastepack;
}
// 新增:判断是否为不可交易物品
private bool IsNonTradableItem(Thing thing)
{
return thing.def.tradeability == Tradeability.None;
}
public override IEnumerable<Gizmo> CompGetGizmosExtra()
{
// 首先处理基类的Gizmo但过滤掉原版的发射按钮
// 移除原有的发射按钮,替换为我们自己的价值转换按钮
foreach (Gizmo gizmo in base.CompGetGizmosExtra())
{
// 跳过原版的发射按钮
if (gizmo is Command_Action launchCommand &&
(launchCommand.defaultDesc == "CommandLaunchGroupDesc".Translate() ||
launchCommand.defaultDesc == "CommandLaunchSingleDesc".Translate()))
{
continue;
continue; // 跳过原版的发射按钮
}
yield return gizmo;
}
// 添加我们的转换按钮
if (Transporter != null && Transporter.innerContainer.Any)
if (this.Transporter.LoadingInProgressOrReadyToLaunch)
{
Command_Action command = new Command_Action();
command.defaultLabel = "WULA_ConvertToSilver".Translate();
command.defaultDesc = "WULA_ConvertToSilverDesc".Translate(Props.conversionRate.ToStringPercent());
command.icon = ContentFinder<Texture2D>.Get("UI/Commands/ConvertToSilver");
command.defaultLabel = "WULA_ConvertToCurrency".Translate();
command.defaultDesc = GetConversionDescription();
command.icon = ContentFinder<Texture2D>.Get("UI/Commands/LaunchShip");
command.action = delegate
{
this.TryLaunchToSilver();
this.ConvertToCurrency();
};
// 添加禁用状态检查
if (!CanConvert())
// 禁用条件检查
string disableReason;
if (!CanConvert(out disableReason))
{
command.Disable("WULA_CannotConvert".Translate());
command.Disable(disableReason);
}
yield return command;
}
}
/// <summary>
/// 检查是否可以执行转换
/// 获取转换描述信息
/// </summary>
private bool CanConvert()
private string GetConversionDescription()
{
if (Transporter == null || !Transporter.innerContainer.Any)
return false;
// 检查垃圾屏蔽
if (GarbageShieldComp != null && GarbageShieldComp.GarbageShieldEnabled)
try
{
List<Thing> forbiddenItems = GarbageShieldComp.GetForbiddenItems(Transporter.innerContainer);
if (forbiddenItems.Count > 0)
return false;
StringBuilder sb = new StringBuilder();
// 安全地获取目标货币标签
string targetCurrencyLabel = "Unknown Currency";
if (Props?.targetCurrency != null)
{
targetCurrencyLabel = Props.targetCurrency.LabelCap;
}
sb.AppendLine("WULA_ConvertToCurrencyDesc".Translate(targetCurrencyLabel, (Props.conversionRatio * 100f).ToString("F0")));
// 显示当前物品总价值和预计转换结果
float totalValue = CalculateTotalValue();
float convertedValue = totalValue * Props.conversionRatio;
// 显示物品列表
var items = GetItemList();
if (items.Count > 0)
{
sb.AppendLine();
sb.AppendLine("WULA_ContainedItems".Translate());
foreach (Thing item in items)
{
sb.AppendLine(" - " + item.LabelCap + " x" + item.stackCount);
}
}
return sb.ToString();
}
catch (System.Exception ex)
{
Log.Error($"[WULA ValueConverter] Error in GetConversionDescription: {ex}");
return "WULA_ConversionDescriptionError".Translate();
}
}
/// <summary>
/// 检查是否可以转换
/// </summary>
private bool CanConvert(out string reason)
{
reason = null;
if (!this.parent.Spawned)
{
reason = "WULA_ConverterNotSpawned".Translate();
return false;
}
CompTransporter transporter = this.Transporter;
if (transporter == null || !transporter.innerContainer.Any)
{
reason = "WULA_NoItemsToConvert".Translate();
return false;
}
// 检查基类的发射条件(燃料、冷却时间等)
var baseResult = base.CanLaunch(null);
if (!baseResult.Accepted)
{
reason = baseResult.Reason;
return false;
}
return true;
}
/// <summary>
/// 将物品价值转换为白银
/// 转换为货币
/// </summary>
public void TryLaunchToSilver()
public void ConvertToCurrency()
{
CompTransporter transporter = this.Transporter;
var globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
// 检查垃圾屏蔽 - 使用价值转换器专用的检查方法
List<Thing> forbiddenItems = GetForbiddenItemsForConverter(transporter.innerContainer);
if (forbiddenItems.Count > 0)
{
// 显示取消发射消息
StringBuilder forbiddenList = new StringBuilder();
foreach (Thing item in forbiddenItems)
{
if (forbiddenList.Length > 0) forbiddenList.Append(", ");
forbiddenList.Append($"{item.LabelCap} x{item.stackCount}");
}
Messages.Message("WULA_LaunchCancelledDueToForbiddenItems".Translate(forbiddenList.ToString()),
this.parent, MessageTypeDefOf.RejectInput);
// 触发垃圾屏蔽UI事件
ProcessGarbageShieldTriggerForConverter(forbiddenItems);
return; // 取消发射
}
if (!this.parent.Spawned)
{
Log.Error("Tried to convert value from " + this.parent + " but it's not spawned.");
Log.Error("Tried to convert " + this.parent + " but it's not spawned.");
return;
}
var globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
if (globalStorage == null)
{
Log.Error("Could not find GlobalStorageWorldComponent.");
return;
}
if (Transporter == null || !Transporter.innerContainer.Any)
if (transporter == null || !transporter.innerContainer.Any)
{
Messages.Message("WULA_NoItemsToConvert".Translate(), this.parent, MessageTypeDefOf.RejectInput);
return;
}
// 检查垃圾屏蔽
if (GarbageShieldComp != null && GarbageShieldComp.GarbageShieldEnabled)
{
List<Thing> forbiddenItems = GarbageShieldComp.GetForbiddenItems(Transporter.innerContainer);
if (forbiddenItems.Count > 0)
{
StringBuilder forbiddenList = new StringBuilder();
foreach (Thing item in forbiddenItems)
{
if (forbiddenList.Length > 0) forbiddenList.Append(", ");
forbiddenList.Append($"{item.LabelCap} x{item.stackCount}");
}
Messages.Message("WULA_ConversionCancelledDueToForbiddenItems".Translate(forbiddenList.ToString()),
this.parent, MessageTypeDefOf.RejectInput);
GarbageShieldComp.ProcessGarbageShieldTrigger(forbiddenItems);
return;
}
}
// 计算总价值
// 1. 计算总价值并生成白银
float totalValue = CalculateTotalValue();
if (totalValue <= 0)
{
Messages.Message("WULA_NoValuableItems".Translate(), this.parent, MessageTypeDefOf.RejectInput);
return;
}
float convertedValue = totalValue * Props.conversionRatio;
int silverAmount = Mathf.FloorToInt(convertedValue);
// 应用转换倍率
int silverAmount = CalculateSilverAmount(totalValue);
if (silverAmount <= 0)
{
Messages.Message("WULA_ConversionValueTooLow".Translate(), this.parent, MessageTypeDefOf.RejectInput);
Messages.Message("WULA_ConvertedValueTooLow".Translate(), this.parent, MessageTypeDefOf.RejectInput);
return;
}
// 执行转换
PerformConversion(globalStorage, silverAmount, totalValue);
// 2. 将白银添加到全局存储的输入储存器
if (globalStorage != null)
{
globalStorage.AddToInputStorage(Props.targetCurrency, silverAmount);
}
else
{
Log.Error("Could not find GlobalStorageWorldComponent.");
return;
}
// 调用基类的发射方法,让它处理动画和销毁
// 注意:这里我们发射到当前地图的同一个位置,实际上只是利用发射动画
// 3. 统计转换的物品信息
StringBuilder convertedItems = new StringBuilder();
int itemCount = 0;
float originalTotalValue = 0f;
foreach (Thing item in transporter.innerContainer)
{
itemCount += item.stackCount;
originalTotalValue += item.MarketValue * item.stackCount;
if (convertedItems.Length > 0) convertedItems.Append(", ");
convertedItems.Append($"{item.LabelCap} x{item.stackCount}");
}
// 4. 清空容器
transporter.innerContainer.ClearAndDestroyContents();
// 5. 显示转换结果消息
string message = BuildConversionMessage(itemCount, originalTotalValue, silverAmount, convertedItems.ToString());
Messages.Message(message, this.parent, MessageTypeDefOf.PositiveEvent);
// 6. 调用基类的发射方法,处理动画和销毁
// 使用当前地图的tile作为目的地arrivalAction为null
base.TryLaunch(this.parent.Map.Tile, null);
}
/// <summary>
/// 重写基类的TryLaunch方法阻止原版发射逻辑
/// 新增:价值转换器专用的垃圾屏蔽触发处理
/// </summary>
public new void TryLaunch(PlanetTile destinationTile, TransportersArrivalAction arrivalAction)
private void ProcessGarbageShieldTriggerForConverter(List<Thing> forbiddenItems)
{
// 阻止原版发射逻辑,使用我们的转换逻辑
TryLaunchToSilver();
if (forbiddenItems.Count > 0)
{
string uiEventDefName = Props.garbageShieldUIEventDefName;
// 如果配置了专门的垃圾屏蔽组件使用它的UI事件配置
if (GarbageShieldComp != null && !string.IsNullOrEmpty(GarbageShieldComp.Props.garbageShieldUIEventDefName))
{
uiEventDefName = GarbageShieldComp.Props.garbageShieldUIEventDefName;
}
if (!string.IsNullOrEmpty(uiEventDefName))
{
EventDef uiDef = DefDatabase<EventDef>.GetNamed(uiEventDefName, false);
if (uiDef != null)
{
Find.WindowStack.Add(new Dialog_CustomDisplay(uiDef));
}
else
{
Log.Error($"[CompValueConverter] Could not find EventDef named '{uiEventDefName}'.");
}
}
}
}
/// <summary>
@@ -160,145 +319,67 @@ namespace WulaFallenEmpire
private float CalculateTotalValue()
{
float totalValue = 0f;
foreach (Thing item in Transporter.innerContainer)
CompTransporter transporter = this.Transporter;
if (transporter != null)
{
// 计算单个物品的市场价值
float itemValue = item.MarketValue * item.stackCount;
totalValue += itemValue;
if (Prefs.DevMode)
foreach (Thing item in transporter.innerContainer)
{
Log.Message($"[ValueConverter] {item.LabelCap} x{item.stackCount}: {item.MarketValue} each, total: {itemValue}");
totalValue += item.MarketValue * item.stackCount;
}
}
if (Prefs.DevMode)
{
Log.Message($"[ValueConverter] Total value before conversion: {totalValue}");
}
return totalValue;
}
/// <summary>
/// 计算转换后的白银数量
/// 获取物品列表
/// </summary>
private int CalculateSilverAmount(float totalValue)
private List<Thing> GetItemList()
{
// 应用转换倍率
float convertedValue = totalValue * Props.conversionRate;
// 转换为白银白银的市场价值为1
int silverAmount = Mathf.FloorToInt(convertedValue);
if (Prefs.DevMode)
List<Thing> items = new List<Thing>();
CompTransporter transporter = this.Transporter;
if (transporter != null)
{
Log.Message($"[ValueConverter] After conversion rate ({Props.conversionRate}): {convertedValue}, Silver amount: {silverAmount}");
foreach (Thing item in transporter.innerContainer)
{
items.Add(item);
}
}
return silverAmount;
return items;
}
/// <summary>
/// 执行转换操作
/// 构建转换消息
/// </summary>
private void PerformConversion(GlobalStorageWorldComponent globalStorage, int silverAmount, float originalValue)
private string BuildConversionMessage(int itemCount, float originalValue, int silverAmount, string itemList)
{
// 1. 将白银添加到全局存储器的输入端
ThingDef silverDef = Props.outputThingDef ?? ThingDefOf.Silver;
globalStorage.AddToInputStorage(silverDef, silverAmount);
// 2. 显示转换结果消息
ShowConversionMessage(silverAmount, originalValue);
// 4. 清空容器
Transporter.innerContainer.ClearAndDestroyContents();
// 5. 如果配置为转换后销毁,则销毁建筑
if (Props.destroyAfterConversion)
StringBuilder message = new StringBuilder();
message.Append("WULA_ConversionComplete".Translate(itemCount, originalValue.ToString("F2"), silverAmount, Props.targetCurrency?.LabelCap ?? "Unknown Currency"));
if (!string.IsNullOrEmpty(itemList))
{
this.parent.Destroy(DestroyMode.Vanish);
message.Append("\n\n");
message.Append("WULA_ConvertedItems".Translate(itemList));
}
message.Append("\n\n");
message.Append("WULA_ConversionRatioApplied".Translate((Props.conversionRatio * 100f).ToString("F0")));
return message.ToString();
}
/// <summary>
/// 显示转换结果消息
/// 重写基类的发射方法,确保使用我们的逻辑
/// </summary>
private void ShowConversionMessage(int silverAmount, float originalValue)
public new void TryLaunch(PlanetTile destinationTile, TransportersArrivalAction arrivalAction)
{
string message;
if (Props.conversionRate < 1.0f)
{
message = "WULA_ValueConvertedWithLoss".Translate(
originalValue.ToString("F0"),
silverAmount,
Props.conversionRate.ToStringPercent()
);
}
else if (Props.conversionRate > 1.0f)
{
message = "WULA_ValueConvertedWithBonus".Translate(
originalValue.ToString("F0"),
silverAmount,
Props.conversionRate.ToStringPercent()
);
}
else
{
message = "WULA_ValueConverted".Translate(
originalValue.ToString("F0"),
silverAmount
);
}
Messages.Message(message, this.parent, MessageTypeDefOf.PositiveEvent);
}
/// <summary>
/// 获取转换效率描述(用于界面显示)
/// </summary>
public string GetConversionEfficiencyDescription()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("WULA_ConversionEfficiency".Translate(Props.conversionRate.ToStringPercent()));
if (Props.conversionRate < 1.0f)
{
sb.AppendLine("WULA_ConversionEfficiencyLoss".Translate());
}
else if (Props.conversionRate > 1.0f)
{
sb.AppendLine("WULA_ConversionEfficiencyBonus".Translate());
}
else
{
sb.AppendLine("WULA_ConversionEfficiencyNormal".Translate());
}
return sb.ToString();
}
/// <summary>
/// 在检查器中显示转换信息
/// </summary>
public override string CompInspectStringExtra()
{
StringBuilder sb = new StringBuilder();
if (Transporter != null && Transporter.innerContainer.Any)
{
// 显示容器内物品总价值
float currentValue = CalculateTotalValue();
int potentialSilver = CalculateSilverAmount(currentValue);
sb.AppendLine("WULA_CurrentValueInContainer".Translate(currentValue.ToString("F0")));
sb.AppendLine("WULA_PotentialSilver".Translate(potentialSilver));
sb.AppendLine("WULA_ConversionRate".Translate(Props.conversionRate.ToStringPercent()));
}
return sb.ToString().TrimEndNewlines();
// 这个方法不应该被直接调用应该使用ConvertToCurrency
Log.Warning("CompValueConverter.TryLaunch should not be called directly. Use ConvertToCurrency instead.");
ConvertToCurrency();
}
}
}

View File

@@ -0,0 +1,94 @@
using HarmonyLib;
using RimWorld;
using System.Collections.Generic;
using System.Reflection;
using Verse;
namespace WulaFallenEmpire
{
[HarmonyPatch(typeof(ScenPart_PlayerPawnsArriveMethod))]
[HarmonyPatch("DoDropPods")]
public static class ScenPart_PlayerPawnsArriveMethod_ReflectionPatch
{
/// <summary>
/// 使用反射来直接调用正确的方法
/// </summary>
[HarmonyPrefix]
public static bool Prefix(ScenPart_PlayerPawnsArriveMethod __instance, Map map, List<Thing> startingItems)
{
try
{
// 获取私有字段 "method"
FieldInfo methodField = typeof(ScenPart_PlayerPawnsArriveMethod).GetField("method", BindingFlags.NonPublic | BindingFlags.Instance);
PlayerPawnsArriveMethod method = (PlayerPawnsArriveMethod)methodField.GetValue(__instance);
// 重新创建物品分组逻辑
List<List<Thing>> thingGroups = new List<List<Thing>>();
foreach (Pawn startingPawn in Find.GameInitData.startingAndOptionalPawns)
{
List<Thing> pawnGroup = new List<Thing>();
pawnGroup.Add(startingPawn);
thingGroups.Add(pawnGroup);
}
int itemIndex = 0;
foreach (Thing startingItem in startingItems)
{
if (startingItem.def.CanHaveFaction)
{
startingItem.SetFactionDirect(Faction.OfPlayer);
}
thingGroups[itemIndex].Add(startingItem);
itemIndex++;
if (itemIndex >= thingGroups.Count)
{
itemIndex = 0;
}
}
// 使用反射调用正确的 DropThingGroupsNear 方法11个参数版本
MethodInfo dropMethod = typeof(DropPodUtility).GetMethod("DropThingGroupsNear", new System.Type[]
{
typeof(IntVec3),
typeof(Map),
typeof(List<List<Thing>>),
typeof(int),
typeof(bool),
typeof(bool),
typeof(bool),
typeof(bool),
typeof(bool),
typeof(bool),
typeof(Faction)
});
if (dropMethod != null)
{
dropMethod.Invoke(null, new object[]
{
MapGenerator.PlayerStartSpot,
map,
thingGroups,
110,
Find.GameInitData.QuickStarted || method != PlayerPawnsArriveMethod.DropPods,
true, // leaveSlag
true, // canRoofPunch
true, // forbid
false, // allowFogged
false, // canTransfer
Faction.OfPlayer // faction
});
Log.Message("[WULA] Successfully called DropThingGroupsNear with faction parameter via reflection");
}
else
{
Log.Error("[WULA] Could not find 11-parameter DropThingGroupsNear method");
}
// 返回 false 来跳过原方法的执行
return false;
}
catch (System.Exception ex)
{
Log.Error($"[WULA] Error in DoDropPods prefix: {ex}");
// 如果出错,让原方法继续执行
return true;
}
}
}
}

View File

@@ -0,0 +1,84 @@
using HarmonyLib;
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using Verse;
namespace WulaFallenEmpire
{
[HarmonyPatch(typeof(ThingDefGenerator_Corpses))]
[HarmonyPatch("GenerateCorpseDef")]
public static class WulaSpeciesCorpsePatch
{
/// <summary>
/// 在生成尸体定义后,对 WulaSpecies 进行特殊处理
/// </summary>
[HarmonyPostfix]
public static void ModifyWulaSpeciesCorpse(ThingDef pawnDef, ref ThingDef __result)
{
// 检查是否是 WulaSpecies 种族
if (pawnDef?.defName == "WulaSpecies")
{
ApplyWulaSpeciesCorpseModifications(__result);
}
}
/// <summary>
/// 应用 WulaSpecies 尸体的特殊修改
/// </summary>
private static void ApplyWulaSpeciesCorpseModifications(ThingDef corpseDef)
{
if (corpseDef == null) return;
Log.Message($"[WulaSpecies] Starting corpse modification for WulaSpecies");
// 1. 移除腐烂组件(如果存在)
RemoveCompProperties(corpseDef, typeof(CompProperties_Rottable));
// 2. 移除污物生成组件(如果存在)
RemoveCompProperties(corpseDef, typeof(CompProperties_SpawnerFilth));
// 3. 修改可食用属性,设置为 NeverForNutrition
if (corpseDef.ingestible != null)
{
corpseDef.ingestible.preferability = FoodPreferability.NeverForNutrition;
Log.Message($"[WulaSpecies] Set ingestible preferability to NeverForNutrition");
}
// 4. 移除 HarbingerTreeConsumable 组件(如果存在)
RemoveCompProperties(corpseDef, typeof(CompProperties), "CompHarbingerTreeConsumable");
Log.Message($"[WulaSpecies] Completed corpse modification for WulaSpecies");
}
/// <summary>
/// 移除指定类型的组件属性
/// </summary>
private static void RemoveCompProperties(ThingDef thingDef, System.Type compType, string compClassName = null)
{
if (thingDef.comps == null) return;
var compsToRemove = new List<CompProperties>();
foreach (var comp in thingDef.comps)
{
if (comp.GetType() == compType)
{
compsToRemove.Add(comp);
Log.Message($"[WulaSpecies] Found and will remove component: {comp.GetType().Name}");
}
else if (!string.IsNullOrEmpty(compClassName) && comp.compClass?.Name == compClassName)
{
compsToRemove.Add(comp);
Log.Message($"[WulaSpecies] Found and will remove component by class name: {compClassName}");
}
}
foreach (var comp in compsToRemove)
{
thingDef.comps.Remove(comp);
Log.Message($"[WulaSpecies] Removed component: {comp.GetType().Name}");
}
}
}
}

View File

@@ -3,6 +3,7 @@ using UnityEngine;
using Verse;
using System.Collections.Generic;
using HarmonyLib;
using RimWorld.Planet;
namespace WulaFallenEmpire
{
@@ -67,6 +68,10 @@ namespace WulaFallenEmpire
{
if (!Props.showInGUI) yield break;
// 只对玩家所有的物体显示Gizmo
if (parent.Faction != Faction.OfPlayer)
yield break;
// 创建切换 gizmo
Command_Toggle toggleCommand = new Command_Toggle();
toggleCommand.defaultLabel = Props.label;
@@ -98,6 +103,20 @@ namespace WulaFallenEmpire
{
return Props.color;
}
// 检查是否应该绘制半径
public bool ShouldDrawRadius()
{
// 只绘制玩家所有的物体
if (parent.Faction != Faction.OfPlayer)
return false;
// 检查是否在地图视图中(不在世界地图)
if (Find.CurrentMap == null || WorldRendererUtility.WorldRendered)
return false;
return RadiusVisible;
}
}
// 自定义放置工作器
@@ -105,11 +124,15 @@ namespace WulaFallenEmpire
{
public override void DrawGhost(ThingDef def, IntVec3 center, Rot4 rot, Color ghostCol, Thing thing = null)
{
// 检查是否在地图视图中
if (Find.CurrentMap == null || WorldRendererUtility.WorldRendered)
return;
// 如果已经有物体存在,则检查其组件的可见性设置
if (thing != null)
{
CompCustomRadius comp = thing.TryGetComp<CompCustomRadius>();
if (comp == null || !comp.RadiusVisible)
if (comp == null || !comp.ShouldDrawRadius())
return;
}
@@ -178,15 +201,21 @@ namespace WulaFallenEmpire
{
try
{
if (Find.CurrentMap == null) return;
// 检查是否在地图视图中(不在世界地图)
if (Find.CurrentMap == null || WorldRendererUtility.WorldRendered)
return;
// 绘制所有带有自定义半径组件的已放置建筑
foreach (var thing in Find.CurrentMap.listerThings.AllThings)
{
// 只绘制玩家所有的物体
if (thing.Faction != Faction.OfPlayer)
continue;
if (thing.Spawned && thing.def.HasComp(typeof(CompCustomRadius)))
{
CompCustomRadius comp = thing.TryGetComp<CompCustomRadius>();
if (comp != null && comp.RadiusVisible)
if (comp != null && comp.ShouldDrawRadius())
{
float effectiveRadius = comp.EffectiveRadius;
if (effectiveRadius > 0f)
@@ -236,14 +265,22 @@ namespace WulaFallenEmpire
{
try
{
// 检查是否在地图视图中(不在世界地图)
if (Find.CurrentMap == null || WorldRendererUtility.WorldRendered)
return;
if (Find.Selector == null) return;
foreach (object selected in Find.Selector.SelectedObjectsListForReading)
{
if (selected is Thing thing && thing.Spawned && thing.def.HasComp(typeof(CompCustomRadius)))
{
// 只绘制玩家所有的物体
if (thing.Faction != Faction.OfPlayer)
continue;
CompCustomRadius comp = thing.TryGetComp<CompCustomRadius>();
if (comp != null && comp.RadiusVisible)
if (comp != null && comp.ShouldDrawRadius())
{
float effectiveRadius = comp.EffectiveRadius;
if (effectiveRadius > 0f)

View File

@@ -0,0 +1,73 @@
using RimWorld;
using System;
using Verse;
namespace WulaFallenEmpire
{
public class CompProperties_UseEffect_OpenCustomUI : CompProperties_UseEffect
{
public string uiDefName; // 要打开的UI的EventDef名称
public bool requireFactionPlayer = true; // 是否要求玩家派系才能使用
public CompProperties_UseEffect_OpenCustomUI()
{
this.compClass = typeof(CompUseEffect_OpenCustomUI);
}
}
public class CompUseEffect_OpenCustomUI : CompUseEffect
{
public CompProperties_UseEffect_OpenCustomUI Props => (CompProperties_UseEffect_OpenCustomUI)this.props;
public override void DoEffect(Pawn usedBy)
{
base.DoEffect(usedBy);
try
{
// 查找对应的EventDef
EventDef uiDef = DefDatabase<EventDef>.GetNamed(Props.uiDefName, false);
if (uiDef != null)
{
// 创建并打开自定义UI窗口
Window window = (Window)Activator.CreateInstance(uiDef.windowType, uiDef);
Find.WindowStack.Add(window);
Log.Message($"[CompUseEffect] Opened custom UI: {Props.uiDefName}");
}
else
{
Log.Error($"[CompUseEffect] Could not find EventDef named '{Props.uiDefName}'");
Messages.Message($"Error: Could not find UI definition '{Props.uiDefName}'", MessageTypeDefOf.RejectInput);
}
}
catch (Exception ex)
{
Log.Error($"[CompUseEffect] Error opening custom UI '{Props.uiDefName}': {ex}");
Messages.Message($"Error opening UI: {ex.Message}", MessageTypeDefOf.RejectInput);
}
}
public override AcceptanceReport CanBeUsedBy(Pawn p)
{
// 基础检查
AcceptanceReport baseResult = base.CanBeUsedBy(p);
if (!baseResult.Accepted)
return baseResult;
// 检查派系要求
if (Props.requireFactionPlayer && parent.Faction != Faction.OfPlayer)
{
return "Must be player faction to use this".Translate();
}
// 检查EventDef是否存在
if (DefDatabase<EventDef>.GetNamed(Props.uiDefName, false) == null)
{
return $"UI definition '{Props.uiDefName}' not found".Translate();
}
return true;
}
}
}

View File

@@ -76,8 +76,6 @@ namespace WulaFallenEmpire
// 如果武器已经有品质使用现有品质否则设置为Normal
currentQuality = qualityComp.Quality;
initialized = true;
Log.Message($"[ExperienceCore] Initialized {parent.Label} with quality: {currentQuality}");
}
}
@@ -149,8 +147,6 @@ namespace WulaFallenEmpire
ResetWeaponState(retainedExperience);
Messages.Message("WULA_DataPackEjected".Translate(experienceToStore.ToString("F0")), parent, MessageTypeDefOf.PositiveEvent);
Log.Message($"[ExperienceCore] Ejected data pack with {experienceToStore} experience, retained {retainedExperience}");
}
else
{
@@ -208,8 +204,6 @@ namespace WulaFallenEmpire
ProcessRemainingExperience(dataPacks, remainingExperience);
// 发送消息 - 修复阵营检查
SendAbsorptionMessage(actualExperienceToAbsorb, remainingExperience);
Log.Message($"[ExperienceCore] {parent.Label} absorbed {actualExperienceToAbsorb} experience, remaining: {remainingExperience}, current: {currentExperience}");
}
// 处理剩余的经验 - 更新现有数据包
private void ProcessRemainingExperience(List<Thing> dataPacks, float remainingExperience)
@@ -346,8 +340,6 @@ namespace WulaFallenEmpire
}
}
}
Log.Message($"[ExperienceCore] Found {foundDataPacks.Count} data packs within {Props.absorbRadius} tiles");
return foundDataPacks;
}
@@ -377,8 +369,6 @@ namespace WulaFallenEmpire
{
qualityComp.SetQuality(currentQuality, ArtGenerationContext.Outsider);
}
Log.Message($"[ExperienceCore] {parent.Label} reset from {oldTotalExperience} total experience to {currentExperience} + {overflowExperience} overflow");
}
public override void Notify_Equipped(Pawn pawn)
@@ -394,7 +384,6 @@ namespace WulaFallenEmpire
if (skill != null)
{
lastSkillExperience = skill.XpTotalEarned;
Log.Message($"[ExperienceCore] {parent.Label} equipped by {pawn.Name}, tracking {Props.trackedSkill.defName}, starting experience: {lastSkillExperience}");
}
}
}
@@ -405,8 +394,6 @@ namespace WulaFallenEmpire
equippedPawn = null;
lastSkillExperience = 0f;
Log.Message($"[ExperienceCore] {parent.Label} unequipped from {pawn.Name}");
}
public override void CompTick()
@@ -460,8 +447,6 @@ namespace WulaFallenEmpire
}
}
Log.Message($"[ExperienceCore] {parent.Label} gained {actualGained:F1} experience (current: {currentExperience:F1}, overflow: {overflowExperience:F1})");
// 检查品质升级
CheckForQualityUpgrade();
@@ -490,7 +475,6 @@ namespace WulaFallenEmpire
if (qualityComp != null)
{
qualityComp.SetQuality(threshold.quality, ArtGenerationContext.Outsider);
Log.Message($"[ExperienceCore] SUCCESS: {parent.Label} quality updated to {threshold.quality}");
}
else
{
@@ -513,8 +497,6 @@ namespace WulaFallenEmpire
Messages.Message(messageText, parent, MessageTypeDefOf.PositiveEvent);
}
Log.Message($"[ExperienceCore] {parent.Label} upgraded from {oldQuality} to {threshold.quality} at {currentExperience} experience");
}
public override string CompInspectStringExtra()
{
@@ -626,7 +608,6 @@ namespace WulaFallenEmpire
if (qualityComp != null && qualityComp.Quality != currentQuality)
{
qualityComp.SetQuality(currentQuality, ArtGenerationContext.Outsider);
Log.Message($"[ExperienceCore] PostLoad: Updated {parent.Label} quality to {currentQuality}");
}
}
}

View File

@@ -187,6 +187,8 @@
<Compile Include="HarmonyPatches\Faction_ShouldHaveLeader_Patch.cs" />
<Compile Include="HarmonyPatches\Hediff_Mechlink_PostAdd_Patch.cs" />
<Compile Include="HarmonyPatches\Patch_ThingDefGenerator_Techprints_ImpliedTechprintDefs.cs" />
<Compile Include="HarmonyPatches\ScenPart_PlayerPawnsArriveMethod_Patch.cs" />
<Compile Include="HarmonyPatches\WulaSpeciesCorpsePatch.cs" />
<Compile Include="HarmonyPatches\WULA_AutonomousMech\Patch_FloatMenuOptionProvider_SelectedPawnValid.cs" />
<Compile Include="HarmonyPatches\WULA_AutonomousMech\Patch_IsColonyMechPlayerControlled.cs" />
<Compile Include="HarmonyPatches\WULA_AutonomousMech\Patch_MechanitorUtility_CanDraftMech.cs" />
@@ -269,6 +271,7 @@
<Compile Include="ThingComp\CompApparelInterceptor.cs" />
<Compile Include="ThingComp\CompPsychicScaling.cs" />
<Compile Include="ThingComp\CompUseEffect_AddDamageShieldCharges.cs" />
<Compile Include="ThingComp\CompUseEffect_OpenCustomUI.cs" />
<Compile Include="ThingComp\CompUseEffect_PassionTrainer.cs" />
<Compile Include="ThingComp\CompUseEffect_WulaSkillTrainer.cs" />
<Compile Include="ThingComp\Comp_WeaponRenderDynamic.cs" />