暂存
This commit is contained in:
Binary file not shown.
@@ -69,7 +69,7 @@
|
||||
</graphicData>
|
||||
<thingClass>WulaFallenEmpire.Projectile_TrackingBullet</thingClass>
|
||||
<projectile>
|
||||
<speed>30</speed>
|
||||
<speed>60</speed>
|
||||
<damageDef>Bullet</damageDef>
|
||||
<damageAmountBase>15</damageAmountBase>
|
||||
<armorPenetrationBase>0.5</armorPenetrationBase>
|
||||
@@ -78,7 +78,12 @@
|
||||
<modExtensions>
|
||||
<li Class="WulaFallenEmpire.TrackingBulletDef">
|
||||
<homingSpeed>0.5</homingSpeed>
|
||||
<initRotateAngle>10</initRotateAngle>
|
||||
<initRotateAngle>30</initRotateAngle>
|
||||
<destroyTicksAfterLosingTrack>
|
||||
<min>60</min>
|
||||
<max>120</max>
|
||||
</destroyTicksAfterLosingTrack>
|
||||
<tailFleckDef>WULA_GunTail_Blue</tailFleckDef>
|
||||
</li>
|
||||
</modExtensions>
|
||||
</ThingDef>
|
||||
|
||||
@@ -89,7 +89,17 @@
|
||||
<li Class="WulaFallenEmpire.TrackingBulletDef">
|
||||
<homingSpeed>0.5</homingSpeed>
|
||||
<initRotateAngle>5</initRotateAngle>
|
||||
<!-- 爆炸相关配置,可以直接在projectile节点下定义,Projectile_TrackingBullet 不直接处理爆炸逻辑 -->
|
||||
<destroyTicksAfterLosingTrack>
|
||||
<min>60</min>
|
||||
<max>120</max>
|
||||
</destroyTicksAfterLosingTrack>
|
||||
<tailFleckDef>Mote_BlastFlame</tailFleckDef>
|
||||
<fleckMakeFleckTickMax>3</fleckMakeFleckTickMax>
|
||||
<fleckMakeFleckNum>1</fleckMakeFleckNum>
|
||||
<fleckAngle>30</fleckAngle>
|
||||
<fleckScale>0.8~1.2</fleckScale>
|
||||
<fleckSpeed>0.2~0.5</fleckSpeed>
|
||||
<fleckRotation>0~360</fleckRotation>
|
||||
</li>
|
||||
</modExtensions>
|
||||
</ThingDef>
|
||||
|
||||
24
Source/WulaFallenEmpire/ExplosiveTrackingBulletDef.cs
Normal file
24
Source/WulaFallenEmpire/ExplosiveTrackingBulletDef.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Verse;
|
||||
using RimWorld;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class ExplosiveTrackingBulletDef : DefModExtension
|
||||
{
|
||||
public float explosionRadius = 1.9f;
|
||||
public DamageDef damageDef;
|
||||
public int explosionDelay = 0;
|
||||
public SoundDef soundExplode;
|
||||
public FleckDef preExplosionFlash;
|
||||
public ThingDef postExplosionSpawnThingDef;
|
||||
public float postExplosionSpawnChance = 0f;
|
||||
public int postExplosionSpawnThingCount = 1;
|
||||
public GasType? gasType; // 修改为可空类型
|
||||
public bool applyDamageToExplosionCellsNeighbors = false;
|
||||
public bool doExplosionDamageAfterThingDestroyed = false;
|
||||
public float preExplosionSpawnMinMeleeThreat = -1f;
|
||||
public float explosionChanceToStartFire = 0f; // 从bool改为float,并设置默认值
|
||||
public bool explosionDamageFalloff = false;
|
||||
public bool doExplosionVFX = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.Sound;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class Projectile_ExplosiveTrackingBullet : Projectile_TrackingBullet
|
||||
{
|
||||
private ExplosiveTrackingBulletDef explosiveDefInt;
|
||||
|
||||
public ExplosiveTrackingBulletDef ExplosiveDef
|
||||
{
|
||||
get
|
||||
{
|
||||
if (explosiveDefInt == null)
|
||||
{
|
||||
explosiveDefInt = def.GetModExtension<ExplosiveTrackingBulletDef>();
|
||||
if (explosiveDefInt == null)
|
||||
{
|
||||
Log.ErrorOnce($"ExplosiveTrackingBulletDef for {this.def.defName} is null. Creating a default instance.", this.thingIDNumber ^ 0x12345679);
|
||||
this.explosiveDefInt = new ExplosiveTrackingBulletDef();
|
||||
}
|
||||
}
|
||||
return explosiveDefInt;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Impact(Thing hitThing, bool blockedByShield = false)
|
||||
{
|
||||
base.Impact(hitThing, blockedByShield); // 调用基类的Impact逻辑
|
||||
|
||||
if (ExplosiveDef.explosionRadius > 0f)
|
||||
{
|
||||
// 爆炸逻辑
|
||||
GenExplosion.DoExplosion(
|
||||
center: Position, // 爆炸中心
|
||||
map: Map, // 地图
|
||||
radius: ExplosiveDef.explosionRadius, // 爆炸半径
|
||||
damType: ExplosiveDef.damageDef ?? DamageDefOf.Bomb, // 伤害类型,如果未配置则默认为Bomb
|
||||
instigator: launcher, // 制造者
|
||||
damAmount: this.DamageAmount, // 伤害量,使用子弹当前的伤害量
|
||||
armorPenetration: this.ArmorPenetration, // 护甲穿透,使用子弹当前的护甲穿透
|
||||
explosionSound: ExplosiveDef.soundExplode, // 爆炸音效
|
||||
weapon: equipmentDef, // 武器
|
||||
projectile: def, // 弹药定义
|
||||
intendedTarget: intendedTarget.Thing, // 预期目标
|
||||
postExplosionSpawnThingDef: ExplosiveDef.postExplosionSpawnThingDef, // 爆炸后生成物
|
||||
postExplosionSpawnChance: ExplosiveDef.postExplosionSpawnChance, // 爆炸后生成几率
|
||||
postExplosionSpawnThingCount: ExplosiveDef.postExplosionSpawnThingCount, // 爆炸后生成数量
|
||||
postExplosionGasType: ExplosiveDef.gasType, // 气体类型 (注意参数名已修正)
|
||||
postExplosionGasRadiusOverride: null, // 爆炸气体半径覆盖 (我没有定义这个参数)
|
||||
postExplosionGasAmount: 255, // 爆炸气体数量 (默认值)
|
||||
applyDamageToExplosionCellsNeighbors: ExplosiveDef.applyDamageToExplosionCellsNeighbors, // 是否对爆炸单元格邻居造成伤害
|
||||
preExplosionSpawnThingDef: null, // 爆炸前生成物 (我没有定义这个参数)
|
||||
preExplosionSpawnChance: 0f, // 爆炸前生成几率 (默认值)
|
||||
preExplosionSpawnThingCount: 0, // 爆炸前生成数量 (默认值)
|
||||
chanceToStartFire: ExplosiveDef.explosionChanceToStartFire, // 是否有几率点燃 (注意参数名已修正)
|
||||
damageFalloff: ExplosiveDef.explosionDamageFalloff, // 爆炸伤害衰减
|
||||
direction: null, // 方向 (我没有定义这个参数)
|
||||
ignoredThings: null, // 忽略的物体 (我没有定义这个参数)
|
||||
affectedAngle: null, // 受影响角度 (我没有定义这个参数)
|
||||
doVisualEffects: ExplosiveDef.doExplosionVFX, // 是否显示视觉效果
|
||||
propagationSpeed: 1f, // 传播速度 (默认值)
|
||||
excludeRadius: 0f, // 排除半径 (默认值)
|
||||
doSoundEffects: true, // 是否播放音效 (默认值)
|
||||
postExplosionSpawnThingDefWater: null, // 爆炸后在水中生成物 (我没有定义这个参数)
|
||||
screenShakeFactor: 1f, // 屏幕震动因子 (默认值)
|
||||
flammabilityChanceCurve: null, // 易燃性几率曲线 (我没有定义这个参数)
|
||||
overrideCells: null, // 覆盖单元格 (我没有定义这个参数)
|
||||
postExplosionSpawnSingleThingDef: null, // 爆炸后生成单个物体 (我没有定义这个参数)
|
||||
preExplosionSpawnSingleThingDef: null // 爆炸前生成单个物体 (我没有定义这个参数)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@ namespace WulaFallenEmpire
|
||||
protected Vector3 exactPositionInt;
|
||||
public Vector3 curSpeed;
|
||||
public bool homing = true;
|
||||
private int destroyTicksAfterLosingTrack = -1; // 失去追踪后多少tick自毁,-1表示不自毁
|
||||
private int Fleck_MakeFleckTick; // 拖尾特效的计时器
|
||||
private Vector3 lastTickPosition; // 记录上一帧的位置,用于计算移动方向
|
||||
|
||||
private static class NonPublicFields
|
||||
{
|
||||
@@ -58,6 +61,7 @@ namespace WulaFallenEmpire
|
||||
curSpeed = rotatedDirection * def.projectile.SpeedTilesPerTick;
|
||||
|
||||
ReflectInit();
|
||||
lastTickPosition = origin; // 初始化 lastTickPosition
|
||||
}
|
||||
|
||||
protected void ReflectInit()
|
||||
@@ -80,67 +84,41 @@ namespace WulaFallenEmpire
|
||||
|
||||
if (homing)
|
||||
{
|
||||
// 计算需要转向的方向
|
||||
Vector3 desiredDirection = vectorToTarget.normalized;
|
||||
Vector3 currentDirection = curSpeed.normalized;
|
||||
|
||||
// 计算方向差异
|
||||
Vector3 directionDifference = desiredDirection - currentDirection;
|
||||
|
||||
// 如果方向差异过大,可能失去追踪,或者直接转向
|
||||
if (directionDifference.sqrMagnitude > 0.001f) // 避免浮点数精度问题
|
||||
// 如果目标消失或距离太远,停止追踪
|
||||
if (!intendedTarget.IsValid || !intendedTarget.Thing.Spawned || (intendedTarget.Cell.ToVector3() - ExactPosition).magnitude > def.projectile.speed * 2f) // 假设2倍速度为最大追踪距离
|
||||
{
|
||||
// 调整当前速度,使其更接近目标方向
|
||||
curSpeed += directionDifference * TrackingDef.homingSpeed * curSpeed.magnitude;
|
||||
curSpeed = curSpeed.normalized * def.projectile.SpeedTilesPerTick; // 保持速度恒定
|
||||
homing = false;
|
||||
destroyTicksAfterLosingTrack = TrackingDef.destroyTicksAfterLosingTrack.RandomInRange; // 失去追踪后根据XML配置的范围自毁
|
||||
}
|
||||
else
|
||||
{
|
||||
// 计算需要转向的方向
|
||||
Vector3 desiredDirection = vectorToTarget.normalized;
|
||||
Vector3 currentDirection = curSpeed.normalized;
|
||||
|
||||
// 计算方向差异
|
||||
Vector3 directionDifference = desiredDirection - currentDirection;
|
||||
|
||||
// 如果方向差异过大,可能失去追踪,或者直接转向
|
||||
if (directionDifference.sqrMagnitude > 0.001f) // 避免浮点数精度问题
|
||||
{
|
||||
// 调整当前速度,使其更接近目标方向
|
||||
curSpeed += directionDifference * TrackingDef.homingSpeed * curSpeed.magnitude;
|
||||
curSpeed = curSpeed.normalized * def.projectile.SpeedTilesPerTick; // 保持速度恒定
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exactPositionInt = ExactPosition + curSpeed; // 更新位置
|
||||
}
|
||||
|
||||
protected override void Tick()
|
||||
{
|
||||
base.Tick(); // 调用父类Bullet的Tick,处理一些基本逻辑,如lifetime, ticksToImpact
|
||||
|
||||
MovementTick(); // 调用追踪移动逻辑
|
||||
|
||||
// 检查是否撞到东西或超出地图
|
||||
Vector3 exactPosition = ExactPosition; // 之前的ExactPosition
|
||||
ticksToImpact--; // 减少impact计时器
|
||||
|
||||
if (!ExactPosition.InBounds(base.Map)) // 超出地图边界
|
||||
{
|
||||
base.Position = exactPosition.ToIntVec3(); // 设回旧位置,然后销毁
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否有东西在路径上拦截
|
||||
Vector3 exactPositionAfterMove = ExactPosition; // 移动后的ExactPosition
|
||||
object[] parameters = new object[2] { exactPosition, exactPositionAfterMove };
|
||||
if (!(bool)NonPublicFields.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters))
|
||||
{
|
||||
base.Position = ExactPosition.ToIntVec3(); // 更新位置到当前精确位置
|
||||
if (ticksToImpact <= 0) // 达到impact时间
|
||||
{
|
||||
ImpactSomething(); // 触发Impact
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Impact(Thing hitThing, bool blockedByShield = false)
|
||||
{
|
||||
// 默认Impact逻辑,可以根据需要扩展
|
||||
base.Impact(hitThing, blockedByShield);
|
||||
}
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look(ref exactPositionInt, "exactPosition");
|
||||
Scribe_Values.Look(ref curSpeed, "curSpeed");
|
||||
Scribe_Values.Look(ref homing, "homing", defaultValue: true);
|
||||
Scribe_Values.Look(ref destroyTicksAfterLosingTrack, "destroyTicksAfterLosingTrack", -1);
|
||||
if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
||||
{
|
||||
ReflectInit();
|
||||
@@ -155,5 +133,84 @@ namespace WulaFallenEmpire
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Tick()
|
||||
{
|
||||
base.Tick(); // 调用父类Bullet的Tick,处理 ticksToImpact 减少和最终命中
|
||||
|
||||
if (destroyTicksAfterLosingTrack > 0)
|
||||
{
|
||||
destroyTicksAfterLosingTrack--;
|
||||
if (destroyTicksAfterLosingTrack <= 0)
|
||||
{
|
||||
Destroy(); // 如果自毁计时器归零,直接销毁
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理拖尾特效
|
||||
if (TrackingDef != null && TrackingDef.tailFleckDef != null)
|
||||
{
|
||||
Fleck_MakeFleckTick++;
|
||||
// 只有当达到延迟时间后才开始生成Fleck
|
||||
if (Fleck_MakeFleckTick >= TrackingDef.fleckDelayTicks)
|
||||
{
|
||||
if (Fleck_MakeFleckTick >= (TrackingDef.fleckDelayTicks + TrackingDef.fleckMakeFleckTickMax))
|
||||
{
|
||||
Fleck_MakeFleckTick = TrackingDef.fleckDelayTicks; // 重置计时器,从延迟时间开始循环
|
||||
}
|
||||
|
||||
Map map = base.Map;
|
||||
int randomInRange = TrackingDef.fleckMakeFleckNum.RandomInRange;
|
||||
Vector3 currentPosition = ExactPosition;
|
||||
Vector3 previousPosition = lastTickPosition;
|
||||
|
||||
for (int i = 0; i < randomInRange; i++)
|
||||
{
|
||||
float num = (currentPosition - previousPosition).AngleFlat();
|
||||
float velocityAngle = TrackingDef.fleckAngle.RandomInRange + num;
|
||||
float randomInRange2 = TrackingDef.fleckScale.RandomInRange;
|
||||
float randomInRange3 = TrackingDef.fleckSpeed.RandomInRange;
|
||||
|
||||
FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, TrackingDef.tailFleckDef, randomInRange2);
|
||||
dataStatic.rotation = (currentPosition - previousPosition).AngleFlat();
|
||||
dataStatic.rotationRate = TrackingDef.fleckRotation.RandomInRange;
|
||||
dataStatic.velocityAngle = velocityAngle;
|
||||
dataStatic.velocitySpeed = randomInRange3;
|
||||
map.flecks.CreateFleck(dataStatic);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastTickPosition = ExactPosition; // 更新上一帧位置
|
||||
|
||||
// 保存移动前的精确位置
|
||||
Vector3 exactPositionBeforeMove = exactPositionInt;
|
||||
|
||||
MovementTick(); // 调用追踪移动逻辑,更新 exactPositionInt (即新的 ExactPosition)
|
||||
|
||||
// 检查是否超出地图边界
|
||||
if (!ExactPosition.InBounds(base.Map))
|
||||
{
|
||||
// 如果超出地图,直接销毁,不触发 ImpactSomething()
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否有东西在路径上拦截
|
||||
// ProjectileCheckForFreeInterceptBetween 会在内部处理命中,并调用 ImpactSomething()
|
||||
// 所以这里不需要额外的 ImpactSomething() 调用
|
||||
object[] parameters = new object[2] { exactPositionBeforeMove, exactPositionInt }; // 传入移动前和移动后的位置
|
||||
|
||||
// 调用 ProjectileCheckForFreeInterceptBetween
|
||||
// 如果它返回 true,说明有拦截,并且拦截逻辑已在内部处理。
|
||||
// 如果返回 false,说明没有拦截,子弹继续飞行。
|
||||
NonPublicFields.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters);
|
||||
}
|
||||
|
||||
protected override void Impact(Thing hitThing, bool blockedByShield = false)
|
||||
{
|
||||
// 默认Impact逻辑,可以根据需要扩展
|
||||
base.Impact(hitThing, blockedByShield);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ namespace WulaFallenEmpire
|
||||
// If true, this projectile will never cause friendly fire, regardless of game settings.
|
||||
public bool preventFriendlyFire = false;
|
||||
public FleckDef tailFleckDef; // 用于配置拖尾特效的 FleckDef
|
||||
public int fleckDelayTicks = 10; // 拖尾特效延迟生成时间(tick)
|
||||
}
|
||||
|
||||
public class Projectile_WulaLineAttack : Bullet
|
||||
@@ -62,26 +63,31 @@ namespace WulaFallenEmpire
|
||||
if (this.Destroyed) return;
|
||||
|
||||
this.Fleck_MakeFleckTick++;
|
||||
bool flag = this.Fleck_MakeFleckTick >= this.Fleck_MakeFleckTickMax;
|
||||
if (flag)
|
||||
// 只有当达到延迟时间后才开始生成Fleck
|
||||
if (this.Fleck_MakeFleckTick >= Props.fleckDelayTicks)
|
||||
{
|
||||
this.Fleck_MakeFleckTick = 0;
|
||||
if (this.Fleck_MakeFleckTick >= (Props.fleckDelayTicks + this.Fleck_MakeFleckTickMax))
|
||||
{
|
||||
this.Fleck_MakeFleckTick = Props.fleckDelayTicks; // 重置计时器,从延迟时间开始循环
|
||||
}
|
||||
|
||||
Map map = base.Map;
|
||||
int randomInRange = this.Fleck_MakeFleckNum.RandomInRange;
|
||||
Vector3 vector = this.ExactPosition; // Current position of the bullet
|
||||
Vector3 vector2 = this.lastTickPosition; // Previous position of the bullet
|
||||
Vector3 currentPosition = this.ExactPosition; // Current position of the bullet
|
||||
Vector3 previousPosition = this.lastTickPosition; // Previous position of the bullet
|
||||
|
||||
for (int i = 0; i < randomInRange; i++)
|
||||
{
|
||||
float num = (vector - vector2).AngleFlat(); // Angle based on movement direction
|
||||
float velocityAngle = this.Fleck_Angle.RandomInRange + num;
|
||||
float currentBulletAngle = ExactRotation.eulerAngles.y; // 使用子弹当前的水平旋转角度
|
||||
float fleckRotationAngle = currentBulletAngle; // Fleck 的旋转角度与子弹方向一致
|
||||
float velocityAngle = this.Fleck_Angle.RandomInRange + currentBulletAngle; // Fleck 的速度角度基于子弹方向加上随机偏移
|
||||
float randomInRange2 = this.Fleck_Scale.RandomInRange;
|
||||
float randomInRange3 = this.Fleck_Speed.RandomInRange;
|
||||
|
||||
if (Props?.tailFleckDef != null)
|
||||
{
|
||||
FleckCreationData dataStatic = FleckMaker.GetDataStatic(vector, map, Props.tailFleckDef, randomInRange2);
|
||||
dataStatic.rotation = (vector - vector2).AngleFlat();
|
||||
FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, Props.tailFleckDef, randomInRange2);
|
||||
dataStatic.rotation = fleckRotationAngle;
|
||||
dataStatic.rotationRate = this.Fleck_Rotation.RandomInRange;
|
||||
dataStatic.velocityAngle = velocityAngle;
|
||||
dataStatic.velocitySpeed = randomInRange3;
|
||||
|
||||
@@ -6,5 +6,15 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
public float homingSpeed = 0.1f; // 追踪速度,值越大追踪越灵敏
|
||||
public float initRotateAngle = 0f; // 初始旋转角度
|
||||
|
||||
public FleckDef tailFleckDef; // 拖尾特效的FleckDef
|
||||
public int fleckMakeFleckTickMax = 1; // 拖尾特效的生成间隔(tick)
|
||||
public int fleckDelayTicks = 10; // 拖尾特效延迟生成时间(tick)
|
||||
public IntRange fleckMakeFleckNum = new IntRange(1, 1); // 每次生成拖尾特效的数量
|
||||
public FloatRange fleckAngle = new FloatRange(-180f, 180f); // 拖尾特效的初始角度范围
|
||||
public FloatRange fleckScale = new FloatRange(1f, 1f); // 拖尾特效的缩放范围
|
||||
public FloatRange fleckSpeed = new FloatRange(0f, 0f); // 拖尾特效的初始速度范围
|
||||
public FloatRange fleckRotation = new FloatRange(-180f, 180f); // 拖尾特效的旋转速度范围
|
||||
public IntRange destroyTicksAfterLosingTrack = new IntRange(60, 120); // 失去追踪后多少tick自毁
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,8 @@
|
||||
<Compile Include="Projectile_Homing_Explosive.cs" />
|
||||
<Compile Include="Projectile_TrackingBullet.cs" />
|
||||
<Compile Include="TrackingBulletDef.cs" />
|
||||
<Compile Include="ExplosiveTrackingBulletDef.cs" />
|
||||
<Compile Include="Projectile_ExplosiveTrackingBullet.cs" />
|
||||
<Compile Include="ModExtension_Cone.cs" />
|
||||
<Compile Include="HomingProjectileDef.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
||||
Reference in New Issue
Block a user