Skip to content
2 changes: 2 additions & 0 deletions Languages/English/Keyed/Messages.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
<CE_Message_CounterShelling>Artillery fire incoming from {0} ({1}).</CE_Message_CounterShelling>
<CE_Message_CounterRaid>A group from {0} is planning to raid {1} at {2} soon in retaliation for recent events.</CE_Message_CounterRaid>

<CE_Message_ArtilleryBadLayer>Cannot fire on different layer tile with this piece of artillery.</CE_Message_ArtilleryBadLayer>

</LanguageData>
2 changes: 1 addition & 1 deletion Source/BetterTurretsCompat/BetterTurretsCompat.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.6.4543" GeneratePathProperty="true" />
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.6.4633" GeneratePathProperty="true" />
<PackageReference Include="Lib.Harmony" Version="2.3.6" ExcludeAssets="runtime" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion Source/CombatExtended/CombatExtended.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.6.4543" GeneratePathProperty="true" />
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.6.4633" GeneratePathProperty="true" />
<PackageReference Include="Lib.Harmony" Version="2.3.6" ExcludeAssets="runtime" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Verse;

namespace CombatExtended;

public class OrbitalTurretExtension : DefModExtension
{
public float interLayerPrecisionBonusFactor = 1;
public bool isMarkMandatory = false;
}
333 changes: 211 additions & 122 deletions Source/CombatExtended/CombatExtended/Gizmos/Command_ArtilleryTarget.cs

Large diffs are not rendered by default.

52 changes: 31 additions & 21 deletions Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1396,27 +1396,7 @@ public override void Tick()
{
if (globalTargetInfo.IsValid)
{
TravelingShell shell = (TravelingShell)WorldObjectMaker.MakeWorldObject(CE_WorldObjectDefOf.TravelingShell);
if (launcher?.Faction != null)
{
shell.SetFaction(launcher.Faction);
}
shell.Tile = Map.Tile;
shell.SpawnSetup();
Find.World.worldObjects.Add(shell);
shell.launcher = launcher;
shell.equipmentDef = equipmentDef;
shell.globalSource = new GlobalTargetInfo(OriginIV3, Map);
shell.globalSource.tileInt = Map.Tile;
shell.globalSource.mapInt = Map;
shell.globalSource.worldObjectInt = Map.Parent;
shell.shellDef = def;
shell.globalTarget = globalTargetInfo;
if (!shell.TryTravel(Map.Tile, globalTargetInfo.Tile))
{
Log.Error($"CE: Travling shell {this.def} failed to launch!");
shell.Destroy();
}
CreateShellWorldObject();
}
Destroy();
return;
Expand Down Expand Up @@ -1473,6 +1453,36 @@ public override void Tick()
}
}

protected void CreateShellWorldObject()
{
TravelingShell shell = (TravelingShell)WorldObjectMaker.MakeWorldObject(CE_WorldObjectDefOf.TravelingShell);
if (launcher?.Faction != null)
{
shell.SetFaction(launcher.Faction);
}
shell.Tile = Map.Tile;
shell.SpawnSetup();
Find.World.worldObjects.Add(shell);
shell.launcher = launcher;
shell.equipmentDef = equipmentDef;
shell.globalSource = new GlobalTargetInfo(OriginIV3, Map);
shell.globalSource.tileInt = Map.Tile;
shell.globalSource.mapInt = Map;
shell.globalSource.worldObjectInt = Map.Parent;
shell.shellDef = def;
shell.globalTarget = globalTargetInfo;
if (Props.shellingProps?.arrivedAtSameProps ?? false)
{
shell.arrivedShotHeight = shotHeight;
shell.arrivedShotSpeed = shotSpeed;
}
if (!shell.TryTravel(Map.Tile, globalTargetInfo.Tile))
{
Log.Error($"CE: Travling shell {this.def} failed to launch!");
shell.Destroy();
}
}

/// <summary>
/// Draws projectile if at least a tick away from caster (or always if no caster)
/// </summary>
Expand Down
89 changes: 86 additions & 3 deletions Source/CombatExtended/CombatExtended/ShellingUtility.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;
using CombatExtended.WorldObjects;

