[Idea/request] Spearman Script?

Users who are viewing this thread

Sahran

Grandmaster Knight
I have no experience in scripting, but I am curious about if an idea would be scriptable and if someone could do the script.

A problem faced in Mount and Blade and to an extent Total war is the equipping of spearmen. More often than not mods have to produce artificial swordsmen units because the AI doesn't handle spears and sidearms mixed together. This ends up making players or the AI able to field anachronistic, romanesque armies for people that never would have done so. Ideally, a sword would be found in many of their ranks as a sidearm for the spearman and the archer but not the primary weapon of the spearman.

The goal of this "Spearman script" idea would be:

1) Guarantee unit X always has a spear and sword and shield in his inventory (I am pretty sure this has been done)
2) Guarantee that unit X will always wield the spear unless one of the following criteria is met:
A) The spear breaks (I'm sure this has been done in 1257 for cavalry)
B) The unit isn't in formation or isn't hold position or whatever
C) It's a siege

What I'd be most interested in is 1 and 2-A. Make spearmen always carry a spear and a sword, always wield the spear until it breaks, then they wield swords. Spears would break due to whatever variables (probably a damage threshold & the weapon skill of the NPC).

Would that be possible? Can anyone point me in the right direction for how to script that, or have a script on hand itself?
 
Sorry to post so much on the fly and without links. I'll try and add them later.

SonKidd has provided a script that guarantees weapons. (1)
My code for lancers/horse-archers/spearman should accomplish 2, though it has distance-to-enemy checks for the decision making. That could be changed of course.
 
Just pointing the direction...

You could set slots to mark a spearman as a spearman. As soon you enter combat you could run a script that equips the spearman with the spear. If a spear breaks it will be unequipped automatically so the AI will do the rest on its own. If not in formation is a bit harder. You would need to have a check for that which hardly depends on how formations are set up.
While you can always check if the unit is ordered to hold position.

Something like this should be all that's needed:

(again, just pointing the direction....sorry for that.)



(agent_get_team, ":team", ":agent"),
(agent_get_division, ":division", ":agent"),
(eq, ":division", 3), #3 is the division I put spearmen in, would be key #4 ingame
(team_get_movement_order, ":cur_order", ":team", ":division"),
(eq, ":cur_order", mordr_hold),
....some equipment switching goes here...

If it is a siege or not is easily done. You would have to mess around in game_mission_templates and add your code to open field battles, sieges, village raids and such manually. So you could just leave it out.

Here is an example to make an agent switching weapons. Just put the first spear item and the one item that comes after the last spear in. A range is always 1st value until (2nd value -1).

(assign, ":max", 4),
(try_for_range, ":slots", 0, ":max"), # equip throwing weapon
(agent_get_item_slot, ":item", ":agent", ":slots"),
(is_between, ":item", "itm_darts", "itm_crossbow"),
(agent_set_wielded_item, ":agent", ":item"),
(assign, ":max", ":slots"),
(try_end),


Well, have a lot of fun!  :razz:

I hope this helps a bit.


I've been ninja'd by Caba....  nevertheless...
 
Well I appreciate both your guys help. :grin:

I'll give my hand at trying it myself in the near future (or bow and scape for someone's help!). I'm thinking more of the latter.  :shock: Stuff is moonspeak to me! But I'm glad to hear this is feasible.
 
Considering the great times I had while enjoying how your research and what not was set up in the other mod I am willing to lend you a hand on this one. That is as long as you don't want me to add the spear breaking stuff!

 
That'd be great. It's for an upcoming mod project that should be announced in a few weeks, so it might be a bit before I'm able to take up your offer. We might be able to get Othr to lend us the spear breaking stuff, unless you mean that making it based on spear breaking would be easier, rather than harder? Afraid my cluttered mind is a tad confused. Would it be easier for you to do the "Spearmen with a sidearm" script with spear breaking being what decides what weapon is used? Or to make formation or distance or whatever determine what weapon is used? You mighta been the one to do the spear breaking script in 1257 in the first place!  :grin:

 
Will you believe I'm clapping with glee at this? No? Me neither, but I'm still well chuffed at this thread. I knew only of the middle one but all three of those are quite interesting.
 
