Modding Q&A [For Quick Questions and Answers]

Users who are viewing this thread

Status
Not open for further replies.
Caba`drin said:
It's a presentation. See how the Native presentations are set up, or look at other presentations from mods that you enjoy...and make a presentation.

Presentations, the supporting scripts, etc, can be some of the most complex systems to create, however, getting things to display correctly and then accept and record input from the player.

The adventure begins! When/if I figure it out I'll make a tutorial for other modders :grin:
 
Hi there, I was wondering how you would prevent the Npc's in your party's gear from being replaced,
when you create your own faction and give them a fief.

I'm wanting to know how to do this via editing the .txt files, not the Module system. I'm assuming it would be "Scripts.txt"
 
TheLordAidan said:
MadVader said:
TheLordAidan said:
I'm trying to make it so certain factions won't declare war on each other. Does anyone know if this is possible, and if so, where is the script that governs it?
In the script "randomly_start_war_peace_new", insert some lines like this (the example is about Swadia and Vaegirs):

    (try_for_range, ":cur_kingdom", "fac_kingdom_1", kingdoms_end),
        (faction_slot_eq, ":cur_kingdom", slot_faction_state, sfs_active),
 
(try_for_range, ":cur_kingdom_2", kingdoms_begin, kingdoms_end),
(neq, ":cur_kingdom", ":cur_kingdom_2"),
(assign, ":dont_start_wars", 0),
(try_begin),
  (eq, ":cur_kingdom", "fac_kingdom_1"),
  (eq, ":cur_kingdom_2", "fac_kingdom_2"),
  (assign, ":dont_start_wars", 1),
(else_try),
  (eq, ":cur_kingdom", "fac_kingdom_2"),
  (eq, ":cur_kingdom_2", "fac_kingdom_1"),
  (assign, ":dont_start_wars", 1),
(try_end),
(eq, ":dont_start_wars", 0),

(faction_slot_eq, ":cur_kingdom_2", slot_faction_state, sfs_active),

Hey, MadVader, on the module build I get "Error: Usage of Unassigned Local Variable: cur_kingdom_2. I also get some errors in game, which I'm guessing is when one of the factions in the script tries to declare war on the other.
MadVader wasn't suggesting you copy paste the exact code he showed, just that something similar to it would be appropriate. That said, I don't see any unassigned uses of ":cur_kingdom_2" there--you'll note that they all come after it was used as a destination for the try_for_range loop. You sure that's where the error came from?

TheLordAidan said:
Edit: New problem! I was editing multiplayer troops, and giving them some custom items. However, the build module said none of the custom item_[item]s existed. Is this because it was done in items.txt instead of module_items?
Absolutely. If you are editing the module system, everything must be done in the module system.

Jamould said:
Hi there, I was wondering how you would prevent the Npc's in your party's gear from being replaced,
when you create your own faction and give them a fief.

I'm wanting to know how to do this via editing the .txt files, not the Module system. I'm assuming it would be "Scripts.txt"
It's conversation.txt; I don't know the changes off hand, but they are in the "member_fief_grant_3" and would involved deleting each operation set of digits that begins with troop_add_item (or, in .txt form, 1530 ). There should be 8 1530 .....s that need to be deleted. Then you should decrease the number at the start of "member_fief_grant_3" that says how many commands there are by 8.
 
MadocComadrin said:
What are you aiming for? That looks like generation-appropriate glass.

Look at the inside, it's not displaying what is exactly inside as the counters and such. Top left corner, see anything wrong.

 
Somebody said:
RobSmith176 said:
Next I attempted to make that very basic menu, with only the option to go back to the camp menu:
The menu itself has a code execution block, followed by the list of menu options. Insert an extra [], after "none",

Wow that was... very simple.  Yes, that took care of the problem.  Thank you for helping with that.  It dawns on me, though, that to do what I plan to do is going to take a lot more than I hoped it would so I'll either come back for more help or just hope someone with more time and patience than I have will elect to do it.
 
Code:
bloody_screen = (
0, 0, 0, [],
  [  (multiplayer_get_my_player, ":myplayer"),
     (player_get_agent_id, ":myagent", ":myplayer"),

      (store_agent_hit_points, ":myhp", ":myagent"),

     (try_begin),
      (le, ":myhp", 30),
       (start_presentation, "prsnt_bloodhigh"),
      (else_try),
      (le, ":myhp", 20),
       (start_presentation, "prsnt_bloodmed"),
      (else_try),
      (le, ":myhp", 10),
       (start_presentation, "prsnt_bloodlow"),
      (try_end),

Is "multiplayer_get_my_player" deprecated or does it only work for online servers?
 
Caba`drin said:
It works in multiplayer mode, client side.
For SP, use get_player_agent_no

