Skip to content

Commit

Permalink
Arbitrary trainer scripts + on frame/trigger softlock prevention
Browse files Browse the repository at this point in the history
Script_HasNoEffect returns TRUE if the script definitely has no player-
visible effect, or FALSE if it may/does have a player-visible effect.

Opcodes have been manually tagged with whether they abort if they would
have a player-visible effect, and the natives and specials have been
manually tagged with whether they definitely have no player-visible
effect or not.

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. 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.
3. 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.
  • Loading branch information
mrgriffin committed Jul 25, 2024
1 parent ae48293 commit 2c04041
Show file tree
Hide file tree
Showing 12 changed files with 759 additions and 279 deletions.
89 changes: 81 additions & 8 deletions asm/macros/event.inc
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,13 @@
.endm

@ Calls the native C function stored at func.
.macro callnative func:req
.macro callnative func:req, player_visible=TRUE
.byte 0x23
.if \player_visible
.4byte \func
.else
.4byte \func + 0x02000000
.endif
.endm

@ Replaces the script with the function stored at func. Execution returns to the bytecode script when func returns TRUE.
Expand Down Expand Up @@ -999,7 +1003,7 @@
.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
.byte 0
.byte 6 @ PARTY_SIZE - assign to first empty slot
.byte PARTY_SIZE
.set givemon_flags, 0
.2byte \species
.2byte \level
Expand Down Expand Up @@ -2183,7 +2187,7 @@
@ 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, player_visible=FALSE
.byte \stat
.2byte \slot
.endm
Expand All @@ -2198,7 +2202,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, player_visible=FALSE
.2byte \slot
.endm

Expand Down Expand Up @@ -2251,7 +2255,7 @@

@ Sets VAR_RESULT to the Pokémon in \slot's Tera Type
.macro checkteratype slot:req
callnative CheckTeraType
callnative CheckTeraType, player_visible=FALSE
.2byte \slot
.endm

Expand All @@ -2278,7 +2282,7 @@

@ Buffers the nickname of the first alive party member.
.macro bufferlivemonnickname out:req
callnative BufferFirstLiveMonNickname
callnative BufferFirstLiveMonNickname, player_visible=FALSE
.byte \out
.endm

Expand All @@ -2289,13 +2293,21 @@

@ Checks if Field move is being used by the current follower.
.macro isfollowerfieldmoveuser var:req
callnative IsFollowerFieldMoveUser
.if (\var >= SPECIAL_VARS_START && \var <= SPECIAL_VARS_END)
callnative IsFollowerFieldMoveUser, player_visible=FALSE
.else
callnative IsFollowerFieldMoveUser, player_visible=TRUE
.endif
.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
.if (\var >= SPECIAL_VARS_START && \var <= SPECIAL_VARS_END)
callnative GetDirectionToFaceScript, player_visible=FALSE
.else
callnative GetDirectionToFaceScript, player_visible=TRUE
.endif
.2byte \var
.byte \sourceId
.byte \targetId
Expand All @@ -2321,3 +2333,64 @@
.macro togglefakertc
callnative Script_ToggleFakeRtc
.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, player_visible=FALSE
.byte \condition
.endm

.macro cant_see
cant_see_if_unset 0
.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
148 changes: 76 additions & 72 deletions data/script_cmd_table.inc
Original file line number Diff line number Diff line change
@@ -1,52 +1,54 @@
#define MUT_INSTRUMENTED(symbol) ((symbol) + 0x02000000)