Yeah, I already wrote something similar based on the scripts Caba'drin mentioned. Also wrote a lance-breaking script, but that could be extended to include spears as well.
Code:
common_battle_cavalry_lance_break = (
  ti_on_agent_hit, 0.1, 0, [ 
  #delay so we don't break lance before impact?
  (is_between, reg0, all_items_begin, all_items_end),
  (item_slot_eq, reg0, slot_item_cant_on_horseback, 2), #is a lance
  (item_get_type, ":type", reg0),
  (eq, ":type", itp_type_polearm),
  ],
  [ (store_trigger_param_1, ":inflicted"),
    (store_trigger_param_2, ":dealer"),
    (store_trigger_param_3, ":damage"),
    (assign, ":item", reg0),
    (agent_get_horse, ":horse", ":dealer"),
    (ge, ":horse", 0), #mount exists
    #DO ARBITRARY CONDITIONS - speed, damage checks
    #do not break lance if only remaining weapon?
    (agent_unequip_item, ":dealer", ":item"),
    (try_begin),
      (agent_slot_eq, ":dealer", slot_agent_polearm, ":item"),
      (agent_set_slot, ":dealer", slot_agent_polearm, -1), #UNSET
    (try_end),
    (call_script, "script_agent_equip_backup", ":dealer"),

    (str_store_item_name, s0, ":item"),
    (str_store_agent_name, s1, ":dealer"),
    (try_begin),
      (agent_is_human, ":inflicted"),
      (str_store_agent_name, s2, ":inflicted"),
    (else_try),
      (agent_get_item_id, ":horse", ":inflicted"),
      (str_store_item_name, s2, ":horse"),
    (try_end),

    (display_message, "@{s1}'s {s0} broke against {s2}!"),
    (agent_play_sound, ":inflicted", "snd_shield_broken"),
    (particle_system_burst, "psys_dummy_straw", pos0, ":damage"),
  ])

common_battle_init = (ti_on_agent_spawn,0,0, [],
   [
    (store_trigger_param_1, ":agent"),
    (agent_is_human, ":agent"),
    (agent_get_troop_id, ":agent"),
    (try_begin),
      (troop_get_slot, ":polearm", ":troop", slot_troop_polearm),
     # (gt, ":polearm", 0),
      (assign, ":end", ek_head), #4 cycles
      (try_for_range, ":slot", ek_item_0, ek_head),
        (agent_get_item_slot, ":item", ":agent", ":slot"),
        (gt, ":item", 0), #might be -1
        (try_begin), #found guaranteed polearm
          (eq, ":item", ":polearm"), #one found already equipped
          (assign, ":end", 0),
        (else_try), #parse if polearm
          (eq, ":polearm", 0), #not filled
          (item_get_type, ":type", ":item"),
          (eq, ":type", itp_type_polearm),
          (try_begin),
            (troop_is_guarantee_horse, ":troop"), #is cavalry
            (item_slot_eq, ":item", slot_item_cant_on_horseback, 2), #couching lances
            (assign, ":end", 0),
          (else_try),
            (item_slot_eq, ":item", slot_item_cant_on_horseback, 1), #can't use on horseback
            (item_slot_ge, ":item", slot_item_length, 245), #long pikes
            (assign, ":end", 0),
          (try_end),
          (eq, ":end", 0),
          (assign, ":polearm", ":item"),
        (try_end),
      (try_end),
      #regardless of the case
       (agent_set_slot, ":agent", slot_agent_polearm, ":polearm"),
      #still not found
       (eq, ":end", ek_head),
       (agent_equip_item, ":agent", ":polearm"),
      # (agent_set_wielded_item, ":agent", ":polearm"),
    (try_end),
  ]
 ),

common_battle_weapon_check = (2.5,0,0, [],
    [(call_script, "script_agent_check_backup"),]
    )

