Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Pages: 1 ... 385 386 [387] 388 389 ... 710

Author Topic: Misc modding questions that are too minor to warrant their own thread  (Read 1720477 times)

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 24118
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5790 on: December 08, 2019, 10:08:12 AM »

And I actually have a different question now - is there a way to make a single fighter return to its mothership? I'm thinking of a hullmod that makes a fighter retreat if it suffers a certain amount of hull damage.

See: FighterWingAPI.orderReturn(ShipAPI fighter)

If a route-spawned fleet takes losses in combat, is this reflected anywhere in the route data at all? Neither OptionalFleetData.fp nor OptionalFleetData.damage are being updated in my RouteFleetSpawner implementation.

It's not reflected anywhere. However, there is an OptionalFleetData.damage field - which is *only* used in WarSimScript.getFactionStrength(). So if one wanted to, one could have their route-spawned fleet store the level of damage (i.e. losses taken) in that value, use it when spawning (or re-spawning) the fleet, and its strength would vary accordingly for the various strength checks used for resolving not-near-the-player events.

I don't know if I'd recommend it, though - if you try to spawn a fleet using the same random seed but less fleet points, it'd likely end up being a very different fleet. Using the damage field would make more sense for fleets that have never actually spawned.

However, none of the vanilla fleets will use the damage field when spawning, so this would only work for routes where both the spawning and taking damage aspect of this is used. I.E. you couldn't hurt an existing patrol fleet route by setting its OptionalFleetData.damage - or, rather, it would affect it for strength checks, but not for when it was spawned due to being near the player.

What about when two hostile routes meet in a location while player isn't nearby, is any combat simulated between them (or with local non-abstracted fleets)?

No. Route fleets used for strength checks which can affect things like, say, the outcome of a raid, but don't actually affect the routes themselves.

(What I'm trying to do: a persistent route-based fleet that flies around joining raids against hostile systems, or defending against raids on friendly systems, or simply patrols friendly systems. If it takes enough losses, it goes to a faction-held market to replace lost ships with new ones. The route is never actually terminated unless its FP drops to zero, or certain (currently undetermined) conditions are met).

The "damage" field sounds like it'd work for your case, I think. Except for the part where if it despawns and respawns again, the ships would be different.

Btw, you should be able to force a route to end by setting the current segment to null and by clearing the segments, i.e.:

route.setCurrent(null);
route.getSegments().clear();

Should do it.
Logged

creature

  • Captain
  • ****
  • Posts: 400
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5791 on: December 08, 2019, 01:47:38 PM »

FighterWingAPI.orderReturn(ShipAPI fighter)

Thanks for pointing this out, but I have a follow up question regarding this - is it possible to retrieve the FIghterWingAPI from the fighter and not the mothership? I would like the hullmod to be on the fighter, so it would take effect no matter which ship it is mounted.
Logged

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 24118
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5792 on: December 08, 2019, 02:16:35 PM »

ShipAPI.getWing(), iirc.
Logged

creature

  • Captain
  • ****
  • Posts: 400
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5793 on: December 08, 2019, 03:30:15 PM »

ShipAPI.getWing(), iirc.
Again, thank you very much!
Logged

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 24118
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5794 on: December 08, 2019, 03:50:55 PM »

No problem :)
Logged

Sundog

  • Admiral
  • *****
  • Posts: 1727
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5795 on: December 09, 2019, 07:43:15 PM »

Two questions:
1. Will Global.getSector().getCampaignUI().isFollowingDirectCommand() only return false when the autopilot for "lay in course" is active? Is there some other reliable way to find out if autopilot is on?
2. Is there a way to find out which key is bound to a command? Failing that, is there a way to tell when the player is slowing down their fleet even if they've rebound to something other than S?

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 24118
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5796 on: December 09, 2019, 08:17:01 PM »

1) I think so, yes. If isFollowingDirectCommand() returns false, autopilot becomes suspended. So, if you check that
Global.getSector().getUIData().getCourseTarget() (I think this is in the current API? not 100% sure) and then check that it's not following a direct command, then autopilot is on.

2) Hmm - SettingsAPI.getControlStringForEnumName("GO_SLOW") will return the string.

In the next release, there'll be:

Misc.isSlowMoving(fleet)

Which returns true if a fleet is slow-moving, which is a "status" which is used for several things (avoiding collisions with asteroids, etc).
Logged

Sundog

  • Admiral
  • *****
  • Posts: 1727
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5797 on: December 09, 2019, 08:22:05 PM »

Excellent. Thanks Alex!

Histidine

  • Admiral
  • *****
  • Posts: 4682
    • View Profile
    • GitHub profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5798 on: December 10, 2019, 02:24:00 AM »

