OSP Code Combat Shield Bash kit. Bug fixed and expanded!

Users who are viewing this thread

Is that "strike_chest_front_stop"? I tried that and felt it was a bit static. I'll try it again.
 
I like "strike_head_front_left" but it's too short to allow the player to follow up with a strike, and it looks horrible when made slower.

The animations could be varied as well, sometimes knocking the opponent over and sometimes barely having an effect (like the "strike_head_front_left"). It's just too bad we can't set all of the animations, otherwise we could also set and vary the struck by weapon animations.
 
It should be a major feature, especially if some sort of restriction is placed on it (which I'm working on now). I'd go as far as saying it completely revolutionizes combat.

I've put in various animations, one knock down, one stun and one that barely has an effect (it's not enough for an attack). It's all currently random with being knocked down unlikely, and the most likely result being stunned, but I'm going to use shield skill as the major factor. Some randomness will remain, as luck is always a factor and things don't always go as planned. The fact that skill is a factor and that there's always randomness is a restriction in itself, since a failed attack leaves you vulnerable.
 
It adds a completely new element. When shields heavily involved (as they are in my mod), they pretty much dominate combat, so it's hard to say that shield suddenly becoming offensive weapons isn't revolutionary :razz:. You can stand there and know you will block anything, and combat gets repetitive knowing you'll just block until the enemy attacks, afterwhich you're guaranteed a successful hit. With shield bash, shield blocking is now vulnerable and you can't be so passive. You can't just stand there blocking as the AI will bash you, which is even more signicant if they're mobbing you. It's less exploitable and less repetitive.

I've made it a skill-dependent action now and I'm about to throw a lot of randomness in. I really wish we had access to normal strikes.
 
Just tested it and it feels good, although with my changes I think it represents more of a grappling system. Barely any direct damage, trading moving and jostling for a position, it all feels more like two soldiers trying to pull and shove each other to allow them to deliver a blow. I found myself using it a lot, but it's definitely not an exploit as it leaves you vulnerable and the AI seems to do it pretty well.
 
New animations:

Code:
# strike_fall_back_rise_after_bashed 
 ["bash_knocked", acf_enforce_all|acf_align_with_ground,
   [2.0, "anim_human", blow+5400, blow+5453, arf_blend_in_2], 
 ],
# strike_chest_front_stop 
 ["bash_stun", acf_enforce_all,
   [1.5, "anim_human", blow+5000, blow+5010, arf_blend_in_3], 
 ],
# strike_chest_front_stop 
 ["bash_mini_stun", acf_enforce_all,
   [0.6, "anim_human", blow+5000, blow+5010, arf_blend_in_3], 
 ], 
 # anim jump end
 ["bash_crouch", acf_enforce_all|acf_enforce_lowerbody,
   [0.5, "anim_human", 280, 290, arf_blend_in_3],
 ],  
# strike_head_front_left 
 ["bash_unsuccessful", acf_enforce_all,
   [0.55, "anim_human", blow+0, blow+10, arf_blend_in_3], 
 ],

Script:

