summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engine')
-rwxr-xr-xengine/events/basement_key.asm34
-rw-r--r--engine/events/battle_tower.asm210
-rw-r--r--engine/events/battle_tower_rules.asm342
-rw-r--r--engine/events/buena.asm336
-rw-r--r--engine/events/buena_menu.asm58
-rw-r--r--engine/events/bug_contest/caught_mon.asm38
-rw-r--r--engine/events/bug_contest/contest.asm43
-rwxr-xr-xengine/events/bug_contest/contest_2.asm133
-rw-r--r--engine/events/bug_contest/display_stats.asm107
-rwxr-xr-xengine/events/bug_contest/judging.asm395
-rwxr-xr-xengine/events/card_key.asm39
-rw-r--r--engine/events/catch_tutorial.asm81
-rw-r--r--engine/events/catch_tutorial_input.asm43
-rwxr-xr-xengine/events/celebi.asm380
-rw-r--r--engine/events/crystal_unown.asm327
-rwxr-xr-xengine/events/daycare.asm792
-rw-r--r--engine/events/dratini.asm112
-rwxr-xr-xengine/events/elevator.asm283
-rwxr-xr-xengine/events/field_moves.asm469
-rw-r--r--engine/events/fish.asm133
-rwxr-xr-xengine/events/forced_movement.asm60
-rw-r--r--engine/events/fruit_trees.asm132
-rwxr-xr-xengine/events/halloffame.asm622
-rwxr-xr-xengine/events/happiness_egg.asm223
-rwxr-xr-xengine/events/heal_machine_anim.asm265
-rwxr-xr-xengine/events/itemfinder.asm58
-rw-r--r--engine/events/kurt.asm413
-rw-r--r--engine/events/kurt_selectquantity_interpretjoypad.asm4
-rw-r--r--engine/events/lucky_number.asm226
-rw-r--r--engine/events/magikarp.asm342
-rwxr-xr-xengine/events/magnet_train.asm482
-rwxr-xr-xengine/events/misc_scripts.asm62
-rw-r--r--engine/events/misc_scripts_2.asm51
-rw-r--r--engine/events/mom.asm745
-rwxr-xr-xengine/events/mom_phone.asm264
-rw-r--r--engine/events/move_deleter.asm166
-rw-r--r--engine/events/move_tutor.asm103
-rw-r--r--engine/events/name_rater.asm250
-rw-r--r--engine/events/odd_egg.asm96
-rwxr-xr-xengine/events/overworld.asm1846
-rwxr-xr-xengine/events/poisonstep.asm162
-rw-r--r--engine/events/poisonstep_pals.asm48
-rw-r--r--engine/events/poke_seer.asm461
-rwxr-xr-xengine/events/pokecenter_pc.asm678
-rwxr-xr-xengine/events/pokepic.asm49
-rw-r--r--engine/events/pokerus/apply_pokerus_tick.asm26
-rw-r--r--engine/events/pokerus/check_pokerus.asm25
-rw-r--r--engine/events/pokerus/pokerus.asm160
-rwxr-xr-xengine/events/print_photo.asm61
-rw-r--r--engine/events/print_unown.asm233
-rw-r--r--engine/events/print_unown_2.asm111
-rwxr-xr-xengine/events/prof_oaks_pc.asm213
-rwxr-xr-xengine/events/sacred_ash.asm74
-rwxr-xr-xengine/events/special.asm235
-rwxr-xr-xengine/events/squirtbottle.asm47
-rw-r--r--engine/events/std_collision.asm29
-rw-r--r--engine/events/std_scripts.asm1914
-rwxr-xr-xengine/events/sweet_scent.asm75
-rw-r--r--engine/events/trainer_scripts.asm31
-rwxr-xr-xengine/events/whiteout.asm82
60 files changed, 15479 insertions, 0 deletions
diff --git a/engine/events/basement_key.asm b/engine/events/basement_key.asm
new file mode 100755
index 000000000..b15288d09
--- /dev/null
+++ b/engine/events/basement_key.asm
@@ -0,0 +1,34 @@
+_BasementKey: ; 507b4
+; Are we even in the right map to use this?
+ ld a, [MapGroup]
+ cp GROUP_GOLDENROD_UNDERGROUND
+ jr nz, .nope
+
+ ld a, [MapNumber]
+ cp MAP_GOLDENROD_UNDERGROUND
+ jr nz, .nope
+; Are we on the tile in front of the door?
+ call GetFacingTileCoord
+ ld a, d
+ cp 22
+ jr nz, .nope
+ ld a, e
+ cp 10
+ jr nz, .nope
+; Let's use the Basement Key
+ ld hl, .BasementKeyScript
+ call QueueScript
+ ld a, TRUE
+ ld [wItemEffectSucceeded], a
+ ret
+
+.nope
+ ld a, FALSE
+ ld [wItemEffectSucceeded], a
+ ret
+; 507e1
+
+.BasementKeyScript: ; 0x507e1
+ closetext
+ farjump BasementDoorScript
+; 0x507e6
diff --git a/engine/events/battle_tower.asm b/engine/events/battle_tower.asm
new file mode 100644
index 000000000..b880a099b
--- /dev/null
+++ b/engine/events/battle_tower.asm
@@ -0,0 +1,210 @@
+Function_LoadOpponentTrainerAndPokemons: ; 1f8000
+ ld a, [rSVBK]
+ push af
+ ld a, BANK(BT_OTTrainer)
+ ld [rSVBK], a
+
+ ; Fill BT_OTTrainer with zeros
+ xor a
+ ld hl, BT_OTTrainer
+ ld bc, BT_OTTrainerEnd - BT_OTTrainer
+ call ByteFill
+
+ ; Write $ff into the Item-Slots
+ ld a, $ff
+ ld [BT_OTPkmn1Item], a
+ ld [BT_OTPkmn2Item], a
+ ld [BT_OTPkmn3Item], a
+
+ ; Set BT_OTTrainer as start address to write the following data to
+ ld de, BT_OTTrainer
+
+ ld a, [hRandomAdd]
+ ld b, a
+.resample ; loop to find a random trainer
+ call Random
+ ld a, [hRandomAdd]
+ add b
+ ld b, a ; b contains the nr of the trainer
+IF DEF(CRYSTAL11)
+ and (1 << 7) - 1
+ cp 70
+ELSE
+ and (1 << 5) - 1
+ cp 21
+ENDC
+ jr nc, .resample
+ ld b, a
+
+ ld a, BANK(sBTTrainers)
+ call GetSRAMBank
+
+ ld c, BATTLETOWER_NROFTRAINERS
+ ld hl, sBTTrainers
+.next_trainer
+ ld a, [hli]
+ cp b
+ jr z, .resample
+ dec c
+ jr nz, .next_trainer ; c <= 7 initialise all 7 trainers?
+
+ ld hl, sBTTrainers
+ ld a, [sNrOfBeatenBattleTowerTrainers]
+ ld c, a
+ ld a, b
+ ld b, 0
+ add hl, bc
+ ld [hl], a
+
+ call CloseSRAM
+
+ push af
+; Copy name (10 bytes) and class (1 byte) of trainer
+ ld hl, BattleTowerTrainers
+ ld bc, NAME_LENGTH
+ call AddNTimes
+ ld bc, NAME_LENGTH
+ call CopyBytes
+
+ call Function_LoadRandomBattleTowerPkmn
+ pop af
+
+ ld hl, BattleTowerTrainerData
+ ld bc, BATTLETOWER_TRAINERDATALENGTH
+ call AddNTimes
+ ld bc, BATTLETOWER_TRAINERDATALENGTH
+.copy_bt_trainer_data_loop
+ ld a, BANK(BattleTowerTrainerData)
+ call GetFarByte
+ ld [de], a
+ inc hl
+ inc de
+ dec bc
+ ld a, b
+ or c
+ jr nz, .copy_bt_trainer_data_loop
+
+ pop af
+ ld [rSVBK], a
+
+ ret
+
+
+Function_LoadRandomBattleTowerPkmn: ; 1f8081
+ ld c, BATTLETOWER_NROFPKMNS
+.loop
+ push bc
+ ld a, BANK(sBTPkmnPrevTrainer1)
+ call GetSRAMBank
+
+.FindARandomBattleTowerPkmn:
+ ; From Which LevelGroup are the Pkmn loaded
+ ; a = 1..10
+ ld a, [wBTChoiceOfLvlGroup] ; [$d800]
+ dec a
+ ld hl, BattleTowerMons
+ ld bc, BattleTowerMons2 - BattleTowerMons1
+ call AddNTimes
+
+ ld a, [hRandomAdd]
+ ld b, a
+.resample
+ call Random
+ ld a, [hRandomAdd]
+ add b
+ ld b, a
+ and $1f
+ cp BATTLETOWER_NRMONSPERLEVELBRACKET
+ jr nc, .resample
+ ; in register 'a' is the chosen Pkmn of the LevelGroup
+
+ ; Check if Pkmn was already loaded before
+ ; Check current and the 2 previous teams
+ ; includes check if item is double at the current team
+ ld bc, PARTYMON_STRUCT_LENGTH + PKMN_NAME_LENGTH
+ call AddNTimes
+ ld a, [hli]
+ ld b, a
+ ld a, [hld]
+ ld c, a
+ ld a, [BT_OTPkmn1]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [BT_OTPkmn1Item]
+ cp c
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [BT_OTPkmn2]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [BT_OTPkmn2Item]
+ cp c
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [BT_OTPkmn3]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [BT_OTPkmn3Item]
+ cp c
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [sBTPkmnPrevTrainer1]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [sBTPkmnPrevTrainer2]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [sBTPkmnPrevTrainer3]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [sBTPkmnPrevPrevTrainer1]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [sBTPkmnPrevPrevTrainer2]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+ ld a, [sBTPkmnPrevPrevTrainer3]
+ cp b
+ jr z, .FindARandomBattleTowerPkmn
+
+ ld bc, PARTYMON_STRUCT_LENGTH + PKMN_NAME_LENGTH
+ call CopyBytes
+
+ ld a, [wNamedObjectIndexBuffer]
+ push af
+ push de
+ ld hl, - (PARTYMON_STRUCT_LENGTH + PKMN_NAME_LENGTH)
+ add hl, de
+ ld a, [hl]
+ ld [wNamedObjectIndexBuffer], a
+ ld bc, PARTYMON_STRUCT_LENGTH
+ add hl, bc
+ push hl
+ call GetPokemonName
+ ld h, d
+ ld l, e
+ pop de
+ ld bc, PKMN_NAME_LENGTH
+ call CopyBytes
+
+ pop de
+ pop af
+ ld [wNamedObjectIndexBuffer], a
+ pop bc
+ dec c
+ jp nz, .loop
+
+ ld a, [sBTPkmnPrevTrainer1]
+ ld [sBTPkmnPrevPrevTrainer1], a
+ ld a, [sBTPkmnPrevTrainer2]
+ ld [sBTPkmnPrevPrevTrainer2], a
+ ld a, [sBTPkmnPrevTrainer3]
+ ld [sBTPkmnPrevPrevTrainer3], a
+ ld a, [BT_OTPkmn1]
+ ld [sBTPkmnPrevTrainer1], a
+ ld a, [BT_OTPkmn2]
+ ld [sBTPkmnPrevTrainer2], a
+ ld a, [BT_OTPkmn3]
+ ld [sBTPkmnPrevTrainer3], a
+ call CloseSRAM
+ ret
+; 1f814e
+
+INCLUDE "data/battle_tower.asm"
diff --git a/engine/events/battle_tower_rules.asm b/engine/events/battle_tower_rules.asm
new file mode 100644
index 000000000..de6022145
--- /dev/null
+++ b/engine/events/battle_tower_rules.asm
@@ -0,0 +1,342 @@
+CheckForMobileBattleRules: ; 8b1e1
+ ld de, .PointerTables
+ call BattleTower_ExecuteJumptable
+ ret z
+ call BattleTower_PleaseReturnWhenReady
+ scf
+ ret
+; 8b1ed
+
+.PointerTables: ; 8b1ed
+ db 2
+ dw .Functions
+ dw .TextPointers
+
+.Functions: ; 8b1f2
+ dw BattleTower_CheckPartyLengthIs3
+ dw BattleTower_CheckPartyHasThreeMonsThatAreNotEggs
+; 8b1f6
+
+.TextPointers: ; 8b1f6
+ dw .ExcuseMeText
+ dw JumpText_NeedAtLeastThreeMon
+ dw JumpText_EggDoesNotQualify
+; 8b1fc
+
+.ExcuseMeText: ; 0x8b1fc
+ ; Excuse me!
+ text_jump UnknownText_0x1c5937
+ db "@"
+; 0x8b201
+
+CheckForBattleTowerRules: ; 8b201
+ ld hl, StringBuffer2
+ ld [hl], "3"
+ inc hl
+ ld [hl], "@"
+ ld de, .PointerTables
+ call BattleTower_ExecuteJumptable
+ ret z
+ call BattleTower_PleaseReturnWhenReady
+ scf
+ ret
+; 8b215
+
+.PointerTables: ; 8b215
+ db 4
+ dw .Functions
+ dw .TextPointers
+
+.Functions: ; 8b21a
+ dw Function_PartyCountEq3
+ dw Function_PartySpeciesAreUnique
+ dw Function_PartyItemsAreUnique
+ dw Function_HasPartyAnEgg
+; 8b222
+
+.TextPointers: ; 8b222
+ dw JumpText_ExcuseMeYoureNotReady
+ dw JumpText_OnlyThreePkmnMayBeEntered
+ dw JumpText_ThePkmnMustAllBeDifferentKinds
+ dw JumpText_ThePkmnMustNotHoldTheSameItems
+ dw JumpText_YouCantTakeAnEgg
+; 8b22c
+
+JumpText_ExcuseMeYoureNotReady: ; 0x8b22c
+ ; Excuse me. You're not ready.
+ text_jump Text_ExcuseMeYoureNotReady
+ db "@"
+; 0x8b231
+
+BattleTower_PleaseReturnWhenReady: ; 8b231
+ ld hl, .PleaseReturnWhenReady
+ call PrintText
+ ret
+; 8b238
+
+.PleaseReturnWhenReady: ; 0x8b238
+ ; Please return when you're ready.
+ text_jump UnknownText_0x1c5962
+ db "@"
+; 0x8b23d
+
+JumpText_NeedAtLeastThreeMon: ; 0x8b23d
+ ; You need at least three #MON.
+ text_jump UnknownText_0x1c5983
+ db "@"
+; 0x8b242
+
+JumpText_EggDoesNotQualify: ; 0x8b242
+ ; Sorry, an EGG doesn't qualify.
+ text_jump UnknownText_0x1c59a3
+ db "@"
+; 0x8b247
+
+JumpText_OnlyThreePkmnMayBeEntered: ; 0x8b247
+ ; Only three #MON may be entered.
+ text_jump Text_OnlyThreePkmnMayBeEntered
+ db "@"
+; 0x8b24c
+
+JumpText_ThePkmnMustAllBeDifferentKinds: ; 0x8b24c
+ ; The @ #MON must all be different kinds.
+ text_jump Text_ThePkmnMustAllBeDifferentKinds
+ db "@"
+; 0x8b251
+
+JumpText_ThePkmnMustNotHoldTheSameItems: ; 0x8b251
+ ; The @ #MON must not hold the same items.
+ text_jump Text_ThePkmnMustNotHoldTheSameItems
+ db "@"
+; 0x8b256
+
+JumpText_YouCantTakeAnEgg: ; 0x8b256
+ ; You can't take an EGG!
+ text_jump Text_YouCantTakeAnEgg
+ db "@"
+; 0x8b25b
+
+BattleTower_ExecuteJumptable: ; 8b25b
+ ld bc, 0
+.loop
+ call .DoJumptableFunction
+ call c, .PrintFailureText
+ call .Next_CheckReachedEnd
+ jr nz, .loop
+ ld a, b
+ and a
+ ret
+; 8b26c
+
+.DoJumptableFunction: ; 8b26c
+ push de
+ push bc
+ call .GetFunctionPointer
+ ld a, c
+ rst JumpTable
+ pop bc
+ pop de
+ ret
+; 8b276
+
+.Next_CheckReachedEnd: ; 8b276
+ inc c
+ ld a, [de]
+ cp c
+ ret
+; 8b27a
+
+.GetFunctionPointer: ; 8b27a
+ inc de
+ ld a, [de]
+ ld l, a
+ inc de
+ ld a, [de]
+ ld h, a
+ ret
+; 8b281
+
+.GetTextPointers: ; 8b281
+ inc de
+ inc de
+ inc de
+ ld a, [de]
+ ld l, a
+ inc de
+ ld a, [de]
+ ld h, a
+ ret
+; 8b28a
+
+.LoadTextPointer: ; 8b28a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ret
+; 8b28e
+
+.PrintFailureText: ; 8b28e
+ push de
+ push bc
+ ld a, b
+ and a
+ call z, .PrintFirstText
+ pop bc
+ call .PrintNthText
+ ld b, $1
+ pop de
+ ret
+; 8b29d
+
+.PrintFirstText: ; 8b29d
+ push de
+ call .GetTextPointers
+ call .LoadTextPointer
+ call PrintText
+ pop de
+ ret
+; 8b2a9
+
+.PrintNthText: ; 8b2a9
+ push bc
+ call .GetTextPointers
+ inc hl
+ inc hl
+ ld b, $0
+ add hl, bc
+ add hl, bc
+ call .LoadTextPointer
+ call PrintText
+ pop bc
+ ret
+; 8b2bb
+
+BattleTower_CheckPartyLengthIs3: ; 8b2bb
+ ld a, [PartyCount]
+ cp 3
+ ret
+; 8b2c1
+
+BattleTower_CheckPartyHasThreeMonsThatAreNotEggs: ; 8b2c1
+ ld hl, PartyCount
+ ld a, [hli]
+ ld b, $0
+ ld c, a
+.loop
+ ld a, [hli]
+ cp EGG
+ jr z, .egg
+ inc b
+
+.egg
+ dec c
+ jr nz, .loop
+ ld a, [PartyCount]
+ cp b
+ ret z
+ ld a, b
+ cp 3
+ ret
+; 8b2da
+
+Function_PartyCountEq3: ; 8b2da
+ ld a, [PartyCount]
+ cp 3
+ ret z
+ scf
+ ret
+; 8b2e2
+
+Function_PartySpeciesAreUnique: ; 8b2e2
+ ld hl, PartyMon1Species
+ call VerifyUniqueness
+ ret
+; 8b2e9
+
+VerifyUniqueness: ; 8b2e9
+ ld de, PartyCount
+ ld a, [de]
+ inc de
+ dec a
+ jr z, .done
+ ld b, a
+.loop
+ push hl
+ push de
+ ld c, b
+ call .isegg
+ jr z, .next
+ ld a, [hl]
+ and a
+ jr z, .next
+.loop2
+ call .nextmon
+ call .isegg
+ jr z, .next2
+ cp [hl]
+ jr z, .gotcha
+
+.next2
+ dec c
+ jr nz, .loop2
+
+.next
+ pop de
+ pop hl
+ call .nextmon
+ dec b
+ jr nz, .loop
+
+.done
+ and a
+ ret
+
+.gotcha
+ pop de
+ pop hl
+ scf
+ ret
+; 8b31a
+
+.nextmon ; 8b31a
+ push bc
+ ld bc, PARTYMON_STRUCT_LENGTH
+ add hl, bc
+ inc de
+ pop bc
+ ret
+; 8b322
+
+.isegg ; 8b322
+ push bc
+ ld b, a
+ ld a, [de]
+ cp EGG
+ ld a, b
+ pop bc
+ ret
+; 8b32a
+
+Function_PartyItemsAreUnique: ; 8b32a
+ ld hl, PartyMon1Item
+ call VerifyUniqueness
+ ret
+; 8b331
+
+Function_HasPartyAnEgg: ; 8b331
+ ld hl, PartyCount
+ ld a, [hli]
+ ld c, a
+.loop
+ ld a, [hli]
+ cp EGG
+ jr z, .found
+ dec c
+ jr nz, .loop
+ and a
+ ret
+
+.found
+ scf
+ ret
+; 8b342
diff --git a/engine/events/buena.asm b/engine/events/buena.asm
new file mode 100644
index 000000000..1227593eb
--- /dev/null
+++ b/engine/events/buena.asm
@@ -0,0 +1,336 @@
+SpecialBuenasPassword: ; 8af6b
+ xor a
+ ld [wWhichIndexSet], a
+ ld hl, .MenuDataHeader
+ call CopyMenuDataHeader
+ ld a, [wBuenasPassword]
+ ld c, a
+ farcall GetBuenasPassword
+ ld a, [wMenuBorderLeftCoord]
+ add c
+ add $2
+ ld [wMenuBorderRightCoord], a
+ call PushWindow
+ call DoNthMenu ; menu
+ farcall Buena_ExitMenu
+ ld b, $0
+ ld a, [MenuSelection]
+ ld c, a
+ ld a, [wBuenasPassword]
+ and $3
+ cp c
+ jr nz, .wrong
+ ld b, $1
+
+.wrong
+ ld a, b
+ ld [ScriptVar], a
+ ret
+; 8afa9
+
+.MenuDataHeader: ; 0x8afa9
+ db $40 ; flags
+ db 00, 00 ; start coords
+ db 07, 10 ; end coords
+ dw .MenuData2
+ db 1 ; default option
+; 0x8afb1
+
+ db 0
+
+.MenuData2: ; 0x8afb2
+ db $81 ; flags
+ db 0 ; items
+ dw .PasswordIndices
+ dw .PlacePasswordChoices
+; 0x8afb4
+
+.PasswordIndices: ; 8afb8
+ db 3
+ db 0, 1, 2
+ db -1
+
+.PlacePasswordChoices: ; 8afbd
+ push de
+ ld a, [wBuenasPassword]
+ and $f0
+ ld c, a
+ ld a, [MenuSelection]
+ add c
+ ld c, a
+ farcall GetBuenasPassword
+ pop hl
+ call PlaceString
+ ret
+; 8afd4
+
+SpecialBuenaPrize: ; 8afd4
+ xor a
+ ld [wMenuScrollPosition], a
+ ld a, $1
+ ld [MenuSelection], a
+ call Buena_PlacePrizeMenuBox
+ call Buena_DisplayBlueCardBalance
+ ld hl, .Text_AskWhichPrize
+ call PrintText
+ jr .okay
+
+.loop
+ ld hl, .Text_AskWhichPrize
+ call BuenaPrintText
+
+.okay
+ call DelayFrame
+ call UpdateSprites
+ call PrintBlueCardBalance
+ call Buena_PrizeMenu
+ jr z, .done
+ ld [MenuSelectionQuantity], a
+ call Buena_getprize
+ ld a, [hl]
+ ld [wNamedObjectIndexBuffer], a
+ call GetItemName
+ ld hl, .Text_IsThatRight
+ call BuenaPrintText
+ call YesNoBox
+ jr c, .loop
+
+ ld a, [MenuSelectionQuantity]
+ call Buena_getprize
+ inc hl
+ ld a, [hld]
+ ld c, a
+ ld a, [wBlueCardBalance]
+ cp c
+ jr c, .InsufficientBalance
+
+ ld a, [hli]
+ push hl
+ ld [CurItem], a
+ ld a, $1
+ ld [wItemQuantityChangeBuffer], a
+ ld hl, NumItems
+ call ReceiveItem
+ pop hl
+ jr nc, .BagFull
+ ld a, [hl]
+ ld c, a
+ ld a, [wBlueCardBalance]
+ sub c
+ ld [wBlueCardBalance], a
+ call PrintBlueCardBalance
+ jr .Purchase
+
+.InsufficientBalance:
+ ld hl, .Text_NotEnoughPoints
+ jr .print
+
+.BagFull:
+ ld hl, .Text_NoRoom
+ jr .print
+
+.Purchase:
+ ld de, SFX_TRANSACTION
+ call PlaySFX
+ ld hl, .Text_HereYouGo
+
+.print
+ call BuenaPrintText
+ jr .loop
+
+.done
+ call CloseWindow
+ call CloseWindow
+ ld hl, .Text_PleaseComeBackAgain
+ call PrintText
+ call JoyWaitAorB
+ call PlayClickSFX
+ ret
+; 8b072
+
+.Text_AskWhichPrize: ; 0x8b072
+ ; Which prize would you like?
+ text_jump UnknownText_0x1c589f
+ db "@"
+; 0x8b077
+
+.Text_IsThatRight: ; 0x8b077
+ ; ? Is that right?
+ text_jump UnknownText_0x1c58bc
+ db "@"
+; 0x8b07c
+
+.Text_HereYouGo: ; Here you go!
+ text_jump UnknownText_0x1c58d1
+ db "@"
+; 0x8b081
+
+.Text_NotEnoughPoints: ; 0x8b081
+ ; You don't have enough points.
+ text_jump UnknownText_0x1c58e0
+ db "@"
+; 0x8b086
+
+.Text_NoRoom: ; 0x8b086
+ ; You have no room for it.
+ text_jump UnknownText_0x1c58ff
+ db "@"
+; 0x8b08b
+
+.Text_PleaseComeBackAgain: ; 0x8b08b
+ ; Oh. Please come back again!
+ text_jump UnknownText_0x1c591a
+ db "@"
+; 0x8b090
+
+Buena_DisplayBlueCardBalance: ; 8b090
+ ld hl, BlueCardBalanceMenuDataHeader
+ call LoadMenuDataHeader
+ ret
+; 8b097
+
+PrintBlueCardBalance: ; 8b097
+ ld de, wBlueCardBalance
+ call .DrawBox
+ ret
+; 8b09e
+
+.DrawBox: ; 8b09e
+ push de
+ xor a
+ ld [hBGMapMode], a
+ ld hl, BlueCardBalanceMenuDataHeader
+ call CopyMenuDataHeader
+ call MenuBox
+ call UpdateSprites
+ call MenuBoxCoord2Tile
+ ld bc, SCREEN_WIDTH + 1
+ add hl, bc
+ ld de, .Points_string
+ call PlaceString
+ ld h, b
+ ld l, c
+ inc hl
+ ld a, " "
+ ld [hli], a
+ ld [hld], a
+ pop de
+ lb bc, 1, 2
+ call PrintNum
+ ret
+; 8b0ca
+
+.Points_string:
+ db "Points@"
+; 8b0d1
+
+BlueCardBalanceMenuDataHeader: ; 0x8b0d1
+ db $40 ; flags
+ db 11, 00 ; start coords
+ db 13, 11 ; end coords
+; 8b0d6
+
+Buena_PlacePrizeMenuBox: ; 8b0d6
+ ld hl, .menudataheader
+ call LoadMenuDataHeader
+ ret
+; 8b0dd
+
+.menudataheader ; 0x8b0dd
+ db $40 ; flags
+ db 00, 00 ; start coords
+ db 11, 17 ; end coords
+; 8b0e2
+
+Buena_PrizeMenu: ; 8b0e2
+ ld hl, .MenuDataHeader
+ call CopyMenuDataHeader
+ ld a, [MenuSelection]
+ ld [wMenuCursorBuffer], a
+ xor a
+ ld [wWhichIndexSet], a
+ ld [hBGMapMode], a
+ call InitScrollingMenu
+ call UpdateSprites
+ call ScrollingMenu
+ ld a, [MenuSelection]
+ ld c, a
+ ld a, [wMenuCursorY]
+ ld [MenuSelection], a
+ ld a, [wMenuJoypad]
+ cp $2
+ jr z, .cancel
+ ld a, c
+ and a
+ ret nz
+
+.cancel
+ xor a
+ ret
+; 8b113
+
+.MenuDataHeader: ; 0x8b113
+ db $40 ; flags
+ db 01, 01 ; start coords
+ db 09, 16 ; end coords
+ dw .MenuData2
+ db 1 ; default option
+; 0x8b11b
+
+ db 0
+
+.MenuData2: ; 0x8b11c
+ db $10 ; flags
+ db 4, 13 ; rows, columns
+ db 1 ; spacing
+ dba .indices
+ dba .prizeitem
+ dba .prizepoints
+; 8b129
+
+NUM_BUENA_PRIZES EQU 9 ; ((BuenaPrizeItemsEnd - BuenaPrizeItems) / 2)
+
+.indices ; 8b129
+ db NUM_BUENA_PRIZES
+x = 1
+rept NUM_BUENA_PRIZES
+ db x
+x = x + 1
+endr
+ db -1
+; 8b134
+
+.prizeitem ; 8b134
+ ld a, [MenuSelection]
+ call Buena_getprize
+ ld a, [hl]
+ push de
+ ld [wNamedObjectIndexBuffer], a
+ call GetItemName
+ pop hl
+ call PlaceString
+ ret
+; 8b147
+
+.prizepoints ; 8b147
+ ld a, [MenuSelection]
+ call Buena_getprize
+ inc hl
+ ld a, [hl]
+ ld c, "0"
+ add c
+ ld [de], a
+ ret
+; 8b154
+
+Buena_getprize: ; 8b154
+ dec a
+ ld hl, BuenaPrizeItems
+ ld b, 0
+ ld c, a
+ add hl, bc
+ add hl, bc
+ ret
+; 8b15e
+
+INCLUDE "data/items/buena_prizes.asm"
diff --git a/engine/events/buena_menu.asm b/engine/events/buena_menu.asm
new file mode 100644
index 000000000..b453da783
--- /dev/null
+++ b/engine/events/buena_menu.asm
@@ -0,0 +1,58 @@
+AskRememberPassword: ; 4ae12
+ call .DoMenu
+ ld a, $0
+ jr c, .okay
+ ld a, $1
+
+.okay
+ ld [ScriptVar], a
+ ret
+
+.DoMenu: ; 4ae1f
+ lb bc, 14, 7
+ push bc
+ ld hl, YesNoMenuDataHeader
+ call CopyMenuDataHeader
+ pop bc
+ ld a, b
+ ld [wMenuBorderLeftCoord], a
+ add $5
+ ld [wMenuBorderRightCoord], a
+ ld a, c
+ ld [wMenuBorderTopCoord], a
+ add $4
+ ld [wMenuBorderBottomCoord], a
+ call PushWindow
+ call VerticalMenu
+ push af
+ ld c, 15
+ call DelayFrames
+ call Buena_ExitMenu
+ pop af
+ jr c, .refused
+ ld a, [wMenuCursorY]
+ cp $2
+ jr z, .refused
+ and a
+ ret
+
+.refused
+ ld a, $2
+ ld [wMenuCursorY], a
+ scf
+ ret
+
+Buena_ExitMenu: ; 4ae5e
+ ld a, [hOAMUpdate]
+ push af
+ call ExitMenu
+ call UpdateSprites
+ xor a
+ ld [hOAMUpdate], a
+ call DelayFrame
+ ld a, $1
+ ld [hOAMUpdate], a
+ call ApplyTilemap
+ pop af
+ ld [hOAMUpdate], a
+ ret
diff --git a/engine/events/bug_contest/caught_mon.asm b/engine/events/bug_contest/caught_mon.asm
new file mode 100644
index 000000000..5d423f466
--- /dev/null
+++ b/engine/events/bug_contest/caught_mon.asm
@@ -0,0 +1,38 @@
+BugContest_SetCaughtContestMon: ; e6ce
+ ld a, [wContestMon]
+ and a
+ jr z, .firstcatch
+ ld [wd265], a
+ farcall DisplayAlreadyCaughtText
+ farcall DisplayCaughtContestMonStats
+ lb bc, 14, 7
+ call PlaceYesNoBox
+ ret c
+
+.firstcatch
+ call .generatestats
+ ld a, [TempEnemyMonSpecies]
+ ld [wd265], a
+ call GetPokemonName
+ ld hl, .caughttext
+ call PrintText
+ ret
+
+.generatestats ; e6fd
+ ld a, [TempEnemyMonSpecies]
+ ld [CurSpecies], a
+ ld [CurPartySpecies], a
+ call GetBaseData
+ xor a
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld hl, wContestMon
+ call ByteFill
+ xor a
+ ld [MonType], a
+ ld hl, wContestMon
+ jp GeneratePartyMonStats
+
+.caughttext ; 0xe71d
+ ; Caught @ !
+ text_jump UnknownText_0x1c10c0
+ db "@"
diff --git a/engine/events/bug_contest/contest.asm b/engine/events/bug_contest/contest.asm
new file mode 100644
index 000000000..ba561abf2
--- /dev/null
+++ b/engine/events/bug_contest/contest.asm
@@ -0,0 +1,43 @@
+Special_GiveParkBalls: ; 135db
+ xor a
+ ld [wContestMon], a
+ ld a, 20
+ ld [wParkBallsRemaining], a
+ farcall StartBugContestTimer
+ ret
+
+BugCatchingContestBattleScript:: ; 0x135eb
+ writecode VAR_BATTLETYPE, BATTLETYPE_CONTEST
+ randomwildmon
+ startbattle
+ reloadmapafterbattle
+ copybytetovar wParkBallsRemaining
+ iffalse BugCatchingContestOutOfBallsScript
+ end
+
+BugCatchingContestOverScript:: ; 0x135f8
+ playsound SFX_ELEVATOR_END
+ opentext
+ writetext BugCatchingContestText_BeeepTimesUp
+ waitbutton
+ jump BugCatchingContestReturnToGateScript
+
+BugCatchingContestOutOfBallsScript: ; 0x13603
+ playsound SFX_ELEVATOR_END
+ opentext
+ writetext BugCatchingContestText_ContestIsOver
+ waitbutton
+
+BugCatchingContestReturnToGateScript: ; 0x1360b
+ closetext
+ jumpstd bugcontestresultswarp
+
+BugCatchingContestText_BeeepTimesUp: ; 0x1360f
+ ; ANNOUNCER: BEEEP! Time's up!
+ text_jump UnknownText_0x1bd2ca
+ db "@"
+
+BugCatchingContestText_ContestIsOver: ; 0x13614
+ ; ANNOUNCER: The Contest is over!
+ text_jump UnknownText_0x1bd2e7
+ db "@"
diff --git a/engine/events/bug_contest/contest_2.asm b/engine/events/bug_contest/contest_2.asm
new file mode 100755
index 000000000..493c69d0c
--- /dev/null
+++ b/engine/events/bug_contest/contest_2.asm
@@ -0,0 +1,133 @@
+Special_SelectRandomBugContestContestants: ; 139a8
+; Select five random people to participate in the current contest.
+
+; First we have to make sure that any old data is cleared away.
+ ld c, 10 ; Number of people to choose from.
+ ld hl, BugCatchingContestantEventFlagTable
+.loop1
+ push bc
+ push hl
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld b, RESET_FLAG
+ call EventFlagAction
+ pop hl
+ inc hl
+ inc hl
+ pop bc
+ dec c
+ jr nz, .loop1
+
+; Now that that's out of the way, we can get on to the good stuff.
+ ld c, 5
+.loop2
+ push bc
+.next
+; Choose a flag at uniform random to be set.
+ call Random
+ cp 250
+ jr nc, .next
+ ld c, 25
+ call SimpleDivide
+ ld e, b
+ ld d, 0
+ ld hl, BugCatchingContestantEventFlagTable
+ add hl, de
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ push de
+; If we've already set it, it doesn't count.
+ ld b, CHECK_FLAG
+ call EventFlagAction
+ pop de
+ ld a, c
+ and a
+ jr nz, .next
+; Set the flag. This will cause that sprite to not be visible in the contest.
+ ld b, SET_FLAG
+ call EventFlagAction
+ pop bc
+; Check if we're done. If so, return. Otherwise, choose the next victim.
+ dec c
+ jr nz, .loop2
+ ret
+; 139ed
+
+Special_CheckBugContestContestantFlag: ; 139ed
+; Checks the flag of the Bug Catching Contestant whose index is loaded in a.
+
+; Bug: If a >= 10 when this is called, it will read beyond the table.
+
+ ld hl, BugCatchingContestantEventFlagTable
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld b, CHECK_FLAG
+ call EventFlagAction
+ ret
+; 139fe
+
+BugCatchingContestantEventFlagTable: ; 139fe
+ dw EVENT_BUG_CATCHING_CONTESTANT_1A
+ dw EVENT_BUG_CATCHING_CONTESTANT_2A
+ dw EVENT_BUG_CATCHING_CONTESTANT_3A
+ dw EVENT_BUG_CATCHING_CONTESTANT_4A
+ dw EVENT_BUG_CATCHING_CONTESTANT_5A
+ dw EVENT_BUG_CATCHING_CONTESTANT_6A
+ dw EVENT_BUG_CATCHING_CONTESTANT_7A
+ dw EVENT_BUG_CATCHING_CONTESTANT_8A
+ dw EVENT_BUG_CATCHING_CONTESTANT_9A
+ dw EVENT_BUG_CATCHING_CONTESTANT_10A
+; 13a12
+
+ContestDropOffMons: ; 13a12
+ ld hl, PartyMon1HP
+ ld a, [hli]
+ or [hl]
+ jr z, .fainted
+; Mask the rest of your party by setting the count to 1...
+ ld hl, PartyCount
+ ld a, 1
+ ld [hli], a
+ inc hl
+; ... backing up the second mon index somewhere...
+ ld a, [hl]
+ ld [wBugContestSecondPartySpecies], a
+; ... and replacing it with the terminator byte
+ ld [hl], $ff
+ xor a
+ ld [ScriptVar], a
+ ret
+
+.fainted
+ ld a, $1
+ ld [ScriptVar], a
+ ret
+; 13a31
+
+ContestReturnMons: ; 13a31
+; Restore the species of the second mon.
+ ld hl, PartySpecies + 1
+ ld a, [wBugContestSecondPartySpecies]
+ ld [hl], a
+; Restore the party count, which must be recomputed.
+ ld b, $1
+.loop
+ ld a, [hli]
+ cp -1
+ jr z, .done
+ inc b
+ jr .loop
+
+.done
+ ld a, b
+ ld [PartyCount], a
+ ret
+; 13a47
diff --git a/engine/events/bug_contest/display_stats.asm b/engine/events/bug_contest/display_stats.asm
new file mode 100644
index 000000000..d6ad3997e
--- /dev/null
+++ b/engine/events/bug_contest/display_stats.asm
@@ -0,0 +1,107 @@
+DisplayCaughtContestMonStats: ; cc000
+ call ClearBGPalettes
+ call ClearTileMap
+ call ClearSprites
+ call LoadFontsBattleExtra
+
+ ld hl, Options
+ ld a, [hl]
+ push af
+ set 4, [hl]
+
+ hlcoord 0, 0
+ ld b, 4
+ ld c, 13
+ call TextBox
+
+ hlcoord 0, 6
+ ld b, 4
+ ld c, 13
+ call TextBox
+
+ hlcoord 2, 0
+ ld de, .Stock
+ call PlaceString
+
+ hlcoord 2, 6
+ ld de, .This
+ call PlaceString
+
+ hlcoord 5, 4
+ ld de, .Health
+ call PlaceString
+
+ hlcoord 5, 10
+ ld de, .Health
+ call PlaceString
+
+ ld a, [wContestMon]
+ ld [wd265], a
+ call GetPokemonName
+ ld de, StringBuffer1
+ hlcoord 1, 2
+ call PlaceString
+
+ ld h, b
+ ld l, c
+ ld a, [wContestMonLevel]
+ ld [TempMonLevel], a
+ call PrintLevel
+
+ ld de, EnemyMonNick
+ hlcoord 1, 8
+ call PlaceString
+
+ ld h, b
+ ld l, c
+ ld a, [EnemyMonLevel]
+ ld [TempMonLevel], a
+ call PrintLevel
+
+ hlcoord 11, 4
+ ld de, wContestMonMaxHP
+ lb bc, 2, 3
+ call PrintNum
+
+ hlcoord 11, 10
+ ld de, EnemyMonMaxHP
+ call PrintNum
+
+ ld hl, SwitchMonText
+ call PrintText
+
+ pop af
+ ld [Options], a
+
+ call WaitBGMap
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call SetPalettes
+ ret
+
+.Health:
+ db "HEALTH@"
+.Stock:
+ db " STOCK ", $4a, " @"
+.This:
+ db " THIS ", $4a, " @"
+
+SwitchMonText: ; cc0c2
+ ; Switch #MON?
+ text_jump UnknownText_0x1c10cf
+ db "@"
+
+DisplayAlreadyCaughtText: ; cc0c7
+ call GetPokemonName
+ ld hl, .AlreadyCaughtText
+ jp PrintText
+
+.AlreadyCaughtText: ; 0xcc0d0
+ ; You already caught a @ .
+ text_jump UnknownText_0x1c10dd
+ db "@"
+
+Predef2F:
+Predef38:
+Predef39: ; cc0d5
+ ret
diff --git a/engine/events/bug_contest/judging.asm b/engine/events/bug_contest/judging.asm
new file mode 100755
index 000000000..901ae88fa
--- /dev/null
+++ b/engine/events/bug_contest/judging.asm
@@ -0,0 +1,395 @@
+_BugContestJudging: ; 1369d
+ call ContestScore
+ farcall TrainerRankings_BugContestScore
+ call BugContest_JudgeContestants
+ ld a, [wBugContestThirdPlaceWinnerID]
+ call LoadContestantName
+ ld a, [wBugContestThirdPlaceMon]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, BugContest_ThirdPlaceText
+ call PrintText
+ ld a, [wBugContestSecondPlaceWinnerID]
+ call LoadContestantName
+ ld a, [wBugContestSecondPlaceMon]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, BugContest_SecondPlaceText
+ call PrintText
+ ld a, [wBugContestFirstPlaceWinnerID]
+ call LoadContestantName
+ ld a, [wBugContestFirstPlaceMon]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, BugContest_FirstPlaceText
+ call PrintText
+ jp BugContest_GetPlayersResult
+; 136eb
+
+BugContest_FirstPlaceText: ; 0x136eb
+ text_jump ContestJudging_FirstPlaceText
+ start_asm
+ ld de, SFX_1ST_PLACE
+ call PlaySFX
+ call WaitSFX
+ ld hl, BugContest_FirstPlaceScoreText
+ ret
+; 136fd
+
+BugContest_FirstPlaceScoreText: ; 0x136fd
+ ; The winning score was @ points!
+ text_jump ContestJudging_FirstPlaceScoreText
+ db "@"
+; 0x13702
+
+BugContest_SecondPlaceText: ; 0x13702
+ ; Placing second was @ , who caught a @ !@ @
+ text_jump ContestJudging_SecondPlaceText
+ start_asm
+ ld de, SFX_2ND_PLACE
+ call PlaySFX
+ call WaitSFX
+ ld hl, BugContest_SecondPlaceScoreText
+ ret
+; 13714
+
+BugContest_SecondPlaceScoreText: ; 0x13714
+ ; The score was @ points!
+ text_jump ContestJudging_SecondPlaceScoreText
+ db "@"
+; 0x13719
+
+BugContest_ThirdPlaceText: ; 0x13719
+ ; Placing third was @ , who caught a @ !@ @
+ text_jump ContestJudging_ThirdPlaceText
+ start_asm
+ ld de, SFX_3RD_PLACE
+ call PlaySFX
+ call WaitSFX
+ ld hl, BugContest_ThirdPlaceScoreText
+ ret
+; 1372b
+
+BugContest_ThirdPlaceScoreText: ; 0x1372b
+ ; The score was @ points!
+ text_jump ContestJudging_ThirdPlaceScoreText
+ db "@"
+; 0x13730
+
+LoadContestantName: ; 13730
+
+; If a = 0, get your name.
+ dec a
+ jr z, .player
+; Find the pointer for the trainer class of the Bug Catching Contestant whose ID is in a.
+ ld c, a
+ ld b, 0
+ ld hl, BugContestantPointers
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+; Copy the Trainer Class to c.
+ ld a, [hli]
+ ld c, a
+; Save hl and bc for later.
+ push hl
+ push bc
+; Get the Trainer Class name and copy it into wBugContestWinnerName.
+ callfar GetTrainerClassName
+ ld hl, StringBuffer1
+ ld de, wBugContestWinnerName
+ ld bc, TRAINER_CLASS_NAME_LENGTH
+ call CopyBytes
+ ld hl, wBugContestWinnerName
+; Delete the trailing terminator and replace it with a space.
+.next
+ ld a, [hli]
+ cp "@"
+ jr nz, .next
+ dec hl
+ ld [hl], " "
+ inc hl
+ ld d, h
+ ld e, l
+; Restore the Trainer Class ID and Trainer ID pointer. Save de for later.
+ pop bc
+ pop hl
+ push de
+; Get the name of the trainer with class c and ID b.
+ ld a, [hl]
+ ld b, a
+ callfar GetTrainerName
+; Append the name to wBugContestWinnerName.
+ ld hl, StringBuffer1
+ pop de
+ ld bc, NAME_LENGTH - 1
+ jp CopyBytes
+
+.player
+ ld hl, PlayerName
+ ld de, wBugContestWinnerName
+ ld bc, NAME_LENGTH
+ jp CopyBytes
+; 13783
+
+
+INCLUDE "data/bug_contest_winners.asm"
+; 13807
+
+
+BugContest_GetPlayersResult: ; 13807
+ ld hl, wBugContestThirdPlaceWinnerID
+ ld de, -4
+ ld b, 3
+.loop
+ ld a, [hl]
+ cp 1 ; Player
+ jr z, .done
+ add hl, de
+ dec b
+ jr nz, .loop
+
+.done
+ ret
+; 13819
+
+BugContest_JudgeContestants: ; 13819
+ call ClearContestResults
+ call ComputeAIContestantScores
+ ld hl, wBugContestTempWinnerID
+ ld a, 1 ; Player
+ ld [hli], a
+ ld a, [wContestMon]
+ ld [hli], a
+ ld a, [hProduct]
+ ld [hli], a
+ ld a, [hProduct + 1]
+ ld [hl], a
+ call DetermineContestWinners
+ ret
+; 13833
+
+ClearContestResults: ; 13833
+ ld hl, wBugContestResults
+ ld b, wBugContestWinnersEnd - wBugContestResults
+ xor a
+.loop
+ ld [hli], a
+ dec b
+ jr nz, .loop
+ ret
+; 1383e
+
+DetermineContestWinners: ; 1383e
+ ld de, wBugContestTempScore
+ ld hl, wBugContestFirstPlaceScore
+ ld c, 2
+ call StringCmp
+ jr c, .not_first_place
+ ld hl, wBugContestSecondPlaceWinnerID
+ ld de, wBugContestThirdPlaceWinnerID
+ ld bc, 4
+ call CopyBytes
+ ld hl, wBugContestFirstPlaceWinnerID
+ ld de, wBugContestSecondPlaceWinnerID
+ ld bc, 4
+ call CopyBytes
+ ld hl, wBugContestFirstPlaceWinnerID
+ call CopyTempContestant
+ jr .done
+
+.not_first_place
+ ld de, wBugContestTempScore
+ ld hl, wBugContestSecondPlaceScore
+ ld c, 2
+ call StringCmp
+ jr c, .not_second_place
+ ld hl, wBugContestSecondPlaceWinnerID
+ ld de, wBugContestThirdPlaceWinnerID
+ ld bc, 4
+ call CopyBytes
+ ld hl, wBugContestSecondPlaceWinnerID
+ call CopyTempContestant
+ jr .done
+
+.not_second_place
+ ld de, wBugContestTempScore
+ ld hl, wBugContestThirdPlaceScore
+ ld c, 2
+ call StringCmp
+ jr c, .done
+ ld hl, wBugContestThirdPlaceWinnerID
+ call CopyTempContestant
+
+.done
+ ret
+; 138a0
+
+CopyTempContestant: ; 138a0
+; Could've just called CopyBytes.
+ ld de, wBugContestTempWinnerID
+rept 3
+ ld a, [de]
+ inc de
+ ld [hli], a
+endr
+ ld a, [de]
+ inc de
+ ld [hl], a
+ ret
+; 138b0
+
+ComputeAIContestantScores: ; 138b0
+ ld e, 0
+.loop
+ push de
+ call Special_CheckBugContestContestantFlag
+ pop de
+ jr nz, .done
+ ld a, e
+ inc a
+ inc a
+ ld [wBugContestTempWinnerID], a
+ dec a
+ ld c, a
+ ld b, 0
+ ld hl, BugContestantPointers
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ inc hl
+ inc hl
+.loop2
+ call Random
+ and 3
+ cp 3
+ jr z, .loop2
+ ld c, a
+ ld b, 0
+ add hl, bc
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld [wBugContestTempMon], a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call Random
+ and 7
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld a, h
+ ld [wBugContestTempScore], a
+ ld a, l
+ ld [wBugContestTempScore + 1], a
+ push de
+ call DetermineContestWinners
+ pop de
+
+.done
+ inc e
+ ld a, e
+ cp 10
+ jr nz, .loop
+ ret
+; 13900
+
+ContestScore: ; 13900
+; Determine the player's score in the Bug Catching Contest.
+
+ xor a
+ ld [hProduct], a
+ ld [hMultiplicand], a
+
+ ld a, [wContestMonSpecies] ; Species
+ and a
+ jr z, .done
+
+ ; Tally the following:
+
+ ; Max HP * 4
+ ld a, [wContestMonMaxHP + 1]
+ call .AddContestStat
+ ld a, [wContestMonMaxHP + 1]
+ call .AddContestStat
+ ld a, [wContestMonMaxHP + 1]
+ call .AddContestStat
+ ld a, [wContestMonMaxHP + 1]
+ call .AddContestStat
+
+ ; Stats
+ ld a, [wContestMonAttack + 1]
+ call .AddContestStat
+ ld a, [wContestMonDefense + 1]
+ call .AddContestStat
+ ld a, [wContestMonSpeed + 1]
+ call .AddContestStat
+ ld a, [wContestMonSpclAtk + 1]
+ call .AddContestStat
+ ld a, [wContestMonSpclDef + 1]
+ call .AddContestStat
+
+ ; DVs
+ ld a, [wContestMonDVs + 0]
+ ld b, a
+ and 2
+ add a
+ add a
+ ld c, a
+
+ swap b
+ ld a, b
+ and 2
+ add a
+ add c
+ ld d, a
+
+ ld a, [wContestMonDVs + 1]
+ ld b, a
+ and 2
+ ld c, a
+
+ swap b
+ ld a, b
+ and 2
+ srl a
+ add c
+ add c
+ add d
+ add d
+
+ call .AddContestStat
+
+ ; Remaining HP / 8
+ ld a, [wContestMonHP + 1]
+ srl a
+ srl a
+ srl a
+ call .AddContestStat
+
+ ; Whether it's holding an item
+ ld a, [wContestMonItem]
+ and a
+ jr z, .done
+
+ ld a, 1
+ call .AddContestStat
+
+.done
+ ret
+; 1397f
+
+.AddContestStat: ; 1397f
+ ld hl, hMultiplicand
+ add [hl]
+ ld [hl], a
+ ret nc
+ dec hl
+ inc [hl]
+ ret
+; 13988
diff --git a/engine/events/card_key.asm b/engine/events/card_key.asm
new file mode 100755
index 000000000..dc4c73ad2
--- /dev/null
+++ b/engine/events/card_key.asm
@@ -0,0 +1,39 @@
+_CardKey: ; 50779
+; Are we even in the right map to use this?
+ ld a, [MapGroup]
+ cp GROUP_RADIO_TOWER_3F
+ jr nz, .nope
+
+ ld a, [MapNumber]
+ cp MAP_RADIO_TOWER_3F
+ jr nz, .nope
+; Are we facing the slot?
+ ld a, [PlayerDirection]
+ and %1100
+ cp OW_UP
+ jr nz, .nope
+
+ call GetFacingTileCoord
+ ld a, d
+ cp 18
+ jr nz, .nope
+ ld a, e
+ cp 6
+ jr nz, .nope
+; Let's use the Card Key.
+ ld hl, .CardKeyScript
+ call QueueScript
+ ld a, TRUE
+ ld [wItemEffectSucceeded], a
+ ret
+
+.nope
+ ld a, FALSE
+ ld [wItemEffectSucceeded], a
+ ret
+; 507af
+
+.CardKeyScript: ; 0x507af
+ closetext
+ farjump MapRadioTower3FSignpost2Script
+; 0x507b4
diff --git a/engine/events/catch_tutorial.asm b/engine/events/catch_tutorial.asm
new file mode 100644
index 000000000..b9352ccd6
--- /dev/null
+++ b/engine/events/catch_tutorial.asm
@@ -0,0 +1,81 @@
+CatchTutorial:: ; 4e554
+ ld a, [BattleType]
+ dec a
+ ld c, a
+ ld hl, .dw
+ ld b, 0
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.dw ; 4e564 (13:6564)
+ dw .DudeTutorial
+ dw .DudeTutorial
+ dw .DudeTutorial
+
+.DudeTutorial: ; 4e56a (13:656a)
+; Back up your name to your Mom's name.
+ ld hl, PlayerName
+ ld de, MomsName
+ ld bc, NAME_LENGTH
+ call CopyBytes
+; Copy Dude's name to your name
+ ld hl, .Dude
+ ld de, PlayerName
+ ld bc, NAME_LENGTH
+ call CopyBytes
+
+ call .LoadDudeData
+
+ xor a
+ ld [hJoyDown], a
+ ld [hJoyPressed], a
+ ld a, [Options]
+ push af
+ and $f8
+ add $3
+ ld [Options], a
+ ld hl, .AutoInput
+ ld a, BANK(.AutoInput)
+ call StartAutoInput
+ callfar StartBattle
+ call StopAutoInput
+ pop af
+
+ ld [Options], a
+ ld hl, MomsName
+ ld de, PlayerName
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ret
+
+.LoadDudeData: ; 4e5b7 (13:65b7)
+ ld hl, wDudeNumItems
+ ld [hl], 1
+ inc hl
+ ld [hl], POTION
+ inc hl
+ ld [hl], 1
+ inc hl
+ ld [hl], -1
+ ld hl, wDudeNumKeyItems
+ ld [hl], 0
+ inc hl
+ ld [hl], -1
+ ld hl, wDudeNumBalls
+ ld a, 1
+ ld [hli], a
+ ld a, POKE_BALL ; 5
+ ld [hli], a
+ ld [hli], a
+ ld [hl], -1
+ ret
+
+.Dude: ; 4e5da
+ db "DUDE@"
+
+.AutoInput: ; 4e5df
+ db NO_INPUT, $ff ; end
diff --git a/engine/events/catch_tutorial_input.asm b/engine/events/catch_tutorial_input.asm
new file mode 100644
index 000000000..9d2a03db2
--- /dev/null
+++ b/engine/events/catch_tutorial_input.asm
@@ -0,0 +1,43 @@
+_DudeAutoInput_A:: ; 1de28a
+ ld hl, DudeAutoInput_A
+ jr _DudeAutoInput
+
+_DudeAutoInput_RightA: ; 1de28f
+ ld hl, DudeAutoInput_RightA
+ jr _DudeAutoInput
+
+_DudeAutoInput_DownA: ; 1de294
+ ld hl, DudeAutoInput_DownA
+ jr _DudeAutoInput
+
+_DudeAutoInput: ; 1de299
+ ld a, BANK(DudeAutoInputs)
+ call StartAutoInput
+ ret
+
+DudeAutoInputs:
+
+DudeAutoInput_A: ; 1de29f
+ db NO_INPUT, $50
+ db A_BUTTON, $00
+ db NO_INPUT, $ff ; end
+
+DudeAutoInput_RightA: ; 1de2a5
+ db NO_INPUT, $08
+ db D_RIGHT, $00
+ db NO_INPUT, $08
+ db A_BUTTON, $00
+ db NO_INPUT, $ff ; end
+
+DudeAutoInput_DownA: ; 1de2af
+ db NO_INPUT, $fe
+ db NO_INPUT, $fe
+ db NO_INPUT, $fe
+ db NO_INPUT, $fe
+ db D_DOWN, $00
+ db NO_INPUT, $fe
+ db NO_INPUT, $fe
+ db NO_INPUT, $fe
+ db NO_INPUT, $fe
+ db A_BUTTON, $00
+ db NO_INPUT, $ff ; end
diff --git a/engine/events/celebi.asm b/engine/events/celebi.asm
new file mode 100755
index 000000000..b7bf95145
--- /dev/null
+++ b/engine/events/celebi.asm
@@ -0,0 +1,380 @@
+Special_CelebiShrineEvent: ; 4989a
+ call DelayFrame
+ ld a, [VramState]
+ push af
+ xor a
+ ld [VramState], a
+ call LoadCelebiGFX
+ depixel 0, 10, 7, 0
+ ld a, SPRITE_ANIM_INDEX_CELEBI
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $84
+ ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+ add hl, bc
+ ld [hl], SPRITE_ANIM_SEQ_CELEBI
+ ld hl, SPRITEANIMSTRUCT_0F
+ add hl, bc
+ ld a, $80
+ ld [hl], a
+ ld a, 160 ; frame count
+ ld [wcf64], a
+ ld d, $0
+.loop
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .done
+ push bc
+ call GetCelebiSpriteTile
+ inc d
+ push de
+ ld a, $90
+ ld [wCurrSpriteOAMAddr], a
+ farcall DoNextFrameForAllSprites
+ call CelebiEvent_CountDown
+ ld c, 2
+ call DelayFrames
+ pop de
+ pop bc
+ jr .loop
+
+
+.done
+ pop af
+ ld [VramState], a
+ call .RefreshPlayerSprite_ClearAllOthers
+ call CelebiEvent_SetBattleType
+ ret
+
+; 498f9
+
+.RefreshPlayerSprite_ClearAllOthers: ; 498f9
+ ld hl, Sprites + 2
+ xor a
+ ld c, $4
+.OAMloop:
+ ld [hli], a
+ inc hl
+ inc hl
+ inc hl
+ inc a
+ dec c
+ jr nz, .OAMloop
+ ld hl, Sprites + 4 * 4
+ ld bc, 36 * 4
+ xor a
+ call ByteFill
+ ret
+
+; 49912
+
+LoadCelebiGFX: ; 49912
+ farcall ClearSpriteAnims
+ ld de, SpecialCelebiLeafGFX
+ ld hl, VTiles1
+ lb bc, BANK(SpecialCelebiLeafGFX), 4
+ call Request2bpp
+ ld de, SpecialCelebiGFX
+ ld hl, VTiles0 tile $84
+ lb bc, BANK(SpecialCelebiGFX), $10
+ call Request2bpp
+ xor a
+ ld [wJumptableIndex], a
+ ret
+
+; 49935
+
+CelebiEvent_CountDown: ; 49935
+ ld hl, wcf64
+ ld a, [hl]
+ and a
+ jr z, .done
+ dec [hl]
+ ret
+
+
+.done
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+; 49944
+
+CelebiEvent_SpawnLeaf: ; 49944
+; unused
+ ld hl, wcf65
+ ld a, [hl]
+ inc [hl]
+ and $7
+ ret nz
+ ld a, [hl]
+ and $18
+ sla a
+ add $40
+ ld d, a
+ ld e, $0
+ ld a, SPRITE_ANIM_INDEX_FLY_LEAF ; fly land
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $80
+ ret
+
+; 49962
+
+SpecialCelebiLeafGFX: ; 49962
+INCBIN "gfx/overworld/cut_grass.2bpp"
+
+SpecialCelebiGFX: ; 499a2
+INCBIN "gfx/overworld/celebi/1.2bpp"
+INCBIN "gfx/overworld/celebi/2.2bpp"
+INCBIN "gfx/overworld/celebi/3.2bpp"
+INCBIN "gfx/overworld/celebi/4.2bpp"
+
+
+UpdateCelebiPosition: ; 49aa2 (12:5aa2)
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld a, [hl]
+ push af
+ ld hl, SPRITEANIMSTRUCT_YCOORD
+ add hl, bc
+ ld a, [hl]
+ cp 8 * 10 + 2
+ jp nc, .FreezeCelebiPosition
+ ld hl, SPRITEANIMSTRUCT_YCOORD
+ add hl, bc
+ inc [hl]
+ ld hl, SPRITEANIMSTRUCT_0F
+ add hl, bc
+ ld a, [hl]
+ ld d, a
+ cp $3a
+ jr c, .skip
+ jr z, .skip
+ sub $3
+ ld [hl], a
+.skip
+ ld hl, SPRITEANIMSTRUCT_0E
+ add hl, bc
+ ld a, [hl]
+ inc [hl]
+ call CelebiEvent_Cosine
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld [hl], a
+ ld d, a
+ ld hl, SPRITEANIMSTRUCT_XCOORD
+ add hl, bc
+ add [hl]
+ cp 8 * 11 + 4
+ jr nc, .ShiftY
+ cp 8 * 8 + 4
+ jr nc, .ReinitSpriteAnimFrame
+.ShiftY:
+ pop af
+ push af
+ cp d
+ jr nc, .moving_left
+ ld hl, SPRITEANIMSTRUCT_XCOORD
+ add hl, bc
+ add [hl]
+ cp 8 * 10
+ jr c, .float_up
+ jr .float_down
+
+.moving_left
+ ld hl, SPRITEANIMSTRUCT_XCOORD
+ add hl, bc
+ add [hl]
+ cp 8 * 10
+ jr nc, .float_up
+.float_down
+ ld hl, SPRITEANIMSTRUCT_YCOORD
+ add hl, bc
+ ld a, [hl]
+ sub $2
+ ld [hl], a
+ jr .ReinitSpriteAnimFrame
+
+.float_up
+ ld hl, SPRITEANIMSTRUCT_YCOORD
+ add hl, bc
+ ld a, [hl]
+ add $1
+ ld [hl], a
+.ReinitSpriteAnimFrame:
+ pop af
+ ld hl, SPRITEANIMSTRUCT_XCOORD
+ add hl, bc
+ add [hl]
+ cp 8 * 10
+ jr c, .left
+ cp -(8 * 3 + 2)
+ jr nc, .left
+ ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+ add hl, bc
+ ld a, SPRITE_ANIM_FRAMESET_CELEBI_RIGHT
+ call ReinitSpriteAnimFrame
+ jr .done
+
+.left
+ ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+ add hl, bc
+ ld a, SPRITE_ANIM_FRAMESET_CELEBI_LEFT
+ call ReinitSpriteAnimFrame
+.done
+ ret
+
+
+.FreezeCelebiPosition: ; 49b30 (12:5b30)
+ pop af
+ ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+ add hl, bc
+ ld a, SPRITE_ANIM_FRAMESET_CELEBI_LEFT
+ call ReinitSpriteAnimFrame
+ ret
+
+
+CelebiEvent_Cosine: ; 49b3b (12:5b3b)
+ add $10
+ and $3f
+ cp $20
+ jr nc, .negative
+ call .SineFunction
+ ld a, h
+ ret
+
+.negative
+ and $1f
+ call .SineFunction
+ ld a, h
+ xor $ff
+ inc a
+ ret
+
+
+.SineFunction: ; 49b52 (12:5b52)
+ ld e, a
+ ld a, d
+ ld d, $0
+ ld hl, .sinewave
+ add hl, de
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld hl, 0
+.multiply
+ srl a
+ jr nc, .even
+ add hl, de
+.even
+ sla e
+ rl d
+ and a
+ jr nz, .multiply
+ ret
+
+; 49b6e (12:5b6e)
+
+.sinewave ; 49b6e
+ sine_wave $100
+; 49bae
+
+GetCelebiSpriteTile: ; 49bae
+ push hl
+ push bc
+ push de
+ ld a, d
+ ld d, $3
+ ld e, d
+ cp $0
+ jr z, .Frame1
+ cp d
+ jr z, .Frame2
+ call .AddE
+ cp d
+ jr z, .Frame3
+ call .AddE
+ cp d
+ jr z, .Frame4
+ call .AddE
+ cp d
+ jr c, .done
+ jr .restart
+
+
+.Frame1:
+ ld a, $84
+ jr .load_tile
+
+
+.Frame2:
+ ld a, $88
+ jr .load_tile
+
+
+.Frame3:
+ ld a, $8c
+ jr .load_tile
+
+
+.Frame4:
+ ld a, $90
+
+.load_tile
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], a
+ jr .done
+
+
+.restart
+ pop de
+ ld d, $ff
+ push de
+
+.done
+ pop de
+ pop bc
+ pop hl
+ ret
+
+; 49bed
+
+.AddE: ; 49bed
+ push af
+ ld a, d
+ add e
+ ld d, a
+ pop af
+ ret
+
+; 49bf3
+
+CelebiEvent_SetBattleType: ; 49bf3
+ ld a, BATTLETYPE_CELEBI
+ ld [BattleType], a
+ ret
+
+; 49bf9
+
+CheckCaughtCelebi: ; 49bf9
+ ld a, [wBattleResult]
+ bit 6, a
+ jr z, .false
+ ld a, $1
+ ld [ScriptVar], a
+ jr .done
+
+
+.false
+ xor a
+ ld [ScriptVar], a
+
+.done
+ ret
+
+; 49c0c
diff --git a/engine/events/crystal_unown.asm b/engine/events/crystal_unown.asm
new file mode 100644
index 000000000..6c0e972f8
--- /dev/null
+++ b/engine/events/crystal_unown.asm
@@ -0,0 +1,327 @@
+SpecialHoOhChamber: ; 0x8addb
+ ld hl, PartySpecies
+ ld a, [hl]
+ cp HO_OH ; is Ho-oh the first Pokémon in the party?
+ jr nz, .done ; if not, we're done
+ call GetSecondaryMapHeaderPointer
+ ld de, EVENT_WALL_OPENED_IN_HO_OH_CHAMBER
+ ld b, SET_FLAG
+ call EventFlagAction
+.done
+ ret
+; 0x8adef
+
+SpecialOmanyteChamber: ; 8adef
+ call GetSecondaryMapHeaderPointer
+ ld de, EVENT_WALL_OPENED_IN_OMANYTE_CHAMBER
+ ld b, CHECK_FLAG
+ call EventFlagAction
+ ld a, c
+ and a
+ jr nz, .nope
+
+ ld a, WATER_STONE
+ ld [CurItem], a
+ ld hl, NumItems
+ call CheckItem
+ jr c, .open
+
+ ld a, [PartyCount]
+ ld b, a
+ inc b
+.loop
+ dec b
+ jr z, .nope
+ ld a, b
+ dec a
+ ld [CurPartyMon], a
+ push bc
+ ld a, MON_ITEM
+ call GetPartyParamLocation
+ pop bc
+ ld a, [hl]
+ cp WATER_STONE
+ jr nz, .loop
+
+.open
+ call GetSecondaryMapHeaderPointer
+ ld de, EVENT_WALL_OPENED_IN_OMANYTE_CHAMBER
+ ld b, SET_FLAG
+ call EventFlagAction
+
+.nope
+ ret
+; 8ae30
+
+SpecialAerodactylChamber: ; 8ae30
+ push de
+ push bc
+
+ call GetSecondaryMapHeaderPointer
+ ld a, h
+ cp HIGH(RuinsOfAlphAerodactylChamber_SecondMapHeader)
+ jr nz, .nope
+ ld a, l
+ cp LOW(RuinsOfAlphAerodactylChamber_SecondMapHeader)
+ jr nz, .nope
+
+ ld de, EVENT_WALL_OPENED_IN_AERODACTYL_CHAMBER
+ ld b, SET_FLAG
+ call EventFlagAction
+
+ scf
+ jr .done
+
+.nope
+ and a
+
+.done
+ pop bc
+ pop de
+ ret
+; 8ae4e
+
+SpecialKabutoChamber: ; 8ae4e
+ push hl
+ push de
+
+ call GetSecondaryMapHeaderPointer
+ ld a, h
+ cp HIGH(RuinsOfAlphKabutoChamber_SecondMapHeader)
+ jr nz, .done
+ ld a, l
+ cp LOW(RuinsOfAlphKabutoChamber_SecondMapHeader)
+ jr nz, .done
+
+ ld de, EVENT_WALL_OPENED_IN_KABUTO_CHAMBER
+ ld b, SET_FLAG
+ call EventFlagAction
+
+.done
+ pop de
+ pop hl
+ ret
+; 8ae68
+
+Special_DisplayUnownWords: ; 8ae68
+ ld a, [ScriptVar]
+ ld hl, .MenuDataHeader_Escape
+ and a
+ jr z, .load
+
+ ld d, $0
+ ld e, $5
+.loop
+ add hl, de
+ dec a
+ jr nz, .loop
+
+.load
+ call LoadMenuDataHeader
+ xor a
+ ld [hBGMapMode], a
+ call MenuBox
+ call UpdateSprites
+ call ApplyTilemap
+ call MenuBoxCoord2Tile
+ inc hl
+ ld d, 0
+ ld e, SCREEN_WIDTH
+ add hl, de
+ add hl, de
+ ld a, [ScriptVar]
+ ld c, a
+ ld de, .UnownText
+ and a
+ jr z, .copy
+.loop2
+ ld a, [de]
+ inc de
+ cp $ff
+ jr nz, .loop2
+ dec c
+ jr nz, .loop2
+.copy
+ call .CopyWord
+ ld bc, AttrMap - TileMap
+ add hl, bc
+ call .FillAttr
+ call WaitBGMap2
+ call JoyWaitAorB
+ call PlayClickSFX
+ call CloseWindow
+ ret
+; 8aebc
+
+.UnownText: ; 8aebc
+
+unownwall: MACRO
+rept _NARG
+if \1 == "-"
+x = $64
+else
+if \1 >= "Y"
+x = 2 * (\1 - "Y") + $60
+else
+if \1 >= "Q"
+x = 2 * (\1 - "Q") + $40
+else
+if \1 >= "I"
+x = 2 * (\1 - "I") + $20
+else
+x = 2 * (\1 - "A")
+endc
+endc
+endc
+endc
+ db x
+shift
+endr
+ db $ff
+endm
+
+.UnownText_Escape:
+ ; db $08, $44, $04, $00, $2e, $08, $ff
+ unownwall "E", "S", "C", "A", "P", "E"
+.UnownText_Light:
+ ; db $26, $20, $0c, $0e, $46, $ff
+ unownwall "L", "I", "G", "H", "T"
+.UnownText_Water:
+ ; db $4c, $00, $46, $08, $42, $ff
+ unownwall "W", "A", "T", "E", "R"
+.UnownText_Ho_Oh:
+ ; db $0e, $2c, $64, $2c, $0e, $ff
+ unownwall "H", "O", "-", "O", "H"
+; 8aed5
+
+.MenuDataHeader_Escape: ; 0x8aed5
+ db $40 ; flags
+ db 04, 03 ; start coords
+ db 09, 16 ; end coords
+
+.MenuDataHeader_Light: ; 0x8aeda
+ db $40 ; flags
+ db 04, 04 ; start coords
+ db 09, 15 ; end coords
+
+.MenuDataHeader_Water: ; 0x8aedf
+ db $40 ; flags
+ db 04, 04 ; start coords
+ db 09, 15 ; end coords
+
+.MenuDataHeader_Ho_Oh: ; 0x8aee4
+ db $40 ; flags
+ db 04, 04 ; start coords
+ db 09, 15 ; end coords
+; 8aee9
+
+.FillAttr: ; 8aee9
+ ld a, [de]
+ cp $ff
+ ret z
+ cp $60
+ ld a, VRAM_BANK_1 | PAL_BG_BROWN
+ jr c, .got_pal
+ ld a, PAL_BG_BROWN
+
+.got_pal
+ call .PlaceSquare
+ inc hl
+ inc hl
+ inc de
+ jr .FillAttr
+; 8aefd
+
+.PlaceSquare: ; 8aefd
+ push hl
+ ld [hli], a
+ ld [hld], a
+ ld b, 0
+ ld c, SCREEN_WIDTH
+ add hl, bc
+ ld [hli], a
+ ld [hl], a
+ pop hl
+ ret
+; 8af09
+
+.CopyWord: ; 8af09
+ push hl
+ push de
+.word_loop
+ ld a, [de]
+ cp $ff
+ jr z, .word_done
+ ld c, a
+ call .ConvertChar
+ inc hl
+ inc hl
+ inc de
+ jr .word_loop
+
+.word_done
+ pop de
+ pop hl
+ ret
+; 8af1c
+
+.ConvertChar: ; 8af1c
+ push hl
+ ld a, c
+ cp $60
+ jr z, .Tile60
+ cp $62
+ jr z, .Tile62
+ cp $64
+ jr z, .Tile64
+ ld [hli], a
+ inc a
+ ld [hld], a
+ dec a
+ ld b, 0
+ ld c, SCREEN_WIDTH
+ add hl, bc
+ ld c, $10
+ add c
+ ld [hli], a
+ inc a
+ ld [hl], a
+ pop hl
+ ret
+
+.Tile60:
+ ld [hl], $5b
+ inc hl
+ ld [hl], $5c
+ ld bc, SCREEN_WIDTH - 1
+ add hl, bc
+ ld [hl], $4d
+ inc hl
+ ld [hl], $5d
+ pop hl
+ ret
+
+.Tile62:
+ ld [hl], $4e
+ inc hl
+ ld [hl], $4f
+ ld bc, SCREEN_WIDTH - 1
+ add hl, bc
+ ld [hl], $5e
+ inc hl
+ ld [hl], $5f
+ pop hl
+ ret
+
+.Tile64:
+ ld [hl], $2
+ inc hl
+ ld [hl], $3
+ ld bc, SCREEN_WIDTH - 1
+ add hl, bc
+ ld [hl], $3
+ inc hl
+ ld [hl], $2
+ pop hl
+ ret
+; 8af6b
diff --git a/engine/events/daycare.asm b/engine/events/daycare.asm
new file mode 100755
index 000000000..6395a40fb
--- /dev/null
+++ b/engine/events/daycare.asm
@@ -0,0 +1,792 @@
+ const_def
+ const DAYCARETEXT_MAN_INTRO
+ const DAYCARETEXT_MAN_EGG
+ const DAYCARETEXT_LADY_INTRO
+ const DAYCARETEXT_LADY_EGG
+ const DAYCARETEXT_WHICH_ONE
+ const DAYCARETEXT_DEPOSIT
+ const DAYCARETEXT_CANT_BREED_EGG
+ const DAYCARETEXT_LAST_MON
+ const DAYCARETEXT_LAST_ALIVE_MON
+ const DAYCARETEXT_COME_BACK_LATER
+ const DAYCARETEXT_REMOVE_MAIL
+ const DAYCARETEXT_GENIUSES
+ const DAYCARETEXT_ASK_WITHDRAW
+ const DAYCARETEXT_WITHDRAW
+ const DAYCARETEXT_TOO_SOON
+ const DAYCARETEXT_PARTY_FULL
+ const DAYCARETEXT_NOT_ENOUGH_MONEY
+ const DAYCARETEXT_OH_FINE
+ const DAYCARETEXT_COME_AGAIN
+ const DAYCARETEXT_13
+
+Special_DayCareMan: ; 166d6
+ ld hl, wDayCareMan
+ bit 0, [hl]
+ jr nz, .AskWithdrawMon
+ ld hl, wDayCareMan
+ ld a, DAYCARETEXT_MAN_INTRO
+ call DayCareManIntroText
+ jr c, .cancel
+ call DayCareAskDepositPokemon
+ jr c, .print_text
+ farcall DepositMonWithDayCareMan
+ ld hl, wDayCareMan
+ set 0, [hl]
+ call DayCare_DepositPokemonText
+ call DayCare_InitBreeding
+ ret
+
+.AskWithdrawMon:
+ farcall GetBreedMon1LevelGrowth
+ ld hl, wBreedMon1Nick
+ call GetPriceToRetrieveBreedmon
+ call DayCare_AskWithdrawBreedMon
+ jr c, .print_text
+ farcall RetrievePokemonFromDayCareMan
+ call DayCare_TakeMoney_PlayCry
+ ld hl, wDayCareMan
+ res 0, [hl]
+ res 5, [hl]
+ jr .cancel
+
+.print_text
+ call PrintDayCareText
+
+.cancel
+ ld a, DAYCARETEXT_13
+ call PrintDayCareText
+ ret
+; 1672a
+
+Special_DayCareLady: ; 1672a
+ ld hl, wDayCareLady
+ bit 0, [hl]
+ jr nz, .AskWithdrawMon
+ ld hl, wDayCareLady
+ ld a, DAYCARETEXT_LADY_INTRO
+ call DayCareLadyIntroText
+ jr c, .cancel
+ call DayCareAskDepositPokemon
+ jr c, .print_text
+ farcall DepositMonWithDayCareLady
+ ld hl, wDayCareLady
+ set 0, [hl]
+ call DayCare_DepositPokemonText
+ call DayCare_InitBreeding
+ ret
+
+.AskWithdrawMon:
+ farcall GetBreedMon2LevelGrowth
+ ld hl, wBreedMon2Nick
+ call GetPriceToRetrieveBreedmon
+ call DayCare_AskWithdrawBreedMon
+ jr c, .print_text
+ farcall RetrievePokemonFromDayCareLady
+ call DayCare_TakeMoney_PlayCry
+ ld hl, wDayCareLady
+ res 0, [hl]
+ ld hl, wDayCareMan
+ res 5, [hl]
+ jr .cancel
+
+.print_text
+ call PrintDayCareText
+
+.cancel
+ ld a, DAYCARETEXT_13
+ call PrintDayCareText
+ ret
+; 16781
+
+DayCareLadyIntroText: ; 16781
+ bit 7, [hl]
+ jr nz, .okay
+ set 7, [hl]
+ inc a
+.okay
+ call PrintDayCareText
+ call YesNoBox
+ ret
+; 1678f
+
+DayCareManIntroText: ; 1678f
+ set 7, [hl]
+ call PrintDayCareText
+ call YesNoBox
+ ret
+; 16798
+
+DayCareAskDepositPokemon: ; 16798
+ ld a, [PartyCount]
+ cp 2
+ jr c, .OnlyOneMon
+ ld a, DAYCARETEXT_WHICH_ONE
+ call PrintDayCareText
+ ld b, PARTYMENUACTION_GIVE_MON
+ farcall SelectTradeOrDayCareMon
+ jr c, .Declined
+ ld a, [CurPartySpecies]
+ cp EGG
+ jr z, .Egg
+ farcall CheckCurPartyMonFainted
+ jr c, .OutOfUsableMons
+ ld hl, PartyMon1Item
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, [CurPartyMon]
+ call AddNTimes
+ ld d, [hl]
+ farcall ItemIsMail
+ jr c, .HoldingMail
+ ld hl, PartyMonNicknames
+ ld a, [CurPartyMon]
+ call GetNick
+ and a
+ ret
+
+.Declined:
+ ld a, DAYCARETEXT_COME_AGAIN
+ scf
+ ret
+
+.Egg:
+ ld a, DAYCARETEXT_CANT_BREED_EGG
+ scf
+ ret
+
+.OnlyOneMon:
+ ld a, DAYCARETEXT_LAST_MON
+ scf
+ ret
+
+.OutOfUsableMons:
+ ld a, DAYCARETEXT_LAST_ALIVE_MON
+ scf
+ ret
+
+.HoldingMail:
+ ld a, DAYCARETEXT_REMOVE_MAIL
+ scf
+ ret
+; 167f1
+
+.DummyText: ; 0x167f1
+ ;
+ text_jump UnknownText_0x1bdaa7
+ db "@"
+; 0x167f6
+
+DayCare_DepositPokemonText: ; 167f6
+ ld a, DAYCARETEXT_DEPOSIT
+ call PrintDayCareText
+ ld a, [CurPartySpecies]
+ call PlayCry
+ ld a, DAYCARETEXT_COME_BACK_LATER
+ call PrintDayCareText
+ ret
+; 16807
+
+DayCare_AskWithdrawBreedMon: ; 16807
+ ld a, [StringBuffer2 + 1]
+ and a
+ jr nz, .grew_at_least_one_level
+ ld a, DAYCARETEXT_PARTY_FULL
+ call PrintDayCareText
+ call YesNoBox
+ jr c, .refused
+ jr .check_money
+
+.grew_at_least_one_level
+ ld a, DAYCARETEXT_GENIUSES
+ call PrintDayCareText
+ call YesNoBox
+ jr c, .refused
+ ld a, DAYCARETEXT_ASK_WITHDRAW
+ call PrintDayCareText
+ call YesNoBox
+ jr c, .refused
+
+.check_money
+ ld de, Money
+ ld bc, StringBuffer2 + 2
+ farcall CompareMoney
+ jr c, .not_enough_money
+ ld a, [PartyCount]
+ cp PARTY_LENGTH
+ jr nc, .PartyFull
+ and a
+ ret
+
+.refused
+ ld a, DAYCARETEXT_COME_AGAIN
+ scf
+ ret
+
+.not_enough_money
+ ld a, DAYCARETEXT_OH_FINE
+ scf
+ ret
+
+.PartyFull:
+ ld a, DAYCARETEXT_NOT_ENOUGH_MONEY
+ scf
+ ret
+; 16850
+
+DayCare_TakeMoney_PlayCry: ; 16850
+ ld bc, StringBuffer2 + 2
+ ld de, Money
+ farcall TakeMoney
+ ld a, DAYCARETEXT_WITHDRAW
+ call PrintDayCareText
+ ld a, [CurPartySpecies]
+ call PlayCry
+ ld a, DAYCARETEXT_TOO_SOON
+ call PrintDayCareText
+ ret
+; 1686d
+
+GetPriceToRetrieveBreedmon: ; 1686d
+ ld a, b
+ ld [StringBuffer2], a
+ ld a, d
+ ld [StringBuffer2 + 1], a
+ ld de, StringBuffer1
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ld hl, 0
+ ld bc, 100
+ ld a, [StringBuffer2 + 1]
+ call AddNTimes
+ ld de, 100
+ add hl, de
+ xor a
+ ld [StringBuffer2 + 2], a
+ ld a, h
+ ld [StringBuffer2 + 3], a
+ ld a, l
+ ld [StringBuffer2 + 4], a
+ ret
+; 1689b
+
+PrintDayCareText: ; 1689b
+ ld e, a
+ ld d, 0
+ ld hl, .TextTable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call PrintText
+ ret
+; 168aa
+
+.TextTable: ; 168aa
+ dw .DayCareManIntro ; 00
+ dw .DayCareManOddEgg ; 01
+ dw .DayCareLadyIntro ; 02
+ dw .DayCareLadyOddEgg ; 03
+ dw .WhichOne ; 04
+ dw .OkayIllRaiseYourMon ; 05
+ dw .CantAcceptEgg ; 06
+ dw .JustOneMon ; 07
+ dw .LastHealthyMon ; 08
+ dw .ComeBackForItLater ; 09
+ dw .RemoveMail ; 0a
+ dw .AreWeGeniusesOrWhat ; 0b
+ dw .AskRetrieveMon ; 0c
+ dw .PerfectHeresYourMon ; 0d
+ dw .GotBackMon ; 0e
+ dw .ImmediatelyWithdrawMon ; 0f
+ dw .PartyFull ; 10
+ dw .NotEnoughMoney ; 11
+ dw .OhFineThen ; 12
+ dw .ComeAgain ; 13
+; 168d2
+
+.DayCareManIntro: ; 0x168d2
+ ; I'm the DAY-CARE MAN. Want me to raise a #MON?
+ text_jump UnknownText_0x1bdaa9
+ db "@"
+; 0x168d7
+
+.DayCareManOddEgg: ; 0x168d7
+ ; I'm the DAY-CARE MAN. Do you know about EGGS? I was raising #MON with my wife, you see. We were shocked to find an EGG! How incredible is that? So, want me to raise a #MON?
+ text_jump UnknownText_0x1bdad8
+ db "@"
+; 0x168dc
+
+.DayCareLadyIntro: ; 0x168dc
+ ; I'm the DAY-CARE LADY. Should I raise a #MON for you?
+ text_jump UnknownText_0x1bdb85
+ db "@"
+; 0x168e1
+
+.DayCareLadyOddEgg: ; 0x168e1
+ ; I'm the DAY-CARE LADY. Do you know about EGGS? My husband and I were raising some #MON, you see. We were shocked to find an EGG! How incredible could that be? Should I raise a #MON for you?
+ text_jump UnknownText_0x1bdbbb
+ db "@"
+; 0x168e6
+
+.WhichOne: ; 0x168e6
+ ; What should I raise for you?
+ text_jump UnknownText_0x1bdc79
+ db "@"
+; 0x168eb
+
+.JustOneMon: ; 0x168eb
+ ; Oh? But you have just one #MON.
+ text_jump UnknownText_0x1bdc97
+ db "@"
+; 0x168f0
+
+.CantAcceptEgg: ; 0x168f0
+ ; Sorry, but I can't accept an EGG.
+ text_jump UnknownText_0x1bdcb8
+ db "@"
+; 0x168f5
+
+.RemoveMail: ; 0x168f5
+ ; Remove MAIL before you come see me.
+ text_jump UnknownText_0x1bdcda
+ db "@"
+; 0x168fa
+
+.LastHealthyMon: ; 0x168fa
+ ; If you give me that, what will you battle with?
+ text_jump UnknownText_0x1bdcff
+ db "@"
+; 0x168ff
+
+.OkayIllRaiseYourMon: ; 0x168ff
+ ; OK. I'll raise your @ .
+ text_jump UnknownText_0x1bdd30
+ db "@"
+; 0x16904
+
+.ComeBackForItLater: ; 0x16904
+ ; Come back for it later.
+ text_jump UnknownText_0x1bdd4b
+ db "@"
+; 0x16909
+
+.AreWeGeniusesOrWhat: ; 0x16909
+ ; Are we geniuses or what? Want to see your @ ?
+ text_jump UnknownText_0x1bdd64
+ db "@"
+; 0x1690e
+
+.AskRetrieveMon: ; 0x1690e
+ ; Your @ has grown a lot. By level, it's grown by @ . If you want your #MON back, it will cost ¥@ .
+ text_jump UnknownText_0x1bdd96
+ db "@"
+; 0x16913
+
+.PerfectHeresYourMon: ; 0x16913
+ ; Perfect! Here's your #MON.
+ text_jump UnknownText_0x1bde04
+ db "@"
+; 0x16918
+
+.GotBackMon: ; 0x16918
+ ; got back @ .
+ text_jump UnknownText_0x1bde1f
+ db "@"
+; 0x1691d
+
+.ImmediatelyWithdrawMon: ; 0x1691d
+ ; Huh? Back already? Your @ needs a little more time with us. If you want your #MON back, it will cost ¥100.
+ text_jump UnknownText_0x1bde32
+ db "@"
+; 0x16922
+
+.PartyFull: ; 0x16922
+ ; You have no room for it.
+ text_jump UnknownText_0x1bdea2
+ db "@"
+; 0x16927
+
+.NotEnoughMoney: ; 0x16927
+ ; You don't have enough money.
+ text_jump UnknownText_0x1bdebc
+ db "@"
+; 0x1692c
+
+.OhFineThen: ; 0x1692c
+ ; Oh, fine then.
+ text_jump UnknownText_0x1bded9
+ db "@"
+; 0x16931
+
+.ComeAgain: ; 0x16931
+ ; Come again.
+ text_jump UnknownText_0x1bdee9
+ db "@"
+; 0x16936
+
+Special_DayCareManOutside: ; 16936
+ ld hl, wDayCareMan
+ bit 6, [hl]
+ jr nz, .AskGiveEgg
+ ld hl, .NotYet
+ call PrintText
+ ret
+
+.NotYet: ; 0x16944
+ ; Not yet…
+ text_jump UnknownText_0x1bdef6
+ db "@"
+; 0x16949
+
+.AskGiveEgg: ; 16949
+ ld hl, .IntroText
+ call PrintText
+ call YesNoBox
+ jr c, .Declined
+ ld a, [PartyCount]
+ cp PARTY_LENGTH
+ jr nc, .PartyFull
+ call DayCare_GiveEgg
+ ld hl, wDayCareMan
+ res 6, [hl]
+ call DayCare_InitBreeding
+ ld hl, .GotEggText
+ call PrintText
+ ld de, SFX_GET_EGG_FROM_DAY_CARE_LADY
+ call PlaySFX
+ ld c, 120
+ call DelayFrames
+ ld hl, .TakeGoodCareOfItText
+ jr .Load0
+
+.Declined:
+ ld hl, .IllKeepItThanksText
+
+.Load0:
+ call PrintText
+ xor a
+ ld [ScriptVar], a
+ ret
+
+.PartyFull:
+ ld hl, .PartyFullText
+ call PrintText
+ ld a, $1
+ ld [ScriptVar], a
+ ret
+; 16993
+
+.IntroText: ; 0x16993
+ ; Ah, it's you! We were raising your #MON, and my goodness, were we surprised! Your #MON had an EGG! We don't know how it got there, but your #MON had it. You want it?
+ text_jump UnknownText_0x1bdf00
+ db "@"
+; 0x16998
+
+.GotEggText: ; 0x16998
+ ; received the EGG!
+ text_jump UnknownText_0x1bdfa5
+ db "@"
+; 0x1699d
+
+.TakeGoodCareOfItText: ; 0x1699d
+ ; Take good care of it.
+ text_jump UnknownText_0x1bdfba
+ db "@"
+; 0x169a2
+
+.IllKeepItThanksText: ; 0x169a2
+ ; Well then, I'll keep it. Thanks!
+ text_jump UnknownText_0x1bdfd1
+ db "@"
+; 0x169a7
+
+.PartyFullText: ; 0x169a7
+ ; You have no room in your party. Come back later.
+ text_jump UnknownText_0x1bdff2
+ db "@"
+; 0x169ac
+
+DayCare_GiveEgg: ; 169ac
+ ld a, [wEggMonLevel]
+ ld [CurPartyLevel], a
+ ld hl, PartyCount
+ ld a, [hl]
+ cp PARTY_LENGTH
+ jr nc, .PartyFull
+ inc a
+ ld [hl], a
+
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld a, EGG
+ ld [hli], a
+ ld a, [wEggMonSpecies]
+ ld [CurSpecies], a
+ ld [CurPartySpecies], a
+ ld a, -1
+ ld [hl], a
+
+ ld hl, PartyMonNicknames
+ ld bc, PKMN_NAME_LENGTH
+ call DayCare_GetCurrentPartyMember
+ ld hl, wEggNick
+ call CopyBytes
+
+ ld hl, PartyMonOT
+ ld bc, NAME_LENGTH
+ call DayCare_GetCurrentPartyMember
+ ld hl, wEggOT
+ call CopyBytes
+
+ ld hl, PartyMon1
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call DayCare_GetCurrentPartyMember
+ ld hl, wEggMon
+ ld bc, wEggMonEnd - wEggMon
+ call CopyBytes
+
+ call GetBaseData
+ ld a, [PartyCount]
+ dec a
+ ld hl, PartyMon1
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ ld b, h
+ ld c, l
+ ld hl, MON_ID + 1
+ add hl, bc
+ push hl
+ ld hl, MON_MAXHP
+ add hl, bc
+ ld d, h
+ ld e, l
+ pop hl
+ push bc
+ ld b, $0
+ predef CalcPkmnStats
+ pop bc
+ ld hl, MON_HP
+ add hl, bc
+ xor a
+ ld [hli], a
+ ld [hl], a
+ and a
+ ret
+
+.PartyFull:
+ scf
+ ret
+; 16a31
+
+DayCare_GetCurrentPartyMember: ; 16a31
+ ld a, [PartyCount]
+ dec a
+ call AddNTimes
+ ld d, h
+ ld e, l
+ ret
+; 16a3b
+
+DayCare_InitBreeding: ; 16a3b
+ ld a, [wDayCareLady]
+ bit 0, a
+ ret z
+ ld a, [wDayCareMan]
+ bit 0, a
+ ret z
+ callfar CheckBreedmonCompatibility
+ ld a, [wd265]
+ and a
+ ret z
+ inc a
+ ret z
+ ld hl, wDayCareMan
+ set 5, [hl]
+.loop
+ call Random
+ cp 150
+ jr c, .loop
+ ld [wStepsToEgg], a
+ jp .UselessJump
+; 16a66
+
+.UselessJump: ; 16a66
+ xor a
+ ld hl, wEggMon
+ ld bc, wEggMonEnd - wEggMon
+ call ByteFill
+ ld hl, wEggNick
+ ld bc, PKMN_NAME_LENGTH
+ call ByteFill
+ ld hl, wEggOT
+ ld bc, NAME_LENGTH
+ call ByteFill
+ ld a, [wBreedMon1DVs]
+ ld [TempMonDVs], a
+ ld a, [wBreedMon1DVs + 1]
+ ld [TempMonDVs + 1], a
+ ld a, [wBreedMon1Species]
+ ld [CurPartySpecies], a
+ ld a, $3
+ ld [MonType], a
+ ld a, [wBreedMon1Species]
+ cp DITTO
+ ld a, $1
+ jr z, .LoadWhichBreedmonIsTheMother
+ ld a, [wBreedMon2Species]
+ cp DITTO
+ ld a, $0
+ jr z, .LoadWhichBreedmonIsTheMother
+ farcall GetGender
+ ld a, $0
+ jr z, .LoadWhichBreedmonIsTheMother
+ inc a
+
+.LoadWhichBreedmonIsTheMother:
+ ld [wBreedMotherOrNonDitto], a
+ and a
+ ld a, [wBreedMon1Species]
+ jr z, .GotMother
+ ld a, [wBreedMon2Species]
+
+.GotMother:
+ ld [CurPartySpecies], a
+ callfar GetPreEvolution
+ callfar GetPreEvolution
+ ld a, EGG_LEVEL
+ ld [CurPartyLevel], a
+
+ ld a, [CurPartySpecies]
+ cp NIDORAN_F
+ jr nz, .GotEggSpecies
+ call Random
+ cp 1 + 50 percent
+ ld a, NIDORAN_F
+ jr c, .GotEggSpecies
+ ld a, NIDORAN_M
+.GotEggSpecies:
+ ld [CurPartySpecies], a
+ ld [CurSpecies], a
+ ld [wEggMonSpecies], a
+
+ call GetBaseData
+ ld hl, wEggNick
+ ld de, .String_EGG
+ call CopyName2
+ ld hl, PlayerName
+ ld de, wEggOT
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ xor a
+ ld [wEggMonItem], a
+ ld de, wEggMonMoves
+ xor a
+ ld [Buffer1], a
+ predef FillMoves
+ farcall InitEggMoves
+ ld hl, wEggMonID
+ ld a, [PlayerID]
+ ld [hli], a
+ ld a, [PlayerID + 1]
+ ld [hl], a
+ ld a, [CurPartyLevel]
+ ld d, a
+ callfar CalcExpAtLevel
+ ld hl, wEggMonExp
+ ld a, [hMultiplicand]
+ ld [hli], a
+ ld a, [hMultiplicand + 1]
+ ld [hli], a
+ ld a, [hMultiplicand + 2]
+ ld [hl], a
+ xor a
+ ld b, wEggMonDVs - wEggMonStatExp
+ ld hl, wEggMonStatExp
+.loop2
+ ld [hli], a
+ dec b
+ jr nz, .loop2
+ ld hl, wEggMonDVs
+ call Random
+ ld [hli], a
+ ld [TempMonDVs], a
+ call Random
+ ld [hld], a
+ ld [TempMonDVs + 1], a
+ ld de, wBreedMon1DVs
+ ld a, [wBreedMon1Species]
+ cp DITTO
+ jr z, .GotDVs
+ ld de, wBreedMon2DVs
+ ld a, [wBreedMon2Species]
+ cp DITTO
+ jr z, .GotDVs
+ ld a, TEMPMON
+ ld [MonType], a
+ push hl
+ farcall GetGender
+ pop hl
+ ld de, wBreedMon1DVs
+ ld bc, wBreedMon2DVs
+ jr c, .SkipDVs
+ jr z, .ParentCheck2
+ ld a, [wBreedMotherOrNonDitto]
+ and a
+ jr z, .GotDVs
+ ld d, b
+ ld e, c
+ jr .GotDVs
+
+.ParentCheck2:
+ ld a, [wBreedMotherOrNonDitto]
+ and a
+ jr nz, .GotDVs
+ ld d, b
+ ld e, c
+
+.GotDVs:
+ ld a, [de]
+ inc de
+ and $f
+ ld b, a
+ ld a, [hl]
+ and $f0
+ add b
+ ld [hli], a
+ ld a, [de]
+ and $7
+ ld b, a
+ ld a, [hl]
+ and $f8
+ add b
+ ld [hl], a
+
+.SkipDVs:
+ ld hl, StringBuffer1
+ ld de, wMonOrItemNameBuffer
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ld hl, wEggMonMoves
+ ld de, wEggMonPP
+ predef FillPP
+ ld hl, wMonOrItemNameBuffer
+ ld de, StringBuffer1
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ld a, [BaseEggSteps]
+ ld hl, wEggMonHappiness
+ ld [hli], a
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ ld a, [CurPartyLevel]
+ ld [wEggMonLevel], a
+ ret
+; 16be0
+
+.String_EGG: ; 16be0
+ db "EGG@"
+; 16be4
diff --git a/engine/events/dratini.asm b/engine/events/dratini.asm
new file mode 100644
index 000000000..f110b34ab
--- /dev/null
+++ b/engine/events/dratini.asm
@@ -0,0 +1,112 @@
+SpecialDratini: ; 0x8b170
+; if ScriptVar is 0 or 1, change the moveset of the last Dratini in the party.
+; 0: give it a special moveset with Extremespeed.
+; 1: give it the normal moveset of a level 15 Dratini.
+
+ ld a, [ScriptVar]
+ cp $2
+ ret nc
+ ld bc, PartyCount
+ ld a, [bc]
+ ld hl, MON_SPECIES
+ call .GetNthPartyMon
+ ld a, [bc]
+ ld c, a
+ ld de, PARTYMON_STRUCT_LENGTH
+.CheckForDratini:
+; start at the end of the party and search backwards for a Dratini
+ ld a, [hl]
+ cp DRATINI
+ jr z, .GiveMoveset
+ ld a, l
+ sub e
+ ld l, a
+ ld a, h
+ sbc d
+ ld h, a
+ dec c
+ jr nz, .CheckForDratini
+ ret
+
+.GiveMoveset:
+ push hl
+ ld a, [ScriptVar]
+ ld hl, .Movesets
+ ld bc, .Moveset1 - .Moveset0
+ call AddNTimes
+
+ ; get address of mon's first move
+ pop de
+ inc de
+ inc de
+
+.GiveMoves:
+ ld a, [hl]
+ and a ; is the move 00?
+ ret z ; if so, we're done here
+
+ push hl
+ push de
+ ld [de], a ; give the Pokémon the new move
+
+ ; get the PP of the new move
+ dec a
+ ld hl, Moves + MOVE_PP
+ ld bc, MOVE_LENGTH
+ call AddNTimes
+ ld a, BANK(Moves)
+ call GetFarByte
+
+ ; get the address of the move's PP and update the PP
+ ld hl, MON_PP - MON_MOVES
+ add hl, de
+ ld [hl], a
+
+ pop de
+ pop hl
+ inc de
+ inc hl
+ jr .GiveMoves
+
+.Movesets:
+.Moveset0:
+; Dratini does not normally learn Extremespeed. This is a special gift.
+ db WRAP
+ db THUNDER_WAVE
+ db TWISTER
+ db EXTREMESPEED
+ db 0
+.Moveset1:
+; This is the normal moveset of a level 15 Dratini
+ db WRAP
+ db LEER
+ db THUNDER_WAVE
+ db TWISTER
+ db 0
+
+.GetNthPartyMon: ; 0x8b1ce
+; inputs:
+; hl must be set to 0 before calling this function.
+; a must be set to the number of Pokémon in the party.
+
+; outputs:
+; returns the address of the last Pokémon in the party in hl.
+; sets carry if a is 0.
+
+ ld de, PartyMon1
+ add hl, de
+ and a
+ jr z, .EmptyParty
+ dec a
+ ret z
+ ld de, PARTYMON_STRUCT_LENGTH
+.loop
+ add hl, de
+ dec a
+ jr nz, .loop
+ ret
+
+.EmptyParty:
+ scf
+ ret
+; 8b1e1
diff --git a/engine/events/elevator.asm b/engine/events/elevator.asm
new file mode 100755
index 000000000..9170b642d
--- /dev/null
+++ b/engine/events/elevator.asm
@@ -0,0 +1,283 @@
+Elevator:: ; 1342d
+ call .LoadPointer
+ call .FindCurrentFloor
+ jr c, .quit
+ ld [wElevatorOriginFloor], a
+ call Elevator_AskWhichFloor
+ jr c, .quit
+ ld hl, wElevatorOriginFloor
+ cp [hl]
+ jr z, .quit
+ call Elevator_GoToFloor
+ and a
+ ret
+
+.quit
+ scf
+ ret
+; 1344a
+
+.LoadPointer: ; 1344a
+ ld a, b
+ ld [wElevatorPointerBank], a
+ ld a, e
+ ld [wElevatorPointer], a
+ ld a, d
+ ld [wElevatorPointer + 1], a
+ call .LoadFloors
+ ret
+; 1345a
+
+.LoadFloors: ; 1345a
+ ld de, CurElevator
+ ld bc, 4
+ ld hl, wElevatorPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wElevatorPointerBank]
+ call GetFarByte
+ inc hl
+ ld [de], a
+ inc de
+.loop
+ ld a, [wElevatorPointerBank]
+ call GetFarByte
+ ld [de], a
+ inc de
+ add hl, bc
+ cp -1
+ jr nz, .loop
+ ret
+; 1347d
+
+.FindCurrentFloor: ; 1347d
+ ld hl, wElevatorPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wElevatorPointerBank]
+ call GetFarByte
+ ld c, a
+ inc hl
+ ld a, [BackupMapGroup]
+ ld d, a
+ ld a, [BackupMapNumber]
+ ld e, a
+ ld b, 0
+.loop2
+ ld a, [wElevatorPointerBank]
+ call GetFarByte
+ cp -1
+ jr z, .fail
+ inc hl
+ inc hl
+ ld a, [wElevatorPointerBank]
+ call GetFarByte
+ inc hl
+ cp d
+ jr nz, .next1
+ ld a, [wElevatorPointerBank]
+ call GetFarByte
+ inc hl
+ cp e
+ jr nz, .next2
+ jr .done
+
+.next1
+ inc hl
+.next2
+ inc b
+ jr .loop2
+
+.done
+ xor a
+ ld a, b
+ ret
+
+.fail
+ scf
+ ret
+; 134c0
+
+Elevator_GoToFloor: ; 134c0
+ push af
+ ld hl, wElevatorPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ inc hl
+ pop af
+ ld bc, 4
+ call AddNTimes
+ inc hl
+ ld de, BackupWarpNumber
+ ld a, [wElevatorPointerBank]
+ ld bc, 3
+ call FarCopyBytes
+ ret
+; 134dd
+
+Elevator_AskWhichFloor: ; 134dd
+ call LoadStandardMenuDataHeader
+ ld hl, Elevator_WhichFloorText
+ call PrintText
+ call Elevator_GetCurrentFloorText
+ ld hl, Elevator_MenuDataHeader
+ call CopyMenuDataHeader
+ call InitScrollingMenu
+ call UpdateSprites
+ xor a
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ call CloseWindow
+ ld a, [wMenuJoypad]
+ cp B_BUTTON
+ jr z, .cancel
+ xor a
+ ld a, [wScrollingMenuCursorPosition]
+ ret
+
+.cancel
+ scf
+ ret
+; 1350d
+
+Elevator_WhichFloorText: ; 0x1350d
+ ; Which floor?
+ text_jump UnknownText_0x1bd2bc
+ db "@"
+; 0x13512
+
+
+Elevator_GetCurrentFloorText: ; 13512
+ ld hl, Options
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ hlcoord 0, 0
+ ld b, 4
+ ld c, 8
+ call TextBox
+ hlcoord 1, 2
+ ld de, Elevator_CurrentFloorText
+ call PlaceString
+ hlcoord 4, 4
+ call Elevator_GetCurrentFloorString
+ pop af
+ ld [Options], a
+ ret
+; 13537
+
+Elevator_CurrentFloorText: ; 13537
+ db "Now on:@"
+; 1353f
+
+
+Elevator_GetCurrentFloorString: ; 1353f
+ push hl
+ ld a, [wElevatorOriginFloor]
+ ld e, a
+ ld d, 0
+ ld hl, CurElevatorFloors
+ add hl, de
+ ld a, [hl]
+ pop de
+ call GetFloorString
+ ret
+; 13550
+
+Elevator_MenuDataHeader: ; 0x13550
+ db $40 ; flags
+ db 01, 12 ; start coords
+ db 09, 18 ; end coords
+ dw Elevator_MenuData2
+ db 1 ; default option
+; 0x13558
+
+Elevator_MenuData2: ; 0x13558
+ db $10 ; flags
+ db 4, 0 ; rows, columns
+ db 1 ; horizontal spacing
+ dbw 0, CurElevator
+ dba GetElevatorFlorStrings
+ dba NULL
+ dba NULL
+; 13568
+
+GetElevatorFlorStrings: ; 13568
+ ld a, [MenuSelection]
+GetFloorString: ; 1356b
+ push de
+ call FloorToString
+ ld d, h
+ ld e, l
+ pop hl
+ jp PlaceString
+; 13575
+
+FloorToString: ; 13575
+ push de
+ ld e, a
+ ld d, 0
+ ld hl, .floors
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ pop de
+ ret
+; 13583
+
+.floors
+ dw .b4f
+ dw .b3f
+ dw .b2f
+ dw .b1f
+ dw ._1f
+ dw ._2f
+ dw ._3f
+ dw ._4f
+ dw ._5f
+ dw ._6f
+ dw ._7f
+ dw ._8f
+ dw ._9f
+ dw ._10f
+ dw ._11f
+ dw .roof
+
+.b4f
+ db "B4F@"
+.b3f
+ db "B3F@"
+.b2f
+ db "B2F@"
+.b1f
+ db "B1F@"
+._1f
+ db "1F@"
+._2f
+ db "2F@"
+._3f
+ db "3F@"
+._4f
+ db "4F@"
+._5f
+ db "5F@"
+._6f
+ db "6F@"
+._7f
+ db "7F@"
+._8f
+ db "8F@"
+._9f
+ db "9F@"
+._10f
+ db "10F@"
+._11f
+ db "11F@"
+.roof
+ db "ROOF@"
+; 135db
diff --git a/engine/events/field_moves.asm b/engine/events/field_moves.asm
new file mode 100755
index 000000000..1c21f4995
--- /dev/null
+++ b/engine/events/field_moves.asm
@@ -0,0 +1,469 @@
+PlayWhirlpoolSound: ; 8c7d4
+ call WaitSFX
+ ld de, SFX_SURF
+ call PlaySFX
+ call WaitSFX
+ ret
+; 8c7e1
+
+BlindingFlash: ; 8c7e1
+ farcall FadeOutPalettes
+ ld hl, StatusFlags
+ set 2, [hl] ; Flash
+ farcall ReplaceTimeOfDayPals
+ farcall UpdateTimeOfDayPal
+ ld b, SCGB_MAPPALS
+ call GetSGBLayout
+ farcall LoadOW_BGPal7
+ farcall FadeInPalettes
+ ret
+; 8c80a
+
+ShakeHeadbuttTree: ; 8c80a
+ farcall ClearSpriteAnims
+ ld de, CutGrassGFX
+ ld hl, VTiles1
+ lb bc, BANK(CutGrassGFX), 4
+ call Request2bpp
+ ld de, HeadbuttTreeGFX
+ ld hl, VTiles1 tile $04
+ lb bc, BANK(HeadbuttTreeGFX), 8
+ call Request2bpp
+ call Cut_Headbutt_GetPixelFacing
+ ld a, SPRITE_ANIM_INDEX_HEADBUTT
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $84
+ ld a, 36 * 4
+ ld [wCurrSpriteOAMAddr], a
+ farcall DoNextFrameForAllSprites
+ call HideHeadbuttTree
+ ld a, $20
+ ld [wcf64], a
+ call WaitSFX
+ ld de, SFX_SANDSTORM
+ call PlaySFX
+.loop
+ ld hl, wcf64
+ ld a, [hl]
+ and a
+ jr z, .done
+ dec [hl]
+ ld a, 36 * 4
+ ld [wCurrSpriteOAMAddr], a
+ farcall DoNextFrameForAllSprites
+ call DelayFrame
+ jr .loop
+
+.done
+ call OverworldTextModeSwitch
+ call WaitBGMap
+ xor a
+ ld [hBGMapMode], a
+ farcall ClearSpriteAnims
+ ld hl, Sprites + 36 * 4
+ ld bc, SpritesEnd - (Sprites + 36 * 4)
+ xor a
+ call ByteFill
+ ld de, Font
+ ld hl, VTiles1
+ lb bc, BANK(Font), 12
+ call Get1bpp
+ call ReplaceKrisSprite
+ ret
+; 8c893
+
+HeadbuttTreeGFX: ; 8c893
+INCBIN "gfx/overworld/headbutt_tree.2bpp"
+; 8c913
+
+HideHeadbuttTree: ; 8c913
+ xor a
+ ld [hBGMapMode], a
+ ld a, [PlayerDirection]
+ and %00001100
+ srl a
+ ld e, a
+ ld d, 0
+ ld hl, TreeRelativeLocationTable
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+
+ ld a, $5
+ ld [hli], a
+ ld [hld], a
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hli], a
+ ld [hld], a
+ call WaitBGMap
+ xor a
+ ld [hBGMapMode], a
+ ret
+; 8c938
+
+TreeRelativeLocationTable: ; 8c938
+ dwcoord 8, 8 + 2 ; RIGHT
+ dwcoord 8, 8 - 2 ; LEFT
+ dwcoord 8 - 2, 8 ; DOWN
+ dwcoord 8 + 2, 8 ; UP
+; 8c940
+
+OWCutAnimation: ; 8c940
+ ; Animation index in e
+ ; 0: Split tree in half
+ ; 1: Mow the lawn
+ ld a, e
+ and $1
+ ld [wJumptableIndex], a
+ call .LoadCutGFX
+ call WaitSFX
+ ld de, SFX_PLACE_PUZZLE_PIECE_DOWN
+ call PlaySFX
+.loop
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .finish
+ ld a, 36 * 4
+ ld [wCurrSpriteOAMAddr], a
+ callfar DoNextFrameForAllSprites
+ call OWCutJumptable
+ call DelayFrame
+ jr .loop
+
+.finish
+ ret
+; 8c96d
+
+.LoadCutGFX: ; 8c96d
+ callfar ClearSpriteAnims ; pointless to farcall
+ ld de, CutGrassGFX
+ ld hl, VTiles1
+ lb bc, BANK(CutGrassGFX), 4
+ call Request2bpp
+ ld de, CutTreeGFX
+ ld hl, VTiles1 tile $4
+ lb bc, BANK(CutTreeGFX), 4
+ call Request2bpp
+ ret
+; 8c98c
+
+CutTreeGFX: ; c898c
+INCBIN "gfx/overworld/cut_tree.2bpp"
+; c89cc
+
+CutGrassGFX: ; 8c9cc
+INCBIN "gfx/overworld/cut_grass.2bpp"
+; 8ca0c
+
+OWCutJumptable: ; 8ca0c
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, 0
+ ld hl, .dw
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+; 8ca1b
+
+
+.dw ; 8ca1b (23:4a1b)
+ dw Cut_SpawnAnimateTree
+ dw Cut_SpawnAnimateLeaves
+ dw Cut_StartWaiting
+ dw Cut_WaitAnimSFX
+
+
+Cut_SpawnAnimateTree: ; 8ca23 (23:4a23)
+ call Cut_Headbutt_GetPixelFacing
+ ld a, SPRITE_ANIM_INDEX_CUT_TREE ; cut tree
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $84
+ ld a, 32
+ ld [wcf64], a
+; Cut_StartWaiting
+ ld hl, wJumptableIndex
+ inc [hl]
+ inc [hl]
+ ret
+
+Cut_SpawnAnimateLeaves: ; 8ca3c (23:4a3c)
+ call Cut_GetLeafSpawnCoords
+ xor a
+ call Cut_SpawnLeaf
+ ld a, $10
+ call Cut_SpawnLeaf
+ ld a, $20
+ call Cut_SpawnLeaf
+ ld a, $30
+ call Cut_SpawnLeaf
+ ld a, 32 ; frames
+ ld [wcf64], a
+; Cut_StartWaiting
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+Cut_StartWaiting: ; 8ca5c (23:4a5c)
+ ld a, $1
+ ld [hBGMapMode], a
+; Cut_WaitAnimSFX
+ ld hl, wJumptableIndex
+ inc [hl]
+
+Cut_WaitAnimSFX: ; 8ca64 (23:4a64)
+ ld hl, wcf64
+ ld a, [hl]
+ and a
+ jr z, .finished
+ dec [hl]
+ ret
+
+.finished
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+Cut_SpawnLeaf: ; 8ca73 (23:4a73)
+ push de
+ push af
+ ld a, SPRITE_ANIM_INDEX_LEAF ; leaf
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $80
+ ld hl, SPRITEANIMSTRUCT_0E
+ add hl, bc
+ ld [hl], $4
+ pop af
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], a
+ pop de
+ ret
+
+Cut_GetLeafSpawnCoords: ; 8ca8e (23:4a8e)
+ ld de, 0
+ ld a, [wMetatileStandingX]
+ bit 0, a
+ jr z, .left_side
+ set 0, e
+.left_side
+ ld a, [wMetatileStandingY]
+ bit 0, a
+ jr z, .top_side
+ set 1, e
+.top_side
+ ld a, [PlayerDirection]
+ and %00001100
+ add e
+ ld e, a
+ ld hl, .Coords
+ add hl, de
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ret
+; 8cab3 (23:4ab3)
+
+.Coords: ; 8cab3
+ dbpixel 11, 12 ; facing down, top left
+ dbpixel 9, 12 ; facing down, top right
+ dbpixel 11, 14 ; facing down, bottom left
+ dbpixel 9, 14 ; facing down, bottom right
+
+ dbpixel 11, 8 ; facing up, top left
+ dbpixel 9, 8 ; facing up, top right
+ dbpixel 11, 10 ; facing up, bottom left
+ dbpixel 9, 10 ; facing up, bottom right
+
+ dbpixel 7, 12 ; facing left, top left
+ dbpixel 9, 12 ; facing left, top right
+ dbpixel 7, 10 ; facing left, bottom left
+ dbpixel 9, 10 ; facing left, bottom right
+
+ dbpixel 11, 12 ; facing right, top left
+ dbpixel 13, 12 ; facing right, top right
+ dbpixel 11, 10 ; facing right, bottom left
+ dbpixel 13, 10 ; facing right, bottom right
+; 8cad3
+
+Cut_Headbutt_GetPixelFacing: ; 8cad3 (23:4ad3)
+ ld a, [PlayerDirection]
+ and %00001100
+ srl a
+ ld e, a
+ ld d, 0
+ ld hl, .Coords
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ret
+; 8cae5 (23:4ae5)
+
+.Coords: ; 8cae5
+ dbpixel 10, 13
+ dbpixel 10, 9
+ dbpixel 8, 11
+ dbpixel 12, 11
+; 8caed
+
+
+FlyFromAnim: ; 8caed
+ call DelayFrame
+ ld a, [VramState]
+ push af
+ xor a
+ ld [VramState], a
+ call FlyFunction_InitGFX
+ depixel 10, 10, 4, 0
+ ld a, SPRITE_ANIM_INDEX_RED_WALK
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $84
+ ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+ add hl, bc
+ ld [hl], SPRITE_ANIM_SEQ_FLY_FROM
+ ld a, 128
+ ld [wcf64], a
+.loop
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .exit
+ ld a, 0 * 4
+ ld [wCurrSpriteOAMAddr], a
+ callfar DoNextFrameForAllSprites
+ call FlyFunction_FrameTimer
+ call DelayFrame
+ jr .loop
+
+.exit
+ pop af
+ ld [VramState], a
+ ret
+; 8cb33
+
+FlyToAnim: ; 8cb33
+ call DelayFrame
+ ld a, [VramState]
+ push af
+ xor a
+ ld [VramState], a
+ call FlyFunction_InitGFX
+ depixel 31, 10, 4, 0
+ ld a, SPRITE_ANIM_INDEX_RED_WALK
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $84
+ ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+ add hl, bc
+ ld [hl], SPRITE_ANIM_SEQ_FLY_TO
+ ld hl, SPRITEANIMSTRUCT_0F
+ add hl, bc
+ ld [hl], 11 * 8
+ ld a, 64
+ ld [wcf64], a
+.loop
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .exit
+ ld a, 0 * 4
+ ld [wCurrSpriteOAMAddr], a
+ callfar DoNextFrameForAllSprites
+ call FlyFunction_FrameTimer
+ call DelayFrame
+ jr .loop
+
+.exit
+ pop af
+ ld [VramState], a
+ call .RestorePlayerSprite_DespawnLeaves
+ ret
+
+.RestorePlayerSprite_DespawnLeaves: ; 8cb82 (23:4b82)
+ ld hl, Sprites + 2 ; Tile ID
+ xor a
+ ld c, $4
+.loop2
+ ld [hli], a
+ inc hl
+ inc hl
+ inc hl
+ inc a
+ dec c
+ jr nz, .loop2
+ ld hl, Sprites + 4 * 4
+ ld bc, SpritesEnd - (Sprites + 4 * 4)
+ xor a
+ call ByteFill
+ ret
+
+FlyFunction_InitGFX: ; 8cb9b (23:4b9b)
+ callfar ClearSpriteAnims
+ ld de, CutGrassGFX
+ ld hl, VTiles1 tile $00
+ lb bc, BANK(CutGrassGFX), 4
+ call Request2bpp
+ ld a, [CurPartyMon]
+ ld hl, PartySpecies
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld a, [hl]
+ ld [wd265], a
+ ld e, $84
+ farcall FlyFunction_GetMonIcon
+ xor a
+ ld [wJumptableIndex], a
+ ret
+
+FlyFunction_FrameTimer: ; 8cbc8 (23:4bc8)
+ call .SpawnLeaf
+ ld hl, wcf64
+ ld a, [hl]
+ and a
+ jr z, .exit
+ dec [hl]
+ cp $40
+ ret c
+ and $7
+ ret nz
+ ld de, SFX_FLY
+ call PlaySFX
+ ret
+
+.exit
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+.SpawnLeaf: ; 8cbe6 (23:4be6)
+ ld hl, wcf65
+ ld a, [hl]
+ inc [hl]
+ and $7
+ ret nz
+ ld a, [hl]
+ and (6 * 8) >> 1
+ sla a
+ add 8 * 8 ; gives a number in [$40, $50, $60, $70]
+ ld d, a
+ ld e, $0
+ ld a, SPRITE_ANIM_INDEX_FLY_LEAF ; fly land
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $80
+ ret
diff --git a/engine/events/fish.asm b/engine/events/fish.asm
new file mode 100644
index 000000000..c571bba56
--- /dev/null
+++ b/engine/events/fish.asm
@@ -0,0 +1,133 @@
+Fish: ; 92402
+; Using a fishing rod.
+; Fish for monsters with rod e in encounter group d.
+; Return monster e at level d.
+
+ push af
+ push bc
+ push hl
+
+ ld b, e
+ call GetFishGroupIndex
+
+ ld hl, FishGroups
+rept 7
+ add hl, de
+endr
+ call .Fish
+
+ pop hl
+ pop bc
+ pop af
+ ret
+; 9241a
+
+
+.Fish: ; 9241a
+; Fish for monsters with rod b from encounter data in FishGroup at hl.
+; Return monster e at level d.
+
+ call Random
+ cp [hl]
+ jr nc, .no_bite
+
+ ; Get encounter data by rod:
+ ; 0: Old
+ ; 1: Good
+ ; 2: Super
+ inc hl
+ ld e, b
+ ld d, 0
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+
+ ; Compare the encounter chance to select a Pokemon.
+ call Random
+.loop
+ cp [hl]
+ jr z, .ok
+ jr c, .ok
+ inc hl
+ inc hl
+ inc hl
+ jr .loop
+.ok
+ inc hl
+
+ ; Species 0 reads from a time-based encounter table.
+ ld a, [hli]
+ ld d, a
+ and a
+ call z, .TimeEncounter
+
+ ld e, [hl]
+ ret
+
+.no_bite
+ ld de, 0
+ ret
+
+.TimeEncounter:
+ ; The level byte is repurposed as the index for the new table.
+ ld e, [hl]
+ ld d, 0
+ ld hl, TimeFishGroups
+rept 4
+ add hl, de
+endr
+
+ ld a, [TimeOfDay]
+ and 3
+ cp NITE_F
+ jr c, .time_species
+ inc hl
+ inc hl
+
+.time_species
+ ld d, [hl]
+ inc hl
+ ret
+; 9245b
+
+
+GetFishGroupIndex: ; 9245b
+; Return the index of fishgroup d in de.
+
+ push hl
+ ld hl, DailyFlags
+ bit 2, [hl]
+ pop hl
+ jr z, .done
+
+ ld a, d
+ cp FISHGROUP_QWILFISH
+ jr z, .qwilfish
+ cp FISHGROUP_REMORAID
+ jr z, .remoraid
+
+.done
+ dec d
+ ld e, d
+ ld d, 0
+ ret
+
+.qwilfish
+ ld a, [wFishingSwarmFlag]
+ cp FISHSWARM_QWILFISH
+ jr nz, .done
+ ld d, FISHGROUP_QWILFISH_SWARM
+ jr .done
+
+.remoraid
+ ld a, [wFishingSwarmFlag]
+ cp FISHSWARM_REMORAID
+ jr nz, .done
+ ld d, FISHGROUP_REMORAID_SWARM
+ jr .done
+; 92488
+
+
+INCLUDE "data/wild/fish.asm"
diff --git a/engine/events/forced_movement.asm b/engine/events/forced_movement.asm
new file mode 100755
index 000000000..136698501
--- /dev/null
+++ b/engine/events/forced_movement.asm
@@ -0,0 +1,60 @@
+Script_ForcedMovement:: ; 0x1253d
+ checkcode VAR_FACING
+ if_equal DOWN, .down
+ if_equal UP, .up
+ if_equal LEFT, .left
+ if_equal RIGHT, .right
+ end
+; 0x12550
+
+.up ; 0x12550
+ applymovement PLAYER, .MovementData_up
+ end
+; 0x12555
+
+.down ; 0x12555
+ applymovement PLAYER, .MovementData_down
+ end
+; 0x1255a
+
+.right ; 0x1255a
+ applymovement PLAYER, .MovementData_right
+ end
+; 0x1255f
+
+.left ; 0x1255f
+ applymovement PLAYER, .MovementData_left
+ end
+; 0x12564
+
+.MovementData_up: ; 0x12564
+ step_dig 16
+ turn_in DOWN
+ step_dig 16
+ turn_head DOWN
+ step_end
+; 0x1256b
+
+.MovementData_down: ; 0x1256b
+ step_dig 16
+ turn_in UP
+ step_dig 16
+ turn_head UP
+ step_end
+; 0x12572
+
+.MovementData_right: ; 0x12572
+ step_dig 16
+ turn_in LEFT
+ step_dig 16
+ turn_head LEFT
+ step_end
+; 0x12579
+
+.MovementData_left: ; 0x12579
+ step_dig 16
+ turn_in RIGHT
+ step_dig 16
+ turn_head RIGHT
+ step_end
+; 0x12580
diff --git a/engine/events/fruit_trees.asm b/engine/events/fruit_trees.asm
new file mode 100644
index 000000000..595e41824
--- /dev/null
+++ b/engine/events/fruit_trees.asm
@@ -0,0 +1,132 @@
+FruitTreeScript:: ; 44000
+ callasm GetCurTreeFruit
+ opentext
+ copybytetovar CurFruit
+ itemtotext $0, $0
+ writetext FruitBearingTreeText
+ buttonsound
+ callasm TryResetFruitTrees
+ callasm CheckFruitTree
+ iffalse .fruit
+ writetext NothingHereText
+ waitbutton
+ jump .end
+
+.fruit
+ writetext HeyItsFruitText
+ copybytetovar CurFruit
+ giveitem ITEM_FROM_MEM
+ iffalse .packisfull
+ buttonsound
+ writetext ObtainedFruitText
+ callasm PickedFruitTree
+ specialsound
+ itemnotify
+ jump .end
+
+.packisfull
+ buttonsound
+ writetext FruitPackIsFullText
+ waitbutton
+
+.end
+ closetext
+ end
+; 44041
+
+GetCurTreeFruit: ; 44041
+ ld a, [CurFruitTree]
+ dec a
+ call GetFruitTreeItem
+ ld [CurFruit], a
+ ret
+; 4404c
+
+TryResetFruitTrees: ; 4404c
+ ld hl, DailyFlags
+ bit 4, [hl]
+ ret nz
+ jp ResetFruitTrees
+; 44055
+
+CheckFruitTree: ; 44055
+ ld b, 2
+ call GetFruitTreeFlag
+ ld a, c
+ ld [ScriptVar], a
+ ret
+; 4405f
+
+PickedFruitTree: ; 4405f
+ farcall TrainerRankings_FruitPicked
+ ld b, 1
+ jp GetFruitTreeFlag
+; 4406a
+
+ResetFruitTrees: ; 4406a
+ xor a
+ ld hl, FruitTreeFlags
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ ld hl, DailyFlags
+ set 4, [hl]
+ ret
+; 44078
+
+GetFruitTreeFlag: ; 44078
+ push hl
+ push de
+ ld a, [CurFruitTree]
+ dec a
+ ld e, a
+ ld d, 0
+ ld hl, FruitTreeFlags
+ call FlagAction
+ pop de
+ pop hl
+ ret
+; 4408a
+
+GetFruitTreeItem: ; 4408a
+ push hl
+ push de
+ ld e, a
+ ld d, 0
+ ld hl, FruitTreeItems
+ add hl, de
+ ld a, [hl]
+ pop de
+ pop hl
+ ret
+; 44097
+
+
+INCLUDE "data/items/fruit_trees.asm"
+
+
+FruitBearingTreeText: ; 440b5
+ text_jump _FruitBearingTreeText
+ db "@"
+; 440ba
+
+HeyItsFruitText: ; 440ba
+ text_jump _HeyItsFruitText
+ db "@"
+; 440bf
+
+ObtainedFruitText: ; 440bf
+ text_jump _ObtainedFruitText
+ db "@"
+; 440c4
+
+FruitPackIsFullText: ; 440c4
+ text_jump _FruitPackIsFullText
+ db "@"
+; 440c9
+
+NothingHereText: ; 440c9
+ text_jump _NothingHereText
+ db "@"
+; 440ce
diff --git a/engine/events/halloffame.asm b/engine/events/halloffame.asm
new file mode 100755
index 000000000..5fa1dc270
--- /dev/null
+++ b/engine/events/halloffame.asm
@@ -0,0 +1,622 @@
+HALLOFFAME_COLON EQU $63
+
+HallOfFame:: ; 0x8640e
+ call HallOfFame_FadeOutMusic
+ ld a, [StatusFlags]
+ push af
+ ld a, 1
+ ld [wGameLogicPaused], a
+ call DisableSpriteUpdates
+ ld a, SPAWN_LANCE
+ ld [wSpawnAfterChampion], a
+
+ ; Enable the Pokégear map to cycle through all of Kanto
+ ld hl, StatusFlags
+ set 6, [hl] ; hall of fame
+
+ farcall HallOfFame_InitSaveIfNeeded
+
+ ld hl, wHallOfFameCount
+ ld a, [hl]
+ cp 200
+ jr nc, .ok
+ inc [hl]
+.ok
+ farcall SaveGameData
+ call GetHallOfFameParty
+ farcall AddHallOfFameEntry
+
+ xor a
+ ld [wGameLogicPaused], a
+ call AnimateHallOfFame
+ pop af
+ ld b, a
+ farcall Credits
+ ret
+; 0x86455
+
+RedCredits:: ; 86455
+ ld a, LOW(MUSIC_NONE)
+ ld [MusicFadeID], a
+ ld a, HIGH(MUSIC_NONE)
+ ld [MusicFadeID + 1], a
+ ld a, 10
+ ld [MusicFade], a
+ farcall FadeOutPalettes
+ xor a
+ ld [VramState], a
+ ld [hMapAnims], a
+ farcall InitDisplayForRedCredits
+ ld c, 8
+ call DelayFrames
+ call DisableSpriteUpdates
+ ld a, SPAWN_RED
+ ld [wSpawnAfterChampion], a
+ ld a, [StatusFlags]
+ ld b, a
+ farcall Credits
+ ret
+; 8648e
+
+HallOfFame_FadeOutMusic: ; 8648e
+ ld a, LOW(MUSIC_NONE)
+ ld [MusicFadeID], a
+ ld a, HIGH(MUSIC_NONE)
+ ld [MusicFadeID + 1], a
+ ld a, 10
+ ld [MusicFade], a
+ farcall FadeOutPalettes
+ xor a
+ ld [VramState], a
+ ld [hMapAnims], a
+ farcall InitDisplayForHallOfFame
+ ld c, 100
+ jp DelayFrames
+; 864b4
+
+HallOfFame_PlayMusicDE: ; 864b4
+ push de
+ ld de, MUSIC_NONE
+ call PlayMusic
+ call DelayFrame
+ pop de
+ call PlayMusic
+ ret
+; 864c3
+
+AnimateHallOfFame: ; 864c3
+ xor a
+ ld [wJumptableIndex], a
+ call LoadHOFTeam
+ jr c, .done
+ ld de, MUSIC_HALL_OF_FAME
+ call HallOfFame_PlayMusicDE
+ xor a
+ ld [wcf64], a
+.loop
+ ld a, [wcf64]
+ cp PARTY_LENGTH
+ jr nc, .done
+ ld hl, wHallOfFameTempMon1
+ ld bc, wHallOfFameTempMon1End - wHallOfFameTempMon1
+ call AddNTimes
+ ld a, [hl]
+ cp -1
+ jr z, .done
+ push hl
+ call AnimateHOFMonEntrance
+ pop hl
+ call .DisplayNewHallOfFamer
+ jr c, .done
+ ld hl, wcf64
+ inc [hl]
+ jr .loop
+
+.done
+ call HOF_AnimatePlayerPic
+ ld a, $4
+ ld [MusicFade], a
+ call RotateThreePalettesRight
+ ld c, 8
+ call DelayFrames
+ ret
+; 8650c
+
+.DisplayNewHallOfFamer: ; 8650c
+ call DisplayHOFMon
+ ld de, .String_NewHallOfFamer
+ hlcoord 1, 2
+ call PlaceString
+ call WaitBGMap
+ decoord 6, 5
+ ld c, $6
+ predef HOF_AnimateFrontpic
+ ld c, 60
+ call DelayFrames
+ and a
+ ret
+; 8652c
+
+.String_NewHallOfFamer:
+ db "New Hall of Famer!@"
+; 8653f
+
+
+GetHallOfFameParty: ; 8653f
+ ld hl, OverworldMap
+ ld bc, HOF_LENGTH
+ xor a
+ call ByteFill
+ ld a, [wHallOfFameCount]
+ ld de, OverworldMap
+ ld [de], a
+ inc de
+ ld hl, PartySpecies
+ ld c, 0
+.next
+ ld a, [hli]
+ cp -1
+ jr z, .done
+ cp EGG
+ jr nz, .mon
+ inc c
+ jr .next
+
+.mon
+ push hl
+ push de
+ push bc
+
+ ld a, c
+ ld hl, PartyMons
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ ld c, l
+ ld b, h
+
+ ld hl, MON_SPECIES
+ add hl, bc
+ ld a, [hl]
+ ld [de], a
+ inc de
+
+ ld hl, MON_ID
+ add hl, bc
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ inc de
+
+ ld hl, MON_DVS
+ add hl, bc
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ inc de
+
+ ld hl, MON_LEVEL
+ add hl, bc
+ ld a, [hl]
+ ld [de], a
+ inc de
+
+ pop bc
+ push bc
+ ld a, c
+ ld hl, PartyMonNicknames
+ ld bc, PKMN_NAME_LENGTH
+ call AddNTimes
+ ld bc, PKMN_NAME_LENGTH - 1
+ call CopyBytes
+
+ pop bc
+ inc c
+ pop de
+ ld hl, HOF_MON_LENGTH
+ add hl, de
+ ld e, l
+ ld d, h
+ pop hl
+ jr .next
+
+.done
+ ld a, $ff
+ ld [de], a
+ ret
+; 865b5
+
+AnimateHOFMonEntrance: ; 865b5
+ push hl
+ call ClearBGPalettes
+ farcall ResetDisplayBetweenHallOfFameMons
+ pop hl
+ ld a, [hli]
+ ld [TempMonSpecies], a
+ ld [CurPartySpecies], a
+ inc hl
+ inc hl
+ ld a, [hli]
+ ld [TempMonDVs], a
+ ld a, [hli]
+ ld [TempMonDVs + 1], a
+ ld hl, TempMonDVs
+ predef GetUnownLetter
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ ld de, VTiles2 tile $31
+ predef GetMonBackpic
+ ld a, $31
+ ld [hGraphicStartTile], a
+ hlcoord 6, 6
+ lb bc, 6, 6
+ predef PlaceGraphic
+ ld a, $d0
+ ld [hSCY], a
+ ld a, $90
+ ld [hSCX], a
+ call WaitBGMap
+ xor a
+ ld [hBGMapMode], a
+ ld b, SCGB_PLAYER_OR_MON_FRONTPIC_PALS
+ call GetSGBLayout
+ call SetPalettes
+ call HOF_SlideBackpic
+ xor a
+ ld [wBoxAlignment], a
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ hlcoord 6, 5
+ call _PrepMonFrontpic
+ call WaitBGMap
+ xor a
+ ld [hBGMapMode], a
+ ld [hSCY], a
+ call HOF_SlideFrontpic
+ ret
+; 86635
+
+HOF_SlideBackpic:
+.backpicloop
+ ld a, [hSCX]
+ cp $70
+ ret z
+ add $4
+ ld [hSCX], a
+ call DelayFrame
+ jr .backpicloop
+; 86643
+
+HOF_SlideFrontpic:
+.frontpicloop
+ ld a, [hSCX]
+ and a
+ ret z
+ dec a
+ dec a
+ ld [hSCX], a
+ call DelayFrame
+ jr .frontpicloop
+; 86650
+
+_HallOfFamePC: ; 86650
+ call LoadFontsBattleExtra
+ xor a
+ ld [wJumptableIndex], a
+.MasterLoop:
+ call LoadHOFTeam
+ ret c
+ call .DisplayTeam
+ ret c
+ ld hl, wJumptableIndex
+ inc [hl]
+ jr .MasterLoop
+
+.DisplayTeam:
+ xor a
+ ld [wcf64], a
+.next
+ call .DisplayMonAndStrings
+ jr c, .start_button
+.loop
+ call JoyTextDelay
+ ld hl, hJoyLast
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b_button
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a_button
+ ld a, [hl]
+ and START
+ jr nz, .start_button
+ call DelayFrame
+ jr .loop
+
+.a_button
+ ld hl, wcf64
+ inc [hl]
+ jr .next
+
+.b_button
+ scf
+ ret
+
+.start_button
+ and a
+ ret
+
+.DisplayMonAndStrings:
+; Print the number of times the player has entered the Hall of Fame.
+; If that number is above 200, print "HOF Master!" instead.
+ ld a, [wcf64]
+ cp PARTY_LENGTH
+ jr nc, .fail
+ ld hl, wHallOfFameTempMon1
+ ld bc, wHallOfFameTempMon1End - wHallOfFameTempMon1
+ call AddNTimes
+ ld a, [hl]
+ cp -1
+ jr nz, .okay
+
+.fail
+ scf
+ ret
+
+.okay
+ push hl
+ call ClearBGPalettes
+ pop hl
+ call DisplayHOFMon
+ ld a, [wHallOfFameTempWinCount]
+ cp 200 + 1
+ jr c, .print_num_hof
+ ld de, .HOFMaster
+ hlcoord 1, 2
+ call PlaceString
+ hlcoord 13, 2
+ jr .finish
+
+.print_num_hof
+ ld de, .TimeFamer
+ hlcoord 1, 2
+ call PlaceString
+ hlcoord 2, 2
+ ld de, wHallOfFameTempWinCount
+ lb bc, 1, 3
+ call PrintNum
+ hlcoord 11, 2
+
+.finish
+ ld de, .EmptyString
+ call PlaceString
+ call WaitBGMap
+ ld b, SCGB_PLAYER_OR_MON_FRONTPIC_PALS
+ call GetSGBLayout
+ call SetPalettes
+ decoord 6, 5
+ ld c, $6
+ predef HOF_AnimateFrontpic
+ and a
+ ret
+
+.EmptyString:
+ db "@"
+
+.HOFMaster:
+ db " HOF Master!@"
+
+.TimeFamer:
+ db " -Time Famer@"
+; 8671c
+
+LoadHOFTeam: ; 8671c
+ ld a, [wJumptableIndex]
+ cp NUM_HOF_TEAMS
+ jr nc, .invalid
+ ld hl, sHallOfFame
+ ld bc, HOF_LENGTH
+ call AddNTimes
+ ld a, BANK(sHallOfFame)
+ call GetSRAMBank
+ ld a, [hl]
+ and a
+ jr z, .absent
+ ld de, wHallOfFameTemp
+ ld bc, HOF_LENGTH
+ call CopyBytes
+ call CloseSRAM
+ and a
+ ret
+
+.absent
+ call CloseSRAM
+
+.invalid
+ scf
+ ret
+; 86748
+
+DisplayHOFMon: ; 86748
+ xor a
+ ld [hBGMapMode], a
+ ld a, [hli]
+ ld [TempMonSpecies], a
+ ld a, [hli]
+ ld [TempMonID], a
+ ld a, [hli]
+ ld [TempMonID + 1], a
+ ld a, [hli]
+ ld [TempMonDVs], a
+ ld a, [hli]
+ ld [TempMonDVs + 1], a
+ ld a, [hli]
+ ld [TempMonLevel], a
+ ld de, StringBuffer2
+ ld bc, PKMN_NAME_LENGTH - 1
+ call CopyBytes
+ ld a, "@"
+ ld [StringBuffer2 + 10], a
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ hlcoord 0, 0
+ lb bc, 3, SCREEN_WIDTH - 2
+ call TextBox
+ hlcoord 0, 12
+ lb bc, 4, SCREEN_WIDTH - 2
+ call TextBox
+ ld a, [TempMonSpecies]
+ ld [CurPartySpecies], a
+ ld [wd265], a
+ ld hl, TempMonDVs
+ predef GetUnownLetter
+ xor a
+ ld [wBoxAlignment], a
+ hlcoord 6, 5
+ call _PrepMonFrontpic
+ ld a, [CurPartySpecies]
+ cp EGG
+ jr z, .print_id_no
+ hlcoord 1, 13
+ ld a, "№"
+ ld [hli], a
+ ld [hl], "<DOT>"
+ hlcoord 3, 13
+ ld de, wd265
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 3
+ call PrintNum
+ call GetBasePokemonName
+ hlcoord 7, 13
+ call PlaceString
+ ld a, TEMPMON
+ ld [MonType], a
+ farcall GetGender
+ ld a, " "
+ jr c, .got_gender
+ ld a, "♂"
+ jr nz, .got_gender
+ ld a, "♀"
+
+.got_gender
+ hlcoord 18, 13
+ ld [hli], a
+ hlcoord 8, 14
+ ld a, "/"
+ ld [hli], a
+ ld de, StringBuffer2
+ call PlaceString
+ hlcoord 1, 16
+ call PrintLevel
+
+.print_id_no
+ hlcoord 7, 16
+ ld a, "<ID>"
+ ld [hli], a
+ ld a, "№"
+ ld [hli], a
+ ld [hl], "/"
+ hlcoord 10, 16
+ ld de, TempMonID
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+ call PrintNum
+ ret
+; 86810
+
+HOF_AnimatePlayerPic: ; 86810
+ call ClearBGPalettes
+ ld hl, VTiles2 tile HALLOFFAME_COLON
+ ld de, FontExtra + 13 tiles ; "<COLON>"
+ lb bc, BANK(FontExtra), 1
+ call Request2bpp
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ farcall GetPlayerBackpic
+ ld a, $31
+ ld [hGraphicStartTile], a
+ hlcoord 6, 6
+ lb bc, 6, 6
+ predef PlaceGraphic
+ ld a, $d0
+ ld [hSCY], a
+ ld a, $90
+ ld [hSCX], a
+ call WaitBGMap
+ xor a
+ ld [hBGMapMode], a
+ ld [CurPartySpecies], a
+ ld b, SCGB_PLAYER_OR_MON_FRONTPIC_PALS
+ call GetSGBLayout
+ call SetPalettes
+ call HOF_SlideBackpic
+ xor a
+ ld [wBoxAlignment], a
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ farcall HOF_LoadTrainerFrontpic
+ xor a
+ ld [hGraphicStartTile], a
+ hlcoord 12, 5
+ lb bc, 7, 7
+ predef PlaceGraphic
+ ld a, $c0
+ ld [hSCX], a
+ call WaitBGMap
+ xor a
+ ld [hBGMapMode], a
+ ld [hSCY], a
+ call HOF_SlideFrontpic
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 0, 2
+ lb bc, 8, 9
+ call TextBox
+ hlcoord 0, 12
+ lb bc, 4, 18
+ call TextBox
+ hlcoord 2, 4
+ ld de, PlayerName
+ call PlaceString
+ hlcoord 1, 6
+ ld a, "<ID>"
+ ld [hli], a
+ ld a, "№"
+ ld [hli], a
+ ld [hl], "/"
+ hlcoord 4, 6
+ ld de, PlayerID
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+ call PrintNum
+ hlcoord 1, 8
+ ld de, .PlayTime
+ call PlaceString
+ hlcoord 3, 9
+ ld de, GameTimeHours
+ lb bc, 2, 3
+ call PrintNum
+ ld [hl], HALLOFFAME_COLON
+ inc hl
+ ld de, GameTimeMinutes
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ call PrintNum
+ call WaitBGMap
+ farcall ProfOaksPCRating
+ ret
+; 868ed
+
+.PlayTime:
+ db "PLAY TIME@"
+; 868f7
+
diff --git a/engine/events/happiness_egg.asm b/engine/events/happiness_egg.asm
new file mode 100755
index 000000000..a4ae8b7e6
--- /dev/null
+++ b/engine/events/happiness_egg.asm
@@ -0,0 +1,223 @@
+GetFirstPokemonHappiness: ; 718d
+ ld hl, PartyMon1Happiness
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld de, PartySpecies
+.loop
+ ld a, [de]
+ cp EGG
+ jr nz, .done
+ inc de
+ add hl, bc
+ jr .loop
+
+.done
+ ld [wd265], a
+ ld a, [hl]
+ ld [ScriptVar], a
+ call GetPokemonName
+ jp CopyPokemonName_Buffer1_Buffer3
+
+CheckFirstMonIsEgg: ; 71ac
+ ld a, [PartySpecies]
+ ld [wd265], a
+ cp EGG
+ ld a, $1
+ jr z, .egg
+ xor a
+
+.egg
+ ld [ScriptVar], a
+ call GetPokemonName
+ jp CopyPokemonName_Buffer1_Buffer3
+
+ChangeHappiness: ; 71c2
+; Perform happiness action c on CurPartyMon
+
+ ld a, [CurPartyMon]
+ inc a
+ ld e, a
+ ld d, 0
+ ld hl, PartySpecies - 1
+ add hl, de
+ ld a, [hl]
+ cp EGG
+ ret z
+
+ push bc
+ ld hl, PartyMon1Happiness
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, [CurPartyMon]
+ call AddNTimes
+ pop bc
+
+ ld d, h
+ ld e, l
+
+ push de
+ ld a, [de]
+ cp HAPPINESS_THRESHOLD_1
+ ld e, 0
+ jr c, .ok
+ inc e
+ cp HAPPINESS_THRESHOLD_2
+ jr c, .ok
+ inc e
+
+.ok
+ dec c
+ ld b, 0
+ ld hl, HappinessChanges
+ add hl, bc
+ add hl, bc
+ add hl, bc
+ ld d, 0
+ add hl, de
+ ld a, [hl]
+ cp $64 ; why not $80?
+ pop de
+
+ ld a, [de]
+ jr nc, .negative
+ add [hl]
+ jr nc, .done
+ ld a, -1
+ jr .done
+
+.negative
+ add [hl]
+ jr c, .done
+ xor a
+
+.done
+ ld [de], a
+ ld a, [wBattleMode]
+ and a
+ ret z
+ ld a, [CurPartyMon]
+ ld b, a
+ ld a, [wPartyMenuCursor]
+ cp b
+ ret nz
+ ld a, [de]
+ ld [BattleMonHappiness], a
+ ret
+
+
+INCLUDE "data/happiness_changes.asm"
+
+
+StepHappiness:: ; 725a
+; Raise the party's happiness by 1 point every other step cycle.
+
+ ld hl, wHappinessStepCount
+ ld a, [hl]
+ inc a
+ and 1
+ ld [hl], a
+ ret nz
+
+ ld de, PartyCount
+ ld a, [de]
+ and a
+ ret z
+
+ ld c, a
+ ld hl, PartyMon1Happiness
+.loop
+ inc de
+ ld a, [de]
+ cp EGG
+ jr z, .next
+ inc [hl]
+ jr nz, .next
+ ld [hl], $ff
+
+.next
+ push de
+ ld de, PARTYMON_STRUCT_LENGTH
+ add hl, de
+ pop de
+ dec c
+ jr nz, .loop
+ ret
+
+
+DayCareStep:: ; 7282
+; Raise the experience of Day-Care Pokémon every step cycle.
+
+ ld a, [wDayCareMan]
+ bit 0, a
+ jr z, .day_care_lady
+
+ ld a, [wBreedMon1Level] ; level
+ cp MAX_LEVEL
+ jr nc, .day_care_lady
+ ld hl, wBreedMon1Exp + 2 ; exp
+ inc [hl]
+ jr nz, .day_care_lady
+ dec hl
+ inc [hl]
+ jr nz, .day_care_lady
+ dec hl
+ inc [hl]
+ ld a, [hl]
+ cp HIGH(MAX_DAY_CARE_EXP >> 8)
+ jr c, .day_care_lady
+ ld a, HIGH(MAX_DAY_CARE_EXP >> 8)
+ ld [hl], a
+
+.day_care_lady
+ ld a, [wDayCareLady]
+ bit 0, a
+ jr z, .check_egg
+
+ ld a, [wBreedMon2Level] ; level
+ cp MAX_LEVEL
+ jr nc, .check_egg
+ ld hl, wBreedMon2Exp + 2 ; exp
+ inc [hl]
+ jr nz, .check_egg
+ dec hl
+ inc [hl]
+ jr nz, .check_egg
+ dec hl
+ inc [hl]
+ ld a, [hl]
+ cp HIGH(MAX_DAY_CARE_EXP >> 8)
+ jr c, .check_egg
+ ld a, HIGH(MAX_DAY_CARE_EXP >> 8)
+ ld [hl], a
+
+.check_egg
+ ld hl, wDayCareMan
+ bit 5, [hl] ; egg
+ ret z
+ ld hl, wStepsToEgg
+ dec [hl]
+ ret nz
+
+ call Random
+ ld [hl], a
+ callfar CheckBreedmonCompatibility
+ ld a, [wd265]
+ cp 230
+ ld b, 32 percent - 1
+ jr nc, .okay
+ ld a, [wd265]
+ cp 170
+ ld b, 16 percent
+ jr nc, .okay
+ ld a, [wd265]
+ cp 110
+ ld b, 12 percent
+ jr nc, .okay
+ ld b, 4 percent
+
+.okay
+ call Random
+ cp b
+ ret nc
+ ld hl, wDayCareMan
+ res 5, [hl]
+ set 6, [hl]
+ ret
diff --git a/engine/events/heal_machine_anim.asm b/engine/events/heal_machine_anim.asm
new file mode 100755
index 000000000..c7789a28d
--- /dev/null
+++ b/engine/events/heal_machine_anim.asm
@@ -0,0 +1,265 @@
+HealMachineAnim: ; 12324
+ ; If you have no Pokemon, don't change the buffer. This can lead to some glitchy effects if you have no Pokemon.
+ ld a, [PartyCount]
+ and a
+ ret z
+ ; The location of the healing machine relative to the player is stored in ScriptVar.
+ ; 0: Up and left (Pokemon Center)
+ ; 1: Left (Elm's Lab)
+ ; 2: Up (Hall of Fame)
+ ld a, [ScriptVar]
+ ld [Buffer1], a
+ ld a, [rOBP1]
+ ld [Buffer2], a
+ call .DoJumptableFunctions
+ ld a, [Buffer2]
+ call DmgToCgbObjPal1
+ ret
+; 1233e
+
+.DoJumptableFunctions: ; 1233e
+ xor a
+ ld [Buffer3], a
+.jumpable_loop
+ ld a, [Buffer1]
+ ld e, a
+ ld d, 0
+ ld hl, .Pointers
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [Buffer3]
+ ld e, a
+ inc a
+ ld [Buffer3], a
+ add hl, de
+ ld a, [hl]
+ cp 5
+ jr z, .finish
+ ld hl, .Jumptable
+ rst JumpTable
+ jr .jumpable_loop
+
+.finish
+ ret
+; 12365
+
+.Pointers: ; 12365
+ dw .Pokecenter
+ dw .ElmLab
+ dw .HallOfFame
+; 1236b
+
+.Pokecenter: ; 1236b
+ db 0, 1, 3, 5
+.ElmLab: ; 1236f
+ db 0, 1, 3, 5
+.HallOfFame: ; 12373
+ db 0, 2, 4, 5
+; 12377
+
+.Jumptable: ; 12377
+ dw .LoadGFX
+ dw .PC_LoadBallsOntoMachine
+ dw .HOF_LoadBallsOntoMachine
+ dw .PlayHealMusic
+ dw .HOF_PlaySFX
+ dw .dummy_5 ; never encountered
+; 12383
+
+.LoadGFX: ; 12383
+ call .LoadPalettes
+ ld de, .HealMachineGFX
+ ld hl, VTiles0 tile $7c
+ lb bc, BANK(.HealMachineGFX), $2
+ call Request2bpp
+ ret
+; 12393
+
+.PC_LoadBallsOntoMachine: ; 12393
+ ld hl, Sprites + $80
+ ld de, .PC_ElmsLab_OAM
+ call .PlaceHealingMachineTile
+ call .PlaceHealingMachineTile
+ jr .LoadBallsOntoMachine
+
+.HOF_LoadBallsOntoMachine: ; 123a1
+ ld hl, Sprites + $80
+ ld de, .HOF_OAM
+
+.LoadBallsOntoMachine: ; 123a7
+ ld a, [PartyCount]
+ ld b, a
+.party_loop
+ call .PlaceHealingMachineTile
+ push de
+ ld de, SFX_SECOND_PART_OF_ITEMFINDER
+ call PlaySFX
+ pop de
+ ld c, 30
+ call DelayFrames
+ dec b
+ jr nz, .party_loop
+ ret
+; 123bf
+
+.PlayHealMusic: ; 123bf
+ ld de, MUSIC_HEAL
+ call PlayMusic
+ jp .FlashPalettes8Times
+; 123c8
+
+.HOF_PlaySFX: ; 123c8
+ ld de, SFX_GAME_FREAK_LOGO_GS
+ call PlaySFX
+ call .FlashPalettes8Times
+ call WaitSFX
+ ld de, SFX_BOOT_PC
+ call PlaySFX
+ ret
+; 123db
+
+.dummy_5 ; 123db
+ ret
+; 123dc
+
+.PC_ElmsLab_OAM: ; 123dc
+ dsprite 4, 0, 4, 2, $7c, PAL_OW_TREE | OBP_NUM
+ dsprite 4, 0, 4, 6, $7c, PAL_OW_TREE | OBP_NUM
+ dsprite 4, 6, 4, 0, $7d, PAL_OW_TREE | OBP_NUM
+ dsprite 4, 6, 5, 0, $7d, PAL_OW_TREE | OBP_NUM | X_FLIP
+ dsprite 5, 3, 4, 0, $7d, PAL_OW_TREE | OBP_NUM
+ dsprite 5, 3, 5, 0, $7d, PAL_OW_TREE | OBP_NUM | X_FLIP
+ dsprite 6, 0, 4, 0, $7d, PAL_OW_TREE | OBP_NUM
+ dsprite 6, 0, 5, 0, $7d, PAL_OW_TREE | OBP_NUM | X_FLIP
+; 123fc
+
+.HealMachineGFX: ; 123fc
+INCBIN "gfx/overworld/heal_machine.2bpp"
+; 1241c
+
+.HOF_OAM: ; 1241c
+ dsprite 7, 4, 10, 1, $7d, PAL_OW_TREE | OBP_NUM
+ dsprite 7, 4, 10, 6, $7d, PAL_OW_TREE | OBP_NUM
+ dsprite 7, 3, 9, 5, $7d, PAL_OW_TREE | OBP_NUM
+ dsprite 7, 3, 11, 2, $7d, PAL_OW_TREE | OBP_NUM
+ dsprite 7, 1, 9, 1, $7d, PAL_OW_TREE | OBP_NUM
+ dsprite 7, 1, 11, 5, $7d, PAL_OW_TREE | OBP_NUM
+; 12434
+
+.LoadPalettes: ; 12434
+ call IsCGB
+ jr nz, .cgb
+ ld a, %11100000
+ ld [rOBP1], a
+ ret
+
+.cgb
+ ld hl, .palettes
+ ld de, OBPals palette PAL_OW_TREE
+ ld bc, 1 palettes
+ ld a, $5
+ call FarCopyWRAM
+ ld a, $1
+ ld [hCGBPalUpdate], a
+ ret
+; 12451
+
+.palettes ; 12451
+ RGB 31, 31, 31
+ RGB 31, 19, 10
+ RGB 31, 07, 01
+ RGB 00, 00, 00
+; 12459
+
+.FlashPalettes8Times: ; 12459
+ ld c, $8
+.palette_loop
+ push bc
+ call .FlashPalettes
+ ld c, 10
+ call DelayFrames
+ pop bc
+ dec c
+ jr nz, .palette_loop
+ ret
+; 12469
+
+.FlashPalettes: ; 12469
+ call IsCGB
+ jr nz, .go
+ ld a, [rOBP1]
+ xor %00101000
+ ld [rOBP1], a
+ ret
+
+.go
+ ld a, [rSVBK]
+ push af
+ ld a, $5
+ ld [rSVBK], a
+
+ ld hl, OBPals palette PAL_OW_TREE
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ push de
+ ld c, $3
+.palette_loop_2
+ ld a, [hli]
+ ld e, a
+ ld a, [hld]
+ ld d, a
+ dec hl
+ ld a, d
+ ld [hld], a
+ ld a, e
+ ld [hli], a
+ inc hl
+ inc hl
+ inc hl
+ dec c
+ jr nz, .palette_loop_2
+ pop de
+ dec hl
+ ld a, d
+ ld [hld], a
+ ld a, e
+ ld [hl], a
+
+ pop af
+ ld [rSVBK], a
+ ld a, $1
+ ld [hCGBPalUpdate], a
+ ret
+; 124a3
+
+.PlaceHealingMachineTile: ; 124a3
+ push bc
+ ld a, [Buffer1]
+ bcpixel 2, 4
+ cp $1 ; ElmsLab
+ jr z, .okay
+ bcpixel 0, 0
+
+.okay
+ ld a, [de]
+ add c
+ inc de
+ ld [hli], a
+ ld a, [de]
+ add b
+ inc de
+ ld [hli], a
+ ld a, [de]
+ inc de
+ ld [hli], a
+ ld a, [de]
+ inc de
+ ld [hli], a
+ pop bc
+ ret
+; 124c1
diff --git a/engine/events/itemfinder.asm b/engine/events/itemfinder.asm
new file mode 100755
index 000000000..71aaa5b69
--- /dev/null
+++ b/engine/events/itemfinder.asm
@@ -0,0 +1,58 @@
+ItemFinder: ; 12580
+ farcall CheckForHiddenItems
+ jr c, .found_something
+ ld hl, .Script_FoundNothing
+ jr .resume
+
+.found_something
+ ld hl, .Script_FoundSomething
+
+.resume
+ call QueueScript
+ ld a, $1
+ ld [wItemEffectSucceeded], a
+ ret
+; 12599
+
+.ItemfinderSound: ; 12599
+ ld c, 4
+.sfx_loop
+ push bc
+ ld de, SFX_SECOND_PART_OF_ITEMFINDER
+ call WaitPlaySFX
+ ld de, SFX_TRANSACTION
+ call WaitPlaySFX
+ pop bc
+ dec c
+ jr nz, .sfx_loop
+ ret
+; 125ad
+
+.Script_FoundSomething: ; 0x125ad
+ reloadmappart
+ special UpdateTimePals
+ callasm .ItemfinderSound
+ writetext .Text_FoundSomething
+ closetext
+ end
+; 0x125ba
+
+.Script_FoundNothing: ; 0x125ba
+ reloadmappart
+ special UpdateTimePals
+ writetext .Text_FoundNothing
+ closetext
+ end
+; 0x125c3
+
+.Text_FoundSomething: ; 0x125c3
+ ; Yes! ITEMFINDER indicates there's an item nearby.
+ text_jump UnknownText_0x1c0a77
+ db "@"
+; 0x125c8
+
+.Text_FoundNothing: ; 0x125c8
+ ; Nope! ITEMFINDER isn't responding.
+ text_jump UnknownText_0x1c0aa9
+ db "@"
+; 0x125cd
diff --git a/engine/events/kurt.asm b/engine/events/kurt.asm
new file mode 100644
index 000000000..9bc06a613
--- /dev/null
+++ b/engine/events/kurt.asm
@@ -0,0 +1,413 @@
+Kurt_PrintTextWhichApricorn: ; 88000
+ ld hl, .Text
+ call PrintText
+ ret
+; 88007
+
+.Text: ; 0x88007
+ ; Which APRICORN should I use?
+ text_jump UnknownText_0x1bc06b
+ db "@"
+; 0x8800c
+
+Kurt_PrintTextHowMany: ; 8800c
+ ld hl, .Text
+ call PrintText
+ ret
+; 88013
+
+.Text: ; 0x88013
+ ; How many should I make?
+ text_jump UnknownText_0x1bc089
+ db "@"
+; 0x88018
+
+Special_SelectApricornForKurt: ; 88018
+ call LoadStandardMenuDataHeader
+ ld c, $1
+ xor a
+ ld [wMenuScrollPosition], a
+ ld [wKurtApricornQuantity], a
+.loop
+ push bc
+ call Kurt_PrintTextWhichApricorn
+ pop bc
+ ld a, c
+ ld [MenuSelection], a
+ call Kurt_SelectApricorn
+ ld a, c
+ ld [ScriptVar], a
+ and a
+ jr z, .done
+ ld [CurItem], a
+ ld a, [wMenuCursorY]
+ ld c, a
+ push bc
+ call Kurt_PrintTextHowMany
+ call Kurt_SelectQuantity
+ pop bc
+ jr nc, .loop
+ ld a, [wItemQuantityChangeBuffer]
+ ld [wKurtApricornQuantity], a
+ call Kurt_GiveUpSelectedQuantityOfSelectedApricorn
+
+.done
+ call Call_ExitMenu
+ ret
+; 88055
+
+Kurt_SelectApricorn: ; 88055
+ farcall FindApricornsInBag
+ jr c, .nope
+ ld hl, .MenuDataHeader
+ call CopyMenuDataHeader
+ ld a, [MenuSelection]
+ ld [wMenuCursorBuffer], a
+ xor a
+ ld [hBGMapMode], a
+ call InitScrollingMenu
+ call UpdateSprites
+ call ScrollingMenu
+ ld a, [wMenuJoypad]
+ cp B_BUTTON
+ jr z, .nope
+ ld a, [MenuSelection]
+ cp -1
+ jr nz, .done
+
+.nope
+ xor a
+
+.done
+ ld c, a
+ ret
+; 88086
+
+.MenuDataHeader: ; 0x88086
+ db $40 ; flags
+ db 01, 01 ; start coords
+ db 10, 13 ; end coords
+ dw .MenuData2
+ db 1 ; default option
+; 0x8808e
+
+ db 0
+
+.MenuData2: ; 0x8808f
+ db $10 ; flags
+ db 4, 7
+ db 1
+ dbw 0, Buffer1
+ dba .Name
+ dba .Quantity
+ dba NULL
+
+.Name: ; 8809f
+ ld a, [MenuSelection]
+ and a
+ ret z
+ farcall PlaceMenuItemName
+ ret
+; 880ab
+
+.Quantity: ; 880ab
+ ld a, [MenuSelection]
+ ld [CurItem], a
+ call Kurt_GetQuantityOfApricorn
+ ret z
+ ld a, [wItemQuantityChangeBuffer]
+ ld [MenuSelectionQuantity], a
+ farcall PlaceMenuItemQuantity
+ ret
+; 880c2
+
+Kurt_SelectQuantity: ; 880c2
+ ld a, [CurItem]
+ ld [MenuSelection], a
+ call Kurt_GetQuantityOfApricorn
+ jr z, .done
+ ld a, [wItemQuantityChangeBuffer]
+ ld [wItemQuantityBuffer], a
+ ld a, $1
+ ld [wItemQuantityChangeBuffer], a
+ ld hl, .MenuDataHeader
+ call LoadMenuDataHeader
+.loop
+ xor a
+ ld [hBGMapMode], a
+ call MenuBox
+ call UpdateSprites
+ call .PlaceApricornName
+ call PlaceApricornQuantity
+ call ApplyTilemap
+ farcall Kurt_SelectQuantity_InterpretJoypad
+ jr nc, .loop
+
+ push bc
+ call PlayClickSFX
+ pop bc
+ ld a, b
+ cp -1
+ jr z, .done
+ ld a, [wItemQuantityChangeBuffer]
+ ld [wItemQuantityChangeBuffer], a ; What is the point of this operation?
+ scf
+
+.done
+ call CloseWindow
+ ret
+; 8810d
+
+.MenuDataHeader: ; 0x8810d
+ db $40 ; flags
+ db 09, 06 ; start coords
+ db 12, 19 ; end coords
+
+ db 0, 0, -1, 0 ; XXX
+
+.PlaceApricornName: ; 88116
+ call MenuBoxCoord2Tile
+ ld de, SCREEN_WIDTH + 1
+ add hl, de
+ ld d, h
+ ld e, l
+ farcall PlaceMenuItemName
+ ret
+; 88126
+
+PlaceApricornQuantity: ; 88126
+ call MenuBoxCoord2Tile
+ ld de, 2 * SCREEN_WIDTH + 10
+ add hl, de
+ ld [hl], "×"
+ inc hl
+ ld de, wItemQuantityChangeBuffer
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ jp PrintNum
+; 88139
+
+Kurt_GetQuantityOfApricorn: ; 88139
+ push bc
+ ld hl, NumItems
+ ld a, [CurItem]
+ ld c, a
+ ld b, $0
+.loop
+ inc hl
+ ld a, [hli]
+ cp -1
+ jr z, .done
+ cp c
+ jr nz, .loop
+ ld a, [hl]
+ add b
+ ld b, a
+ jr nc, .loop
+ ld b, -1
+
+.done
+ ld a, b
+ sub 99
+ jr c, .done2
+ ld b, 99
+
+.done2
+ ld a, b
+ ld [wItemQuantityChangeBuffer], a
+ and a
+ pop bc
+ ret
+; 88161
+
+Kurt_GiveUpSelectedQuantityOfSelectedApricorn: ; 88161
+; Get the quantity of Apricorns of type [CurItem]
+; in the bag. Compatible with multiple stacks.
+
+; Initialize the search.
+ push de
+ push bc
+ ld hl, NumItems
+ ld a, [CurItem]
+ ld c, a
+ ld e, $0
+ xor a
+ ld [CurItemQuantity], a
+ ld a, -1
+ ld [wApricorns], a
+
+; Search for [CurItem] in the bag.
+.loop1
+; Increase the total count.
+ ld a, [CurItemQuantity]
+ inc a
+ ld [CurItemQuantity], a
+; Get the index of the next item.
+ inc hl
+ ld a, [hli]
+; If we've reached the end of the pocket, break.
+ cp -1
+ jr z, .okay1
+; If we haven't found what we're looking for, continue.
+ cp c
+ jr nz, .loop1
+; Increment the result counter and store the bag index of the match.
+ ld d, $0
+ push hl
+ ld hl, wApricorns
+ add hl, de
+ inc e
+ ld a, [CurItemQuantity]
+ dec a
+ ld [hli], a
+ ld a, -1
+ ld [hl], a
+ pop hl
+ jr .loop1
+
+.okay1
+; How many stacks have we found?
+ ld a, e
+ and a
+ jr z, .done
+ dec a
+ jr z, .OnlyOne
+ ld hl, wApricorns
+
+.loop2
+ ld a, [hl]
+ ld c, a
+ push hl
+.loop3
+ inc hl
+ ld a, [hl]
+ cp -1
+ jr z, .okay2
+ ld b, a
+ ld a, c
+ call Kurt_GetAddressOfApricornQuantity
+ ld e, a
+ ld a, b
+ call Kurt_GetAddressOfApricornQuantity
+ sub e
+ jr z, .equal
+ jr c, .less
+ jr .loop3
+
+.equal
+ ld a, c
+ sub b
+ jr nc, .loop3
+
+.less
+ ld a, c
+ ld c, b
+ ld [hl], a
+ ld a, c
+ pop hl
+ ld [hl], a
+ push hl
+ jr .loop3
+
+.okay2
+ pop hl
+ inc hl
+ ld a, [hl]
+ cp -1
+ jr nz, .loop2
+
+.OnlyOne:
+ ld hl, wApricorns
+.loop4
+ ld a, [hl]
+ cp -1
+ jr z, .done
+ push hl
+ ld [CurItemQuantity], a
+ call Kurt_GetRidOfItem
+ pop hl
+ ld a, [wItemQuantityChangeBuffer]
+ and a
+ jr z, .done
+ push hl
+ ld a, [hli]
+ ld c, a
+.loop5
+ ld a, [hli]
+ cp -1
+ jr z, .okay3
+ cp c
+ jr c, .loop5
+ dec a
+ dec hl
+ ld [hli], a
+ jr .loop5
+
+.okay3
+ pop hl
+ inc hl
+ jr .loop4
+
+.done
+ ld a, [wItemQuantityChangeBuffer]
+ and a
+ pop bc
+ pop de
+ ret
+; 88201
+
+Kurt_GetAddressOfApricornQuantity: ; 88201
+ push hl
+ push bc
+ ld hl, NumItems
+ inc hl
+ ld c, a
+ ld b, $0
+ add hl, bc
+ add hl, bc
+ inc hl
+ ld a, [hl]
+ pop bc
+ pop hl
+ ret
+; 88211
+
+Kurt_GetRidOfItem: ; 88211
+ push bc
+ ld hl, NumItems
+ ld a, [CurItemQuantity]
+ ld c, a
+ ld b, $0
+ inc hl
+ add hl, bc
+ add hl, bc
+ ld a, [CurItem]
+ ld c, a
+ ld a, [hli]
+ cp -1
+ jr z, .done
+ cp c
+ jr nz, .done
+ ld a, [wItemQuantityChangeBuffer]
+ ld c, a
+ ld a, [hl]
+ sub c
+ ld b, c
+ jr nc, .okay
+ add c
+ ld b, a
+
+.okay
+ push bc
+ ld hl, NumItems
+ ld a, b
+ ld [wItemQuantityChangeBuffer], a
+ call TossItem
+ pop bc
+ ld a, c
+ sub b
+
+.done
+ ld [wItemQuantityChangeBuffer], a
+ pop bc
+ ret
+; 88248
diff --git a/engine/events/kurt_selectquantity_interpretjoypad.asm b/engine/events/kurt_selectquantity_interpretjoypad.asm
new file mode 100644
index 000000000..12a43e325
--- /dev/null
+++ b/engine/events/kurt_selectquantity_interpretjoypad.asm
@@ -0,0 +1,4 @@
+Kurt_SelectQuantity_InterpretJoypad: ; 27a28
+ call BuySellToss_InterpretJoypad
+ ld b, a
+ ret
diff --git a/engine/events/lucky_number.asm b/engine/events/lucky_number.asm
new file mode 100644
index 000000000..4488cfcc9
--- /dev/null
+++ b/engine/events/lucky_number.asm
@@ -0,0 +1,226 @@
+Special_CheckForLuckyNumberWinners: ; 4d87a
+ xor a
+ ld [ScriptVar], a
+ ld [wFoundMatchingIDInParty], a
+ ld a, [PartyCount]
+ and a
+ ret z
+ ld d, a
+ ld hl, PartyMon1ID
+ ld bc, PartySpecies
+.PartyLoop:
+ ld a, [bc]
+ inc bc
+ cp EGG
+ call nz, .CompareLuckyNumberToMonID
+ push bc
+ ld bc, PARTYMON_STRUCT_LENGTH
+ add hl, bc
+ pop bc
+ dec d
+ jr nz, .PartyLoop
+ ld a, BANK(sBox)
+ call GetSRAMBank
+ ld a, [sBoxCount]
+ and a
+ jr z, .SkipOpenBox
+ ld d, a
+ ld hl, sBoxMon1ID
+ ld bc, sBoxSpecies
+.OpenBoxLoop:
+ ld a, [bc]
+ inc bc
+ cp EGG
+ jr z, .SkipOpenBoxMon
+ call .CompareLuckyNumberToMonID
+ jr nc, .SkipOpenBoxMon
+ ld a, 1
+ ld [wFoundMatchingIDInParty], a
+
+.SkipOpenBoxMon:
+ push bc
+ ld bc, BOXMON_STRUCT_LENGTH
+ add hl, bc
+ pop bc
+ dec d
+ jr nz, .OpenBoxLoop
+
+.SkipOpenBox:
+ call CloseSRAM
+ ld c, $0
+.BoxesLoop:
+ ld a, [wCurBox]
+ and $f
+ cp c
+ jr z, .SkipBox
+ ld hl, .BoxBankAddresses
+ ld b, 0
+ add hl, bc
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ call GetSRAMBank
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a ; hl now contains the address of the loaded box in SRAM
+ ld a, [hl]
+ and a
+ jr z, .SkipBox ; no mons in this box
+ push bc
+ ld b, h
+ ld c, l
+ inc bc
+ ld de, sBoxMon1ID - sBox
+ add hl, de
+ ld d, a
+.BoxNLoop:
+ ld a, [bc]
+ inc bc
+ cp EGG
+ jr z, .SkipBoxMon
+
+ call .CompareLuckyNumberToMonID ; sets ScriptVar and CurPartySpecies appropriately
+ jr nc, .SkipBoxMon
+ ld a, 1
+ ld [wFoundMatchingIDInParty], a
+
+.SkipBoxMon:
+ push bc
+ ld bc, BOXMON_STRUCT_LENGTH
+ add hl, bc
+ pop bc
+ dec d
+ jr nz, .BoxNLoop
+ pop bc
+
+.SkipBox:
+ inc c
+ ld a, c
+ cp NUM_BOXES
+ jr c, .BoxesLoop
+
+ call CloseSRAM
+ ld a, [ScriptVar]
+ and a
+ ret z ; found nothing
+ farcall TrainerRankings_LuckyNumberShow
+ ld a, [wFoundMatchingIDInParty]
+ and a
+ push af
+ ld a, [CurPartySpecies]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, .FoundPartymonText
+ pop af
+ jr z, .print
+ ld hl, .FoundBoxmonText
+
+.print
+ jp PrintText
+
+.CompareLuckyNumberToMonID: ; 4d939
+ push bc
+ push de
+ push hl
+ ld d, h
+ ld e, l
+ ld hl, Buffer1
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+ call PrintNum
+ ld hl, LuckyNumberDigit1Buffer
+ ld de, wLuckyIDNumber
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+ call PrintNum
+ ld b, 5
+ ld c, 0
+ ld hl, LuckyNumberDigit5Buffer
+ ld de, Buffer5
+.loop
+ ld a, [de]
+ cp [hl]
+ jr nz, .done
+ dec de
+ dec hl
+ inc c
+ dec b
+ jr nz, .loop
+
+.done
+ pop hl
+ push hl
+ ld de, -6
+ add hl, de
+ ld a, [hl]
+ pop hl
+ pop de
+ push af
+ ld a, c
+ ld b, 1
+ cp 5
+ jr z, .okay
+ ld b, 2
+ cp 3
+ jr nc, .okay
+ ld b, 3
+ cp 2
+ jr nz, .nomatch
+
+.okay
+ inc b
+ ld a, [ScriptVar]
+ and a
+ jr z, .bettermatch
+ cp b
+ jr c, .nomatch
+
+.bettermatch
+ dec b
+ ld a, b
+ ld [ScriptVar], a
+ pop bc
+ ld a, b
+ ld [CurPartySpecies], a
+ pop bc
+ scf
+ ret
+
+.nomatch
+ pop bc
+ pop bc
+ and a
+ ret
+
+.BoxBankAddresses: ; 4d99f
+ dba sBox1
+ dba sBox2
+ dba sBox3
+ dba sBox4
+ dba sBox5
+ dba sBox6
+ dba sBox7
+ dba sBox8
+ dba sBox9
+ dba sBox10
+ dba sBox11
+ dba sBox12
+ dba sBox13
+ dba sBox14
+
+.FoundPartymonText: ; 0x4d9c9
+ ; Congratulations! We have a match with the ID number of @ in your party.
+ text_jump UnknownText_0x1c1261
+ db "@"
+
+.FoundBoxmonText: ; 0x4d9ce
+ ; Congratulations! We have a match with the ID number of @ in your PC BOX.
+ text_jump UnknownText_0x1c12ae
+ db "@"
+
+Special_PrintTodaysLuckyNumber: ; 4d9d3
+ ld hl, StringBuffer3
+ ld de, wLuckyIDNumber
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+ call PrintNum
+ ld a, "@"
+ ld [StringBuffer3 + 5], a
+ ret
diff --git a/engine/events/magikarp.asm b/engine/events/magikarp.asm
new file mode 100644
index 000000000..02c4b10cd
--- /dev/null
+++ b/engine/events/magikarp.asm
@@ -0,0 +1,342 @@
+Special_CheckMagikarpLength: ; fbb32
+ ; Returns 3 if you select a Magikarp that beats the previous record.
+ ; Returns 2 if you select a Magikarp, but the current record is longer.
+ ; Returns 1 if you press B in the Pokemon selection menu.
+ ; Returns 0 if the Pokemon you select is not a Magikarp.
+
+ ; Let's start by selecting a Magikarp.
+ farcall SelectMonFromParty
+ jr c, .declined
+ ld a, [CurPartySpecies]
+ cp MAGIKARP
+ jr nz, .not_magikarp
+
+ ; Now let's compute its length based on its DVs and ID.
+ ld a, [CurPartyMon]
+ ld hl, PartyMon1Species
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ push hl
+ ld bc, MON_DVS
+ add hl, bc
+ ld d, h
+ ld e, l
+ pop hl
+ ld bc, MON_ID
+ add hl, bc
+ ld b, h
+ ld c, l
+ call CalcMagikarpLength
+ call PrintMagikarpLength
+ farcall TrainerRankings_MagikarpLength
+ ld hl, .MeasureItText
+ call PrintText
+
+ ; Did we beat the record?
+ ld hl, wMagikarpLength
+ ld de, wBestMagikarpLengthFeet
+ ld c, 2
+ call StringCmp
+ jr nc, .not_long_enough
+
+ ; NEW RECORD!!! Let's save that.
+ ld hl, wMagikarpLength
+ ld de, wBestMagikarpLengthFeet
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ inc de
+ ld a, [CurPartyMon]
+ ld hl, PartyMonOT
+ call SkipNames
+ call CopyBytes
+ ld a, 3
+ ld [ScriptVar], a
+ ret
+
+.not_long_enough
+ ld a, 2
+ ld [ScriptVar], a
+ ret
+
+.declined
+ ld a, 1
+ ld [ScriptVar], a
+ ret
+
+.not_magikarp
+ xor a
+ ld [ScriptVar], a
+ ret
+; fbba9
+
+.MeasureItText: ; 0xfbba9
+ ; Let me measure that MAGIKARP. …Hm, it measures @ .
+ text_jump UnknownText_0x1c1203
+ db "@"
+; 0xfbbae
+
+Magikarp_LoadFeetInchesChars: ; fbbae
+ ld hl, VTiles2 tile "′" ; $6e
+ ld de, .feetinchchars
+ lb bc, BANK(.feetinchchars), 2
+ call Request2bpp
+ ret
+; fbbbb
+
+.feetinchchars ; fbbb
+INCBIN "gfx/font/feet_inches.2bpp"
+; fbbdb
+
+PrintMagikarpLength: ; fbbdb
+ call Magikarp_LoadFeetInchesChars
+ ld hl, StringBuffer1
+ ld de, wMagikarpLength
+ lb bc, PRINTNUM_RIGHTALIGN | 1, 2
+ call PrintNum
+ ld [hl], "′"
+ inc hl
+ ld de, wMagikarpLength + 1
+ lb bc, PRINTNUM_RIGHTALIGN | 1, 2
+ call PrintNum
+ ld [hl], "″"
+ inc hl
+ ld [hl], "@"
+ ret
+; fbbfc
+
+CalcMagikarpLength: ; fbbfc
+; Return Magikarp's length (in mm) at wMagikarpLength (big endian).
+;
+; input:
+; de: EnemyMonDVs
+; bc: PlayerID
+
+; This function is poorly commented.
+
+; In short, it generates a value between 190 and 1786 using
+; a Magikarp's DVs and its trainer ID. This value is further
+; filtered in LoadEnemyMon to make longer Magikarp even rarer.
+
+; The value is generated from a lookup table.
+; The index is determined by the dv xored with the player's trainer id.
+
+; bc = rrc(dv[0]) ++ rrc(dv[1]) ^ rrc(id)
+
+; if bc < 10: [wMagikarpLength] = c + 190
+; if bc ≥ $ff00: [wMagikarpLength] = c + 1370
+; else: [wMagikarpLength] = z * 100 + (bc - x) / y
+
+; X, Y, and Z depend on the value of b as follows:
+
+; if b = 0: x = 310, y = 2, z = 3
+; if b = 1: x = 710, y = 4, z = 4
+; if b = 2-9: x = 2710, y = 20, z = 5
+; if b = 10-29: x = 7710, y = 50, z = 6
+; if b = 30-68: x = 17710, y = 100, z = 7
+; if b = 69-126: x = 32710, y = 150, z = 8
+; if b = 127-185: x = 47710, y = 150, z = 9
+; if b = 186-224: x = 57710, y = 100, z = 10
+; if b = 225-243: x = 62710, y = 50, z = 11
+; if b = 244-251: x = 64710, y = 20, z = 12
+; if b = 252-253: x = 65210, y = 5, z = 13
+; if b = 254: x = 65410, y = 2, z = 14
+
+
+ ; bc = rrc(dv[0]) ++ rrc(dv[1]) ^ rrc(id)
+
+ ; id
+ ld h, b
+ ld l, c
+ ld a, [hli]
+ ld b, a
+ ld c, [hl]
+ rrc b
+ rrc c
+
+ ; dv
+ ld a, [de]
+ inc de
+ rrca
+ rrca
+ xor b
+ ld b, a
+
+ ld a, [de]
+ rrca
+ rrca
+ xor c
+ ld c, a
+
+ ; if bc < 10:
+ ; de = bc + 190
+ ; break
+
+ ld a, b
+ and a
+ jr nz, .no
+ ld a, c
+ cp 10
+ jr nc, .no
+
+ ld hl, 190
+ add hl, bc
+ ld d, h
+ ld e, l
+ jr .done
+
+.no
+
+ ld hl, .Lengths
+ ld a, 2
+ ld [wd265], a
+
+.read
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ call .BCLessThanDE
+ jr nc, .next
+
+ ; c = (bc - de) / [hl]
+ call .BCMinusDE
+ ld a, b
+ ld [hDividend + 0], a
+ ld a, c
+ ld [hDividend + 1], a
+ ld a, [hl]
+ ld [hDivisor], a
+ ld b, 2
+ call Divide
+ ld a, [hQuotient + 2]
+ ld c, a
+
+ ; de = c + 100 × (2 + i)
+ xor a
+ ld [hMultiplicand + 0], a
+ ld [hMultiplicand + 1], a
+ ld a, 100
+ ld [hMultiplicand + 2], a
+ ld a, [wd265]
+ ld [hMultiplier], a
+ call Multiply
+ ld b, 0
+ ld a, [hProduct + 3]
+ add c
+ ld e, a
+ ld a, [hProduct + 2]
+ adc b
+ ld d, a
+ jr .done
+
+.next
+ inc hl ; align to next triplet
+ ld a, [wd265]
+ inc a
+ ld [wd265], a
+ cp 16
+ jr c, .read
+
+ call .BCMinusDE
+ ld hl, 1600
+ add hl, bc
+ ld d, h
+ ld e, l
+
+.done
+ ; hl = de × 10
+ ld h, d
+ ld l, e
+ add hl, hl
+ add hl, hl
+ add hl, de
+ add hl, hl
+
+ ; hl = hl / 254
+ ld de, -254
+ ld a, -1
+.div_254
+ inc a
+ add hl, de
+ jr c, .div_254
+
+ ; d, e = hl / 12, hl % 12
+ ld d, 0
+.mod_12
+ cp 12
+ jr c, .ok
+ sub 12
+ inc d
+ jr .mod_12
+.ok
+ ld e, a
+
+ ld hl, wMagikarpLength
+ ld [hl], d
+ inc hl
+ ld [hl], e
+ ret
+; fbc9a
+
+.BCLessThanDE: ; fbc9a
+; Intention: Return bc < de.
+; Reality: Return b < d.
+ ld a, b
+ cp d
+ ret c
+ ret nc ; whoops
+ ld a, c
+ cp e
+ ret
+; fbca1
+
+.BCMinusDE: ; fbca1
+; bc -= de
+ ld a, c
+ sub e
+ ld c, a
+ ld a, b
+ sbc d
+ ld b, a
+ ret
+; fbca8
+
+.Lengths: ; fbca8
+; ????, divisor
+ dwb 110, 1
+ dwb 310, 2
+ dwb 710, 4
+ dwb 2710, 20
+ dwb 7710, 50
+ dwb 17710, 100
+ dwb 32710, 150
+ dwb 47710, 150
+ dwb 57710, 100
+ dwb 62710, 50
+ dwb 64710, 20
+ dwb 65210, 5
+ dwb 65410, 2
+ dwb 65510, 1 ; not used
+; fbcd2
+
+
+
+Special_MagikarpHouseSign: ; fbcd2
+ ld a, [wBestMagikarpLengthFeet]
+ ld [wMagikarpLength], a
+ ld a, [wBestMagikarpLengthInches]
+ ld [wMagikarpLength + 1], a
+ call PrintMagikarpLength
+ ld hl, .CurrentRecordtext
+ call PrintText
+ ret
+; fbce8
+
+.CurrentRecordtext: ; 0xfbce8
+ ; "CURRENT RECORD"
+ text_jump UnknownText_0x1c123a
+ db "@"
+; 0xfbced
diff --git a/engine/events/magnet_train.asm b/engine/events/magnet_train.asm
new file mode 100755
index 000000000..3a2f902c2
--- /dev/null
+++ b/engine/events/magnet_train.asm
@@ -0,0 +1,482 @@
+Special_MagnetTrain: ; 8cc04
+ ld a, [ScriptVar]
+ and a
+ jr nz, .ToGoldenrod
+ ld a, 1 ; forwards
+ lb bc, $40, $60
+ lb de, (11 * 8) - (11 * 8 + 4), -$60
+ jr .continue
+
+.ToGoldenrod:
+ ld a, -1 ; backwards
+ lb bc, -$40, -$60
+ lb de, (11 * 8) + (11 * 8 + 4), $60
+
+.continue
+ ld h, a
+ ld a, [rSVBK]
+ push af
+ ld a, $5
+ ld [rSVBK], a
+
+ ld a, h
+ ld [wMagnetTrainDirection], a
+ ld a, c
+ ld [wMagnetTrainInitPosition], a
+ ld a, b
+ ld [wMagnetTrainHoldPosition], a
+ ld a, e
+ ld [wMagnetTrainFinalPosition], a
+ ld a, d
+ ld [wMagnetTrainPlayerSpriteInitX], a
+
+ ld a, [hSCX]
+ push af
+ ld a, [hSCY]
+ push af
+ call MagntTrain_LoadGFX_PlayMusic
+ ld hl, hVBlank
+ ld a, [hl]
+ push af
+ ld [hl], $1
+.loop
+ ld a, [wJumptableIndex]
+ and a
+ jr z, .initialize
+ bit 7, a
+ jr nz, .done
+ callfar PlaySpriteAnimations
+ call MagnetTrain_Jumptable
+ call MagnetTrain_UpdateLYOverrides
+ call PushLYOverrides
+ call DelayFrame
+ jr .loop
+
+.initialize
+ call MagnetTrain_Jumptable_FirstRunThrough
+ jr .loop
+
+.done
+ pop af
+ ld [hVBlank], a
+ call ClearBGPalettes
+ xor a
+ ld [hLCDCPointer], a
+ ld [hLYOverrideStart], a
+ ld [hLYOverrideEnd], a
+ ld [hSCX], a
+ ld [Requested2bppSource], a
+ ld [Requested2bppSource + 1], a
+ ld [Requested2bppDest], a
+ ld [Requested2bppDest + 1], a
+ ld [Requested2bpp], a
+ call ClearTileMap
+
+ pop af
+ ld [hSCY], a
+ pop af
+ ld [hSCX], a
+ xor a
+ ld [hBGMapMode], a
+ pop af
+ ld [rSVBK], a
+ ret
+; 8cc99
+
+MagnetTrain_UpdateLYOverrides: ; 8cc99
+ ld hl, LYOverridesBackup
+ ld c, $2f
+ ld a, [wcf64]
+ add a
+ ld [hSCX], a
+ call .loadloop
+ ld c, $30
+ ld a, [wcf65]
+ call .loadloop
+ ld c, $31
+ ld a, [wcf64]
+ add a
+ call .loadloop
+ ld a, [wMagnetTrainDirection]
+ ld d, a
+ ld hl, wcf64
+ ld a, [hl]
+ add d
+ add d
+ ld [hl], a
+ ret
+
+.loadloop
+ ld [hli], a
+ dec c
+ jr nz, .loadloop
+ ret
+; 8ccc9
+
+MagntTrain_LoadGFX_PlayMusic: ; 8ccc9
+ call ClearBGPalettes
+ call ClearSprites
+ call DisableLCD
+ callfar ClearSpriteAnims
+ call SetMagnetTrainPals
+ call DrawMagnetTrain
+ ld a, $90
+ ld [hWY], a
+ call EnableLCD
+ xor a
+ ld [hBGMapMode], a
+ ld [hSCX], a
+ ld [hSCY], a
+ ld a, [rSVBK]
+ push af
+ ld a, $1
+ ld [rSVBK], a
+ farcall GetPlayerIcon
+ pop af
+ ld [rSVBK], a
+ ld hl, VTiles0
+ ld c, 4
+ call Request2bpp
+ ld hl, 12 tiles
+ add hl, de
+ ld d, h
+ ld e, l
+ ld hl, VTiles0 tile $04
+ ld c, 4
+ call Request2bpp
+ call MagnetTrain_InitLYOverrides
+ ld hl, wJumptableIndex
+ xor a
+ ld [hli], a
+ ld a, [wMagnetTrainInitPosition]
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld de, MUSIC_MAGNET_TRAIN
+ call PlayMusic2
+ ret
+; 8cd27
+
+DrawMagnetTrain: ; 8cd27
+ hlbgcoord 0, 0
+ xor a
+.loop
+ call GetMagnetTrainBGTiles
+ ld b, 32 / 2
+ call .FillAlt
+ inc a
+ cp $12
+ jr c, .loop
+ hlbgcoord 0, 6
+ ld de, MagnetTrainTilemap1
+ ld c, 20
+ call .FillLine
+ hlbgcoord 0, 7
+ ld de, MagnetTrainTilemap2
+ ld c, 20
+ call .FillLine
+ hlbgcoord 0, 8
+ ld de, MagnetTrainTilemap3
+ ld c, 20
+ call .FillLine
+ hlbgcoord 0, 9
+ ld de, MagnetTrainTilemap4
+ ld c, 20
+ call .FillLine
+ ret
+; 8cd65
+
+.FillLine: ; 8cd65
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec c
+ jr nz, .FillLine
+ ret
+; 8cd6c
+
+.FillAlt: ; 8cd6c
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ inc hl
+ dec b
+ jr nz, .FillAlt
+ ret
+; 8cd74
+
+GetMagnetTrainBGTiles: ; 8cd74
+ push hl
+ ld e, a
+ ld d, 0
+ ld hl, MagnetTrainBGTiles
+ add hl, de
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ pop hl
+ ret
+; 8cd82
+
+MagnetTrainBGTiles: ; 8cd82
+; Alternating tiles for each line
+; of the Magnet Train tilemap.
+ db $4c, $4d ; bush
+ db $5c, $5d ; bush
+ db $4c, $4d ; bush
+ db $5c, $5d ; bush
+ db $08, $08 ; fence
+ db $18, $18 ; fence
+ db $1f, $1f ; track
+ db $31, $31 ; track
+ db $11, $11 ; track
+ db $11, $11 ; track
+ db $0d, $0d ; track
+ db $31, $31 ; track
+ db $04, $04 ; fence
+ db $18, $18 ; fence
+ db $4c, $4d ; bush
+ db $5c, $5d ; bush
+ db $4c, $4d ; bush
+ db $5c, $5d ; bush
+; 8cda6
+
+MagnetTrain_InitLYOverrides: ; 8cda6
+ ld hl, LYOverrides
+ ld bc, LYOverridesEnd - LYOverrides
+ ld a, [wMagnetTrainInitPosition]
+ call ByteFill
+ ld hl, LYOverridesBackup
+ ld bc, LYOverridesBackupEnd - LYOverridesBackup
+ ld a, [wMagnetTrainInitPosition]
+ call ByteFill
+ ld a, rSCX - $ff00
+ ld [hLCDCPointer], a
+ ret
+; 8cdc3
+
+SetMagnetTrainPals: ; 8cdc3
+ ld a, $1
+ ld [rVBK], a
+
+ ; bushes
+ hlbgcoord 0, 0
+ ld bc, 4 bgrows
+ ld a, $2
+ call ByteFill
+
+ ; train
+ hlbgcoord 0, 4
+ ld bc, 10 bgrows
+ xor a
+ call ByteFill
+
+ ; more bushes
+ hlbgcoord 0, 14
+ ld bc, 4 bgrows
+ ld a, $2
+ call ByteFill
+
+ ; train window
+ hlbgcoord 7, 8
+ ld bc, 6
+ ld a, $4
+ call ByteFill
+
+ ld a, $0
+ ld [rVBK], a
+ ret
+; 8cdf7
+
+MagnetTrain_Jumptable: ; 8cdf7
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+; 8ce06
+
+.Jumptable: ; 8ce06
+
+ dw .InitPlayerSpriteAnim
+ dw .WaitScene
+ dw .MoveTrain1
+ dw .WaitScene
+ dw .MoveTrain2
+ dw .WaitScene
+ dw .TrainArrived
+; 8ce14
+
+.Next: ; 8ce14
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+; 8ce19
+
+.InitPlayerSpriteAnim: ; 8ce19
+ ld d, 10 * 8 + 5
+ ld a, [wMagnetTrainPlayerSpriteInitX]
+ ld e, a
+ ld b, SPRITE_ANIM_INDEX_MAGNET_TRAIN_RED
+ ld a, [rSVBK]
+ push af
+ ld a, $1
+ ld [rSVBK], a
+ ld a, [PlayerGender]
+ bit 0, a
+ jr z, .got_gender
+ ld b, SPRITE_ANIM_INDEX_MAGNET_TRAIN_BLUE
+
+.got_gender
+ pop af
+ ld [rSVBK], a
+ ld a, b
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $0
+ call .Next
+ ld a, $80
+ ld [wcf66], a
+ ret
+; 8ce47
+
+.MoveTrain1: ; 8ce47
+ ld hl, wMagnetTrainHoldPosition
+ ld a, [wcf65]
+ cp [hl]
+ jr z, .PrepareToHoldTrain
+ ld e, a
+ ld a, [wMagnetTrainDirection]
+ xor $ff
+ inc a
+ add e
+ ld [wcf65], a
+ ld hl, wGlobalAnimXOffset
+ ld a, [wMagnetTrainDirection]
+ add [hl]
+ ld [hl], a
+ ret
+
+.PrepareToHoldTrain:
+ call .Next
+ ld a, $80
+ ld [wcf66], a
+ ret
+; 8ce6d
+
+.WaitScene: ; 8ce6d
+ ld hl, wcf66
+ ld a, [hl]
+ and a
+ jr z, .DoneWaiting
+ dec [hl]
+ ret
+
+.DoneWaiting:
+ call .Next
+ ret
+; 8ce7a
+
+.MoveTrain2: ; 8ce7a
+ ld hl, wMagnetTrainFinalPosition
+ ld a, [wcf65]
+ cp [hl]
+ jr z, .PrepareToFinishAnim
+ ld e, a
+ ld a, [wMagnetTrainDirection]
+ xor $ff
+ inc a
+ ld d, a
+ ld a, e
+ add d
+ add d
+ ld [wcf65], a
+ ld hl, wGlobalAnimXOffset
+ ld a, [wMagnetTrainDirection]
+ ld d, a
+ ld a, [hl]
+ add d
+ add d
+ ld [hl], a
+ ret
+
+ ret
+
+.PrepareToFinishAnim:
+ call .Next
+ ret
+; 8cea2
+
+.TrainArrived: ; 8cea2
+ ld a, $80
+ ld [wJumptableIndex], a
+ ld de, SFX_TRAIN_ARRIVED
+ call PlaySFX
+ ret
+; 8ceae
+
+MagnetTrain_Jumptable_FirstRunThrough: ; 8ceae
+ farcall PlaySpriteAnimations
+ call MagnetTrain_Jumptable
+ call MagnetTrain_UpdateLYOverrides
+ call PushLYOverrides
+ call DelayFrame
+ ld a, [rSVBK]
+ push af
+ ld a, $1
+ ld [rSVBK], a
+ ld a, [TimeOfDayPal]
+ push af
+ ld a, [wEnvironment]
+ push af
+ ld a, [TimeOfDay]
+ and $3
+ ld [TimeOfDayPal], a
+ ld a, $1
+ ld [wEnvironment], a
+ ld b, SCGB_MAPPALS
+ call GetSGBLayout
+ call UpdateTimePals
+ ld a, [rBGP]
+ ld [wBGP], a
+ ld a, [rOBP0]
+ ld [wOBP0], a
+ ld a, [rOBP1]
+ ld [wOBP1], a
+ pop af
+ ld [wEnvironment], a
+ pop af
+ ld [TimeOfDayPal], a
+ pop af
+ ld [rSVBK], a
+ ret
+; 8ceff
+
+MagnetTrainTilemap1:
+ db $1f, $05, $06, $0a, $0a
+ db $0a, $09, $0a, $0a, $0a
+ db $0a, $0a, $0a, $09, $0a
+ db $0a, $0a, $0b, $0c, $1f
+MagnetTrainTilemap2:
+ db $14, $15, $16, $1a, $1a
+ db $1a, $19, $1a, $1a, $1a
+ db $1a, $1a, $1a, $19, $1a
+ db $1a, $1a, $1b, $1c, $1d
+MagnetTrainTilemap3:
+ db $24, $25, $26, $27, $07
+ db $2f, $29, $28, $28, $28
+ db $28, $28, $28, $29, $07
+ db $2f, $2a, $2b, $2c, $2d
+MagnetTrainTilemap4:
+ db $20, $1f, $2e, $1f, $17
+ db $00, $2e, $1f, $1f, $1f
+ db $1f, $1f, $1f, $2e, $17
+ db $00, $1f, $2e, $1f, $0f
+; 8cf4f
diff --git a/engine/events/misc_scripts.asm b/engine/events/misc_scripts.asm
new file mode 100755
index 000000000..97372a57a
--- /dev/null
+++ b/engine/events/misc_scripts.asm
@@ -0,0 +1,62 @@
+Script_AbortBugContest: ; 0x122c1
+ checkflag ENGINE_BUG_CONTEST_TIMER
+ iffalse .finish
+ setflag ENGINE_DAILY_BUG_CONTEST
+ special ContestReturnMons
+.finish
+ end
+
+FindItemInBallScript:: ; 0x122ce
+ callasm .TryReceiveItem
+ iffalse .no_room
+ disappear LAST_TALKED
+ opentext
+ writetext .text_found
+ playsound SFX_ITEM
+ pause 60
+ itemnotify
+ closetext
+ end
+; 0x122e3
+
+.no_room ; 0x122e3
+ opentext
+ writetext .text_found
+ waitbutton
+ writetext .text_bag_full
+ waitbutton
+ closetext
+ end
+; 0x122ee
+
+.text_found ; 0x122ee
+ ; found @ !
+ text_jump UnknownText_0x1c0a1c
+ db "@"
+; 0x122f3
+
+.text_bag_full ; 0x122f3
+ ; But can't carry any more items.
+ text_jump UnknownText_0x1c0a2c
+ db "@"
+; 0x122f8
+
+.TryReceiveItem: ; 122f8
+ xor a
+ ld [ScriptVar], a
+ ld a, [EngineBuffer1]
+ ld [wNamedObjectIndexBuffer], a
+ call GetItemName
+ ld hl, StringBuffer3
+ call CopyName2
+ ld a, [EngineBuffer1]
+ ld [CurItem], a
+ ld a, [CurFruit]
+ ld [wItemQuantityChangeBuffer], a
+ ld hl, NumItems
+ call ReceiveItem
+ ret nc
+ ld a, $1
+ ld [ScriptVar], a
+ ret
+; 12324
diff --git a/engine/events/misc_scripts_2.asm b/engine/events/misc_scripts_2.asm
new file mode 100644
index 000000000..c4c51d5e6
--- /dev/null
+++ b/engine/events/misc_scripts_2.asm
@@ -0,0 +1,51 @@
+RepelWoreOffScript:: ; 0x13619
+ opentext
+ writetext .text
+ waitbutton
+ closetext
+ end
+
+.text ; 0x13620
+ ; REPEL's effect wore off.
+ text_jump UnknownText_0x1bd308
+ db "@"
+
+HiddenItemScript:: ; 0x13625
+ opentext
+ copybytetovar EngineBuffer3
+ itemtotext 0, 0
+ writetext .found_text
+ giveitem ITEM_FROM_MEM
+ iffalse .bag_full
+ callasm SetMemEvent
+ specialsound
+ itemnotify
+ jump .finish
+
+.bag_full ; 0x1363e
+ buttonsound
+ writetext .no_room_text
+ waitbutton
+
+.finish ; 13643
+ closetext
+ end
+
+.found_text ; 0x13645
+ ; found @ !
+ text_jump UnknownText_0x1bd321
+ db "@"
+
+.no_room_text ; 0x1364a
+ ; But has no space left…
+ text_jump UnknownText_0x1bd331
+ db "@"
+
+SetMemEvent: ; 1364f
+ ld hl, EngineBuffer1
+ ld a, [hli]
+ ld d, [hl]
+ ld e, a
+ ld b, SET_FLAG
+ call EventFlagAction
+ ret
diff --git a/engine/events/mom.asm b/engine/events/mom.asm
new file mode 100644
index 000000000..6e3c7b320
--- /dev/null
+++ b/engine/events/mom.asm
@@ -0,0 +1,745 @@
+Special_BankOfMom: ; 16218
+ ld a, [hInMenu]
+ push af
+ ld a, $1
+ ld [hInMenu], a
+ xor a
+ ld [wJumptableIndex], a
+.loop
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .done
+ call .RunJumptable
+ jr .loop
+
+.done
+ pop af
+ ld [hInMenu], a
+ ret
+; 16233
+
+.RunJumptable: ; 16233
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, 0
+ ld hl, .dw
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+; 16242
+
+.dw ; 16242
+
+ dw .CheckIfBankInitialized
+ dw .InitializeBank
+ dw .IsThisAboutYourMoney
+ dw .AccessBankOfMom
+ dw .StoreMoney
+ dw .TakeMoney
+ dw .StopOrStartSavingMoney
+ dw .AskDST
+ dw .JustDoWhatYouCan
+; 16254
+
+.CheckIfBankInitialized: ; 16254
+ ld a, [wMomSavingMoney]
+ bit 7, a
+ jr nz, .savingmoneyalready
+ set 7, a
+ ld [wMomSavingMoney], a
+ ld a, $1
+ jr .done_0
+
+.savingmoneyalready
+ ld a, $2
+
+.done_0
+ ld [wJumptableIndex], a
+ ret
+; 1626a
+
+.InitializeBank: ; 1626a
+ ld hl, UnknownText_0x16649
+ call PrintText
+ call YesNoBox
+ jr c, .DontSaveMoney
+ ld hl, UnknownText_0x1664e
+ call PrintText
+ ld a, %10000001
+ jr .done_1
+
+.DontSaveMoney:
+ ld a, %10000000
+
+.done_1
+ ld [wMomSavingMoney], a
+ ld hl, UnknownText_0x16653
+ call PrintText
+ ld a, $8
+ ld [wJumptableIndex], a
+ ret
+; 16290
+
+.IsThisAboutYourMoney: ; 16290
+ ld hl, UnknownText_0x16658
+ call PrintText
+ call YesNoBox
+ jr c, .nope
+ ld a, $3
+ jr .done_2
+
+.nope
+ call DSTChecks
+ ld a, $7
+
+.done_2
+ ld [wJumptableIndex], a
+ ret
+; 162a8
+
+.AccessBankOfMom: ; 162a8
+ ld hl, UnknownText_0x1665d
+ call PrintText
+ call LoadStandardMenuDataHeader
+ ld hl, MenuDataHeader_0x166b5
+ call CopyMenuDataHeader
+ call VerticalMenu
+ call CloseWindow
+ jr c, .cancel
+ ld a, [wMenuCursorY]
+ cp $1
+ jr z, .withdraw
+ cp $2
+ jr z, .deposit
+ cp $3
+ jr z, .stopsaving
+
+.cancel
+ ld a, $7
+ jr .done_3
+
+.withdraw
+ ld a, $5
+ jr .done_3
+
+.deposit
+ ld a, $4
+ jr .done_3
+
+.stopsaving
+ ld a, $6
+
+.done_3
+ ld [wJumptableIndex], a
+ ret
+; 162e0
+
+.StoreMoney: ; 162e0
+ ld hl, UnknownText_0x16662
+ call PrintText
+ xor a
+ ld hl, StringBuffer2
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ ld a, $5
+ ld [wcf64], a
+ call LoadStandardMenuDataHeader
+ call Mom_SetUpDepositMenu
+ call Mom_Wait10Frames
+ call Mom_WithdrawDepositMenuJoypad
+ call CloseWindow
+ jr c, .CancelDeposit
+ ld hl, StringBuffer2
+ ld a, [hli]
+ or [hl]
+ inc hl
+ or [hl]
+ jr z, .CancelDeposit
+ ld de, Money
+ ld bc, StringBuffer2
+ farcall CompareMoney
+ jr c, .DontHaveThatMuchToDeposit
+ ld hl, StringBuffer2
+ ld de, StringBuffer2 + 3
+ ld bc, 3
+ call CopyBytes
+ ld bc, wMomsMoney
+ ld de, StringBuffer2
+ farcall GiveMoney
+ jr c, .CantDepositThatMuch
+ ld bc, StringBuffer2 + 3
+ ld de, Money
+ farcall TakeMoney
+ ld hl, StringBuffer2
+ ld de, wMomsMoney
+ ld bc, 3
+ call CopyBytes
+ ld de, SFX_TRANSACTION
+ call PlaySFX
+ call WaitSFX
+ ld hl, UnknownText_0x1668a
+ call PrintText
+ ld a, $8
+ jr .done_4
+
+.DontHaveThatMuchToDeposit:
+ ld hl, UnknownText_0x1667b
+ call PrintText
+ ret
+
+.CantDepositThatMuch:
+ ld hl, UnknownText_0x16680
+ call PrintText
+ ret
+
+.CancelDeposit:
+ ld a, $7
+
+.done_4
+ ld [wJumptableIndex], a
+ ret
+; 16373
+
+.TakeMoney: ; 16373
+ ld hl, UnknownText_0x16667
+ call PrintText
+ xor a
+ ld hl, StringBuffer2
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ ld a, $5
+ ld [wcf64], a
+ call LoadStandardMenuDataHeader
+ call Mom_SetUpWithdrawMenu
+ call Mom_Wait10Frames
+ call Mom_WithdrawDepositMenuJoypad
+ call CloseWindow
+ jr c, .CancelWithdraw
+ ld hl, StringBuffer2
+ ld a, [hli]
+ or [hl]
+ inc hl
+ or [hl]
+ jr z, .CancelWithdraw
+ ld hl, StringBuffer2
+ ld de, StringBuffer2 + 3
+ ld bc, 3
+ call CopyBytes
+ ld de, wMomsMoney
+ ld bc, StringBuffer2
+ farcall CompareMoney
+ jr c, .InsufficientFundsInBank
+ ld bc, Money
+ ld de, StringBuffer2
+ farcall GiveMoney
+ jr c, .NotEnoughRoomInWallet
+ ld bc, StringBuffer2 + 3
+ ld de, wMomsMoney
+ farcall TakeMoney
+ ld hl, StringBuffer2
+ ld de, Money
+ ld bc, 3
+ call CopyBytes
+ ld de, SFX_TRANSACTION
+ call PlaySFX
+ call WaitSFX
+ ld hl, UnknownText_0x1668f
+ call PrintText
+ ld a, $8
+ jr .done_5
+
+.InsufficientFundsInBank:
+ ld hl, UnknownText_0x16671
+ call PrintText
+ ret
+
+.NotEnoughRoomInWallet:
+ ld hl, UnknownText_0x16676
+ call PrintText
+ ret
+
+.CancelWithdraw:
+ ld a, $7
+
+.done_5
+ ld [wJumptableIndex], a
+ ret
+; 16406
+
+.StopOrStartSavingMoney: ; 16406
+ ld hl, UnknownText_0x1666c
+ call PrintText
+ call YesNoBox
+ jr c, .StopSavingMoney
+ ld a, $81
+ ld [wMomSavingMoney], a
+ ld hl, UnknownText_0x16685
+ call PrintText
+ ld a, $8
+ ld [wJumptableIndex], a
+ ret
+
+.StopSavingMoney:
+ ld a, $80
+ ld [wMomSavingMoney], a
+ ld a, $7
+ ld [wJumptableIndex], a
+ ret
+; 1642d
+
+.AskDST: ; 1642d
+ ld hl, UnknownText_0x16694
+ call PrintText
+
+.JustDoWhatYouCan: ; 16433
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+; 16439
+
+DSTChecks: ; 16439
+; check the time; avoid changing DST if doing so would change the current day
+ ld a, [wDST]
+ bit 7, a
+ ld a, [hHours]
+ jr z, .NotDST
+ and a ; within one hour of 00:00?
+ jr z, .LostBooklet
+ jr .loop
+
+.NotDST:
+ cp 23 ; within one hour of 23:00?
+ jr nz, .loop
+ ; fallthrough
+
+.LostBooklet:
+ call .ClearBox
+ bccoord 1, 14
+ ld hl, .Text_AdjustClock
+ call PlaceHLTextAtBC
+ call YesNoBox
+ ret c
+ call .ClearBox
+ bccoord 1, 14
+ ld hl, .Text_LostInstructionBooklet
+ call PlaceHLTextAtBC
+ ret
+
+.loop
+ call .ClearBox
+ bccoord 1, 14
+ ld a, [wDST]
+ bit 7, a
+ jr z, .SetDST
+ ld hl, .Text_IsDSTOver
+ call PlaceHLTextAtBC
+ call YesNoBox
+ ret c
+ ld a, [wDST]
+ res 7, a
+ ld [wDST], a
+ call .SetClockBack
+ call .ClearBox
+ bccoord 1, 14
+ ld hl, .Text_SetClockBack
+ call PlaceHLTextAtBC
+ ret
+
+.SetDST:
+ ld hl, .Text_SwitchToDST
+ call PlaceHLTextAtBC
+ call YesNoBox
+ ret c
+ ld a, [wDST]
+ set 7, a
+ ld [wDST], a
+ call .SetClockForward
+ call .ClearBox
+ bccoord 1, 14
+ ld hl, .Text_SetClockForward
+ call PlaceHLTextAtBC
+ ret
+; 164b9
+
+.SetClockForward: ; 164b9
+ ld a, [StartHour]
+ add 1
+ sub 24
+ jr nc, .DontLoopHourForward
+ add 24
+.DontLoopHourForward:
+ ld [StartHour], a
+ ccf
+ ld a, [StartDay]
+ adc 0
+ ld [StartDay], a
+ ret
+; 164d1
+
+.SetClockBack: ; 164d1
+ ld a, [StartHour]
+ sub 1
+ jr nc, .DontLoopHourBack
+ add 24
+.DontLoopHourBack:
+ ld [StartHour], a
+ ld a, [StartDay]
+ sbc 0
+ jr nc, .DontLoopDayBack
+ add 7
+.DontLoopDayBack:
+ ld [StartDay], a
+ ret
+; 164ea
+
+.ClearBox: ; 164ea
+ hlcoord 1, 14
+ lb bc, 3, 18
+ call ClearBox
+ ret
+; 164f4
+
+.Text_AdjustClock: ; 0x164f4
+ ; Do you want to adjust your clock for Daylight Saving Time?
+ text_jump UnknownText_0x1c6095
+ db "@"
+; 0x164f9
+
+.Text_LostInstructionBooklet: ; 0x164f9
+ ; I lost the instruction booklet for the POKéGEAR.
+ ; Come back again in a while.
+ text_jump UnknownText_0x1c60d1
+ db "@"
+; 0x164fe
+
+.Text_SwitchToDST: ; 0x164fe
+ ; Do you want to switch to Daylight Saving Time?
+ text_jump UnknownText_0x1c6000
+ db "@"
+; 0x16503
+
+.Text_SetClockForward: ; 0x16503
+ ; I set the clock forward by one hour.
+ text_jump UnknownText_0x1c6030
+ db "@"
+; 0x16508
+
+.Text_IsDSTOver: ; 0x16508
+ ; Is Daylight Saving Time over?
+ text_jump UnknownText_0x1c6056
+ db "@"
+; 0x1650d
+
+.Text_SetClockBack: ; 0x1650d
+ ; I put the clock back one hour.
+ text_jump UnknownText_0x1c6075
+ db "@"
+; 0x16512
+
+Mom_SetUpWithdrawMenu: ; 16512
+ ld de, Mon_WithdrawString
+ jr Mom_ContinueMenuSetup
+
+Mom_SetUpDepositMenu: ; 16517
+ ld de, Mom_DepositString
+Mom_ContinueMenuSetup: ; 1651a
+ push de
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 0, 0
+ lb bc, 6, 18
+ call TextBox
+ hlcoord 1, 2
+ ld de, Mom_SavedString
+ call PlaceString
+ hlcoord 12, 2
+ ld de, wMomsMoney
+ lb bc, PRINTNUM_MONEY | 3, 6
+ call PrintNum
+ hlcoord 1, 4
+ ld de, Mom_HeldString
+ call PlaceString
+ hlcoord 12, 4
+ ld de, Money
+ lb bc, PRINTNUM_MONEY | 3, 6
+ call PrintNum
+ hlcoord 1, 6
+ pop de
+ call PlaceString
+ hlcoord 12, 6
+ ld de, StringBuffer2
+ lb bc, PRINTNUM_MONEY | PRINTNUM_LEADINGZEROS | 3, 6
+ call PrintNum
+ call UpdateSprites
+ call CGBOnly_CopyTilemapAtOnce
+ ret
+; 1656b
+
+Mom_Wait10Frames: ; 1656b
+ ld c, 10
+ call DelayFrames
+ ret
+; 16571
+
+Mom_WithdrawDepositMenuJoypad: ; 16571
+.loop
+ call JoyTextDelay
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .pressedB
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .pressedA
+ call .dpadaction
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 12, 6
+ ld bc, 7
+ ld a, " "
+ call ByteFill
+ hlcoord 12, 6
+ ld de, StringBuffer2
+ lb bc, PRINTNUM_MONEY | PRINTNUM_LEADINGZEROS | 3, 6
+ call PrintNum
+ ld a, [hVBlankCounter]
+ and $10
+ jr nz, .skip
+ hlcoord 13, 6
+ ld a, [wMomBankDigitCursorPosition]
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld [hl], " "
+
+.skip
+ call WaitBGMap
+ jr .loop
+
+.pressedB
+ scf
+ ret
+
+.pressedA
+ and a
+ ret
+
+.dpadaction
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .incrementdigit
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .decrementdigit
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .movecursorleft
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .movecursorright
+ and a
+ ret
+
+.movecursorleft
+ ld hl, wMomBankDigitCursorPosition
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ ret
+
+.movecursorright
+ ld hl, wMomBankDigitCursorPosition
+ ld a, [hl]
+ cp 5
+ ret nc
+ inc [hl]
+ ret
+
+.incrementdigit
+ ld hl, .DigitQuantities
+ call .getdigitquantity
+ ld c, l
+ ld b, h
+ ld de, StringBuffer2
+ farcall GiveMoney
+ ret
+
+.decrementdigit
+ ld hl, .DigitQuantities
+ call .getdigitquantity
+ ld c, l
+ ld b, h
+ ld de, StringBuffer2
+ farcall TakeMoney
+ ret
+
+.getdigitquantity
+ ld a, [wMomBankDigitCursorPosition]
+ push de
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ add hl, de
+ pop de
+ ret
+; 16613
+
+.DigitQuantities: ; 16613
+ dt 100000
+ dt 10000
+ dt 1000
+ dt 100
+ dt 10
+ dt 1
+
+ dt 100000
+ dt 10000
+ dt 1000
+ dt 100
+ dt 10
+ dt 1
+
+ dt 900000
+ dt 90000
+ dt 9000
+ dt 900
+ dt 90
+ dt 9
+; 16649
+
+UnknownText_0x16649: ; 0x16649
+ ; Wow, that's a cute #MON. Where did you get it? … So, you're leaving on an adventure… OK! I'll help too. But what can I do for you? I know! I'll save money for you. On a long journey, money's important. Do you want me to save your money?
+ text_jump UnknownText_0x1bd77f
+ db "@"
+; 0x1664e
+
+UnknownText_0x1664e: ; 0x1664e
+ ; OK, I'll take care of your money.
+ text_jump UnknownText_0x1bd868
+ db "@"
+; 0x16653
+
+UnknownText_0x16653: ; 0x16653
+ ; Be careful. #MON are your friends. You need to work as a team. Now, go on!
+ text_jump UnknownText_0x1bd88e
+ db "@"
+; 0x16658
+
+UnknownText_0x16658: ; 0x16658
+ ; Hi! Welcome home! You're trying very hard, I see. I've kept your room tidy. Or is this about your money?
+ text_jump UnknownText_0x1bd8da
+ db "@"
+; 0x1665d
+
+UnknownText_0x1665d: ; 0x1665d
+ ; What do you want to do?
+ text_jump UnknownText_0x1bd942
+ db "@"
+; 0x16662
+
+UnknownText_0x16662: ; 0x16662
+ ; How much do you want to save?
+ text_jump UnknownText_0x1bd95b
+ db "@"
+; 0x16667
+
+UnknownText_0x16667: ; 0x16667
+ ; How much do you want to take?
+ text_jump UnknownText_0x1bd97a
+ db "@"
+; 0x1666c
+
+UnknownText_0x1666c: ; 0x1666c
+ ; Do you want to save some money?
+ text_jump UnknownText_0x1bd999
+ db "@"
+; 0x16671
+
+UnknownText_0x16671: ; 0x16671
+ ; You haven't saved that much.
+ text_jump UnknownText_0x1bd9ba
+ db "@"
+; 0x16676
+
+UnknownText_0x16676: ; 0x16676
+ ; You can't take that much.
+ text_jump UnknownText_0x1bd9d7
+ db "@"
+; 0x1667b
+
+UnknownText_0x1667b: ; 0x1667b
+ ; You don't have that much.
+ text_jump UnknownText_0x1bd9f1
+ db "@"
+; 0x16680
+
+UnknownText_0x16680: ; 0x16680
+ ; You can't save that much.
+ text_jump UnknownText_0x1bda0b
+ db "@"
+; 0x16685
+
+UnknownText_0x16685: ; 0x16685
+ ; OK, I'll save your money. Trust me! , stick with it!
+ text_jump UnknownText_0x1bda25
+ db "@"
+; 0x1668a
+
+UnknownText_0x1668a: ; 0x1668a
+ ; Your money's safe here! Get going!
+ text_jump UnknownText_0x1bda5b
+ db "@"
+; 0x1668f
+
+UnknownText_0x1668f: ; 0x1668f
+ ; , don't give up!
+ text_jump UnknownText_0x1bda7e
+ db "@"
+; 0x16694
+
+UnknownText_0x16694: ; 0x16694
+ ; Just do what you can.
+ text_jump UnknownText_0x1bda90
+ db "@"
+; 0x16699
+
+Mom_SavedString: ; 16699
+ db "SAVED@"
+; 1669f
+
+Mon_WithdrawString: ; 1669f
+ db "WITHDRAW@"
+; 166a8
+
+Mom_DepositString: ; 166a8
+ db "DEPOSIT@"
+; 166b0
+
+Mom_HeldString: ; 166b0
+ db "HELD@"
+; 166b5
+
+MenuDataHeader_0x166b5: ; 0x166b5
+ db $40 ; flags
+ db 00, 00 ; start coords
+ db 10, 10 ; end coords
+ dw MenuData2_0x166bd
+ db 1 ; default option
+; 0x166bd
+
+MenuData2_0x166bd: ; 0x166bd
+ db $80 ; flags
+ db 4 ; items
+ db "GET@"
+ db "SAVE@"
+ db "CHANGE@"
+ db "CANCEL@"
+; 0x166d6
diff --git a/engine/events/mom_phone.asm b/engine/events/mom_phone.asm
new file mode 100755
index 000000000..bef7d5688
--- /dev/null
+++ b/engine/events/mom_phone.asm
@@ -0,0 +1,264 @@
+NUM_MOM_ITEMS_1 EQUS "((MomItems_1End - MomItems_1) / 8)"
+NUM_MOM_ITEMS_2 EQUS "((MomItems_2End - MomItems_2) / 8)"
+
+const_value = 1
+ const MOM_ITEM
+ const MOM_DOLL
+
+MomTriesToBuySomething:: ; fcfec
+ ld a, [wMapReentryScriptQueueFlag]
+ and a
+ ret nz
+ call GetMapHeaderPhoneServiceNybble
+ and a
+ ret nz
+ xor a
+ ld [wWhichMomItemSet], a
+ call CheckBalance_MomItem2
+ ret nc
+ call Mom_GiveItemOrDoll
+ ret nc
+ ld b, BANK(.Script)
+ ld de, .Script
+ farcall LoadScriptBDE
+ scf
+ ret
+; fd00f
+
+.Script: ; 0xfd00f
+ callasm .ASMFunction
+ farjump Script_ReceivePhoneCall
+; 0xfd017
+
+.ASMFunction: ; fd017
+ call MomBuysItem_DeductFunds
+ call Mom_GetScriptPointer
+ ld a, [wWhichMomItemSet]
+ and a
+ jr nz, .ok
+ ld hl, wWhichMomItem
+ inc [hl]
+.ok
+ ld a, PHONE_MOM
+ ld [wCurrentCaller], a
+ ld bc, EngineBuffer2
+ ld hl, 0
+ add hl, bc
+ ld [hl], 0
+ inc hl
+ ld [hl], 1
+ ld hl, wPhoneScriptPointer - EngineBuffer2
+ add hl, bc
+ ld a, BANK(Mom_GetScriptPointer)
+ ld [hli], a
+ ld a, e
+ ld [hli], a
+ ld a, d
+ ld [hl], a
+ ret
+; fd044
+
+CheckBalance_MomItem2: ; fd044
+ ld a, [wWhichMomItem]
+ cp NUM_MOM_ITEMS_2
+ jr nc, .nope
+ call GetItemFromMom
+ ld a, [hli]
+ ld [hMoneyTemp], a
+ ld a, [hli]
+ ld [hMoneyTemp + 1], a
+ ld a, [hli]
+ ld [hMoneyTemp + 2], a
+ ld de, wMomsMoney
+ ld bc, hMoneyTemp
+ farcall CompareMoney
+ jr nc, .have_enough_money
+
+.nope
+ jr .check_have_2300
+
+.have_enough_money
+ scf
+ ret
+
+.check_have_2300
+ ld hl, hMoneyTemp
+ ld [hl], HIGH(MOM_MONEY >> 8)
+ inc hl
+ ld [hl], HIGH(MOM_MONEY) ; mid
+ inc hl
+ ld [hl], LOW(MOM_MONEY)
+.loop
+ ld de, MomItemTriggerBalance
+ ld bc, wMomsMoney
+ farcall CompareMoney
+ jr z, .exact
+ jr nc, .less_than
+ call .AddMoney
+ jr .loop
+
+.less_than
+ xor a
+ ret
+
+.exact
+ call .AddMoney
+ ld a, NUM_MOM_ITEMS_1
+ call RandomRange
+ inc a
+ ld [wWhichMomItemSet], a
+ scf
+ ret
+
+.AddMoney:
+ ld de, MomItemTriggerBalance
+ ld bc, hMoneyTemp
+ farcall AddMoney
+ ret
+; fd0a6
+
+
+MomBuysItem_DeductFunds: ; fd0a6 (3f:50a6)
+ call GetItemFromMom
+ ld de, 3 ; cost
+ add hl, de
+ ld a, [hli]
+ ld [hMoneyTemp], a
+ ld a, [hli]
+ ld [hMoneyTemp + 1], a
+ ld a, [hli]
+ ld [hMoneyTemp + 2], a
+ ld de, wMomsMoney
+ ld bc, hMoneyTemp
+ farcall TakeMoney
+ ret
+
+
+Mom_GiveItemOrDoll: ; fd0c3
+ call GetItemFromMom
+ ld de, 6 ; item type
+ add hl, de
+ ld a, [hli]
+ cp MOM_ITEM
+ jr z, .not_doll
+ ld a, [hl]
+ ld c, a
+ ld b, 1
+ farcall DecorationFlagAction_c
+ scf
+ ret
+
+.not_doll
+ ld a, [hl]
+ ld [CurItem], a
+ ld a, 1
+ ld [wItemQuantityChangeBuffer], a
+ ld hl, PCItems
+ call ReceiveItem
+ ret
+; fd0eb
+
+
+Mom_GetScriptPointer: ; fd0eb (3f:50eb)
+ call GetItemFromMom
+ ld de, 6 ; item type
+ add hl, de
+ ld a, [hli]
+ ld de, .ItemScript
+ cp MOM_ITEM
+ ret z
+ ld de, .DollScript
+ ret
+; fd0fd (3f:50fd)
+
+.ItemScript: ; 0xfd0fd
+ writetext _MomText_HiHowAreYou
+ writetext _MomText_FoundAnItem
+ writetext _MomText_BoughtWithYourMoney
+ writetext _MomText_ItsInPC
+ end
+; 0xfd10a
+
+.DollScript: ; 0xfd10a
+ writetext _MomText_HiHowAreYou
+ writetext _MomText_FoundADoll
+ writetext _MomText_BoughtWithYourMoney
+ writetext _MomText_ItsInRoom
+ end
+; 0xfd117
+
+
+GetItemFromMom: ; fd117
+ ld a, [wWhichMomItemSet]
+ and a
+ jr z, .zero
+ dec a
+ ld de, MomItems_1
+ jr .GetFromList1
+
+.zero
+ ld a, [wWhichMomItem]
+ cp NUM_MOM_ITEMS_2
+ jr c, .ok
+ xor a
+
+.ok
+ ld de, MomItems_2
+
+.GetFromList1:
+ ld l, a
+ ld h, 0
+rept 3 ; multiply hl by 8
+ add hl, hl
+endr
+ add hl, de
+ ret
+; fd136
+
+INCLUDE "data/items/mom_phone.asm"
+
+ db 0, 0, 0 ; XXX
+
+_MomText_HiHowAreYou: ; 0xfd1b1
+ ; Hi, ! How are you?
+ text_jump UnknownText_0x1bc615
+ db "@"
+; 0xfd1b6
+
+_MomText_FoundAnItem: ; 0xfd1b6
+ ; I found a useful item shopping, so
+ text_jump UnknownText_0x1bc62a
+ db "@"
+; 0xfd1bb
+
+_MomText_BoughtWithYourMoney: ; 0xfd1bb
+ ; I bought it with your money. Sorry!
+ text_jump UnknownText_0x1bc64e
+ db "@"
+; 0xfd1c0
+
+_MomText_ItsInPC: ; 0xfd1c0
+ ; It's in your PC. You'll like it!
+ text_jump UnknownText_0x1bc673
+ db "@"
+; 0xfd1c5
+
+_MomText_FoundADoll: ; 0xfd1c5
+ ; While shopping today, I saw this adorable doll, so
+ text_jump UnknownText_0x1bc693
+ db "@"
+; 0xfd1ca
+
+_MomText_ItsInRoom: ; 0xfd1ca
+ ; It's in your room. You'll love it!
+ text_jump UnknownText_0x1bc6c7
+ db "@"
+; 0xfd1cf
+
+ db 0 ; XXX
+
+Predef3A: ; fd1d0
+ ret
+; fd1d1
+
+ ret ; XXX
diff --git a/engine/events/move_deleter.asm b/engine/events/move_deleter.asm
new file mode 100644
index 000000000..95fc0f1d8
--- /dev/null
+++ b/engine/events/move_deleter.asm
@@ -0,0 +1,166 @@
+MoveDeletion:
+ ld hl, .IntroText
+ call PrintText
+ call YesNoBox
+ jr c, .declined
+ ld hl, .AskWhichMonText
+ call PrintText
+ farcall SelectMonFromParty
+ jr c, .declined
+ ld a, [CurPartySpecies]
+ cp EGG
+ jr z, .egg
+ ld a, [CurPartyMon]
+ ld hl, PartyMon1Moves + 1
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ ld a, [hl]
+ and a
+ jr z, .onlyonemove
+ ld hl, .AskWhichMoveText
+ call PrintText
+ call LoadStandardMenuDataHeader
+ farcall ChooseMoveToDelete
+ push af
+ call ReturnToMapWithSpeechTextbox
+ pop af
+ jr c, .declined
+ ld a, [wMenuCursorY]
+ push af
+ ld a, [CurSpecies]
+ ld [wd265], a
+ call GetMoveName
+ ld hl, .ConfirmDeleteText
+ call PrintText
+ call YesNoBox
+ pop bc
+ jr c, .declined
+ call .DeleteMove
+ call WaitSFX
+ ld de, SFX_MOVE_DELETED
+ call PlaySFX
+ call WaitSFX
+ ld hl, .MoveDeletedText
+ call PrintText
+ ret
+
+.egg
+ ld hl, .EggText
+ call PrintText
+ ret
+
+.declined
+ ld hl, .DeclinedDeletionText
+ call PrintText
+ ret
+
+.onlyonemove
+ ld hl, .OnlyOneMoveText
+ call PrintText
+ ret
+
+.OnlyOneMoveText: ; 0x2c5d1
+ ; That #MON knows only one move.
+ text_jump UnknownText_0x1c5eba
+ db "@"
+; 0x2c5d6
+
+.ConfirmDeleteText: ; 0x2c5d6
+ ; Oh, make it forget @ ?
+ text_jump UnknownText_0x1c5eda
+ db "@"
+; 0x2c5db
+
+.MoveDeletedText: ; 0x2c5db
+ ; Done! Your #MON forgot the move.
+ text_jump UnknownText_0x1c5ef5
+ db "@"
+; 0x2c5e0
+
+.EggText: ; 0x2c5e0
+ ; An EGG doesn't know any moves!
+ text_jump UnknownText_0x1c5f17
+ db "@"
+; 0x2c5e5
+
+.DeclinedDeletionText: ; 0x2c5e5
+ ; No? Come visit me again.
+ text_jump UnknownText_0x1c5f36
+ db "@"
+; 0x2c5ea
+
+.AskWhichMoveText: ; 0x2c5ea
+ ; Which move should it forget, then?
+ text_jump UnknownText_0x1c5f50
+ db "@"
+; 0x2c5ef
+
+.IntroText: ; 0x2c5ef
+ ; Um… Oh, yes, I'm the MOVE DELETER. I can make #MON forget moves. Shall I make a #MON forget?
+ text_jump UnknownText_0x1c5f74
+ db "@"
+; 0x2c5f4
+
+.AskWhichMonText: ; 0x2c5f4
+ ; Which #MON?
+ text_jump UnknownText_0x1c5fd1
+ db "@"
+; 0x2c5f9
+
+.DeleteMove: ; 2c5f9
+ ld a, b
+ push bc
+ dec a
+ ld c, a
+ ld b, 0
+ ld hl, PartyMon1Moves
+ add hl, bc
+ ld a, [CurPartyMon]
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ pop bc
+ push bc
+ inc b
+.loop
+ ld a, b
+ cp NUM_MOVES + 1
+ jr z, .okay
+ inc hl
+ ld a, [hld]
+ ld [hl], a
+ inc hl
+ inc b
+ jr .loop
+
+.okay
+ xor a
+ ld [hl], a
+ pop bc
+
+ ld a, b
+ push bc
+ dec a
+ ld c, a
+ ld b, 0
+ ld hl, PartyMon1PP
+ add hl, bc
+ ld a, [CurPartyMon]
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ pop bc
+ inc b
+.loop2
+ ld a, b
+ cp NUM_MOVES + 1
+ jr z, .done
+ inc hl
+ ld a, [hld]
+ ld [hl], a
+ inc hl
+ inc b
+ jr .loop2
+
+.done
+ xor a
+ ld [hl], a
+ ret
diff --git a/engine/events/move_tutor.asm b/engine/events/move_tutor.asm
new file mode 100644
index 000000000..a15ecaf93
--- /dev/null
+++ b/engine/events/move_tutor.asm
@@ -0,0 +1,103 @@
+Special_MoveTutor: ; 4925b
+ call FadeToMenu
+ call ClearBGPalettes
+ call ClearScreen
+ call DelayFrame
+ ld b, SCGB_PACKPALS
+ call GetSGBLayout
+ xor a
+ ld [wItemAttributeParamBuffer], a
+ call .GetMoveTutorMove
+ ld [wd265], a
+ ld [wPutativeTMHMMove], a
+ call GetMoveName
+ call CopyName1
+ farcall ChooseMonToLearnTMHM
+ jr c, .cancel
+ jr .enter_loop
+
+.loop
+ farcall ChooseMonToLearnTMHM_NoRefresh
+ jr c, .cancel
+.enter_loop
+ call CheckCanLearnMoveTutorMove
+ jr nc, .loop
+ xor a
+ ld [ScriptVar], a
+ jr .quit
+
+.cancel
+ ld a, -1
+ ld [ScriptVar], a
+.quit
+ call CloseSubmenu
+ ret
+
+.GetMoveTutorMove: ; 492a5
+ ld a, [ScriptVar]
+ cp 1
+ jr z, .flamethrower
+ cp 2
+ jr z, .thunderbolt
+ ld a, ICE_BEAM
+ ret
+
+.flamethrower
+ ld a, FLAMETHROWER
+ ret
+
+.thunderbolt
+ ld a, THUNDERBOLT
+ ret
+
+CheckCanLearnMoveTutorMove: ; 492b9
+ ld hl, .MenuDataHeader
+ call LoadMenuDataHeader
+
+ predef CanLearnTMHMMove
+
+ push bc
+ ld a, [CurPartyMon]
+ ld hl, PartyMonNicknames
+ call GetNick
+ pop bc
+
+ ld a, c
+ and a
+ jr nz, .can_learn
+ push de
+ ld de, SFX_WRONG
+ call PlaySFX
+ pop de
+ ld a, BANK(Text_TMHMNotCompatible)
+ ld hl, Text_TMHMNotCompatible
+ call FarPrintText
+ jr .didnt_learn
+
+.can_learn
+ callfar KnowsMove
+ jr c, .didnt_learn
+
+ predef LearnMove
+ ld a, b
+ and a
+ jr z, .didnt_learn
+
+ ld c, HAPPINESS_LEARNMOVE
+ callfar ChangeHappiness
+ jr .learned
+
+.didnt_learn
+ call ExitMenu
+ and a
+ ret
+
+.learned
+ call ExitMenu
+ scf
+ ret
+
+.MenuDataHeader: ; 0x4930a
+ db $40 ; flags
+ db 12, 00 ; start coords
+ db 17, 19 ; end coords
diff --git a/engine/events/name_rater.asm b/engine/events/name_rater.asm
new file mode 100644
index 000000000..771c5090a
--- /dev/null
+++ b/engine/events/name_rater.asm
@@ -0,0 +1,250 @@
+NameRater: ; fb6ed
+; Introduce himself
+ ld hl, NameRaterIntroText
+ call PrintText
+ call YesNoBox
+ jp c, .cancel
+; Select a Pokemon from your party
+ ld hl, NameRaterWhichMonText
+ call PrintText
+ farcall SelectMonFromParty
+ jr c, .cancel
+; He can't rename an egg...
+ ld a, [CurPartySpecies]
+ cp EGG
+ jr z, .egg
+; ... or a Pokemon you got from a trade.
+ call GetCurNick
+ call CheckIfMonIsYourOT
+ jr c, .traded
+; This name is good, but we can do better. How about it?
+ ld hl, NameRaterIsGoodText
+ call PrintText
+ call YesNoBox
+ jr c, .cancel
+; What name shall I give it then?
+ ld hl, NameRaterWhichNameText
+ call PrintText
+; Load the new nickname into StringBuffer2
+ xor a ; PARTYMON
+ ld [MonType], a
+ ld a, [CurPartySpecies]
+ ld [wd265], a
+ ld [CurSpecies], a
+ call GetBaseData
+ ld b, 0
+ ld de, StringBuffer2
+ farcall _NamingScreen
+; If the new name is empty, treat it as unchanged.
+ call IsNewNameEmpty
+ ld hl, NameRaterSameAsBeforeText
+ jr c, .samename
+; If the new name is the same as the old name, treat it as unchanged.
+ call CompareNewToOld
+ ld hl, NameRaterSameAsBeforeText
+ jr c, .samename
+; Copy the new name from StringBuffer2
+ ld hl, PartyMonNicknames
+ ld bc, PKMN_NAME_LENGTH
+ ld a, [CurPartyMon]
+ call AddNTimes
+ ld e, l
+ ld d, h
+ ld hl, StringBuffer2
+ ld bc, PKMN_NAME_LENGTH
+ call CopyBytes
+ ld hl, NameRaterEvenBetterText
+
+.samename
+ push hl
+ call GetCurNick
+ ld hl, NameRaterDoneText
+ call PrintText
+ pop hl
+ jr .done
+
+.traded
+ ld hl, NameRaterTradedText
+ jr .done
+
+.cancel
+ ld hl, NameRaterCancelText
+ jr .done
+
+.egg
+ ld hl, NameRaterEggText
+
+.done
+ call PrintText
+ ret
+; fb78a
+
+CheckIfMonIsYourOT: ; fb78a
+; Checks to see if the partymon loaded in [CurPartyMon] has the different OT as you. Returns carry if not.
+ ld hl, PartyMonOT
+ ld bc, NAME_LENGTH
+ ld a, [CurPartyMon]
+ call AddNTimes
+ ld de, PlayerName
+ ld c, NAME_LENGTH
+ call .loop
+ jr c, .nope
+
+ ld hl, PartyMon1ID
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, [CurPartyMon]
+ call AddNTimes
+ ld de, PlayerID
+ ld c, 2 ; number of bytes in which your ID is stored
+.loop
+ ld a, [de]
+ cp [hl]
+ jr nz, .nope
+ inc hl
+ inc de
+ dec c
+ jr nz, .loop
+ and a
+ ret
+
+.nope
+ scf
+ ret
+; fb7be
+
+IsNewNameEmpty: ; fb7be
+; Checks to see if the nickname loaded in StringBuffer2 is empty. If so, return carry.
+ ld hl, StringBuffer2
+ ld c, PKMN_NAME_LENGTH - 1
+.loop
+ ld a, [hli]
+ cp "@"
+ jr z, .terminator
+ cp " "
+ jr nz, .nonspace
+ dec c
+ jr nz, .loop
+
+.terminator
+ scf
+ ret
+
+.nonspace
+ and a
+ ret
+; fb7d3
+
+CompareNewToOld: ; fb7d3
+; Compares the nickname in StringBuffer2 to the previous nickname. If they are the same, return carry.
+ ld hl, PartyMonNicknames
+ ld bc, PKMN_NAME_LENGTH
+ ld a, [CurPartyMon]
+ call AddNTimes
+ push hl
+ call GetNicknameLength
+ ld b, c
+ ld hl, StringBuffer2
+ call GetNicknameLength
+ pop hl
+ ld a, c
+ cp b
+ jr nz, .different
+ ld de, StringBuffer2
+.loop
+ ld a, [de]
+ cp "@"
+ jr z, .terminator
+ cp [hl]
+ jr nz, .different
+ inc hl
+ inc de
+ jr .loop
+
+.different
+ and a
+ ret
+
+.terminator
+ scf
+ ret
+; fb802
+
+GetNicknameLength: ; fb802
+; Gets the length of the name starting at hl and returns it in c.
+ ld c, 0
+.loop
+ ld a, [hli]
+ cp "@"
+ ret z
+ inc c
+ ld a, c
+ cp PKMN_NAME_LENGTH - 1
+ jr nz, .loop
+ ret
+; fb80f
+
+NameRaterIntroText: ; 0xfb80f
+ ; Hello, hello! I'm the NAME RATER.
+ ; I rate the names of #MON.
+ ; Would you like me to rate names?
+ text_jump UnknownText_0x1c0043
+ db "@"
+; 0xfb814
+
+NameRaterWhichMonText: ; 0xfb814
+ ; Which #MON's nickname should I rate for you?
+ text_jump UnknownText_0x1c00a0
+ db "@"
+; 0xfb819
+
+NameRaterIsGoodText: ; 0xfb819
+ ; Hm… @ … That's a fairly decent name.
+ ; But, how about a slightly better nickname?
+ ; Want me to give it a better name?
+ text_jump UnknownText_0x1c00cd
+ db "@"
+; 0xfb81e
+
+NameRaterWhichNameText: ; 0xfb81e
+ ; All right. What name should we give it, then?
+ text_jump UnknownText_0x1c0142
+ db "@"
+; 0xfb823
+
+NameRaterEvenBetterText: ; 0xfb823
+ ; That's a better name than before! Well done!
+ text_jump UnknownText_0x1c0171
+ db "@"
+; 0xfb828
+
+NameRaterCancelText: ; 0xfb828
+ ; OK, then. Come again sometime.
+ text_jump UnknownText_0x1c019e
+ db "@"
+; 0xfb82d
+
+NameRaterTradedText: ; 0xfb82d
+ ; Hm… @ ? What a great name! It's perfect.
+ ; Treat @ with loving care.
+ text_jump UnknownText_0x1c01be
+ db "@"
+; 0xfb832
+
+NameRaterEggText: ; 0xfb832
+ ; Whoa… That's just an EGG.
+ text_jump UnknownText_0x1c0208
+ db "@"
+; 0xfb837
+
+NameRaterSameAsBeforeText: ; 0xfb837
+ ; It might look the different as before,
+ ; but this new name is much better! Well done!
+ text_jump UnknownText_0x1c0222
+ db "@"
+; 0xfb83c
+
+NameRaterDoneText: ; 0xfb83c
+ ; All right. This #MON is now named @ .
+ text_jump UnknownText_0x1c0272
+ db "@"
+; 0xfb841
diff --git a/engine/events/odd_egg.asm b/engine/events/odd_egg.asm
new file mode 100644
index 000000000..4cbeb34dc
--- /dev/null
+++ b/engine/events/odd_egg.asm
@@ -0,0 +1,96 @@
+GiveOddEgg: ; 1fb4b6
+ ; Figure out which egg to give.
+
+ ; Compare a random word to
+ ; probabilities out of 0xffff.
+ call Random
+ ld hl, OddEggProbabilities
+ ld c, 0
+ ld b, c
+.loop
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+
+ ; Break on $ffff.
+ ld a, d
+ cp HIGH($ffff)
+ jr nz, .not_done
+ ld a, e
+ cp LOW($ffff)
+ jr z, .done
+.not_done
+
+ ; Break when [hRandom] <= de.
+ ld a, [hRandom + 1]
+ cp d
+ jr c, .done
+ jr z, .ok
+ jr .next
+.ok
+ ld a, [hRandom + 0]
+ cp e
+ jr c, .done
+ jr z, .done
+.next
+ inc bc
+ jr .loop
+.done
+
+ ld hl, OddEggs
+ ld a, OddEgg2 - OddEgg1
+ call AddNTimes
+
+ ld de, OddEggSpecies
+ ld bc, PARTYMON_STRUCT_LENGTH + 2 * PKMN_NAME_LENGTH
+ call CopyBytes
+
+ ld a, EGG_TICKET
+ ld [CurItem], a
+ ld a, 1
+ ld [wItemQuantityChangeBuffer], a
+ ld a, -1
+ ld [CurItemQuantity], a
+ ld hl, NumItems
+ call TossItem
+
+ ; load species in wcd2a
+ ld a, EGG
+ ld [wMobileMonSpeciesBuffer], a
+
+ ; load pointer to (wMobileMonSpeciesBuffer - 1) in wMobileMonSpeciesPointerBuffer
+ ld a, LOW(wMobileMonSpeciesBuffer - 1)
+ ld [wMobileMonSpeciesPointerBuffer], a
+ ld a, HIGH(wMobileMonSpeciesBuffer - 1)
+ ld [wMobileMonSpeciesPointerBuffer + 1], a
+ ; load pointer to OddEggSpecies in wMobileMonStructurePointerBuffer
+ ld a, LOW(OddEggSpecies)
+ ld [wMobileMonStructurePointerBuffer], a
+ ld a, HIGH(OddEggSpecies)
+ ld [wMobileMonStructurePointerBuffer + 1], a
+
+ ; load Odd Egg Name in wTempOddEggNickname
+ ld hl, .Odd
+ ld de, wTempOddEggNickname
+ ld bc, PKMN_NAME_LENGTH
+ call CopyBytes
+
+ ; load pointer to wTempOddEggNickname in wMobileMonOTNamePointerBuffer
+ ld a, LOW(wTempOddEggNickname)
+ ld [wMobileMonOTNamePointerBuffer], a
+ ld a, HIGH(wTempOddEggNickname)
+ ld [wMobileMonOTNamePointerBuffer + 1], a
+ ; load pointer to wOddEggName in wMobileMonNicknamePointerBuffer
+ ld a, LOW(wOddEggName)
+ ld [wMobileMonNicknamePointerBuffer], a
+ ld a, HIGH(wOddEggName)
+ ld [wMobileMonNicknamePointerBuffer + 1], a
+ farcall AddMobileMonToParty
+ ret
+; 1fb546
+
+.Odd:
+ db "ODD@@@@@@@@@"
+
+INCLUDE "data/odd_eggs.asm"
diff --git a/engine/events/overworld.asm b/engine/events/overworld.asm
new file mode 100755
index 000000000..370162fa9
--- /dev/null
+++ b/engine/events/overworld.asm
@@ -0,0 +1,1846 @@
+FieldMoveJumptableReset: ; c6ea
+ xor a
+ ld hl, Buffer1
+ ld bc, 7
+ call ByteFill
+ ret
+
+FieldMoveJumptable: ; c6f5
+ ld a, [Buffer1]
+ rst JumpTable
+ ld [Buffer1], a
+ bit 7, a
+ jr nz, .okay
+ and a
+ ret
+
+.okay
+ and $7f
+ scf
+ ret
+
+GetPartyNick: ; c706
+; write CurPartyMon nickname to StringBuffer1-3
+ ld hl, PartyMonNicknames
+ ld a, BOXMON
+ ld [MonType], a
+ ld a, [CurPartyMon]
+ call GetNick
+ call CopyName1
+; copy text from StringBuffer2 to StringBuffer3
+ ld de, StringBuffer2
+ ld hl, StringBuffer3
+ call CopyName2
+ ret
+
+CheckEngineFlag: ; c721
+; Check engine flag de
+; Return carry if flag is not set
+ ld b, CHECK_FLAG
+ farcall EngineFlagAction
+ ld a, c
+ and a
+ jr nz, .isset
+ scf
+ ret
+.isset
+ xor a
+ ret
+
+CheckBadge: ; c731
+; Check engine flag a (ENGINE_ZEPHYRBADGE thru ENGINE_EARTHBADGE)
+; Display "Badge required" text and return carry if the badge is not owned
+ call CheckEngineFlag
+ ret nc
+ ld hl, .BadgeRequiredText
+ call MenuTextBoxBackup ; push text to queue
+ scf
+ ret
+
+.BadgeRequiredText: ; c73d
+ ; Sorry! A new BADGE
+ ; is required.
+ text_jump _BadgeRequiredText
+ db "@"
+
+CheckPartyMove: ; c742
+; Check if a monster in your party has move d.
+
+ ld e, 0
+ xor a
+ ld [CurPartyMon], a
+.loop
+ ld c, e
+ ld b, 0
+ ld hl, PartySpecies
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .no
+ cp -1
+ jr z, .no
+ cp EGG
+ jr z, .next
+
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld hl, PartyMon1Moves
+ ld a, e
+ call AddNTimes
+ ld b, NUM_MOVES
+.check
+ ld a, [hli]
+ cp d
+ jr z, .yes
+ dec b
+ jr nz, .check
+
+.next
+ inc e
+ jr .loop
+
+.yes
+ ld a, e
+ ld [CurPartyMon], a ; which mon has the move
+ xor a
+ ret
+.no
+ scf
+ ret
+
+FieldMoveFailed: ; c779
+ ld hl, .CantUseHere
+ call MenuTextBoxBackup
+ ret
+
+.CantUseHere: ; 0xc780
+ ; Can't use that here.
+ text_jump UnknownText_0x1c05c8
+ db "@"
+
+CutFunction: ; c785
+ call FieldMoveJumptableReset
+.loop
+ ld hl, .Jumptable
+ call FieldMoveJumptable
+ jr nc, .loop
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.Jumptable: ; c796 (3:4796)
+
+ dw .CheckAble
+ dw .DoCut
+ dw .FailCut
+
+.CheckAble: ; c79c (3:479c)
+ ld de, ENGINE_HIVEBADGE
+ call CheckBadge
+ jr c, .nohivebadge
+ call CheckMapForSomethingToCut
+ jr c, .nothingtocut
+ ld a, $1
+ ret
+
+.nohivebadge
+ ld a, $80
+ ret
+
+.nothingtocut
+ ld a, $2
+ ret
+
+.DoCut: ; c7b2 (3:47b2)
+ ld hl, Script_CutFromMenu
+ call QueueScript
+ ld a, $81
+ ret
+
+.FailCut: ; c7bb (3:47bb)
+ ld hl, Text_NothingToCut
+ call MenuTextBoxBackup
+ ld a, $80
+ ret
+
+Text_UsedCut: ; 0xc7c4
+ ; used CUT!
+ text_jump UnknownText_0x1c05dd
+ db "@"
+
+Text_NothingToCut: ; 0xc7c9
+ ; There's nothing to CUT here.
+ text_jump UnknownText_0x1c05ec
+ db "@"
+
+CheckMapForSomethingToCut: ; c7ce
+ ; Does the collision data of the facing tile permit cutting?
+ call GetFacingTileCoord
+ ld c, a
+ push de
+ farcall CheckCutCollision
+ pop de
+ jr nc, .fail
+ ; Get the location of the current block in OverworldMap.
+ call GetBlockLocation
+ ld c, [hl]
+ ; See if that block contains something that can be cut.
+ push hl
+ ld hl, CutTreeBlockPointers
+ call CheckOverworldTileArrays
+ pop hl
+ jr nc, .fail
+ ; Back up the OverworldMap address to Buffer3
+ ld a, l
+ ld [Buffer3], a
+ ld a, h
+ ld [Buffer4], a
+ ; Back up the replacement tile to Buffer5
+ ld a, b
+ ld [Buffer5], a
+ ; Back up the animation index to Buffer6
+ ld a, c
+ ld [Buffer6], a
+ xor a
+ ret
+
+.fail
+ scf
+ ret
+
+Script_CutFromMenu: ; c7fe
+ reloadmappart
+ special UpdateTimePals
+
+Script_Cut: ; 0xc802
+ callasm GetPartyNick
+ writetext Text_UsedCut
+ reloadmappart
+ callasm CutDownTreeOrGrass
+ closetext
+ end
+
+CutDownTreeOrGrass: ; c810
+ ld hl, Buffer3 ; OverworldMapTile
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [Buffer5] ; ReplacementTile
+ ld [hl], a
+ xor a
+ ld [hBGMapMode], a
+ call OverworldTextModeSwitch
+ call UpdateSprites
+ call DelayFrame
+ ld a, [Buffer6] ; Animation type
+ ld e, a
+ farcall OWCutAnimation
+ call BufferScreen
+ call GetMovementPermissions
+ call UpdateSprites
+ call DelayFrame
+ call LoadStandardFont
+ ret
+
+CheckOverworldTileArrays: ; c840
+ ; Input: c contains the tile you're facing
+ ; Output: Replacement tile in b and effect on wild encounters in c, plus carry set.
+ ; Carry is not set if the facing tile cannot be replaced, or if the tileset
+ ; does not contain a tile you can replace.
+
+ ; Dictionary lookup for pointer to tile replacement table
+ push bc
+ ld a, [wTileset]
+ ld de, 3
+ call IsInArray
+ pop bc
+ jr nc, .nope
+ ; Load the pointer
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ; Look up the tile you're facing
+ ld de, 3
+ ld a, c
+ call IsInArray
+ jr nc, .nope
+ ; Load the replacement to b
+ inc hl
+ ld b, [hl]
+ ; Load the animation type parameter to c
+ inc hl
+ ld c, [hl]
+ scf
+ ret
+
+.nope
+ xor a
+ ret
+
+
+INCLUDE "data/field_move_blocks.asm"
+
+
+OWFlash: ; c8ac
+ call .CheckUseFlash
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.CheckUseFlash: ; c8b5
+; Flash
+ ld de, ENGINE_ZEPHYRBADGE
+ farcall CheckBadge
+ jr c, .nozephyrbadge
+ push hl
+ farcall SpecialAerodactylChamber
+ pop hl
+ jr c, .useflash
+ ld a, [wTimeOfDayPalset]
+ cp %11111111 ; 3, 3, 3, 3
+ jr nz, .notadarkcave
+.useflash
+ call UseFlash
+ ld a, $81
+ ret
+
+.notadarkcave
+ call FieldMoveFailed
+ ld a, $80
+ ret
+
+.nozephyrbadge
+ ld a, $80
+ ret
+
+UseFlash: ; c8e0
+ ld hl, Script_UseFlash
+ jp QueueScript
+
+Script_UseFlash: ; 0xc8e6
+ reloadmappart
+ special UpdateTimePals
+ writetext UnknownText_0xc8f3
+ callasm BlindingFlash
+ closetext
+ end
+
+UnknownText_0xc8f3: ; 0xc8f3
+ text_jump UnknownText_0x1c0609
+ start_asm
+ call WaitSFX
+ ld de, SFX_FLASH
+ call PlaySFX
+ call WaitSFX
+ ld hl, .BlankText
+ ret
+
+.BlankText: ; 0xc908
+ db "@"
+
+SurfFunction: ; c909
+ call FieldMoveJumptableReset
+.loop
+ ld hl, .Jumptable
+ call FieldMoveJumptable
+ jr nc, .loop
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.Jumptable: ; c91a (3:491a)
+ dw .TrySurf
+ dw .DoSurf
+ dw .FailSurf
+ dw .AlreadySurfing
+
+.TrySurf: ; c922 (3:4922)
+ ld de, ENGINE_FOGBADGE
+ call CheckBadge
+ jr c, .asm_c956
+ ld hl, BikeFlags
+ bit 1, [hl] ; always on bike
+ jr nz, .cannotsurf
+ ld a, [PlayerState]
+ cp PLAYER_SURF
+ jr z, .alreadyfail
+ cp PLAYER_SURF_PIKA
+ jr z, .alreadyfail
+ call GetFacingTileCoord
+ call GetTileCollision
+ cp WATERTILE
+ jr nz, .cannotsurf
+ call CheckDirection
+ jr c, .cannotsurf
+ farcall CheckFacingObject
+ jr c, .cannotsurf
+ ld a, $1
+ ret
+.asm_c956
+ ld a, $80
+ ret
+.alreadyfail
+ ld a, $3
+ ret
+.cannotsurf
+ ld a, $2
+ ret
+
+.DoSurf: ; c95f (3:495f)
+ call GetSurfType
+ ld [Buffer2], a
+ call GetPartyNick
+ ld hl, SurfFromMenuScript
+ call QueueScript
+ ld a, $81
+ ret
+
+.FailSurf: ; c971 (3:4971)
+ ld hl, CantSurfText
+ call MenuTextBoxBackup
+ ld a, $80
+ ret
+
+.AlreadySurfing: ; c97a (3:497a)
+ ld hl, AlreadySurfingText
+ call MenuTextBoxBackup
+ ld a, $80
+ ret
+
+SurfFromMenuScript: ; c983
+ special UpdateTimePals
+
+UsedSurfScript: ; c986
+ writetext UsedSurfText ; "used SURF!"
+ waitbutton
+ closetext
+
+ callasm .empty_fn ; empty function
+
+ copybytetovar Buffer2
+ writevarcode VAR_MOVEMENT
+
+ special ReplaceKrisSprite
+ special PlayMapMusic
+; step into the water
+ special Special_SurfStartStep ; (slow_step_x, step_end)
+ applymovement PLAYER, MovementBuffer ; PLAYER, MovementBuffer
+ end
+
+.empty_fn ; c9a2
+ farcall TrainerRankings_Surf
+ ret
+
+UsedSurfText: ; c9a9
+ text_jump _UsedSurfText
+ db "@"
+
+CantSurfText: ; c9ae
+ text_jump _CantSurfText
+ db "@"
+
+AlreadySurfingText: ; c9b3
+ text_jump _AlreadySurfingText
+ db "@"
+
+GetSurfType: ; c9b8
+; Surfing on Pikachu uses an alternate sprite.
+; This is done by using a separate movement type.
+
+ ld a, [CurPartyMon]
+ ld e, a
+ ld d, 0
+ ld hl, PartySpecies
+ add hl, de
+
+ ld a, [hl]
+ cp PIKACHU
+ ld a, PLAYER_SURF_PIKA
+ ret z
+ ld a, PLAYER_SURF
+ ret
+
+CheckDirection: ; c9cb
+; Return carry if a tile permission prevents you
+; from moving in the direction you're facing.
+
+; Get player direction
+ ld a, [PlayerDirection]
+ and %00001100 ; bits 2 and 3 contain direction
+ rrca
+ rrca
+ ld e, a
+ ld d, 0
+ ld hl, .Directions
+ add hl, de
+
+; Can you walk in this direction?
+ ld a, [TilePermissions]
+ and [hl]
+ jr nz, .quit
+ xor a
+ ret
+
+.quit
+ scf
+ ret
+
+.Directions:
+ db FACE_DOWN
+ db FACE_UP
+ db FACE_LEFT
+ db FACE_RIGHT
+
+TrySurfOW:: ; c9e7
+; Checking a tile in the overworld.
+; Return carry if fail is allowed.
+
+; Don't ask to surf if already fail.
+ ld a, [PlayerState]
+ cp PLAYER_SURF_PIKA
+ jr z, .quit
+ cp PLAYER_SURF
+ jr z, .quit
+
+; Must be facing water.
+ ld a, [EngineBuffer1]
+ call GetTileCollision
+ cp WATERTILE
+ jr nz, .quit
+
+; Check tile permissions.
+ call CheckDirection
+ jr c, .quit
+
+ ld de, ENGINE_FOGBADGE
+ call CheckEngineFlag
+ jr c, .quit
+
+ ld d, SURF
+ call CheckPartyMove
+ jr c, .quit
+
+ ld hl, BikeFlags
+ bit 1, [hl] ; always on bike (can't surf)
+ jr nz, .quit
+
+ call GetSurfType
+ ld [Buffer2], a
+ call GetPartyNick
+
+ ld a, BANK(AskSurfScript)
+ ld hl, AskSurfScript
+ call CallScript
+
+ scf
+ ret
+
+.quit
+ xor a
+ ret
+
+AskSurfScript: ; ca2c
+ opentext
+ writetext AskSurfText
+ yesorno
+ iftrue UsedSurfScript
+ closetext
+ end
+
+AskSurfText: ; ca36
+ text_jump _AskSurfText ; The water is calm.
+ db "@" ; Want to SURF?
+
+FlyFunction: ; ca3b
+ call FieldMoveJumptableReset
+.loop
+ ld hl, .Jumptable
+ call FieldMoveJumptable
+ jr nc, .loop
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.Jumptable:
+ dw .TryFly
+ dw .DoFly
+ dw .FailFly
+
+.TryFly: ; ca52
+; Fly
+ ld de, ENGINE_STORMBADGE
+ call CheckBadge
+ jr c, .nostormbadge
+ call GetMapEnvironment
+ call CheckOutdoorMap
+ jr z, .outdoors
+ jr .indoors
+
+.outdoors
+ xor a
+ ld [hMapAnims], a
+ call LoadStandardMenuDataHeader
+ call ClearSprites
+ farcall _FlyMap
+ ld a, e
+ cp -1
+ jr z, .illegal
+ cp NUM_SPAWNS
+ jr nc, .illegal
+
+ ld [DefaultSpawnpoint], a
+ call CloseWindow
+ ld a, $1
+ ret
+
+.nostormbadge
+ ld a, $82
+ ret
+
+.indoors
+ ld a, $2
+ ret
+
+.illegal
+ call CloseWindow
+ call WaitBGMap
+ ld a, $80
+ ret
+
+.DoFly: ; ca94
+ ld hl, .FlyScript
+ call QueueScript
+ ld a, $81
+ ret
+
+.FailFly: ; ca9d
+ call FieldMoveFailed
+ ld a, $82
+ ret
+
+.FlyScript: ; 0xcaa3
+ reloadmappart
+ callasm HideSprites
+ special UpdateTimePals
+ callasm FlyFromAnim
+ farscall Script_AbortBugContest
+ special WarpToSpawnPoint
+ callasm DelayLoadingNewSprites
+ writecode VAR_MOVEMENT, PLAYER_NORMAL
+ newloadmap MAPSETUP_FLY
+ callasm FlyToAnim
+ special WaitSFX
+ callasm .ReturnFromFly
+ end
+
+.ReturnFromFly: ; cacb
+ farcall Function561d
+ call DelayFrame
+ call ReplaceKrisSprite
+ farcall LoadOverworldFont
+ ret
+
+WaterfallFunction: ; cade
+ call .TryWaterfall
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.TryWaterfall: ; cae7
+; Waterfall
+ ld de, ENGINE_RISINGBADGE
+ farcall CheckBadge
+ ld a, $80
+ ret c
+ call CheckMapCanWaterfall
+ jr c, .failed
+ ld hl, Script_WaterfallFromMenu
+ call QueueScript
+ ld a, $81
+ ret
+
+.failed
+ call FieldMoveFailed
+ ld a, $80
+ ret
+
+CheckMapCanWaterfall: ; cb07
+ ld a, [PlayerDirection]
+ and $c
+ cp FACE_UP
+ jr nz, .failed
+ ld a, [TileUp]
+ call CheckWaterfallTile
+ jr nz, .failed
+ xor a
+ ret
+
+.failed
+ scf
+ ret
+
+Script_WaterfallFromMenu: ; 0xcb1c
+ reloadmappart
+ special UpdateTimePals
+
+Script_UsedWaterfall: ; 0xcb20
+ callasm GetPartyNick
+ writetext .Text_UsedWaterfall
+ waitbutton
+ closetext
+ playsound SFX_BUBBLEBEAM
+.loop
+ applymovement PLAYER, .WaterfallStep
+ callasm .CheckContinueWaterfall
+ iffalse .loop
+ end
+
+.CheckContinueWaterfall: ; cb38
+ xor a
+ ld [ScriptVar], a
+ ld a, [PlayerStandingTile]
+ call CheckWaterfallTile
+ ret z
+ farcall TrainerRankings_Waterfall
+ ld a, $1
+ ld [ScriptVar], a
+ ret
+
+.WaterfallStep: ; cb4f
+ turn_waterfall UP
+ step_end
+
+.Text_UsedWaterfall: ; 0xcb51
+ ; used WATERFALL!
+ text_jump UnknownText_0x1c068e
+ db "@"
+
+TryWaterfallOW:: ; cb56
+ ld d, WATERFALL
+ call CheckPartyMove
+ jr c, .failed
+ ld de, ENGINE_RISINGBADGE
+ call CheckEngineFlag
+ jr c, .failed
+ call CheckMapCanWaterfall
+ jr c, .failed
+ ld a, BANK(Script_AskWaterfall)
+ ld hl, Script_AskWaterfall
+ call CallScript
+ scf
+ ret
+
+.failed
+ ld a, BANK(Script_CantDoWaterfall)
+ ld hl, Script_CantDoWaterfall
+ call CallScript
+ scf
+ ret
+
+Script_CantDoWaterfall: ; 0xcb7e
+ jumptext .Text_CantDoWaterfall
+
+.Text_CantDoWaterfall: ; 0xcb81
+ ; Wow, it's a huge waterfall.
+ text_jump UnknownText_0x1c06a3
+ db "@"
+
+Script_AskWaterfall: ; 0xcb86
+ opentext
+ writetext .AskUseWaterfall
+ yesorno
+ iftrue Script_UsedWaterfall
+ closetext
+ end
+
+.AskUseWaterfall: ; 0xcb90
+ ; Do you want to use WATERFALL?
+ text_jump UnknownText_0x1c06bf
+ db "@"
+
+EscapeRopeFunction: ; cb95
+ call FieldMoveJumptableReset
+ ld a, $1
+ jr dig_incave
+
+DigFunction: ; cb9c
+ call FieldMoveJumptableReset
+ ld a, $2
+
+dig_incave
+ ld [Buffer2], a
+.loop
+ ld hl, .DigTable
+ call FieldMoveJumptable
+ jr nc, .loop
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.DigTable: ; cbb2
+ dw .CheckCanDig
+ dw .DoDig
+ dw .FailDig
+
+.CheckCanDig: ; cbb8
+ call GetMapEnvironment
+ cp CAVE
+ jr z, .incave
+ cp DUNGEON
+ jr z, .incave
+.fail
+ ld a, $2
+ ret
+
+.incave
+ ld hl, wDigWarpNumber
+ ld a, [hli]
+ and a
+ jr z, .fail
+ ld a, [hli]
+ and a
+ jr z, .fail
+ ld a, [hl]
+ and a
+ jr z, .fail
+ ld a, $1
+ ret
+
+.DoDig: ; cbd8
+ ld hl, wDigWarpNumber
+ ld de, wNextWarp
+ ld bc, 3
+ call CopyBytes
+ call GetPartyNick
+ ld a, [Buffer2]
+ cp $2
+ jr nz, .escaperope
+ ld hl, .UsedDigScript
+ call QueueScript
+ ld a, $81
+ ret
+
+.escaperope
+ farcall SpecialKabutoChamber
+ ld hl, .UsedEscapeRopeScript
+ call QueueScript
+ ld a, $81
+ ret
+
+.FailDig: ; cc06
+ ld a, [Buffer2]
+ cp $2
+ jr nz, .failescaperope
+ ld hl, .Text_CantUseHere
+ call MenuTextBox
+ call WaitPressAorB_BlinkCursor
+ call CloseWindow
+
+.failescaperope
+ ld a, $80
+ ret
+
+.Text_UsedDig: ; 0xcc1c
+ ; used DIG!
+ text_jump UnknownText_0x1c06de
+ db "@"
+
+.Text_UsedEscapeRope: ; 0xcc21
+ ; used an ESCAPE ROPE.
+ text_jump UnknownText_0x1c06ed
+ db "@"
+
+.Text_CantUseHere: ; 0xcc26
+ ; Can't use that here.
+ text_jump UnknownText_0x1c0705
+ db "@"
+
+.UsedEscapeRopeScript: ; 0xcc2b
+ reloadmappart
+ special UpdateTimePals
+ writetext .Text_UsedEscapeRope
+ jump .UsedDigOrEscapeRopeScript
+
+.UsedDigScript: ; 0xcc35
+ reloadmappart
+ special UpdateTimePals
+ writetext .Text_UsedDig
+
+.UsedDigOrEscapeRopeScript: ; 0xcc3c
+ waitbutton
+ closetext
+ playsound SFX_WARP_TO
+ applymovement PLAYER, .DigOut
+ farscall Script_AbortBugContest
+ special WarpToSpawnPoint
+ writecode VAR_MOVEMENT, PLAYER_NORMAL
+ newloadmap MAPSETUP_DOOR
+ playsound SFX_WARP_FROM
+ applymovement PLAYER, .DigReturn
+ end
+
+.DigOut: ; 0xcc59
+ step_dig 32
+ hide_object
+ step_end
+
+.DigReturn: ; 0xcc5d
+ show_object
+ return_dig 32
+ step_end
+
+TeleportFunction: ; cc61
+ call FieldMoveJumptableReset
+.loop
+ ld hl, .Jumptable
+ call FieldMoveJumptable
+ jr nc, .loop
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.Jumptable: ; cc72
+ dw .TryTeleport
+ dw .DoTeleport
+ dw .FailTeleport
+
+.TryTeleport: ; cc78
+ call GetMapEnvironment
+ call CheckOutdoorMap
+ jr z, .CheckIfSpawnPoint
+ jr .nope
+
+.CheckIfSpawnPoint:
+ ld a, [wLastSpawnMapGroup]
+ ld d, a
+ ld a, [wLastSpawnMapNumber]
+ ld e, a
+ farcall IsSpawnPoint
+ jr nc, .nope
+ ld a, c
+ ld [DefaultSpawnpoint], a
+ ld a, $1
+ ret
+
+.nope
+ ld a, $2
+ ret
+
+.DoTeleport: ; cc9c
+ call GetPartyNick
+ ld hl, .TeleportScript
+ call QueueScript
+ ld a, $81
+ ret
+
+.FailTeleport: ; cca8
+ ld hl, .Text_CantUseHere
+ call MenuTextBoxBackup
+ ld a, $80
+ ret
+
+.Text_ReturnToLastMonCenter: ; 0xccb1
+ ; Return to the last #MON CENTER.
+ text_jump UnknownText_0x1c071a
+ db "@"
+
+.Text_CantUseHere: ; 0xccb6
+ ; Can't use that here.
+ text_jump UnknownText_0x1c073b
+ db "@"
+
+.TeleportScript: ; 0xccbb
+ reloadmappart
+ special UpdateTimePals
+ writetext .Text_ReturnToLastMonCenter
+ pause 60
+ reloadmappart
+ closetext
+ playsound SFX_WARP_TO
+ applymovement PLAYER, .TeleportFrom
+ farscall Script_AbortBugContest
+ special WarpToSpawnPoint
+ writecode VAR_MOVEMENT, PLAYER_NORMAL
+ newloadmap MAPSETUP_TELEPORT
+ playsound SFX_WARP_FROM
+ applymovement PLAYER, .TeleportTo
+ end
+
+.TeleportFrom: ; cce1
+ teleport_from
+ step_end
+
+.TeleportTo: ; cce3
+ teleport_to
+ step_end
+
+StrengthFunction: ; cce5
+ call .TryStrength
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.TryStrength: ; ccee
+; Strength
+ ld de, ENGINE_PLAINBADGE
+ call CheckBadge
+ jr c, .Failed
+ jr .UseStrength
+
+.AlreadyUsing: ; unreferenced
+ ld hl, .JumpText
+ call MenuTextBoxBackup
+ ld a, $80
+ ret
+
+.JumpText: ; 0xcd01
+ text_jump UnknownText_0x1c0751
+ db "@"
+
+.Failed: ; cd06
+ ld a, $80
+ ret
+
+.UseStrength: ; cd09
+ ld hl, Script_StrengthFromMenu
+ call QueueScript
+ ld a, $81
+ ret
+
+SetStrengthFlag: ; cd12
+ ld hl, BikeFlags
+ set 0, [hl]
+ ld a, [CurPartyMon]
+ ld e, a
+ ld d, 0
+ ld hl, PartySpecies
+ add hl, de
+ ld a, [hl]
+ ld [Buffer6], a
+ call GetPartyNick
+ ret
+
+Script_StrengthFromMenu: ; 0xcd29
+ reloadmappart
+ special UpdateTimePals
+
+Script_UsedStrength: ; 0xcd2d
+ callasm SetStrengthFlag
+ writetext .UsedStrength
+ copybytetovar Buffer6
+ cry 0
+ pause 3
+ writetext .StrengthAllowedItToMoveBoulders
+ closetext
+ end
+
+.UsedStrength: ; 0xcd41
+ text_jump UnknownText_0x1c0774
+ db "@"
+
+.StrengthAllowedItToMoveBoulders: ; 0xcd46
+ text_jump UnknownText_0x1c0788
+ db "@"
+
+AskStrengthScript:
+ callasm TryStrengthOW
+ iffalse .AskStrength
+ if_equal $1, .DontMeetRequirements
+ jump .AlreadyUsedStrength
+
+.DontMeetRequirements: ; 0xcd59
+ jumptext UnknownText_0xcd73
+
+.AlreadyUsedStrength: ; 0xcd5c
+ jumptext UnknownText_0xcd6e
+
+.AskStrength: ; 0xcd5f
+ opentext
+ writetext UnknownText_0xcd69
+ yesorno
+ iftrue Script_UsedStrength
+ closetext
+ end
+
+UnknownText_0xcd69: ; 0xcd69
+ ; A #MON may be able to move this. Want to use STRENGTH?
+ text_jump UnknownText_0x1c07a0
+ db "@"
+
+UnknownText_0xcd6e: ; 0xcd6e
+ ; Boulders may now be moved!
+ text_jump UnknownText_0x1c07d8
+ db "@"
+
+UnknownText_0xcd73: ; 0xcd73
+ ; A #MON may be able to move this.
+ text_jump UnknownText_0x1c07f4
+ db "@"
+
+TryStrengthOW: ; cd78
+ ld d, STRENGTH
+ call CheckPartyMove
+ jr c, .nope
+
+ ld de, ENGINE_PLAINBADGE
+ call CheckEngineFlag
+ jr c, .nope
+
+ ld hl, BikeFlags
+ bit 0, [hl]
+ jr z, .already_using
+
+ ld a, 2
+ jr .done
+
+.nope
+ ld a, 1
+ jr .done
+
+.already_using
+ xor a
+ jr .done
+
+.done
+ ld [ScriptVar], a
+ ret
+
+WhirlpoolFunction: ; cd9d
+ call FieldMoveJumptableReset
+.loop
+ ld hl, Jumptable_cdae
+ call FieldMoveJumptable
+ jr nc, .loop
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+Jumptable_cdae: ; cdae
+ dw .TryWhirlpool
+ dw .DoWhirlpool
+ dw .FailWhirlpool
+
+.TryWhirlpool: ; cdb4
+ ld de, ENGINE_GLACIERBADGE
+ call CheckBadge
+ jr c, .noglacierbadge
+ call TryWhirlpoolMenu
+ jr c, .failed
+ ld a, $1
+ ret
+
+.failed
+ ld a, $2
+ ret
+
+.noglacierbadge
+ ld a, $80
+ ret
+
+.DoWhirlpool: ; cdca
+ ld hl, Script_WhirlpoolFromMenu
+ call QueueScript
+ ld a, $81
+ ret
+
+.FailWhirlpool: ; cdd3
+ call FieldMoveFailed
+ ld a, $80
+ ret
+
+Text_UsedWhirlpool: ; 0xcdd9
+ ; used WHIRLPOOL!
+ text_jump UnknownText_0x1c0816
+ db "@"
+
+TryWhirlpoolMenu: ; cdde
+ call GetFacingTileCoord
+ ld c, a
+ push de
+ call CheckWhirlpoolTile
+ pop de
+ jr c, .failed
+ call GetBlockLocation
+ ld c, [hl]
+ push hl
+ ld hl, WhirlpoolBlockPointers
+ call CheckOverworldTileArrays
+ pop hl
+ jr nc, .failed
+ ld a, l
+ ld [Buffer3], a
+ ld a, h
+ ld [Buffer4], a
+ ld a, b
+ ld [Buffer5], a
+ ld a, c
+ ld [Buffer6], a
+ xor a
+ ret
+
+.failed
+ scf
+ ret
+
+Script_WhirlpoolFromMenu: ; 0xce0b
+ reloadmappart
+ special UpdateTimePals
+
+Script_UsedWhirlpool: ; 0xce0f
+ callasm GetPartyNick
+ writetext Text_UsedWhirlpool
+ reloadmappart
+ callasm DisappearWhirlpool
+ closetext
+ end
+
+DisappearWhirlpool: ; ce1d
+ ld hl, Buffer3
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [Buffer5]
+ ld [hl], a
+ xor a
+ ld [hBGMapMode], a
+ call OverworldTextModeSwitch
+ ld a, [Buffer6]
+ ld e, a
+ farcall PlayWhirlpoolSound
+ call BufferScreen
+ call GetMovementPermissions
+ ret
+
+TryWhirlpoolOW:: ; ce3e
+ ld d, WHIRLPOOL
+ call CheckPartyMove
+ jr c, .failed
+ ld de, ENGINE_GLACIERBADGE
+ call CheckEngineFlag
+ jr c, .failed
+ call TryWhirlpoolMenu
+ jr c, .failed
+ ld a, BANK(Script_AskWhirlpoolOW)
+ ld hl, Script_AskWhirlpoolOW
+ call CallScript
+ scf
+ ret
+
+.failed
+ ld a, BANK(Script_MightyWhirlpool)
+ ld hl, Script_MightyWhirlpool
+ call CallScript
+ scf
+ ret
+
+Script_MightyWhirlpool: ; 0xce66
+ jumptext .MightyWhirlpoolText
+
+.MightyWhirlpoolText: ; 0xce69
+ text_jump UnknownText_0x1c082b
+ db "@"
+
+Script_AskWhirlpoolOW: ; 0xce6e
+ opentext
+ writetext UnknownText_0xce78
+ yesorno
+ iftrue Script_UsedWhirlpool
+ closetext
+ end
+
+UnknownText_0xce78: ; 0xce78
+ text_jump UnknownText_0x1c0864
+ db "@"
+
+HeadbuttFunction: ; ce7d
+ call TryHeadbuttFromMenu
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+TryHeadbuttFromMenu: ; ce86
+ call GetFacingTileCoord
+ call CheckHeadbuttTreeTile
+ jr nz, .no_tree
+
+ ld hl, HeadbuttFromMenuScript
+ call QueueScript
+ ld a, $81
+ ret
+
+.no_tree
+ call FieldMoveFailed
+ ld a, $80
+ ret
+
+UnknownText_0xce9d: ; 0xce9d
+ ; did a HEADBUTT!
+ text_jump UnknownText_0x1c0897
+ db "@"
+
+UnknownText_0xcea2: ; 0xcea2
+ ; Nope. Nothing…
+ text_jump UnknownText_0x1c08ac
+ db "@"
+
+HeadbuttFromMenuScript: ; 0xcea7
+ reloadmappart
+ special UpdateTimePals
+
+HeadbuttScript: ; 0xceab
+ callasm GetPartyNick
+ writetext UnknownText_0xce9d
+
+ reloadmappart
+ callasm ShakeHeadbuttTree
+
+ callasm TreeMonEncounter
+ iffalse .no_battle
+ closetext
+ randomwildmon
+ startbattle
+ reloadmapafterbattle
+ end
+
+.no_battle
+ writetext UnknownText_0xcea2
+ waitbutton
+ closetext
+ end
+
+TryHeadbuttOW:: ; cec9
+ ld d, HEADBUTT
+ call CheckPartyMove
+ jr c, .no
+
+ ld a, BANK(AskHeadbuttScript)
+ ld hl, AskHeadbuttScript
+ call CallScript
+ scf
+ ret
+
+.no
+ xor a
+ ret
+
+AskHeadbuttScript: ; 0xcedc
+ opentext
+ writetext UnknownText_0xcee6
+ yesorno
+ iftrue HeadbuttScript
+ closetext
+ end
+
+UnknownText_0xcee6: ; 0xcee6
+ ; A #MON could be in this tree. Want to HEADBUTT it?
+ text_jump UnknownText_0x1c08bc
+ db "@"
+
+RockSmashFunction: ; ceeb
+ call TryRockSmashFromMenu
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+TryRockSmashFromMenu: ; cef4
+ call GetFacingObject
+ jr c, .no_rock
+ ld a, d
+ cp $18
+ jr nz, .no_rock
+
+ ld hl, RockSmashFromMenuScript
+ call QueueScript
+ ld a, $81
+ ret
+
+.no_rock
+ call FieldMoveFailed
+ ld a, $80
+ ret
+
+GetFacingObject: ; cf0d
+ farcall CheckFacingObject
+ jr nc, .fail
+
+ ld a, [hObjectStructIndexBuffer]
+ call GetObjectStruct
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, bc
+ ld a, [hl]
+ ld [hLastTalked], a
+ call GetMapObject
+ ld hl, MAPOBJECT_MOVEMENT
+ add hl, bc
+ ld a, [hl]
+ ld d, a
+ and a
+ ret
+
+.fail
+ scf
+ ret
+
+RockSmashFromMenuScript: ; 0xcf2e
+ reloadmappart
+ special UpdateTimePals
+
+RockSmashScript: ; cf32
+ callasm GetPartyNick
+ writetext UnknownText_0xcf58
+ closetext
+ special WaitSFX
+ playsound SFX_STRENGTH
+ earthquake 84
+ applymovement2 MovementData_0xcf55
+ disappear -2
+
+ callasm RockMonEncounter
+ copybytetovar TempWildMonSpecies
+ iffalse .done
+ randomwildmon
+ startbattle
+ reloadmapafterbattle
+.done
+ end
+
+MovementData_0xcf55: ; 0xcf55
+ rock_smash 10
+ step_end
+
+UnknownText_0xcf58: ; 0xcf58
+ text_jump UnknownText_0x1c08f0
+ db "@"
+
+AskRockSmashScript: ; 0xcf5d
+ callasm HasRockSmash
+ if_equal 1, .no
+
+ opentext
+ writetext UnknownText_0xcf77
+ yesorno
+ iftrue RockSmashScript
+ closetext
+ end
+.no
+ jumptext UnknownText_0xcf72
+
+UnknownText_0xcf72: ; 0xcf72
+ ; Maybe a #MON can break this.
+ text_jump UnknownText_0x1c0906
+ db "@"
+
+UnknownText_0xcf77: ; 0xcf77
+ ; This rock looks breakable. Want to use ROCK SMASH?
+ text_jump UnknownText_0x1c0924
+ db "@"
+
+HasRockSmash: ; cf7c
+ ld d, ROCK_SMASH
+ call CheckPartyMove
+ jr nc, .yes
+.no
+ ld a, 1
+ jr .done
+.yes
+ xor a
+ jr .done
+.done
+ ld [ScriptVar], a
+ ret
+
+FishFunction: ; cf8e
+ ld a, e
+ push af
+ call FieldMoveJumptableReset
+ pop af
+ ld [Buffer2], a
+.loop
+ ld hl, .FishTable
+ call FieldMoveJumptable
+ jr nc, .loop
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.FishTable: ; cfa5
+ dw .TryFish
+ dw .FishNoBite
+ dw .FishGotSomething
+ dw .FailFish
+ dw .FishNoFish
+
+.TryFish: ; cfaf
+ ld a, [PlayerState]
+ cp PLAYER_SURF
+ jr z, .fail
+ cp PLAYER_SURF_PIKA
+ jr z, .fail
+ call GetFacingTileCoord
+ call GetTileCollision
+ cp WATERTILE
+ jr z, .facingwater
+.fail
+ ld a, $3
+ ret
+
+.facingwater
+ call GetFishingGroup
+ and a
+ jr nz, .goodtofish
+ ld a, $4
+ ret
+
+.goodtofish
+ ld d, a
+ ld a, [Buffer2]
+ ld e, a
+ farcall Fish
+ ld a, d
+ and a
+ jr z, .nonibble
+ ld [TempWildMonSpecies], a
+ ld a, e
+ ld [CurPartyLevel], a
+ ld a, BATTLETYPE_FISH
+ ld [BattleType], a
+ ld a, $2
+ ret
+
+.nonibble
+ ld a, $1
+ ret
+
+.FailFish: ; cff1
+ ld a, $80
+ ret
+
+.FishGotSomething: ; cff4
+ ld a, $1
+ ld [Buffer6], a
+ ld hl, Script_GotABite
+ call QueueScript
+ ld a, $81
+ ret
+
+.FishNoBite: ; d002
+ ld a, $2
+ ld [Buffer6], a
+ ld hl, Script_NotEvenANibble
+ call QueueScript
+ ld a, $81
+ ret
+
+.FishNoFish: ; d010
+ ld a, $0
+ ld [Buffer6], a
+ ld hl, Script_NotEvenANibble2
+ call QueueScript
+ ld a, $81
+ ret
+
+Script_NotEvenANibble: ; 0xd01e
+ scall Script_FishCastRod
+ writetext UnknownText_0xd0a9
+ jump Script_NotEvenANibble_FallThrough
+
+Script_NotEvenANibble2: ; 0xd027
+ scall Script_FishCastRod
+ writetext UnknownText_0xd0a9
+
+Script_NotEvenANibble_FallThrough: ; 0xd02d
+ loademote EMOTE_SHADOW
+ callasm PutTheRodAway
+ closetext
+ end
+
+Script_GotABite: ; 0xd035
+ scall Script_FishCastRod
+ callasm Fishing_CheckFacingUp
+ iffalse .NotFacingUp
+ applymovement PLAYER, .Movement_FacingUp
+ jump .FightTheHookedPokemon
+
+.NotFacingUp: ; 0xd046
+ applymovement PLAYER, .Movement_NotFacingUp
+
+.FightTheHookedPokemon: ; 0xd04a
+ pause 40
+ applymovement PLAYER, .Movement_RestoreRod
+ writetext UnknownText_0xd0a4
+ callasm PutTheRodAway
+ closetext
+ randomwildmon
+ startbattle
+ reloadmapafterbattle
+ end
+
+.Movement_NotFacingUp: ; d05c
+ fish_got_bite
+ fish_got_bite
+ fish_got_bite
+ fish_got_bite
+ show_emote
+ step_end
+
+.Movement_FacingUp: ; d062
+ fish_got_bite
+ fish_got_bite
+ fish_got_bite
+ fish_got_bite
+ step_sleep 1
+ show_emote
+ step_end
+
+.Movement_RestoreRod: ; d069
+ hide_emote
+ fish_cast_rod
+ step_end
+
+Fishing_CheckFacingUp: ; d06c
+ ld a, [PlayerDirection]
+ and $c
+ cp OW_UP
+ ld a, $1
+ jr z, .up
+ xor a
+
+.up
+ ld [ScriptVar], a
+ ret
+
+Script_FishCastRod: ; 0xd07c
+ reloadmappart
+ loadvar hBGMapMode, $0
+ special UpdateTimePals
+ loademote EMOTE_ROD
+ callasm LoadFishingGFX
+ loademote EMOTE_SHOCK
+ applymovement PLAYER, MovementData_0xd093
+ pause 40
+ end
+
+MovementData_0xd093: ; d093
+ fish_cast_rod
+ step_end
+
+PutTheRodAway: ; d095
+ xor a
+ ld [hBGMapMode], a
+ ld a, $1
+ ld [PlayerAction], a
+ call UpdateSprites
+ call ReplaceKrisSprite
+ ret
+
+UnknownText_0xd0a4: ; 0xd0a4
+ ; Oh! A bite!
+ text_jump UnknownText_0x1c0958
+ db "@"
+
+UnknownText_0xd0a9: ; 0xd0a9
+ ; Not even a nibble!
+ text_jump UnknownText_0x1c0965
+ db "@"
+
+UnknownText_0xd0ae: ; unused
+ ; Looks like there's nothing here.
+ text_jump UnknownText_0x1c0979
+ db "@"
+
+BikeFunction: ; d0b3
+ call .TryBike
+ and $7f
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.TryBike: ; d0bc
+ call .CheckEnvironment
+ jr c, .CannotUseBike
+ ld a, [PlayerState]
+ cp PLAYER_NORMAL
+ jr z, .GetOnBike
+ cp PLAYER_BIKE
+ jr z, .GetOffBike
+ jr .CannotUseBike
+
+.GetOnBike:
+ ld hl, Script_GetOnBike
+ ld de, Script_GetOnBike_Register
+ call .CheckIfRegistered
+ call QueueScript
+ xor a
+ ld [MusicFade], a
+ ld de, MUSIC_NONE
+ call PlayMusic
+ call DelayFrame
+ call MaxVolume
+ ld de, MUSIC_BICYCLE
+ ld a, e
+ ld [wMapMusic], a
+ call PlayMusic
+ ld a, $1
+ ret
+
+.GetOffBike:
+ ld hl, BikeFlags
+ bit 1, [hl]
+ jr nz, .CantGetOffBike
+ ld hl, Script_GetOffBike
+ ld de, Script_GetOffBike_Register
+ call .CheckIfRegistered
+ ld a, BANK(Script_GetOffBike)
+ jr .done
+
+.CantGetOffBike:
+ ld hl, Script_CantGetOffBike
+ jr .done
+
+.CannotUseBike:
+ ld a, $0
+ ret
+
+.done
+ call QueueScript
+ ld a, $1
+ ret
+
+.CheckIfRegistered: ; d119
+ ld a, [wUsingItemWithSelect]
+ and a
+ ret z
+ ld h, d
+ ld l, e
+ ret
+
+.CheckEnvironment: ; d121
+ call GetMapEnvironment
+ call CheckOutdoorMap
+ jr z, .ok
+ cp CAVE
+ jr z, .ok
+ cp GATE
+ jr z, .ok
+ jr .nope
+
+.ok
+ call GetPlayerStandingTile
+ and WALLTILE | WATERTILE ; can't use our bike in a wall or on water
+ jr nz, .nope
+ xor a
+ ret
+
+.nope
+ scf
+ ret
+
+Script_GetOnBike: ; 0xd13e
+ reloadmappart
+ special UpdateTimePals
+ writecode VAR_MOVEMENT, PLAYER_BIKE
+ writetext GotOnTheBikeText
+ waitbutton
+ closetext
+ special ReplaceKrisSprite
+ end
+
+Script_GetOnBike_Register: ; 0xd14e
+ writecode VAR_MOVEMENT, PLAYER_BIKE
+ closetext
+ special ReplaceKrisSprite
+ end
+
+; XXX
+ nop
+ ret
+
+Script_GetOffBike: ; 0xd158
+ reloadmappart
+ special UpdateTimePals
+ writecode VAR_MOVEMENT, PLAYER_NORMAL
+ writetext GotOffTheBikeText
+ waitbutton
+
+FinishGettingOffBike:
+ closetext
+ special ReplaceKrisSprite
+ special PlayMapMusic
+ end
+
+Script_GetOffBike_Register: ; 0xd16b
+ writecode VAR_MOVEMENT, PLAYER_NORMAL
+ jump FinishGettingOffBike
+
+Script_CantGetOffBike: ; 0xd171
+ writetext .CantGetOffBikeText
+ waitbutton
+ closetext
+ end
+
+.CantGetOffBikeText: ; 0xd177
+ ; You can't get off here!
+ text_jump UnknownText_0x1c099a
+ db "@"
+
+GotOnTheBikeText: ; 0xd17c
+ ; got on the @ .
+ text_jump UnknownText_0x1c09b2
+ db "@"
+
+GotOffTheBikeText: ; 0xd181
+ ; got off the @ .
+ text_jump UnknownText_0x1c09c7
+ db "@"
+
+TryCutOW:: ; d186
+ ld d, CUT
+ call CheckPartyMove
+ jr c, .cant_cut
+
+ ld de, ENGINE_HIVEBADGE
+ call CheckEngineFlag
+ jr c, .cant_cut
+
+ ld a, BANK(AskCutScript)
+ ld hl, AskCutScript
+ call CallScript
+ scf
+ ret
+
+.cant_cut
+ ld a, BANK(CantCutScript)
+ ld hl, CantCutScript
+ call CallScript
+ scf
+ ret
+
+AskCutScript: ; 0xd1a9
+ opentext
+ writetext UnknownText_0xd1c8
+ yesorno
+ iffalse .script_d1b8
+ callasm .CheckMap
+ iftrue Script_Cut
+.script_d1b8
+ closetext
+ end
+
+.CheckMap: ; d1ba
+ xor a
+ ld [ScriptVar], a
+ call CheckMapForSomethingToCut
+ ret c
+ ld a, TRUE
+ ld [ScriptVar], a
+ ret
+
+UnknownText_0xd1c8: ; 0xd1c8
+ text_jump UnknownText_0x1c09dd
+ db "@"
+
+CantCutScript: ; 0xd1cd
+ jumptext UnknownText_0xd1d0
+
+UnknownText_0xd1d0: ; 0xd1d0
+ text_jump UnknownText_0x1c0a05
+ db "@"
diff --git a/engine/events/poisonstep.asm b/engine/events/poisonstep.asm
new file mode 100755
index 000000000..00c7477bc
--- /dev/null
+++ b/engine/events/poisonstep.asm
@@ -0,0 +1,162 @@
+DoPoisonStep:: ; 505da
+ ld a, [PartyCount]
+ and a
+ jr z, .no_faint
+
+ xor a
+ ld c, 7
+ ld hl, EngineBuffer1
+.loop_clearEngineBuffer1
+ ld [hli], a
+ dec c
+ jr nz, .loop_clearEngineBuffer1
+
+ xor a
+ ld [CurPartyMon], a
+.loop_check_poison
+ call .DamageMonIfPoisoned
+ jr nc, .not_poisoned
+; the output flag is stored in c, copy it to the ([CurPartyMon] + 2)nd EngineBuffer
+; and set the corresponding flag in EngineBuffer1
+ ld a, [CurPartyMon]
+ ld e, a
+ ld d, 0
+ ld hl, EngineBuffer2
+ add hl, de
+ ld [hl], c
+ ld a, [EngineBuffer1]
+ or c
+ ld [EngineBuffer1], a
+
+.not_poisoned
+ ld a, [PartyCount]
+ ld hl, CurPartyMon
+ inc [hl]
+ cp [hl]
+ jr nz, .loop_check_poison
+
+ ld a, [EngineBuffer1]
+ and %10
+ jr nz, .someone_has_fainted
+ ld a, [EngineBuffer1]
+ and %01
+ jr z, .no_faint
+ call .PlayPoisonSFX
+ xor a
+ ret
+
+.someone_has_fainted
+ ld a, BANK(.Script_MonFaintedToPoison)
+ ld hl, .Script_MonFaintedToPoison
+ call CallScript
+ scf
+ ret
+
+.no_faint
+ xor a
+ ret
+; 5062e
+
+.DamageMonIfPoisoned: ; 5062e
+; check if mon is poisoned, return if not
+ ld a, MON_STATUS
+ call GetPartyParamLocation
+ ld a, [hl]
+ and 1 << PSN
+ ret z
+
+; check if mon is already fainted, return if so
+ ld a, MON_HP
+ call GetPartyParamLocation
+ ld a, [hli]
+ ld b, a
+ ld c, [hl]
+ or c
+ ret z
+
+; do 1 HP damage
+ dec bc
+ ld [hl], c
+ dec hl
+ ld [hl], b
+
+; check if mon has fainted as a result of poison damage
+ ld a, b
+ or c
+ jr nz, .not_fainted
+
+; the mon has fainted, reset its status, set carry, and return %10
+ ld a, MON_STATUS
+ call GetPartyParamLocation
+ ld [hl], 0
+ ld c, %10
+ scf
+ ret
+
+.not_fainted
+; set carry and return %01
+ ld c, %01
+ scf
+ ret
+; 50658
+
+.PlayPoisonSFX: ; 50658
+ ld de, SFX_POISON
+ call PlaySFX
+ ld b, $2
+ predef LoadPoisonBGPals
+ call DelayFrame
+ ret
+; 50669
+
+.Script_MonFaintedToPoison: ; 50669
+ callasm .PlayPoisonSFX
+ opentext
+ callasm .CheckWhitedOut
+ iffalse .whiteout
+ closetext
+ end
+; 50677
+
+.whiteout ; 50677
+ farjump Script_OverworldWhiteout
+; 5067b
+
+.CheckWhitedOut: ; 5067b
+ xor a
+ ld [CurPartyMon], a
+ ld de, EngineBuffer2
+.party_loop
+ push de
+ ld a, [de]
+ and %10
+ jr z, .mon_not_fainted
+ ld c, HAPPINESS_POISONFAINT
+ farcall ChangeHappiness
+ farcall GetPartyNick
+ ld hl, .PoisonFaintText
+ call PrintText
+
+.mon_not_fainted
+ pop de
+ inc de
+ ld hl, CurPartyMon
+ inc [hl]
+ ld a, [PartyCount]
+ cp [hl]
+ jr nz, .party_loop
+ predef CheckPlayerPartyForFitPkmn
+ ld a, d
+ ld [ScriptVar], a
+ ret
+; 506b2
+
+.PoisonFaintText: ; 506b2
+ text_jump UnknownText_0x1c0acc
+ db "@"
+; 506b7
+
+.PoisonWhiteOutText: ; 506b7
+ text_jump UnknownText_0x1c0ada
+ db "@"
+; 506bc
diff --git a/engine/events/poisonstep_pals.asm b/engine/events/poisonstep_pals.asm
new file mode 100644
index 000000000..088be8848
--- /dev/null
+++ b/engine/events/poisonstep_pals.asm
@@ -0,0 +1,48 @@
+LoadPoisonBGPals: ; cbcdd
+ call .LoadPals
+ ld a, [hCGB]
+ and a
+ ret nz
+ ret ; ????
+
+.LoadPals: ; cbce5
+ ld a, [hCGB]
+ and a
+ jr nz, .cgb
+ ld a, [TimeOfDayPal]
+ and $3
+ cp $3
+ ld a, %00000000
+ jr z, .convert_pals
+ ld a, %10101010
+
+.convert_pals
+ call DmgToCgbBGPals
+ ld c, 4
+ call DelayFrames
+ farcall _UpdateTimePals
+ ret
+
+.cgb
+ ld a, [rSVBK]
+ push af
+ ld a, $5
+ ld [rSVBK], a
+ ld hl, BGPals
+ ld c, $20
+.loop
+; RGB 28, 21, 31
+ ld a, LOW(palred 28 + palgreen 21 + palblue 31)
+ ld [hli], a
+ ld a, HIGH(palred 28 + palgreen 21 + palblue 31)
+ ld [hli], a
+ dec c
+ jr nz, .loop
+ pop af
+ ld [rSVBK], a
+ ld a, $1
+ ld [hCGBPalUpdate], a
+ ld c, 4
+ call DelayFrames
+ farcall _UpdateTimePals
+ ret
diff --git a/engine/events/poke_seer.asm b/engine/events/poke_seer.asm
new file mode 100644
index 000000000..d6e335298
--- /dev/null
+++ b/engine/events/poke_seer.asm
@@ -0,0 +1,461 @@
+ const_def
+ const SEER_INTRO
+ const SEER_CANT_TELL
+ const SEER_MET_AT
+ const SEER_TIME_LEVEL
+ const SEER_TRADED
+ const SEER_CANCEL
+ const SEER_EGG
+ const SEER_LEVEL_ONLY
+
+ const_def
+ const SEERACTION_MET
+ const SEERACTION_TRADED
+ const SEERACTION_CANT_TELL_1
+ const SEERACTION_CANT_TELL_2
+ const SEERACTION_LEVEL_ONLY
+
+SpecialPokeSeer: ; 4f0bc
+ ld a, SEER_INTRO
+ call PrintSeerText
+ call JoyWaitAorB
+
+ ld b, $6
+ farcall SelectMonFromParty
+ jr c, .cancel
+
+ ld a, [CurPartySpecies]
+ cp EGG
+ jr z, .egg
+
+ call IsAPokemon
+ jr c, .no_mon
+
+ call ReadCaughtData
+ call SeerAction
+ ret
+
+.cancel
+ ld a, SEER_CANCEL
+ call PrintSeerText
+ ret
+
+.no_mon
+ ret
+
+.egg
+ ld a, SEER_EGG
+ call PrintSeerText
+ ret
+; 4f0ee
+
+
+SeerAction: ; 4f0ee
+ ld a, [wSeerAction]
+ ld hl, SeerActions
+ rst JumpTable
+ ret
+; 4f0f6
+
+SeerActions: ; 4f0f6
+ dw SeerAction0
+ dw SeerAction1
+ dw SeerAction2
+ dw SeerAction3
+ dw SeerAction4
+; 4f100
+
+SeerAction0: ; 4f100
+ ld a, SEER_MET_AT
+ call PrintSeerText
+ ld a, SEER_TIME_LEVEL
+ call PrintSeerText
+ call SeerAdvice
+ ret
+; 4f10e
+
+SeerAction1: ; 4f10e
+ call GetCaughtOT
+ ld a, SEER_TRADED
+ call PrintSeerText
+ ld a, SEER_TIME_LEVEL
+ call PrintSeerText
+ call SeerAdvice
+ ret
+; 4f11f
+
+SeerAction2: ; 4f11f
+ ld a, SEER_CANT_TELL
+ call PrintSeerText
+ ret
+; 4f125
+
+SeerAction3: ; 4f125
+ ld a, SEER_CANT_TELL
+ call PrintSeerText
+ ret
+; 4f12b
+
+SeerAction4: ; 4f12b
+ ld a, SEER_LEVEL_ONLY
+ call PrintSeerText
+ call SeerAdvice
+ ret
+; 4f134
+
+ReadCaughtData: ; 4f134
+ ld a, MON_CAUGHTDATA
+ call GetPartyParamLocation
+ ld a, [hli]
+ ld [wSeerCaughtData], a
+ ld a, [hld]
+ ld [wSeerCaughtGender], a
+ or [hl]
+ jr z, .error
+
+ ld a, SEERACTION_TRADED
+ ld [wSeerAction], a
+
+ ld a, MON_ID
+ call GetPartyParamLocation
+ ld a, [PlayerID]
+ cp [hl]
+ jr nz, .traded
+
+ inc hl
+ ld a, [PlayerID + 1]
+ ; cp [hl]
+ jr nz, .traded
+
+ ld a, SEERACTION_MET
+ ld [wSeerAction], a
+
+.traded
+ call GetCaughtLevel
+ call GetCaughtOT
+ call GetCaughtName
+ call GetCaughtTime
+ call GetCaughtLocation
+ and a
+ ret
+
+.error
+ ld a, SEERACTION_CANT_TELL_1
+ ld [wSeerAction], a
+ ret
+; 4f176
+
+GetCaughtName: ; 4f176
+ ld a, [CurPartyMon]
+ ld hl, PartyMonNicknames
+ ld bc, PKMN_NAME_LENGTH
+ call AddNTimes
+ ld de, wSeerNickname
+ ld bc, PKMN_NAME_LENGTH
+ call CopyBytes
+ ret
+; 4f18c
+
+GetCaughtLevel: ; 4f18c
+ ld a, "@"
+ ld hl, wSeerCaughtLevelString
+ ld bc, 4
+ call ByteFill
+
+ ; caught level
+ ; Limited to between 1 and 63 for some reason.
+ ld a, [wSeerCaughtData]
+ and $3f
+ jr z, .unknown
+ cp 1 ; hatched from an egg
+ jr nz, .print
+ ld a, EGG_LEVEL ; egg hatch level
+
+.print
+ ld [wSeerCaughtLevel], a
+ ld hl, wSeerCaughtLevelString
+ ld de, wSeerCaughtLevel
+ lb bc, PRINTNUM_RIGHTALIGN | 1, 3
+ call PrintNum
+ ret
+
+.unknown
+ ld de, wSeerCaughtLevelString
+ ld hl, .unknown_level
+ ld bc, 4
+ call CopyBytes
+ ret
+; 4f1c1
+
+.unknown_level ; 4f1c1
+ db "???@"
+; 4f1c5
+
+GetCaughtTime: ; 4f1c5
+ ld a, [wSeerCaughtData]
+ and $c0
+ jr z, .none
+
+ rlca
+ rlca
+ dec a
+ ld hl, .times
+ call GetNthString
+ ld d, h
+ ld e, l
+ ld hl, wSeerTimeOfDay
+ call CopyName2
+ and a
+ ret
+
+.none
+ ld de, wSeerTimeOfDay
+ call UnknownCaughtData
+ ret
+; 4f1e6
+
+.times ; 4f1e6
+ db "Morning@"
+ db "Day@"
+ db "Night@"
+; 4f1f8
+
+UnknownCaughtData: ; 4f1f8
+ ld hl, .unknown
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ret
+; 4f202
+
+.unknown ; 4f202
+ db "Unknown@"
+; 4f20a
+
+GetCaughtLocation: ; 4f20a
+ ld a, [wSeerCaughtGender]
+ and $7f
+ jr z, .Unknown
+ cp $7f
+ jr z, .event
+ cp $7e
+ jr z, .fail
+ ld e, a
+ farcall GetLandmarkName
+ ld hl, StringBuffer1
+ ld de, wSeerCaughtLocation
+ ld bc, 17
+ call CopyBytes
+ and a
+ ret
+
+.Unknown:
+ ld de, wSeerCaughtLocation
+ jp UnknownCaughtData
+
+.event
+ ld a, SEERACTION_LEVEL_ONLY
+ ld [wSeerAction], a
+ scf
+ ret
+
+.fail
+ ld a, SEERACTION_CANT_TELL_2
+ ld [wSeerAction], a
+ scf
+ ret
+; 4f242
+
+GetCaughtOT: ; 4f242
+ ld a, [CurPartyMon]
+ ld hl, PartyMonOT
+ ld bc, NAME_LENGTH
+ call AddNTimes
+ ld de, wSeerOTName
+ ld bc, NAME_LENGTH
+ call CopyBytes
+
+; this routine is useless in Western localizations
+ ld hl, .male
+ ld a, [wSeerCaughtGender]
+ bit 7, a
+ jr z, .got_grammar
+ ld hl, .female
+
+.got_grammar
+ ld de, wSeerOTNameGrammar
+ ld a, "@"
+ ld [de], a
+ ret
+; 4f26b
+
+.male ; 4f26b
+ db "@"
+.female ; 4f26c
+ db "@"
+; 4f26d
+
+PrintSeerText: ; 4f26d
+ ld e, a
+ ld d, 0
+ ld hl, SeerTexts
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call PrintText
+ ret
+; 4f27c
+
+SeerTexts: ; 4f27c
+ dw SeerIntroText
+ dw SeerCantTellText
+ dw SeerMetAtText
+ dw SeerTimeLevelText
+ dw SeerTradedText
+ dw SeerCancelText
+ dw SeerEggText
+ dw SeerLevelOnlyText
+; 4f28c
+
+SeerIntroText: ; 0x4f28c
+ ; I see all. I know all… Certainly, I know of your #MON!
+ text_jump UnknownText_0x1c475f
+ db "@"
+; 0x4f291
+
+SeerCantTellText: ; 0x4f291
+ ; Whaaaat? I can't tell a thing! How could I not know of this?
+ text_jump UnknownText_0x1c4797
+ db "@"
+; 0x4f296
+
+SeerMetAtText: ; 0x4f296
+ ; Hm… I see you met @ here: @ !
+ text_jump UnknownText_0x1c47d4
+ db "@"
+; 0x4f29b
+
+SeerTimeLevelText: ; 0x4f29b
+ ; The time was @ ! Its level was @ ! Am I good or what?
+ text_jump UnknownText_0x1c47fa
+ db "@"
+; 0x4f2a0
+
+SeerTradedText: ; 0x4f2a0
+ ; Hm… @ came from @ in a trade? @ was where @ met @ !
+ text_jump UnknownText_0x1c4837
+ db "@"
+; 0x4f2a5
+
+SeerLevelOnlyText: ; 0x4f2a5
+ ; What!? Incredible! I don't understand how, but it is incredible! You are special. I can't tell where you met it, but it was at level @ . Am I good or what?
+ text_jump UnknownText_0x1c487f
+ db "@"
+; 0x4f2aa
+
+SeerEggText: ; 0x4f2aa
+ ; Hey! That's an EGG! You can't say that you've met it yet…
+ text_jump UnknownText_0x1c491d
+ db "@"
+; 0x4f2af
+
+SeerCancelText: ; 0x4f2af
+ ; Fufufu! I saw that you'd do nothing!
+ text_jump UnknownText_0x1c4955
+ db "@"
+; 0x4f2b4
+
+
+SeerAdvice: ; 4f2b4
+ ld a, MON_LEVEL
+ call GetPartyParamLocation
+ ld a, [wSeerCaughtLevel]
+ ld c, a
+ ld a, [hl]
+ sub c
+ ld c, a
+
+ ld hl, SeerAdviceTexts
+ ld de, 3
+.next
+ cp [hl]
+ jr c, .print
+ jr z, .print
+ add hl, de
+ jr .next
+
+.print
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call PrintText
+ ret
+; 4f2d6
+
+SeerAdviceTexts: ; 4f2d6
+; level, text
+ dbw 9, SeerAdvice1
+ dbw 29, SeerAdvice2
+ dbw 59, SeerAdvice3
+ dbw 89, SeerAdvice4
+ dbw 100, SeerAdvice5
+ dbw 255, SeerAdvice1
+; 4f2e8
+
+SeerAdvice1: ; 0x4f2e8
+ ; Incidentally… It would be wise to raise your #MON with a little more care.
+ text_jump UnknownText_0x1c497a
+ db "@"
+; 0x4f2ed
+
+SeerAdvice2: ; 0x4f2ed
+ ; Incidentally… It seems to have grown a little. @ seems to be becoming more confident.
+ text_jump UnknownText_0x1c49c6
+ db "@"
+; 0x4f2f2
+
+SeerAdvice3: ; 0x4f2f2
+ ; Incidentally… @ has grown. It's gained much strength.
+ text_jump UnknownText_0x1c4a21
+ db "@"
+; 0x4f2f7
+
+SeerAdvice4: ; 0x4f2f7
+ ; Incidentally… It certainly has grown mighty! This @ must have come through numerous #MON battles. It looks brimming with confidence.
+ text_jump UnknownText_0x1c4a5b
+ db "@"
+; 0x4f2fc
+
+SeerAdvice5: ; 0x4f2fc
+ ; Incidentally… I'm impressed by your dedication. It's been a long time since I've seen a #MON as mighty as this @ . I'm sure that seeing @ in battle would excite anyone.
+ text_jump UnknownText_0x1c4ae5
+ db "@"
+; 0x4f301
+
+
+GetCaughtGender: ; 4f301
+ ld hl, MON_CAUGHTGENDER
+ add hl, bc
+
+ ld a, [hl]
+ and $7f
+ jr z, .genderless
+ cp $7f
+ jr z, .genderless
+
+ ld a, [hl]
+ and $80
+ jr nz, .male
+ ld c, 1
+ ret
+
+.male
+ ld c, 2
+ ret
+
+.genderless
+ ld c, 0
+ ret
+; 4f31c
diff --git a/engine/events/pokecenter_pc.asm b/engine/events/pokecenter_pc.asm
new file mode 100755
index 000000000..7045dc1c8
--- /dev/null
+++ b/engine/events/pokecenter_pc.asm
@@ -0,0 +1,678 @@
+PokemonCenterPC: ; 1559a
+ call PC_CheckPartyForPokemon
+ ret c
+ call PC_PlayBootSound
+ ld hl, PokecenterPCText_BootedUpPC
+ call PC_DisplayText
+ ld hl, PokecenterPCText_AccessWhosePC
+ call PC_DisplayTextWaitMenu
+ ld hl, .TopMenu
+ call LoadMenuDataHeader
+.loop
+ xor a
+ ld [hBGMapMode], a
+ call .ChooseWhichPCListToUse
+ ld [wWhichIndexSet], a
+ call DoNthMenu
+ jr c, .shutdown
+ ld a, [MenuSelection]
+ ld hl, .JumpTable
+ call MenuJumptable
+ jr nc, .loop
+
+.shutdown
+ call PC_PlayShutdownSound
+ call ExitMenu
+ call CloseWindow
+ ret
+
+.TopMenu:
+ db $48 ; flags
+ db 00, 00 ; start coords
+ db 12, 15 ; end coords
+ dw .MenuData2
+ db 1 ; default option
+
+.MenuData2:
+ db $a0 ; flags
+ db 0 ; items
+ dw .WhichPC
+ dw PlaceNthMenuStrings
+ dw .JumpTable
+
+.JumpTable:
+ dw PlayersPC, .String_PlayersPC
+ dw BillsPC, .String_BillsPC
+ dw OaksPC, .String_OaksPC
+ dw HallOfFamePC, .String_HallOfFame
+ dw TurnOffPC, .String_TurnOff
+
+.String_PlayersPC: db "<PLAYER>'s PC@"
+.String_BillsPC: db "BILL's PC@"
+.String_OaksPC: db "PROF.OAK's PC@"
+.String_HallOfFame: db "HALL OF FAME@"
+.String_TurnOff: db "TURN OFF@"
+
+.WhichPC:
+ ; before pokedex
+ db 3 ; items
+ db 1, 0, 4 ; bill's, player's, turn off
+ db -1
+
+ ; before Hall Of Fame
+ db 4 ; items
+ db 1, 0, 2, 4 ; bill's, player's, oak's, turn off
+ db -1
+
+ ; postgame
+ db 5 ; items
+ db 1, 0, 2, 3, 4 ; bill's, player's, oak's, hall of fame, turn off
+ db -1
+
+.ChooseWhichPCListToUse:
+ call CheckReceivedDex
+ jr nz, .got_dex
+ ld a, $0
+ ret
+
+.got_dex
+ ld a, [wHallOfFameCount]
+ and a
+ ld a, $1
+ ret z
+ ld a, $2
+ ret
+; 15650
+
+PC_CheckPartyForPokemon: ; 15650
+ ld a, [PartyCount]
+ and a
+ ret nz
+ ld de, SFX_CHOOSE_PC_OPTION
+ call PlaySFX
+ ld hl, .MustHavePokemonToUse
+ call PC_DisplayText
+ scf
+ ret
+
+.MustHavePokemonToUse:
+ ; Bzzzzt! You must have a #MON to use this!
+ text_jump UnknownText_0x1c1328
+ db "@"
+; 0x15668
+
+BillsPC: ; 15668
+ call PC_PlayChoosePCSound
+ ld hl, PokecenterPCText_AccessedBillsPC
+ call PC_DisplayText
+ farcall _BillsPC
+ and a
+ ret
+; 15679 (5:5679)
+
+PlayersPC: ; 15679
+ call PC_PlayChoosePCSound
+ ld hl, PokecenterPCText_AccessedOwnPC
+ call PC_DisplayText
+ ld b, $0
+ call _PlayersPC
+ and a
+ ret
+; 15689
+
+OaksPC: ; 15689
+ call PC_PlayChoosePCSound
+ ld hl, PokecenterPCText_AccessedOaksPC
+ call PC_DisplayText
+ farcall ProfOaksPC
+ and a
+ ret
+; 1569a
+
+HallOfFamePC: ; 1569a
+ call PC_PlayChoosePCSound
+ call FadeToMenu
+ farcall _HallOfFamePC
+ call CloseSubmenu
+ and a
+ ret
+; 156ab
+
+TurnOffPC: ; 156ab
+ ld hl, PokecenterPCText_LinkClosed
+ call PrintText
+ scf
+ ret
+; 156b3
+
+PC_PlayBootSound: ; 156b3
+ ld de, SFX_BOOT_PC
+ jr PC_WaitPlaySFX
+
+PC_PlayShutdownSound: ; 156b8
+ ld de, SFX_SHUT_DOWN_PC
+ call PC_WaitPlaySFX
+ call WaitSFX
+ ret
+
+PC_PlayChoosePCSound: ; 156c2
+ ld de, SFX_CHOOSE_PC_OPTION
+ jr PC_WaitPlaySFX
+
+PC_PlaySwapItemsSound: ; 156c7
+ ld de, SFX_SWITCH_POKEMON
+ call PC_WaitPlaySFX
+ ld de, SFX_SWITCH_POKEMON
+
+PC_WaitPlaySFX: ; 156d0
+ push de
+ call WaitSFX
+ pop de
+ call PlaySFX
+ ret
+; 156d9
+
+_KrissHousePC: ; 156d9
+ call PC_PlayBootSound
+ ld hl, UnknownText_0x156ff
+ call PC_DisplayText
+ ld b, $1
+ call _PlayersPC
+ and a
+ jr nz, .asm_156f9
+ call OverworldTextModeSwitch
+ call ApplyTilemap
+ call UpdateSprites
+ call PC_PlayShutdownSound
+ ld c, $0
+ ret
+
+.asm_156f9
+ call ClearBGPalettes
+ ld c, $1
+ ret
+; 156ff
+
+UnknownText_0x156ff: ; 0x156ff
+ ; turned on the PC.
+ text_jump UnknownText_0x1c1353
+ db "@"
+; 0x15704
+
+_PlayersPC: ; 15704
+ ld a, b
+ ld [wWhichIndexSet], a
+ ld hl, UnknownText_0x157cc
+ call PC_DisplayTextWaitMenu
+ call Function15715
+ call ExitMenu
+ ret
+; 15715
+
+Function15715: ; 15715
+ xor a
+ ld [wPCItemsCursor], a
+ ld [wPCItemsScrollPosition], a
+ ld hl, KrissPCMenuData
+ call LoadMenuDataHeader
+.asm_15722
+ call UpdateTimePals
+ call DoNthMenu
+ jr c, .asm_15731
+ call MenuJumptable
+ jr nc, .asm_15722
+ jr .asm_15732
+
+.asm_15731
+ xor a
+
+.asm_15732
+ call ExitMenu
+ ret
+; 15736
+
+KrissPCMenuData: ; 0x15736
+ db %01000000
+ db 0, 0 ; top left corner coords (y, x)
+ db 12, 15 ; bottom right corner coords (y, x)
+ dw .KrissPCMenuData2
+ db 1 ; default selected option
+
+.KrissPCMenuData2:
+ db %10100000 ; bit7
+ db 0 ; # items?
+ dw .KrissPCMenuList1
+ dw PlaceNthMenuStrings
+ dw .KrissPCMenuPointers
+
+.KrissPCMenuPointers: ; 0x15746
+ dw KrisWithdrawItemMenu, .WithdrawItem
+ dw KrisDepositItemMenu, .DepositItem
+ dw KrisTossItemMenu, .TossItem
+ dw KrisMailBoxMenu, .MailBox
+ dw KrisDecorationMenu, .Decoration
+ dw KrisLogOffMenu, .LogOff
+ dw KrisLogOffMenu, .TurnOff
+
+.WithdrawItem: db "WITHDRAW ITEM@"
+.DepositItem: db "DEPOSIT ITEM@"
+.TossItem: db "TOSS ITEM@"
+.MailBox: db "MAIL BOX@"
+.Decoration: db "DECORATION@"
+.TurnOff: db "TURN OFF@"
+.LogOff: db "LOG OFF@"
+
+WITHDRAW_ITEM EQU 0
+DEPOSIT_ITEM EQU 1
+TOSS_ITEM EQU 2
+MAIL_BOX EQU 3
+DECORATION EQU 4
+TURN_OFF EQU 5
+LOG_OFF EQU 6
+
+.KrissPCMenuList1:
+ db 5
+ db WITHDRAW_ITEM
+ db DEPOSIT_ITEM
+ db TOSS_ITEM
+ db MAIL_BOX
+ db TURN_OFF
+ db -1
+
+.KrissPCMenuList2:
+ db 6
+ db WITHDRAW_ITEM
+ db DEPOSIT_ITEM
+ db TOSS_ITEM
+ db MAIL_BOX
+ db DECORATION
+ db LOG_OFF
+ db -1
+
+PC_DisplayTextWaitMenu: ; 157bb
+ ld a, [Options]
+ push af
+ set NO_TEXT_SCROLL, a
+ ld [Options], a
+ call MenuTextBox
+ pop af
+ ld [Options], a
+ ret
+; 157cc
+
+UnknownText_0x157cc: ; 0x157cc
+ ; What do you want to do?
+ text_jump UnknownText_0x1c1368
+ db "@"
+; 0x157d1
+
+KrisWithdrawItemMenu: ; 0x157d1
+ call LoadStandardMenuDataHeader
+ farcall ClearPCItemScreen
+.loop
+ call PCItemsJoypad
+ jr c, .quit
+ call .Submenu
+ jr .loop
+
+.quit
+ call CloseSubmenu
+ xor a
+ ret
+
+.Submenu:
+ ; check if the item has a quantity
+ farcall _CheckTossableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr z, .askquantity
+
+ ; items without quantity are always ×1
+ ld a, 1
+ ld [wItemQuantityChangeBuffer], a
+ jr .withdraw
+
+.askquantity
+ ld hl, .HowManyText
+ call MenuTextBox
+ farcall SelectQuantityToToss
+ call ExitMenu
+ call ExitMenu
+ jr c, .done
+
+.withdraw
+ ld a, [wItemQuantityChangeBuffer]
+ ld [Buffer1], a ; quantity
+ ld a, [CurItemQuantity]
+ ld [Buffer2], a
+ ld hl, NumItems
+ call ReceiveItem
+ jr nc, .PackFull
+ ld a, [Buffer1]
+ ld [wItemQuantityChangeBuffer], a
+ ld a, [Buffer2]
+ ld [CurItemQuantity], a
+ ld hl, PCItems
+ call TossItem
+ predef PartyMonItemName
+ ld hl, .WithdrewText
+ call MenuTextBox
+ xor a
+ ld [hBGMapMode], a
+ call ExitMenu
+ ret
+
+.PackFull:
+ ld hl, .NoRoomText
+ call MenuTextBoxBackup
+ ret
+
+.done
+ ret
+
+.HowManyText: ; 0x15850
+ text_jump _KrissPCHowManyWithdrawText
+ db "@"
+
+.WithdrewText: ; 0x15855
+ text_jump _KrissPCWithdrewItemsText
+ db "@"
+
+.NoRoomText: ; 0x1585a
+ text_jump _KrissPCNoRoomWithdrawText
+ db "@"
+
+KrisTossItemMenu: ; 0x1585f
+ call LoadStandardMenuDataHeader
+ farcall ClearPCItemScreen
+.loop
+ call PCItemsJoypad
+ jr c, .quit
+ ld de, PCItems
+ farcall TossItemFromPC
+ jr .loop
+
+.quit
+ call CloseSubmenu
+ xor a
+ ret
+; 0x1587d
+
+KrisDecorationMenu: ; 0x1587d
+ farcall _KrisDecorationMenu
+ ld a, c
+ and a
+ ret z
+ scf
+ ret
+; 0x15888
+
+KrisLogOffMenu: ; 0x15888
+ xor a
+ scf
+ ret
+; 0x1588b
+
+KrisDepositItemMenu: ; 0x1588b
+ call .CheckItemsInBag
+ jr c, .nope
+ call DisableSpriteUpdates
+ call LoadStandardMenuDataHeader
+ farcall DepositSellInitPackBuffers
+.loop
+ farcall DepositSellPack
+ ld a, [wcf66]
+ and a
+ jr z, .close
+ call .TryDepositItem
+ farcall CheckRegisteredItem
+ jr .loop
+
+.close
+ call CloseSubmenu
+
+.nope
+ xor a
+ ret
+
+.CheckItemsInBag:
+ farcall HasNoItems
+ ret nc
+ ld hl, .NoItemsInBag
+ call MenuTextBoxBackup
+ scf
+ ret
+
+.NoItemsInBag:
+ ; No items here!
+ text_jump UnknownText_0x1c13df
+ db "@"
+
+.TryDepositItem:
+ ld a, [wSpriteUpdatesEnabled]
+ push af
+ ld a, $0
+ ld [wSpriteUpdatesEnabled], a
+ farcall CheckItemMenu
+ ld a, [wItemAttributeParamBuffer]
+ ld hl, .dw
+ rst JumpTable
+ pop af
+ ld [wSpriteUpdatesEnabled], a
+ ret
+
+.dw
+ dw .tossable
+ dw .no_toss
+ dw .no_toss
+ dw .no_toss
+ dw .tossable
+ dw .tossable
+ dw .tossable
+
+.no_toss
+ ret
+
+.tossable
+ ld a, [Buffer1]
+ push af
+ ld a, [Buffer2]
+ push af
+ call .DepositItem_
+ pop af
+ ld [Buffer2], a
+ pop af
+ ld [Buffer1], a
+ ret
+
+.DepositItem_:
+ farcall _CheckTossableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr z, .AskQuantity
+ ld a, $1
+ ld [wItemQuantityChangeBuffer], a
+ jr .DepositItem
+
+.AskQuantity:
+ ld hl, .HowManyText
+ call MenuTextBox
+ farcall SelectQuantityToToss
+ push af
+ call ExitMenu
+ call ExitMenu
+ pop af
+ jr c, .DeclinedToDeposit
+
+.DepositItem:
+ ld a, [wItemQuantityChangeBuffer]
+ ld [Buffer1], a
+ ld a, [CurItemQuantity]
+ ld [Buffer2], a
+ ld hl, PCItems
+ call ReceiveItem
+ jr nc, .NoRoomInPC
+ ld a, [Buffer1]
+ ld [wItemQuantityChangeBuffer], a
+ ld a, [Buffer2]
+ ld [CurItemQuantity], a
+ ld hl, NumItems
+ call TossItem
+ predef PartyMonItemName
+ ld hl, .DepositText
+ call PrintText
+ ret
+
+.NoRoomInPC:
+ ld hl, .NoRoomText
+ call PrintText
+ ret
+
+.DeclinedToDeposit:
+ and a
+ ret
+
+.HowManyText: ; 0x1596e
+ text_jump _KrissPCHowManyDepositText
+ db "@"
+
+.DepositText: ; 0x15973
+ text_jump _KrissPCDepositItemsText
+ db "@"
+
+.NoRoomText: ; 0x15978
+ text_jump _KrissPCNoRoomDepositText
+ db "@"
+
+KrisMailBoxMenu: ; 0x1597d
+ farcall _KrisMailBoxMenu
+ xor a
+ ret
+; 0x15985
+
+PCItemsJoypad: ; 0x15985
+ xor a
+ ld [wSwitchItem], a
+.loop
+ ld a, [wSpriteUpdatesEnabled]
+ push af
+ ld a, $0
+ ld [wSpriteUpdatesEnabled], a
+ ld hl, .PCItemsMenuData
+ call CopyMenuDataHeader
+ hlcoord 0, 0
+ ld b, 10
+ ld c, 18
+ call TextBox
+ ld a, [wPCItemsCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wPCItemsScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wPCItemsScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wPCItemsCursor], a
+ pop af
+ ld [wSpriteUpdatesEnabled], a
+ ld a, [wSwitchItem]
+ and a
+ jr nz, .moving_stuff_around
+ ld a, [wMenuJoypad]
+ cp B_BUTTON
+ jr z, .b_1
+ cp A_BUTTON
+ jr z, .a_1
+ cp SELECT
+ jr z, .select_1
+ jr .next
+
+.moving_stuff_around
+ ld a, [wMenuJoypad]
+ cp B_BUTTON
+ jr z, .b_2
+ cp A_BUTTON
+ jr z, .a_select_2
+ cp SELECT
+ jr z, .a_select_2
+ jr .next
+
+.b_2
+ xor a
+ ld [wSwitchItem], a
+ jr .next
+
+.a_select_2
+ call PC_PlaySwapItemsSound
+.select_1
+ farcall SwitchItemsInBag
+.next
+ jp .loop
+
+.a_1
+ farcall ScrollingMenu_ClearLeftColumn
+ call PlaceHollowCursor
+ and a
+ ret
+
+.b_1
+ scf
+ ret
+
+.PCItemsMenuData:
+ db %01000000
+ db 1, 4 ; start coords
+ db 10, 18 ; end coords
+ dw .MenuData2
+ db 1 ; default option
+
+.MenuData2:
+ db %10110000
+ db 4, 8 ; rows/cols?
+ db 2 ; horizontal spacing?
+ dbw 0, PCItems
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+
+PC_DisplayText: ; 15a20
+ call MenuTextBox
+ call ExitMenu
+ ret
+; 15a27
+
+PokecenterPCText_BootedUpPC: ; 0x15a27
+ ; turned on the PC.
+ text_jump UnknownText_0x1c144d
+ db "@"
+; 0x15a2c
+
+PokecenterPCText_AccessWhosePC: ; 0x15a2c
+ ; Access whose PC?
+ text_jump UnknownText_0x1c1462
+ db "@"
+; 0x15a31
+
+PokecenterPCText_AccessedBillsPC: ; 0x15a31
+ ; BILL's PC accessed. #MON Storage System opened.
+ text_jump UnknownText_0x1c1474
+ db "@"
+; 0x15a36
+
+PokecenterPCText_AccessedOwnPC: ; 0x15a36
+ ; Accessed own PC. Item Storage System opened.
+ text_jump UnknownText_0x1c14a4
+ db "@"
+; 0x15a3b
+
+PokecenterPCText_AccessedOaksPC: ; 0x15a3b
+ ; PROF.OAK's PC accessed. #DEX Rating System opened.
+ text_jump UnknownText_0x1c14d2
+ db "@"
+; 0x15a40
+
+PokecenterPCText_LinkClosed: ; 0x15a40
+ ; … Link closed…
+ text_jump UnknownText_0x1c1505
+ db "@"
+; 0x15a45
diff --git a/engine/events/pokepic.asm b/engine/events/pokepic.asm
new file mode 100755
index 000000000..ea5b3c300
--- /dev/null
+++ b/engine/events/pokepic.asm
@@ -0,0 +1,49 @@
+Pokepic:: ; 244e3
+ ld hl, PokepicMenuDataHeader
+ call CopyMenuDataHeader
+ call MenuBox
+ call UpdateSprites
+ call ApplyTilemap
+ ld b, SCGB_POKEPIC
+ call GetSGBLayout
+ xor a
+ ld [hBGMapMode], a
+ ld a, [CurPartySpecies]
+ ld [CurSpecies], a
+ call GetBaseData
+ ld de, VTiles1
+ predef GetMonFrontpic
+ ld a, [wMenuBorderTopCoord]
+ inc a
+ ld b, a
+ ld a, [wMenuBorderLeftCoord]
+ inc a
+ ld c, a
+ call Coord2Tile
+ ld a, $80
+ ld [hGraphicStartTile], a
+ lb bc, 7, 7
+ predef PlaceGraphic
+ call WaitBGMap
+ ret
+
+ClosePokepic:: ; 24528
+ ld hl, PokepicMenuDataHeader
+ call CopyMenuDataHeader
+ call ClearMenuBoxInterior
+ call WaitBGMap
+ call GetMemSGBLayout
+ xor a
+ ld [hBGMapMode], a
+ call OverworldTextModeSwitch
+ call ApplyTilemap
+ call UpdateSprites
+ call LoadStandardFont
+ ret
+
+PokepicMenuDataHeader: ; 0x24547
+ db $40 ; flags
+ db 04, 06 ; start coords
+ db 13, 14 ; end coords
+ dw NULL
+ db 1 ; default option
diff --git a/engine/events/pokerus/apply_pokerus_tick.asm b/engine/events/pokerus/apply_pokerus_tick.asm
new file mode 100644
index 000000000..3c97fdc5e
--- /dev/null
+++ b/engine/events/pokerus/apply_pokerus_tick.asm
@@ -0,0 +1,26 @@
+ApplyPokerusTick: ; 13988
+; decreases all pokemon's pokerus counter by b. if the lower nybble reaches zero, the pokerus is cured.
+ ld hl, PartyMon1PokerusStatus ; PartyMon1 + MON_PKRS
+ ld a, [PartyCount]
+ and a
+ ret z ; make sure it's not wasting time on an empty party
+ ld c, a
+.loop
+ ld a, [hl]
+ and $f ; lower nybble is the number of days remaining
+ jr z, .next ; if already 0, skip
+ sub b ; subtract the number of days
+ jr nc, .ok ; max(result, 0)
+ xor a
+.ok
+ ld d, a ; back up this value because we need to preserve the strain (upper nybble)
+ ld a, [hl]
+ and $f0
+ add d
+ ld [hl], a ; this prevents a cured pokemon from recontracting pokerus
+.next
+ ld de, PARTYMON_STRUCT_LENGTH
+ add hl, de
+ dec c
+ jr nz, .loop
+ ret
diff --git a/engine/events/pokerus/check_pokerus.asm b/engine/events/pokerus/check_pokerus.asm
new file mode 100644
index 000000000..285024754
--- /dev/null
+++ b/engine/events/pokerus/check_pokerus.asm
@@ -0,0 +1,25 @@
+CheckPokerus: ; 4d860
+; Return carry if a monster in your party has Pokerus
+
+; Get number of monsters to iterate over
+ ld a, [PartyCount]
+ and a
+ jr z, .NoPokerus
+ ld b, a
+; Check each monster in the party for Pokerus
+ ld hl, PartyMon1PokerusStatus
+ ld de, PARTYMON_STRUCT_LENGTH
+.Check:
+ ld a, [hl]
+ and $0f ; only the bottom nybble is used
+ jr nz, .HasPokerus
+; Next PartyMon
+ add hl, de
+ dec b
+ jr nz, .Check
+.NoPokerus:
+ and a
+ ret
+.HasPokerus:
+ scf
+ ret
diff --git a/engine/events/pokerus/pokerus.asm b/engine/events/pokerus/pokerus.asm
new file mode 100644
index 000000000..3e5e094e4
--- /dev/null
+++ b/engine/events/pokerus/pokerus.asm
@@ -0,0 +1,160 @@
+GivePokerusAndConvertBerries: ; 2ed44
+ call ConvertBerriesToBerryJuice
+ ld hl, PartyMon1PokerusStatus
+ ld a, [PartyCount]
+ ld b, a
+ ld de, PARTYMON_STRUCT_LENGTH
+; Check to see if any of your Pokemon already has Pokerus.
+; If so, sample its spread through your party.
+; This means that you cannot get Pokerus de novo while
+; a party member has an active infection.
+.loopMons
+ ld a, [hl]
+ and $f
+ jr nz, .TrySpreadPokerus
+ add hl, de
+ dec b
+ jr nz, .loopMons
+
+; If we haven't been to Goldenrod City at least once,
+; prevent the contraction of Pokerus.
+ ld hl, StatusFlags2
+ bit 6, [hl]
+ ret z
+ call Random
+ ld a, [hRandomAdd]
+ and a
+ ret nz
+ ld a, [hRandomSub]
+ cp $3
+ ret nc ; 3/65536 chance (00 00, 00 01 or 00 02)
+ ld a, [PartyCount]
+ ld b, a
+.randomMonSelectLoop
+ call Random
+ and $7
+ cp b
+ jr nc, .randomMonSelectLoop
+ ld hl, PartyMon1PokerusStatus
+ call GetPartyLocation ; get pokerus byte of random mon
+ ld a, [hl]
+ and $f0
+ ret nz ; if it already has pokerus, do nothing
+.randomPokerusLoop ; Simultaneously sample the strain and duration
+ call Random
+ and a
+ jr z, .randomPokerusLoop
+ ld b, a
+ and $f0
+ jr z, .load_pkrs
+ ld a, b
+ and $7
+ inc a
+.load_pkrs
+ ld b, a ; this should come before the label
+ swap b
+ and $3
+ inc a
+ add b
+ ld [hl], a
+ ret
+
+.TrySpreadPokerus:
+ call Random
+ cp 1 + 33 percent
+ ret nc ; 1/3 chance
+
+ ld a, [PartyCount]
+ cp 1
+ ret z ; only one mon, nothing to do
+
+ ld c, [hl]
+ ld a, b
+ cp 2
+ jr c, .checkPreviousMonsLoop ; no more mons after this one, go backwards
+
+ call Random
+ cp 1 + 50 percent
+ jr c, .checkPreviousMonsLoop ; 1/2 chance, go backwards
+.checkFollowingMonsLoop
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .infectMon
+ ld c, a
+ and $3
+ ret z ; if mon has cured pokerus, stop searching
+ dec b ; go on to next mon
+ ld a, b
+ cp 1
+ jr nz, .checkFollowingMonsLoop ; no more mons left
+ ret
+
+.checkPreviousMonsLoop
+ ld a, [PartyCount]
+ cp b
+ ret z ; no more mons
+ ld a, l
+ sub e
+ ld l, a
+ ld a, h
+ sbc d
+ ld h, a
+ ld a, [hl]
+ and a
+ jr z, .infectMon
+ ld c, a
+ and $3
+ ret z ; if mon has cured pokerus, stop searching
+ inc b ; go on to next mon
+ jr .checkPreviousMonsLoop
+
+.infectMon
+ ld a, c
+ and $f0
+ ld b, a
+ ld a, c
+ swap a
+ and $3
+ inc a
+ add b
+ ld [hl], a
+ ret
+
+; any berry held by a Shuckle may be converted to berry juice
+ConvertBerriesToBerryJuice: ; 2ede6
+ ld hl, StatusFlags2
+ bit 6, [hl]
+ ret z
+ call Random
+ cp $10
+ ret nc ; 1/16 chance
+ ld hl, PartyMons
+ ld a, [PartyCount]
+.partyMonLoop
+ push af
+ push hl
+ ld a, [hl]
+ cp SHUCKLE
+ jr nz, .loopMon
+ ld bc, MON_ITEM
+ add hl, bc
+ ld a, [hl]
+ cp BERRY
+ jr z, .convertToJuice
+
+.loopMon
+ pop hl
+ ld bc, PARTYMON_STRUCT_LENGTH
+ add hl, bc
+ pop af
+ dec a
+ jr nz, .partyMonLoop
+ ret
+
+.convertToJuice
+ ld a, BERRY_JUICE
+ ld [hl], a
+ pop hl
+ pop af
+ ret
diff --git a/engine/events/print_photo.asm b/engine/events/print_photo.asm
new file mode 100755
index 000000000..06b01bbcf
--- /dev/null
+++ b/engine/events/print_photo.asm
@@ -0,0 +1,61 @@
+PhotoStudio: ; 16dc7
+ ld hl, .Text_AskWhichMon
+ call PrintText
+ farcall SelectMonFromParty
+ jr c, .cancel
+ ld a, [CurPartySpecies]
+ cp EGG
+ jr z, .egg
+
+ ld hl, .Text_HoldStill
+ call PrintText
+ call DisableSpriteUpdates
+ farcall PrintPartymon
+ call ReturnToMapWithSpeechTextbox
+ ld a, [hPrinter]
+ and a
+ jr nz, .cancel
+ ld hl, .Text_Presto
+ jr .print_text
+
+.cancel
+ ld hl, .Text_NoPicture
+ jr .print_text
+
+.egg
+ ld hl, .Text_Egg
+
+.print_text
+ call PrintText
+ ret
+; 16e04
+
+.Text_AskWhichMon: ; 0x16e04
+ ; Which #MON should I photo- graph?
+ text_jump UnknownText_0x1be024
+ db "@"
+; 0x16e09
+
+.Text_HoldStill: ; 0x16e09
+ ; All righty. Hold still for a bit.
+ text_jump UnknownText_0x1be047
+ db "@"
+; 0x16e0e
+
+.Text_Presto: ; 0x16e0e
+ ; Presto! All done. Come again, OK?
+ text_jump UnknownText_0x1be06a
+ db "@"
+; 0x16e13
+
+.Text_NoPicture: ; 0x16e13
+ ; Oh, no picture? Come again, OK?
+ text_jump UnknownText_0x1c0000
+ db "@"
+; 0x16e18
+
+.Text_Egg: ; 0x16e18
+ ; An EGG? My talent is worth more…
+ text_jump UnknownText_0x1c0021
+ db "@"
+; 0x16e1d
diff --git a/engine/events/print_unown.asm b/engine/events/print_unown.asm
new file mode 100644
index 000000000..7841a688b
--- /dev/null
+++ b/engine/events/print_unown.asm
@@ -0,0 +1,233 @@
+UnownPrinter: ; 16be4
+ ld a, [UnownDex]
+ and a
+ ret z
+
+ ld a, [hInMenu]
+ push af
+ ld a, $1
+ ld [hInMenu], a
+ ld a, [Options]
+ push af
+ set NO_TEXT_SCROLL, a
+ ld [Options], a
+ call ClearBGPalettes
+ call ClearTileMap
+
+ ld de, UnownDexATile
+ ld hl, VTiles1 tile $6f
+ lb bc, BANK(UnownDexBTile), 1
+ call Request1bpp
+
+ ld de, UnownDexBTile
+ ld hl, VTiles1 tile $75
+ lb bc, BANK(UnownDexBTile), 1
+ call Request1bpp
+
+ hlcoord 0, 0
+ lb bc, 3, 18
+ call TextBox
+
+ hlcoord 0, 5
+ lb bc, 7, 7
+ call TextBox
+
+ hlcoord 0, 14
+ lb bc, 2, 18
+ call TextBox
+
+ hlcoord 1, 2
+ ld de, AlphRuinsStampString
+ call PlaceString
+
+ hlcoord 1, 16
+ ld de, UnownDexDoWhatString
+ call PlaceString
+
+ hlcoord 10, 6
+ ld de, UnownDexMenuString
+ call PlaceString
+
+ xor a
+ ld [wJumptableIndex], a
+ call .UpdateUnownFrontpic
+ call WaitBGMap
+
+ ld a, UNOWN
+ ld [CurPartySpecies], a
+ xor a
+ ld [TempMonDVs], a
+ ld [TempMonDVs + 1], a
+
+ ld b, SCGB_TRAINER_OR_MON_FRONTPIC_PALS
+ call GetSGBLayout
+ call SetPalettes
+
+.joy_loop
+ call JoyTextDelay
+
+ ld a, [hJoyPressed]
+ and B_BUTTON
+ jr nz, .pressed_b
+
+ ld a, [hJoyPressed]
+ and A_BUTTON
+ jr nz, .pressed_a
+
+ call .LeftRight
+ call DelayFrame
+ jr .joy_loop
+
+.pressed_a
+ ld a, [wJumptableIndex]
+ push af
+ farcall PrintUnownStamp
+ call RestartMapMusic
+ pop af
+ ld [wJumptableIndex], a
+ jr .joy_loop
+
+.pressed_b
+ pop af
+ ld [Options], a
+ pop af
+ ld [hInMenu], a
+ call ReturnToMapFromSubmenu
+ ret
+; 16ca0
+
+.LeftRight: ; 16ca0
+ ld a, [hJoyLast]
+ and D_RIGHT
+ jr nz, .press_right
+ ld a, [hJoyLast]
+ and D_LEFT
+ jr nz, .press_left
+ ret
+
+.press_left
+ ld hl, wJumptableIndex
+ ld a, [hl]
+ and a
+ jr nz, .wrap_around_left
+ ld [hl], 26 + 1
+.wrap_around_left
+ dec [hl]
+ jr .return
+
+.press_right
+ ld hl, wJumptableIndex
+ ld a, [hl]
+ cp 26
+ jr c, .wrap_around_right
+ ld [hl], -1
+.wrap_around_right
+ inc [hl]
+
+.return
+ call .UpdateUnownFrontpic
+ ret
+; 16cc8
+
+.UpdateUnownFrontpic: ; 16cc8
+ ld a, [wJumptableIndex]
+ cp 26
+ jr z, .vacant
+ inc a
+ ld [UnownLetter], a
+ ld a, UNOWN
+ ld [CurPartySpecies], a
+ xor a
+ ld [wBoxAlignment], a
+ ld de, VTiles2
+ predef GetMonFrontpic
+ call .Load2bppToSRAM
+ hlcoord 1, 6
+ xor a
+ ld [hGraphicStartTile], a
+ lb bc, 7, 7
+ predef PlaceGraphic
+ ld de, VTiles2 tile $31
+ farcall RotateUnownFrontpic
+ ret
+
+.Load2bppToSRAM: ; 16cff
+ ld a, [rSVBK]
+ push af
+ ld a, $6
+ ld [rSVBK], a
+
+ ld a, BANK(sScratch)
+ call GetSRAMBank
+ ld de, wDecompressScratch
+ ld hl, sScratch
+ ld a, [hROMBank]
+ ld b, a
+ ld c, $31
+ call Get2bpp
+ call CloseSRAM
+
+ pop af
+ ld [rSVBK], a
+ ret
+
+.vacant
+ hlcoord 1, 6
+ lb bc, 7, 7
+ call ClearBox
+ hlcoord 1, 9
+ ld de, UnownDexVacantString
+ call PlaceString
+ xor a
+ call GetSRAMBank
+ ld hl, sScratch
+ ld bc, $31 tiles
+ xor a
+ call ByteFill
+ ld hl, VTiles2 tile $31
+ ld de, sScratch
+ ld c, $31
+ ld a, [hROMBank]
+ ld b, a
+ call Get2bpp
+ call CloseSRAM
+ ld c, 20
+ call DelayFrames
+ ret
+; 16d57
+
+AlphRuinsStampString:
+ db " ALPH RUINS STAMP@"
+
+UnownDexDoWhatString:
+ db "Do what?@"
+
+UnownDexMenuString:
+ db "♂ PRINT"
+ next "♀ CANCEL"
+ next "← PREVIOUS"
+ next "→ NEXT"
+ db "@"
+
+UnownDexVacantString:
+ db "VACANT@"
+; 16d9c
+
+UnownDexATile: ; 16d9c
+INCBIN "gfx/printer/bold_a.1bpp"
+UnownDexBTile: ; 16da4
+INCBIN "gfx/printer/bold_b.1bpp"
+; 16dac
+
+PlaceUnownPrinterFrontpic: ; 16dac
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ hlcoord 7, 11
+ ld a, $31
+ ld [hGraphicStartTile], a
+ lb bc, 7, 7
+ predef PlaceGraphic
+ ret
+; 16dc7
diff --git a/engine/events/print_unown_2.asm b/engine/events/print_unown_2.asm
new file mode 100644
index 000000000..057db5176
--- /dev/null
+++ b/engine/events/print_unown_2.asm
@@ -0,0 +1,111 @@
+RotateUnownFrontpic: ; e0000
+; something to do with Unown printer
+ push de
+ xor a
+ call GetSRAMBank
+ ld hl, sScratch
+ ld bc, 0
+.loop
+ push bc
+ push hl
+ push bc
+ ld de, wd002
+ call .Copy
+ call .Rotate
+ ld hl, UnownPrinter_OverworldMapRectangle
+ pop bc
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld e, a
+ ld d, [hl]
+ ld hl, wd012
+ call .Copy
+ pop hl
+ ld bc, $10
+ add hl, bc
+ pop bc
+ inc c
+ ld a, c
+ cp 7 * 7
+ jr c, .loop
+
+ ld hl, OverworldMap
+ ld de, sScratch
+ ld bc, 7 * 7 tiles
+ call CopyBytes
+ pop hl
+ ld de, sScratch
+ ld c, 7 * 7
+ ld a, [hROMBank]
+ ld b, a
+ call Get2bpp
+ call CloseSRAM
+ ret
+
+.Copy: ; e004e
+ ld c, $10
+.loop_copy
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .loop_copy
+ ret
+
+.Rotate: ; e0057
+ ld hl, wd012
+ ld e, %10000000
+ ld d, 8
+.loop_decompress
+ push hl
+ ld hl, wd002
+ call .CountSetBit
+ pop hl
+ ld a, b
+ ld [hli], a
+ push hl
+ ld hl, wd003
+ call .CountSetBit
+ pop hl
+ ld a, b
+ ld [hli], a
+ srl e
+ dec d
+ jr nz, .loop_decompress
+ ret
+
+.CountSetBit: ; e0078
+ ld b, 0
+ ld c, 8
+.loop_count
+ ld a, [hli]
+ and e
+ jr z, .clear
+ scf
+ jr .apply
+
+.clear
+ and a
+
+.apply
+ rr b
+ inc hl
+ dec c
+ jr nz, .loop_count
+ ret
+
+overworldmaprect: MACRO
+y = 0
+rept \1
+x = \1 * (\2 +- 1) + y
+rept \2
+ dw OverworldMap tile x
+x = x +- \2
+endr
+y = y + 1
+endr
+endm
+
+UnownPrinter_OverworldMapRectangle: ; e008b
+ overworldmaprect 7, 7
diff --git a/engine/events/prof_oaks_pc.asm b/engine/events/prof_oaks_pc.asm
new file mode 100755
index 000000000..69949940b
--- /dev/null
+++ b/engine/events/prof_oaks_pc.asm
@@ -0,0 +1,213 @@
+ProfOaksPC: ; 0x265d3
+ ld hl, OakPCText1
+ call MenuTextBox
+ call YesNoBox
+ jr c, .shutdown
+ call ProfOaksPCBoot ; player chose "yes"?
+.shutdown
+ ld hl, OakPCText4
+ call PrintText
+ call JoyWaitAorB
+ call ExitMenu
+ ret
+
+ProfOaksPCBoot ; 0x265ee
+ ld hl, OakPCText2
+ call PrintText
+ call Rate
+ call PlaySFX ; sfx loaded by previous Rate function call
+ call JoyWaitAorB
+ call WaitSFX
+ ret
+
+ProfOaksPCRating: ; 0x26601
+ call Rate
+ push de
+ ld de, MUSIC_NONE
+ call PlayMusic
+ pop de
+ call PlaySFX
+ call JoyWaitAorB
+ call WaitSFX
+ ret
+
+Rate: ; 0x26616
+; calculate Seen/Owned
+ ld hl, PokedexSeen
+ ld b, EndPokedexSeen - PokedexSeen
+ call CountSetBits
+ ld [wd002], a
+ ld hl, PokedexCaught
+ ld b, EndPokedexCaught - PokedexCaught
+ call CountSetBits
+ ld [wd003], a
+
+; print appropriate rating
+ call .UpdateRatingBuffers
+ ld hl, OakPCText3
+ call PrintText
+ call JoyWaitAorB
+ ld a, [wd003]
+ ld hl, OakRatings
+ call FindOakRating
+ push de
+ call PrintText
+ pop de
+ ret
+
+.UpdateRatingBuffers: ; 0x26647
+ ld hl, StringBuffer3
+ ld de, wd002
+ call .UpdateRatingBuffer
+ ld hl, StringBuffer4
+ ld de, wd003
+ call .UpdateRatingBuffer
+ ret
+
+.UpdateRatingBuffer: ; 0x2665a
+ push hl
+ ld a, "@"
+ ld bc, ITEM_NAME_LENGTH
+ call ByteFill
+ pop hl
+ lb bc, PRINTNUM_RIGHTALIGN | 1, 3
+ call PrintNum
+ ret
+
+FindOakRating: ; 0x2666b
+; return sound effect in de
+; return text pointer in hl
+ nop
+ ld c, a
+.loop
+ ld a, [hli]
+ cp c
+ jr nc, .match
+rept 4
+ inc hl
+endr
+ jr .loop
+
+.match
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ret
+
+OakRatings: ; 0x2667f
+; if you caught at most this many, play this sound, load this text
+ dbww 9, SFX_DEX_FANFARE_LESS_THAN_20, OakRating01
+ dbww 19, SFX_DEX_FANFARE_LESS_THAN_20, OakRating02
+ dbww 34, SFX_DEX_FANFARE_20_49, OakRating03
+ dbww 49, SFX_DEX_FANFARE_20_49, OakRating04
+ dbww 64, SFX_DEX_FANFARE_50_79, OakRating05
+ dbww 79, SFX_DEX_FANFARE_50_79, OakRating06
+ dbww 94, SFX_DEX_FANFARE_80_109, OakRating07
+ dbww 109, SFX_DEX_FANFARE_80_109, OakRating08
+ dbww 124, SFX_CAUGHT_MON, OakRating09
+ dbww 139, SFX_CAUGHT_MON, OakRating10
+ dbww 154, SFX_DEX_FANFARE_140_169, OakRating11
+ dbww 169, SFX_DEX_FANFARE_140_169, OakRating12
+ dbww 184, SFX_DEX_FANFARE_170_199, OakRating13
+ dbww 199, SFX_DEX_FANFARE_170_199, OakRating14
+ dbww 214, SFX_DEX_FANFARE_200_229, OakRating15
+ dbww 229, SFX_DEX_FANFARE_200_229, OakRating16
+ dbww 239, SFX_DEX_FANFARE_230_PLUS, OakRating17
+ dbww 248, SFX_DEX_FANFARE_230_PLUS, OakRating18
+ dbww 255, SFX_DEX_FANFARE_230_PLUS, OakRating19
+
+OakPCText1: ; 0x266de
+ text_jump _OakPCText1
+ db "@"
+
+OakPCText2: ; 0x266e3
+ text_jump _OakPCText2
+ db "@"
+
+OakPCText3: ; 0x266e8
+ text_jump _OakPCText3
+ db "@"
+
+OakRating01:
+ text_jump _OakRating01
+ db "@"
+
+OakRating02:
+ text_jump _OakRating02
+ db "@"
+
+OakRating03:
+ text_jump _OakRating03
+ db "@"
+
+OakRating04:
+ text_jump _OakRating04
+ db "@"
+
+OakRating05:
+ text_jump _OakRating05
+ db "@"
+
+OakRating06:
+ text_jump _OakRating06
+ db "@"
+
+OakRating07:
+ text_jump _OakRating07
+ db "@"
+
+OakRating08:
+ text_jump _OakRating08
+ db "@"
+
+OakRating09:
+ text_jump _OakRating09
+ db "@"
+
+OakRating10:
+ text_jump _OakRating10
+ db "@"
+
+OakRating11:
+ text_jump _OakRating11
+ db "@"
+
+OakRating12:
+ text_jump _OakRating12
+ db "@"
+
+OakRating13:
+ text_jump _OakRating13
+ db "@"
+
+OakRating14:
+ text_jump _OakRating14
+ db "@"
+
+OakRating15:
+ text_jump _OakRating15
+ db "@"
+
+OakRating16:
+ text_jump _OakRating16
+ db "@"
+
+OakRating17:
+ text_jump _OakRating17
+ db "@"
+
+OakRating18:
+ text_jump _OakRating18
+ db "@"
+
+OakRating19:
+ text_jump _OakRating19
+ db "@"
+
+OakPCText4: ; 0x2674c
+ text_jump _OakPCText4
+ db "@"
diff --git a/engine/events/sacred_ash.asm b/engine/events/sacred_ash.asm
new file mode 100755
index 000000000..cc46eac9f
--- /dev/null
+++ b/engine/events/sacred_ash.asm
@@ -0,0 +1,74 @@
+
+_SacredAsh: ; 507e6
+ ld a, $0
+ ld [wItemEffectSucceeded], a
+ call CheckAnyFaintedMon
+ ret nc
+
+ ld hl, SacredAshScript
+ call QueueScript
+ ld a, $1
+ ld [wItemEffectSucceeded], a
+ ret
+; 507fb
+
+CheckAnyFaintedMon: ; 507fb
+ ld de, PARTYMON_STRUCT_LENGTH
+ ld bc, PartySpecies
+ ld hl, PartyMon1HP
+ ld a, [PartyCount]
+ and a
+ ret z
+
+.loop
+ push af
+ push hl
+ ld a, [bc]
+ inc bc
+ cp EGG
+ jr z, .next
+
+ ld a, [hli]
+ or [hl]
+ jr z, .done
+
+.next
+ pop hl
+ add hl, de
+ pop af
+ dec a
+ jr nz, .loop
+ xor a
+ ret
+
+.done
+ pop hl
+ pop af
+ scf
+ ret
+; 50821
+
+SacredAshScript: ; 0x50821
+ special HealParty
+ reloadmappart
+ playsound SFX_WARP_TO
+ special FadeOutPalettes
+ special FadeInPalettes
+ special FadeOutPalettes
+ special FadeInPalettes
+ special FadeOutPalettes
+ special FadeInPalettes
+ waitsfx
+ writetext UnknownText_0x50845
+ playsound SFX_CAUGHT_MON
+ waitsfx
+ waitbutton
+ closetext
+ end
+; 0x50845
+
+UnknownText_0x50845: ; 0x50845
+ ; 's #MON were all healed!
+ text_jump UnknownText_0x1c0b65
+ db "@"
+; 0x5084a
diff --git a/engine/events/special.asm b/engine/events/special.asm
new file mode 100755
index 000000000..d28d0de64
--- /dev/null
+++ b/engine/events/special.asm
@@ -0,0 +1,235 @@
+SpecialGiveShuckle: ; 7305
+
+; Adding to the party.
+ xor a
+ ld [MonType], a
+
+; Level 15 Shuckle.
+ ld a, SHUCKLE
+ ld [CurPartySpecies], a
+ ld a, 15
+ ld [CurPartyLevel], a
+
+ predef TryAddMonToParty
+ jr nc, .NotGiven
+
+; Caught data.
+ ld b, 0
+ farcall SetGiftPartyMonCaughtData
+
+; Holding a Berry.
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, [PartyCount]
+ dec a
+ push af
+ push bc
+ ld hl, PartyMon1Item
+ call AddNTimes
+ ld [hl], BERRY
+ pop bc
+ pop af
+
+; OT ID.
+ ld hl, PartyMon1ID
+ call AddNTimes
+ ld a, $2
+ ld [hli], a
+ ld [hl], $6
+
+; Nickname.
+ ld a, [PartyCount]
+ dec a
+ ld hl, PartyMonNicknames
+ call SkipNames
+ ld de, SpecialShuckleNick
+ call CopyName2
+
+; OT.
+ ld a, [PartyCount]
+ dec a
+ ld hl, PartyMonOT
+ call SkipNames
+ ld de, SpecialShuckleOT
+ call CopyName2
+
+; Engine flag for this event.
+ ld hl, DailyFlags
+ set 5, [hl]
+; setflag ENGINE_SHUCKLE_GIVEN
+ ld a, 1
+ ld [ScriptVar], a
+ ret
+
+.NotGiven:
+ xor a
+ ld [ScriptVar], a
+ ret
+
+SpecialShuckleOT:
+ db "MANIA@"
+SpecialShuckleNick:
+ db "SHUCKIE@"
+
+SpecialReturnShuckle: ; 737e
+ farcall SelectMonFromParty
+ jr c, .refused
+
+ ld a, [CurPartySpecies]
+ cp SHUCKLE
+ jr nz, .DontReturn
+
+ ld a, [CurPartyMon]
+ ld hl, PartyMon1ID
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+
+; OT ID
+ ld a, [hli]
+ cp HIGH(00518)
+ jr nz, .DontReturn
+ ld a, [hl]
+ cp LOW(00518)
+ jr nz, .DontReturn
+
+; OT
+ ld a, [CurPartyMon]
+ ld hl, PartyMonOT
+ call SkipNames
+ ld de, SpecialShuckleOT
+.CheckOT:
+ ld a, [de]
+ cp [hl]
+ jr nz, .DontReturn
+ cp "@"
+ jr z, .done
+ inc de
+ inc hl
+ jr .CheckOT
+
+.done
+ farcall CheckCurPartyMonFainted
+ jr c, .fainted
+ ld a, [CurPartyMon]
+ ld hl, PartyMon1Happiness
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ ld a, [hl]
+ cp 150
+ ld a, $3
+ jr nc, .HappyToStayWithYou
+ xor a ; take from pc
+ ld [wPokemonWithdrawDepositParameter], a
+ callfar RemoveMonFromPartyOrBox
+ ld a, $2
+.HappyToStayWithYou:
+ ld [ScriptVar], a
+ ret
+
+.refused
+ ld a, $1
+ ld [ScriptVar], a
+ ret
+
+.DontReturn:
+ xor a
+ ld [ScriptVar], a
+ ret
+
+.fainted
+ ld a, $4
+ ld [ScriptVar], a
+ ret
+
+Special_BillsGrandfather: ; 73f7
+ farcall SelectMonFromParty
+ jr c, .cancel
+ ld a, [CurPartySpecies]
+ ld [ScriptVar], a
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ jp CopyPokemonName_Buffer1_Buffer3
+
+.cancel
+ xor a
+ ld [ScriptVar], a
+ ret
+
+Special_YoungerHaircutBrother: ; 7413
+ ld hl, Data_YoungerHaircutBrother
+ jr MassageOrHaircut
+
+Special_OlderHaircutBrother: ; 7418
+ ld hl, Data_OlderHaircutBrother
+ jr MassageOrHaircut
+
+Special_DaisyMassage: ; 741d
+ ld hl, Data_DaisyMassage
+
+MassageOrHaircut: ; 7420
+ push hl
+ farcall SelectMonFromParty
+ pop hl
+ jr c, .nope
+ ld a, [CurPartySpecies]
+ cp EGG
+ jr z, .egg
+ push hl
+ call GetCurNick
+ call CopyPokemonName_Buffer1_Buffer3
+ pop hl
+ call Random
+; Bug: Subtracting $ff from $ff fails to set c.
+; This can result in overflow into the next data array.
+; In the case of getting a massage from Daisy, we bleed
+; into CopyPokemonName_Buffer1_Buffer3, which passes
+; $d0 to ChangeHappiness and returns $73 to the script.
+; The end result is that there is a 0.4% chance your
+; Pokemon's happiness will not change at all.
+.loop
+ sub [hl]
+ jr c, .ok
+ inc hl
+ inc hl
+ inc hl
+ jr .loop
+
+.ok
+ inc hl
+ ld a, [hli]
+ ld [ScriptVar], a
+ ld c, [hl]
+ call ChangeHappiness
+ ret
+
+.nope
+ xor a
+ ld [ScriptVar], a
+ ret
+
+.egg
+ ld a, 1
+ ld [ScriptVar], a
+ ret
+
+Data_YoungerHaircutBrother: ; 7459
+ db $4c, 2, HAPPINESS_YOUNGCUT1 ; 30% chance
+ db $80, 3, HAPPINESS_YOUNGCUT2 ; 20% chance
+ db $ff, 4, HAPPINESS_YOUNGCUT3 ; 50% chance
+
+Data_OlderHaircutBrother: ; 7462
+ db $9a, 2, HAPPINESS_OLDERCUT1 ; 60% chance
+ db $4c, 3, HAPPINESS_OLDERCUT2 ; 10% chance
+ db $ff, 4, HAPPINESS_OLDERCUT3 ; 30% chance
+
+Data_DaisyMassage: ; 746b
+ db $ff, 2, HAPPINESS_MASSAGE ; 99.6% chance
+
+CopyPokemonName_Buffer1_Buffer3: ; 746e
+ ld hl, StringBuffer1
+ ld de, StringBuffer3
+ ld bc, PKMN_NAME_LENGTH
+ jp CopyBytes
+
+Predef1: ; 747a
+; not used
+ ret
diff --git a/engine/events/squirtbottle.asm b/engine/events/squirtbottle.asm
new file mode 100755
index 000000000..1134f1bb0
--- /dev/null
+++ b/engine/events/squirtbottle.asm
@@ -0,0 +1,47 @@
+_Squirtbottle: ; 50730
+ ld hl, .SquirtbottleScript
+ call QueueScript
+ ld a, $1
+ ld [wItemEffectSucceeded], a
+ ret
+
+.SquirtbottleScript:
+ reloadmappart
+ special UpdateTimePals
+ callasm .CheckCanUseSquirtbottle
+ iffalse .NothingHappenedScript
+ farjump WateredWeirdTreeScript
+
+.NothingHappenedScript:
+ jumptext .NothingHappenedText
+
+.NothingHappenedText:
+ ; sprinkled water. But nothing happened…
+ text_jump UnknownText_0x1c0b3b
+ db "@"
+
+.CheckCanUseSquirtbottle:
+ ld a, [MapGroup]
+ cp GROUP_ROUTE_36
+ jr nz, .nope
+
+ ld a, [MapNumber]
+ cp MAP_ROUTE_36
+ jr nz, .nope
+
+ farcall GetFacingObject
+ jr c, .nope
+
+ ld a, d
+ cp SPRITEMOVEDATA_SUDOWOODO
+ jr nz, .nope
+
+ ld a, 1
+ ld [ScriptVar], a
+ ret
+
+.nope
+ xor a
+ ld [ScriptVar], a
+ ret
+; 50779
diff --git a/engine/events/std_collision.asm b/engine/events/std_collision.asm
new file mode 100644
index 000000000..79dbc71f1
--- /dev/null
+++ b/engine/events/std_collision.asm
@@ -0,0 +1,29 @@
+CheckFacingTileForStdScript:: ; 1365b
+; Checks to see if the tile you're facing has a std script associated with it. If so, executes the script and returns carry.
+ ld a, c
+ ld de, 3
+ ld hl, TileCollisionStdScripts
+ call IsInArray
+ jr nc, .notintable
+
+ ld a, jumpstd_command
+ ld [wJumpStdScriptBuffer], a
+ inc hl
+ ld a, [hli]
+ ld [wJumpStdScriptBuffer + 1], a
+ ld a, [hli]
+ ld [wJumpStdScriptBuffer + 2], a
+ ld a, BANK(Script_JumpStdFromRAM)
+ ld hl, Script_JumpStdFromRAM
+ call CallScript
+ scf
+ ret
+
+.notintable
+ xor a
+ ret
+
+INCLUDE "data/collision_stdscripts.asm"
+
+Script_JumpStdFromRAM: ; 0x1369a
+ jump wJumpStdScriptBuffer
diff --git a/engine/events/std_scripts.asm b/engine/events/std_scripts.asm
new file mode 100644
index 000000000..297725c60
--- /dev/null
+++ b/engine/events/std_scripts.asm
@@ -0,0 +1,1914 @@
+StdScripts::
+ dba PokecenterNurseScript
+ dba DifficultBookshelfScript
+ dba PictureBookshelfScript
+ dba MagazineBookshelfScript
+ dba TeamRocketOathScript
+ dba IncenseBurnerScript
+ dba MerchandiseShelfScript
+ dba TownMapScript
+ dba WindowScript
+ dba TVScript
+ dba HomepageScript
+ dba Radio1Script
+ dba Radio2Script
+ dba TrashCanScript
+ dba StrengthBoulderScript
+ dba SmashRockScript
+ dba PokecenterSignScript
+ dba MartSignScript
+ dba GoldenrodRocketsScript
+ dba RadioTowerRocketsScript
+ dba ElevatorButtonScript
+ dba DayToTextScript
+ dba BugContestResultsWarpScript
+ dba BugContestResultsScript
+ dba InitializeEventsScript
+ dba AskNumber1MScript
+ dba AskNumber2MScript
+ dba RegisteredNumberMScript
+ dba NumberAcceptedMScript
+ dba NumberDeclinedMScript
+ dba PhoneFullMScript
+ dba RematchMScript
+ dba GiftMScript
+ dba PackFullMScript
+ dba RematchGiftMScript
+ dba AskNumber1FScript
+ dba AskNumber2FScript
+ dba RegisteredNumberFScript
+ dba NumberAcceptedFScript
+ dba NumberDeclinedFScript
+ dba PhoneFullFScript
+ dba RematchFScript
+ dba GiftFScript
+ dba PackFullFScript
+ dba RematchGiftFScript
+ dba GymStatue1Script
+ dba GymStatue2Script
+ dba ReceiveItemScript
+ dba ReceiveTogepiEggScript
+ dba PCScript
+ dba GameCornerCoinVendorScript
+ dba HappinessCheckScript
+
+PokecenterNurseScript:
+; EVENT_WELCOMED_TO_POKECOM_CENTER is never set
+
+ opentext
+ checkmorn
+ iftrue .morn
+ checkday
+ iftrue .day
+ checknite
+ iftrue .nite
+ jump .ok
+
+.morn
+ checkevent EVENT_WELCOMED_TO_POKECOM_CENTER
+ iftrue .morn_comcenter
+ farwritetext NurseMornText
+ buttonsound
+ jump .ok
+.morn_comcenter
+ farwritetext PokeComNurseMornText
+ buttonsound
+ jump .ok
+
+.day
+ checkevent EVENT_WELCOMED_TO_POKECOM_CENTER
+ iftrue .day_comcenter
+ farwritetext NurseDayText
+ buttonsound
+ jump .ok
+.day_comcenter
+ farwritetext PokeComNurseDayText
+ buttonsound
+ jump .ok
+
+.nite
+ checkevent EVENT_WELCOMED_TO_POKECOM_CENTER
+ iftrue .nite_comcenter
+ farwritetext NurseNiteText
+ buttonsound
+ jump .ok
+.nite_comcenter
+ farwritetext PokeComNurseNiteText
+ buttonsound
+ jump .ok
+
+.ok
+ ; only do this once
+ clearevent EVENT_WELCOMED_TO_POKECOM_CENTER
+
+ farwritetext NurseAskHealText
+ yesorno
+ iffalse .done
+
+ farwritetext NurseTakePokemonText
+ pause 20
+ special TrainerRankings_Healings
+ spriteface LAST_TALKED, LEFT
+ pause 10
+ special HealParty
+ playmusic MUSIC_NONE
+ writebyte 0 ; Machine is at a Pokemon Center
+ special HealMachineAnim
+ pause 30
+ special RestartMapMusic
+ spriteface LAST_TALKED, DOWN
+ pause 10
+
+ checkphonecall ; elm already called about pokerus
+ iftrue .no
+ checkflag ENGINE_POKERUS ; nurse already talked about pokerus
+ iftrue .no
+ special SpecialCheckPokerus
+ iftrue .pokerus
+.no
+
+ farwritetext NurseReturnPokemonText
+ pause 20
+
+.done
+ farwritetext NurseGoodbyeText
+
+ spriteface LAST_TALKED, UP
+ pause 10
+ spriteface LAST_TALKED, DOWN
+ pause 10
+
+ waitbutton
+ closetext
+ end
+
+.pokerus
+ ; already cleared earlier in the script
+ checkevent EVENT_WELCOMED_TO_POKECOM_CENTER
+ iftrue .pokerus_comcenter
+ farwritetext NursePokerusText
+ waitbutton
+ closetext
+ jump .pokerus_done
+
+.pokerus_comcenter
+ farwritetext PokeComNursePokerusText
+ waitbutton
+ closetext
+
+.pokerus_done
+ setflag ENGINE_POKERUS
+ specialphonecall SPECIALCALL_POKERUS
+ end
+
+DifficultBookshelfScript:
+ farjumptext DifficultBookshelfText
+
+PictureBookshelfScript:
+ farjumptext PictureBookshelfText
+
+MagazineBookshelfScript:
+ farjumptext MagazineBookshelfText
+
+TeamRocketOathScript:
+ farjumptext TeamRocketOathText
+
+IncenseBurnerScript:
+ farjumptext IncenseBurnerText
+
+MerchandiseShelfScript:
+ farjumptext MerchandiseShelfText
+
+TownMapScript:
+ opentext
+ farwritetext TownMapText
+ waitbutton
+ special Special_TownMap
+ closetext
+ end
+
+WindowScript:
+ farjumptext WindowText
+
+TVScript:
+ opentext
+ farwritetext TVText
+ waitbutton
+ closetext
+ end
+
+HomepageScript:
+ farjumptext HomepageText
+
+Radio1Script:
+ opentext
+ writebyte MAPRADIO_POKEMON_CHANNEL
+ special MapRadio
+ closetext
+ end
+
+Radio2Script:
+; Lucky Channel
+ opentext
+ writebyte MAPRADIO_LUCKY_CHANNEL
+ special MapRadio
+ closetext
+ end
+
+TrashCanScript: ; 0xbc1a5
+ farjumptext TrashCanText
+
+PCScript:
+ opentext
+ special PokemonCenterPC
+ closetext
+ end
+
+ElevatorButtonScript:
+ playsound SFX_READ_TEXT_2
+ pause 15
+ playsound SFX_ELEVATOR_END
+ end
+
+StrengthBoulderScript:
+ farjump AskStrengthScript
+
+SmashRockScript:
+ farjump AskRockSmashScript
+
+PokecenterSignScript:
+ farjumptext PokecenterSignText
+
+MartSignScript
+ farjumptext MartSignText
+
+DayToTextScript:
+ checkcode VAR_WEEKDAY
+ if_equal MONDAY, .Monday
+ if_equal TUESDAY, .Tuesday
+ if_equal WEDNESDAY, .Wednesday
+ if_equal THURSDAY, .Thursday
+ if_equal FRIDAY, .Friday
+ if_equal SATURDAY, .Saturday
+ stringtotext .SundayText, 0
+ end
+.Monday:
+ stringtotext .MondayText, 0
+ end
+.Tuesday:
+ stringtotext .TuesdayText, 0
+ end
+.Wednesday:
+ stringtotext .WednesdayText, 0
+ end
+.Thursday:
+ stringtotext .ThursdayText, 0
+ end
+.Friday:
+ stringtotext .FridayText, 0
+ end
+.Saturday:
+ stringtotext .SaturdayText, 0
+ end
+.SundayText:
+ db "SUNDAY@"
+.MondayText:
+ db "MONDAY@"
+.TuesdayText:
+ db "TUESDAY@"
+.WednesdayText:
+ db "WEDNESDAY@"
+.ThursdayText:
+ db "THURSDAY@"
+.FridayText:
+ db "FRIDAY@"
+.SaturdayText:
+ db "SATURDAY@"
+
+GoldenrodRocketsScript:
+ clearevent EVENT_GOLDENROD_CITY_ROCKET_TAKEOVER
+ end
+
+RadioTowerRocketsScript:
+ setflag ENGINE_ROCKETS_IN_RADIO_TOWER
+ setevent EVENT_GOLDENROD_CITY_CIVILIANS
+ setevent EVENT_RADIO_TOWER_BLACKBELT_BLOCKS_STAIRS
+ clearevent EVENT_RADIO_TOWER_ROCKET_TAKEOVER
+ clearevent EVENT_USED_THE_CARD_KEY_IN_THE_RADIO_TOWER
+ setevent EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_EAST
+ specialphonecall SPECIALCALL_WEIRDBROADCAST
+ setmapscene MAHOGANY_TOWN, $1
+ end
+
+BugContestResultsWarpScript:
+ special ClearBGPalettes
+ scall BugContestResults_CopyContestantsToResults
+ setevent EVENT_ROUTE_36_NATIONAL_PARK_GATE_OFFICER_CONTEST_DAY
+ clearevent EVENT_ROUTE_36_NATIONAL_PARK_GATE_OFFICER_NOT_CONTEST_DAY
+ setevent EVENT_WARPED_FROM_ROUTE_35_NATIONAL_PARK_GATE
+ warp ROUTE_36_NATIONAL_PARK_GATE, $0, $4
+ applymovement PLAYER, Movement_ContestResults_WalkAfterWarp
+
+BugContestResultsScript:
+ clearflag ENGINE_BUG_CONTEST_TIMER
+ clearevent EVENT_WARPED_FROM_ROUTE_35_NATIONAL_PARK_GATE
+ clearevent EVENT_CONTEST_OFFICER_HAS_SUN_STONE
+ clearevent EVENT_CONTEST_OFFICER_HAS_EVERSTONE
+ clearevent EVENT_CONTEST_OFFICER_HAS_GOLD_BERRY
+ clearevent EVENT_CONTEST_OFFICER_HAS_BERRY
+ opentext
+ farwritetext ContestResults_ReadyToJudgeText
+ waitbutton
+ special BugContestJudging
+ RAM2MEM $0
+ if_equal 1, BugContestResults_FirstPlace
+ if_equal 2, BugContestResults_SecondPlace
+ if_equal 3, BugContestResults_ThirdPlace
+ farwritetext ContestResults_ConsolationPrizeText
+ buttonsound
+ waitsfx
+ verbosegiveitem BERRY
+ iffalse BugContestResults_NoRoomForBerry
+
+BugContestResults_DidNotWin
+ farwritetext ContestResults_DidNotWinText
+ buttonsound
+ jump BugContestResults_FinishUp
+; 0xbc2b1
+
+BugContestResults_ReturnAfterWinnersPrize ; 0xbc2b1
+ farwritetext ContestResults_JoinUsNextTimeText
+ buttonsound
+
+BugContestResults_FinishUp
+ checkevent EVENT_LEFT_MONS_WITH_CONTEST_OFFICER
+ iffalse BugContestResults_DidNotLeaveMons
+ farwritetext ContestResults_ReturnPartyText
+ waitbutton
+ special ContestReturnMons
+BugContestResults_DidNotLeaveMons
+ special CheckPartyFullAfterContest
+ if_equal $0, BugContestResults_CleanUp
+ if_equal $2, BugContestResults_CleanUp
+ farwritetext ContestResults_PartyFullText
+ waitbutton
+BugContestResults_CleanUp
+ closetext
+ setscene $0
+ setmapscene ROUTE_35_NATIONAL_PARK_GATE, $0
+ setevent EVENT_BUG_CATCHING_CONTESTANT_1A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_2A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_3A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_4A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_5A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_6A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_7A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_8A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_9A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_10A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_1B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_2B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_3B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_4B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_5B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_6B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_7B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_8B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_9B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_10B
+ setflag ENGINE_DAILY_BUG_CONTEST
+ special PlayMapMusic
+ end
+; 0xbc31e
+
+BugContestResults_FirstPlace ; 0xbc31e
+ setevent EVENT_GAVE_KURT_APRICORNS
+ itemtotext SUN_STONE, $1
+ farwritetext ContestResults_PlayerWonAPrizeText
+ waitbutton
+ verbosegiveitem SUN_STONE
+ iffalse BugContestResults_NoRoomForSunStone
+ jump BugContestResults_ReturnAfterWinnersPrize
+; 0xbc332
+
+BugContestResults_SecondPlace ; 0xbc332
+ itemtotext EVERSTONE, $1
+ farwritetext ContestResults_PlayerWonAPrizeText
+ waitbutton
+ verbosegiveitem EVERSTONE
+ iffalse BugContestResults_NoRoomForEverstone
+ jump BugContestResults_ReturnAfterWinnersPrize
+; 0xbc343
+
+BugContestResults_ThirdPlace ; 0xbc343
+ itemtotext GOLD_BERRY, $1
+ farwritetext ContestResults_PlayerWonAPrizeText
+ waitbutton
+ verbosegiveitem GOLD_BERRY
+ iffalse BugContestResults_NoRoomForGoldBerry
+ jump BugContestResults_ReturnAfterWinnersPrize
+; 0xbc354
+
+BugContestResults_NoRoomForSunStone ; 0xbc354
+ farwritetext BugContestPrizeNoRoomText
+ buttonsound
+ setevent EVENT_CONTEST_OFFICER_HAS_SUN_STONE
+ jump BugContestResults_ReturnAfterWinnersPrize
+; 0xbc35f
+
+BugContestResults_NoRoomForEverstone ; 0xbc35f
+ farwritetext BugContestPrizeNoRoomText
+ buttonsound
+ setevent EVENT_CONTEST_OFFICER_HAS_EVERSTONE
+ jump BugContestResults_ReturnAfterWinnersPrize
+; 0xbc36a
+
+BugContestResults_NoRoomForGoldBerry ; 0xbc36a
+ farwritetext BugContestPrizeNoRoomText
+ buttonsound
+ setevent EVENT_CONTEST_OFFICER_HAS_GOLD_BERRY
+ jump BugContestResults_ReturnAfterWinnersPrize
+; 0xbc375
+
+BugContestResults_NoRoomForBerry ; 0xbc375
+ farwritetext BugContestPrizeNoRoomText
+ buttonsound
+ setevent EVENT_CONTEST_OFFICER_HAS_BERRY
+ jump BugContestResults_DidNotWin
+; 0xbc380
+
+BugContestResults_CopyContestantsToResults ; 0xbc380
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_1A
+ iftrue .skip1
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_1B
+.skip1
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_2A
+ iftrue .skip2
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_2B
+.skip2
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_3A
+ iftrue .skip3
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_3B
+.skip3
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_4A
+ iftrue .skip4
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_4B
+.skip4
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_5A
+ iftrue .skip5
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_5B
+.skip5
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_6A
+ iftrue .skip6
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_6B
+.skip6
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_7A
+ iftrue .skip7
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_7B
+.skip7
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_8A
+ iftrue .skip8
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_8B
+.skip8
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_9A
+ iftrue .skip9
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_9B
+.skip9
+ checkevent EVENT_BUG_CATCHING_CONTESTANT_10A
+ iftrue .skip10
+ clearevent EVENT_BUG_CATCHING_CONTESTANT_10B
+.skip10
+ end
+
+InitializeEventsScript:
+ setevent EVENT_EARLS_ACADEMY_EARL
+ setevent EVENT_RADIO_TOWER_ROCKET_TAKEOVER
+ setevent EVENT_GOLDENROD_CITY_ROCKET_TAKEOVER
+ setevent EVENT_RADIO_TOWER_CIVILIANS_AFTER
+ setevent EVENT_ILEX_FOREST_APPRENTICE
+ setevent EVENT_ILEX_FOREST_FARFETCHD
+ setevent EVENT_ILEX_FOREST_CHARCOAL_MASTER
+ setevent EVENT_MAHOGANY_MART_LANCE_AND_DRAGONITE
+ setevent EVENT_TEAM_ROCKET_BASE_B2F_GRUNT_WITH_EXECUTIVE
+ setevent EVENT_TEAM_ROCKET_BASE_B2F_EXECUTIVE
+ setevent EVENT_TEAM_ROCKET_BASE_B2F_DRAGONITE
+ setevent EVENT_RIVAL_TEAM_ROCKET_BASE
+ setevent EVENT_BLACKTHORN_CITY_SUPER_NERD_DOES_NOT_BLOCK_GYM
+ setevent EVENT_USED_THE_CARD_KEY_IN_THE_RADIO_TOWER
+ setevent EVENT_RIVAL_CHERRYGROVE_CITY
+ setevent EVENT_RIVAL_AZALEA_TOWN
+ setevent EVENT_RIVAL_GOLDENROD_UNDERGROUND
+ setevent EVENT_AZALEA_TOWN_SLOWPOKES
+ setevent EVENT_KURTS_HOUSE_SLOWPOKE
+ setevent EVENT_GUIDE_GENT_VISIBLE_IN_CHERRYGROVE
+ setevent EVENT_ELMS_AIDE_IN_VIOLET_POKEMON_CENTER
+ setevent EVENT_COP_IN_ELMS_LAB
+ setevent EVENT_RUINS_OF_ALPH_OUTSIDE_SCIENTIST
+ setevent EVENT_RUINS_OF_ALPH_RESEARCH_CENTER_SCIENTIST
+ setevent EVENT_BOULDER_IN_ICE_PATH_1A
+ setevent EVENT_BOULDER_IN_ICE_PATH_2A
+ setevent EVENT_BOULDER_IN_ICE_PATH_3A
+ setevent EVENT_BOULDER_IN_ICE_PATH_4A
+ setevent EVENT_ROUTE_30_YOUNGSTER_JOEY
+ setevent EVENT_BUG_CATCHING_CONTESTANT_1A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_2A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_3A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_4A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_5A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_6A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_7A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_8A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_9A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_10A
+ setevent EVENT_BUG_CATCHING_CONTESTANT_1B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_2B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_3B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_4B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_5B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_6B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_7B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_8B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_9B
+ setevent EVENT_BUG_CATCHING_CONTESTANT_10B
+ setevent EVENT_FAST_SHIP_1F_GENTLEMAN
+ setevent EVENT_FAST_SHIP_B1F_SAILOR_RIGHT
+ setevent EVENT_FAST_SHIP_CABINS_NNW_NNE_NE_SAILOR
+ setevent EVENT_LAKE_OF_RAGE_CIVILIANS
+ setevent EVENT_MAHOGANY_MART_OWNERS
+ setevent EVENT_TIN_TOWER_ROOF_HO_OH
+ setevent EVENT_WHIRL_ISLAND_LUGIA_CHAMBER_LUGIA
+ setevent EVENT_KRISS_HOUSE_2F_CONSOLE
+ setevent EVENT_KRISS_HOUSE_2F_DOLL_1
+ setevent EVENT_KRISS_HOUSE_2F_DOLL_2
+ setevent EVENT_KRISS_HOUSE_2F_BIG_DOLL
+ setevent EVENT_DECO_BED_1
+ setevent EVENT_DECO_PLANT_4
+ setevent EVENT_GOLDENROD_TRAIN_STATION_GENTLEMAN
+ setevent EVENT_OLIVINE_GYM_JASMINE
+ setevent EVENT_BLACKTHORN_CITY_GRAMPS_NOT_BLOCKING_DRAGONS_DEN
+ setevent EVENT_MET_BILL
+ setevent EVENT_ECRUTEAK_POKE_CENTER_BILL
+ setevent EVENT_MYSTERY_GIFT_DELIVERY_GUY
+ setevent EVENT_LAKE_OF_RAGE_LANCE
+ setevent EVENT_GOLDENROD_DEPT_STORE_B1F_LAYOUT_1
+ setevent EVENT_GOLDENROD_UNDERGROUND_WAREHOUSE_BLOCKED_OFF
+ setevent EVENT_DRAGONS_DEN_CLAIR
+ setevent EVENT_RIVAL_OLIVINE_CITY
+ setevent EVENT_RIVAL_VICTORY_ROAD
+ setevent EVENT_RIVAL_DRAGONS_DEN
+ setevent EVENT_LANCES_ROOM_OAK_AND_MARY
+ setevent EVENT_FAST_SHIP_CABINS_SE_SSE_CAPTAINS_CABIN_TWIN_1
+ setevent EVENT_BURNED_TOWER_B1F_BEASTS_1
+ setevent EVENT_RED_IN_MT_SILVER
+ setevent EVENT_OLIVINE_PORT_SPRITES_AFTER_HALL_OF_FAME
+ setevent EVENT_FAST_SHIP_PASSENGERS_EASTBOUND
+ setevent EVENT_FAST_SHIP_PASSENGERS_WESTBOUND
+ setevent EVENT_OLIVINE_PORT_PASSAGE_POKEFAN_M
+ setevent EVENT_KURTS_HOUSE_KURT_2
+ setevent EVENT_KURTS_HOUSE_GRANDDAUGHTER_2
+ setevent EVENT_RANG_CLEAR_BELL_1
+ setevent EVENT_FLORIA_AT_FLOWER_SHOP
+ setevent EVENT_FLORIA_AT_SUDOWOODO
+ setevent EVENT_GOLDENROD_CITY_MOVE_TUTOR
+ setevent EVENT_RUINS_OF_ALPH_OUTSIDE_TOURIST_FISHER
+ setevent EVENT_RUINS_OF_ALPH_OUTSIDE_TOURIST_YOUNGSTERS
+ setevent EVENT_DRAGON_SHRINE_CLAIR
+ setevent EVENT_BATTLE_TOWER_BATTLE_ROOM_YOUNGSTER
+ setevent EVENT_KRISS_NEIGHBORS_HOUSE_NEIGHBOR
+ setevent EVENT_AZALEA_TOWN_KURT
+ setevent EVENT_AZALEA_TOWN_KURT
+ setevent EVENT_ILEX_FOREST_KURT
+ setevent EVENT_ROUTE_34_ILEX_FOREST_GATE_TEACHER_IN_WALKWAY
+ setevent EVENT_ILEX_FOREST_LASS
+ setevent EVENT_GOLDENROD_SALE_OFF
+ setevent EVENT_ECRUTEAK_CITY_GRAMPS
+ setevent EVENT_EUSINE_IN_BURNED_TOWER
+ setevent EVENT_KRISS_HOUSE_MOM_2
+ setevent EVENT_WISE_TRIOS_ROOM_WISE_TRIO_2
+ setevent EVENT_CIANWOOD_CITY_EUSINE
+ setevent EVENT_TIN_TOWER_1F_EUSINE
+ setevent EVENT_TIN_TOWER_1F_WISE_TRIO_1
+ setevent EVENT_TIN_TOWER_1F_WISE_TRIO_2
+ setevent EVENT_SET_WHEN_FOUGHT_HO_OH
+ setevent EVENT_SAW_SUICUNE_ON_ROUTE_36
+ setevent EVENT_SAW_SUICUNE_ON_ROUTE_42
+ setevent EVENT_SAW_SUICUNE_AT_CIANWOOD_CITY
+ setevent EVENT_BATTLE_TOWER_OUTSIDE_SAILOR
+ setflag ENGINE_ROCKET_SIGNAL_ON_CH20
+ setflag ENGINE_ROCKETS_IN_MAHOGANY
+ variablesprite SPRITE_WEIRD_TREE, SPRITE_SUDOWOODO
+ variablesprite SPRITE_OLIVINE_RIVAL, SPRITE_SILVER
+ variablesprite SPRITE_AZALEA_ROCKET, SPRITE_ROCKET
+ variablesprite SPRITE_FUCHSIA_GYM_1, SPRITE_JANINE
+ variablesprite SPRITE_FUCHSIA_GYM_2, SPRITE_JANINE
+ variablesprite SPRITE_FUCHSIA_GYM_3, SPRITE_JANINE
+ variablesprite SPRITE_FUCHSIA_GYM_4, SPRITE_JANINE
+ variablesprite SPRITE_COPYCAT, SPRITE_LASS
+ variablesprite SPRITE_JANINE_IMPERSONATOR, SPRITE_LASS
+ setevent EVENT_FOUND_MACHINE_PART_IN_CERULEAN_GYM
+ setevent EVENT_CERULEAN_GYM_ROCKET
+ setevent EVENT_ROUTE_24_ROCKET
+ setevent EVENT_ROUTE_25_MISTY_BOYFRIEND
+ setevent EVENT_TRAINERS_IN_CERULEAN_GYM
+ setevent EVENT_COPYCATS_HOUSE_2F_DOLL
+ setevent EVENT_VIRIDIAN_GYM_BLUE
+ setevent EVENT_SEAFOAM_GYM_GYM_GUY
+ setevent EVENT_MT_MOON_SQUARE_CLEFAIRY
+ setevent EVENT_SAFFRON_TRAIN_STATION_POPULATION
+ setevent EVENT_INDIGO_PLATEAU_POKECENTER_RIVAL
+ setevent EVENT_INITIALIZED_EVENTS
+ return
+
+AskNumber1MScript:
+ special RandomPhoneMon
+ checkcode VAR_CALLERID
+ if_equal PHONE_SCHOOLBOY_JACK, .Jack
+ if_equal PHONE_SAILOR_HUEY, .Huey
+ if_equal PHONE_COOLTRAINERM_GAVEN, .Gaven
+ if_equal PHONE_BIRDKEEPER_JOSE, .Jose
+ if_equal PHONE_YOUNGSTER_JOEY, .Joey
+ if_equal PHONE_BUG_CATCHER_WADE, .Wade
+ if_equal PHONE_FISHER_RALPH, .Ralph
+ if_equal PHONE_HIKER_ANTHONY, .Anthony
+ if_equal PHONE_CAMPER_TODD, .Todd
+ if_equal PHONE_JUGGLER_IRWIN, .Irwin
+ if_equal PHONE_BUG_CATCHER_ARNIE, .Arnie
+ if_equal PHONE_SCHOOLBOY_ALAN, .Alan
+ if_equal PHONE_SCHOOLBOY_CHAD, .Chad
+ if_equal PHONE_POKEFANM_DEREK, .Derek
+ if_equal PHONE_FISHER_TULLY, .Tully
+ if_equal PHONE_POKEMANIAC_BRENT, .Brent
+ if_equal PHONE_BIRDKEEPER_VANCE, .Vance
+ if_equal PHONE_FISHER_WILTON, .Wilton
+ if_equal PHONE_BLACKBELT_KENJI, .Kenji
+ if_equal PHONE_HIKER_PARRY, .Parry
+
+.Jack:
+ farwritetext JackAskNumber1Text
+ end
+.Huey:
+ farwritetext HueyAskNumber1Text
+ end
+.Gaven:
+ farwritetext GavenAskNumber1Text
+ end
+.Jose:
+ farwritetext JoseAskNumber1Text
+ end
+.Joey:
+ farwritetext JoeyAskNumber1Text
+ end
+.Wade:
+ farwritetext WadeAskNumber1Text
+ end
+.Ralph:
+ farwritetext RalphAskNumber1Text
+ end
+.Anthony:
+ farwritetext AnthonyAskNumber1Text
+ end
+.Todd:
+ farwritetext ToddAskNumber1Text
+ end
+.Irwin:
+ farwritetext IrwinAskNumber1Text
+ end
+.Arnie:
+ farwritetext ArnieAskNumber1Text
+ end
+.Alan:
+ farwritetext AlanAskNumber1Text
+ end
+.Chad:
+ farwritetext ChadAskNumber1Text
+ end
+.Derek:
+ farwritetext DerekAskNumber1Text
+ end
+.Tully:
+ farwritetext TullyAskNumber1Text
+ end
+.Brent:
+ farwritetext BrentAskNumber1Text
+ end
+.Vance:
+ farwritetext VanceAskNumber1Text
+ end
+.Wilton:
+ farwritetext WiltonAskNumber1Text
+ end
+.Kenji:
+ farwritetext KenjiAskNumber1Text
+ end
+.Parry:
+ farwritetext ParryAskNumber1Text
+ end
+
+AskNumber2MScript:
+ special RandomPhoneMon
+ checkcode VAR_CALLERID
+ if_equal PHONE_SCHOOLBOY_JACK, .Jack
+ if_equal PHONE_SAILOR_HUEY, .Huey
+ if_equal PHONE_COOLTRAINERM_GAVEN, .Gaven
+ if_equal PHONE_BIRDKEEPER_JOSE, .Jose
+ if_equal PHONE_YOUNGSTER_JOEY, .Joey
+ if_equal PHONE_BUG_CATCHER_WADE, .Wade
+ if_equal PHONE_FISHER_RALPH, .Ralph
+ if_equal PHONE_HIKER_ANTHONY, .Anthony
+ if_equal PHONE_CAMPER_TODD, .Todd
+ if_equal PHONE_JUGGLER_IRWIN, .Irwin
+ if_equal PHONE_BUG_CATCHER_ARNIE, .Arnie
+ if_equal PHONE_SCHOOLBOY_ALAN, .Alan
+ if_equal PHONE_SCHOOLBOY_CHAD, .Chad
+ if_equal PHONE_POKEFANM_DEREK, .Derek
+ if_equal PHONE_FISHER_TULLY, .Tully
+ if_equal PHONE_POKEMANIAC_BRENT, .Brent
+ if_equal PHONE_BIRDKEEPER_VANCE, .Vance
+ if_equal PHONE_FISHER_WILTON, .Wilton
+ if_equal PHONE_BLACKBELT_KENJI, .Kenji
+ if_equal PHONE_HIKER_PARRY, .Parry
+
+.Jack:
+ farwritetext JackAskNumber2Text
+ end
+.Huey:
+ farwritetext HueyAskNumber2Text
+ end
+.Gaven:
+ farwritetext GavenAskNumber2Text
+ end
+.Jose:
+ farwritetext JoseAskNumber2Text
+ end
+.Joey:
+ farwritetext JoeyAskNumber2Text
+ end
+.Wade:
+ farwritetext WadeAskNumber2Text
+ end
+.Ralph:
+ farwritetext RalphAskNumber2Text
+ end
+.Anthony:
+ farwritetext AnthonyAskNumber2Text
+ end
+.Todd:
+ farwritetext ToddAskNumber2Text
+ end
+.Irwin:
+ farwritetext IrwinAskNumber2Text
+ end
+.Arnie:
+ farwritetext ArnieAskNumber2Text
+ end
+.Alan:
+ farwritetext AlanAskNumber2Text
+ end
+.Chad:
+ farwritetext ChadAskNumber2Text
+ end
+.Derek:
+ farwritetext DerekAskNumber2Text
+ end
+.Tully:
+ farwritetext TullyAskNumber2Text
+ end
+.Brent:
+ farwritetext BrentAskNumber2Text
+ end
+.Vance:
+ farwritetext VanceAskNumber2Text
+ end
+.Wilton:
+ farwritetext WiltonAskNumber2Text
+ end
+.Kenji:
+ farwritetext KenjiAskNumber2Text
+ end
+.Parry:
+ farwritetext ParryAskNumber2Text
+ end
+
+RegisteredNumberMScript:
+ farwritetext RegisteredNumber1Text
+ playsound SFX_REGISTER_PHONE_NUMBER
+ waitsfx
+ buttonsound
+ end
+
+NumberAcceptedMScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_SCHOOLBOY_JACK, .Jack
+ if_equal PHONE_SAILOR_HUEY, .Huey
+ if_equal PHONE_COOLTRAINERM_GAVEN, .Gaven
+ if_equal PHONE_BIRDKEEPER_JOSE, .Jose
+ if_equal PHONE_YOUNGSTER_JOEY, .Joey
+ if_equal PHONE_BUG_CATCHER_WADE, .Wade
+ if_equal PHONE_FISHER_RALPH, .Ralph
+ if_equal PHONE_HIKER_ANTHONY, .Anthony
+ if_equal PHONE_CAMPER_TODD, .Todd
+ if_equal PHONE_JUGGLER_IRWIN, .Irwin
+ if_equal PHONE_BUG_CATCHER_ARNIE, .Arnie
+ if_equal PHONE_SCHOOLBOY_ALAN, .Alan
+ if_equal PHONE_SCHOOLBOY_CHAD, .Chad
+ if_equal PHONE_POKEFANM_DEREK, .Derek
+ if_equal PHONE_FISHER_TULLY, .Tully
+ if_equal PHONE_POKEMANIAC_BRENT, .Brent
+ if_equal PHONE_BIRDKEEPER_VANCE, .Vance
+ if_equal PHONE_FISHER_WILTON, .Wilton
+ if_equal PHONE_BLACKBELT_KENJI, .Kenji
+ if_equal PHONE_HIKER_PARRY, .Parry
+
+.Jack:
+ farwritetext JackNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Huey:
+ farwritetext HueyNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Gaven:
+ farwritetext GavenNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Jose:
+ farwritetext JoseNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Joey:
+ farwritetext JoeyNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Wade:
+ farwritetext WadeNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Ralph:
+ farwritetext RalphNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Anthony:
+ farwritetext AnthonyNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Todd:
+ farwritetext ToddNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Irwin:
+ farwritetext IrwinNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Arnie:
+ farwritetext ArnieNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Alan:
+ farwritetext AlanNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Chad:
+ farwritetext ChadNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Derek:
+ farwritetext DerekNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Tully:
+ farwritetext TullyNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Brent:
+ farwritetext BrentNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Vance:
+ farwritetext VanceNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Wilton:
+ farwritetext WiltonNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Kenji:
+ farwritetext KenjiNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Parry:
+ farwritetext ParryNumberAcceptedText
+ waitbutton
+ closetext
+ end
+
+NumberDeclinedMScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_SCHOOLBOY_JACK, .Jack
+ if_equal PHONE_SAILOR_HUEY, .Huey
+ if_equal PHONE_COOLTRAINERM_GAVEN, .Gaven
+ if_equal PHONE_BIRDKEEPER_JOSE, .Jose
+ if_equal PHONE_YOUNGSTER_JOEY, .Joey
+ if_equal PHONE_BUG_CATCHER_WADE, .Wade
+ if_equal PHONE_FISHER_RALPH, .Ralph
+ if_equal PHONE_HIKER_ANTHONY, .Anthony
+ if_equal PHONE_CAMPER_TODD, .Todd
+ if_equal PHONE_JUGGLER_IRWIN, .Irwin
+ if_equal PHONE_BUG_CATCHER_ARNIE, .Arnie
+ if_equal PHONE_SCHOOLBOY_ALAN, .Alan
+ if_equal PHONE_SCHOOLBOY_CHAD, .Chad
+ if_equal PHONE_POKEFANM_DEREK, .Derek
+ if_equal PHONE_FISHER_TULLY, .Tully
+ if_equal PHONE_POKEMANIAC_BRENT, .Brent
+ if_equal PHONE_BIRDKEEPER_VANCE, .Vance
+ if_equal PHONE_FISHER_WILTON, .Wilton
+ if_equal PHONE_BLACKBELT_KENJI, .Kenji
+ if_equal PHONE_HIKER_PARRY, .Parry
+
+.Jack:
+ farwritetext JackNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Huey:
+ farwritetext HueyNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Gaven:
+ farwritetext GavenNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Jose:
+ farwritetext JoseNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Joey:
+ farwritetext JoeyNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Wade:
+ farwritetext WadeNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Ralph:
+ farwritetext RalphNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Anthony:
+ farwritetext AnthonyNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Todd:
+ farwritetext ToddNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Irwin:
+ farwritetext IrwinNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Arnie:
+ farwritetext ArnieNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Alan:
+ farwritetext AlanNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Chad:
+ farwritetext ChadNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Derek:
+ farwritetext DerekNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Tully:
+ farwritetext TullyNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Brent:
+ farwritetext BrentNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Vance:
+ farwritetext VanceNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Wilton:
+ farwritetext WiltonNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Kenji:
+ farwritetext KenjiNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Parry:
+ farwritetext ParryNumberDeclinedText
+ waitbutton
+ closetext
+ end
+
+PhoneFullMScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_SCHOOLBOY_JACK, .Jack
+ if_equal PHONE_SAILOR_HUEY, .Huey
+ if_equal PHONE_COOLTRAINERM_GAVEN, .Gaven
+ if_equal PHONE_BIRDKEEPER_JOSE, .Jose
+ if_equal PHONE_YOUNGSTER_JOEY, .Joey
+ if_equal PHONE_BUG_CATCHER_WADE, .Wade
+ if_equal PHONE_FISHER_RALPH, .Ralph
+ if_equal PHONE_HIKER_ANTHONY, .Anthony
+ if_equal PHONE_CAMPER_TODD, .Todd
+ if_equal PHONE_JUGGLER_IRWIN, .Irwin
+ if_equal PHONE_BUG_CATCHER_ARNIE, .Arnie
+ if_equal PHONE_SCHOOLBOY_ALAN, .Alan
+ if_equal PHONE_SCHOOLBOY_CHAD, .Chad
+ if_equal PHONE_POKEFANM_DEREK, .Derek
+ if_equal PHONE_FISHER_TULLY, .Tully
+ if_equal PHONE_POKEMANIAC_BRENT, .Brent
+ if_equal PHONE_BIRDKEEPER_VANCE, .Vance
+ if_equal PHONE_FISHER_WILTON, .Wilton
+ if_equal PHONE_BLACKBELT_KENJI, .Kenji
+ if_equal PHONE_HIKER_PARRY, .Parry
+
+.Jack:
+ farwritetext JackPhoneFullText
+ waitbutton
+ closetext
+ end
+.Huey:
+ farwritetext HueyPhoneFullText
+ waitbutton
+ closetext
+ end
+.Gaven:
+ farwritetext GavenPhoneFullText
+ waitbutton
+ closetext
+ end
+.Jose:
+ farwritetext JosePhoneFullText
+ waitbutton
+ closetext
+ end
+.Joey:
+ farwritetext JoeyPhoneFullText
+ waitbutton
+ closetext
+ end
+.Wade:
+ farwritetext WadePhoneFullText
+ waitbutton
+ closetext
+ end
+.Ralph:
+ farwritetext RalphPhoneFullText
+ waitbutton
+ closetext
+ end
+.Anthony:
+ farwritetext AnthonyPhoneFullText
+ waitbutton
+ closetext
+ end
+.Todd:
+ farwritetext ToddPhoneFullText
+ waitbutton
+ closetext
+ end
+.Irwin:
+ farwritetext IrwinPhoneFullText
+ waitbutton
+ closetext
+ end
+.Arnie:
+ farwritetext ArniePhoneFullText
+ waitbutton
+ closetext
+ end
+.Alan:
+ farwritetext AlanPhoneFullText
+ waitbutton
+ closetext
+ end
+.Chad:
+ farwritetext ChadPhoneFullText
+ waitbutton
+ closetext
+ end
+.Derek:
+ farwritetext DerekPhoneFullText
+ waitbutton
+ closetext
+ end
+.Tully:
+ farwritetext TullyPhoneFullText
+ waitbutton
+ closetext
+ end
+.Brent:
+ farwritetext BrentPhoneFullText
+ waitbutton
+ closetext
+ end
+.Vance:
+ farwritetext VancePhoneFullText
+ waitbutton
+ closetext
+ end
+.Wilton:
+ farwritetext WiltonPhoneFullText
+ waitbutton
+ closetext
+ end
+.Kenji:
+ farwritetext KenjiPhoneFullText
+ waitbutton
+ closetext
+ end
+.Parry:
+ farwritetext ParryPhoneFullText
+ waitbutton
+ closetext
+ end
+
+RematchMScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_SCHOOLBOY_JACK, .Jack
+ if_equal PHONE_SAILOR_HUEY, .Huey
+ if_equal PHONE_COOLTRAINERM_GAVEN, .Gaven
+ if_equal PHONE_BIRDKEEPER_JOSE, .Jose
+ if_equal PHONE_YOUNGSTER_JOEY, .Joey
+ if_equal PHONE_BUG_CATCHER_WADE, .Wade
+ if_equal PHONE_FISHER_RALPH, .Ralph
+ if_equal PHONE_HIKER_ANTHONY, .Anthony
+ if_equal PHONE_CAMPER_TODD, .Todd
+ if_equal PHONE_BUG_CATCHER_ARNIE, .Arnie
+ if_equal PHONE_SCHOOLBOY_ALAN, .Alan
+ if_equal PHONE_SCHOOLBOY_CHAD, .Chad
+ if_equal PHONE_FISHER_TULLY, .Tully
+ if_equal PHONE_POKEMANIAC_BRENT, .Brent
+ if_equal PHONE_BIRDKEEPER_VANCE, .Vance
+ if_equal PHONE_FISHER_WILTON, .Wilton
+ if_equal PHONE_HIKER_PARRY, .Parry
+
+.Jack:
+ farwritetext JackRematchText
+ waitbutton
+ closetext
+ end
+.Huey:
+ farwritetext HueyRematchText
+ waitbutton
+ closetext
+ end
+.Gaven:
+ farwritetext GavenRematchText
+ waitbutton
+ closetext
+ end
+.Jose:
+ farwritetext JoseRematchText
+ waitbutton
+ closetext
+ end
+.Joey:
+ farwritetext JoeyRematchText
+ waitbutton
+ closetext
+ end
+.Wade:
+ farwritetext WadeRematchText
+ waitbutton
+ closetext
+ end
+.Ralph:
+ farwritetext RalphRematchText
+ waitbutton
+ closetext
+ end
+.Anthony:
+ farwritetext AnthonyRematchText
+ waitbutton
+ closetext
+ end
+.Todd:
+ farwritetext ToddRematchText
+ waitbutton
+ closetext
+ end
+.Arnie:
+ farwritetext ArnieRematchText
+ waitbutton
+ closetext
+ end
+.Alan:
+ farwritetext AlanRematchText
+ waitbutton
+ closetext
+ end
+.Chad:
+ farwritetext ChadRematchText
+ waitbutton
+ closetext
+ end
+.Tully:
+ farwritetext TullyRematchText
+ waitbutton
+ closetext
+ end
+.Brent:
+ farwritetext BrentRematchText
+ waitbutton
+ closetext
+ end
+.Vance:
+ farwritetext VanceRematchText
+ waitbutton
+ closetext
+ end
+.Wilton:
+ farwritetext WiltonRematchText
+ waitbutton
+ closetext
+ end
+.Parry:
+ farwritetext ParryRematchText
+ waitbutton
+ closetext
+ end
+
+GiftMScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_BIRDKEEPER_JOSE, .Jose
+ if_equal PHONE_BUG_CATCHER_WADE, .Wade
+ if_equal PHONE_SCHOOLBOY_ALAN, .Alan
+ if_equal PHONE_POKEFANM_DEREK, .Derek
+ if_equal PHONE_FISHER_TULLY, .Tully
+ if_equal PHONE_FISHER_WILTON, .Wilton
+ if_equal PHONE_BLACKBELT_KENJI, .Kenji
+
+.Jose:
+ farwritetext JoseGiftText
+ buttonsound
+ end
+.Wade:
+ farwritetext WadeGiftText
+ buttonsound
+ end
+.Alan:
+ farwritetext AlanGiftText
+ buttonsound
+ end
+.Derek:
+ farwritetext DerekGiftText
+ buttonsound
+ end
+.Tully:
+ farwritetext TullyGiftText
+ buttonsound
+ end
+.Wilton:
+ farwritetext WiltonGiftText
+ buttonsound
+ end
+.Kenji:
+ farwritetext KenjiGiftText
+ buttonsound
+ end
+
+PackFullMScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_SAILOR_HUEY, .Huey
+ if_equal PHONE_BIRDKEEPER_JOSE, .Jose
+ if_equal PHONE_YOUNGSTER_JOEY, .Joey
+ if_equal PHONE_BUG_CATCHER_WADE, .Wade
+ if_equal PHONE_SCHOOLBOY_ALAN, .Alan
+ if_equal PHONE_POKEFANM_DEREK, .Derek
+ if_equal PHONE_FISHER_TULLY, .Tully
+ if_equal PHONE_BIRDKEEPER_VANCE, .Vance
+ if_equal PHONE_FISHER_WILTON, .Wilton
+ if_equal PHONE_BLACKBELT_KENJI, .Kenji
+ if_equal PHONE_HIKER_PARRY, .Parry
+
+.Huey:
+ farwritetext HueyPackFullText
+ waitbutton
+ closetext
+ end
+.Jose:
+ farwritetext JosePackFullText
+ waitbutton
+ closetext
+ end
+.Joey:
+ farwritetext JoeyPackFullText
+ waitbutton
+ closetext
+ end
+.Wade:
+ farwritetext WadePackFullText
+ waitbutton
+ closetext
+ end
+.Alan:
+ farwritetext AlanPackFullText
+ waitbutton
+ closetext
+ end
+.Derek:
+ farwritetext DerekPackFullText
+ waitbutton
+ closetext
+ end
+.Tully:
+ farwritetext TullyPackFullText
+ waitbutton
+ closetext
+ end
+.Vance:
+ farwritetext VancePackFullText
+ waitbutton
+ closetext
+ end
+.Wilton:
+ farwritetext WiltonPackFullText
+ waitbutton
+ closetext
+ end
+.Kenji:
+ farwritetext KenjiPackFullText
+ waitbutton
+ closetext
+ end
+.Parry:
+ farwritetext ParryPackFullText
+ waitbutton
+ closetext
+ end
+
+RematchGiftMScript:
+ opentext
+ checkcode VAR_CALLERID
+ if_equal PHONE_SAILOR_HUEY, .Huey
+ if_equal PHONE_YOUNGSTER_JOEY, .Joey
+ if_equal PHONE_BIRDKEEPER_VANCE, .Vance
+ if_equal PHONE_HIKER_PARRY, .Parry
+
+.Huey:
+ farwritetext HueyRematchGiftText
+ buttonsound
+ end
+.Joey:
+ farwritetext JoeyRematchGiftText
+ buttonsound
+ end
+.Vance:
+ farwritetext VanceRematchGiftText
+ buttonsound
+ end
+.Parry:
+ farwritetext ParryRematchGiftText
+ buttonsound
+ end
+
+AskNumber1FScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_POKEFAN_BEVERLY, .Beverly
+ if_equal PHONE_COOLTRAINERF_BETH, .Beth
+ if_equal PHONE_COOLTRAINERF_REENA, .Reena
+ if_equal PHONE_PICNICKER_LIZ, .Liz
+ if_equal PHONE_PICNICKER_GINA, .Gina
+ if_equal PHONE_LASS_DANA, .Dana
+ if_equal PHONE_PICNICKER_TIFFANY, .Tiffany
+ if_equal PHONE_PICNICKER_ERIN, .Erin
+
+.Beverly:
+ farwritetext BeverlyAskNumber1Text
+ end
+.Beth:
+ farwritetext BethAskNumber1Text
+ end
+.Reena:
+ farwritetext ReenaAskNumber1Text
+ end
+.Liz:
+ farwritetext LizAskNumber1Text
+ end
+.Gina:
+ farwritetext GinaAskNumber1Text
+ end
+.Dana:
+ farwritetext DanaAskNumber1Text
+ end
+.Tiffany:
+ farwritetext TiffanyAskNumber1Text
+ end
+.Erin:
+ farwritetext ErinAskNumber1Text
+ end
+
+AskNumber2FScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_POKEFAN_BEVERLY, .Beverly
+ if_equal PHONE_COOLTRAINERF_BETH, .Beth
+ if_equal PHONE_COOLTRAINERF_REENA, .Reena
+ if_equal PHONE_PICNICKER_LIZ, .Liz
+ if_equal PHONE_PICNICKER_GINA, .Gina
+ if_equal PHONE_LASS_DANA, .Dana
+ if_equal PHONE_PICNICKER_TIFFANY, .Tiffany
+ if_equal PHONE_PICNICKER_ERIN, .Erin
+
+.Beverly:
+ farwritetext BeverlyAskNumber2Text
+ end
+.Beth:
+ farwritetext BethAskNumber2Text
+ end
+.Reena:
+ farwritetext ReenaAskNumber2Text
+ end
+.Liz:
+ farwritetext LizAskNumber2Text
+ end
+.Gina:
+ farwritetext GinaAskNumber2Text
+ end
+.Dana:
+ farwritetext DanaAskNumber2Text
+ end
+.Tiffany:
+ farwritetext TiffanyAskNumber2Text
+ end
+.Erin:
+ farwritetext ErinAskNumber2Text
+ end
+
+RegisteredNumberFScript:
+ farwritetext RegisteredNumber2Text
+ playsound SFX_REGISTER_PHONE_NUMBER
+ waitsfx
+ buttonsound
+ end
+
+NumberAcceptedFScript: ; 0xbcbd3
+ checkcode VAR_CALLERID
+ if_equal PHONE_POKEFAN_BEVERLY, .Beverly
+ if_equal PHONE_COOLTRAINERF_BETH, .Beth
+ if_equal PHONE_COOLTRAINERF_REENA, .Reena
+ if_equal PHONE_PICNICKER_LIZ, .Liz
+ if_equal PHONE_PICNICKER_GINA, .Gina
+ if_equal PHONE_LASS_DANA, .Dana
+ if_equal PHONE_PICNICKER_TIFFANY, .Tiffany
+ if_equal PHONE_PICNICKER_ERIN, .Erin
+
+.Beverly:
+ farwritetext BeverlyNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Beth:
+ farwritetext BethNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Reena:
+ farwritetext ReenaNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Liz:
+ farwritetext LizNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Gina:
+ farwritetext GinaNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Dana:
+ farwritetext DanaNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Tiffany:
+ farwritetext TiffanyNumberAcceptedText
+ waitbutton
+ closetext
+ end
+.Erin:
+ farwritetext ErinNumberAcceptedText
+ waitbutton
+ closetext
+ end
+
+NumberDeclinedFScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_POKEFAN_BEVERLY, .Beverly
+ if_equal PHONE_COOLTRAINERF_BETH, .Beth
+ if_equal PHONE_COOLTRAINERF_REENA, .Reena
+ if_equal PHONE_PICNICKER_LIZ, .Liz
+ if_equal PHONE_PICNICKER_GINA, .Gina
+ if_equal PHONE_LASS_DANA, .Dana
+ if_equal PHONE_PICNICKER_TIFFANY, .Tiffany
+ if_equal PHONE_PICNICKER_ERIN, .Erin
+
+.Beverly:
+ farwritetext BeverlyNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Beth:
+ farwritetext BethNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Reena:
+ farwritetext ReenaNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Liz:
+ farwritetext LizNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Gina:
+ farwritetext GinaNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Dana:
+ farwritetext DanaNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Tiffany:
+ farwritetext TiffanyNumberDeclinedText
+ waitbutton
+ closetext
+ end
+.Erin:
+ farwritetext ErinNumberDeclinedText
+ waitbutton
+ closetext
+ end
+
+PhoneFullFScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_POKEFAN_BEVERLY, .Beverly
+ if_equal PHONE_COOLTRAINERF_BETH, .Beth
+ if_equal PHONE_COOLTRAINERF_REENA, .Reena
+ if_equal PHONE_PICNICKER_LIZ, .Liz
+ if_equal PHONE_PICNICKER_GINA, .Gina
+ if_equal PHONE_LASS_DANA, .Dana
+ if_equal PHONE_PICNICKER_TIFFANY, .Tiffany
+ if_equal PHONE_PICNICKER_ERIN, .Erin
+
+.Beverly:
+ farwritetext BeverlyPhoneFullText
+ waitbutton
+ closetext
+ end
+.Beth:
+ farwritetext BethPhoneFullText
+ waitbutton
+ closetext
+ end
+.Reena:
+ farwritetext ReenaPhoneFullText
+ waitbutton
+ closetext
+ end
+.Liz:
+ farwritetext LizPhoneFullText
+ waitbutton
+ closetext
+ end
+.Gina:
+ farwritetext GinaPhoneFullText
+ waitbutton
+ closetext
+ end
+.Dana:
+ farwritetext DanaPhoneFullText
+ waitbutton
+ closetext
+ end
+.Tiffany:
+ farwritetext TiffanyPhoneFullText
+ waitbutton
+ closetext
+ end
+.Erin:
+ farwritetext ErinPhoneFullText
+ waitbutton
+ closetext
+ end
+
+RematchFScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_COOLTRAINERF_BETH, .Beth
+ if_equal PHONE_COOLTRAINERF_REENA, .Reena
+ if_equal PHONE_PICNICKER_LIZ, .Liz
+ if_equal PHONE_PICNICKER_GINA, .Gina
+ if_equal PHONE_LASS_DANA, .Dana
+ if_equal PHONE_PICNICKER_TIFFANY, .Tiffany
+ if_equal PHONE_PICNICKER_ERIN, .Erin
+
+.Beth:
+ farwritetext BethRematchText
+ waitbutton
+ closetext
+ end
+.Reena:
+ farwritetext ReenaRematchText
+ waitbutton
+ closetext
+ end
+.Liz:
+ farwritetext LizRematchText
+ waitbutton
+ closetext
+ end
+.Gina:
+ farwritetext GinaRematchText
+ waitbutton
+ closetext
+ end
+.Dana:
+ farwritetext DanaRematchText
+ waitbutton
+ closetext
+ end
+.Tiffany:
+ farwritetext TiffanyRematchText
+ waitbutton
+ closetext
+ end
+.Erin:
+ farwritetext ErinRematchText
+ waitbutton
+ closetext
+ end
+
+GiftFScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_POKEFAN_BEVERLY, .Beverly
+ if_equal PHONE_PICNICKER_GINA, .Gina
+ if_equal PHONE_LASS_DANA, .Dana
+ if_equal PHONE_PICNICKER_TIFFANY, .Tiffany
+
+.Beverly:
+ farwritetext BeverlyGiftText
+ buttonsound
+ end
+.Gina:
+ farwritetext GinaGiftText
+ buttonsound
+ end
+.Dana:
+ farwritetext DanaGiftText
+ buttonsound
+ end
+.Tiffany:
+ farwritetext TiffanyGiftText
+ buttonsound
+ end
+
+PackFullFScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_POKEFAN_BEVERLY, .Beverly
+ if_equal PHONE_PICNICKER_GINA, .Gina
+ if_equal PHONE_LASS_DANA, .Dana
+ if_equal PHONE_PICNICKER_TIFFANY, .Tiffany
+ if_equal PHONE_PICNICKER_ERIN, .Erin
+
+.Beverly:
+ farwritetext BeverlyPackFullText
+ waitbutton
+ closetext
+ end
+.Gina:
+ farwritetext GinaPackFullText
+ waitbutton
+ closetext
+ end
+.Dana:
+ farwritetext DanaPackFullText
+ waitbutton
+ closetext
+ end
+.Tiffany:
+ farwritetext TiffanyPackFullText
+ waitbutton
+ closetext
+ end
+.Erin:
+ farwritetext ErinPackFullText
+ waitbutton
+ closetext
+ end
+
+RematchGiftFScript:
+ checkcode VAR_CALLERID
+ if_equal PHONE_PICNICKER_ERIN, .Erin
+
+.Erin:
+ opentext
+ farwritetext ErinRematchGiftText
+ buttonsound
+ end
+
+GymStatue1Script:
+ mapnametotext $0
+ opentext
+ farwritetext GymStatue_CityGymText
+ waitbutton
+ closetext
+ end
+
+GymStatue2Script:
+ mapnametotext $0
+ opentext
+ farwritetext GymStatue_CityGymText
+ buttonsound
+ farwritetext GymStatue_WinningTrainersText
+ waitbutton
+ closetext
+ end
+
+ReceiveItemScript: ; 0xbcdb9
+ waitsfx
+ farwritetext ReceivedItemText
+ playsound SFX_ITEM
+ waitsfx
+ end
+; 0xbcdc3
+
+ReceiveTogepiEggScript: ; 0xbcdc3
+ waitsfx
+ farwritetext ReceivedItemText
+ playsound SFX_GET_EGG_FROM_DAY_CARE_LADY
+ waitsfx
+ end
+; 0xbcdcd
+
+GameCornerCoinVendorScript: ; 0xbcdcd
+ faceplayer
+ opentext
+ farwritetext CoinVendor_WelcomeText
+ buttonsound
+ checkitem COIN_CASE
+ iftrue CoinVendor_IntroScript
+ farwritetext CoinVendor_NoCoinCaseText
+ waitbutton
+ closetext
+ end
+; 0xbcde0
+
+CoinVendor_IntroScript: ; 0xbcde0
+ farwritetext CoinVendor_IntroText
+
+.loop ; 0xbcde4
+ special Special_DisplayMoneyAndCoinBalance
+ loadmenudata .MenuDataHeader
+ verticalmenu
+ closewindow
+ if_equal $1, .Buy50
+ if_equal $2, .Buy500
+ jump .Cancel
+; 0xbcdf7
+
+.Buy50: ; 0xbcdf7
+ checkcoins 9949
+ if_equal $0, .CoinCaseFull
+ checkmoney $0, 1000
+ if_equal $2, .NotEnoughMoney
+ givecoins 50
+ takemoney $0, 1000
+ waitsfx
+ playsound SFX_TRANSACTION
+ farwritetext CoinVendor_Buy50CoinsText
+ waitbutton
+ jump .loop
+; 0xbce1b
+
+.Buy500: ; 0xbce1b
+ checkcoins 9499
+ if_equal $0, .CoinCaseFull
+ checkmoney $0, 10000
+ if_equal $2, .NotEnoughMoney
+ givecoins 500
+ takemoney $0, 10000
+ waitsfx
+ playsound SFX_TRANSACTION
+ farwritetext CoinVendor_Buy500CoinsText
+ waitbutton
+ jump .loop
+; 0xbce3f
+
+.NotEnoughMoney: ; 0xbce3f
+ farwritetext CoinVendor_NotEnoughMoneyText
+ waitbutton
+ closetext
+ end
+; 0xbce46
+
+.CoinCaseFull: ; 0xbce46
+ farwritetext CoinVendor_CoinCaseFullText
+ waitbutton
+ closetext
+ end
+; 0xbce4d
+
+.Cancel: ; 0xbce4d
+ farwritetext CoinVendor_CancelText
+ waitbutton
+ closetext
+ end
+; 0xbce54
+
+
+.MenuDataHeader:
+ db $40 ; flags
+ db 04, 00 ; start coords
+ db 11, 15 ; end coords
+ dw .MenuData2
+ db 1 ; default option
+
+.MenuData2:
+ db $80 ; flags
+ db 3 ; items
+ db " 50 : ¥1000@"
+ db "500 : ¥10000@"
+ db "CANCEL@"
+; 0xbce7f
+
+
+HappinessCheckScript:
+ faceplayer
+ opentext
+ special GetFirstPokemonHappiness
+ if_less_than 50, .Unhappy
+ if_less_than 150, .KindaHappy
+ farwritetext HappinessText3
+ waitbutton
+ closetext
+ end
+
+.KindaHappy:
+ farwritetext HappinessText2
+ waitbutton
+ closetext
+ end
+
+.Unhappy:
+ farwritetext HappinessText1
+ waitbutton
+ closetext
+ end
+
+Movement_ContestResults_WalkAfterWarp: ; bcea1
+ step RIGHT
+ step DOWN
+ turn_head UP
+ step_end
+; bcea5
diff --git a/engine/events/sweet_scent.asm b/engine/events/sweet_scent.asm
new file mode 100755
index 000000000..77567488c
--- /dev/null
+++ b/engine/events/sweet_scent.asm
@@ -0,0 +1,75 @@
+SweetScentFromMenu: ; 506bc
+ ld hl, .SweetScent
+ call QueueScript
+ ld a, $1
+ ld [wFieldMoveSucceeded], a
+ ret
+; 506c8
+
+.SweetScent: ; 0x506c8
+ reloadmappart
+ special UpdateTimePals
+ callasm GetPartyNick
+ writetext UnknownText_0x50726
+ waitbutton
+ callasm SweetScentEncounter
+ iffalse SweetScentNothing
+ checkflag ENGINE_BUG_CONTEST_TIMER
+ iftrue .BugCatchingContest
+ randomwildmon
+ startbattle
+ reloadmapafterbattle
+ end
+; 0x506e5
+
+.BugCatchingContest: ; 0x506e5
+ farjump BugCatchingContestBattleScript
+; 0x506e9
+
+SweetScentNothing: ; 0x506e9
+ writetext UnknownText_0x5072b
+ waitbutton
+ closetext
+ end
+; 0x506ef
+
+SweetScentEncounter: ; 506ef
+ farcall CanUseSweetScent
+ jr nc, .no_battle
+ ld hl, StatusFlags2
+ bit 2, [hl]
+ jr nz, .not_in_bug_contest
+ farcall GetMapEncounterRate
+ ld a, b
+ and a
+ jr z, .no_battle
+ farcall ChooseWildEncounter
+ jr nz, .no_battle
+ jr .start_battle
+
+.not_in_bug_contest
+ farcall ChooseWildEncounter_BugContest
+
+.start_battle
+ ld a, $1
+ ld [ScriptVar], a
+ ret
+
+.no_battle
+ xor a
+ ld [ScriptVar], a
+ ld [BattleType], a
+ ret
+; 50726
+
+UnknownText_0x50726: ; 0x50726
+ ; used SWEET SCENT!
+ text_jump UnknownText_0x1c0b03
+ db "@"
+; 0x5072b
+
+UnknownText_0x5072b: ; 0x5072b
+ ; Looks like there's nothing here…
+ text_jump UnknownText_0x1c0b1a
+ db "@"
+; 0x50730
diff --git a/engine/events/trainer_scripts.asm b/engine/events/trainer_scripts.asm
new file mode 100644
index 000000000..212cd7f28
--- /dev/null
+++ b/engine/events/trainer_scripts.asm
@@ -0,0 +1,31 @@
+TalkToTrainerScript:: ; 0xbe66a
+ faceplayer
+ trainerflagaction CHECK_FLAG
+ iftrue AlreadyBeatenTrainerScript
+ loadmemtrainer
+ encountermusic
+ jump StartBattleWithMapTrainerScript
+
+SeenByTrainerScript:: ; 0xbe675
+ loadmemtrainer
+ encountermusic
+ showemote EMOTE_SHOCK, LAST_TALKED, 30
+ callasm TrainerWalkToPlayer
+ applymovement2 MovementBuffer
+ writeobjectxy LAST_TALKED
+ faceobject PLAYER, LAST_TALKED
+ jump StartBattleWithMapTrainerScript
+
+StartBattleWithMapTrainerScript: ; 0xbe68a
+ opentext
+ trainertext $0
+ waitbutton
+ closetext
+ loadmemtrainer
+ startbattle
+ reloadmapafterbattle
+ trainerflagaction SET_FLAG
+ loadvar wRunningTrainerBattleScript, -1
+
+AlreadyBeatenTrainerScript:
+ scripttalkafter
diff --git a/engine/events/whiteout.asm b/engine/events/whiteout.asm
new file mode 100755
index 000000000..a9d6f900e
--- /dev/null
+++ b/engine/events/whiteout.asm
@@ -0,0 +1,82 @@
+Script_BattleWhiteout:: ; 0x124c1
+ callasm BattleBGMap
+ jump Script_Whiteout
+; 0x124c8
+
+Script_OverworldWhiteout:: ; 0x124c8
+ refreshscreen $0
+ callasm OverworldBGMap
+
+Script_Whiteout: ; 0x124ce
+ writetext .WhitedOutText
+ waitbutton
+ special FadeOutPalettes
+ pause 40
+ special HealParty
+ checkflag ENGINE_BUG_CONTEST_TIMER
+ iftrue .bug_contest
+ callasm HalveMoney
+ callasm GetWhiteoutSpawn
+ farscall Script_AbortBugContest
+ special WarpToSpawnPoint
+ newloadmap MAPSETUP_WARP
+ end_all
+
+.bug_contest
+ jumpstd bugcontestresultswarp
+; 0x124f5
+
+.WhitedOutText: ; 0x124f5
+ ; is out of useable #MON! whited out!
+ text_jump UnknownText_0x1c0a4e
+ db "@"
+; 0x124fa
+
+OverworldBGMap: ; 124fa
+ call ClearPalettes
+ call ClearScreen
+ call WaitBGMap2
+ call HideSprites
+ call RotateThreePalettesLeft
+ ret
+; 1250a
+
+BattleBGMap: ; 1250a
+ ld b, SCGB_BATTLE_GRAYSCALE
+ call GetSGBLayout
+ call SetPalettes
+ ret
+; 12513
+
+HalveMoney: ; 12513
+ farcall TrainerRankings_WhiteOuts
+
+; Halve the player's money.
+ ld hl, Money
+ ld a, [hl]
+ srl a
+ ld [hli], a
+ ld a, [hl]
+ rra
+ ld [hli], a
+ ld a, [hl]
+ rra
+ ld [hl], a
+ ret
+; 12527
+
+
+GetWhiteoutSpawn: ; 12527
+ ld a, [wLastSpawnMapGroup]
+ ld d, a
+ ld a, [wLastSpawnMapNumber]
+ ld e, a
+ farcall IsSpawnPoint
+ ld a, c
+ jr c, .yes
+ xor a ; SPAWN_HOME
+
+.yes
+ ld [DefaultSpawnpoint], a
+ ret
+; 1253d