OSP Code Combat Multiplayer Sprinting and Walking

Users who are viewing this thread

_Sebastian_

Punkbuster 2.0
Baron
Edit
the latest working code;
http://forums.taleworlds.com/index.php/topic,228997.msg5515692.html#msg5515692



Hi guys.
I wrote this sprinting code for warband.
It works in singleplayer only and now I want to set it up for multiplayer.

I know that I need a server- and/or client event for this, but I dont know how to write it for this code.
module_constants
Code:
slot_agent_sprint_time            = 27
slot_agent_sprint_mode            = 28
module_mission_templates
Code:
#sprinting
sprint_limiter = (
  0, 0, 1,
  [
    (this_or_next|multiplayer_is_server),
    (neg|game_in_multiplayer_mode),
    
    (game_key_is_down, gk_move_forward),
    (game_key_clicked, gk_crouch),
 
    (get_player_agent_no, ":player_agent"),
    (agent_is_alive,":player_agent"),
    (agent_is_human, ":player_agent"),
    (agent_get_horse, ":horse", ":player_agent"),
    (try_begin),
      (le, ":horse", 0),
      (agent_get_wielded_item, ":weapon_r", ":player_agent", 0),#right hand
      (le, ":weapon_r", 0),
      (agent_get_wielded_item, ":weapon_l", ":player_agent", 1),#left hand
      (le, ":weapon_l", 0),
      (agent_slot_eq, ":player_agent", slot_agent_sprint_time, 0),
      (agent_set_slot, ":player_agent", slot_agent_sprint_time, 1),
      (agent_set_slot, ":player_agent", slot_agent_sprint_mode, 1),
    
      (agent_get_troop_id, ":sprint_troop", ":player_agent"),
      (gt,":sprint_troop",-1),
      (store_skill_level, ":athletics", "skl_athletics", ":sprint_troop"),
      (val_mul, ":athletics", 2),
      (store_sub, ":speed", 200, ":athletics"),
      (agent_set_speed_modifier, ":player_agent", ":speed"),
    (try_end),
  ], [])

sprint_time = (
  1, 0, 0,
  [
    (this_or_next|multiplayer_is_server),
    (neg|game_in_multiplayer_mode),

    (try_for_agents,":agent"),
      (neg|agent_is_non_player, ":agent"),
      (agent_is_alive,":agent"),
      (agent_get_horse, ":horse", ":agent"),
      (try_begin),
        (le, ":horse", 0),
        (agent_get_slot, ":time", ":agent", slot_agent_sprint_time),
        (ge, ":time", 1),
        (agent_get_wielded_item, ":weapon_r", ":agent", 0),#right hand
        (agent_get_wielded_item, ":weapon_l", ":agent", 1),#left hand
        (assign, ":lower_time", 0),
        (try_begin),
          (agent_slot_eq, ":agent", slot_agent_sprint_mode, 1),
          (le, ":weapon_r", 0),
          (le, ":weapon_l", 0),
          (game_key_is_down, gk_move_forward),
          (game_key_is_down, gk_crouch),
          (val_add, ":time", 2),#1/2 sec
        (else_try),
          (assign, ":lower_time", 1),
        (try_end),
        (val_min, ":time", 31),
        (agent_set_slot, ":agent", slot_agent_sprint_time, ":time"),
        (try_begin),
          (gt, ":time", 30),#sprint time = 1/2
          (assign, ":lower_time", 1),
        (try_end),
        (try_begin),
          (eq, ":lower_time", 1),
          (agent_set_speed_modifier, ":agent", 100),
          (agent_get_slot, ":time", ":agent", slot_agent_sprint_time),
          (val_sub, ":time", 1),
          (val_max, ":time", 0),
          (agent_set_slot, ":agent", slot_agent_sprint_time, ":time"),
          (agent_set_slot, ":agent", slot_agent_sprint_mode, 0),
        (try_end),
      (try_end),
    (try_end),
  ], [])
The sprinting should work for singleplayer and multiplayer.
Does anyone know how to write the server-/client-event for this :?:
 
I just tried putting the code in my Warband for SP to see if it works, and at first i got syntax errors, but because i put it in the wrong spot, now i getting alot of name errors specifically related to "agent_set_speed_modifier", and I had to alter the "gk_crouch" to a different key command, i chose "gk_action" and that error went away, though the agent_set_speed_modifier is still not working. I'm by no means a expert, still trying to figure all of this stuff out. But you said you got it to work for SP? how?
 
