接上回 zhuanlan.zhihu.com/p/61

這回可很好的提高了生產力。現在使用正則表達式。和多行操作

將指令腳本 對應的case 轉換成了函數。

local t={}
t[0x000b]=walk_one_step
t[0x000c]=walk_one_step
t[0x000d]=walk_one_step
t[0x000e]=walk_one_step
t[0x000f]=set_the_direction
t[0x0010]=walk_straight_to_pos
t[0x0011]=walk_straight_to_pos_lower_speed
t[0x0012]=event_object_set_offset_pos
t[0x0013]=event_object_set_pos
t[0x0014]=event_object_set_gesture
t[0x0015]=player_set_direction_and_gesture
t[0x0016]=event_object_set_direction_and_gesture
t[0x0017]=player_set_extra_attribute --pointer to equipment item
t[0x0018]=equip_selected_item
t[0x0019]=player_compute_attribute
t[0x001a]=player_set_stat
t[0x001b]=player_modify_hp
t[0x001c]=player_modify_mp
t[0x001d]=player_modify_hp_and_mp
t[0x001e]=globals_set_cash_amount
t[0x001f]=add_item_to_inventory
t[0x0020]=remove_item_from_inventory --d.i =9999

t[0x0021]=inflict_damage_to_one_enemy -- battle serire need to bind
t[0x0022]=revive_player --need to bind new function
t[0x0023]=player_remove_equipment
t[0x0024]=evtobj_set_autoscript_entry_addr
t[0x0025]=evtobj_set_trigger_script_entry_addr
t[0x0026]=menu_buy_item_show
t[0x0027]=menu_sell_item_show
t[0x0028]=enemy_apply_poison --g_Battle (rgObject,getPoison )(get_rgEnemy,getPoisonItem )
t[0x0029]=player_apply_poison --must look PAL_RunTriggerScript below

t[0x002a]=enemy_cure_poison --Cure poison by object ID for enemy
t[0x002b]=player_cure_poison_by_id
t[0x002c]=player_cure_poison_by_level
t[0x002d]=player_set_status
t[0x002e]=enemy_set_status
t[0x002f]=player_remove_status

t[0x0030]=palyer_increase_stat_by_percent --temporarily
t[0x0031]=player_change_battle_sprite
--t[0x0032]=
t[0x0033]=enemy_collect_items
t[0x0034]=enemy_transform_collected_into_items
t[0x0035]=screen_shake
t[0x0036]=RNG_set_current_playering_animation
t[0x0037]=RNG_play_animation
t[0x0038]=party_teleport_out_of_scene
t[0x0039]=enemy_drain_HP
t[0x003a]=player_flee_frome_battle
--t[0x003b]=
--t[0x003c]=
--t[0x003d]=
--t[0x003e]=
t[0x003f]=evtobj_rided_to_pos_low_speed --at low speed
t[0x0040]=evtobj_set_trigger_method
t[0x0041]=script_marked_as_faild
t[0x0042]=player_simulate_a_magic
t[0x0043]=music_set_background
t[0x0044]=evtobj_rided_to_pos_normal_speed
t[0x0045]=music_set_battle
t[0x0046]=party_set_pos_on_map
t[0x0047]=sound_play_effect
--[0x0048]=
t[0x0049]=evtobj_set_state
t[0x004a]=battle_set_current_field
t[0x004b]=evtobj_set_nullify_short_while
t[0x004c]=monster_chase_player
t[0x004d]=sys_wait_for_any_key
t[0x004e]=sys_load_last_saved_game
t[0x004f]=sys_fade_screen_to_red_color --game over

t[0x0050]=screen_fade_out
t[0x0051]=screen_fade_in
t[0x0052]=evtobj_set_hide_for_a_while
t[0x0053]=palette_use_white_day
t[0x0054]=palette_use_night
t[0x0055]=player_add_magic
t[0x0056]=player_remove_magic
t[0x0057]=magic_set_base_damage --according to MP value
t[0x0058]=entry_jump_if_less_than_item_number --inventory
t[0x0059]=scene_change_to_specified
t[0x005a]=player_halve_HP
t[0x005b]=enemy_halve_HP
t[0x005c]=battle_hide_a_while
t[0x005d]=entry_jump_if_player_no_have_specified_poison
t[0x005e]=entry_jump_if_enemy_no_have_specified_poison
t[0x005f]=player_killed_immediately

