骑马与砍杀中文站论坛

 找回密码
 注册(Register!)

QQ登录

只需一步,快速开始

搜索
购买霸主CDKEY 购买战帆CDKEY
查看: 10491|回复: 13

[原创] 泡菜步射AI分享

[复制链接]

18

主题

247

回帖

125

积分

见习骑士

Rank: 3

UID
1404850
第纳尔
895
精华
0
互助
9
荣誉
0
贡献
0
魅力
14
注册时间
2013-6-9
鲜花(50) 鸡蛋(0)
发表于 2025-5-31 04:42:36 | 显示全部楼层 |阅读模式
本帖最后由 jackjian321 于 2025-11-2 10:01 编辑

2025-11-02 更新
为“安全射程”添加友方单位判断,如果友方部队 骑兵与步兵 数量更多,则更倾向于靠近射击;反之则依旧保持远距离射击。
很多骑友表示战场上射手都在很远的地方射击,不靠近射。但我实测下来这样其实战损比是最好的,虽然有点反直觉,但让射手靠近有时候反而把能打赢的仗给打输了……
毕竟 F1 F3 的初衷就是为了解手。
为了找到一个折中方案,我根据友方 步兵与骑兵 的数量与质量,去降低安全距离。然后让这个“安全距离”与“精准射程”做一个 取较小值 ,这样如果友方 步兵与骑兵 够多,他们等级够高,我就认为这是可靠的前排,允许射手靠近射击。
然后随着战场前排死亡,射手们也会发觉不对劲,不够安全,进而不再靠近射击。
备注:代码里的系数(5、15、1、11)是基于泡菜里顶级兵等级在35级左右调整的,友方单位 近距离射击的距离 会基于友方的 等级 × 类型系数(步兵/骑兵/射手/骑射手)。


2025-09-17 更新

新增一个“安全射程”,若敌人数量过少,可以视为威胁过小,允许近距离射击。
该射程与精准射程取较小值,基础15米,每多一个敌人增加2.5米。
方便在收尾的时候更倾向于靠近射杀。


2025-06-02 更新

修复两个bug,
一个是在指令判断处有遗漏,导致玩家下达 停止射击 指令,步射AI依旧会射击;
另一个是当单位退出步射AI时,若手中持有的是 无法持盾的远程武器 ,将不再会攻击,直到切换武器后可以做出 格挡或持盾 动作为止。


这个AI仅适用于 步射(投掷、弓、弩、火器),且指令是“冲锋”时才会启用。

需要战团版本达到v1.165。
目前在 泡菜【黎明时代】版本里,仅添加于 野战、村庄强盗/抢劫战、自定义战斗(快速战斗) 以及 军事演练(主线剧情结束后,在禅达 特殊战斗回顾 中新增的自定义战斗)。


命中率采用战团原版的AI辅助射击,避免人人都是神射手。
瞄准时机参考 君悦 提供的 shoot_ai 源码。

实际射程经过我的测试总结得出近似值(详见附件 战团AI射程测试.rar)。


我想尽可能适用于战团原版的AI模式,同时让“冲锋”的射击不如“坚守”,但又区别于“坚守”(会强制射击,而非怕误伤前方队友,因为冲锋容易让人挤在一起)。

- 如果目标在射程内,会开始射击。射击时有4%几率边走边射,而非立定射击(视为失误,因为移动时散射很高)。
- 如果目标不在精准射程范围内,则会向目标靠近;否则会随机向前移动。
- 如果目标距离低于安全距离(默认30米),则会开始后退。


