Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIWS v2 #3534

Open
wants to merge 118 commits into
base: Development
Choose a base branch
from
Open

CIWS v2 #3534

wants to merge 118 commits into from

Conversation

MaxDorob
Copy link
Contributor

@MaxDorob MaxDorob commented Nov 5, 2024

Additions

Describe new functionality added by your code

  • Multi verb turret
  • CIWS turret
  • Projectile, skyfaller CIWS verb (and verb that targets things with CompCIWSTarget childs)
  • Trajectory workers (mostly necessary because we need to know the trajectory before we launch projectile)
    • LerpedTrajectoryWorker - original trajectory
    • BallisticsTrajectoryWorker - non-lerped trajectory worker, mostly moved code from ProjectileCE
    • SmartRocketTrajectoryWorker - trajectory worker for projectile that chase target
  • ProjectilePropertiesCE
    • speedGain (float)
    • collideDistance and impactChance (float, used for CIWS projectile)
    • CIWSVersion (ThingDef, used to swap projectiles when CIWS verbs used)
    • trajectoryWorker (Type, if not specified LerpedTrajectoryWorker is used (BallisticsTrajectoryWorker if lerpPosition false))

Changes

Describe adjustments to existing features made in this merge

  • Changed some base verb methods
  • Moved some trajectory work to worker class (because we need to know trajectory before launch)

References

ToDo

  • Skyfaller verb targeting
  • TurretTop aim line
  • Improve accuracy
  • Unlock rotation in mid burst for CIWS
  • CompCIWSTarget for skyfaller (similar to VerbCIWSSkyfaller, but for third party skyfaller should be intercepted)
  • Fix CIWS projectile hits ground
  • Fix incorrect direction for first CIWS shot
  • Fix VFX position on intercepted
  • IgnoredDefs
  • Hold fire option
  • VFX
  • Smart rockets trajectory worker
  • Performance
  • Code cleanup
  • Delete/move example defs
  • Move verbs to correct folder

Testing

Check tests you have performed:

  • Compiles without warnings
  • Game runs without errors
  • Playtested a colony (tested few variants of CIWS and other weapons)

Examples

Turrets should use projectiles with thingClass ProjectileCE_CIWS.
You can specify CIWS version in def with CIWSVersion node like this:

<ThingDef Name="Bullet_8x35mmCharged" ParentName="Base8x35mmChargedBullet">
		<defName>Bullet_8x35mmCharged</defName>
		<label>8x35mm Charged bullet</label>
		<projectile Class="CombatExtended.ProjectilePropertiesCE">
      <CIWSVersion>Bullet_8x35mmChargedCIWS</CIWSVersion>
			<damageAmountBase>19</damageAmountBase>
			<secondaryDamage>
				<li>
					<def>Bomb_Secondary</def>
					<amount>6</amount>
				</li>
			</secondaryDamage>
			<armorPenetrationSharp>16</armorPenetrationSharp>
			<armorPenetrationBlunt>57.6</armorPenetrationBlunt>
		</projectile>
	</ThingDef>
	...

  <ThingDef Name="Bullet_8x35mmChargedCIWS" ParentName="Base8x35mmChargedBullet">
    <defName>Bullet_8x35mmChargedCIWS</defName>
    <thingClass>CombatExtended.ProjectileCE_CIWS</thingClass>
    <label>8x35mm Charged bullet</label>
    <projectile Class="CombatExtended.ProjectilePropertiesCE">
      <damageAmountBase>19</damageAmountBase>
      <secondaryDamage>
        <li>
          <def>Bomb_Secondary</def>
          <amount>6</amount>
        </li>
      </secondaryDamage>
      <armorPenetrationSharp>16</armorPenetrationSharp>
      <armorPenetrationBlunt>57.6</armorPenetrationBlunt>
      <trajectoryWorker>CombatExtended.LerpedTrajectoryWorker_ExactPosDrawing</trajectoryWorker>
    </projectile>
  </ThingDef>

