Hi,
I got a Java Null Pointer Exception / crash to destop during a battle against an ORA bounty fleet.
It's been a long long time since I've had a crash. Version 0.9.1 has been rock solid both without mods and with mods. Previous run was something like 3 month ago, with maybe 2 additionnal mods than those mentionned below. Before starting this run, I downloaded and replaced the mods that were updated during the last months, so I should have the latest versions.
How it happened:
- I think it was my first battle againts an ORA fleet for this run
- met the ORA bounty fleet in its fringe system
- IIRC the fleet had 1 Discernment, 4 Enlightments, and many smaller ships - the bounty reward was something like 284K or 294K
- battle went well, but 4 ORA ships managed to retreat - including the Discernment flagship
- pursued them, IIRC there was: 1 Discernment, 1 Enlightment, 1 Beatitude or Felicity, 1 Bliss
- the Discernment went down while I destroyed the cruiser
- not sure what happened to the Bliss, I did not pay attention
- we surrounded the Enlightment
- it looked like the game crashed at the moment the Enlightment exploded, but I'm not 100% sure
I gave a quick look at the ORA mod source code, my understanding is the game crashed early in the ORA custom missile/projectile AI for the Calling Scatterer weapon.
This is Starsector 0.9.1a-RC8 with the mod Outer Rim Alliance 0.87 running on macOS 10.14, details:
Spoiler
0 [main] INFO com.fs.starfarer.StarfarerLauncher - Starting Starsector 0.9.1a-RC8 launcher
1 [main] INFO com.fs.starfarer.StarfarerLauncher - Running in /Applications/Games/Starsector.app/Contents/Resources/Java
1 [main] INFO com.fs.starfarer.StarfarerLauncher - OS: Mac OS X 10.14.6
2 [main] INFO com.fs.starfarer.StarfarerLauncher - Java version: 1.7.0_79 (64-bit)
(...)
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Running with the following mods (in order of priority):
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Blackrock Drive Yards [id: blackrock_driveyards] [version 0.9.5] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Blackrock Drive Yards)
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Dassault-Mikoyan Engineering [id: istl_dam] [version 1.18a] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Dassault-Mikoyan Engineering 1.18)
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Diable Avionics [id: diableavionics] [version 2.04] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/DIABLEAVIONICS)
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Disassemble Reassemble [id: DisassembleReassemble] [version v 1.6.9] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/DisassembleReassemble_v1.6.9)
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Extratential Lanestate Union [id: XLU] [version 0.7.0a] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Extratential Lanestate Union)
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Foundation Of Borken [id: foundation] [version 0.2.4-RC3] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Foundation Of Borken)
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Interstellar Imperium [id: Imperium] [version 2.1.2] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Interstellar Imperium)
3835 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - LazyLib [id: lw_lazylib] [version 2.4e] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/LazyLib)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - MagicLib [id: MagicLib] [version 0.28] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/MagicLib)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Nexerelin [id: nexerelin] [version 0.9.5h] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Nexerelin)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Outer Rim Alliance [id: ORA] [version 0.87] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/ORA)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Scy Nation [id: SCY] [version 1.58] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/SCY)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Shadowyards [id: shadow_ships] [version 0.9RC1] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Shadowyards)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Ship/Weapon Pack [id: swp] [version 1.10.5] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Ship and Weapon Pack)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Tiandong Heavy Industries [id: THI] [version 1.2.1a] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Tiandong Heavy Industries 1.2.1a)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Underworld [id: underworld] [version 1.4.2] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Underworld)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Version Checker [id: lw_version_checker] [version 2.0] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/Version Checker)
3836 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - ZZ GraphicsLib [id: shaderLib] [version 1.4.1] (from /Applications/Games/Starsector.app/Contents/Resources/Java/../../../mods/GraphicsLib)
3840 [Thread-5] INFO com.fs.starfarer.StarfarerLauncher - Mod list finished
Crash log:
Spoiler
2481324 [Thread-11] INFO sound.H - Playing music with id [miscallenous_corvus_campaign_music.ogg]
2481424 [Thread-5] INFO com.fs.starfarer.api.impl.campaign.events.OfficerManagerEvent - Removed freelance admin from diableavionics_ressource, 20 total available
2481611 [Thread-5] INFO com.fs.starfarer.api.impl.campaign.events.OfficerManagerEvent - Added admin at tiandong_mogui_market, 20 total available
2482049 [Thread-5] INFO com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetRouteManager - Added trade fleet route from Amity Freeport to Kazeron
2483817 [Thread-5] INFO com.fs.starfarer.api.impl.campaign.intel.ProcurementMissionIntel - Created ProcurementMissionIntel: hand_weapons to Three Bodies
2485837 [Thread-11] INFO sound.public - Creating streaming player for music with id [faction_pirate_encounter_02_hostile.ogg]
2485837 [Thread-11] INFO sound.H - Playing music with id [faction_pirate_encounter_02_hostile.ogg]
2489145 [Thread-5] INFO data.scripts.plugins.tiandong_ModuleRetreatCleaner - Another module retreat cleaner already running, suspending plugin
2490160 [Thread-9] INFO sound.public - Cleaning up music with id [faction_pirate_encounter_02_hostile.ogg]
2490346 [Thread-11] INFO sound.public - Creating streaming player for music with id [battle_ambience_01.ogg]
2490346 [Thread-11] INFO sound.H - Playing music with id [battle_ambience_01.ogg]
3177748 [Thread-9] INFO sound.public - Cleaning up music with id [battle_ambience_01.ogg]
3178247 [Thread-11] INFO sound.public - Creating streaming player for music with id [faction_pirate_encounter_02_hostile.ogg]
3178247 [Thread-11] INFO sound.H - Playing music with id [faction_pirate_encounter_02_hostile.ogg]
3207046 [Thread-5] INFO data.scripts.plugins.tiandong_ModuleRetreatCleaner - Another module retreat cleaner already running, suspending plugin
3208066 [Thread-9] INFO sound.public - Cleaning up music with id [faction_pirate_encounter_02_hostile.ogg]
3208331 [Thread-11] INFO sound.public - Creating streaming player for music with id [battle_ambience_01.ogg]
3208331 [Thread-11] INFO sound.H - Playing music with id [battle_ambience_01.ogg]
3310399 [Thread-5] INFO sound.public - Cleaning up music with id [miscallenous_corvus_campaign_music.ogg]
3310408 [Thread-5] INFO sound.public - Cleaning up music with id [campaign_music_part_2_v28.ogg]
3310427 [Thread-9] INFO sound.public - Cleaning up music with id [battle_ambience_01.ogg]
3310599 [Thread-11] INFO sound.public - Creating streaming player for music with id [battle_ambience_01.ogg]
3310599 [Thread-11] INFO sound.H - Playing music with id [battle_ambience_01.ogg]
3311121 [Thread-5] ERROR com.fs.starfarer.combat.CombatMain - java.lang.NullPointerException
java.lang.NullPointerException
at data.scripts.ai.ORA_callingAI.<init>(ORA_callingAI.java:41)
at data.scripts.ORA_modPlugin.pickMissileAI(ORA_modPlugin.java:38)
at com.fs.starfarer.launcher.ModManager$6.super(Unknown Source)
at com.fs.starfarer.launcher.ModManager.getPriorityPlugin(Unknown Source)
at com.fs.starfarer.launcher.ModManager.pickMissileAIOverride(Unknown Source)
at com.fs.starfarer.loading.specs.a.o00000(Unknown Source)
at com.fs.starfarer.loading.specs.a.o00000(Unknown Source)
at com.fs.starfarer.combat.entities.ship.A.J.o00000(Unknown Source)
at com.fs.starfarer.combat.entities.ship.A.J.fireProjectile(Unknown Source)
at com.fs.starfarer.combat.entities.ship.trackers.B.øO0000(Unknown Source)
at com.fs.starfarer.combat.entities.ship.trackers.B.super(Unknown Source)
at com.fs.starfarer.combat.entities.ship.trackers.D.super(Unknown Source)
at com.fs.starfarer.combat.entities.ship.trackers.D.super(Unknown Source)
at com.fs.starfarer.combat.entities.ship.trackers.B.String(Unknown Source)
at com.fs.starfarer.combat.entities.ship.A.J.advance(Unknown Source)
at com.fs.starfarer.combat.entities.Ship.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$1.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
That makes a lot of sense. It would explain both the rarity of the crash and how it could occur in the first place.
Here's the class source:
Spoiler
//By Tartiflette, simple and fast rocket AI that will try to attack a target in a frontal cone, and not reengage any if it misses.
//V2 done
package data.scripts.ai;
import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.AutofireAIPlugin;
import com.fs.starfarer.api.combat.CollisionClass;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.MissileAIPlugin;
import com.fs.starfarer.api.combat.MissileAPI;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ShipCommand;
import com.fs.starfarer.api.combat.WeaponGroupAPI;
import com.fs.starfarer.api.util.IntervalUtil;
import java.awt.Color;
import org.lazywizard.lazylib.MathUtils;
import org.lazywizard.lazylib.VectorUtils;
import org.lazywizard.lazylib.combat.AIUtils;
import org.lwjgl.util.vector.Vector2f;
public class ORA_callingAI implements MissileAIPlugin {
private CombatEngineAPI engine;
private final MissileAPI missile;
private Vector2f lead = new Vector2f();
private float deviation=0;
private IntervalUtil timer = new IntervalUtil(0.1f,0.5f);
private final float DAMPING = 0.05f, RANDOMNESS;
private final int side;
//////////////////////
// DATA COLLECTING //
//////////////////////
public ORA_callingAI(MissileAPI missile, ShipAPI launchingShip) {
this.missile = missile;
// MAX_SPEED = missile.getMaxSpeed();
//force a lead point since the auto fire AI don't lead with missiles
WeaponGroupAPI group = missile.getSource().getWeaponGroupFor(missile.getWeapon());
if(group.getAutofirePlugin(missile.getWeapon())!=null){
AutofireAIPlugin auto = group.getAutofirePlugin(missile.getWeapon());
if(group.isAutofiring() && auto.getTargetShip()!=null){
lead = AIUtils.getBestInterceptPoint(missile.getLocation(), missile.getMaxSpeed(), auto.getTargetShip().getLocation(), auto.getTargetShip().getVelocity());
//debug
// Global.getCombatEngine().addHitParticle(lead, new Vector2f(), 20, 1, 1, Color.red);
if(lead!=null){
lead=MathUtils.getPoint(missile.getLocation(), missile.getWeapon().getRange(), VectorUtils.getAngle(missile.getLocation(), lead));
} else {
lead=MathUtils.getPoint(missile.getLocation(), missile.getWeapon().getRange(), missile.getFacing());
}
} else {
lead=MathUtils.getPoint(missile.getLocation(), missile.getWeapon().getRange(), missile.getFacing());
//debug
// Global.getCombatEngine().addHitParticle(lead, new Vector2f(), 20, 1, 1, Color.blue);
}
} else {
lead=MathUtils.getPoint(missile.getLocation(), missile.getWeapon().getRange(), missile.getFacing());
}
if (engine != Global.getCombatEngine()) {
this.engine = Global.getCombatEngine();
}
timer.forceIntervalElapsed();
RANDOMNESS=45;
//swap the damage bonuses from missile to energy
missile.setDamageAmount(
missile.getBaseDamageAmount()
*missile.getSource().getMutableStats().getEnergyWeaponDamageMult().computeMultMod()
/missile.getSource().getMutableStats().getMissileWeaponDamageMult().computeMultMod()
);
side=missile.getOwner();
missile.setCollisionClass(CollisionClass.MISSILE_NO_FF);
}
//////////////////////
// MAIN AI LOOP //
//////////////////////
@Override
public void advance(float amount) {
//skip the AI if the game is paused, the missile is engineless or fading
if (Global.getCombatEngine().isPaused()) {return;}
if(missile.isFading() || missile.isFizzling() || missile.getOwner()!=side){
engine.addSmoothParticle(missile.getLocation(), missile.getVelocity(), 100, 0.5f, 0.25f, Color.blue);
engine.addHitParticle(missile.getLocation(), missile.getVelocity(), 100, 1f, 0.1f, Color.white);
engine.removeEntity(missile);
return;
}
//forced acceleration by default
missile.giveCommand(ShipCommand.ACCELERATE);
timer.advance(amount);
if(timer.intervalElapsed()){
deviation = (-(RANDOMNESS/2)+(float)Math.random()*RANDOMNESS)*(4-missile.getFlightTime())/3;
float d=missile.getBaseDamageAmount()*0.95f;
missile.setDamageAmount(d);
//debug
// engine.addFloatingText(missile.getLocation(), ""+d, 20, Color.yellow, missile, 1, 1);
// engine.addFloatingText(missile.getLocation(), ""+missile.getDamageAmount(), 20, Color.yellow, missile, 1, 1);
}
//best angle for interception
float aimAngle = deviation +
MathUtils.getShortestRotation(
missile.getFacing(),
VectorUtils.getAngle(
missile.getLocation(),
lead
)
);
if (aimAngle < 0) {
missile.giveCommand(ShipCommand.TURN_RIGHT);
} else {
missile.giveCommand(ShipCommand.TURN_LEFT);
}
// Damp angular velocity if the missile aim is getting close to the targeted angle
if (Math.abs(aimAngle) < Math.abs(missile.getAngularVelocity()) * DAMPING) {
missile.setAngularVelocity(aimAngle / DAMPING);
}
}
}
Lines 40 and 41:
WeaponGroupAPI group = missile.getSource().getWeaponGroupFor(missile.getWeapon());
if(group.getAutofirePlugin(missile.getWeapon())!=null){