Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Starsector 0.9.1a is out! (05/10/19); Updated the Forum Rules and Guidelines (02/29/20); Blog post: GIF Roundup (04/11/20)

Author Topic: Terrain Modding  (Read 2530 times)

mendonca

  • Global Moderator
  • Admiral
  • *****
  • Posts: 1125
    • View Profile
Terrain Modding
« on: March 02, 2017, 05:52:38 AM »

Hi,

I'm looking in to creating a simple terrain type, and am struggling to understand how to work with existing systems to create my own modified version of, say, a magnetic field.

As there is limited discussion generally about this I thought I would open up a new topic, for future reference of others as well as to serve my own needs.

What I do know:

system.addTerrain(Terrain.TERRAIN_TYPE, new TerrainTypeParams)

would add a general terrain thing.

I therefore need to define Terrain.TERRAIN_TYPE somehow (in com.fs.starfarer.api.impl.campaign.ids.Terrain) to allow the code to understand what my new terrain is called.

I suspect I'll also need to make a TerrainTypePlugin and TerrainTypeParams; say for arguments sake I'll borrow MagneticFieldTerrainPlugin and rename it PlumeTerrainPlugin, and create a similar params file.

All the pieces seem to be there for me to be able to:

a) generate a pretty corona (if I want to)
b) fire off a flare at a FIXED (not random) angle, at a given frequency.
c) color the flare; with possibly a modified version of flareManager to allow different criteria to be set (but I can create a duplicate; modified version of this and call it in a similar manner)

But I'm finding it all a bit impenetrable, and having difficulty (in my head) of closing all the loops of where things act upon other things.

I'm not particularly Java Literate but I am (in the simplest fashion) code literate and can normally figure out how to make something do the same thing as it did but different.

Essentially it seems like I want to mimic the magnetic field; with a fixed angle flare relative to the orbiting object; which will allow for me to create a (variable size) plume of ejecta from an orbiting body. If done correctly I can set angle, colors etc. in the params.

Is this something someone understands and would be able / willing to provide guidance / comment on?

Am I being a bit thick?

Is anybody else looking in to terrain modding and find it really easy (hence limited discussion) - or is it really a little bit complicated?

Thanks for any help.

mendonca
Logged


"I'm doing it, I'm making them purple! No one can stop me!"

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 16600
    • View Profile
Re: Terrain Modding
« Reply #1 on: March 02, 2017, 08:52:27 AM »

Hey!

Some basic stuff: all terrain is defined in data/campaign/terrain.json. The TERRAIN_TYPE you're referring to is just a string that needs to match the key in the terrain.json file. So for example for a magnetic field, you could pass in "magnetic_field" instead of Terrain.MAGNETIC_FIELD. I just tend to put strings into constants in files to avoid typos/make it easier to look up where they're all used.

For example Terrain.java has this in it, along with entries for the other terrain types:
Code: java
public static final String MAGNETIC_FIELD = "magnetic_field";
   
As far as making specifically what you want, I'd suggest copying either the corona or magnetic field terrain plugin (making sure to rename the inner *Params class as well), and then tweaking it, which is pretty much what you're thinking. And, right, adding an entry for it in your mod's terrain.json.

What I suspect you'd want to do is look at the various getAurora*() methods - such as getAuroraThicknessMult() - and then changing them to return values based on a fixed-angle flare rather than using the flare manager, which is responsible for creating random flares.

This is probably going to require setting up an IDE, if you haven't already - or, at least, it'd require more code tweaking for it to compile using Janino if you don't.
Logged

mendonca

  • Global Moderator
  • Admiral
  • *****
  • Posts: 1125
    • View Profile
Re: Terrain Modding
« Reply #2 on: March 10, 2017, 12:47:15 AM »

I've just about got my head round it, but am having problems with a null pointer exception when the AuroraRenderer is being called by my custom terrain type.

First pass, I tried to surgically remove all the flareManager aspects of the StarCoronaTerrainPlugin as I felt like these are not required. After some playing around, and double / triple checking I would not pass a null value to the AuroraRenderer via renderer.advance(amount) call, the problem persists.

That was failing with a null error when starting a new game - but the game would run (with no sign of the terrain type, obviously) when I comment out the renderer.advance(amount) call.

So, second pass, start a new plugin based solely on StarCoronaTerrainPlugin - but this time only changing the parameters of the terrain type (I want to be able to set direction, size, and colour of plume so I need to be able to get this known somehow) and in the first instance just modifying getAuroraThicknessMult to increase the thickness of the aurora at a given range of angles (defined by the parameters).

I tried setting flareProbability to zero (null error) and flareProbability non-zero (null error) with no success so far.

