Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Starsector 0.97a is out! (02/02/24); New blog post: Simulator Enhancements (03/13/24)

Pages: [1] 2

Author Topic: Global.getSector().isInNewGameAdvance()  (Read 7803 times)

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Global.getSector().isInNewGameAdvance()
« on: May 29, 2017, 04:57:03 PM »

...it returns TRUE on the Title Screen, in the Missions, etc., etc.

Pretty sure that's a bug.

But I've got a question, related to this.

Is there a method to determine, in EveryFrameCombatScripts, if the game's currently running that initial Economy sim (you know, starting with Jan 1)? 

Because running EveryFrameCombatScripts there is causing some sort of endless-loop hang pretty consistently, running here with 64-bit Java.  Or it's exposing a bug in there, I don't know.

And the CombatEngine doesn't report isPaused() being true, etc., etc., when that's happening, so I don't see a clear way to detect that state and halt the scripts then.
Logged
Please check out my SS projects :)
Xeno's Mod Pack

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 23986
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #1 on: May 29, 2017, 05:07:36 PM »

I'm confused - why would you be calling this from *combat* scripts? They would never run during the new game advance period (i.e. the jan 1st -> march 1st interval) since there is never any non-autoresolved combat/
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #2 on: May 30, 2017, 10:15:29 AM »

The game's still running EveryFrameCombatScript() during this period, because of the "attraction" ships in the Title screen.  I've repeatedly confirmed that, not only is it running, the game is not returning isPaused(), etc., so I can't get the script to halt.  It's causing some sort of issue with the core gamecode during that period, that I can't see (looks like a timer exceeds <some value> from here) that then causes the application to terminate.
Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #3 on: May 30, 2017, 10:19:57 AM »

I've tested a bunch of ways to find a valid method to halt that stuff during this period, but to no avail thus far.  I'm really not sure why other EveryFrameCombatScripts aren't causing issues (or they are, but nobody's been reporting them), but it's happening with all of mine.

Here's some of the code, just to see what it's trying to do:

Code
package data.scripts.plugins;

import com.fs.starfarer.api.combat.BeamAPI;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.DamagingProjectileAPI;
import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.MutableShipStatsAPI;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ViewportAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import com.fs.starfarer.api.input.InputEventAPI;
import java.awt.Color;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class FormShieldPlugin implements EveryFrameCombatPlugin
{
private final float shieldDamage = 0.25f;
private final float shieldDamageShot = 0.05f;
    private CombatEngineAPI engine;

private HashSet<ShipAPI> reflectingMap = new HashSet<>();
private HashSet<ShipAPI> damagedMap = new HashSet<>();

private List<BeamAPI> beamList = new ArrayList<>();
private List<DamagingProjectileAPI> projList = new ArrayList<>();

public static final Color JITTER_UNDER_COLOR = new Color(0,200,255,155);
public static final Color JITTER_COLOR = new Color(0,200,255,32);
  
    
    @Override
    public void advance(float amount,List<InputEventAPI> events)
    {
        if (engine.isPaused()) return;
        for (ShipAPI ship : engine.getShips()) {
List hullmods = ship.getVariant().getSortedMods();
if(hullmods.contains("shields_formshield")){
if (!reflectingMap.contains(ship))
{
reflectingMap.add(ship);
MutableShipStatsAPI stats = ship.getMutableStats();
stats.getEmpDamageTakenMult().modifyFlatAfterMult(null, -1f);
stats.getArmorDamageTakenMult().modifyFlatAfterMult(null, -1f);
stats.getHullDamageTakenMult().modifyFlatAfterMult(null, -1f);
stats.getWeaponDamageTakenMult().modifyFlatAfterMult(null, -1f);
stats.getEngineDamageTakenMult().modifyFlatAfterMult(null, -1f);
}
if(reflectingMap.contains(ship) && ship.getFluxTracker().isOverloadedOrVenting() || ship.isHulk()){
MutableShipStatsAPI stats = ship.getMutableStats();
stats.getEmpDamageTakenMult().modifyFlatAfterMult(null, 1f);
stats.getArmorDamageTakenMult().modifyFlatAfterMult(null, 1f);
stats.getHullDamageTakenMult().modifyFlatAfterMult(null, 1f);
stats.getWeaponDamageTakenMult().modifyFlatAfterMult(null, 1f);
stats.getEngineDamageTakenMult().modifyFlatAfterMult(null, 1f);
reflectingMap.remove(ship);
}
            }
        }

beamList = engine.getBeams();
        projList = engine.getProjectiles();

        if(!beamList.isEmpty()){    
for (BeamAPI thisBeam : beamList)
{
CombatEntityAPI thisBeamTarget = thisBeam.getDamageTarget();
if(thisBeamTarget != null)
{    
if(thisBeamTarget instanceof ShipAPI)
{
ShipAPI shipTarget = (ShipAPI) thisBeamTarget;
if(reflectingMap.contains(shipTarget))
{
float dps = 0f;
if(thisBeam.getWeapon().isBurstBeam()){
dps = thisBeam.getWeapon().getDerivedStats().getBurstDamage() * shieldDamage;
dps = thisBeam.getWeapon().getDerivedStats().getBurstFireDuration() * dps;
} else {
dps = thisBeam.getWeapon().getDerivedStats().getDps() * shieldDamage * amount;
}
shipTarget.getFluxTracker().increaseFlux(dps, true);
damagedMap.add(shipTarget);
}
}
}    
}
}

if(!projList.isEmpty()){
for (DamagingProjectileAPI thisProj : projList)
{
if(thisProj.didDamage())
{    
CombatEntityAPI thisProjTarget = thisProj.getDamageTarget();
if(thisProjTarget instanceof ShipAPI){
ShipAPI shipTarget = (ShipAPI) thisProjTarget;
if(reflectingMap.contains(shipTarget))
{
float dps = thisProj.getWeapon().getDerivedStats().getDamagePerShot() * shieldDamageShot;
shipTarget.getFluxTracker().increaseFlux(dps, true);
damagedMap.add(shipTarget);
}
}
}    
}  
}

for(ShipAPI damagedShip : damagedMap){
damagedShip.setJitterUnder(this, JITTER_UNDER_COLOR, 3f, 4, 0f, 5f);
damagedShip.setJitter(this, JITTER_COLOR, 3f, 4, 0f, 5f);
}
damagedMap.clear();
    }

    @Override
    public void init(CombatEngineAPI eng) {
        this.engine = eng;
        reflectingMap.clear();
beamList.clear();
projList.clear();
    }

@Override
public void renderInWorldCoords(ViewportAPI vapi) {
}

@Override
public void renderInUICoords(ViewportAPI vapi) {

}
}