namespace CombatExtended;
public static class ShellingUtility
Expand All @@ -16,6 +14,91 @@ public static class ShellingUtility
private static ProjectilePropertiesCE props;
private static DamageDef projectileDamageDef;

private struct DistanceCache
{
public PlanetTile startingTile;
public PlanetTile destinationTile;
public int distance;
}
private static DistanceCache distanceCache = new DistanceCache();

public static int GetDistancePlanetTiles(PlanetTile startingTile, PlanetTile destinationTile, int maxDist = int.MaxValue)
{
if (distanceCache.startingTile == startingTile && distanceCache.destinationTile == destinationTile)
{
return distanceCache.distance;
}

distanceCache.startingTile = startingTile;
distanceCache.destinationTile = destinationTile;

distanceCache.distance =
(int)(Find.WorldGrid.TraversalDistanceBetween(startingTile, destinationTile, true, maxDist, true) * destinationTile.LayerDef.rangeDistanceFactor);

return distanceCache.distance;
}

private struct RadiusCache
{
public PlanetTile realCenterTile;
public int radius;
}
private static Dictionary<int, RadiusCache> radiusCache = new Dictionary<int, RadiusCache>();

public static void ClearRadiusCache()
{
radiusCache.Clear();
}

public static void CachedDrawTurretRadiusRing(PlanetTile center, int radius, bool canShootOtherLayers = false)
{
PlanetTile realCenterTile;
int realRadius;
RadiusCache cache;

// Try to find cache.
bool cacheFound = radiusCache.TryGetValue(center.tileId, out cache);

// If the result is not on the current layer, we need to recalculate it
if (cacheFound && cache.realCenterTile.Layer != PlanetLayer.Selected)
{
if (!canShootOtherLayers)
{
// Don't display radius
return;
}

cacheFound = false;
radiusCache.Remove(center.tileId);
}

// Use cached values
if (cacheFound)
{
realCenterTile = cache.realCenterTile;
realRadius = cache.radius;
}
else
{
// We cache these operations, because there is no need to overcharge the update.
realCenterTile = center;
float rangeDistanceFactor = PlanetLayer.Selected.Def.rangeDistanceFactor;
if (center.Layer != PlanetLayer.Selected)
{
realCenterTile = PlanetLayer.Selected.GetClosestTile_NewTemp(center);
}
realRadius = Mathf.FloorToInt(radius / rangeDistanceFactor);

// Add result to cache
radiusCache.Add(center.tileId, new RadiusCache()
{
realCenterTile = realCenterTile,
radius = realRadius
});
}
GenDraw.DrawWorldRadiusRing(realCenterTile, realRadius);
}

public static IntVec3 FindRandomImpactCell(Map map, ThingDef shellDef = null)
{
ShellingUtility.map = map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class Building_TurretGunCE : Building_Turret
private CompAmmoUser compAmmo = null;
private CompFireModes compFireModes = null;
private CompChangeableProjectile compChangeable = null;
private OrbitalTurretExtension orbitalTurretExtension = null;
public bool isReloading = false;
private int ticksUntilAutoReload = 0;
private bool everSpawned = false;
Expand Down Expand Up @@ -156,6 +157,19 @@ public CompFireModes CompFireModes
return compFireModes;
}
}

public OrbitalTurretExtension OrbitalTurretExtension
{
get
{
if (orbitalTurretExtension == null && Gun != null)
{
orbitalTurretExtension = Gun.def.GetModExtension<OrbitalTurretExtension>();
}
return orbitalTurretExtension;
}
}

