Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Starsector 0.95.1a is out! (12/10/21); Blog post: The Pilgrim's Path (07/19/22)

Author Topic: Manually changing of animation frame refusing to cooperate  (Read 1125 times)

AxleMC131

  • Admiral
  • *****
  • Posts: 1721
  • Amateur World-Builder
    • View Profile
Manually changing of animation frame refusing to cooperate
« on: August 17, 2019, 05:44:23 PM »

I've been tearing my hair out for about three weeks trying to figure out why I can't make (what I thought was) a pretty simple setup work, and I've come to the conclusion that there's something very strange and fundamental going on in the core game that's preventing me from achieving this. Whether it is a bug or not I have no clue, but I would very much like it to be looked into either way, as it makes zero sense. Regardless, that's why I've stuck it here in Bug Reports. If a moderator would rather it be in the Modded subforum, that's fine by me, as long as it gets addressed, or at the very least explained.



Situation/objective:
I have a decorative weapon with multiple animation frames on a ship. The ship also has two unique hullmods: one built-in and hidden, the other modular and visible. The built-in hullmod does all the work. If the player tries to remove the modular hullmod, the built-in one notices this as a trigger, and "does something", before manually re-installing the modular hullmod. The result is a "cyclic" function that lets the player toggle through a series of options by repeatedly removing the modular hullmod. Presently, that series of options is the series of animation frames for the decorative weapon. (This is all cosmetic for now.)

Problem:
No matter which way I slice this damn system, I cannot get the deco weapon to change animation frame in the way I want it. I can forcibly set it to a particular value if I just stick a hard number in the script, but the moment I put in a saved number attached to the ship ID (fleetMemberId actually), it refuses to change.

Worse, I've set up a logger so I can see if the saved value is incrementing... And it goddamn IS! For reasons beyond my comprehension, this line...
Code: java
wpn.getAnimation().setFrame(SAVED_DATA.get(shipId));
... does not work.

For full context, here's the whole of the meat of the script (this is the built-in hullmod). "dara_arrow_paintcycle_trigger" is the modular hullmod that the player removes to cycle the setup.
Code: java
@Override
    public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
       
        String shipId = ship.getFleetMemberId();
       
        if (SAVED_DATA.get(shipId) == null) {
            SAVED_DATA.put(shipId, 0);
            log.info("Reset frame to #0");
        }
       
        if (!ship.getVariant().hasHullMod("dara_arrow_paintcycle_trigger")) {
            for (WeaponAPI wpn : ship.getAllWeapons()) {
                if (wpn.getId().contains("dara_arrow_paint")) {
                    int currFrame = SAVED_DATA.get(shipId);
                    log.info("Retrieved frame #" + currFrame);
                    if (currFrame + 1 > 12) {
                        currFrame = 0;
                    } else {
                        currFrame += 1;
                    }
                    SAVED_DATA.put(shipId, currFrame);
                    log.info("Incremented to and saved frame #" + SAVED_DATA.get(shipId));
                    wpn.getAnimation().setFrame(SAVED_DATA.get(shipId));
                    ship.getVariant().addMod("dara_arrow_paintcycle_trigger");
                    runOnce = false;
                    break;
                }
            }
        }
       
    }
As you can see, I've got multiple log outputs here, which have very clearly been showing the saved value incrementing, live, as I try to cycle the hullmod from the refit screen:

Code
98010 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Reset frame to #0
98010 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Retrieved frame #0
98010 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Incremented to and saved frame #1
98977 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Retrieved frame #1
98977 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Incremented to and saved frame #2
113244 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Retrieved frame #2
113245 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Incremented to and saved frame #3
114526 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Retrieved frame #3
114527 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Incremented to and saved frame #4
127248 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Retrieved frame #4
127248 [Thread-4] INFO  data.scripts.hullmods.dara_RedArrowPaint  - Incremented to and saved frame #5
And yet, in the refit screen, the animation frame of the weapon does not change.

YES the deco weapon has the right frames setup and is visible and all that jazz. I've tried multiple ways to ensure this, everything from manually giving the setFrame() call values for each one, to just making the animation have a non-zero frame rate and watching it go through each one from the refit screen.

NO the frame does not update in combat. It refuses to work anywhere... Except for the codex. If you repeatedly click the ship's entry in the codex, you can see the image of the ship cycling through the animation frames exactly as I want it to elsewhere. What the hell!?



