Try_for_agents question

Users who are viewing this thread

Grendal-777

Veteran
In my Legend of the Red Axe mod currently my redaxe will only spawn once per game. I am looking for a way to make the scene prop check upon use if the redaxe exists in the scene/world and if not to spawn it.

Using try_for_agents or try_for_range I can run through the player agents and determine if it is equiped using  (agent_has_item_equipped, ":agent", ":item"),  however, if the player wanted they could simply drop the axe by the spawn and respawn another for his pal.

Does anyone know of a way to determine if the agent (itm_name) currently exists in the scene/world?
 
You could try see if (scene_spawned_item_get_num_instances, ":num", "itm_red_axe") works for what you want (and using scene_spawned_item_get_instance, if needed). I haven't used it for myself, so I don't know if it works; and it doesn't seem to be used at all in native. I'm not sure if it only checks items that have been spawned, or whether it finds items that have been picked up and dropped as well.


The suggestion by Somebody has the (dis)advantage of making sure the item is spawned only once per mission; whereas if a player died while having the axe equipped but not wielded, it would disappear, and then the check for spawned items would probably not find anything.
 
Scene props have slots too... In the conditions of your trigger, check that the slot is 0 (by default), and after the first use/spawn, set the slot to 1.
I currently keep it from being respawned by dropping the spawn prop under the ground after it spawns the axe. It makes the scene tidy and people don't keep trying to use the skeleton to get another axe.

I want to keep the prop though and simply put in a check to determine if redaxe exists in world already at time of use (not that its already spawned once or more).  The goal is simply to avoild multiple instances at once and also to allow a respawn if the axe is lost/decayed.

You could try see if (scene_spawned_item_get_num_instances, ":num", "itm_red_axe") works for what you want (and using scene_spawned_item_get_instance, if needed). I haven't used it for myself, so I don't know if it works; and it doesn't seem to be used at all in native. I'm not sure if it only checks items that have been spawned, or whether it finds items that have been picked up and dropped as well.
I hadn't seen those, I will definately be checking them out! They seem to be the closest to doing what I am after. Thanks for the info.



 
You'll probably would have seen it anyway, but I forgot to mention that there are another couple of operations listed (in header_operations) that might be what you need: scene_item_get_num_instances and scene_item_get_instance.
 
Here is what I put together so far. It looks to me with my limited M&B/pyton scripting skills like it "should" be working.
It checks to see if any active player has the axe (tested with a neg| so will pass if no one is..), it then checks if the axe is laying on the ground somewhere, it finally checks the players kill_count (set to 0 for testing).

The check for red axe on ground and kill_count work perfectly.. but when I add the check for try_for_agent check it kicks out and won't spawn the axe anymore even when none exists.
#Add Rex Axe spawn
check_redaxe_spawn = (ti_on_scene_prop_use,
    [
  (store_trigger_param_1, ":agent_id"),
      (store_trigger_param_2, ":instance_id"),
  (multiplayer_is_server),
  (assign, ":num", 0), #added to test respawn, this number is to make test pass if :num void
  (assign, ":axes", 1),
  (agent_get_player_id,":player_no",":agent_id"),
  (player_get_kill_count, ":player_kill_count",":player_no"),
  (get_max_players, ":num_players"),                             
      (try_for_range, ":player_no", 1, ":num_players"), #0 is server so starting from 1
        (player_is_active, ":player_no"),
    (neg|agent_has_item_equipped, ":player_no", "itm_red_axe"),
    (try_begin), #added to test respawn
      (scene_spawned_item_get_num_instances, ":num", "itm_red_axe"), #added to test respawn, not sure if this is returning valid number
          (lt, ":num", ":axes"), #added to test respawn 
      (try_begin),
            (ge, ":player_kill_count", 0), 
            (prop_instance_get_position, pos1, ":instance_id"),
            (position_move_z,pos1,55), #Use this to tell where item will spawn to in relation to scene prop
#          (position_rotate_x,pos1,180), #Make weapon stand on haft 
            (set_spawn_position, pos1),
        (spawn_item,"itm_red_axe"), #actual spawning of the item
    (display_message, "@You have found the Red Axe, the blood lust is upon you!"),
#         (try_begin), #Add next 5 lines back to make spawning prop disappear underground if respawn isn't working right
#       (prop_instance_get_position, pos1, ":instance_id"),
#           (position_move_z, pos2, -2200),      #move down  #disabled to test spawn limiter code
#            (prop_instance_animate_to_position, ":instance_id", 2, 500),
#          (try_end),
          (try_end),
    (try_end),
      (try_end),
    ])
