OSP Code SP [WB] Unit Upgrade Academy

Currently Viewing (Users: 0, Guests: 1)

Somebody

Code Pope
Baron
WBWF&S
Best answers
1
This OSP script of the week fills in the functionality for the Military Academy from the previous combat modifier buildings. If you would rather not add in the framework some extra buildings, simply replace all references of slot_center_has_academy with slot_town_prosperity, which should limit the number of troops available for upgrade in a semi-reasonable fashion.

To use this, go through the party list on the left and select one of the two options below the troop's tableau. This is intended for usage in promoting troops to alternative branches (i.e. knighthood, bandits into faction recruits) but that implementation is left as an exercise for the reader. Holding shift/ctrl has the same effect as it would in the party menu, and up/down or mwheel goes through the stacks. There are also some gamepad buttons that you can experiment with, but are untested.
("upgrade_troops", 0, mesh_face_gen_window, [
    (ti_on_presentation_load,
      [
        (presentation_set_duration, 999999),
        (set_fixed_point_multiplier, 1000),

        ## next presentation
        (assign, "$g_presentation_next_presentation", -1),
        (assign, "$g_talk_troop", -1),
        (assign, "$g_talk_troop_met", -1),

        (str_clear, s0),
        (create_text_overlay, "$g_presentation_obj_1", s0, tf_scrollable),
        (position_set_x, pos1, 510),
        (position_set_y, pos1, 100),
        (overlay_set_position, "$g_presentation_obj_1", pos1),
        (position_set_x, pos1, 400),
        (position_set_y, pos1, 600),
        (overlay_set_area_size, "$g_presentation_obj_1", pos1),
        (set_container_overlay, "$g_presentation_obj_1"),

        (assign, ":pos_x", 150),
        (party_get_num_companion_stacks, ":num_stacks", "p_main_party"),
        (try_begin), #limit stack range to updated stacks
          (val_clamp, "$g_cur_stack", -1, ":num_stacks"),
          (party_stack_get_troop_id, ":troop_no", "p_main_party", "$g_cur_stack"),
          (this_or_next|le, ":troop_no", 0),
          (troop_is_hero, ":troop_no"),
          (assign, "$g_cur_stack", -1),
        (try_end),
        (store_mul, ":pos_y", ":num_stacks", 40),
        (val_sub, ":pos_y", 40),
        (val_max, ":pos_y", 560),
        (try_for_range, ":slot_no", 0, ":num_stacks"),
          (party_stack_get_troop_id, ":troop_no", "p_main_party", ":slot_no"),
          (troop_is_hero, ":troop_no"), #discard results from displaying
          (troop_set_slot, "trp_temp_array_a", ":slot_no", -1),
        (else_try),
          (party_stack_get_size, ":stack_size", "p_main_party", ":slot_no"),
          (party_stack_get_num_wounded, ":num_wounded", "p_main_party", ":slot_no"),
          (str_store_troop_name, s1, ":troop_no"),
          (assign, reg2, ":stack_size"),
          (try_begin),
            (gt, ":num_wounded", 0),
            (store_sub, reg3, ":stack_size", ":num_wounded"),
            (str_store_string, s1, "@{s1} ({reg3}/{reg2})"),
          (else_try),
            (str_store_string, s1, "@{s1} ({reg2})"),
          (try_end),
          (create_game_button_overlay, reg1, s1),
          (position_set_x, pos1, ":pos_x"),
          (position_set_y, pos1, ":pos_y"),
          (overlay_set_position, reg1, pos1),
          (position_set_x, pos1, 300),
          (position_set_y, pos1, 32),
          (overlay_set_size, reg1, pos1),
          (troop_set_slot, "trp_temp_array_a", ":slot_no", reg1),
          (val_sub, ":pos_y", 40),
        (try_end),
        (try_begin),
          (gt, "$g_cur_stack", -1),
          (troop_get_slot, ":dest_obj", "trp_temp_array_a", "$g_cur_stack"),
          (gt, ":dest_obj", 0),
          (overlay_set_alpha, ":dest_obj", 0x80),
          (party_stack_get_troop_id, "$g_talk_troop", "p_main_party", "$g_cur_stack"),
          (neg|troop_is_hero, "$g_talk_troop"),
          (party_stack_get_size, "$g_talk_troop_met", "p_main_party", "$g_cur_stack"),
          (party_stack_get_num_wounded, ":num_wounded", "p_main_party", "$g_cur_stack"),
          (val_sub, "$g_talk_troop_met", ":num_wounded"),
          (try_begin),
            (gt, "$g_talk_troop_met", 0),
            (store_faction_of_troop, ":color", "$g_talk_troop"),
            (faction_get_color, ":color", ":color"),
            (overlay_set_color, ":dest_obj", ":color"),
          (else_try), #all wounded - cannot upgrade
            (overlay_set_color, ":dest_obj", 0xFF0000),
            (overlay_set_alpha, ":dest_obj", 0xFF),
          (try_end),
        (try_end),
        (set_container_overlay, -1),

        #availability description
        (party_get_slot, "$g_talk_troop_relation", "$current_town", slot_center_has_academy),
        (assign, reg1, "$g_talk_troop_relation"),
        (faction_get_color, ":color", "$g_encountered_party_faction"),
        (position_set_x, pos1, 275),
        (position_set_y, pos1, 210),
        (create_text_overlay, reg1, "@There are {reg1} upgrade available", tf_with_outline|tf_center_justify),
        (overlay_set_position, reg1, pos1),
        (overlay_set_color, reg1, ":color"),

        (store_troop_gold, "$g_talk_agent", "trp_player"),
        (try_begin),
          (gt, "$g_talk_troop", 0),
          (position_set_x, pos1, 275),
          (try_begin),
            (troop_get_upgrade_troop, ":upgrade_troop", "$g_talk_troop", 0),
            (gt, ":upgrade_troop", 0),
            (str_store_troop_name, s2, ":upgrade_troop"),
            (create_button_overlay, "$g_presentation_obj_2", "@Upgrade to {s2}", tf_center_justify),
            (call_script, "script_game_get_join_cost", ":upgrade_troop"),
            (try_begin),
              (lt, "$g_talk_agent", reg0),
              (str_store_string, s1, "@Insufficient funds"),
              (overlay_set_color, "$g_presentation_obj_2", 0xFF1111),
            (else_try),
              (call_script, "script_game_get_money_text", reg0),
            (try_end),
            (overlay_set_tooltip, "$g_presentation_obj_2", s1),
           
            (position_set_y, pos1, 100),
            (overlay_set_position, "$g_presentation_obj_2", pos1),
          (try_end),
          (try_begin),
            (troop_get_upgrade_troop, ":upgrade_troop", "$g_talk_troop", 1),
            (gt, ":upgrade_troop", 0),
            (str_store_troop_name, s3, ":upgrade_troop"),
            (create_button_overlay, "$g_presentation_obj_3", "@Promote to {s3}", tf_center_justify),
            (call_script, "script_game_get_join_cost", ":upgrade_troop"),
            (try_begin),
              (lt, "$g_talk_agent", reg0),
              (str_store_string, s1, "@Insufficient funds"),
              (overlay_set_color, "$g_presentation_obj_3", 0xFF1111),
            (else_try),
              (call_script, "script_game_get_money_text", reg0),
            (try_end),
            (overlay_set_tooltip, "$g_presentation_obj_3", s1),
           
            (position_set_y, pos1, 150),
            (overlay_set_position, "$g_presentation_obj_3", pos1),
          (try_end),
        (try_end),

        # cur troop
        (try_begin),
          (gt, "$g_cur_stack", -1),
          (party_stack_get_troop_id, ":troop_no", "p_main_party", "$g_cur_stack"),
          (store_mul, ":cur_troop", ":troop_no", 2), #with weapons
          (create_image_button_overlay_with_tableau_material, "$g_presentation_obj_6", -1, "tableau_game_party_window", ":cur_troop"),
          (position_set_x, pos1, 1750),
          (position_set_y, pos1, 1750),
          (overlay_set_size, "$g_presentation_obj_6", pos1),
          (position_set_x, pos1, 50),
          (position_set_y, pos1, 240),
          (overlay_set_position, "$g_presentation_obj_6", pos1),

        (else_try), #default, startup
          (create_mesh_overlay, "$g_presentation_obj_6", "mesh_pic_mb_warrior_1"),
          (position_set_x, pos1, -500),
          (position_set_y, pos1, 250),
          (overlay_set_position, "$g_presentation_obj_6", pos1),
          # (overlay_set_display, "$g_presentation_obj_6", 0),
          (display_message, "@Press Shift or Ctrl to upgrade up to 5 or all members"),
        (try_end),

        #gold overlay (image button so we can click on it)
        (position_set_x, pos1, 500),
        (position_set_y, pos1, 500),
        (create_image_button_overlay, "$g_presentation_obj_10", "mesh_icon_gold", "mesh_icon_gold"),
        (overlay_set_size, "$g_presentation_obj_10", pos1),
        (position_set_x, pos1, 580),
        (position_set_y, pos1, 40),
        (overlay_set_position, "$g_presentation_obj_10", pos1),
        (overlay_set_tooltip, "$g_presentation_obj_10", "@Click here or press ESC to finish recruiting"),

        #gold display
        (call_script, "script_game_get_money_text", "$g_talk_agent"),
        (create_text_overlay, reg1, "@You have {s1}", tf_with_outline),
        (position_set_x, pos1, 690),
        (position_set_y, pos1, 60),
        (overlay_set_position, reg1, pos1),
        (overlay_set_color, reg1, 0xFFFFFF),
        # done
        # (create_game_button_overlay, "$g_presentation_obj_10", "str_done"),
        # (position_set_x, pos1, 900),
        # (position_set_y, pos1, 50),
        # (overlay_set_position, "$g_presentation_obj_10", pos1),

      ]
    ),

    (ti_on_presentation_event_state_change,
      [
      (store_trigger_param_1, ":eek:bject"),

      (party_get_num_companion_stacks, ":num_stacks", "p_main_party"),
      (try_for_range, ":slot_no", 0, ":num_stacks"),
        (troop_slot_eq, "trp_temp_array_a", ":slot_no", ":eek:bject"),
        (assign, "$g_cur_stack", ":slot_no"),
        (assign, ":num_stacks", -1),
        (start_presentation, "prsnt_upgrade_troops"),
      (try_end),

      (try_begin),
        (gt, "$g_cur_stack", -1),
        (assign, ":quantity", 1),
        (try_begin),
          (this_or_next|key_is_down, key_left_shift),
          (this_or_next|key_is_down, key_right_shift),
          (key_is_down, key_xbox_lbumber),
          (assign, ":quantity", 5),
        (else_try),
          (this_or_next|key_is_down, key_left_control),
          (this_or_next|key_is_down, key_right_control),
          (key_is_down, key_xbox_rbumber),
          (assign, ":quantity", 9999),
        (try_end),
        (val_min, ":quantity", "$g_talk_troop_met"),
        (val_min, ":quantity", "$g_talk_troop_relation"),

        (try_begin),
          (this_or_next|key_is_down, key_xbox_dpad_right),
          (this_or_next|key_is_down, key_xbox_dpad_left),
          (this_or_next|eq, ":eek:bject", "$g_presentation_obj_2"),
          (eq, ":eek:bject", "$g_presentation_obj_3"),
          (gt, "$g_talk_troop", 0),
         
          (try_begin),
            (this_or_next|key_is_down, key_xbox_dpad_left),
            (eq, ":eek:bject", "$g_presentation_obj_3"),
            (troop_get_upgrade_troop, ":upgrade_troop", "$g_talk_troop", 1),
          (else_try),
            (this_or_next|key_is_down, key_xbox_dpad_right),
            (eq, ":eek:bject", "$g_presentation_obj_2"),
            (troop_get_upgrade_troop, ":upgrade_troop", "$g_talk_troop", 0),
          (try_end),
          (call_script, "script_game_get_join_cost", ":upgrade_troop"),
          (assign, ":cost", reg0),
          (gt, ":upgrade_troop", 0),
          #gold check
          (store_mul, ":gold", ":cost", ":quantity"),
          (try_begin), #sufficient funds
            (ge, "$g_talk_agent", ":gold"),
            (val_sub, "$g_talk_agent", ":gold"),
          (else_try),
            (store_div, ":quantity", "$g_talk_agent", ":cost"),
            (store_mul, ":gold", ":cost", ":quantity"),
          (try_end),
          (gt, ":quantity", 0),
          (party_remove_members, "p_main_party", "$g_talk_troop", ":quantity"),
          (troop_remove_gold, "trp_player", ":gold"),

          (party_add_members, "p_main_party", ":upgrade_troop", ":quantity"),
          (val_sub, "$g_talk_troop_relation", ":quantity"),
          (party_set_slot, "$current_town", slot_center_has_academy, "$g_talk_troop_relation"),
         
          #do stack reassignment
          (party_stack_get_troop_id, ":troop", "p_main_party", "$g_cur_stack"),
          (try_begin),
            (neq, ":troop", "$g_talk_troop"), #if we don't have any of the cur stack remaining
            (neq, ":troop", ":upgrade_troop"), #or if we haven't upgraded all of them at once
            (party_get_num_companion_stacks, ":no_stacks", "p_main_party"),
            (try_for_range, ":stacks", 1, ":no_stacks"),
              (party_stack_get_troop_id, ":troop", "p_main_party", ":stacks"),
              (eq, ":troop", ":upgrade_troop"), #since we already upgraded at least 1
              (assign, "$g_cur_stack", ":stacks"),
              (assign, ":no_stacks", -1),
            (try_end),
          (try_end),
         
          (start_presentation, "prsnt_upgrade_troops"),
        (else_try), #this can be expanded with
          (eq, ":eek:bject", "$g_presentation_obj_6"), # troop note
          (assign, "$g_presentation_next_presentation", "prsnt_upgrade_troops"),
          (assign, "$temp", "$g_talk_troop"),
          # (start_presentation, "prsnt_troop_note"),
        (try_end),
      (try_end),
      (try_begin),
        # (this_or_next|key_clicked, key_escape),
        (this_or_next|le, "$g_talk_troop_relation", 1),
        (eq, ":eek:bject", "$g_presentation_obj_10"),
        #unset globals
        (assign, "$g_talk_troop", -1),
        (assign, "$g_talk_troop_relation", -1),
        (assign, "$g_presentation_next_presentation", -1),
        (assign, "$g_talk_troop_met", -1),
        (play_sound, "snd_enemy_flag_taken"),
        (presentation_set_duration, 0),
      (try_end),
    ]),
    (ti_on_presentation_run,
    [
      (party_get_num_companion_stacks, ":num_stacks", "p_main_party"),
      (assign, ":cur_slots", "$g_cur_stack"),
      (try_begin),
        (this_or_next|key_clicked, key_escape),
        (key_clicked, key_xbox_start),
        (presentation_set_duration, 0),
      (else_try),
        (this_or_next|key_clicked, key_xbox_dpad_down),
        (this_or_next|key_clicked, key_mouse_scroll_down),
        (key_clicked, key_down),
        (store_add, ":cur_slots", "$g_cur_stack", 1),
        (try_begin),
          (val_mod, ":cur_slots", ":num_stacks"),
        (try_end),
        (assign, ":dir", 1),
      (else_try),
        (this_or_next|key_clicked, key_xbox_dpad_up),
        (this_or_next|key_clicked, key_mouse_scroll_up),
        (key_clicked, key_up),
        (store_sub, ":cur_slots", "$g_cur_stack", 1),
        (try_begin),
          (lt, ":cur_slots", 1),
          (store_sub, ":cur_slots", ":num_stacks", 1),
        (try_end),
        (assign, ":dir", -1),
      (try_end),
     
      (try_begin), #do actual offset calcs - loopover already done previously
        (neq, ":cur_slots", "$g_cur_stack"),
        (assign, ":prev", 0),
        (assign, ":next", ":num_stacks"),
        (try_for_range, ":slot_no", ":prev", ":next"),
          (neg|troop_slot_eq, "trp_temp_array_a", ":slot_no", -1),
          (try_begin), #find previous
            (le, ":slot_no", ":cur_slots"),
            (assign, ":prev", ":slot_no"),
          (try_end),
          (try_begin),
            (ge, ":slot_no", ":cur_slots"),
            (assign, ":next", ":slot_no"),
          (try_end),
        (try_end),
        (try_begin),
          (eq, ":dir", 1),
          (assign, "$g_cur_stack", ":next"),
        (else_try),
          (eq, ":dir", -1),
          (assign, "$g_cur_stack", ":prev"),
        (try_end),
        (start_presentation, "prsnt_upgrade_troops"),
      (try_end),
      ]),
  ]),

