Modding Q&A [For Quick Questions and Answers]

Users who are viewing this thread

Status
Not open for further replies.
I'm trying to add a scripted siege defence event, but I'm struggling to understand exactly how sieges are setup in the game and how the attacking and defending teams are decided. This code, for example, sets up and runs a siege, but I don't know where in mt_castle_attack_walls_ladder the game decides which parties to use as attackers and which to use as defenders.
Code:
("test_defence_battle",0,
    "The forces of the placeholders are attacking the stronghold.",
    "none",
    [],
    [
    ("test_defend",
       [],
       "Lead your soldiers in the defence.",
       [
           (assign, ":battle_scene", "scn_test_capital_walls"),
           (call_script, "script_calculate_renown_value"),
           (call_script, "script_calculate_battle_advantage"),
           (assign, ":battle_advantage", reg0),
           (val_mul, ":battle_advantage", 2),
           (val_div, ":battle_advantage", 3), #scale down the advantage a bit in sieges.
           (set_battle_advantage, ":battle_advantage"),
           (set_party_battle_mode),
           (assign, "$g_siege_battle_state", 1),
           (set_jump_mission,"mt_castle_attack_walls_ladder"),
           (assign, "$cant_talk_to_enemy", 0),
           (assign, "$g_siege_final_menu", "mnu_castle_besiege"),
            (try_begin),
             (call_script, "script_party_count_members_with_full_health","$g_encountered_party"),
             (le, reg0, 0), #(TODO : compare with num_routed_enemies)
             (assign, "$g_next_menu", "mnu_test_stronghold"),
            (else_try),
             (assign, "$g_next_menu", "mnu_test_defence_battle"),
            (try_end),             
           (assign, "$g_siege_method", 0), #reset siege timer
           (jump_to_scene,":battle_scene"),
           (jump_to_menu, "mnu_battle_debrief"),
           (change_screen_mission),
       ]),
    ]
  ),
I assumed that it had something to do with p_collective_ally and p_collective_enemy at first, but that appears to only be used for battle simulation. Where exactly are attackers and defenders decided?
 
Abot said:
Where exactly are attackers and defenders decided?
do a reverse search. Who calls this mt? And who calls that caller? And so on. Also check the basic engine scripts and how the globals are validated.

search for "mt_castle_attack_walls_ladder" on the entire modsys.

you can use a good text editor like SublimeText or Notepad++ (with explorer plugin) to make this easier.
 
kalarhan said:
Abot said:
Where exactly are attackers and defenders decided?
do a reverse search. Who calls this mt? And who calls that caller? And so on. Also check the basic engine scripts and how the globals are validated.

search for "mt_castle_attack_walls_ladder" on the entire modsys.

you can use a good text editor like SublimeText or Notepad++ (with explorer plugin) to make this easier.
Yes I've been digging around the castle_besiege game menu where mt_castle_attack_ladders appears and also looking around the mission template itself to see how it does what. I'm clearly missing something, I'm just not sure what I'm missing  :???:

Thanks for your help  :smile:
 
Hi all,

Strange bug: When I use "party_add_members" and add to my main party (p_main_party), my party icon shows the amount added + player, but the party screen does not show the added troops, nor do these troops appear in battle.

Am I using the operation wrong?


Thanks in advance.

EDIT: Nvm, found my bug  :oops:
 
Abot said:
I'm just not sure what I'm missing 

keep digging. Somewhere the menu is called. And somewhere that caller is called. And so on. Until you get to the original event.

Also examine code responsible for setup of important globals on dialogs, menus, scripts, etc (with a search for them)
 
What determines how long particle systems will stay?

I wanna make like a fireball effect but the particles just stay there leaving a line.

what determines how fast particles disappear


Code:
  psys("fireball", psf_billboard_3d|psf_global_emit_dir|psf_always_emit|psf_randomize_size|psf_randomize_rotation, "prt_mesh_fire_1",
    number=50.0, life=0.1, damping=0.2, gravity=0.03, turbulence_size=10.0, turbulence_strength=0.0,
    alpha=[(0.5, 0.8), (1.0, 0.0)],
    red=  [(0.5, 1.0), (1.0, 0.9)],
    green=[(0.5, 0.7), (1.0, 0.3)],
    blue= [(0.5, 0.2), (1.0, 0.0)],
    scale=[(0.0, 0.15), (0.4, 0.10)],
    emit_box=     (0.04, 0.04, 0.01),
    emit_velocity=(0.0, 0.0, 0.5),
    emit_direction_randomness=0.0,
    rotation_speed=200.0,
    rotation_damping=0.5),
 