这套代码仅适用于本版,因为里面有段关于 检测是否下雨 的判断是通过多方实现的。
在 mission_templates 中的频率为 0.3 秒。

  1. (set_fixed_point_multiplier, 1000),
  2. (assign, ":ally_cs_shoot_range", 1250),                        # 根据敌人数量,制定安全射击距离(近距离射击)
  3. (assign, ":enemy_cs_shoot_range", 1250),
  4. (try_for_agents, ":agent"),
  5.     (agent_is_alive, ":agent"),
  6.     (agent_is_human, ":agent"),
  7.     (agent_get_troop_id, ":troop", ":agent"),
  8.     (store_character_level, ":distance", ":troop"),
  9.     (try_begin),
  10.         (troop_is_hero, ":troop"),
  11.         (val_mul, ":distance", 10),                       # 英雄提供的安全感
  12.     (else_try),
  13.         (troop_is_guarantee_horse, ":troop"),
  14.         (try_begin),
  15.             (troop_is_guarantee_ranged, ":troop"),
  16.             (val_mul, ":distance", 5),                    # 骑射手提供的安全感
  17.         (else_try),
  18.             (val_mul, ":distance", 15),                   # 骑兵提供的安全感
  19.         (try_end),
  20.     (else_try),
  21.         (try_begin),
  22.             (troop_is_guarantee_ranged, ":troop"),
  23.             (val_mul, ":distance", 1),                    # 射手提供的安全感
  24.         (else_try),
  25.             (val_mul, ":distance", 11),                   # 步兵提供的安全感
  26.         (try_end),
  27.     (try_end),
  28.     (try_begin),
  29.         (agent_is_ally, ":agent"),
  30.         (val_add, ":enemy_cs_shoot_range", 250),
  31.         (val_sub, ":ally_cs_shoot_range", ":distance"),       # 我方高级步兵与骑兵越多,相对越安全,越可以靠近射击
  32.     (else_try),
  33.         (val_add, ":ally_cs_shoot_range", 250),               # 敌人越多,相对越不安全,便不倾向于靠近射击
  34.         (val_sub, ":enemy_cs_shoot_range", ":distance"),
  35.     (try_end),
  36. (try_end),
  37. (val_max, ":ally_cs_shoot_range", 1500),
  38. (val_max, ":enemy_cs_shoot_range", 1500),
  39. (try_for_agents, ":agent"),
  40.     (agent_is_alive, ":agent"),
  41.     (agent_is_human, ":agent"),
  42.     (agent_is_non_player, ":agent"),
  43.     (try_begin),
  44.         (agent_slot_eq, ":agent", slot_agent_is_running_away, 0),            # 没有处在逃跑中的单位
  45.         (agent_slot_eq, ":agent", slot_agent_is_not_reinforcement, 0),       # 没有处于 泡菜 野战敌方陷入混乱AI
  46.         (agent_get_horse, ":agent_horse", ":agent"),
  47.         (eq, ":agent_horse", -1),                                    # 仅步射应用此AI,骑射由 君悦骑射AI 接管
  48.         (agent_get_wielded_item, ":weapon", ":agent", 0),
  49.         (gt, ":weapon", 0),
  50.         (item_get_type, ":type", ":weapon"),
  51.         (this_or_next|eq, ":type", 8),
  52.         (this_or_next|eq, ":type", 9),
  53.         (this_or_next|eq, ":type", 16),
  54.         (this_or_next|eq, ":type", 17),
  55.         (eq, ":type", 10),
  56.         (agent_get_team, ":agent_team", ":agent"),
  57.         (agent_get_division, ":agent_group", ":agent"),
  58.         (team_get_movement_order, ":agent_team_order", ":agent_team", ":agent_group"),      # 仅适用于“冲锋”中的 agent
  59.         (eq, ":agent_team_order", 2),
  60.         (team_get_weapon_usage_order, ":agent_team_order", ":agent_team", ":agent_group"),  # 武器指令是 任意 或 远程
  61.         (neg|eq, ":agent_team_order", 1),
  62.         (neg|eq, ":agent_team_order", 2),
  63.         (team_get_hold_fire_order, ":agent_team_order", ":agent_team", ":agent_group"),     # 射击指令是 自由开火
  64.         (neg|eq, ":agent_team_order", 1),
  65.         (agent_set_slot, ":agent", 100, 1),                          # 启用此AI
  66.         (agent_get_attack_action, ":action", ":agent"),
  67.         (try_begin),
  68.             (eq, ":action", 0),                                      # 若 弩、火器 没有上膛弹药,优先进行装填
  69.             (this_or_next|eq, ":type", 9),
  70.             (this_or_next|eq, ":type", 16),
  71.             (eq, ":type", 17),
  72.             (assign, ":slot_max", 4),
  73.             (try_for_range, ":slot", 0, ":slot_max"),
  74.                 (agent_get_item_slot, ":item", ":agent", ":slot"),
  75.                 (eq, ":item", ":weapon"),
  76.                 (assign, ":slot_max", ":slot"),
  77.             (try_end),
  78.             (neg|eq, ":slot_max", 4),
  79.             (agent_get_item_cur_ammo, ":ammo", ":agent", ":slot_max"),
  80.             (eq, ":ammo", 0),
  81.             (agent_get_ammo, ":ammo", ":agent", 1),
  82.             (gt, ":ammo", 0),
  83.             (agent_set_defend_action, ":agent", -2, 1),
  84.             (agent_set_attack_action, ":agent", 3, 1),
  85.             (assign, ":action", 5),
  86.             (agent_set_slot, ":agent", 102, 6),
  87.         (try_end),
  88.         (try_begin),
  89.             (agent_ai_get_look_target, ":target", ":agent"),         # 计算攻击距离与移动距离
  90.             (try_begin),
  91.                 (ge, ":target", 0),
  92.                 (agent_is_alive, ":target"),
  93.                 (agent_get_team, ":target_team", ":target"),
  94.                 (teams_are_enemies, ":agent_team", ":target_team"),
  95.             (else_try),
  96.                 (assign, ":target", -1),
  97.             (try_end),
  98.             (ge, ":target", 0),
  99.             (2076, 1, ":agent", 9, 1),
  100.             (2076, 2, ":target", 9, 1),
  101.             (position_has_line_of_sight_to_position, pos1, pos2),
  102.             (get_distance_between_positions, ":distance", pos1, pos2),
  103.             (agent_get_troop_id, ":troop", ":agent"),
  104.             (try_begin),
  105.                 (eq, ":type", 8),
  106.                 (store_skill_level, ":weapon_skill_level", "skl_power_draw", ":troop"),
  107.                 (store_proficiency_level, ":weapon_proficiency_level", ":troop", wpt_archery),
  108.             (else_try),
  109.                 (eq, ":type", 9),
  110.                 (assign, ":weapon_skill_level", 0),
  111.                 (store_proficiency_level, ":weapon_proficiency_level", ":troop", wpt_crossbow),
  112.             (else_try),
  113.                 (eq, ":type", 10),
  114.                 (store_skill_level, ":weapon_skill_level", "skl_power_throw", ":troop"),
  115.                 (store_proficiency_level, ":weapon_proficiency_level", ":troop", wpt_throwing),
  116.             (else_try),
  117.                 (assign, ":weapon_skill_level", 0),
  118.                 (store_proficiency_level, ":weapon_proficiency_level", ":troop", wpt_firearm),
  119.             (try_end),
  120.             (2709, ":missile_speed", ":weapon"),           # 武器弹速
  121.             (2711, ":missile_accuracy", ":weapon"),        # 武器精准度
  122.             (try_begin),
  123.                 (troop_is_hero, ":troop"),               # 英雄根据物品栏获取前缀
  124.                 (assign, ":modifier", -1),
  125.                 (assign, ":slot_max", 4),
  126.                 (try_for_range, ":slot", 0, ":slot_max"),
  127.                     (troop_get_inventory_slot, ":item", ":troop", ":slot"),
  128.                     (eq, ":item", ":weapon"),
  129.                     (troop_get_inventory_slot_modifier, ":modifier", ":troop", ":slot"),
  130.                     (assign, ":slot_max", 0),
  131.                 (try_end),
  132.                 (val_max, ":modifier", 0),
  133.             (else_try),
  134.                 (assign, ":modifier", 0),                # 普通士兵无法通过快照物品栏获取正确的前缀
  135.             (try_end),
  136.             (val_mul, ":missile_speed", 100),              # 单位转换:米 -> 厘米 /秒
  137.             (try_begin),                                   # 计算AI有效射程(ai_shoot_range)
  138.                 (eq, ":type", 8),                    # 弓
  139.                 (2702, ":difficulty", ":weapon"),          # 弓的难度
  140.                 (try_begin),                               # 根据前缀校准弓的难度
  141.                     (eq, ":modifier", 17),            # - 精良的
  142.                     (val_add, ":difficulty", 4),
  143.                 (else_try),
  144.                     (eq, ":modifier", 19),            # - 坚硬的
  145.                     (val_add, ":difficulty", 2),
  146.                 (else_try),
  147.                     (eq, ":modifier", 18),            # - 重
  148.                     (val_add, ":difficulty", 1),
  149.                 (try_end),
  150.                 (val_add, ":difficulty", 4),                        # 弓的难度加四
  151.                 (val_min, ":weapon_skill_level", ":difficulty"),    # 强弓的有效上限
  152.                 (store_mul, ":shoot_range_mult", ":weapon_skill_level", 104),
  153.                 (val_add, ":shoot_range_mult", 2200),
  154.                 (store_mul, ":ai_shoot_range", ":missile_speed", ":shoot_range_mult"),
  155.                 (val_div, ":ai_shoot_range", 1000),
  156.             (else_try),
  157.                 (eq, ":type", 9),                    # 弩
  158.                 (store_mul, ":ai_shoot_range", ":missile_speed", 24),
  159.                 (val_div, ":ai_shoot_range", 10),
  160.             (else_try),
  161.                 (eq, ":type", 10),                   # 投掷
  162.                 (store_mul, ":shoot_range_mult", ":weapon_skill_level", 62),
  163.                 (val_add, ":shoot_range_mult", 1575),
  164.                 (store_mul, ":ai_shoot_range", ":missile_speed", ":shoot_range_mult"),
  165.                 (val_div, ":ai_shoot_range", 1000),
  166.             (else_try),
  167.                 (this_or_next|eq, ":type", 16),      # 手枪
  168.                 (eq, ":type", 17),                   # 步枪
  169.                 (store_mul, ":ai_shoot_range", ":missile_speed", 132),
  170.                 (val_div, ":ai_shoot_range", 100),
  171.             (try_end),
  172.             (try_begin),
  173.                 (eq, "$scene_is_raining", 1),             # 下雨天对于 弓、弩 的影响
  174.                 (try_begin),
  175.                     (eq, ":type", 8),
  176.                     (val_mul, ":ai_shoot_range", 95),
  177.                     (val_div, ":ai_shoot_range", 100),
  178.                 (else_try),
  179.                     (eq, ":type", 9),
  180.                     (val_mul, ":ai_shoot_range", 100),
  181.                     (val_div, ":ai_shoot_range", 115),
  182.                 (try_end),
  183.             (try_end),
  184.             (val_sub, ":ai_shoot_range", 300),            # 误差修正,单位:厘米
  185.             (try_begin),                                  # 根据武器精准度,计算更为精准的射程(ac_shoot_range)
  186.                 (eq, ":missile_accuracy", 0),
  187.                 (assign, ":missile_accuracy", 99),
  188.             (else_try),
  189.                 (val_abs, ":missile_accuracy"),
  190.                 (val_min, ":missile_accuracy", 100),
  191.             (try_end),
  192.             (store_mul, ":ac_shoot_range", ":ai_shoot_range", ":missile_accuracy"),
  193.             (val_mul, ":ac_shoot_range", ":missile_accuracy"),
  194.             (val_div, ":ac_shoot_range", 12500),                    # (射程 * 精准度 * 精准度) ÷10000 ×0.8
  195.             (val_sub, ":ac_shoot_range", 100),                      # 误差修正,单位:厘米
  196.             (try_begin),                                                # 若敌人数量过少,威胁过小,就更靠近射击
  197.                 (agent_is_ally, ":agent"),
  198.                 (val_min, ":ac_shoot_range", ":ally_cs_shoot_range"),
  199.             (else_try),
  200.                 (val_min, ":ac_shoot_range", ":enemy_cs_shoot_range"),
  201.             (try_end),
  202.             (store_sub, ":mv_shoot_range", ":ac_shoot_range", 300),        # 若敌人靠近,边后撤边射击的距离(mv_shoot_range)
  203.             (val_min, ":mv_shoot_range", 3000),                            # 30米视为安全距离,因为后续每次会撤退2米,而33米是最佳射击距离。 战团原版射击AI命中率 经不可靠测试,40米约为75%,45米约为36%,50米约为25% ……
  204.             (try_begin),
  205.                 (eq, ":action", 1),
  206.                 (agent_get_slot, ":fire_weapon_time", ":agent", 102),
  207.                 (neg|ge, ":fire_weapon_time", 6),
  208.                 (val_add, ":fire_weapon_time", 1),
  209.                 (try_begin),
  210.                     (gt, ":distance", ":ai_shoot_range"),                  # 若敌人脱离射程,取消射击
  211.                     (agent_set_attack_action, ":agent", -2, 0),
  212.                     (agent_set_defend_action, ":agent", 3, 1),
  213.                 (else_try),
  214.                     (neg|gt, ":distance", 700),                            # 若敌人就在眼前,下一刻立即射击
  215.                     (neg|eq, ":fire_weapon_time", 0),
  216.                     (assign, ":fire_weapon_time", -1),
  217.                 (else_try),
  218.                     (eq, ":fire_weapon_time", 0),                          # 瞄准时机已过,则开始射击
  219.                     (agent_set_defend_action, ":agent", -2, 1),
  220.                     (agent_set_attack_action, ":agent", 3, 0),
  221.                 (try_end),
  222.                 (agent_set_slot, ":agent", 102, ":fire_weapon_time"),
  223.             (else_try),
  224.                 (neg|gt, ":distance", ":ai_shoot_range"),
  225.                 (neg|eq, ":action", 5),
  226.                 (store_random_in_range, ":anim_random", 0, 100),           # 射击欲望,让想要射击的时机随机化
  227.                 (try_begin),
  228.                     (gt, ":distance", ":ac_shoot_range"),                  # 如果超出精准射程,降低射击欲望
  229.                     (val_sub, ":anim_random", 8),
  230.                 (else_try),
  231.                     (eq, ":action", 1),                                    # 如果是 弩、火器 有装填时间,对此补偿
  232.                     (val_add, ":anim_random", 15),
  233.                 (try_end),
  234.                 (ge, ":anim_random", 62),
  235.                 (agent_set_defend_action, ":agent", -2, 1),
  236.                 (agent_set_attack_action, ":agent", 3, 1),
  237.                 (2708, ":weapon_speed", ":weapon"),        # 武器速度
  238.                 (try_begin),                               # 根据前缀校准武器速度
  239.                     (eq, ":modifier", 17),            # - 精良的
  240.                     (val_add, ":weapon_speed", 1),
  241.                 (else_try),
  242.                     (eq, ":modifier", 19),            # - 坚硬的
  243.                     (val_sub, ":weapon_speed", 3),
  244.                 (else_try),
  245.                     (eq, ":modifier", 18),            # - 重
  246.                     (val_sub, ":weapon_speed", 2),
  247.                 (else_try),
  248.                     (eq, ":modifier", 13),            # - 平衡的
  249.                     (val_add, ":weapon_speed", 3),
  250.                 (try_end),
  251.                 (try_begin),                                               # 根据武器熟练度与武器速度,计算准心合拢时机
  252.                     (eq, ":type", 8),
  253.                     (store_mul, ":anim_delay_time", ":weapon_proficiency_level", 123),
  254.                     (val_div, ":anim_delay_time", 10),
  255.                     (val_add, ":anim_delay_time", 10000),
  256.                     (val_mul, ":anim_delay_time", ":weapon_speed"),
  257.                     (store_div, ":anim_delay_time", 1000000000, ":anim_delay_time"),
  258.                     (val_add, ":anim_delay_time", 1000),
  259.                 (else_try),
  260.                     (eq, ":type", 10),
  261.                     (store_mul, ":anim_delay_time", ":weapon_proficiency_level", 8),
  262.                     (val_add, ":anim_delay_time", 10000),
  263.                     (val_mul, ":anim_delay_time", ":weapon_speed"),
  264.                     (store_div, ":anim_delay_time", 640000000, ":anim_delay_time"),
  265.                     (val_add, ":anim_delay_time", 400),
  266.                 (else_try),
  267.                     (store_add, ":anim_delay_time", ":weapon_proficiency_level", 100),
  268.                     (store_div, ":anim_delay_time", 80000, ":anim_delay_time"),
  269.                     (val_add, ":anim_delay_time", 1100),
  270.                 (try_end),
  271.                 (store_random_in_range, ":anim_random", 50, 260),
  272.                 (val_add, ":anim_delay_time", ":anim_random"),
  273.                 (val_div, ":anim_delay_time", 300),                        # 在mst中触发频率为 300ms
  274.                 (try_begin),
  275.                     (neg|gt, ":distance", 3300),                           # 距离越近,命中率越高,不需要更多时间瞄准(允许更大的散射误差范围)
  276.                     (val_sub, ":anim_delay_time", 1),
  277.                 (try_end),
  278.                 (val_max, ":anim_delay_time", 1),
  279.                 (val_mul, ":anim_delay_time", -1),
  280.                 (agent_set_slot, ":agent", 102, ":anim_delay_time"),
  281.             (else_try),
  282.                 (eq, ":action", 1),
  283.                 (agent_set_attack_action, ":agent", -2, 0),
  284.                 (agent_set_defend_action, ":agent", 3, 300),
  285.             (else_try),
  286.                 (eq, ":action", 0),
  287.                 (agent_set_defend_action, ":agent", 3, 300),
  288.             (try_end),
  289.             (try_begin),
  290.                 (eq, ":action", 1),
  291.                 (gt, ":distance", 700),
  292.                 (agent_set_speed_limit, ":agent", 1),                   # 射击时减速(若依然在移动时)作为限制
  293.             (else_try),
  294.                 (agent_set_speed_limit, ":agent", 1000),
  295.             (try_end),
  296.             (try_begin),
  297.                 (eq, ":action", 5),                                     # 弩装填时,让 agent 立定,避免因移动打断装填
  298.                 (eq, ":type", 9),
  299.                 (agent_get_position, pos1, ":agent"),
  300.                 (agent_set_scripted_destination_no_attack, ":agent", pos1, 1),
  301.             (else_try),
  302.                 (eq, ":action", 1),                                     # 射击时,让 agent 立定,为了兼容火器(战团原版AI没有对火器的射击作处理)
  303.                 (store_random_in_range, ":anim_random", 0, 100),        # 给予一定几率慢速移动射击,避免一直站在原地(毕竟是在“冲锋”)
  304.                 (ge, ":anim_random", 2),
  305.                 (agent_get_position, pos1, ":agent"),
  306.                 (agent_set_scripted_destination_no_attack, ":agent", pos1, 1),
  307.             (else_try),
  308.                 (gt, ":distance", ":ac_shoot_range"),                   # 距离过远、超出精准射程,则靠近目标
  309.                 (agent_get_position, pos1, ":target"),
  310.                 (agent_set_scripted_destination_no_attack, ":agent", pos1, 1),
  311.             (else_try),
  312.                 (neg|gt, ":distance", ":mv_shoot_range"),               # 距离过近、在安全距离内,则后退两步
  313.                 (agent_get_position, pos1, ":agent"),
  314.                 (position_move_y, pos1, -200, 0),
  315.                 (agent_set_scripted_destination_no_attack, ":agent", pos1, 1),
  316.             (else_try),
  317.                 (neg|eq, ":action", 2),
  318.                 (store_random_in_range, ":anim_random", 0, 100),        # 若没有移动,且未射击,则随机移动
  319.                 (ge, ":anim_random", 50),
  320.                 (agent_get_position, pos1, ":agent"),
  321.                 (store_random_in_range, ":anim_random", -400, 401),
  322.                 (position_move_x, pos1, ":anim_random", 0),
  323.                 (store_random_in_range, ":anim_random", -200, 601),
  324.                 (position_move_y, pos1, ":anim_random", 0),
  325.                 (agent_set_scripted_destination_no_attack, ":agent", pos1, 1),
  326.             (try_end),
  327.             (try_begin),
  328.                 (neg|gt, ":distance", 500),                            # 敌人过于靠近,强制切换近战武器,以长度优先
  329.                 (assign, ":weapon_2", -1),
  330.                 (assign, ":weapon_quality", 0),
  331.                 (try_for_range, ":slot", 0, 4),
  332.                     (agent_get_item_slot, ":item", ":agent", ":slot"),
  333.                     (gt, ":item", 0),
  334.                     (item_get_type, ":type_2", ":item"),
  335.                     (this_or_next|eq, ":type_2", 2),
  336.                     (this_or_next|eq, ":type_2", 3),
  337.                     (eq, ":type_2", 4),
  338.                     (2707, ":weapon_length", ":item"),
  339.                     (gt, ":weapon_length", ":weapon_quality"),
  340.                     (assign, ":weapon_2", ":item"),
  341.                     (assign, ":weapon_quality", ":weapon_length"),
  342.                 (try_end),
  343.                 (agent_set_wielded_item, ":agent", ":weapon_2"),
  344.             (try_end),
  345.         (else_try),
  346.             (try_begin),
  347.                 (ge, ":target", 0),                                # 若有目标,只是被障碍物挡住了,则向目标靠近
  348.                 (agent_get_position, pos1, ":target"),
  349.                 (agent_set_scripted_destination_no_attack, ":agent", pos1, 1),
  350.                 (agent_get_slot, ":fire_weapon_time", ":agent", 102),
  351.                 (try_begin),
  352.                     (neg|ge, ":fire_weapon_time", 0),                    # 若目标丢失,则根据情况取消射击
  353.                     (val_add, ":fire_weapon_time", 1),
  354.                     (agent_set_slot, ":agent", 102, ":fire_weapon_time"),
  355.                 (else_try),
  356.                     (agent_set_speed_limit, ":agent", 1000),
  357.                     (eq, ":action", 1),
  358.                     (agent_set_attack_action, ":agent", -2, 0),
  359.                     (agent_set_defend_action, ":agent", 3, 1),
  360.                 (try_end),
  361.                 (try_begin),
  362.                     (2670, ":slot_max", ":agent"),                       # 尝试换一个视野中的其他目标
  363.                     (gt, ":slot_max", 1),
  364.                     (store_random_in_range, ":slot", 0, ":slot_max"),
  365.                     (2671, ":target", ":agent", ":slot"),
  366.                     (agent_is_alive, ":target"),
  367.                     (2076, 1, ":agent", 9, 1),
  368.                     (2076, 2, ":target", 9, 1),
  369.                     (position_has_line_of_sight_to_position, pos1, pos2),
  370.                     (agent_set_look_target_agent, ":agent", ":target"),
  371.                 (try_end),
  372.             (else_try),
  373.                 (agent_get_position, pos1, ":agent"),                    # 若没有目标,在原地等待筛选(避免战斗结束后依然往尸体目标处前行)
  374.                 (agent_get_scripted_destination, pos2, ":agent"),
  375.                 (get_distance_between_positions, ":distance", pos1, pos2),
  376.                 (try_begin),
  377.                     (gt, ":distance", 100),
  378.                     (agent_set_scripted_destination_no_attack, ":agent", pos1, 1),
  379.                     (agent_force_rethink, ":agent"),
  380.                     (agent_set_slot, ":agent", 102, 7),
  381.                 (else_try),
  382.                     (agent_get_slot, ":fire_weapon_time", ":agent", 102),
  383.                     (neg|ge, ":fire_weapon_time", 7),
  384.                     (agent_set_slot, ":agent", 102, 7),
  385.                 (else_try),
  386.                     (neg|eq, ":action", 5),
  387.                     (eq, ":fire_weapon_time", 7),
  388.                     (agent_set_attack_action, ":agent", -2, 0),
  389.                     (agent_set_defend_action, ":agent", 3, 1),
  390.                     (agent_set_speed_limit, ":agent", 1000),
  391.                     (agent_clear_scripted_mode, ":agent"),               # 退出 script mode (用于战斗结束后响应欢呼动作)
  392.                     (agent_force_rethink, ":agent"),
  393.                     (agent_set_slot, ":agent", 102, 8),
  394.                 (try_end),
  395.             (try_end),
  396.         (try_end),
  397.     (else_try),
  398.         (agent_slot_eq, ":agent", 100, 1),                            # 结束此AI
  399.         (agent_set_slot, ":agent", 100, 0),
  400.         (agent_set_attack_action, ":agent", -2, 0),
  401.         (agent_set_defend_action, ":agent", -2, 0),     # 不能持盾的远程武器 因切换指令(如 冲锋 -> 坚守)而退出此AI,须解除防御行为,否则会 因未做出1ms的防御动作 而卡住不攻击
  402.         (try_begin),
  403.             (agent_slot_eq, ":agent", slot_agent_is_not_reinforcement, 0),   # 若未触发 泡菜 野战敌方陷入混乱AI,则清除脚本设置;否则由 陷入混乱AI 继续接管
  404.             (agent_set_speed_limit, ":agent", 1000),
  405.             (agent_clear_scripted_mode, ":agent"),
  406.             (agent_ai_get_look_target, ":target", ":agent"),             # 若目标在近距离,则让 agent 强制重新思考 以进入近战模式;
  407.             (gt, ":target", -1),                                         # 否则让 agent 自然更新思考,避免频繁切换武器(agent_force_rethink 的 bug)
  408.             (agent_get_horse, ":agent_horse", ":target"),                # 同时针对 agent 拥有 长杆武器 与 远程武器 去对抗 骑马敌人 时,避免频繁切换武器
  409.             (eq, ":agent_horse", -1),
  410.             (2076, 1, ":agent", 9, 1),
  411.             (2076, 2, ":target", 9, 1),
  412.             (get_distance_between_positions, ":distance", pos1, pos2),
  413.             (neg|gt, ":distance", 500),
  414.             (agent_force_rethink, ":agent"),
  415.         (try_end),
  416.     (try_end),
  417. (try_end),
