Better strategy AI on following and besieging for AI lords

rubik

Squire
Best answers
0
There is a problem about following and besieging for AI lords. When they see some weak enemy parties nearby, they will interrupt following the marshal or interrupt besieging, and chase these weak enemy parties.

I have written some code to solve this problem.

1. Define slot_party_blind_to_other_parties in module_constants.py. For example:
slot_party_blind_to_other_parties  = 101

2. Open module_scripts.py. 
  2.1 Modify script_game_context_menu_get_buttons like the following.
  ("game_context_menu_get_buttons",
  [(store_script_param,
":party_no", 1),
    (try_begin),
      (neq,
":party_no", "p_main_party"),
      (context_menu_add_item,
"@Move here", cmenu_move),
    (try_end),
    (try_begin),
      (is_between,
":party_no", centers_begin, centers_end),
      (context_menu_add_item,
"@View notes", 1),
    (else_try),
      (party_get_num_companion_stacks,
":num_stacks", ":party_no"),
      (gt,
":num_stacks", 0),
      (party_stack_get_troop_id,
":troop_no", ":party_no", 0),
      (is_between,
":troop_no", kingdom_heroes_begin, kingdom_heroes_end),
      (context_menu_add_item,
"@View notes", 2),
     
## CC
     
(try_begin),
        (party_slot_eq,
":party_no", slot_party_ai_state, spai_accompanying_army),
        (party_slot_eq,
":party_no", slot_party_ai_object, "p_main_party"),
        (try_begin),
          (party_slot_eq,
":party_no", slot_party_blind_to_other_parties, 0),
          (context_menu_add_item,
"@Blind to other parties(Disabled)", 3),
        (else_try),
          (party_slot_eq,
":party_no", slot_party_blind_to_other_parties, 1),
          (context_menu_add_item,
"@Blind to other parties(Enabled)", 3),
        (try_end),
        (context_menu_add_item,
"@Force all lords followed to blind to other parties", 4),
        (context_menu_add_item,
"@Force all lords followed not to blind to other parties", 5),
      (try_end),
     
## CC
   
(try_end),
  ]),
  2.2. Modify script_game_event_context_menu_button_clicked like the following.
  ("game_event_context_menu_button_clicked",
  [(store_script_param,
":party_no", 1),
    (store_script_param,
":button_value", 2),
    (try_begin),
      (eq,
":button_value", 1),
      (change_screen_notes,
3, ":party_no"),
    (else_try),
      (eq,
":button_value", 2),
      (party_stack_get_troop_id,
":troop_no", ":party_no", 0),
      (change_screen_notes,
1, ":troop_no"),
   
## CC
   
(else_try),
      (eq,
":button_value", 3),
      (party_get_slot,
":follow_state", ":party_no", slot_party_blind_to_other_parties),
      (val_add,
":follow_state", 1),
      (val_mod,
":follow_state", 2),
      (party_set_slot,
":party_no", slot_party_blind_to_other_parties, ":follow_state"),
    (else_try),
      (eq,
":button_value", 4),
      (try_for_range,
":troop_no", kingdom_heroes_begin, kingdom_heroes_end),
        (troop_get_slot,
":party_no", ":troop_no", slot_troop_leaded_party),
        (ge,
":party_no", 1),
        (party_slot_eq,
":party_no", slot_party_ai_state, spai_accompanying_army),
        (party_slot_eq,
":party_no", slot_party_ai_object, "p_main_party"),
        (party_set_slot,
":party_no", slot_party_blind_to_other_parties, 1),
      (try_end),
    (else_try),
      (eq,
":button_value", 5),
      (try_for_range,
":troop_no", kingdom_heroes_begin, kingdom_heroes_end),
        (troop_get_slot,
":party_no", ":troop_no", slot_troop_leaded_party),
        (ge,
":party_no", 1),
        (party_slot_eq,
":party_no", slot_party_ai_state, spai_accompanying_army),
        (party_slot_eq,
":party_no", slot_party_ai_object, "p_main_party"),
        (party_set_slot,
":party_no", slot_party_blind_to_other_parties, 0),
      (try_end),
   
## CC
   
(try_end),
  ]),

  2.3. Add the following into module_scripts.py.
# Note to modders: Uncomment these if you'd like to use the following.

  #script_game_check_party_sees_party
  # This script is called from the game engine when a party is inside the range of another party
  # INPUT: arg1 = party_no_seer, arg2 = party_no_seen
  # OUTPUT: trigger_result = true or false (1 = true, 0 = false)