I'm not sure, but probably either number, life, damping, or a combination of them

Code:
#  5) Particle Life:    Each particle lives this long (in seconds).
 
Ikaguia said:
I'm not sure, but probably either number, life, damping, or a combination of them

Code:
#  5) Particle Life:    Each particle lives this long (in seconds).


I tried that but that seems to just be how long the particle lives before dying and reappearing again.
Ill keep experimenting and see what i learn.
 
are u using particle_system_emit? it has a field for duration

Code:
particle_system_emit                        = 1968  # (particle_system_emit, <par_sys_id>, <value_num_particles>, <value_period>),
																										# Adds a particle system in some fancy way. Uses position offset and color provided to previous calls to (set_position_delta) and (set_current_color). Can only be used in item/prop triggers.
 
Ikaguia said:
are u using particle_system_emit? it has a field for duration

Code:
particle_system_emit                        = 1968  # (particle_system_emit, <par_sys_id>, <value_num_particles>, <value_period>),
                                                                              # Adds a particle system in some fancy way. Uses position offset and color provided to previous calls to (set_position_delta) and (set_current_color). Can only be used in item/prop triggers.


Yeah i so that but it doesn't have a position parameter. So i decided against using it.


On Another note. How demanding is it if i have a spell that every time its cast it has to loop through all the agents to see how close they are. This is also for multiplayer. If you have any good tips on the most efficient way of doing this, im all ears!


There is no item or scene prop attached to this spell. Just a path that the particles take and if agent is close enough to that path id like to deal damage.


My first idea was:
loop through agents and check dist between the particle path pos and the agent pos but if the spell is being used more than once id imagine this could be pretty taxing on the server and game in general.
 
kalarhan said:
Arthur_Pendragon said:
loop through all the agents

filter the loop by distance (radius)


How exactly can i run a loop through agents that are just inside a radius?
Heres my code, and it works great but spamming it has its downsides lol.
How would you optimize it.




Code:
  ("fireball_spell", [
    (store_script_param, ":agent_id", 1),
    (set_fixed_point_multiplier, 100),
    (agent_get_look_position, pos2, ":agent_id"),
    (position_move_y,pos2,200),
    #(position_set_z_to_ground_level, pos2),
    (try_for_range, ":loop", 1, 11),
      (position_move_y,pos2,100),  ## It moves forward 30 each iteration
      (try_for_agents, ":agent"),
        (agent_is_human, ":agent"),
        (agent_is_alive, ":agent"),
        (agent_get_position, pos3, ":agent"),
        (get_distance_between_positions, ":dist_between", pos2, pos3),
        (lt, ":dist_between", 100),
        (agent_set_animation, ":agent", "anim_strike_fall_back_rise"),
      (try_end),
      (particle_system_burst, "psys_greek_fire", pos2, 1000),
    (try_end),
  ]),
 
Arthur_Pendragon said:
How exactly can i run a loop through agents that are just inside a radius?

see header_operations.py for the operations documentation

Code:
try_for_agents          =   12  #(try_for_agents, <destination>, [<position_no>], [<radius_fixed_point>]),
                                # Runs a cycle, iterating all agents on the scene. Optional parameters can be used to limit it to a circle area. Avoid using pos0.

3rd parameter is the radius
 
kalarhan said:
Arthur_Pendragon said:
How exactly can i run a loop through agents that are just inside a radius?

see header_operations.py for the operations documentation

Code:
try_for_agents          =   12  #(try_for_agents, <destination>, [<position_no>], [<radius_fixed_point>]),
                                # Runs a cycle, iterating all agents on the scene. Optional parameters can be used to limit it to a circle area. Avoid using pos0.

3rd parameter is the radius
silly me was using outdated header_operations as a reference.


Code:
try_for_agents          =   12  # (try_for_agents, <destination>),
                                # Runs a cycle, iterating all agents on the scene.


Thanks kalarhan!
 
Arthur_Pendragon said:
Ikaguia said:
I'm not sure, but probably either number, life, damping, or a combination of them
Code:
#  5) Particle Life:    Each particle lives this long (in seconds).
I tried that but that seems to just be how long the particle lives before dying and reappearing again.
Ill keep experimenting and see what i learn.
The life parameter is the actual duration time of each particle, so after this time the particle disappears.
I assume you're using  particle_system_burst (_no_sync) and want to know how to define the duration time of the burst?
Well, the burst_strength parameter within the operation defines the total number of particles that will be emitted.
The num_particles parameter of the particle system defines the number of particles that will be emitted per second, the lower the value, the longer it takes to emit all particles.