复制代码

(点击展开 / 收起)


战团AI射程测试.rar (19.32 KB, 下载次数: 99)







18

主题

247

回帖

125

积分

见习骑士

Rank: 3

UID
1404850
第纳尔
895
精华
0
互助
9
荣誉
0
贡献
0
魅力
14
注册时间
2013-6-9
鲜花(50) 鸡蛋(0)
 楼主| 发表于 2025-5-31 04:49:07 | 显示全部楼层
本帖最后由 jackjian321 于 2025-5-31 13:04 编辑

关于下雨,泡菜【黎明时代】版本里,用一套新的算法来代替 战团引擎 的下雨机制。

(点击展开 / 收起)





232

主题

3065

回帖

1629

积分

骑士长

中级译典官

Rank: 5Rank: 5Rank: 5

UID
2572488
第纳尔
4662
精华
0
互助
122
荣誉
3
贡献
355
魅力
316
注册时间
2015-8-1

骑砍中文站APP会员勋章原版正版勋章战团正版勋章火与剑正版勋章拿破仑正版勋章维京征服正版勋章汉匈决战正版勋章霸主正版勋章骑士美德之英勇勋章[杰出会员活跃勋章]骑士美德之仁慈勋章[杰出会员互助勋章]骑士美德之奉献勋章元老骑士勋章丝绸之路勋章