Code:
 ("cf_agent_shield_bash",
    [(store_script_param, ":agent",1),
     (agent_get_position,pos1,":agent"),
     (agent_set_animation, ":agent", "anim_release_bash"),
     (agent_play_sound,":agent","snd_man_grunt"),
     (assign,":victim",-1),
     (try_for_agents,":possible_victim"),
        (agent_is_alive,":possible_victim"),
        (agent_is_human,":possible_victim"),
        (neq,":possible_victim",":agent"),
        (agent_get_class ,":class", ":possible_victim"),
        (neq,":class",grc_cavalry),
        (agent_get_position,pos2,":possible_victim"),
        (get_distance_between_positions,":dist",pos1,pos2),
        (lt,":dist",150),
        (neg|position_is_behind_position,pos2,pos1),
        (assign,":victim",":possible_victim"),
     (end_try),
     (gt,":victim",-1),
     (store_random_in_range,":rand",0,2),
     (store_agent_hit_points,":hp",":victim",1),
     (val_sub,":hp",":rand"),
     (store_random_in_range,":hit_reaction",1,101),
     (store_skill_level,":a_shield",skl_shield,":victim"),
     (store_skill_level,":v_shield",skl_shield,":agent"),	 
     (try_begin),
         (gt,":hp",0),
         (agent_set_hit_points,":victim",":hp",1),
         (agent_play_sound,":agent","snd_shield_hit_wood_wood"),
         (agent_play_sound,":victim","snd_blunt_hit"),
         (try_begin),		 
           (gt,":a_shield", ":v_shield"),
              (try_begin),		 
                (is_between,":hit_reaction",0,10),	 
                (agent_set_animation, ":victim", "anim_bash_unsuccessful"),
              (else_try),		 
                (is_between,":hit_reaction",11,20),	 
                (agent_set_animation, ":victim", "anim_bash_crouch"),				
              (else_try),
                (is_between,":hit_reaction",21,30),	 
                (agent_set_animation, ":victim", "anim_bash_mini_stun"),
              (else_try),
                (is_between,":hit_reaction",21,79),	 
                (agent_set_animation, ":victim", "anim_bash_stun"),				
              (else_try),
                (is_between,":hit_reaction",80,100),	 
                (agent_set_animation, ":victim", "anim_bash_knocked"),
              (end_try),			   
         (else_try),
           (lt,":a_shield", ":v_shield"), 
              (try_begin),		 
                (is_between,":hit_reaction",0,20),	 
                (agent_set_animation, ":victim", "anim_bash_unsuccessful"),
              (else_try),		 
                (is_between,":hit_reaction",21,42),	 
                (agent_set_animation, ":victim", "anim_bash_crouch"),				
              (else_try),
                (is_between,":hit_reaction",43,65),	 
                (agent_set_animation, ":victim", "anim_bash_mini_stun"),
              (else_try),
                (is_between,":hit_reaction",66,92),	 
                (agent_set_animation, ":victim", "anim_bash_stun"),				
              (else_try),
                (is_between,":hit_reaction",93,100),	 
                (agent_set_animation, ":victim", "anim_bash_knocked"),
              (end_try),
         (else_try),
           (eq,":a_shield", ":v_shield"),
              (try_begin),		 
                (is_between,":hit_reaction",0,16),	 
                (agent_set_animation, ":victim", "anim_bash_unsuccessful"),
              (else_try),		 
                (is_between,":hit_reaction",17,33),	 
                (agent_set_animation, ":victim", "anim_bash_crouch"),				
              (else_try),
                (is_between,":hit_reaction",34,50),	 
                (agent_set_animation, ":victim", "anim_bash_mini_stun"),
              (else_try),
                (is_between,":hit_reaction",51,89),	 
                (agent_set_animation, ":victim", "anim_bash_stun"),				
              (else_try),
                (is_between,":hit_reaction",90,100),	 
                (agent_set_animation, ":victim", "anim_bash_knocked"),
              (end_try),
         (end_try),		 
     (else_try),
         (agent_play_sound,":agent","snd_shield_hit_wood_wood"),
         (agent_play_sound,":victim","snd_blunt_hit"),
         (agent_deliver_damage_to_agent,":agent",":victim"),
     (end_try),
   ]),

The shield skill could be more progressive, but as it currently is there's 70% success if you're higher skilled, 1 in 2 if you're evenly matched and about 1 in 3 if you're inferior.

Edit, there still needs to be some sort of restriction. I don't know how to see if a script has been called recently though.
 
That's excellent, Zaro, I think I'll move that to the front page, and don't worry about the player spamming, I'll fix that.
 
I noticed. I was going to do that anyway. There's enough ways to hurt somebody in m+b, but not nearly enough ways to set up a kill.
 
I was wondering if this could be used to have horses attack in battle? I tried doing it and I'm not sure it worked, but it screwed up the horse animation anyway.
 