Refer for details in: http://forums.taleworlds.com/index.php/topic,94854.0.html

It would be something like this:

In module_mission_templates, make a tuple:

Code:
If gk_sprint_key is clicked:
multiplayer_send_message_to_server, your_message_defined_in_module_headers

Then, "Open up module_scripts and search for this script "game_receive_network_message".",

add all your remaining "sprint_limiter" scripts there inside an "try_else" block with your network_message.

The "sprint_time" script does not need to be in "game_receive_network_message" and it is fine as now.

I know I didn't go into too much detail, but seeing that you have written quite nice piece of script already I think that's enough to point you in the right direction; just ask if you need more help w/ this.

SirSlaughter357 said:
I just tried putting the code in my Warband for SP to see if it works, and at first i got syntax errors, but because i put it in the wrong spot, now i getting alot of name errors specifically related to "agent_set_speed_modifier", and I had to alter the "gk_crouch" to a different key command, i chose "gk_action" and that error went away, though the agent_set_speed_modifier is still not working. I'm by no means a expert, still trying to figure all of this stuff out. But you said you got it to work for SP? how?

Which MS version?
 
SirSlaughter357 said:
Warband v. 1.143

errm it's a diplo v1.143 however. so its not pure native.
You need 1.152 for this...
You also have to enable "can_crouch" in the module.ini to get the crouch key.

SonKidd said:
Then, "Open up module_scripts and search for this script "game_receive_network_message".",

add all your remaining "sprint_limiter" scripts there inside an "try_else" block with your network_message.

The "sprint_time" script does not need to be in "game_receive_network_message" and it is fine as now.

I know I didn't go into too much detail, but seeing that you have written quite nice piece of script already I think that's enough to point you in the right direction; just ask if you need more help w/ this.
Thank you.
I already wrote a couple of server-/client events, but I didnt knew if I would need two events(for sprint_limiter and sprint_time).
So thanks for your help.

SonKidd said:
I think the agent_set_speed_modifier is new for 1.152. (wait until 1.153 if you want to port).
I hope there will be just some new header files :wink:
 
Hmm the "sprint_limiter" works but not the "sprint_time".
Atfer one second the sprint mode ends, because "sprint_time" sets the timer to 0.
I guess I need a server event for "sprint_time" to check if "gk_move_forward" and "gk_crouch" is down (if these keys are not clicked then the timer will be 0).
I tested it on my own dedicated server.

So here is what I did.
Code:
sprint_limiter = (
  0, 0, 1,
  [   
    (game_key_is_down, gk_move_forward),
    (game_key_clicked, gk_crouch),

    (game_in_multiplayer_mode),
    (multiplayer_send_message_to_server, multiplayer_event_set_sprinting),
  ], [])

sprint_time = (
  1, 0, 0,
  [
    (this_or_next|multiplayer_is_server),
    (neg|game_in_multiplayer_mode),

    (try_for_agents,":agent"),
      (neg|agent_is_non_player, ":agent"),
      (agent_is_alive,":agent"),
      (agent_get_horse, ":horse", ":agent"),
      (try_begin),
        (le, ":horse", 0),
        (agent_get_slot, ":time", ":agent", slot_agent_sprint_time),
        (ge, ":time", 1),
        (agent_get_wielded_item, ":weapon_r", ":agent", 0),#right hand
        (agent_get_wielded_item, ":weapon_l", ":agent", 1),#left hand
        (assign, ":lower_time", 0),
        (try_begin),
          (agent_slot_eq, ":agent", slot_agent_sprint_mode, 1),
          (le, ":weapon_r", 0),
          (le, ":weapon_l", 0),
          (game_key_is_down, gk_move_forward),
          (game_key_is_down, gk_crouch),
          (val_add, ":time", 2),#1/2 sec
        (else_try),
          (assign, ":lower_time", 1),
        (try_end),
        (val_min, ":time", 31),
        (agent_set_slot, ":agent", slot_agent_sprint_time, ":time"),
        (try_begin),
          (gt, ":time", 30),#sprint time = 1/2
          (assign, ":lower_time", 1),
        (try_end),
        (try_begin),
          (eq, ":lower_time", 1),
          (agent_set_speed_modifier, ":agent", 100),
          (agent_get_slot, ":time", ":agent", slot_agent_sprint_time),
          (val_sub, ":time", 1),
          (val_max, ":time", 0),
          (agent_set_slot, ":agent", slot_agent_sprint_time, ":time"),
          (agent_set_slot, ":agent", slot_agent_sprint_mode, 0),
        (try_end),
      (try_end),
    (try_end),
  ], [])