This mesh used for the background requires a planar mesh and a duplicate material with the following settings - otherwise you get psychedelic transparency issues.

Code:
("face_gen_window", 0, "upgrade_window", 0, 0, 0, 0, 0, 0, 1, 1, 1),
("icon_gold", 0, "mp_ico_gold", 0, 0, 0, 0, 0, 0, 1, 1, 1),
Alternatively, download the following WIP with some extra bits, you still need to add the two lines above

To access the presentation drop this in the appropriate menu (the recommended being the default town in which buildings are probably present)
Code:
    ("town_upgrade",
      [
         (party_get_slot, reg12, "$current_town", slot_center_has_academy),
         (is_between, "$g_encountered_party_faction", kingdoms_begin, kingdoms_end),
         (ge, reg12, 1), #this value is used later
         (eq, "$g_encountered_party_faction", "$players_kingdom"),
         (this_or_next|party_slot_eq, "$current_town", slot_town_lord, "trp_player"),
         (faction_slot_eq, "$players_kingdom", slot_faction_marshall, "trp_player"),
      ],"Enlist troops in the military academy ({reg12} available).",
      [
        (assign, "$g_cur_stack", -1),
        (start_presentation, "prsnt_upgrade_troops"),
      ]),
Credits for the original party stack interface go to rubik's Custom Commander - "Sort the Defender" presentation.
 

