Modding Help Auto-lounge the player in a vehicle?

Discussion in 'Starbound Modding' started by Severyx, Jul 25, 2017.

  1. Severyx

    Severyx Void-Bound Voyager

    Hello all! So I'm brand new to modding and have been spending a lot of time trying out all sorts of things. Little by little things are coming together, but I've hit a brick wall.

    Essentially what I'm trying to achieve is that the player is automatically placed into a new 'vehicle' object when it is instantiated. The vehicle itself is so far working as I expect (extremely barebones, but as expected nonetheless), but there's an error in my .lua script when I try to call:
    player.lounge(entity.id())
    in my init function.

    [12:41:36.805] [Error] Exception while calling script init: (LuaException) Error code 2, [string "/vehicles/animControl/animControl.lua"]:135: attempt to index a nil value (global 'player')

    I realize that the player.lounge() documentation says it can have two parameters(one for a loungeable entityID and one for an anchor index), but I've looked up other uses of this line and they only include a loungeableID and if I try to include an int for the index it throws a different error. I have similar errors any time I try to use the player API in general.

    Any thoughts?
     
    Last edited: Jul 26, 2017
  2. bk3k

    bk3k Oxygen Tank

    You don't have access to the player table from all contexts. You'd need to add a messaging handler to the player's _ENV

    Unless there is another way to accomplish what you're trying to do with that function.
     
    Errors4l likes this.
  3. Severyx

    Severyx Void-Bound Voyager

    Attempting to work around the context limitations using this process:

    function makePlayerLounge()

    sb.logInfo("should be making the player lounge.")
    local currentPlayers = world.players()
    sb.logInfo(currentPlayers[1] .. " is the entity")
    local uniquePlayer = world.entityUniqueId(currentPlayers[1])
    sb.logInfo(uniquePlayer .. " is the unique id")
    world.sendEntityMessage(uniquePlayer, "onInteraction", {sourceId = entity.id()})
    if world.loungeableOccupied(entity.id()) then notLounging = false else notLounging = true end

    end​

    This is called in update (I read that calling this during init is not advised as the source entity might not yet be loaded) and only called if notLounging is true. Since the player doesn't lounge, this is always true. I also notice that if the vehicle has more than one lounging position (such as the passenger on the hoverbikes), it doesn't register as occupied when someone is in any loungePosition other than the first.

    The log shows this:

    [15:29:03.137] [Info] should be making the player lounge.
    [15:29:03.137] [Info] -65536 is the entity
    [15:29:03.137] [Info] bb1b69bbcff6bee0f146f7fdf54ddd83 is the unique id
    <repeat ad nauseum>

    Nothing seems to happen though, not even error messages. The logInfo messages come through just fine, but the message callback doesn't produce anything. Am I to assume the unique id is just as invalid as the entity id?

    As you can see I'm pretty new to the _ENV deal. How would I go about making such additions to the player _ENV?
     
    Last edited: Jul 25, 2017
  4. cpeosphoros

    cpeosphoros Orbital Explorer

    There is a "Thread tools" link on the right top corner which allows you to do that, amongst other things.

    Now, for the API thing. In your Starbound installation folder, there is a directory called doc/lua, which holds *.md files for all the API tables, which seems you have already read, by the context of your question. Also, by the same context, it seems though you are new to modding you are not new to coding, so please ask further if my answer is too terse.

    For "player.md", there is this remark just in the beginning:
    Code:
    The player table contains functions with privileged access to the player which
    run in a few contexts on the client such as scripted interface panes, quests,
    and player companions.
    One possible way for accomplishing what you want would be by giving the player an invisible quest and inside that quest's code calling player.lounge.

    Here is some sample boilerplate for an invisible quest:
    Code:
    {
        "id" : "inv01",
        "mainQuest" : false,
        "title" : "invisible quest 01.",
        "text" : "Go with the player.",
        "completionText" : "Should never be completed, nor fail!",
        "moneyRange" : [0, 0],
        "canBeAbandoned" : false,
        "invisible" : true,
        "logOnly" : true,
        "updateDelta" : 60,
        "script" : "/scripts/myscripts/inv01.lua"
    }
    Then you will be able to call player.lounge inside inv01.lua.
     
  5. Severyx

    Severyx Void-Bound Voyager

    Thank you for the information, cpeosphoros. As you guessed, I am new to modding, lua, and JSON but not necessarily new to coding in general (I typically program in C# in Unity3D, occasionally C++ when I have time to attempt learning it). Also thanks for the thread tools pointer, I clearly failed that perception check hah.

    I had always expected I would need to do something with quests (Looking to eventually build the foundations for a persistent animation control framework utilizing .dance files) but I hadn't gotten to delving into quest files and structure yet. I'm still learning how context/privileges in regards to metatables and such work. I also anticipated that I would need to also figure out stagehands, since that SEEMS to be the way the game handles quest processes. Though if the quest is always running in the background I may not need to.

    I'll dive into quests next, then, and see what I can come up with. Again, thank you for the info!
     
  6. Severyx

    Severyx Void-Bound Voyager

    So I've made a quest and it's running and such in the background and I've set up a message handler, but I don't know how to send it a message to enact a function that has it lounge the player. Typically I see other scripts use sendEntityMessage(xx, yy, zz), but I'm not sure how to utilize the correct entityID to call this quest script. Ideas?

    Additionally, every time I try to pull an entityId from anything, it's always -65536....
     
    Last edited: Jul 29, 2017
  7. cpeosphoros

    cpeosphoros Orbital Explorer

    This is from something I'm working on:
    Code:
    function onInit()
        message.setHandler("setParameter",setParameter)
       -- more init code
    end
    
    data = {
        parm1 = false,
        parm2 = false,
        parm3 = false,
        -- etc
    }
    function setParameter(_, _, parameter, value)
        -- check for nil
        if parameter and data[parameter] ~= nil then
            data[parameter].value = value
        elseif parameter then
            sb.logWarn("CPE: Missing parameter "..parameter)
        else
            sb.logWarn("CPE: Nil parameter argument")
        end
    end
    Then in the quest script I call world.sendEntityMessage( entityId, "setParameter", "parm1", value)
     
  8. cpeosphoros

    cpeosphoros Orbital Explorer

    Oh, rereading your question, I see you need to find entityId. Here is how I do it:
    Code:
    function update(dt)
        --we just need to scan the local shops near the player 
        --as it walks around.
    
        --the radius can be tinkered around, if performance is a problem
        entityIds = world.objectQuery(playerPosition(), 200)
    
        if entityIds then
            for _, entityId in ipairs( entityIds ) do
                name = world.entityName(entityId)
                if name = myName then
                    -- those are the droids we are looking for
                    sb.logInfo("--------------------------------------------- We've got a "..name)
                    -- send the messages
                    world.sendEntityMessage( entityId, "setParameter", "parm1", value)
                    -- etc
                end
            end
        end
    end
     
  9. Severyx

    Severyx Void-Bound Voyager

    I managed to figure it out a couple hours ago. The main point of confusion I was having was that I didn't understand that quests had the same entityID as the player, so I was pulling my hair out for a while. I seem to have managed to achieve the effect I was looking for, for the most part. Right now I have an item that when used sends a message to the quest to call up the function to spawn a vehicle and trigger auto-lounge.
     
    cpeosphoros likes this.
  10. cpeosphoros

    cpeosphoros Orbital Explorer

    Nicely done!
     

Share This Page