Logged
Please check out my SS projects :)
Xeno's Mod Pack

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 23986
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #4 on: May 30, 2017, 10:28:25 AM »

The game's still running EveryFrameCombatScript() during this period, because of the "attraction" ships in the Title screen.

It's 100% not doing that. It couldn't possibly. Because I'm paranoid, I also just tested to make sure, and it indeed doesn't.

To clarify: it's running those scripts in the title screen, but NOT once the "new campaign game creation" progress bar starts up.
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #5 on: May 30, 2017, 10:34:28 AM »

Uh, I hate to put it this way, but something's still running then; I can watch the FX script doing <something> during that period (it's also the best way to see this crash occur- get a bunch of ships fighting on the screen, hit "start game").

So... maybe it's during the drawing portion that this occurs?

But, more importantly, ships and weapons and all that are getting drawn while that code is running; so obviously a lot of things are still happening.  How can I detect that you've entered that special state and halt all operations?
Logged
Please check out my SS projects :)
Xeno's Mod Pack

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 23986
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #6 on: May 30, 2017, 10:42:11 AM »

The rendering is not running either. The reason you still see the last frame before you hit "start new game" is the screen buffer isn't cleared, and the progress bar stuff is just rendered on top of it. Occasionally, you'll see the title screen stuff in the background shifting between two frames, this is due to different frames being double buffered, but again, no actual combat rendering going on at that point.

However: it will render two frames in a row *right before* the progress bar etc starts, without an intervening advance() call, so if there's anything in your code that relies on render()/advance() always being precisely interleaved, that could cause a problem.
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #7 on: May 30, 2017, 10:44:49 AM »

Here's the code from the current release of FX mod, for comparison's sake.  Note all the ways I'm trying to return during Advance() here.

Code
package data.scripts.plugins;

import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.BeamAPI;
import com.fs.starfarer.api.combat.CombatAsteroidAPI;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.DamagingProjectileAPI;
import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.MissileAPI;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ViewportAPI;
import com.fs.starfarer.api.graphics.SpriteAPI;

import data.scripts.fx_Particle;

import static data.scripts.fx_SharedLib.circularVelocity;
import static data.scripts.fx_SharedLib.getBeamColors;
import static data.scripts.fx_SharedLib.getProjectileColors;
import static data.scripts.fx_SharedLib.isWithinShieldArc;

import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import java.util.List;
import java.util.Map;

import org.lazywizard.lazylib.MathUtils;
import org.lazywizard.lazylib.VectorUtils;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.opengl.GL11;
import static org.lazywizard.lazylib.MathUtils.getRandomNumberInRange;


public class FX_Plugin implements EveryFrameCombatPlugin
{
CombatEngineAPI engine;
private Vector2f centerPoint;
private float frameTime;
private final float longDist = 3000f * 3000f;

//Default Sprite
private final SpriteAPI eSprite = Global.getSettings().getSprite("fx", "fx_muzzleflash_001");

//FX Sprites
private final SpriteAPI fx_muzzleflash_001 = Global.getSettings().getSprite("fx", "fx_muzzleflash_001");
private final SpriteAPI fx_muzzleflash_002 = Global.getSettings().getSprite("fx", "fx_muzzleflash_002");
private final SpriteAPI fx_muzzleflash_003 = Global.getSettings().getSprite("fx", "fx_muzzleflash_003");

private final SpriteAPI fx_shieldflash_001 = Global.getSettings().getSprite("fx", "fx_shieldflash_001");
private final SpriteAPI fx_shieldflash_002 = Global.getSettings().getSprite("fx", "fx_shieldflash_002");
private final SpriteAPI fx_shieldflash_003 = Global.getSettings().getSprite("fx", "fx_shieldflash_003");

private final SpriteAPI fx_laserflash_001 = Global.getSettings().getSprite("fx", "fx_laserflash_001");
private final SpriteAPI fx_laserflash_002 = Global.getSettings().getSprite("fx", "fx_laserflash_002");
private final SpriteAPI fx_laserflash_003 = Global.getSettings().getSprite("fx", "fx_laserflash_003");

private final SpriteAPI fx_smoke_tendril_001 = Global.getSettings().getSprite("fx", "fx_smoke_tendril_001");
private final SpriteAPI fx_smoke_tendril_002 = Global.getSettings().getSprite("fx", "fx_smoke_tendril_002");
private final SpriteAPI fx_smoke_tendril_003 = Global.getSettings().getSprite("fx", "fx_smoke_tendril_003");

private final SpriteAPI fx_generic_pulse = Global.getSettings().getSprite("fx", "fx_generic_pulse");

public static List<fx_Particle> particleList = new ArrayList<>();

public static Map projCoreColorMap = new HashMap();
public static Map projFringeColorMap = new HashMap();

//public static List<ShipAPI> engineList = new ArrayList<>();
public static HashSet<DamagingProjectileAPI> deadShotList = new HashSet<>(100);
//public static Map engineMap = new HashMap();

public static HashSet<MissileAPI> seenMissiles = new HashSet<>(100);