If a route-spawned fleet takes losses in combat, is this reflected anywhere in the route data at all? Neither OptionalFleetData.fp nor OptionalFleetData.damage are being updated in my RouteFleetSpawner implementation.

It's not reflected anywhere. However, there is an OptionalFleetData.damage field - which is *only* used in WarSimScript.getFactionStrength(). So if one wanted to, one could have their route-spawned fleet store the level of damage (i.e. losses taken) in that value, use it when spawning (or re-spawning) the fleet, and its strength would vary accordingly for the various strength checks used for resolving not-near-the-player events.

I don't know if I'd recommend it, though - if you try to spawn a fleet using the same random seed but less fleet points, it'd likely end up being a very different fleet. Using the damage field would make more sense for fleets that have never actually spawned.

However, none of the vanilla fleets will use the damage field when spawning, so this would only work for routes where both the spawning and taking damage aspect of this is used. I.E. you couldn't hurt an existing patrol fleet route by setting its OptionalFleetData.damage - or, rather, it would affect it for strength checks, but not for when it was spawned due to being near the player.

What about when two hostile routes meet in a location while player isn't nearby, is any combat simulated between them (or with local non-abstracted fleets)?

No. Route fleets used for strength checks which can affect things like, say, the outcome of a raid, but don't actually affect the routes themselves.
Thanks for clearing that up!
Although I have to say, not recording damage looks it leads to some obvious (albeit minor) issues. Two that come readily to mind (I've encountered at least one personally):
  • If the player intercepts a raid fleet short of its target and damages it, then flees elsewhere, one would expect the raid's autoresolve strength to be weakened as a result, but it isn't.
  • If the player encounters raid fleets returning to base after a failed raid, they'll be at full strength when one expects them not to be.
(Anyway, for my current use, I'm currently accepting the fact that the fleet composition can change wildly when recreated after taking damage.
If enough people notice it and get weirded out enough to mention it, I could make the fleets never despawn once spawned by the route manager, although I'm afraid that risks consuming a lot of memory and save file space given how many fleets the player might encounter and how big they'll be)


Other related question: I seem to recall debris and derelict ships being present in star systems with ongoing raids, when the player visits them. Is there some vanilla code that generates them, or am I just completely misremembering things?
Logged

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 24118
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5799 on: December 10, 2019, 03:03:44 PM »

Thanks for clearing that up!
Although I have to say, not recording damage looks it leads to some obvious (albeit minor) issues. Two that come readily to mind (I've encountered at least one personally):
  • If the player intercepts a raid fleet short of its target and damages it, then flees elsewhere, one would expect the raid's autoresolve strength to be weakened as a result, but it isn't.
  • If the player encounters raid fleets returning to base after a failed raid, they'll be at full strength when one expects them not to be.

Fair! Not sure it's worth the complications, but, well, will keep that in mind. It's a bit of work to make everything record and respect the "damage" parameter and it just makes certain things that are already fairly messy (such as the aforementioned raids) messier.

Other related question: I seem to recall debris and derelict ships being present in star systems with ongoing raids, when the player visits them. Is there some vanilla code that generates them, or am I just completely misremembering things?

IIRC that's just from fights that happen after the fleets spawn-in due to the player approaching.
Logged

creature

  • Captain
  • ****
  • Posts: 400
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5800 on: December 12, 2019, 11:44:46 PM »

Hmm, if that's all you need, maybe something like this in your ModPlugin implementation, to provide a custom drone AI that doesn't do anything except stop?

Code
	public PluginPick<ShipAIPlugin> pickDroneAI(final ShipAPI drone, ShipAPI mothership, DroneLauncherShipSystemAPI system) {
if (<not your drone>) return null;
return new PluginPick<ShipAIPlugin>(new ShipAIPlugin() {
ShipwideAIFlags flags = new ShipwideAIFlags();
public void forceCircumstanceEvaluation() {
}
public void advance(float amount) {
drone.giveCommand(ShipCommand.DECELERATE, null, 0);
}
public void setDoNotFireDelay(float amount) {

}
public boolean needsRefit() {
return false;
}
public ShipwideAIFlags getAIFlags() {
return flags;
}
public void cancelCurrentManeuver() {

}
public ShipAIConfig getConfig() {
return null;
}
}, PickPriority.MOD_SPECIFIC);
}
Thank you very much Alex, this worked perfectly!
Going back to this, I finally had some time to test it a bit and realized it made the drone really do nothing but stop. It doesn't even fire or track its target. All of that AI being a bit over my head, is it possible to retain all default AI functions and only override its movement?
Logged

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 24118
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5801 on: December 13, 2019, 09:05:51 AM »

Hmm, not sure what else to suggest then, beyond expanding the custom AI to handle some basic firing. Keeping the standard drone AI means it'll move the way you don't want it to.
Logged

Mongreal

  • Ensign
  • *
  • Posts: 46
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5802 on: December 13, 2019, 12:03:55 PM »

Hello, I haven't been modding Starsector since a very long time, and I'm stuck with some weapon script.
The goal is to make some gatlings spoolup to reach their maximal firerate, starting by firing at a fraction of the final deal.
I'm using Intellij and the compiler doesn't find any mistakes when compiling.
I end up with a error that I mainly see when I made typos in plugins or files names or IDs, but I checked everything multiple times without any succes at troubleshooting this.
Here's the log :
Spoiler
Code
40164 [Thread-4] ERROR com.fs.starfarer.combat.CombatMain  - java.lang.ClassCastException: data.scripts.weapons.SCQ_GatlingSpoolUp cannot be cast to com.fs.starfarer.api.combat.EveryFrameWeaponEffectPlugin
java.lang.ClassCastException: data.scripts.weapons.SCQ_GatlingSpoolUp cannot be cast to com.fs.starfarer.api.combat.EveryFrameWeaponEffectPlugin
at com.fs.starfarer.loading.specs.BaseWeaponSpec.getEveryFrameEffect(Unknown Source)
at com.fs.starfarer.combat.entities.ship.oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.O0oO.<init>(Unknown Source)
at com.fs.starfarer.loading.specs.oooo.super(Unknown Source)
at com.fs.starfarer.loading.specs.oooo.super(Unknown Source)
at com.fs.starfarer.coreui.refit.A.updateFromCurrentVariant(Unknown Source)
at com.fs.starfarer.coreui.refit.A.syncWithVariant(Unknown Source)
at com.fs.starfarer.coreui.refit.C.syncWithVariant(Unknown Source)
at com.fs.starfarer.coreui.refit.W.syncWithCurrentVariant(Unknown Source)
at com.fs.starfarer.coreui.refit.W.syncWithCurrentVariant(Unknown Source)
at com.fs.starfarer.coreui.refit.A.fitWeaponIfPossible(Unknown Source)
at com.fs.starfarer.coreui.refit.A.dialogDismissed(Unknown Source)
at com.fs.starfarer.ui.Oo0OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.dismiss(Unknown Source)
at com.fs.starfarer.ui.impl.K.dismiss(Unknown Source)
at com.fs.starfarer.coreui.refit.WeaponPickerDialog.actionPerformed(Unknown Source)
at com.fs.starfarer.ui.k.buttonPressed(Unknown Source)
at com.fs.starfarer.ui.oooO.new(Unknown Source)
at com.fs.starfarer.ui.oooO.processInput(Unknown Source)
at com.fs.starfarer.ui.k.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.ui.e$Oo.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.ui.v.dispatchEventsToChildren(Unknown Source)
at com.fs.starfarer.ui.v.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.e.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.ui.v.dispatchEventsToChildren(Unknown Source)
at com.fs.starfarer.ui.v.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.ui.v.dispatchEventsToChildren(Unknown Source)
at com.fs.starfarer.ui.v.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.O0OO.oooO.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.ui.v.dispatchEventsToChildren(Unknown Source)
at com.fs.starfarer.ui.v.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.Oo0OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.processInputImpl(Unknown Source)
at com.fs.starfarer.coreui.refit.WeaponPickerDialog.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.ui.v.dispatchEventsToChildren(Unknown Source)
at com.fs.starfarer.ui.v.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.Oo0OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.newui.J.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.ui.v.dispatchEventsToChildren(Unknown Source)
at com.fs.starfarer.ui.v.processInputImpl(Unknown Source)
at com.fs.starfarer.ui.interface.processInput(Unknown Source)
at com.fs.starfarer.campaign.CampaignState.processInput(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]

And this is my attempt at making this plugin :
Spoiler
Code
package data.scripts.weapons;

import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.EveryFrameWeaponEffectPlugin;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.*;
import com.fs.starfarer.api.loading.WeaponSpecAPI;
import com.fs.starfarer.api.util.IntervalUtil;
import org.lazywizard.lazylib.MathUtils;
import org.lwjgl.util.vector.Vector2f;

public class SCQ_GatlingSpoolUp implements EveryFrameWeaponEffectPlugin {

    private CombatEngineAPI engine;
    private static final String DATA_KEY = "SCQ_Gatling";
    private static String weaponSound = "";
    private static String weaponProjectile = "";
    private static final String SMALL_SHOT_ID = "small_gatling_shot";
    private static final String MEDIUM_SHOT_ID = "medium_gatling_shot";
    private static final String LARGE_SHOT_ID = "large_gatling_shot";
    private float charge = 0f;
    private float modifier = 0f;
    private float startingDelay = 0f;
    private float delayDecrement = 0f;
    private float lastDelay = 0f;
    private float finalDelay = 0f;
    private float minSpread = 0;
    private float maxSpread = 0;
    private boolean runOnce = false;
    private IntervalUtil fireInterval;

    @Override
    public void advance(float amount, CombatEngineAPI engine, WeaponAPI weapon) {
        if (this.engine == null) {
            return;
        }
        if (this.engine.isPaused()) {

            return;
        }

        WeaponAPI.WeaponSize size = weapon.getSize();

        if (!runOnce) {
            runOnce = true;
            modifier = 1f;
            switch (size){
                case SMALL:
                    startingDelay = 30f;
                    delayDecrement = 3f;
                    finalDelay = 3f;
                    weaponSound = "small_gatling_fire";
                    weaponProjectile = SMALL_SHOT_ID;
                    minSpread = 2f;
                    maxSpread = 6f;
                    break;
                case MEDIUM:
                    startingDelay = 40f;
                    delayDecrement = 3f;
                    finalDelay = 4f;
                    weaponSound = "medium_gatling_fire";
                    weaponProjectile = MEDIUM_SHOT_ID;
                    minSpread = 2f;
                    maxSpread = 5f;
                    break;
                case LARGE:
                    startingDelay = 50f;
                    delayDecrement = 3f;
                    finalDelay = 5f;
                    weaponSound = "large_gatling_fire";
                    weaponProjectile = LARGE_SHOT_ID;
                    minSpread = 1.5f;
                    maxSpread = 4.5f;
                    break;
                default:
                    return;
            }
            fireInterval = new IntervalUtil(0f, startingDelay);
        }

        ShipAPI ship = weapon.getShip();
        if (ship != null) {
                modifier = ship.getMutableStats().getBallisticRoFMult().getModifiedValue();
            }

            charge = weapon.getChargeLevel();
            if (charge > 0f) {
                lastDelay = fireInterval.getMaxInterval();
                fireInterval.advance(amount);
                if (fireInterval.intervalElapsed()) {
                    float spread = MathUtils.getRandomNumberInRange(minSpread, maxSpread);
                    Global.getSoundPlayer().playSound(weaponSound, 1f, 1f, weapon.getLocation(), ship.getVelocity());
                    engine.spawnProjectile(
                            ship,
                            weapon,
                            weapon.getId(),
                            weaponProjectile,
                            weapon.getLocation(),
                            weapon.getArcFacing(),
                            new Vector2f(weapon.getProjectileSpeed(), spread));
                    if (lastDelay > (finalDelay * modifier)) {
                        lastDelay -= delayDecrement;
                    }
                    fireInterval = new IntervalUtil(0f, lastDelay);
                }
            } else {
                lastDelay = fireInterval.getMaxInterval();
                if (lastDelay < (finalDelay * modifier)) {
                    lastDelay += (delayDecrement * 1.5f);
                }
            }
        }
    }
[close]
Logged

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 24118
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5803 on: December 13, 2019, 12:15:13 PM »

Nothing jumps out as being wrong (though I could be missing something), so my guess is "Janino doesn't like something about this so doesn't actually manage to compile it". Suggestions: add a default constructor to the class (helps sometimes), or (more recommended) compile this into a jar and provide that with your mod instead of having the game try to compile it on startup.
Logged

creature

  • Captain
  • ****
  • Posts: 400
    • View Profile
Re: Misc modding questions that are too minor to warrant their own thread
« Reply #5804 on: December 13, 2019, 04:13:15 PM »

Hmm, not sure what else to suggest then, beyond expanding the custom AI to handle some basic firing. Keeping the standard drone AI means it'll move the way you don't want it to.
Hmm... I see, is there a sort of code sample I could take a look at to implement aiming a weapon and firing it? I've never actually visited this corner of the API before...

And I have another, different question -  how does one give commands to single fighters (i.e. spawned via code using engine.getFleetManager(owner).spawnFleetMember())? I'm aware of how to give commands to bigger ships via fleetManager.getTaskManager(false), but am unsure if the same would work for commanding fighters.

Also, how would they behave once their ammo was depleted, if they were set as bombers? If there was a command to make them retreat, where would they go? Would their behavior be similar to fighters whose motherships had retreated? (i.e. they bunch up at your edge of the map)
Logged
Pages: 1 ... 385 386 [387] 388 389 ... 710