本帖最后由 武安apk43 于 2023-8-6 23:01 编辑
分享一下我的动态圈数和半径的圆阵算法,可能大佬有更优方案,欢迎提出见解。声明,下面代码由于关联到我的mod其他模块,所以不能直接复制粘贴,得根据需要自己改写。
首先是关系式:
其中S为分队士兵总数,r为最内圈半径,n为圈数,d为同圈相邻士兵间隔,D为相邻圈之间间隔。d应该与分散聚拢命令关联,命令的间隔差为50cm,D我设为了d/2。
脚本应该输入士兵人数、相邻士兵间隔、圈数和最内圈最大半径限制,圈数作为递归的变量参数,从1开始输入。计算得到最内圈半径,如果超出最内圈最大半径限制,则圈数+1,如此递归,直到满足条件输出最内圈半径和圈数。
script:
##Wuan
("calculate_formation_circle",
[
(store_script_param, ":num_troops", 1),
(store_script_param, ":distance", 2),
(store_script_param, ":circles", 3),
(store_script_param, ":first_circle_max_radius", 4),
(store_div, ":space_between_circles", ":distance", 2),
# num_troops = 2pi/distance*( first_circle_radius + (first_circle_radius + space_between_circles) + ... + (first_circle_radius + (circles -1)*space_between_circles) )
# = 2pi*circles/distance*( first_circle_radius + (circles - 1)*space_between_circles/2 )
# So: first_circle_radius = ( num_troops*distance/(2pi*circles) ) - ( (circles - 1)*space_between_circles/2 )
(store_mul, ":minuend", ":num_troops", ":distance"),
(val_mul, ":minuend", 100),
(val_div, ":minuend", Two_Hundred_Pi),
(val_div, ":minuend", ":circles"),
(store_sub, ":subtrahend", ":circles", 1),
(val_mul, ":subtrahend", ":space_between_circles"),
(val_div, ":subtrahend", 2),
(store_sub, ":first_circle_radius", ":minuend", ":subtrahend"),
(try_begin),
(gt, ":first_circle_radius", ":first_circle_max_radius"),
(val_add, ":circles", 1),# 圈数加1
(call_script, "script_calculate_formation_circle", ":num_troops", ":distance", ":circles", ":first_circle_max_radius"),# 递归
(else_try),
(assign, reg0, ":circles"),
(assign, reg1, ":first_circle_radius"),
# (try_begin),
# (ge, "$cheat_mode", 1),
# (display_message,"@circles:{reg0}, first circle radius:{reg1}"),
# (try_end),
(try_end),
]),
##Wuan
|
主要是通过圆心坐标不断旋转角度,然后前进半径。由于计算可能有误差,最后需将剩余士兵放在圆心。
代码:
(eq, ":infantry_formation", formation_circle),
(try_begin),
(eq, ":include_leader", 0),
(store_add, ":slot", slot_team_d0_first_member, ":fdivision"),
(team_set_slot, ":fteam", ":slot", -1),
(else_try), #after leader, move to next position (copied from below)
(team_set_slot, ":fteam", ":slot", ":fleader"),
(try_end),
(copy_position, pos2, pos1),
(call_script, "script_calculate_formation_circle", ":num_troops", ":distance", 1, 1000),
(assign, ":circles", reg0),
(assign, ":first_circle_radius", reg1),
(store_add, ":slot", slot_team_d0_formation_num_ranks, ":fdivision"),
(team_set_slot, ":fteam", ":slot", ":circles"),
(store_add, ":slot", slot_team_d0_first_circle_radius, ":fdivision"),
(team_set_slot, ":fteam", ":slot", ":first_circle_radius"),
(try_for_agents, ":agent"),
(call_script, "script_cf_valid_formation_member", ":fteam", ":fdivision", ":fleader", ":agent"),
(agent_set_slot, ":agent", slot_agent_positioned, 0),
(try_end),
(assign, ":fixed_point_multiplier", 1),
(convert_to_fixed_point, ":fixed_point_multiplier"),
(set_fixed_point_multiplier, 100),
(assign, ":cur_circle_radius", ":first_circle_radius"),
(try_for_range, ":cur_circle", 0, ":circles"),
(store_mul, ":cur_circle_num_troops", ":cur_circle_radius", Two_Hundred_Pi),
(val_div, ":cur_circle_num_troops", 100),
(val_div, ":cur_circle_num_troops", ":distance"),
# (try_begin),
# (ge, "$cheat_mode", 1),
# (assign, reg11, ":cur_circle"),
# (val_add, reg11, 1),
# (assign, reg12, ":cur_circle_num_troops"),
# (display_message, "@current circle:{reg11};cur circle num troops{reg12}"),
# (try_end),
(le, ":cur_circle_num_troops", ":num_troops"),
(store_div, ":base_angle", 36000, ":cur_circle_num_troops"),
(assign, ":positioned_num_agents", 0),
(try_for_agents, ":agent"),
(copy_position, pos3, pos2),
(lt, ":positioned_num_agents", ":cur_circle_num_troops"),
(call_script, "script_cf_valid_formation_member", ":fteam", ":fdivision", ":fleader", ":agent"),
(agent_slot_eq, ":agent", slot_agent_positioned, 0),
(store_mul, ":rotate_angle", ":positioned_num_agents", ":base_angle"),
(val_add, ":rotate_angle", ":base_angle"),
(position_rotate_z_floating, pos3, ":rotate_angle", 1),
(position_move_y, pos3, ":cur_circle_radius", 0),
(copy_position, pos1, pos3),
(try_begin),
(eq, "$battle_phase", BP_Deploy),
(agent_set_scripted_destination, ":agent", pos1),
(else_try),
(store_sub, ":rank", ":circles", ":cur_circle"),
(call_script, "script_formation_process_agent_move", ":fteam", ":fdivision", ":agent", ":rank"),
(try_end),
(try_begin),
(eq, formation_reequip, 1),
(eq, ":weapon_order", wordr_use_any_weapon),
(call_script, "script_equip_best_melee_weapon", ":agent", 1, 0, ":fire_order"), #best weapon, force shield
(try_end),
(agent_set_slot, ":agent", slot_agent_positioned, 1),
(val_add, ":positioned_num_agents", 1),
(eq, ":cur_circle", 0),
(agent_set_slot, ":agent", slot_agent_inside_formation, 1),
(try_end),
(val_add, ":cur_circle_radius", ":distance"),
(try_end),
(try_for_agents, ":agent"),
(call_script, "script_cf_valid_formation_member", ":fteam", ":fdivision", ":fleader", ":agent"),
(agent_slot_eq, ":agent", slot_agent_positioned, 0),
(copy_position, pos1, pos2),
(try_begin),
(eq, "$battle_phase", BP_Deploy),
(agent_set_scripted_destination, ":agent", pos1),
(else_try),
(store_add, ":rank", ":cur_circle", 1),
(call_script, "script_formation_process_agent_move", ":fteam", ":fdivision", ":agent", ":rank"),
(try_end),
(agent_set_slot, ":agent", slot_agent_positioned, 1),
(agent_set_slot, ":agent", slot_agent_inside_formation, 1),
(try_end),
(set_fixed_point_multiplier, ":fixed_point_multiplier"),
|
|