    @Override
public void init(CombatEngineAPI engine) {
this.engine = engine;
clearMe();
}

public void clearMe(){
particleList.clear();
deadShotList.clear();
seenMissiles.clear();
}
        
    @Override
public void advance(float amount, List events)
{
// Obvious exploits are obvious
if (engine == null){ clearMe(); return;}
if(engine.isPaused()){ frameTime = 0f; return;}
if(engine.isInFastTimeAdvance() || engine.isUIShowingDialog()){ clearMe(); return;}
frameTime = amount;
if(engine.getTimeMult().getModifiedValue() != 1f){
frameTime /= engine.getTimeMult().getModifiedValue();
}

        // get the missiles in this frame  
        HashSet<MissileAPI> activeMissiles = new HashSet<>();  
        activeMissiles.addAll(engine.getMissiles());  
  
        // the difference between the missiles in the last frame to this frame are those that *could* have done damage  
        //seenMissiles.removeAll(activeMissiles);  
        for(MissileAPI missile : seenMissiles){  
if(deadShotList.contains(missile)) continue;
            if(missile.didDamage()){  
int damageType;
switch (missile.getDamageType()) {
case ENERGY:
damageType = 0;
break;
case HIGH_EXPLOSIVE:
damageType = 1;
break;
case KINETIC:
damageType = 2;
break;
case FRAGMENTATION:
damageType = 3;
break;
default:
damageType = 0;
break;
}
                int power = Math.min(200,Math.max(1,Math.round(missile.getWeapon().getDerivedStats().getDamagePerShot() / 5)));
doProjectileExplosion(missile,null,power,power > 3,damageType);
deadShotList.add(missile);
            }  
        }  
  
        // set our missiles for the next frame  
        seenMissiles = activeMissiles;

for(BeamAPI beam : engine.getBeams()){
//Generates a bit of "spark" when the Beam strikes something.
if(beam.didDamageThisFrame() && beam.getBrightness() > 0.99f){
float angle = VectorUtils.getAngle(beam.getFrom(), beam.getTo());
int power = Math.min(5,Math.max(1,Math.round(beam.getWeapon().getDerivedStats().getDps() / 75)));
boolean didEffect = false;
CombatEntityAPI target = beam.getDamageTarget();
if(target instanceof ShipAPI){
ShipAPI tShip = (ShipAPI) target;
if(tShip.getShield() != null){
if(tShip.getShield().isOn() && isWithinShieldArc(tShip,beam.getTo())){
didEffect = true;

if(beam.getWeapon() == null) continue;
if(beam.getWeapon().getShip() == null) continue;
if(beam.getWeapon().isBurstBeam() || getRandomNumberInRange(0f,10f) > 9f){
power = Math.min(400,Math.max(1,Math.round(beam.getWeapon().getDerivedStats().getDamagePerShot())));
float newAngle = VectorUtils.getAngle(tShip.getShield().getLocation(),beam.getTo()) + getRandomNumberInRange(-45f, 45f);
float vel = getRandomNumberInRange(0, 3f);
float size = getRandomNumberInRange(50f + (float) power,75f + (float) power);
float growth = getRandomNumberInRange(0.995f,1.0f);
float ratio = 1.0f;
float lifeTime = getRandomNumberInRange(0.1f,0.15f);
float fadeTime = getRandomNumberInRange(0.1f,0.15f);
Color projColor;
Color projColorFade;
if(!projCoreColorMap.containsKey(beam.getWeapon().getId())){
Color[] bColors = getBeamColors(beam);
projColor = bColors[0];
projColorFade = bColors[1];
} else {
projColor = (Color) projCoreColorMap.get(beam.getWeapon().getId());
projColorFade = (Color) projFringeColorMap.get(beam.getWeapon().getId());
}
int muzzleflash = getRandomNumberInRange(1,3);
Vector2f velocity = circularVelocity(newAngle,vel);
Vector2f targetVel = beam.getWeapon().getShip().getVelocity();
velocity = velocity.translate(targetVel.getX(), targetVel.getY());
newParticle(beam.getTo(),velocity, size, ratio, newAngle, true, true, "fx_shieldflash_00"+muzzleflash,projColor,projColorFade,lifeTime,fadeTime,growth);
}
}
}
}

if(target instanceof MissileAPI || target instanceof CombatAsteroidAPI || !didEffect){
for(int i = 0; i < power; i++){
if(getRandomNumberInRange(0f,10f) > 5f){
float newAngle = MathUtils.clampAngle(angle -180f + MathUtils.getRandomNumberInRange(-20f, 20f));
float vel = getRandomNumberInRange(200f + (power * 100f), 400f + (power * 100f));
float size = getRandomNumberInRange(10f + (float) power * 3f,20f + (float) power * 3f);
float growth = getRandomNumberInRange(0.995f,1.0f);
float ratio = 1.0f;
float lifeTime = getRandomNumberInRange(0.1f,0.3f);
float fadeTime = getRandomNumberInRange(0.1f,0.3f);
Vector2f velocity = circularVelocity(newAngle,vel);
Vector2f targetVel = beam.getDamageTarget().getVelocity();
velocity = velocity.translate(targetVel.getX(), targetVel.getY());
newParticle(beam.getTo(),velocity, size, ratio, newAngle, true, true, "fx_generic_pulse",new Color(255,255,0,255),new Color(128,32,0,255),lifeTime,fadeTime,growth);
}
}
}
}

//Generates a "muzzle flash" for a Beam that's active
if(beam.getBrightness() > 0.5f && getRandomNumberInRange(0f,10f) > 5f){
if(beam.getWeapon() == null) continue;
if(beam.getWeapon().getShip() == null) continue;
int power = Math.min(200,Math.max(1,Math.round(beam.getWeapon().getDerivedStats().getDamagePerShot() / 15)));
float newAngle = VectorUtils.getAngle(beam.getFrom(), beam.getTo());
float vel = getRandomNumberInRange(10, 15f);
float size = getRandomNumberInRange(100f + (float) power,125f + (float) power);
float growth = getRandomNumberInRange(0.8f,0.9f);
float ratio = 1.0f;
float lifeTime = getRandomNumberInRange(0.1f,0.15f);
float fadeTime = getRandomNumberInRange(0.1f,0.15f);
Color projColor;
Color projColorFade;
if(!projCoreColorMap.containsKey(beam.getWeapon().getId())){
Color[] bColors = getBeamColors(beam);
projColor = bColors[0];
projColorFade = bColors[1];
} else {
projColor = (Color) projCoreColorMap.get(beam.getWeapon().getId());
projColorFade = (Color) projFringeColorMap.get(beam.getWeapon().getId());
}
int muzzleflash = getRandomNumberInRange(1,3);
Vector2f velocity = circularVelocity(newAngle,vel);
Vector2f targetVel = beam.getWeapon().getShip().getVelocity();
velocity = velocity.translate(targetVel.getX(), targetVel.getY());
newParticle(beam.getFrom(),velocity, size, ratio, newAngle, true, true, "fx_laserflash_00"+muzzleflash,projColor,projColorFade,lifeTime,fadeTime,growth);
}
}

//Kills dead particles; fast boolean checker
for(int i = 0; i < particleList.size(); i++){
if(particleList.get(i).isDead() == true){
particleList.remove(i);
i--;
}
}

//Handles explosions and muzzle-flashes for projectiles.
for(DamagingProjectileAPI projectile : engine.getProjectiles()){
if(deadShotList.contains(projectile)) continue;
if(projectile instanceof MissileAPI){
if(projectile.getElapsed() < 0.01f){
projectileHandler(projectile);
}
} else {
projectileHandler(projectile);
}
}
}

public void projectileHandler(DamagingProjectileAPI projectile){
if(projectile.getWeapon() == null) return;
if(projectile.getWeapon().getShip() == null) return;

CombatEntityAPI dTarg = projectile.getDamageTarget();

//PROJECTILE EXPLOSION HANDLER
if(dTarg != null){
int damageType;
switch (projectile.getDamageType()) {
case ENERGY:
damageType = 0;
break;
case HIGH_EXPLOSIVE:
damageType = 1;
break;
case KINETIC:
damageType = 2;
break;
case FRAGMENTATION:
damageType = 3;
break;
default:
damageType = 0;
break;
}
int power = Math.min(200,Math.max(1,Math.round(projectile.getWeapon().getDerivedStats().getDamagePerShot() / 15)));
doProjectileExplosion(projectile,dTarg,power,power > 3,damageType);
deadShotList.add(projectile);
}

//MUZZLE-FLASH HANDLER
if(projectile.getElapsed() < 0.01f){
int power = Math.min(200,Math.max(1,Math.round(projectile.getWeapon().getDerivedStats().getDamagePerShot() / 15)));
float newAngle = projectile.getFacing();
float vel = getRandomNumberInRange(5, 10f);
float size = getRandomNumberInRange(50f + (float) power,100f + (float) power);
float growth = getRandomNumberInRange(0.8f,0.9f);
float ratio = 1.0f;
float lifeTime = getRandomNumberInRange(0.1f,0.3f);
float fadeTime = getRandomNumberInRange(0.1f,0.15f);
Color projColor;
Color projColorFade;
if(!projCoreColorMap.containsKey(projectile.getProjectileSpecId())){
Color[] bColors = getProjectileColors(projectile);
projColor = bColors[0];
projColorFade = bColors[1];
} else {
projColor = (Color) projCoreColorMap.get(projectile.getProjectileSpecId());
projColorFade = (Color) projFringeColorMap.get(projectile.getProjectileSpecId());
}
int muzzleflash = getRandomNumberInRange(1,3);
Vector2f velocity = circularVelocity(newAngle,vel);
Vector2f targetVel = projectile.getWeapon().getShip().getVelocity();
velocity = velocity.translate(targetVel.getX(), targetVel.getY());
newParticle(projectile.getLocation(),velocity, size, ratio, newAngle, true, true, "fx_muzzleflash_00"+muzzleflash,projColor,projColorFade,lifeTime,fadeTime,growth);
}
}

public void doProjectileExplosion(DamagingProjectileAPI proj, CombatEntityAPI targ, int power, boolean doSmoke, int damageType){
int repeats = Math.min(7,Math.max(1, power / 5));
float facing = proj.getFacing();
Vector2f targetVel;
if(targ == null){
targetVel = new Vector2f(0.0f,0.0f);
} else {
targetVel = targ.getVelocity();
}
for(int i = 0; i < repeats; i++){
float angle = facing + 180 + getRandomNumberInRange(-35f,35f);
float vel = getRandomNumberInRange(5, 10f);
float size = getRandomNumberInRange(10f + (float) power,20f + (float) power);
float growth = getRandomNumberInRange(1.02f,1.05f);
float ratio = 1.0f;
float lifeTime = getRandomNumberInRange(0.1f,0.3f);
float fadeTime = getRandomNumberInRange(0.1f,0.15f);
Color projColor;
Color projColorFade;
if(!projCoreColorMap.containsKey(proj.getProjectileSpecId())){
Color[] bColors = getProjectileColors(proj);
projColor = bColors[0];
projColorFade = bColors[1];
} else {
projColor = (Color) projCoreColorMap.get(proj.getProjectileSpecId());
projColorFade = (Color) projFringeColorMap.get(proj.getProjectileSpecId());
}
int muzzleflash = getRandomNumberInRange(1,3);
Vector2f velocity = circularVelocity(angle,vel);
velocity = new Vector2f(velocity.getX() + targetVel.getX(), velocity.getY() + targetVel.getY());
//Smoke particles.  Limits on how powerful a shot needs to be to generate, to prevent certain borks and optimize
if(doSmoke && getRandomNumberInRange(0,10) > 7){
switch (damageType) {
case 0:
//Does a glow effect
newParticle(proj.getLocation(),new Vector2f(0f,0f), size * getRandomNumberInRange(0.75f,2.0f), ratio, getRandomNumberInRange(0f,359f), false, false, "fx_generic_pulse",projColor,projColorFade,lifeTime * 0.5f,fadeTime * getRandomNumberInRange(0.5f,0.85f),getRandomNumberInRange(1.005f,1.01f));
break;
case 1:
//Does a smoke-tendril effect
newParticle(proj.getLocation(),new Vector2f(0f,0f), size * getRandomNumberInRange(0.75f,2.0f), ratio, getRandomNumberInRange(0f,359f), false, false, "fx_smoke_tendril_00"+muzzleflash,new Color (255,255,255,255),new Color (255,255,255,255),lifeTime * getRandomNumberInRange(2f,5f),fadeTime * getRandomNumberInRange(5f,10f),getRandomNumberInRange(1.001f,1.005f));
break;
case 2:
//Does a spike effect
newParticle(proj.getLocation(),new Vector2f(0f,0f), size * getRandomNumberInRange(0.75f,2.0f), ratio, getRandomNumberInRange(0f,359f), false, false, "fx_smoke_tendril_00"+muzzleflash,new Color (255,255,255,255),new Color (255,255,255,255),lifeTime * getRandomNumberInRange(2f,5f),fadeTime * getRandomNumberInRange(5f,10f),getRandomNumberInRange(1.001f,1.005f));
break;
case 3:
//Does a burst effect
newParticle(proj.getLocation(),new Vector2f(0f,0f), size * getRandomNumberInRange(0.75f,2.0f), ratio, getRandomNumberInRange(0f,359f), false, false, "fx_smoke_tendril_00"+muzzleflash,new Color (255,255,255,255),new Color (255,255,255,255),lifeTime * getRandomNumberInRange(2f,5f),fadeTime * getRandomNumberInRange(5f,10f),getRandomNumberInRange(1.001f,1.005f));
break;
default:
//Does a burst effect
newParticle(proj.getLocation(),new Vector2f(0f,0f), size * getRandomNumberInRange(0.75f,2.0f), ratio, getRandomNumberInRange(0f,359f), false, false, "fx_smoke_tendril_00"+muzzleflash,new Color (255,255,255,255),new Color (255,255,255,255),lifeTime * getRandomNumberInRange(2f,5f),fadeTime * getRandomNumberInRange(5f,10f),getRandomNumberInRange(1.001f,1.005f));
break;
}
}
newParticle(proj.getLocation(),velocity, size, ratio, angle, true, true, "fx_muzzleflash_00"+muzzleflash,projColor,projColorFade,lifeTime,fadeTime,growth);
}
}

public SpriteAPI pickSprite(String spriteName){
if (spriteName.equalsIgnoreCase("fx_muzzleflash_001")){
return fx_muzzleflash_001;
} else if (spriteName.equalsIgnoreCase("fx_muzzleflash_002")) {
return fx_muzzleflash_002;
} else if (spriteName.equalsIgnoreCase("fx_muzzleflash_003")) {
return fx_muzzleflash_003;
} else if (spriteName.equalsIgnoreCase("fx_laserflash_001")) {
return fx_laserflash_001;
} else if (spriteName.equalsIgnoreCase("fx_laserflash_002")) {
return fx_laserflash_002;
} else if (spriteName.equalsIgnoreCase("fx_laserflash_003")) {
return fx_laserflash_003;
} else if (spriteName.equalsIgnoreCase("fx_shieldflash_001")) {
return fx_shieldflash_001;
} else if (spriteName.equalsIgnoreCase("fx_shieldflash_002")) {
return fx_shieldflash_002;
} else if (spriteName.equalsIgnoreCase("fx_shieldflash_003")) {
return fx_shieldflash_003;
} else if (spriteName.equalsIgnoreCase("fx_smoke_tendril_001")) {
return fx_smoke_tendril_001;
} else if (spriteName.equalsIgnoreCase("fx_smoke_tendril_002")) {
return fx_smoke_tendril_002;
} else if (spriteName.equalsIgnoreCase("fx_smoke_tendril_003")) {
return fx_smoke_tendril_003;
} else if (spriteName.equalsIgnoreCase("fx_generic_pulse")) {
return fx_generic_pulse;
} else {
return eSprite;
}
}


public void newParticle(Vector2f location, Vector2f velocity, float size, float ratio, float angle, boolean isAdditive, boolean isBlended, String spriteName, Color startColor, Color endColor, float lifeTime, float fadeTime, float growth){
//Don't build new particles if there are already too many.
if(particleList.size() > 1000) return;
//Don't build new particles outside the view-distance.
if(location == null || centerPoint == null) return;
if(MathUtils.getDistanceSquared(location, centerPoint) > longDist) return;
//Weird fix for angle weirdness
angle = angle - 90f;
Vector2f initialSize = new Vector2f(size / ratio, size * ratio);
fx_Particle data = new fx_Particle(pickSprite(spriteName), lifeTime, fadeTime, initialSize, location, velocity, angle, isAdditive, isBlended, startColor, endColor, growth);
particleList.add(data);
}

public Color blend(Color c1, Color c2, float ratio) {
if ( ratio > 1f ) ratio = 1f;
else if ( ratio < 0f ) ratio = 0f;
float iRatio = 1.0f - ratio;

int redOne = Math.min(255,Math.max(0,Math.round((c1.getRed() * iRatio) + (c2.getRed() * ratio))));
int greenOne = Math.min(255,Math.max(0,Math.round((c1.getGreen() * iRatio) + (c2.getGreen() * ratio))));
int blueOne = Math.min(255,Math.max(0,Math.round((c1.getBlue() * iRatio) + (c2.getBlue() * ratio))));
int alphaOne = Math.min(255,Math.max(0,Math.round((c1.getAlpha() * iRatio) + (c2.getAlpha() * ratio))));

return new Color(redOne,greenOne,blueOne,alphaOne);
}

@Override
public void renderInWorldCoords(ViewportAPI vapi) {
if(engine == null) return;
if(engine.isInFastTimeAdvance() || engine.isUIShowingDialog() || engine.isPaused()){ frameTime = 0f; return;}
centerPoint = vapi.getCenter();
//if(centerPoint == null) return;
/*
for(ShipAPI ship : engine.getShips()){
if(!engineList.contains(ship)){
for(ShipEngineAPI sEngine : ship.getEngineController().getShipEngines()){
EngineSlotAPI slot = sEngine.getEngineSlot();
ship.getEngineController().setFlameLevel(slot, 0f);
}
engineList.add(ship);
} else {
ShipEngineControllerAPI sEngineControl = ship.getEngineController();
if(!sEngineControl.isDisabled()
&& !sEngineControl.isFlamedOut()
&& !sEngineControl.isFlamingOut()
){
float angle = ship.getFacing() - 270f;
for(ShipEngineAPI sEngine : sEngineControl.getShipEngines()){
if(!sEngine.isDisabled()){
EngineSlotAPI slot = sEngine.getEngineSlot();
ship.getEngineController().setFlameLevel(slot, 0f);
Vector2f eLoc = sEngine.getLocation();
eSprite.setAngle(angle);
eSprite.setSize(20f, 20f);
eSprite.setColor(Color.yellow);
eSprite.setAdditiveBlend();
eSprite.renderAtCenter(eLoc.getX(), eLoc.getY());
}
}
}
}
}*/

//Runs the projectiles that are generated here, based on their parameters
for (fx_Particle thisParticle : particleList) {
//Don't bother moving or doing any math on dead particles
if(thisParticle.isDead()) continue;
//Age the living particles
thisParticle.timerChange(thisParticle.timeLeft() - frameTime);

float timeLeft = thisParticle.timeLeft();
boolean isFading = thisParticle.isFading();
//Sets this particle to fade out, if we're not already there
if(timeLeft <= 0f && !isFading){
thisParticle.fade();
thisParticle.timerChange(thisParticle.fadeTime);
thisParticle.totalTime = thisParticle.fadeTime;
}

//Kill particles and exit the loop, or move them around and Do Stuff.
if(timeLeft <= 0f && isFading){
thisParticle.kill();
} else {
Vector2f movement = thisParticle.position;
if(frameTime > 0f){
if(thisParticle.isFading){
thisParticle.curColor = blend(new Color(0,0,0,0),thisParticle.endRGB,timeLeft / thisParticle.totalTime);
} else {
if(thisParticle.isBlended){
thisParticle.curColor = blend(thisParticle.endRGB,thisParticle.startRGB,timeLeft / thisParticle.totalTime);
}
}
if (thisParticle.growth != 1.0f) thisParticle.size = new Vector2f(thisParticle.size.getX() * thisParticle.growth, thisParticle.size.getY() * thisParticle.growth);
movement = new Vector2f(movement.getX() + (thisParticle.velocity.getX() * frameTime),
movement.getY() + (thisParticle.velocity.getY() * frameTime));
}
thisParticle.position = movement;
SpriteAPI thisSprite = thisParticle.sprite;
thisSprite.setColor(thisParticle.curColor);
thisSprite.setAngle(thisParticle.angle);
thisSprite.setSize(thisParticle.size.getX(), thisParticle.size.getY());
if(thisParticle.isAdditive){
thisSprite.setAdditiveBlend();
} else {
thisSprite.setBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE_MINUS_SRC_ALPHA);
}
thisSprite.renderAtCenter(movement.getX(), movement.getY());
}
}
}