t[0x0060]=enemy_Dead_immediate
t[0x0061]=entry_jump_if_player_no_poisoned
t[0x0062]=enemy_pause_chasing_a_while
t[0x0063]=enemy_speed_up_chasing_a_while
t[0x0064]=entry_jump_if_enemy_HP_more_than_percentage
t[0x0065]=player_set_sprite
t[0x0066]=player_throw_weapon_to_enemy
t[0x0067]=enemy_use_magic
t[0x0068]=entry_jump_if_is_enemy_turn
t[0x0069]=enemy_escape_in_battle
t[0x006a]=player_steal_from_enemy
t[0x006b]=enemy_blow_away
t[0x006c]=NPC_walk_in_one_step
t[0x006d]=scene_set_entry_and_teleport_script
t[0x006e]=player_move_to_pos_in_one_step
t[0x006f]=evtobj_sync_state_with_other

t[0x0070]=party_walk_to_pos
t[0x0071]=screen_wave
--t[0x0072]=
t[0x0073]=screen_fade_to_scene
t[0x0074]=entry_jump_if_all_players_no_full_HP
t[0x0075]=party_set_player
t[0x0076]=FBP_show_picture
t[0x0077]=music_stop_current_playing
t[0x0078]=no_happend --fix me
t[0x0079]=entry_jump_if_player_in_party
t[0x007a]=party_walk_to_pos_higher_speed
t[0x007b]=party_walk_to_pos_highest_speed
t[0x007c]=NPC_walk_straight_to_pos
t[0x007d]=evtobj_move
t[0x007e]=evtobj_set_layer
t[0x007f]=viewport_move

t[0x0080]=palette_toggle_day_or_night
t[0x0081]=entry_jump_if_player_not_facing_evtobj
t[0x0082]=NPC_walk_straight_to_pos_high_speed
t[0x0083]=entry_jump_if_evtobj_not_in_specified_zone_of_curr_evtobj
t[0x0084]=player_place_item_to_scene --item like a event object --found Z item
t[0x0085]=sys_delay_a_period
t[0x0086]=entry_jump_if_item_is_not_equipped
t[0x0087]=NPC_Animate_the_evtobj
t[0x0088]=magic_set_base_damage_look_at_amount_of_money
t[0x0089]=battle_set_result
t[0x008a]=battle_set_auto_next
t[0x008b]=palette_change_current
t[0x008c]=color_fade_from_or_to
t[0x008d]=player_increase_level
--t[0x008e]=
t[0x008f]=cash_halve_amount

t[0x0090]=object_set_script
t[0x0091]=entry_jump_if_enemy_not_alone
t[0x0092]=player_show_magic_casting_animation_in_battle
t[0x0093]=screen_fade_and_update_screen_in_process
t[0x0094]=entry_jump_if_evtobj_state_is_specified
t[0x0095]=entry_jump_if_scene_is_specified
t[0x0096]=sys_show_ending_animation
t[0x0097]=evtobj_rided_to_pos_higher_speed
t[0x0098]=party_set_follower
t[0x0099]=map_change_for_scene
t[0x009a]=evtobj_set_state_many
t[0x009b]=scene_fade_to_current
t[0x009c]=enemy_duplicate_itself -- copy itself to another just create new self
--t[0x009d]=
t[0x009e]=enemy_summons_another_monster -- Z all human
t[0x009f]=enemy_transforms_into_sth_else --wan thing changed

t[0x00a0]=sys_quit_game
t[0x00a1]=party_set_pos_to_same_as_first_one -- study_first
t[0x00a2]=entry_jump_to_one_in_following_instructions_randomly -- jump to
t[0x00a3]=music_play_CD
t[0x00a4]=FBP_scroll_to_screen
t[0x00a5]=FBP_show_picture_with_sprite_effects
t[0x00a6]=screen_backup

local dst =_G[fullNameOnClass]
if dst then
dst[dst_name]=t
end
return t

呵呵,函數源碼片段

很顯然,我們光看 這些數字0x00xx 根本不知道,調用了什麼函數。

所以說,用表做一個映射,直接通過正則表達式的方法來轉換一下。

就拿到了。

