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

Users who are viewing this thread

Ye that makes sense.
The previously defined lists like lhs_operations were defined as frozenset
Code:
...
lhs_operations = frozenset([
...,
...,
...,
])
...
so the regex had no match because of frozenset()

Thanks for the help so far and again, you've done great work there. Really looking forward now to build it properly and then start with the scripting.
 
Right so I finally got everything to work and now I wanted to try out the example that is included in the luaGuide.
This is the error:
f8f0caeb03a13442bb2ac02b07736bcc.png

illegal left value for the store_trigger_param function. Seems strange. So it is most certain something with store_trigger_param since it returns 1, at least that's my first guess. Also as addition it displays this "At Mission Template [ 0 ] mst_conquest Trigger [50] Conditions."

The code of the main.lua
Code:
myLog = io.open("custom_log.txt", "a")
myLog:write("Server started at " .. os.date("%Y.%m.%d, %X") .. "\n")
myLog:flush()

function getTriggerParam(index)
  return game.store_trigger_param(0, index)
end

function playerJoinedCallback()
  local playerNo = getTriggerParam(1)

  game.str_store_player_username(0, playerNo)
  game.str_store_player_ip(1, playerNo)

  print(game.sreg[0] .. " joined with IP " .. game.sreg[1] ..
    " at " .. os.date("%Y.%m.%d, %X") .. "\n")
  
  return false
end

game.addTrigger("mst_conquest",game.const.ti_server_player_joined,0,0,playerJoinedCallback);
I got following files in the msfiles folder:
header_common
header_items
header_operations
header_scene_props
header_triggers
module_scripts

Am I missing something?
 
AgentSmith said:
You still might have issues with your operations header. Is "store_trigger_param" correctly flagged as lhs_operations?
Ye the operations header seems fine. As a last resort I've now dumped all header_* and module_* files into my msfiles folder, which resolved the issue.
So some of these files apparently have something in them necessary for store_trigger_param to work.
 
And there I am again. Sorry for the spam, but your project here really caugth my full interest.

Is there any possibility to actually handle ingame chat or server console input via lua? Some sort of trigger that is fired upon these events which can be added within your lua scripts? Or is it only possible via the module_scripts.py?

Greetings and thanks for your support so far.
 
Bridge_Troll said:
AgentSmith said:
You still might have issues with your operations header. Is "store_trigger_param" correctly flagged as lhs_operations?
Ye the operations header seems fine. As a last resort I've now dumped all header_* and module_* files into my msfiles folder, which resolved the issue.
So some of these files apparently have something in them necessary for store_trigger_param to work.
Nah the only relevant file is the operations header, something was wrong there.
And don't worry, I'm always glad if someone makes use of the work I put into this.
About the trigger, what you can do is look up "Module operation hooking" in the manual. Basically you hook the "call_script" operation and check for example if it's the "wse_multiplayer_message_received" script (game.getScriptNo(script_name), 1st param in your callback is the script no).
 
AgentSmith said:
Nah the only relevant file is the operations header, something was wrong there.
Ye I explored there a bit more. Since python 2.7 is corrupted on my pc I used the newest python 3. So converted all the python files, did some minor changes. Something changed after the convertion which made the operation header work again, it didn't beforehand. Not sure what changed, there is not much that would make sense if we talk about convertion from py 2 to 3. But ye, it does work now

AgentSmith said:
About the trigger, what you can do is look up "Module operation hooking" in the manual. Basically you hook the "call_script" operation and check for example if it's the "wse_multiplayer_message_received" script (game.getScriptNo(script_name), 1st param in your callback is the script no).
Ah yes of course. Seems as if this download here includes an old luaGuide file as Module operation hooking is not present in it. I downloaded the WSE package from here https://forums.taleworlds.com/index.php?topic=324890.0 and this included a newer Guide, including the module operation hooking.
Thanks for the heads up, I'll have a look at it.
 
Bridge_Troll said:
Seems as if this download here includes an old luaGuide file as Module operation hooking is not present in it. I downloaded the WSE package from here https://forums.taleworlds.com/index.php?topic=324890.0 and this included a newer Guide, including the module operation hooking.
Thanks for the heads up, I'll have a look at it.
Yep sorry, forgot to link to the latest WSE. Old link was quite outdated :wink:
 
Thanks for the help so far again, your suggestions works like a charm.
Code:
function getScriptOnRuntime(...)
	local args = {...}
	if ( args[0] == game.getScriptNo("script_wse_chat_message_received")) then

		print("Message by PlayerNo"..args[1]..": ".. game.sreg[0]);

	end
	return true;
end

