冠军甲

This commit is contained in:
Tourswen
2025-11-28 01:01:31 +08:00
parent de8b0ab8d7
commit 3d14169b0d
45 changed files with 983 additions and 119 deletions

View File

@@ -51,7 +51,7 @@
<defName>WULA_PsiCrusher</defName>
<label>乌拉帝国术式:灵能尖啸</label>
<description>以灵能能量发出非人尖啸,直接解构面前扇形区域内的所有目标,无论是建筑物还是活物都难逃毁灭。这种术式需要的灵能难以估量,只有搭载大量封闭灵能回路的灵能泰坦可以连续使用。</description>
<iconPath>UI/Abilities/FireSpew</iconPath>
<iconPath>Wula/UI/Abilities/WULA_PsiCrusher</iconPath>
<writeCombatLog>True</writeCombatLog>
<showPsycastEffects>False</showPsycastEffects>
<aiCanUse>true</aiCanUse>
@@ -247,7 +247,7 @@
<defName>WULA_Psi_Skip</defName>
<label>乌拉帝国术式:灵能跃迁</label>
<description>使用灵能撕开一个连接自身、虚境和目的地的单向通道,随后以极短的时间穿过整个通道,以瞬间移动到目标地点。</description>
<iconPath>UI/Abilities/Skip</iconPath>
<iconPath>Wula/UI/Abilities/WULA_TeleportSelf</iconPath>
<writeCombatLog>True</writeCombatLog>
<showPsycastEffects>False</showPsycastEffects>
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
@@ -396,7 +396,7 @@
<defName>WULA_Psi_Black_Hole</defName>
<label>乌拉帝国术式:虚境阴影</label>
<description>撕开虚境的裂口,在目标地点召唤一道虚境阴影,它泄露的庞大灵能会持续伤害范围内的敌方单位和建筑,并让物品快速损坏,即使是心灵失聪的目标也不能完全免疫这种超现实伤害——对于高心灵敏感度的单位这种伤害则更加致命。</description>
<iconPath>UI/Abilities/FireSpew</iconPath>
<iconPath>Wula/UI/Abilities/WULA_Psi_Black_Hole</iconPath>
<writeCombatLog>True</writeCombatLog>
<showPsycastEffects>False</showPsycastEffects>
<aiCanUse>true</aiCanUse>

View File

@@ -675,6 +675,84 @@
<li>这是一个测试选项,你可以吃到各种打</li>
</descriptions>
<options>
<li>
<label>来,冠军勇士援军</label>
<optionEffects>
<li>
<effects>
<li Class="WulaFallenEmpire.Effect_TriggerRaid">
<points>4000</points>
<faction>Wula_PIA_Legion_Faction</faction>
<raidStrategy>ImmediateAttackFriendly</raidStrategy>
<raidArrivalMode>EdgeDropGroups</raidArrivalMode>
<groupKind>Combat</groupKind>
<pawnGroupMakers>
<li>
<kindDef>Combat</kindDef>
<commonality>100</commonality>
<options>
<Wula_PIA_Heavy_Unit_Melee>1</Wula_PIA_Heavy_Unit_Melee>
</options>
</li>
</pawnGroupMakers>
</li>
<li Class="WulaFallenEmpire.Effect_CloseDialog" />
</effects>
</li>
</optionEffects>
</li>
<li>
<label>来,百战军锋援军</label>
<optionEffects>
<li>
<effects>
<li Class="WulaFallenEmpire.Effect_TriggerRaid">
<points>4000</points>
<faction>Wula_PIA_Legion_Faction</faction>
<raidStrategy>ImmediateAttackFriendly</raidStrategy>
<raidArrivalMode>EdgeDropGroups</raidArrivalMode>
<groupKind>Combat</groupKind>
<pawnGroupMakers>
<li>
<kindDef>Combat</kindDef>
<commonality>100</commonality>
<options>
<Wula_PIA_Heavy_Unit_Range>1</Wula_PIA_Heavy_Unit_Range>
</options>
</li>
</pawnGroupMakers>
</li>
<li Class="WulaFallenEmpire.Effect_CloseDialog" />
</effects>
</li>
</optionEffects>
</li>
<li>
<label>来,断爪卫队</label>
<optionEffects>
<li>
<effects>
<li Class="WulaFallenEmpire.Effect_TriggerRaid">
<points>1000</points>
<faction>Wula_PIA_Legion_Faction</faction>
<raidStrategy>ImmediateAttackFriendly</raidStrategy>
<raidArrivalMode>EdgeDropGroups</raidArrivalMode>
<groupKind>Combat</groupKind>
<pawnGroupMakers>
<li>
<kindDef>Combat</kindDef>
<commonality>100</commonality>
<options>
<Wula_PIA_Legion_Escort_Unit>1</Wula_PIA_Legion_Escort_Unit>
</options>
</li>
</pawnGroupMakers>
</li>
<li Class="WulaFallenEmpire.Effect_CloseDialog" />
</effects>
</li>
</optionEffects>
</li>
<li>
<label>来,陆行舰</label>
<optionEffects>

View File