header_common
Code:
multiplayer_event_set_sprinting                               = 48
Server Event
Code:
      # multiplayer_event_set_sprinting
      (else_try),
        (eq, ":event_type", multiplayer_event_set_sprinting),

        (get_max_players, ":num_players"),
        (try_for_range, ":cur_player", 1, ":num_players"),
          (player_is_active,":cur_player"),
          (player_get_agent_id, ":agent", ":cur_player"),
          (agent_is_alive,":agent"),
          (agent_is_human, ":agent"),
          (agent_get_horse, ":horse", ":agent"),
          (le, ":horse", 0),
          (agent_get_wielded_item, ":weapon_r", ":agent", 0),#right hand
          (le, ":weapon_r", 0),
          (agent_get_wielded_item, ":weapon_l", ":agent", 1),#left hand
          (le, ":weapon_l", 0),
          (agent_slot_eq, ":agent", slot_agent_sprint_time, 0),
          (agent_set_slot, ":agent", slot_agent_sprint_time, 1),
          (agent_set_slot, ":agent", slot_agent_sprint_mode, 1),
          (agent_set_speed_modifier, ":agent", 200),
        (try_end),

Does anyone know, how to get the "sprint_time" to work in multiplayer :?:
 
Ah sorry, I missed these two lines:
Code:
          (game_key_is_down, gk_move_forward),
          (game_key_is_down, gk_crouch),

I would suggest splitting up the "timer" and the "stop" part.