multiplayer_server_manage_bots = (
  3, 0, 0, [(multiplayer_is_server),],
  [
    (try_for_agents, ":agent"),
      (agent_is_non_player, ":agent"),
      (agent_is_human, ":agent"),
      (agent_is_alive, ":agent"),
      
      (agent_get_group, ":agent_group", ":agent"),
      (try_begin),
        (neg|player_is_active, ":agent_group"),
        (call_script, "script_multiplayer_change_leader_of_bot", ":agent"),
      (else_try),
        (player_get_team_no, ":leader_team_no", ":agent_group"),
        (agent_get_team, ":agent_team", ":agent"),
        (neq, ":leader_team_no", ":agent_team"),
        (call_script, "script_multiplayer_change_leader_of_bot", ":agent"),
      (try_end),
      
      (try_begin),
        (agent_get_slot, ":lance", ":agent", slot_agent_polearm),
        (gt, ":lance", 0),
        (agent_get_wielded_item, ":wielded", ":agent", 0), # Get wielded item.
        (gt, ":wielded", 0), #not fisting
        (item_get_type, ":type", ":wielded"),  #using melees 
        (is_between, ":type", itp_type_one_handed_wpn, itp_type_arrows),
        (item_get_slot, ":type", ":lance", slot_item_cant_on_horseback), #polearm type
        (try_begin),
          (agent_get_horse, ":horse", ":agent"),# They riding a horse?
          (try_begin),  # Still mounted lancer or pikeman
            (this_or_next|ge, ":horse", 0),
            (neq, ":type", 2),
            (item_get_slot, ":distance", ":lance", slot_item_length),
            (agent_get_position, pos1,  ":agent"),
            (agent_get_team, ":team_no", ":agent"),
            (try_for_agents,":cur_agent"),
              (gt, ":distance", 0),
              (agent_is_alive, ":cur_agent"),
              (agent_is_human, ":cur_agent"),
              (agent_get_team, ":agent_team", ":cur_agent"),
              (neq, ":agent_team", ":team_no"), #only 2 teams in multiplayer
              (agent_get_position, pos2, ":cur_agent"),
              (get_distance_between_positions,":cur_dist",pos2,pos1),
              (lt, ":cur_dist", ":distance"),
              (assign, ":distance", -1), #found at least 1 within 2xrange of weapon
            (try_end),
            (agent_get_combat_state, ":cs", ":agent"),
            (try_begin),
              (eq, ":distance", -1), #found within range
              (gt, ":cs", 3),
              (eq, ":wielded", ":lance"),
              (call_script, "script_agent_equip_backup", ":agent"),
            (else_try),
              (gt, ":distance", 0), #some distance outside weapon reach
              (le, ":cs", 3),
              (neq, ":wielded", ":lance"), # Enemies farther than 5 meters and/or not fighting, and not using lance?
              (agent_set_wielded_item, ":agent", ":lance"), # Then equip it!
            (try_end),
          (else_try),
            (le, ":horse", 0), # Isn't riding a horse.
            (neq, ":type", 1), #not unusable on horseback
            (eq, ":wielded", ":lance"), #If the item wasn't actually usable, this wouldn't happen
            (call_script, "script_agent_equip_backup", ":agent"),
          (try_end),
        (try_end),
      (try_end),
    (try_end),
    ])
