Quest creation using Lua

    Joined
    Jun 10, 2015
    Messages
    333
    Reaction score
    98
    • Community Content - Bronze 1
    • Purchased!
    • Legacy Citizen 4
    Okay, so I've been messing around with Lua for the past week and looking at the different Npc files that control their behavior with an Lua editor.

    Now I can basically alter what the TG merchant says in his text dialogs, what he sells, and the prices he charges, but just looking at the code can only tell me so much.

    I was wondering what other calls Lua can make to the Java code to change certain things like;

    • Charging FP for things instead of credits. Would also have to check if the player talking to the merchant is the faction founder.
    • Check if the player has a specific quest item, which could be turned in for a reward.
    • Lastly, if it's possible to alter the name, skin, and equipment hired crew spawns with when you hire them using Lua script.
    Any tutorials you guys could point me to would be extremely helpful.

    The quest I had in mind is a simple "clear out the quads piers on my ship" kind of quest, if anyone is curious as to what I'm up to. Other quests may come later, we will see.
     

    nightrune

    Wizard/Developer/Project Manager
    Joined
    May 11, 2015
    Messages
    1,324
    Reaction score
    577
    • Schine
    • Top Forum Contributor
    • Thinking Positive
    There is actually a fare bit you can do but its all completely unsupported. You won't be able to make quests yet (easily) since there is no way (I've found) to save state, and there is no way to update quest states on the character either.
     
    Joined
    Jun 10, 2015
    Messages
    333
    Reaction score
    98
    • Community Content - Bronze 1
    • Purchased!
    • Legacy Citizen 4
    There is actually a fare bit you can do but its all completely unsupported. You won't be able to make quests yet (easily) since there is no way (I've found) to save state, and there is no way to update quest states on the character either.
    I kind of figured that keeping track of completed quests or even making them reset after completion would either be tricky or impossible at this point in time, but if I can get a basis to start off with until it gets supported then I'll be ready for it.
     

    nightrune

    Wizard/Developer/Project Manager
    Joined
    May 11, 2015
    Messages
    1,324
    Reaction score
    577
    • Schine
    • Top Forum Contributor
    • Thinking Positive
    I kind of figured that keeping track of completed quests or even making them reset after completion would either be tricky or impossible at this point in time, but if I can get a basis to start off with until it gets supported then I'll be ready for it.
    The only useful thing I've managed to do was to make HTTP calls to external sites and show its text in the dialog box. You could probably use it to do quests but the only way they interact is if talk to an NPC.
     
    Joined
    Jun 10, 2015
    Messages
    333
    Reaction score
    98
    • Community Content - Bronze 1
    • Purchased!
    • Legacy Citizen 4
    The only useful thing I've managed to do was to make HTTP calls to external sites and show its text in the dialog box. You could probably use it to do quests but the only way they interact is if talk to an NPC.
    I've been tinkering with an npc you could chat with for lore info, but he doesn't do much else right now.
     

    nightrune

    Wizard/Developer/Project Manager
    Joined
    May 11, 2015
    Messages
    1,324
    Reaction score
    577
    • Schine
    • Top Forum Contributor
    • Thinking Positive
    I've been tinkering with an npc you could chat with for lore info, but he doesn't do much else right now.
    That's do able right now. I think you can get a uid or name for the npc and a uid for the player. Then you could probably key off of where the conversation was in the backend. Most of the complexity would be in your backend which you control. Which is actually pretty awesome.
     

    Benevolent27

    Join the Dark Side
    Joined
    Aug 21, 2015
    Messages
    585
    Reaction score
    327
    • Purchased!
    The only useful thing I've managed to do was to make HTTP calls to external sites and show its text in the dialog box. You could probably use it to do quests but the only way they interact is if talk to an NPC.
    May I ask how you did this? I'm going to give custom NPC's a go for the Light vs Dark server and this this would actually be quite useful. I've never dabbled with Lua scripting before, but I'd like see what is possible here. For quests, if I could make http calls out, then I could replace the HTTP file with different quests and such, and perhaps even use http calls to manage the quests. (like when someone completes a quest, it performs a request to the server which triggers a script that completes the quest and loads up a different one for viewing)

    Is it something like this?

    local http = require("socket.http")
    local resp = {}
    local r, c, h, s = http.request{
    url = "http://my-server/blah.html",
    sink = ltn12.sink.table(resp),
    protocol = "tlsv1"
    }
     
    Last edited:
    Joined
    Jul 20, 2013
    Messages
    128
    Reaction score
    8
    • Legacy Citizen 4
    • Purchased!
    That's do able right now. I think you can get a uid or name for the npc and a uid for the player. Then you could probably key off of where the conversation was in the backend. Most of the complexity would be in your backend which you control. Which is actually pretty awesome.
    That would be something that could add a'lot to the game, a simple quest line.
    I had not even though that was possible with the place holder NPC, go on see if you can beat the Dev's to getting it working ! lol
     

    nightrune

    Wizard/Developer/Project Manager
    Joined
    May 11, 2015
    Messages
    1,324
    Reaction score
    577
    • Schine
    • Top Forum Contributor
    • Thinking Positive
    May I ask how you did this? I'm going to give custom NPC's a go for the Light vs Dark server and this this would actually be quite useful. I've never dabbled with Lua scripting before, but I'd like see what is possible here. For quests, if I could make http calls out, then I could replace the HTTP file with different quests and such, and perhaps even use http calls to manage the quests. (like when someone completes a quest, it performs a request to the server which triggers a script that completes the quest and loads up a different one for viewing)

    Is it something like this?

    local http = require("socket.http")
    local resp = {}
    local r, c, h, s = http.request{
    url = "http://my-server/blah.html",
    sink = ltn12.sink.table(resp),
    protocol = "tlsv1"
    }

    I'll have to find the script and attach it.
     

    nightrune

    Wizard/Developer/Project Manager
    Joined
    May 11, 2015
    Messages
    1,324
    Reaction score
    577
    • Schine
    • Top Forum Contributor
    • Thinking Positive
    I would definitely appreciate it. :) Thanks for the quick response!
    Its not really the prettiest thing. I just hacked it together in a night to figure out if it was possible. I started with the advanced trader script and went from there. Its got examples of how to build GUI screens and add buttons. I've not found a good way to get any persistent state that seems to happen in the java layer in the game.

    A good recommendation during your development process that started to save me time was to wrap most of your code in one pcall, it adds overhead but its the only way to capture an error and not have to restart a server to get it to quit as well as an actual stack trace.

    Code:
    function unhireHookFunc(dialogObject)
      return dialogObject:unhireConverationPartner();
    end
    
    function hireHookFunc(dialogObject)
      return dialogObject:hireConverationPartner();
    end
    
    function create(dialogObject, bindings)
     
      dSysClass = luajava.bindClass( "org.schema.game.common.data.player.dialog.DialogSystem" );
      dSysFactoryClass = luajava.bindClass( "org.schema.game.common.data.player.dialog.DialogStateMachineFactory" );
      dSysEntryClass = luajava.bindClass( "org.schema.game.common.data.player.dialog.DialogStateMachineFactoryEntry" );
      hookClass = luajava.bindClass( "org.schema.game.common.data.player.dialog.DialogTextEntryHookLua" );
     
      dSys = luajava.newInstance( "org.schema.game.common.data.player.dialog.DialogSystem", dialogObject );
     
      hireHook = luajava.newInstance( "org.schema.game.common.data.player.dialog.DialogTextEntryHookLua", "hireHookFunc", {} );
      unhireHook = luajava.newInstance( "org.schema.game.common.data.player.dialog.DialogTextEntryHookLua", "unhireHookFunc", {} );
     
      factory = dSys:getFactory(bindings);
     
      print("Test1");
      http_clients = luajava.bindClass("org.apache.http.impl.client.HttpClients");
      http_req = luajava.newInstance("org.apache.http.client.methods.HttpGet", "http://www.google.com");
      http_client = http_clients:createDefault()
      print(http_client.execute)
      print(http_req)
      if not http_client then
        resp = "No client"
      elseif not http_req then
        resp = "No req"
      else
        local status, ans = pcall(function()  return http_client:execute(http_req) end );
        print("Error: ", status)
        print(ans)
        print("Answer");
        resp = ans:getStatusLine()
        ans:close()
        --resp = "Tried to call it!"
      end
    
      entry = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry",
      dialogObject:format("Greetings space traveller!\n\n" ..
      "My name is %s, I'm currently part of %s,\n"..
      "and under the command of %s in the faction: %s.\n",
      resp, dialogObject:getConverationPartnerAffinity(), dialogObject:getConverationPartnerOwnerName(), dialogObject:getConverationPartnerFactionName()), 2000 );
      factory:setRootEntry(entry);
      if dialogObject:isConverationPartnerInTeam() then
     
         entryUnCrewSuccess = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("Yes, commander!"), 2000 );
         entryUnCrewFailed = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("No, commander!"), 2000 );
     
         entryCrew = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("Please wait! I'm currently calculating."), 2000 );
         entryCrew:setHook(unhireHook);
         entryCrew:addReaction(unhireHook, 0, entryUnCrewSuccess);
         entryCrew:addReaction(unhireHook, -1, entryUnCrewFailed);
       
         entry:add(entryCrew, dialogObject:format("I want you off my team. Stay where you are!"));
      else
        entryCrewFailed = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("You don't have enough money!"), 2000 );
        entryCrewFailed2 = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("You can't have more crew!"), 2000 );
        entryCrewFailed3 = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("I won't follow you."), 2000 );
        entryCrewSuccess = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("I'm honoured to work with you, commander!"), 2000 );
     
     
        entryCrew = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("Please wait! I'm currently calculating."), 2000 );
        entryCrew:setHook(hireHook);
       
        entryCrew:addReaction(hireHook, 0, entryCrewSuccess);
        entryCrew:addReaction(hireHook, -1, entryCrewFailed);
        entryCrew:addReaction(hireHook, -2, entryCrewFailed2);
        entryCrew:addReaction(hireHook, -3, entryCrewFailed3);
     
        entry:add(entryCrew, dialogObject:format("Hey Baby, wanna destroy all humans?"));
      end
     
      dSys:add(factory)
    
      return dSys
    
    --frame = luajava.newInstance( "org.schema.game.common.data.player.dialog.DialogSystem", "Texts" );
    --frame:test()
    end
     
    • Like
    Reactions: HerrColonel

    Benevolent27

    Join the Dark Side
    Joined
    Aug 21, 2015
    Messages
    585
    Reaction score
    327
    • Purchased!
    Its not really the prettiest thing. I just hacked it together in a night to figure out if it was possible. I started with the advanced trader script and went from there. Its got examples of how to build GUI screens and add buttons. I've not found a good way to get any persistent state that seems to happen in the java layer in the game.

    A good recommendation during your development process that started to save me time was to wrap most of your code in one pcall, it adds overhead but its the only way to capture an error and not have to restart a server to get it to quit as well as an actual stack trace.

    Code:
    function unhireHookFunc(dialogObject)
      return dialogObject:unhireConverationPartner();
    end
    
    function hireHookFunc(dialogObject)
      return dialogObject:hireConverationPartner();
    end
    
    function create(dialogObject, bindings)
     
      dSysClass = luajava.bindClass( "org.schema.game.common.data.player.dialog.DialogSystem" );
      dSysFactoryClass = luajava.bindClass( "org.schema.game.common.data.player.dialog.DialogStateMachineFactory" );
      dSysEntryClass = luajava.bindClass( "org.schema.game.common.data.player.dialog.DialogStateMachineFactoryEntry" );
      hookClass = luajava.bindClass( "org.schema.game.common.data.player.dialog.DialogTextEntryHookLua" );
     
      dSys = luajava.newInstance( "org.schema.game.common.data.player.dialog.DialogSystem", dialogObject );
     
      hireHook = luajava.newInstance( "org.schema.game.common.data.player.dialog.DialogTextEntryHookLua", "hireHookFunc", {} );
      unhireHook = luajava.newInstance( "org.schema.game.common.data.player.dialog.DialogTextEntryHookLua", "unhireHookFunc", {} );
     
      factory = dSys:getFactory(bindings);
     
      print("Test1");
      http_clients = luajava.bindClass("org.apache.http.impl.client.HttpClients");
      http_req = luajava.newInstance("org.apache.http.client.methods.HttpGet", "http://www.google.com");
      http_client = http_clients:createDefault()
      print(http_client.execute)
      print(http_req)
      if not http_client then
        resp = "No client"
      elseif not http_req then
        resp = "No req"
      else
        local status, ans = pcall(function()  return http_client:execute(http_req) end );
        print("Error: ", status)
        print(ans)
        print("Answer");
        resp = ans:getStatusLine()
        ans:close()
        --resp = "Tried to call it!"
      end
    
      entry = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry",
      dialogObject:format("Greetings space traveller!\n\n" ..
      "My name is %s, I'm currently part of %s,\n"..
      "and under the command of %s in the faction: %s.\n",
      resp, dialogObject:getConverationPartnerAffinity(), dialogObject:getConverationPartnerOwnerName(), dialogObject:getConverationPartnerFactionName()), 2000 );
      factory:setRootEntry(entry);
      if dialogObject:isConverationPartnerInTeam() then
     
         entryUnCrewSuccess = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("Yes, commander!"), 2000 );
         entryUnCrewFailed = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("No, commander!"), 2000 );
     
         entryCrew = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("Please wait! I'm currently calculating."), 2000 );
         entryCrew:setHook(unhireHook);
         entryCrew:addReaction(unhireHook, 0, entryUnCrewSuccess);
         entryCrew:addReaction(unhireHook, -1, entryUnCrewFailed);
      
         entry:add(entryCrew, dialogObject:format("I want you off my team. Stay where you are!"));
      else
        entryCrewFailed = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("You don't have enough money!"), 2000 );
        entryCrewFailed2 = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("You can't have more crew!"), 2000 );
        entryCrewFailed3 = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("I won't follow you."), 2000 );
        entryCrewSuccess = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("I'm honoured to work with you, commander!"), 2000 );
     
     
        entryCrew = luajava.newInstance( "org.schema.game.common.data.player.dialog.TextEntry", dialogObject:format("Please wait! I'm currently calculating."), 2000 );
        entryCrew:setHook(hireHook);
      
        entryCrew:addReaction(hireHook, 0, entryCrewSuccess);
        entryCrew:addReaction(hireHook, -1, entryCrewFailed);
        entryCrew:addReaction(hireHook, -2, entryCrewFailed2);
        entryCrew:addReaction(hireHook, -3, entryCrewFailed3);
     
        entry:add(entryCrew, dialogObject:format("Hey Baby, wanna destroy all humans?"));
      end
     
      dSys:add(factory)
    
      return dSys
    
    --frame = luajava.newInstance( "org.schema.game.common.data.player.dialog.DialogSystem", "Texts" );
    --frame:test()
    end
    Oh my goodness, I got so busy with everything, focusing on other scripting for my wrapper. I really understand lua at all, it makes absolutely no sense to me, but I was wondering if it were possible to simply display the output text of a webserver page, and then have the buttons request different pages? I could essentially have these buttons act as webhooks. When a player types "!quest start whatever," it then loads a sector export with a unique NPC in it with it's own webhooks, then when that specific NPC calls out to the server, it could pair it to the player running that quest. If other players also want to run the same quest, it would use different sector exports with different NPC's to pair them. But my lack of knowledge in LUA is making this rather difficult.
     

    Lone_Puppy

    Me, myself and I.
    Joined
    Mar 12, 2015
    Messages
    1,274
    Reaction score
    529
    • Purchased!
    • Community Content - Bronze 2
    • Legacy Citizen 8
    How do you spawn an NPC with your custom lua script?