Arbitrary trainer scripts + map script/trigger softlock prevention (#5033)
Script_RunImmediatelyUntilEffect runs a script until either a specified effect may occur or it reaches an end. All existing script commands and natives, and some specials, call Script_RequestEffects which allows us to analyze them. Any downstream script commands/natives/specials will be statically known not to call Script_RequestEffects and treated as if they have all effects. Manually tagging them with requests_effects=1 and calling Script_RequestEffects will make them analyzable. Using these, we're able to execute scripts until they either exit with no effect, or would possibly have an effect. This allows us to: 1. Not run on frame map scripts or triggers if they would have no effect. 2. Immediately run triggers if they only affect flags/vars. This removes the lag frames when biking into the Cycling Road, for example. 3. Migrate on load/on transition/on resume/on return to field/on dive warp scripts onto the global script context if they would block (approximated via SCREFF_HARDWARE). 4. Support arbitrary control flow in trainer scripts. The trainer does not see the player if the script has no effect, and the trainer will use whichever trainerbattle command is branched to. 5. Support arbitrary scripts in trainer scripts. cant_see and cant_see_if_* commands have been introduced so that scripts are able to do something when the player interacts with the trainer even if that trainer wouldn't see them.
This commit is contained in:
parent
5391b451ae
commit
bb781f21a1
@ -251,15 +251,26 @@
|
||||
.endm
|
||||
|
||||
@ Calls the native C function stored at func.
|
||||
.macro callnative func:req
|
||||
@ 'callnative's should set 'requests_effects=1' if the native
|
||||
@ contains a call to 'Script_RequestEffects', which allows them
|
||||
@ to be analyzed by 'RunScriptImmediatelyUntilEffect'.
|
||||
.macro callnative func:req, requests_effects=0
|
||||
.byte 0x23
|
||||
.if \requests_effects == 0
|
||||
.4byte \func
|
||||
.else
|
||||
.4byte \func + ROM_SIZE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
@ Replaces the script with the function stored at func. Execution returns to the bytecode script when func returns TRUE.
|
||||
.macro gotonative func:req
|
||||
.macro gotonative func:req, requests_effects=0
|
||||
.byte 0x24
|
||||
.if \requests_effects == 0
|
||||
.4byte \func
|
||||
.else
|
||||
.4byte \func + ROM_SIZE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
@ Calls a function listed in the table in data/specials.inc.
|
||||
@ -997,9 +1008,9 @@
|
||||
@ Gives the player a Pokémon of the specified species and level, and allows to customize extra parameters.
|
||||
@ VAR_RESULT will be set to MON_GIVEN_TO_PARTY, MON_GIVEN_TO_PC, or MON_CANT_GIVE depending on the outcome.
|
||||
.macro givemon species:req, level:req, item, ball, nature, abilityNum, gender, hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv, hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv, move1, move2, move3, move4, isShiny, ggMaxFactor, teraType
|
||||
callnative ScrCmd_createmon
|
||||
callnative ScrCmd_createmon, requests_effects=1
|
||||
.byte 0
|
||||
.byte 6 @ PARTY_SIZE - assign to first empty slot
|
||||
.byte PARTY_SIZE @ assign to first empty slot
|
||||
.set givemon_flags, 0
|
||||
.2byte \species
|
||||
.2byte \level
|
||||
@ -1057,7 +1068,7 @@
|
||||
@ creates a mon for a given party and slot
|
||||
@ otherwise
|
||||
.macro createmon side:req, slot:req, species:req, level:req, item, ball, nature, abilityNum, gender, hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv, hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv, move1, move2, move3, move4, isShiny, ggMaxFactor, teraType
|
||||
callnative ScrCmd_createmon
|
||||
callnative ScrCmd_createmon, requests_effects=1
|
||||
.byte \side @ 0 - player, 1 - opponent
|
||||
.byte \slot @ 0-5
|
||||
.set givemon_flags, 0
|
||||
@ -2103,7 +2114,7 @@
|
||||
.endm
|
||||
|
||||
.macro setdynamicaifunc func:req
|
||||
callnative ScriptSetDynamicAiFunc
|
||||
callnative ScriptSetDynamicAiFunc, requests_effects=1
|
||||
.4byte \func
|
||||
.endm
|
||||
|
||||
@ -2112,7 +2123,7 @@
|
||||
@ The rest of the arguments are the stat change values to each stat.
|
||||
@ For example, giving the first opponent +1 to atk and -2 to speed would be: settotemboost B_POSITION_OPPONENT_LEFT, 1, 0, -2
|
||||
.macro settotemboost battler:req, atk=0,def=0,speed=0,spatk=0,spdef=0,acc=0,evas=0
|
||||
callnative ScriptSetTotemBoost
|
||||
callnative ScriptSetTotemBoost, requests_effects=1
|
||||
.2byte \battler
|
||||
.2byte \atk
|
||||
.2byte \def
|
||||
@ -2183,21 +2194,21 @@
|
||||
.macro ai_vs_ai_battle trainer1:req, trainer2:req
|
||||
setflag B_FLAG_AI_VS_AI_BATTLE
|
||||
setvar VAR_0x8004, \trainer1
|
||||
callnative CreateTrainerPartyForPlayer
|
||||
callnative CreateTrainerPartyForPlayer, requests_effects=1
|
||||
trainerbattle_no_intro \trainer2, NULL
|
||||
.endm
|
||||
|
||||
@ Sets VAR_RESULT to TRUE if stat can be hyper trained, or to
|
||||
@ FALSE otherwise.
|
||||
.macro canhypertrain stat:req, slot:req
|
||||
callnative CanHyperTrain
|
||||
callnative CanHyperTrain, requests_effects=1
|
||||
.byte \stat
|
||||
.2byte \slot
|
||||
.endm
|
||||
|
||||
@ Hyper Trains a stat.
|
||||
.macro hypertrain stat:req, slot:req
|
||||
callnative HyperTrain
|
||||
callnative HyperTrain, requests_effects=1
|
||||
.byte \stat
|
||||
.2byte \slot
|
||||
.endm
|
||||
@ -2205,7 +2216,7 @@
|
||||
@ Sets VAR_RESULT to TRUE if the Pokemon has the Gigantamax Factor,
|
||||
@ or to FALSE otherwise.
|
||||
.macro hasgigantamaxfactor slot:req
|
||||
callnative HasGigantamaxFactor
|
||||
callnative HasGigantamaxFactor, requests_effects=1
|
||||
.2byte \slot
|
||||
.endm
|
||||
|
||||
@ -2213,7 +2224,7 @@
|
||||
@ Fails for Melmetal (vanilla behavior).
|
||||
@ Sets VAR_RESULT to TRUE if it succeeds, and FALSE otherwise.
|
||||
.macro togglegigantamaxfactor slot:req
|
||||
callnative ToggleGigantamaxFactor
|
||||
callnative ToggleGigantamaxFactor, requests_effects=1
|
||||
.2byte \slot
|
||||
.endm
|
||||
|
||||
@ -2251,27 +2262,27 @@
|
||||
@ Inflicts \status1 to the Pokémon in \slot.
|
||||
@ If \slot is greater or equal than PARTY_SIZE, the status is inflicted on each of the Player's Pokémon.
|
||||
.macro setstatus1 status1:req, slot:req
|
||||
callnative Script_SetStatus1
|
||||
callnative Script_SetStatus1, requests_effects=1
|
||||
.2byte \status1
|
||||
.2byte \slot
|
||||
.endm
|
||||
|
||||
@ Sets VAR_RESULT to the Pokémon in \slot's Tera Type
|
||||
.macro checkteratype slot:req
|
||||
callnative CheckTeraType
|
||||
callnative CheckTeraType, requests_effects=1
|
||||
.2byte \slot
|
||||
.endm
|
||||
|
||||
@ Sets the Pokémon in \slot's Tera Type
|
||||
.macro setteratype type:req, slot:req
|
||||
callnative SetTeraType
|
||||
callnative SetTeraType, requests_effects=1
|
||||
.byte \type
|
||||
.2byte \slot
|
||||
.endm
|
||||
|
||||
@ Saves species and forms of Daycare Pokémon to specific vars. Saves the amount of Daycare mon to VAR_RESULT.
|
||||
.macro getdaycaregfx varSpecies1:req varSpecies2:req varForm1:req varForm2:req
|
||||
callnative GetDaycareGraphics
|
||||
callnative GetDaycareGraphics, requests_effects=1
|
||||
.2byte \varSpecies1
|
||||
.2byte \varSpecies2
|
||||
.2byte \varForm1
|
||||
@ -2280,12 +2291,12 @@
|
||||
|
||||
@ Plays the cry of the first alive party member.
|
||||
.macro playfirstmoncry
|
||||
callnative PlayFirstMonCry
|
||||
callnative PlayFirstMonCry, requests_effects=1
|
||||
.endm
|
||||
|
||||
@ Buffers the nickname of the first alive party member.
|
||||
.macro bufferlivemonnickname out:req
|
||||
callnative BufferFirstLiveMonNickname
|
||||
callnative BufferFirstLiveMonNickname, requests_effects=1
|
||||
.byte \out
|
||||
.endm
|
||||
|
||||
@ -2296,13 +2307,13 @@
|
||||
|
||||
@ Checks if Field move is being used by the current follower.
|
||||
.macro isfollowerfieldmoveuser var:req
|
||||
callnative IsFollowerFieldMoveUser
|
||||
callnative IsFollowerFieldMoveUser, requests_effects=1
|
||||
.2byte \var
|
||||
.endm
|
||||
|
||||
@ Saves the direction from where source object event would need to turn to to face the target into the specified var.
|
||||
.macro getdirectiontoface var:req, sourceId:req, targetId:req
|
||||
callnative GetDirectionToFaceScript
|
||||
callnative GetDirectionToFaceScript, requests_effects=1
|
||||
.2byte \var
|
||||
.byte \sourceId
|
||||
.byte \targetId
|
||||
@ -2311,50 +2322,50 @@
|
||||
@ set the wild double battle flag
|
||||
@ can be used in conjunection with createmon to set up a wild battle with 2 player mons vs. 1 enemy mon
|
||||
.macro setwilddoubleflag
|
||||
callnative ScriptSetDoubleBattleFlag
|
||||
callnative ScriptSetDoubleBattleFlag, requests_effects=1
|
||||
.endm
|
||||
|
||||
@ When OW_USE_FAKE_RTC and OW_FLAG_PAUSE_TIME is assigned, this macro will stop the flow of time.
|
||||
.macro pausefakertc
|
||||
callnative Script_PauseFakeRtc
|
||||
callnative Script_PauseFakeRtc, requests_effects=1
|
||||
.endm
|
||||
|
||||
@ When OW_USE_FAKE_RTC and OW_FLAG_PAUSE_TIME is assigned, this macro will resume the flow of time.
|
||||
.macro resumefakertc
|
||||
callnative Script_ResumeFakeRtc
|
||||
callnative Script_ResumeFakeRtc, requests_effects=1
|
||||
.endm
|
||||
|
||||
@ When OW_USE_FAKE_RTC and OW_FLAG_PAUSE_TIME is assigned, this macro will resume the flow of time if paused, and stop the flow of time otherwise.
|
||||
.macro togglefakertc
|
||||
callnative Script_ToggleFakeRtc
|
||||
callnative Script_ToggleFakeRtc, requests_effects=1
|
||||
.endm
|
||||
|
||||
@ ============================ @
|
||||
@ ITEM DESCRIPTION HEADER MACROS
|
||||
@ Used with OW_SHOW_ITEM_DESCRIPTIONS config
|
||||
.macro showitemdescription
|
||||
callnative ScriptShowItemDescription
|
||||
callnative ScriptShowItemDescription, requests_effects=1
|
||||
.byte 0
|
||||
.endm
|
||||
|
||||
.macro showberrydescription
|
||||
callnative ScriptShowItemDescription
|
||||
callnative ScriptShowItemDescription, requests_effects=1
|
||||
.byte 1
|
||||
.endm
|
||||
|
||||
.macro hideitemdescription
|
||||
callnative ScriptHideItemDescription
|
||||
callnative ScriptHideItemDescription, requests_effects=1
|
||||
.endm
|
||||
|
||||
@ Remove all of specified item from the player's bag and return the number of removed items to VAR_RESULT
|
||||
.macro removeallitem itemId:req
|
||||
callnative ScrCmd_removeallitem
|
||||
callnative ScrCmd_removeallitem, requests_effects=1
|
||||
.2byte \itemId
|
||||
.endm
|
||||
|
||||
@ Stores the position of the given object in destX and destY. Mode CURRENT_POSITION will take the object's current position. Mode TEMPLATE_POSITION will take the object's template position.
|
||||
.macro getobjectxy localId:req, posType:req, destX:req, destY:req
|
||||
callnative ScrCmd_getobjectxy
|
||||
callnative ScrCmd_getobjectxy, request_effects=1
|
||||
.2byte \localId
|
||||
.2byte \posType
|
||||
.2byte \destX
|
||||
@ -2362,7 +2373,7 @@
|
||||
.endm
|
||||
|
||||
.macro getobjecttemplatexy localId:req, posType = TEMPLATE_POSITION, destX:req, destY:req
|
||||
callnative ScrCmd_getobjectxy
|
||||
callnative ScrCmd_getobjectxy, request_effects=1
|
||||
.2byte \localId
|
||||
.2byte \posType
|
||||
.2byte \destX
|
||||
@ -2370,7 +2381,7 @@
|
||||
.endm
|
||||
|
||||
.macro getobjectcurrentxy localId:req, posType = CURRENT_POSITION, destX:req, destY:req
|
||||
callnative ScrCmd_getobjectxy
|
||||
callnative ScrCmd_getobjectxy, request_effects=1
|
||||
.2byte \localId
|
||||
.2byte \posType
|
||||
.2byte \destX
|
||||
@ -2379,7 +2390,7 @@
|
||||
|
||||
@ Return TRUE to dest if there is an object at the position x and y.
|
||||
.macro checkobjectat x:req, y:req, dest = VAR_RESULT
|
||||
callnative ScrCmd_checkobjectat
|
||||
callnative ScrCmd_checkobjectat, request_effects=1
|
||||
.2byte \x
|
||||
.2byte \y
|
||||
.2byte \dest
|
||||
@ -2387,28 +2398,28 @@
|
||||
|
||||
@ Returns the state of the Pokedex Seen Flag to VAR_RESULT for the Pokemon with speciesId
|
||||
.macro getseenmon species:req
|
||||
callnative Scrcmd_getsetpokedexflag
|
||||
callnative Scrcmd_getsetpokedexflag, request_effects=1
|
||||
.2byte \species
|
||||
.2byte FLAG_GET_SEEN
|
||||
.endm
|
||||
|
||||
@ Returns the state of the Pokedex Caught Flag to VAR_RESULT for the Pokemon with speciesId
|
||||
.macro getcaughtmon species:req
|
||||
callnative Scrcmd_getsetpokedexflag
|
||||
callnative Scrcmd_getsetpokedexflag, request_effects=1
|
||||
.2byte \species
|
||||
.2byte FLAG_GET_CAUGHT
|
||||
.endm
|
||||
|
||||
@ Sets the Pokedex Seen Flag for the Pokemon with speciesId
|
||||
.macro setseenmon species:req
|
||||
callnative Scrcmd_getsetpokedexflag
|
||||
callnative Scrcmd_getsetpokedexflag, request_effects=1
|
||||
.2byte \species
|
||||
.2byte FLAG_SET_SEEN
|
||||
.endm
|
||||
|
||||
@ Sets the Pokedex Caught Flag for the Pokemon with speciesId
|
||||
.macro setcaughtmon species:req
|
||||
callnative Scrcmd_getsetpokedexflag
|
||||
callnative Scrcmd_getsetpokedexflag, request_effects=1
|
||||
.2byte \species
|
||||
.2byte FLAG_SET_CAUGHT
|
||||
.endm
|
||||
@ -2418,10 +2429,10 @@
|
||||
.if \mode == OPEN_PARTY_SCREEN
|
||||
special ChoosePartyMon
|
||||
waitstate
|
||||
callnative Scrcmd_checkspecies_choose
|
||||
callnative Scrcmd_checkspecies_choose, request_effects=1
|
||||
.2byte \speciesId
|
||||
.else
|
||||
callnative Scrcmd_checkspecies
|
||||
callnative Scrcmd_checkspecies, request_effects=1
|
||||
.2byte \speciesId
|
||||
.endif
|
||||
.endm
|
||||
@ -2432,24 +2443,85 @@
|
||||
|
||||
@ Gets the facing direction of a given event object and stores it in the variable dest.
|
||||
.macro getobjectfacingdirection localId:req, dest:req
|
||||
callnative Scrcmd_getobjectfacingdirection
|
||||
callnative Scrcmd_getobjectfacingdirection, request_effects=1
|
||||
.2byte \localId
|
||||
.2byte \dest
|
||||
.endm
|
||||
|
||||
.macro increasedifficulty
|
||||
callnative Script_IncreaseDifficulty
|
||||
callnative Script_IncreaseDifficulty, requests_effects=1
|
||||
.endm
|
||||
|
||||
.macro decreasedifficulty
|
||||
callnative Script_DecreaseDifficulty
|
||||
callnative Script_DecreaseDifficulty, requests_effects=1
|
||||
.endm
|
||||
|
||||
.macro getdifficulty var:req
|
||||
callnative Script_GetDifficulty
|
||||
callnative Script_GetDifficulty, requests_effects=1
|
||||
.endm
|
||||
|
||||
.macro setdifficulty difficulty:req
|
||||
callnative Script_SetDifficulty
|
||||
callnative Script_SetDifficulty, requests_effects=1
|
||||
.byte \difficulty
|
||||
.endm
|
||||
|
||||
@ Makes the trainer unable to see the player if executed.
|
||||
@ This is a no-op if the player interacts with the trainer.
|
||||
.macro cant_see_if, condition:req
|
||||
callnative Script_EndTrainerCanSeeIf, requests_effects=1
|
||||
.byte \condition
|
||||
.endm
|
||||
|
||||
.macro cant_see
|
||||
cant_see_if_unset 0 @ flag 0 is always FALSE.
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_unset, flag:req
|
||||
checkflag \flag
|
||||
cant_see_if FALSE
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_set, flag:req
|
||||
checkflag \flag
|
||||
cant_see_if TRUE
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_trainerflag_unset, trainer:req
|
||||
checktrainerflag \trainer
|
||||
cant_see_if FALSE
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_trainerflag_set, trainer:req
|
||||
checktrainerflag \trainer
|
||||
cant_see_if TRUE
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_lt, a:req, b:req
|
||||
compare \a, \b
|
||||
cant_see_if 0
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_eq, a:req, b:req
|
||||
compare \a, \b
|
||||
cant_see_if 1
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_gt, a:req, b:req
|
||||
compare \a, \b
|
||||
cant_see_if 2
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_le, a:req, b:req
|
||||
compare \a, \b
|
||||
cant_see_if 3
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_ge, a:req, b:req
|
||||
compare \a, \b
|
||||
cant_see_if 4
|
||||
.endm
|
||||
|
||||
.macro cant_see_if_ne, a:req, b:req
|
||||
compare \a, \b
|
||||
cant_see_if 5
|
||||
.endm
|
||||
|
||||
@ -29,6 +29,9 @@
|
||||
|
||||
.set OAM, 0x7000000
|
||||
|
||||
.set ROM, 0x8000000
|
||||
.set ROM_SIZE, 0x2000000
|
||||
|
||||
.set SOUND_INFO_PTR, 0x3007FF0
|
||||
.set INTR_CHECK, 0x3007FF8
|
||||
.set INTR_VECTOR, 0x3007FFC
|
||||
|
||||
@ -11,6 +11,7 @@ Route110_MapScripts::
|
||||
|
||||
Route110_OnResume:
|
||||
special UpdateCyclingRoadState
|
||||
msgbox Route110_Text_WeCantTalkAboutAquaActivities, MSGBOX_SIGN
|
||||
end
|
||||
|
||||
Route110_OnTransition:
|
||||
|
||||
@ -1,234 +1,245 @@
|
||||
@ 'requests_effects' should be set to 1 if the command contains a call
|
||||
@ to 'Script_RequestEffects', which allows it to be analyzed with
|
||||
@ 'RunScriptImmediatelyUntilEffect'.
|
||||
.macro cmd func:req, requests_effects=0
|
||||
.if \requests_effects == 0
|
||||
.4byte \func
|
||||
.else
|
||||
.4byte \func + ROM_SIZE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.align 2
|
||||
gScriptCmdTable::
|
||||
.4byte ScrCmd_nop @ 0x00
|
||||
.4byte ScrCmd_nop1 @ 0x01
|
||||
.4byte ScrCmd_end @ 0x02
|
||||
.4byte ScrCmd_return @ 0x03
|
||||
.4byte ScrCmd_call @ 0x04
|
||||
.4byte ScrCmd_goto @ 0x05
|
||||
.4byte ScrCmd_goto_if @ 0x06
|
||||
.4byte ScrCmd_call_if @ 0x07
|
||||
.4byte ScrCmd_gotostd @ 0x08
|
||||
.4byte ScrCmd_callstd @ 0x09
|
||||
.4byte ScrCmd_gotostd_if @ 0x0a
|
||||
.4byte ScrCmd_callstd_if @ 0x0b
|
||||
.4byte ScrCmd_returnram @ 0x0c
|
||||
.4byte ScrCmd_endram @ 0x0d
|
||||
.4byte ScrCmd_setmysteryeventstatus @ 0x0e
|
||||
.4byte ScrCmd_loadword @ 0x0f
|
||||
.4byte ScrCmd_loadbyte @ 0x10
|
||||
.4byte ScrCmd_setptr @ 0x11
|
||||
.4byte ScrCmd_loadbytefromptr @ 0x12
|
||||
.4byte ScrCmd_setptrbyte @ 0x13
|
||||
.4byte ScrCmd_copylocal @ 0x14
|
||||
.4byte ScrCmd_copybyte @ 0x15
|
||||
.4byte ScrCmd_setvar @ 0x16
|
||||
.4byte ScrCmd_addvar @ 0x17
|
||||
.4byte ScrCmd_subvar @ 0x18
|
||||
.4byte ScrCmd_copyvar @ 0x19
|
||||
.4byte ScrCmd_setorcopyvar @ 0x1a
|
||||
.4byte ScrCmd_compare_local_to_local @ 0x1b
|
||||
.4byte ScrCmd_compare_local_to_value @ 0x1c
|
||||
.4byte ScrCmd_compare_local_to_ptr @ 0x1d
|
||||
.4byte ScrCmd_compare_ptr_to_local @ 0x1e
|
||||
.4byte ScrCmd_compare_ptr_to_value @ 0x1f
|
||||
.4byte ScrCmd_compare_ptr_to_ptr @ 0x20
|
||||
.4byte ScrCmd_compare_var_to_value @ 0x21
|
||||
.4byte ScrCmd_compare_var_to_var @ 0x22
|
||||
.4byte ScrCmd_callnative @ 0x23
|
||||
.4byte ScrCmd_gotonative @ 0x24
|
||||
.4byte ScrCmd_special @ 0x25
|
||||
.4byte ScrCmd_specialvar @ 0x26
|
||||
.4byte ScrCmd_waitstate @ 0x27
|
||||
.4byte ScrCmd_delay @ 0x28
|
||||
.4byte ScrCmd_setflag @ 0x29
|
||||
.4byte ScrCmd_clearflag @ 0x2a
|
||||
.4byte ScrCmd_checkflag @ 0x2b
|
||||
.4byte ScrCmd_initclock @ 0x2c
|
||||
.4byte ScrCmd_dotimebasedevents @ 0x2d
|
||||
.4byte ScrCmd_gettime @ 0x2e
|
||||
.4byte ScrCmd_playse @ 0x2f
|
||||
.4byte ScrCmd_waitse @ 0x30
|
||||
.4byte ScrCmd_playfanfare @ 0x31
|
||||
.4byte ScrCmd_waitfanfare @ 0x32
|
||||
.4byte ScrCmd_playbgm @ 0x33
|
||||
.4byte ScrCmd_savebgm @ 0x34
|
||||
.4byte ScrCmd_fadedefaultbgm @ 0x35
|
||||
.4byte ScrCmd_fadenewbgm @ 0x36
|
||||
.4byte ScrCmd_fadeoutbgm @ 0x37
|
||||
.4byte ScrCmd_fadeinbgm @ 0x38
|
||||
.4byte ScrCmd_warp @ 0x39
|
||||
.4byte ScrCmd_warpsilent @ 0x3a
|
||||
.4byte ScrCmd_warpdoor @ 0x3b
|
||||
.4byte ScrCmd_warphole @ 0x3c
|
||||
.4byte ScrCmd_warpteleport @ 0x3d
|
||||
.4byte ScrCmd_setwarp @ 0x3e
|
||||
.4byte ScrCmd_setdynamicwarp @ 0x3f
|
||||
.4byte ScrCmd_setdivewarp @ 0x40
|
||||
.4byte ScrCmd_setholewarp @ 0x41
|
||||
.4byte ScrCmd_getplayerxy @ 0x42
|
||||
.4byte ScrCmd_getpartysize @ 0x43
|
||||
.4byte ScrCmd_additem @ 0x44
|
||||
.4byte ScrCmd_removeitem @ 0x45
|
||||
.4byte ScrCmd_checkitemspace @ 0x46
|
||||
.4byte ScrCmd_checkitem @ 0x47
|
||||
.4byte ScrCmd_checkitemtype @ 0x48
|
||||
.4byte ScrCmd_addpcitem @ 0x49
|
||||
.4byte ScrCmd_checkpcitem @ 0x4a
|
||||
.4byte ScrCmd_adddecoration @ 0x4b
|
||||
.4byte ScrCmd_removedecoration @ 0x4c
|
||||
.4byte ScrCmd_checkdecor @ 0x4d
|
||||
.4byte ScrCmd_checkdecorspace @ 0x4e
|
||||
.4byte ScrCmd_applymovement @ 0x4f
|
||||
.4byte ScrCmd_applymovementat @ 0x50
|
||||
.4byte ScrCmd_waitmovement @ 0x51
|
||||
.4byte ScrCmd_waitmovementat @ 0x52
|
||||
.4byte ScrCmd_removeobject @ 0x53
|
||||
.4byte ScrCmd_removeobjectat @ 0x54
|
||||
.4byte ScrCmd_addobject @ 0x55
|
||||
.4byte ScrCmd_addobjectat @ 0x56
|
||||
.4byte ScrCmd_setobjectxy @ 0x57
|
||||
.4byte ScrCmd_showobjectat @ 0x58
|
||||
.4byte ScrCmd_hideobjectat @ 0x59
|
||||
.4byte ScrCmd_faceplayer @ 0x5a
|
||||
.4byte ScrCmd_turnobject @ 0x5b
|
||||
.4byte ScrCmd_trainerbattle @ 0x5c
|
||||
.4byte ScrCmd_dotrainerbattle @ 0x5d
|
||||
.4byte ScrCmd_gotopostbattlescript @ 0x5e
|
||||
.4byte ScrCmd_gotobeatenscript @ 0x5f
|
||||
.4byte ScrCmd_checktrainerflag @ 0x60
|
||||
.4byte ScrCmd_settrainerflag @ 0x61
|
||||
.4byte ScrCmd_cleartrainerflag @ 0x62
|
||||
.4byte ScrCmd_setobjectxyperm @ 0x63
|
||||
.4byte ScrCmd_copyobjectxytoperm @ 0x64
|
||||
.4byte ScrCmd_setobjectmovementtype @ 0x65
|
||||
.4byte ScrCmd_waitmessage @ 0x66
|
||||
.4byte ScrCmd_message @ 0x67
|
||||
.4byte ScrCmd_closemessage @ 0x68
|
||||
.4byte ScrCmd_lockall @ 0x69
|
||||
.4byte ScrCmd_lock @ 0x6a
|
||||
.4byte ScrCmd_releaseall @ 0x6b
|
||||
.4byte ScrCmd_release @ 0x6c
|
||||
.4byte ScrCmd_waitbuttonpress @ 0x6d
|
||||
.4byte ScrCmd_yesnobox @ 0x6e
|
||||
.4byte ScrCmd_multichoice @ 0x6f
|
||||
.4byte ScrCmd_multichoicedefault @ 0x70
|
||||
.4byte ScrCmd_multichoicegrid @ 0x71
|
||||
.4byte ScrCmd_drawbox @ 0x72
|
||||
.4byte ScrCmd_erasebox @ 0x73
|
||||
.4byte ScrCmd_drawboxtext @ 0x74
|
||||
.4byte ScrCmd_showmonpic @ 0x75
|
||||
.4byte ScrCmd_hidemonpic @ 0x76
|
||||
.4byte ScrCmd_showcontestpainting @ 0x77
|
||||
.4byte ScrCmd_braillemessage @ 0x78
|
||||
.4byte ScrCmd_nop1 @ 0x79
|
||||
.4byte ScrCmd_giveegg @ 0x7a
|
||||
.4byte ScrCmd_setmonmove @ 0x7b
|
||||
.4byte ScrCmd_checkpartymove @ 0x7c
|
||||
.4byte ScrCmd_bufferspeciesname @ 0x7d
|
||||
.4byte ScrCmd_bufferleadmonspeciesname @ 0x7e
|
||||
.4byte ScrCmd_bufferpartymonnick @ 0x7f
|
||||
.4byte ScrCmd_bufferitemname @ 0x80
|
||||
.4byte ScrCmd_bufferdecorationname @ 0x81
|
||||
.4byte ScrCmd_buffermovename @ 0x82
|
||||
.4byte ScrCmd_buffernumberstring @ 0x83
|
||||
.4byte ScrCmd_bufferstdstring @ 0x84
|
||||
.4byte ScrCmd_bufferstring @ 0x85
|
||||
.4byte ScrCmd_pokemart @ 0x86
|
||||
.4byte ScrCmd_pokemartdecoration @ 0x87
|
||||
.4byte ScrCmd_pokemartdecoration2 @ 0x88
|
||||
.4byte ScrCmd_playslotmachine @ 0x89
|
||||
.4byte ScrCmd_setberrytree @ 0x8a
|
||||
.4byte ScrCmd_choosecontestmon @ 0x8b
|
||||
.4byte ScrCmd_startcontest @ 0x8c
|
||||
.4byte ScrCmd_showcontestresults @ 0x8d
|
||||
.4byte ScrCmd_contestlinktransfer @ 0x8e
|
||||
.4byte ScrCmd_random @ 0x8f
|
||||
.4byte ScrCmd_addmoney @ 0x90
|
||||
.4byte ScrCmd_removemoney @ 0x91
|
||||
.4byte ScrCmd_checkmoney @ 0x92
|
||||
.4byte ScrCmd_showmoneybox @ 0x93
|
||||
.4byte ScrCmd_hidemoneybox @ 0x94
|
||||
.4byte ScrCmd_updatemoneybox @ 0x95
|
||||
.4byte ScrCmd_getpokenewsactive @ 0x96
|
||||
.4byte ScrCmd_fadescreen @ 0x97
|
||||
.4byte ScrCmd_fadescreenspeed @ 0x98
|
||||
.4byte ScrCmd_setflashlevel @ 0x99
|
||||
.4byte ScrCmd_animateflash @ 0x9a
|
||||
.4byte ScrCmd_messageautoscroll @ 0x9b
|
||||
.4byte ScrCmd_dofieldeffect @ 0x9c
|
||||
.4byte ScrCmd_setfieldeffectargument @ 0x9d
|
||||
.4byte ScrCmd_waitfieldeffect @ 0x9e
|
||||
.4byte ScrCmd_setrespawn @ 0x9f
|
||||
.4byte ScrCmd_checkplayergender @ 0xa0
|
||||
.4byte ScrCmd_playmoncry @ 0xa1
|
||||
.4byte ScrCmd_setmetatile @ 0xa2
|
||||
.4byte ScrCmd_resetweather @ 0xa3
|
||||
.4byte ScrCmd_setweather @ 0xa4
|
||||
.4byte ScrCmd_doweather @ 0xa5
|
||||
.4byte ScrCmd_setstepcallback @ 0xa6
|
||||
.4byte ScrCmd_setmaplayoutindex @ 0xa7
|
||||
.4byte ScrCmd_setobjectsubpriority @ 0xa8
|
||||
.4byte ScrCmd_resetobjectsubpriority @ 0xa9
|
||||
.4byte ScrCmd_createvobject @ 0xaa
|
||||
.4byte ScrCmd_turnvobject @ 0xab
|
||||
.4byte ScrCmd_opendoor @ 0xac
|
||||
.4byte ScrCmd_closedoor @ 0xad
|
||||
.4byte ScrCmd_waitdooranim @ 0xae
|
||||
.4byte ScrCmd_setdooropen @ 0xaf
|
||||
.4byte ScrCmd_setdoorclosed @ 0xb0
|
||||
.4byte ScrCmd_addelevmenuitem @ 0xb1
|
||||
.4byte ScrCmd_showelevmenu @ 0xb2
|
||||
.4byte ScrCmd_checkcoins @ 0xb3
|
||||
.4byte ScrCmd_addcoins @ 0xb4
|
||||
.4byte ScrCmd_removecoins @ 0xb5
|
||||
.4byte ScrCmd_setwildbattle @ 0xb6
|
||||
.4byte ScrCmd_dowildbattle @ 0xb7
|
||||
.4byte ScrCmd_setvaddress @ 0xb8
|
||||
.4byte ScrCmd_vgoto @ 0xb9
|
||||
.4byte ScrCmd_vcall @ 0xba
|
||||
.4byte ScrCmd_vgoto_if @ 0xbb
|
||||
.4byte ScrCmd_vcall_if @ 0xbc
|
||||
.4byte ScrCmd_vmessage @ 0xbd
|
||||
.4byte ScrCmd_vbuffermessage @ 0xbe
|
||||
.4byte ScrCmd_vbufferstring @ 0xbf
|
||||
.4byte ScrCmd_showcoinsbox @ 0xc0
|
||||
.4byte ScrCmd_hidecoinsbox @ 0xc1
|
||||
.4byte ScrCmd_updatecoinsbox @ 0xc2
|
||||
.4byte ScrCmd_incrementgamestat @ 0xc3
|
||||
.4byte ScrCmd_setescapewarp @ 0xc4
|
||||
.4byte ScrCmd_waitmoncry @ 0xc5
|
||||
.4byte ScrCmd_bufferboxname @ 0xc6
|
||||
.4byte ScrCmd_nop1 @ 0xc7
|
||||
.4byte ScrCmd_nop1 @ 0xc8
|
||||
.4byte ScrCmd_nop1 @ 0xc9
|
||||
.4byte ScrCmd_nop1 @ 0xca
|
||||
.4byte ScrCmd_nop1 @ 0xcb
|
||||
.4byte ScrCmd_nop1 @ 0xcc
|
||||
.4byte ScrCmd_setmodernfatefulencounter @ 0xcd
|
||||
.4byte ScrCmd_checkmodernfatefulencounter @ 0xce
|
||||
.4byte ScrCmd_trywondercardscript @ 0xcf
|
||||
.4byte ScrCmd_nop1 @ 0xd0
|
||||
.4byte ScrCmd_warpspinenter @ 0xd1
|
||||
.4byte ScrCmd_setmonmetlocation @ 0xd2
|
||||
.4byte ScrCmd_moverotatingtileobjects @ 0xd3
|
||||
.4byte ScrCmd_turnrotatingtileobjects @ 0xd4
|
||||
.4byte ScrCmd_initrotatingtilepuzzle @ 0xd5
|
||||
.4byte ScrCmd_freerotatingtilepuzzle @ 0xd6
|
||||
.4byte ScrCmd_warpmossdeepgym @ 0xd7
|
||||
.4byte ScrCmd_selectapproachingtrainer @ 0xd8
|
||||
.4byte ScrCmd_lockfortrainer @ 0xd9
|
||||
.4byte ScrCmd_closebraillemessage @ 0xda
|
||||
.4byte ScrCmd_messageinstant @ 0xdb
|
||||
.4byte ScrCmd_fadescreenswapbuffers @ 0xdc
|
||||
.4byte ScrCmd_buffertrainerclassname @ 0xdd
|
||||
.4byte ScrCmd_buffertrainername @ 0xde
|
||||
.4byte ScrCmd_pokenavcall @ 0xdf
|
||||
.4byte ScrCmd_warpwhitefade @ 0xe0
|
||||
.4byte ScrCmd_buffercontestname @ 0xe1
|
||||
.4byte ScrCmd_bufferitemnameplural @ 0xe2
|
||||
.4byte ScrCmd_dynmultichoice @ 0xe3
|
||||
.4byte ScrCmd_dynmultipush @ 0xe4
|
||||
cmd ScrCmd_nop, requests_effects=1 @ 0x00
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0x01
|
||||
cmd ScrCmd_end, requests_effects=1 @ 0x02
|
||||
cmd ScrCmd_return, requests_effects=1 @ 0x03
|
||||
cmd ScrCmd_call, requests_effects=1 @ 0x04
|
||||
cmd ScrCmd_goto, requests_effects=1 @ 0x05
|
||||
cmd ScrCmd_goto_if, requests_effects=1 @ 0x06
|
||||
cmd ScrCmd_call_if, requests_effects=1 @ 0x07
|
||||
cmd ScrCmd_gotostd, requests_effects=1 @ 0x08
|
||||
cmd ScrCmd_callstd, requests_effects=1 @ 0x09
|
||||
cmd ScrCmd_gotostd_if, requests_effects=1 @ 0x0a
|
||||
cmd ScrCmd_callstd_if, requests_effects=1 @ 0x0b
|
||||
cmd ScrCmd_returnram, requests_effects=1 @ 0x0c
|
||||
cmd ScrCmd_endram, requests_effects=1 @ 0x0d
|
||||
cmd ScrCmd_setmysteryeventstatus, requests_effects=1 @ 0x0e
|
||||
cmd ScrCmd_loadword, requests_effects=1 @ 0x0f
|
||||
cmd ScrCmd_loadbyte, requests_effects=1 @ 0x10
|
||||
cmd ScrCmd_setptr, requests_effects=1 @ 0x11
|
||||
cmd ScrCmd_loadbytefromptr, requests_effects=1 @ 0x12
|
||||
cmd ScrCmd_setptrbyte, requests_effects=1 @ 0x13
|
||||
cmd ScrCmd_copylocal, requests_effects=1 @ 0x14
|
||||
cmd ScrCmd_copybyte, requests_effects=1 @ 0x15
|
||||
cmd ScrCmd_setvar, requests_effects=1 @ 0x16
|
||||
cmd ScrCmd_addvar, requests_effects=1 @ 0x17
|
||||
cmd ScrCmd_subvar, requests_effects=1 @ 0x18
|
||||
cmd ScrCmd_copyvar, requests_effects=1 @ 0x19
|
||||
cmd ScrCmd_setorcopyvar, requests_effects=1 @ 0x1a
|
||||
cmd ScrCmd_compare_local_to_local, requests_effects=1 @ 0x1b
|
||||
cmd ScrCmd_compare_local_to_value, requests_effects=1 @ 0x1c
|
||||
cmd ScrCmd_compare_local_to_ptr, requests_effects=1 @ 0x1d
|
||||
cmd ScrCmd_compare_ptr_to_local, requests_effects=1 @ 0x1e
|
||||
cmd ScrCmd_compare_ptr_to_value, requests_effects=1 @ 0x1f
|
||||
cmd ScrCmd_compare_ptr_to_ptr, requests_effects=1 @ 0x20
|
||||
cmd ScrCmd_compare_var_to_value, requests_effects=1 @ 0x21
|
||||
cmd ScrCmd_compare_var_to_var, requests_effects=1 @ 0x22
|
||||
cmd ScrCmd_callnative, requests_effects=1 @ 0x23
|
||||
cmd ScrCmd_gotonative, requests_effects=1 @ 0x24
|
||||
cmd ScrCmd_special, requests_effects=1 @ 0x25
|
||||
cmd ScrCmd_specialvar, requests_effects=1 @ 0x26
|
||||
cmd ScrCmd_waitstate, requests_effects=1 @ 0x27
|
||||
cmd ScrCmd_delay, requests_effects=1 @ 0x28
|
||||
cmd ScrCmd_setflag, requests_effects=1 @ 0x29
|
||||
cmd ScrCmd_clearflag, requests_effects=1 @ 0x2a
|
||||
cmd ScrCmd_checkflag, requests_effects=1 @ 0x2b
|
||||
cmd ScrCmd_initclock, requests_effects=1 @ 0x2c
|
||||
cmd ScrCmd_dotimebasedevents, requests_effects=1 @ 0x2d
|
||||
cmd ScrCmd_gettime, requests_effects=1 @ 0x2e
|
||||
cmd ScrCmd_playse, requests_effects=1 @ 0x2f
|
||||
cmd ScrCmd_waitse, requests_effects=1 @ 0x30
|
||||
cmd ScrCmd_playfanfare, requests_effects=1 @ 0x31
|
||||
cmd ScrCmd_waitfanfare, requests_effects=1 @ 0x32
|
||||
cmd ScrCmd_playbgm, requests_effects=1 @ 0x33
|
||||
cmd ScrCmd_savebgm, requests_effects=1 @ 0x34
|
||||
cmd ScrCmd_fadedefaultbgm, requests_effects=1 @ 0x35
|
||||
cmd ScrCmd_fadenewbgm, requests_effects=1 @ 0x36
|
||||
cmd ScrCmd_fadeoutbgm, requests_effects=1 @ 0x37
|
||||
cmd ScrCmd_fadeinbgm, requests_effects=1 @ 0x38
|
||||
cmd ScrCmd_warp, requests_effects=1 @ 0x39
|
||||
cmd ScrCmd_warpsilent, requests_effects=1 @ 0x3a
|
||||
cmd ScrCmd_warpdoor, requests_effects=1 @ 0x3b
|
||||
cmd ScrCmd_warphole, requests_effects=1 @ 0x3c
|
||||
cmd ScrCmd_warpteleport, requests_effects=1 @ 0x3d
|
||||
cmd ScrCmd_setwarp, requests_effects=1 @ 0x3e
|
||||
cmd ScrCmd_setdynamicwarp, requests_effects=1 @ 0x3f
|
||||
cmd ScrCmd_setdivewarp, requests_effects=1 @ 0x40
|
||||
cmd ScrCmd_setholewarp, requests_effects=1 @ 0x41
|
||||
cmd ScrCmd_getplayerxy, requests_effects=1 @ 0x42
|
||||
cmd ScrCmd_getpartysize, requests_effects=1 @ 0x43
|
||||
cmd ScrCmd_additem, requests_effects=1 @ 0x44
|
||||
cmd ScrCmd_removeitem, requests_effects=1 @ 0x45
|
||||
cmd ScrCmd_checkitemspace, requests_effects=1 @ 0x46
|
||||
cmd ScrCmd_checkitem, requests_effects=1 @ 0x47
|
||||
cmd ScrCmd_checkitemtype, requests_effects=1 @ 0x48
|
||||
cmd ScrCmd_addpcitem, requests_effects=1 @ 0x49
|
||||
cmd ScrCmd_checkpcitem, requests_effects=1 @ 0x4a
|
||||
cmd ScrCmd_adddecoration, requests_effects=1 @ 0x4b
|
||||
cmd ScrCmd_removedecoration, requests_effects=1 @ 0x4c
|
||||
cmd ScrCmd_checkdecor, requests_effects=1 @ 0x4d
|
||||
cmd ScrCmd_checkdecorspace, requests_effects=1 @ 0x4e
|
||||
cmd ScrCmd_applymovement, requests_effects=1 @ 0x4f
|
||||
cmd ScrCmd_applymovementat, requests_effects=1 @ 0x50
|
||||
cmd ScrCmd_waitmovement, requests_effects=1 @ 0x51
|
||||
cmd ScrCmd_waitmovementat, requests_effects=1 @ 0x52
|
||||
cmd ScrCmd_removeobject, requests_effects=1 @ 0x53
|
||||
cmd ScrCmd_removeobjectat, requests_effects=1 @ 0x54
|
||||
cmd ScrCmd_addobject, requests_effects=1 @ 0x55
|
||||
cmd ScrCmd_addobjectat, requests_effects=1 @ 0x56
|
||||
cmd ScrCmd_setobjectxy, requests_effects=1 @ 0x57
|
||||
cmd ScrCmd_showobjectat, requests_effects=1 @ 0x58
|
||||
cmd ScrCmd_hideobjectat, requests_effects=1 @ 0x59
|
||||
cmd ScrCmd_faceplayer, requests_effects=1 @ 0x5a
|
||||
cmd ScrCmd_turnobject, requests_effects=1 @ 0x5b
|
||||
cmd ScrCmd_trainerbattle, requests_effects=1 @ 0x5c
|
||||
cmd ScrCmd_dotrainerbattle, requests_effects=1 @ 0x5d
|
||||
cmd ScrCmd_gotopostbattlescript, requests_effects=1 @ 0x5e
|
||||
cmd ScrCmd_gotobeatenscript, requests_effects=1 @ 0x5f
|
||||
cmd ScrCmd_checktrainerflag, requests_effects=1 @ 0x60
|
||||
cmd ScrCmd_settrainerflag, requests_effects=1 @ 0x61
|
||||
cmd ScrCmd_cleartrainerflag, requests_effects=1 @ 0x62
|
||||
cmd ScrCmd_setobjectxyperm, requests_effects=1 @ 0x63
|
||||
cmd ScrCmd_copyobjectxytoperm, requests_effects=1 @ 0x64
|
||||
cmd ScrCmd_setobjectmovementtype, requests_effects=1 @ 0x65
|
||||
cmd ScrCmd_waitmessage, requests_effects=1 @ 0x66
|
||||
cmd ScrCmd_message, requests_effects=1 @ 0x67
|
||||
cmd ScrCmd_closemessage, requests_effects=1 @ 0x68
|
||||
cmd ScrCmd_lockall, requests_effects=1 @ 0x69
|
||||
cmd ScrCmd_lock, requests_effects=1 @ 0x6a
|
||||
cmd ScrCmd_releaseall, requests_effects=1 @ 0x6b
|
||||
cmd ScrCmd_release, requests_effects=1 @ 0x6c
|
||||
cmd ScrCmd_waitbuttonpress, requests_effects=1 @ 0x6d
|
||||
cmd ScrCmd_yesnobox, requests_effects=1 @ 0x6e
|
||||
cmd ScrCmd_multichoice, requests_effects=1 @ 0x6f
|
||||
cmd ScrCmd_multichoicedefault, requests_effects=1 @ 0x70
|
||||
cmd ScrCmd_multichoicegrid, requests_effects=1 @ 0x71
|
||||
cmd ScrCmd_drawbox, requests_effects=1 @ 0x72
|
||||
cmd ScrCmd_erasebox, requests_effects=1 @ 0x73
|
||||
cmd ScrCmd_drawboxtext, requests_effects=1 @ 0x74
|
||||
cmd ScrCmd_showmonpic, requests_effects=1 @ 0x75
|
||||
cmd ScrCmd_hidemonpic, requests_effects=1 @ 0x76
|
||||
cmd ScrCmd_showcontestpainting, requests_effects=1 @ 0x77
|
||||
cmd ScrCmd_braillemessage, requests_effects=1 @ 0x78
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0x79
|
||||
cmd ScrCmd_giveegg, requests_effects=1 @ 0x7a
|
||||
cmd ScrCmd_setmonmove, requests_effects=1 @ 0x7b
|
||||
cmd ScrCmd_checkpartymove, requests_effects=1 @ 0x7c
|
||||
cmd ScrCmd_bufferspeciesname, requests_effects=1 @ 0x7d
|
||||
cmd ScrCmd_bufferleadmonspeciesname, requests_effects=1 @ 0x7e
|
||||
cmd ScrCmd_bufferpartymonnick, requests_effects=1 @ 0x7f
|
||||
cmd ScrCmd_bufferitemname, requests_effects=1 @ 0x80
|
||||
cmd ScrCmd_bufferdecorationname, requests_effects=1 @ 0x81
|
||||
cmd ScrCmd_buffermovename, requests_effects=1 @ 0x82
|
||||
cmd ScrCmd_buffernumberstring, requests_effects=1 @ 0x83
|
||||
cmd ScrCmd_bufferstdstring, requests_effects=1 @ 0x84
|
||||
cmd ScrCmd_bufferstring, requests_effects=1 @ 0x85
|
||||
cmd ScrCmd_pokemart, requests_effects=1 @ 0x86
|
||||
cmd ScrCmd_pokemartdecoration, requests_effects=1 @ 0x87
|
||||
cmd ScrCmd_pokemartdecoration2, requests_effects=1 @ 0x88
|
||||
cmd ScrCmd_playslotmachine, requests_effects=1 @ 0x89
|
||||
cmd ScrCmd_setberrytree, requests_effects=1 @ 0x8a
|
||||
cmd ScrCmd_choosecontestmon, requests_effects=1 @ 0x8b
|
||||
cmd ScrCmd_startcontest, requests_effects=1 @ 0x8c
|
||||
cmd ScrCmd_showcontestresults, requests_effects=1 @ 0x8d
|
||||
cmd ScrCmd_contestlinktransfer, requests_effects=1 @ 0x8e
|
||||
cmd ScrCmd_random, requests_effects=1 @ 0x8f
|
||||
cmd ScrCmd_addmoney, requests_effects=1 @ 0x90
|
||||
cmd ScrCmd_removemoney, requests_effects=1 @ 0x91
|
||||
cmd ScrCmd_checkmoney, requests_effects=1 @ 0x92
|
||||
cmd ScrCmd_showmoneybox, requests_effects=1 @ 0x93
|
||||
cmd ScrCmd_hidemoneybox, requests_effects=1 @ 0x94
|
||||
cmd ScrCmd_updatemoneybox, requests_effects=1 @ 0x95
|
||||
cmd ScrCmd_getpokenewsactive, requests_effects=1 @ 0x96
|
||||
cmd ScrCmd_fadescreen, requests_effects=1 @ 0x97
|
||||
cmd ScrCmd_fadescreenspeed, requests_effects=1 @ 0x98
|
||||
cmd ScrCmd_setflashlevel, requests_effects=1 @ 0x99
|
||||
cmd ScrCmd_animateflash, requests_effects=1 @ 0x9a
|
||||
cmd ScrCmd_messageautoscroll, requests_effects=1 @ 0x9b
|
||||
cmd ScrCmd_dofieldeffect, requests_effects=1 @ 0x9c
|
||||
cmd ScrCmd_setfieldeffectargument, requests_effects=1 @ 0x9d
|
||||
cmd ScrCmd_waitfieldeffect, requests_effects=1 @ 0x9e
|
||||
cmd ScrCmd_setrespawn, requests_effects=1 @ 0x9f
|
||||
cmd ScrCmd_checkplayergender, requests_effects=1 @ 0xa0
|
||||
cmd ScrCmd_playmoncry, requests_effects=1 @ 0xa1
|
||||
cmd ScrCmd_setmetatile, requests_effects=1 @ 0xa2
|
||||
cmd ScrCmd_resetweather, requests_effects=1 @ 0xa3
|
||||
cmd ScrCmd_setweather, requests_effects=1 @ 0xa4
|
||||
cmd ScrCmd_doweather, requests_effects=1 @ 0xa5
|
||||
cmd ScrCmd_setstepcallback, requests_effects=1 @ 0xa6
|
||||
cmd ScrCmd_setmaplayoutindex, requests_effects=1 @ 0xa7
|
||||
cmd ScrCmd_setobjectsubpriority, requests_effects=1 @ 0xa8
|
||||
cmd ScrCmd_resetobjectsubpriority, requests_effects=1 @ 0xa9
|
||||
cmd ScrCmd_createvobject, requests_effects=1 @ 0xaa
|
||||
cmd ScrCmd_turnvobject, requests_effects=1 @ 0xab
|
||||
cmd ScrCmd_opendoor, requests_effects=1 @ 0xac
|
||||
cmd ScrCmd_closedoor, requests_effects=1 @ 0xad
|
||||
cmd ScrCmd_waitdooranim, requests_effects=1 @ 0xae
|
||||
cmd ScrCmd_setdooropen, requests_effects=1 @ 0xaf
|
||||
cmd ScrCmd_setdoorclosed, requests_effects=1 @ 0xb0
|
||||
cmd ScrCmd_addelevmenuitem, requests_effects=1 @ 0xb1
|
||||
cmd ScrCmd_showelevmenu, requests_effects=1 @ 0xb2
|
||||
cmd ScrCmd_checkcoins, requests_effects=1 @ 0xb3
|
||||
cmd ScrCmd_addcoins, requests_effects=1 @ 0xb4
|
||||
cmd ScrCmd_removecoins, requests_effects=1 @ 0xb5
|
||||
cmd ScrCmd_setwildbattle, requests_effects=1 @ 0xb6
|
||||
cmd ScrCmd_dowildbattle, requests_effects=1 @ 0xb7
|
||||
cmd ScrCmd_setvaddress, requests_effects=1 @ 0xb8
|
||||
cmd ScrCmd_vgoto, requests_effects=1 @ 0xb9
|
||||
cmd ScrCmd_vcall, requests_effects=1 @ 0xba
|
||||
cmd ScrCmd_vgoto_if, requests_effects=1 @ 0xbb
|
||||
cmd ScrCmd_vcall_if, requests_effects=1 @ 0xbc
|
||||
cmd ScrCmd_vmessage, requests_effects=1 @ 0xbd
|
||||
cmd ScrCmd_vbuffermessage, requests_effects=1 @ 0xbe
|
||||
cmd ScrCmd_vbufferstring, requests_effects=1 @ 0xbf
|
||||
cmd ScrCmd_showcoinsbox, requests_effects=1 @ 0xc0
|
||||
cmd ScrCmd_hidecoinsbox, requests_effects=1 @ 0xc1
|
||||
cmd ScrCmd_updatecoinsbox, requests_effects=1 @ 0xc2
|
||||
cmd ScrCmd_incrementgamestat, requests_effects=1 @ 0xc3
|
||||
cmd ScrCmd_setescapewarp, requests_effects=1 @ 0xc4
|
||||
cmd ScrCmd_waitmoncry, requests_effects=1 @ 0xc5
|
||||
cmd ScrCmd_bufferboxname, requests_effects=1 @ 0xc6
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0xc7
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0xc8
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0xc9
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0xca
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0xcb
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0xcc
|
||||
cmd ScrCmd_setmodernfatefulencounter, requests_effects=1 @ 0xcd
|
||||
cmd ScrCmd_checkmodernfatefulencounter, requests_effects=1 @ 0xce
|
||||
cmd ScrCmd_trywondercardscript, requests_effects=1 @ 0xcf
|
||||
cmd ScrCmd_nop1, requests_effects=1 @ 0xd0
|
||||
cmd ScrCmd_warpspinenter, requests_effects=1 @ 0xd1
|
||||
cmd ScrCmd_setmonmetlocation, requests_effects=1 @ 0xd2
|
||||
cmd ScrCmd_moverotatingtileobjects, requests_effects=1 @ 0xd3
|
||||
cmd ScrCmd_turnrotatingtileobjects, requests_effects=1 @ 0xd4
|
||||
cmd ScrCmd_initrotatingtilepuzzle, requests_effects=1 @ 0xd5
|
||||
cmd ScrCmd_freerotatingtilepuzzle, requests_effects=1 @ 0xd6
|
||||
cmd ScrCmd_warpmossdeepgym, requests_effects=1 @ 0xd7
|
||||
cmd ScrCmd_selectapproachingtrainer, requests_effects=1 @ 0xd8
|
||||
cmd ScrCmd_lockfortrainer, requests_effects=1 @ 0xd9
|
||||
cmd ScrCmd_closebraillemessage, requests_effects=1 @ 0xda
|
||||
cmd ScrCmd_messageinstant, requests_effects=1 @ 0xdb
|
||||
cmd ScrCmd_fadescreenswapbuffers, requests_effects=1 @ 0xdc
|
||||
cmd ScrCmd_buffertrainerclassname, requests_effects=1 @ 0xdd
|
||||
cmd ScrCmd_buffertrainername, requests_effects=1 @ 0xde
|
||||
cmd ScrCmd_pokenavcall, requests_effects=1 @ 0xdf
|
||||
cmd ScrCmd_warpwhitefade, requests_effects=1 @ 0xe0
|
||||
cmd ScrCmd_buffercontestname, requests_effects=1 @ 0xe1
|
||||
cmd ScrCmd_bufferitemnameplural, requests_effects=1 @ 0xe2
|
||||
cmd ScrCmd_dynmultichoice, requests_effects=1 @ 0xe3
|
||||
cmd ScrCmd_dynmultipush, requests_effects=1 @ 0xe4
|
||||
|
||||
gScriptCmdTableEnd::
|
||||
.4byte ScrCmd_nop
|
||||
|
||||
@ -20,3 +20,9 @@ EventScript_GotoTrainerScript::
|
||||
gotobeatenscript
|
||||
releaseall
|
||||
end
|
||||
|
||||
EventScript_ObjectApproachPlayer::
|
||||
lock
|
||||
special DoTrainerApproach
|
||||
waitstate
|
||||
gotonative LoadTrainerObjectScript
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
.macro def_special ptr
|
||||
@ 'requests_effects' should be set to 1 if the special contains a call
|
||||
@ to 'Script_RequestEffects', which allows it to be analyzed with
|
||||
@ 'RunScriptImmediatelyUntilEffect'.
|
||||
.macro def_special ptr:req, requests_effects=0
|
||||
.global SPECIAL_\ptr
|
||||
.set SPECIAL_\ptr, __special__
|
||||
.set __special__, __special__ + 1
|
||||
.if \requests_effects == 0
|
||||
.4byte \ptr
|
||||
.endm
|
||||
.else
|
||||
.4byte \ptr + ROM_SIZE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.set __special__, 0
|
||||
.align 2
|
||||
@ -297,7 +304,7 @@ gSpecials::
|
||||
def_special WaitWeather
|
||||
def_special BufferEReaderTrainerName
|
||||
def_special GetSlotMachineId
|
||||
def_special GetPlayerFacingDirection
|
||||
def_special GetPlayerFacingDirection, requests_effects=TRUE
|
||||
def_special FoundAbandonedShipRoom1Key
|
||||
def_special FoundAbandonedShipRoom2Key
|
||||
def_special FoundAbandonedShipRoom4Key
|
||||
|
||||
@ -36,6 +36,7 @@ extern const u8 EventScript_TryDoDoubleTrainerBattle[];
|
||||
extern const u8 EventScript_TryDoNormalTrainerBattle[];
|
||||
extern const u8 EventScript_TryDoDoubleRematchBattle[];
|
||||
extern const u8 EventScript_TryDoRematchBattle[];
|
||||
extern const u8 EventScript_ObjectApproachPlayer[];
|
||||
|
||||
extern const u8 BerryTreeScript[];
|
||||
|
||||
|
||||
112
include/script.h
112
include/script.h
@ -1,6 +1,8 @@
|
||||
#ifndef GUARD_SCRIPT_H
|
||||
#define GUARD_SCRIPT_H
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
struct ScriptContext;
|
||||
|
||||
typedef bool8 (*ScrCmdFunc)(struct ScriptContext *);
|
||||
@ -11,6 +13,7 @@ struct ScriptContext
|
||||
u8 stackDepth;
|
||||
u8 mode;
|
||||
u8 comparisonResult;
|
||||
bool8 breakOnTrainerBattle;
|
||||
u8 (*nativePtr)(void);
|
||||
const u8 *scriptPtr;
|
||||
const u8 *stack[20];
|
||||
@ -39,12 +42,13 @@ void ScriptContext_Init(void);
|
||||
bool8 ScriptContext_IsEnabled(void);
|
||||
bool8 ScriptContext_RunScript(void);
|
||||
void ScriptContext_SetupScript(const u8 *ptr);
|
||||
void ScriptContext_ContinueScript(struct ScriptContext *ctx);
|
||||
void ScriptContext_Stop(void);
|
||||
void ScriptContext_Enable(void);
|
||||
void RunScriptImmediately(const u8 *ptr);
|
||||
u8 *MapHeaderGetScriptTable(u8 tag);
|
||||
const u8 *MapHeaderGetScriptTable(u8 tag);
|
||||
void MapHeaderRunScriptType(u8 tag);
|
||||
u8 *MapHeaderCheckScriptTable(u8 tag);
|
||||
const u8 *MapHeaderCheckScriptTable(u8 tag);
|
||||
void RunOnLoadMapScript(void);
|
||||
void RunOnTransitionMapScript(void);
|
||||
void RunOnResumeMapScript(void);
|
||||
@ -66,4 +70,108 @@ void SetMovingNpcId(u16 npcId);
|
||||
extern u8 gMsgIsSignPost;
|
||||
extern u8 gMsgBoxIsCancelable;
|
||||
|
||||
/* Script effects analysis.
|
||||
*
|
||||
* 'RunScriptImmediatelyUntilEffect' executes a script until it reaches
|
||||
* the first command which calls 'Script_RequestEffects' with an
|
||||
* effect in 'effects' in which case it returns 'TRUE' and stores the
|
||||
* current state in 'ctx'; or until it reaches an 'end'/'return' in
|
||||
* which case it returns 'FALSE'.
|
||||
*
|
||||
* 'Script_HasNoEffect' wraps 'RunScriptImmediatelyUntilEffect' and
|
||||
* returns 'TRUE' if the script exits without an effect on the save or
|
||||
* the hardware, or 'FALSE' if it would have an effect (the effect is
|
||||
* not performed).
|
||||
*
|
||||
* Commands, natives, and specials which call 'Script_RequestEffects'
|
||||
* must be explicitly tagged with 'requests_effects=1', and must call
|
||||
* the function before any of those effects occur. An untagged function
|
||||
* could cause any effect, so execution is stopped to be safe. If the
|
||||
* code has no effects it must call 'Script_RequestEffects(SCREFF_V1)'
|
||||
* to note that explicitly.
|
||||
*
|
||||
* Regular variables are in the save (so should use 'SCREFF_SAVE'), but
|
||||
* special variables are not in the save, so 'Script_RequestWriteVar' is
|
||||
* provided to only request the 'SCREFF_SAVE' effect for a non-special
|
||||
* variable.
|
||||
*
|
||||
* The 'effects' parameter to 'RunScriptImmediatelyUntilEffect' and
|
||||
* 'Script_RequestEffects' must be the bitwise or of an effects version
|
||||
* (currently 'SCREFF_V1') and any number of effects. For example
|
||||
* 'Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE)'. */
|
||||
|
||||
enum // effects
|
||||
{
|
||||
SCREFF_SAVE = 1 << 0, // writes to the save.
|
||||
SCREFF_HARDWARE = 1 << 1, // writes to a hardware register.
|
||||
SCREFF_TRAINERBATTLE = 1 << 2, // 'trainerbattle' command.
|
||||
};
|
||||
|
||||
enum // effects versions
|
||||
{
|
||||
SCREFF_V1 = ~7,
|
||||
};
|
||||
|
||||
extern struct ScriptEffectContext *gScriptEffectContext;
|
||||
|
||||
bool32 RunScriptImmediatelyUntilEffect_Internal(u32 effects, const u8 *ptr, struct ScriptContext *ctx);
|
||||
bool32 Script_HasNoEffect(const u8 *ptr);
|
||||
void Script_GotoBreak_Internal(void);
|
||||
void Script_RequestEffects_Internal(u32 effects);
|
||||
void Script_RequestWriteVar_Internal(u32 varId);
|
||||
|
||||
static inline bool32 Script_IsAnalyzingEffects(void)
|
||||
{
|
||||
return gScriptEffectContext != NULL;
|
||||
}
|
||||
|
||||
#define RunScriptImmediatelyUntilEffect(effects, ptr, ctx) \
|
||||
({ \
|
||||
_Static_assert((effects) & 0x80000000, "RunScriptImmediatelyUntilEffect requires an effects version"); \
|
||||
RunScriptImmediatelyUntilEffect_Internal(effects, ptr, ctx); \
|
||||
})
|
||||
|
||||
/* Optimize 'Script_RequestEffects' to a no-op if it would have no
|
||||
* effect. 'Script_RequestEffects' must be called in all commands and
|
||||
* natives/specials with 'request_effects=TRUE' even if it would have
|
||||
* no effect to future-proof against new effects. */
|
||||
#define Script_RequestEffects(effects) \
|
||||
({ \
|
||||
_Static_assert((effects) & 0x80000000, "Script_RequestEffects requires an effects version"); \
|
||||
if ((effects) != SCREFF_V1) \
|
||||
if (Script_IsAnalyzingEffects()) \
|
||||
Script_RequestEffects_Internal(effects); \
|
||||
})
|
||||
|
||||
/* Optimize 'Script_RequestWriteVar' to a no-op if it would have no
|
||||
* effect. */
|
||||
#define Script_RequestWriteVar(varId) \
|
||||
({ \
|
||||
if (Script_IsAnalyzingEffects()) \
|
||||
Script_RequestWriteVar_Internal(varId); \
|
||||
})
|
||||
|
||||
static inline void Script_CheckEffectInstrumentedSpecial(u32 specialId)
|
||||
{
|
||||
typedef u16 (*SpecialFunc)(void);
|
||||
extern const SpecialFunc gSpecials[];
|
||||
// In ROM mirror 1.
|
||||
if (Script_IsAnalyzingEffects() && (((uintptr_t)gSpecials[specialId]) & 0xE000000) != 0xA000000)
|
||||
Script_GotoBreak_Internal();
|
||||
}
|
||||
|
||||
static inline void Script_CheckEffectInstrumentedGotoNative(bool8 (*func)(void))
|
||||
{
|
||||
// In ROM mirror 1.
|
||||
if (Script_IsAnalyzingEffects() && (((uintptr_t)func) & 0xE000000) != 0xA000000)
|
||||
Script_GotoBreak_Internal();
|
||||
}
|
||||
|
||||
static inline void Script_CheckEffectInstrumentedCallNative(void (*func)(struct ScriptContext *))
|
||||
{
|
||||
// In ROM mirror 1.
|
||||
if (Script_IsAnalyzingEffects() && (((uintptr_t)func) & 0xE000000) != 0xA000000)
|
||||
Script_GotoBreak_Internal();
|
||||
}
|
||||
|
||||
#endif // GUARD_SCRIPT_H
|
||||
|
||||
@ -42,6 +42,17 @@
|
||||
|
||||
#define RUN_OVERWORLD_SCRIPT(...) RunScriptImmediately(OVERWORLD_SCRIPT(__VA_ARGS__))
|
||||
|
||||
// Make important constants available.
|
||||
// TODO: Find a better approach to this.
|
||||
asm(".set FALSE, 0\n"
|
||||
".set TRUE, 1\n"
|
||||
".set PARTY_SIZE, " STR(PARTY_SIZE) "\n"
|
||||
".set VARS_START, " STR(VARS_START) "\n"
|
||||
".set VARS_END, " STR(VARS_END) "\n"
|
||||
".set SPECIAL_VARS_START, " STR(SPECIAL_VARS_START) "\n"
|
||||
".set SPECIAL_VARS_END, " STR(SPECIAL_VARS_END) "\n");
|
||||
asm(".include \"constants/gba_constants.inc\"\n");
|
||||
|
||||
// Make overworld script macros available.
|
||||
asm(".include \"asm/macros/event.inc\"\n");
|
||||
|
||||
|
||||
@ -5353,6 +5353,8 @@ static s32 AI_DynamicFunc(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
|
||||
void ScriptSetDynamicAiFunc(struct ScriptContext *ctx)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
AiScoreFunc func = (AiScoreFunc)ScriptReadWord(ctx);
|
||||
sDynamicAiFunc = func;
|
||||
}
|
||||
|
||||
@ -2060,6 +2060,8 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
|
||||
|
||||
void CreateTrainerPartyForPlayer(void)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
ZeroPlayerPartyMons();
|
||||
gPartnerTrainerId = gSpecialVar_0x8004;
|
||||
CreateNPCTrainerPartyFromTrainer(gPlayerParty, GetTrainerStructFromId(gSpecialVar_0x8004), TRUE, BATTLE_TYPE_TRAINER);
|
||||
@ -6135,6 +6137,8 @@ void ScriptSetTotemBoost(struct ScriptContext *ctx)
|
||||
u32 stat;
|
||||
u32 i;
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
for (i = 0; i < (NUM_BATTLE_STATS - 1); i++)
|
||||
{
|
||||
stat = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
@ -64,6 +64,9 @@ void Script_IncreaseDifficulty(void)
|
||||
if (currentDifficulty++ > DIFFICULTY_MAX)
|
||||
return;
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
Script_RequestWriteVar(B_VAR_DIFFICULTY);
|
||||
|
||||
SetCurrentDifficultyLevel(currentDifficulty);
|
||||
}
|
||||
|
||||
@ -79,11 +82,15 @@ void Script_DecreaseDifficulty(void)
|
||||
if (!currentDifficulty)
|
||||
return;
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
Script_RequestWriteVar(B_VAR_DIFFICULTY);
|
||||
|
||||
SetCurrentDifficultyLevel(--currentDifficulty);
|
||||
}
|
||||
|
||||
void Script_GetDifficulty(void)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
gSpecialVar_Result = GetCurrentDifficultyLevel();
|
||||
}
|
||||
|
||||
@ -91,5 +98,8 @@ void Script_SetDifficulty(struct ScriptContext *ctx)
|
||||
{
|
||||
enum DifficultyLevel desiredDifficulty = ScriptReadByte(ctx);
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
Script_RequestWriteVar(B_VAR_DIFFICULTY);
|
||||
|
||||
SetCurrentDifficultyLevel(desiredDifficulty);
|
||||
}
|
||||
|
||||
@ -6012,9 +6012,15 @@ u8 GetDirectionToFace(s16 x, s16 y, s16 targetX, s16 targetY)
|
||||
// Uses the above, but script accessible, and uses localIds
|
||||
void GetDirectionToFaceScript(struct ScriptContext *ctx)
|
||||
{
|
||||
u16 *var = GetVarPointer(ScriptReadHalfword(ctx));
|
||||
u32 varId = ScriptReadHalfword(ctx);
|
||||
u8 sourceId = GetObjectEventIdByLocalId(ScriptReadByte(ctx));
|
||||
u8 targetId = GetObjectEventIdByLocalId(ScriptReadByte(ctx));
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
Script_RequestWriteVar(varId);
|
||||
|
||||
u16 *var = GetVarPointer(varId);
|
||||
|
||||
if (var == NULL)
|
||||
return;
|
||||
if (sourceId >= OBJECT_EVENTS_COUNT || targetId >= OBJECT_EVENTS_COUNT)
|
||||
@ -6030,7 +6036,12 @@ void GetDirectionToFaceScript(struct ScriptContext *ctx)
|
||||
// Intended to be called before the field effect itself
|
||||
void IsFollowerFieldMoveUser(struct ScriptContext *ctx)
|
||||
{
|
||||
u16 *var = GetVarPointer(ScriptReadHalfword(ctx));
|
||||
u32 varId = ScriptReadHalfword(ctx);
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
Script_RequestWriteVar(varId);
|
||||
|
||||
u16 *var = GetVarPointer(varId);
|
||||
u16 userIndex = gFieldEffectArguments[0]; // field move user index
|
||||
struct Pokemon *follower = GetFirstLiveMon();
|
||||
struct ObjectEvent *obj = GetFollowerObject();
|
||||
@ -10995,6 +11006,13 @@ void GetDaycareGraphics(struct ScriptContext *ctx)
|
||||
u8 form;
|
||||
u8 shiny;
|
||||
s32 i;
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
Script_RequestWriteVar(varGfx[0]);
|
||||
Script_RequestWriteVar(varGfx[1]);
|
||||
Script_RequestWriteVar(varForm[0]);
|
||||
Script_RequestWriteVar(varForm[1]);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
GetMonInfo((struct Pokemon *) &gSaveBlock1Ptr->daycare.mons[i].mon, &specGfx, &form, &shiny);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "rtc.h"
|
||||
#include "fake_rtc.h"
|
||||
#include "event_data.h"
|
||||
#include "script.h"
|
||||
|
||||
struct Time *FakeRtc_GetCurrentTime(void)
|
||||
{
|
||||
@ -90,15 +91,21 @@ STATIC_ASSERT((OW_FLAG_PAUSE_TIME == 0 || OW_USE_FAKE_RTC == TRUE), FakeRtcMustB
|
||||
|
||||
void Script_PauseFakeRtc(void)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
|
||||
FlagSet(OW_FLAG_PAUSE_TIME);
|
||||
}
|
||||
|
||||
void Script_ResumeFakeRtc(void)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
|
||||
FlagClear(OW_FLAG_PAUSE_TIME);
|
||||
}
|
||||
|
||||
void Script_ToggleFakeRtc(void)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
|
||||
FlagToggle(OW_FLAG_PAUSE_TIME);
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ static u16 GetPlayerCurMetatileBehavior(int runningState)
|
||||
static bool8 TryStartInteractionScript(struct MapPosition *position, u16 metatileBehavior, u8 direction)
|
||||
{
|
||||
const u8 *script = GetInteractionScript(position, metatileBehavior, direction);
|
||||
if (script == NULL)
|
||||
if (script == NULL || Script_HasNoEffect(script))
|
||||
return FALSE;
|
||||
|
||||
// Don't play interaction sound for certain scripts.
|
||||
@ -590,7 +590,12 @@ static bool8 TryStartCoordEventScript(struct MapPosition *position)
|
||||
|
||||
if (script == NULL)
|
||||
return FALSE;
|
||||
ScriptContext_SetupScript(script);
|
||||
|
||||
struct ScriptContext ctx;
|
||||
if (!RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_HARDWARE, script, &ctx))
|
||||
return FALSE;
|
||||
|
||||
ScriptContext_ContinueScript(&ctx);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -1236,6 +1236,8 @@ u8 player_get_pos_including_state_based_drift(s16 *x, s16 *y)
|
||||
|
||||
u8 GetPlayerFacingDirection(void)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
return gObjectEvents[gPlayerAvatar.objectEventId].facingDirection;
|
||||
}
|
||||
|
||||
|
||||
@ -93,7 +93,9 @@ void AgbMain()
|
||||
{
|
||||
*(vu16 *)BG_PLTT = RGB_WHITE; // Set the backdrop to white on startup
|
||||
InitGpuRegManager();
|
||||
REG_WAITCNT = WAITCNT_PREFETCH_ENABLE | WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3;
|
||||
REG_WAITCNT = WAITCNT_PREFETCH_ENABLE
|
||||
| WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3
|
||||
| WAITCNT_WS1_S_1 | WAITCNT_WS1_N_3;
|
||||
InitKeys();
|
||||
InitIntrHandlers();
|
||||
m4aSoundInit();
|
||||
|
||||
@ -3386,6 +3386,9 @@ static u8 ReformatItemDescription(u16 item, u8 *dest)
|
||||
void ScriptShowItemDescription(struct ScriptContext *ctx)
|
||||
{
|
||||
u8 headerType = ScriptReadByte(ctx);
|
||||
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE);
|
||||
|
||||
struct WindowTemplate template;
|
||||
u16 item = gSpecialVar_0x8006;
|
||||
u8 textY;
|
||||
@ -3425,6 +3428,8 @@ void ScriptShowItemDescription(struct ScriptContext *ctx)
|
||||
|
||||
void ScriptHideItemDescription(struct ScriptContext *ctx)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE);
|
||||
|
||||
DestroyItemIconSprite();
|
||||
|
||||
if (!GetSetItemObtained(gSpecialVar_0x8006, FLAG_GET_ITEM_OBTAINED))
|
||||
|
||||
613
src/scrcmd.c
613
src/scrcmd.c
File diff suppressed because it is too large
Load Diff
150
src/script.c
150
src/script.c
@ -2,6 +2,8 @@
|
||||
#include "script.h"
|
||||
#include "event_data.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "random.h"
|
||||
#include "trainer_see.h"
|
||||
#include "util.h"
|
||||
#include "constants/event_objects.h"
|
||||
#include "constants/map_scripts.h"
|
||||
@ -50,6 +52,8 @@ void InitScriptContext(struct ScriptContext *ctx, void *cmdTable, void *cmdTable
|
||||
|
||||
for (i = 0; i < (int)ARRAY_COUNT(ctx->stack); i++)
|
||||
ctx->stack[i] = NULL;
|
||||
|
||||
ctx->breakOnTrainerBattle = FALSE;
|
||||
}
|
||||
|
||||
u8 SetupBytecodeScript(struct ScriptContext *ctx, const u8 *ptr)
|
||||
@ -258,6 +262,14 @@ void ScriptContext_SetupScript(const u8 *ptr)
|
||||
sGlobalScriptContextStatus = CONTEXT_RUNNING;
|
||||
}
|
||||
|
||||
// Moves a script from a local context to the global context and enables it.
|
||||
void ScriptContext_ContinueScript(struct ScriptContext *ctx)
|
||||
{
|
||||
sGlobalScriptContext = *ctx;
|
||||
LockPlayerFieldControls();
|
||||
sGlobalScriptContextStatus = CONTEXT_RUNNING;
|
||||
}
|
||||
|
||||
// Puts the script into waiting mode; usually called from a wait* script command.
|
||||
void ScriptContext_Stop(void)
|
||||
{
|
||||
@ -281,7 +293,7 @@ void RunScriptImmediately(const u8 *ptr)
|
||||
while (RunScriptCommand(&sImmediateScriptContext) == TRUE);
|
||||
}
|
||||
|
||||
u8 *MapHeaderGetScriptTable(u8 tag)
|
||||
const u8 *MapHeaderGetScriptTable(u8 tag)
|
||||
{
|
||||
const u8 *mapScripts = gMapHeader.mapScripts;
|
||||
|
||||
@ -303,14 +315,18 @@ u8 *MapHeaderGetScriptTable(u8 tag)
|
||||
|
||||
void MapHeaderRunScriptType(u8 tag)
|
||||
{
|
||||
u8 *ptr = MapHeaderGetScriptTable(tag);
|
||||
const u8 *ptr = MapHeaderGetScriptTable(tag);
|
||||
if (ptr)
|
||||
RunScriptImmediately(ptr);
|
||||
{
|
||||
struct ScriptContext ctx;
|
||||
if (RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_HARDWARE, ptr, &ctx))
|
||||
ScriptContext_ContinueScript(&ctx);
|
||||
}
|
||||
}
|
||||
|
||||
u8 *MapHeaderCheckScriptTable(u8 tag)
|
||||
const u8 *MapHeaderCheckScriptTable(u8 tag)
|
||||
{
|
||||
u8 *ptr = MapHeaderGetScriptTable(tag);
|
||||
const u8 *ptr = MapHeaderGetScriptTable(tag);
|
||||
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
@ -332,7 +348,12 @@ u8 *MapHeaderCheckScriptTable(u8 tag)
|
||||
|
||||
// Run map script if vars are equal
|
||||
if (VarGet(varIndex1) == VarGet(varIndex2))
|
||||
return T2_READ_PTR(ptr);
|
||||
{
|
||||
const u8 *mapScript = T2_READ_PTR(ptr);
|
||||
if (!Script_HasNoEffect(mapScript))
|
||||
return mapScript;
|
||||
}
|
||||
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
@ -364,7 +385,7 @@ void RunOnDiveWarpMapScript(void)
|
||||
|
||||
bool8 TryRunOnFrameMapScript(void)
|
||||
{
|
||||
u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_FRAME_TABLE);
|
||||
const u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_FRAME_TABLE);
|
||||
|
||||
if (!ptr)
|
||||
return FALSE;
|
||||
@ -375,7 +396,7 @@ bool8 TryRunOnFrameMapScript(void)
|
||||
|
||||
void TryRunOnWarpIntoMapScript(void)
|
||||
{
|
||||
u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_WARP_INTO_MAP_TABLE);
|
||||
const u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_WARP_INTO_MAP_TABLE);
|
||||
if (ptr)
|
||||
RunScriptImmediately(ptr);
|
||||
}
|
||||
@ -504,3 +525,116 @@ void InitRamScript_NoObjectEvent(u8 *script, u16 scriptSize)
|
||||
InitRamScript(script, scriptSize, MAP_GROUP(UNDEFINED), MAP_NUM(UNDEFINED), NO_OBJECT);
|
||||
#endif //FREE_MYSTERY_EVENT_BUFFERS
|
||||
}
|
||||
|
||||
bool8 LoadTrainerObjectScript(void)
|
||||
{
|
||||
sGlobalScriptContext.scriptPtr = gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct ScriptEffectContext {
|
||||
u32 breakOn;
|
||||
intptr_t breakTo[5];
|
||||
const u8 *nextCmd;
|
||||
};
|
||||
|
||||
struct ScriptEffectContext *gScriptEffectContext = NULL;
|
||||
|
||||
static bool32 Script_IsEffectInstrumentedCommand(ScrCmdFunc func)
|
||||
{
|
||||
// In ROM mirror 1.
|
||||
return (((uintptr_t)func) & 0xE000000) == 0xA000000;
|
||||
}
|
||||
|
||||
/* 'setjmp' and 'longjmp' cause link errors, so we use
|
||||
* '__builtin_setjmp' and '__builtin_longjmp' instead.
|
||||
* See https://gcc.gnu.org/onlinedocs/gcc/Nonlocal-Gotos.html */
|
||||
static bool32 RunScriptImmediatelyUntilEffect_InternalLoop(struct ScriptContext *ctx)
|
||||
{
|
||||
if (__builtin_setjmp(gScriptEffectContext->breakTo) == 0)
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
u32 cmdCode;
|
||||
ScrCmdFunc *func;
|
||||
|
||||
gScriptEffectContext->nextCmd = ctx->scriptPtr;
|
||||
|
||||
if (!ctx->scriptPtr)
|
||||
return FALSE;
|
||||
|
||||
cmdCode = *ctx->scriptPtr;
|
||||
ctx->scriptPtr++;
|
||||
func = &ctx->cmdTable[cmdCode];
|
||||
|
||||
// Invalid script command.
|
||||
if (func >= ctx->cmdTableEnd)
|
||||
return TRUE;
|
||||
|
||||
if (!Script_IsEffectInstrumentedCommand(*func))
|
||||
return TRUE;
|
||||
|
||||
// Command which waits for a frame.
|
||||
if ((*func)(ctx))
|
||||
{
|
||||
gScriptEffectContext->nextCmd = ctx->scriptPtr;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void Script_GotoBreak_Internal(void)
|
||||
{
|
||||
__builtin_longjmp(gScriptEffectContext->breakTo, 1);
|
||||
}
|
||||
|
||||
bool32 RunScriptImmediatelyUntilEffect_Internal(u32 effects, const u8 *ptr, struct ScriptContext *ctx)
|
||||
{
|
||||
bool32 result;
|
||||
struct ScriptEffectContext seCtx;
|
||||
seCtx.breakOn = effects & 0x7FFFFFFF;
|
||||
|
||||
if (ctx == NULL)
|
||||
ctx = &sImmediateScriptContext;
|
||||
|
||||
InitScriptContext(ctx, gScriptCmdTable, gScriptCmdTableEnd);
|
||||
if (effects & SCREFF_TRAINERBATTLE)
|
||||
ctx->breakOnTrainerBattle = TRUE;
|
||||
SetupBytecodeScript(ctx, ptr);
|
||||
|
||||
rng_value_t rngValue = gRngValue;
|
||||
gScriptEffectContext = &seCtx;
|
||||
result = RunScriptImmediatelyUntilEffect_InternalLoop(ctx);
|
||||
gScriptEffectContext = NULL;
|
||||
gRngValue = rngValue;
|
||||
|
||||
if (result)
|
||||
ctx->scriptPtr = seCtx.nextCmd;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool32 Script_HasNoEffect(const u8 *ptr)
|
||||
{
|
||||
return !RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE, ptr, NULL);
|
||||
}
|
||||
|
||||
void Script_RequestEffects_Internal(u32 effects)
|
||||
{
|
||||
if (gScriptEffectContext->breakOn & effects)
|
||||
__builtin_longjmp(gScriptEffectContext->breakTo, 1);
|
||||
}
|
||||
|
||||
void Script_RequestWriteVar_Internal(u32 varId)
|
||||
{
|
||||
if (varId == 0)
|
||||
return;
|
||||
if (SPECIAL_VARS_START <= varId && varId <= SPECIAL_VARS_END)
|
||||
return;
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
}
|
||||
|
||||
@ -240,6 +240,9 @@ void CanHyperTrain(struct ScriptContext *ctx)
|
||||
{
|
||||
u32 stat = ScriptReadByte(ctx);
|
||||
u32 partyIndex = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
if (stat < NUM_STATS
|
||||
&& partyIndex < PARTY_SIZE
|
||||
&& !GetMonData(&gPlayerParty[partyIndex], MON_DATA_HYPER_TRAINED_HP + stat)
|
||||
@ -257,6 +260,9 @@ void HyperTrain(struct ScriptContext *ctx)
|
||||
{
|
||||
u32 stat = ScriptReadByte(ctx);
|
||||
u32 partyIndex = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
|
||||
if (stat < NUM_STATS && partyIndex < PARTY_SIZE)
|
||||
{
|
||||
bool32 data = TRUE;
|
||||
@ -268,6 +274,9 @@ void HyperTrain(struct ScriptContext *ctx)
|
||||
void HasGigantamaxFactor(struct ScriptContext *ctx)
|
||||
{
|
||||
u32 partyIndex = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
if (partyIndex < PARTY_SIZE)
|
||||
gSpecialVar_Result = GetMonData(&gPlayerParty[partyIndex], MON_DATA_GIGANTAMAX_FACTOR);
|
||||
else
|
||||
@ -278,6 +287,8 @@ void ToggleGigantamaxFactor(struct ScriptContext *ctx)
|
||||
{
|
||||
u32 partyIndex = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
|
||||
gSpecialVar_Result = FALSE;
|
||||
|
||||
if (partyIndex < PARTY_SIZE)
|
||||
@ -298,6 +309,8 @@ void CheckTeraType(struct ScriptContext *ctx)
|
||||
{
|
||||
u32 partyIndex = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
gSpecialVar_Result = TYPE_NONE;
|
||||
|
||||
if (partyIndex < PARTY_SIZE)
|
||||
@ -309,6 +322,8 @@ void SetTeraType(struct ScriptContext *ctx)
|
||||
u32 type = ScriptReadByte(ctx);
|
||||
u32 partyIndex = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
|
||||
if (type < NUMBER_OF_MON_TYPES && partyIndex < PARTY_SIZE)
|
||||
SetMonData(&gPlayerParty[partyIndex], MON_DATA_TERA_TYPE, &type);
|
||||
}
|
||||
@ -542,6 +557,11 @@ void ScrCmd_createmon(struct ScriptContext *ctx)
|
||||
u8 ivs[NUM_STATS] = {hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv};
|
||||
u16 moves[MAX_MON_MOVES] = {move1, move2, move3, move4};
|
||||
|
||||
if (side == 0)
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
else
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
gSpecialVar_Result = ScriptGiveMonParameterized(side, slot, species, level, item, ball, nature, abilityNum, gender, evs, ivs, moves, isShiny, ggMaxFactor, teraType);
|
||||
}
|
||||
|
||||
@ -580,6 +600,8 @@ void Script_SetStatus1(struct ScriptContext *ctx)
|
||||
u32 status1 = VarGet(ScriptReadHalfword(ctx));
|
||||
u32 slot = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE);
|
||||
|
||||
if (slot >= PARTY_SIZE)
|
||||
{
|
||||
u16 species;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "battle_setup.h"
|
||||
#include "event_data.h"
|
||||
#include "event_object_movement.h"
|
||||
#include "event_scripts.h"
|
||||
#include "field_effect.h"
|
||||
#include "field_player_avatar.h"
|
||||
#include "pokemon.h"
|
||||
@ -375,6 +376,16 @@ bool8 CheckForTrainersWantingBattle(void)
|
||||
continue;
|
||||
|
||||
numTrainers = CheckTrainer(i);
|
||||
if (numTrainers == 0xFF) // non-trainerbatle script
|
||||
{
|
||||
u32 objectEventId = gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId;
|
||||
gSelectedObjectEvent = objectEventId;
|
||||
gSpecialVar_LastTalked = gObjectEvents[objectEventId].localId;
|
||||
ScriptContext_SetupScript(EventScript_ObjectApproachPlayer);
|
||||
LockPlayerFieldControls();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (numTrainers == 2)
|
||||
break;
|
||||
|
||||
@ -417,14 +428,33 @@ bool8 CheckForTrainersWantingBattle(void)
|
||||
|
||||
static u8 CheckTrainer(u8 objectEventId)
|
||||
{
|
||||
const u8 *scriptPtr;
|
||||
const u8 *scriptPtr, *trainerBattlePtr;
|
||||
u8 numTrainers = 1;
|
||||
u8 approachDistance;
|
||||
|
||||
u8 approachDistance = GetTrainerApproachDistance(&gObjectEvents[objectEventId]);
|
||||
if (approachDistance == 0)
|
||||
return 0;
|
||||
|
||||
if (InTrainerHill() == TRUE)
|
||||
scriptPtr = GetTrainerHillTrainerScript();
|
||||
{
|
||||
trainerBattlePtr = scriptPtr = GetTrainerHillTrainerScript();
|
||||
}
|
||||
else
|
||||
scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId);
|
||||
{
|
||||
trainerBattlePtr = scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId);
|
||||
struct ScriptContext ctx;
|
||||
if (RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE | SCREFF_TRAINERBATTLE, scriptPtr, &ctx))
|
||||
{
|
||||
if (*ctx.scriptPtr == 0x5c) // trainerbattle
|
||||
trainerBattlePtr = ctx.scriptPtr;
|
||||
else
|
||||
trainerBattlePtr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0; // no effect
|
||||
}
|
||||
}
|
||||
|
||||
if (InBattlePyramid())
|
||||
{
|
||||
@ -436,25 +466,28 @@ static u8 CheckTrainer(u8 objectEventId)
|
||||
if (GetHillTrainerFlag(objectEventId))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
else if (trainerBattlePtr)
|
||||
{
|
||||
if (GetTrainerFlagFromScriptPointer(scriptPtr))
|
||||
if (GetTrainerFlagFromScriptPointer(trainerBattlePtr))
|
||||
return 0;
|
||||
}
|
||||
|
||||
approachDistance = GetTrainerApproachDistance(&gObjectEvents[objectEventId]);
|
||||
|
||||
if (approachDistance != 0)
|
||||
else
|
||||
{
|
||||
if (scriptPtr[1] == TRAINER_BATTLE_DOUBLE
|
||||
|| scriptPtr[1] == TRAINER_BATTLE_REMATCH_DOUBLE
|
||||
|| scriptPtr[1] == TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE)
|
||||
numTrainers = 0xFF;
|
||||
}
|
||||
|
||||
if (trainerBattlePtr)
|
||||
{
|
||||
if (trainerBattlePtr[1] == TRAINER_BATTLE_DOUBLE
|
||||
|| trainerBattlePtr[1] == TRAINER_BATTLE_REMATCH_DOUBLE
|
||||
|| trainerBattlePtr[1] == TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE)
|
||||
{
|
||||
if (GetMonsStateToDoubles_2() != PLAYER_HAS_TWO_USABLE_MONS)
|
||||
return 0;
|
||||
|
||||
numTrainers = 2;
|
||||
}
|
||||
}
|
||||
|
||||
gApproachingTrainers[gNoOfApproachingTrainers].objectEventId = objectEventId;
|
||||
gApproachingTrainers[gNoOfApproachingTrainers].trainerScriptPtr = scriptPtr;
|
||||
@ -463,9 +496,6 @@ static u8 CheckTrainer(u8 objectEventId)
|
||||
gNoOfApproachingTrainers++;
|
||||
|
||||
return numTrainers;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 GetTrainerApproachDistance(struct ObjectEvent *trainerObj)
|
||||
|
||||
116
test/script.c
Normal file
116
test/script.c
Normal file
@ -0,0 +1,116 @@
|
||||
#include "global.h"
|
||||
#include "test/test.h"
|
||||
#include "test/overworld_script.h"
|
||||
#include "script.h"
|
||||
#include "constants/decorations.h"
|
||||
#include "constants/moves.h"
|
||||
|
||||
TEST("Script_HasNoEffect control flow")
|
||||
{
|
||||
const u8 *script = OVERWORLD_SCRIPT(
|
||||
nop;
|
||||
nop1;
|
||||
checkflag FLAG_TEMP_1;
|
||||
checktrainerflag 0;
|
||||
compare VAR_TEMP_0, 0;
|
||||
goto_if_eq GoneTo;
|
||||
GoneTo:
|
||||
call Sub;
|
||||
call_if_eq Sub;
|
||||
end;
|
||||
|
||||
Sub:
|
||||
goto SubRet;
|
||||
SubRet:
|
||||
return;
|
||||
);
|
||||
EXPECT(Script_HasNoEffect(script));
|
||||
}
|
||||
|
||||
TEST("Script_HasNoEffect variables")
|
||||
{
|
||||
// Writes to special variables are not considered player-visible
|
||||
// because their values are indeterminate if the player has control.
|
||||
const u8 *writeSpecial = OVERWORLD_SCRIPT(
|
||||
setvar VAR_0x8000, 1;
|
||||
addvar VAR_0x8000, 1;
|
||||
subvar VAR_0x8000, VAR_TEMP_0;
|
||||
copyvar VAR_0x8000, VAR_TEMP_0;
|
||||
setorcopyvar VAR_0x8000, VAR_TEMP_0;
|
||||
specialvar VAR_RESULT, GetPlayerFacingDirection;
|
||||
getplayerxy VAR_0x8000, VAR_0x8001;
|
||||
getpartysize;
|
||||
checkitemspace ITEM_POTION, 1;
|
||||
checkitem ITEM_POTION, 1;
|
||||
checkitemtype ITEM_POTION;
|
||||
checkpcitem ITEM_POTION, 1;
|
||||
checkdecorspace DECOR_SNORLAX_DOLL;
|
||||
checkdecor DECOR_SNORLAX_DOLL;
|
||||
checkpartymove MOVE_CELEBRATE;
|
||||
random 2;
|
||||
checkmoney 5000;
|
||||
getpokenewsactive POKENEWS_LILYCOVE;
|
||||
checkplayergender;
|
||||
checkcoins VAR_RESULT;
|
||||
checkmodernfatefulencounter 0;
|
||||
end;
|
||||
);
|
||||
|
||||
// Writes to other variables are considered player-visible because
|
||||
// their values are preserved even while the player has control.
|
||||
const u8 *setVariable = OVERWORLD_SCRIPT(
|
||||
setvar VAR_TEMP_0, 1;
|
||||
end;
|
||||
);
|
||||
|
||||
const u8 *addVariable = OVERWORLD_SCRIPT(
|
||||
addvar VAR_TEMP_0, 1;
|
||||
end;
|
||||
);
|
||||
|
||||
const u8 *subVariable = OVERWORLD_SCRIPT(
|
||||
subvar VAR_TEMP_0, 1;
|
||||
end;
|
||||
);
|
||||
|
||||
const u8 *copyVariable = OVERWORLD_SCRIPT(
|
||||
copyvar VAR_TEMP_0, VAR_RESULT;
|
||||
end;
|
||||
);
|
||||
|
||||
const u8 *setorcopyVariable = OVERWORLD_SCRIPT(
|
||||
setorcopyvar VAR_TEMP_0, VAR_RESULT;
|
||||
end;
|
||||
);
|
||||
|
||||
const u8 *specialvarVariable = OVERWORLD_SCRIPT(
|
||||
specialvar VAR_TEMP_0, GetPlayerFacingDirection;
|
||||
end;
|
||||
);
|
||||
|
||||
const u8 *getPlayerXYVariable1 = OVERWORLD_SCRIPT(
|
||||
getplayerxy VAR_TEMP_0, VAR_RESULT;
|
||||
end;
|
||||
);
|
||||
|
||||
const u8 *getPlayerXYVariable2 = OVERWORLD_SCRIPT(
|
||||
getplayerxy VAR_RESULT, VAR_TEMP_0;
|
||||
end;
|
||||
);
|
||||
|
||||
const u8 *checkCoinsVariable = OVERWORLD_SCRIPT(
|
||||
checkcoins VAR_TEMP_0;
|
||||
end;
|
||||
);
|
||||
|
||||
EXPECT(Script_HasNoEffect(writeSpecial));
|
||||
EXPECT(!Script_HasNoEffect(setVariable));
|
||||
EXPECT(!Script_HasNoEffect(addVariable));
|
||||
EXPECT(!Script_HasNoEffect(subVariable));
|
||||
EXPECT(!Script_HasNoEffect(copyVariable));
|
||||
EXPECT(!Script_HasNoEffect(setorcopyVariable));
|
||||
EXPECT(!Script_HasNoEffect(specialvarVariable));
|
||||
EXPECT(!Script_HasNoEffect(getPlayerXYVariable1));
|
||||
EXPECT(!Script_HasNoEffect(getPlayerXYVariable2));
|
||||
EXPECT(!Script_HasNoEffect(checkCoinsVariable));
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user