I was trying to add constant damage per shield and shield skill to add a bonus, I noticed a tiny mistake,

agent_id is not equal to troop_id

Code:
     (store_skill_level,":a_shield",skl_shield,":victim"),
     (store_skill_level,":v_shield",skl_shield,":agent"),

Those lines check totally unrelated troops skills.

Edit;
Whoops forgot my addon :razz:


#Fixx0red script, remove the debug stuff


("cf_agent_shield_bash",
    [(store_script_param, ":agent",1),
(store_script_param, ":shield", 2),
    (agent_get_position,pos1,":agent"),
    (agent_set_animation, ":agent", "anim_release_bash"),
    (agent_play_sound,":agent","snd_man_grunt"),
    (assign,":victim",-1),
    (try_for_agents,":possible_victim"),
        (agent_is_alive,":possible_victim"),
        (agent_is_human,":possible_victim"),
        (neq,":possible_victim",":agent"),
        (agent_get_class ,":class", ":possible_victim"),
        (neq,":class",grc_cavalry),
        (agent_get_position,pos2,":possible_victim"),
        (get_distance_between_positions,":dist",pos1,pos2),
        (lt,":dist",150),
        (neg|position_is_behind_position,pos2,pos1),
        (assign,":victim",":possible_victim"),
    (end_try),

#Random not...
    (gt,":victim",-1),
    (store_agent_hit_points,":hp",":victim",1),

    (store_random_in_range,":hit_reaction",1,101),

#This doesn't work like that, agent_id is not equal to troop_id
    # (store_skill_level,":a_shield",skl_shield,":victim"),
    # (store_skill_level,":v_shield",skl_shield,":agent"),

(agent_get_troop_id,":victim_trp_id", ":victim"),
(agent_get_troop_id,":agent_trp_id", ":agent"),
    (store_skill_level,":v_shield",skl_shield,":victim_trp_id"),
    (store_skill_level,":a_shield",skl_shield,":agent_trp_id"), 

#Let's get skl_shield involved more, every 2 points add 1 damage, so the most damaging shield can plant a nice 9 damage
(item_get_slot,":shield_str", ":shield",slot_shield_damage_value),
(assign, ":shield_skl_dmg_bonus", ":a_shield"),
(val_div, ":shield_skl_dmg_bonus", 2),
(store_add, ":shield_damage", ":shield_str", ":shield_skl_dmg_bonus"),

  (str_store_item_name, s1, ":shield"),
  (str_store_troop_name,s2,":victim_trp_id"),
  (str_store_troop_name,s3,":agent_trp_id"),
(assign, reg0, ":shield_damage"),
(assign, reg1, ":shield_skl_dmg_bonus"),
(assign, reg2, ":shield_str"),
(display_message, "@Calculated Damage {reg0} (shield damage was {reg2} bonus was; {reg1} for {s1}"),
(display_message, "@Victim was {s2} Agent was {s3}"),
    (val_sub,":hp",":shield_damage"),

    (try_begin),
        (gt,":hp",0),
        (agent_set_hit_points,":victim",":hp",1),
        (agent_play_sound,":agent","snd_shield_hit_wood_wood"),
        (agent_play_sound,":victim","snd_blunt_hit"),
        (try_begin),     
          (gt,":a_shield", ":v_shield"),
              (try_begin),     
                (is_between,":hit_reaction",0,10), 
                (agent_set_animation, ":victim", "anim_bash_unsuccessful"),
              (else_try),     
                (is_between,":hit_reaction",11,20), 
                (agent_set_animation, ":victim", "anim_bash_crouch"),           
              (else_try),
                (is_between,":hit_reaction",21,30), 
                (agent_set_animation, ":victim", "anim_bash_mini_stun"),
              (else_try),
                (is_between,":hit_reaction",31,79), 
                (agent_set_animation, ":victim", "anim_bash_stun"),           
              (else_try),
                (is_between,":hit_reaction",80,100), 
                (agent_set_animation, ":victim", "anim_bash_knocked"),
              (end_try),           
        (else_try),
          (lt,":a_shield", ":v_shield"),
              (try_begin),     
                (is_between,":hit_reaction",0,20), 
                (agent_set_animation, ":victim", "anim_bash_unsuccessful"),
              (else_try),     
                (is_between,":hit_reaction",21,42), 
                (agent_set_animation, ":victim", "anim_bash_crouch"),           
              (else_try),
                (is_between,":hit_reaction",43,65), 
                (agent_set_animation, ":victim", "anim_bash_mini_stun"),
              (else_try),
                (is_between,":hit_reaction",66,92), 
                (agent_set_animation, ":victim", "anim_bash_stun"),           
              (else_try),
                (is_between,":hit_reaction",93,100), 
                (agent_set_animation, ":victim", "anim_bash_knocked"),
              (end_try),
        (else_try),
          (eq,":a_shield", ":v_shield"),
              (try_begin),     
                (is_between,":hit_reaction",0,16), 
                (agent_set_animation, ":victim", "anim_bash_unsuccessful"),
              (else_try),     
                (is_between,":hit_reaction",17,33), 
                (agent_set_animation, ":victim", "anim_bash_crouch"),           
              (else_try),
                (is_between,":hit_reaction",34,50), 
                (agent_set_animation, ":victim", "anim_bash_mini_stun"),
              (else_try),
                (is_between,":hit_reaction",51,89), 
                (agent_set_animation, ":victim", "anim_bash_stun"),           
              (else_try),
                (is_between,":hit_reaction",90,100), 
                (agent_set_animation, ":victim", "anim_bash_knocked"),
              (end_try),
        (end_try),     
    (else_try),
        (agent_play_sound,":agent","snd_shield_hit_wood_wood"),
        (agent_play_sound,":victim","snd_blunt_hit"),
        (agent_deliver_damage_to_agent,":agent",":victim"),
    (end_try),
  ]),


