OSP Code Combat Poisoned weapons

Dalion

Squire
Best answers
0
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  :wink:



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

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  :shifty:
 

BerTolkien

Sergeant Knight
Best answers
0
Hello!

Awesone!
I tested and it works perfectly!  :grin:

The only problem is when the enemy dies from his poison, one who poisoned him don't receive xp. So we must be able to complete this code which is an excellent starting point.

I will use this code in the next and latest version of my module, Nox RPG.
We should even be able to adapt it for vampire weapons! It's always good to recover some hp!  :wink:

Cheers!
:twisted:
 

Dalion

Squire
Best answers
0
BerTolkien said:
when the enemy dies from his poison, one who poisoned him don't receive xp
It is intended. Poison did the job, not you :grin:  You could be anywhere when the enemy died, he might not even have been in your line of sight at this moment, how could you get xp from it  :razz:

Jokes aside, thats the remove_agent operation that prevents you from getting xp. You can replace it with agent_deliver_damage_to_agent to get it. But it will also add some messages about damage dealt, which are quite out of place imo that's why I didn't go this way.
 

builder of the gods

Sergeant at Arms
Best answers
0
UndeadDuke said:
BerTolkien said:
when the enemy dies from his poison, one who poisoned him don't receive xp
It is intended. Poison did the job, not you :grin:  You could be anywhere when the enemy died, he might not even have been in your line of sight at this moment, how could you get xp from it  :razz:

Jokes aside, thats the remove_agent operation that prevents you from getting xp. You can replace it with agent_deliver_damage_to_agent to get it. But it will also add some messages about damage dealt, which are quite out of place imo that's why I didn't go this way.
use
Code:
(set_show_messages, 0),
(agent_deliver_damage_to_agent, x, y, z),
(set_show_messages, 1),
this will make sure you won't get a notification but still recieve the xp (if thats what you are after)
 

SaskyGames

Regular
Best answers
0
Hey,how do I properly add the mission_templates part?
I added the code that needed to be pasted,but can somebody tell me how do I add the poison "properties" to a mission?
To elaborate: I have the code in,everything works,but the falchion and arrows do not poison the enemies when in-game


Edit: I guess that I should add something to "call" the script,but i don't know what.
I should add something in "common_battle_mission_start = (" right?
 

Dalion

Squire
Best answers
0
SaskyGames said:
everything works
SaskyGames said:
falchion and arrows do not poison the enemies when in-game
Thats not the same thing you know


I guess you don't know how to "activate" the code in appropriate missions. Well, thats easy, simply list their names after the first bracket block of the mission. Like this:

(
    "village_attack_bandits",mtf_battle_mode|mtf_synch_inventory,charge,
    "You lead your men to battle.",
    [
    (3,mtef_visitor_source|mtef_team_1,0,aif_start_alarmed,1,[]),
    (1,mtef_team_0|mtef_use_exact_number,0,aif_start_alarmed, 7,[]),
    (1,mtef_visitor_source|mtef_team_0,0,aif_start_alarmed,1,[]),
    ],
    [
    common_battle_tab_press,
    common_battle_init_banner,
    poison1,
    poison2,
    poison3,


 
      (ti_question_answered, 0, 0, [],
      [(store_trigger_param_1,":answer"),
        (eq,":answer",0),
        (assign, "$pin_player_fallen", 0),
        (str_store_string, s5, "str_retreat"),
        (call_script, "script_simulate_retreat", 10, 20, 1),
        (assign, "$g_battle_result", -1),
        (call_script, "script_count_mission_casualties_from_agents"),
        (finish_mission,0),]),

  Blue ones - our added lines
 

SaskyGames

Regular
Best answers
0
Hey,thanks for the help,everything works when i put the names in village_attack and bandit lairs script :smile:
I've got one more question,how do i make it so the script starts in every battle? From what i understand common_battle cannot use lists to activate mission triggers
 

Eärendil the Mariner

Subforum Moderator
WBWF&SM&B
Best answers
36
It would be nice if you stay at one place with your questions regarding the mission template since you are also asking about it here: https://forums.taleworlds.com/index.php/topic,381679.0.html
 

Raqqa

Knight
WBNWVCWF&SM&B
Best answers
0
UndeadDuke said:
Code:
#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),
     ])
Here;
#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
Don't miss this, this will cause the error...

And thanks for your code, a really useful code!

 

Dalion

Squire
Best answers
0
Sure, it is possible. From the three triggers, poison2 is the one dealing damage/killing, so you can tell him when to stop. The easiest way would be adding another agent slot, and use it as timer (i.e. if you want poison to be active for 5 seconds, you make poison1 trigger assign victim slot value to 5, and make poison2 to decrease it by 1 every time it triggers, and be triggered only if slot value is higher than zero).