Fractal Softworks Forum

Please login or register.

Login with username, password and session length

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - float

Pages: [1] 2
1
Ship Mastery System
 

Gain mastery in ship hulls to unlock S-mod slots and additional bonuses. (Sort of) a spiritual successor to Progressive S-Mods.

Requires Particle Engine.


Ship Masteries

  • Gain mastery points (MP) in a specific ship type randomly while gaining XP.
    • XP gained from combat has a chance to grant MP in combat ship types in your fleet.
    • XP gained from any other source has a chance to grant MP in civilian ship types in your fleet.
  • MP can also be acquired by consuming knowledge constructs, which appear as rare loot under certain circumstances.
  • Use MP to build in hullmods or advance your mastery level in a specific ship type.
    • Each ship type (a.k.a. hull spec) has its own MP pool that is shared between all ships of that type.
    • Mastery level and mastery selections (for levels that have more than one option) are also shared between all ships of a ship type.
  • Advancing your mastery of a ship type improves its performance in a variety of ways. Some mastery levels have randomized bonuses, while others' are fixed.




Revamped S-Mod System

  • All ships start with 0 S-mod capacity. Level up ship mastery to gain S-mod capacity.
  • Each ship class has exactly 3 available S-mod capacity upgrades, available at levels 2, 4, and 6.
  • Building in hullmods no longer costs story points, instead costing mastery points (MP) and credits.




NPC Masteries

  • NPC fleets follow the same general rules as player fleets, and may have mastery levels in some ship classes.
  • Ships in an NPC fleet that have mastery effects applied will also have a marker hullmod added, so hovering over that ship will show its mastery level.
  • Adds a post-inflation sequence to add S-mods to ships in generic NPC fleets, if they've unlocked mastery levels that grant them S-mod capacity.
  • NPC fleets' average mastery levels (and other mastery-related settings) can be changed in the difficulty subsection of the settings.



Skill Changes
Best of the Best

  • Removed the additional S-mod from Best of the Best; default cap is now 3 (at max mastery) regardless of skills.
  • Added effect: +20% effectiveness of all mastery bonuses.
  • Added effect: +15% CR, +10% hull and flux capacity for capital ships with officers.


Cybernetic Augmentation

  • Removed the 1% damage dealt / damage taken bonus per commander's elite skill.
  • Added an ordnance points bonus that scales based on the number of ship types the player has mastered (bonus is fixed for NPC fleets)

[close]

Miscellaneous Features
Adds a system for reclaiming ships lost in battle

  • Player ships that are lost but not recovered, either by choice or due to disengaging early from or losing a battle, spawn as derelicts near the battle site.
  • In order to spawn as a derelict, the ship must have been recoverable should the player have won (affected by reinforced bulkheads / hull restoration / etc.).
  • If the player is given a post-battle salvage option, weapons and wings from the wrecks are stripped.
  • The wrecks disappear permanently after 365 days, or if the player dismisses the fleet log entry.
  • Greatly facilitates insurance fraud if using Nexerelin's ship insurance feature.



Adds the ability to view details about and replay recent battles

  • Keeps track of the 10 most recent battles you've won, displaying detailed enemy fleet and officer data.
  • Replay battles in a simulation-like environment -- quit anytime, gain nothing, and lose nothing.
  • Solo replay allows fighting against individual ships from recorded battles.
  • Pin notable battles to keep them in the intel log permanently, allowing you to replay limited boss battles at any time.



Adds an S-mods option to the refit screen autofit menu

  • This will attempt to copy S-mods from the goal variant, automatically spending the required credits and mastery points.


Also adds a small amount of exploration content.
[close]

Version log

2
Mods / [0.97a] Unthemed Weapons Collection 0.6.5 (4/9/24)
« on: May 29, 2023, 07:58:26 PM »
Unthemed Weapons Collection


No hard dependencies. Soft dependency on Particle Engine. Will run without it, but some visual effects will be missing.


Weapon pack. No factions, no ships*, no faction-themed stuff. Adds 42 weapons to the game. Also adds fortified caches and a few secrets.

Some of the weapons
Ballistic

Railburst Rifle: Two-shot burst railgun. Regenerating ammo.



Demolisher Cannon: High damage per shot, for a small weapon. Regenerating ammo.



Mortar Screen: Low range, low accuracy, very flux efficient.



Spreadfire Cannon: Shotgun that gets more accurate the longer you fire.



Pummeler: Heavy fragmentation damage. Sustained fire increases fire rate.



Helios Artillery: Long range, low DPS, poor efficiency. AOE damage on hit.



? ? ?
[close]
Energy

Boltgun: Terrible damage output, but cheap and long range (relatively speaking).



Mining Laser Mk.2: What even is this thing? Limited ammo HE beam weapon.



Enhanced Tactical Laser: Bigger tactical laser that also has a secondary flux-based effect on the target.



Bolt Scrambler: Long range (relatively speaking) shotgun. Difficult to use on turrets, less difficult to use on hardpoints.



Graviton Array: Instant +15% shield damage. Doesn't stack with itself or with graviton beams.



Chaos Pulser: Long range, randomized damage. The stronger a shot is, the less accurate it becomes.



? ? ?
[close]
Missile

