// This file documents newserv's quest assembler syntax and format. This is a
// slightly modified copy of the English version of Sega's Lost HEAT SWORD quest
// for PSO GC.

// Generally the metadata directives should appear before the quest's code.
// These specify the quest's name, description, and other information.

// The .version directive specifies which version of the game the quest is for.
// The values are DC_NTE, DC_V1_11_2000_PROTOTYPE, DC_V1, DC_V2, PC_V2, GC_NTE,
// GC_V3, GC_EP3_NTE, GC_EP3, XB_V3, and BB_V4. This determines which set of
// opcodes to use during compilation, and also specifies the header format and
// string encoding. This does not affect where the quest appears in menus, so
// for versions that use the same opcodes, headers, and string encodings, it is
// OK to use a symbolic link (hence q058-xb-e.bin.txt is a link to this file).
.version GC_V3

// The .quest_num directive specifies the internal number of the quest. This
// has no meaning for online quests, though it's recommended for this value to
// match the number in the filename. For download quests, the game deduplicates
// quest files with the same number, so download quests should all have unique
// numbers in this field. On Episodes 1&2, this field must be in the range
// 0-255; on other versions, it can be 0-65535, but generally numbers less than
// 1000 are recommended.
.quest_num 58

// The .language field specifies the internal language of the quest. On console
// versions (DC, GC, and XB), this affects how strings are encoded - Japanese
// uses Shift-JIS and other languages use ISO8859. (On PC V2 and BB, UTF-16 is
// used for strings in all languages.) The language values are:
//   0 = Japanese
//   1 = English
//   2 = German
//   3 = French
//   4 = Spanish
//   5 = Chinese (simplified)
//   6 = Chinese (traditional)
//   7 = Korean
.language 1

// The .episode directive specifies the quest's episode. The server ignores this
// if a set_episode or set_episode2 opcode is present in the code following the
// start label.
.episode Episode1

// These directives specify the quest's name, short description, and long
// description. Non-ASCII characters can be used here and in the script below;
// this entire file is encoded as UTF-8 and strings are transcoded to the
// encoding the client expects based on the .version and .language directives.
// Common escape codes (e.g. \n for a newline) are supported in these strings.
.name "Lost HEAT SWORD"
.short_desc "Retrieve a\nweapon from\na Dragon!"
.long_desc "Client:  Hopkins, hunter\nQuest:\n My weapon was taken\n from me when I was\n fighting a Dragon.\nReward:  ??? Meseta\n\n\n"

// On BB, quests may specify a maximum number of players with this directive. If
// not given, the default is 4. On non-BB versions, this directive is ignored.
// .max_players 4

// On BB, quests may be joinable while in progress. This directive enables that
// capability.
// .joinable

// The quest script begins after the header directives. A quest script is a
// sequence of opcodes, and labels denoting positions within that sequence that
// can be jumped to or called like a function. All labels have names, and some
// have numbers. (In the compiled format, labels have only numbers and no names;
// during compilation, each label that doesn't have a number is assigned a
// number that isn't in use by another label.) To explicitly specify a label
// number (for example, if an object or NPC refers to a label by number), use an
// @ sign followed by the desired number. Note that numbers can be specified in
// decimal or hexadecimal; see on_talk_to_npc1 and on_talk_to_npc2 for examples.

// Registers may be named as well as labels. (In the compiled script, registers
// do not have names, so disassembling a quest script always produces only
// numbered registers.) When compiling, all of the following are valid:
//   r83                    (explicitly numbered register)
//   r:difficulty_level     (the compiler will assign an unused register number)
//   r:difficulty_level@83  (named and explicitly numbered)
// You don't always have to use the same form for each register; for example,
// if you use r:difficulty_level@83 anywhere in the quest script, you can also
// use r:difficulty_level and r83 in other places and they will all refer to the
// same register. (However, if you don't use r:difficulty_level@83 anywhere, but
// you do use r83 and r:difficulty_level, the compiler will assign these to two
// different registers since there is nothing linking the name to the number.)