game.hookOperation("call_script", getScriptOnRuntime);
I have 2 more questions if you allow:
What would be the best way to check whether the chat was used by a player and not by the server, right if the server set's up, the hook is used as well. Would be to check player_get_unique_id and see if it is anything other than 0 to determine it's not the server?

And also it seems as if script_wse_chat_message_received can only receive faction or global chat. Anyway to distinguish local or shout as well?

Greetings,
Bridge_Troll
 
I allow, as I said I'm glad to help :wink:
Bridge_Troll said:
Thanks for the help so far again, your suggestions works like a charm.
Code:
function getScriptOnRuntime(...)
	local args = {...}
	if ( args[0] == game.getScriptNo("script_wse_chat_message_received")) then

		print("Message by PlayerNo"..args[1]..": ".. game.sreg[0]);

	end
	return true;
end

game.hookOperation("call_script", getScriptOnRuntime);
I have 2 more questions if you allow:
What would be the best way to check whether the chat was used by a player and not by the server, right if the server set's up, the hook is used as well. Would be to check player_get_unique_id and see if it is anything other than 0 to determine it's not the server?
You got a bug there - lua tables start at 1, so args[0] == nil. game.getScriptNo("script_wse_chat_message_received") is also nil because you must omit the "script_" part (probably should have mentioned that in the manual). Both are nil and so the check never fails  :grin:
Bridge_Troll said:
And also it seems as if script_wse_chat_message_received can only receive faction or global chat. Anyway to distinguish local or shout as well?
I don't think that exists in native. You're using PW, right? Must be done in their module.
 
AgentSmith said:
You got a bug there - lua tables start at 1, so args[0] == nil. game.getScriptNo("script_wse_chat_message_received") is also nil because you must omit the "script_" part (probably should have mentioned that in the manual). Both are nil and so the check never fails  :grin:
hahaha, damn that's a bad one. Thanks for pointing that out, didn't know about it and wouldn't have thought about it.

AgentSmith said:
I don't think that exists in native. You're using PW, right? Must be done in their module.
Ah damn, ye it's PW only, I forgot that. Well, faction and global chat has to be enough for now.
Seems the chat type is only received within game_receive_network_message which is a pretty big control statement which checks for the chat_event_type and a lot of other stuff. chat_event_type_local_shout seems to do the trick.
I don't really dare to touch it yet, rather getting used to how client and server communicate for now.

Thanks again.
 
How am I actually able to execute something only on one certain client?
For example, trigger for joining by a player get's fired. I now have that players ID. How can I execute for example the display_message operation only on that client?

Would I just do something like  if game.get_player_agent_no == PlayerID then display_message("Welcome "..PayerID)
Or would I need to hook into some script like game_receive_network_message, check if it is the server, use multiplayer_send_message_to_player(...,...) and then use that with for example server_event_local_chat,"Welcome" ?

Also, which hexadecimal colors are actually allowed/are able to be displayed when using display_message? Or do I have the full 0xRRGGBBAA range available?
 
Alright, seems as if I found a workaround(gameRef is the game table via dependency injection for a lua pseudo class)
Code:
  for curPlayer in self.gameRef.playersI(0) do
    if ( curPlayer == 0 and self.gameRef.multiplayer_is_server()) then
      self.gameRef.multiplayer_send_string_to_player(PlayerID,self.gameRef.const.server_event_local_chat_shout,"test message with string")
    end
  end
this does seem to display a chat message for that player. But is there for example a possibility to execute display_message on only one particular client machine?
 
It depends on your setup. I personally don't have much experience besides server-side modding in native.
If your code is running on both sides, you can use "multiplayer_is_server" and "multiplayer_is_dedicated_server" to control what to run. For example, hotkey triggers would have a no-server condition. Server announcements get a server-only condition.
Not sure right now but I think most events trigger on client as well.

If you're on the server only, what you do is send events to the clients you want. They receive it in "game_receive_network_message" and do their thing.
One event that exists in native by default is "multiplayer_event_show_server_message". So you could send a message to a client like "(multiplayer_send_string_to_player, ":player_no", multiplayer_event_show_server_message, "@text")". But you have no control over the color because that's client side. You have full rbg in display_message but no alpha I think, maybe you wanna test that.
So if you want to execute code on a client and it's triggered by the server, it must exist in the installed client module and be triggered by a server event via the network script.
 
Right, seems as if I am kinda limited on that side.

Another question about general scripting with warband, how can you add/remove items to a player. I have only found player_add_spawn_item.
How can you remove an item from a player? Or is player_set_slot used for that?
I was unable to find any sort of documentation on a lot of the operations in the module system.


Trying to remove the spawn cloths after respawning.

Ok I got this so far:
Code:
[...]
function PlayerController:spawn(AgentID)