CIWS must use Building_CIWS_CE as thingClass

<!--=============== Blaster CIWS ===============-->

	<ThingDef ParentName="TurretAutoBase">
		<defName>CIWS_Blaster</defName>
    <thingClass>CombatExtended.Building_CIWS_CE</thingClass>
		<label>charge blaster CIWS</label>
		<constructionSkillPrerequisite>8</constructionSkillPrerequisite>
		<graphicData>
			<texPath>Things/Building/Turrets/MachineGunBase</texPath>
			<shadowData>
				<volume>(0.27,0.25,0.27)</volume>
				<offset>(0,0,0)</offset>
			</shadowData>
		</graphicData>
		<uiIconPath>UI/Icons/Turrets/ChargeBlaster_uiIcon</uiIconPath>
		<statBases>
			<WorkToBuild>23000</WorkToBuild>
			<MaxHitPoints>150</MaxHitPoints>
			<Mass>20</Mass>
			<Bulk>25</Bulk>
			<AimingAccuracy>0.75</AimingAccuracy>
			<ShootingAccuracyTurret>1.25</ShootingAccuracyTurret>
			<NightVisionEfficiency>0.5</NightVisionEfficiency>
		</statBases>
		<techLevel>Spacer</techLevel>
		<comps>
			<li Class="CompProperties_Power">
				<compClass>CompPowerTrader</compClass>
				<basePowerConsumption>400</basePowerConsumption>
			</li>
		</comps>
		<description>Automatic turret equipped with a charge blaster.</description>
		<costList>
			<Steel>125</Steel>
			<Plasteel>40</Plasteel>
			<ComponentIndustrial>6</ComponentIndustrial>
			<ComponentSpacer>1</ComponentSpacer>
		</costList>
		<building>
			<turretGunDef>Gun_CIWSBlasterTurret</turretGunDef>
			<ai_combatDangerous>true</ai_combatDangerous>
		</building>
		<designatorDropdown>CE_AutoTurrets</designatorDropdown>
		<placeWorkers>
			<li>PlaceWorker_TurretTop</li>
			<li>PlaceWorker_ShowTurretRadius</li>
		</placeWorkers>
		<researchPrerequisites>
			<li>CE_ChargeTurret</li>
		</researchPrerequisites>
		<minifiedDef>MinifiedThing</minifiedDef>
	</ThingDef>

