OSP Code QoL Dark Souls Reference Pack

Users who are viewing this thread

This thread will contain all DS references I made. If I make more in the future, they will be added here as well. As of now, we have:

A simple presentation using progress overlay as boss hp (still not perfect as it has slider and isn't full even at max value). The intention was to recreate only the visuals, not the whole boss system, so I assigned only 1 specific troop for this purpose. If you are going to create multiple bosses, you'll have to heavily modify this code (considering presentation shift when there are more than 1 boss in a fight).

This goes to module_mission_templates.py
Code:
boss_agent_set = (ti_on_agent_spawn, 0, 0,
   [
   (store_trigger_param_1, ":agent"),
   (agent_get_troop_id, ":troop", ":agent"),
   (eq, ":troop", "trp_npc12"), # list of your bosses
   ],
   [
   (store_trigger_param_1, ":agent"),
   (agent_set_max_hit_points, ":agent", 1000, 1), # their hp
   (assign, "$boss_agent", ":agent"), # if you have more than 1 boss, global variable is not the way to go, use agent slots
   (start_presentation, "prsnt_boss_hp_bar"),
   ])
 
boss_agent_death = (ti_on_agent_killed_or_wounded, 0, 0,
   [
   (store_trigger_param_1, ":agent"),
   (agent_get_troop_id, ":troop", ":agent"),
   (eq, ":troop", "trp_npc12"),
   ],
   [
   (set_fixed_point_multiplier, 100),  
   (tutorial_message_set_size, 20, 100),
   (tutorial_message_set_background, 1),
   (tutorial_message_set_position, 500, 400),
   (tutorial_message, "@                    H E I R   O F   F I R E   D E S T R O Y E D", 0xFFFAEA9D, 5), # spaces are needed to centrify the text
   (play_sound, "snd_quest_failed", sf_vol_15),  
   ])


This goes to module_presentations.py
Code:
("boss_hp_bar", prsntf_read_only, 0,[

      (ti_on_presentation_load,
      [    
      (set_fixed_point_multiplier, 100),
      (store_agent_hit_points, ":hp", "$boss_agent", 1),
      (str_store_string, s1, "@Jeremus, High Priest of Calradia"), # here you can set some fancy name for your boss
      #(str_store_agent_name, s1, "$boss_agent"), # or just take real name of the agent, if it's already fancy enough
      (create_progress_overlay, "$boss_hp_bar", 0, ":hp"),  
      (create_text_overlay, "$boss_name", s1, tf_with_outline|tf_center_justify),  
      (overlay_set_val, "$boss_hp_bar", ":hp"),
      (overlay_set_color, "$boss_name", 0xFAFAFA),
      (position_set_x, pos1, 80),
      (position_set_y, pos1, 80),      
      (overlay_set_size, "$boss_name", pos1),
      (position_set_x, pos1, 200),
      (position_set_y, pos1, 70),      
      (overlay_set_size, "$boss_hp_bar", pos1),
      (position_set_x, pos1, 50),
      (position_set_y, pos1, 10),
      (overlay_set_position, "$boss_hp_bar", pos1),
      (position_set_x, pos1, 35),
      (position_set_y, pos1, 12),
      (overlay_set_position, "$boss_name", pos1),
      (presentation_set_duration, 999999),      
      ]),
     
      (ti_on_presentation_run,
      [
      (store_agent_hit_points, ":hp", "$boss_agent", 1),
      (overlay_set_val, "$boss_hp_bar", ":hp"),
      (try_begin),
        (le, ":hp", 0),
        (presentation_set_duration, 0),
      (try_end),
      ]),    
  ]),


Final result: https://drive.google.com/file/d/1agDRq2oGRTlXz6QCIXaEkUUCCgx03qvg/view

This system allows you to make any wall illusory. When such wall gets hit, it will emit a sound and disappear, opening a passage or revealing a hidden loot. You can use illusory walls to make locations more interesting to explore. Again, this was made for recreation only, so it supports only 1 illusory wall per scene. If you introduce the whole illusory wall system, you should create more scene slots and rework the hiding code at ti_on_init_scene_prop.

This goes to module_scene_props.py
Code:
("z_illusory_wall",sokf_moveable|sokf_missiles_not_attached,"village_wall_a","bo_village_wall_a", [ # you can put your own mesh and collision but keep the flags

(ti_on_init_scene_prop, # this will remove wall when entering scene if it has been revealed previously
    [
    (store_trigger_param_1, ":instance_no"),
    (store_current_scene, ":cur_scene"),
    (scene_slot_eq, ":cur_scene", 739, 1), # some random number instead of name to avoid declaring
    (prop_instance_is_valid, ":instance_no"),
    (scene_prop_set_visibility, ":instance_no", 0),
    (prop_instance_get_position, pos1, ":instance_no"),
    (position_move_z, pos1, -3000, 1),
    (prop_instance_set_position, ":instance_no", pos1),
    (rebuild_shadow_map),
    ]),

(ti_on_scene_prop_hit, # fading out should start at the moment of hit, but player should see it fully, so we
                       # need a delay. To avoid mission triggers we just animate wall to current position with
                       # some timer and move the rest of the hiding code to ti_on_scene_prop_animation_finished
    [
    (store_trigger_param_1, ":instance_no"),
    (set_fixed_point_multiplier, 100),
    (prop_instance_get_position, pos1, ":instance_no"),
    (copy_position, pos2, pos1),
    (prop_instance_animate_to_position, ":instance_no", pos2, 100),
    (scene_prop_fade_out, ":instance_no", 100),
    (prop_instance_enable_physics, ":instance_no", 0),
    (prop_instance_play_sound, ":instance_no", "snd_quest_failed"),  
    ]),

(ti_on_scene_prop_animation_finished,
    [
    (store_trigger_param_1, ":instance_no"),
    (prop_instance_is_valid, ":instance_no"),
    (scene_prop_set_visibility, ":instance_no", 0),
    (prop_instance_get_position, pos1, ":instance_no"),
    (position_move_z, pos1, -3000, 1),
    (prop_instance_set_position, ":instance_no", pos1),
    (rebuild_shadow_map),
    (store_current_scene, ":cur_scene"),
    (neg|scene_slot_eq, ":cur_scene", 739, 1),
    (scene_set_slot, ":cur_scene", 739, 1),  
    ]),      
]),


Final result:


This will allow you to turn your character into scene object in order to blend-in with the enviroment. Code is singleplayer but it's quite useless in this mode - your collision is still human (so you can get a headshot while being a chair), enemies still see you, you need to code-in a lot of dependecies to make a use of being a prop. In multiplayer however, this will work as is, cuz you can fool human eye with transformtion alone, and ambush another players without additional coding. Just replace singleplayer get_player_agent_no operation with some multiplayer equivalent that will allow you to take a correct referrence. And maybe mask walking sounds somehow.

This goes to module_scene_props.py
Code:
# these are just duplicates of native props with removed collision. spr_tavern_barrel fits too, but it is spawned half underground so I excluded it
("cm_apple_basket", 0, "apple_basket", "0", []),
("cm_box_a", 0, "box_a", "0", []),
("cm_chair_trunk_b", 0, "chair_trunk_b", "0", []),
("cm_chair_trunk_c", 0, "chair_trunk_c", "0", []),
("cm_chest_b", 0, "chest_b", "0", []),
("cm_cupboard_a", 0, "cupboard_a", "0", []),
("cm_dummy_a", 0, "arena_archery_target_b", "0", []),
("cm_straw_c", 0, "straw_c", "0", []),
("cm_tavern_chair_b",0,"tavern_chair_b", "0", []),
("cm_torture_tool_c", 0, "torture_tool_c", "0", []),
("cm_tripod_cauldron_b", 0, "tripod_cauldron_b", "0", []),
("cm_water_well_a", 0, "water_well_a", "0", []),
("cm_wood_heap", 0, "wood_heap_a", "0", []),
("cm_prop_end", 0, "wood_heap_a", "0", []),


This goes to module_constants.py
Code:
slot_agent_is_transformed = 797
slot_agent_target_prop = 798


This goes to module_mission_templates.py
Code:
chameleon_1 = (0, 2, 0, # starting transformation
[
    (key_clicked, key_numpad_slash), # replace with any button you want
    (get_player_agent_no, ":player"),
    (neg|agent_slot_eq, ":player", slot_agent_is_transformed, 1),
    (agent_set_animation, ":player", "anim_cheer", 1), # this animation lasts around 4 sec so we
                                                       # put consequences delay on 2 for it to
                                                       # interrupt it on half
],
[
    (get_player_agent_no, ":player"),
    (agent_set_visibility, ":player", 0),
    (agent_set_slot, ":player", slot_agent_is_transformed, 1),
    (agent_get_position, pos1, ":player"),
    (particle_system_burst, "psys_ladder_dust_14m", pos1, 300),
    (play_sound_at_position, "snd_quest_failed", pos1),
    (set_spawn_position, pos1),
    (store_random_in_range, ":target_prop", "spr_cm_apple_basket", "spr_cm_prop_end"),
    (spawn_scene_prop, ":target_prop"),
    (agent_set_slot, ":player", slot_agent_target_prop, reg0),
])

chameleon_2 = (0, 0, 0, # this moves the prop to wherever we move
[
    (get_player_agent_no, ":player"),
    (agent_slot_eq, ":player", slot_agent_is_transformed, 1),
],
[
    (get_player_agent_no, ":player"),
    (agent_get_slot, ":instance_no", ":player", slot_agent_target_prop),
    (agent_get_position, pos1, ":player"),
    (position_rotate_z, pos1, 180),
    (prop_instance_set_position, ":instance_no", pos1),
])

chameleon_3 = (0, 0, 0, # ending transformation
[
    (get_player_agent_no, ":player"),
    (agent_slot_eq, ":player", slot_agent_is_transformed, 1),
    (this_or_next|game_key_clicked, gk_attack), # here are listed main actions which should turn you
    (this_or_next|game_key_clicked, gk_defend), # human again. gk_attack also triggers when you choose
    (this_or_next|game_key_clicked, gk_jump),   # a dialog answer. You may contribute to this list
    (game_key_clicked, gk_kick),  
],
[
    (get_player_agent_no, ":player"),
    (agent_set_slot, ":player", slot_agent_is_transformed, 0),
    (agent_get_slot, ":instance_no", ":player", slot_agent_target_prop),
    (prop_instance_get_position, pos1, ":instance_no"),
    (particle_system_burst, "psys_ladder_dust_14m", pos1, 300),
    (position_move_z, pos1, -3000, 1),
    (prop_instance_set_position, ":instance_no", pos1),
    (rebuild_shadow_map),
    (agent_set_visibility, ":player", 1),
    (agent_set_slot, ":player", slot_agent_target_prop, -1),
])


Final result: https://drive.google.com/file/d/1135PoK9QIlMxUTRvp6V_4JpeyrUTvBgM/view

Enjoy!
 
giphy.gif


Especially that illusory wall is extraordinary!
 
The chameleon has no effect, can you help me? Where is chameleon_ placed in MT?
(get_player_agent_no, ":player"),
(agent_set_visibility, ":player", 0),
(agent_set_slot, ":player", slot_agent_is_transformed, 1),
(agent_get_position, pos1, ":player"),
(particle_system_burst, "psys_ladder_dust_14m", pos1, 300),
(play_sound_at_position, "snd_quest_failed", pos1),
(set_spawn_position, pos1),
(store_random_in_range, ":target_prop", "spr_cm_apple_basket", "spr_cm_prop_end"),

(get_player_agent_no, ":player"), What statement should be used for multiplayer server?
 
Yes, I might be able to help you.
I need to have some free time first, I don't have too much of it these days.
Making that script working in multiplayer Is not a task you can do in 10 minutes.
I'll try doing that in following week.
 
(get_player_agent_no, ":player"),
(agent_set_visibility, ":player", 0),
(agent_set_slot, ":player", slot_agent_is_transformed, 1),
(agent_get_position, pos1, ":player"),
(particle_system_burst, "psys_ladder_dust_14m", pos1, 300),
(play_sound_at_position, "snd_quest_failed", pos1),
(set_spawn_position, pos1),
(store_random_in_range, ":target_prop", "spr_cm_apple_basket", "spr_cm_prop_end"),

(get_player_agent_no, ":player"), What statement should be used for multiplayer server?
I won't bring you script on plate, but i'l lgive you overall idea how to do that.
Please note, my code snippets are full of bugs.
I did not made everything the right way.
You also gonna have to reset agent slots once he dies or round ends.
You will have to fix bugs and improve it by yourself.
Works only on dedicated server. (intended)
Note: You have to add/uncomment agent_set_visibility operation. I don't have it in my module system.

Proof of concept video.


We will ask server to start transformation here.

Python:
chameleon_1 = (0, 0, 0, # request transformation
[

## clientside checks
    (key_clicked, key_numpad_slash),
    (multiplayer_get_my_player, ":player_no"),
       (player_get_agent_id, ":agent", ":player_no"),
      (agent_slot_eq, ":agent", slot_agent_is_transformed, 0),
    
],
[
### send event to the server
     (multiplayer_send_int_to_server, multiplayer_event_trans_request, 1),
])

We will request server to stop transformation here.

Python:
chameleon_3 = (0, 0, 0, # ending transformation
[

#### clientside checks
(neg|multiplayer_is_server),
    (multiplayer_get_my_player, ":player"),
(player_get_agent_id, ":agent", ":player"),
    (agent_slot_eq, ":agent", slot_agent_is_transformed, 1),
    (this_or_next|game_key_clicked, gk_attack), # here are listed main actions which should turn you
    (this_or_next|game_key_clicked, gk_defend), # human again. gk_attack also triggers when you choose
    (this_or_next|game_key_clicked, gk_jump),   # a dialog answer. You may contribute to this list
    (game_key_clicked, gk_kick),
],
[
### send event to the server
   (multiplayer_send_int_to_server, multiplayer_event_trans_disable_request, 1),

])



Ok, this one is weird one. Idk if it's best way to do that. Probably not.
Serverside only.
Python:
chameleon_2 = (0, 0, 0, # this moves the prop to wherever we move
[
    (multiplayer_is_dedicated_server),
  
],
[

(get_max_players, ":num_players"),
(try_for_range, ":player_no", 0, ":num_players"),
  (player_is_active, ":player_no"),
    (player_get_agent_id, ":agent_id", ":player_no"),


      (agent_is_active, ":agent_id"),
     (agent_is_alive, ":agent_id"),
    
  (agent_slot_eq, ":agent_id", slot_agent_is_transformed, 1),
    (agent_get_slot, ":instance_no", ":agent_id", slot_agent_target_prop),
    (neg|eq, ":instance_no", -1),
    (agent_get_position, pos1, ":agent_id"),
    (position_rotate_z, pos1, 180),
    (prop_instance_set_position, ":instance_no", pos1),

    (try_end),
])


My serverside events (game_receive_network_message script).
Python:
# enable transformation
(try_begin),
               (eq, ":event_type", multiplayer_event_trans_request),
               (player_get_agent_id, ":player", ":player_no"),
#   (agent_set_visibility, ":player", 0),
    (agent_set_slot, ":player", slot_agent_is_transformed, 1),
    (agent_set_animation, ":player", 442),
    (agent_get_position, pos1, ":player"),
    (particle_system_burst, "psys_ladder_dust_14m", pos1, 300),
    (play_sound_at_position, "snd_quest_failed", pos1),
    (set_spawn_position, pos1),
    (store_random_in_range, ":target_prop", "spr_cm_apple_basket", "spr_cm_prop_end"),
    (spawn_scene_prop, ":target_prop"),
    (agent_set_slot, ":player", slot_agent_target_prop, reg0),
  (multiplayer_send_int_to_player, ":player_no", multiplayer_event_trans_inform, 1), ## let's inform client about transformation state.
  
               (try_end),


# disable transformation
                (try_begin),
               (eq, ":event_type", multiplayer_event_trans_disable_request),
  (player_get_agent_id, ":agent", ":player_no"),
    (agent_set_slot, ":agent", slot_agent_is_transformed, 0),
    (agent_get_slot, ":instance_no", ":player", slot_agent_target_prop),
    (prop_instance_get_position, pos1, ":instance_no"),
    (particle_system_burst, "psys_ladder_dust_14m", pos1, 300),
    (position_move_z, pos1, -3000, 1),
    (prop_instance_set_position, ":instance_no", pos1),
  #  (agent_set_visibility, ":player", 1),
    (agent_set_slot, ":agent", slot_agent_target_prop, -1),
  (multiplayer_send_int_to_player, ":player_no", multiplayer_event_trans_inform, 0), ## let's inform client about transformation state.

               (try_end),


Clientside events. So client will know what's happening.

Code:
 (try_begin),   
          (eq, ":event_type", multiplayer_event_trans_inform),
          (store_script_param, reg50, 3),
          (multiplayer_get_my_player, ":player_noo"),
       (player_get_agent_id, ":agent", ":player_noo"),
        (agent_set_slot, ":agent", slot_agent_is_transformed, reg50),


        (else_try),


Add events to header_common

Python:
multiplayer_event_trans_request                  = 120
multiplayer_event_trans_disable_request                  = 121

multiplayer_event_trans_inform                  = 122

### USE FREE ONES. 120,121,122 might be already used in Warband!!!
 
Last edited:
Back
Top Bottom