// Using opcodes that take a consecutive sequence of registers, such as
// map_designate which takes 4, introduces constraints on which registers may be
// assigned to which numbers. For example, before one of the map_designate
// opcodes after the start label, we explicitly assign one register's number,
// but leave the nearby registers' numbers unassigned. The compiler assigns
// those four registers to r60-r63, because they are used in a map_designate
// call. If we didn't explicitly number any of those registers, the compiler
// would instead choose a consecutive sequence of register numbers that aren't
// used anywhere else in the script.

// This quest does not contain any examples of non-script data, but such data
// can be included in the quest script using the .data directive, like this:
//   hello_symbol_chat:
//     .data 28000000 FFFF 0D00 FFFF FFFF 05 18 1D 00 05 28 1D 01 36 20 2A 00 3C 00 32 00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00 02 FF 00 00 02 FF 00 00 02 FF 00 00 02 FF 00 00 02
// There is also a directive for including a large number of zero bytes:
//   lots_of_zeroes:
//     .zero 0x400  // 1024 bytes of zeroes

// Every quest must have a start label; this is the main thread that starts when
// the quest begins. The start label is always assigned number 0.
start:
  gget                            0x0091, r:flag_0091_value@252
  set_floor_handler               0, floor_handler_pioneer_2
  set_floor_handler               1, floor_handler_forest_1
  set_floor_handler               2, floor_handler_forest_2
  set_floor_handler               11, floor_handler_dragon
  set_qt_success                  on_quest_success
  get_difficulty_level_v2         r:difficulty_level@83
  leti                            r:op_arg1, 0 // Pioneer 2
  leti                            r:op_arg2, 0
  leti                            r:op_arg3@62, 0 // See comment above about register assignment
  leti                            r:op_arg4, 0
  map_designate                   (r:op_arg1, r:op_arg2, r:op_arg3, r:op_arg4)
  leti                            r:op_arg1, 1 // Forest 1
  leti                            r:op_arg2, 0
  leti                            r:op_arg3, 0
  leti                            r:op_arg4, 0
  map_designate                   (r:op_arg1, r:op_arg2, r:op_arg3, r:op_arg4)
  leti                            r:op_arg1, 2 // Forest 2
  leti                            r:op_arg2, 0
  leti                            r:op_arg3, 0
  leti                            r:op_arg4, 0
  map_designate                   (r:op_arg1, r:op_arg2, r:op_arg3, r:op_arg4)
  leti                            r:op_arg1, 11  // Dragon
  leti                            r:op_arg2, 0
  leti                            r:op_arg3, 0
  leti                            r:op_arg4, 0
  map_designate                   (r:op_arg1, r:op_arg2, r:op_arg3, r:op_arg4)
  ret

return_immediately:
  ret

floor_handler_pioneer_2:
  switch_jmp                      r:has_talked_to_hopkins, [floor_handler_pioneer_2_first_time, floor_handler_pioneer_2_not_first_time]
floor_handler_pioneer_2_first_time:
  set                             r50
  set_mainwarp                    1
  leti                            r:op_arg1, 0x000000ED
  leti                            r:op_arg2, 0x00000000
  leti                            r:op_arg3, 0x0000014D
  leti                            r:op_arg4, 0xFFFFFFF1
  p_setpos                        0, (r:op_arg1, r:op_arg2, r:op_arg3, r:op_arg4)
  leti                            r:op_arg1, 0x000000FF
  leti                            r:op_arg2, 0x00000000
  leti                            r:op_arg3, 0x00000152
  leti                            r:op_arg4, 0xFFFFFFD5
  p_setpos                        1, (r:op_arg1, r:op_arg2, r:op_arg3, r:op_arg4)
  leti                            r:op_arg1, 0x000000DE
  leti                            r:op_arg2, 0x00000000
  leti                            r:op_arg3, 0x00000142
  leti                            r:op_arg4, 0x00000019
  p_setpos                        2, (r:op_arg1, r:op_arg2, r:op_arg3, r:op_arg4)
  leti                            r:op_arg1, 0x000000F8
  leti                            r:op_arg2, 0x00000000
  leti                            r:op_arg3, 0x00000143
  leti                            r:op_arg4, 0xFFFFFFEC
  p_setpos                        3, (r:op_arg1, r:op_arg2, r:op_arg3, r:op_arg4)
  call                            on_talk_to_hopkins
  ret