Gun of such CIWS may have few attack verbs unlike usual turret.
Usual attack verb (non CIWS) must be specified first (otherwise turret may ignore it).
Also you may specify CompVerbDisabler in comps to make CIWS disablable.
Example of such gun:

	<ThingDef ParentName="BaseAutoTurretGun">
		<defName>Gun_CIWSBlasterTurret</defName>
		<label>blaster turret gun</label>
		<graphicData>
			<texPath>Things/Building/Turrets/BlasterTurret_Top</texPath>
			<graphicClass>Graphic_Single</graphicClass>
		</graphicData>
		<description>Charge blaster attached to a turret mount.</description>
		<soundInteract>Interact_ChargeRifle</soundInteract>
		<statBases>
			<SightsEfficiency>1</SightsEfficiency>
			<ShotSpread>0.06</ShotSpread>
			<SwayFactor>0.86</SwayFactor>
			<RangedWeapon_Cooldown>0.36</RangedWeapon_Cooldown>
			<Mass>10</Mass>
		</statBases>
		<verbs>
			<li Class="CombatExtended.VerbPropertiesCE">
				<recoilAmount>0.90</recoilAmount>
				<verbClass>CombatExtended.Verb_ShootCE</verbClass>
				<hasStandardCommand>true</hasStandardCommand>
				<defaultProjectile>Bullet_8x35mmCharged</defaultProjectile>
				<warmupTime>1.3</warmupTime>
				<range>55</range>
				<ticksBetweenBurstShots>5</ticksBetweenBurstShots>
				<burstShotCount>10</burstShotCount>
				<soundCast>Shot_ChargeBlaster</soundCast>
				<soundCastTail>GunTail_Heavy</soundCastTail>
				<muzzleFlashScale>9</muzzleFlashScale>
				<recoilPattern>Mounted</recoilPattern>
			</li>
      <li Class="CombatExtended.VerbProperties_CIWSProjectile">
        <verbClass>CombatExtended.VerbCIWSProjectile</verbClass>
        <recoilAmount>0.90</recoilAmount>
        <hasStandardCommand>true</hasStandardCommand>
        <defaultProjectile>Bullet_8x35mmCharged</defaultProjectile>
        <warmupTime>0.4</warmupTime>
        <range>105</range>
        <ticksBetweenBurstShots>5</ticksBetweenBurstShots>
        <burstShotCount>10</burstShotCount>
        <soundCast>Shot_ChargeBlaster</soundCast>
        <soundCastTail>GunTail_Heavy</soundCastTail>
        <muzzleFlashScale>9</muzzleFlashScale>
        <recoilPattern>Mounted</recoilPattern>
        <holdFireLabel>HoldCloseInProjectilesFire</holdFireLabel>
        <holdFireDesc>HoldCloseInProjectilesFireDesc</holdFireDesc>
      </li>
      <li Class="CombatExtended.VerbProperties_CIWSSkyfaller">
        <verbClass>CombatExtended.VerbCIWSSkyfaller</verbClass>
        <recoilAmount>0.90</recoilAmount>
        <hasStandardCommand>true</hasStandardCommand>
        <defaultProjectile>Bullet_8x35mmCharged</defaultProjectile>
        <warmupTime>0.4</warmupTime>
        <range>105</range>
        <ticksBetweenBurstShots>5</ticksBetweenBurstShots>
        <burstShotCount>10</burstShotCount>
        <soundCast>Shot_ChargeBlaster</soundCast>
        <soundCastTail>GunTail_Heavy</soundCastTail>
        <muzzleFlashScale>9</muzzleFlashScale>
        <recoilPattern>Mounted</recoilPattern>
        <holdFireLabel>HoldCloseInSkyfallersFire</holdFireLabel>
      </li>
		</verbs>
		<comps>
			<li Class="CombatExtended.CompProperties_AmmoUser">
				<magazineSize>100</magazineSize>
				<reloadTime>7.8</reloadTime>
				<ammoSet>AmmoSet_8x35mmCharged</ammoSet>
			</li>
      <li>
        <compClass>CombatExtended.CompVerbDisabler</compClass>
      </li>
		</comps>
	</ThingDef>

Example of smart rocket, that use specific trajectory worker

	<ThingDef Name="Base50mmRocket" ParentName="BaseExplosiveBullet" Abstract="true">
		...
		<projectile Class="CombatExtended.ProjectilePropertiesCE">
			...
      <ballisticCoefficient>1.0</ballisticCoefficient>
      <mass>1.0</mass>
      <diameter>2</diameter>
		</projectile>
	</ThingDef>

	<ThingDef ParentName="Base50mmRocket">
		<defName>Bullet_50mmRocket_HE</defName>
		...
		<projectile Class="CombatExtended.ProjectilePropertiesCE">
                 ...
      <CIWSVersion>Bullet_50mmRocket_HE_CIWS</CIWSVersion>
		</projectile>
		...
	</ThingDef>

  <ThingDef ParentName="Base50mmRocket">
    <defName>Bullet_50mmRocket_HE_CIWS</defName>
    <thingClass>CombatExtended.ProjectileCE_CIWS</thingClass>
    <label>50mm rocket (HE)</label>
    <graphicData>
      <texPath>Things/Projectile/Rocket/70mmAPKWS</texPath>
      <graphicClass>Graphic_Single</graphicClass>
      <drawSize>0.70</drawSize>
    </graphicData>
    <projectile Class="CombatExtended.ProjectilePropertiesCE">
      <damageDef>Bomb</damageDef>
      <damageAmountBase>147</damageAmountBase>
      <explosionRadius>0</explosionRadius>
      <trajectoryWorker>CombatExtended.SmartRocketTrajectoryWorker</trajectoryWorker>
      <speed>120</speed>
      <speedGain>32</speedGain>
    </projectile>
    ...
  </ThingDef>
  
  <ThingDef>
     <defName>Turret_RocketswarmLauncher</defName>
     <thingClass>CombatExtended.Building_CIWS_CE</thingClass>
     ...
  </ThingDef>