local PlayerID = self.gameRef.agent_get_player_id(0,AgentID);
self.gameRef.multiplayer_send_string_to_player(PlayerID,self.gameRef.const.server_event_admin_chat,"Tried spawning without anything");

local scriptChangeArmor = self.gameRef.getScriptNo("change_armor");
self.gameRef.call_script(scriptChangeArmor, AgentID, "no_head");
self.gameRef.call_script(scriptChangeArmor, AgentID, "no_body");
self.gameRef.call_script(scriptChangeArmor, AgentID, "no_foot");
self.gameRef.call_script(scriptChangeArmor, AgentID, "no_hand");

[...]

Still doesn't seem to work. I assume the parameters don't get trasmitted. Any ideas?
 
Bridge_Troll said:
Trying to remove the spawn cloths after respawning.

You can't. Either set their clothing before spawn or respawn them (and if you respawn, you have to use a timer. Can't happen on the same tick for some reason).
Setting other items is no problem tho, there are operations for that.
And yeah ms documentation is really an issue... You have to read a lot of code yourself, look at other mods... or ask on the forum  :grin:
 
Damn.
There should be an extra function to change armor in PW. If you buy new armor or cloths, your players does not get respawned but changes cloth directly on the sport:
Code:
 ("change_armor", # server: equip an armor item on an agent, sending messages to all clients to update the mesh
   [(store_script_param, ":agent_id", 1),
    (store_script_param, ":item_id", 2),

    (call_script, "script_agent_equip_armor", ":agent_id", ":item_id"),
    (get_max_players, ":num_players"),
    (try_for_range, ":player_id", 1, ":num_players"),
      (player_is_active, ":player_id"),
      (multiplayer_send_2_int_to_player, ":player_id", server_event_agent_equip_armor, ":agent_id", ":item_id"),
    (try_end),
    ]),

and

(else_try), # equip the visual armor mesh on an agent
        (eq, ":event_type", server_event_agent_equip_armor),
        (store_script_param, ":agent_id", 3),
        (store_script_param, ":item_id", 4),
        (try_begin),
          (agent_is_active, ":agent_id"),
          (agent_is_alive, ":agent_id"),
          (try_begin),
            (gt, ":item_id", -1),
            (call_script, "script_agent_equip_armor", ":agent_id", ":item_id"),
          (else_try),
            (call_script, "script_agent_clean_blood", ":agent_id"),
          (try_end),
        (try_end),
Pretty sure this looks like as if every player get's updated with the new cloth this player wears.

Is that the correct way to use the call_script function with parameters?
 
Oh pretty nice, I wish we had this in vanilla...
I guess the problem then is that you pass strings to that script as the 2nd param.
Code:
self.gameRef.call_script(scriptChangeArmor, AgentID, "no_head");

should be

self.gameRef.call_script(scriptChangeArmor, AgentID, 12345);
 
AgentSmith said:
Oh pretty nice, I wish we had this in vanilla...
I guess the problem then is that you pass strings to that script as the 2nd param.
Code:
self.gameRef.call_script(scriptChangeArmor, AgentID, "no_head");

should be

self.gameRef.call_script(scriptChangeArmor, AgentID, 12345);
Already thought that. Problem is that these no_<item> have all the same ids
Code:
["no_item", "INVALID ITEM", [("invalid_item", 0)], itp_type_one_handed_wpn|itp_primary|itp_secondary|itp_no_parry, itc_dagger,
 0, weight(1)|spd_rtng(1)|weapon_length(1)|swing_damage(1, blunt)|thrust_damage(1, blunt), imodbits_none],
["no_head", "INVALID HEAD", [("invalid_item", 0)], itp_type_head_armor, 0,
 0, weight(1)|head_armor(1)|difficulty(0), imodbits_none],
["no_body", "INVALID BODY", [("invalid_item", 0)], itp_type_body_armor, 0,
 0, weight(1)|body_armor(1)|difficulty(0), imodbits_none],
["no_foot", "INVALID FOOT", [("invalid_item", 0)], itp_type_foot_armor, 0,
 0, weight(1)|leg_armor(1)|difficulty(0), imodbits_none],
["no_hand", "INVALID HAND", [("invalid_item", 0)], itp_type_hand_armor, 0,
 0, weight(1)|body_armor(1)|difficulty(0), imodbits_none],
["no_horse", "INVALID HORSE", [("invalid_item", 0)], itp_type_horse, 0,
 0, hit_points(1)|body_armor(1)|difficulty(0)|horse_speed(10)|horse_maneuver(40)|horse_charge(1)|horse_scale(1), imodbits_none],
How should it know which armor slot to use. Kinda seems a bit random to me.
 
Back
Top Bottom