Alright. Thanks. There is also this,

Code:
poison_weaponry = (
ti_on_agent_hit, 0, 0, [],
  [  (store_trigger_param_1, ":receiver15"),
     (store_trigger_param_2, ":dealer15"),
     #(store_trigger_param_3, ":damage15"),

    (assign, ":receiver15", "$receiver17"),
    (assign, ":dealer15", "$dealer17"),

    (agent_get_wielded_item, ":poison", "$dealer17", 1),
     (eq, ":poison", "itm_poison_dagger"),

     (agent_is_alive, "$receiver17"),    
   
    #(store_agent_hit_points, "$receiverhp", "$receiver17"),
     (agent_set_slot, "$receiver17", slot_agent_poisoned,1),
    
         
    ])


poison_weaponry_0 = (
3, 0, 0, [
     (agent_is_alive, "$receiver17"),    
     (agent_slot_eq, "$receiver17", slot_agent_poisoned,1),
     ],
  [ 
    (store_random_in_range, ":poisondmg", 1, 5),
     (agent_deliver_damage_to_agent, "$dealer17", "$receiver17", ":poisondmg"),
         
    ])

These two trigger gives me a classic "unassigned local/global variable" errors, I know this is a bit buggy system-wise, so it should be working, I presume? Even though what MS says while compiling.
 
I don't see either global variable initialized...or even assigned...in those two triggers. Are they given values elsewhere?
Similarly, why store the trigger params in local variables if you're just going to overwrite them with the values from global variables anyway?
 
Caba`drin said:
I don't see either global variable initialized...or even assigned...in those two triggers. Are they given values elsewhere?
Similarly, why store the trigger params in local variables if you're just going to overwrite them with the values from global variables anyway?

So,

-Can I store the trigger params into Global variables directly without needing to assign?
-Do the same local vars get applied in two seperate triggers?
 
Belendor said:
-Can I store the trigger params into Global variables directly without needing to assign?
Yes, of course. (if that was your intent above, note that your assigns are backwards)
Belendor said:
-Do the same local vars get applied in two seperate triggers?
No. Local variables are only persistent in a single code block [  ]
(so not even between the conditions and consequences block of a single trigger, let alone multiple triggers)
 
Just askin', should this do the trick for poisoning the hit-agent and delivering it a range of damage between 1 to 5 every 3 seconds after he is hit?
Code:
poison_weaponry = (
ti_on_agent_hit, 0, 0, [],
  [  (store_trigger_param_1, "$receiver15"),
     (store_trigger_param_2, "$dealer15"),
     #(store_trigger_param_3, "$damage15"),

    (agent_get_wielded_item, ":poison", "$dealer17", 1),
     (eq, ":poison", "itm_poison_dagger"),

     (agent_is_alive, "$receiver17"),    
   
    #(store_agent_hit_points, "$receiverhp", "$receiver17"),
     (agent_set_slot, "$receiver17", slot_agent_poisoned,1),
    
         
    ])


poison_weaponry_0 = (
3, 0, 0, [
     (agent_is_alive, "$receiver17"),    
     (agent_slot_eq, "$receiver17", slot_agent_poisoned,1),
     ],
  [ 
    (store_random_in_range, ":poisondmg", 1, 5),
     (agent_deliver_damage_to_agent, "$dealer17", "$receiver17", ":poisondmg"),
         
    ])
 
I'm guessing you want receiver/damager15 to be receiver/damager17, as you use both but it looks like there should only be one.

Two major problems:
-the receiver/damager globals will be reset every time any agent is hit (so you won't be consistently checking the same agent every 3 seconds)
-even if not the above, it would only allow one agent to be damaged by poison at any one time

There's really no need for global variables at all, if you're using a slot to track the agent being poisoned anyway--just use an agent loop--and if you want to credit the damager agent with the damage, add a second slot to track that

Also
(store_random_in_range, ":poisondmg", 1, 5),
will store a value 1, 2, 3, or 4. Lower inclusive, higher exclusive, like the other range-based operations.
 
Ah, no. Doesn't matter if it is "17" or "15", it was saying something about "same name used for both local and global."

So, is it wrong that i use "ti_on_agent_hit"?
 
Belendor said:
Ah, no. Doesn't matter if it is "17" or "15", it was saying something about "same name used for both local and global."
Well, it does matter that they are both the same, though, cause in the code above they are two different variables.

Belendor said:
So, is it wrong that i use "ti_on_agent_hit"?
No, you'll need to use on_agent_hit, or you won't know that the agent was hit...

What I mean by this
Caba`drin said:
There's really no need for global variables at all, if you're using a slot to track the agent being poisoned anyway--just use an agent loop--and if you want to credit the damager agent with the damage, add a second slot to track that
is as follows:
Code:
poison_weaponry = (
ti_on_agent_hit, 0, 0, [(eq, reg0, "itm_poison_dagger")], #note that the item used to hit is stored in reg0 for this trigger, as listed in header_triggers         
  [  
     (store_trigger_param_1, ":receiver"),
     (store_trigger_param_2, ":dealer"),    
   
     (agent_set_slot, ":receiver", slot_agent_poisoned, 1),
     (agent_set_slot, ":receiver", slot_agent_poisoner, ":dealer"),          
  ])