t[0x000b]={func=walk_one_step,name="walk_one_step" }
t[0x000c]={func=walk_one_step,name="walk_one_step" }
t[0x000d]={func=walk_one_step,name="walk_one_step" }
t[0x000e]={func=walk_one_step,name="walk_one_step" }
t[0x000f]={func=set_the_direction,name="set_the_direction" }
t[0x0010]={func=walk_straight_to_pos,name="walk_straight_to_pos" }
t[0x0011]={func=walk_straight_to_pos_lower_speed,name="walk_straight_to_pos_lower_speed" }
t[0x0012]={func=event_object_set_offset_pos,name="event_object_set_offset_pos" }
t[0x0013]={func=event_object_set_pos,name="event_object_set_pos" }
t[0x0014]={func=event_object_set_gesture,name="event_object_set_gesture" }
t[0x0015]={func=player_set_direction_and_gesture,name="player_set_direction_and_gesture" }
t[0x0016]={func=event_object_set_direction_and_gesture,name="event_object_set_direction_and_gesture" }
t[0x0017]={func=player_set_extra_attribute,name="player_set_extra_attribute" } --pointer to equipment item
t[0x0018]={func=equip_selected_item,name="equip_selected_item" }
t[0x0019]={func=player_compute_attribute,name="player_compute_attribute" }
t[0x001a]={func=player_set_stat,name="player_set_stat" }
t[0x001b]={func=player_modify_hp,name="player_modify_hp" }
t[0x001c]={func=player_modify_mp,name="player_modify_mp" }
t[0x001d]={func=player_modify_hp_and_mp,name="player_modify_hp_and_mp" }
t[0x001e]={func=globals_set_cash_amount,name="globals_set_cash_amount" }
t[0x001f]={func=add_item_to_inventory,name="add_item_to_inventory" }
t[0x0020]={func=remove_item_from_inventory,name="remove_item_from_inventory" } --d.i =9999

t[0x0021]={func=inflict_damage_to_one_enemy,name="inflict_damage_to_one_enemy" } -- battle serire need to bind
t[0x0022]={func=revive_player,name="revive_player" } --need to bind new function
t[0x0023]={func=player_remove_equipment,name="player_remove_equipment" }
t[0x0024]={func=evtobj_set_autoscript_entry_addr,name="evtobj_set_autoscript_entry_addr" }
t[0x0025]={func=evtobj_set_trigger_script_entry_addr,name="evtobj_set_trigger_script_entry_addr" }
t[0x0026]={func=menu_buy_item_show,name="menu_buy_item_show" }
t[0x0027]={func=menu_sell_item_show,name="menu_sell_item_show" }
t[0x0028]={func=enemy_apply_poison,name="enemy_apply_poison" } --g_Battle (rgObject,getPoison )(get_rgEnemy,getPoisonItem )
t[0x0029]={func=player_apply_poison,name="player_apply_poison" } --must look PAL_RunTriggerScript below

t[0x002a]={func=enemy_cure_poison,name="enemy_cure_poison" } --Cure poison by object ID for enemy
t[0x002b]={func=player_cure_poison_by_id,name="player_cure_poison_by_id" }
t[0x002c]={func=player_cure_poison_by_level,name="player_cure_poison_by_level" }
t[0x002d]={func=player_set_status,name="player_set_status" }
t[0x002e]={func=enemy_set_status,name="enemy_set_status" }
t[0x002f]={func=player_remove_status,name="player_remove_status" }