@@ -36,7 +36,7 @@
<FactionDef ParentName="FactionBase">
<defName>Wula_PIA_Legion_Faction</defName>
<label>乌拉帝国 行星封锁机关</label>
<description>隶属于乌拉帝国开发署的暴力机关,主要职责是对那些已经有人占领但是军事实力较弱的星球进行封锁和原住民驱离。虽然她们不是真正的军队,但是所保有的舰队和武装力量足以支撑其发起一场横跨星域的战争。\n\n她们之中大部分人居住在自己的庞大舰队中地表只有零星前哨殖民地。她们也不会派出商队之类的交易者只会在自己的派系范围内活动并使用舰队支援这些地面据点的生产和战斗。你可以通过任务接洽和</description>
<description>隶属于乌拉帝国开发署的暴力机关,主要职责是对那些已经有人占领但是军事实力较弱的星球进行封锁和原住民驱离。虽然她们不是真正的军队,但是所保有的舰队和武装力量足以支撑其发起一场横跨星域的战争。\n\n她们之中大部分人居住在自己的庞大舰队中地表只有零星前哨殖民地。她们也不会派出商队之类的交易者只会在自己的派系范围内活动并使用舰队支援这些地面据点的生产和战斗。</description>
<basicMemberKind>Wula_PawnKind</basicMemberKind>
<pawnSingular>乌拉帝国合成人</pawnSingular>
<pawnsPlural>乌拉帝国合成人</pawnsPlural>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<!-- 保持这个pawnkind是无派系以供空投系统调取其他的乌拉pawnkind必须有默认派系 -->
<PawnKindDef>
<defName>Wula_PawnKind</defName>
<label>机械乌拉</label>
@@ -55,7 +56,7 @@
<maskPath>Wula/Things/WULA_Cat/AllegianceOverlays/None</maskPath>
<shaderType>CutoutWithOverlay</shaderType>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>1</drawSize>
<drawSize>1.2</drawSize>
</bodyGraphicData>
</li>
</lifeStages>
@@ -68,7 +69,7 @@
<maskPath>Wula/Things/WULA_Attack_Cat/AllegianceOverlays/None</maskPath>
<shaderType>CutoutWithOverlay</shaderType>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>1</drawSize>
<drawSize>1.2</drawSize>
</bodyGraphicData>
</li>
</lifeStages>
@@ -95,7 +96,7 @@
<maskPath>Wula/Things/WULA_Constructor_Cat/AllegianceOverlays/None</maskPath>
<shaderType>CutoutWithOverlay</shaderType>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>1</drawSize>
<drawSize>1.2</drawSize>
</bodyGraphicData>
</li>
</lifeStages>
@@ -112,7 +113,7 @@
<maskPath>Wula/Things/WULA_Assault_Cat/AllegianceOverlays/None</maskPath>
<shaderType>CutoutWithOverlay</shaderType>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>1</drawSize>
<drawSize>1.2</drawSize>
</bodyGraphicData>
</li>
</lifeStages>
@@ -212,7 +213,7 @@
<maskPath>Wula/Things/WULA_Cat/AllegianceOverlays/None</maskPath>
<shaderType>CutoutWithOverlay</shaderType>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>3.8</drawSize>
<drawSize>3.4</drawSize>
<shadowData>
<volume>(1.4, 1.8, 1.4)</volume>
</shadowData>
@@ -345,6 +346,7 @@
<defName>Wula_PIA_Light_Unit</defName>
<label>帝国冲锋队</label>
<race>WulaSpecies</race>
<defaultFactionType>Wula_PIA_Legion_Faction</defaultFactionType>
<lifeStages>
<li>
<bodyGraphicData>
@@ -370,6 +372,7 @@
<isFighter>true</isFighter>
<apparelTags>
<li>Wula_Armor_Light</li>
<li>Wula_Inner</li>
</apparelTags>
<weaponTags>
<li>Wula_Melee_Weapon_T1</li>
@@ -402,6 +405,7 @@
<defName>Wula_PIA_Heavy_Unit</defName>
<label>军团步兵</label>
<race>WulaSpecies</race>
<defaultFactionType>Wula_PIA_Legion_Faction</defaultFactionType>
<lifeStages>
<li>
<bodyGraphicData>
@@ -427,6 +431,7 @@
<isFighter>true</isFighter>
<apparelTags>
<li>Wula_Armor_Super_Heavy</li>
<li>Wula_Inner</li>
</apparelTags>
<weaponTags>
<li>Wula_Melee_Weapon_T1</li>
@@ -460,6 +465,7 @@
<defName>Wula_PIA_Heavy_Unit_Melee</defName>
<label>野心冠军勇士</label>
<race>WulaSpecies</race>
<defaultFactionType>Wula_PIA_Legion_Faction</defaultFactionType>
<lifeStages>
<li>
<bodyGraphicData>
@@ -477,8 +483,8 @@
<minGenerationAge>18</minGenerationAge>
<maxGenerationAge>20</maxGenerationAge>
<combatPower>500</combatPower>
<initialWillRange>10~20</initialWillRange>
<initialResistanceRange>10~20</initialResistanceRange>
<initialWillRange>99~99</initialWillRange>
<initialResistanceRange>99~99</initialResistanceRange>
<itemQuality>Legendary</itemQuality>
<minApparelQuality>Legendary</minApparelQuality>
<maxApparelQuality>Legendary</maxApparelQuality>
@@ -488,13 +494,14 @@
<weaponStuffOverride>Plasteel</weaponStuffOverride>
<apparelTags>
<li>Wula_Armor_Super_Heavy</li>
<li>Wula_Inner</li>
</apparelTags>
<weaponTags>
<li>Wula_Melee_Weapon_T3</li>
</weaponTags>
<apparelRequired>
<li>WULA_Heavy_Infantry_PowerArmor</li>
<li>WULA_Heavy_Infantry_Helmet</li>
<li>WULA_Heavy_Infantry_Helmet_Nomask</li>
</apparelRequired>
<weaponMoney>999999~999999</weaponMoney>
<biocodeWeaponChance>1</biocodeWeaponChance>
@@ -523,6 +530,7 @@
<defName>Wula_PIA_Heavy_Unit_Range</defName>
<label>帝国百战军锋</label>
<race>WulaSpecies</race>
<defaultFactionType>Wula_PIA_Legion_Faction</defaultFactionType>
<lifeStages>
<li>
<bodyGraphicData>
@@ -540,8 +548,8 @@
<minGenerationAge>18</minGenerationAge>
<maxGenerationAge>20</maxGenerationAge>
<combatPower>500</combatPower>
<initialWillRange>10~20</initialWillRange>
<initialResistanceRange>10~20</initialResistanceRange>
<initialWillRange>99~99</initialWillRange>
<initialResistanceRange>99~99</initialResistanceRange>
<itemQuality>Legendary</itemQuality>
<minApparelQuality>Legendary</minApparelQuality>
<maxApparelQuality>Legendary</maxApparelQuality>
@@ -549,6 +557,7 @@
<apparelTags>
<li>Wula_Armor_Super_Heavy</li>
<li>Wula_Armor_Shield</li>
<li>Wula_Inner</li>
</apparelTags>
<weaponTags>
<li>Wula_Ranged_Weapon_T3</li>
@@ -586,6 +595,7 @@
<defName>WULA_Legion_PawnKind</defName>
<label>「军团」</label>
<race>WulaSpecies</race>
<defaultFactionType>Wula_PIA_Legion_Faction</defaultFactionType>
<lifeStages>
<li>
<bodyGraphicData>
@@ -600,6 +610,7 @@
</bodyGraphicData>
</li>
</lifeStages>
<forceDeathOnDowned>true</forceDeathOnDowned>
<combatPower>0</combatPower>
<factionLeader>true</factionLeader>
@@ -625,6 +636,7 @@
<defName>Wula_PIA_Legion_Escort_Unit</defName>
<label>断爪卫队</label>
<race>WulaSpecies</race>
<defaultFactionType>Wula_PIA_Legion_Faction</defaultFactionType>
<lifeStages>
<li>
<bodyGraphicData>
@@ -639,11 +651,15 @@
</bodyGraphicData>
</li>
</lifeStages>
<isBoss>true</isBoss>
<maxPerGroup>1</maxPerGroup>
<minGenerationAge>18</minGenerationAge>
<maxGenerationAge>20</maxGenerationAge>
<combatPower>500</combatPower>
<initialWillRange>10~20</initialWillRange>
<initialResistanceRange>10~20</initialResistanceRange>
<initialWillRange>99~99</initialWillRange>
<initialResistanceRange>99~99</initialResistanceRange>
<itemQuality>Legendary</itemQuality>
<minApparelQuality>Legendary</minApparelQuality>
<maxApparelQuality>Legendary</maxApparelQuality>
@@ -652,14 +668,14 @@
<isFighter>true</isFighter>
<weaponStuffOverride>Plasteel</weaponStuffOverride>
<apparelTags>
<li>Wula_Armor_Super_Heavy</li>
<li>Wula_Legion_Apparel</li>
</apparelTags>
<weaponTags>
<li>WULA_MW_Twohanded_ChainBroadsword</li>
</weaponTags>
<apparelRequired>
<li>WULA_Heavy_Infantry_PowerArmor</li>
<li>WULA_Heavy_Infantry_Helmet</li>
<li>WULA_Heavy_Infantry_Helmet_Nomask</li>
<li>WULA_Champion_Warrior_Armor</li>
</apparelRequired>
<weaponMoney>999999~999999</weaponMoney>
<biocodeWeaponChance>1</biocodeWeaponChance>
@@ -682,5 +698,9 @@
<fixedAdultBackstories>
<li>WULA_Adult_Backstory_Legion_Escort</li>
</fixedAdultBackstories>
<forcedTraits>
<li>WULA_Trait_Broken_Personality</li>
</forcedTraits>
</PawnKindDef>
</Defs>

View File

@@ -331,9 +331,9 @@
<parms>
<allowedThreats>Raids</allowedThreats>
<onDays>1.0</onDays>
<offDays>1.5</offDays>
<offDays>0.25</offDays>
<minSpacingDays>0.04</minSpacingDays>
<numIncidentsRange>1~1</numIncidentsRange>
<numIncidentsRange>1~2</numIncidentsRange>
<currentThreatPointsFactor>1.1</currentThreatPointsFactor>
<minThreatPoints>500</minThreatPoints>
</parms>

View File

@@ -81,11 +81,6 @@
<thingDef>Apparel_WULA_Manpack_Loitering_Munition</thingDef>
<count>2</count>
</li>
<li Class="ScenPart_StartingThing_Defined">
<def>StartingThing_Defined</def>
<thingDef>WULA_Charge_Cube</thingDef>
<count>10</count>
</li>
<li Class="ScenPart_StartingThing_Defined">
<def>StartingThing_Defined</def>
<thingDef>WULA_Fake_Mothership_Beacon_Building</thingDef>

View File

@@ -1618,7 +1618,7 @@
<texPath>Wula/Building/Wula_Fusion_Generators_Incoming</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutFlying</shaderType>
<drawSize>(3,3)</drawSize>
<drawSize>(3.5,3.5)</drawSize>
</graphicData>
<skyfaller>
<movementType>Accelerate</movementType>
@@ -1654,7 +1654,8 @@
<graphicData>
<texPath>Wula/Building/Wula_Fusion_Generators</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>(3,3)</drawSize>
<drawSize>(3.5,3.5)</drawSize>
<drawOffset>(0, 0, 0.3)</drawOffset>
<shadowData>
<volume>(1.93,1,1.69)</volume>
<offset>(-0.03,0,-0.1)</offset>

View File