Cluster Mine Launcher: Launches a cluster of mines, as expected.



Spiker SRM: Light sustained shield pressure. Does additional soft flux damage on shield hits.



Paralyzer Rocket Launcher: High tech annihilator.



Bloom Autolauncher: Slow, guided torpedo. Low damage, but causes secondary explosions.



Stinger Swarm Battery: Energy swarmer. Unspectacular damage output, but spammable.



Ion Storm GLMRS: For when you really need to flame something out. Missiles surround the target.



? ? ?
[close]
[close]

Fortified Caches
Procedurally generated caches with defenders. Defenders aren't automated (no lore reason, gameplay reason is that the player already fights enough derelict drones and remnants). These contain normal loot, though with a rewritten loot system, so quantities and types of items may be different from what you're used to seeing. Can change cache frequency in the settings; toggle off by setting frequency to 0.

Also has an option to regenerate caches. This is OFF by default, but if enabled, fortified caches that are looted will be replaced eventually. Essentially allows the player to have a theoretically endless amount of stuff to loot, allowing them to complete their blueprint collection, etc. without having to raid core worlds.
[close]

Utilities
Modifies the refit screen to show updated weapon statistics based on the ship being refitted, as well as total weapons flux generation:



UI modification code is finicky. There are a few limitations:
  • Damage modifiers that affect specific ship classes differently (target analysis, s-modded gyros) are not included.
  • Doesn't affect weapon group flux displays in the weapons group selector.
  • Doesn't affect fighters or fighter weapons.
  • Won't work out-of-the-box with translation packs as many UI elements are acquired by parsing their (English) text.
[close]

Version History
0.6.5: Here
0.6.4: Here
0.6.3: Here
0.6.2: Here
0.6.1: Here
0.6: Here
0.5.4: Here
0.5.3: Here
0.5.2: Here
0.5.1: Here
0.5: Here
[close]

3
e.g. projectileWeaponSpec.setChargeTime(3f) inside WeaponEffectPluginWithInit.init, expected behavior would be to change the charge time of the weapon to 3 seconds, but nothing happens.
Or projectileWeaponSpec.setEnergyPerShot(1000f) inside WeaponEffectPluginWithInit.init, expected behavior would be to change the base flux per shot to 1000, but this doesn't happen. Interestingly though, weapon.getFluxCostToFire does correctly get modified.

4
Outside of a market, if the core UI is closed, CoreUITabId becomes null, as expected.
However, inside a market, if the core UI is closed, CoreUITabId remains what it was before it was closed. For example, if you open the refit screen from a market's menu, then close it via the escape key or the top-right button, the refit screen itself closes but CoreUITabId is still REFIT.

5
Bug Reports & Support / Planetkiller issues
« on: May 08, 2023, 09:50:45 AM »
- Trying to turn the planetkiller in to the Diktat via the option "I have something that will be of great interest to the Lion of Sindria" gives a rule-not-found error.

- Turning the planetkiller in to the LP base that started "The Scythe of Orion" quest rewards a very high LP contact but doesn't actually do anything about the LP hostile activity. The receiver also doesn't make any mention about betraying you, etc., so I would assume that he'd uphold his end of the deal -- but he doesn't.

