逆向:程序研究/AT1/事件处理例程
AT的事件处理/触发例程。
AT有一个EventCheck函数来检查事件的触发。该例程接受一个枚举值来确认触发的类型。
EventCheck 通常由一个包装函数调用,该包装函数会设置触发类型的枚举值。并对另一参数设定一个值。
EventCheck
日版地址:197214。
首先读取半字A7A7C8,如果大于0则表示事件执行中,该函数会报错:Event Doing... EventCheck Canceled. %d并退出。%d为此次触发的事件类型,是ECC枚举值的数值表示。
如果提供的检查参数大于等于 ECC_ALL,则不进行判断,直接开始事件执行【?需要检查】 、
a3 - 若为0 ,则EventCheck不会调用EventExecFile。
EventCheck检查一个EventCondList,EventCondList和evd一一对应。每个EventCondList记录对应一个evd的触发条件。
ECC 枚举值
- ECC_WORLDMAP
- ECC_WORLDMAP_P
- ECC_WORLDMAP_A
- ECC_GET_ITEM
- ECC_QVM QvMap任何事件触发时触发
- ECC_MIX
- ECC_PROGRAM
- ECC_TOWN
- ECC_QVM_CHG :QvMap 变更时触发。a1:变更前地图编号,a2:变更后地图编号,a3:总是为1
- ECC_QVM_CHG_BEFORE
- ECC_QVM_T
- ECC_QVM_T_BEFORE
- ECC_EVENT_END
- ECC_W_QVM
- ECC_W_QVM_BEFORE
- ECC_QVM_W_BEFORE
- ECC_W_T
- ECC_T_W
- ECC_T_W_BEFORE
- ECC_T_QVM
- ECC_T_QVM_BEFORE
- ECC_QVCHARA
- ECC_QVG_HIT
- ECC_QVG_BREAK
- ECC_QVG_EXEC
- ECC_SHOP_END
- ECC_WARP
- ECC_SPIRITUAL
- ECC_SPIRITUAL_IN
- ECC_SPIRITUAL_REJECT
- ECC_SPIRITUAL_OUT
- ECC_TALK
- ECC_SLEEP
- ECC_ALL
- ECC_NO_CHECK
- MAX_ECC
EventCondList
日版位置:0x74CA50
<struct name='EventTriggerGroup'> <field type='int8' name='grp' /> <field type='int8' name='enable' /> <field type='int8' name='repeatable' /> <field type='int8' name='qvtrigger' /> <field type='int8' name='ukn_flg1' /> <field type='int8' name='ukn_flg2' /> <field type='int8' name='rt_chk_flg' /> <field type='int8' name='ukn_flg3' /> <field type='EventCond[]*' name='grp1' /> <field type='EventCond[]*' name='grp2' /> <field type='EventCond[]*' name='grp3' /> <field type='EventCond[]*' name='grp4' /> <field type='EventCond[]*' name='grp5' /> </struct>
grp,编组,目前不知道有何作用,似乎从未被使用(看上去可以用来优化判断??
enable,启用,未使用,所有事件都处于启用状态
repeatable,事件是否可重复触发。若为0则只可被触发一次。
qvtrigger?未确认,Qv上的检查检查此项,若为0则会忽略此触发。【在需要Qv触发的记录中找到0,该项可能有其他意义】
grp1-5,触发条件组。任意一组条件为真则该规则为真,触发对应事件。若为NULL则为假。(DNF
触发条件组
一个以0x7FFFFF49为结束的列表。0x7FFFFF00以上的为条件宏。后跟数量不定的参数。每个条件宏的求值结果均需为真则此条件组才为真。
触发条件宏
- EVENT_FLAG 检查指定事件的旗标是否设置
- EVENT_RISE 检查指定事件是否已经实行
- EVENT_RISE_N 检查指定事件是否尚未被实行
- EVENT_RISE_U 指定事件执行次数大于
- EVENT_RISE_D ~小于
- EVENT_RISE_EQ ~等于
- FRIEND_PRM_U
- FRIEND_PRM_D
- FRIEND_PRM_EQ
- ITEM_CNT_U 物品数量大于
- ITEM_CNT_D ~小于
- ITEM_CNT_EQ ~等于
- MYPARAM_U
- MYPARAM_D
- MYPARAM_EQ
- PARTY_EXIST 指定角色在队
- PARTY_EXIST_N 指定角色不在队
- QV
- QV_XYZ_AREA Qv地图XYZ区域
- FIELD_POINTER
- ASSIST_MIXING
- RT_GD_U
- RT_GD_D
- RT_GD_EQ
- RT_MP_U
- RT_MP_D
- RT_MP_EQ
- RT_MAGIC_Y
- RT_MAGIC_N
- RT_ACC_SLV_U
- RT_ACC_SLV_D
- RT_ACC_SLV_EQ
- MISYA_CHIBI 检查弥纱是否是小的
- MISYA_DEKA 检查弥纱是否是大的
- WIN_MIKO_U 检查光之巫女战胜次数大于
- WIN_MIKO_D ~小于
- WIN_MIKO_EQ ~等于
- ZTRG_ZTRG_FIELD
- ZTRG_ZTRG_FIELD_POINTER
- ZTRG_ZTRG_FIELD_POINTER_A
- ZTRG_ZTRG_ITEM_GET 获得指定物品触发
- ZTRG_ZTRG_MASTER_DIR_A
- ZTRG_ZTRG_MIX
- ZTRG_ZTRG_PROGRAM 由程序直接进行触发
- ZTRG_ZTRG_QV
- ZTRG_ZTRG_TOWN
- ZTRG_ZTRG_QV_A2B
- ZTRG_ZTRG_QV_TOWN_A2B
- ZTRG_ZTRG_QV_CHG
- ZTRG_ZTRG_QV_TOWN_CHG
- ZTRG_ZTRG_QV_BASE
- ZTRG_ZTRG_EVENT_FINISH
- ZTRG_ZTRG_QV_FROM_FIELD
- ZTRG_ZTRG_TOWN_FROM_FIELD
- ZTRG_ZTRG_QV_TO_FIELD
- ZTRG_ZTRG_FIELD_FROM_TOWN
- ZTRG_ZTRG_FIELD_TOWN_A2B
- ZTRG_ZTRG_QV_FROM_TOWN
- ZTRG_ZTRG_TOWN_QV_A2B
- ZTRG_ZTRG_QVC_XYZ 进入指定QvMap区域触发
- ZTRG_ZTRG_QVC_TALK
- ZTRG_ZTRG_QVC_TALK_XYZ
- ZTRG_ZTRG_SHOP_END 指定的商店触发
- ZTRG_ZTRG_WARP
- ZTRG_ZTRG_SLEEP
- ZTRG_ZTRG_GIMMICK_BREAK 场景(区域地图)物件被破坏时触发
- ZTRG_ZTRG_GIMMICK_ATTACK
- ZTRG_ZTRG_GIMMICK_EXEC 场景物件被调查时触发
- ZTRG_ZTRG_DPOINT_ACCESS
- ZTRG_ZTRG_SWORLD_ACCESS
- ZTRG_ZTRG_SWORLD_ACCESS_REJECT
- ZTRG_ZTRG_SWORLD_EXIT
- ZTRG_ZTRG_TALK_ON
EventExecFile
加载一个逆向:程序研究/AT1/Evd文件并执行其中的宏序列。
主动夜会话触发检查
夜会话也有一套触发检查用的数据。登记为mk_trig_metadata。还有触发之后的数据记录,MkTrigSaveData。
MkTrigSaveData
保存数据之一。位置可通过保存数据表确认。
struct MkTrigSaveDatum {uint32_t flg; uint32_t expire;}
记录两个数据。flg用于记录该事件是否被标记需要触发/抑制等信息。休息时检查这个标志,如果为2就会触发对应的对话。expire记录事件过期时间,和ManaClock做比较。ManaClock似乎总是0,该机制如何生效仍需进一步检查。
mk_trig_metadata
日版位置:0x7359B0
下记条件登记为-1的表示不检查此条件。
<struct name='MusumeKaiwaTrigCond'> <field type='uint16' name='character' /> <field type='uint16' name='mkdata_id' /> <!-- 触发时调用的mkdata,为-1表示不适用 --> <field type='uint16' name='evd_id' /> <!-- 触发时调用的evd,为-1表示不适用 --> <field type='uint16' name='chk_type' /> <!-- 类型?排他性标记?优先级? --> <field type='uint16' name='ukn' /> <field type='uint16' name='evd_not_cond' /> <!-- 抑制evd,为-1表示不检查。一旦指定evd被调用此会话就不再可以触发 --> <field type='uint16' name='evd_req_cond' /> <!-- 前置evd,为-1表示不检查,否则前置evd必须首先运行才可触发本会话 --> <field type='uint16' name='ukn' /> <field type='uint16' name='ukn' /> <field type='uint16' name='para1' /> <!-- 含义变化的参数/chk_type==0xA, 持有指定物品 --> <field type='uint16' name='para2' /> <!-- 含义变化的参数/check_tyep==0xA时:持有指定数量 --> </struct>
chk_type
方式1
计算和RT对应的TriggerData中,连续五个字节的记录值【现在推定为过去5次战斗消耗的MP的百分比】,小于para1的个数。计数结果若小于para2,则不动作。否则设定对应项为准备触发。
- para1 比较对象(标记需要小于此值才通过)
- para2 数量要求
方式10
检查物品ID为para1的物品数量是否有para2个。若有则标记需要触发。