How to code a Breakable Helmet

Users who are viewing this thread

Hello,

I am trying to implement a breakable helmet in MB Warband.

In my mind this should work in-game like shields, where after a certain amount of hitpoints is consumed the helmet (itm_breakable_helmet) switches to a damaged mesh (itm_breakable_helmet_broken) and then eventually disappears completetely, uncovering the face of the character.

I don't think I've seen anything like this before and would appreciate any input / suggestion! Thanks!

EDIT: it is worth pointing out that I've been unable to even locate the script that allows shields to be broken, so if you know where that is it would be again a massive help!
 
Solution
So I can offer some guidance as to how I would do it.

Step 1: Set up per-agent item durability via slots and fill them in ti_on_agent_spawn

In module_constants
Python:
# First among your agent slots
agent_armor_dur_head = 100 # whatever number is open for you
agent_armor_dur_hand = agent_armor_dur_head + 1
agent_armor_dur_feet = agent_armor_dur_head + 2
agent_armor_dur_main = agent_armor_dur_head + 3

# and in your item_slots
slot_damaged_variant = 100 # Or, again, whatever you have available

In mission_templates, attached to a common ti_on_agent_spawn
Python:
agent_spawn_effects = (
    ti_on_agent_spawn, 0, 0, [], [
    (store_trigger_param_1, ":agent"),

    (try_for_range, ":equipment_slot", 4, 8),
        (agent_get_item_slot...
The shield breaking stuff is hard-coded and not accessible for us modders. So there is no script etc. to which we can point you. There is however a weapon-breaking-trigger script which is OSP, you can find it here:

It will however not help you since it's - like you see at the name - for weapons. Weapons can get easily reequiped with the operation agent_equip_item which only works for weapon-like stuff. The armoury of a player (armour, helmet, gloves, boots) would require the agent to be respawned. So you would need to check the agent, remove his helmet (or replace with a broken one), let the agent fade out, respawn the agent at the same position. And I don't think it would even look good in the end. So it's not really worth the time and effort.
 
Upvote 0
The shield breaking stuff is hard-coded and not accessible for us modders. So there is no script etc. to which we can point you. There is however a weapon-breaking-trigger script which is OSP, you can find it here:

It will however not help you since it's - like you see at the name - for weapons. Weapons can get easily reequiped with the operation agent_equip_item which only works for weapon-like stuff. The armoury of a player (armour, helmet, gloves, boots) would require the agent to be respawned. So you would need to check the agent, remove his helmet (or replace with a broken one), let the agent fade out, respawn the agent at the same position. And I don't think it would even look good in the end. So it's not really worth the time and effort.

You are not fully correct.

Singleplayer

Changing/replacing armors of agents in singleplayer works straight away.. There is no need to respawn agent.

Multiplayer

You can do that without re-spawning agent. You have to create client & server event and inform other clients about that "event".
Without doing that, other clients will still see old armor.

Multiplayer Serverside Only

As @Eärendil Ardamírë said. You have to re-spawn agent in order to achieve that.


General

Let us know if you are working on MP script or SP script.
MP script will be more complex.
You will have to make slots which gonna keep current "hitpoints" of agents helmets.
Part of your code will be located in on_hit trigger.You will have to update "hitpoints" of damaged agent helmet.
If "hitpoints" of helmet are less than X, send info to client about that. Tell other players to update that agent armor.


Additional tips

WSE can provide information about which part of the agent body was damaged.
That can help you in making your script more immersing.
 
Upvote 0
You are not fully correct.

Singleplayer

Changing/replacing armors of agents in singleplayer works straight away.. There is no need to respawn agent.

Multiplayer

You can do that without re-spawning agent. You have to create client & server event and inform other clients about that "event".
Without doing that, other clients will still see old armor.

Multiplayer Serverside Only

As @Eärendil Ardamírë said. You have to re-spawn agent in order to achieve that.


General

Let us know if you are working on MP script or SP script.
MP script will be more complex.
You will have to make slots which gonna keep current "hitpoints" of agents helmets.
Part of your code will be located in on_hit trigger.You will have to update "hitpoints" of damaged agent helmet.
If "hitpoints" of helmet are less than X, send info to client about that. Tell other players to update that agent armor.


Additional tips

WSE can provide information about which part of the agent body was damaged.
That can help you in making your script more immersing.

Sorry I should have specified it’s single player only!
Would you mind elaborating on what it’s required to implement it? Thanks!
 
Upvote 0
So I can offer some guidance as to how I would do it.

Step 1: Set up per-agent item durability via slots and fill them in ti_on_agent_spawn

In module_constants
Python:
# First among your agent slots
agent_armor_dur_head = 100 # whatever number is open for you
agent_armor_dur_hand = agent_armor_dur_head + 1
agent_armor_dur_feet = agent_armor_dur_head + 2
agent_armor_dur_main = agent_armor_dur_head + 3

# and in your item_slots
slot_damaged_variant = 100 # Or, again, whatever you have available

In mission_templates, attached to a common ti_on_agent_spawn
Python:
agent_spawn_effects = (
    ti_on_agent_spawn, 0, 0, [], [
    (store_trigger_param_1, ":agent"),

    (try_for_range, ":equipment_slot", 4, 8),
        (agent_get_item_slot, ":equipment", ":agent", ":equipment_slot"),
        (gt, ":equipment", 0), # Agent does have an armor equipped here
 
        (item_get_hit_points, ":hp", ":equipment"),
 
        (try_begin),
            (eq, ":equipment_slot", 4), # Head
            (agent_set_slot, ":agent", agent_armor_dur_head, ":hp"),
        (else_try),
            (eq, ":equipment_slot", 5),    # Body
            (agent_set_slot, ":agent", agent_armor_dur_main, ":hp"),
        (else_try),
            (eq, ":equipment_slot", 6),    # Leg
            (agent_set_slot, ":agent", agent_armor_dur_feet, ":hp"),
        (else_try),
            # Would be 7, Hand
            (agent_set_slot, ":agent", agent_armor_dur_hand, ":hp"),
        (try_end),
    (try_end),

    ]),

As you can tell, this assumes you are declaring hitpoints for EACH AND EVERY ARMOR, if you do not, every hit will be shattering these poor things.

Also you need to set up a script inside game_start and game_quick_start to assign the damaged variants to their original forms

Step 2: Locational Damage, Breaking and Swapping -
First, we need to determine where damage was on the agent.

In mission_templates, attached to a common ti_on_agent_hit
Python:
common_damage_system= (
ti_on_agent_hit, 0, 0, [],
[
    (set_fixed_point_multiplier, 100),
    (store_trigger_param, ":agent", 1),
    (store_trigger_param, ":attacker", 2),
    (store_trigger_param, ":damage", 3),
    (store_trigger_param, ":bodypart", 4),
    # (store_trigger_param, ":missile", 5),
    (agent_get_troop_id, ":troop", ":agent"),
    (agent_get_troop_id, ":attacker_troop", ":attacker"),
    (assign, ":attacker_weapon", reg0),

    (agent_is_alive, ":agent"),
    (agent_is_human, ":agent"),

    (store_agent_hit_points, ":health_remaining_actual", ":agent", 1),

    (store_troop_health, ":current_health", ":troop"),
    (troop_set_health, ":troop", 100),
    (store_troop_health, ":max_health_actual", ":troop", 1),
    (troop_set_health, ":troop", ":current_health"),


    # This is a listing of bones for usage in locational damage tracking
    # hb_abdomen = 0
    # hb_thigh_l = 1
    # hb_calf_l = 2
    # hb_foot_l = 3
    # hb_thigh_r = 4
    # hb_calf_r = 5
    # hb_foot_r = 6
    # hb_spine = 7
    # hb_thorax = 8
    # hb_head = 9
    # hb_shoulder_l = 10
    # hb_upperarm_l = 11
    # hb_forearm_l = 12
    # hb_hand_l = 13
    # hb_item_l = 14
    # hb_shoulder_r = 15
    # hb_upperarm_r = 16
    # hb_forearm_r = 17
    # hb_hand_r = 18

    (try_begin),
        (gt, ":attacker_weapon", 0),
        (item_get_swing_damage_type, ":damage_type", ":attacker_weapon"),
        # I dunno how to determine which attack was unleashed, but this will work
        # We can use this to make certain damage types, such as blunt, do more damage
        # to armor durability vs things like pierce which should nearly pass through
    (else_try),
        (assign, ":damage_type", 2),
    (try_end),

    (try_begin),
        (eq, ":damage_type", 0),    # Cut
        (assign, ":dampen", 30),
    (else_try),
        (eq, ":damage_type", 1),    # Pierce
        (assign, ":dampen", 35),
    (else_try),
        (eq, ":damage_type", 2),    # Blunt
        (assign, ":dampen", 15),
    (try_end),

    (store_div, ":durability_hit", ":damage", ":dampen"),

    (agent_get_slot, ":head_durability", ":agent", agent_armor_dur_head),
    (agent_get_slot, ":hand_durability", ":agent", agent_armor_dur_hand),
    (agent_get_slot, ":feet_durability", ":agent", agent_armor_dur_feet),
    (agent_get_slot, ":main_durability", ":agent", agent_armor_dur_main),

    (agent_get_item_slot, ":head_armor", ":agent", 4),
    (agent_get_item_slot, ":hand_armor", ":agent", 7),
    (agent_get_item_slot, ":feet_armor", ":agent", 6),
    (agent_get_item_slot, ":main_armor", ":agent", 5),

    (item_get_slot, ":head_damaged_var", ":head_armor", slot_damaged_variant),
    (item_get_slot, ":hand_damaged_var", ":hand_armor", slot_damaged_variant),
    (item_get_slot, ":feet_damaged_var", ":feet_armor", slot_damaged_variant),
    (item_get_slot, ":main_damaged_var", ":main_armor", slot_damaged_variant),
 
    (try_begin),
        (this_or_next|eq, ":bodypart", 0), # Guts
        (is_between, ":bodypart", 7, 9), # Spine and Thorax
 
        (gt, ":main_armor", 0), # Has Armor

        (val_sub, ":main_durability", ":durability_hit"),
        (val_max, ":main_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_main, ":main_durability"),
        (eq, ":main_durability", 0),
        (agent_unequip_item, ":agent", ":main_armor", 5),
        (neq, ":main_damaged_var", 0),
        (item_get_hit_points, ":hp", ":main_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_main, ":hp"),
        (agent_equip_item, ":agent", ":main_damaged_var", 5),
    (else_try),
        (is_between, ":bodypart", 1, 7), # Legs

        (gt, ":feet_armor", 0), # Has Armor 

        (val_sub, ":feet_durability", ":durability_hit"),
        (val_max, ":feet_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_feet, ":feet_durability"),
        (eq, ":feet_durability", 0),
        (agent_unequip_item, ":agent", ":feet_armor", 4),
        (neq, ":feet_damaged_var", 0),
        (item_get_hit_points, ":hp", ":feet_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_feet, ":hp"),
        (agent_equip_item, ":agent", ":feet_damaged_var", 4),
    (else_try),
        (eq, ":bodypart", 9), # head

        (gt, ":head_armor", 0), # Has Armor

        (val_sub, ":head_durability", ":durability_hit"),
        (val_max, ":head_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_head, ":head_durability"),
        (eq, ":head_durability", 0),
        (agent_unequip_item, ":agent", ":head_armor", 5),
        (neq, ":head_damaged_var", 0),
        (item_get_hit_points, ":hp", ":head_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_head, ":hp"),
        (agent_equip_item, ":agent", ":head_damaged_var", 5),
    (else_try),
        (this_or_next|is_between, ":bodypart", 12, 14), # Left Forearms and Hand
        (gt, ":bodypart", 17), # Right Forearms and Hand

        (gt, ":hand_armor", 0), # Has Armor

        (val_sub, ":hand_durability", ":durability_hit"),
        (val_max, ":hand_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_hand, ":hand_durability"),
        (eq, ":hand_durability", 0),
        (agent_unequip_item, ":agent", ":hand_armor", 5),
        (neq, ":hand_damaged_var", 0),
        (item_get_hit_points, ":hp", ":hand_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_hand, ":hp"),
        (agent_equip_item, ":agent", ":hand_damaged_var", 5),
    (try_end),

    (set_trigger_result, ":damage"),
])
That bad boy will also handle breaking, and equipping a damaged variant if applicable

I did not fact-check, prototype or demo this at all, so, I cannot guarantee its functionality, but it looks accurate enough to me.

Also, the above is part of OSP, you may use it at your discretion, credit is always appreciated, but not necessary.

Tweaks I would do to make it more satisfying:
Store the location of the bone, make a particle burst at the location.
Create a physics item for the armor in the mod and allow it to pop off into the scene if destroyed.
 
Last edited:
Upvote 0
Solution
So I can offer some guidance as to how I would do it.

Step 1: Set up per-agent item durability via slots and fill them in ti_on_agent_spawn

In module_constants
Python:
# First among your agent slots
agent_armor_dur_head = 100 # whatever number is open for you
agent_armor_dur_hand = agent_armor_dur_head + 1
agent_armor_dur_feet = agent_armor_dur_head + 2
agent_armor_dur_main = agent_armor_dur_head + 3

# and in your item_slots
slot_damaged_variant = 100 # Or, again, whatever you have available

In mission_templates, attached to a common ti_on_agent_spawn
Python:
agent_spawn_effects = (
    ti_on_agent_spawn, 0, 0, [], [
    (store_trigger_param_1, ":agent"),

    (try_for_range, ":equipment_slot", 4, 8),
        (agent_get_item_slot, ":equipment", ":agent", ":equipment_slot"),
        (gt, ":equipment", 0), # Agent does have an armor equipped here
 
        (item_get_hit_points, ":hp", ":equipment"),
 
        (try_begin),
            (eq, ":equipment_slot", 4), # Head
            (agent_set_slot, ":agent", agent_armor_dur_head, ":hp"),
        (else_try),
            (eq, ":equipment_slot", 5),    # Body
            (agent_set_slot, ":agent", agent_armor_dur_main, ":hp"),
        (else_try),
            (eq, ":equipment_slot", 6),    # Leg
            (agent_set_slot, ":agent", agent_armor_dur_feet, ":hp"),
        (else_try),
            # Would be 7, Hand
            (agent_set_slot, ":agent", agent_armor_dur_hand, ":hp"),
        (try_end)
    (try_end),

    ]),

As you can tell, this assumes you are declaring hitpoints for EACH AND EVERY ARMOR, if you do not, every hit will be shattering these poor things.

Also you need to set up a script inside game_start and game_quick_start to assign the damaged variants to their original forms

Step 2: Locational Damage, Breaking and Swapping -
First, we need to determine where damage was on the agent.

In mission_templates, attached to a common ti_on_agent_hit
Python:
common_damage_system= (
ti_on_agent_hit, 0, 0, [],
[
    (set_fixed_point_multiplier, 100),
    (store_trigger_param, ":agent", 1),
    (store_trigger_param, ":attacker", 2),
    (store_trigger_param, ":damage", 3),
    (store_trigger_param, ":bodypart", 4),
    # (store_trigger_param, ":missile", 5),
    (agent_get_troop_id, ":troop", ":agent"),
    (agent_get_troop_id, ":attacker_troop", ":attacker"),
    (assign, ":attacker_weapon", reg0),

    (agent_is_alive, ":agent"),
    (agent_is_human, ":agent"),

    (store_agent_hit_points, ":health_remaining_actual", ":agent", 1),

    (store_troop_health, ":current_health", ":troop"),
    (troop_set_health, ":troop", 100),
    (store_troop_health, ":max_health_actual", ":troop", 1),
    (troop_set_health, ":troop", ":current_health"),


    # This is a listing of bones for usage in locational damage tracking
    # hb_abdomen = 0
    # hb_thigh_l = 1
    # hb_calf_l = 2
    # hb_foot_l = 3
    # hb_thigh_r = 4
    # hb_calf_r = 5
    # hb_foot_r = 6
    # hb_spine = 7
    # hb_thorax = 8
    # hb_head = 9
    # hb_shoulder_l = 10
    # hb_upperarm_l = 11
    # hb_forearm_l = 12
    # hb_hand_l = 13
    # hb_item_l = 14
    # hb_shoulder_r = 15
    # hb_upperarm_r = 16
    # hb_forearm_r = 17
    # hb_hand_r = 18

    (try_begin),
        (gt, ":attacker_weapon", 0),
        (item_get_swing_damage_type, ":damage_type", ":attacker_weapon"),
        # I dunno how to determine which attack was unleashed, but this will work
        # We can use this to make certain damage types, such as blunt, do more damage
        # to armor durability vs things like pierce which should nearly pass through
    (else_try),
        (assign, ":damage_type", 2),
    (try_end),

    (try_begin),
        (eq, ":damage_type", 0),    # Cut
        (assign, ":dampen", 30),
    (else_try),
        (eq, ":damage_type", 1),    # Pierce
        (assign, ":dampen", 35),
    (else_try),
        (eq, ":damage_type", 2),    # Blunt
        (assign, ":dampen", 15),
    (try_end),

    (store_div, ":durability_hit", ":damage", ":dampen"),

    (agent_get_slot, ":head_durability", ":agent", agent_armor_dur_head),
    (agent_get_slot, ":hand_durability", ":agent", agent_armor_dur_hand),
    (agent_get_slot, ":feet_durability", ":agent", agent_armor_dur_feet),
    (agent_get_slot, ":main_durability", ":agent", agent_armor_dur_main),

    (agent_get_item_slot, ":head_armor", ":agent", 4),
    (agent_get_item_slot, ":hand_armor", ":agent", 7),
    (agent_get_item_slot, ":feet_armor", ":agent", 6),
    (agent_get_item_slot, ":main_armor", ":agent", 5),

    (item_get_slot, ":head_damaged_var", ":head_armor", slot_damaged_variant),
    (item_get_slot, ":hand_damaged_var", ":hand_armor", slot_damaged_variant),
    (item_get_slot, ":feet_damaged_var", ":feet_armor", slot_damaged_variant),
    (item_get_slot, ":main_damaged_var", ":main_armor", slot_damaged_variant),
 
    (try_begin),
        (this_or_next|eq, ":bodypart", 0), # Guts
        (is_between, ":bodypart", 7, 9), # Spine and Thorax
 
        (gt, ":main_armor", 0), # Has Armor

        (val_sub, ":main_durability", ":durability_hit"),
        (val_max, ":main_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_main, ":main_durability"),
        (eq, ":main_durability", 0),
        (agent_unequip_item, ":agent", ":main_armor", 5),
        (neq, ":main_damaged_var", 0),
        (item_get_hit_points, ":hp", ":main_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_main, ":hp"),
        (agent_equip_item, ":agent", ":main_damaged_var", 5),
    (else_try),
        (is_between, ":bodypart", 1, 7), # Legs

        (gt, ":feet_armor", 0), # Has Armor 

        (val_sub, ":feet_durability", ":durability_hit"),
        (val_max, ":feet_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_feet, ":feet_durability"),
        (eq, ":feet_durability", 0),
        (agent_unequip_item, ":agent", ":feet_armor", 4),
        (neq, ":feet_damaged_var", 0),
        (item_get_hit_points, ":hp", ":feet_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_feet, ":hp"),
        (agent_equip_item, ":agent", ":feet_damaged_var", 4),
    (else_try),
        (eq, ":bodypart", 9), # head

        (gt, ":head_armor", 0), # Has Armor

        (val_sub, ":head_durability", ":durability_hit"),
        (val_max, ":head_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_head, ":head_durability"),
        (eq, ":head_durability", 0),
        (agent_unequip_item, ":agent", ":head_armor", 5),
        (neq, ":head_damaged_var", 0),
        (item_get_hit_points, ":hp", ":head_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_head, ":hp"),
        (agent_equip_item, ":agent", ":head_damaged_var", 5),
    (else_try),
        (this_or_next|is_between, ":bodypart", 12, 14), # Left Forearms and Hand
        (gt, ":body_part", 17), # Right Forearms and Hand

        (gt, ":hand_armor", 0), # Has Armor

        (val_sub, ":hand_durability", ":durability_hit"),
        (val_max, ":hand_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_hand, ":hand_durability"),
        (eq, ":hand_durability", 0),
        (agent_unequip_item, ":agent", ":hand_armor", 5),
        (neq, ":hand_damaged_var", 0),
        (item_get_hit_points, ":hp", ":hand_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_hand, ":hp"),
        (agent_equip_item, ":agent", ":hand_damaged_var", 5),
    (try_end),

    (set_trigger_result, ":damage"),
])
That bad boy will also handle breaking, and equipping a damaged variant if applicable

I did not fact-check, prototype or demo this at all, so, I cannot guarantee its functionality, but it looks accurate enough to me.

Also, the above is part of OSP, you may use it at your discretion, credit is always appreciated, but not necessary.

Tweaks I would do to make it more satisfying:
Store the location of the bone, make a particle burst at the location.
Create a physics item for the armor in the mod and allow it to pop off into the scene if destroyed.

Thanks for your help! I gave it a go but unfortunately I cannot see any effect in game; I must be missing something.

1. I'd need some guidance / example on the script to assign damage variants (I assumed that for testing purposes without this script it would swap to the character's naked head)

2. In mission_templates, does it matter where I place the two blocks of code? I placed them right after the first ti_on_agent_spawn, ti_on agent_hit in the file. Maybe that's the reason why it is not triggered?

Thanks again for the help!
 
Upvote 0
The dampening is probably way too strong, as it was based off my mods damage values which are always way too high, so maybe tweak then to like 3, 5 and 2 respectively.

A good way to check if it is firing is to put something like
Code:
(assign, reg15, ":durability_hit"),
(display_message, "@I received {reg15} damage to my armor),
I would personally place it inside each body_part clause and have it also tell you where they were hit

1. In module_scripts find "game_start" and "game_quick_start" and include something like:
(item_set_slot, "itm_that_breaks", slot_damaged_variant, "itm_that_breaks_broken"),

2. I would just list them where the other common triggers are, then in the actual missions like charge, include the name somewhere the other common triggers are being called. I do not know what might happen if two ti_on_agent_hit are called separately, so if you already have one, just merge the above inside of it. ti_on_agent_spawn should work fine though.
 
Last edited:
Upvote 0
I finally got around to testing it out and it worked like a charm, the only modification to the above code I made for my test only storing a flat hp value for all items instead of doing a store_item_hitpoints operation as I didn't want any permanent changes on my mod.




I think the issue may be that you are not registering the triggers inside the combat mission you are testing them in.
EDIT: Updated video because my microphone was unplugged. Whoops.
 
Last edited:
Upvote 0
That's pretty great! Thank you for following up on this, the video shows exactly what I had in mind.

Due to my (very) modest knowledge of MS I'm still struggling to make it work: it compiles with no error but in-game I can't see results.

So if it's not it's not too much trouble I'd ask you if you could post a longer version of your code, in particular highlighting how you integrated ti_on_agent_spawn and ti_on_agent_hit entries in mission_templates; also including in 'lead_charge' mission for example.

Thanks!

PS. I guess you'll get the best answer because the video shows that this is clearly working!
 
Upvote 0
Ahh, so, when you're adding scripts to mission_template entries, like lead_charge, there are two ways to do it.


Python:
    # Obviously, don't make a new one, this is just an example
    ("mission_entry", 0, -1,
    "Some Entry",
    [
        # Entry Points List, not necessary for this
    ], 
    [
        # Triggers List, This is where you add the triggers that were shared
    
        # Example trigger broken down, this is ugly, but Python doesn't allow inline comments
        (0,  # Check Interval or What makes this fire
         0,  # Delay Interval, how long to wait before applying the consequences
         0,  # Rearm Interval, how long to wait before the trigger can fire again
         [], # Conditions Block, do not fire unless this is true
         []  # Consequence Block, what operations will fire
        ),
        # As you can see, you could copy and paste the trigger inside the mission directly
        # But it will quickly get unwieldy and is not really considered best practice
        # Ideally only do it this way for testing or for one off triggers.

        # If you are going to reuse a trigger in other missions (Which you will)
        # The easiest way is to declare the trigger above the mission entries
        # and call the name inside the trigger list, like
        some_trigger, example_trigger, agent_spawn_effects, common_damage_system
    ]),

I also had trouble with this when I started out, so don't worry too much about it.
So, to simplify it:
  1. Create the trigger declaration before the entries i.e. trigger_name = (0,0,0,[],[]).
  2. Inside the mission entry you want this trigger to be active in, inside the consequence block, add the trigger name.
  3. And that's it!
 
Upvote 0
Thank you for the detailed explanation, I finally managed to make it work like in the video that you posted!

I've got one last question, please. Every time I hit an enemy I get the following error onscreen. As far as I can tell, it does not stop the code from working properly.

Code:
Invalid Item Kind ID: -1; LINE NO: 41:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 43:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 40:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 41:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. vdt_regular discard_buffer()
 SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 41:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 43:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 40:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 41:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 41:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. SCRIPT ERROR ON OPCODE 527: Invalid Item Kind ID: -1; LINE NO: 43:
 At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences. At Mission Template mst_lead_charge trigger no: 2 consequences.

By any chance did you experience something similar and you know what is causing the error? I'm also including my mst_lead_charge below. Thanks!
Code:
  (
    "lead_charge",mtf_battle_mode|mtf_synch_inventory,charge,
    "You lead your men to battle.",
    [
     (1,mtef_defenders|mtef_team_0,0,aif_start_alarmed,12,[]),
     (0,mtef_defenders|mtef_team_0,0,aif_start_alarmed,0,[]),
     (4,mtef_attackers|mtef_team_1,0,aif_start_alarmed,12,[]),
     (4,mtef_attackers|mtef_team_1,0,aif_start_alarmed,0,[]),
     ],
    [
    
      (ti_on_agent_spawn, 0, 0, [],
       [
         (store_trigger_param_1, ":agent_no"),
         (call_script, "script_agent_reassign_team", ":agent_no"),

         (assign, ":initial_courage_score", 5000),

         (agent_get_troop_id, ":troop_id", ":agent_no"),
         (store_character_level, ":troop_level", ":troop_id"),
         (val_mul, ":troop_level", 100), #was 35
         (val_add, ":initial_courage_score", ":troop_level"), #average : 20 * 35 = 700

         (store_random_in_range, ":randomized_addition_courage", 0, 3000), #average : 1500
         (val_add, ":initial_courage_score", ":randomized_addition_courage"),

         (agent_get_party_id, ":agent_party", ":agent_no"),
         (party_get_morale, ":cur_morale", ":agent_party"),

         (store_sub, ":morale_effect_on_courage", ":cur_morale", 70),
         (val_mul, ":morale_effect_on_courage", 30), #this can effect morale with -2100..900
         (val_add, ":initial_courage_score", ":morale_effect_on_courage"),

         #average = 5000 + 700 + 1500 = 7200; min : 5700, max : 8700
         #morale effect = min : -2100(party morale is 0), average : 0(party morale is 70), max : 900(party morale is 100)
         #min starting : 3600, max starting  : 9600, average starting : 7200
         (agent_set_slot, ":agent_no", slot_agent_courage_score, ":initial_courage_score"),
         ]),
        
        #Breakable Item Begin+
      (ti_on_agent_spawn, 0, 0, [],
        [
          (store_trigger_param_1, ":agent"),

            (try_for_range, ":equipment_slot", 4, 8),
            (agent_get_item_slot, ":equipment", ":agent", ":equipment_slot"),
            (gt, ":equipment", 0), # Agent does have an armor equipped here
 
            #(item_get_hit_points, ":hp", ":equipment"),
            (assign, ":hp", 1), #Flat Hitpoints
 
            (try_begin),
            (eq, ":equipment_slot", 4), # Head
            (agent_set_slot, ":agent", agent_armor_dur_head, ":hp"),
            (else_try),
            (eq, ":equipment_slot", 5),    # Body
            (agent_set_slot, ":agent", agent_armor_dur_main, ":hp"),
            (else_try),
            (eq, ":equipment_slot", 6),    # Leg
            (agent_set_slot, ":agent", agent_armor_dur_feet, ":hp"),
            (else_try),
            # Would be 7, Hand
            (agent_set_slot, ":agent", agent_armor_dur_hand, ":hp"),
            (try_end),
            (try_end),

        ]),
        
        
        
        
        
        (ti_on_agent_hit, 0, 0, [],
    [
    (set_fixed_point_multiplier, 100),
    (store_trigger_param, ":agent", 1),
    (store_trigger_param, ":attacker", 2),
    (store_trigger_param, ":damage", 3),
    (store_trigger_param, ":bodypart", 4),
    # (store_trigger_param, ":missile", 5),
    (agent_get_troop_id, ":troop", ":agent"),
    (agent_get_troop_id, ":attacker_troop", ":attacker"),
    (assign, ":attacker_weapon", reg0),

    (agent_is_alive, ":agent"),
    (agent_is_human, ":agent"),

    (store_agent_hit_points, ":health_remaining_actual", ":agent", 1),

    (store_troop_health, ":current_health", ":troop"),
    (troop_set_health, ":troop", 100),
    (store_troop_health, ":max_health_actual", ":troop", 1),
    (troop_set_health, ":troop", ":current_health"),


    # This is a listing of bones for usage in locational damage tracking
    # hb_abdomen = 0
    # hb_thigh_l = 1
    # hb_calf_l = 2
    # hb_foot_l = 3
    # hb_thigh_r = 4
    # hb_calf_r = 5
    # hb_foot_r = 6
    # hb_spine = 7
    # hb_thorax = 8
    # hb_head = 9
    # hb_shoulder_l = 10
    # hb_upperarm_l = 11
    # hb_forearm_l = 12
    # hb_hand_l = 13
    # hb_item_l = 14
    # hb_shoulder_r = 15
    # hb_upperarm_r = 16
    # hb_forearm_r = 17
    # hb_hand_r = 18

    (try_begin),
        (gt, ":attacker_weapon", 0),
        (item_get_swing_damage_type, ":damage_type", ":attacker_weapon"),
        # I dunno how to determine which attack was unleashed, but this will work
        # We can use this to make certain damage types, such as blunt, do more damage
        # to armor durability vs things like pierce which should nearly pass through
    (else_try),
        (assign, ":damage_type", 2),
    (try_end),

    (try_begin),
        (eq, ":damage_type", 0),    # Cut
        (assign, ":dampen", 3),
    (else_try),
        (eq, ":damage_type", 1),    # Pierce
        (assign, ":dampen", 5),
    (else_try),
        (eq, ":damage_type", 2),    # Blunt
        (assign, ":dampen", 2),
    (try_end),

    (store_div, ":durability_hit", ":damage", ":dampen"),

    (agent_get_slot, ":head_durability", ":agent", agent_armor_dur_head),
    (agent_get_slot, ":hand_durability", ":agent", agent_armor_dur_hand),
    (agent_get_slot, ":feet_durability", ":agent", agent_armor_dur_feet),
    (agent_get_slot, ":main_durability", ":agent", agent_armor_dur_main),

    (agent_get_item_slot, ":head_armor", ":agent", 4),
    (agent_get_item_slot, ":hand_armor", ":agent", 7),
    (agent_get_item_slot, ":feet_armor", ":agent", 6),
    (agent_get_item_slot, ":main_armor", ":agent", 5),

    (item_get_slot, ":head_damaged_var", ":head_armor", slot_damaged_variant),
    (item_get_slot, ":hand_damaged_var", ":hand_armor", slot_damaged_variant),
    (item_get_slot, ":feet_damaged_var", ":feet_armor", slot_damaged_variant),
    (item_get_slot, ":main_damaged_var", ":main_armor", slot_damaged_variant),
 
    (try_begin),
        (this_or_next|eq, ":bodypart", 0), # Guts
        (is_between, ":bodypart", 7, 9), # Spine and Thorax
 
        (gt, ":main_armor", 0), # Has Armor

        (val_sub, ":main_durability", ":durability_hit"),
        (val_max, ":main_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_main, ":main_durability"),
        (eq, ":main_durability", 0),
        (agent_unequip_item, ":agent", ":main_armor", 5),
        (neq, ":main_damaged_var", 0),
        (item_get_hit_points, ":hp", ":main_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_main, ":hp"),
        (agent_equip_item, ":agent", ":main_damaged_var", 5),
    (else_try),
        (is_between, ":bodypart", 1, 7), # Legs

        (gt, ":feet_armor", 0), # Has Armor

        (val_sub, ":feet_durability", ":durability_hit"),
        (val_max, ":feet_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_feet, ":feet_durability"),
        (eq, ":feet_durability", 0),
        (agent_unequip_item, ":agent", ":feet_armor", 4),
        (neq, ":feet_damaged_var", 0),
        (item_get_hit_points, ":hp", ":feet_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_feet, ":hp"),
        (agent_equip_item, ":agent", ":feet_damaged_var", 4),
    (else_try),
        (eq, ":bodypart", 9), # head

        (gt, ":head_armor", 0), # Has Armor

        (val_sub, ":head_durability", ":durability_hit"),
        (val_max, ":head_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_head, ":head_durability"),
        (eq, ":head_durability", 0),
        (agent_unequip_item, ":agent", ":head_armor", 5),
        (neq, ":head_damaged_var", 0),
        (item_get_hit_points, ":hp", ":head_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_head, ":hp"),
        (agent_equip_item, ":agent", ":head_damaged_var", 5),
    (else_try),
        (this_or_next|is_between, ":bodypart", 12, 14), # Left Forearms and Hand
        (gt, ":bodypart", 17), # Right Forearms and Hand

        (gt, ":hand_armor", 0), # Has Armor

        (val_sub, ":hand_durability", ":durability_hit"),
        (val_max, ":hand_durability", 0), # Durability cannot be negative

        (agent_set_slot, ":agent", agent_armor_dur_hand, ":hand_durability"),
        (eq, ":hand_durability", 0),
        (agent_unequip_item, ":agent", ":hand_armor", 5),
        (neq, ":hand_damaged_var", 0),
        (item_get_hit_points, ":hp", ":hand_damaged_var"),
        (agent_set_slot, ":agent", agent_armor_dur_hand, ":hp"),
        (agent_equip_item, ":agent", ":hand_damaged_var", 5),
    (try_end),

    (set_trigger_result, ":damage"),
    ]),
        #Breakable Item End+


      common_battle_init_banner,

#more triggers...
 
Upvote 0
When debugging Warband, look up the Error Opcode inside of header_operation.

In this case, 527 is item_get_slot. So you're looking up some slot of the item id -1 which is telling you nothing is happening, so, we look for the item_get_slot in question and put a (gt, ":whateverlocalisbeingused", 0),

In this case it is definitely the damaged variant lookup on being hit so add something like
Python:
   # Replace this block with
    #(item_get_slot, ":head_damaged_var", ":head_armor", slot_damaged_variant),
    #(item_get_slot, ":hand_damaged_var", ":hand_armor", slot_damaged_variant),
    #(item_get_slot, ":feet_damaged_var", ":feet_armor", slot_damaged_variant),
    #(item_get_slot, ":main_damaged_var", ":main_armor", slot_damaged_variant),

(try_begin),
    (gt, ":head_armor", 0),
    (item_get_slot, ":head_damaged_var", ":head_armor", slot_damaged_variant),
(try_end),

(try_begin),
    (gt, ":hand_armor", 0),
    (item_get_slot, ":hand_damaged_var", ":hand_armor", slot_damaged_variant),
(try_end),

(try_begin),
    (gt, ":feet_armor", 0),
    (item_get_slot, ":feet_damaged_var", ":feet_armor", slot_damaged_variant),
(try_end),

(try_begin),
    (gt, ":main_armor", 0),
    (item_get_slot, ":main_damaged_var", ":main_armor", slot_damaged_variant),
(try_end),

You could nest all the assignment things into a single try_for_range loop, but this is easier to grasp at your stage.

Each check before the item_get_slot is placed into a try_ loop to prevent it from stopping the script after the loop ends in case of the armor being -1, but also, separated because we want each one to be checked separately.
 
Upvote 0
Back
Top Bottom