QQ
鲜花(428) 鸡蛋(200)
发表于 2025-5-31 11:30:57 来自手机 | 显示全部楼层
好东西啊,支持一下来自: iPhone客户端

28

主题

405

回帖

130

积分

见习骑士

Rank: 3

UID
3452728
第纳尔
233
精华
0
互助
0
荣誉
0
贡献
0
魅力
4
注册时间
2022-12-3
鲜花(5) 鸡蛋(0)
发表于 2025-5-31 16:57:34 | 显示全部楼层
之前听说有些使用步射ai的mod,容易被几个轻骑甚至步兵吓得整组经常移动,无法有效射击?

18

主题

247

回帖

125

积分

见习骑士

Rank: 3

UID
1404850
第纳尔
895
精华
0
互助
9
荣誉
0
贡献
0
魅力
14
注册时间
2013-6-9
鲜花(50) 鸡蛋(0)
 楼主| 发表于 2025-5-31 20:25:12 | 显示全部楼层
本帖最后由 jackjian321 于 2025-5-31 20:29 编辑
gzfh 发表于 2025-5-31 16:57
之前听说有些使用步射ai的mod,容易被几个轻骑甚至步兵吓得整组经常移动,无法有效射击? ...

目前我这边测试下来这个问题表现还行,
单个士兵,如果对方骑兵接近,会切近战武器,然后观望2秒,如果敌人还是很靠近就进入近战,否则尝试后退并切换远程武器。
如果对方步兵接近,直接切近战武器,并且开始进入近战。