floor_handler_pioneer_2_not_first_time:
  set                             r50
  thread_stg                      watch_for_dragon_killed_in_forest
  thread_stg                      show_mission_complete_if_needed
  ret

label00CA@0x00CA:
  clear                           r50
  set                             r51
  ret

label00CB@0x00CB:
  clear                           r51
  set                             r50
  ret

on_quest_success:
  jmpi_eq                         r:difficulty_level, 0, on_quest_success_normal
  jmpi_eq                         r:difficulty_level, 1, on_quest_success_hard
  jmpi_eq                         r:difficulty_level, 2, on_quest_success_very_hard
  jmpi_eq                         r:difficulty_level, 3, on_quest_success_ultimate
on_quest_success_normal:
  window_msg                      "You\'ve been awarded\n100 Meseta."
  bgm                             1
  winend
  pl_add_meseta2                  100
  ret
on_quest_success_hard:
  window_msg                      "You\'ve been awarded\n5000 Meseta."
  bgm                             1
  winend
  pl_add_meseta2                  5000
  ret
on_quest_success_very_hard:
  window_msg                      "You\'ve been awarded\n10000 Meseta."
  bgm                             1
  winend
  pl_add_meseta2                  10000
  ret
on_quest_success_ultimate:
  window_msg                      "You\'ve been awarded\n15000 Meseta."
  bgm                             1
  winend
  pl_add_meseta2                  15000
  ret

floor_handler_forest_1:
  thread_stg                      watch_for_dragon_killed_in_forest
  thread_stg                      show_mission_complete_if_needed
  ret

floor_handler_forest_2:
  thread_stg                      watch_for_dragon_killed_in_forest
  thread_stg                      show_mission_complete_if_needed
  ret

floor_handler_dragon:
  thread_stg                      watch_for_dragon_zone_clear
  thread_stg                      play_dragon_killed_cutscene_when_ready
  thread_stg                      show_mission_complete_if_needed
  ret

watch_for_dragon_zone_clear:
  jmpi_eq                         r15, 1, return_immediately
  sync
  leti                            r240, 11
  leti                            r241, 1
  if_zone_clear                   r242, r240-r241
  jmpi_eq                         r242, 0, watch_for_dragon_zone_clear
  sync_register2                  r15, 1
  ret

watch_for_dragon_killed_in_forest:
  jmpi_eq                         r18, 1, return_immediately
  jmpi_eq                         r19, 1, return_immediately
watch_for_dragon_killed_in_forest_check_again:
  sync
  jmpi_eq                         r15, 0, watch_for_dragon_killed_in_forest_check_again
  call                            wait_30_frames
  p_action_disable
  call                            on_dragon_killed
  set                             r18
  p_action_enable
  ret

play_dragon_killed_cutscene_when_ready:
  jmpi_eq                         r18, 1, return_immediately
  jmpi_eq                         r19, 1, return_immediately
play_dragon_killed_cutscene_when_ready_check_again:
  sync
  jmpi_eq                         r15, 0, play_dragon_killed_cutscene_when_ready_check_again
  call                            wait_30_frames
  call                            start_cutscene
  set                             r19
  set_quest_board_handler         0, quest_board_item_handler, "HEAT SWORD"
  set                             r74
  set                             r254
  call                            on_dragon_killed
  call                            end_cutscene
  ret

on_dragon_killed:
  jmpi_eq                         r:difficulty_level, 3, on_dragon_killed_ultimate
  window_msg                      "Dragon killed!"
  add_msg                         "Hopkins\'s HEAT SWORD found\nin Dragon\'s mouth!"
  se                              1
  winend
  ret