The worst bit about all of this? I KNOW that you CAN make a system just like this that manually changes weapon animation frame on a cyclic basis, because I've already done it once. I'm not annoyed because it looks like this is impossible: I'm annoyed because I know it IS possible, and I cannot understand why I'm unable to make it work a second time.

I'm at my wit's end with this damn thing, tried about five different methods to make it work, and I'm |this close| to giving up. Help is sorely, desperately wanted.
Logged

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 20606
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #1 on: August 17, 2019, 06:05:16 PM »

(Moved this to modding because the bug reports section is for bugs that affect vanilla. It could arguably go into bug reports (modded) but it's not clear if there's a bug here or not.)

It's not clear to me exactly what's going on here. If you say hardcoded numbers work, but putting in the same values (verified by logging them) from variables doesn't... that's not actually possible, so something else must be going on.

I would suggest getting something that works, and then, step by tiny step, moving until it doesn't. It sort of sounds like you've been doing that, but...
Logged

AxleMC131

  • Admiral
  • *****
  • Posts: 1721
  • Amateur World-Builder
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #2 on: August 17, 2019, 06:08:53 PM »

(Moved this to modding because the bug reports section is for bugs that affect vanilla. It could arguably go into bug reports (modded) but it's not clear if there's a bug here or not.)

It's not clear to me exactly what's going on here. If you say hardcoded numbers work, but putting in the same values (verified by logging them) from variables doesn't... that's not actually possible, so something else must be going on.

I would suggest getting something that works, and then, step by tiny step, moving until it doesn't. It sort of sounds like you've been doing that, but...

Yeah, each time I've been starting afresh from the most basic possible form, which doesn't even use saved data but just looks at the weapon's current frame; goes "current frame + 1", and then sets the weapon frame to that new value. (Problem is I think this doesn't carry over through refit functions.)

I even tried it without the specific hullmod trigger, I just tied to checking for an arbitrary vanilla hullmod to be installed (Auxiliary Fuel Tanks, if it helps) and increment the frame then. The result was that when the hullmod was installed, the frame incremented to the next successfully, but when removed it went back to the previous one again, despite there not being anything in the script telling it to. Again: Pretty sure the value doesn't carry over refit functions... Does refitting a ship reset the animation state of animated weapons?

Damn, though, that's really frustrating. I'm convinced there's something fundamental about the way this script should work that I'm missing, but... It's just not showing itself. Incidentally I have also tried this with the frame set occuring in the advanceInCombat() part of the hullmod script, but that didn't work either. I'm honestly out of ideas.  :-[
« Last Edit: August 17, 2019, 06:13:04 PM by AxleMC131 »
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 4931
  • naively breaking things!
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #3 on: August 17, 2019, 06:23:39 PM »

OK, let's start with some basics here:

1.  If you set it to frame 0, 1, 2, etc. by fiat... that works as intended, correct?

i.e., in Loadout: 

wpn.getAnimation().setFrame(0); 

This works as intended?  I haven't tried that before; I always presumed that Decoratives were locked on Frame 0 while in Loadout.

2.  If that's working, then we're dealing with an issue of saved data. 

Do you have a data-source where you're storing that data when the Campaign gets loaded?  This SAVED_DATA appears to be the place.  How's that set up?  From what you're saying thus far, it sounds like maybe you're trying to get that number to increment, but write access to that data might be one-way.

3.  There is a lot in that code that could be improved. 

Like, if the FleetMemberAPI doesn't have the Hull Mod, it doesn't need to be in SAVED_DATA at all (if anything, it should be in a globally-accessible HashSet so it never gets past the first check again). 

You should not use a break statement; that is unnecessary and might be problematic unless a ship may have more than one dara_arrow_paint (as the code's written, it looks pretty obvious that you're expecting one, and only one, to be installed).  In general, only use break when, and only when, you really absolutely have to and know exactly what loop(s) you may be exiting as a result.

You can use a globally-accessible HashMap to store <FleetMemberAPI,currentFrameState>.
Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 4931
  • naively breaking things!
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #4 on: August 17, 2019, 06:24:59 PM »