#end
Anyone see any glaring problems in my code (besides indentions which get thrown off in spoiler)?
 
There are a few things that could be cleaned up...I'm not sure if this will fix your issues, but it would make things cleaner.

First, the code tries to find the axe on the ground or respawn it after each time a player doesn't have the axe equipped. Wouldn't it be easier to loop through all players to check for the axe, then ONLY if the axe isn't found, look for it on the ground or respawn it?

Also, just some optimization--some code can be moved further down so it is only called if needed.

Taking those into account, an edited version:
Code:
#Add Rex Axe spawn
check_redaxe_spawn = (ti_on_scene_prop_use,
    [
    (store_trigger_param_1, ":agent_id"),
    (store_trigger_param_2, ":instance_id"), 
    (multiplayer_is_server),
    (get_max_players, ":num_players"),    
    (assign, ":found_axe", 0), #NEW    
    (try_for_range, ":player_no", 1, ":num_players"), #0 is server so starting from 1
        (player_is_active, ":player_no"),
        (player_get_agent_id, ":other_agent_id", ":player_no"), #NEW-Vornne
        (agent_has_item_equipped, ":other_agent_id", "itm_red_axe"), #EDITED
        (assign, ":found_axe", 1), #NEW
        (assign, ":num_players", 1), #NEW - Loop Breaker
    (try_end),
    (eq, ":found_axe", 0), #NEW
    (try_begin), #added to test respawn
        (assign, ":axes", 1), #MOVED - is this needed? couldn't you just replace ":axes" with 1?
        (assign, ":num", 0), #MOVED - added to test respawn, this number is to make test pass if :num void
        (scene_spawned_item_get_num_instances, ":num", "itm_red_axe"), #added to test respawn, not sure if this is returning valid number
        (lt, ":num", ":axes"), #added to test respawn         
        (try_begin),
            (agent_get_player_id,":player_no",":agent_id"), #MOVED
            (player_get_kill_count, ":player_kill_count",":player_no"), #MOVED
            (ge, ":player_kill_count", 0), 
            (prop_instance_get_position, pos1, ":instance_id"),
            (position_move_z,pos1,55), #Use this to tell where item will spawn to in relation to scene prop
            # (position_rotate_x,pos1,180), #Make weapon stand on haft 
            (set_spawn_position, pos1),
            (spawn_item,"itm_red_axe"), #actual spawning of the item
            (display_message, "@You have found the Red Axe, the blood lust is upon you!"),
            # (try_begin), #Add next 5 lines back to make spawning prop disappear underground if respawn isn't working right
                # (prop_instance_get_position, pos1, ":instance_id"),
                # (position_move_z, pos2, -2200),      #move down  #disabled to test spawn limiter code
                #  (prop_instance_animate_to_position, ":instance_id", 2, 500),
            # (try_end),
        (try_end),
    (try_end),      
    ])
#end