对于部队,一部分士兵会按上述方式切为近战,其余士兵会边后退边继续射击。

因为步兵容易追击,而骑兵不容易追击(除非骑兵自己停下来打肉搏)。
可惜由于 force_agent_rethink 代码的bug,没法在更合适的地方使用,只能让战团原版AI自然思考。


你可以在完成主线剧情后(包括针对拉格纳国王的行动),可在 禅达 找 普林斯/军需官 对话,在 特殊战斗回顾模式 中,选择 军事演练 即可开启自定义战场。
然后设置 100维吉亚弓箭大师 vs 100芮尔典皇家骑士 或 100诺德圣堂卫士,地图选 图尔布克草原,看看表现如何。

如果是v1.22版本,数值还没平衡过,弓箭数值太高,应该维大师能战胜。
如果是v1.23版本,数值平衡过了,维大师应该打不过。
不过这张地图在射手对射时,玩家一方的地形会产生小优,可惜我不会做地形,没法处理这个问题。


23

主题

505

回帖

168

积分

见习骑士

Rank: 3

UID
3318406
第纳尔
1134
精华
0
互助
2
荣誉
0
贡献
0
魅力
2
注册时间
2022-1-26
鲜花(10) 鸡蛋(0)
发表于 2025-5-31 22:55:09 来自手机 | 显示全部楼层
这群就是菱角大佬修改添加的光明与黑暗讨论群,需要加群的扫码就行
20250531225417front2_0_3318406_Fs92wweY6oVN6wqBM4Qp9q57OHuW.jpg
来自: Android客户端