add to game_start, I just needed different values to test the script...
#Set Shield Damage Values
# itm_wooden_shield, itm_tab_shield_kite_a
(try_for_range, ":cur_item", "itm_wooden_shield","itm_heraldic_mail_with_surcoat"),
(try_begin),
# itm_wooden_shield, itm_tab_shield_kite_a
(is_between, ":cur_item", "itm_wooden_shield", "itm_tab_shield_kite_a"),
(item_set_slot,":cur_item",slot_shield_damage_value,1),
(else_try),
# itm_tab_shield_kite_a itm_tab_shield_pavise_a
(is_between, ":cur_item", "itm_tab_shield_kite_a", "itm_tab_shield_pavise_a"),
(item_set_slot,":cur_item",slot_shield_damage_value,2),
(else_try),
# itm_tab_shield_pavise_a itm_tab_shield_small_round_a
(is_between, ":cur_item", "itm_tab_shield_pavise_a", "itm_tab_shield_small_round_a"),
(item_set_slot,":cur_item",slot_shield_damage_value,3),
(else_try),
# itm_tab_shield_small_round_a itm_heraldic_mail_with_surcoat
(is_between, ":cur_item", "itm_tab_shield_small_round_a", "itm_heraldic_mail_with_surcoat"),
(item_set_slot,":cur_item",slot_shield_damage_value,1),
(try_end),
(try_end),
#exceptions; itm_steel_shield
(item_set_slot,"itm_steel_shield",slot_shield_damage_value,4),