## CC
 
("game_check_party_sees_party",
  [
    (store_script_param,
":party_no_seer", 1),
    (store_script_param,
":party_no_seen", 2),
    (assign,
":seen_result", 1),
    (try_begin),
      (party_slot_eq,
":party_no_seer", slot_party_blind_to_other_parties, 1),
      (this_or_next|party_slot_eq,
":party_no_seer", slot_party_ai_state, spai_accompanying_army),
      (party_slot_eq,
":party_no_seer", slot_party_ai_state, spai_besieging_center),
      (party_get_slot,
":dest_ai_party", ":party_no_seer", slot_party_ai_object),
      (neq,
":party_no_seen", ":dest_ai_party"),
      (assign,
":seen_result", 0),
    (try_end),
    (set_trigger_result,
":seen_result"),
    ]),
## CC

3. Paste the following into module_simple_triggers.py:

  (1,
    [
      (try_for_parties,
":party_no"),
        (party_slot_eq,
":party_no", slot_party_type, spt_kingdom_hero_party),
        (store_faction_of_party,
":party_faction", ":party_no"),
        (try_begin),
## follow
         
(party_slot_eq, ":party_no", slot_party_ai_state, spai_accompanying_army),
          (party_get_slot,
":dest_ai_party", ":party_no", slot_party_ai_object),
          (gt,
":dest_ai_party", -1),
          (party_is_active,
":dest_ai_party"),
          (try_begin),
# skip player's party
           
(eq, ":dest_ai_party", "p_main_party"),
          (else_try),
            (party_set_slot,
":party_no", slot_party_blind_to_other_parties, 1),
            (try_begin),
              (party_get_battle_opponent,
":eek:pponent_party", ":dest_ai_party"),
              (store_distance_to_party_from_party,
":dist", ":party_no", ":dest_ai_party"),
              (gt,
":eek:pponent_party", -1),
              (le,
":dist", 5),
              (party_set_slot,
":party_no", slot_party_blind_to_other_parties, 0),
            (try_end),
          (try_end),
        (else_try),
## besiege
         
(party_slot_eq, ":party_no", slot_party_ai_state, spai_besieging_center),
          (party_get_slot,
":ai_object", ":party_no", slot_party_ai_object),
          (gt,
":ai_object", -1),
          (party_set_slot,
":party_no", slot_party_blind_to_other_parties, 1),
          (try_for_parties,
":party_no_2"),
            (neq,
":party_no_2", ":party_no"),
            (store_distance_to_party_from_party,
":dist_2", ":party_no", ":party_no_2"),
            (le,
":dist_2", 5),
            (party_slot_eq,
":party_no_2", slot_party_type, spt_kingdom_hero_party),
            (store_faction_of_party,
":party_faction_2", ":party_no_2"),
            (eq,
":party_faction_2", ":party_faction"),
            (party_get_battle_opponent,
":eek:pponent_party_2", ":party_no_2"),
            (gt,
":eek:pponent_party_2", -1),
            (party_set_slot,
":party_no", slot_party_blind_to_other_parties, 0),
          (try_end),
        (else_try),
          (party_set_slot,
":party_no", slot_party_blind_to_other_parties, 0),
        (try_end),
      (try_end),
    ]),


Effect:
1. You can order the lords which are accompanying you to blind to other parties by right click on them and click the 3rd option. This option is a toggle. When enabled, the lord will follow you with blinding to other parties. When disabled, the lord will follow you as normal, he can see other parties and runs toward them or runs away from them. You can click the 4th option make all lords which are accompanying you to blind to other parties, and click the 5th option to make all of them not to blind to other parties.

2. When a lord is following an AI marshal, he blind to other parties except the marshal. When the marshal is sinked into a battle, the lords which are following will cancel the state of blind to other parties, and then join the battle. After the battle is over, the lords will come back to the state of  blind to other parties and continue to follow the marshal wholeheartedly.

3. When a group of AI lords is besieging a castle or town. All of them blind to other parties, they won't attack any enemy parties nearby actively except one of them is attacked by an enemy party.
 

Cruger

This is some really great work. Is it an open source? I might want to use it in my mod.
 

Twan

Sergeant Knight
Best answers
0
It's not easy at all.

If you absolutely want to do so, you would need to
1. copy native module system
2. correctly add the new code to native module system and compile
3. use a text comparator to find what was changed in native text files
4. copy the changes
5. replace the good scripts text and add the simple trigger text in the other module
6. (may work or not ; will also probably break saves)