23

主题

505

回帖

168

积分

见习骑士

Rank: 3

UID
3318406
第纳尔
1134
精华
0
互助
2
荣誉
0
贡献
0
魅力
2
注册时间
2022-1-26
鲜花(10) 鸡蛋(0)
发表于 2025-6-1 07:08:49 来自手机 | 显示全部楼层
扣扣号码779053975来自: Android客户端

28

主题

405

回帖

130

积分

见习骑士

Rank: 3

UID
3452728
第纳尔
233
精华
0
互助
0
荣誉
0
贡献
0
魅力
4
注册时间
2022-12-3
鲜花(5) 鸡蛋(0)
发表于 2025-6-1 07:11:45 | 显示全部楼层
太牛了

34

主题

175

回帖

103

积分

见习骑士

Rank: 3

UID
2827349
第纳尔
1881
精华
0
互助
8
荣誉
0
贡献
0
魅力
21
注册时间
2017-4-20
鲜花(12) 鸡蛋(0)
发表于 2025-6-4 17:20:49 | 显示全部楼层
不错的代码!学到了,我把预瞄AI加在里头,让射手无敌

18

主题

247

回帖

125

积分

见习骑士

Rank: 3

UID
1404850
第纳尔
895
精华
0
互助
9
荣誉
0
贡献
0
魅力
14
注册时间
2013-6-9
鲜花(50) 鸡蛋(0)
 楼主| 发表于 2025-6-7 20:38:37 | 显示全部楼层