Quote
Does refitting a ship reset the animation state of animated weapons?
I think it does; IIRC, I used that for my "flames" trick for the retros I put on the Vacuum ships.  Like I said above; if setting it manually works... store the data somewhere that's accessible globally (i.e., write your own class etc.) and if you need it to survive in a savegame, then that's another wrinkle.
Logged
Please check out my SS projects :)
Xeno's Mod Pack

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 20606
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #5 on: August 17, 2019, 06:37:59 PM »

Again: Pretty sure the value doesn't carry over refit functions... Does refitting a ship reset the animation state of animated weapons?

It should reset the state, yeah. Every time the variant changes I think the ship gets recreated? Not 100% sure offhand...

Might be worth calling pause() on all the animations regardless of what else happens, so that they don't try to run due to time advancing (which shouldn't happen in the refit screen, but...)
Logged

AxleMC131

  • Admiral
  • *****
  • Posts: 1721
  • Amateur World-Builder
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #6 on: August 17, 2019, 06:40:48 PM »

Again: Pretty sure the value doesn't carry over refit functions... Does refitting a ship reset the animation state of animated weapons?

It should reset the state, yeah. Every time the variant changes I think the ship gets recreated? Not 100% sure offhand...

Might be worth calling pause() on all the animations regardless of what else happens, so that they don't try to run due to time advancing (which shouldn't happen in the refit screen, but...)

I'm not sure pause would be necessary, the animation is static normally, ie. has a frame rate of zero and "alwaysAnimate" set to false. It should only be changed by the hullmod setup.
Logged

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 20606
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #7 on: August 17, 2019, 06:43:01 PM »

Hmm, alright, yeah, that should cover it.
Logged

AxleMC131

  • Admiral
  • *****
  • Posts: 1721
  • Amateur World-Builder
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #8 on: August 17, 2019, 06:45:55 PM »

1.  If you set it to frame 0, 1, 2, etc. by fiat... that works as intended, correct?

Yes.

2.  If that's working, then we're dealing with an issue of saved data. 

Do you have a data-source where you're storing that data when the Campaign gets loaded?  This SAVED_DATA appears to be the place.  How's that set up?  From what you're saying thus far, it sounds like maybe you're trying to get that number to increment, but write access to that data might be one-way.

SAVED_DATA is a Hashmap.
Code
private Map<String, Integer> SAVED_DATA = new HashMap<>();
Access is definitely read and write. The log outputs prove that.

3.  There is a lot in that code that could be improved. 

Like, if the FleetMemberAPI doesn't have the Hull Mod, it doesn't need to be in SAVED_DATA at all (if anything, it should be in a globally-accessible HashSet so it never gets past the first check again). 

The code extract in the OP is from the hullmod in question. It only applies to those ships using this system.

You should not use a break statement; that is unnecessary and might be problematic unless a ship may have more than one dara_arrow_paint (as the code's written, it looks pretty obvious that you're expecting one, and only one, to be installed).  In general, only use break when, and only when, you really absolutely have to and know exactly what loop(s) you may be exiting as a result.

The break probably isn't necessary, it's mostly there as a safeguard against I-don't-know-what. What are the issues with having one there though?

You can use a globally-accessible HashMap to store <FleetMemberAPI,currentFrameState>.

This is pretty similar to what we have already, except we're storing the FleetMemberAPI ID as a string, rather than the whole API instance.
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 4931
  • naively breaking things!
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #9 on: August 17, 2019, 07:15:14 PM »

Quote
Yes.
That's cool.  Didn't know we could mess with it there :)

Quote
The break probably isn't necessary, it's mostly there as a safeguard against I-don't-know-what. What are the issues with having one there though?
It's probably safe there... but a break can, well, break things in weird ways, because of how it skips to the next operation.  I avoid it in favor of <boolean check, continue if true / false> or return instead, for things like this, where we're more worried about safety than speed.  I can count the number of times I've used break outside of switches without running out of fingers and toes, honestly.

Code
private Map<String, Integer> SAVED_DATA = new HashMap<>();
So, you're storing this in the Hull Mod's code? 

I'd suggest another class, instantiated at runtime, like the modPlugin, where you know it's instantiated and, if it has some data pulled in from the save-file to populate that HashMap that will get accessed, it won't get GC'd.

Another possibility is that the FleetMemberAPI ID's not stable; maybe it's getting re-built as a result of other things? 

From what you've said thus far, it appears that the big problem's not that wpn.getAnimation().setFrame() doesn't work in that context, it's just not getting the right integer.

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