Let's say you want to emit 50 paricles within 10 seconds;
burst_strength = 50
num_particles = 5
50/5 = 10 sec.

Arthur_Pendragon said:
How would you optimize it.
Code:
  ("fireball_spell", [
    (store_script_param, ":agent_id", 1),
    (set_fixed_point_multiplier, 100),
    (agent_get_look_position, pos2, ":agent_id"),
    (position_move_y,pos2,200),
    #(position_set_z_to_ground_level, pos2),
    (try_for_range, ":loop", 1, 11),
      (position_move_y,pos2,100),  ## It moves forward 30 each iteration
      (try_for_agents, ":agent"),
        (agent_is_human, ":agent"),
        (agent_is_alive, ":agent"),
        (agent_get_position, pos3, ":agent"),
        (get_distance_between_positions, ":dist_between", pos2, pos3),
        (lt, ":dist_between", 100),
        (agent_set_animation, ":agent", "anim_strike_fall_back_rise"),
      (try_end),
      (particle_system_burst, "psys_greek_fire", pos2, 1000),
    (try_end),
  ]),
Instead of using tons of agent loops to check for distances along a given axis, do a single "raycast".
Code:
  ("fireball_spell", [
    (store_script_param, ":agent_id", 1),

    (set_fixed_point_multiplier, 100),
    (agent_get_look_position, pos2, ":agent_id"),
    (position_move_y, pos2, 200),#why 200?
    (particle_system_burst, "psys_greek_fire", pos2, 100),#do a single burst only, adjust the particle system accordingly, 100 is max burst btw
    (assign, ":ray_length", 1000),#10 meters, adjust the paricle life and emit speed accordingly
    (position_move_z, pos2, -90, 1),#pre applied center of body adjustment

    (try_for_agents, ":agent", pos2, ":ray_length"),
      (agent_is_alive, ":agent"),
      (agent_is_human, ":agent"),
      (agent_get_position, pos3, ":agent"),
      (position_transform_position_to_local, pos4, pos2, pos3),
      (position_get_x, ":val", pos4),
      (is_between, ":val", -35, 36),#horizontal body size
      (position_get_y, ":val", pos4),
      (is_between, ":val", 0, ":ray_length"),#check forward only
      (position_get_z, ":val", pos4),
      (is_between, ":val", -90, 91),#vertical body size
      (agent_set_animation, ":agent", "anim_strike_fall_back_rise"),
    (try_end),
  ]),
 
you could also use the actual cast_ray operation, it will stop at the first agent/scene_prop/ground it hits, so it wont hit trought walls or other agents.

Code:
cast_ray                                     = 1900  # (cast_ray, <destination>, <hit_position_register>, <ray_position_register>, [<ray_length_fixed_point>]),
# Version 1.161+. Casts a ray starting from <ray_position_register> and stores the closest hit position into <hit_position_register> (fails if no hits). If the body hit is a scene prop, its instance id will be stored into <destination>, otherwise it will be -1. Optional <ray_length> parameter seems to have no effect.

edit:

actually, Im not sure it it hits agents, but if it does you could do a quick check to get the one that is nearest to the hit point
 
Ikaguia said:
you could also use the actual cast_ray operation, it will stop at the first agent/scene_prop/ground it hits, so it wont hit trought walls or other agents.
Code:
cast_ray                                     = 1900  # (cast_ray, <destination>, <hit_position_register>, <ray_position_register>, [<ray_length_fixed_point>]),
# Version 1.161+. Casts a ray starting from <ray_position_register> and stores the closest hit position into <hit_position_register> (fails if no hits). If the body hit is a scene prop, its instance id will be stored into <destination>, otherwise it will be -1. Optional <ray_length> parameter seems to have no effect.
edit:
actually, Im not sure it it hits agents, but if it does you could do a quick check to get the one that is nearest to the hit point
Nope, it only works for scene props- and ground collision.
 
on multiplayer, does anyone know any way to diferentiate players actually joining the server and players "joining" the server because of map changes?

this could be either from the server or the client.
 
Ikaguia said:
on multiplayer, does anyone know any way to diferentiate players actually joining the server and players "joining" the server because of map changes?

this could be either from the server or the client.
Check the mission time when a player joins.
It's already stored in slot_player_join_time in Native.
 
Status
Not open for further replies.
Back
Top Bottom