private ProjectilePropertiesCE ProjectileProps => (ProjectilePropertiesCE)Projectile?.projectile;
public float MaxWorldRange => ProjectileProps?.shellingProps.range ?? -1f;
public bool EmptyMagazine => CompAmmo?.EmptyMagazine ?? false;
Expand Down Expand Up @@ -676,7 +690,7 @@ public bool TryAttackWorldTarget(GlobalTargetInfo targetInfo, LocalTargetInfo lo
{
ResetCurrentTarget();
ResetForcedTarget();
int distanceToTarget = Find.WorldGrid.TraversalDistanceBetween(Map.Tile, targetInfo.Tile, true, maxDist: (int)(this.MaxWorldRange * 1.5f));
int distanceToTarget = ShellingUtility.GetDistancePlanetTiles(Map.Tile, targetInfo.Tile, (int)(MaxWorldRange * 1.5f));
if (distanceToTarget > MaxWorldRange)
{
return false;
Expand All @@ -698,8 +712,8 @@ public bool TryAttackWorldTarget(GlobalTargetInfo targetInfo, LocalTargetInfo lo

public virtual void TryOrderAttackWorldTile(GlobalTargetInfo targetInf, IntVec3? cell = null)
{
int startingTile = Map.Tile;
int destinationTile = targetInf.Tile;
PlanetTile startingTile = Map.Tile;
PlanetTile destinationTile = targetInf.Tile;

Vector3 direction = (Find.WorldGrid.GetTileCenter(startingTile) - Find.WorldGrid.GetTileCenter(destinationTile)).normalized;
Vector3 shotPos = DrawPos.Yto0();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ public virtual ShiftVecReport ShiftVecReportFor(GlobalTargetInfo target)
return null;
}
// multiplie by 250 to emulate cells
int distanceToTarget = Find.WorldGrid.TraversalDistanceBetween(target.Tile, caster.Map.Tile, true);
int distanceToTarget = Find.WorldGrid.TraversalDistanceBetween(target.Tile, caster.Map.Tile, true, int.MaxValue, true);

LocalTargetInfo localTarget = new LocalTargetInfo();
localTarget.cellInt = target.Cell;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using VEF;
using Verse;
using Verse.Sound;

Expand Down Expand Up @@ -29,12 +30,12 @@ public class Verb_ShootMortarCE : Verb_ShootCE
/// <summary>
/// Wether the target is marked
/// </summary>
private bool targetHasMarker = false;
protected bool targetHasMarker = false;

// for global target only
//
private int startingTile;
private int destinationTile;
private PlanetTile startingTile;
private PlanetTile destinationTile;
private int globalDistance;
private Vector3 direction;
private new int numShotsFired;
Expand Down Expand Up @@ -112,7 +113,20 @@ public override ShiftVecReport ShiftVecReportFor(GlobalTargetInfo target)
return null;
}
ShiftVecReport report = base.ShiftVecReportFor(target);
report.circularMissRadius = GetGlobalMissRadiusForDist(report.shotDist);

float shotDist = report.shotDist;

// Shelling across layers
if (globalSourceInfo.Tile.Layer != globalTargetInfo.Tile.Layer)
{
OrbitalTurretExtension orbitalTurretExtension = caster.def.GetModExtension<OrbitalTurretExtension>();
if (orbitalTurretExtension != null && orbitalTurretExtension.interLayerPrecisionBonusFactor != 0)
{
shotDist = shotDist / orbitalTurretExtension.interLayerPrecisionBonusFactor;
}
}

report.circularMissRadius = GetGlobalMissRadiusForDist(shotDist);
report.weatherShift = (1f - globalTargetInfo.Map.weatherManager.CurWeatherAccuracyMultiplier) * 1.5f + (1 - globalSourceInfo.Map.weatherManager.CurWeatherAccuracyMultiplier) * 0.5f;

ArtilleryMarker marker = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ public class TravelingRaycast : TravelingShell
public float aperatureSize;
public Thing equipement;

protected override void LaunchProjectile(IntVec3 sourceCell, LocalTargetInfo target, Map map, float shotSpeed = 20, float shotHeight = 200)
protected override void LaunchProjectile(IntVec3 sourceCell, LocalTargetInfo target, Map map)
{
Vector3 source = new Vector3(sourceCell.x, shotHeight, sourceCell.z);
Vector3 source = new Vector3(sourceCell.x, arrivedShotHeight, sourceCell.z);
Vector3 targetPos = target.Cell.ToVector3Shifted();

ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(shellDef);
ProjectilePropertiesCE pprops = projectile.def.projectile as ProjectilePropertiesCE;
float shotRotation = pprops.TrajectoryWorker.ShotRotation(pprops, source, targetPos);
float shotAngle = pprops.TrajectoryWorker.ShotAngle(pprops, source, targetPos, shotSpeed);
float shotAngle = pprops.TrajectoryWorker.ShotAngle(pprops, source, targetPos, arrivedShotSpeed);

projectile.canTargetSelf = false;
projectile.Position = sourceCell;
Expand All @@ -34,14 +34,14 @@ protected override void LaunchProjectile(IntVec3 sourceCell, LocalTargetInfo tar
return;
}

float tsa = verbToUse.AdjustShotHeight(launcher, target, ref shotHeight);
float tsa = verbToUse.AdjustShotHeight(launcher, target, ref arrivedShotHeight);
projectile.RayCast(launcher,
verbToUse.verbProps,
new Vector2(source.x, source.z),
shotAngle,
shotRotation,
shotHeight + tsa,
shotSpeed,
arrivedShotHeight + tsa,
arrivedShotSpeed,
spreadDegrees,
aperatureSize,
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class TravelingShell : TravelingThing
public ThingDef equipmentDef;
public ThingDef shellDef;
public Thing launcher;
public float arrivedShotHeight = 200f;
public float arrivedShotSpeed = 55f;
private Texture2D expandingIcon;
public override Texture2D ExpandingIcon
{
Expand Down Expand Up @@ -44,6 +46,7 @@ public override bool ExpandingIconFlipHorizontal
{
get => GenWorldUI.WorldToUIPosition(Start).x > GenWorldUI.WorldToUIPosition(End).x;
}

public bool IsInstant => (shellDef.projectile as ProjectilePropertiesCE).isInstant;

public override float ExpandingIconRotation
Expand Down Expand Up @@ -97,7 +100,7 @@ public override string GetDescription()
protected override void Arrived()
{
int tile = Tile;
foreach (WorldObject worldObject in Find.World.worldObjects.ObjectsAt(tile))
foreach (WorldObject worldObject in Find.World.worldObjects.ObjectsAt(Tile))
{
if (TryShell(worldObject))
{
Expand Down Expand Up @@ -145,20 +148,20 @@ private bool TryShell(WorldObject worldObject)
return shelled;
}

protected virtual void LaunchProjectile(IntVec3 sourceCell, LocalTargetInfo target, Map map, float shotSpeed = 20, float shotHeight = 200)
protected virtual void LaunchProjectile(IntVec3 sourceCell, LocalTargetInfo target, Map map)
{
Vector3 source = new Vector3(sourceCell.x, shotHeight, sourceCell.z);
Vector3 source = new Vector3(sourceCell.x, arrivedShotHeight, sourceCell.z);
Vector3 targetPos = target.Cell.ToVector3Shifted();

ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(shellDef);
ProjectilePropertiesCE pprops = projectile.def.projectile as ProjectilePropertiesCE;
float shotRotation = pprops.TrajectoryWorker.ShotRotation(pprops, source, targetPos);
float shotAngle = pprops.TrajectoryWorker.ShotAngle(pprops, source, targetPos, shotSpeed);
float shotAngle = pprops.TrajectoryWorker.ShotAngle(pprops, source, targetPos, arrivedShotSpeed);

projectile.canTargetSelf = false;
projectile.Position = sourceCell;
projectile.SpawnSetup(map, false);
projectile.Launch(launcher, new Vector2(source.x, source.z), shotAngle, shotRotation, shotHeight, shotSpeed);
projectile.Launch(launcher, new Vector2(source.x, source.z), shotAngle, shotRotation, arrivedShotHeight, arrivedShotSpeed);
//projectile.cameraShakingInit = Rand.Range(0f, 2f);
}

Expand Down
Loading
Loading