@@ -751,6 +751,8 @@
</statBases>
<equippedStatOffsets>
<IncomingDamageFactor>-0.1</IncomingDamageFactor>
<ToxicResistance>1</ToxicResistance>
<ToxicEnvironmentResistance MayRequire="Ludeon.RimWorld.Biotech">1</ToxicEnvironmentResistance>
</equippedStatOffsets>
<apparel>
<tags>
@@ -766,6 +768,134 @@
<Uranium>20</Uranium>
</costList>
</ThingDef>
<ThingDef ParentName="WULA_ApparelHelmetBase">
<defName>WULA_Heavy_Infantry_Helmet_Nomask</defName>
<label>乌拉帝国重装头盔(无面罩)</label>
<description>与乌拉帝国重装装甲配套的头盔,防御力强大。这个版本不配发面罩,因为军需处终于想起来了机械乌拉是不会中毒的。</description>
<thingCategories>
<li>HeadgearNoble</li>
</thingCategories>
<recipeMaker>
<skillRequirements>
<Crafting>10</Crafting>
</skillRequirements>
<researchPrerequisite>WULA_Synth_Armor_2_Technology</researchPrerequisite>
</recipeMaker>
<graphicData>
<texPath>Wula/Apparel/WULA_Heavy_Infantry_Helmet_Nomask</texPath>
</graphicData>
<statBases>
<WorkToMake>20000</WorkToMake>
<MaxHitPoints>1000</MaxHitPoints>
<Mass>5</Mass>
<Flammability>0</Flammability>
<ArmorRating_Sharp>1.5</ArmorRating_Sharp>
<ArmorRating_Blunt>1.5</ArmorRating_Blunt>
<ArmorRating_Heat>2.0</ArmorRating_Heat>
<EquipDelay>5</EquipDelay>
</statBases>
<equippedStatOffsets>
<IncomingDamageFactor>-0.1</IncomingDamageFactor>
</equippedStatOffsets>
<apparel>
<tags>
<li>WULA_Heavy_Infantry_Helmet_Nomask</li>
<li>RoyalTier5</li>
<li>Royal</li>
</tags>
<wornGraphicPath>Wula/Apparel/WULA_Heavy_Infantry_Helmet_Nomask</wornGraphicPath>
</apparel>
<costStuffCount>0</costStuffCount>
<costList Inherit="False">
<WULA_Neutronium>2</WULA_Neutronium>
<Uranium>15</Uranium>
</costList>
</ThingDef>
<ThingDef ParentName="WULA_ApparelArmorBase">
<defName>WULA_Champion_Warrior_Armor</defName>
<label>乌拉帝国冠军甲胄</label>
<description>为乌拉帝国的野心冠军勇士提供的护甲,它比起那些重型护甲要轻便不少。此外,它装备了稀有的双层全反射盾,外部射弹根本无法穿透其护盾,这使得对手只能进入护盾范围内与其近身搏斗。</description>
<thingCategories>
<li>ApparelNoble</li>
</thingCategories>
<recipeMaker Inherit="False"/>
<useHitPoints>false</useHitPoints>
<graphicData>
<texPath>Wula/Apparel/WULA_Champion_Warrior_Armor</texPath>
</graphicData>
<statBases>
<WorkToMake>50000</WorkToMake>
<Mass>5</Mass>
<Flammability>0</Flammability>
<ArmorRating_Sharp>1.3</ArmorRating_Sharp>
<ArmorRating_Blunt>1.3</ArmorRating_Blunt>
<ArmorRating_Heat>1.5</ArmorRating_Heat>
<EquipDelay>1</EquipDelay>
<MaxHitPoints>-1</MaxHitPoints>
<Flammability>0</Flammability>
<DeteriorationRate>0</DeteriorationRate>
<EnergyShieldEnergyMax>3</EnergyShieldEnergyMax>
</statBases>
<equippedStatOffsets>
<IncomingDamageFactor>-0.8</IncomingDamageFactor>
<StaggerDurationFactor>-2</StaggerDurationFactor>
<CarryingCapacity>250</CarryingCapacity>
<MoveSpeed>1</MoveSpeed>
<Flammability>-2</Flammability>
</equippedStatOffsets>
<costStuffCount>0</costStuffCount>
<costList Inherit="False">
<WULA_Alloy>300</WULA_Alloy>
<WULA_Dark_Matter_Item>25</WULA_Dark_Matter_Item>
<WULA_Neutronium>25</WULA_Neutronium>
<Uranium>200</Uranium>
</costList>
<apparel>
<tags>
<li>WULA_Champion_Warrior_Armor</li>
<li>RoyalTier5</li>
<li>Royal</li>
</tags>
<wornGraphicPath>Wula/Apparel/WULA_Champion_Warrior_Armor</wornGraphicPath>
</apparel>
<comps>
<li Class="CompProperties_Shield">
<startingTicksToReset>1000</startingTicksToReset><!-- 10 mins -->
<minDrawSize>2.5</minDrawSize>
<maxDrawSize>2.8</maxDrawSize>
<energyLossPerDamage>0.01</energyLossPerDamage>
<energyOnReset>4.0</energyOnReset>
<blocksRangedWeapons>false</blocksRangedWeapons>
</li>
<li Class="WulaFallenEmpire.CompProperties_AreaShield">
<radius>6</radius>
<baseHitPoints>1</baseHitPoints>
<rechargeDelay>1</rechargeDelay>
<rechargeHitPointsIntervalTicks>30</rechargeHitPointsIntervalTicks>
<!-- 效果器配置 -->
<absorbEffecter>Interceptor_BlockedProjectile</absorbEffecter>
<interceptEffecter>Interceptor_BlockedProjectile</interceptEffecter>
<breakEffecter>Shield_Break</breakEffecter>
<reactivateEffecter>BulletShieldGenerator_Reactivate</reactivateEffecter>
<color>(0.9, 0.2, 0.2, 0.5)</color> <!-- 护盾气泡的颜色 (RGBA) -->
<!-- 拦截设置 -->
<interceptGroundProjectiles>true</interceptGroundProjectiles>
<interceptNonHostileProjectiles>false</interceptNonHostileProjectiles>
<interceptAirProjectiles>true</interceptAirProjectiles>
<!-- 反射设置 -->
<canReflect>true</canReflect>
<reflectChance>1</reflectChance>
<reflectAngleRange>30</reflectAngleRange>
<reflectCost>0</reflectCost>
<reflectEffecter>Interceptor_BlockedProjectile</reflectEffecter>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="WULA_ApparelShieldBase">
<defName>WULA_Shield_Base</defName>

View File

@@ -324,7 +324,7 @@
<li>WULA_MW_ChainSword_MultiStrike</li>
</capacities>
<armorPenetration>1.75</armorPenetration>
<power>35</power>
<power>30</power>
<cooldownTime>2</cooldownTime>
<soundMeleeHit>WULA_MW_ChainSword_Hit</soundMeleeHit>
<soundMeleeMiss>WULA_MW_ChainSword_Hit</soundMeleeMiss>
@@ -351,17 +351,19 @@
<strikeCount>8~12</strikeCount>
<damageMultiplierPerStrike>0.2</damageMultiplierPerStrike>
</li>
<li Class="CompProperties_EquippableAbilityReloadable">
<abilityDef>WULA_MW_Twohanded_ChainBroadsword_Ability</abilityDef>
<chargeNoun>传送核心</chargeNoun>
<li Class="WulaFallenEmpire.CompProperties_EquippableAbilities">
<abilityDefs>
<li>WULA_MW_Twohanded_ChainBroadsword_Second_Ability</li>
<li>WULA_MW_Twohanded_ChainBroadsword_Ability</li>
</abilityDefs>
</li>
</comps>
</ThingDef>
<AbilityDef>
<defName>WULA_MW_Twohanded_ChainBroadsword_Ability</defName>
<label>短距离跃迁</label>
<description>使用CBs-25"地狱牙"刀头的相位引擎立刻折跃至一个新的位置——这种折跃引擎只能折跃小型目标,如果持刀者体型大于1则无法发起传送。</description>
<iconPath>UI/Abilities/Skip</iconPath>
<description>使用CBs-25"地狱牙"刀头的相位引擎立刻折跃至一个新的位置——这种折跃引擎只能折跃小型目标,如果持刀者体型大于3则无法发起传送。</description>
<iconPath>Wula/UI/Abilities/WULA_TeleportSelf</iconPath>
<writeCombatLog>True</writeCombatLog>
<showPsycastEffects>False</showPsycastEffects>
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
@@ -385,7 +387,7 @@
<min>0</min>
<max>0</max>
</stunTicks>
<maxBodySize>1</maxBodySize>
<maxBodySize>3</maxBodySize>
<destClamorType>Impact</destClamorType>
<destClamorRadius>3</destClamorRadius>
<requireLineOfSight>false</requireLineOfSight>
@@ -399,6 +401,45 @@
</li>
</comps>
</AbilityDef>
<AbilityDef>
<defName>WULA_MW_Twohanded_ChainBroadsword_Second_Ability</defName>
<label>空间删除</label>
<description>使用CBs-25"地狱牙"刀头的相位引擎将目标拉近到施法者身边——这种折跃引擎只能折跃小型目标如果持刀者体型大于3则无法发起传送。</description>
<iconPath>Wula/UI/Abilities/WULA_PullTarget</iconPath>
<writeCombatLog>True</writeCombatLog>
<showPsycastEffects>False</showPsycastEffects>
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
<cooldownTicksRange>200</cooldownTicksRange>
<warmupEffecter>HoraxianSpellLight_Warmup</warmupEffecter>
<aiCanUse>true</aiCanUse>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<warmupTime>1</warmupTime>
<range>30</range>
<soundCast>WULA_Psi_Skip_Sound</soundCast>
<requireLineOfSight>false</requireLineOfSight>
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</verbProperties>
<comps>
<li Class="WulaFallenEmpire.CompProperties_AbilityPullTarget">
<range>30</range>
<maxTargetBodySize>3</maxTargetBodySize>
<minRange>1.75</minRange> <!-- 最小距离1格 -->
<stunTicks>
<min>15</min>
<max>15</max>
</stunTicks>
<pullDestinationSearchRadius>3</pullDestinationSearchRadius>
<destClamorType>Impact</destClamorType>
<destClamorRadius>3</destClamorRadius>
<canPullHostile>true</canPullHostile>
<canPullNeutral>true</canPullNeutral>
<canPullFriendly>true</canPullFriendly>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="WULA_ExperienceCore_Weapon_Melee">
<defName>WULA_MW_Breaker_Bar</defName>
<label>PMb-97"破墙槌"</label>
@@ -508,7 +549,7 @@
<defName>WULA_MW_Breaker_Bar_Ability</defName>
<label>破阵重击</label>
<description>将PMb-97"破墙槌"的锤头加到最大压强,随后挥出必中的一击,以突破严密的人墙——即使敌人侥幸存活,也会头晕目眩并被砸飞出一段距离。</description>
<iconPath>UI/Abilities/UnnaturalHealing</iconPath>
<iconPath>Wula/UI/Abilities/WULA_MW_Breaker_Bar_Ability</iconPath>
<cooldownTicksRange>300</cooldownTicksRange> <!-- 6 days -->
<showPsycastEffects>false</showPsycastEffects>
<stunTargetWhileCasting>true</stunTargetWhileCasting>
@@ -1030,7 +1071,7 @@
<defName>WULA_RW_EMP_RF_EMP_Ability</defName>
<label>发射EMP榴弹</label>
<description>使用FLm-78"萤石"下挂的榴弹发射器发射一枚EMP榴弹以击破护盾和控制机械族这种重型榴弹发射器发射距离较远但是需要一点时间架设开火。</description>
<iconPath>Wula/UI/Abilities/WULA_RW_Auto_GL_Smoke_Ability</iconPath>
<iconPath>Wula/UI/Abilities/WULA_RW_EMP_RF_EMP_Ability</iconPath>
<writeCombatLog>True</writeCombatLog>
<showPsycastEffects>False</showPsycastEffects>
<hotKey>Misc11</hotKey>