One error (which I can't immediately explain) is that the getRenderRange() is null-ing out with calls to flareManager.

Commenting out this to test, I then get a null at the trusty old renderer.advance(amount) line.

What are the likely causes of null errors in this case? Do I need to set some other information up for e.g. the flareManager to return non-null (but there is a null check in this line anyway?). Is my render range flipping out because I'm changing the dimensions of the Aurora?

For clarity, I'm compiling code in an IDE and it sits in a .jar, called by the .json as relevant. I call the terrain type in the system generation - and whilst I'm setting up the 'aurora' around a 'station' rather than a 'planet' - there seems to be all the right methods in SectorEntityToken to deal with the relevant calls I could make / am making in terms of radius etc.?

Any thoughts welcome.
Logged


"I'm doing it, I'm making them purple! No one can stop me!"

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 16600
    • View Profile
Re: Terrain Modding
« Reply #3 on: March 10, 2017, 07:53:08 AM »

It'd really help to see your full code, as well as a stack trace of the null pointer exception.

If it's actually happening on "renderer.advance(amount)" (and not some call below that), then the only way that could happen is if renderer is null, meaning it was probably not initialized to a new AuroraRenderer() or some such.
Logged

mendonca

  • Global Moderator
  • Admiral
  • *****
  • Posts: 1125
    • View Profile
Re: Terrain Modding
« Reply #4 on: March 10, 2017, 01:11:32 PM »

PlumeTerrainPlugin:
Spoiler
package com.fs.starfarer.api.impl.campaign.terrain;

import java.awt.Color;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

import org.lwjgl.util.vector.Vector2f;

import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.campaign.CampaignEngineLayers;
import com.fs.starfarer.api.campaign.CampaignFleetAPI;
import com.fs.starfarer.api.campaign.PlanetAPI;
import com.fs.starfarer.api.campaign.SectorEntityToken;
import com.fs.starfarer.api.campaign.TerrainAIFlags;
import com.fs.starfarer.api.combat.ViewportAPI;
import com.fs.starfarer.api.fleet.FleetMemberAPI;
import com.fs.starfarer.api.fleet.FleetMemberViewAPI;
import com.fs.starfarer.api.graphics.SpriteAPI;
import com.fs.starfarer.api.impl.campaign.ids.Stats;
import com.fs.starfarer.api.impl.campaign.terrain.AuroraRenderer.AuroraRendererDelegat e;
import com.fs.starfarer.api.impl.campaign.terrain.FlareManager.Flare;
import com.fs.starfarer.api.impl.campaign.terrain.FlareManager.FlareManagerDelegate;
import com.fs.starfarer.api.loading.Description.Type;
import com.fs.starfarer.api.ui.Alignment;
import com.fs.starfarer.api.ui.TooltipMakerAPI;
import com.fs.starfarer.api.util.Misc;

public class PlumeTerrainPlugin extends BaseRingTerrain implements AuroraRendererDelegate, FlareManagerDelegate {
   
   public static final float CR_LOSS_MULT_GLOBAL = 0.25f;
   
   public static class PlumeParams extends RingParams {
      public float windBurnLevel;
      public float flareProbability;
      public float crLossMult;
      public float plumeDir;
      public float plumeWidth;
      public int plumeR;
      public int plumeG;
      public int plumeB;
      
      public PlumeParams(float bandWidthInEngine, float middleRadius,
            SectorEntityToken relatedEntity,
            float windBurnLevel, float flareProbability, float crLossMult, float plumeDir, float plumeWidth, int plumeR, int plumeG, int plumeB) {
         super(bandWidthInEngine, middleRadius, relatedEntity);
         this.windBurnLevel = windBurnLevel;
         this.flareProbability = flareProbability;
         this.crLossMult = crLossMult;
         this.plumeDir = plumeDir;
         this.plumeWidth = plumeWidth;
         this.plumeR = plumeR;
         this.plumeG = plumeG;
         this.plumeB = plumeB;
      }
   }
   
   transient protected SpriteAPI texture = null;
   transient protected Color color;
   
   protected AuroraRenderer renderer;
   protected FlareManager flareManager;
   protected PlumeParams params;
   
   public void init(String terrainId, SectorEntityToken entity, Object param) {
      super.init(terrainId, entity, param);
      params = (PlumeParams) param;
      if (params.name == null) {
         params.name = "Plume";
      }
   }
   
   @Override
   Object readResolve() {
      super.readResolve();
      texture = Global.getSettings().getSprite("terrain", "aurora");
      layers = EnumSet.of(CampaignEngineLayers.TERRAIN_7);
      if (renderer == null) {
         renderer = new AuroraRenderer(this);
      }
      if (flareManager == null) {
         flareManager = new FlareManager(this);
      }
      return this;
   }
   
   Object writeReplace() {
      return this;
   }
   
   @Override
   protected boolean shouldPlayLoopOne() {
      return super.shouldPlayLoopOne() && !flareManager.isInActiveFlareArc(Global.getSector().getPlayerFleet());
   }

   @Override
   protected boolean shouldPlayLoopTwo() {
      return super.shouldPlayLoopTwo() && flareManager.isInActiveFlareArc(Global.getSector().getPlayerFleet());
   }



   transient private EnumSet<CampaignEngineLayers> layers = EnumSet.of(CampaignEngineLayers.TERRAIN_7);
   public EnumSet<CampaignEngineLayers> getActiveLayers() {
      return layers;
   }

   public PlumeParams getParams() {
      return params;
   }

   public void advance(float amount) {
      super.advance(amount);
      renderer.advance(amount);
      flareManager.advance(amount);
   }

   public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
      renderer.render(viewport.getAlphaMult());
   }
   
   @Override
   public float getRenderRange() {
      //Flare curr = flareManager.getActiveFlare();
      //if (curr != null) {
      //   float outerRadiusWithFlare = computeRadiusWithFlare(flareManager.getActiveFlare());
      //   return outerRadiusWithFlare + 200f;
      //}
      return super.getRenderRange();
   }
   
   @Override
   public boolean containsPoint(Vector2f point, float radius) {
      if (flareManager.isInActiveFlareArc(point)) {
         float outerRadiusWithFlare = computeRadiusWithFlare(flareManager.getActiveFlare());
         float dist = Misc.getDistance(this.entity.getLocation(), point);
         if (dist > outerRadiusWithFlare + radius) return false;
         if (dist + radius < params.middleRadius - params.bandWidthInEngine / 2f) return false;
         return true;
      }
      return super.containsPoint(point, radius);
   }
   
   protected float computeRadiusWithFlare(Flare flare) {
      float inner = getAuroraInnerRadius();
      float outer = params.middleRadius + params.bandWidthInEngine * 0.5f;
      float thickness = outer - inner;
      
      thickness *= flare.extraLengthMult;
      thickness += flare.extraLengthFlat;
      
      return inner + thickness;
   }
   
   @Override
   protected float getExtraSoundRadius() {
      float base = super.getExtraSoundRadius();
      
      float angle = Misc.getAngleInDegrees(params.relatedEntity.getLocation(), Global.getSector().getPlayerFleet().getLocation());
      float extra = 0f;
      if (flareManager.isInActiveFlareArc(angle)) {
         extra = computeRadiusWithFlare(flareManager.getActiveFlare()) - params.bandWidthInEngine;
      }
      //System.out.println("Extra: " + extra);
      return base + extra;
   }
   

   @Override
   public void applyEffect(SectorEntityToken entity, float days) {
      if (entity instanceof CampaignFleetAPI) {
         CampaignFleetAPI fleet = (CampaignFleetAPI) entity;
         
         boolean inFlare = false;
         if (flareManager.isInActiveFlareArc(fleet)) {
            inFlare = true;
         }
         
         float intensity = getIntensityAtPoint(fleet.getLocation());
         if (intensity <= 0) return;

         String buffId = getModId();
         float buffDur = 0.1f;
         
         // CR loss
         for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
            float recoveryRate = member.getStats().getBaseCRRecoveryRatePercentPerDay().getModifiedValue();
            float lossRate = member.getStats().getBaseCRRecoveryRatePercentPerDay().getBaseValue();
            
            float resistance = member.getStats().getDynamic().getValue(Stats.CORONA_RESISTANCE);
            //if (inFlare) loss *= 2f;
            float lossMult = 1f;
            if (inFlare) lossMult = 2f;
            float adjustedLossMult = (0f + params.crLossMult * intensity * resistance * lossMult * CR_LOSS_MULT_GLOBAL);
            
            float loss = (-1f * recoveryRate + -1f * lossRate * adjustedLossMult) * days * 0.01f;
            float curr = member.getRepairTracker().getBaseCR();
            if (loss > curr) loss = curr;
            if (inFlare) {
               member.getRepairTracker().applyCREvent(loss, "flare", "Solar flare effect");
            } else {
               member.getRepairTracker().applyCREvent(loss, "corona", "Star corona effect");
            }
            
            float peakFraction = 1f / Math.max(1.3333f, 1f + params.crLossMult * intensity);
            float peakLost = 1f - peakFraction;
            peakLost *= resistance;
            
            float degradationMult = 1f + (params.crLossMult * intensity * resistance) / 2f;
            
            member.getBuffManager().addBuffOnlyUpdateStat(new PeakPerformanceBuff(buffId + "_1", 1f - peakLost, buffDur));
            member.getBuffManager().addBuffOnlyUpdateStat(new CRLossPerSecondBuff(buffId + "_2", degradationMult, buffDur));
         }
         
         // "wind" effect - adjust velocity
         float maxFleetBurn = fleet.getFleetData().getBurnLevel();
         float currFleetBurn = fleet.getCurrBurnLevel();
         
         float maxWindBurn = params.windBurnLevel;
         if (inFlare) {
            maxWindBurn *= 2f;
         }
         
         
         float currWindBurn = intensity * maxWindBurn;
         float maxFleetBurnIntoWind = maxFleetBurn - currWindBurn;
         
         float angle = Misc.getAngleInDegrees(this.entity.getLocation(), fleet.getLocation());
         Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(angle);
         Vector2f velDir = Misc.normalise(new Vector2f(fleet.getVelocity()));
         velDir.scale(currFleetBurn);
         
         float fleetBurnAgainstWind = -1f * Vector2f.dot(windDir, velDir);
         
         float accelMult = 0.5f;
         if (fleetBurnAgainstWind > maxFleetBurnIntoWind) {
            accelMult += 0.75f + 0.25f * (fleetBurnAgainstWind - maxFleetBurnIntoWind);
         }
         
         float seconds = days * Global.getSector().getClock().getSecondsPerDay();
         
         Vector2f vel = fleet.getVelocity();
         windDir.scale(seconds * fleet.getAcceleration() * accelMult);
         fleet.setVelocity(vel.x + windDir.x, vel.y + windDir.y);
         
         Color glowColor = getAuroraColorForAngle(angle);
         int alpha = glowColor.getAlpha();
         if (alpha < 75) {
            glowColor = Misc.setAlpha(glowColor, 75);
         }
         // visual effects - glow, tail
         
         float durIn = 1f;
         float durOut = 10f;
         Misc.normalise(windDir);
         float sizeNormal = 5f + 10f * intensity;
         float sizeFlare = 10f + 15f * intensity;
         for (FleetMemberViewAPI view : fleet.getViews()) {
            if (inFlare) {
               view.getWindEffectDirX().shift(getModId() + "_flare", windDir.x * sizeFlare, durIn, durOut, 1f);
               view.getWindEffectDirY().shift(getModId() + "_flare", windDir.y * sizeFlare, durIn, durOut, 1f);
               view.getWindEffectColor().shift(getModId() + "_flare", glowColor, durIn, durOut, intensity);
            } else {
               view.getWindEffectDirX().shift(getModId(), windDir.x * sizeNormal, durIn, durOut, 1f);
               view.getWindEffectDirY().shift(getModId(), windDir.y * sizeNormal, durIn, durOut, 1f);
               view.getWindEffectColor().shift(getModId(), glowColor, durIn, durOut, intensity);
            }
         }
      }
   }
   
   public float getIntensityAtPoint(Vector2f point) {
      float angle = Misc.getAngleInDegrees(params.relatedEntity.getLocation(), point);
      float maxDist = params.bandWidthInEngine;
      if (flareManager.isInActiveFlareArc(angle)) {
         maxDist = computeRadiusWithFlare(flareManager.getActiveFlare());
      }
      float minDist = params.relatedEntity.getRadius();
      float dist = Misc.getDistance(point, params.relatedEntity.getLocation());
      
      if (dist > maxDist) return 0f;
      
      float intensity = 1f;
      if (minDist < maxDist) {
         intensity = 1f - (dist - minDist) / (maxDist - minDist);
         //intensity = 0.5f + intensity * 0.5f;
         if (intensity < 0) intensity = 0;
         if (intensity > 1) intensity = 1;
      }
      
      return intensity;
   }
   
   
   
   @Override
   public Color getNameColor() {
      Color bad = Misc.getNegativeHighlightColor();
      Color base = super.getNameColor();
      //bad = Color.red;
      return Misc.interpolateColor(base, bad, Global.getSector().getCampaignUI().getSharedFader().getBrightness() * 1f);
   }

   public boolean hasTooltip() {
      return true;
   }
   
   public void createTooltip(TooltipMakerAPI tooltip, boolean expanded) {
      float pad = 10f;
      float small = 5f;
      Color gray = Misc.getGrayColor();
      Color highlight = Misc.getHighlightColor();
      Color fuel = Global.getSettings().getColor("progressBarFuelColor");
      Color bad = Misc.getNegativeHighlightColor();
      
      tooltip.addTitle(params.name);
      tooltip.addPara(Global.getSettings().getDescription(getTerrainId(), Type.TERRAIN).getText1(), pad);
      
      float nextPad = pad;
      if (expanded) {
         tooltip.addSectionHeading("Travel", Alignment.MID, pad);
         nextPad = small;
      }
      tooltip.addPara("Reduces the combat readiness of " +
            "all ships in the plume at a steady pace.", nextPad);
      tooltip.addPara("The fields of high velocity micro-debris disrupt the ships systems.", pad);
      
      if (expanded) {
         tooltip.addSectionHeading("Combat", Alignment.MID, pad);
         tooltip.addPara("Reduces the peak performance time of ships and increases the rate of combat readiness degradation in protracted engagements.", small);
      }
      
      //tooltip.addPara("Does not stack with other similar terrain effects.", pad);
   }
   
   public boolean isTooltipExpandable() {
      return true;
   }
   
   public float getTooltipWidth() {
      return 350f;
   }
   
   public String getTerrainName() {
      if (flareManager.isInActiveFlareArc(Global.getSector().getPlayerFleet())) {
         return "Plume Flare";
      }
      return params.name;
   }
   
   public String getEffectCategory() {
      return null; // to ensure multiple coronas overlapping all take effect
      //return "corona_" + (float) Math.random();
   }

   public float getAuroraAlphaMultForAngle(float angle) {
      return 1f;
   }

   public float getAuroraBandWidthInTexture() {
      return 256f;
      //return 512f;
   }
   
   public float getAuroraTexPerSegmentMult() {
      return 1f;
      //return 2f;
   }

   public Vector2f getAuroraCenterLoc() {
      return params.relatedEntity.getLocation();
   }

   public Color getAuroraColorForAngle(float angle) {
      if (color == null) {
         if (params.relatedEntity instanceof PlanetAPI) {
            color = ((PlanetAPI)params.relatedEntity).getSpec().getCoronaColor();
            //color = Misc.interpolateColor(color, Color.white, 0.5f);
         } else {
            color = Color.white;
         }
         color = Misc.setAlpha(color, 25);
      }
      if (flareManager.isInActiveFlareArc(angle)) {
         return flareManager.getColorForAngle(color, angle);
      }
      return color;
   }

   public float getAuroraInnerRadius() {
      return params.relatedEntity.getRadius() + 10f;
   }

   public float getAuroraOuterRadius() {
      return params.middleRadius + params.bandWidthInEngine * 0.5f;
   }

   public float getAuroraShortenMult(float angle) {
      return 0.85f + flareManager.getShortenMod(angle);
   }
   
   public float getAuroraInnerOffsetMult(float angle) {
      return flareManager.getInnerOffsetMult(angle);
   }

   public SpriteAPI getAuroraTexture() {
      return texture;
   }

   public float getAuroraThicknessFlat(float angle) {
      if (flareManager.isInActiveFlareArc(angle)) {
         return flareManager.getExtraLengthFlat(angle);
      }
      return 0;
   }

   public float getAuroraThicknessMult(float angle) {
      if (flareManager.isInActiveFlareArc(angle)) {
         return flareManager.getExtraLengthMult(angle);
      }
      float face_trouser = params.plumeWidth / 2;
      float nose_beak = 1f;
      float ear_sweeper = 1f;
      float cheek_piston = 1f;
      if (angle > params.plumeDir - face_trouser && angle < params.plumeDir + face_trouser) {
      if (angle < params.plumeDir) {  nose_beak = params.plumeDir - angle;
      } else { nose_beak = angle - params.plumeDir;
      }
      ear_sweeper = params.plumeWidth - nose_beak;
      if (ear_sweeper == 0) {return 0.2f;} else { cheek_piston = ( ear_sweeper * 2f ) / params.plumeWidth; }
      return cheek_piston + 0.2f;
      }
      return 0.2f;
   }
   
   
   
   

   public List<Color> getFlareColorRange() {
      List<Color> result = new ArrayList<Color>();
      
      if (params.relatedEntity instanceof PlanetAPI) {
         Color color = ((PlanetAPI)params.relatedEntity).getSpec().getCoronaColor();
         result.add(Misc.setAlpha(color, 255));
      } else {
         result.add(Color.white);
      }
      //result.add(Misc.setAlpha(getAuroraColorForAngle(0), 127));
      return result;
   }
   
   public float getFlareArcMax() {
      return 60;
   }
   
   public float getFlareArcMin() {
      return 30;
   }

   public float getFlareExtraLengthFlatMax() {
      return 500;
   }

   public float getFlareExtraLengthFlatMin() {
      return 200;
   }

   public float getFlareExtraLengthMultMax() {
      return 1.5f;
   }

   public float getFlareExtraLengthMultMin() {
      return 1;
   }

   public float getFlareFadeInMax() {
      return 10f;
   }

   public float getFlareFadeInMin() {
      return 3f;
   }

   public float getFlareFadeOutMax() {
      return 10f;
   }

   public float getFlareFadeOutMin() {
      return 3f;
   }

   public float getFlareOccurrenceAngle() {
      return 0;
   }

   public float getFlareOccurrenceArc() {
      return 360f;
   }

   public float getFlareProbability() {
      return params.flareProbability;
   }

   public float getFlareSmallArcMax() {
      return 20;
   }

   public float getFlareSmallArcMin() {
      return 10;
   }

   public float getFlareSmallExtraLengthFlatMax() {
      return 100;
   }

   public float getFlareSmallExtraLengthFlatMin() {
      return 50;
   }

   public float getFlareSmallExtraLengthMultMax() {
      return 1.05f;
   }

   public float getFlareSmallExtraLengthMultMin() {
      return 1;
   }

   public float getFlareSmallFadeInMax() {
      return 2f;
   }

   public float getFlareSmallFadeInMin() {
      return 1f;
   }

   public float getFlareSmallFadeOutMax() {
      return 2f;
   }

   public float getFlareSmallFadeOutMin() {
      return 1f;
   }

   public float getFlareShortenFlatModMax() {
      return 0.05f;
   }

   public float getFlareShortenFlatModMin() {
      return 0.05f;
   }

   public float getFlareSmallShortenFlatModMax() {
      return 0.05f;
   }

   public float getFlareSmallShortenFlatModMin() {
      return 0.05f;
   }

   public int getFlareMaxSmallCount() {
      return 3;
   }

   public int getFlareMinSmallCount() {
      return 5;
   }

   public float getFlareSkipLargeProbability() {
      return 0f;
   }

   public SectorEntityToken getFlareCenterEntity() {
      return this.entity;
   }
   
   public boolean hasAIFlag(Object flag) {
      return flag == TerrainAIFlags.CR_DRAIN ||
            flag == TerrainAIFlags.EFFECT_DIMINISHED_WITH_RANGE;
   }
   
   public float getMaxEffectRadius(Vector2f locFrom) {
      float angle = Misc.getAngleInDegrees(params.relatedEntity.getLocation(), locFrom);
      float maxDist = params.bandWidthInEngine;
      if (flareManager.isInActiveFlareArc(angle)) {
         maxDist = computeRadiusWithFlare(flareManager.getActiveFlare());
      }
      return maxDist;
   }
   public float getMinEffectRadius(Vector2f locFrom) {
      return 0f;
   }
   
   public float getOptimalEffectRadius(Vector2f locFrom) {
      return params.relatedEntity.getRadius();
   }
   
   public boolean canPlayerHoldStationIn() {
      return false;
   }
}
[close]