@Override
public void renderInUICoords(ViewportAPI vapi) {
}
}

Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #8 on: May 30, 2017, 10:49:24 AM »

Hmm.  That might explain the FX issues, but what about the code in the Rebalance mod, that also causes this issue, and doesn't do anything in the rendering cycle at all?

It's either this:
Code
//Drains a smallish amount of Hard Flux per second, depending on ship size and total Flux Capacity.
package data.scripts.plugins;

import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ViewportAPI;
import java.util.List;


public class FluxCapHardFluxDrain implements EveryFrameCombatPlugin
{
CombatEngineAPI engine;

    @Override
public void init(CombatEngineAPI cEngine) {
this.engine = cEngine;
}
       
    @Override
public void advance(float amount, List events)
{
// Obvious exploits are obvious
if (engine == null) return;
if(engine.isInFastTimeAdvance() || engine.isUIShowingDialog() || engine.isPaused()) return;
float drainFraction = 150f;

for (ShipAPI ship : engine.getShips()){
//Skip all the ships that this shouldn't apply to, like ships that are Phased, Venting, etc., etc.
if(!ship.isAlive() || ship.isPhased() || ship.getFluxTracker().isOverloadedOrVenting() || ship.getHardFluxLevel() <= 0f) continue;
//If the ship qualifies for a drain, drain now.
//Start by computing the Drain Threshold, which is a ratio of Capacity vs. a number that results in total drain / second.
//Small stuff gets a better (lower) number here, because they get significantly less Capacity per OP, etc.
if(ship.isDestroyer()){
drainFraction = 250f;
} else if(ship.isCruiser()) {
drainFraction = 350f;
} else if(ship.isCapital()){
drainFraction = 500f;
}
//Now apply the drainThreshold vs Capacity and time elapsed to get the amount of Hard Flux drain this frame
drainFraction = (ship.getMutableStats().getFluxCapacity().getModifiedValue() / drainFraction) * engine.getElapsedInLastFrame();
//Apply time mult here, if that's a thing
if(engine.getTimeMult().getModifiedValue() != 1f){
drainFraction *= engine.getTimeMult().getModifiedValue();
}
//How much Hard Flux should we have now?
if ((ship.getFluxTracker().getHardFlux() - drainFraction) < 0f) {
ship.getFluxTracker().setHardFlux(0f);
} else {
drainFraction = ship.getFluxTracker().getHardFlux() - drainFraction;
//Set it.
ship.getFluxTracker().setHardFlux(drainFraction);
}
}
}

@Override
public void renderInWorldCoords(ViewportAPI vapi) {
}

@Override
public void renderInUICoords(ViewportAPI vapi) {
}
}

