First of all, thanks to kalarhan for help with issues during making this. This code is made for SP mode. Tbh my modding skills are below average so any part of this code could use improvements. You are free to improve this or to use as it is, just don't forget to give credits.
How does it work? You can set any weapons to be poisoned. After your enemies have been hit with such weapon, their hp will start to decrease over time (-1% per second so it will take the same 100 seconds to kill an enemy with 40hp or with 1000hp). When their hp becomes zero, they will always die unless they have hero flag (no surgery can save from this :p). The game will inform you when you managed to poison someone, when you got poisoned yourself, and when someone dies of poison. It is recommended to have some sort of deathcam installed so the battle will continue after you are defeated so that you can watch poison avenging you after some time
Now let's get to the implementation itself. There are 3 steps:
1) Add this anywhere in module_constants.py:
2) Add this at the end of game_get_item_extra_text script in module_scripts.py:
3) Add these mission triggers in mission_templates.py and later on add their names on any needed template:
poison1 => marks the target as poisoned after it gets hit with certain weapons
poison2 => deals damage over time if mark is active
poison3 => determines what should happen if target died of poison and not of something else
That's all, you are ready to go! Have fun with destroying your enemies from the inside
How does it work? You can set any weapons to be poisoned. After your enemies have been hit with such weapon, their hp will start to decrease over time (-1% per second so it will take the same 100 seconds to kill an enemy with 40hp or with 1000hp). When their hp becomes zero, they will always die unless they have hero flag (no surgery can save from this :p). The game will inform you when you managed to poison someone, when you got poisoned yourself, and when someone dies of poison. It is recommended to have some sort of deathcam installed so the battle will continue after you are defeated so that you can watch poison avenging you after some time
Now let's get to the implementation itself. There are 3 steps:
1) Add this anywhere in module_constants.py:
Code:
slot_agent_is_poisoned = 30
2) Add this at the end of game_get_item_extra_text script in module_scripts.py:
Code:
(else_try),
(this_or_next|eq, ":item_no", "itm_falchion"), #This is a list of weapons that should have poison effect
(eq, ":item_no", "itm_arrows"),
(try_begin),
(eq, ":extra_text_id", 0),
(set_result_string, "@Poisoned"),
(set_trigger_result, 0x3F8000),
(try_end),
]),
("game_get_item_extra_text",
[
(store_script_param, ":item_no", 1),
(store_script_param, ":extra_text_id", 2),
(store_script_param, ":item_modifier", 3),
(try_begin),
(is_between, ":item_no", food_begin, food_end),
(try_begin),
(eq, ":extra_text_id", 0),
(assign, ":continue", 1),
(try_begin),
(this_or_next|eq, ":item_no", "itm_cattle_meat"),
(this_or_next|eq, ":item_no", "itm_pork"),
(eq, ":item_no", "itm_chicken"),
(eq, ":item_modifier", imod_rotten),
(assign, ":continue", 0),
(try_end),
(eq, ":continue", 1),
(item_get_slot, ":food_bonus", ":item_no", slot_item_food_bonus),
(assign, reg1, ":food_bonus"),
(set_result_string, "@+{reg1} to party morale"),
(set_trigger_result, 0x4444FF),
(try_end),
(else_try),
(is_between, ":item_no", readable_books_begin, readable_books_end),
(try_begin),
(eq, ":extra_text_id", 0),
(item_get_slot, reg1, ":item_no", slot_item_intelligence_requirement),
(set_result_string, "@Requires {reg1} intelligence to read"),
(set_trigger_result, 0xFFEEDD),
(else_try),
(eq, ":extra_text_id", 1),
(item_get_slot, ":progress", ":item_no", slot_item_book_reading_progress),
(val_div, ":progress", 10),
(assign, reg1, ":progress"),
(set_result_string, "@Reading Progress: {reg1}%"),
(set_trigger_result, 0xFFEEDD),
(try_end),
(else_try),
(is_between, ":item_no", reference_books_begin, reference_books_end),
(try_begin),
(eq, ":extra_text_id", 0),
(try_begin),
(eq, ":item_no", "itm_book_wound_treatment_reference"),
(str_store_string, s1, "@wound treament"),
(else_try),
(eq, ":item_no", "itm_book_training_reference"),
(str_store_string, s1, "@trainer"),
(else_try),
(eq, ":item_no", "itm_book_surgery_reference"),
(str_store_string, s1, "@surgery"),
(try_end),
(set_result_string, "@+1 to {s1} while in inventory"),
(set_trigger_result, 0xFFEEDD),
(else_try),
(this_or_next|eq, ":item_no", "itm_falchion"), #This is a list of weapons that should have poison effect
(eq, ":item_no", "itm_arrows"),
(try_begin),
(eq, ":extra_text_id", 0),
(set_result_string, "@Poisoned"),
(set_trigger_result, 0x3F8000),
(try_end),
]),
Blue ones => our added lines
[
(store_script_param, ":item_no", 1),
(store_script_param, ":extra_text_id", 2),
(store_script_param, ":item_modifier", 3),
(try_begin),
(is_between, ":item_no", food_begin, food_end),
(try_begin),
(eq, ":extra_text_id", 0),
(assign, ":continue", 1),
(try_begin),
(this_or_next|eq, ":item_no", "itm_cattle_meat"),
(this_or_next|eq, ":item_no", "itm_pork"),
(eq, ":item_no", "itm_chicken"),
(eq, ":item_modifier", imod_rotten),
(assign, ":continue", 0),
(try_end),
(eq, ":continue", 1),
(item_get_slot, ":food_bonus", ":item_no", slot_item_food_bonus),
(assign, reg1, ":food_bonus"),
(set_result_string, "@+{reg1} to party morale"),
(set_trigger_result, 0x4444FF),
(try_end),
(else_try),
(is_between, ":item_no", readable_books_begin, readable_books_end),
(try_begin),
(eq, ":extra_text_id", 0),
(item_get_slot, reg1, ":item_no", slot_item_intelligence_requirement),
(set_result_string, "@Requires {reg1} intelligence to read"),
(set_trigger_result, 0xFFEEDD),
(else_try),
(eq, ":extra_text_id", 1),
(item_get_slot, ":progress", ":item_no", slot_item_book_reading_progress),
(val_div, ":progress", 10),
(assign, reg1, ":progress"),
(set_result_string, "@Reading Progress: {reg1}%"),
(set_trigger_result, 0xFFEEDD),
(try_end),
(else_try),
(is_between, ":item_no", reference_books_begin, reference_books_end),
(try_begin),
(eq, ":extra_text_id", 0),
(try_begin),
(eq, ":item_no", "itm_book_wound_treatment_reference"),
(str_store_string, s1, "@wound treament"),
(else_try),
(eq, ":item_no", "itm_book_training_reference"),
(str_store_string, s1, "@trainer"),
(else_try),
(eq, ":item_no", "itm_book_surgery_reference"),
(str_store_string, s1, "@surgery"),
(try_end),
(set_result_string, "@+1 to {s1} while in inventory"),
(set_trigger_result, 0xFFEEDD),
(else_try),
(this_or_next|eq, ":item_no", "itm_falchion"), #This is a list of weapons that should have poison effect
(eq, ":item_no", "itm_arrows"),
(try_begin),
(eq, ":extra_text_id", 0),
(set_result_string, "@Poisoned"),
(set_trigger_result, 0x3F8000),
(try_end),
]),
Blue ones => our added lines
3) Add these mission triggers in mission_templates.py and later on add their names on any needed template:
poison1 => marks the target as poisoned after it gets hit with certain weapons
poison2 => deals damage over time if mark is active
poison3 => determines what should happen if target died of poison and not of something else
Code:
poison1 = (ti_on_agent_hit, 0, 0, [], [
(store_trigger_param_1, ":victim"),
(store_trigger_param_2, ":attacker"),
(store_trigger_param, ":missile", 5),
#Here we should add weapons that were listed before. Note that weapons are added in reg0 and missiles in ":missile"
variable. It is important. Also do keep in mind that in this case, throwing weapons are treated as missiles
(this_or_next|eq, reg0, "itm_falchion"),
(eq, ":missile", "itm_arrows"),
(try_begin),
(agent_get_slot, ":is_poisoned", ":victim", slot_agent_is_poisoned),
(get_player_agent_no, ":player"),
(agent_get_horse, ":p_horse", ":player"),
(try_begin),
(eq, ":attacker", ":player"),
(neq, ":is_poisoned", 1),
(try_begin),
(neg|agent_is_human, ":victim"),
(display_message, "@You have poisoned a horse!", 0x3F8000),
(agent_set_slot, ":victim", slot_agent_is_poisoned, 1),
(else_try),
(display_message, "@You have poisoned the enemy!", 0x3F8000),
(agent_set_slot, ":victim", slot_agent_is_poisoned, 1),
(try_end),
(else_try),
(eq, ":victim", ":player"),
(neq, ":is_poisoned", 1),
(display_message, "@You are poisoned!", 0x3F8000),
(agent_set_slot, ":victim", slot_agent_is_poisoned, 1),
(else_try),
(eq, ":victim", ":p_horse"),
(neq, ":is_poisoned", 1),
(display_message, "@Your horse is poisoned!", 0x3F8000),
(agent_set_slot, ":victim", slot_agent_is_poisoned, 1),
(else_try),
(neq, ":is_poisoned", 1),
(agent_set_slot, ":victim", slot_agent_is_poisoned, 1),
(try_end),
(try_end),
])
poison2 = (1, 0, 0, [], [
(try_for_agents,":cur_agent"),
(agent_is_alive, ":cur_agent"),
(agent_get_slot, ":is_poisoned", ":cur_agent", slot_agent_is_poisoned),
(eq, ":is_poisoned", 1),
(try_begin),
(store_agent_hit_points,":agent_hp",":cur_agent", 0),
(val_sub,":agent_hp", 1),
(agent_set_hit_points,":cur_agent",":agent_hp", 0),
(le,":agent_hp", 1),
(remove_agent,":cur_agent"),
(try_end),
(try_end),
])
poison3 = (ti_on_agent_killed_or_wounded, 0, 0, [], [
(store_trigger_param_1, ":victim"),
(agent_get_troop_id, ":troop", ":victim"),
(str_store_troop_name, s33, ":troop"),
(agent_get_slot, ":is_poisoned", ":victim", slot_agent_is_poisoned),
(try_begin),
(eq, ":is_poisoned", 1),
(agent_is_human, ":victim"),
(troop_is_hero, ":troop"),
(display_message, "@{s33} fainted of poison.", 0x3F8000),
(set_trigger_result, 2),
(else_try),
(eq, ":is_poisoned", 1),
(agent_is_human, ":victim"),
(display_message, "@{s33} died of poison.", 0x3F8000),
(set_trigger_result, 1),
(else_try),
(eq, ":is_poisoned", 1),
(display_message, "@Horse died of poison.", 0x3F8000),
(set_trigger_result, 1),
(try_end),
])
That's all, you are ready to go! Have fun with destroying your enemies from the inside
