WSE - Lua edition [Beta], a new way of scripting

Users who are viewing this thread

Q1:
Code:
("wse_console_command_received", [ #this is a script that WSE adds
  (store_script_param, ":command_type", 1),

  (str_equals, s0, "@reloadMain"),
  (lua_push_str, "@main.lua"),
  (lua_call, "@dofile", 1), #one param, the string we pushed
  (set_trigger_result, 1),
]),
Note that this does not reset the entire lua state. It just runs main.lua again, but it's fine in most situations.

Q2: As the luaGuide says, main.lua will get executed at startup, nothing else. There you can set triggers and so on. It will also try to load all the constants and opcodes from msfiles/ so that you can use them directly.

Q3: Yes it's normal, you can put
Code:
[lua]
disable_game_const_warnings = 1
in wse_settings.ini to get rid of it. It just means that wse doesn't fully understand some line - I haven't implemented full parsing  :grin:

For calling lua scripts with an integer, the simplest way off the top of my head would be like so:
Code:
funcTable = {
  function(...) ... end, --remember this is [1] in lua
  function(...) ... end,
  ...
}

function call_index(index, ...)
  funcTable[index](...)
end
And just call call_index with an integer. But there are certainly prettier ways to do what you want.

Hope this helps, don't be shy to ask more questions :grin:
 
Hey, very helpful indeed :grin:! Thanks so much.

Yeah I've thought of the table solution, as you say it's not very clean and the issue is the fact I'd preferably need to call a 'class' that has a list of functions, not a single function (Example: begin/update/end), and the problem is that each "state" are instances and share the same functions name, so the machine can call whatever state needs to be begun/updated/ended.

The only way I found to do this so far is to call "dofile" (on for example let's say idle.lua or goto.lua) whenever a State is updated, since it looks like lua has no problem having duplicated functions, but it seems it prefers functions depending on whatever last file was last loaded. I dropped it because it doesn't sound performance efficient at all (or am I wrong?).

(edit: the solution using a table would be similar to the one I used in the module system, give every 'state' one single function with an unique name (state_idle, state_goto), and pass the "mode" as a parameter (begin/update/end) along with the "object" to run it on (an Agent for example) but it forces performing checks to differenciate the mode, and for some reason i'm obsessed with doing it super clean lol)

I've been looking around looking for a proper OOP-style solution to this in LUA, most solutions are very confusing to me for now (probably due to the syntax that i'm new to). In C# for example, it's very straight-forward. I typed an example below.

Code:
public class Game
{
	// Some singleton pattern here before anything, lazy to type it.

	public List<Player> playerList = new List<Player>();

	// Suppose it is run at game Start....
	public void OnGameStart()
	{
		Player bob = new Player("Bob");
		// Create a new player on start.
		playerList.Add(bob);

		// Execute a the idle state.
		bob.ExecuteState(new Idle());
	}

	//Let's suppose it runs on every frame.
	public void GameUpdate()
	{
		foreach (Player player in playerList)
			player.curState.Update(player);
	}
}

public class Player
{
	public string name;
	public State curState;

	public void ExecuteState(State state)
	{	
		curState.Exit(this);
		curState = state;
		curState.Begin(this);
	}

	public Player(string nName)
	{
		name = nName;
	}
}

// The base class, it's a proxy for any state.
public abstract class State
{
	public abstract void Begin(Player p);

	public abstract void Update(Player p);

	public abstract void Exit(Player p);
}

// The children classes, preferably stored in different files.
// The parent class (State) forces implementation of each previously abstract-defined methods, very fool proof.
public class Idle : State
{
	public override void Begin(Player p)
	{
		Console.WriteLine(p.name + " is idle");
	}

	public override void Update(Player p)
	{
		//Update some stuff.	
	}

	public override void Exit(Player p)
	{
		//Reset whatever variables on exit.
	}
}
 
Calling dofile will just execute the file and overwrite all functions in the global table (_G) with the functions from it. It's a bit like having
Code:
   --b.lua
a = 3

  --main.lua
a = 5
dofile(b.lua)
->a=3

I'll give you some quick code to get you started. It's been a while so please excuse any mistakes. Also its probably not exactly what you need but I want to show the important concepts.
If you haven't learned how tables and metatables work, I recommend you do some reading. It's really crucial to do abstractions in lua. There are no things like classes, its all up to the user to implement himself with these two.
Code:
-------BasicState.lua--------
BasicState = {
  new = function()
    local obj = {} -- you can also init some stuff in here if you dont want them in BasicState itself
    setmetatable(obj, BasicState)
    return obj
  end,

  begin = function()
    error("Did not overwrite default begin()")
    --or maybe some default code?
  end,
}

----------IdleState.lua-----------
IdleState = {
  new = function()
    local obj = State.new()
    setmetatable(obj, IdleState)
    return obj
  end,

  begin = function()
....
}
setmetatable(IdleState, BasicState) --so the table returned by idlestate.new has metatable IdleState, which has metatable BasicState. This is the lua way to do inheritance

----------main.lua------------
require("BasicState")
require("IdleState")

globalStates = {
  idle = IdleState.new(),
  ...
}
selectedState = nil

function setState(state)
  selectedState = globalStates[state]
end

function exec(funcName, ...)
  if selectedState then --not nil
    selectedState[funcName](...)
  end
end

----or----

function exec(stateName, funcName, ...)
  if globalStates[stateName] and globalStates[stateName][funcName] then
    globalStates[stateName][funcName](...)
  end
end
 
Back
Top Bottom