@MaxDorob MaxDorob marked this pull request as ready for review November 28, 2024 18:29
@MaxDorob MaxDorob requested review from a team as code owners November 28, 2024 18:29
Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12074143163.zip

Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12074185893.zip

Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12087826645.zip

Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12087876448.zip

Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12089209302.zip

Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12097015705.zip

Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12097281167.zip

Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12097480056.zip

Copy link

You can download the rebuilt assembly for this PR here: https://combatextended.lp-programming.com/CombatExtended-12097511410.zip

float speedGain,
float maxSpeed,
int flightTicks)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: It might simplify things to pack all these parameters into a ref struct and pass that around instead. Right now the full parameter list has to be spelled out in a lot of places.

Pawn pawn = thing2 as Pawn;
if (pawn != null)
{
if (pawn.RaceProps.Humanlike)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (thing2 is Pawn pawn && pawn.RaceProps.Humanlike)

private Thing TryDropThing(Thing thing, Map map, IntVec3 position)
{
var contents = (parent as IActiveDropPod)?.Contents;
Rot4 rot = (contents?.setRotation != null) ? contents.setRotation.Value : Rot4.North;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could return early if contents are null here and spare a lot of null checks down the line

return targetHeight;
}
protected virtual bool LockRotationAndAngle => numShotsFired > 0;
public virtual void ShiftTarget(ShiftVecReport report, bool calculateMechanicalOnly = false, bool isInstant = false, bool midBurst = false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: midBurst is now unused and could be removed, that could also allow getting rid of the override.

var _target = Targets.Where(x => Props.Interceptable(x.def) && !Props.Ignored.Contains(x.def) && !Turret.IgnoredDefsSettings.Contains(x.def)).Where(x => !IsFriendlyTo(x)).FirstOrDefault(t =>
{
var verb = this;
if (Caster.Map.GetComponent<TurretTracker>().CIWS.Any(turret => turret.currentTargetInt.Thing == t) || ProjectileCE_CIWS.ProjectilesAt(Caster.Map).Any(x => x.intendedTarget.Thing == t))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: may need to profile this to ensure the linq isn't an issue

}
targetList.Add(parent);
}
public override void PostDeSpawn(Map map)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: does this cover the case where the map itself gets reaped (incident maps)?

return Targets(map).Where(x => x.HasComp<T>());
}

public CompProperties_CIWSTarget Props => props as CompProperties_CIWSTarget;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: props getters should always use a (cast) expression since a type mismatch here would be an unrecoverable error. that also reduces the chance of people then treating the props as nullable and adding unnecessary null checks elsewhere.

}
return targetHeight;
}
protected virtual bool LockRotationAndAngle => numShotsFired > 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the previous name MidBurst is I think more descriptive since this property is used also in shootline checks where it has nothing to do with ballistics. Also this should move up to live alongside the other property declarations.

@@ -969,43 +1046,16 @@ public override bool TryCastShot()
// 6: Interruptible -> stop shooting
// 7: Not interruptible -> shoot along previous line
// 8: else -> stop
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: these should move into the newly extracted method

}
else // We cannot hit the current target
{
if (midBurst) // Case 2,3,6,7
if (!KeepBurstOnNoShootLine(suppressing, out shootLine))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: merge into enclosing block

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Download in Comments This PR has a zipfile download available.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants