Fractal Softworks Forum

Starsector => Bug Reports & Support => Bug Reports & Support (modded) => Topic started by: pairedeciseaux on March 09, 2020, 01:26:51 PM

Title: CTD: NPE at data.scripts.ai.ORA_callingAI.<init>(ORA_callingAI.java:41)
Post by: pairedeciseaux on March 09, 2020, 01:26:51 PM
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 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

[close]

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)

[close]
Title: Re: CTD: NPE at data.scripts.ai.ORA_callingAI.<init>(ORA_callingAI.java:41)
Post by: Sundog on March 09, 2020, 02:52:42 PM
That's a very good bug report. Thank you for being so thorough!
Are you using any sort of AI overhaul mod?
Were you careful to delete the ORI mod folder before replacing it with the updated one?

After taking a look at the source, it looks like the problem might have been caused by the missile's weapon not being assigned to a weapon group, but if that's the case I don't see how the missile AI would become active in the first place.

You might want to post in the ORI thread to make sure the author is aware: http://fractalsoftworks.com/forum/index.php?topic=11646.0
Title: Re: CTD: NPE at data.scripts.ai.ORA_callingAI.<init>(ORA_callingAI.java:41)
Post by: pairedeciseaux on March 09, 2020, 03:14:21 PM
Are you using any sort of AI overhaul mod?

Not to my knowledge. I would say none unless some of the mods below do that:

Were you careful to delete the ORI mod folder before replacing it with the updated one?

I always do that, so I'm pretty confident I removed the old mod folder before copying the new one.

You might want to post in the ORI thread to make sure the author is aware: http://fractalsoftworks.com/forum/index.php?topic=11646.0

Ok, will do. Thanks for the quick reply!
Title: Re: CTD: NPE at data.scripts.ai.ORA_callingAI.<init>(ORA_callingAI.java:41)
Post by: Wyvern on March 11, 2020, 12:33:11 PM
After taking a look at the source, it looks like the problem might have been caused by the missile's weapon not being assigned to a weapon group, but if that's the case I don't see how the missile AI would become active in the first place.
  • we surrounded the Enlightment
  • it looked like the game crashed at the moment the Enlightment exploded, but I'm not 100% sure
From these two statements, I'd guess that this is a bug that can happen when a missile is in flight and the ship that was firing it dies?
Title: Re: CTD: NPE at data.scripts.ai.ORA_callingAI.<init>(ORA_callingAI.java:41)
Post by: Tartiflette on March 11, 2020, 01:15:08 PM
I can't check the script since I'm away from home until this weekend. I'd say if that's the case, it can only occur if the target ship dies the same frame the weapon AI is activated, otherwise it would occur all the time.
Title: Re: CTD: NPE at data.scripts.ai.ORA_callingAI.<init>(ORA_callingAI.java:41)
Post by: Sundog on March 11, 2020, 04:00:54 PM
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
Quote
//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);
        }
    }
}
[close]

Lines 40 and 41:
Code: java
        WeaponGroupAPI group = missile.getSource().getWeaponGroupFor(missile.getWeapon());
        if(group.getAutofirePlugin(missile.getWeapon())!=null){