AntiN0m1
AntiN0m1
当前离线
好友6
在线时间0 小时
最后登录2026-1-27
10
主题92
回帖56
积分
扈从
扈从, 积分 56, 距离下一级还需 43 积分
扈从, 积分 56, 距离下一级还需 43 积分
UID3713555
第纳尔227
精华0
互助3
荣誉1
贡献0
魅力230
注册时间2024-11-10
发消息
鲜花(20) 鸡蛋(0)
电梯直达
1楼
发表于 2024-12-10 20:28:54
|
只看该作者
|倒序浏览
|阅读模式
本帖最后由 AntiN0m1 于 2024-12-28 18:54 编辑
大家是否遇到过这种情况:单刷时每招一个NPC就让他出去宣传或收集情报,回来了再把他送出去。时间久了就会发现,执行完任务归队的NPC总是任务列表最后的三四个人,其他人就没回来过。你再想让排在前面的人去做宣传,或者想等一个特定的NPC归队先给他练级,只能先把后面的NPC留在队里几天。
造成这种情况的原因是什么呢?我们先看一个每小时1次的简单触发器,在module_simple_triggers.py中找到以下代码:
(点击展开 / 收起)
#NPC changes begin
#Resolve one issue each hour
(1,
[
(str_store_string, s51, "str_no_trigger_noted"),
# Rejoining party
(try_begin),
(gt, "$npc_to_rejoin_party", 0), ##有NPC要归队
(eq, "$g_infinite_camping", 0), ##不在无限露营
(try_begin), ##NPC可以归队的条件
(neg|main_party_has_troop, "$npc_to_rejoin_party"), ##玩家队伍没有该NPC
(neq, "$g_player_is_captive", 1), ##玩家不是俘虏
(str_store_string, s51, "str_triggered_by_npc_to_rejoin_party"),
(assign, "$npc_map_talk_context", slot_troop_days_on_mission),
(start_map_conversation, "$npc_to_rejoin_party", -1), ##触发归队对话
(else_try), ##NPC暂不能归队
(troop_set_slot, "$npc_to_rejoin_party", slot_troop_current_mission, npc_mission_rejoin_when_possible),
(assign, "$npc_to_rejoin_party", 0),
(try_end),
# Here do NPC that is quitting
(else_try),
#略
#略
#略
]),复制代码
可以看到,在# Rejoining party这一段控制着NPC的归队。有一个关键的全局变量$npc_to_rejoin_party,这是准备归队的NPC的id。
触发归队对话后,在module_dialogs.py里会有(assign, "$npc_to_rejoin_party", 0)将其清零。我们需要找到它是在哪设置的。
打开module_triggers.py找到以下冷却时间为1天的触发器:
(点击展开 / 收起)
#Process morale and determine personality clashes
(0, 0, 24,[],
[
#略
#略
#略
(try_for_range, ":npc", companions_begin, companions_end), ##循环所有NPC
###Reset meeting variables
#略
#略
#略
#Check for quitting
(try_begin),
(main_party_has_troop, ":npc"),
#略
#略
#略
#main party does not have troop, and the troop is a companion ##同伴NPC不在玩家部队
(else_try),
(neg|main_party_has_troop, ":npc"),
(eq, ":occupation", slto_player_companion),
(troop_get_slot, ":days_on_mission", ":npc", slot_troop_days_on_mission),
(try_begin), ##任务天数大于0时,天数减1。影响天数的好像不止这一处。
(gt, ":days_on_mission", 0),
(val_sub, ":days_on_mission", 1),
(troop_set_slot, ":npc", slot_troop_days_on_mission, ":days_on_mission"),
(else_try), ##任务天数等于0。任务天数刚变成0的那天NPC是不会回来的,方法1会自然修复这一问题。
(troop_slot_ge, ":npc", slot_troop_current_mission, 1),
#If the hero can join ##判断NPC能否归队
(this_or_next|neg|troop_slot_eq, ":npc", slot_troop_current_mission, npc_mission_rejoin_when_possible),
(hero_can_join, ":npc"),
(assign, "$npc_to_rejoin_party", ":npc"), ##设置归队NPC的id,罪魁祸首
(try_end),
(try_end),
(try_end),
]),复制代码
可以看到,每循环一个NPC,如果他能归队,就会把$npc_to_rejoin_party设置成他,如此以来id越靠后的NPC就会优先归队。又因为触发器每天只触发1次,所以NPC一多,前面的人还没回来,后面的人就又回来了。
原因找到了,现在该如何解决呢?自然会想到记录NPC离队的顺序,我选择用部队记录,把NPC按顺序加入一个记录部队,归队时让记录部队的第一个NPC回来然后删掉。具体实现方法我给出2种。
方法1:
第一步:在module_parties.py里创建一个记录部队,以那些用于计算的部队为模板,如"temp_casualties",和它们放在一起,也就是"zendar"的上面:
("npcs_on_missions","{!}npcs_on_missions",pf_disabled, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(1,1),[]),
第二步:在NPC外出执行任务时把他加入记录部队,这个在原版战团中比较简单,只在module_dialogs.py中有3处:
1.宣传统治权:[anyone,"member_kingsupport_4", [略],
2.收集情报:[anyone,"member_intelgathering_4", [略],
3.派遣使者:[anyone|plyr, "minister_diplomatic_dispatch_confirm",[], "Yes, do that", "minister_pretalk",[略],
只需要在[略]中找到:
(remove_member_from_party, <代表NPC的id的变量>, "p_main_party"),
在下面加上以下一句即可:
(party_add_members, "p_npcs_on_missions", <代表NPC的id的变量>, 1),
这种方法略显繁琐,而且每个mod可能不同。你如果不喜欢可以看方法2。
第三步:设置$npc_to_rejoin_party。在module_triggers.py的那段代码中作如下修改:
(点击展开 / 收起)
(try_begin),
(gt, ":days_on_mission", 0),
(val_sub, ":days_on_mission", 1),
(troop_set_slot, ":npc", slot_troop_days_on_mission, ":days_on_mission"),
# (else_try), ##注释掉原方法
# (troop_slot_ge, ":npc", slot_troop_current_mission, 1),
# #If the hero can join
# (this_or_next|neg|troop_slot_eq, ":npc", slot_troop_current_mission, npc_mission_rejoin_when_possible),
# (hero_can_join, ":npc"),
# (assign, "$npc_to_rejoin_party", ":npc"),
(try_end),
(try_end),
(try_end),
#在所有NPC的循环之外加上:
###(((方法1
(party_get_num_companion_stacks, ":num_stacks", "p_npcs_on_missions"),
(try_for_range, ":cur_stack", 0, ":num_stacks"), ##循环记录部队的兵种
(party_stack_get_troop_id, ":npc", "p_npcs_on_missions", ":cur_stack"),
##判断NPC能否归队
(troop_slot_eq, ":npc", slot_troop_days_on_mission, 0),
(troop_slot_ge, ":npc", slot_troop_current_mission, 1),
(this_or_next|neg|troop_slot_eq, ":npc", slot_troop_current_mission, npc_mission_rejoin_when_possible),
(hero_can_join, ":npc"),
(assign, "$npc_to_rejoin_party", ":npc"),
(assign, ":num_stacks", 0), ##跳出循环
(try_end),
###)))
]),
复制代码
第四步:在NPC触发归队对话的时候从记录部队把他删掉。在module_simple_triggers.py的那段代码中插入###(((方法1)))这一句:
(点击展开 / 收起)
(assign, "$npc_map_talk_context", slot_troop_days_on_mission),
(party_remove_members, "p_npcs_on_missions", "$npc_to_rejoin_party", 1), ###(((方法1)))
(start_map_conversation, "$npc_to_rejoin_party", -1),复制代码
方法2:
第一步:与方法1相同,作为区别名字改一下:
("npcs_days_on_mission_0","{!}npcs_days_on_mission_0",pf_disabled, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(1,1),[]),
第二步:在任务天数减为0时将NPC加入记录部队,然后设置$npc_to_rejoin_party。在module_triggers.py的那段代码中作如下修改:
(点击展开 / 收起)
(try_begin),
(gt, ":days_on_mission", 0),
(val_sub, ":days_on_mission", 1),
(troop_set_slot, ":npc", slot_troop_days_on_mission, ":days_on_mission"),
# (else_try), ##注释掉原方法
# (troop_slot_ge, ":npc", slot_troop_current_mission, 1),
# #If the hero can join
# (this_or_next|neg|troop_slot_eq, ":npc", slot_troop_current_mission, npc_mission_rejoin_when_possible),
# (hero_can_join, ":npc"),
# (assign, "$npc_to_rejoin_party", ":npc"),
###(((方法2,将任务天数为0的NPC加入记录部队
(else_try),
(assign, ":add_num", 1),
(party_get_num_companion_stacks, ":num_stacks", "p_npcs_days_on_mission_0"),
(try_for_range, ":cur_stack", 0, ":num_stacks"), ##判断记录部队中有没有此NPC,若有则不加入
(party_stack_get_troop_id, ":cur_stack_id", "p_npcs_days_on_mission_0", ":cur_stack"),
(eq, ":npc", ":cur_stack_id"),
(assign, ":add_num", 0),
(assign, ":num_stacks", 0),
(try_end),
(eq, ":add_num", 1),
(party_add_members, "p_npcs_days_on_mission_0", ":npc", ":add_num"),
###)))
(try_end),
(try_end),
(try_end),
#在所有NPC的循环之外加上:
###(((方法2
(party_get_num_companion_stacks, ":num_stacks", "p_npcs_days_on_mission_0"),
(try_for_range, ":cur_stack", 0, ":num_stacks"), ##循环记录部队的兵种
(party_stack_get_troop_id, ":npc", "p_npcs_days_on_mission_0", ":cur_stack"),
##判断NPC能否归队
(troop_slot_eq, ":npc", slot_troop_days_on_mission, 0), ##可以删除此行
(troop_slot_ge, ":npc", slot_troop_current_mission, 1),
(this_or_next|neg|troop_slot_eq, ":npc", slot_troop_current_mission, npc_mission_rejoin_when_possible),
(hero_can_join, ":npc"),
(assign, "$npc_to_rejoin_party", ":npc"),
(assign, ":num_stacks", 0), ##跳出循环
(try_end),
###)))
]),复制代码
第三步:与方法1第四步相同。在module_simple_triggers.py的那段代码中插入###(((方法2)))这一句:
(点击展开 / 收起)
(assign, "$npc_map_talk_context", slot_troop_days_on_mission),
(party_remove_members, "p_npcs_days_on_mission_0", "$npc_to_rejoin_party", 1), ###(((方法2)))
(start_map_conversation, "$npc_to_rejoin_party", -1),复制代码
总结:
方法1可以严格区分任意NPC离队的顺序,但有点繁琐,适合强迫症。方法2不能区分任务天数在同一天减为0的NPC顺序,会将其按照id正序排列。但两者在实战中几乎没有区别,都能达到目的。我更推荐方法2,改的地方少,方便查错。
对于不开源的mod,方法2似乎可以用于魔球修改,我不太了解,欢迎熟悉魔球的大佬补充。