Somebody

Code Pope
Baron
WBWF&S
Best answers
1
Yes, the presentation can be expanded for custom upgrade paths, as mentioned in the original post. This version is for Native-based mods and such fetch the successor from the original troop's upgrade.
 

fladin

Baron
M&BWBWF&SNWVC
Best answers
0
with your permission of course , I will use your awesome code (with some modifications) in my mod ...


Thanks
 

Heroes_Witch_King

Wow, this is really great! I will definitely use this...
 

wld427

Recruit
Best answers
0
Where exactly do i drop the last piece of code to get the menu action to show up in a specific castle?


EDIT: i thought i would elaborate a little....

What i have done is add a new castle in each factions territory. What i want to do is assign these new castles purpose as the military academy. So you can stop by there and if you are allowed entry to the castle then the player can upgrade his troops if he has enough money.

 

Somebody

Code Pope
Baron
WBWF&S
Best answers
1
Assign some arbitrary value to slot_center_has_academy for those castles at the start of the game, then inject some code to refresh it in one of the existing center maintenance scripts and/or triggers. I recommend one of the weekly triggers that process center wealth/reinforcement or the taxes one. Modify the conditions so that the player won't need to own it or be marshal if necessary.
 

aliemre461

Banned
Best answers
0
Where should i put this code please help me