Code:
#script_agent_check_backup
("agent_check_backup", [
    (get_player_agent_no, ":player_agent"),
    (agent_get_team, ":player_team", ":player_agent"),
    #we parse the 3 base class weapon order here - doing so inside the loop would be repetitive
    (team_get_weapon_usage_order, ":inf_order", ":player_team", grc_infantry),
    (team_get_weapon_usage_order, ":rag_order", ":player_team", grc_archers),
    (team_get_weapon_usage_order, ":cav_order", ":player_team", grc_cavalry),
    (team_get_weapon_usage_order, ":fmd_order", ":player_team", grc_formed),
    
    #do lance sorts
    (try_for_agents, ":agent"),
      (agent_is_alive, ":agent"),
      (neq, ":agent", ":player_agent"),
      (agent_get_slot, ":lance", ":agent", slot_agent_polearm),
      (gt, ":lance", 0),
      #this would be a lot better inside slots & such
      (try_begin), #player weapon orders 
        #wordr_any is 0  - continue sort
        #wordr_blunt is 1 - we could actually fetch dmg types, but we won't bother
        (agent_is_ally, ":agent"),
        (agent_get_class, ":type", ":agent"),
        (try_begin), #this is probably a faster operation than refetching
          (eq, ":type", grc_infantry),
          (assign, ":order", ":inf_order"),
        (else_try),
          (eq, ":type", grc_archers),
          (assign, ":order", ":rag_order"),
        (else_try),
          (eq, ":type", grc_cavalry),
          (assign, ":order", ":cav_order"),
        (else_try),
          (eq, ":type", grc_formed),
          (assign, ":order", ":fmd_order"),
        (else_try), #custom types - rarely used?
          (team_get_weapon_usage_order, ":order", ":player_team", ":type"),
        (try_end),
      (try_end),
      (eq, ":order", 0),
      (agent_get_wielded_item, ":wielded", ":agent", 0), # Get wielded item.
      (gt, ":wielded", 0), #not fisting
      (item_get_type, ":type", ":wielded"),  #using melees 
      (is_between, ":type", itp_type_one_handed_wpn, itp_type_arrows),
      (item_get_slot, ":type", ":lance", slot_item_cant_on_horseback), #polearm type
      (try_begin),
        (agent_get_horse, ":horse", ":agent"),# They riding a horse?
        (try_begin),  # Still mounted lancer or pikeman
          (this_or_next|ge, ":horse", 0),
          (neq, ":type", 2),
          (item_get_slot, ":distance", ":lance", slot_item_length),
          (agent_get_position, pos1,  ":agent"),
          (agent_get_team, ":team_no", ":agent"),
          (try_for_agents,":cur_agent"),
            (gt, ":distance", 0),
            (agent_is_alive, ":cur_agent"),
            (agent_is_human, ":cur_agent"),
            (agent_get_team, ":agent_team", ":cur_agent"),
            (teams_are_enemies, ":agent_team", ":team_no"),
            (agent_get_position, pos2, ":cur_agent"),
            (get_distance_between_positions,":cur_dist",pos2,pos1),
            (lt, ":cur_dist", ":distance"),
            (assign, ":distance", -1), #found at least 1 within 2xrange of weapon
          (try_end),
          (agent_get_combat_state, ":cs", ":agent"),
          (try_begin),
            (eq, ":distance", -1), #found within range
            (gt, ":cs", 3),
            (eq, ":wielded", ":lance"),
            (call_script, "script_agent_equip_backup", ":agent"),
          (else_try),
            (gt, ":distance", 0), #some distance outside weapon reach
            (le, ":cs", 3),
            (neq, ":wielded", ":lance"), # Enemies farther than 5 meters and/or not fighting, and not using lance?
            (agent_set_wielded_item, ":agent", ":lance"), # Then equip it!
          (try_end),
        (else_try),
          (le, ":horse", 0), # Isn't riding a horse.
          (neq, ":type", 1), #not unusable on horseback
          (eq, ":wielded", ":lance"), #If the item wasn't actually usable, this wouldn't happen
          (call_script, "script_agent_equip_backup", ":agent"),
        (try_end),
      (try_end),
    (try_end),
  ]),
("agent_equip_backup", [
  (store_script_param, ":agent", 1),
  (assign, ":end", ek_head),
  (try_for_range, ":slot", ek_item_0, ":end"),
    (agent_get_item_slot, ":cur_weapon", ":agent", ":slot"),
    (gt, ":cur_weapon", -1),
    (item_get_type, ":type", ":cur_weapon"),
    (is_between, ":type", itp_type_one_handed_wpn, itp_type_polearm),#one or two handed
    (agent_set_wielded_item, ":agent", ":cur_weapon"), #1st one that matches
    (assign, ":end", ek_item_0),
  (try_end),
  ]),
 
Really appreciate it all, though it's making my head swirl. Think I'll try and enlist a coder for this sekret project to handle the coding stuff!

The concern I have with the proximity for spearmen script is that it would make them use spears when there aren't many enemies nearby (cavalry, in other words) but when it comes to infantry they would switch to a sword. My intention would be for the two infantry formations to behave like a Hoplite phalanx - charge at eachother with spears, then switch to swords when it's a bloody mess. So I am finding myself partial to the idea of spears being forced until the spear is broken (A'la the lance breaking script), then they switch to swords.

So I suppose I'll try and look into, or get a coding guru buddeh, to look into appropriating Somebody's lance break script for spears, use the script to guarantee specific weaponry, and then how would I say "Always wield spears first, then you can switch to swords".
 
Back
Top Bottom