On second thought...you can eliminate the try blocks
Code:
#Add Rex Axe spawn
check_redaxe_spawn = (ti_on_scene_prop_use,
    [
    (store_trigger_param_1, ":agent_id"),
    (store_trigger_param_2, ":instance_id"), 
    (multiplayer_is_server),
    (get_max_players, ":num_players"),    
    (assign, ":found_axe", 0), #NEW    
    (try_for_range, ":player_no", 1, ":num_players"), #0 is server so starting from 1
        (player_is_active, ":player_no"),
        (player_get_agent_id, ":test_agent_id", ":player_no"), #NEW - Vornne
        (agent_has_item_equipped, ":test_agent_id", "itm_red_axe"), #EDITED
        (assign, ":found_axe", 1), #NEW
        (assign, ":num_players", 1), #NEW - Loop Breaker
    (try_end),
    (eq, ":found_axe", 0), #NEW
    (assign, ":axes", 1), #MOVED - is this needed? couldn't you just replace ":axes" with 1?
    (assign, ":num", 0), #MOVED - added to test respawn, this number is to make test pass if :num void
    (scene_spawned_item_get_num_instances, ":num", "itm_red_axe"), #added to test respawn, not sure if this is returning valid number
    (lt, ":num", ":axes"), #added to test respawn         
    (agent_get_player_id,":player_no",":agent_id"), #MOVED
    (player_get_kill_count, ":player_kill_count",":player_no"), #MOVED
    (ge, ":player_kill_count", 0), 
    (prop_instance_get_position, pos1, ":instance_id"),
    (position_move_z,pos1,55), #Use this to tell where item will spawn to in relation to scene prop
    # (position_rotate_x,pos1,180), #Make weapon stand on haft 
    (set_spawn_position, pos1),
    (spawn_item,"itm_red_axe"), #actual spawning of the item
    (display_message, "@You have found the Red Axe, the blood lust is upon you!"),
    # (try_begin), #Add next 5 lines back to make spawning prop disappear underground if respawn isn't working right
        # (prop_instance_get_position, pos1, ":instance_id"),
        # (position_move_z, pos2, -2200),      #move down  #disabled to test spawn limiter code
        #  (prop_instance_animate_to_position, ":instance_id", 2, 500),
    # (try_end),
    ])
#end

Not knowing multiplayer coding, I'm not sure if you need to adjust the  (agent_has_item_equipped, ":player_no", "itm_red_axe"),  operation. As it looks to me, you are feeding an agent-based operation a player number...but perhaps player number=agent number in multiplayer. My total ignorance of the differences there shines through at times like these, but you may need a line before that in the try_for_range loop to convert the player number into an agent.

EDIT-EDIT Looks like I ninja-edited Vornne...and learned something in the process.

And on the iteration destination and triggering player Vornne, that is why I moved get player_id down to after the try_for_range loop.
 
There is one major problem I noticed from a quick glance: you are using the player id when the operation needs the agent id; these are two different things: the player object stays the same as long as they are connected, the agent is tied to the character - after they die and respawn the player has a new agent associated with it. So in the try_for_range over the players, you need to do "(player_get_agent_id, ":eek:ther_agent_id", ":player_no")," then maybe "(agent_is_alive, ":eek:ther_agent_id")," or something similar, and then the "(agent_has_item_equipped, ":eek:ther_agent_id", "itm_red_axe"),". It also might be a good idea to use a different name for the triggering player id variable and the one used when looping over all players (they both use ":player_no") for clarity, and in case you want to use the triggering player for something at the end of the script, some time later.
 