(Unrelated issue, but if multiple LP fleets are pursuing you and you pay the "larger tithe" to one of them, the others don't stop pursuing and you can end up paying the "larger tithe" multiple times).

6
Suggestions / Miscellaneous small 0.96a suggestions
« on: May 08, 2023, 08:29:28 AM »
I’ll start:

- Inverting the behavior of shift-strafe button should set the default strafe lock mode to enabled if used in tandem with the strafe lock toggle. Or, the strafe lock setting should be remembered between battles.

- The hidden cache in Sentinel is currently a valid random exploration mission target — not sure if that’s intended or not.

- FMR recharges way too fast on the Pegasus IMO (and also has too many charges when considering the Pegasus specifically), it’s actually kind of hilarious with hurricanes + system specialization. I’d consider changing the system entirely and maybe even adding an innate missile fire rate nerf to the ship.

Edit: current state of Pegasus also severely limits the design space of modded missiles. Basically any large missile that’s guided with a long cooldown becomes OP.

7
After scanning the center of a binary star system and receiving the topography data, any subsequent sensor burst triggers the "center of star system already scanned" message, regardless of where the scan took place.

8
I assume this is happening when the hostile event tracker reaches 75, upon which some event is supposed to be revealed.

Stack trace:
java.lang.RuntimeException: Texture [hostile_activity_MINOR_EVENT] from category [events] not found
   at com.fs.starfarer.settings.StarfarerSettings.Ò00000(Unknown Source)
   at com.fs.starfarer.settings.StarfarerSettings$1.getSpriteName(Unknown Source)
   at com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.getSt ageIconImpl(HostileActivityEventIntel.java:503)
   at com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.getStageIcon(BaseEventIntel.java:460)
   at com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.createDisplayDat a(BaseEventIntel.java:442)
   at com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.addStageDescript ionWithImage(BaseEventIntel.java:409)
   at com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.createLargeDescr iption(BaseEventIntel.java:251)
   at com.fs.starfarer.campaign.comms.v2.EventsPanel.new(Unknown Source)
   at com.fs.starfarer.campaign.comms.v2.EventsPanel.actionPerformed(Unknown Source)
   at com.fs.starfarer.campaign.comms.v2.EventsPanel.new.String(Unknown Source)
   at com.fs.starfarer.campaign.comms.v2.EventsPanel.advanceImpl(Unknown Source)
   at com.fs.starfarer.ui.thissuper.advance(Unknown Source)
   at com.fs.starfarer.ui.o000.advanceImpl(Unknown Source)
   at com.fs.starfarer.campaign.comms.OOoO.advanceImpl(Unknown Source)
   at com.fs.starfarer.ui.thissuper.advance(Unknown Source)
   at com.fs.starfarer.ui.o000.advanceImpl(Unknown Source)
   at com.fs.starfarer.ui.newui.o0OO.advanceImpl(Unknown Source)
   at com.fs.starfarer.ui.thissuper.advance(Unknown Source)
   at com.fs.starfarer.ui.o000.advanceImpl(Unknown Source)
   at com.fs.starfarer.ui.O.advanceImpl(Unknown Source)
   at com.fs.starfarer.ui.newui.OO0O.advanceImpl(Unknown Source)
   at com.fs.starfarer.ui.thissuper.advance(Unknown Source)
   at com.fs.starfarer.ui.o000.advanceImpl(Unknown Source)
   at com.fs.starfarer.ui.thissuper.advance(Unknown Source)
   at com.fs.starfarer.campaign.CampaignState.advance(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.o00000(Unknown Source)
   at com.fs.starfarer.StarfarerLauncher$1.run(Unknown Source)
   at java.lang.Thread.run(Thread.java:748)

9
If both "invert behavior of shift key" and the strafe lock are enabled, the strafe lock doesn't do anything -- shift key needs to be held down to use keyboard turning.

10
Modding Resources / [0.97a] Particle Engine (4/2/24)
« on: April 10, 2023, 06:49:27 PM »
Particle Engine
 


A library that implements a stateless, instanced particle system.

What is this?
This is a utility mod and a tool. Downloading it and adding it to your game as-is does nothing. It is intended to provide a fast, relatively simple, and relatively up-to-date system for generating, allocating, and rendering particles.
[close]

Why does this exist?
Vanilla particles are CPU-bound (individual particles are simulated on the CPU), and essentially the entire game only utilizes a single CPU core. Furthermore, each particle has its own rendering loop. To keep performance reasonable, vanilla Starsector has a fairly low particle limit, after which old particles start getting replaced.

This mod uses slightly more modern (but not actually all that modern) techniques to minimize CPU strain. Most of the work, including simulation, is done on the GPU. The CPU doesn't keep track of individual particles. The particle engine is a singleton object (accessed via static methods) that performs a single draw call per particle type (every particle with the same sprite and blend mode has the same type) per frame. The result is a much more performant particle system.

The part of the vanilla particle system that is exposed and usable by modders is highly limited. As a modder, you're essentially only easily able to add a few types of particles, all via i.e. Global.getCombatEngine().addSmoothParticle. It's also possible to use a CombatEntityPluginWithParticles, though that has its own limitations -- you're forced to use a 4x4 sprite sheet, the plugin has its own state that must be initialized and updated, and you have to set the properties of each particle using a prev pointer. It also seems to be partially broken, i.e. endSizeMult doesn't actually seem to work, and particles either grow or shrink at a fixed rate.
[close]

How do I use this?
The starting point of all particle generation is the Particles class. There are essentially just three steps:
  • Create an emitter using Particles.initialize. This returns a default Emitter object.
  • Set the emitter's properties. Here you can set and randomize particles' positions, velocities, accelerations, sizes, colors, shift their colors over time, add radial motion, revolution, and so on.
  • Generate the particles using Particles.burst or Particles.stream, passing in an emitter whose properties you want to use.
There is also a javadoc bundled with the zip download that explains the function of each class and method in more detail.
[close]

What are the limitations?
Because particles are simulated on the GPU, they are also stateless (technically it's possible to store state in, e.g. an SSBO, but that's not relevant for now). This means that they don't interact with the game world -- once they're generated, their trajectories are fixed. As a result, particles won't be able to interact with ships or projectiles in either direction -- they can't affect the game state and they can't be affected by the game state. Still, because emitters are managed by the CPU, it's possible to modify emitters according to the game state, so a large variety of effects are nevertheless possible.

Performance is GPU dependent, so PCs with poor graphics cards or low VRAM might experience stuttering or drop outs with obscene numbers of particles. GPU code is also finicky, so with this early version you may run into system-specific issues or bugs.
[close]

Additional features
It's possible to read and write emitter properties from and to JSON files. To read an emitter from a JSON file, simply use Emitter.fromJSON in conjunction with Global.getSettings().loadJSON. For an example emitter JSON, see data/particleengine/sample_emitter.json.

Writing emitters to file is a bit tricker due to file IO limitations put in place by Starsector's custom class loader. The particleengine.json file in the mod's root directory contains the directory that saved emitters should be written to. By default, this is ../saved_emitters, i.e. the saved_emitters directory in the Starsector root. If this directory doesn't exist, you will have to create it manually before any write operations will work.

The JSON functionality can be a valuable tool when designing particle effects as changes to the JSON file can be effected without having to restart Starsector. In released code, it's not recommended to use writeJSON, and, if intending to use readJSON, the files should be batch-read at some initialization stage and cached for later reuse.
[close]

Custom emitters
While the default Emitter can generate a variety of effects already, it is possible to make your own emitters by implementing IEmitter, or extending the BaseIEmitter class. This is helpful in creating emitters with inter-particle dependencies, i.e. particles whose properties depend on other properties in a non-random way.

You will have to implement the initParticle function, which takes in the index of the particle in the burst or stream and outputs a ParticleData that is passed into the vertex shader. The below sample emitter replicates the vanilla muzzle flash visual, whereby particles' velocities are directed outwards and dependent on their initial distance from the emitter origin:

Muzzle flash emitter code

public class MuzzleFlashEmitter extends BaseIEmitter {

    private final Vector2f location;
    private float angle, arc, range, minLife, maxLife, minSize, maxSize, velocityScale;
    private final float[] color = new float[] {1f, 1f, 1f, 1f};
    private CombatEntityAPI anchor;

    public MuzzleFlashEmitter() {
        location = new Vector2f();
        angle = arc = range = 0f;
        minLife = maxLife = 0.5f;
        minSize = 20f;
        maxSize = 30f;
        velocityScale = 1f;
    }

    @Override
    public SpriteAPI getSprite() {
        return particleengine.Utils.getLoadedSprite("graphics/fx/particlealpha64sq.png");
    }

    public MuzzleFlashEmitter anchor(CombatEntityAPI anchor) {
        this.anchor = anchor;
        return this;
    }

    public MuzzleFlashEmitter location(Vector2f location) {
        this.location.set(location);
        return this;
    }

    public MuzzleFlashEmitter angle(float angle) {
        this.angle = angle;
        return this;
    }

    public MuzzleFlashEmitter arc(float arc) {
        this.arc = arc;
        return this;
    }

    public MuzzleFlashEmitter range(float range) {
        this.range = range;
        return this;
    }

    public MuzzleFlashEmitter life(float minLife, float maxLife) {
        this.minLife = minLife;
        this.maxLife = maxLife;
        return this;
    }

    public MuzzleFlashEmitter size(float minSize, float maxSize) {
        this.minSize = minSize;
        this.maxSize = maxSize;
        return this;
    }

    public MuzzleFlashEmitter color(float r, float g, float b, float a) {
        color[0] = r;
        color[1] = g;
        color[2] = b;
        color[3] = a;
        return this;
    }

    public MuzzleFlashEmitter velocityScale(float velocityScale) {
        this.velocityScale = velocityScale;
        return this;
    }

    @Override
    public Vector2f getLocation() {
        return location;
    }

    @Override
    protected ParticleData initParticle(int i) {
        ParticleData data = new ParticleData();

        // Life uniformly random between minLife and maxLife
        float life = randBetween(minLife, maxLife);
        data.life(life).fadeTime(0f, life);

        float theta = angle + randBetween(-arc / 2f, arc / 2f);
        float r = range * (float) Math.sqrt(Misc.random.nextFloat());
        Vector2f pt = new Vector2f(r*(float)Math.cos(theta*Misc.RAD_PER_DEG), r*(float)Math.sin(theta*Misc.RAD_PER_DEG));
        // Velocity is proportional to distance from center
        Vector2f vel = Misc.getUnitVectorAtDegreeAngle(theta);
        vel.scale(velocityScale);
        vel.scale(r);
        // Add the anchor's velocity, if it exists
        if (anchor != null) {
            Vector2f.add(anchor.getVelocity(), vel, vel);
        }
        data.offset(pt).velocity(vel);

        // Size uniformly random between minSize and maxSize
        float size = randBetween(minSize, maxSize);
        data.size(size, size);

        // Color
        data.color(color);

        return data;
    }

    public float randBetween(float a, float b) {
        return Misc.random.nextFloat() * (b - a) + a;
    }
}

[close]

[close]

Sample emitters with code
Ion explosion
Effect

[close]
Code
       
        Emitter emitter = Particles.initialize(pt, "graphics/fx/explosion1.png");
        emitter.circleOffset(30f, 50f);
        emitter.life(0.75f, 1.25f);
        emitter.fadeTime(0.1f, 0.1f, 0.3f, 0.5f);
        emitter.facing(0f, 360f);
        emitter.turnRate(-50f, 50f);
        emitter.turnAcceleration(-50f, 50f);
        emitter.circleVelocity(100f, 100f);
        emitter.radialAcceleration(-50f, -100f);
        emitter.revolutionRate(-20f, 20f);
        emitter.color(colorIn);
        emitter.randomHSVA(20f, 0.1f, 0f, 0f);
        emitter.colorShiftHSVA(0f, -0.3f, -0.3f, -0.05f);
        emitter.size(150f, 200f);
        emitter.growthRate(100f, 150f);
        emitter.growthAcceleration(-50f, -75f);
        Particles.burst(emitter, 50);

        Emitter ringEmitter = Particles.initialize(pt, "graphics/fx/custom_ring.png"); // Just a simple white ring
        ringEmitter.setAxis(proj.getFacing());
        ringEmitter.life(0.75f, 1f);
        ringEmitter.fadeTime(0.1f, 0.1f, 0.5f, 0.7f);
        ringEmitter.size(300f, 400f, 40f, 60f);
        ringEmitter.growthRate(400f, 500f);
        ringEmitter.growthAcceleration(-50f, -60f);
        ringEmitter.color(ringColorIn);
        ringEmitter.hueShift(-50f, 50f);
        ringEmitter.saturationShift(-0.2f, -0.2f);
        ringEmitter.facing(-55f, -35f);
        Particles.burst(ringEmitter, 10);
        ringEmitter.facing(35f, 55f);
        Particles.burst(ringEmitter, 10);

        Emitter arcEmitter = Particles.initialize(pt, "graphics/fx/custom_emp_arcs.png"); // Just emp_arcs.png with a darkening filter applied to border
        arcEmitter.life(0.25f, 0.3f);
        arcEmitter.fadeTime(0f, 0f, 0.15f, 0.25f);
        arcEmitter.size(350f, 350f, 300f, 300f);
        arcEmitter.growthRate(-40f, -80f);
        arcEmitter.turnRate(-10f, 10f);
        arcEmitter.facing(0f, 360f);
        arcEmitter.color(0.7f, 1f, 1f, 0.7f);
        arcEmitter.facing(0f, 360f);
        arcEmitter.alphaShift(-0.5f, -0.5f);
        Particles.stream(arcEmitter, 1, 50, 0.75f);

[close]
[close]

Simple trail
Effect

[close]
Code

        Emitter emitter = Particles.initialize(proj.getLocation(), "graphics/fx/particlealpha_textured.png");
        emitter.life(1f, 1.2f);
        emitter.fadeTime(0f, 0f, 0.5f, 0.5f);
        emitter.offset(-50f, -5f, 0f, 0f);
        emitter.velocity(-40f, -20f, 0f, 0f);
        emitter.color(1f, 0f, 1f, 0.8f);
        emitter.randomHSVA(40f, 0.2f, 0f, 0f);
        emitter.saturationShift(-1f, -1.5f);
        emitter.alphaShift(-0.6f, -0.6f);
        emitter.size(80f, 80f, 20f, 20f);
        emitter.growthRate(-50f, -50f, -8f, -8f);
        Particles.stream(emitter, 1, 100f, 5f, new Particles.StreamAction() {
            @Override
            public boolean apply(Emitter emitter) {
                // Set the emission location and axis to match the projectile's right before each burst of particles is generated.
                emitter.setLocation(proj.getLocation());
                emitter.setAxis(proj.getFacing());
                return !proj.isExpired();
            }
        });

[close]
[close]

Stress test with 1 million particles

WARNING: 55MB gif
Effect

[close]

Code
        Emitter emitter = Particles.initialize(pt);
        emitter.setSyncSize(true);
        emitter.setBlendMode(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL14.GL_FUNC_ADD);
        emitter.life(10f, 10f);
        emitter.fadeTime(0f, 0f, 0.5f, 0.5f);
        emitter.circleOffset(0f, 30f);
        emitter.colorHSVA(new float[] {0f, 0.5f, 1f, 1f});
        emitter.size(10f, 25f, 10f, 25f);
        emitter.growthRate(-10f, 10f, -10f, 10f);
        emitter.randomHSVA(360f, 1f, 0f, 0f);
        emitter.revolutionRate(-30f, 30f);
        emitter.colorShiftHSVA(-200f, 200f, -0.1f, 0.1f, -0.1f, 0.1f, -0.1f, -0.1f);
        final float[] amp = {200f};
        emitter.sinusoidalMotionX(-amp[0], amp[0], 0.25f, 0.25f, 0f, 0f);
        emitter.sinusoidalMotionY(-amp[0], amp[0], 0.25f, 0.25f, 0f, 0f);
        Particles.stream(emitter, 1000, 100000, 10f, new Particles.StreamAction() {
            @Override
            public boolean apply(Emitter emitter) {
                amp[0] += 2f;
                emitter.sinusoidalMotionX(-amp[0], amp[0], 0.25f, 0.25f, 0f, 0f);
                emitter.sinusoidalMotionY(-amp[0], amp[0], 0.25f, 0.25f, 0f, 0f);
                return true;
            }
        });

[close]

[close]
[close]

Version log
  • 0.73 (4/2/24):
    Added a toggle to disable particle effects while keeping the mod enabled.
  • 0.72 (3/3/24):
    Updated SS version to 0.97a. No changes.
  • 0.71 (12/29/23):
    Fixed default particle falloff, now is actually using square falloff and should look like particlealpha64sq.png in graphics/fx
    Made ParticleData.colorHSVA public
    No longer hard crashes if glMapBufferRange encounters an error, and will log an error message into the console
  • 0.7 (11/27/23):
    Added preInitParticles, which is called only once per burst and can be used to avoid re-computation.
    Shader now uses SpriteAPI's textureWidth and textureLength, scaling the image up when they are less than 1.
    Shader now uses SpriteAPI's centerX and centerY if they are non-negative and sticks to using the standard (0.5, 0.5) center otherwise.
    Updated dynamic anchoring to also dynamically update the emitter's axis. Note: Particles.anchorEmitter still only anchors position, not angle.
    Fixed untextured particles' alpha being capped to 0.25.
    Removed multiple extraneous getLocation calls when adding particle data to a float buffer
    Halved maximum simultaneous active dynamic emitters, down to 1024 from 2048
    Various optimizations
  • 0.62 (11/19/23):
    Fixed an issue where dynamically tracked particles could be jittery on their first frame.
    Fixed a bug where the wrong emitters were being evicted when the tracked emitter buffer was full.
    Greatly optimized the tracked emitter buffer handler. It now no longer holds on to stale emitters longer than necessary and only binds the UBO data each frame up to its maximum used index.
  • 0.61 (11/19/23):
    Hotfix a crash when doWhenFinished is null
    Fixed an issue where streams were finishing when they weren't supposed to
    Fixed an issue where streams would no longer generate more than 1 burst per frame
    Changed maxDuration in Particles.stream back to float from Float, set to negative value to never expire
  • 0.6 (11/18/23):
    Added anchorEmitter to Particles, which automates the task of setting the emitter's location to a combat entity's location each frame as well as destroying streams when the anchored-to combat entity leaves play.
    Added the ability to dynamically anchor particles to their emitters, allowing them to track and follow changes in their emitters' locations. Applied on a per-emitter basis, using enableDynamicAnchoring. Useful for particles that are meant to follow a combat entity.
    Note: emitter locations are stored in a UBO. Due to buffer size limitations, a maximum of 2048 emitters' locations can be tracked at a time. If more than 2048 emitters are being tracked, stale ones will start to be deleted. Use disableDynamicAnchoring to free an emitter's slot in the buffer.
    Added an optional doWhenFinished parameter when creating particle streams.
    Particles.stream now takes a Float for maxDuration rather than a float -- set it to null to make a stream never expire naturally.
    Particles.stream should now more accurately handle particles per burst, particles per second, and total duration.
    Optimized the particle allocation process a bit; should be less taxing on the CPU.
    Fixed an issue where createCopy was overriding the copy's sprite and blend mode settings
  • 0.5 (5/29/23):
    New classes, IEmitter and BaseIEmitter, that may be extended to generate custom particle emitters. Particles can now depend on each other's properties (prior to generation).
    Generify Particles.StreamAction. Note: this will break implementations using StreamAction, to fix, replace all StreamAction with StreamAction<Emitter>.
    Change license, relevant for v0.5+
  • 0.4 (5/5/23):
    Update Starsector version to 0.96a-RC6
    Change default out-of-bounds range from 100 to 500
    Change default particle layer to ABOVE_PARTICLES_LOWER
    Add early exit on Particles.burst if number of particles is <= 0
  • 0.3 (5/1/23):
    Emitters now support CombatEngineLayers, layer can be set via Emitter.setLayer
    Added Emitter.setInactiveBorder. Emitters outside of the screen by more than this amount of world units will ignore particle generation calls.
  • 0.2 (4/11/23):
    Add mod thread id to version file
    Remove axis from json output (it's an emitter property, not a particle property)
    Allow changing of emitter sprite and blend mode via setters
    Add setSyncSize to Emitter, which allows random particle sizes that are the same in the x and y directions (uses the x direction values)
  • 0.1: Initial release (4/10/23)
[close]

11
Mods / [0.97a] Officer Extension (0.6.7)
« on: January 26, 2022, 10:26:20 PM »
Officer Extension
 

Overhauls the officer selection dialog, adding additional features:


Features:

Manage more officers
  • Manage as many officers as you'd like. Hire new officers regardless of how many are currently under your command.
  • The 8 officer limit (10 with officer management) still applies -- however, it only applies to officers in command of a ship. Officers not in command of a ship do not count toward your officer limit.
[close]

Suspend officers
  • Suspend officers in your fleet for an upfront fee equal to twelve times their monthly salary.
  • Suspended officers cannot be assigned to any ship and must be paid 10% of their standard salary.
  • Suspended officers can be reinstated at any time for no cost.
  • Does not apply to mercenaries or AI cores.
Screenshot
[close]
[close]

Demote officers
  • Select skill icons directly from an officer’s skills panel to prime them for removal. Then remove those skills by demoting that officer. This causes the officer to lose levels equal to the number of skills forgotten.
  • Demoting an officer requires a story point and grants 100% bonus experience.
  • Officers cannot be demoted below level 1.
  • Does not apply to mercenaries or AI cores.
Screenshot

[close]
[close]

Additional menu options
  • Undo your most recent assignments. This may fail if you suspend, dismiss, or fully integrate officers or AI cores beforehand.
  • Filter officers by skills or by custom user-defined tags. Officers that don't have the selected skills or tags will be hidden from the selection panel.
  • Sort officers, which will sort officers in your fleet in the following order: unassigned mercenaries, assigned mercenaries, unassigned non-mercenary officers, assigned non-mercenary officers, suspended officers. Officers in the same category are sorted by level, followed by name.
Screenshot
[close]
[close]

Miscellaneous QoL
Sorts officer payroll in the income tab by pay, followed by officer name for officers with equal pay. This applies to suspended officers as well.

Screenshot
[close]

Upon interacting with another fleet, displays that fleet's commander's combat skills, including fleet-wide skills.

Screenshot
[close]

Level 7 cryopod officers will maintain their maximum level and number of elite skills even if you demote them or remove their elite skills via the retrain option. Like normal officers, they can no longer be retrained if they have fewer than their maximum allowed number of elite skills.
[close]

Additional notes:

Show

  • Safe to add to or remove from an existing save file.
  • Inspiration to modify the core UI directly (rather than making yet another rule-based interaction dialog or possibly a new intel tab) derived from andylizi's Planet Search and Dialog Minimap mods.
[close]

Version history:

Show
0.6.7: Here
0.6.6: Here
0.6.5: Here
0.6.4: Here
0.6.3: Here
0.6.2: Here
0.6.1:
- Fixed issue where zip folder was empty
- Tentative fix for bug when FleetEncounterContext is different from 0.97a-RC11 version, should improve flexibility for different Starsector versions
0.6.0:
- Suspended officers no longer count for battle bonus XP calculation
- Officer promotion candidate intel event is no longer locked when vanilla officer cap is reached
- No longer uses a custom officer level-up plugin, instead sets max level and max elite skills values in the officer's local memory
- Added handling for "unremovable" skills via tag "officerextension_unremovable"
- Disabled demotion if officer is not leveled up
- Tentative fix for possible NPE when getOtherSideCombined is null
0.5.0:
- Just update Starsector version to 0.96a-RC6 and make sure nothing broke as a result
0.4.3:
- Reset game pause state on load
- Fix NoSuchMethodException issue on Linux machines
0.4.2:
- Add a field for persistent tags for filtering officers in the mod settings. Persistent tags will always be shown before any other custom-defined tags and will be shown even if you don't have any officers with that tag.
- Change all getMemory to getMemoryWithoutUpdate. This should fix crash bugs for officers with empty rank, post, name, etc.
0.4.1:
- Overhaul the "edit tags" feature. Now allows you to add tags individually as well as select from a list of all custom-defined tags.
- Add filters for personality and the "exceptional sleeper pod" status
- Allow filtering for elite versions of skills
- Sorting now takes number of elite skills into account
0.4.0:
- Change officer count so that only assigned officers count against your limit
- Add undo, filter, sort features in the selection menu
- Allow hiring of officers regardless of current number in fleet
- Allow special cryopod officers to regain lost levels and elite skills
- Suspending an officer now costs 12x their monthly salary (up from 10x). Suspended officers receive 10% pay (down from 25%).
- More detailed revisions in README
0.3.1:
- Added two new configurable settings: SP cost to demote officers, and whether the fleet commander skills panel should be split between personal and admiral skills.
- The fleet commander skills display will now display info for the enemy fleet in an ongoing battle, regardless of which fleet you clicked on.
- Renamed the "forget" buttons to "demote"
- Fixed an issue with the ReflectionEnabledClassLoader where it wasn't checking for findLoadedClass before calling findClass
- Various typo fixes and clarifications
0.3.0: initial release
[close]

12
This is a bug that's likely never to be encountered in any standard vanilla (or modded) playthrough, but I thought it'd be worth mentioning nonetheless. The following conditions have to be met:

- You have a ship with modules
- The hint popup that says "you've made changes to the ship's loadout, but have not adjusted the weapon groups" is enabled

To reproduce the bug:

- Open the refit screen for a ship with modules
- Select and add weapons to any module
- Select a different module. The hint popup asking to adjust weapon groups should appear.
- Select "adjust weapon groups"
- Make any nontrivial adjustment (i.e. toggle autofire, change the weapon group of a single weapon)
- After confirming, click on any module
- The previously selected module should disappear and be replaced with a copy of the original module
- This can be done repeatedly, leading to some interesting results (see attached)

Even though ships with modules are not normally obtainable in vanilla, I was able to reproduce the bug in vanilla by temporarily using console commands to spawn a station, saving the game, and then disabling console commands.

[attachment deleted by admin]

13
After the shield shunt nerf, I got to thinking -- how bad or not bad is it now?

Since the armor damage reduction calculation is rather complex, it's unclear how well a +15% increase to armor actually translates to combat performance. So I devised a couple of metrics to quantify how strong armor is in practical terms, as well as to gauge how strong skills and hull mods that affect armor actually are.

A note: I am making some simplifications for this analysis. First, I'm only going to consider a single block of armor, and I'll assume that that single block contributes all of its armor value, rather than taking an average over many surrounding blocks. Next, I'm going to assume that weapons deal continuous damage with two parameters: a hit strength H, and a base DPS B. Projectiles weapons can be approximated as beam weapons with B equal to their stated DPS and H equal to the projectile damage. The continuous assumption is what makes an analytical solution possible; otherwise, we'd be looking at some ugly recurrence relations.

For those who are unfamiliar with the armor mechanics, I'll give a brief recap. Suppose that A is the total armor of your ship. This is the number that appears in the refit screen, and is modified by hull mods like shield shunt, heavy armor, armored weapon mounts. However, it doesn't account for skills like polarized armor (which gives invisible armor for damage reduction purposes only) and impact mitigation (which reduces damage taken by armor, and used to give a flat invisible armor bonus). The total effective armor, which is the number actually used for damage reduction purposes, can be written as e(A) = uA + v, where u accounts for bonuses of the form "grants x% armor for damage reduction calculation purposes only," and v accounts for bonuses of the form "grants y (flat) armor for damage reduction calculation purposes only."

Suppose your ship currently has X armor. When your ship's armor gets hit by a beam with stated DPS B and hit strength H (usually H = B/2 for beams), the DPS sustained by the armor is (1 - R) * B, where R is the damage reduction fraction. Normally, R = e(X) / (e(X) + H) . However, there are two exceptions: if e(X) / (e(X) + H) > 0.85, then R is set to 0.85 (or 0.9 if you have polarized armor), so that your ship will always take a minimum fraction of damage regardless of how much armor it has. The second exception is if e(X) < e(0.05*A), in which case the armor value used is instead e(0.05*A), so that you will always have a minimum base armor value for damage reduction calculation, even if your armor is fully stripped.

A natural way to judge practical effectiveness of armor is to consider how long it takes for a particular weapon to fully strip it. I'll call this the strip time T. It turns out that, in the absence of the two exceptions above, T is quadratic in A -- that is, T is proportional to A^2. So, the more armor you have, the more effective the additional armor is. This makes flat armor bonuses -- heavy armor in particular -- more useful than they might initially seem.

What I'm really interested in is how much longer it takes to fully strip armor once we add certain skills and hull mods. For this, I'll consider the strip time ratio -- the amount of time it takes to fully strip armor with said skill or hull mod, divided by the amount of time it takes to fully strip armor without it. Skills and hull mods with higher strip time ratios are, in a very practical way, better. However, it comes as no surprise that the strip time ratio varies depending on the ship's base armor value. Here are graphs of strip time ratios of various skills, hull mods, and combinations thereof, for the following weapons: tactical laser (B = 75, H = 37.5), heavy mortar(B = 220, H = 220), and plasma cannon (B = 750, H = 500).

Tactical Laser

[close]

Heavy Mortar

[close]

Plasma Cannon

[close]

Some observations from these graphs:

- For most armor modifiers, strip time ratio increases with increased base armor until it hits a peak, after which it starts to decrease. The peak is the point at which the 85% damage reduction cap starts to kick in, since at this point the strip time goes from quadratic to linear. The obvious exceptions to this are polarized armor, which gains effectiveness past the damage reduction cap due to it increasing said cap to 90%; and heavy armor, due to being a flat increase.

- The general individual order of effectiveness of skills, along with shield shunt, is IM > SS (pre-nerf) > SS (post-nerf) > PA (assuming constant 25% bonus). PA dominates when the weapon's hit strength is low or base armor is high, due to gaining effectiveness once the damage cap is reached. With a 50% constant bonus (pre-nerf), PA actually competes with SS (post-nerf) against a plasma cannon, being weaker up until ~850 base armor and stronger after that. Note that since IM reduces damage and hit strength to armor by 25% (reference: https://fractalsoftworks.com/forum/index.php?topic=22699.15), it is effectively increasing armor by 33%, which is better than even pre-nerf shield shunt.

- Individually, the skills aren't particularly strong, improving strip time by a modest factor. The strongest, impact mitigation, caps out at about a 1.5 strip time ratio. However, they are comparatively much stronger when combined. With a decent base armor, the strip time ratio can be improved by a factor of 2-2.5 when stacking all three of SS, IM, and PA together (assuming 25% bonus for PA). When combined with HA and AWM, you can triple to quadruple your ship's armor's strip time, even with upwards of 1000 base armor. The reason why the skills and hull mods work so well when combined is due to how they stack. Hull mods affect the visible armor value and stack additively with each other, but everything else stacks multiplicatively. Polarized armor affects effective armor and impact mitigation affects hit strength and damage taken, each of which are modified separately from the ship's base armor.

I've attached a pdf showing how I derived the strip time formula, as well as a Mathematica notebook that I used to create the graphs, for anyone who is interested in playing around with the values themselves.

[attachment deleted by admin]

14
If you just deploy one ship and instantly retreat it, after disengaging, the station bounty will be marked as complete and you will receive the bounty for it.

Bonus: I just completed a station bounty for Kanta’s Den from watching another fleet engaging and failing to destroy it.

15
Occasionally, when trying to visit the bar at a colony, my game would hang. After some testing, it seems that the culprit is a specific bar event that is causing an infinite loop if it can't find a blueprint to pick. Specifically, in BlueprintIntel.pickItem, the picker is empty after every iteration of the loop.

Curiously, I went ahead and checked if I really had every ship, weapon, and fighter blueprint -- I don't. For example, I'm missing Astral, Champion, and some XIV blueprints. Is this specific bar event meant to always have a quality of 0 (meaning that the only blueprints with positive weight are those with tier 0, or ships with at most 5 FP)? I don't think I've ever seen a version of this bar event that offered anything with a higher tier -- that would explain why this event always seems to have such a small selection. It's always revenant (5 FP), phantom (3 FP), buffalo, perdition wing, and with mods, LR pulse laser.

Pages: [1] 2