t[0x0030]={func=palyer_increase_stat_by_percent,name="palyer_increase_stat_by_percent" } --temporarily
t[0x0031]={func=player_change_battle_sprite,name="player_change_battle_sprite" }
--t[0x0032]=
t[0x0033]={func=enemy_collect_items,name="enemy_collect_items" }
t[0x0034]={func=enemy_transform_collected_into_items,name="enemy_transform_collected_into_items" }
t[0x0035]={func=screen_shake,name="screen_shake" }
t[0x0036]={func=RNG_set_current_playering_animation,name="RNG_set_current_playering_animation" }
t[0x0037]={func=RNG_play_animation,name="RNG_play_animation" }
t[0x0038]={func=party_teleport_out_of_scene,name="party_teleport_out_of_scene" }
t[0x0039]={func=enemy_drain_HP,name="enemy_drain_HP" }
t[0x003a]={func=player_flee_frome_battle,name="player_flee_frome_battle" }
--t[0x003b]=
--t[0x003c]=
--t[0x003d]=
--t[0x003e]=
t[0x003f]={func=evtobj_rided_to_pos_low_speed,name="evtobj_rided_to_pos_low_speed" } --at low speed
t[0x0040]={func=evtobj_set_trigger_method,name="evtobj_set_trigger_method" }
t[0x0041]={func=script_marked_as_faild,name="script_marked_as_faild" }
t[0x0042]={func=player_simulate_a_magic,name="player_simulate_a_magic" }
t[0x0043]={func=music_set_background,name="music_set_background" }
t[0x0044]={func=evtobj_rided_to_pos_normal_speed,name="evtobj_rided_to_pos_normal_speed" }
t[0x0045]={func=music_set_battle,name="music_set_battle" }
t[0x0046]={func=party_set_pos_on_map,name="party_set_pos_on_map" }
t[0x0047]={func=sound_play_effect,name="sound_play_effect" }
--[0x0048]=
t[0x0049]={func=evtobj_set_state,name="evtobj_set_state" }
t[0x004a]={func=battle_set_current_field,name="battle_set_current_field" }
t[0x004b]={func=evtobj_set_nullify_short_while,name="evtobj_set_nullify_short_while" }
t[0x004c]={func=monster_chase_player,name="monster_chase_player" }
t[0x004d]={func=sys_wait_for_any_key,name="sys_wait_for_any_key" }
t[0x004e]={func=sys_load_last_saved_game,name="sys_load_last_saved_game" }
t[0x004f]={func=sys_fade_screen_to_red_color,name="sys_fade_screen_to_red_color" } --game over

t[0x0050]={func=screen_fade_out,name="screen_fade_out" }
t[0x0051]={func=screen_fade_in,name="screen_fade_in" }
t[0x0052]={func=evtobj_set_hide_for_a_while,name="evtobj_set_hide_for_a_while" }
t[0x0053]={func=palette_use_white_day,name="palette_use_white_day" }
t[0x0054]={func=palette_use_night,name="palette_use_night" }
t[0x0055]={func=player_add_magic,name="player_add_magic" }
t[0x0056]={func=player_remove_magic,name="player_remove_magic" }
t[0x0057]={func=magic_set_base_damage,name="magic_set_base_damage" } --according to MP value
t[0x0058]={func=entry_jump_if_less_than_item_number,name="entry_jump_if_less_than_item_number" } --inventory
t[0x0059]={func=scene_change_to_specified,name="scene_change_to_specified" }
t[0x005a]={func=player_halve_HP,name="player_halve_HP" }
t[0x005b]={func=enemy_halve_HP,name="enemy_halve_HP" }
t[0x005c]={func=battle_hide_a_while,name="battle_hide_a_while" }
t[0x005d]={func=entry_jump_if_player_no_have_specified_poison,name="entry_jump_if_player_no_have_specified_poison" }
t[0x005e]={func=entry_jump_if_enemy_no_have_specified_poison,name="entry_jump_if_enemy_no_have_specified_poison" }
t[0x005f]={func=player_killed_immediately,name="player_killed_immediately" }

t[0x0060]={func=enemy_Dead_immediate,name="enemy_Dead_immediate" }
t[0x0061]={func=entry_jump_if_player_no_poisoned,name="entry_jump_if_player_no_poisoned" }
t[0x0062]={func=enemy_pause_chasing_a_while,name="enemy_pause_chasing_a_while" }
t[0x0063]={func=enemy_speed_up_chasing_a_while,name="enemy_speed_up_chasing_a_while" }
t[0x0064]={func=entry_jump_if_enemy_HP_more_than_percentage,name="entry_jump_if_enemy_HP_more_than_percentage" }
t[0x0065]={func=player_set_sprite,name="player_set_sprite" }
t[0x0066]={func=player_throw_weapon_to_enemy,name="player_throw_weapon_to_enemy" }
t[0x0067]={func=enemy_use_magic,name="enemy_use_magic" }
t[0x0068]={func=entry_jump_if_is_enemy_turn,name="entry_jump_if_is_enemy_turn" }
t[0x0069]={func=enemy_escape_in_battle,name="enemy_escape_in_battle" }
t[0x006a]={func=player_steal_from_enemy,name="player_steal_from_enemy" }
t[0x006b]={func=enemy_blow_away,name="enemy_blow_away" }
t[0x006c]={func=NPC_walk_in_one_step,name="NPC_walk_in_one_step" }
t[0x006d]={func=scene_set_entry_and_teleport_script,name="scene_set_entry_and_teleport_script" }
t[0x006e]={func=player_move_to_pos_in_one_step,name="player_move_to_pos_in_one_step" }
t[0x006f]={func=evtobj_sync_state_with_other,name="evtobj_sync_state_with_other" }