View File

@@ -166,7 +166,7 @@
<degreeDatas>
<li>
<label>破碎人格</label>
<description>这个乌拉帝国合成人没有完整的人格,这使得她更像是一台真正的机械——除了饮食外,所有的需求都已经被禁用</description>
<description>这个乌拉帝国合成人没有完整的人格,这使得她更像是一台真正的机械。</description>
<disablesNeeds>
<li>Mood</li>
<li>Joy</li>

View File

@@ -57,24 +57,6 @@
<WULA_NanoRepair_DisabledMsg>{0}的纳米修复系统已禁用</WULA_NanoRepair_DisabledMsg>
<WULA_NanoRepair_Disabled>纳米修复: 已禁用</WULA_NanoRepair_Disabled>
<!-- 消息文本 -->
<WULA_NoRecyclableMechanoidsNearby>附近没有可回收的乌拉猫猫。</WULA_NoRecyclableMechanoidsNearby>
<WULA_RecyclerStorageFull>地堡已满。</WULA_RecyclerStorageFull>
<WULA_CalledMechanoidsForRecycling>已调用 {0} 个乌拉猫猫回到地堡。</WULA_CalledMechanoidsForRecycling>
<WULA_MechanoidRecycled>已回收 {0}。</WULA_MechanoidRecycled>
<WULA_NoMechanoidsAvailableForConversion>没有可转换的乌拉猫猫。</WULA_NoMechanoidsAvailableForConversion>
<WULA_NotEnoughStoredMechanoids>地堡内的的乌拉猫猫不足。</WULA_NotEnoughStoredMechanoids>
<WULA_ConvertingMechanoids>正在将地堡内的{0}个乌拉猫猫转换为{1}。</WULA_ConvertingMechanoids>
<!-- Gizmo 文本 -->
<WULA_RecycleNearbyMechanoids>呼叫乌拉猫猫进驻</WULA_RecycleNearbyMechanoids>
<WULA_RecycleNearbyMechanoidsDesc>呼叫{0}格内的乌拉猫猫前来报到,以便转换为其他类型的猫猫,或是使用地堡内武器抵御敌军。</WULA_RecycleNearbyMechanoidsDesc>
<WULA_RecycleNearbyMechanoidsDisabled>地堡存储已满。</WULA_RecycleNearbyMechanoidsDisabled>
<WULA_ConvertMechanoids>释放乌拉猫猫</WULA_ConvertMechanoids>
<WULA_ConvertMechanoidsDesc>将地堡内的乌拉猫猫释放出来,它们可以在离开前重新选择装备以转变类型。\n容量{0}/{1}</WULA_ConvertMechanoidsDesc>
<WULA_ConvertMechanoidsDisabled>地堡内没有乌拉猫猫待命。</WULA_ConvertMechanoidsDisabled>
<!-- 检查字符串 -->
<WULA_StoredInfo>容量:{0}/{1}</WULA_StoredInfo>
<WULA_CallSkyfaller>召唤空投建筑</WULA_CallSkyfaller>
<WULA_CallSkyfallerDesc>从乌拉帝国的舰队呼叫对应的建筑空投到此处</WULA_CallSkyfallerDesc>
<WULA_SkyfallerIncoming>空投建筑将在 {0} 后到达</WULA_SkyfallerIncoming>
@@ -311,4 +293,54 @@
<WULA_ShowAreaShieldLabel>显示区域反射盾</WULA_ShowAreaShieldLabel>
<WULA_HideAreaShieldDesc>隐藏该单位的区域反射盾,这不会影响其实际功能,仅影响视觉效果</WULA_HideAreaShieldDesc>
<WULA_ShowAreaShieldDesc>显示该单位的区域反射盾,这不会影响其实际功能,仅影响视觉效果</WULA_ShowAreaShieldDesc>
<!-- Building_MechanoidRecycler.cs -->
<WULA_RecyclerFull>地堡已满。</WULA_RecyclerFull>
<WULA_MechRecycled>已回收 {0}。 (当前: {1}/{2})</WULA_MechRecycled>
<WULA_NoMechsToConvert>没有可转换的乌拉猫猫。</WULA_NoMechsToConvert>
<WULA_NotEnoughMechs>地堡内的的乌拉猫猫不足。</WULA_NotEnoughMechs>
<WULA_ConvertingMechs>正在将地堡内的{0}个乌拉猫猫转换为{1}。</WULA_ConvertingMechs>
<WULA_RecycleNearbyMechs>呼叫乌拉猫猫进驻</WULA_RecycleNearbyMechs>
<WULA_RecycleNearbyMechsDesc>呼叫{0}格内的乌拉猫猫前来报到,以便转换为其他类型的猫猫,或是使用地堡内武器抵御敌军。</WULA_RecycleNearbyMechsDesc>
<WULA_StorageFull>地堡存储已满。</WULA_StorageFull>
<WULA_ConvertMechs>释放乌拉猫猫</WULA_ConvertMechs>
<WULA_ConvertMechsDesc>将地堡内的乌拉猫猫释放出来,它们可以在离开前重新选择装备以转变类型。\n容量{0}/{1}</WULA_ConvertMechsDesc>
<WULA_NoAvailableMechs>地堡内没有乌拉猫猫待命。</WULA_NoAvailableMechs>
<WULA_NoNearbyRecyclableMechs>附近没有可回收的乌拉猫猫。</WULA_NoNearbyRecyclableMechs>
<WULA_MechsOrderedToRecycle>已调用 {0} 个乌拉猫猫回到地堡。</WULA_MechsOrderedToRecycle>
<WULA_StoredMechs>容量: {0}/{1}</WULA_StoredMechs>
<WULA_TransformCooldown>转换冷却: {0} 小时</WULA_TransformCooldown>
<!-- CompTransformAtFullCapacity.cs -->
<WULA_BuildingCooldown>建筑刚部署,需要等待 {0} 小时后才能转换</WULA_BuildingCooldown>
<WULA_NeedMoreMechs>需要进驻 {0} 个乌拉猫猫,当前: {1}/{2}</WULA_NeedMoreMechs>
<WULA_CooldownRemaining>冷却时间剩余: {0} 小时</WULA_CooldownRemaining>
<WULA_TargetUnit>目标单位: {0}</WULA_TargetUnit>
<WULA_MechsRequired>需要乌拉猫猫: {0} 个</WULA_MechsRequired>
<WULA_BuildingTransformedToPawn>{0} 已转换为 {1}</WULA_BuildingTransformedToPawn>
<!-- CompTransformIntoBuilding.cs -->
<WULA_UnitNotSpawned>单位未生成或已销毁</WULA_UnitNotSpawned>
<WULA_CannotDetermineBuildingType>无法确定目标建筑类型</WULA_CannotDetermineBuildingType>
<WULA_NoSuitablePositionFound>周围没有找到合适的放置位置</WULA_NoSuitablePositionFound>
<WULA_DeployingAtNearbyPosition>将在附近位置 {0} 部署建筑</WULA_DeployingAtNearbyPosition>
<WULA_CannotDeployBuilding>无法部署建筑: {0}</WULA_CannotDeployBuilding>
<WULA_PawnDeployedAsBuilding>{0} 已部署为 {1}</WULA_PawnDeployedAsBuilding>
<WULA_WillRestoreTo>将恢复为: {0}</WULA_WillRestoreTo>
<WULA_MaxStorageCapacity>最大存储容量: {0} 个乌拉猫猫</WULA_MaxStorageCapacity>
<WULA_PositionValid>✓ 当前位置可以放置建筑</WULA_PositionValid>
<WULA_PositionInvalid>✗ {0}</WULA_PositionInvalid>
<WULA_TeleportFailedNoValidLocation>传送后无有效落脚位置,已取消传送。</WULA_TeleportFailedNoValidLocation>
<WULA_CannotTeleportToLocation>无效传送位置</WULA_CannotTeleportToLocation>
<!-- CompAbilityEffect_PullTarget.cs -->
<WULA_InvalidPullTarget>无法拉取该目标</WULA_InvalidPullTarget>
<WULA_TargetTooLarge>{0} 体型过大,无法拉取(最大体型:{1}</WULA_TargetTooLarge>
<WULA_PullFailedNoValidLocation>拉取失败:找不到合适的落地位置</WULA_PullFailedNoValidLocation>
<WULA_MustTargetPawn>必须选择一个生物作为目标</WULA_MustTargetPawn>
<WULA_TargetOutOfRange>目标超出范围(最大范围:{0}</WULA_TargetOutOfRange>
<WULA_TargetTooClose>目标距离过近(最小距离:{0}格)</WULA_TargetTooClose>
<WULA_NoLineOfSight>没有视线到目标</WULA_NoLineOfSight>
<WULA_CannotPullTarget>无法拉取该目标</WULA_CannotPullTarget>
</LanguageData>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -97,7 +97,7 @@ namespace WulaFallenEmpire
// 如果无法找到有效位置,取消传送
if (!CanTeleportTo(finalTargetCell, map))
{
Messages.Message("TeleportFailedNoValidLocation".Translate(), caster, MessageTypeDefOf.RejectInput);
Messages.Message("WULA_TeleportFailedNoValidLocation".Translate(), caster, MessageTypeDefOf.RejectInput);
return;
}
@@ -218,7 +218,7 @@ namespace WulaFallenEmpire
{
if (showMessages)
{
Messages.Message("CannotTeleportToLocation".Translate(),
Messages.Message("WULA_CannotTeleportToLocation".Translate(),
new LookTargets(target.Cell, parent.pawn.Map),
MessageTypeDefOf.RejectInput);
}
@@ -294,7 +294,7 @@ namespace WulaFallenEmpire
{
if (!CanHitTarget(target))
{
return "CannotTeleportToLocation".Translate();
return "WULA_CannotTeleportToLocation".Translate();
}
return base.ExtraLabelMouseAttachment(target);
}

View File

@@ -0,0 +1,66 @@
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using Verse;
namespace WulaFallenEmpire
{
public class CompEquippableAbilities : ThingComp
{
public CompProperties_EquippableAbilities Props => (CompProperties_EquippableAbilities)props;
private Pawn wearer;
private List<Ability> grantedAbilities = new List<Ability>();
public override void Notify_Equipped(Pawn pawn)
{
base.Notify_Equipped(pawn);
wearer = pawn;
GrantAbilities(pawn);
}
public override void Notify_Unequipped(Pawn pawn)
{
base.Notify_Unequipped(pawn);
RemoveAbilities(pawn);
wearer = null;
}
private void GrantAbilities(Pawn pawn)
{
if (pawn.abilities == null || Props.abilityDefs == null)
return;
foreach (AbilityDef abilityDef in Props.abilityDefs)
{
if (!pawn.abilities.abilities.Any(a => a.def == abilityDef))
{
Ability ability = new Ability(pawn, abilityDef);
pawn.abilities.GainAbility(abilityDef);
grantedAbilities.Add(ability);
}
}
}
private void RemoveAbilities(Pawn pawn)
{
if (pawn.abilities == null)
return;
foreach (Ability ability in grantedAbilities)
{
pawn.abilities.RemoveAbility(ability.def);
}
grantedAbilities.Clear();
}
public override string CompInspectStringExtra()
{
if (Props.abilityDefs != null && Props.abilityDefs.Count > 0)
{
return $"授予技能: {Props.abilityDefs.Count}";
}
return base.CompInspectStringExtra();
}
}
}

View File

@@ -0,0 +1,16 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
namespace WulaFallenEmpire
{
public class CompProperties_EquippableAbilities : CompProperties
{
public List<AbilityDef> abilityDefs;
public CompProperties_EquippableAbilities()
{
compClass = typeof(CompEquippableAbilities);
}
}
}

View File

@@ -0,0 +1,439 @@
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.Sound;
namespace WulaFallenEmpire
{
public class CompAbilityEffect_PullTarget : CompAbilityEffect
{
public static string PullUsedSignalTag = "CompAbilityEffect.PullUsed";
public new CompProperties_AbilityPullTarget Props => (CompProperties_AbilityPullTarget)props;
public override IEnumerable<PreCastAction> GetPreCastActions()
{
yield return new PreCastAction
{
action = delegate(LocalTargetInfo target, LocalTargetInfo dest)
{
Pawn caster = parent.pawn;
Pawn targetPawn = target.Pawn;
Map map = caster.Map;
if (targetPawn == null || !IsValidPullTarget(targetPawn))
{
Messages.Message("WULA_InvalidPullTarget".Translate(), caster, MessageTypeDefOf.RejectInput);
return;
}
// 在目标位置创建入口特效
if (Props.customEntryFleck != null)
{
FleckMaker.Static(targetPawn.Position, map, Props.customEntryFleck);
}
else
{
FleckMaker.Static(targetPawn.Position, map, FleckDefOf.PsycastSkipFlashEntry);
}
// 播放拉取音效
SoundDefOf.Psycast_Skip_Entry.PlayOneShot(new TargetInfo(targetPawn.Position, map));
// 计算拉取目的地
IntVec3 pullDestination = FindPullDestination(caster, targetPawn, map);
// 存储拉取目的地
this.pullDestination = pullDestination;
},
ticksAwayFromCast = 5
};
}
private IntVec3 pullDestination = IntVec3.Invalid;
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
Pawn caster = parent.pawn;
Pawn targetPawn = target.Pawn;
Map map = caster.Map;
if (targetPawn == null || !IsValidPullTarget(targetPawn))
{
Messages.Message("WULA_InvalidPullTarget".Translate(), caster, MessageTypeDefOf.RejectInput);
return;
}
// 使用存储的拉取目的地或重新计算
IntVec3 finalDestination = this.pullDestination.IsValid ? this.pullDestination : FindPullDestination(caster, targetPawn, map);
this.pullDestination = IntVec3.Invalid;
// 验证目的地
finalDestination = ValidateAndAdjustDestination(finalDestination, targetPawn, map);
if (!CanTeleportTo(finalDestination, map))
{
Messages.Message("WULA_PullFailedNoValidLocation".Translate(), caster, MessageTypeDefOf.RejectInput);
return;
}
// 目标位置入口效果器
EffecterDef entryEffecter = Props.customEntryEffecter ?? EffecterDefOf.Skip_Entry;
Effecter entryEffect = entryEffecter.Spawn(targetPawn, map);
parent.AddEffecterToMaintain(entryEffect, targetPawn.Position, 60);
// 目的地出口效果器
EffecterDef exitEffecter = Props.customExitEffecter ?? EffecterDefOf.Skip_Exit;
Effecter exitEffect = exitEffecter.Spawn(finalDestination, map);
parent.AddEffecterToMaintain(exitEffect, finalDestination, 60);
// 执行传送(拉取)
targetPawn.Position = finalDestination;
targetPawn.Notify_Teleported();
// 如果是玩家阵营,解除战争迷雾
if ((targetPawn.Faction == Faction.OfPlayer || targetPawn.IsPlayerControlled) && targetPawn.Position.Fogged(map))
{
FloodFillerFog.FloodUnfog(targetPawn.Position, map);
}
// 拉取后眩晕目标
targetPawn.stances.stunner.StunFor(Props.stunTicks.RandomInRange, caster, addBattleLog: true, showMote: true);
// 发送拉取信号
SendPullUsedSignal(targetPawn.Position, caster);
// 播放到达时的喧嚣效果
if (Props.destClamorType != null)
{
float adjustedRadius = Props.destClamorRadius * Props.effectScale;
GenClamor.DoClamor(caster, finalDestination, adjustedRadius, Props.destClamorType);
}
// 播放拉取成功音效
SoundDefOf.Psycast_Skip_Exit.PlayOneShot(new TargetInfo(finalDestination, map));
// 记录拉取信息
if (Prefs.DevMode)
{
Log.Message($"[PullTarget] {caster.Label} 将 {targetPawn.Label} 拉取到 {finalDestination}");
}
}
/// <summary>
/// 检查目标是否可以被拉取
/// </summary>
private bool IsValidPullTarget(Pawn target)
{
// 检查目标是否为Pawn
if (target == null)
return false;
// 检查体型限制
if (target.BodySize > Props.maxTargetBodySize)
{
Messages.Message("WULA_TargetTooLarge".Translate(target.LabelShort, Props.maxTargetBodySize),
parent.pawn, MessageTypeDefOf.RejectInput);
return false;
}
// 检查目标是否死亡或倒下
if (target.Dead || target.Downed)
return false;
// 检查目标是否可被影响(根据派系关系)
if (!Props.canPullHostile && target.HostileTo(parent.pawn.Faction))
return false;
if (!Props.canPullNeutral && target.Faction != null && !target.HostileTo(parent.pawn.Faction) && target.Faction != parent.pawn.Faction)
return false;
if (!Props.canPullFriendly && target.Faction == parent.pawn.Faction)
return false;
// 检查特殊免疫状态
if (target.GetComp<CompImmuneToPull>() != null)
return false;
return true;
}
/// <summary>
/// 寻找拉取目的地(施法者附近的合适位置)
/// </summary>
private IntVec3 FindPullDestination(Pawn caster, Pawn target, Map map)
{
// 在施法者周围寻找合适的拉取位置
IntVec3 center = caster.Position;
int searchRadius = Props.pullDestinationSearchRadius;
// 优先选择施法者周围的空位
for (int radius = 1; radius <= searchRadius; radius++)
{
foreach (IntVec3 cell in GenRadial.RadialCellsAround(center, radius, true))
{
if (cell.InBounds(map) &&
CanTeleportTo(cell, map) &&
cell != caster.Position && // 避免和目标重叠
cell != target.Position)
{
// 检查该位置是否在施法者视线内(可选)
if (!Props.requireLineOfSightToDestination || GenSight.LineOfSight(center, cell, map))
{
return cell;
}
}
}
}
// 如果找不到合适位置,返回施法者位置(作为备选)
return center;
}
/// <summary>
/// 验证并调整拉取目的地
/// </summary>
private IntVec3 ValidateAndAdjustDestination(IntVec3 destination, Pawn target, Map map)
{
// 如果目的地不可传送,寻找替代位置
if (!CanTeleportTo(destination, map))
{
IntVec3 adjustedCell = FindNearestValidTeleportPosition(destination, target, map, Props.maxPositionAdjustRadius);
if (adjustedCell.IsValid)
{
return adjustedCell;
}
}
return destination;
}
/// <summary>
/// 寻找最近的可行传送位置
/// </summary>
private IntVec3 FindNearestValidTeleportPosition(IntVec3 center, Pawn pawn, Map map, int maxRadius = 15)
{
// 首先检查中心点本身
if (CanTeleportTo(center, map))
return center;
// 在逐渐增大的半径内搜索
for (int radius = 1; radius <= maxRadius; radius++)
{
int numCells = GenRadial.NumCellsInRadius(radius);
for (int i = 0; i < numCells; i++)
{
IntVec3 cell = center + GenRadial.RadialPattern[i];
if (cell.InBounds(map) && CanTeleportTo(cell, map))
{
return cell;
}
}
}
return IntVec3.Invalid;
}
public override bool Valid(LocalTargetInfo target, bool showMessages = true)
{
Pawn targetPawn = target.Pawn;
if (targetPawn == null)
{
if (showMessages)
{
Messages.Message("WULA_MustTargetPawn".Translate(),
new LookTargets(parent.pawn),
MessageTypeDefOf.RejectInput);
}
return false;
}
if (!IsValidPullTarget(targetPawn))
{
if (showMessages)
{
// 错误消息已经在IsValidPullTarget中显示
}
return false;
}
// 检查最小距离 - 新增:不允许对身边一格的单位释放
float distance = target.Cell.DistanceTo(parent.pawn.Position);
if (distance <= Props.minRange)
{
if (showMessages)
{
Messages.Message("WULA_TargetTooClose".Translate(Props.minRange),
new LookTargets(parent.pawn),
MessageTypeDefOf.RejectInput);
}
return false;
}
// 检查最大距离
if (distance > Props.range)
{
if (showMessages)
{
Messages.Message("WULA_TargetOutOfRange".Translate(Props.range),
new LookTargets(parent.pawn),
MessageTypeDefOf.RejectInput);
}
return false;
}
// 检查视线(如果需要)
if (Props.requireLineOfSight && !GenSight.LineOfSight(parent.pawn.Position, target.Cell, parent.pawn.Map))
{
if (showMessages)
{
Messages.Message("WULA_NoLineOfSight".Translate(),
new LookTargets(parent.pawn),
MessageTypeDefOf.RejectInput);
}
return false;
}
return base.Valid(target, showMessages);
}
/// <summary>
/// 检查是否可以命中目标
/// </summary>
public bool CanHitTarget(LocalTargetInfo target)
{
Pawn targetPawn = target.Pawn;
if (targetPawn == null)
return false;
// 检查距离
float distance = target.Cell.DistanceTo(parent.pawn.Position);
// 新增:检查最小距离
if (distance <= Props.minRange)
return false;
if (Props.range > 0f && distance > Props.range)
return false;
// 检查视线(如果需要)
if (Props.requireLineOfSight && !GenSight.LineOfSight(parent.pawn.Position, target.Cell, parent.pawn.Map))
return false;
// 检查目标有效性
return IsValidPullTarget(targetPawn);
}
/// <summary>
/// 检查是否可以传送到指定位置
/// </summary>
private bool CanTeleportTo(IntVec3 cell, Map map)
{
if (!cell.InBounds(map))
return false;
// 检查战争迷雾
if (!Props.canTeleportToFogged && cell.Fogged(map))
return false;
// 检查屋顶
if (!Props.canTeleportToRoofed && map.roofGrid.Roofed(cell))
return false;
// 检查是否可站立
if (!cell.Standable(map))
return false;
// 检查是否有障碍物
Building edifice = cell.GetEdifice(map);
if (edifice != null && edifice.def.surfaceType != SurfaceType.Item &&
edifice.def.surfaceType != SurfaceType.Eat && !(edifice is Building_Door { Open: not false }))
{
return false;
}
// 检查是否有物品阻挡
List<Thing> thingList = cell.GetThingList(map);
for (int i = 0; i < thingList.Count; i++)
{
if (thingList[i].def.category == ThingCategory.Item)
{
return false;
}
}
return true;
}
public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
{
if (!CanHitTarget(target))
{
// 检查具体原因以提供更精确的错误信息
Pawn targetPawn = target.Pawn;
float distance = target.Cell.DistanceTo(parent.pawn.Position);
if (targetPawn == null)
return "WULA_MustTargetPawn".Translate();
if (distance <= Props.minRange)
return "WULA_TargetTooClose".Translate(Props.minRange);
if (Props.range > 0f && distance > Props.range)
return "WULA_TargetOutOfRange".Translate(Props.range);
if (Props.requireLineOfSight && !GenSight.LineOfSight(parent.pawn.Position, target.Cell, parent.pawn.Map))
return "WULA_NoLineOfSight".Translate();
return "WULA_CannotPullTarget".Translate();
}
return base.ExtraLabelMouseAttachment(target);
}
public override void DrawEffectPreview(LocalTargetInfo target)
{
// 绘制目标高亮
GenDraw.DrawTargetHighlight(target);
// 绘制拉取范围
if (Props.range > 0)
{
GenDraw.DrawRadiusRing(parent.pawn.Position, Props.range);
}
// 绘制最小范围环 - 新增:显示不允许释放的区域
if (Props.minRange > 0)
{
GenDraw.DrawRadiusRing(parent.pawn.Position, Props.minRange, Color.red);
}
// 预览拉取目的地(如果可能)
Pawn targetPawn = target.Pawn;
if (targetPawn != null && IsValidPullTarget(targetPawn))
{
IntVec3 destination = FindPullDestination(parent.pawn, targetPawn, parent.pawn.Map);
if (destination.IsValid)
{
GenDraw.DrawCircleOutline(destination.ToVector3Shifted(), 1f, SimpleColor.Green);
}
}
}
public static void SendPullUsedSignal(LocalTargetInfo target, Thing initiator)
{
Find.SignalManager.SendSignal(new Signal(PullUsedSignalTag, target.Named("POSITION"), initiator.Named("SUBJECT")));
}
}
// 可选的免疫组件
public class CompImmuneToPull : ThingComp
{
// 简单的标记组件,表示该单位免疫拉取效果
}
}

View File

@@ -0,0 +1,47 @@
using RimWorld;
using Verse;
namespace WulaFallenEmpire
{
public class CompProperties_AbilityPullTarget : CompProperties_AbilityEffect
{
public float range = 12f;
public float minRange = 1f; // 新增最小拉取距离默认为1格
public IntRange stunTicks = new IntRange(30, 60);
public float maxTargetBodySize = 2f; // 最大可拉取目标的体型
// 拉取目的地设置
public int pullDestinationSearchRadius = 3; // 在施法者周围搜索拉取目的地的半径
public bool requireLineOfSightToDestination = false; // 是否需要视线到拉取目的地
// 到达时的喧嚣效果
public ClamorDef destClamorType;
public float destClamorRadius = 2f;
// 拉取限制
public bool requireLineOfSight = true;
public bool canTeleportToFogged = true;
public bool canTeleportToRoofed = true;
// 派系关系限制
public bool canPullHostile = true;
public bool canPullNeutral = true;
public bool canPullFriendly = false; // 默认不拉取友军
// 自定义效果器
public EffecterDef customEntryEffecter;
public EffecterDef customExitEffecter;
public FleckDef customEntryFleck;
public FleckDef customExitFleck;
public float effectScale = 1.0f; // 效果缩放比例
// 位置调整设置
public int maxPositionAdjustRadius = 15; // 最大位置调整半径
public bool allowPositionAdjustment = true; // 是否允许自动调整位置
public CompProperties_AbilityPullTarget()
{
compClass = typeof(CompAbilityEffect_PullTarget);
}
}
}

View File

@@ -53,14 +53,14 @@ namespace WulaFallenEmpire
{
if (storedMechanoidCount >= Props.maxStorageCapacity)
{
Messages.Message("回收器已满", MessageTypeDefOf.RejectInput);
Messages.Message("WULA_RecyclerFull".Translate(), MessageTypeDefOf.RejectInput);
return;
}
storedMechanoidCount++;
mech.Destroy(); // 直接销毁,不存储实例
Messages.Message($"机械族 {mech.LabelCap} 已回收 (当前: {storedMechanoidCount}/{Props.maxStorageCapacity})",
Messages.Message("WULA_MechRecycled".Translate(mech.LabelCap, storedMechanoidCount, Props.maxStorageCapacity),
MessageTypeDefOf.PositiveEvent);
// 通知转换组件存储更新
@@ -100,7 +100,7 @@ namespace WulaFallenEmpire
{
if (storedMechanoidCount == 0)
{
Messages.Message("没有可用的机械族进行转换", MessageTypeDefOf.RejectInput);
Messages.Message("WULA_NoMechsToConvert".Translate(), MessageTypeDefOf.RejectInput);
return;
}
@@ -121,7 +121,7 @@ namespace WulaFallenEmpire
{
if (!ConsumeMechanoids(count))
{
Messages.Message("机械族数量不足", MessageTypeDefOf.RejectInput);
Messages.Message("WULA_NotEnoughMechs".Translate(), MessageTypeDefOf.RejectInput);
return;
}
@@ -143,7 +143,7 @@ namespace WulaFallenEmpire
}
TrySpawnFromQueue();
Messages.Message($"正在转换 {count} 个机械族为 {kindDef.LabelCap}", MessageTypeDefOf.PositiveEvent);
Messages.Message("WULA_ConvertingMechs".Translate(count, kindDef.LabelCap), MessageTypeDefOf.PositiveEvent);
}
private void TrySpawnFromQueue()
@@ -194,15 +194,15 @@ namespace WulaFallenEmpire
// 回收附近机械族按钮
Command_Action recycleCommand = new Command_Action
{
defaultLabel = "回收附近机械族",
defaultDesc = $"命令附近 {Props.recycleRange} 格内的机械族前来回收",
defaultLabel = "WULA_RecycleNearbyMechs".Translate(),
defaultDesc = "WULA_RecycleNearbyMechsDesc".Translate(Props.recycleRange),
icon = ContentFinder<Texture2D>.Get("Wula/UI/Commands/WULA_RecycleNearbyMechanoids"),
action = RecycleNearbyMechanoids
};
if (storedMechanoidCount >= Props.maxStorageCapacity)
{
recycleCommand.Disable("储存器已满");
recycleCommand.Disable("WULA_StorageFull".Translate());
}
yield return recycleCommand;
@@ -210,15 +210,15 @@ namespace WulaFallenEmpire
// 生成机械族按钮
Command_Action spawnCommand = new Command_Action
{
defaultLabel = "转换机械族",
defaultDesc = $"将储存的机械族转换为其他单位 (当前: {storedMechanoidCount}/{Props.maxStorageCapacity})",
defaultLabel = "WULA_ConvertMechs".Translate(),
defaultDesc = "WULA_ConvertMechsDesc".Translate(storedMechanoidCount, Props.maxStorageCapacity),
icon = ContentFinder<Texture2D>.Get("Wula/UI/Commands/WULA_ConvertMechanoids"),
action = OpenSpawnInterface
};
if (storedMechanoidCount == 0)
{
spawnCommand.Disable("没有可用的机械族");
spawnCommand.Disable("WULA_NoAvailableMechs".Translate());
}
yield return spawnCommand;
@@ -229,7 +229,7 @@ namespace WulaFallenEmpire
{
if (storedMechanoidCount >= Props.maxStorageCapacity)
{
Messages.Message("储存器已满", MessageTypeDefOf.RejectInput);
Messages.Message("WULA_StorageFull".Translate(), MessageTypeDefOf.RejectInput);
return;
}
@@ -237,7 +237,7 @@ namespace WulaFallenEmpire
if (nearbyMechs.Count == 0)
{
Messages.Message("附近没有可回收的机械族", MessageTypeDefOf.RejectInput);
Messages.Message("WULA_NoNearbyRecyclableMechs".Translate(), MessageTypeDefOf.RejectInput);
return;
}
@@ -250,7 +250,7 @@ namespace WulaFallenEmpire
}
}
Messages.Message($"已命令 {assignedCount} 个机械族前来回收", MessageTypeDefOf.PositiveEvent);
Messages.Message("WULA_MechsOrderedToRecycle".Translate(assignedCount), MessageTypeDefOf.PositiveEvent);
}
private List<Pawn> FindNearbyRecyclableMechanoids()
@@ -312,7 +312,7 @@ namespace WulaFallenEmpire
stringBuilder.Append(baseString);
}
string storedInfo = $"储存机械族: {storedMechanoidCount}/{Props.maxStorageCapacity}";
string storedInfo = "WULA_StoredMechs".Translate(storedMechanoidCount, Props.maxStorageCapacity);
if (stringBuilder.Length > 0)
stringBuilder.AppendLine();
@@ -322,7 +322,7 @@ namespace WulaFallenEmpire
if (IsCooldownActive)
{
stringBuilder.AppendLine();
stringBuilder.Append($"转换冷却: {GetRemainingCooldownHours():F1} 小时");
stringBuilder.Append("WULA_TransformCooldown".Translate(GetRemainingCooldownHours().ToString("F1")));
}
return stringBuilder.ToString();

View File

@@ -9,8 +9,7 @@ namespace WulaFallenEmpire
{
private CompProperties_TransformAtFullCapacity Props => (CompProperties_TransformAtFullCapacity)props;
// 存储转换前的计数,用于恢复
private int storedCountAtTransform = 0;
// 移除存储计数的字段,不再进行数量传递
public Building_MechanoidRecycler Recycler => parent as Building_MechanoidRecycler;
public bool IsCooldownActive => Recycler?.IsCooldownActive ?? false;
@@ -24,7 +23,7 @@ namespace WulaFallenEmpire
public override void PostExposeData()
{
base.PostExposeData();
Scribe_Values.Look(ref storedCountAtTransform, "storedCountAtTransform", 0);
// 移除存储计数的保存
}
public override IEnumerable<Gizmo> CompGetGizmosExtra()
@@ -33,7 +32,7 @@ namespace WulaFallenEmpire
{
Command_Action command = new Command_Action
{
defaultLabel = Props.gizmoLabel,
defaultLabel = Props.gizmoLabel.Translate(),
defaultDesc = GetGizmoDescription(),
icon = GetGizmoIcon(),
action = TransformToPawn
@@ -42,11 +41,11 @@ namespace WulaFallenEmpire
// 禁用条件
if (IsCooldownActive)
{
command.Disable($"建筑刚部署,需要等待 {Recycler.GetRemainingCooldownHours():F1} 小时后才能转换");
command.Disable("WULA_BuildingCooldown".Translate(Recycler.GetRemainingCooldownHours().ToString("F1")));
}
else if (!IsAtFullCapacity)
{
command.Disable($"需要储存 {Props.requiredCapacity} 个机械族,当前: {Recycler.StoredCount}/{Props.requiredCapacity}");
command.Disable("WULA_NeedMoreMechs".Translate(Props.requiredCapacity, Recycler.StoredCount, Props.requiredCapacity));
}
yield return command;
@@ -55,12 +54,13 @@ namespace WulaFallenEmpire
private string GetGizmoDescription()
{
string desc = Props.gizmoDesc;
string desc = Props.gizmoDesc.Translate();
if (IsCooldownActive)
{
desc += $"\n\n冷却时间剩余: {Recycler.GetRemainingCooldownHours():F1} 小时";
desc += "\n\n" + "WULA_CooldownRemaining".Translate(Recycler.GetRemainingCooldownHours().ToString("F1"));
}
desc += $"\n目标单位: {Props.targetPawnKind.LabelCap}";
desc += "\n" + "WULA_TargetUnit".Translate(Props.targetPawnKind.LabelCap);
desc += "\n" + "WULA_MechsRequired".Translate(Props.requiredCapacity);
return desc;
}
@@ -92,13 +92,10 @@ namespace WulaFallenEmpire
IntVec3 position = parent.Position;
Faction faction = parent.Faction;
// 存储当前的机械族计数(用于恢复)
storedCountAtTransform = Recycler.StoredCount;
// 消耗存储的机械族
if (!Recycler.ConsumeMechanoids(Props.requiredCapacity))
{
Messages.Message("机械族数量不足", MessageTypeDefOf.RejectInput);
Messages.Message("WULA_NotEnoughMechs".Translate(), MessageTypeDefOf.RejectInput);
return;
}
@@ -117,11 +114,12 @@ namespace WulaFallenEmpire
Pawn newPawn = PawnGenerator.GeneratePawn(request);
// 添加转换组件并设置恢复数据
// 添加转换组件,只传递建筑定义,不传递数量
var transformComp = newPawn.GetComp<CompTransformIntoBuilding>();
if (transformComp != null)
{
transformComp.SetRestoreData(parent.def, storedCountAtTransform);
// 只设置建筑定义,不设置恢复数量
transformComp.SetRestoreData(parent.def);
}
else
{
@@ -135,7 +133,8 @@ namespace WulaFallenEmpire
transformComp.props = compProps;
newPawn.AllComps.Add(transformComp);
transformComp.Initialize(compProps);
transformComp.SetRestoreData(parent.def, storedCountAtTransform);
// 只设置建筑定义,不设置恢复数量
transformComp.SetRestoreData(parent.def);
}
// 移除建筑
@@ -150,7 +149,7 @@ namespace WulaFallenEmpire
Find.Selector.Select(newPawn);
}
Messages.Message($"{parent.Label} 已转换为 {newPawn.LabelCap}", MessageTypeDefOf.PositiveEvent);
Messages.Message("WULA_BuildingTransformedToPawn".Translate(parent.Label, newPawn.LabelCap), MessageTypeDefOf.PositiveEvent);
// 播放转换效果
PlayTransformEffects(position, map);

View File

@@ -11,9 +11,8 @@ namespace WulaFallenEmpire
private CompProperties_TransformIntoBuilding Props => (CompProperties_TransformIntoBuilding)props;
private Pawn Pawn => (Pawn)parent;
// 恢复数据
// 恢复数据 - 只存储建筑定义,不存储数量
private ThingDef restoreBuildingDef;
private int restoreMechanoidCount;
// 缓存校验结果
private bool? lastValidationResult = null;
@@ -29,14 +28,13 @@ namespace WulaFallenEmpire
{
base.PostExposeData();
Scribe_Defs.Look(ref restoreBuildingDef, "restoreBuildingDef");
Scribe_Values.Look(ref restoreMechanoidCount, "restoreMechanoidCount", 0);
// 移除存储数量的保存
}
// 设置恢复数据
public void SetRestoreData(ThingDef buildingDef, int mechanoidCount)
// 设置恢复数据 - 只设置建筑定义
public void SetRestoreData(ThingDef buildingDef)
{
restoreBuildingDef = buildingDef;
restoreMechanoidCount = mechanoidCount;
}
public override IEnumerable<Gizmo> CompGetGizmosExtra()
@@ -45,7 +43,7 @@ namespace WulaFallenEmpire
{
Command_Action command = new Command_Action
{
defaultLabel = Props.gizmoLabel,
defaultLabel = Props.gizmoLabel.Translate(),
defaultDesc = GetGizmoDescription(),
icon = GetGizmoIcon(),
action = TransformToBuilding
@@ -67,18 +65,20 @@ namespace WulaFallenEmpire
private string GetGizmoDescription()
{
StringBuilder sb = new StringBuilder();
sb.Append(Props.gizmoDesc);
sb.Append(Props.gizmoDesc.Translate());
if (restoreBuildingDef != null)
{
sb.AppendLine();
sb.AppendLine();
sb.Append($"将恢复为: {restoreBuildingDef.LabelCap}");
sb.Append("WULA_WillRestoreTo".Translate(restoreBuildingDef.LabelCap));
if (restoreMechanoidCount > 0)
// 显示目标建筑的最大存储容量
var recyclerProps = restoreBuildingDef.GetCompProperties<CompProperties_MechanoidRecycler>();
if (recyclerProps != null)
{
sb.AppendLine();
sb.Append($"恢复机械族储存: {restoreMechanoidCount}");
sb.Append("WULA_MaxStorageCapacity".Translate(recyclerProps.maxStorageCapacity));
}
}
@@ -90,11 +90,11 @@ namespace WulaFallenEmpire
sb.AppendLine();
if (isValid)
{
sb.Append("<color=green>✓ 当前位置可以放置建筑</color>");
sb.Append("WULA_PositionValid".Translate());
}
else
{
sb.Append($"<color=red>✗ {failReason}</color>");
sb.Append("WULA_PositionInvalid".Translate(failReason));
}
return sb.ToString();
@@ -118,7 +118,7 @@ namespace WulaFallenEmpire
if (parent == null || !parent.Spawned)
{
failReason = "单位未生成或已销毁";
failReason = "WULA_UnitNotSpawned".Translate();
return false;
}
@@ -126,7 +126,7 @@ namespace WulaFallenEmpire
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
if (buildingDef == null)
{
failReason = "无法确定目标建筑类型";
failReason = "WULA_CannotDetermineBuildingType".Translate();
return false;
}
@@ -166,7 +166,7 @@ namespace WulaFallenEmpire
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
if (buildingDef == null)
{
failReason = "无法确定目标建筑类型";
failReason = "WULA_CannotDetermineBuildingType".Translate();
return false;
}
@@ -185,7 +185,7 @@ namespace WulaFallenEmpire
}
}
failReason = "周围没有找到合适的放置位置";
failReason = "WULA_NoSuitablePositionFound".Translate();
return false;
}
@@ -202,7 +202,7 @@ namespace WulaFallenEmpire
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
if (buildingDef == null)
{
Messages.Message("无法确定目标建筑类型", MessageTypeDefOf.RejectInput);
Messages.Message("WULA_CannotDetermineBuildingType".Translate(), MessageTypeDefOf.RejectInput);
return;
}
@@ -215,11 +215,11 @@ namespace WulaFallenEmpire
if (TryFindNearbyValidPosition(out alternativePosition, out failReason))
{
desiredPosition = alternativePosition;
Messages.Message($"将在附近位置 {desiredPosition} 部署建筑", MessageTypeDefOf.NeutralEvent);
Messages.Message("WULA_DeployingAtNearbyPosition".Translate(desiredPosition), MessageTypeDefOf.NeutralEvent);
}
else
{
Messages.Message($"无法部署建筑: {failReason}", MessageTypeDefOf.RejectInput);
Messages.Message("WULA_CannotDeployBuilding".Translate(failReason), MessageTypeDefOf.RejectInput);
return;
}
}
@@ -231,12 +231,8 @@ namespace WulaFallenEmpire
Building newBuilding = (Building)GenSpawn.Spawn(buildingDef, desiredPosition, map, WipeMode.Vanish);
newBuilding.SetFaction(faction);
// 恢复机械族计数
var recycler = newBuilding as Building_MechanoidRecycler;
if (recycler != null && restoreMechanoidCount > 0)
{
recycler.SetMechanoidCount(restoreMechanoidCount);
}
// 不再恢复机械族计数,新建筑为空状态
// 如果需要,可以在这里设置初始状态,但不再传递之前的数量
// 添加建筑转换组件
var transformComp = newBuilding.TryGetComp<CompTransformAtFullCapacity>();
@@ -260,7 +256,7 @@ namespace WulaFallenEmpire
Find.Selector.Select(newBuilding);
}
Messages.Message($"{Pawn.LabelCap} 已部署为 {newBuilding.Label}", MessageTypeDefOf.PositiveEvent);
Messages.Message("WULA_PawnDeployedAsBuilding".Translate(Pawn.LabelCap, newBuilding.Label), MessageTypeDefOf.PositiveEvent);
// 播放转换效果
PlayTransformEffects(desiredPosition, map);

View File

@@ -94,6 +94,10 @@
<Compile Include="Ability\WULA_AbilityTeleportSelf\CompProperties_AbilityTeleportSelf.cs" />
<Compile Include="Ability\WULA_AbilityStunKnockback\CompAbilityEffect_StunKnockback.cs" />
<Compile Include="Ability\WULA_AbilityStunKnockback\CompProperties_StunKnockback.cs" />
<Compile Include="Ability\WULA_EquippableAbilities\CompEquippableAbilities.cs" />
<Compile Include="Ability\WULA_EquippableAbilities\CompProperties_EquippableAbilities.cs" />
<Compile Include="Ability\WULA_PullTarget\CompAbilityEffect_PullTarget.cs" />
<Compile Include="Ability\WULA_PullTarget\CompProperties_AbilityPullTarget.cs" />
<Compile Include="BuildingComp\Building_ExtraGraphics.cs" />
<Compile Include="BuildingComp\Building_MapObserver.cs" />
<Compile Include="BuildingComp\WULA_BuildingBombardment\CompBuildingBombardment.cs" />