三叉戟
This commit is contained in:
Binary file not shown.
@@ -62,11 +62,10 @@
|
|||||||
<isBad>false</isBad>
|
<isBad>false</isBad>
|
||||||
<comps>
|
<comps>
|
||||||
<li Class="WulaFallenEmpire.HediffCompProperties_WulaCharging">
|
<li Class="WulaFallenEmpire.HediffCompProperties_WulaCharging">
|
||||||
<!-- 充能效果的总持续时间(以 tick 为单位,60 ticks = 1 秒) -->
|
|
||||||
<!-- 充能效果的总持续时间(以 tick 为单位,60 ticks = 1 秒) -->
|
<!-- 充能效果的总持续时间(以 tick 为单位,60 ticks = 1 秒) -->
|
||||||
<durationTicks>20,000</durationTicks>
|
<durationTicks>20,000</durationTicks>
|
||||||
<!-- 备用能量恢复值:如果能量核心没有定义具体的能量值,则每 tick 恢复这么多能量 -->
|
<!-- 备用能量恢复值:如果能量核心没有定义具体的能量值,则每 tick 恢复这么多能量 -->
|
||||||
<energyPerTick>0.00011667</energyPerTick>
|
<energyPerTick>0.0002</energyPerTick>
|
||||||
</li>
|
</li>
|
||||||
</comps>
|
</comps>
|
||||||
<stages>
|
<stages>
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<Defs>
|
||||||
|
|
||||||
|
<!-- Penetrating Beam Rifle -->
|
||||||
|
<ThingDef ParentName="BaseHumanMakeableGun">
|
||||||
|
<defName>WULA_RW_Penetrating_Beam_Rifle</defName>
|
||||||
|
<label>SLb-15 "三叉戟"</label>
|
||||||
|
<description>一把经过实验性改造的“蓝锥”步枪,能够发射一道可以穿透多个目标的能量光束。</description>
|
||||||
|
<techLevel>Spacer</techLevel>
|
||||||
|
<graphicData>
|
||||||
|
<texPath>Wula/Weapon/WULA_RW_Fractal_RF</texPath>
|
||||||
|
<graphicClass>Graphic_Single</graphicClass>
|
||||||
|
</graphicData>
|
||||||
|
<soundInteract>Interact_Rifle</soundInteract>
|
||||||
|
<weaponClasses>
|
||||||
|
<li>LongShots</li>
|
||||||
|
<li>RangedHeavy</li>
|
||||||
|
</weaponClasses>
|
||||||
|
<statBases>
|
||||||
|
<WorkToMake>1300</WorkToMake>
|
||||||
|
<Mass>3.5</Mass>
|
||||||
|
<AccuracyTouch>0.65</AccuracyTouch>
|
||||||
|
<AccuracyShort>0.72</AccuracyShort>
|
||||||
|
<AccuracyMedium>0.65</AccuracyMedium>
|
||||||
|
<AccuracyLong>0.6</AccuracyLong>
|
||||||
|
<RangedWeapon_Cooldown>2.0</RangedWeapon_Cooldown>
|
||||||
|
</statBases>
|
||||||
|
<costList Inherit="False">
|
||||||
|
<Steel>120</Steel>
|
||||||
|
<ComponentIndustrial>6</ComponentIndustrial>
|
||||||
|
</costList>
|
||||||
|
<verbs>
|
||||||
|
<li>
|
||||||
|
<verbClass>WulaFallenEmpire.Verb_ShootShotgun</verbClass>
|
||||||
|
<hasStandardCommand>true</hasStandardCommand>
|
||||||
|
<defaultProjectile>Bullet_WULA_RW_Penetrating_Beam</defaultProjectile>
|
||||||
|
<warmupTime>3.0</warmupTime>
|
||||||
|
<range>28</range>
|
||||||
|
<burstShotCount>3</burstShotCount>
|
||||||
|
<ticksBetweenBurstShots>12</ticksBetweenBurstShots>
|
||||||
|
<soundCast>Shot_BeamRepeater</soundCast>
|
||||||
|
<soundCastTail>GunTail_Medium</soundCastTail>
|
||||||
|
<muzzleFlashScale>9</muzzleFlashScale>
|
||||||
|
<aimingChargeMote>Mote_BeamRepeater_Charge</aimingChargeMote>
|
||||||
|
<aimingChargeMoteOffset>1.07</aimingChargeMoteOffset>
|
||||||
|
</li>
|
||||||
|
</verbs>
|
||||||
|
<weaponTags>
|
||||||
|
<li>Wula_Weapon_Init</li>
|
||||||
|
</weaponTags>
|
||||||
|
<thingSetMakerTags><li>RewardStandardQualitySuper</li></thingSetMakerTags>
|
||||||
|
</ThingDef>
|
||||||
|
|
||||||
|
<ThingDef ParentName="BaseBullet">
|
||||||
|
<defName>Bullet_WULA_RW_Penetrating_Beam</defName>
|
||||||
|
<label>穿透光束</label>
|
||||||
|
<thingClass>WulaFallenEmpire.Projectile_WulaBeam</thingClass>
|
||||||
|
<modExtensions>
|
||||||
|
<li Class="WulaFallenEmpire.Wula_BeamPierce_Extension">
|
||||||
|
<maxHits>-1</maxHits> <!-- -1 for infinite hits -->
|
||||||
|
<damageFalloff>0</damageFalloff> <!-- 0 for no damage falloff -->
|
||||||
|
<preventFriendlyFire>false</preventFriendlyFire>
|
||||||
|
<beamMoteDef>Mote_WULA_RW_Penetrating_Beam</beamMoteDef>
|
||||||
|
<beamStartOffset>0.5</beamStartOffset>
|
||||||
|
</li>
|
||||||
|
<li Class="WulaFallenEmpire.ShotgunExtension">
|
||||||
|
<pelletCount>3</pelletCount>
|
||||||
|
</li>
|
||||||
|
</modExtensions>
|
||||||
|
<graphicData>
|
||||||
|
<texPath>Things/Projectile/ChargeLanceShot</texPath>
|
||||||
|
<graphicClass>Graphic_Single</graphicClass>
|
||||||
|
</graphicData>
|
||||||
|
<projectile>
|
||||||
|
<damageDef>BeamBypassShields</damageDef>
|
||||||
|
<damageAmountBase>5</damageAmountBase>
|
||||||
|
<armorPenetrationBase>0.8</armorPenetrationBase>
|
||||||
|
<stoppingPower>1</stoppingPower>
|
||||||
|
</projectile>
|
||||||
|
</ThingDef>
|
||||||
|
|
||||||
|
<ThingDef ParentName="MoteBase">
|
||||||
|
<defName>Mote_WULA_RW_Penetrating_Beam</defName>
|
||||||
|
<thingClass>MoteDualAttached</thingClass>
|
||||||
|
<altitudeLayer>MoteOverhead</altitudeLayer>
|
||||||
|
<mote>
|
||||||
|
<fadeInTime>0.1</fadeInTime>
|
||||||
|
<fadeOutTime>0.1</fadeOutTime>
|
||||||
|
<solidTime>0.1</solidTime>
|
||||||
|
<rotateTowardsTarget>True</rotateTowardsTarget>
|
||||||
|
<scaleToConnectTargets>True</scaleToConnectTargets>
|
||||||
|
</mote>
|
||||||
|
<drawOffscreen>true</drawOffscreen>
|
||||||
|
<graphicData>
|
||||||
|
<texPath>Things/Projectile/ChargeLanceShot</texPath>
|
||||||
|
<graphicClass>Graphic_MoteWithAgeSecs</graphicClass>
|
||||||
|
<shaderType>MoteBeam</shaderType>
|
||||||
|
<shaderParameters>
|
||||||
|
<_ScrollSpeedA>0</_ScrollSpeedA>
|
||||||
|
<_ScrollSpeedB>0</_ScrollSpeedB>
|
||||||
|
<_Intensity>2</_Intensity>
|
||||||
|
</shaderParameters>
|
||||||
|
</graphicData>
|
||||||
|
</ThingDef>
|
||||||
|
|
||||||
|
</Defs>
|
||||||
134
Source/WulaFallenEmpire/Projectile_WulaBeam.cs
Normal file
134
Source/WulaFallenEmpire/Projectile_WulaBeam.cs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using RimWorld;
|
||||||
|
using UnityEngine;
|
||||||
|
using Verse;
|
||||||
|
|
||||||
|
namespace WulaFallenEmpire
|
||||||
|
{
|
||||||
|
// A new, dedicated extension class for the penetrating beam.
|
||||||
|
public class Wula_BeamPierce_Extension : DefModExtension
|
||||||
|
{
|
||||||
|
public int maxHits = 3;
|
||||||
|
public float damageFalloff = 0.25f;
|
||||||
|
public bool preventFriendlyFire = false;
|
||||||
|
public ThingDef beamMoteDef;
|
||||||
|
public float beamWidth = 1f;
|
||||||
|
public float beamStartOffset = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Projectile_WulaBeam : Bullet
|
||||||
|
{
|
||||||
|
private int hitCounter = 0;
|
||||||
|
private List<Thing> alreadyDamaged = new List<Thing>();
|
||||||
|
|
||||||
|
// It now gets its properties from the new, dedicated extension.
|
||||||
|
private Wula_BeamPierce_Extension Props => def.GetModExtension<Wula_BeamPierce_Extension>();
|
||||||
|
|
||||||
|
public override Vector3 ExactPosition => destination + Vector3.up * def.Altitude;
|
||||||
|
|
||||||
|
public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
|
||||||
|
{
|
||||||
|
base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
|
||||||
|
|
||||||
|
Wula_BeamPierce_Extension props = Props;
|
||||||
|
if (props == null)
|
||||||
|
{
|
||||||
|
Log.Error("Projectile_WulaBeam requires a Wula_BeamPierce_Extension in its def.");
|
||||||
|
Destroy(DestroyMode.Vanish);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hitCounter = 0;
|
||||||
|
this.alreadyDamaged.Clear();
|
||||||
|
|
||||||
|
bool shouldPreventFriendlyFire = preventFriendlyFire || props.preventFriendlyFire;
|
||||||
|
|
||||||
|
Map map = this.Map;
|
||||||
|
// --- Corrected Start Position Calculation ---
|
||||||
|
// The beam should start from the gun's muzzle, not the pawn's center.
|
||||||
|
Vector3 endPosition = usedTarget.Cell.ToVector3Shifted();
|
||||||
|
Vector3 castPosition = origin + (endPosition - origin).Yto0().normalized * props.beamStartOffset;
|
||||||
|
|
||||||
|
// --- Vanilla Beam Drawing Logic ---
|
||||||
|
if (props.beamMoteDef != null)
|
||||||
|
{
|
||||||
|
// Calculate the offset exactly like the vanilla Beam class does.
|
||||||
|
// The offset for the mote is calculated from the launcher's true position, not the cast position.
|
||||||
|
Vector3 moteOffset = (endPosition - launcher.Position.ToVector3Shifted()).Yto0().normalized * props.beamStartOffset;
|
||||||
|
MoteMaker.MakeInteractionOverlay(props.beamMoteDef, launcher, usedTarget.ToTargetInfo(map), moteOffset, Vector3.zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
float distance = Vector3.Distance(castPosition, endPosition);
|
||||||
|
Vector3 direction = (endPosition - castPosition).normalized;
|
||||||
|
|
||||||
|
var thingsOnPath = new HashSet<Thing>();
|
||||||
|
for (float i = 0; i < distance; i += 1.0f)
|
||||||
|
{
|
||||||
|
IntVec3 cell = (castPosition + direction * i).ToIntVec3();
|
||||||
|
if (cell.InBounds(map))
|
||||||
|
{
|
||||||
|
thingsOnPath.AddRange(map.thingGrid.ThingsListAt(cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// CRITICAL FIX: Manually add the intended target to the list.
|
||||||
|
// This guarantees the primary target is always processed, even if the loop sampling misses its exact cell.
|
||||||
|
if (intendedTarget.HasThing)
|
||||||
|
{
|
||||||
|
thingsOnPath.Add(intendedTarget.Thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxHits = props.maxHits;
|
||||||
|
bool infinitePenetration = maxHits < 0;
|
||||||
|
|
||||||
|
foreach (Thing thing in thingsOnPath)
|
||||||
|
{
|
||||||
|
if (!infinitePenetration && hitCounter >= maxHits) break;
|
||||||
|
|
||||||
|
if (thing is Pawn pawn && pawn != launcher && !alreadyDamaged.Contains(pawn))
|
||||||
|
{
|
||||||
|
bool shouldDamage = false;
|
||||||
|
if (intendedTarget.Thing == pawn) shouldDamage = true;
|
||||||
|
else if (pawn.HostileTo(launcher)) shouldDamage = true;
|
||||||
|
else if (!shouldPreventFriendlyFire) shouldDamage = true;
|
||||||
|
|
||||||
|
if (shouldDamage)
|
||||||
|
{
|
||||||
|
ApplyPathDamage(pawn, props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (thing.def.Fillage == FillCategory.Full && thing.def.blockLight)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Destroy(DestroyMode.Vanish);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyPathDamage(Pawn pawn, Wula_BeamPierce_Extension props)
|
||||||
|
{
|
||||||
|
float damageMultiplier = Mathf.Pow(1f - props.damageFalloff, hitCounter);
|
||||||
|
int damageAmount = (int)(this.DamageAmount * damageMultiplier);
|
||||||
|
|
||||||
|
if (damageAmount <= 0) return;
|
||||||
|
|
||||||
|
var dinfo = new DamageInfo(
|
||||||
|
this.def.projectile.damageDef,
|
||||||
|
damageAmount,
|
||||||
|
this.ArmorPenetration * damageMultiplier,
|
||||||
|
this.ExactRotation.eulerAngles.y,
|
||||||
|
this.launcher,
|
||||||
|
null,
|
||||||
|
this.equipmentDef,
|
||||||
|
DamageInfo.SourceCategory.ThingOrUnknown,
|
||||||
|
this.intendedTarget.Thing);
|
||||||
|
|
||||||
|
pawn.TakeDamage(dinfo);
|
||||||
|
alreadyDamaged.Add(pawn);
|
||||||
|
hitCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Tick() { }
|
||||||
|
protected override void Impact(Thing hitThing, bool blockedByShield = false) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,6 +118,7 @@
|
|||||||
<Compile Include="Need_WulaEnergy.cs" />
|
<Compile Include="Need_WulaEnergy.cs" />
|
||||||
<Compile Include="NeedDefExtension_Energy.cs" />
|
<Compile Include="NeedDefExtension_Energy.cs" />
|
||||||
<Compile Include="Projectile_WulaPenetrating.cs" />
|
<Compile Include="Projectile_WulaPenetrating.cs" />
|
||||||
|
<Compile Include="Projectile_WulaBeam.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="PsychicRitual_TechOffering.cs" />
|
<Compile Include="PsychicRitual_TechOffering.cs" />
|
||||||
<Compile Include="PsychicRitualDef_AddHediff.cs" />
|
<Compile Include="PsychicRitualDef_AddHediff.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user