Stack Trace:
Spoiler
36043 [Thread-5] INFO  com.fs.starfarer.loading.scripts.OoOO  - Loading class: com.fs.starfarer.api.impl.campaign.terrain.AuroraRenderer
36059 [Thread-5] INFO  com.fs.profiler.Profiler  - ID                                                                                                                                                                                                                                                                                     Calls   Duration    Percent
36059 [Thread-5] INFO  com.fs.profiler.Profiler  - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
36060 [Thread-5] INFO  com.fs.profiler.Profiler  - Main loop in Title Screen State                                                                                                                                                                                                                                                           95      1.85s    100.00%
36060 [Thread-5] INFO  com.fs.profiler.Profiler  -   CombatEngine.advance()                                                                                                                                                                                                                                                                  95      0.85s     46.00%
36060 [Thread-5] INFO  com.fs.profiler.Profiler  -     Advancing entities                                                                                                                                                                                                                                                                    95      0.38s     20.45%
36061 [Thread-5] INFO  com.fs.profiler.Profiler  -       Ship.advance()                                                                                                                                                                                                                                                                    1564      0.35s     18.94%
36061 [Thread-5] INFO  com.fs.profiler.Profiler  -         Advancing weapon groups                                                                                                                                                                                                                                                         1564      0.21s     11.31%
36061 [Thread-5] INFO  com.fs.profiler.Profiler  -           Advance group                                                                                                                                                                                                                                                                 2668      0.19s     10.17%
36061 [Thread-5] INFO  com.fs.profiler.Profiler  -             Advancing weapon AI                                                                                                                                                                                                                                                         5521      0.11s      6.22%
36061 [Thread-5] INFO  com.fs.profiler.Profiler  -               BasicWeaponAI.advance()                                                                                                                                                                                                                                                   5521      0.11s      6.11%
36061 [Thread-5] INFO  com.fs.profiler.Profiler  -                 Other                                                                                                                                                                                                                                                                      -      0.11s      6.01%
36062 [Thread-5] INFO  com.fs.profiler.Profiler  -                 Computing FF danger                                                                                                                                                                                                                                                      140      0.00s      0.11%
36062 [Thread-5] INFO  com.fs.profiler.Profiler  -                 Checking if ship hulks are in the way                                                                                                                                                                                                                                    191      0.00s      0.00%
36062 [Thread-5] INFO  com.fs.profiler.Profiler  -               Other                                                                                                                                                                                                                                                                        -      0.00s      0.11%
36062 [Thread-5] INFO  com.fs.profiler.Profiler  -             Advancing individual weapon                                                                                                                                                                                                                                                 5521      0.04s      2.16%
36062 [Thread-5] INFO  com.fs.profiler.Profiler  -               Advancing projectile weapon                                                                                                                                                                                                                                               5187      0.03s      1.68%
36062 [Thread-5] INFO  com.fs.profiler.Profiler  -               Advancing beam weapon                                                                                                                                                                                                                                                      334      0.01s      0.27%
36063 [Thread-5] INFO  com.fs.profiler.Profiler  -               Other                                                                                                                                                                                                                                                                        -      0.00s      0.22%
36063 [Thread-5] INFO  com.fs.profiler.Profiler  -             Other                                                                                                                                                                                                                                                                          -      0.02s      0.92%
36063 [Thread-5] INFO  com.fs.profiler.Profiler  -             Linked & alternating                                                                                                                                                                                                                                                         762      0.02s      0.87%
36063 [Thread-5] INFO  com.fs.profiler.Profiler  -               Advancing projectile weapon                                                                                                                                                                                                                                               1106      0.01s      0.76%
36063 [Thread-5] INFO  com.fs.profiler.Profiler  -               Other                                                                                                                                                                                                                                                                        -      0.00s      0.11%
36063 [Thread-5] INFO  com.fs.profiler.Profiler  -               Advancing beam weapon                                                                                                                                                                                                                                                       34      0.00s      0.00%
36064 [Thread-5] INFO  com.fs.profiler.Profiler  -           Other                                                                                                                                                                                                                                                                            -      0.01s      0.60%
36064 [Thread-5] INFO  com.fs.profiler.Profiler  -           Selection & AF status                                                                                                                                                                                                                                                         2668      0.01s      0.54%
36064 [Thread-5] INFO  com.fs.profiler.Profiler  -         Other                                                                                                                                                                                                                                                                              -      0.13s      6.87%
36064 [Thread-5] INFO  com.fs.profiler.Profiler  -         Advancing projectile weapon                                                                                                                                                                                                                                                      552      0.01s      0.27%
36064 [Thread-5] INFO  com.fs.profiler.Profiler  -         Linked & alternating                                                                                                                                                                                                                                                             147      0.01s      0.27%
36064 [Thread-5] INFO  com.fs.profiler.Profiler  -           Advancing projectile weapon                                                                                                                                                                                                                                                    147      0.01s      0.27%
36065 [Thread-5] INFO  com.fs.profiler.Profiler  -           Other                                                                                                                                                                                                                                                                            -      0.00s      0.00%
36065 [Thread-5] INFO  com.fs.profiler.Profiler  -         Updating armor state                                                                                                                                                                                                                                                              20      0.00s      0.22%
36065 [Thread-5] INFO  com.fs.profiler.Profiler  -       Other                                                                                                                                                                                                                                                                                -      0.03s      1.52%
36065 [Thread-5] INFO  com.fs.profiler.Profiler  -     CombatState AI                                                                                                                                                                                                                                                                        95      0.25s     13.42%
36065 [Thread-5] INFO  com.fs.profiler.Profiler  -       Advancing entity AI                                                                                                                                                                                                                                                                 95      0.21s     11.53%
36065 [Thread-5] INFO  com.fs.profiler.Profiler  -         Ship AI                                                                                                                                                                                                                                                                          276      0.11s      5.79%
36066 [Thread-5] INFO  com.fs.profiler.Profiler  -           Other                                                                                                                                                                                                                                                                            -      0.03s      1.46%
36066 [Thread-5] INFO  com.fs.profiler.Profiler  -           Maneuver direct control                                                                                                                                                                                                                                                        187      0.02s      0.87%
36066 [Thread-5] INFO  com.fs.profiler.Profiler  -             StrafeTargetManeuverV2                                                                                                                                                                                                                                                        92      0.01s      0.38%
36066 [Thread-5] INFO  com.fs.profiler.Profiler  -               Other                                                                                                                                                                                                                                                                        -      0.00s      0.22%
36066 [Thread-5] INFO  com.fs.profiler.Profiler  -               Computing ship threat                                                                                                                                                                                                                                                      147      0.00s      0.16%
36066 [Thread-5] INFO  com.fs.profiler.Profiler  -                 Other                                                                                                                                                                                                                                                                      -      0.00s      0.16%
36067 [Thread-5] INFO  com.fs.profiler.Profiler  -                 Checking if ship hulks are in the way                                                                                                                                                                                                                                    147      0.00s      0.00%
36067 [Thread-5] INFO  com.fs.profiler.Profiler  -             Other                                                                                                                                                                                                              &nbs
[close]
« Last Edit: March 10, 2017, 01:26:16 PM by mendonca »
Logged


