Mod info: Operations

Users who are viewing this thread

Effidian

Recruit
Operations are used in various files, conversation.txt, triggers.txt, etc. Operations are always 3 numbers, the operation id, the first argument and the second argument. The following table lists all current operations. The first number is the operation id, this is followed by a C like function which attempts to show how the operation works. The first argument is identified as 'X' and the second as 'Y'. If X or Y are not listed, they are not used. Following the function definition there may be a comment (//) that identifies what the arguments are.

Operations below 10000 are conditional arguments. They can be negated by setting the high bit. For example: since 10 is 'if(X >= Y)', then -2147483638 is 'if(!(X >= Y))'. -2147483638 is 0x8000000A, which has the high bit set (0x80000000) and has the operation of 10 (A). In the table below negation is identified using [NOT], meaning the operation can be optionally negated.

Stringing conditional operations together result in an AND meaning that if either one returns a false condition the condition will end. However, you may us OR as well. By setting bit 0x40000000 on the operation, it can be OR'd together with the next operation. (I have not verified this)

There are two ways memory is used within these operations, registers and cookies. Registers are temporary storage that can be used while in a single operation sequence, but no guarantee is made to what is in them when you enter a sequence. Cookies are permanent storage that are saved with the save game files. Registers are the index within the register list at 0x1000000. So reg[0] = 0x1000000 or 16777216. reg[4] = 0x1000004 or 16777220. Cookies are similar, but are the index within the cookie list at 0x2000000.

If the comment section defines X as a "reg", that means that if you use '0' it would be the equivalent of using 166777216 (or reg[0]). The same thing applies if "cookie" is used. String registers "sreg" are the equivalent of registers, but they hold pointers to strings. Other argument types are as follows:

(All are indexes in the related file unless otherwise noted.)
troop_id = troops.txt
item_id = items.txt
town_id = towns.txt
party_id = parties.txt
party_template_id = party_templates.txt
skill_id = skills.txt
faction_id = factions.txt
quest_id = quests.txt
site_id = sites.txt
mission_template_id = mission_templates.txt
location_id = this is a combination of an index in sites.txt and an entry no

Code:
    1: if([NOT] X != 0) [OR]                            
    2: if([NOT] X == 0) [OR]                            
    9: if([NOT] map_free()) [OR]                        
   10: if([NOT] X >= Y) [OR]                            
   11: if([NOT] X == Y) [OR]                            
   12: if([NOT] entering_town(X) [OR]                   //X = town_id
   20: if([NOT] num_free_stacks_ge(X, Y)) [OR]          
   21: if([NOT] num_free_prisoner_stacks_ge(X, Y)) [OR] 
   22: if([NOT] player_gold_ge() >= X) [OR]             
   24: if([NOT] in_meta_mission()) [OR]                 
   25: if([NOT] partner_is_hero()) [OR]                 
   26: if([NOT] partner_is_mercmaster()) [OR]           
   28: if([NOT] partner_is_merchant()) [OR]             
   29: if([NOT] partner_is_slavemaster()) [OR]          
   32: if([NOT] partner_introduced()) [OR]              
   90: if([NOT] player_is_female()) [OR]                
  100: if([NOT] party_encounter()) [OR]                 
  101: if([NOT] hero_can_join()) [OR]                   
  102: if([NOT] hero_can_join_as_prisoner()) [OR]       
  103: if([NOT] party_can_join()) [OR]                  
  104: if([NOT] party_can_join_as_prisoner()) [OR]      
  110: if([NOT] main_party_has_troop(X)) [OR]           //X = troop_id
  111: if([NOT] troop_is_in_party(X, Y)) [OR]           
  130: if([NOT] party_is_in_town(X, Y)) [OR]            //X = party_id, Y = town_id
  131: if([NOT] party_is_in_any_town(X)) [OR]           //X = party_id
  132: if([NOT] party_is_active(X)) [OR]                //X = party_id
  150: if([NOT] player_has_item(X)) [OR]                //X = item_id
  200: if([NOT] check_quest_active(X)) [OR]             //X = quest_id
  201: if([NOT] check_quest_finished(X, Y)) [OR]        
 1003: if([NOT] all_enemies_defeated(X, Y)) [OR]        
 1004: if([NOT] race_completed_by_player(X, Y)) [OR]    
 1005: if([NOT] num_active_teams_le() <= X)) [OR]       
 1006: if([NOT] main_hero_fallen()) [OR]                //X = party_id
 1500: if([NOT] check_mission_cookie(X, Y)) [OR]        
 1501: if([NOT] X >= Y) [OR]                            //X = cookie
 1502: if([NOT] X == Y) [OR]                            //X = cookie
10019: set_partner_introduced(X, Y)                     
10025: start_map_conversation(X)                        //X = troop_id
10030: rest_for_hours(X)                                //X = number of hours
10060: add_gold_to_troop(X, Y)                          //X = denar amount, Y = [troop_id]
10061: deduce_gold_from_troop(X, Y)                     //X = denar amount, Y = [troop_id]
10062: add_xp_to_troop(X, Y)                            //X = xp amount, Y = [troop_id]
10063: add_gold_as_xp(X, Y)                             
10064: add_xp_as_reward(X)                              //X = xp amount
10070: add_gold_to_party(X, Y)                          //X = denar amount, Y = party_id
10090: learn_skill(X)                                   //X = skill_id
10100: spawn_around_party(X, Y)                         //X = party_id, Y = party_template_id
10101: spawn_from_town(X, Y)                            //X = town_id, Y = party_template_id
10102: spawn_around_town(X, Y)                          //X = town_id, Y = party_template_id
10103: set_spawn_radius(X)                              
10105: unhide_town(X)                                   //X = town_id
10106: hide_town(X)                                     //X = town_id
10110: display_message(X)                               
10190: add_item_to_player(X)                            //X = item_id
10191: equip_item(X, Y)                                 //X = equipment_no, Y = item_id
10192: add_item_to_troop(X, Y)                          //X = item_id, Y = troop_id
10193: remove_item_from_troop(X, Y)                     //X = item_id, Y = troop_id
10194: add_items_to_player(X, Y)                        //X = item_id, Y = number
10195: reg[0] = remove_items_from_player(X, Y)          //X = item_id, Y = number
10201: party_join()                                     
10202: party_join_as_prisoner()                         
10203: troop_join(X)                                    //X = troop_id
10204: troop_join_as_prisoner(X)                        //X = troop_id
10210: remove_member_from_party(X, Y)                   //X = troop_id, Y = [party_id]
10211: remove_regular_prisoners(X, Y)                   
10215: remove_troops_from_companions(X, Y)              //X = troop_id, Y = number
10216: remove_troops_from_prisoners(X, Y)               //X = troop_id, Y = number
10220: move_member_to_speaker_party(X, Y)               
10225: heal_party()                                     
10230: disable_party(X)                                 //X = party_id
10231: enable_party(X)                                  //X = party_id
10232: remove_party(X)                                  //X = party_id
10233: add_companion_party(X)                           //X = party_id
10240: set_party_ai_behavior(X, Y)                      //X = party_id, Y = ai_goal
10241: set_party_ai_object(X, Y)                        //X = party_id, Y = ai_object
10245: set_party_faction(X, Y)                          //X = party_id, Y = faction_id
10250: add_troop_to_site(X, Y)                          //X = troop_id, Y = location_id
10251: remove_troop_from_site(X)                        //X = troop_id
10261: modify_residents_at_site(X)                      //X = site_id
10262: reset_residents()                                
10263: set_resident(X, Y)                               //X = entry_no, Y = troop_id
10270: reg[0] = set_relation_to_reg0(X)                 //X = faction_id
10280: start_quest(X)                                   //X = quest_id
10281: complete_quest(X)                                //X = quest_id
10282: succeed_quest(X)                                 //X = quest_id
10283: fail_quest(X)                                    //X = quest_id
10284: cancel_quest(X)                                  //X = quest_id
10285: set_quest_progression(X, Y)                      //X = quest_id, Y = number
10301: meta_mission_leave(X, Y)                         
10302: meta_mission_attack{0}()(X, Y)                   
10312: screen_change_trade()                            
10313: screen_change_exchange_members()                 
10314: screen_change_trade_prisoners()                  
10315: screen_change_buy_mercenaries()                  
10316: screen_change_view_character()                   
10317: screen_change_training()                         
10401: set_quest_string1(X, Y)                          //X = quest_id, Y = sreg
10402: set_quest_string2(X, Y)                          //X = quest_id, Y = sreg
10403: set_quest_string3(X, Y)                          //X = quest_id, Y = sreg
10404: set_quest_string4(X, Y)                          //X = quest_id, Y = sreg
10410: set_quest_number(X, Y)                           //X = quest_id, Y = number
11006: set_mission_result(X)                            
11007: finish_mission(X)                                
11010: jump_to_site(X)                                  //X = site_id
11011: set_jump_mission(X)                              //X = mission_template_id
11020: start_mission_conversation(X)                    //X = troop_id
11030: add_reinforcements_to_entry(X, Y)                //X = entry_no, Y = number_of_reinforcements
15000: set_mission_cookie(X, Y)                         
15001: reset_mission_cookie(X, Y)                       
15002: assign_mission_cookie(X, Y)                      
15003: ++X                                              //X = cookie
15004: --X                                              //X = cookie
15005: add_to_mission_cookie(X, Y)                      
20001: X /= Y                                           //X = reg
20002: X -= Y                                           //X = reg
20003: X %= Y                                           //X = reg
20004: X += Y                                           //X = reg
20005: X *= Y                                           //X = reg
20006: X = (X > Y ? Y : X)                              //X = reg
20007: X = (X > Y ? X : Y)                              //X = reg
20013: ++X                                              
20014: --X                                              
20015: X += Y                                           //X = cookie
20016: X -= Y                                           //X = cookie
20017: X *= Y                                           //X = cookie
20018: X /= Y                                           //X = cookie
20019: X %= Y                                           //X = cookie
20020: X = (X > Y ? Y : X)                              //X = cookie
20021: X = (X > Y ? X : Y)                              //X = cookie
20028: if(reg[0] != 0) X = Y                            //X = reg
20029: X = Y                                            //X = reg
20030: Y = X                                            //X = cookie, Y = reg
20033: shuffle_range(X, Y)                              //X = start, Y = end
20034: store_shuffled_range(X, Y)                       //X = num_distinct_randoms
20035: X = store_random(Y)                              //X = reg, Y = random_range
20048: X = Y                                            //X = reg
20049: X = store_gold()                                 //X = reg
20054: X = store_num_free_stacks()                      //X = reg
20055: X = store_num_free_prisoner_stacks()             //X = reg
20056: X = store_total_party_size()                     //X = reg
20057: X = store_party_size_wo_prisoners()              //X = reg
20058: X = store_troop_kind_count(Y)                    //X = reg, Y = troop_id
20059: X = store_num_regular_prisoners()                //X = reg
20060: X = store_troop_count_companions(Y)              //X = reg, Y = troop_id
20061: X = store_troop_count_prisoners(Y)               //X = reg, Y = troop_id
20065: X = store_item_kind_count(Y)                     //X = reg, Y = item_id
20067: X = store_free_inventory_capacity(Y)             //X = reg
20070: reg[0] = store0_skill_level(X, Y)                //X = skill_id, Y = [troop_id]
20071: X = store_character_level(Y)                     //X = reg, Y = [troop_id]
20080: X = store_healing_cost(Y)                        //X = reg
20090: reg[0] = store0_relation(X, Y)                   //X = faction_id, Y = faction_id
20100: X = store_conversation_troop()                   //X = reg
20101: X = store_partner_faction()                      //X = reg
20102: X = store_encountered_party()                    //X = reg
20110: X = store_current_town()                         //X = reg
20111: X = store_current_site()                         //X = reg
20130: X = store_item_value(Y)                          //X = reg, Y = item_id
20131: X = store_troop_value(Y)                         //X = reg, Y = troop_id
20200: X = store_partner_quest()                        //X = reg
20210: reg[0] = store0_random_quest_in_range(X, Y)      //X = quest_id, Y = quest_id
20211: X = store_random_troop_to_raise(Y)               //X = reg, Y = troop_id
20212: X = store_random_troop_to_capture(Y)             //X = reg, Y = troop_id
20214: reg[0] = store0_random_town_in_range(X, Y)       //X = town_id, Y = town_id
20215: reg[0..1] = store01_random_towns_in_range(X, Y)  //X = town_id, Y = town_id
20217: X = store_random_horse()                         //X = reg
20218: X = store_random_equipment()                     //X = reg
20219: X = store_random_armor()                         //X = reg
20221: X = store_quest_number(Y)                        //X = reg, Y = quest_id
20222: X = store_quest_item(Y)                          //X = reg, Y = quest_id
20223: X = store_quest_troop(Y)                         //X = reg, Y = quest_id
20250: X = store_current_hours()                        //X = reg
20251: X = store_time_of_day()                          //X = reg
20252: X = store_current_day()                          //X = reg
20300: reg[0] = store0_distance_to_town_from_party(X, Y)//X = town_id, Y = party_id
20301: reg[0] = store0_distance_to_party_from_party(X, Y)//X = party_id, Y = party_id
20302: reg[0] = store0_distance_to_town_from_town(X, Y) //X = town_id, Y = town_id
20340: get_party_ai_behavior(X, Y)                      
20341: X = get_party_ai_object(Y)                       //X = reg, Y = party_id
20350: X = store_num_parties_created(Y)                 //X = reg, Y = party_template_id
20351: X = store_num_parties_destroyed(Y)               //X = reg, Y = party_template_id
20352: X = store_num_parties_destroyed_by_player(Y)     //X = reg, Y = party_template_id
20400: X = store_num_parties_of_template(Y)             //X = reg, Y = party_template_id
20401: X = store_random_party_of_template(Y)            //X = reg, Y = party_template_id
20500: X = str_store_troop_name(Y)                      //X = sreg, Y = troop_id
20501: X = str_store_item_name(Y)                       //X = sreg, Y = item_id
20510: X = str_store_town_name(Y)                       //X = sreg, Y = town_id
20600: X = str_store_date_from_hours(Y)                 //X = sreg
21000: X = store_remaining_team_no()                    //X = reg
30100: X = store_mission_timer_a()                      //X = reg
30101: X = store_mission_timer_b()                      //X = reg
30102: X = store_mission_timer_c()                      //X = reg
30105: X = reset_mission_timer_a()                      //X = reg
30106: X = reset_mission_timer_b()                      //X = reg
30107: X = reset_mission_timer_c()                      //X = reg
30110: X = store_enemy_count()                          //X = reg
30111: X = store_friend_count()                         //X = reg
30112: X = store_ally_count()                           //X = reg
 
Oh my god!

Armagan's gonna kill ye!...with a big hug... :lol:

How about a small tutorial for people that never HEXed in their life?
like me...

Just the necessities for modding the game...
 
Murka said:
How about a small tutorial for people that never HEXed in their life?

You don't actually need to hex edit. All these files are text. For general hex stuff, you could look at the following threads. They have some posts and links to other places.

http://taleworlds.com/v-web/bulletin/bb/viewtopic.php?t=792

http://taleworlds.com/v-web/bulletin/bb/viewtopic.php?t=1391


bloodmerc said:
how about a new mod section to the forums?

pavlov said we'd probably get a mod forum when armagan starts releasing tools. Until then I'm just polluting the main forum. :wink:
 
Thanks for collecting all the info into one place. I'd feel remiss if I didn't point out that some of the operations I figured out are, at best, a guess, so proceed cautiously.

I'm also feeling a little sheepish for not noticing 0x1000000 == 16777216
 
Just to contribute an addition.

It seems code 10201 joins the party you're talking to into your own. It's used in rescued prisoners parties when you meet them on the field and they join your party. I have put river pirates joining my party this way. The command just adds the units in the other party into yours, it doesn't check if you have enough room, so you might end up with more party members than your leadership/charisma allows, although it didn't crash the game. I disbanded until I was inside the limit, and then everything went smoothly.
 
Okay . . . I'm not quite sure I get this reg business. What does "20030 33554464 0" mean, for instance? reg[0] == 33554464, but that means what? Setting a variable of some sort? I'm interested in modifying the tournaments to be fairer and more varied.

-Simetrical
 
Simetrical said:
Okay . . . I'm not quite sure I get this reg business. What does "20030 33554464 0" mean, for instance? reg[0] == 33554464, but that means what? Setting a variable of some sort? I'm interested in modifying the tournaments to be fairer and more varied.

20030 33554464 0

Actually means:

reg[0] = var[32]
 
My question is, what's the difference between a variable and the register? I probably should've been clearer.

-Simetrical
 
Simetrical said:
My question is, what's the difference between a variable and the register? I probably should've been clearer.

Variables are permanent storage and saved in the save game. Registers are temporary storage and are only valid during the set of instructions currently executing.
 
Ah, I see. Let me see if I can decipher the tournament stuff now.

Edit: Alas, there are too many unknown codes for me to handle. Here's my deciphering of the two-vs.-two tourney code, in case anyone else can make heads or tails of it.
Code:
reg[10] = 5
reg[11] = 5
reg[12] = 5
reg[13] = 5
reg[14] = 6
reg[15] = 6
reg[16] = 6
reg[17] = 95
reg[18] = 96
reg[19] = 97
20033 10 20             only used for tourneys--values 10 20, 0 8, 0 8 for both
10261 8 0               used for tourneys (8 0) and training (7 0)
10262 0 0               used for tourneys and training (both 0 0), immediately follows 10261
20034 8 0               used only twice: here (2 vs. 2 arena fight), and immediately *before* training (4 0)
reg[0] = 9
reg[1] = 10
reg[2] = 11
reg[3] = 12
reg[4] = 13
reg[5] = 14
reg[6] = 15
reg[7] = 16
20033 0 8               only used for tourneys--values 10 20, 0 8, 0 8 for both
10263 reg[0] reg[10]    used for *any* fight spawn event: watching tourney, being in tourney, being in practice, all immediately before.  Usually two regs, sometimes the latter is 0, once it's 5 (for watching tourney)
10263 reg[1] reg[11]    used for *any* fight spawn event: watching tourney, being in tourney, being in practice, all immediately before.  Usually two regs, sometimes the latter is 0, once it's 5 (for watching tourney)
reg[0] = 9
reg[1] = 10
reg[2] = 11
reg[3] = 12
reg[4] = 13
reg[5] = 14
reg[6] = 15
reg[7] = 16
20033 0 8               only used for tourneys--values 10 20, 0 8, 0 8 for both
10263 reg[0] 0          used for *any* fight spawn event: watching tourney, being in tourney, being in practice, all immediately before.  Usually two regs, sometimes the latter is 0, once it's 5 (for watching tourney)
add[27] = reg[0]
10263 reg[1] reg[13]
-Simetrical
 
Added a lot more information (thanks to armagan). Hopefully, this will make sense to everyone. And no I have not tested each one.
 
Great work effidian, few questions if you, or anyone, finds the time to answer them,

1. operation 10203 . . . troop_join(X), is there a way to modify the number of said troops to join your party, or do you have to copy the bit of code a bunch of times?

and 2. operation 10090 . . . learn_skill(X), what is the range of numbers corresponding to the skill? -(guess and check only revealed that anything between 1 and 19 revealed "you learned nothing new" while 20 and above ((as far as I checked)) came back with an error.) Who does it apply to, and if possible, how do you set the amount to increment the skill by?
 
Back
Top Bottom