他年我若为青帝 发表于 2025-6-4 17:20
不错的代码!学到了,我把预瞄AI加在里头,让射手无敌

如果是君悦自瞄,最好确保计算期间数值不要太高,战团原版var是32位int,数值超过21亿就会出现偏差
(例如 13628227602 会变成 743325714),即便后续会作除法也不会校正。
尤其其中用到的浮点倍率是10000(我个人感觉100就够了,不过即便如此在15强弓或高弹速的情况下依然可能溢出,或者放弃 厘米 改为 米 来计算,这样就没问题,但会造成精度丢失)。

如果是WSE2则没有这个问题。


另外,我对君悦自瞄有个补充,如果计算后的弹速大于 7071 厘米/秒 ,由于箭矢飞行10秒后会消失,所以实际射程并非 v*v/g ,而是 10*√(v*v-25*g*g) ,单位都取 厘米/秒。

以此作为一个检测,判断目标是否处于射程内。
不过这只是一个射程范围判断,用于计算仰角高度距离的 delta 用的都是 v*v/g 的最大预计射程来计算。
而且如果用战团AI射程、而非真实射程,那基本达不到那么远的距离,可以忽略。

28

主题

405

回帖

130

积分

见习骑士

Rank: 3

UID
3452728
第纳尔
233
精华
0
互助
0
荣誉
0
贡献
0
魅力
4
注册时间
2022-12-3
鲜花(5) 鸡蛋(0)
发表于 2025-6-12 13:24:35 来自手机 | 显示全部楼层
可以做个骑射ai一键添加器吗?

