Miscellaneous modding tidbits

From Starsector Wiki
Jump to navigation Jump to search

This page is to hold any miscellaneous modding tidbits which are too insightful to discard but do not currently well fit anywhere specific

  • Mac systems cannot play .wav format files, use .ogg instead
  • Check if in refit screen via original owner value being -1, i.e.
    if (ship.getOriginalOwner() == -1){do something}
  • BaseModPlugin method call order is onNewGame -> onNewGameAfterProcGen -> onNewGameAfterEconomyLoad -> onEnabled -> onNewGameAfterTimePass -> onGameLoad
  • Fighter wings without an autofit tag (like "bomber3", "fighter6", etc) in wing_data.csv will not show up in the refit menu for missions. This is mostly useful for exclusive built-ins. Generally speaking if your fighter wing has "no_drop, no_sell", it should not have an autofit tag.
  • weapon sprites with an odd number pixel width will blur in the inventory screen
  • Vanilla scripts that are compiled can be found within \Starsector\starsector-core\starfarer.api.zip
  • Vanilla AOE can never deal less than half of its max damage. So yes it has a linear falloff from the inner and outer radius, but then stops getting weaker at half the listed damage. (version 0.8.1a-RC8)
  • Hide decorative weapons in the preview image of a ship; you need to have a 2 frame animation with the first frame empty, the second frame with the deco and a framerate of 0. Then you add a script that'll only run once and just check if you are in refit or deployed and change the frame in the latter case
  • Case sensitivity is important. Windows systems will often overlook differences in case but it will crash 'Nix systems
  • a module only needs none-zero ordnance points to be able to be refitted
  • scripts in \data\scripts\ and subdirectories will be automatically compiled
  • java.lang.RuntimeException: Error loading messages may include your mod name, as missing resources are searched for in every mod folder before Starsector gives up and all active mods should be included in that error message
  • missiles may potentially stop ticking their "elapsed" counter without being flagged "dealtDamage" if the missile is destroyed by weapons fire
  • The final modified value of mutable stats is floored at zero (Version 0.8.1a-RC8)
  • Starsector's JSON parser has been modified to allow java style comments. It has some quirks and in particular it is not recommended to use JSON comments for issue isolation identification, as it will not behave as expected in 100% of situations
  • EveryFrameCombatPlugin should perform a sanity check [1]regarding EveryFrameCombatPlugin main menu behaviour, such as "if (engine == null) return"
  • Almost all sprites need to be saved in 8 bit colour mode, not 16 bit
  • It's a good rule of thumb not to use static inside a plugin, due to potential garbage collection prevention issues[2]
  • One in-game day is 10 seconds
  • Default relative position of angles in the game engine is to the right, 0 degrees is to the right. It also moves anti-clockwise so 90 degrees is pointing straight upwards
  • Ship death explosion radius is collision radius + 200
  • SS does optimization bullshit, via polling for detecting if a hit occurred more often the faster the shot is! And it will speed up this check when the shot is near a shield or collision radius, distilled down into finite iterating radius checks using bin lattice bullshit. So if a shot is forced to move FAR faster than its listed stat in the .csv? It can pass all the way through targets or hit inside of them!
  • Ship system states

Mutually exclusive states, only one at a time. IDLE -> IN -> ACTIVE -> OUT -> COOLDOWN -> (loops)

  • IDLE - When it is not in use nor on cooldown
  • IN - After activating while still charging up. effectLevel between 0 & 1
  • ACTIVE - When activated, completed chargeup and not yet started winding down. effectiveLevel is 1
  • OUT - When activated, completed IN & ACTIVE and now winding down but not yet in cooldown. effectLevel between 1 & 0
  • COOLDOWN - When OUT completed but not finished cooldown
  • Missile impact values govern the impact imparted to ships when the missile goes dud, high values get multiplied and can lead to impact glitches the likes of ship flying off the map as seen with the Scyan Singularity Torpedo (until now that is). Unless necessary for the weapon to function correctly, this value should stay within vanilla range (0 to 75)
  • How do modifyPercent or modifyMult stack with themselves?
  • modifyPercent(String, float) & modifyPercent(String, float, String) are both additive
  • modifyMult(String, float) & modifyMult(String, float, String) are both multiplicative
  • The missileTypes used in vanilla are BOMB, BOMB_WITH_SLOW, FLARE, FLARE_JAMMER, FLARE_SEEKER, MIRV, MISSILE, MISSILE_TWO_STAGE_SECOND_UNGUIDED, NO_AI, PHASE_CHARGE, PHASE_MINE, and ROCKET
  • When testing your mods I'd recommend running Starsector via the bat and adding this (on a new line) to the end of the bat file:

if %errorlevel% neq 0 pause

That will make the command prompt stay open if there's a crash, letting you see the stack trace and preceding log lines immediately rather than needing to open starsector.log.

  • BaseEveryFrameCombatPlugin scripts are triggered by adding them into the settings.json plugins list (or put it in data/scripts/plugins as a loose script, so you probably won't want to go that route)
  • Weapon sprite center should always be between pixels; if the mounting point is not on a half pixel and your weapon sprite is also on a half pixel it may blur it

STATIC keyword

Be careful using the STATIC keyword. The STATIC keyword in java means that it will not be garbage collected. Storing anything other than primitives or strings in static variables is an easy way to cause memory leaks and/or save file bloating. Storing API objects in static variables would be particularly bad as it could store an entire tree of objects.
Instances of the log4j logger need to be static and static variables are preferable for storing shared primitives or strings instead of in files or custom data for memory & performance reasons.
For shared custom data that are not primitives or strings consider using SectorAPI.getPersistentData() or CombatEngineAPI.getCustomData(). Both return a Map<String, Object>. You put your data using a unique String ID as the key and the data as the value and any other class can retrieve it using that key.
The real danger is when someone is tempted to use something like static ShipAPI player so they can easily reference it in other scripts. That variable will retain its value until its changed, so even if you clear it in a plugin's init(), it'll still stick around on the campaign layer (along with the entire combat engine, if the ship's class references it) until the next combat starts and it's set to a new value.
The worst memory leak in Starsector's history was almost certainly in the Omnifactory mod. In one old version it stored a list of the active factories in your current game in a static variable, but due to the API of the time lacking 90% of its current methods there was no way to detect when a new campaign was loaded, so that list was never cleared. That meant every time you loaded a save the old campaign was kept around in memory for the rest of that game session. And this bug stacked. All due to a single line of erroneous code.

Stat bonuses order

the formula for stat calculations is

        modified = base + base * percentMod / 100f + flatMod;
        modified *= mult;

So percent mods are applied to the base, flat mods are (oddly enough) added as flat bonuses, and multipliers are applied to the modified value of base+percent+flat.

Percent mods are also additive (two +50% mods will add 100% of base, and a +50 and -50 will cancel out), whereas multipliers are multiplicative (two .5s will equal .25, a 1.5 and a 0.5 will equal 0.75). So you could reliably set a stat to zero with modifyMult(0f), but couldn't do the same with percent or flat mods.

Linux / Mac file path compatibility

Use / instead of \ in paths for compatibility (required to work on OS X and Linux).

Multithreading

The game logic is single-threaded, so you'll never need to worry about concurrency issues unless you create them yourself.

---

Icon cross.png
At least two versions out of date. Last verified for version 0.8.1a. Please refer to Version History and update this page.

---

Return to Modding