Warning: to implement this OSP, coding skills aren't enough, you should also have at least basic scene editor experience. If you don't, hiner's tutorial is a great starting point.
I'm not much of a coder myself, 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? The trap consists of 2 parts: point of impact and a trigger prop. When you hit a trigger prop (with any weapon, from any range), the spikes will come out around the impact point and damage all nearby agents. One trigger prop can activate multiple impact points, so you can add more of them if you want trap to cover wider area. With my poor skills I can't assign trigger prop to some exact imact points, so hitting one trigger will activate all traps on a scene, that's why it is recommended not to place more than one trap per scene. If anyone knows how to separate them and allow multiple traps, please let me know.
Now let's get to the implementation itself. There are 5 steps:
1) First of all, we need to determine which props will play a role of trigger and impact point. Open module_scene_props.py. For a trigger you should pick one that has collision, so ti_on_scene_prop_hit can actually work. How to check if a prop has collision? Look at its record, if some names in it have bo_ prefix - collision is there. If not - scroll along. For an impact point you should pick some invisible object, and better remove its collision (replace "bo_***" with "0"). When you are done chosing, duplicate their records and rename trigger prop to "st_trigger", impact point prop to "st_impact_point", and also duplicate spike_group_a and rename it to "st_spikes". I've chosen bucket_a as a trigger and barrier_capsule as an impact point, so here is my record:
2) Add this anywhere in module_constants.py:
3) Add these mission triggers at the top of mission_templates.py and later on add their names on any needed template:
spike_trap_setup => spawns four groups of spikes around each impact point when mission starts. It will spawn them underground so when moving impact point don't forget to move the camera below and delete all the spikes from previous spawn
spike_trap_hide => hides the spikes and reloads the trap, preparing it for the next use
spike_trap_check => sort of a timer, every second decreases time left for next trap activation by 1
4) Now we need to make our trigger prop do its job. Put this in its square brackets:
5) Now we are set, and ready to put the trap on our scene in-game. Open scene editor, and find our props:
Place impact points anywhere you like, and then put trigger somewhere near:
That's all. No need to place spikes, they will be spawned automatically when you restart the mission.
This was really painful to create, but definitely worth it imo
I'm not much of a coder myself, 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? The trap consists of 2 parts: point of impact and a trigger prop. When you hit a trigger prop (with any weapon, from any range), the spikes will come out around the impact point and damage all nearby agents. One trigger prop can activate multiple impact points, so you can add more of them if you want trap to cover wider area. With my poor skills I can't assign trigger prop to some exact imact points, so hitting one trigger will activate all traps on a scene, that's why it is recommended not to place more than one trap per scene. If anyone knows how to separate them and allow multiple traps, please let me know.
Now let's get to the implementation itself. There are 5 steps:
1) First of all, we need to determine which props will play a role of trigger and impact point. Open module_scene_props.py. For a trigger you should pick one that has collision, so ti_on_scene_prop_hit can actually work. How to check if a prop has collision? Look at its record, if some names in it have bo_ prefix - collision is there. If not - scroll along. For an impact point you should pick some invisible object, and better remove its collision (replace "bo_***" with "0"). When you are done chosing, duplicate their records and rename trigger prop to "st_trigger", impact point prop to "st_impact_point", and also duplicate spike_group_a and rename it to "st_spikes". I've chosen bucket_a as a trigger and barrier_capsule as an impact point, so here is my record:
2) Add this anywhere in module_constants.py:
Code:
slot_trap_time_left = 50
3) Add these mission triggers at the top of mission_templates.py and later on add their names on any needed template:
spike_trap_setup => spawns four groups of spikes around each impact point when mission starts. It will spawn them underground so when moving impact point don't forget to move the camera below and delete all the spikes from previous spawn
spike_trap_hide => hides the spikes and reloads the trap, preparing it for the next use
spike_trap_check => sort of a timer, every second decreases time left for next trap activation by 1
Code:
spike_trap_setup = (0, 0, ti_once, [],
[
(assign, "$trap_used", 0),
(try_for_prop_instances, ":instance_id", "spr_st_impact_point"),
(prop_instance_get_starting_position, pos2, ":instance_id"),
(position_get_x, ":x", pos2),
(position_get_y, ":y", pos2),
(position_get_z, ":z", pos2),
(position_rotate_x, pos2, 320), #spikes are tilted by default so we should rotate their X axis before spawn
(val_sub, ":z", 240),
(val_add, ":x", 120),
(position_set_z, pos2, ":z"),
(position_set_x, pos2, ":x"),
(set_spawn_position, pos2),
(spawn_scene_prop, "spr_st_spikes"),
(val_sub, ":x", 240),
(position_set_x, pos2, ":x"),
(set_spawn_position, pos2),
(spawn_scene_prop, "spr_st_spikes"),
(val_add, ":x", 120),
(val_add, ":y", 120),
(position_set_x, pos2, ":x"),
(position_set_y, pos2, ":y"),
(set_spawn_position, pos2),
(spawn_scene_prop, "spr_st_spikes"),
(val_sub, ":y", 240),
(position_set_y, pos2, ":y"),
(set_spawn_position, pos2),
(spawn_scene_prop, "spr_st_spikes"),
(try_end),
])
spike_trap_hide = (0, 2, 0, [(eq, "$trap_used", 1),],
[
(try_for_prop_instances, ":spike", "spr_st_spikes"),
(prop_instance_get_position, pos3, ":spike"),
(position_get_z, ":z2", pos3),
(val_sub, ":z2", 280),
(position_set_z, pos3, ":z2"),
(prop_instance_animate_to_position, ":spike", pos3, 300),
(try_end),
(assign, "$trap_used", 0),
])
spike_trap_check = (1, 0, 0, [],
[
(try_for_prop_instances, ":trigger", "spr_st_trigger"),
(scene_prop_get_slot, ":time_left", ":trigger", slot_trap_time_left),
(gt, ":time_left", 0),
(val_sub, ":time_left", 1),
(scene_prop_set_slot, ":trigger", slot_trap_time_left, ":time_left"),
(try_end),
])
Example for ai_training mission, the one that is called when entering the siege scenes via cheats
4) Now we need to make our trigger prop do its job. Put this in its square brackets:
Code:
(ti_on_scene_prop_hit,
[
(store_trigger_param_1, ":prop"),
(store_trigger_param_3, ":attacker"),
(play_sound, "snd_dummy_hit"),
(particle_system_burst, "psys_dummy_smoke", pos1, 3),
(particle_system_burst, "psys_dummy_straw", pos1, 10),
(try_begin),
(eq, "$trap_used", 0),
(scene_prop_slot_eq, ":prop", slot_trap_time_left, 0),
(try_for_prop_instances, ":spike", "spr_st_spikes"),
(prop_instance_get_position, pos3, ":spike"),
(position_get_z, ":z2", pos3),
(val_add, ":z2", 280),
(position_set_z, pos3, ":z2"),
(prop_instance_animate_to_position, ":spike", pos3, 30),
(try_end),
(play_sound, "snd_metal_hit_high_armor_high_damage"),
(try_for_prop_instances, ":instance_id", "spr_st_impact_point"),
(prop_instance_get_position, pos5, ":instance_id"),
(try_for_agents, ":agent"),
(agent_is_alive, ":agent"),
(agent_get_position, pos4, ":agent"),
(get_distance_between_positions_in_meters, ":dist", pos5, pos4),
(le, ":dist", 2.5),
(agent_deliver_damage_to_agent, ":attacker", ":agent", 300, "itm_war_spear"), #I used spear to make spikes deal piercing damage
(try_end),
(position_get_z, ":z3", pos5),
(val_sub, ":z3", 400),
(position_set_z, pos5, ":z3"),
(particle_system_burst, "psys_dummy_smoke_big", pos5, 30),
(try_end),
(assign, "$trap_used", 1),
(scene_prop_set_slot, ":prop", slot_trap_time_left, 5), #How long trap should reload. To avoid bugs, don't lower it below 5
(else_try),
(display_message, "@Trap is reloading, please wait..."),
(try_end),
]),
5) Now we are set, and ready to put the trap on our scene in-game. Open scene editor, and find our props:
This was really painful to create, but definitely worth it imo