暂存
This commit is contained in:
Binary file not shown.
24
1.6/1.6/Defs/Effects/WulaFleckDefs.xml
Normal file
24
1.6/1.6/Defs/Effects/WulaFleckDefs.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Defs>
|
||||
<FleckDef ParentName="FleckBase">
|
||||
<defName>WULA_GunTail_Blue</defName>
|
||||
<altitudeLayer>Projectile</altitudeLayer>
|
||||
<fadeOutTime>0.5</fadeOutTime>
|
||||
<graphicData>
|
||||
<texPath>Things/Projectile/ChargeLanceShot</texPath>
|
||||
<shaderType>MoteGlow</shaderType>
|
||||
<drawSize>(0.45,2)</drawSize>
|
||||
</graphicData>
|
||||
</FleckDef>
|
||||
|
||||
<FleckDef ParentName="FleckBase">
|
||||
<defName>WULA_GunTail_Smoke</defName>
|
||||
<altitudeLayer>Projectile</altitudeLayer>
|
||||
<fadeOutTime>0.23</fadeOutTime>
|
||||
<graphicData>
|
||||
<texPath>Things/Others/Smoke_Dark</texPath>
|
||||
<shaderType>TransparentPostLight</shaderType>
|
||||
<drawSize>(0.06,0.25)</drawSize>
|
||||
</graphicData>
|
||||
</FleckDef>
|
||||
</Defs>
|
||||
@@ -1725,7 +1725,6 @@
|
||||
<hasStandardCommand>true</hasStandardCommand>
|
||||
<defaultProjectile>Bullet_WULA_WM_Panzer_Turret</defaultProjectile>
|
||||
<warmupTime>0</warmupTime>
|
||||
<forcedMissRadius>0.1</forcedMissRadius>
|
||||
<minRange>5.9</minRange>
|
||||
<range>75</range>
|
||||
<burstShotCount>1</burstShotCount>
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Defs>
|
||||
<ThingDef ParentName="BaseHumanMakeableGun">
|
||||
<defName>Weapon_ExampleCruiseMissileLauncher</defName>
|
||||
<label>Cruise Missile Launcher</label>
|
||||
<description>A heavy launcher designed for cruise missiles, capable of long-range precision strikes and area bombardment.</description>
|
||||
<techLevel>Spacer</techLevel>
|
||||
<graphicData>
|
||||
<texPath>Things/Item/Weapon/Launcher</texPath> <!-- Placeholder, needs a proper texture path -->
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<generateCommonality>1</generateCommonality>
|
||||
<soundInteract>Interact_ChargeRifle</soundInteract> <!-- Placeholder, needs a proper sound -->
|
||||
<weaponClasses>
|
||||
<li>LongShots</li>
|
||||
<li>RangedHeavy</li>
|
||||
</weaponClasses>
|
||||
<recipeMaker>
|
||||
<recipeUsers Inherit="False">
|
||||
<li>WULA_Cube_Productor_BIO</li>
|
||||
<li>WULA_Cube_Productor_Energy</li>
|
||||
</recipeUsers>
|
||||
<researchPrerequisite>WULA_Synth_Weapon_Technology</researchPrerequisite>
|
||||
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
|
||||
</recipeMaker>
|
||||
<statBases>
|
||||
<WorkToMake>2500</WorkToMake>
|
||||
<Mass>6.0</Mass>
|
||||
<AccuracyTouch>0.3</AccuracyTouch>
|
||||
<AccuracyShort>0.5</AccuracyShort>
|
||||
<AccuracyMedium>0.6</AccuracyMedium>
|
||||
<AccuracyLong>0.7</AccuracyLong>
|
||||
<RangedWeapon_Cooldown>4.0</RangedWeapon_Cooldown>
|
||||
</statBases>
|
||||
<costList Inherit="False">
|
||||
<Steel>180</Steel>
|
||||
<ComponentIndustrial>10</ComponentIndustrial>
|
||||
<Plasteel>40</Plasteel>
|
||||
<Uranium>15</Uranium>
|
||||
</costList>
|
||||
<verbs>
|
||||
<li>
|
||||
<verbClass>Verb_LaunchProjectile</verbClass>
|
||||
<hasStandardCommand>true</hasStandardCommand>
|
||||
<defaultProjectile>Bullet_ExampleCruiseMissile</defaultProjectile>
|
||||
<warmupTime>3.0</warmupTime>
|
||||
<range>60</range>
|
||||
<burstShotCount>1</burstShotCount>
|
||||
<soundCast>Shot_ChargeLance</soundCast> <!-- Placeholder, needs a proper sound -->
|
||||
<soundCastTail>GunTail_Heavy</soundCastTail>
|
||||
<muzzleFlashScale>15</muzzleFlashScale>
|
||||
<targetParams>
|
||||
<canTargetLocations>true</canTargetLocations>
|
||||
</targetParams>
|
||||
<forcedMiss>false</forcedMiss>
|
||||
</li>
|
||||
</verbs>
|
||||
<weaponTags>
|
||||
<li>Wula_Weapon_Init</li>
|
||||
<li>CruiseMissileLauncher</li>
|
||||
</weaponTags>
|
||||
<thingSetMakerTags>
|
||||
<li>RewardStandardQualitySuper</li>
|
||||
</thingSetMakerTags>
|
||||
</ThingDef>
|
||||
|
||||
<ThingDef ParentName="BaseBullet">
|
||||
<defName>Bullet_ExampleCruiseMissile</defName>
|
||||
<label>cruise missile</label>
|
||||
<graphicData>
|
||||
<texPath>Things/Projectile/Bullet_Big</texPath> <!-- Placeholder, needs a proper texture path -->
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<thingClass>WulaFallenEmpire.Projectile_CruiseMissile</thingClass>
|
||||
<projectile>
|
||||
<speed>30</speed>
|
||||
<damageDef>Bomb</damageDef>
|
||||
<damageAmountBase>20</damageAmountBase>
|
||||
<stoppingPower>2.5</stoppingPower>
|
||||
<armorPenetrationBase>0.8</armorPenetrationBase>
|
||||
<soundExplode>Explosion_Bomb</soundExplode>
|
||||
<soundImpactAnticipate>Impact_Metal</soundImpactAnticipate>
|
||||
<flyOverhead>true</flyOverhead>
|
||||
<shadowSize>1.0</shadowSize>
|
||||
<explosionRadius>4.0</explosionRadius>
|
||||
<postExplosionSpawnThingDef>Filth_Rubble</postExplosionSpawnThingDef>
|
||||
<postExplosionSpawnChance>1.0</postExplosionSpawnChance>
|
||||
<postExplosionSpawnThingCount>5</postExplosionSpawnThingCount>
|
||||
<explosionDelay>120</explosionDelay>
|
||||
<screenShakeFactor>1.5</screenShakeFactor>
|
||||
<applyDamageToExplosionCellsNeighbors>true</applyDamageToExplosionCellsNeighbors>
|
||||
<preExplosionSpawnChance>1.0</preExplosionSpawnChance>
|
||||
<preExplosionSpawnThingCount>8</preExplosionSpawnThingCount>
|
||||
<explosionChanceToStartFire>0.7</explosionChanceToStartFire>
|
||||
<explosionDamageFalloff>true</explosionDamageFalloff>
|
||||
<doExplosionVFX>true</doExplosionVFX>
|
||||
<modExtensions>
|
||||
<li Class="WulaFallenEmpire.CruiseMissileProperties">
|
||||
<customDamageDef>Bomb</customDamageDef>
|
||||
<customDamageAmount>25</customDamageAmount>
|
||||
<customExplosionRadius>3.5</customExplosionRadius>
|
||||
<customSoundExplode>Explosion_Bomb</customSoundExplode>
|
||||
<useSubExplosions>true</useSubExplosions>
|
||||
<subExplosionCount>5</subExplosionCount>
|
||||
<subExplosionRadius>2.0</subExplosionRadius>
|
||||
<subExplosionDamage>15</subExplosionDamage>
|
||||
<subExplosionSpread>7.0</subExplosionSpread>
|
||||
<subDamageDef>Bomb</subDamageDef>
|
||||
<subSoundExplode>Explosion_Bomb</subSoundExplode>
|
||||
<tailFleckDef>WULA_GunTail_Smoke</tailFleckDef>
|
||||
<homingSpeed>0.05</homingSpeed>
|
||||
<initRotateAngle>15</initRotateAngle>
|
||||
<destroyTicksAfterLosingTrack>
|
||||
<min>180</min>
|
||||
<max>300</max>
|
||||
</destroyTicksAfterLosingTrack>
|
||||
<speedChangePerTick>0.001</speedChangePerTick>
|
||||
<speedRangeOverride>
|
||||
<min>10</min>
|
||||
<max>20</max>
|
||||
</speedRangeOverride>
|
||||
<proximityFuseRange>1.5</proximityFuseRange>
|
||||
</li>
|
||||
</modExtensions>
|
||||
</projectile>
|
||||
</ThingDef>
|
||||
</Defs>
|
||||
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Defs>
|
||||
<ThingDef ParentName="BaseHumanMakeableGun">
|
||||
<defName>Weapon_ExampleHomingGun</defName>
|
||||
<label>Homing Rifle</label>
|
||||
<description>A rifle designed to fire homing projectiles. It can track targets and adjust its trajectory in real-time.</description>
|
||||
<techLevel>Spacer</techLevel>
|
||||
<graphicData>
|
||||
<texPath>Things/Item/Weapon/Rifle</texPath> <!-- Placeholder, needs a proper texture path -->
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<generateCommonality>1</generateCommonality>
|
||||
<soundInteract>Interact_Rifle</soundInteract>
|
||||
<weaponClasses>
|
||||
<li>LongShots</li>
|
||||
<li>RangedHeavy</li>
|
||||
</weaponClasses>
|
||||
<recipeMaker>
|
||||
<recipeUsers Inherit="False">
|
||||
<li>WULA_Cube_Productor_BIO</li>
|
||||
<li>WULA_Cube_Productor_Energy</li>
|
||||
</recipeUsers>
|
||||
<researchPrerequisite>WULA_Synth_Weapon_Technology</researchPrerequisite>
|
||||
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
|
||||
</recipeMaker>
|
||||
<statBases>
|
||||
<WorkToMake>1500</WorkToMake>
|
||||
<Mass>3.0</Mass>
|
||||
<AccuracyTouch>0.6</AccuracyTouch>
|
||||
<AccuracyShort>0.75</AccuracyShort>
|
||||
<AccuracyMedium>0.85</AccuracyMedium>
|
||||
<AccuracyLong>0.8</AccuracyLong>
|
||||
<RangedWeapon_Cooldown>1.2</RangedWeapon_Cooldown>
|
||||
</statBases>
|
||||
<costList Inherit="False">
|
||||
<Steel>100</Steel>
|
||||
<ComponentIndustrial>5</ComponentIndustrial>
|
||||
<Plasteel>20</Plasteel>
|
||||
</costList>
|
||||
<verbs>
|
||||
<li>
|
||||
<verbClass>Verb_Shoot</verbClass>
|
||||
<hasStandardCommand>true</hasStandardCommand>
|
||||
<defaultProjectile>Bullet_ExampleHoming</defaultProjectile>
|
||||
<warmupTime>1.0</warmupTime>
|
||||
<range>35</range>
|
||||
<burstShotCount>1</burstShotCount>
|
||||
<soundCast>Shot_ChargeRifle</soundCast> <!-- Placeholder, needs a proper sound -->
|
||||
<soundCastTail>GunTail_Medium</soundCastTail>
|
||||
<muzzleFlashScale>9</muzzleFlashScale>
|
||||
</li>
|
||||
</verbs>
|
||||
<weaponTags>
|
||||
<li>Wula_Weapon_Init</li>
|
||||
<li>HomingWeapon</li>
|
||||
</weaponTags>
|
||||
<thingSetMakerTags>
|
||||
<li>RewardStandardQualitySuper</li>
|
||||
</thingSetMakerTags>
|
||||
</ThingDef>
|
||||
|
||||
<ThingDef ParentName="BaseBullet">
|
||||
<defName>Bullet_ExampleHoming</defName>
|
||||
<label>homing bullet</label>
|
||||
<graphicData>
|
||||
<texPath>Things/Projectile/Bullet_Big</texPath> <!-- Placeholder, needs a proper texture path -->
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<thingClass>WulaFallenEmpire.Projectile_Homing</thingClass>
|
||||
<projectile>
|
||||
<speed>30</speed>
|
||||
<damageDef>Bullet</damageDef>
|
||||
<damageAmountBase>15</damageAmountBase>
|
||||
<stoppingPower>1.5</stoppingPower>
|
||||
<armorPenetrationBase>0.5</armorPenetrationBase>
|
||||
<soundExplode>Explosion_Blasting</soundExplode>
|
||||
<soundImpactAnticipate>Impact_Metal</soundImpactAnticipate>
|
||||
<flyOverhead>false</flyOverhead>
|
||||
<shadowSize>0.5</shadowSize>
|
||||
<explosionRadius>0.5</explosionRadius>
|
||||
<postExplosionSpawnThingDef>Filth_Rubble</postExplosionSpawnThingDef>
|
||||
<postExplosionSpawnChance>0.5</postExplosionSpawnChance>
|
||||
<postExplosionSpawnThingCount>1</postExplosionSpawnThingCount>
|
||||
<explosionDelay>0</explosionDelay>
|
||||
<screenShakeFactor>0.5</screenShakeFactor>
|
||||
<applyDamageToExplosionCellsNeighbors>false</applyDamageToExplosionCellsNeighbors>
|
||||
<preExplosionSpawnChance>0.5</preExplosionSpawnChance>
|
||||
<preExplosionSpawnThingCount>1</preExplosionSpawnThingCount>
|
||||
<explosionChanceToStartFire>0.1</explosionChanceToStartFire>
|
||||
<explosionDamageFalloff>true</explosionDamageFalloff>
|
||||
<doExplosionVFX>true</doExplosionVFX>
|
||||
<modExtensions>
|
||||
<li Class="WulaFallenEmpire.HomingProjectileDef">
|
||||
<initRotateAngle>10</initRotateAngle>
|
||||
<homingSpeed>0.05</homingSpeed>
|
||||
<destroyTicksAfterLosingTrack>60</destroyTicksAfterLosingTrack>
|
||||
<proximityFuseRange>1.5</proximityFuseRange>
|
||||
<hitChance>0.8</hitChance>
|
||||
<extraProjectile>Bullet_ExampleHoming</extraProjectile>
|
||||
<SpeedChangeTilesPerTickOverride>0.05</SpeedChangeTilesPerTickOverride>
|
||||
<SpeedRangeTilesPerTickOverride>
|
||||
<min>20</min>
|
||||
<max>40</max>
|
||||
</SpeedRangeTilesPerTickOverride>
|
||||
<tailFleckDef>WULA_GunTail_Smoke</tailFleckDef>
|
||||
</li>
|
||||
</modExtensions>
|
||||
</projectile>
|
||||
</ThingDef>
|
||||
</Defs>
|
||||
@@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Defs>
|
||||
<ThingDef ParentName="BaseHumanMakeableGun">
|
||||
<defName>Weapon_ExampleHomingExplosiveLauncher</defName>
|
||||
<label>Homing Explosive Launcher</label>
|
||||
<description>A powerful launcher that fires homing projectiles with explosive payloads. Ideal for area denial and heavy damage.</description>
|
||||
<techLevel>Spacer</techLevel>
|
||||
<graphicData>
|
||||
<texPath>Things/Item/Weapon/Launcher</texPath> <!-- Placeholder, needs a proper texture path -->
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<generateCommonality>0.8</generateCommonality>
|
||||
<soundInteract>Interact_ChargeRifle</soundInteract> <!-- Placeholder, needs a proper sound -->
|
||||
<weaponClasses>
|
||||
<li>LongShots</li>
|
||||
<li>RangedHeavy</li>
|
||||
</weaponClasses>
|
||||
<recipeMaker>
|
||||
<recipeUsers Inherit="False">
|
||||
<li>WULA_Cube_Productor_BIO</li>
|
||||
<li>WULA_Cube_Productor_Energy</li>
|
||||
</recipeUsers>
|
||||
<researchPrerequisite>WULA_Synth_Weapon_Technology</researchPrerequisite>
|
||||
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
|
||||
</recipeMaker>
|
||||
<statBases>
|
||||
<WorkToMake>2000</WorkToMake>
|
||||
<Mass>5.0</Mass>
|
||||
<AccuracyTouch>0.4</AccuracyTouch>
|
||||
<AccuracyShort>0.6</AccuracyShort>
|
||||
<AccuracyMedium>0.7</AccuracyMedium>
|
||||
<AccuracyLong>0.65</AccuracyLong>
|
||||
<RangedWeapon_Cooldown>3.0</RangedWeapon_Cooldown>
|
||||
</statBases>
|
||||
<costList Inherit="False">
|
||||
<Steel>150</Steel>
|
||||
<ComponentIndustrial>8</ComponentIndustrial>
|
||||
<Plasteel>30</Plasteel>
|
||||
<Uranium>10</Uranium>
|
||||
</costList>
|
||||
<verbs>
|
||||
<li>
|
||||
<verbClass>Verb_Shoot</verbClass>
|
||||
<hasStandardCommand>true</hasStandardCommand>
|
||||
<defaultProjectile>Bullet_ExampleHomingExplosive</defaultProjectile>
|
||||
<warmupTime>2.5</warmupTime>
|
||||
<range>40</range>
|
||||
<burstShotCount>1</burstShotCount>
|
||||
<soundCast>Shot_ChargeLance</soundCast> <!-- Placeholder, needs a proper sound -->
|
||||
<soundCastTail>GunTail_Heavy</soundCastTail>
|
||||
<muzzleFlashScale>12</muzzleFlashScale>
|
||||
</li>
|
||||
</verbs>
|
||||
<weaponTags>
|
||||
<li>Wula_Weapon_Init</li>
|
||||
<li>HomingExplosiveWeapon</li>
|
||||
</weaponTags>
|
||||
<thingSetMakerTags>
|
||||
<li>RewardStandardQualitySuper</li>
|
||||
</thingSetMakerTags>
|
||||
</ThingDef>
|
||||
|
||||
<ThingDef ParentName="BaseBullet">
|
||||
<defName>Bullet_ExampleHomingExplosive</defName>
|
||||
<label>homing explosive bullet</label>
|
||||
<graphicData>
|
||||
<texPath>Things/Projectile/Bullet_Big</texPath> <!-- Placeholder, needs a proper texture path -->
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<thingClass>WulaFallenEmpire.Projectile_Homing_Explosive</thingClass>
|
||||
<projectile>
|
||||
<speed>25</speed>
|
||||
<damageDef>Bomb</damageDef>
|
||||
<damageAmountBase>30</damageAmountBase>
|
||||
<stoppingPower>2.0</stoppingPower>
|
||||
<armorPenetrationBase>0.7</armorPenetrationBase>
|
||||
<soundExplode>Explosion_Bomb</soundExplode>
|
||||
<soundImpactAnticipate>Impact_Metal</soundImpactAnticipate>
|
||||
<flyOverhead>true</flyOverhead>
|
||||
<shadowSize>0.8</shadowSize>
|
||||
<explosionRadius>3.0</explosionRadius>
|
||||
<postExplosionSpawnThingDef>Filth_Rubble</postExplosionSpawnThingDef>
|
||||
<postExplosionSpawnChance>1.0</postExplosionSpawnChance>
|
||||
<postExplosionSpawnThingCount>3</postExplosionSpawnThingCount>
|
||||
<explosionDelay>60</explosionDelay>
|
||||
<screenShakeFactor>1.0</screenShakeFactor>
|
||||
<applyDamageToExplosionCellsNeighbors>true</applyDamageToExplosionCellsNeighbors>
|
||||
<preExplosionSpawnChance>1.0</preExplosionSpawnChance>
|
||||
<preExplosionSpawnThingCount>5</preExplosionSpawnThingCount>
|
||||
<explosionChanceToStartFire>0.5</explosionChanceToStartFire>
|
||||
<explosionDamageFalloff>true</explosionDamageFalloff>
|
||||
<doExplosionVFX>true</doExplosionVFX>
|
||||
<modExtensions>
|
||||
<li Class="WulaFallenEmpire.HomingProjectileDef">
|
||||
<initRotateAngle>5</initRotateAngle>
|
||||
<homingSpeed>0.03</homingSpeed>
|
||||
<destroyTicksAfterLosingTrack>90</destroyTicksAfterLosingTrack>
|
||||
<proximityFuseRange>2.0</proximityFuseRange>
|
||||
<hitChance>0.7</hitChance>
|
||||
<extraProjectile>Bullet_ExampleHomingExplosive</extraProjectile>
|
||||
<SpeedChangeTilesPerTickOverride>0.03</SpeedChangeTilesPerTickOverride>
|
||||
<SpeedRangeTilesPerTickOverride>
|
||||
<min>20</min>
|
||||
<max>30</max>
|
||||
</SpeedRangeTilesPerTickOverride>
|
||||
<tailFleckDef>WULA_GunTail_Smoke</tailFleckDef>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.ModExtension_Cone">
|
||||
<coneAngle>30</coneAngle>
|
||||
<coneRange>5</coneRange>
|
||||
<repeatExplosionCount>3</repeatExplosionCount>
|
||||
<fragment>Bullet_ShotgunPellet</fragment> <!-- Example fragment -->
|
||||
<fragmentCount>5</fragmentCount>
|
||||
<fragmentRange>
|
||||
<min>1</min>
|
||||
<max>3</max>
|
||||
</fragmentRange>
|
||||
<showConeEffect>true</showConeEffect>
|
||||
</li>
|
||||
</modExtensions>
|
||||
</projectile>
|
||||
</ThingDef>
|
||||
</Defs>
|
||||
@@ -68,6 +68,7 @@
|
||||
<maxHits>-1</maxHits> <!-- 无限穿透 -->
|
||||
<damageFalloff>0</damageFalloff> <!-- 无伤害衰减 -->
|
||||
<preventFriendlyFire>false</preventFriendlyFire> <!-- 是否阻止友方火力 -->
|
||||
<tailFleckDef>WULA_GunTail_Blue</tailFleckDef> <!-- 拖尾特效定义 -->
|
||||
</li>
|
||||
</modExtensions>
|
||||
<tickerType>Normal</tickerType>
|
||||
|
||||
@@ -9,13 +9,7 @@
|
||||
"path": "../../../../Data"
|
||||
},
|
||||
{
|
||||
"path": "../../../3256974620"
|
||||
},
|
||||
{
|
||||
"path": "../../../2953846705"
|
||||
},
|
||||
{
|
||||
"path": "../../../1635901197"
|
||||
"path": "../../../../../../workshop/content/294100/3534748687"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
|
||||
41
Source/WulaFallenEmpire/HomingProjectileDef.cs
Normal file
41
Source/WulaFallenEmpire/HomingProjectileDef.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class HomingProjectileDef : DefModExtension
|
||||
{
|
||||
public float SpeedChangeTilesPerTickOverride
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.speedChangePerTick / 100f;
|
||||
}
|
||||
}
|
||||
|
||||
public FloatRange SpeedRangeTilesPerTickOverride
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.speedRangeOverride.Value * 0.01f;
|
||||
}
|
||||
}
|
||||
|
||||
public float hitChance = 0.5f;
|
||||
|
||||
public float homingSpeed = 0.1f;
|
||||
|
||||
public float initRotateAngle = 30f;
|
||||
|
||||
public float proximityFuseRange = 0f;
|
||||
|
||||
public IntRange destroyTicksAfterLosingTrack = new IntRange(60, 120);
|
||||
|
||||
public ThingDef extraProjectile;
|
||||
|
||||
public float speedChangePerTick;
|
||||
|
||||
public FloatRange? speedRangeOverride;
|
||||
public FleckDef tailFleckDef;
|
||||
}
|
||||
}
|
||||
105
Source/WulaFallenEmpire/ModExtension_Cone.cs
Normal file
105
Source/WulaFallenEmpire/ModExtension_Cone.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class ModExtension_Cone : DefModExtension
|
||||
{
|
||||
public float coneAngle = 10f;
|
||||
|
||||
public float coneRange = 7f;
|
||||
|
||||
public int repeatExplosionCount = 1;
|
||||
|
||||
public ThingDef fragment;
|
||||
|
||||
public int fragmentCount;
|
||||
|
||||
public FloatRange? fragmentRange;
|
||||
|
||||
public bool showConeEffect = true;
|
||||
|
||||
public void DoConeExplosion(IntVec3 center, Map map, Quaternion rotation, DamageDef damType, Thing instigator, int damAmount = -1, float armorPenetration = -1f, SoundDef explosionSound = null, ThingDef weapon = null, ThingDef projectile = null, Thing intendedTarget = null, ThingDef postExplosionSpawnThingDef = null, float postExplosionSpawnChance = 0f, int postExplosionSpawnThingCount = 1, GasType? postExplosionGasType = null, float? postExplosionGasRadiusOverride = null, int postExplosionGasAmount = 255, bool applyDamageToExplosionCellsNeighbors = false, ThingDef preExplosionSpawnThingDef = null, float preExplosionSpawnChance = 0f, int preExplosionSpawnThingCount = 1, float chanceToStartFire = 0f, bool damageFalloff = false, float? direction = null, List<Thing> ignoredThings = null, float propagationSpeed = 1f, float excludeRadius = 0f, ThingDef postExplosionSpawnThingDefWater = null, float screenShakeFactor = 1f, SimpleCurve flammabilityChanceCurve = null, List<IntVec3> overrideCells = null)
|
||||
{
|
||||
Vector3 v = rotation * Vector3.forward;
|
||||
FloatRange initialAngleRange = new FloatRange(v.ToAngleFlat() - coneAngle, v.ToAngleFlat() + coneAngle);
|
||||
|
||||
for (int i = 0; i < repeatExplosionCount; i++)
|
||||
{
|
||||
// Handle angle wrap-around for max > 360
|
||||
if (initialAngleRange.max > 360f)
|
||||
{
|
||||
GenExplosion.DoExplosion(affectedAngle: new FloatRange(0f, initialAngleRange.max - 360f), center: center, map: map, radius: coneRange, damType: damType, instigator: instigator, damAmount: damAmount, armorPenetration: armorPenetration, explosionSound: explosionSound, weapon: weapon, projectile: projectile, intendedTarget: intendedTarget, postExplosionSpawnThingDef: postExplosionSpawnThingDef, postExplosionSpawnChance: postExplosionSpawnChance, postExplosionSpawnThingCount: postExplosionSpawnThingCount, postExplosionGasType: postExplosionGasType, postExplosionGasRadiusOverride: postExplosionGasRadiusOverride, postExplosionGasAmount: postExplosionGasAmount, applyDamageToExplosionCellsNeighbors: applyDamageToExplosionCellsNeighbors, preExplosionSpawnThingDef: preExplosionSpawnThingDef, preExplosionSpawnChance: preExplosionSpawnChance, preExplosionSpawnThingCount: preExplosionSpawnThingCount, chanceToStartFire: chanceToStartFire, damageFalloff: damageFalloff, direction: direction, ignoredThings: ignoredThings, doVisualEffects: showConeEffect, propagationSpeed: propagationSpeed, excludeRadius: excludeRadius, doSoundEffects: showConeEffect, postExplosionSpawnThingDefWater: postExplosionSpawnThingDefWater, screenShakeFactor: screenShakeFactor, flammabilityChanceCurve: flammabilityChanceCurve, overrideCells: overrideCells);
|
||||
}
|
||||
|
||||
// Handle angle wrap-around for min < 0
|
||||
if (initialAngleRange.min < 0f)
|
||||
{
|
||||
GenExplosion.DoExplosion(affectedAngle: new FloatRange(initialAngleRange.min + 360f, 360f), center: center, map: map, radius: coneRange, damType: damType, instigator: instigator, damAmount: damAmount, armorPenetration: armorPenetration, explosionSound: explosionSound, weapon: weapon, projectile: projectile, intendedTarget: intendedTarget, postExplosionSpawnThingDef: postExplosionSpawnThingDef, postExplosionSpawnChance: postExplosionSpawnChance, postExplosionSpawnThingCount: postExplosionSpawnThingCount, postExplosionGasType: postExplosionGasType, postExplosionGasRadiusOverride: postExplosionGasRadiusOverride, postExplosionGasAmount: postExplosionGasAmount, applyDamageToExplosionCellsNeighbors: applyDamageToExplosionCellsNeighbors, preExplosionSpawnThingDef: preExplosionSpawnThingDef, preExplosionSpawnChance: preExplosionSpawnChance, preExplosionSpawnThingCount: preExplosionSpawnThingCount, chanceToStartFire: chanceToStartFire, damageFalloff: damageFalloff, direction: direction, ignoredThings: ignoredThings, doVisualEffects: showConeEffect, propagationSpeed: propagationSpeed, excludeRadius: excludeRadius, doSoundEffects: showConeEffect, postExplosionSpawnThingDefWater: postExplosionSpawnThingDefWater, screenShakeFactor: screenShakeFactor, flammabilityChanceCurve: flammabilityChanceCurve, overrideCells: overrideCells);
|
||||
}
|
||||
|
||||
// Main explosion
|
||||
GenExplosion.DoExplosion(center, map, coneRange, damType, instigator, damAmount, armorPenetration, explosionSound, weapon, projectile, intendedTarget, postExplosionSpawnThingDef, postExplosionSpawnChance, postExplosionSpawnThingCount, postExplosionGasType, postExplosionGasRadiusOverride, postExplosionGasAmount, applyDamageToExplosionCellsNeighbors, preExplosionSpawnThingDef, preExplosionSpawnChance, preExplosionSpawnThingCount, chanceToStartFire, damageFalloff, direction, ignoredThings, initialAngleRange, showConeEffect, propagationSpeed, excludeRadius, showConeEffect, postExplosionSpawnThingDefWater, screenShakeFactor, flammabilityChanceCurve, overrideCells);
|
||||
}
|
||||
|
||||
if (fragment != null)
|
||||
{
|
||||
FloatRange currentFragmentRange = fragmentRange.HasValue ? fragmentRange.Value : new FloatRange(0f, coneRange);
|
||||
IEnumerable<IntVec3> source = FragmentCells(center, initialAngleRange, currentFragmentRange);
|
||||
for (int j = 0; j < fragmentCount; j++)
|
||||
{
|
||||
IntVec3 intVec = source.RandomElement();
|
||||
((Projectile)GenSpawn.Spawn(fragment, center, map)).Launch(instigator, intVec, intVec, ProjectileHitFlags.All);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<IntVec3> FragmentCells(IntVec3 center, FloatRange? angle, FloatRange range)
|
||||
{
|
||||
int minRadialCells = GenRadial.NumCellsInRadius(range.min);
|
||||
int maxRadialCells = GenRadial.NumCellsInRadius(range.max);
|
||||
|
||||
for (int i = minRadialCells; i < maxRadialCells; i++)
|
||||
{
|
||||
IntVec3 currentCell = center + GenRadial.RadialPattern[i];
|
||||
|
||||
if (angle.HasValue)
|
||||
{
|
||||
float angleMin = angle.Value.min;
|
||||
float angleMax = angle.Value.max;
|
||||
float lengthHorizontal = (currentCell - center).LengthHorizontal;
|
||||
|
||||
if (lengthHorizontal <= 0.5f) // Close to center, always include
|
||||
{
|
||||
yield return currentCell;
|
||||
continue;
|
||||
}
|
||||
|
||||
float cellAngle = Mathf.Atan2(-(currentCell.z - center.z), currentCell.x - center.x) * 57.29578f; // Convert radians to degrees
|
||||
|
||||
// Handle angle wrap-around for comparison
|
||||
if (angleMin < 0f && cellAngle - angleMin > 360f)
|
||||
{
|
||||
cellAngle -= 360f;
|
||||
}
|
||||
if (angleMax > 360f && angleMax - cellAngle < 360f)
|
||||
{
|
||||
cellAngle += 360f;
|
||||
}
|
||||
|
||||
// Check if cell is within the angular range
|
||||
if (cellAngle >= angleMin && cellAngle <= angleMax)
|
||||
{
|
||||
yield return currentCell;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return currentCell; // No angle restriction
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
325
Source/WulaFallenEmpire/Projectile_Homing.cs
Normal file
325
Source/WulaFallenEmpire/Projectile_Homing.cs
Normal file
@@ -0,0 +1,325 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
using Verse.Sound;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class Projectile_Homing : Bullet
|
||||
{
|
||||
public HomingProjectileDef HomingDef
|
||||
{
|
||||
get
|
||||
{
|
||||
bool flag = this.homingDefInt == null;
|
||||
if (flag)
|
||||
{
|
||||
this.homingDefInt = this.def.GetModExtension<HomingProjectileDef>();
|
||||
}
|
||||
return this.homingDefInt;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
|
||||
{
|
||||
bool flag = false;
|
||||
bool flag2 = usedTarget.HasThing && usedTarget.Thing is IAttackTarget;
|
||||
if (flag2)
|
||||
{
|
||||
bool flag3 = Rand.Chance(this.GetHitChance(usedTarget.Thing));
|
||||
if (flag3)
|
||||
{
|
||||
hitFlags |= ProjectileHitFlags.IntendedTarget;
|
||||
intendedTarget = usedTarget;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool flag4 = Rand.Chance(this.GetHitChance(intendedTarget.Thing));
|
||||
if (flag4)
|
||||
{
|
||||
hitFlags |= ProjectileHitFlags.IntendedTarget;
|
||||
usedTarget = intendedTarget;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
bool flag5 = flag;
|
||||
if (flag5)
|
||||
{
|
||||
hitFlags &= ~ProjectileHitFlags.IntendedTarget;
|
||||
}
|
||||
base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
|
||||
this.exactPositionInt = origin.Yto0() + Vector3.up * this.def.Altitude;
|
||||
Vector3 normalized = (this.destination - origin).Yto0().normalized;
|
||||
float degrees = Rand.Range(-this.HomingDef.initRotateAngle, this.HomingDef.initRotateAngle);
|
||||
Vector2 vector = new Vector2(normalized.x, normalized.z);
|
||||
vector = vector.RotatedBy(degrees);
|
||||
Vector3 a = new Vector3(vector.x, 0f, vector.y);
|
||||
bool flag6 = this.HomingDef.speedRangeOverride == null;
|
||||
if (flag6)
|
||||
{
|
||||
this.curSpeed = a * this.def.projectile.SpeedTilesPerTick;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.curSpeed = a * this.HomingDef.SpeedRangeTilesPerTickOverride.RandomInRange;
|
||||
}
|
||||
this.ticksToImpact = int.MaxValue;
|
||||
this.lifetime = int.MaxValue;
|
||||
this.ReflectInit();
|
||||
}
|
||||
|
||||
protected void ReflectInit()
|
||||
{
|
||||
bool flag = !this.def.projectile.soundAmbient.NullOrUndefined();
|
||||
if (flag)
|
||||
{
|
||||
this.ambientSustainer = (Sustainer)NonPublicFields.Projectile_AmbientSustainer.GetValue(this);
|
||||
}
|
||||
this.comps = (List<ThingComp>)NonPublicFields.ThingWithComps_comps.GetValue(this);
|
||||
}
|
||||
|
||||
public float GetHitChance(Thing thing)
|
||||
{
|
||||
float num = this.HomingDef.hitChance;
|
||||
bool flag = thing == null;
|
||||
float result;
|
||||
if (flag)
|
||||
{
|
||||
result = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pawn pawn = thing as Pawn;
|
||||
bool flag2 = pawn != null;
|
||||
if (flag2)
|
||||
{
|
||||
num *= Mathf.Clamp(pawn.BodySize, 0.5f, 1.5f);
|
||||
bool flag3 = pawn.GetPosture() > PawnPosture.Standing;
|
||||
if (flag3)
|
||||
{
|
||||
num *= 0.5f;
|
||||
}
|
||||
float num2 = 1f;
|
||||
switch (this.equipmentQuality)
|
||||
{
|
||||
case QualityCategory.Awful:
|
||||
num2 = 0.5f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Poor:
|
||||
num2 = 0.75f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Normal:
|
||||
num2 = 1f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Excellent:
|
||||
num2 = 1.1f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Masterwork:
|
||||
num2 = 1.2f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Legendary:
|
||||
num2 = 1.3f;
|
||||
goto IL_DD;
|
||||
}
|
||||
Log.Message("Unknown QualityCategory, returning default qualityFactor = 1");
|
||||
IL_DD:
|
||||
num *= num2;
|
||||
}
|
||||
else
|
||||
{
|
||||
num *= 1.5f * thing.def.fillPercent;
|
||||
}
|
||||
result = Mathf.Clamp(num, 0f, 1f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override Vector3 ExactPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.exactPositionInt;
|
||||
}
|
||||
}
|
||||
|
||||
public override Quaternion ExactRotation
|
||||
{
|
||||
get
|
||||
{
|
||||
return Quaternion.LookRotation(this.curSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void MovementTick()
|
||||
{
|
||||
Vector3 vect = this.ExactPosition + this.curSpeed;
|
||||
ShootLine shootLine = new ShootLine(this.ExactPosition.ToIntVec3(), vect.ToIntVec3());
|
||||
Vector3 vector = (this.intendedTarget.Cell.ToVector3() - this.ExactPosition).Yto0();
|
||||
bool flag = this.homing;
|
||||
if (flag)
|
||||
{
|
||||
Vector3 a = vector.normalized - this.curSpeed.normalized;
|
||||
bool flag2 = a.sqrMagnitude >= 1.414f;
|
||||
if (flag2)
|
||||
{
|
||||
this.homing = false;
|
||||
this.lifetime = this.HomingDef.destroyTicksAfterLosingTrack.RandomInRange;
|
||||
this.ticksToImpact = this.lifetime;
|
||||
base.HitFlags &= ~ProjectileHitFlags.IntendedTarget;
|
||||
base.HitFlags |= ProjectileHitFlags.NonTargetPawns;
|
||||
base.HitFlags |= ProjectileHitFlags.NonTargetWorld;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.curSpeed += a * this.HomingDef.homingSpeed * this.curSpeed.magnitude;
|
||||
}
|
||||
}
|
||||
foreach (IntVec3 b in shootLine.Points())
|
||||
{
|
||||
bool flag3 = (this.intendedTarget.Cell - b).SqrMagnitude <= this.HomingDef.proximityFuseRange * this.HomingDef.proximityFuseRange;
|
||||
if (flag3)
|
||||
{
|
||||
this.homing = false;
|
||||
this.lifetime = this.HomingDef.destroyTicksAfterLosingTrack.RandomInRange;
|
||||
bool flag4 = (base.HitFlags & ProjectileHitFlags.IntendedTarget) == ProjectileHitFlags.IntendedTarget || this.HomingDef.proximityFuseRange > 0f;
|
||||
if (flag4)
|
||||
{
|
||||
this.lifetime = 0;
|
||||
this.ticksToImpact = 0;
|
||||
vect = b.ToVector3();
|
||||
bool flag5 = Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && this.def.projectile.soundImpactAnticipate != null;
|
||||
if (flag5)
|
||||
{
|
||||
this.def.projectile.soundImpactAnticipate.PlayOneShot(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.exactPositionInt = vect;
|
||||
this.curSpeed *= (this.curSpeed.magnitude + this.HomingDef.SpeedChangeTilesPerTickOverride) / this.curSpeed.magnitude;
|
||||
}
|
||||
|
||||
protected override void Tick()
|
||||
{
|
||||
this.ThingWithCompsTick();
|
||||
this.lifetime--;
|
||||
if (this.HomingDef.tailFleckDef != null)
|
||||
{
|
||||
FleckMaker.Static(this.ExactPosition, base.Map, this.HomingDef.tailFleckDef, 1f);
|
||||
}
|
||||
bool landed = this.landed;
|
||||
if (!landed)
|
||||
{
|
||||
Vector3 exactPosition = this.ExactPosition;
|
||||
this.ticksToImpact--;
|
||||
this.MovementTick();
|
||||
bool flag = !this.ExactPosition.InBounds(base.Map);
|
||||
if (flag)
|
||||
{
|
||||
base.Position = exactPosition.ToIntVec3();
|
||||
this.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 exactPosition2 = this.ExactPosition;
|
||||
object[] parameters = new object[]
|
||||
{
|
||||
exactPosition,
|
||||
exactPosition2
|
||||
};
|
||||
bool flag2 = (bool)Projectile_Homing.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters);
|
||||
if (!flag2)
|
||||
{
|
||||
base.Position = this.ExactPosition.ToIntVec3();
|
||||
bool flag3 = this.ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && this.def.projectile.soundImpactAnticipate != null;
|
||||
if (flag3)
|
||||
{
|
||||
this.def.projectile.soundImpactAnticipate.PlayOneShot(this);
|
||||
}
|
||||
bool flag4 = this.ticksToImpact <= 0;
|
||||
if (flag4)
|
||||
{
|
||||
this.ImpactSomething();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool flag5 = this.ambientSustainer != null;
|
||||
if (flag5)
|
||||
{
|
||||
this.ambientSustainer.Maintain();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ThingWithCompsTick()
|
||||
{
|
||||
bool flag = this.comps != null;
|
||||
if (flag)
|
||||
{
|
||||
int i = 0;
|
||||
int count = this.comps.Count;
|
||||
while (i < count)
|
||||
{
|
||||
this.comps[i].CompTick();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Impact(Thing hitThing, bool blockedByShield = false)
|
||||
{
|
||||
Map map = base.Map;
|
||||
IntVec3 position = base.Position;
|
||||
base.Impact(hitThing, blockedByShield);
|
||||
bool flag = this.HomingDef.extraProjectile != null;
|
||||
if (flag)
|
||||
{
|
||||
bool flag2 = hitThing != null && hitThing.Spawned;
|
||||
if (flag2)
|
||||
{
|
||||
((Projectile)GenSpawn.Spawn(this.HomingDef.extraProjectile, base.Position, map, WipeMode.Vanish)).Launch(this.launcher, this.ExactPosition, hitThing, hitThing, ProjectileHitFlags.All, false, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
((Projectile)GenSpawn.Spawn(this.HomingDef.extraProjectile, base.Position, map, WipeMode.Vanish)).Launch(this.launcher, this.ExactPosition, position, position, ProjectileHitFlags.All, false, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look<Vector3>(ref this.exactPositionInt, "exactPosition", default(Vector3), false);
|
||||
Scribe_Values.Look<Vector3>(ref this.curSpeed, "curSpeed", default(Vector3), false);
|
||||
Scribe_Values.Look<bool>(ref this.homing, "homing", false, false);
|
||||
bool flag = Scribe.mode == LoadSaveMode.PostLoadInit;
|
||||
if (flag)
|
||||
{
|
||||
this.ReflectInit();
|
||||
}
|
||||
}
|
||||
|
||||
private HomingProjectileDef homingDefInt;
|
||||
|
||||
private Sustainer ambientSustainer;
|
||||
|
||||
private List<ThingComp> comps;
|
||||
|
||||
protected Vector3 exactPositionInt;
|
||||
|
||||
public Vector3 curSpeed;
|
||||
|
||||
public bool homing = true;
|
||||
|
||||
private static MethodInfo ProjectileCheckForFreeInterceptBetween = typeof(Projectile).GetMethod("CheckForFreeInterceptBetween", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
}
|
||||
142
Source/WulaFallenEmpire/Projectile_Homing_Explosive.cs
Normal file
142
Source/WulaFallenEmpire/Projectile_Homing_Explosive.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class Projectile_Homing_Explosive : Projectile_Homing
|
||||
{
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look<int>(ref this.ticksToDetonation, "ticksToDetonation", 0, false);
|
||||
}
|
||||
|
||||
protected override void Tick()
|
||||
{
|
||||
base.Tick();
|
||||
bool flag = this.ticksToDetonation > 0;
|
||||
if (flag)
|
||||
{
|
||||
this.ticksToDetonation--;
|
||||
bool flag2 = this.ticksToDetonation <= 0;
|
||||
if (flag2)
|
||||
{
|
||||
this.Explode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Impact(Thing hitThing, bool blockedByShield = false)
|
||||
{
|
||||
bool flag = blockedByShield || this.def.projectile.explosionDelay == 0;
|
||||
if (flag)
|
||||
{
|
||||
this.Explode();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.landed = true;
|
||||
this.ticksToDetonation = this.def.projectile.explosionDelay;
|
||||
GenExplosion.NotifyNearbyPawnsOfDangerousExplosive(this, this.def.projectile.damageDef, this.launcher.Faction, this.launcher);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Explode()
|
||||
{
|
||||
Map map = base.Map;
|
||||
ModExtension_Cone modExtension = this.def.GetModExtension<ModExtension_Cone>();
|
||||
this.DoExplosion();
|
||||
bool flag = modExtension != null;
|
||||
if (flag)
|
||||
{
|
||||
ProjectileProperties projectile = this.def.projectile;
|
||||
ModExtension_Cone modExtension_Cone = modExtension;
|
||||
IntVec3 position = base.Position;
|
||||
Map map2 = map;
|
||||
Quaternion exactRotation = this.ExactRotation;
|
||||
DamageDef damageDef = projectile.damageDef;
|
||||
Thing launcher = base.Launcher;
|
||||
int damageAmount = this.DamageAmount;
|
||||
float armorPenetration = this.ArmorPenetration;
|
||||
SoundDef soundExplode = this.def.projectile.soundExplode;
|
||||
ThingDef equipmentDef = this.equipmentDef;
|
||||
ThingDef def = this.def;
|
||||
Thing thing = this.intendedTarget.Thing;
|
||||
ThingDef postExplosionSpawnThingDef = null;
|
||||
float postExplosionSpawnChance = 0f;
|
||||
int postExplosionSpawnThingCount = 1;
|
||||
float screenShakeFactor = this.def.projectile.screenShakeFactor;
|
||||
modExtension_Cone.DoConeExplosion(position, map2, exactRotation, damageDef, launcher, damageAmount, armorPenetration, soundExplode, equipmentDef, def, thing, postExplosionSpawnThingDef, postExplosionSpawnChance, postExplosionSpawnThingCount, null, null, 255, false, null, 0f, 1, 0f, false, null, null, 1f, 0f, null, screenShakeFactor, null, null);
|
||||
}
|
||||
bool flag2 = this.def.projectile.explosionEffect != null;
|
||||
if (flag2)
|
||||
{
|
||||
Effecter effecter = this.def.projectile.explosionEffect.Spawn();
|
||||
bool flag3 = this.def.projectile.explosionEffectLifetimeTicks != 0;
|
||||
if (flag3)
|
||||
{
|
||||
map.effecterMaintainer.AddEffecterToMaintain(effecter, base.Position.ToVector3().ToIntVec3(), this.def.projectile.explosionEffectLifetimeTicks);
|
||||
}
|
||||
else
|
||||
{
|
||||
effecter.Trigger(new TargetInfo(base.Position, map, false), new TargetInfo(base.Position, map, false), -1);
|
||||
effecter.Cleanup();
|
||||
}
|
||||
}
|
||||
this.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
|
||||
protected void DoExplosion()
|
||||
{
|
||||
IntVec3 position = base.Position;
|
||||
float explosionRadius = this.def.projectile.explosionRadius;
|
||||
DamageDef damageDef = this.def.projectile.damageDef;
|
||||
Thing launcher = this.launcher;
|
||||
int damageAmount = this.DamageAmount;
|
||||
float armorPenetration = this.ArmorPenetration;
|
||||
SoundDef soundExplode = this.def.projectile.soundExplode;
|
||||
ThingDef equipmentDef = this.equipmentDef;
|
||||
ThingDef def = this.def;
|
||||
Thing thing = this.intendedTarget.Thing;
|
||||
ThingDef thingDef = this.def.projectile.postExplosionSpawnThingDef ?? this.def.projectile.filth;
|
||||
ThingDef postExplosionSpawnThingDefWater = this.def.projectile.postExplosionSpawnThingDefWater;
|
||||
float postExplosionSpawnChance = this.def.projectile.postExplosionSpawnChance;
|
||||
int postExplosionSpawnThingCount = this.def.projectile.postExplosionSpawnThingCount;
|
||||
GasType? postExplosionGasType = this.def.projectile.postExplosionGasType;
|
||||
ThingDef preExplosionSpawnThingDef = this.def.projectile.preExplosionSpawnThingDef;
|
||||
float preExplosionSpawnChance = this.def.projectile.preExplosionSpawnChance;
|
||||
int preExplosionSpawnThingCount = this.def.projectile.preExplosionSpawnThingCount;
|
||||
bool applyDamageToExplosionCellsNeighbors = this.def.projectile.applyDamageToExplosionCellsNeighbors;
|
||||
ThingDef preExplosionSpawnThingDef2 = preExplosionSpawnThingDef;
|
||||
float preExplosionSpawnChance2 = preExplosionSpawnChance;
|
||||
int preExplosionSpawnThingCount2 = preExplosionSpawnThingCount;
|
||||
float explosionChanceToStartFire = this.def.projectile.explosionChanceToStartFire;
|
||||
bool explosionDamageFalloff = this.def.projectile.explosionDamageFalloff;
|
||||
float? direction = new float?(this.origin.AngleToFlat(this.destination));
|
||||
FloatRange? affectedAngle = null;
|
||||
float expolosionPropagationSpeed = this.def.projectile.damageDef.expolosionPropagationSpeed;
|
||||
float screenShakeFactor = this.def.projectile.screenShakeFactor;
|
||||
IntVec3 center = position;
|
||||
Map map = base.Map;
|
||||
float radius = explosionRadius;
|
||||
DamageDef damType = damageDef;
|
||||
Thing instigator = launcher;
|
||||
int damAmount = damageAmount;
|
||||
float armorPenetration2 = armorPenetration;
|
||||
SoundDef explosionSound = soundExplode;
|
||||
ThingDef weapon = equipmentDef;
|
||||
ThingDef projectile = def;
|
||||
Thing intendedTarget = thing;
|
||||
ThingDef postExplosionSpawnThingDef = thingDef;
|
||||
float postExplosionSpawnChance2 = postExplosionSpawnChance;
|
||||
int postExplosionSpawnThingCount2 = postExplosionSpawnThingCount;
|
||||
GasType? postExplosionGasType2 = postExplosionGasType;
|
||||
bool doExplosionVFX = this.def.projectile.doExplosionVFX;
|
||||
ThingDef postExplosionSpawnThingDefWater2 = postExplosionSpawnThingDefWater;
|
||||
GenExplosion.DoExplosion(center, map, radius, damType, instigator, damAmount, armorPenetration2, explosionSound, weapon, projectile, intendedTarget, postExplosionSpawnThingDef, postExplosionSpawnChance2, postExplosionSpawnThingCount2, postExplosionGasType2, null, 255, applyDamageToExplosionCellsNeighbors, preExplosionSpawnThingDef2, preExplosionSpawnChance2, preExplosionSpawnThingCount2, explosionChanceToStartFire, explosionDamageFalloff, direction, null, affectedAngle, doExplosionVFX, expolosionPropagationSpeed, 0f, true, postExplosionSpawnThingDefWater2, screenShakeFactor, null, null, null, null);
|
||||
}
|
||||
|
||||
private int ticksToDetonation;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ namespace WulaFallenEmpire
|
||||
public float damageFalloff = 0.25f;
|
||||
// If true, this projectile will never cause friendly fire, regardless of game settings.
|
||||
public bool preventFriendlyFire = false;
|
||||
public FleckDef tailFleckDef; // 用于配置拖尾特效的 FleckDef
|
||||
}
|
||||
|
||||
public class Projectile_WulaLineAttack : Projectile
|
||||
@@ -21,6 +22,13 @@ namespace WulaFallenEmpire
|
||||
private int hitCounter = 0;
|
||||
private List<Thing> alreadyDamaged = new List<Thing>();
|
||||
private Vector3 lastTickPosition;
|
||||
private int Fleck_MakeFleckTick; // 拖尾特效的计时器
|
||||
public int Fleck_MakeFleckTickMax = 1; // 拖尾特效的生成频率
|
||||
public IntRange Fleck_MakeFleckNum = new IntRange(1, 1); // 每次生成的粒子数量
|
||||
public FloatRange Fleck_Angle = new FloatRange(-180f, 180f); // 粒子角度
|
||||
public FloatRange Fleck_Scale = new FloatRange(1f, 1f); // 粒子大小
|
||||
public FloatRange Fleck_Speed = new FloatRange(0f, 0f); // 粒子速度
|
||||
public FloatRange Fleck_Rotation = new FloatRange(-180f, 180f); // 粒子旋转
|
||||
|
||||
private Wula_PathPierce_Extension Props => def.GetModExtension<Wula_PathPierce_Extension>();
|
||||
|
||||
@@ -49,7 +57,38 @@ namespace WulaFallenEmpire
|
||||
protected override void Tick()
|
||||
{
|
||||
Vector3 startPos = this.lastTickPosition;
|
||||
base.Tick();
|
||||
base.Tick();
|
||||
|
||||
if (this.Destroyed) return;
|
||||
|
||||
this.Fleck_MakeFleckTick++;
|
||||
bool flag = this.Fleck_MakeFleckTick >= this.Fleck_MakeFleckTickMax;
|
||||
if (flag)
|
||||
{
|
||||
this.Fleck_MakeFleckTick = 0;
|
||||
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
|
||||
|
||||
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 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();
|
||||
dataStatic.rotationRate = this.Fleck_Rotation.RandomInRange;
|
||||
dataStatic.velocityAngle = velocityAngle;
|
||||
dataStatic.velocitySpeed = randomInRange3;
|
||||
map.flecks.CreateFleck(dataStatic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.Destroyed) return;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse.Sound;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
@@ -20,58 +22,150 @@ namespace WulaFallenEmpire
|
||||
public float subExplosionSpread = 6f;
|
||||
public DamageDef subDamageDef;
|
||||
public SoundDef subSoundExplode;
|
||||
|
||||
public FleckDef tailFleckDef; // 用于配置拖尾特效的 FleckDef
|
||||
public float homingSpeed = 0.1f;
|
||||
public float initRotateAngle = 30f;
|
||||
public IntRange destroyTicksAfterLosingTrack = new IntRange(60, 120);
|
||||
public float speedChangePerTick;
|
||||
public FloatRange? speedRangeOverride;
|
||||
public float proximityFuseRange = 0f;
|
||||
}
|
||||
|
||||
public class Projectile_CruiseMissile : Projectile_Explosive
|
||||
{
|
||||
private CruiseMissileProperties settings;
|
||||
private bool flag2;
|
||||
private Vector3 Randdd;
|
||||
private Vector3 position2;
|
||||
public Vector3 ExPos;
|
||||
protected Vector3 exactPositionInt;
|
||||
public Vector3 curSpeed;
|
||||
public bool homing = true;
|
||||
private Sustainer ambientSustainer;
|
||||
private List<ThingComp> comps;
|
||||
private int ticksToDestroy = -1;
|
||||
|
||||
// Launch 方法的参数作为字段
|
||||
|
||||
// 拖尾特效相关字段
|
||||
private int Fleck_MakeFleckTick;
|
||||
public int Fleck_MakeFleckTickMax = 1;
|
||||
public IntRange Fleck_MakeFleckNum = new IntRange(1, 1);
|
||||
public FloatRange Fleck_Angle = new FloatRange(-180f, 180f);
|
||||
public FloatRange Fleck_Scale = new FloatRange(1f, 1f);
|
||||
public FloatRange Fleck_Speed = new FloatRange(0f, 0f);
|
||||
public FloatRange Fleck_Rotation = new FloatRange(-180f, 180f);
|
||||
|
||||
public override void SpawnSetup(Map map, bool respawningAfterLoad)
|
||||
{
|
||||
base.SpawnSetup(map, respawningAfterLoad);
|
||||
settings = def.GetModExtension<CruiseMissileProperties>() ?? new CruiseMissileProperties();
|
||||
this.ReflectInit();
|
||||
}
|
||||
|
||||
private void RandFactor()
|
||||
public override void Launch(Thing launcherParam, Vector3 originParam, LocalTargetInfo usedTargetParam, LocalTargetInfo intendedTargetParam, ProjectileHitFlags hitFlagsParam, bool preventFriendlyFireParam = false, Thing equipmentParam = null, ThingDef targetCoverDefParam = null)
|
||||
{
|
||||
// 减少垂直方向随机性,调整水平随机范围
|
||||
Randdd = new Vector3(
|
||||
Rand.Range(-3f, 3f), // 减小水平随机范围
|
||||
Rand.Range(8f, 12f), // 降低基础高度
|
||||
Rand.Range(-3f, 3f)
|
||||
);
|
||||
flag2 = true;
|
||||
this.launcher = launcherParam;
|
||||
this.origin = originParam;
|
||||
this.usedTarget = usedTargetParam;
|
||||
this.intendedTarget = intendedTargetParam;
|
||||
this.HitFlags = hitFlagsParam;
|
||||
this.preventFriendlyFire = preventFriendlyFireParam;
|
||||
this.equipment = equipmentParam;
|
||||
this.targetCoverDef = targetCoverDefParam;
|
||||
|
||||
this.exactPositionInt = origin.Yto0() + Vector3.up * this.def.Altitude;
|
||||
Vector3 normalized = (this.destination - origin).Yto0().normalized;
|
||||
float degrees = Rand.Range(-this.settings.initRotateAngle, this.settings.initRotateAngle);
|
||||
Vector2 vector = new Vector2(normalized.x, normalized.z);
|
||||
vector = vector.RotatedBy(degrees);
|
||||
Vector3 a = new Vector3(vector.x, 0f, vector.y);
|
||||
bool flag6 = this.settings.speedRangeOverride == null;
|
||||
if (flag6)
|
||||
{
|
||||
this.curSpeed = a * this.def.projectile.SpeedTilesPerTick;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.curSpeed = a * this.settings.speedRangeOverride.Value.RandomInRange;
|
||||
}
|
||||
this.ticksToImpact = int.MaxValue;
|
||||
this.lifetime = int.MaxValue;
|
||||
}
|
||||
|
||||
public Vector3 BPos(float t)
|
||||
protected void ReflectInit()
|
||||
{
|
||||
if (!flag2) RandFactor();
|
||||
if (NonPublicFields.Projectile_AmbientSustainer == null)
|
||||
{
|
||||
NonPublicFields.Projectile_AmbientSustainer = typeof(Projectile).GetField("ambientSustainer", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
if (NonPublicFields.ThingWithComps_comps == null)
|
||||
{
|
||||
NonPublicFields.ThingWithComps_comps = typeof(ThingWithComps).GetField("comps", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
if (NonPublicFields.ProjectileCheckForFreeInterceptBetween == null)
|
||||
{
|
||||
NonPublicFields.ProjectileCheckForFreeInterceptBetween = typeof(Projectile).GetMethod("CheckForFreeInterceptBetween", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
// 计算水平距离
|
||||
float horizontalDistance = Vector3.Distance(new Vector3(origin.x, 0, origin.z),
|
||||
new Vector3(destination.x, 0, destination.z));
|
||||
|
||||
// 动态调整控制点高度
|
||||
float arcHeight = Mathf.Clamp(horizontalDistance * 0.2f, 8f, 15f);
|
||||
|
||||
Vector3 a = origin + Vector3.forward * horizontalDistance * 0.2f + new Vector3(0f, arcHeight, 0f);
|
||||
Vector3 a2 = destination - Vector3.forward * horizontalDistance * 0.2f + new Vector3(0f, arcHeight, 0f);
|
||||
|
||||
return BezierCurve(origin, a, a2, destination, t);
|
||||
bool flag = !this.def.projectile.soundAmbient.NullOrUndefined();
|
||||
if (flag)
|
||||
{
|
||||
this.ambientSustainer = (Sustainer)NonPublicFields.Projectile_AmbientSustainer.GetValue(this);
|
||||
}
|
||||
this.comps = (List<ThingComp>)NonPublicFields.ThingWithComps_comps.GetValue(this);
|
||||
}
|
||||
|
||||
private Vector3 BezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
|
||||
public float GetHitChance(Thing thing)
|
||||
{
|
||||
float u = 1 - t;
|
||||
return u * u * u * p0
|
||||
+ 3 * u * u * t * p1
|
||||
+ 3 * u * t * t * p2
|
||||
+ t * t * t * p3;
|
||||
float num = this.settings.homingSpeed;
|
||||
bool flag = thing == null;
|
||||
float result;
|
||||
if (flag)
|
||||
{
|
||||
result = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pawn pawn = thing as Pawn;
|
||||
bool flag2 = pawn != null;
|
||||
if (flag2)
|
||||
{
|
||||
num *= Mathf.Clamp(pawn.BodySize, 0.5f, 1.5f);
|
||||
bool flag3 = pawn.GetPosture() > PawnPosture.Standing;
|
||||
if (flag3)
|
||||
{
|
||||
num *= 0.5f;
|
||||
}
|
||||
float num2 = 1f;
|
||||
switch (this.equipmentQuality)
|
||||
{
|
||||
case QualityCategory.Awful:
|
||||
num2 = 0.5f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Poor:
|
||||
num2 = 0.75f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Normal:
|
||||
num2 = 1f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Excellent:
|
||||
num2 = 1.1f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Masterwork:
|
||||
num2 = 1.2f;
|
||||
goto IL_DD;
|
||||
case QualityCategory.Legendary:
|
||||
num2 = 1.3f;
|
||||
goto IL_DD;
|
||||
}
|
||||
Log.Message("Unknown QualityCategory, returning default qualityFactor = 1");
|
||||
IL_DD:
|
||||
num *= num2;
|
||||
}
|
||||
else
|
||||
{
|
||||
num *= 1.5f * thing.def.fillPercent;
|
||||
}
|
||||
result = Mathf.Clamp(num, 0f, 1f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private IEnumerable<IntVec3> GetValidCells(Map map)
|
||||
@@ -136,43 +230,149 @@ namespace WulaFallenEmpire
|
||||
);
|
||||
}
|
||||
|
||||
protected override void DrawAt(Vector3 position, bool flip = false)
|
||||
public override Quaternion ExactRotation
|
||||
{
|
||||
position2 = BPos(DistanceCoveredFraction - 0.01f);
|
||||
ExPos = position = BPos(DistanceCoveredFraction);
|
||||
base.DrawAt(position, flip);
|
||||
get
|
||||
{
|
||||
return Quaternion.LookRotation(this.curSpeed);
|
||||
}
|
||||
}
|
||||
public override Vector3 ExactPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.exactPositionInt;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Tick()
|
||||
{
|
||||
if (intendedTarget.Thing is Pawn pawn && pawn.Spawned && !pawn.Destroyed)
|
||||
this.ThingWithCompsTick();
|
||||
this.lifetime--;
|
||||
if (this.settings.tailFleckDef != null)
|
||||
{
|
||||
if ((pawn.Dead || pawn.Downed) && DistanceCoveredFraction < 0.6f)
|
||||
this.Fleck_MakeFleckTick++;
|
||||
if (this.Fleck_MakeFleckTick >= this.Fleck_MakeFleckTickMax)
|
||||
{
|
||||
FindNextTarget(pawn.DrawPos);
|
||||
this.Fleck_MakeFleckTick = 0;
|
||||
for (int i = 0; i < this.Fleck_MakeFleckNum.RandomInRange; i++)
|
||||
{
|
||||
FleckMaker.Static(this.ExactPosition + Gen.RandomHorizontalVector(this.Fleck_Scale.RandomInRange / 2f), base.Map, this.settings.tailFleckDef, this.Fleck_Scale.RandomInRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool landed = this.landed;
|
||||
if (!landed)
|
||||
{
|
||||
Vector3 exactPosition = this.ExactPosition;
|
||||
this.ticksToImpact--;
|
||||
this.MovementTick();
|
||||
bool flag = !this.ExactPosition.InBounds(base.Map);
|
||||
if (flag)
|
||||
{
|
||||
base.Position = exactPosition.ToIntVec3();
|
||||
this.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 exactPosition2 = this.ExactPosition;
|
||||
object[] parameters = new object[]
|
||||
{
|
||||
exactPosition,
|
||||
exactPosition2
|
||||
};
|
||||
bool flag2 = (bool)NonPublicFields.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters);
|
||||
if (!flag2)
|
||||
{
|
||||
base.Position = this.ExactPosition.ToIntVec3();
|
||||
bool flag3 = this.ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && this.def.projectile.soundImpactAnticipate != null;
|
||||
if (flag3)
|
||||
{
|
||||
this.def.projectile.soundImpactAnticipate.PlayOneShot(this);
|
||||
}
|
||||
bool flag4 = this.ticksToImpact <= 0;
|
||||
if (flag4)
|
||||
{
|
||||
this.Impact(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool flag5 = this.ambientSustainer != null;
|
||||
if (flag5)
|
||||
{
|
||||
this.ambientSustainer.Maintain();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
destination = pawn.DrawPos;
|
||||
}
|
||||
base.Tick();
|
||||
}
|
||||
|
||||
private void FindNextTarget(Vector3 center)
|
||||
private void MovementTick()
|
||||
{
|
||||
var map = base.Map;
|
||||
if (map == null) return;
|
||||
|
||||
foreach (IntVec3 cell in GenRadial.RadialCellsAround(IntVec3.FromVector3(center), 7f, true))
|
||||
if (this.homing)
|
||||
{
|
||||
if (!cell.InBounds(map)) continue;
|
||||
|
||||
Pawn target = cell.GetFirstPawn(map);
|
||||
if (target != null && target.Faction.HostileTo(launcher?.Faction))
|
||||
if (this.intendedTarget != null && this.intendedTarget.Thing != null)
|
||||
{
|
||||
intendedTarget = target;
|
||||
Vector3 vector = (this.intendedTarget.Thing.DrawPos - this.exactPositionInt).normalized;
|
||||
this.curSpeed = Vector3.RotateTowards(this.curSpeed, vector * this.curSpeed.magnitude, this.settings.homingSpeed, 0f);
|
||||
}
|
||||
else if (this.ticksToDestroy == -1)
|
||||
{
|
||||
this.ticksToDestroy = this.settings.destroyTicksAfterLosingTrack.RandomInRange;
|
||||
}
|
||||
}
|
||||
if (this.ticksToDestroy > 0)
|
||||
{
|
||||
this.ticksToDestroy--;
|
||||
if (this.ticksToDestroy == 0)
|
||||
{
|
||||
this.Destroy(DestroyMode.Vanish);
|
||||
return;
|
||||
}
|
||||
}
|
||||
intendedTarget = CellRect.CenteredOn(IntVec3.FromVector3(center), 7).RandomCell;
|
||||
if (this.settings.speedChangePerTick != 0f)
|
||||
{
|
||||
this.curSpeed = this.curSpeed.normalized * (this.curSpeed.magnitude + this.settings.speedChangePerTick);
|
||||
}
|
||||
if (this.settings.proximityFuseRange > 0f)
|
||||
{
|
||||
if (this.intendedTarget != null && this.intendedTarget.Thing != null && (this.intendedTarget.Thing.DrawPos - this.exactPositionInt).magnitude < this.settings.proximityFuseRange)
|
||||
{
|
||||
this.Impact(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.exactPositionInt += this.curSpeed;
|
||||
}
|
||||
|
||||
protected void ThingWithCompsTick()
|
||||
{
|
||||
if (this.comps != null)
|
||||
{
|
||||
for (int i = 0; i < this.comps.Count; i++)
|
||||
{
|
||||
this.comps[i].CompTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look<Vector3>(ref this.exactPositionInt, "exactPosition", default(Vector3), false);
|
||||
Scribe_Values.Look<Vector3>(ref this.curSpeed, "curSpeed", default(Vector3), false);
|
||||
Scribe_Values.Look<bool>(ref this.homing, "homing", true, false);
|
||||
Scribe_Values.Look<int>(ref this.ticksToDestroy, "ticksToDestroy", -1, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static class NonPublicFields
|
||||
{
|
||||
public static FieldInfo Projectile_AmbientSustainer;
|
||||
public static FieldInfo ThingWithComps_comps;
|
||||
public static MethodInfo ProjectileCheckForFreeInterceptBetween;
|
||||
}
|
||||
}
|
||||
@@ -124,6 +124,10 @@
|
||||
<Compile Include="NeedDefExtension_Energy.cs" />
|
||||
<Compile Include="Projectile_WulaPenetrating.cs" />
|
||||
<Compile Include="Projectile_WulaBeam.cs" />
|
||||
<Compile Include="Projectile_Homing.cs" />
|
||||
<Compile Include="Projectile_Homing_Explosive.cs" />
|
||||
<Compile Include="ModExtension_Cone.cs" />
|
||||
<Compile Include="HomingProjectileDef.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PsychicRitual_TechOffering.cs" />
|
||||
<Compile Include="PsychicRitualDef_AddHediff.cs" />
|
||||
|
||||
Reference in New Issue
Block a user