"I'm doing it, I'm making them purple! No one can stop me!"

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 16600
    • View Profile
Re: Terrain Modding
« Reply #5 on: March 10, 2017, 01:23:55 PM »

I think you need to call readResolve() from the init() method - unless I'm missing something, the issue is indeed that "renderer" is not being initialized.

The other stuff you posted isn't actually a stack trace (unless I've missed some of it?); for a null pointer exception, look for a line that says something like:

Code: java
Exception in thread "main" java.lang.NullPointerException

And then include that and everything similar-looking below that.


Edit: to explain a bit, the readResolve() method gets called automatically when a save game is loaded. Since it does some initialization here - of things that aren't saved, and so need to be re-created on game load - it's commonly also called from a constructor or an init() method to do the same job at object creation/initialization.
« Last Edit: March 10, 2017, 01:25:33 PM by Alex »
Logged

mendonca

  • Global Moderator
  • Admiral
  • *****
  • Posts: 1125
    • View Profile
Re: Terrain Modding
« Reply #6 on: March 10, 2017, 01:28:58 PM »

Oh hey, I lost half the post (including the bit where I said 'thanks' ...)

I think I might have overdone the amount of stuff I posted and it cut the important bits off ...

Spoiler
36095 [Thread-5] ERROR com.fs.starfarer.combat.CombatMain  - java.lang.NullPointerException
java.lang.NullPointerException
   at com.fs.starfarer.api.impl.campaign.terrain.PlumeTerrainPlugin.advance(PlumeTerrainPlugin.java:114)
   at com.fs.starfarer.campaign.CampaignTerrain.advance(Unknown Source)
   at com.fs.starfarer.campaign.BaseLocation.advance(Unknown Source)
   at com.fs.starfarer.campaign.CampaignEngine.advance(Unknown Source)
   at com.fs.starfarer.campaign.save.CampaignGameManager.super(Unknown Source)
   at com.fs.starfarer.title.TitleScreenState.dialogDismissed(Unknown Source)
   at com.fs.starfarer.ui.M.dismiss(Unknown Source)
   at com.fs.starfarer.ui.impl.oooO.dismiss(Unknown Source)
   at com.fs.starfarer.campaign.save.if.actionPerformed(Unknown Source)
   at com.fs.starfarer.ui.h.o00000(Unknown Source)
   at com.fs.starfarer.ui.null.processInput(Unknown Source)
   at com.fs.starfarer.ui.ooOo.o00000(Unknown Source)
   at com.fs.starfarer.BaseGameState.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(Unknown Source)
[close]

(thanks again ...)
Logged


"I'm doing it, I'm making them purple! No one can stop me!"

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 16600
    • View Profile
Re: Terrain Modding
« Reply #7 on: March 10, 2017, 01:42:41 PM »

Oops :)

Looking at the stacktrace - yep, confirms what I was thinking.
Logged

mendonca

  • Global Moderator
  • Admiral
  • *****
  • Posts: 1125
    • View Profile
Re: Terrain Modding
« Reply #8 on: March 10, 2017, 02:01:12 PM »

Cool, thank you very much.

I guess I assumed as StarCoronaTerrainPlugin worked that I wouldn't need to alter any of the initialisation of things.

Crash resolved, I can try and figure the rest out now ...  :)

(see you in a week or so, no doubt ...)
Logged


"I'm doing it, I'm making them purple! No one can stop me!"

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 16600
    • View Profile
Re: Terrain Modding
« Reply #9 on: March 10, 2017, 02:06:28 PM »

Hm, that *is* weird.

super.init(terrainId, entity, param); -> that calls readResolve(), which is why StarCoronaTerrainPlugin works. And, as you say, it ought to work in your case as well. That actually doesn't make any sense.
Logged