Code:
  ("town_upgrade",
      [
         (party_get_slot, reg12, "$current_town", slot_center_has_academy),
         (is_between, "$g_encountered_party_faction", kingdoms_begin, kingdoms_end),
         (ge, reg12, 1), #this value is used later
         (eq, "$g_encountered_party_faction", "$players_kingdom"),
         (this_or_next|party_slot_eq, "$current_town", slot_town_lord, "trp_player"),
         (faction_slot_eq, "$players_kingdom", slot_faction_marshall, "trp_player"),
      ],"Enlist troops in the military academy ({reg12} available).",
      [
        (assign, "$g_cur_stack", -1),
        (start_presentation, "prsnt_upgrade_troops"),
      ]),
 

Somebody

Code Pope
Baron
WBWF&S
Best answers
1
In the town menu. You'll want to initialize the value of slot_center_has_academy, as per my above post. For example, you can refresh this amount weekly as follows
Code:
  #Adding net incomes to heroes (once a week)
  #Increasing debts to heroes by 1% (once a week)
  #Adding net incomes to centers (once a week)
  (24*7,
   [
       (try_for_range, ":troop_no", active_npcs_begin, active_npcs_end),
         (troop_get_slot, ":cur_debt", ":troop_no", slot_troop_player_debt),#Increasing debt
         (val_mul, ":cur_debt", 101),
         (val_div, ":cur_debt", 100),
         (troop_set_slot, ":troop_no", slot_troop_player_debt, ":cur_debt"),
         (call_script, "script_calculate_hero_weekly_net_income_and_add_to_wealth", ":troop_no"),#Adding net income
       (try_end),
	   
       (try_for_range, ":center_no", walled_centers_begin, walled_centers_end),
         #If non-player center, adding income to wealth
         (neg|party_slot_eq, ":center_no", slot_town_lord, "trp_player"), #center does not belong to player.
         (party_slot_ge, ":center_no", slot_town_lord, 1), #center belongs to someone.
         (party_get_slot, ":cur_wealth", ":center_no", slot_town_wealth),
         (party_get_slot, ":prosperity", ":center_no", slot_town_prosperity),
         (store_mul, ":added_wealth", ":prosperity", 15),
         (val_add, ":added_wealth", 700),
         (try_begin),
           (party_slot_eq, ":center_no", slot_party_type, spt_town),
           (val_mul, ":added_wealth", 3),
           (val_div, ":added_wealth", 2),
         (try_end),
         (val_add, ":cur_wealth", ":added_wealth"),
         (call_script, "script_calculate_weekly_party_wage", ":center_no"),
         (val_sub, ":cur_wealth", reg0),
         (val_max, ":cur_wealth", 0),
         (party_set_slot, ":center_no", slot_town_wealth, ":cur_wealth"),
         #add this stuff to refresh upgrade troop count
         (party_get_slot, ":cur_troops", ":center_no", slot_center_has_academy),
         (store_random_in_range, ":added_troops", 3, 8),
         (val_add, ":cur_troops", ":added_troops"),
         (val_min, ":cur_troops", ":prosperity"),
         (party_set_slot, ":center_no", slot_center_has_academy, ":cur_troops"),
       (try_end),
    ]),
The above trigger already exists, just add the few lines at the bottom then start off each walled center with an arbitrary value
Code:
      (try_for_range, ":center_no", walled_centers_begin, walled_centers_end),#add town garrisons
        #add this line
        (party_set_slot, ":center_no", slot_center_has_academy, 30),
        #Add initial center wealth
        (assign, ":initial_wealth", 2000),
        (try_begin),
...