Modding Help Beginner here: Can't get an animation state machine to work

Discussion in 'Starbound Modding' started by blackmagicfine, Apr 26, 2017.

  1. blackmagicfine

    blackmagicfine Void-Bound Voyager

    Hey Community,

    I'm new to the modding scene and lua. As a test, I want to make a simple block which, when interacted with, changes frame. The png file consists of three 8x8 frames which denote the pixelated letters "A", "B", and "C". The state machine's start state is "A", and interacting with the block should advance the state from "A"==>"B", "B"==>"C", and "C"==>"A".

    I seem to have the start state done correctly (as the block shows "A" upon initialization), however I cannot for the life of me get the state to change properly. It looks like I can change the state in lua, but the Starbound's animator infrastructure isn''t propagating this new state correctly: the block forever show's "A" no matter how much I mash the interact button. This is true even when I try setting the state's value to "B" on init. It also show's "A" even if I don't set up anything in init, so I'm not sure what's up with that.

    Could someone here tell me what I'm doing wrong? I imagine it's a problem with writers_block.animation or writers_block.lua but I'm not sure how to fix it. I have a zip file of the work in progress mod attached. It's pretty small, but not so small that I can copy/paste the code to here I think.

    Thanks!
     

    Attached Files:

  2. bk3k

    bk3k Oxygen Tank

    For one thing, your object doesn't define

    "animationParts" : {
    "symbol" : "writers_block.png"
    },

    Your object also lacks "symbol" as a parameter for config.getParameter to retrieve. So you script relies upon the default "A" every time.

    and your .animation file is missing things.
    Recommended animation file
    Code:
    {
      "animatedParts" : {
        "stateTypes" : {
          "symbolState" : {
            "default" : "A",
            "states" : {
              "A" : {"frames": 1},
              "B" : {"frames": 1},
              "C" : {"frames": 1}
            }
          }
        },
        "parts" : {
          "symbol" : {
            "properties" : {
              "centered" : false
            },
    
            "partStates" : {
              "symbolState" : {
                "A" : {
                  "properties" : {
                    "image" : "<partImage>:<color>.A"
                  }
                },
                "B" : {
                  "properties" : {
                    "image" : "<partImage>:<color>.B"
                  }
                },
                "C" : {
                  "properties" : {
                    "image" : "<partImage>:<color>.C"
                  }
                }
              }
            }
          }
        }
      }
    }
    
    Suggested lua file
    Code:
    symbols = {"A", "B", "C"}
    
    function init()
      storage.counter = storage.counter or 1
      --storage.state is somewhat special, only use for boolean.
      symbols = config.getParameter("customSymbols", symbols)
      
      self.interactive = config.getParameter("interactive", true)
      object.setInteractive(self.interactive)
    
      sb.logInfo("writers_block.lua::init: storage.state = " .. storage.state)
      setCharState(symbols[storage.counter])
    end
    
    function onInteraction(args)
      storage.counter = storage.counter + 1
      if symbols[storage.counter] then
        setCharState(symbols[storage.counter])
      else
        storage.counter = 1
        setCharState(symbols[1])
      end
    end
    
    function setCharState(newState)
      animator.setAnimationState("symbolState", newState)
        
      sb.logInfo("\nwriters_block.lua::setCharState: " .. newState .. "\n")
    end
    
    Did I test this to make sure it works? Of course not! I have to leave room for an embarrassing piece of "stupid code" or two. But there is at least a 72.59% chance that works right off.

    And also note that while I noted above that your object lacks a "symbol" parameter, the code change doesn't use it anyhow. You CAN optionally define add something like
    Code:
    "customSymbols" : [
      "B", "A", "D"
      ],
    
    or
    Code:
    "customSymbols" : [
    "0", "1", "2", "3", "4, "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
      ],
    
    Of course that assumes your animation and frames file can accommodate those other states. And if you wanted that many states, a <tag> in your animation might be more practical. For now you wouldn't need that extra attribute, but that code supports replacing the symbol table in any case.

    One other thing, I recommend to only attempt to use storage.state for boolean values. Starbound won't save most your storage table(or much of anything) but it will save storage.state. Yet it only saves in a boolean reduced state. For example 7 after exiting and reloading becomes true.
     
  3. blackmagicfine

    blackmagicfine Void-Bound Voyager

    Thanks for the detailed response!

    Eventually I will in fact want more than just 3 and even 8 states. Realistically, I should only need to save a counter, and have a function which converts the counter to a character. I take it that storage.counter should be explicitly used for integers and storage.state should be explicitly used for booleans?

    I also take it that both <frame> and <color> are examples of tags? How would I go about adding a new <tag>?

    I'm not sure if I even really need a tag or a state machine. My end goal is pretty much a frame grid with each row being a font color and each column being a letter of the alphabet. There is a 1:1 relationship between <frame> and <symbol>. Is it possible to accomplish this using the existing <frame> tag instead of making a new tag entirely? I tried this once before and the object would just loop through all states endlessly.
     
  4. bk3k

    bk3k Oxygen Tank

    <frame> is a special tag used for animations.
    <color> was once used to enable colored object, but they removed this aspect and I think the game is currently hard-coding <color> to "default" where ever you see it:mad:

    Adding new tags is easy, as is setting them in LUA. For example see how doors work.

    storage.counter isn't special. I chose that namespace because it is reasonably obvious. storage.state however is treated specially. Unfortunately the game isn't going to save your counter value easily. It will maintain your values until you exit the game, and after that you've back to square one. There are ways around that.

    You can learn a few methods to retain data from this
    http://community.playstarbound.com/resources/mr-mad-doctors-experiments-2.4130/
    and possibly some other useful things you didn't know how to do.
     

Share This Page