Mission Template Changes, so that we know the shield,

      (0, 0, 0, [(game_key_is_down, gk_defend),(game_key_clicked, gk_attack),],
      [(assign,":continue",0),
        (get_player_agent_no,":player"),
        (agent_is_alive,":player"),
        (try_for_range,":shield","itm_wooden_shield","itm_heraldic_mail_with_surcoat"),
            (agent_has_item_equipped,":player",":shield"),
(assign, ":wielded_shield", ":shield"),
            (assign,":continue",1),
        (end_try),

        (eq,":continue",1),
        (agent_get_horse,":horse",":player"),
        (neg|gt,":horse",0),
        (ge,"$bash_readiness",10),
        (assign,"$bash_readiness",0),
        (call_script,"script_cf_agent_shield_bash",":player", ":wielded_shield"),
        ]),

      (1.0, 0, 0, [],
      [(get_player_agent_no,":player"),
        (try_for_agents,":agent"),
          (agent_is_alive,":agent"),
          (agent_is_human,":agent"),
          (neq,":agent",":player"),
          (agent_get_class ,":class", ":agent"),
          (neq,":class",grc_cavalry),
          (assign,":continue",0),
          (try_for_range,":shield","itm_wooden_shield","itm_heraldic_mail_with_surcoat"),
              (agent_has_item_equipped,":agent",":shield"),
(assign, ":wielded_shield", ":shield"),
              (assign,":continue",1),
          (end_try),
          (eq,":continue",1),
          (assign,":chances",0),
          (agent_get_team,":team",":agent"),
          (agent_get_position,pos1,":agent"),
          (try_for_agents,":eek:ther"),
                (agent_is_alive,":eek:ther"),
                (agent_is_human,":eek:ther"),
                (agent_get_class ,":class", ":eek:ther"),
                (neq,":class",grc_cavalry),
                (agent_get_team,":eek:therteam",":eek:ther"),
                (neq,":team",":eek:therteam"),
                (agent_get_position,pos2,":eek:ther"),
                (get_distance_between_positions,":dist",pos1,pos2),
                (neg|position_is_behind_position,pos2,pos1),
                (lt,":dist",200),
                (val_add,":chances",1),
          (end_try),
          (store_agent_hit_points,":health",":agent",0),
          (val_mul,":health",-1),
          (val_add,":health",100),
          (val_div,":health",10),
          (val_mul,":chances",":health"),
          (store_random_in_range,":rand",1,25),
          (lt,":rand",":chances"),
          (call_script,"script_cf_agent_shield_bash",":agent", ":wielded_shield"),
        (end_try),]),

ofcourse it is useless without this in constants;
slot_shield_damage_value   = 5

finally game_get_item_extra_text to show how much base damage shield has in item description...

      (else_try),
        (is_between, ":item_no", "itm_wooden_shield","itm_heraldic_mail_with_surcoat"),
        (try_begin),
          (eq, ":extra_text_id", 0),
          (item_get_slot, reg1, ":item_no", slot_shield_damage_value),
          (set_result_string, "@Bashing Damage {reg1}b"),
          (set_trigger_result, 0xFFEEDD),
        (try_end),
 
nice addon. pls don't use the code tags to display the script code on this forum though. it messes the whole thin' when copy/paste and ignore any other forum tags like color..
 
At the rate this is going combat in M&B is gonna turn from block, slash, block, slash to something like actual combat in no time o_O stupidly aggressive AI aside, better than a lot of games and mods I've played.

You, sir, have surpassed godliness.
 
Any chance of a crouching kit? I remember there was a mod for 751 but it would be interesting to see if you could make something for 960.
 
I'd recommond adding the bash readiness check to the AI trigger, i.e.

Code:
           (lt,":rand",":chances"),
           (ge,"$bash_readiness",10),
           (assign,"$bash_readiness",0),		   
           (call_script,"script_cf_agent_shield_bash",":agent"),
 
The ai can only bash once per second as is, same as the player, and I'd rather not make it so that multiple people can't bash at the same time.
 
But would there be a way for troops in a line formation to do a kind of shield wall forward push by bashing all at (or nearly at) the same time once engaged?
 
Dryvus said:
But would there be a way for troops in a line formation to do a kind of shield wall forward push by bashing all at (or nearly at) the same time once engaged?
That would most definitely be doable, but unless two large formations engaged one another, it wouldn't be very useful.
 
Back
Top Bottom