on_dragon_killed_ultimate:
  window_msg                      "Sil Dragon killed!"
  add_msg                         "Hopkins\'s HEAT SWORD found\nin Sil Dragon\'s mouth!"
  se                              1
  winend
  ret

quest_board_item_handler:
  disp_msg_qb                     "My dad gave HEAT SWORD\nto me."
  close_msg_qb
  ret

show_mission_complete_if_needed:
  jmpi_eq                         r20, 1, return_immediately

show_mission_complete_if_needed_check_again:
  sync
  jmpi_eq                         r16, 0, show_mission_complete_if_needed_check_again
  jmpi_eq                         r17, 1, return_immediately
  p_action_disable
  window_msg                      "Mission complete!"
  bgm                             0
  add_msg                         "You will be taken to the lobby\nafter you receive your reward."
  set                             r20
  winend
  clear_quest_board_handler       0
  clear                           r74
  p_action_enable
  playbgm_epi                     1
  ret

on_talk_to_hopkins@310:
  jmpi_eq                         r255, 1, on_talk_to_hopkins_complete_again
  jmpi_eq                         r254, 1, on_talk_to_hopkins_complete
  jmpi_eq                         r:has_talked_to_hopkins, 1, on_talk_to_hopkins_incomplete_again
  call                            start_cutscene
  call                            wait_30_frames
  message                         100, "Ca... can you help\nme?  Please?"
  add_msg                         "I almost killed a\nDragon."
  add_msg                         "But... but..."
  add_msg                         "My HEAT SWORD...\nMy dad gave HEAT SWORD\nto me..."
  add_msg                         "It\'s really important to\nme. I don\'t know how it\nwas taken from me."
  add_msg                         "I cannot do my job\nwithout it!  Please\nget it back for me."
  set                             r:has_talked_to_hopkins
  mesend
  bgm                             1
  call                            end_cutscene
  ret
on_talk_to_hopkins_incomplete_again:
  message                         100, "Please get my\nHEAT SWORD\nback to me."
  add_msg                         "Perhaps it\'s in the\nDragon\'s stomach!"
  mesend
  ret
on_talk_to_hopkins_complete:
  call                            start_cutscene
  message                         100, "My item!\nThis is great!  Wow!"
  add_msg                         "Thank you very much!\nYou\'re great!"
  add_msg                         "Please get your reward\nat the counter!"
  add_msg                         "This is all I can do to\nshow my appreciation."
  mesend
  set                             r17
  sync_register2                  r16, 1
  sync_register2                  r255, 1
  clear_quest_board_handler       0
  clear                           r74
  bgm                             0
  playbgm_epi                     1
  call                            end_cutscene
  ret
on_talk_to_hopkins_complete_again:
  message                         100, "Please go get your\nreward at the counter!\nThank you!"
  mesend
  ret

on_talk_to_npc1@320:
  jmpi_eq                         r254, 1, on_talk_to_npc1_complete
  message                         104, "Did Hopkins do it again?"
  add_msg                         "Nothing.  Forget about\nit."
  mesend
  ret
on_talk_to_npc1_complete:
  message                         104, "Well, Hopkins often\nloses his..."
  mesend
  ret

on_talk_to_npc2@0x14A:
  jmpi_eq                         r254, 1, on_talk_to_npc2_complete
  message                         103, "It\'s kind of his\n\"talent,\" I think."
  mesend
  ret
on_talk_to_npc2_complete:
  message                         103, "Thanks for taking care\nof Hopkins."
  mesend
  ret

start_cutscene:
  p_action_disable
  disable_movement1               0
  disable_movement1               1
  disable_movement1               2
  disable_movement1               3
  hud_hide
  cine_enable
  cam_zmin
  ret

end_cutscene:
  cam_zmout
  cine_disable
  hud_show
  enable_movement1                0
  enable_movement1                1
  enable_movement1                2
  enable_movement1                3
  p_action_enable
  ret

wait_30_frames:
  leti                            r72, 0
wait_30_frames_next_frame:
  sync
  addi                            r72, 1
  jmpi_le                         r72, 30, wait_30_frames_next_frame
  ret