.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 MUT_INSTRUMENTED(ScrCmd_nop) @ 0x00
.4byte MUT_INSTRUMENTED(ScrCmd_nop1) @ 0x01
.4byte MUT_INSTRUMENTED(ScrCmd_end) @ 0x02
.4byte MUT_INSTRUMENTED(ScrCmd_return) @ 0x03
.4byte MUT_INSTRUMENTED(ScrCmd_call) @ 0x04
.4byte MUT_INSTRUMENTED(ScrCmd_goto) @ 0x05
.4byte MUT_INSTRUMENTED(ScrCmd_goto_if) @ 0x06
.4byte MUT_INSTRUMENTED(ScrCmd_call_if) @ 0x07
.4byte MUT_INSTRUMENTED(ScrCmd_gotostd) @ 0x08
.4byte MUT_INSTRUMENTED(ScrCmd_callstd) @ 0x09
.4byte MUT_INSTRUMENTED(ScrCmd_gotostd_if) @ 0x0a
.4byte MUT_INSTRUMENTED(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 MUT_INSTRUMENTED(ScrCmd_loadword) @ 0x0f
.4byte MUT_INSTRUMENTED(ScrCmd_loadbyte) @ 0x10
.4byte ScrCmd_setptr @ 0x11
.4byte ScrCmd_loadbytefromptr @ 0x12
.4byte MUT_INSTRUMENTED(ScrCmd_loadbytefromptr) @ 0x12
.4byte ScrCmd_setptrbyte @ 0x13
.4byte ScrCmd_copylocal @ 0x14
.4byte MUT_INSTRUMENTED(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 MUT_INSTRUMENTED(ScrCmd_setvar) @ 0x16
.4byte MUT_INSTRUMENTED(ScrCmd_addvar) @ 0x17
.4byte MUT_INSTRUMENTED(ScrCmd_subvar) @ 0x18
.4byte MUT_INSTRUMENTED(ScrCmd_copyvar) @ 0x19
.4byte MUT_INSTRUMENTED(ScrCmd_setorcopyvar) @ 0x1a
.4byte MUT_INSTRUMENTED(ScrCmd_compare_local_to_local) @ 0x1b
.4byte MUT_INSTRUMENTED(ScrCmd_compare_local_to_value) @ 0x1c
.4byte MUT_INSTRUMENTED(ScrCmd_compare_local_to_ptr) @ 0x1d
.4byte MUT_INSTRUMENTED(ScrCmd_compare_ptr_to_local) @ 0x1e
.4byte MUT_INSTRUMENTED(ScrCmd_compare_ptr_to_value) @ 0x1f
.4byte MUT_INSTRUMENTED(ScrCmd_compare_ptr_to_ptr) @ 0x20
.4byte MUT_INSTRUMENTED(ScrCmd_compare_var_to_value) @ 0x21
.4byte MUT_INSTRUMENTED(ScrCmd_compare_var_to_var) @ 0x22
.4byte MUT_INSTRUMENTED(ScrCmd_callnative) @ 0x23
.4byte MUT_INSTRUMENTED(ScrCmd_gotonative) @ 0x24
.4byte MUT_INSTRUMENTED(ScrCmd_special) @ 0x25
.4byte MUT_INSTRUMENTED(ScrCmd_specialvar) @ 0x26
.4byte ScrCmd_waitstate @ 0x27
.4byte ScrCmd_delay @ 0x28
.4byte ScrCmd_setflag @ 0x29
.4byte ScrCmd_clearflag @ 0x2a
.4byte ScrCmd_checkflag @ 0x2b
.4byte MUT_INSTRUMENTED(ScrCmd_setflag) @ 0x29
.4byte MUT_INSTRUMENTED(ScrCmd_clearflag) @ 0x2a
.4byte MUT_INSTRUMENTED(ScrCmd_checkflag) @ 0x2b
.4byte ScrCmd_initclock @ 0x2c
.4byte ScrCmd_dotimebasedevents @ 0x2d
.4byte ScrCmd_gettime @ 0x2e
.4byte MUT_INSTRUMENTED(ScrCmd_gettime) @ 0x2e
.4byte ScrCmd_playse @ 0x2f
.4byte ScrCmd_waitse @ 0x30
.4byte ScrCmd_playfanfare @ 0x31
Expand All @@ -66,19 +68,19 @@ gScriptCmdTable::
.4byte ScrCmd_setdynamicwarp @ 0x3f
.4byte ScrCmd_setdivewarp @ 0x40
.4byte ScrCmd_setholewarp @ 0x41
.4byte ScrCmd_getplayerxy @ 0x42
.4byte ScrCmd_getpartysize @ 0x43
.4byte MUT_INSTRUMENTED(ScrCmd_getplayerxy) @ 0x42
.4byte MUT_INSTRUMENTED(ScrCmd_getpartysize) @ 0x43
.4byte ScrCmd_additem @ 0x44
.4byte ScrCmd_removeitem @ 0x45
.4byte ScrCmd_checkitemspace @ 0x46
.4byte ScrCmd_checkitem @ 0x47
.4byte ScrCmd_checkitemtype @ 0x48
.4byte MUT_INSTRUMENTED(ScrCmd_checkitemspace) @ 0x46
.4byte MUT_INSTRUMENTED(ScrCmd_checkitem) @ 0x47
.4byte MUT_INSTRUMENTED(ScrCmd_checkitemtype) @ 0x48
.4byte ScrCmd_addpcitem @ 0x49
.4byte ScrCmd_checkpcitem @ 0x4a
.4byte MUT_INSTRUMENTED(ScrCmd_checkpcitem) @ 0x4a
.4byte ScrCmd_adddecoration @ 0x4b
.4byte ScrCmd_removedecoration @ 0x4c
.4byte ScrCmd_checkdecor @ 0x4d
.4byte ScrCmd_checkdecorspace @ 0x4e
.4byte MUT_INSTRUMENTED(ScrCmd_checkdecor) @ 0x4d
.4byte MUT_INSTRUMENTED(ScrCmd_checkdecorspace) @ 0x4e
.4byte ScrCmd_applymovement @ 0x4f
.4byte ScrCmd_applymovementat @ 0x50
.4byte ScrCmd_waitmovement @ 0x51
Expand All @@ -96,7 +98,7 @@ gScriptCmdTable::
.4byte ScrCmd_dotrainerbattle @ 0x5d
.4byte ScrCmd_gotopostbattlescript @ 0x5e
.4byte ScrCmd_gotobeatenscript @ 0x5f
.4byte ScrCmd_checktrainerflag @ 0x60
.4byte MUT_INSTRUMENTED(ScrCmd_checktrainerflag) @ 0x60
.4byte ScrCmd_settrainerflag @ 0x61
.4byte ScrCmd_cleartrainerflag @ 0x62
.4byte ScrCmd_setobjectxyperm @ 0x63
Expand Down Expand Up @@ -124,16 +126,16 @@ gScriptCmdTable::
.4byte ScrCmd_nop1 @ 0x79
.4byte ScrCmd_giveegg @ 0x7a
.4byte ScrCmd_setmonmove @ 0x7b
.4byte ScrCmd_checkpartymove @ 0x7c
.4byte ScrCmd_bufferspeciesname @ 0x7d
.4byte MUT_INSTRUMENTED(ScrCmd_checkpartymove) @ 0x7c
.4byte MUT_INSTRUMENTED(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 MUT_INSTRUMENTED(ScrCmd_bufferpartymonnick) @ 0x7f
.4byte MUT_INSTRUMENTED(ScrCmd_bufferitemname) @ 0x80
.4byte MUT_INSTRUMENTED(ScrCmd_bufferdecorationname) @ 0x81
.4byte MUT_INSTRUMENTED(ScrCmd_buffermovename) @ 0x82
.4byte MUT_INSTRUMENTED(ScrCmd_buffernumberstring) @ 0x83
.4byte MUT_INSTRUMENTED(ScrCmd_bufferstdstring) @ 0x84
.4byte MUT_INSTRUMENTED(ScrCmd_bufferstring) @ 0x85
.4byte ScrCmd_pokemart @ 0x86
.4byte ScrCmd_pokemartdecoration @ 0x87
.4byte ScrCmd_pokemartdecoration2 @ 0x88
Expand All @@ -143,14 +145,14 @@ gScriptCmdTable::
.4byte ScrCmd_startcontest @ 0x8c
.4byte ScrCmd_showcontestresults @ 0x8d
.4byte ScrCmd_contestlinktransfer @ 0x8e
.4byte ScrCmd_random @ 0x8f
.4byte MUT_INSTRUMENTED(ScrCmd_random) @ 0x8f
.4byte ScrCmd_addmoney @ 0x90
.4byte ScrCmd_removemoney @ 0x91
.4byte ScrCmd_checkmoney @ 0x92
.4byte MUT_INSTRUMENTED(ScrCmd_checkmoney) @ 0x92
.4byte ScrCmd_showmoneybox @ 0x93
.4byte ScrCmd_hidemoneybox @ 0x94
.4byte ScrCmd_updatemoneybox @ 0x95
.4byte ScrCmd_getpokenewsactive @ 0x96
.4byte MUT_INSTRUMENTED(ScrCmd_getpokenewsactive) @ 0x96
.4byte ScrCmd_fadescreen @ 0x97
.4byte ScrCmd_fadescreenspeed @ 0x98
.4byte ScrCmd_setflashlevel @ 0x99
Expand All @@ -160,7 +162,7 @@ gScriptCmdTable::
.4byte ScrCmd_setfieldeffectargument @ 0x9d
.4byte ScrCmd_waitfieldeffect @ 0x9e
.4byte ScrCmd_setrespawn @ 0x9f
.4byte ScrCmd_checkplayergender @ 0xa0
.4byte MUT_INSTRUMENTED(ScrCmd_checkplayergender) @ 0xa0
.4byte ScrCmd_playmoncry @ 0xa1
.4byte ScrCmd_setmetatile @ 0xa2
.4byte ScrCmd_resetweather @ 0xa3
Expand All @@ -179,34 +181,34 @@ gScriptCmdTable::
.4byte ScrCmd_setdoorclosed @ 0xb0
.4byte ScrCmd_addelevmenuitem @ 0xb1
.4byte ScrCmd_showelevmenu @ 0xb2
.4byte ScrCmd_checkcoins @ 0xb3
.4byte MUT_INSTRUMENTED(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 MUT_INSTRUMENTED(ScrCmd_vgoto) @ 0xb9
.4byte MUT_INSTRUMENTED(ScrCmd_vcall) @ 0xba
.4byte MUT_INSTRUMENTED(ScrCmd_vgoto_if) @ 0xbb
.4byte MUT_INSTRUMENTED(ScrCmd_vcall_if) @ 0xbc
.4byte ScrCmd_vmessage @ 0xbd
.4byte ScrCmd_vbuffermessage @ 0xbe
.4byte ScrCmd_vbufferstring @ 0xbf
.4byte MUT_INSTRUMENTED(ScrCmd_vbuffermessage) @ 0xbe
.4byte MUT_INSTRUMENTED(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 MUT_INSTRUMENTED(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 MUT_INSTRUMENTED(ScrCmd_checkmodernfatefulencounter) @ 0xce
.4byte ScrCmd_trywondercardscript @ 0xcf
.4byte ScrCmd_nop1 @ 0xd0
.4byte ScrCmd_warpspinenter @ 0xd1
Expand All @@ -221,14 +223,16 @@ gScriptCmdTable::
.4byte ScrCmd_closebraillemessage @ 0xda
.4byte ScrCmd_messageinstant @ 0xdb
.4byte ScrCmd_fadescreenswapbuffers @ 0xdc
.4byte ScrCmd_buffertrainerclassname @ 0xdd
.4byte ScrCmd_buffertrainername @ 0xde
.4byte MUT_INSTRUMENTED(ScrCmd_buffertrainerclassname) @ 0xdd
.4byte MUT_INSTRUMENTED(ScrCmd_buffertrainername) @ 0xde
.4byte ScrCmd_pokenavcall @ 0xdf
.4byte ScrCmd_warpwhitefade @ 0xe0
.4byte ScrCmd_buffercontestname @ 0xe1
.4byte ScrCmd_bufferitemnameplural @ 0xe2
.4byte MUT_INSTRUMENTED(ScrCmd_buffercontestname) @ 0xe1
.4byte MUT_INSTRUMENTED(ScrCmd_bufferitemnameplural) @ 0xe2
.4byte ScrCmd_dynmultichoice @ 0xe3
.4byte ScrCmd_dynmultipush @ 0xe4

gScriptCmdTableEnd::
.4byte ScrCmd_nop

#undef MUT_INSTRUMENTED
Loading

0 comments on commit 2c04041

Please sign in to comment.