Or this:
Code
//What this does:  scales Beam damage w/ range, so that closer ranges mean more Beam damage.
package data.scripts.plugins;

import com.fs.starfarer.api.combat.BeamAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import com.fs.starfarer.api.combat.WeaponAPI.DerivedWeaponStatsAPI;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.DamageType;
import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.MissileAPI;
import com.fs.starfarer.api.combat.ViewportAPI;
import data.scripts.weapons.helperUtils.RebalCollisionCheck;

import org.lazywizard.lazylib.MathUtils;
import data.scripts.weapons.helperUtils.RebalWeaponUtils;
import java.util.List;

public class BeamDamageScalar implements EveryFrameCombatPlugin {
CombatEntityAPI target;
CombatEngineAPI engine;

@Override
public void init(CombatEngineAPI cEngine) {
this.engine = cEngine;
this.target = null;
}

@Override
    public void advance(float amount, List events){
        if(engine == null) return;
if(engine.isInFastTimeAdvance() || engine.isUIShowingDialog() || engine.isPaused()) return;

for(BeamAPI beam : engine.getBeams()){
if(beam.getBrightness() < 0.99f) continue;
if(!beam.didDamageThisFrame()) continue;

//Get the beam's target
target = beam.getDamageTarget();

//If we have a target, target is a Ship or Missile.   
if (target != null && target instanceof ShipAPI || target instanceof MissileAPI) {
boolean damageFlux = false;
if(target instanceof ShipAPI){
ShipAPI sTarg = (ShipAPI) target;
if(sTarg.getShield() != null){
if(sTarg.getShield().isOn() && RebalCollisionCheck.isInShieldArc(sTarg, beam.getTo())){
damageFlux = true;
}
}
}

//Now that we have the target, get the weapon ID and get the adjuested DPS and range
WeaponAPI weapon = beam.getWeapon();
float red = beam.getFringeColor().getRed();
float green = beam.getFringeColor().getGreen();
float blue = beam.getFringeColor().getBlue();

float colorMult = 1.0f;
//Red lasers are much more efficient up close
if(red > (blue + green)){
colorMult = 2.5f;
}
//Green lasers are more efficient than blue / purple
if(green > (blue + (red * 0.5f))){
colorMult = 1.75f;
}

DamageType damType = weapon.getDamageType();
DerivedWeaponStatsAPI stats = weapon.getDerivedStats();
float maxRange = weapon.getRange() * weapon.getShip().getMutableStats().getBeamWeaponRangeBonus().getBonusMult();
//The range is now used to give additional damage output, using how close we are to the target.
//Anything less than 1/3 range is at maximum damage, here at 3X damage (but easily adjusted).
float theRangeMult = Math.min(Math.max(maxRange / MathUtils.getDistance(beam.getTo(), beam.getFrom()),0f),5f) * colorMult;

float dam = (stats.getDps() * amount) / theRangeMult;
float emp = (stats.getEmpPerSecond()) * amount / theRangeMult;

//Do some additional Soft Flux damage now, based on the range
if(!damageFlux){
RebalWeaponUtils.rebalDamageThisEntity(beam.getTo(), target, dam, emp, damType, engine, beam.getSource(), false, true);
} else {
ShipAPI ship = (ShipAPI) target;
ship.getFluxTracker().increaseFlux(dam + emp, true);
}
}
}
    }

@Override
public void renderInWorldCoords(ViewportAPI vapi) {
}

@Override
public void renderInUICoords(ViewportAPI vapi) {
}
}
Logged
Please check out my SS projects :)
Xeno's Mod Pack

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 23986
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #9 on: May 30, 2017, 10:52:27 AM »