t[0x0070]={func=party_walk_to_pos,name="party_walk_to_pos" }
t[0x0071]={func=screen_wave,name="screen_wave" }
--t[0x0072]=
t[0x0073]={func=screen_fade_to_scene,name="screen_fade_to_scene" }
t[0x0074]={func=entry_jump_if_all_players_no_full_HP,name="entry_jump_if_all_players_no_full_HP" }
t[0x0075]={func=party_set_player,name="party_set_player" }
t[0x0076]={func=FBP_show_picture,name="FBP_show_picture" }
t[0x0077]={func=music_stop_current_playing,name="music_stop_current_playing" }
t[0x0078]={func=no_happend,name="no_happend" } --fix me
t[0x0079]={func=entry_jump_if_player_in_party,name="entry_jump_if_player_in_party" }
t[0x007a]={func=party_walk_to_pos_higher_speed,name="party_walk_to_pos_higher_speed" }
t[0x007b]={func=party_walk_to_pos_highest_speed,name="party_walk_to_pos_highest_speed" }
t[0x007c]={func=NPC_walk_straight_to_pos,name="NPC_walk_straight_to_pos" }
t[0x007d]={func=evtobj_move,name="evtobj_move" }
t[0x007e]={func=evtobj_set_layer,name="evtobj_set_layer" }
t[0x007f]={func=viewport_move,name="viewport_move" }

t[0x0080]={func=palette_toggle_day_or_night,name="palette_toggle_day_or_night" }
t[0x0081]={func=entry_jump_if_player_not_facing_evtobj,name="entry_jump_if_player_not_facing_evtobj" }
t[0x0082]={func=NPC_walk_straight_to_pos_high_speed,name="NPC_walk_straight_to_pos_high_speed" }
t[0x0083]={func=entry_jump_if_evtobj_not_in_specified_zone_of_curr_evtobj,name="entry_jump_if_evtobj_not_in_specified_zone_of_curr_evtobj" }
t[0x0084]={func=player_place_item_to_scene,name="player_place_item_to_scene" } --item like a event object --found Z item
t[0x0085]={func=sys_delay_a_period,name="sys_delay_a_period" }
t[0x0086]={func=entry_jump_if_item_is_not_equipped,name="entry_jump_if_item_is_not_equipped" }
t[0x0087]={func=NPC_Animate_the_evtobj,name="NPC_Animate_the_evtobj" }
t[0x0088]={func=magic_set_base_damage_look_at_amount_of_money,name="magic_set_base_damage_look_at_amount_of_money" }
t[0x0089]={func=battle_set_result,name="battle_set_result" }
t[0x008a]={func=battle_set_auto_next,name="battle_set_auto_next" }
t[0x008b]={func=palette_change_current,name="palette_change_current" }
t[0x008c]={func=color_fade_from_or_to,name="color_fade_from_or_to" }
t[0x008d]={func=player_increase_level,name="player_increase_level" }
--t[0x008e]=
t[0x008f]={func=cash_halve_amount,name="cash_halve_amount" }

