I made a custom AI script for a ship system and I'm 99% sure its the cause of null reference crashes I'm having in combat. Here is the log:
271369 [Thread-3] ERROR com.fs.starfarer.combat.CombatMain - java.lang.NullPointerException
java.lang.NullPointerException
at com.fs.starfarer.combat.ai.o0OO.o00000(Unknown Source)
at com.fs.starfarer.combat.ai.BasicShipAI.advance(Unknown Source)
at com.fs.starfarer.combat.CombatEngine.advanceInner(Unknown Source)
at com.fs.starfarer.combat.CombatEngine.advance(Unknown Source)
at com.fs.starfarer.combat.CombatState.traverse(Unknown Source)
at com.fs.state.AppDriver.begin(Unknown Source)
at com.fs.starfarer.combat.CombatMain.main(Unknown Source)
at com.fs.starfarer.StarfarerLauncher.o00000(Unknown Source)
at com.fs.starfarer.StarfarerLauncher$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
And here is the class
//
// Decompiled by Procyon v0.5.36
//
package data.scripts.ai.systems;
import com.fs.starfarer.api.Global;
import org.lazywizard.lazylib.MathUtils;
import org.lwjgl.util.vector.Vector2f;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.util.IntervalUtil;
import com.fs.starfarer.api.combat.ShipSystemAPI;
import com.fs.starfarer.api.combat.ShipwideAIFlags;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ShipSystemAIScript;
import com.fs.starfarer.api.util.Misc;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
public class sfb_CloakingDevice_ai_simple implements ShipSystemAIScript
{
private ShipAPI ship;
private ShipwideAIFlags flags;
private ShipSystemAPI system;
private final IntervalUtil tracker;
private float cloakDuration = 0f;
public sfb_CloakingDevice_ai_simple() {
this.tracker = new IntervalUtil(0.75f, 1.0f);
}
public void init(final ShipAPI ship, final ShipSystemAPI system, final ShipwideAIFlags flags, final CombatEngineAPI engine) {
this.ship = ship;
this.flags = flags;
this.system = system;
}
public void advance(final float amount, final Vector2f missileDangerDir, final Vector2f collisionDangerDir, final ShipAPI target) {
if (this.ship == null) {
return;
}
this.tracker.advance(amount);
this.cloakDuration += amount;
boolean shouldAttack = false;
ShipAPI closestEnemy = null;
if (this.tracker.intervalElapsed()) {
if (this.system.isActive()) {
closestEnemy = FindClosestNonFighterShipWithOwner(this.ship, 1);
if (closestEnemy != null) {
if (!MathUtils.isWithinRange(closestEnemy.getLocation(), this.ship.getLocation(), 1000000.0f)) {
shouldAttack = true;
}
if ( IsCloakedShipBehind(this.ship, closestEnemy)) {
shouldAttack = true;
}
}
if (!this.ship.areSignificantEnemiesInRange()
|| closestEnemy == null
|| shouldAttack
|| this.flags.hasFlag(ShipwideAIFlags.AIFlags.SAFE_VENT )) {
if (this.cloakDuration > 6f) {
ShipAPI myTarget = this.ship.getShipTarget();
if (myTarget != null && myTarget.getOwner() == 0) {
this.ship.setShipTarget(null); // try to prevent friendly fire when decloaking
}
this.system.deactivate();
}
}
}
else if (this.ship.isRetreating() || this.flags.hasFlag(ShipwideAIFlags.AIFlags.IN_CRITICAL_DPS_DANGER)
|| this.flags.hasFlag(ShipwideAIFlags.AIFlags.BACKING_OFF )) {
this.ship.useSystem();
this.cloakDuration = 0f;
}
}
}
public static ShipAPI FindClosestNonFighterShipWithOwner(ShipAPI cloakedShip, int owner) {
List<ShipAPI> allShips = Global.getCombatEngine().getAllShips();
ShipAPI closestNonFighterShip = null;
float closestDistance = Float.MAX_VALUE;
for (ShipAPI ship : allShips) {
if (ship.getOwner() == owner && !ship.isFighter() && !ship.isHulk()) {
float distance = MathUtils.getDistance(ship.getLocation(), cloakedShip.getLocation());
if (distance < closestDistance) {
closestNonFighterShip = ship;
closestDistance = distance;
}
}
}
return closestNonFighterShip;
}
public static boolean IsCloakedShipBehind(ShipAPI cloakedShip, ShipAPI otherShip) {
// Get the direction vector from otherShip to cloakedShip
//Vector2f directionVector = MathUtils.getVector(otherShip.getLocation(), cloakedShip.getLocation());
// Get the forward facing vector of otherShip
Vector2f forwardVector = otherShip.getLocation();
float angle = Misc.getAngleInDegrees(cloakedShip.getLocation(), forwardVector);
// Calculate the angle between direction vector and forward vector
//float angle = MathUtils.getShortestRotation(forwardVector, directionVector);
// Check if the angle is greater than 90 degrees
return Math.abs(angle) > Math.PI / 2f;
}
}