Scripting question: Missing 'item_slots'? How to get needed info?

Users who are viewing this thread

DaLiO

Recruit
(i'm rather experienced programwriter, only i never had to deal with python before)

...so i'm now rather deep into scripting M&B since i just wanted to correct some 'Native Mod Compilation' code... it then turned to some 'improvements' here and there, then - to adding WFaS firearms into Warband, some retexturing (for example i have 4 different-colored Winged Helmets) and so on...

but now i'm stuck: at first i was just wandering why NPCs prefere Barbed Arrows over Khergit ones (in Auto Loot mod) even if they are fewer in scabard and since now i also have bullets to choose from i decided to correct this. and guess what? there's no item_slot_max_ammo...  :sad:

...after some digging through modsystem source files and some testing i realized that also ranged weapon accuracy and shield hit points aren't present in any item_slot even if judging by header_items.py they should be in just different slots... but also judging by the same file horse speed is using shoot speed bits but in scrips it can be found in item_slot_head_armor...

So here's my question: how to obtain given item's max_ammo/accuracy/endurance/... numberic value from script? for now just for comparison reasons, but i'd like to be able to change it too... i have some 'enchantment mod' in mind that would allow to add skill or (if i find out how) attribute modifiers or in other ways 'enhance' certain (or any) items right from in-game  :cool:

thanks in advance for any useful advice or just for pointing me into direction to dig to...  :wink:
 
Though the module system interpreted by the game is not written in Python, the compiler from the human readable data into the numeric .txt files is; just in case you weren't clear on it. You need to set the slots manually in a script when the game is loaded, but Python can be used to avoid tediously typing it out and repetitively updating it - just make a function that loops over all items and checks the module system data you are interested in, generating item_set_slot operations if the values are valid and not 0 (default for all slots), then appending the operations to a list that is inserted as the body of a script. You might be able to include it in module_scripts.py depending on what is done, but you might have to split it into a separate file to break circular dependencies (I hardly ever use a native based module system these days, having almost entirely rewritten it for my own uses).

Another option might be to use the WSE, which adds some of that sort of operation.
 
...if i only knew where to put that item_set_slot part...

in that case i may have better luck of completely rewriting all the module system in some more familiar language, adding some gui in the way  :cool:

... on the second thouht: wouldn't i make of use of that val_shift directive? if so - it'll just take some trial&error to figure out the right bits...
 
No; to explain in more detail, what you need is something like this:
Code:
  ("initialize_item_slots",
   [
    (item_set_slot, "itm_barbed_arrows", slot_item_max_ammo, 30),
    (item_set_slot, "itm_bodkin_arrows", slot_item_max_ammo, 29),
...
    (item_set_slot, "itm_hunting_bow", slot_item_speed_rating, 100),
    (item_set_slot, "itm_short_bow", slot_item_speed_rating, 97),
...
    ]),
But as said, it would be extremely tedious and error prone. Instead, use python to generate the script for you, something like this:
Code:
# near the top of the file (not sure about circular dependencies from importing module_items, untested)
from module_items import *

def generate_initialize_item_slots():
  script_body = []
  for item_id, item in enumerate(items):
    item_type = item[3] & 0xff
    if item_type in (itp_type_arrows, itp_type_bolts, itp_type_thrown):
      script_body.append((item_set_slot, item_id, slot_item_max_ammo, get_max_ammo(item[6])))
    speed_rating = get_speed_rating(item[6])
    if speed_rating > 0:
      script_body.append((item_set_slot, item_id, slot_item_speed_rating, speed_rating))
    ...
  return script_body

# inside the scripts list
  ("initialize_item_slots", generate_initialize_item_slots()),

# added to script_game_start
  (call_script, "script_initialize_item_slots"),
Obviously you also need to define the item slots in module_constants.py to numbers which aren't already in use.
 
a little more clarification please:
[quote author=Vornne]
Code:
[...] get_max_ammo(item[6]) [...]
[/quote]
1) does it really come in module_scripts.py ? not in header?
2) where the number [6] comes from? (i'm not used to seeing so much numberic constants in code - i usually define them somewhere, giving some meaningfull names so it's easier to understand what's going on if i happen to re-work some code piece after a while...)
[quote author=Vornne]
Obviously you also need to define the item slots in module_constants.py to numbers which aren't already in use.
[/quote]
3) obviously... but can't i re-use some of first slots that are used only by itp_type_goods? (ex.: slot_item_primary_raw_material = 50)

and one more question:
(4) in item definitions there are some possible triggers at the end (like ti_on_init_item)... where do i find the complete list of those? and how to add ones myself? 'cause i just can't find 'em nowhere... :sad:
 
[list type=decimal]
[*]So the entire module system is pretty much a list of operations. What generate_initialize_item_slots does is first it generates an empty list, and then it goes through all of the items (which is, again a list of attributes and flags) and uses the header_items function declaration get_max_ammo to find the static value and appends the operation item_set_slot to script_body, and then returns that entire list of operations as script_initialize_item_slots.
[*]The [6] comes from the fact that this is the 0-indexed field of Item stats - look at the top of module_items where it tells you what each field does.
[*]You can define whatever slot values you want - after all, they are just numeric constants as array indices. Keep in mind that while it is always good practice to make sure you have unique slot values, if you're sure that no other scripts will use slot_item_primary_raw_material for your weapons then you can use the same slot constant without conflict
[*]You can find the complete list of triggers in header_triggers.py (not that obvious), but the ones usable in module_items are ti_on_init_item, ti_on_weapon_attack, and ti_on_missile_hit.
[/list]
 
1,2,3 - i was expecting something similar, thanks

4 - figured it out allready, but came across another problem:
Code:
some_test_trigger = [
  (ti_on_weapon_attack,
	[
      (store_trigger_param_1, ":shooter_agent"),
	  # in pos1 = Weapon Item Position
	  (agent_get_wielded_item, ":cur_weapon", ":shooter_agent", 0),
	  (str_store_item_name, s1, ":cur_weapon"),
	  (str_store_troop_name, s2, ":shooter_agent"),
	  (display_message, "@Shooter: {s2} uses weapon: {s1}"),
	])]
this correctly recognizes used weapon BUT!:
with new game started at first town scene 'Shooter' is Novice Fighter
in subsequent town/village scenes it's Camp Defender
in battle scenes: Huntress
(and i even didn't try out what happens with female char...)
how do i get actual trp_ID? (i need to access to some skills/attributes for calculations)
 
DaLiO said:
with new game started at first town scene 'Shooter' is Novice Fighter
in subsequent town/village scenes it's Camp Defender
in battle scenes: Huntress
That's because ":shooter_agent" is an agent id, not a troop id - use agent_get_troop_id first. But you probably want to deal with the agent rather than the troop anyway, unless the weapon will only be used by a hero troop, adjusting something outside the battle.

The difference is explained in this guide, which should be required reading for anyone new to the module system.
 
Vornne said:
That's because ":shooter_agent" is an agent id, not a troop id - use agent_get_troop_id first. But you probably want to deal with the agent rather than the troop anyway, unless the weapon will only be used by a hero troop, adjusting something outside the battle.
ok, got it, thanks

and no - i need troop - i wish to add some weapon effects depending on original troops skills, not the agent and not only the player

e.g: shoot_flame_arrow trigger/script will take in account shooter's power_draw for calculating max_distance and some fire_magic_skill for max_damage or such... just testing the potentional aviable, to figure out how deep into changing anythng i can go...  :cool:

EDIT: allready looked into that guide, prolly just overlooked the thing 'cause was seeking something else..
 
Back
Top Bottom