AxleMC131

  • Admiral
  • *****
  • Posts: 1721
  • Amateur World-Builder
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #10 on: August 17, 2019, 07:19:21 PM »

Something weird, for sure. Idk, I think I'm going to can the concept for now. I'll keep the working files in limbo in case any new ideas come up, but for this update I'll have to put it aside. Somewhat disappointing, but just the way of things I guess.
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 4931
  • naively breaking things!
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #11 on: August 17, 2019, 07:43:49 PM »

Here, try this before giving up.

First, write a non-transient campaignPlugin to store the stuff outside the Hull Mod, etc.
Code
package data.scripts;

public class my_neato_CampaignPlugin extends BaseCampaignPlugin {

  public static Map<String,Integer> myFrameSet = new HashMap<>();
  public static List<String> isSpecial = new ArrayList<>();
  public static List<String> notSpecial = new ArrayList<>();

    @Override
    public String getId() {
            return "my_neato_CampaignPlugin"; // make sure to change this for your mod
    }

    // This plugin is not marked transient, because it saves data in the savefile.
    // Because of that, a savegame that ran with this plugin would not load properly
    // after this mod is disabled.
    @Override
    public boolean isTransient() {
            return false;
    }
}

Ok, the above covers having a data source that should get stored with Campaign states, IIRC.  It also provides a hook for your code.  So, something like this:

Code
	@Override
public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
String fleetMemberId = ship.getFleetMemberId();

//Use an additional invisible Hull Mod's presence to halt useless operations.
if (!ship.getVariant().hasHullMod("check_for_this_hullmod")) {
my_neato_CampaignPlugin.notSpecial.put(fleetMemberId);
return;
} else {
my_neato_CampaignPlugin.isSpecial.put(fleetMemberId);
}

//Only do stuff if we have that special invisible Hull Mod.
if(my_neato_CampaignPlugin.isSpecial.contains(fleetMemberId)){
//Ship is missing the visible Hull Mod that's used as a logic controller
if (!ship.getVariant().hasHullMod("dara_arrow_paintcycle_trigger")) {
boolean stop = false;
for (WeaponAPI wpn : ship.getAllWeapons()) {
if(stop) continue;//Safely ignore rest of loop
if (wpn.getId().equals("dara_arrow_paint")) {
int currFrame = my_neato_CampaignPlugin.myFrameSet.get(fleetMemberId);
log.info("Retrieved frame #" + currFrame);
if (currFrame + 1 > 12) {
currFrame = 0;
} else {
currFrame += 1;
}

my_neato_CampaignPlugin.myFrameSet.put(fleetMemberId, currFrame);
log.info("Incremented to and saved frame #" + currFrame);
wpn.getAnimation().setFrame(currFrame);
ship.getVariant().addMod("dara_arrow_paintcycle_trigger");
}
}
}
}
}
Logged
Please check out my SS projects :)
Xeno's Mod Pack

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 20606
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #12 on: August 17, 2019, 08:08:55 PM »

@Axle: if you can send me a minimal version of this that exhibits the problem and some real simple instructions to reproduce (i.e. do X, you should see Y, but you see Z), I can take a look.
Logged

AxleMC131

  • Admiral
  • *****
  • Posts: 1721
  • Amateur World-Builder
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #13 on: August 17, 2019, 09:55:02 PM »

@Axle: if you can send me a minimal version of this that exhibits the problem and some real simple instructions to reproduce (i.e. do X, you should see Y, but you see Z), I can take a look.

??? I can certainly try. Actually that's going to be far more trouble than it's worth. I'll just send you a dev version of the mod to have a look at, the problem bit isn't hard to find.
« Last Edit: August 17, 2019, 10:00:33 PM by AxleMC131 »
Logged

AxleMC131

  • Admiral
  • *****
  • Posts: 1721
  • Amateur World-Builder
    • View Profile
Re: Manually changing of animation frame refusing to cooperate
« Reply #14 on: August 17, 2019, 09:56:04 PM »

Here, try this before giving up.

First, write a non-transient campaignPlugin to store the stuff outside the Hull Mod, etc.
...

While it's appreciated, at that point the setup is becoming too complex to be worth the effort of having it I'm afraid. This was only really meant to be a gimmick, not a fundamental feature.
Logged