But... that code isn't running. You're definitely barking up the wrong tree here - I'd suggest re-evaluating whatever is causing you to think that that code is running, because something about that is wrong.

(Unless, like, you fire up a new thread and explicitly run it from there for some reason. Seriously, that's the only scenario where that could be running. The title screen is deep inside a method call and not cycling through its advance/render loop during the new game creation progress bar stage.)


Maybe a step back: what's the issue? You mentioned a crash of some sort; what's the deal there? Not "probable causes", but what actually happens.
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #10 on: May 30, 2017, 11:01:35 AM »

OK, I'll quit barking up the wrong tree; I'm not doing anything exotic :)

What's happening is that, once you hit "start game", there is a fairly high probability that the game terminates, during the cycle of Jan 1 to March 1, usually but not always before we exit January, after a long wait, where the game halts on that "day".

This appears to more-or-less directly correspond with the numbers on FPS / CPU; the lower both are at the time you hit "start game" the more likely the crash is to occur (at least, that's what appears to be true, but I've only tested this 20 times, as the timeout wait is long). 

What's important is that it doesn't happen, if these scripts aren't running... I think.

Logged
Please check out my SS projects :)
Xeno's Mod Pack

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 23986
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #11 on: May 30, 2017, 11:03:46 AM »

Hmm, weird! Is there an exception in the log when it crashes? Failing that, is there an hs_errXXX.pid file (XXX being a number) somewhere either in the Starsector or in the starsector-core directory?
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #12 on: May 30, 2017, 11:11:31 AM »

To the best of my knowledge, no (just did a search for *.pid, nope), but I'm on my laptop and I forget if I ever replicated the crash on this.  I'll have to check at home in about an hour and a half.

Best way to replicate the bug is to install:

64-bit Java SE 7 (from the 64-bit page)
FX Mod
Rebalance Mod
The Explorer Society

Installing all three at the same time seems to jump the likelihood a lot.

I know I'm compiling for SE 7 (Netbeans default, what we're still recommended to do to keep away from 8's issues).
Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #13 on: May 30, 2017, 11:36:51 AM »

Just verified this on the laptop.  No .pid file was generated.

Sorry, Alex, I know I manage to kill the engine in the weirdest ways...
« Last Edit: May 30, 2017, 11:38:45 AM by xenoargh »
Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: Global.getSector().isInNewGameAdvance()
« Reply #14 on: May 30, 2017, 11:39:58 AM »

Oh and... this might or might not be related... but on the first run, clean SS install... (i.e., Tutorial not-skippable) it didn't crash.  I'll try taking the Tutorial multiple times, perhaps this is a clue.
Logged
Please check out my SS projects :)
Xeno's Mod Pack
Pages: [1] 2