poison_weaponry_0 = (
3, 0, 0, [], 
  [
    (try_for_agents, ":agent"),
        (agent_is_alive, ":agent"),
        (agent_slot_eq, ":agent", slot_agent_poisoned, 1),
        (agent_get_slot, ":dealer", ":agent", slot_agent_poisoner),
	(store_random_in_range, ":poisondmg", 1, 6),
        (agent_deliver_damage_to_agent, ":dealer", ":agent", ":poisondmg"),
    (try_end),  
  ])

You could, of course, simply store the dealer agent ID in the "poisoned" slot, so you only need one slot instead of two, but then, in case there is a valid agent #0, you'd need to initialize the "poisoned" slot to -1 in a ti_on_agent_spawn trigger.
 
I want to emphasize on something that Caba mentioned:
Caba`drin said:
if that was your intent above, note that your assigns are backwards
The
Code:
    (assign, ":receiver15", "$receiver17"),
    (assign, ":dealer15", "$dealer17"),
means that you assign a value from the global vars (which actually aren't assigned yet) to the locals;
Code:
(assign, <destination>, <value>),
This can be confusing, so you have to be sure where which variable is - on hte left, or on the right. As a general rule, most operations in the ModSys are left-hand-side, which means that the destination stays on the left.
Of course, using slots as outlined above will be a better choice. :smile:
 
That is awesome. Thanks for that.

Only this part, I didn't understand perfectly.
Code:
in case there is a valid agent #0, you'd need to initialize the "poisoned" slot to -1 in a ti_on_agent_spawn trigger.

You mean an alive agent?
 
Not exactly. You can have dead agents that are still valid. That's how you get things such as dead agent positions.

He means something like this:

Code:
poison_weaponry = (
ti_on_agent_hit, 0, 0, [(eq, reg0, "itm_poison_dagger")], #note that the item used to hit is stored in reg0 for this trigger, as listed in header_triggers         
  [  
     (store_trigger_param_1, ":receiver"),
     (store_trigger_param_2, ":dealer"),    
   
     (agent_set_slot, ":receiver", slot_agent_poisoner, ":dealer"),          
  ])

poison_weaponry_0 = (
3, 0, 0, [], 
  [
    (try_for_agents, ":agent"),
        (agent_is_alive, ":agent"),
        (agent_slot_ge, ":agent", slot_agent_poisoner, 0), #if poisoner is valid agent (agent ID > -1)
        (agent_get_slot, ":dealer", ":agent", slot_agent_poisoner),
	(store_random_in_range, ":poisondmg", 1, 6),
        (agent_deliver_damage_to_agent, ":dealer", ":agent", ":poisondmg"),
    (try_end),  
  ])

poison_weaponry_1 = (
ti_on_agent_spawn, 0, 0, [],
  [
    (store_trigger_param_1, ":agent"),
    (agent_set_slot, ":agent", slot_agent_poisoner, -1), #initialise as invalid agent, because slots are 0 by default (0 could be a valid agent ID)
  ])
 
Discoverable parties

Dawiduh said:
dunde said:
Slots do nothing. You should set the party flag.
Code:
(0,
 [(map_free),
  (try_for_range,":cur_icon","p_sietch_village_tabr_1","p_salt_mine"), #go through my own villages I have added after the Native ones
        (store_distance_to_party_from_party,":cur_dist","p_main_party",":cur_icon"), #get the distance between the player party and the village
        (lt,":cur_dist",50), #I guess this must be an if condition, so if current distance is smaller then the minimum distance it  runs next line
        (party_set_flags,":cur_icon",pf_always_visible,1), #this should put the pf_always_visible flag in my previously undiscovered village making it visible for all eternity
  (try_end),]),

Thanks, I'll try it out today after work.

Belendor said:
Why aren't you checking out the source of Rigale, the mod? Where the codes of "Fog of War" lies...

Ikaguia said:
or floris mod pack
I think it's the same code, so nevermind

Thanks guys, I'll look for those mods. Maybe they'll have more goodies I could use.

Lumos said:
Dawiduh said:
In order to do that I need to compare distances, and the only distance-comparing piece of code I know is the one in module_scripts assigning villages to the nearest town.
This gets called only once at game_start, so you're better off using something else. You could use it for the things I say below, but why stick it into some random code blck when you can put it at the start of game_start? :smile:
Just remove the pf_always_visible from your party's flags at game_start, or from its party definition. I'd use game_start though.
That way you will be able to automatically "discover" the party when you get near it, and dunde's code will make it stay visible.
Of course, in order for his code to work properly, set the party to pf_disabled too at game_start.

The code itself works perfectly. I just had to add another loop for the towns.
A distance of 50 was huge so I cut it down to 5 which is still a bit big. I will try a 2.5. I don't want sietches to be too easy to spot  :mrgreen:

@Lumos I don't want to use pf_disabled on those settlements because if I do that it would mean they're totally inactive. I just want them to be hidden until discovered but still work.

So if anyone wants to use this code here it is for both villages and towns (you can add another loop for the castles if you need that also). I placed it in module_simple_triggers.py as the first function, just before this one:
(1,
  [
      (try_begin),
        (eq, "$training_ground_position_changed", 0),
        (assign, "$training_ground_position_changed", 1),
(set_fixed_point_multiplier, 100),
        (position_set_x, pos0, 7050),
        (position_set_y, pos0, 7200),
        (party_set_position, "p_training_ground_3", pos0),
      (try_end),
 
      (gt,"$auto_besiege_town",0),
      (gt,"$g_player_besiege_town", 0),
      (ge, "$g_siege_method", 1),
      (store_current_hours, ":cur_hours"),
      (eq, "$g_siege_force_wait", 0),
      (ge, ":cur_hours", "$g_siege_method_finish_hours"),
      (neg|is_currently_night),
      (rest_for_hours, 0, 0, 0), #stop resting
    ]),

The code is this:
Code:
#DUNE discoverable
(0,
 [(map_free),
  (try_for_range,":cur_icon","p_sietch_village_tabr_1","p_salt_mine"), #go through the villages I want to have hidden
        (store_distance_to_party_from_party,":cur_dist","p_main_party",":cur_icon"), #get the distance between the player party and the village
        (lt,":cur_dist",5), # if current distance is smaller then the minimum distance it  runs next line
        (party_set_flags,":cur_icon",pf_always_visible,1), #this should put the pf_always_visible flag in my previously undiscovered village
  (try_end),

  (try_for_range,":cur_icon","p_sietch_tabr","p_sietch_gara_kulon"), #go through my own towns I want to have hidden
        (store_distance_to_party_from_party,":cur_dist","p_main_party",":cur_icon"), #get the distance between the player party and the town
        (lt,":cur_dist",5), #if current distance is smaller then the minimum distance it  runs next line
        (party_set_flags,":cur_icon",pf_always_visible,1), #this should put the pf_always_visible flag in my previously undiscovered town
  (try_end),
  ]),
#DUNE discoverable end

I am thinking this could be modified to hide a faction from another one. Making them discoverable to one another. In that case there would need to be another loop that goes through all the parties of a faction and the said loop should contain these 2 (or 3 with the castles) loops inside. This would mean the future Harkonnen or Atreides faction won't be able to see the fremen sietches. Which makes sense in the game.
Also once I will be able to add an orni mount (for faster transport and flying over the unwalkable terrain) the view radius would increase. Should be able to spot the sietches easier from the air.

So, a big thanks to Dunde,Lumos,Belendor and Ikaguia for their help  :wink:
 
Status
Not open for further replies.
Back
Top Bottom