Make the timer a true timer only - one that limits the length of the sprinting (I'm guessing that occurs).

And make another event for stopping (detects client's not pressing key and sends message to change a slot that directly makes sprinting stops).
 
Well after some days of testing, I will show you guys what I did.
This code should be absolutly SP and MP friendly.
And it uses just one server event.(to set the players agent id)
I also added a walking mode like in NW.

header_common
Code:
multiplayer_event_set_agent_id                                = 48

module_constants
Code:
slot_agent_walk                   = 27
slot_agent_sprint_time            = 28
slot_agent_sprint_mode            = 29

module_mission_templates
Code:
#walking
walk_limiter = (
  0, 0, 0.5,
  [
    (key_clicked, key_left_shift),

    (try_begin),
      (game_in_multiplayer_mode),
      (neg|multiplayer_is_server),
      (multiplayer_send_int_to_server, multiplayer_event_set_agent_id, 1),
    (else_try),
      (get_player_agent_no, ":player_agent"),
      (gt, ":player_agent", -1),
      (agent_is_alive,":player_agent"),
      (call_script, "script_cf_agent_walk", ":player_agent"),
    (try_end),
  ], [])

#sprinting
sprint_limiter = (
  0, 0, 0.5,
  [
    (game_key_is_down, gk_move_forward),
    (game_key_clicked, gk_crouch),

    (try_begin),
      (game_in_multiplayer_mode),
      (neg|multiplayer_is_server),
      (multiplayer_send_int_to_server, multiplayer_event_set_agent_id, 2),
    (else_try),
      (get_player_agent_no, ":player_agent"),
      (gt, ":player_agent", -1),
      (agent_is_alive,":player_agent"),
      (call_script, "script_cf_agent_sprint_limiter", ":player_agent"),
    (try_end),
  ], [])

sprint_timer = (
  1, 0, 0,
  [
    (try_begin),#keys pressed
      (game_key_is_down, gk_move_forward),
      (game_key_is_down, gk_crouch),

      (try_begin),
        (game_in_multiplayer_mode),
        (neg|multiplayer_is_server),
        (multiplayer_send_int_to_server, multiplayer_event_set_agent_id, 3),
      (else_try),
        (get_player_agent_no, ":player_agent"),
        (gt, ":player_agent", -1),
        (agent_is_alive,":player_agent"),
        (call_script, "script_cf_agent_sprint_time", ":player_agent"),
      (try_end),
    (else_try),#keys losed
      (try_begin),
        (game_in_multiplayer_mode),
        (neg|multiplayer_is_server),
        (multiplayer_send_int_to_server, multiplayer_event_set_agent_id, 4),
      (else_try),
        (get_player_agent_no, ":player_agent"),
        (gt, ":player_agent", -1),
        (agent_is_alive,":player_agent"),
        (call_script, "script_cf_agent_sprint_stop", ":player_agent"),
      (try_end),
    (try_end),
  ], [])

module_scripts
server event
Code:
      # multiplayer_event_set_agent_id
      (else_try),
        (eq, ":event_type", multiplayer_event_set_agent_id),
        (store_script_param, ":script_id", 3),

        (player_get_agent_id, ":player_agent_no", ":player_no"),
        (try_begin),
          (gt, ":player_agent_no", -1),
          (agent_is_alive, ":player_agent_no"),
          (try_begin),
            (eq, ":script_id", 1),
            (call_script, "script_cf_agent_walk", ":player_agent_no"),
          (else_try),
            (eq, ":script_id", 2),
            (call_script, "script_cf_agent_sprint_limiter", ":player_agent_no"),
          (else_try),
            (eq, ":script_id", 3),
            (call_script, "script_cf_agent_sprint_time", ":player_agent_no"),
          (else_try),
            (eq, ":script_id", 4),
            (call_script, "script_cf_agent_sprint_stop", ":player_agent_no"),
          (try_end),
        (try_end),
scripts
Code:
  ("cf_agent_walk",
  [
    (store_script_param, ":agent_id", 1),
     
    (this_or_next|multiplayer_is_server),
    (neg|game_in_multiplayer_mode),

    (agent_slot_eq, ":agent_id", slot_agent_sprint_mode, 0),
    (agent_get_horse, ":horse", ":agent_id"),
    (try_begin),
      (le, ":horse", 0),
      (try_begin),
        (agent_slot_eq, ":agent_id", slot_agent_walk, 0),
        (agent_set_slot, ":agent_id", slot_agent_walk, 1),
        (agent_set_speed_modifier, ":agent_id", 50),
      (else_try),
        (agent_set_slot, ":agent_id", slot_agent_walk, 0),
        (agent_set_speed_modifier, ":agent_id", 100),
      (try_end),
    (try_end),
  ]),

  ("cf_agent_sprint_limiter",
  [
    (store_script_param, ":agent_id", 1),
     
    (this_or_next|multiplayer_is_server),
    (neg|game_in_multiplayer_mode),

    (agent_slot_eq, ":agent_id", slot_agent_walk, 0),
    (agent_get_horse, ":horse", ":agent_id"),
    (try_begin),
      (le, ":horse", 0),
      (agent_get_wielded_item, ":weapon_r", ":agent_id", 0),#right hand
      (le, ":weapon_r", 0),
      (agent_get_wielded_item, ":weapon_l", ":agent_id", 1),#left hand
      (le, ":weapon_l", 0),
      (agent_slot_eq, ":agent_id", slot_agent_sprint_time, 0),
      (agent_set_slot, ":agent_id", slot_agent_sprint_time, 1),
      (agent_set_slot, ":agent_id", slot_agent_sprint_mode, 1),
    
      (agent_get_troop_id, ":sprint_troop", ":agent_id"),
      (gt,":sprint_troop",-1),
      (store_skill_level, ":athletics", "skl_athletics", ":sprint_troop"),
      (val_mul, ":athletics", 2),
      (store_sub, ":speed", 200, ":athletics"),
      (agent_set_speed_modifier, ":agent_id", ":speed"),
    (try_end),
  ]),

  ("cf_agent_sprint_time",
  [
    (store_script_param, ":agent_id", 1),
     
    (this_or_next|multiplayer_is_server),
    (neg|game_in_multiplayer_mode),

    (agent_get_horse, ":horse", ":agent_id"),
    (try_begin),
      (le, ":horse", 0),
      (agent_get_slot, ":time", ":agent_id", slot_agent_sprint_time),
      (try_begin),
        (ge, ":time", 1),
        (agent_get_wielded_item, ":weapon_r", ":agent_id", 0),#right hand
        (agent_get_wielded_item, ":weapon_l", ":agent_id", 1),#left hand
        (assign, ":lower_time", 0),
        (try_begin),
          (agent_slot_eq, ":agent_id", slot_agent_sprint_mode, 1),
          (le, ":weapon_r", 0),
          (le, ":weapon_l", 0),
          (val_add, ":time", 2),#1/2 sec
        (else_try),
          (assign, ":lower_time", 1),
        (try_end),
        (val_min, ":time", 31),
        (agent_set_slot, ":agent_id", slot_agent_sprint_time, ":time"),
        (try_begin),
          (gt, ":time", 30),#sprint time = 1/2
          (assign, ":lower_time", 1),
        (try_end),
        (try_begin),
          (eq, ":lower_time", 1),
          (agent_get_slot, ":time", ":agent_id", slot_agent_sprint_time),
          (val_sub, ":time", 1),
          (val_max, ":time", 0),
          (agent_set_slot, ":agent_id", slot_agent_sprint_time, ":time"),
          (agent_set_slot, ":agent_id", slot_agent_sprint_mode, 0),
          (agent_slot_eq, ":agent_id", slot_agent_walk, 0),
          (agent_set_speed_modifier, ":agent_id", 100),
        (try_end),
      (try_end),
    (try_end),
  ]),
  
  ("cf_agent_sprint_stop",
  [
    (store_script_param, ":agent_id", 1),
     
    (this_or_next|multiplayer_is_server),
    (neg|game_in_multiplayer_mode),
    
    (agent_get_slot, ":time", ":agent_id", slot_agent_sprint_time),
    (try_begin),
      (gt, ":time", 0),
      (val_sub, ":time", 1),
      (agent_set_slot, ":agent_id", slot_agent_sprint_time, ":time"),
      (agent_set_slot, ":agent_id", slot_agent_sprint_mode, 0),
      (agent_slot_eq, ":agent_id", slot_agent_walk, 0),
      (agent_set_speed_modifier, ":agent_id", 100),
    (try_end),
  ]),
 
Isn't your server event dictating the walk/sprint state for all players depending on what 1 player does? You need to send a player/agent ID to the server so you only address the relevant player-agent, not all player-agents.

(And walking can be toggled in module.ini with multiplayer_walk_enabled = 1, right?)
 
Hmm.
So my server event stets one agent id for all players on the server?
How can I change it, that every player gets a different agent id?

Caba`drin said:
(And walking can be toggled in module.ini with multiplayer_walk_enabled = 1, right?)
No you only will walk if the key is pressed constantly... like in SP.
 
Your event isn't sending an agent ID...it is sending a sub-event ID constant (1 for walk limit, 2 for sprint limit, 3 for sprint time, 4 for sprint stop).

You'd need to get either the player or the player-agent ID client side and actually send that variable to the server and then call the script with just that ID, not within a loop for all players. (Probably best to get the player ID client side and send that, then get the player-agent ID serverside and use that in the script...I think.)
 
Haven't had time to check the script in detail yet; but caba, the script game receive network by default already has the player-id for the person who sent it.
 
SonKidd said:
but caba, the script game receive network by default already has the player-id for the person who sent it.
Ah, right. So that should be slick then. Don't even need to change the client-side call of the server event, just the event processing itself to not be a loop and to used the player ID that triggered the event.

_Sebastian_ said:
Caba`drin said:
(And walking can be toggled in module.ini with multiplayer_walk_enabled = 1, right?)
No you only will walk if the key is pressed constantly... like in SP.
Ah, gotcha.
 
NovaTitan said:
Wow, we've waited so long for this. Thanks Sebastian. I'll try it out when I get the chance.
Thank you.
Take what ever you need :wink:

I'm currently working on a sprintmode for horses.
I will post it when it's finished.
 
Caba`drin said:
Isn't your server event dictating the walk/sprint state for all players depending on what 1 player does?
Oh damn.
I tested it today with some friends on my dedicated server and it's true.
All players get the same agent id.
So if someone is in the walking mode, then everyone will walk.
Caba`drin said:
You'd need to get either the player or the player-agent ID client side and actually send that variable to the server and then call the script with just that ID, not within a loop for all players. (Probably best to get the player ID client side and send that, then get the player-agent ID serverside and use that in the script...I think.)
Could you show me an example how to do that?

Edit
Something like this?
Code:
#walking
walk_limiter = (
  0, 0, 0.5,
  [
    (key_clicked, key_left_shift),

    (try_begin),
      (game_in_multiplayer_mode),
      (neg|multiplayer_is_server),
      (multiplayer_get_my_player, ":my_player"),
      (player_get_agent_id, ":agent", ":my_player"),
      (multiplayer_send_2_int_to_server, multiplayer_event_set_agent_id, ":agent", 1),
    (else_try),
...
...
Code:
      # multiplayer_event_set_agent_id
      (else_try),
        (eq, ":event_type", multiplayer_event_set_agent_id),
        (store_script_param, ":agent_id", 3),
        (store_script_param, ":script_id", 4),

        (get_max_players, ":num_players"),
        (try_for_range, ":cur_player", 1, ":num_players"),
          (player_is_active,":cur_player"),
          (try_begin),
            (eq, ":script_id", 1),
            (call_script, "script_cf_agent_walk", ":agent_id"),
          (else_try),
...
...
 
Caba`drin said:
Your event isn't sending an agent ID...it is sending a sub-event ID constant (1 for walk limit, 2 for sprint limit, 3 for sprint time, 4 for sprint stop).
Because of this, I would rename the event from
multiplayer_event_set_agent_id
to
multiplayer_event_set_movement_state

Caba`drin said:
You'd need to get either the player or the player-agent ID client side and actually send that variable to the server and then call the script with just that ID, not within a loop for all players. (Probably best to get the player ID client side and send that, then get the player-agent ID serverside and use that in the script...I think.)
You don't actually need to do this since:
Caba`drin said:
SonKidd said:
but caba, the script game receive network by default already has the player-id for the person who sent it.
Ah, right. So that should be slick then. Don't even need to change the client-side call of the server event, just the event processing itself to not be a loop and to used the player ID that triggered the event.

So you can use the player ID stored at the top of the event-processing script in this line at the top of that script: (store_script_param, ":player_no", 1),
This means you don't need to send anything client-side other than the event and the script-id/movement state type, so your old triggers in the form of:
Code:
walk_limiter = (
  0, 0, 0.5,
  [
    (key_clicked, key_left_shift),

    (try_begin),
      (game_in_multiplayer_mode),
      (neg|multiplayer_is_server),
      (multiplayer_send_int_to_server, multiplayer_event_set_movement_state, 1),
    (else_try),
      (get_player_agent_no, ":player_agent"),
      (call_script, "script_cf_agent_walk", ":player_agent"),
    (try_end),
  ], [])
will work fine.


In your event, you also don't want to use a loop at all--you only want the server to change the 1 player-agent from the player who initiated the event to avoid
Caba`drin said:
Isn't your server event dictating the walk/sprint state for all players depending on what 1 player does? You need to send a player/agent ID to the server so you only address the relevant player-agent, not all player-agents.

So your event code should be quite simply:
Code:
      (else_try),
        (eq, ":event_type", multiplayer_event_set_movement_state),
        (store_script_param, ":script_id", 3),
        
        (player_get_agent_id, ":agent", ":player_no"),
          (try_begin),
            (eq, ":script_id", 1),
            (call_script, "script_cf_agent_walk", ":agent"),
          (else_try),
            (eq, ":script_id", 2),
            (call_script, "script_cf_agent_sprint_limiter", ":agent"),
          (else_try),
            (eq, ":script_id", 3),
            (call_script, "script_cf_agent_sprint_time", ":agent"),
          (else_try),
            (eq, ":script_id", 4),
            (call_script, "script_cf_agent_sprint_stop", ":agent"),
          (try_end),
 
It could be simplified to:
Code:
      (else_try),
        (eq, ":event_type", multiplayer_event_set_movement_state),
        (store_script_param, ":script_id", 3),
        
        (player_get_agent_id, ":agent", ":player_no"),
        (ge, ":script_id", "script_cf_agent_walk"), 
        (le, ":script_id", "script_cf_agent_sprint_stop"),
        (call_script, ":script_id", ":agent"),

so event would be:

(multiplayer_send_int_to_server, multiplayer_event_set_movement_state, "script_cf_agent_walk"),

:evil:
 
Back
Top Bottom