The take 2 works flawlessly thank you Caba`drin and Vornne!

One of my biggest problems is figuring out the sequence inside the code. ie, do I check if player is active before the try loop.. or am I checking all the players during the loop to assure they are active... and usually both.. Most times I can go through it slow and see the order of things but sometimes it throws me.

The ":axes" was actually put in there because I was getting an error when I just used (lt, ":num", 1),. I changed it to ":axe" and assigned it 1 and it worked.. that didn't help my confusion.. 

New question, same topic:I am having another try_for problem with my loot code. It works fine but it causes a lag spike each time it runs which makes for a bad rubberband affect. I am sure this code is as "dirty" as the last. Any help making it more efficient would be greatly appreciated as well. 

It has to check which faction and only give gold to the team on the faction designated in the prop.
My code:
#Middle end pillage prop faction 1
check_pillage_poor1 = (ti_on_scene_prop_use,
    [
      (store_trigger_param_1, ":agent_id"),
      (multiplayer_is_server),
      (assign, ":profit", 3000),
      (agent_get_player_id,":player_no",":agent_id"),
      (player_is_active, ":player_no"),
  (player_get_team_no,  ":myteam", ":player_no"),
      (team_get_faction, ":faction_no", ":myteam" ),
      (get_max_players, ":num_players"),
      (try_begin),
#     (player_get_team_no, ":team", ":player_no"),
    (eq, ":faction_no", "fac_kingdom_1"),
(try_for_range,":player_no",1,":num_players"), #0 is server so starting at 1
          (player_get_team_no, ":team", ":player_no"),
  (eq, ":team", ":myteam"),
      (try_begin),
        (player_get_gold, ":player_gold", ":player_no"),
            (val_add, ":player_gold", ":profit"), #Use val_sub to subtract and val_add to add,
            (player_set_gold, ":player_no", ":player_gold", multi_max_gold_that_can_be_stored),
        (display_message, "@You and your teammates pillage 3000 gold each!"),
          (try_end),
    (try_end),
      (try_end),
  ])

 
In the loop over all player ids you don't check if they are active, so the server console is probably flooded with error messages, which might be your problem. Using display_message on a dedicated server will only print to the server console, which is probably not what you want; to print on the clients you need to send a network message. You also have some unecessary extra operations in there, are overwriting the original ":player_no" variable for the loop, and the formatting is atrocious, sorry :smile:. It's much harder to read and understand code if you don't indent things consistently. Here is an example of how it might look, cleaned up - you don't have to follow my formatting exactly, but it would fit in with the rest of the code if you did; at least make sure each try block is at the same indentation level:
check_pillage_poor1 = (ti_on_scene_prop_use,
[(store_trigger_param_1, ":agent_id"),
  (agent_get_player_id, ":player_no", ":agent_id"),
  (player_is_active, ":player_no"),
  (player_get_team_no,  ":my_team", ":player_no"),
  (team_get_faction, ":faction_no", ":my_team"),
  (eq, ":faction_no", "fac_kingdom_1"),
  (get_max_players, ":num_players"),
  (try_for_range, ":eek:ther_player_no", 1, ":num_players"), #0 is server so starting at 1
    (player_is_active, ":eek:ther_player_no"),
    (player_get_team_no, ":eek:ther_team", ":eek:ther_player_no"),
    (eq, ":eek:ther_team", ":my_team"),
    (player_get_gold, ":player_gold", ":eek:ther_player_no"),
    (val_add, ":player_gold", 3000),
    (player_set_gold, ":player_no", ":player_gold", multi_max_gold_that_can_be_stored),
  (try_end),
  ])
If this code still makes the server "lag", I'm not sure what the problem is, as similar things haven't for me.
 
I rewrote it last night after Dundin's post and think I made it more efficient. I didn't catch where I wasn't checking active or overwriting my player_no though. Thanks for the help and criticism it is much appreciated and deserved. :smile:
I will compare it to your clean efficient version and maybe kill my lag spike!
With as many complaints about formatting I see, maybe a tutorial on it would help those of us who are spacially challenged.

I copy what I see in native code.. and it seems to use the following format..

start
params
code
code
try_stuff
  code
  code
  try_more_stuff 
      code
      code
  try_end
try_end       
 
spoilrs whack it all up, but I indent after each try and then line up my try_ends decrementally back to left.
 
Here are my final versions for the redaxe spawn and pillage props.
Thank you Vornne and Caba'drin!!!

]
Code:
#Add Rex Axe spawn
check_redaxe_spawn = (ti_on_scene_prop_use,  
  [   
  (store_trigger_param_1, ":agent_id"),    
  (store_trigger_param_2, ":instance_id"), 
    (try_begin),
     (multiplayer_is_server),
     (get_max_players, ":num_players"),  
     (assign, ":found_axe", 0), #NEW      
     (try_for_range, ":player_no", 1, ":num_players"), #0 is server so starting from 1   
       (player_is_active, ":player_no"),    
       (player_get_agent_id, ":test_agent_id", ":player_no"), #NEW - Vornne    
       (agent_has_item_equipped, ":test_agent_id", "itm_red_axe"), #EDITED   
       (assign, ":found_axe", 1), #NEW  
       (assign, ":num_players", 1), #NEW - Loop Breaker  
       (try_end),    
         (eq, ":found_axe", 0), #NEW 
         (assign, ":axes", 1), #MOVED - is this needed? couldn't you just replace ":axes" with 1?  
         (assign, ":num", 0), #MOVED - added to test respawn, this number is to make test pass if :num void  
         (scene_spawned_item_get_num_instances, ":num", "itm_red_axe"), #added to test respawn, not sure if this is returning valid number  
         (lt, ":num", ":axes"), #added to test respawn  
         (agent_get_player_id,":player_no",":agent_id"), #MOVED  
         (player_get_kill_count, ":player_kill_count",":player_no"), #MOVED
         (ge, ":player_kill_count", 7),  
         (prop_instance_get_position, pos1, ":instance_id"),
         (position_move_z,pos1,55), #Use this to tell where item will spawn to in relation to scene prop
       # (position_rotate_x,pos1,180), #Make weapon stand on haft  
         (set_spawn_position, pos1),   
         (spawn_item,"itm_red_axe"), #actual spawning of the item  
         (try_end),
         (try_begin),
	       (get_max_players, ":num_players"),                               
           (try_for_range, ":player_no", 1, ":num_players"), #0 is server so starting from 1
             (player_is_active, ":player_no"),
             (multiplayer_send_int_to_player, ":player_no", multiplayer_event_send_redaxe_message_to_everyone , ":agent_id"),
           (try_end),
         (try_end),    
   ])
Code:
#High end pillage prop faction 2
check_pillage_rich2 = (ti_on_scene_prop_use,
    [

      (store_trigger_param_1, ":agent_id"),
            
      (try_begin), 
	    (multiplayer_is_server),
        (assign, ":profit", 10000), #:profit to gain, :cost to loose, edit amount of cost or profit
        (agent_get_player_id,":player_no",":agent_id"),
        (player_is_active, ":player_no"), 
        (player_get_team_no,  ":my_team", ":player_no"),
        (team_get_faction, ":faction_no", ":my_team" ),
        (eq, ":faction_no", "fac_kingdom_2"),
        (get_max_players, ":num_players"),
        (try_for_range,":other_player_no",1,":num_players"), #0 for local testing, 1 when porting to dedicated server
          (player_is_active, ":other_player_no"),  
     	  (player_get_team_no, ":their_team", ":other_player_no"),
          (eq, ":their_team", ":my_team"),
          (player_get_gold, ":player_gold", ":other_player_no"),
          (val_add, ":player_gold", ":profit"), #Use val_sub to subtract and val_add to add, :profit to gain, :cost to loose
          (player_set_gold, ":other_player_no", ":player_gold", multi_max_gold_that_can_be_stored),
        (try_end),
        (try_begin),
          (get_max_players, ":num_players"),                               
          (try_for_range, ":player_no", 1, ":num_players"), #0 is server so starting from 1
            (player_is_active, ":player_no"),
            (multiplayer_send_int_to_player, ":player_no", multiplayer_event_send_pillage_message_to_everyone , ":agent_id"),
          (try_end),
        (try_end),
    ])
 
Back
Top Bottom