t[0x0090]={func=object_set_script,name="object_set_script" }
t[0x0091]={func=entry_jump_if_enemy_not_alone,name="entry_jump_if_enemy_not_alone" }
t[0x0092]={func=player_show_magic_casting_animation_in_battle,name="player_show_magic_casting_animation_in_battle" }
t[0x0093]={func=screen_fade_and_update_screen_in_process,name="screen_fade_and_update_screen_in_process" }
t[0x0094]={func=entry_jump_if_evtobj_state_is_specified,name="entry_jump_if_evtobj_state_is_specified" }
t[0x0095]={func=entry_jump_if_scene_is_specified,name="entry_jump_if_scene_is_specified" }
t[0x0096]={func=sys_show_ending_animation,name="sys_show_ending_animation" }
t[0x0097]={func=evtobj_rided_to_pos_higher_speed,name="evtobj_rided_to_pos_higher_speed" }
t[0x0098]={func=party_set_follower,name="party_set_follower" }
t[0x0099]={func=map_change_for_scene,name="map_change_for_scene" }
t[0x009a]={func=evtobj_set_state_many,name="evtobj_set_state_many" }
t[0x009b]={func=scene_fade_to_current,name="scene_fade_to_current" }
t[0x009c]={func=enemy_duplicate_itself,name="enemy_duplicate_itself" } -- copy itself to another just create new self
--t[0x009d]=
t[0x009e]={func=enemy_summons_another_monster,name="enemy_summons_another_monster" } -- Z all human
t[0x009f]={func=enemy_transforms_into_sth_else,name="enemy_transforms_into_sth_else" } --wan thing changed

t[0x00a0]={func=sys_quit_game,name="sys_quit_game" }
t[0x00a1]={func=party_set_pos_to_same_as_first_one,name="party_set_pos_to_same_as_first_one" } -- study_first
t[0x00a2]={func=entry_jump_to_one_in_following_instructions_randomly,name="entry_jump_to_one_in_following_instructions_randomly" } -- jump to
t[0x00a3]={func=music_play_CD,name="music_play_CD" }
t[0x00a4]={func=FBP_scroll_to_screen,name="FBP_scroll_to_screen" }
t[0x00a5]={func=FBP_show_picture_with_sprite_effects,name="FBP_show_picture_with_sprite_effects" }
t[0x00a6]={func=screen_backup,name="screen_backup" }

這一套的好處,則是等我們要遍歷

遍歷了這個數組之後,會拿到所有的事件組合。將來可以用行為樹來表示,或者是狀態機。

通過遍歷這個數組,拿到的都是數字。我們根本不知道什麼含義。

但是通過映射表之後,把數字轉成了 funcname之後,就很輕鬆理解。

今天的這個進展,讓我感慨頗深。已經完全摸清了,全部腳本的架構。

腳本系統就是一棵樹,事件物體就是一個個枝幹,擁有多個事件。每個事件entry又擁有多個具體葉節點的操作。

  1. 事件物體,只是基層枝幹(場景內),
  2. 任務是中層(跨場景),主線和支線。
  3. 章節劇情是高層,擁有多個任務
  4. 主線和支線各擁有多個章節

這個我用圖片大致畫了圖片,基本就是這樣的了。

下面則是要繼續翻譯 指令函數,並且進行調試了。

目測代碼翻譯量可能要1-2個月。接近200個函數。

看一下,總腳本量,大約在42992個。

重複性很強啊

看來,這個應該用一個編輯器,來顯示效果更好

明白了這些數據結構,大家就心裡有數了

調整了一下,效果挺好的

可以看到大部分,還是對話,調整npc的朝向和姿勢

遊戲結束,居然放到了4000多行。說明布局的時候,先做的結束畫面

好了,進展不易,看到點贊吶。不點贊(這麼狠心)點個收藏也行。

慢慢就能夠追上 仙劍1各種mod的作者們的研究地步了,然後超越他們。仙劍1為什麼會是經典,他們根本不知道,經典該怎麼改,我覺得沒必要改。但是不看源碼,我敢說,沒人理解真的仙劍1。恐怕姚和謝都沒有辦法理解。

這真不是吹牛。後續的分析,請繼續觀看。

更新一下,補全 函數 和對話

這樣的話,更容易了解,仙劍的數據結構和演算法了。

腳本怎麼用的,現在都明白了。

邏輯好清晰。而且都是按順序進行的。

仙劍1絕對是 一個很好的把劇本寫成 代碼的很好的範例。用行為樹替換很輕鬆。

從源碼來看,原來設計是 多條線的,也就是多結局的。可能是多條主線。

最後給坎了成了一條主線。可見姚謝當年做遊戲有多艱苦,缺錢了,只能靠姚式刀法,仙劍變成了腦補過程和結局了。


推薦閱讀:
相关文章