3

主题

157

回帖

48

积分

扈从

自由骑士
战团ID:IB_ran

Rank: 2Rank: 2

UID
1495819
第纳尔
228
精华
0
互助
0
荣誉
0
贡献
0
魅力
0
注册时间
2013-8-20

骑砍中文站APP会员勋章战团正版勋章维京征服正版勋章霸主正版勋章元老骑士勋章

鲜花(14) 鸡蛋(0)
发表于 2025-6-12 20:51:43 | 显示全部楼层
厉害了厉害了
实力不详,遇强则强

28

主题

405

回帖

130

积分

见习骑士

Rank: 3

UID
3452728
第纳尔
233
精华
0
互助
0
荣誉
0
贡献
0
魅力
4
注册时间
2022-12-3
鲜花(5) 鸡蛋(0)
发表于 2025-6-12 22:06:14 | 显示全部楼层
gzfh 发表于 2025-6-12 13:24
可以做个骑射ai一键添加器吗?

呃我是幻想要是有骑兵也能用你这套支持弓弩投的ai,而且可以让我这样的小白一键安装就好了

18

主题

247

回帖

125

积分

见习骑士

Rank: 3

UID
1404850
第纳尔
895
精华
0
互助
9
荣誉
0
贡献
0
魅力
14
注册时间
2013-6-9
鲜花(50) 鸡蛋(0)
 楼主| 发表于 2025-6-15 19:50:07 | 显示全部楼层
gzfh 发表于 2025-6-12 22:06
呃我是幻想要是有骑兵也能用你这套支持弓弩投的ai,而且可以让我这样的小白一键安装就好了 ...

我不想搞这个,
你跟你想玩的mod作者说吧,君悦的源码公开的,而且我也在那篇帖子后面留下了我对于骑射AI支持弩、投掷、火器的一些修改源码。
您需要登录后才可以回帖 登录 | 注册(Register!)

本版积分规则

Archiver|手机版|小黑屋|骑马与砍杀中文站

GMT+8, 2025-12-6 01:01 , Processed in 0.120175 second(s), 30 queries , Gzip On, MemCached On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表