diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 57bc513e..09c2f082 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/1.6/Defs/HediffDefs/Hediffs_WulaFallenEmpire.xml b/1.6/1.6/Defs/HediffDefs/Hediffs_WulaFallenEmpire.xml new file mode 100644 index 00000000..04628ff3 --- /dev/null +++ b/1.6/1.6/Defs/HediffDefs/Hediffs_WulaFallenEmpire.xml @@ -0,0 +1,42 @@ + + + + WULA_WeaponStealEffect + + 被磁力光束命中,磁力光束将会夺走当前所装备的武器. + HediffWithComps + (1,0,0.5) + 1.0 + 0.0 + true + +
  • + 30000 +
  • +
    + +
  • + + 0 +
  • +
  • + + 0.3 + + +
  • +
  • + + 0.6 + + +
  • +
  • + + 0.9 + + +
  • +
    +
    +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/ThingDefs_Races/Races_WulaFlyMech.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_WulaFlyMech.xml new file mode 100644 index 00000000..1dcdb550 --- /dev/null +++ b/1.6/1.6/Defs/ThingDefs_Races/Races_WulaFlyMech.xml @@ -0,0 +1,224 @@ + + + + + + + WULA_Mech_Flyer + + 乌拉帝国小型机械体 + +
  • + + fist + +
  • Blunt
  • + + 12.0 + 2 + LeftHand + true + +
  • + + fist + +
  • Blunt
  • + + 12.0 + 2 + RightHand + true + +
  • + + +
  • Blunt
  • + + 8.5 + 2 + HeadAttackTool + true + 0.2 + +
    + + Lancer + 0.72 + +
  • + ChunkMechanoidSlag + 11 + 0.1 +
  • +
  • + ChunkMechanoidSlag + 12 + 0.1 +
  • +
    + 0.5 +
    + + 0 + 30 + 10 + + + +
  • + +
  • + +
  • + WULA_MechFlyerTurretGun + -90 + false + +
  • + PawnRenderNode_TurretGun + PawnRenderNodeWorker_TurretGun + Body + (1, 1) + 20 + Any + + + 180 + (0, 0, 0) + + +
  • + + +
    +
    + + + WULA_Mech_Flyer + + WULA_Mech_Flyer + 190 + Things/Pawn/Animal/Goose/Goose_Flying_ + 8 + 2 + 1.35 + false + +
  • + + Things/Pawn/Mechanoid/LancerClean + Things/Pawn/Mechanoid/AllegianceOverlays/Mech_Lancer + CutoutWithOverlay + Graphic_Multi + 1.5 + + (0.4, 0.8, 0.4) + + +
  • +
  • + + Things/Pawn/Mechanoid/Lancer + Things/Pawn/Mechanoid/AllegianceOverlays/Mech_Lancer + CutoutWithOverlay + Graphic_Multi + 1.5 + + (0.4, 0.8, 0.4) + + +
  • +
    + 9999~9999 + +
  • MechanoidGunMedium
  • +
    + 1 + 9999~9999 +
    + + + WULA_MechFlyerTurretGun + + 乌拉小镰的内置炮塔。 + None + true + + Things/Building/TacticalTurret/TacticalTurret_Top + Graphic_Single + + + 2.6 + 0.60 + 0.80 + 0.90 + 0.85 + + +
  • + WulaFallenEmpire.Verb_ShootWeaponStealBeam + WULA_WeaponStealEffect + 0.1 + 1.0 + true + + true + 0 + 10 + 5 + 50 + Wula_Dark_Matter_Beam + 3 + + + 1000 + -1 + 0 + 0 + 0 + + + 0 + BeamGraser_Shooting + Fleck_BeamBurn + 0.32 + Mote_Wula_Dark_Matter_Beam + GraserBeam_End + + 0.35 + + + 0.6 + 0.6 + 0.25 + + + true + + +
  • (0, 0)
  • +
  • (0.65, 0.4)
  • +
  • (1, 0.75)
  • + + + + + + true + + + + false + + +
    + +
    + +
    \ No newline at end of file diff --git a/Source/WulaFallenEmpire/3516260226.code-workspace b/Source/WulaFallenEmpire/3516260226.code-workspace index 3a0a3ee4..b9f86d60 100644 --- a/Source/WulaFallenEmpire/3516260226.code-workspace +++ b/Source/WulaFallenEmpire/3516260226.code-workspace @@ -10,6 +10,9 @@ }, { "path": "../../../../../../workshop/content/294100/3534748687" + }, + { + "path": "../../../../../../workshop/content/294100/3550544871" } ], "settings": {} diff --git a/Source/WulaFallenEmpire/MechWeapon/CompMechWeapon.cs b/Source/WulaFallenEmpire/MechWeapon/CompMechWeapon.cs new file mode 100644 index 00000000..84b6ff7b --- /dev/null +++ b/Source/WulaFallenEmpire/MechWeapon/CompMechWeapon.cs @@ -0,0 +1,19 @@ +using Verse; + +namespace WulaFallenEmpire +{ + public class CompMechWeapon : ThingComp +{ + // You can add custom logic or fields here if needed for this component. + // For now, it primarily serves as a marker for mechanical units that can use MechWeapon features. +} + + +public class CompProperties_MechWeapon : CompProperties +{ + public CompProperties_MechWeapon() + { + compClass = typeof(CompMechWeapon); + } +} +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/MechWeapon/FloatMenuProvider_Mech.cs b/Source/WulaFallenEmpire/MechWeapon/FloatMenuProvider_Mech.cs new file mode 100644 index 00000000..1effef00 --- /dev/null +++ b/Source/WulaFallenEmpire/MechWeapon/FloatMenuProvider_Mech.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using RimWorld; +using Verse; +using Verse.AI; + +namespace WulaFallenEmpire +{ + public class FloatMenuProvider_Mech : FloatMenuOptionProvider +{ + protected override bool Drafted => true; + + protected override bool Undrafted => true; + + protected override bool Multiselect => false; + + protected override bool MechanoidCanDo => true; + + public override bool SelectedPawnValid(Pawn pawn, FloatMenuContext context) + { + return base.SelectedPawnValid(pawn, context) && pawn.HasComp(); + } + + public override IEnumerable GetOptionsFor(Thing clickedThing, FloatMenuContext context) + { + Pawn pawn = context.FirstSelectedPawn; + if (clickedThing.def.IsWeapon && pawn.CanReserveAndReach(clickedThing, PathEndMode.Touch, Danger.Deadly)) + { + yield return new FloatMenuOption("Equip".Translate(clickedThing.Label), delegate + { + pawn.jobs.StartJob(JobMaker.MakeJob(JobDefOf.Equip, clickedThing)); + }); + } + } +} +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/MechWeapon/Patch_MissingWeapon.cs b/Source/WulaFallenEmpire/MechWeapon/Patch_MissingWeapon.cs new file mode 100644 index 00000000..b8a4b838 --- /dev/null +++ b/Source/WulaFallenEmpire/MechWeapon/Patch_MissingWeapon.cs @@ -0,0 +1,19 @@ +using HarmonyLib; +using RimWorld; +using Verse; + +namespace WulaFallenEmpire +{ + [HarmonyPatch(typeof(MechRepairUtility), "IsMissingWeapon")] +public class Patch_MissingWeapon +{ + [HarmonyPostfix] + private static void PostFix(ref bool __result, Pawn mech) + { + if (mech.HasComp()) + { + __result = false; + } + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/MechWeapon/Patch_WeaponDrop.cs b/Source/WulaFallenEmpire/MechWeapon/Patch_WeaponDrop.cs new file mode 100644 index 00000000..43253945 --- /dev/null +++ b/Source/WulaFallenEmpire/MechWeapon/Patch_WeaponDrop.cs @@ -0,0 +1,53 @@ +using HarmonyLib; +using RimWorld; +using Verse; + +namespace WulaFallenEmpire +{ + [HarmonyPatch(typeof(Pawn), "DropAndForbidEverything")] +public class Patch_WeaponDrop +{ + [HarmonyPrefix] + private static bool PreFix(ref Pawn __instance, bool keepInventoryAndEquipmentIfInBed, bool rememberPrimary) + { + if (__instance.HasComp()) + { + if (!__instance.InContainerEnclosed) + { + if (__instance.SpawnedOrAnyParentSpawned) + { + if (__instance.carryTracker?.CarriedThing != null) + { + __instance.carryTracker.TryDropCarriedThing(__instance.PositionHeld, ThingPlaceMode.Near, out var _); + } + if (!keepInventoryAndEquipmentIfInBed || !__instance.InBed()) + { + __instance.equipment?.DropAllEquipment(__instance.PositionHeld, forbid: true, rememberPrimary); + if (__instance.inventory != null && __instance.inventory.innerContainer.TotalStackCount > 0) + { + __instance.inventory.DropAllNearPawn(__instance.PositionHeld, forbid: true); + } + } + } + return false; + } + if (__instance.carryTracker?.CarriedThing != null) + { + __instance.carryTracker.innerContainer.TryTransferToContainer(__instance.carryTracker.CarriedThing, __instance.holdingOwner); + } + if (__instance.equipment?.Primary != null) + { + __instance.equipment.TryTransferEquipmentToContainer(__instance.equipment.Primary, __instance.holdingOwner); + } + Pawn_InventoryTracker inventory = __instance.inventory; + if (inventory == null) + { + return false; + } + inventory.innerContainer.TryTransferAllToContainer(__instance.holdingOwner); + return false; + } + return true; + } +} +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Verb/VerbProperties_WeaponStealBeam.cs b/Source/WulaFallenEmpire/Verb/VerbProperties_WeaponStealBeam.cs new file mode 100644 index 00000000..a7899348 --- /dev/null +++ b/Source/WulaFallenEmpire/Verb/VerbProperties_WeaponStealBeam.cs @@ -0,0 +1,18 @@ +using RimWorld; +using Verse; + +namespace WulaFallenEmpire +{ + public class VerbProperties_WeaponStealBeam : VerbPropertiesExplosiveBeam + { + public HediffDef hediffToApply; + public float hediffSeverityPerHit = 0.1f; // 每次命中增加的严重性百分比 + public float hediffMaxSeverity = 1.0f; // 达到此严重性时触发抢夺 + public bool removeHediffOnSteal = true; // 抢夺后是否移除hediff + + public VerbProperties_WeaponStealBeam() + { + verbClass = typeof(Verb_ShootWeaponStealBeam); + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Verb/Verb_ShootWeaponStealBeam.cs b/Source/WulaFallenEmpire/Verb/Verb_ShootWeaponStealBeam.cs new file mode 100644 index 00000000..98ab521f --- /dev/null +++ b/Source/WulaFallenEmpire/Verb/Verb_ShootWeaponStealBeam.cs @@ -0,0 +1,167 @@ +using RimWorld; +using Verse; +using System.Linq; +using System.Collections.Generic; +using UnityEngine; // For Vector3 +using Verse.Sound; // For SoundDef.PlayOneShot +using Verse.AI; // For JobQueue + +namespace WulaFallenEmpire +{ + public class Verb_ShootWeaponStealBeam : Verse.Verb_ShootBeam + { + private int explosionShotCounter = 0; + + protected VerbProperties_WeaponStealBeam StealBeamVerbProps => (VerbProperties_WeaponStealBeam)verbProps; + + protected override bool TryCastShot() + { + bool result = base.TryCastShot(); + + // 如果光束命中,对目标Pawn施加Hediff并检查是否抢夺武器 + if (result && currentTarget.Thing is Pawn targetPawn && targetPawn.RaceProps.Humanlike) // 只对人形Pawn生效 + { + ApplyHediffAndCheckForSteal(targetPawn); + } + + if (result && verbProps is VerbPropertiesExplosiveBeam explosiveProps && explosiveProps.enableExplosion) + { + explosionShotCounter++; + + if (explosionShotCounter >= explosiveProps.explosionShotInterval) + { + explosionShotCounter = 0; + TriggerExplosion(explosiveProps); + } + } + + return result; + } + + private void TriggerExplosion(VerbPropertiesExplosiveBeam explosiveProps) + { + Vector3 explosionPos = InterpolatedPosition; + IntVec3 explosionCell = explosionPos.ToIntVec3(); + + if (!explosionCell.InBounds(caster.Map)) + return; + + // 播放爆炸音效 + if (explosiveProps.explosionSound != null) + { + explosiveProps.explosionSound.PlayOneShot(new TargetInfo(explosionCell, caster.Map)); + } + + // 生成爆炸 + GenExplosion.DoExplosion( + center: explosionCell, + map: caster.Map, + radius: explosiveProps.explosionRadius, + damType: explosiveProps.explosionDamageDef ?? DamageDefOf.Bomb, + instigator: caster, + damAmount: explosiveProps.explosionDamage > 0 ? explosiveProps.explosionDamage : verbProps.defaultProjectile?.projectile?.GetDamageAmount(EquipmentSource) ?? 20, + armorPenetration: explosiveProps.explosionArmorPenetration >= 0 ? explosiveProps.explosionArmorPenetration : verbProps.defaultProjectile?.projectile?.GetArmorPenetration(EquipmentSource) ?? 0.3f, + explosionSound: null, // 我们已经手动播放了音效 + weapon: base.EquipmentSource?.def, + projectile: null, + intendedTarget: currentTarget.Thing, + postExplosionSpawnThingDef: explosiveProps.postExplosionSpawnThingDef, + postExplosionSpawnChance: explosiveProps.postExplosionSpawnChance, + postExplosionSpawnThingCount: explosiveProps.postExplosionSpawnThingCount, + postExplosionGasType: explosiveProps.postExplosionGasType, + applyDamageToExplosionCellsNeighbors: explosiveProps.applyDamageToExplosionCellsNeighbors, + preExplosionSpawnThingDef: explosiveProps.preExplosionSpawnThingDef, + preExplosionSpawnChance: explosiveProps.preExplosionSpawnChance, + preExplosionSpawnThingCount: explosiveProps.preExplosionSpawnThingCount, + chanceToStartFire: explosiveProps.chanceToStartFire, + damageFalloff: explosiveProps.damageFalloff, + direction: null, + ignoredThings: null, + affectedAngle: null, + doVisualEffects: true, + propagationSpeed: 0.6f, + excludeRadius: 0f, + doSoundEffects: false, // 我们手动处理音效 + screenShakeFactor: explosiveProps.screenShakeFactor // 新增:屏幕震动因子 + ); + + // 在这里添加武器抢夺和Hediff施加的逻辑(爆炸命中目标时) + if (currentTarget.Thing is Pawn targetPawn && targetPawn.RaceProps.Humanlike) // 只对人形Pawn生效 + { + ApplyHediffAndCheckForSteal(targetPawn); + } + + // 生成额外的视觉效果 + if (explosiveProps.explosionEffecter != null) + { + Effecter effecter = explosiveProps.explosionEffecter.Spawn(explosionCell, caster.Map); + effecter.Trigger(new TargetInfo(explosionCell, caster.Map), TargetInfo.Invalid); + effecter.Cleanup(); + } + } + + private void ApplyHediffAndCheckForSteal(Pawn targetPawn) + { + if (StealBeamVerbProps.hediffToApply == null) + { + return; + } + + Hediff hediff = targetPawn.health.hediffSet.GetFirstHediffOfDef(StealBeamVerbProps.hediffToApply); + + if (hediff == null) + { + hediff = HediffMaker.MakeHediff(StealBeamVerbProps.hediffToApply, targetPawn); + targetPawn.health.AddHediff(hediff); + } + + hediff.Severity += StealBeamVerbProps.hediffSeverityPerHit; + + if (hediff.Severity >= StealBeamVerbProps.hediffMaxSeverity) + { + TryStealWeapon(targetPawn); + if (StealBeamVerbProps.removeHediffOnSteal) + { + targetPawn.health.RemoveHediff(hediff); + } + } + } + + private void TryStealWeapon(Pawn targetPawn) + { + if (!CasterIsPawn || CasterPawn == null) + { + return; + } + + // 获取目标Pawn的装备武器 + ThingWithComps targetWeapon = targetPawn.equipment?.Primary; + + if (targetWeapon != null) + { + // 将武器从目标Pawn身上移除 + targetPawn.equipment.Remove(targetWeapon); + + // 将武器添加到发射者(宿主)的库存中 + if (!CasterPawn.inventory.innerContainer.TryAdd(targetWeapon)) + { + // 如果无法添加到库存,则尝试丢弃在地上 + GenPlace.TryPlaceThing(targetWeapon, CasterPawn.Position, CasterPawn.Map, ThingPlaceMode.Near); + return; // 如果丢弃了,就不尝试装备了 + } + + // 让发射者装备该武器 + if (CasterPawn.equipment.Primary == null || CasterPawn.equipment.Primary.def != targetWeapon.def) + { + CasterPawn.jobs.StartJob(JobMaker.MakeJob(JobDefOf.Equip, targetWeapon), JobCondition.InterruptForced); + } + } + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref explosionShotCounter, "explosionShotCounter", 0); + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index bacd2e67..594ee04f 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -12,7 +12,7 @@ v4.8 512 true - 8.0 + 11.0 false @@ -170,6 +170,12 @@ + + + + + +