Something went wrong. Try again.
Base for making Paper Mario (N64) mods, built on the decompilation docs.starhaven.dev/papermario-dx
paper-mario n64
Something went wrong. Try again.
59 kB · 1156 lines
C
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157#ifndef _SCRIPT_API_MACROS_H_#define _SCRIPT_API_MACROS_H_
#include "evt.h"#include <stdarg.h>
#ifdef __cplusplus#include <type_traits>
template <typename Actual, typename Expected> struct EvtFuncSignatureMatches { static_assert(std::is_same_v<Actual, Expected>, "EVT_BAD_SIGNATURE");};#endif
#ifdef _LANGUAGE_C_PLUS_PLUSextern "C" {#endif
/****** EXPRESSIONS ***************************************************************************************************/
/// Expressions in EVT instructions should be one of the following types:/// - Integer literals (as-is, s32)/// - Float literals (Float) - cast to int where a float is not accepted/// - Pointers, string literals (Ref)/// - Variables (LW, GW, LSW, GSW, UW)/// - Flags (LF, GF, LSWF, GSWF, UF)/// This is implemented in `evt_get_variable` and `evt_get_float_variable`.
/// Decimal constant./// Despite the name, "floats" are actually stored as fixed-point values.
#define EVT_LOCAL_VAR_CUTOFF -20000000#define EVT_LOCAL_VAR_OFFSET 30000000#define EVT_ARG_VAR_CUTOFF -34000000#define EVT_ARG_VAR_OFFSET 35000000#define EVT_MAP_VAR_CUTOFF -40000000#define EVT_MAP_VAR_OFFSET 50000000#define EVT_LOCAL_FLAG_CUTOFF -60000000#define EVT_LOCAL_FLAG_OFFSET 70000000#define EVT_MAP_FLAG_CUTOFF -80000000#define EVT_MAP_FLAG_OFFSET 90000000#define EVT_AREA_FLAG_CUTOFF -100000000#define EVT_AREA_FLAG_OFFSET 110000000#define EVT_GAME_FLAG_CUTOFF -120000000#define EVT_GAME_FLAG_OFFSET 130000000#define EVT_AREA_BYTE_CUTOFF -140000000#define EVT_AREA_BYTE_OFFSET 150000000#define EVT_GAME_BYTE_CUTOFF -160000000#define EVT_GAME_BYTE_OFFSET 170000000#define EVT_ARRAY_VAR_CUTOFF -180000000#define EVT_ARRAY_VAR_OFFSET 190000000#define EVT_ARRAY_FLAG_CUTOFF -200000000#define EVT_ARRAY_FLAG_OFFSET 210000000#define EVT_FIXED_CUTOFF -220000000#define EVT_FIXED_OFFSET 230000000#define EVT_FIXED_END -240000000#define EVT_IGNORE_ARG -250000000 // used by a couple functions to selectively ignore args#define EVT_LIMIT -270000000 // TODO better name#define EVT_ARG_INT_MARKER (EVT_LIMIT - 1)#define EVT_ARG_FLOAT_MARKER (EVT_LIMIT - 2)
// This fixes an issue with fixed point numbers not being correct. Potentially a truncation vs round difference.#define FLOAT_ROUND(x) ((x) >=0 ? (f64)((x) + 0.9) : (f64)(x))#define Float(DOUBLE) ((Bytecode)FLOAT_ROUND(((DOUBLE) * 1024.0f)) - EVT_FIXED_OFFSET)
/// Programmatically converts Float --> f32#define EVT_FIXED_TO_FLOAT(x) ({f32 var = (x) + EVT_FIXED_OFFSET; var /= 1024.0f; var;})
/// Programmatically converts f32 --> Float#define FLOAT_TO_FIXED(x) ((s32)((x) * 1024.0f) - EVT_FIXED_OFFSET)
/// Address/pointer constant.#define Ref(sym) ((Bytecode) &(sym))
/// Local Word. A variable local to the current script./// These are copied to scripts created by Exec, ExecWait, Thread, and ChildThread./// Additionally, ExecWait copies LWs back from the child when it completes.////// Range: `0 <= v < 0x10`#define LocalVar(INDEX) ((INDEX) - EVT_LOCAL_VAR_OFFSET)
/// Global Word. A variable global to all scripts./// Cleared upon entering a new map.////// Range: `0 <= v < 0x10`#define MapVar(INDEX) ((INDEX) - EVT_MAP_VAR_OFFSET)
/// Local Flag. A boolean variable local to the current script./// These are copied to scripts created by Exec, ExecWait, Thread, and ChildThread./// Additionally, ExecWait copies LFs back from the child when it completes.////// Range: `0 <= v < 0x60`#define LocalFlag(INDEX) ((INDEX) - EVT_LOCAL_FLAG_OFFSET)
/// Global Flag. A boolean variable global to all scripts./// Cleared upon entering a new map.////// Range: `0 <= v < 0x60`#define MapFlag(INDEX) ((INDEX) - EVT_MAP_FLAG_OFFSET)
/// Local Save World Flag. A boolean variable local to the current world area, saved in the savefile./// Cleared upon entering a new world area.////// Used to track whether items that respawn, such as coins, Goomnuts, or Koopa Leaves, have been collected.////// Range: `0 <= v < 0x100`#define AreaFlag(INDEX) ((INDEX) - EVT_AREA_FLAG_OFFSET)
/// Global Save World Flag. A boolean variable saved in the savefile.////// Used to track whether badges, items, etc. have been collected or whether NPCs have been interacted with.////// Range: `0 <= v < 0x800`#define GameFlag(INDEX) ((INDEX) - EVT_GAME_FLAG_OFFSET)
/// Local Saved **Byte**. A variable local to the current world area, saved in the savefile./// Cleared upon a new world area.////// Rarely used. Most common use is for NPCs with dialogue that changes depending on the number of times you have/// interacted with them in their 'recent memory' (i.e. until you leave the area).////// Range: `0 <= v < 0x10`#define AreaByte(INDEX) ((INDEX) - EVT_AREA_BYTE_OFFSET)
/// Global Saved **Byte**. A variable saved in the save file.////// Used for almost all savefile state.#define GameByte(INDEX) ((INDEX) - EVT_GAME_BYTE_OFFSET)
/// User Word. A variable stored within the current script's array./// You can load an array with UseArray or temporarily allocate one with MallocArray, then get/set values with/// the `ArrayVar(index)` macro.////// Range: `0 <= v`#define ArrayVar(INDEX) ((INDEX) - EVT_ARRAY_VAR_OFFSET)
/// User Flag. A boolean variable stored within the current script's flag array./// The flag array is distinct from the word array (unlike UseBuf and UseFBuf).////// Range: `0 <= v`#define ArrayFlag(INDEX) ((INDEX) - EVT_ARRAY_FLAG_OFFSET)
/// Argument Word. A variable parameter to this script execution./// Args are set by Exec/ExecGetID/ExecWait and are not inherited by child scripts or thread blocks./// Assumed to be constant. Mutating by `evt_set_variable` or `evt_set_float_variable` will trigger PANIC.#define ArgVar(INDEX) ((INDEX) - EVT_ARG_VAR_OFFSET)
/// Force an Exec/ExecGetID/ExecWait argument to be dereferenced through `evt_get_variable`./// Arguments not wrapped with ARG_INT or ARG_FLOAT are passed as literal bytecode words.#define ARG_INT(EXPR) EVT_ARG_INT_MARKER, (EXPR)
/// Force an Exec/ExecGetID/ExecWait argument to be dereferenced through `evt_get_float_variable`./// The captured value is stored in the child ArgVar as an EVT fixed-point bytecode word.#define ARG_FLOAT(EXPR) EVT_ARG_FLOAT_MARKER, (EXPR)
typedef s32 (*EvtEval0Func)(void);typedef s32 (*EvtEval1Func)(s32);typedef s32 (*EvtEval2Func)(s32, s32);typedef s32 (*EvtEval3Func)(s32, s32, s32);typedef s32 (*EvtEval4Func)(s32, s32, s32, s32);typedef s32 (*EvtEval5Func)(s32, s32, s32, s32, s32);typedef s32 (*EvtEval6Func)(s32, s32, s32, s32, s32, s32);
typedef f32 (*EvtEvalF0Func)(void);typedef f32 (*EvtEvalF1Func)(f32);typedef f32 (*EvtEvalF2Func)(f32, f32);typedef f32 (*EvtEvalF3Func)(f32, f32, f32);typedef f32 (*EvtEvalF4Func)(f32, f32, f32, f32);typedef f32 (*EvtEvalF5Func)(f32, f32, f32, f32, f32);typedef f32 (*EvtEvalF6Func)(f32, f32, f32, f32, f32, f32);
typedef void (*EvtInvoke0Func)(void);typedef void (*EvtInvoke1Func)(s32);typedef void (*EvtInvoke2Func)(s32, s32);typedef void (*EvtInvoke3Func)(s32, s32, s32);typedef void (*EvtInvoke4Func)(s32, s32, s32, s32);typedef void (*EvtInvoke5Func)(s32, s32, s32, s32, s32);typedef void (*EvtInvoke6Func)(s32, s32, s32, s32, s32, s32);
typedef void (*EvtInvokeF0Func)(void);typedef void (*EvtInvokeF1Func)(f32);typedef void (*EvtInvokeF2Func)(f32, f32);typedef void (*EvtInvokeF3Func)(f32, f32, f32);typedef void (*EvtInvokeF4Func)(f32, f32, f32, f32);typedef void (*EvtInvokeF5Func)(f32, f32, f32, f32, f32);typedef void (*EvtInvokeF6Func)(f32, f32, f32, f32, f32, f32);
typedef b32 (*EvtPredicate0Func)(void);typedef b32 (*EvtPredicate1Func)(s32);typedef b32 (*EvtPredicate2Func)(s32, s32);typedef b32 (*EvtPredicate3Func)(s32, s32, s32);typedef b32 (*EvtPredicate4Func)(s32, s32, s32, s32);typedef b32 (*EvtPredicate5Func)(s32, s32, s32, s32, s32);typedef b32 (*EvtPredicate6Func)(s32, s32, s32, s32, s32, s32);
typedef b32 (*EvtPredicateF0Func)(void);typedef b32 (*EvtPredicateF1Func)(f32);typedef b32 (*EvtPredicateF2Func)(f32, f32);typedef b32 (*EvtPredicateF3Func)(f32, f32, f32);typedef b32 (*EvtPredicateF4Func)(f32, f32, f32, f32);typedef b32 (*EvtPredicateF5Func)(f32, f32, f32, f32, f32);typedef b32 (*EvtPredicateF6Func)(f32, f32, f32, f32, f32, f32);
#ifdef __cplusplus#define EVT_CHECK_FUNC_SIGNATURE(FUNC, TYPE) \ ((Bytecode)(0 * sizeof(EvtFuncSignatureMatches<decltype(&(FUNC)), TYPE>) + (Bytecode)(FUNC)))#elif defined(__GNUC__)#define EVT_CHECK_FUNC_SIGNATURE(FUNC, TYPE) \ (0 * sizeof(struct { \ _Static_assert( \ __builtin_types_compatible_p(__typeof__(&(FUNC)), TYPE), \ "EVT_BAD_SIGNATURE expected " #TYPE \ ); \ char evtSignatureOk; \ }) + (Bytecode)(FUNC))#else#define EVT_CHECK_FUNC_SIGNATURE(FUNC, TYPE) ((Bytecode)(FUNC))#endif
/// An entity index. Entities are assigned indices in the order they are created with Call(MakeEntity, ...)./// Supported in BindTrigger and BindItemPrompt only.#define EVT_ENTITY_ID_BIT 0x4000#define EVT_ENTITY_INDEX(entityIndex) ((entityIndex) + EVT_ENTITY_ID_BIT)
// inverse macros for obtaining the index of a variable from its encoded form#define EVT_INDEX_OF_LOCAL_VAR(v) ((v) + EVT_LOCAL_VAR_OFFSET)#define EVT_INDEX_OF_LOCAL_FLAG(v) ((v) + EVT_LOCAL_FLAG_OFFSET)#define EVT_INDEX_OF_MAP_VAR(v) ((v) + EVT_MAP_VAR_OFFSET)#define EVT_INDEX_OF_MAP_FLAG(v) ((v) + EVT_MAP_FLAG_OFFSET)#define EVT_INDEX_OF_AREA_FLAG(v) ((v) + EVT_AREA_FLAG_OFFSET)#define EVT_INDEX_OF_AREA_BYTE(v) ((v) + EVT_AREA_BYTE_OFFSET)#define EVT_INDEX_OF_GAME_FLAG(v) ((v) + EVT_GAME_FLAG_OFFSET)#define EVT_INDEX_OF_GAME_BYTE(v) ((v) + EVT_GAME_BYTE_OFFSET)#define EVT_INDEX_OF_ARRAY_FLAG(v) ((v) + EVT_ARRAY_FLAG_OFFSET)#define EVT_INDEX_OF_ARRAY_VAR(v) ((v) + EVT_ARRAY_VAR_OFFSET)#define EVT_INDEX_OF_ARG_VAR(v) ((v) + EVT_ARG_VAR_OFFSET)
// shorthand names for LocalVar#define LVar0 LocalVar(0)#define LVar1 LocalVar(1)#define LVar2 LocalVar(2)#define LVar3 LocalVar(3)#define LVar4 LocalVar(4)#define LVar5 LocalVar(5)#define LVar6 LocalVar(6)#define LVar7 LocalVar(7)#define LVar8 LocalVar(8)#define LVar9 LocalVar(9)#define LVarA LocalVar(10)#define LVarB LocalVar(11)#define LVarC LocalVar(12)#define LVarD LocalVar(13)#define LVarE LocalVar(14)#define LVarF LocalVar(15)
// shorthand names for ArgVar#define ArgVar0 ArgVar(0)#define ArgVar1 ArgVar(1)#define ArgVar2 ArgVar(2)#define ArgVar3 ArgVar(3)#define ArgVar4 ArgVar(4)#define ArgVar5 ArgVar(5)#define ArgVar6 ArgVar(6)#define ArgVar7 ArgVar(7)
// shorthand names for common LocalFlags// these actually run all the way up to LocalFlag(96), but nothing past 15 is ever used#define LFlag0 LocalFlag(0)#define LFlag1 LocalFlag(1)#define LFlag2 LocalFlag(2)#define LFlag3 LocalFlag(3)#define LFlag4 LocalFlag(4)#define LFlag5 LocalFlag(5)#define LFlag6 LocalFlag(6)#define LFlag7 LocalFlag(7)#define LFlag8 LocalFlag(8)#define LFlag9 LocalFlag(9)#define LFlagA LocalFlag(10)#define LFlagB LocalFlag(11)#define LFlagC LocalFlag(12)#define LFlagD LocalFlag(13)#define LFlagE LocalFlag(14)#define LFlagF LocalFlag(15)
/****** INSTRUCTIONS **************************************************************************************************/
/// On each frame, the EVT manager will continue executing commands in all scripts until a blocking command is/// encountered. This means that if you have a script that loops but does not block between iterations, the game will/// freeze! Avoid this by inserting a blocking command such as Wait(1) in the loop body.////// Also note that scripts are never executed in parallel. If your EVT script lacks blocking commands, it will be/// executed all in one go, and race conditions cannot occur.////// The following subset of EVT commands are blocking:/// - ExecWait/// - Wait/// - Wait_SECONDS/// - Call (if function returns ApiStatus_BLOCK)
/// Signals the end of EVT script data. A script missing this will likely crash on load.#define End EVT_CMD(EVT_OP_END),
/// Kills the current EVT script./// A script missing a return will live - but do nothing - forever, or until something else kills it (e.g. leaving the/// map).#define Return EVT_CMD(EVT_OP_RETURN),
/// Marks the start of a synchronous cleanup tail for the script./// When present, Return, End, and external kills run the commands after Finally before the script is cleaned up./// Owned children are cleaned up first. The tail ends at the normal End/EndThread/EndChildThread and must not block/// or start an owned child. Exec and ExecGetID may start detached scripts. KillScript is allowed and is idempotent/// for scripts which are already terminating.#define Finally EVT_CMD(EVT_OP_FINALLY),
/// Jumps to a given instruction pointer and begins execution from there./// You can jump to a different EVT source and labels etc. will be loaded as expected./// The timescale for the current script is also reset to the global default.#define Jump(EVT_SOURCE) EVT_CMD(EVT_OP_JUMP, (Bytecode) EVT_SOURCE),
/// Marks this point in the script as a Goto target.////// `LABEL_ID` may be an integer constant outside the EVT expression range, or/// a pointer to an identifier-style string such as `"Resume"` or `Ref(sym)`.#define Label(LABEL_ID) EVT_CMD(EVT_OP_LABEL, (Bytecode) LABEL_ID),
/// Moves execution to the given label.////// `LABEL_ID` must use the same representation as the matching Label.#define Goto(LABEL_ID) EVT_CMD(EVT_OP_GOTO, (Bytecode) LABEL_ID),
/// Marks the beginning of a loop.////// Loop(TIMES)/// .../// EndLoop////// The variable or value given in `TIMES` is decremented upon each loop iteration./// After the "1" iteration completes, the loop exits./// Use Loop(0) for an infinite loop; make sure it breaks or blocks to avoid a freeze.////// Up to 8 loops may be nested within a single script.#define Loop(TIMES) EVT_CMD(EVT_OP_LOOP, TIMES),
/// Marks the end of a loop.#define EndLoop EVT_CMD(EVT_OP_END_LOOP),
/// Breaks out of the innermost loop.#define BreakLoop EVT_CMD(EVT_OP_BREAK_LOOP),
/// Skips to the next iteration of the innermost loop.#define ContinueLoop EVT_CMD(EVT_OP_CONTINUE_LOOP),
/// Immediately restarts the current iteration of the innermost loop without updating its counter.#define RetryLoop EVT_CMD(EVT_OP_RETRY_LOOP),
/// Marks the beginning of a lerp loop.////// Lerp(VAR, START, END, DURATION, EASING)/// .../// EndLerp////// `VAR` is set to the current interpolated value before each iteration./// `START` and `END` may be integer or Float values. `DURATION` is measured in frames./// The body runs once for each elapsed frame from 0 through `DURATION`, then exits./// `EndLerp` yields for one frame between iterations, so no Wait is needed inside the loop.////// `BreakLoop` exits the lerp early. `ContinueLoop` and `RetryLoop` are not allowed inside Lerp./// Lerp blocks cannot be nested. Up to 8 total Loop and Lerp blocks may be/// active within a single script.#define Lerp(VAR, START, END, DURATION, EASING) \ EVT_CMD(EVT_OP_LERP, VAR, START, END, DURATION, EASING),
/// Marks the end of a lerp loop.#define EndLerp EVT_CMD(EVT_OP_END_LERP),
/// Blocks for the given number of frames.#define Wait(NUM_FRAMES) EVT_CMD(EVT_OP_WAIT_FRAMES, NUM_FRAMES),
/// Blocks for the given number of seconds.#define WaitSecs(NUM_SECONDS) EVT_CMD(EVT_OP_WAIT_SECS, NUM_SECONDS),
/// Marks the beginning of an if statement that only executes if `LVAR == RVAR`.////// IfEq(LVAR, RVAR)/// .../// Else/// .../// EndIf////// The Else block is optional.#define IfEq(LVAR, RVAR) EVT_CMD(EVT_OP_IF_EQ, LVAR, RVAR),
/// Marks the beginning of an if statement that only executes if `LVAR != RVAR`.#define IfNe(LVAR, RVAR) EVT_CMD(EVT_OP_IF_NE, LVAR, RVAR),
/// Marks the beginning of an if statement that only executes if `LVAR < RVAR`.#define IfLt(LVAR, RVAR) EVT_CMD(EVT_OP_IF_LT, LVAR, RVAR),
/// Marks the beginning of an if statement that only executes if `LVAR > RVAR`.#define IfGt(LVAR, RVAR) EVT_CMD(EVT_OP_IF_GT, LVAR, RVAR),
/// Marks the beginning of an if statement that only executes if `LVAR <= RVAR`.#define IfLe(LVAR, RVAR) EVT_CMD(EVT_OP_IF_LE, LVAR, RVAR),
/// Marks the beginning of an if statement that only executes if `LVAR >= RVAR`.#define IfGe(LVAR, RVAR) EVT_CMD(EVT_OP_IF_GE, LVAR, RVAR),
/// Marks the beginning of an if statement that only executes if `MIN <= LVAR <= MAX`.#define IfRange(LVAR, MIN, MAX) EVT_CMD(EVT_OP_IF_RANGE, LVAR, MIN, MAX),
/// Marks the beginning of an if statement that only executes if `LVAR < MIN` or `LVAR > MAX`.#define IfNotRange(LVAR, MIN, MAX) EVT_CMD(EVT_OP_IF_NOT_RANGE, LVAR, MIN, MAX),
/// Marks the beginning of an if statement that only executes if the RVAR flag is set on LVAR,/// i.e. `(LVAR & RVAR) != 0`.#define IfFlag(LVAR, RVAR) EVT_CMD(EVT_OP_IF_FLAG, LVAR, RVAR),
/// Marks the beginning of an if statement that only executes if the RVAR flag is unset on LVAR,/// i.e. `(LVAR & RVAR) == 0`.#define IfNotFlag(LVAR, RVAR) EVT_CMD(EVT_OP_IF_NOT_FLAG, LVAR, RVAR),
/// Marks the end of an if statement and the start of the else block.#define Else EVT_CMD(EVT_OP_ELSE),
/// Marks the end of an if statement or an else block.#define EndIf EVT_CMD(EVT_OP_END_IF),
/// Marks the start of a switch statement.////// Switch(LVAR)/// CaseEq(RVAR)/// .../// EndSwitch////// Unlike C, EVT switch statements do not have fallthrough by default./// If you want to opt-in to fallthrough, use CaseOrEq.////// Up to 8 switch statements may be nested within a single script.#define Switch(LVAR) EVT_CMD(EVT_OP_SWITCH, LVAR),
/// Marks the start of a switch statement where the given value is treated as-is instead of using evt_get_variable./// That is, `SwitchConst(LocalVar(0))` will switch over the value `0xFE363C80` instead of the value contained/// within `LocalVar(0)`.#define SwitchConst(LCONST) EVT_CMD(EVT_OP_SWITCH_CONST, LCONST),
/// Marks the start of a switch case that executes only if `LVAR == RVAR`. It also marks the end of any previous case.#define CaseEq(RVAR) EVT_CMD(EVT_OP_CASE_EQ, RVAR),
/// Marks the start of a switch case that executes only if `LVAR != RVAR`. It also marks the end of any previous case.#define CaseNe(RVAR) EVT_CMD(EVT_OP_CASE_NE, RVAR),
/// Marks the start of a switch case that executes only if `LVAR < RVAR`. It also marks the end of any previous case.#define CaseLt(RVAR) EVT_CMD(EVT_OP_CASE_LT, RVAR),
/// Marks the start of a switch case that executes only if `LVAR > RVAR`. It also marks the end of any previous case.#define CaseGt(RVAR) EVT_CMD(EVT_OP_CASE_GT, RVAR),
/// Marks the start of a switch case that executes only if `LVAR <= RVAR`. It also marks the end of any previous case.#define CaseLe(RVAR) EVT_CMD(EVT_OP_CASE_LE, RVAR),
/// Marks the start of a switch case that executes only if `LVAR >= RVAR`. It also marks the end of any previous case.#define CaseGe(RVAR) EVT_CMD(EVT_OP_CASE_GE, RVAR),
/// Marks the start of a switch case that executes unconditionally. It also marks the end of any previous case.#define CaseDefault EVT_CMD(EVT_OP_CASE_DEFAULT),
/// Marks the start of a switch case that executes only if `LVAR == RVAR`. It also marks the end of any previous case./// Unlike CaseEq, CaseOrEq will fallthrough to the next case until EndCaseGroup is reached.#define CaseOrEq(RVAR) EVT_CMD(EVT_OP_CASE_OR_EQ, RVAR),
/// Marks the start of a switch case that executes only if `LVAR == RVAR`. It also marks the end of any previous case./// Similar to CaseOrEq, CaseAndEq has fallthrough. However, if `LVAR != RVAR`, fallthrough does not apply.#define CaseAndEq(RVAR) EVT_CMD(EVT_OP_CASE_AND_EQ, RVAR),
/// Marks the start of a switch case that executes only if the `RVAR` flag is set on `LVAR`, i.e. `(LVAR & RVAR) != 0`./// It also marks the end of any previous case.#define CaseFlag(RVAR) EVT_CMD(EVT_OP_CASE_FLAG, RVAR),
/// Marks the end of a switch case group (CaseOrEq and/or CaseAndEq), stopping fallthrough.#define EndCaseGroup EVT_CMD(EVT_OP_END_CASE_GROUP),
/// Marks the start of a switch case that executes only if `MIN <= LVAR <= MAX` (inclusive)./// It also marks the end of any previous case.#define CaseRange(MIN, MAX) EVT_CMD(EVT_OP_CASE_RANGE, MIN, MAX),
/// Marks the end of a switch case#define BreakSwitch EVT_CMD(EVT_OP_BREAK_SWITCH),
/// Marks the end of a switch statement and any case.#define EndSwitch EVT_CMD(EVT_OP_END_SWITCH),
/// Sets the given variable to a given value casted to an integer.#define Set(VAR, INT_VALUE) EVT_CMD(EVT_OP_SET, VAR, (Bytecode) INT_VALUE),
/// Sets the given variable to a given value, skipping the evt_get_variable call./// That is, `SetConst(LocalVar(0), LocalVar(1))` will set `LocalVar(0)` to `0xFE363C81` instead of copying the value of/// `LocalVar(1)` into `LocalVar(0)`.#define SetConst(VAR, CONST) EVT_CMD(EVT_OP_SET_CONST, VAR, (Bytecode) CONST),
/// Sets the given variable to a given value, but supports Floats.#define SetF(VAR, FLOAT_VALUE) EVT_CMD(EVT_OP_SETF, VAR, FLOAT_VALUE),
/// When used with two args, adds a value to a variable (A += B)./// When used with more args, all are added together and stored in the variable (A = B + C + ...).#define Add(VAR, INT_VALUE, MORE...) EVT_CMD(EVT_OP_ADD, VAR, INT_VALUE, ##MORE),
/// When used with two args, subtracts a value from a variable (A -= B)./// When used with three args, subtracts one value from another and stores the result in the variable (A = B - C).#define Sub(VAR, INT_VALUE, MORE...) EVT_CMD(EVT_OP_SUB, VAR, INT_VALUE, ##MORE),
/// When used with two args, multiplies a variable by a value (A *= B)./// When used with more args, all are multiplied together and stored in the variable (A = B * C * ...).#define Mul(VAR, INT_VALUE, MORE...) EVT_CMD(EVT_OP_MUL, VAR, INT_VALUE, ##MORE),
/// When used with two args, divides a variable by a value (A /= B)./// When used with three args, divides one value by another and stores the result in the variable (A = B / C).#define Div(VAR, INT_VALUE, MORE...) EVT_CMD(EVT_OP_DIV, VAR, INT_VALUE, ##MORE),
/// When used with two args, stores the remainder of a variable divided by a value (A %= B)./// When used with three args, stores the remainder of one value divided by another in the variable (A = B % C).#define Mod(VAR, INT_VALUE, MORE...) EVT_CMD(EVT_OP_MOD, VAR, INT_VALUE, ##MORE),
/// When used with two args, adds a value to a variable (A += B)./// When used with more args, all are added together and stored in the variable (A = B + C + ...).#define AddF(VAR, FLOAT_VALUE, MORE...) EVT_CMD(EVT_OP_ADDF, VAR, FLOAT_VALUE, ##MORE),
/// When used with two args, subtracts a value from a variable (A -= B)./// When used with three args, subtracts one value from another and stores the result in the variable (A = B - C).#define SubF(VAR, FLOAT_VALUE, MORE...) EVT_CMD(EVT_OP_SUBF, VAR, FLOAT_VALUE, ##MORE),
/// When used with two args, multiplies a variable by a value (A *= B)./// When used with more args, all are multiplied together and stored in the variable (A = B * C * ...).#define MulF(VAR, FLOAT_VALUE, MORE...) EVT_CMD(EVT_OP_MULF, VAR, FLOAT_VALUE, ##MORE),
/// When used with two args, divides a variable by a value (A /= B)./// When used with three args, divides one value by another and stores the result in the variable (A = B / C).#define DivF(VAR, FLOAT_VALUE, MORE...) EVT_CMD(EVT_OP_DIVF, VAR, FLOAT_VALUE, ##MORE),
/// When used with one arg, negates a variable (A = -A)./// When used with two args, negates a value and stores the result in the variable (A = -B).#define Neg(VAR, INT_VALUE...) EVT_CMD(EVT_OP_NEG, VAR, ##INT_VALUE),
/// When used with one arg, negates a variable (A = -A)./// When used with two args, negates a value and stores the result in the variable (A = -B).#define NegF(VAR, FLOAT_VALUE...) EVT_CMD(EVT_OP_NEGF, VAR, ##FLOAT_VALUE),
/// When used with one arg, stores the absolute value of a variable (A = abs(A))./// When used with two args, stores the absolute value of another value (A = abs(B)).#define Abs(VAR, INT_VALUE...) EVT_CMD(EVT_OP_ABS, VAR, ##INT_VALUE),
/// When used with one arg, stores the absolute value of a variable (A = abs(A))./// When used with two args, stores the absolute value of another value (A = abs(B)).#define AbsF(VAR, FLOAT_VALUE...) EVT_CMD(EVT_OP_ABSF, VAR, ##FLOAT_VALUE),
/// When used with one arg, stores the sign of a variable as -1, 0, or 1 (A = sign(A))./// When used with two args, stores the sign of another value as -1, 0, or 1 (A = sign(B)).#define Sign(VAR, INT_VALUE...) EVT_CMD(EVT_OP_SIGN, VAR, ##INT_VALUE),
/// When used with one arg, stores the sign of a variable as -1.0, 0.0, or 1.0 (A = sign(A))./// When used with two args, stores the sign of another value as -1.0, 0.0, or 1.0 (A = sign(B)).#define SignF(VAR, FLOAT_VALUE...) EVT_CMD(EVT_OP_SIGNF, VAR, ##FLOAT_VALUE),
/// When used with two args, stores the lower of a variable and another value (A = min(A, B))./// When used with more args, stores the lowest value in the variable (A = min(B, C, ...)).#define Min(VAR, INT_VALUE, MORE...) EVT_CMD(EVT_OP_MIN, VAR, INT_VALUE, ##MORE),
/// When used with two args, stores the lower of a variable and another value (A = min(A, B))./// When used with more args, stores the lowest value in the variable (A = min(B, C, ...)).#define MinF(VAR, FLOAT_VALUE, MORE...) EVT_CMD(EVT_OP_MINF, VAR, FLOAT_VALUE, ##MORE),
/// When used with two args, stores the higher of a variable and another value (A = max(A, B))./// When used with more args, stores the highest value in the variable (A = max(B, C, ...)).#define Max(VAR, INT_VALUE, MORE...) EVT_CMD(EVT_OP_MAX, VAR, INT_VALUE, ##MORE),
/// When used with two args, stores the higher of a variable and another value (A = max(A, B))./// When used with more args, stores the highest value in the variable (A = max(B, C, ...)).#define MaxF(VAR, FLOAT_VALUE, MORE...) EVT_CMD(EVT_OP_MAXF, VAR, FLOAT_VALUE, ##MORE),
/// When used with three args, clamps a variable between a min and max (A = clamp(A, MIN, MAX))./// When used with four args, clamps a value between a min and max and stores the result (A = clamp(B, MIN, MAX)).#define Clamp(VAR, MIN_OR_VALUE, MAX_OR_MIN, MORE...) EVT_CMD(EVT_OP_CLAMP, VAR, MIN_OR_VALUE, MAX_OR_MIN, ##MORE),
/// When used with three args, clamps a variable between a min and max (A = clamp(A, MIN, MAX))./// When used with four args, clamps a value between a min and max and stores the result (A = clamp(B, MIN, MAX)).#define ClampF(VAR, MIN_OR_VALUE, MAX_OR_MIN, MORE...) EVT_CMD(EVT_OP_CLAMPF, VAR, MIN_OR_VALUE, MAX_OR_MIN, ##MORE),
/// Loads a s32 pointer for use with subsequent BufRead commands.#define UseBuf(INT_PTR) EVT_CMD(EVT_OP_USE_BUF, (Bytecode) INT_PTR),
/// Consumes one or more s32s from the buffer and stores them in the given variables.#define BufRead(VAR, MORE...) EVT_CMD(EVT_OP_BUF_READ, VAR, ##MORE),
/// Gets the s32 at the given offset of the buffer and stores it in the given variable, without consuming it.#define BufPeek(VAR, OFFSET) EVT_CMD(EVT_OP_BUF_PEEK, VAR, OFFSET),
/// Loads an s32 pointer of fixed-point `Float(...)` values for use with subsequent FBufRead commands./// Beware that the int buffer and the float buffer are not distinct.#define UseFBuf(FLOAT_PTR) EVT_CMD(EVT_OP_USE_FBUF, (Bytecode) FLOAT_PTR),
/// Consumes one or more fixed-point `Float(...)` values from the buffer and stores them in the given variables.#define FBufRead(VAR, MORE...) EVT_CMD(EVT_OP_FBUF_READ, VAR, ##MORE),
/// Gets the fixed-point `Float(...)` value at the given offset and stores it without consuming it.#define FBufPeek(VAR, OFFSET) EVT_CMD(EVT_OP_FBUF_PEEK, VAR, OFFSET),
#define EVT_MEM_TYPEOF(VALUE) _Generic((VALUE), \ u8: EVT_MEM_U8, \ s8: EVT_MEM_S8, \ u16: EVT_MEM_U16, \ s16: EVT_MEM_S16, \ u32: EVT_MEM_U32, \ s32: EVT_MEM_S32, \ f32: EVT_MEM_F32)
/// Reads a typed value from a C lvalue into an EVT variable./// The address is taken implicitly and must refer to readable memory. No bounds checking is performed.#define MemGet(OUT_VAR, SOURCE) EVT_CMD(EVT_OP_MEM_GET, EVT_MEM_TYPEOF(SOURCE), OUT_VAR, Ref(SOURCE), 0),
/// Writes an EVT value to a typed C lvalue./// The address is taken implicitly and must refer to writable memory. No bounds checking is performed.#define MemSet(DESTINATION, VALUE) EVT_CMD(EVT_OP_MEM_SET, EVT_MEM_TYPEOF(DESTINATION), Ref(DESTINATION), 0, VALUE),
/// Reads a typed array element using an index evaluated when the script runs./// The array must be a link-time-addressable C array, not a pointer stored in an EVT variable.#define MemGetIndex(OUT_VAR, SOURCE_ARRAY, INDEX) \ EVT_CMD(EVT_OP_MEM_GET, EVT_MEM_TYPEOF((SOURCE_ARRAY)[0]), OUT_VAR, Ref((SOURCE_ARRAY)[0]), INDEX),
/// Writes a typed array element using an index evaluated when the script runs./// The array must be a link-time-addressable C array, not a pointer stored in an EVT variable.#define MemSetIndex(DESTINATION_ARRAY, INDEX, VALUE) \ EVT_CMD(EVT_OP_MEM_SET, EVT_MEM_TYPEOF((DESTINATION_ARRAY)[0]), Ref((DESTINATION_ARRAY)[0]), INDEX, VALUE),
/// Loads an s32 array pointer into the current script for use with `ArrayVar(INDEX)`.#define UseArray(INT_PTR) EVT_CMD(EVT_OP_USE_ARRAY, (Bytecode) INT_PTR),
/// Loads an s32 array pointer into the current script for use with `UF(INDEX)`./// Flags are stored in a 'packed' structure where indices refer to bits.#define UseFlagArray(PACKED_FLAGS_PTR) EVT_CMD(EVT_OP_USE_FLAGS, (Bytecode) PACKED_FLAGS_PTR),
/// Allocates a new array of the given size for use with `ArrayVar(INDEX)`./// EVT scripts do not have to worry about freeing this array.#define MallocArray(SIZE, OUT_PTR_VAR) EVT_CMD(EVT_OP_MALLOC_ARRAY, SIZE, OUT_PTR_VAR),
/// `VAR &= VALUE`#define BitwiseAnd(VAR, VALUE) EVT_CMD(EVT_OP_BITWISE_AND, VAR, VALUE),
/// `VAR &= CONST`, but CONST is treated as-is rather than dereferenced with evt_get_variable.#define BitwiseAndConst(VAR, CONST) EVT_CMD(EVT_OP_BITWISE_AND_CONST, VAR, CONST),
/// `VAR |= VALUE`#define BitwiseOr(VAR, VALUE) EVT_CMD(EVT_OP_BITWISE_OR, VAR, VALUE),
/// `VAR |= CONST`, but CONST is treated as-is rather than dereferenced with evt_get_variable.#define BitwiseOrConst(VAR, CONST) EVT_CMD(EVT_OP_BITWISE_OR_CONST, VAR, CONST),
/// Launches a new detached script./// The following values are copied from the current script to the new script:/// - LocalFlags/// - LocalVars/// - Array pointer/// - Flag array pointer/// - Priority/// - Group////// Extra ARGS become ArgVars in the new script. Arguments are passed as literal bytecode words unless explicitly/// wrapped with ARG_INT or ARG_FLOAT.#define Exec(EVT_SOURCE, ARGS...) EVT_CMD(EVT_OP_EXEC, (Bytecode) EVT_SOURCE, ##ARGS),
/// Identical to Exec, but the newly-launched script ID is stored in OUTVAR./// The other script may be interacted with using KillScript, SuspendScript, ResumeScript, and/// IsScriptRunning./// Extra ARGS become ArgVars in the new script with the same capture rules as Exec.#define ExecGetID(OUTVAR, EVT_SOURCE, ARGS...) \ EVT_CMD(EVT_OP_EXEC_GET_ID, (Bytecode) EVT_SOURCE, OUTVAR, ##ARGS),
/// Launches a new child script./// Blocks for at least one frame unless the child is made to have a higher priority than the parent.////// The following values are inherited and then copied back to the parent script upon completion:/// - LocalFlags/// - LocalVars/// - Array pointer/// - Flag array pointer/// - Priority/// - Group////// Child scripts are killed, suspended, and resumed with their parent. For example, using KillScript on the parent/// also kills the child launched by this command./// Extra ARGS become ArgVars in the child script with the same capture rules as Exec.#define ExecWait(EVT_SOURCE, ARGS...) EVT_CMD(EVT_OP_EXEC_WAIT, (Bytecode) EVT_SOURCE, ##ARGS),
/// Assert that this script invocation received exactly NUM_ARGS arguments.#define ExpectArgs(NUM_ARGS) EVT_CMD(EVT_OP_EXPECT_ARGS, NUM_ARGS),
/// Sets up a script to launch when a particular event is triggered.////// EVT_SOURCE is the script to launch when the trigger activates./// TRIGGER is one or more trigger flags./// COLLIDER_ID is the trigger target./// HAS_INTERACT_PROMPT controls whether the player sees the interaction prompt for wall-press-A triggers./// TRIGGER_PTR_OUTVAR receives the Trigger* when nonzero.////// Valid triggers:/// - TRIGGER_WALL_PUSH/// - TRIGGER_FLOOR_TOUCH/// - TRIGGER_WALL_PRESS_A (displays "!" icon above player)/// - TRIGGER_FLOOR_JUMP/// - TRIGGER_WALL_TOUCH/// - TRIGGER_FLOOR_PRESS_A/// - TRIGGER_WALL_HAMMER/// - TRIGGER_GAME_FLAG_SET/// - TRIGGER_AREA_FLAG_SET/// - TRIGGER_CEILING_TOUCH/// - TRIGGER_FLOOR_ABOVE/// - TRIGGER_POINT_BOMB (takes Vec3f* instead of collider ID)////// For the `COLLIDER_ID` param, the following values are accepted:/// - Collider ID/// - Entity ID (use EVT_ENTITY_INDEX)/// - Pointer to a Vec3f (for TRIGGER_POINT_BOMB only)////// Only one script will run for a trigger at once.#define BindTrigger(EVT_SOURCE, TRIGGER, COLLIDER_ID, HAS_INTERACT_PROMPT, TRIGGER_PTR_OUTVAR) \ EVT_CMD(EVT_OP_BIND_TRIGGER, (Bytecode) EVT_SOURCE, TRIGGER, (Bytecode) COLLIDER_ID, HAS_INTERACT_PROMPT, TRIGGER_PTR_OUTVAR),
/// Similar to BindTrigger, but also attaches an item list to the trigger context.////// EVT_SOURCE is responsible for showing any item prompt, typically by calling ShowKeyChoicePopup or/// ShowConsumableChoicePopup. Those APIs read ITEM_LIST from the trigger context created here./// TATTLE_MSG is stored on the trigger and may be read by Goombario tattles./// HAS_INTERACT_PROMPT controls whether the player sees the interaction prompt for wall-press-A triggers.#define BindItemPrompt(EVT_SOURCE, TRIGGER, COLLIDER_ID, ITEM_LIST, TATTLE_MSG, HAS_INTERACT_PROMPT) \ EVT_CMD(EVT_OP_BIND_ITEM_PROMPT, (Bytecode) EVT_SOURCE, TRIGGER, COLLIDER_ID, (Bytecode) ITEM_LIST, TATTLE_MSG, HAS_INTERACT_PROMPT),
/// Unbinds the current script from the trigger it was bound to, if any.#define Unbind EVT_CMD(EVT_OP_UNBIND),
/// Kills a script by its ID.#define KillScript(SCRIPT_ID) EVT_CMD(EVT_OP_KILL_SCRIPT, SCRIPT_ID),
/// Sets the current script's priority. Higher-priority scripts execute before lower-priority scripts on each frame.#define SetPriority(PRIORITY) EVT_CMD(EVT_OP_SET_PRIORITY, PRIORITY),
/// Sets the current script's timescale. This is a multiplier applied to Wait and Wait_SECONDS.#define SetTimescale(TIMESCALE) EVT_CMD(EVT_OP_SET_TIMESCALE, TIMESCALE),
/// Sets the current script's group. Group value meanings are currently not known.#define SetGroup(GROUP) EVT_CMD(EVT_OP_SET_GROUP, GROUP),
/// Suspends all scripts in a group.#define SuspendGroup(GROUP) EVT_CMD(EVT_OP_SUSPEND_GROUP, GROUP),
/// Resumes all scripts in a group.#define ResumeGroup(GROUP) EVT_CMD(EVT_OP_RESUME_GROUP, GROUP),
/// Suspends all scripts in a group, except the current script.#define SuspendOthers(GROUP) EVT_CMD(EVT_OP_SUSPEND_OTHERS, GROUP),
/// Resumes all scripts in a group, except the current script.#define ResumeOthers(GROUP) EVT_CMD(EVT_OP_RESUME_OTHERS, GROUP),
/// Suspends a script by its script ID.#define SuspendScript(SCRIPT_ID) EVT_CMD(EVT_OP_SUSPEND_SCRIPT, SCRIPT_ID),
/// Resumes a script by its script ID.#define ResumeScript(SCRIPT_ID) EVT_CMD(EVT_OP_RESUME_SCRIPT, SCRIPT_ID),
/// Sets OUTVAR to true/false depending on whether a script with the given ID exists (i.e. has not been killed).#define IsScriptRunning(SCRIPT_ID, OUTVAR) EVT_CMD(EVT_OP_IS_SCRIPT_RUNNING, SCRIPT_ID, OUTVAR),
/// Waits until the script with the given ID no longer exists.#define AwaitScript(SCRIPT_ID) EVT_CMD(EVT_OP_AWAIT_SCRIPT, SCRIPT_ID),
/// Marks the start of a thread block. Commands between this and a matching EndThread/// will run as a new detached script.#define Thread EVT_CMD(EVT_OP_THREAD),
/// Marks the end of a thread block.#define EndThread EVT_CMD(EVT_OP_END_THREAD),
/// Marks the start of a child thread block. Commands between this and a matching EndChildThread/// will run as a new child script.////// Child threads are killed if the parent script dies, so the following script does NOT set the player's position:////// ChildThread/// Wait_SECONDS(1) // child thread will be killed whilst waiting/// Call(SetPlayerPos, NPC_DISPOSE_LOCATION) // will not be executed/// EndChildThread/// Return // parent script dies///#define ChildThread EVT_CMD(EVT_OP_CHILD_THREAD),
/// Marks the end of a child thread block.#define EndChildThread EVT_CMD(EVT_OP_END_CHILD_THREAD),
/// Waits until all direct ChildThread children of the current script have finished.#define AwaitChildren EVT_CMD(EVT_OP_AWAIT_CHILDREN),
/// Calls a given C EVT API function with any number of arguments.////// An API function has the following signature:////// ApiStatus ApiFunction(Evt* script, s32 isInitialCall);////// This function could then be called with the following command:////// Call(ApiFunction)////// The given arguments can be accessed from the API function using `script->ptrReadPos`.#define Call(FUNC, ARGS...) EVT_CMD(EVT_OP_CALL, (Bytecode) FUNC, ##ARGS),
/// Calls a C function with integer arguments and stores its return value.////// The function must return s32 and take exactly the supplied number of s32 arguments./// The function is called synchronously and cannot block script execution.#define Eval(ARGS...) VFUNC(Eval, ARGS)#define Eval2(OUT, FUNC) EVT_CMD(EVT_OP_EVAL, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEval0Func)),#define Eval3(OUT, FUNC, A) EVT_CMD(EVT_OP_EVAL, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEval1Func), A),#define Eval4(OUT, FUNC, A, B) EVT_CMD(EVT_OP_EVAL, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEval2Func), A, B),#define Eval5(OUT, FUNC, A, B, C) EVT_CMD(EVT_OP_EVAL, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEval3Func), A, B, C),#define Eval6(OUT, FUNC, A, B, C, D) EVT_CMD(EVT_OP_EVAL, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEval4Func), A, B, C, D),#define Eval7(OUT, FUNC, A, B, C, D, E) EVT_CMD(EVT_OP_EVAL, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEval5Func), A, B, C, D, E),#define Eval8(OUT, FUNC, A, B, C, D, E, F) EVT_CMD(EVT_OP_EVAL, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEval6Func), A, B, C, D, E, F),
/// Calls a C function with float arguments and stores its float return value.////// The function must return f32 and take exactly the supplied number of f32 arguments./// The function is called synchronously and cannot block script execution.#define EvalF(ARGS...) VFUNC(EvalF, ARGS)#define EvalF2(OUT, FUNC) EVT_CMD(EVT_OP_EVALF, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEvalF0Func)),#define EvalF3(OUT, FUNC, A) EVT_CMD(EVT_OP_EVALF, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEvalF1Func), A),#define EvalF4(OUT, FUNC, A, B) EVT_CMD(EVT_OP_EVALF, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEvalF2Func), A, B),#define EvalF5(OUT, FUNC, A, B, C) EVT_CMD(EVT_OP_EVALF, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEvalF3Func), A, B, C),#define EvalF6(OUT, FUNC, A, B, C, D) EVT_CMD(EVT_OP_EVALF, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEvalF4Func), A, B, C, D),#define EvalF7(OUT, FUNC, A, B, C, D, E) EVT_CMD(EVT_OP_EVALF, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEvalF5Func), A, B, C, D, E),#define EvalF8(OUT, FUNC, A, B, C, D, E, F) EVT_CMD(EVT_OP_EVALF, OUT, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtEvalF6Func), A, B, C, D, E, F),
/// Calls a C function with integer arguments and no return value.////// The function must return void and take exactly the supplied number of s32 arguments./// The function is called synchronously and cannot block script execution.#define Invoke(ARGS...) VFUNC(Invoke, ARGS)#define Invoke1(FUNC) EVT_CMD(EVT_OP_INVOKE, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvoke0Func)),#define Invoke2(FUNC, A) EVT_CMD(EVT_OP_INVOKE, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvoke1Func), A),#define Invoke3(FUNC, A, B) EVT_CMD(EVT_OP_INVOKE, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvoke2Func), A, B),#define Invoke4(FUNC, A, B, C) EVT_CMD(EVT_OP_INVOKE, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvoke3Func), A, B, C),#define Invoke5(FUNC, A, B, C, D) EVT_CMD(EVT_OP_INVOKE, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvoke4Func), A, B, C, D),#define Invoke6(FUNC, A, B, C, D, E) EVT_CMD(EVT_OP_INVOKE, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvoke5Func), A, B, C, D, E),#define Invoke7(FUNC, A, B, C, D, E, F) EVT_CMD(EVT_OP_INVOKE, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvoke6Func), A, B, C, D, E, F),
/// Calls a C function with float arguments and no return value.////// The function must return void and take exactly the supplied number of f32 arguments./// The function is called synchronously and cannot block script execution.#define InvokeF(ARGS...) VFUNC(InvokeF, ARGS)#define InvokeF1(FUNC) EVT_CMD(EVT_OP_INVOKEF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvokeF0Func)),#define InvokeF2(FUNC, A) EVT_CMD(EVT_OP_INVOKEF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvokeF1Func), A),#define InvokeF3(FUNC, A, B) EVT_CMD(EVT_OP_INVOKEF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvokeF2Func), A, B),#define InvokeF4(FUNC, A, B, C) EVT_CMD(EVT_OP_INVOKEF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvokeF3Func), A, B, C),#define InvokeF5(FUNC, A, B, C, D) EVT_CMD(EVT_OP_INVOKEF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvokeF4Func), A, B, C, D),#define InvokeF6(FUNC, A, B, C, D, E) EVT_CMD(EVT_OP_INVOKEF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvokeF5Func), A, B, C, D, E),#define InvokeF7(FUNC, A, B, C, D, E, F) EVT_CMD(EVT_OP_INVOKEF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtInvokeF6Func), A, B, C, D, E, F),
/// Marks the beginning of an if statement that only executes if a C function with integer arguments returns nonzero.////// The function must return s32 and take exactly the supplied number of s32 arguments.#define IfEval(ARGS...) VFUNC(IfEval, ARGS)#define IfEval1(FUNC) EVT_CMD(EVT_OP_IF_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate0Func)),#define IfEval2(FUNC, A) EVT_CMD(EVT_OP_IF_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate1Func), A),#define IfEval3(FUNC, A, B) EVT_CMD(EVT_OP_IF_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate2Func), A, B),#define IfEval4(FUNC, A, B, C) EVT_CMD(EVT_OP_IF_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate3Func), A, B, C),#define IfEval5(FUNC, A, B, C, D) EVT_CMD(EVT_OP_IF_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate4Func), A, B, C, D),#define IfEval6(FUNC, A, B, C, D, E) EVT_CMD(EVT_OP_IF_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate5Func), A, B, C, D, E),#define IfEval7(FUNC, A, B, C, D, E, F) EVT_CMD(EVT_OP_IF_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate6Func), A, B, C, D, E, F),
/// Marks the beginning of an if statement that only executes if a C function with integer arguments returns zero.////// The function must return s32 and take exactly the supplied number of s32 arguments.#define IfNotEval(ARGS...) VFUNC(IfNotEval, ARGS)#define IfNotEval1(FUNC) EVT_CMD(EVT_OP_IF_NOT_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate0Func)),#define IfNotEval2(FUNC, A) EVT_CMD(EVT_OP_IF_NOT_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate1Func), A),#define IfNotEval3(FUNC, A, B) EVT_CMD(EVT_OP_IF_NOT_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate2Func), A, B),#define IfNotEval4(FUNC, A, B, C) EVT_CMD(EVT_OP_IF_NOT_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate3Func), A, B, C),#define IfNotEval5(FUNC, A, B, C, D) EVT_CMD(EVT_OP_IF_NOT_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate4Func), A, B, C, D),#define IfNotEval6(FUNC, A, B, C, D, E) EVT_CMD(EVT_OP_IF_NOT_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate5Func), A, B, C, D, E),#define IfNotEval7(FUNC, A, B, C, D, E, F) EVT_CMD(EVT_OP_IF_NOT_EVAL, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicate6Func), A, B, C, D, E, F),
/// Marks the beginning of an if statement that only executes if a C function with float arguments returns nonzero.////// The function must return s32 and take exactly the supplied number of f32 arguments.#define IfEvalF(ARGS...) VFUNC(IfEvalF, ARGS)#define IfEvalF1(FUNC) EVT_CMD(EVT_OP_IF_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF0Func)),#define IfEvalF2(FUNC, A) EVT_CMD(EVT_OP_IF_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF1Func), A),#define IfEvalF3(FUNC, A, B) EVT_CMD(EVT_OP_IF_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF2Func), A, B),#define IfEvalF4(FUNC, A, B, C) EVT_CMD(EVT_OP_IF_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF3Func), A, B, C),#define IfEvalF5(FUNC, A, B, C, D) EVT_CMD(EVT_OP_IF_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF4Func), A, B, C, D),#define IfEvalF6(FUNC, A, B, C, D, E) EVT_CMD(EVT_OP_IF_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF5Func), A, B, C, D, E),#define IfEvalF7(FUNC, A, B, C, D, E, F) EVT_CMD(EVT_OP_IF_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF6Func), A, B, C, D, E, F),
/// Marks the beginning of an if statement that only executes if a C function with float arguments returns zero.////// The function must return s32 and take exactly the supplied number of f32 arguments.#define IfNotEvalF(ARGS...) VFUNC(IfNotEvalF, ARGS)#define IfNotEvalF1(FUNC) EVT_CMD(EVT_OP_IF_NOT_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF0Func)),#define IfNotEvalF2(FUNC, A) EVT_CMD(EVT_OP_IF_NOT_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF1Func), A),#define IfNotEvalF3(FUNC, A, B) EVT_CMD(EVT_OP_IF_NOT_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF2Func), A, B),#define IfNotEvalF4(FUNC, A, B, C) EVT_CMD(EVT_OP_IF_NOT_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF3Func), A, B, C),#define IfNotEvalF5(FUNC, A, B, C, D) EVT_CMD(EVT_OP_IF_NOT_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF4Func), A, B, C, D),#define IfNotEvalF6(FUNC, A, B, C, D, E) EVT_CMD(EVT_OP_IF_NOT_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF5Func), A, B, C, D, E),#define IfNotEvalF7(FUNC, A, B, C, D, E, F) EVT_CMD(EVT_OP_IF_NOT_EVALF, EVT_CHECK_FUNC_SIGNATURE(FUNC, EvtPredicateF6Func), A, B, C, D, E, F),
/// Prints variable name and value#define DebugPrintVar(VAR) EVT_CMD(EVT_OP_DEBUG_PRINT_VAR, VAR),
/// Halt execution after this command#define BreakPoint(TEXT) EVT_CMD(EVT_OP_DEBUG_BREAKPOINT, Ref(TEXT)),
/****** BACKWARD COMPATIBILITY FOR RENAMES ****************************************************************************/
#define BindPadlock(EVT_SOURCE, TRIGGER, COLLIDER_ID, ITEM_LIST, TATTLE_MSG, HAS_INTERACT_PROMPT) \ BindItemPrompt(EVT_SOURCE, TRIGGER, COLLIDER_ID, ITEM_LIST, TATTLE_MSG, HAS_INTERACT_PROMPT)#define ExecGetTID(EVT_SOURCE, OUTVAR, ARGS...) \ ExecGetID(OUTVAR, EVT_SOURCE, ##ARGS)#define KillThread(TID) KillScript(TID)#define IsThreadRunning(TID, OUTVAR) IsScriptRunning(TID, OUTVAR)#define SuspendThread(TID) SuspendScript(TID)#define ResumeThread(TID) ResumeScript(TID)
#define BufRead1(VAR) BufRead(VAR)#define BufRead2(VAR1, VAR2) BufRead(VAR1, VAR2)#define BufRead3(VAR1, VAR2, VAR3) BufRead(VAR1, VAR2, VAR3)#define BufRead4(VAR1, VAR2, VAR3, VAR4) BufRead(VAR1, VAR2, VAR3, VAR4)
#define FBufRead1(VAR) FBufRead(VAR)#define FBufRead2(VAR1, VAR2) FBufRead(VAR1, VAR2)#define FBufRead3(VAR1, VAR2, VAR3) FBufRead(VAR1, VAR2, VAR3)#define FBufRead4(VAR1, VAR2, VAR3, VAR4) FBufRead(VAR1, VAR2, VAR3, VAR4)
/****** VECTOR OPERATIONS *********************************************************************************************/
// expand vector components#define EVT_AS_VEC2(baseVar) (baseVar), (baseVar + 1)#define EVT_AS_VEC3(baseVar) (baseVar), (baseVar + 1), (baseVar + 2)
// extract components from vector#define EVT_VEC_X(baseVar) (baseVar)#define EVT_VEC_Y(baseVar) (baseVar + 1)#define EVT_VEC_Z(baseVar) (baseVar + 2)
#define EVT_VEC2_OP(OPERATION, MUT_BASE, x, y) \ OPERATION(MUT_BASE + 0, x) \ OPERATION(MUT_BASE + 1, y)
#define EVT_VEC3_OP(OPERATION, MUT_BASE, x, y, z) \ OPERATION(MUT_BASE + 0, x) \ OPERATION(MUT_BASE + 1, y) \ OPERATION(MUT_BASE + 2, z)
#define EVT_VEC2_VOP(OPERATION, MUT_BASE, AMT_BASE) \ OPERATION(MUT_BASE + 0, AMT_BASE + 0) \ OPERATION(MUT_BASE + 1, AMT_BASE + 1)
#define EVT_VEC3_VOP(OPERATION, MUT_BASE, AMT_BASE) \ OPERATION(MUT_BASE + 0, AMT_BASE + 0) \ OPERATION(MUT_BASE + 1, AMT_BASE + 1) \ OPERATION(MUT_BASE + 2, AMT_BASE + 2)
#define EVT_VEC2I_SET(baseVar, x, y) EVT_VEC2_OP(Set, baseVar, x, y)#define EVT_VEC2F_SET(baseVar, x, y) EVT_VEC2_OP(SetF, baseVar, x, y)#define EVT_VEC3I_SET(baseVar, x, y, z) EVT_VEC3_OP(Set, baseVar, x, y, z)#define EVT_VEC3F_SET(baseVar, x, y, z) EVT_VEC3_OP(SetF, baseVar, x, y, z)
#define EVT_VEC2I_VSET(baseVar, baseSrc) EVT_VEC2_VOP(Set, baseVar, baseSrc)#define EVT_VEC2F_VSET(baseVar, baseSrc) EVT_VEC2_VOP(SetF, baseVar, baseSrc)#define EVT_VEC3I_VSET(baseVar, baseSrc) EVT_VEC3_VOP(Set, baseVar, baseSrc)#define EVT_VEC3F_VSET(baseVar, baseSrc) EVT_VEC3_VOP(SetF, baseVar, baseSrc)
#define EVT_VEC2I_ADD(baseVar, x, y) EVT_VEC2_OP(Add, baseVar, x, y)#define EVT_VEC2F_ADD(baseVar, x, y) EVT_VEC2_OP(AddF, baseVar, x, y)#define EVT_VEC3I_ADD(baseVar, x, y, z) EVT_VEC3_OP(Add, baseVar, x, y, z)#define EVT_VEC3F_ADD(baseVar, x, y, z) EVT_VEC3_OP(AddF, baseVar, x, y, z)
#define EVT_VEC2I_VADD(baseVar, baseAmt) EVT_VEC2_VOP(Add, baseVar, baseAmt)#define EVT_VEC2F_VADD(baseVar, baseAmt) EVT_VEC2_VOP(AddF, baseVar, baseAmt)#define EVT_VEC3I_VADD(baseVar, baseAmt) EVT_VEC3_VOP(Add, baseVar, baseAmt)#define EVT_VEC3F_VADD(baseVar, baseAmt) EVT_VEC3_VOP(AddF, baseVar, baseAmt)
#define EVT_VEC2I_SUB(baseVar, x, y) EVT_VEC2_OP(Sub, baseVar, x, y)#define EVT_VEC2F_SUB(baseVar, x, y) EVT_VEC2_OP(SubF, baseVar, x, y)#define EVT_VEC3I_SUB(baseVar, x, y, z) EVT_VEC3_OP(Sub, baseVar, x, y, z)#define EVT_VEC3F_SUB(baseVar, x, y, z) EVT_VEC3_OP(SubF, baseVar, x, y, z)
#define EVT_VEC2I_VSUB(baseVar, baseAmt) EVT_VEC2_VOP(Sub, baseVar, baseAmt)#define EVT_VEC2F_VSUB(baseVar, baseAmt) EVT_VEC2_VOP(SubF, baseVar, baseAmt)#define EVT_VEC3I_VSUB(baseVar, baseAmt) EVT_VEC3_VOP(Sub, baseVar, baseAmt)#define EVT_VEC3F_VSUB(baseVar, baseAmt) EVT_VEC3_VOP(SubF, baseVar, baseAmt)
/****** COMMON SCRIPTS ************************************************************************************************/
#define IfTrue(b) IfNe(b, 0)#define IfFalse(b) IfEq(b, 0)
#define EVT_EXIT_WALK(walkDistance, exitIdx, map, entryIdx) \ { \ SetGroup(EVT_GROUP_EXIT_MAP) \ Call(UseExitHeading, walkDistance, exitIdx) \ Exec(ExitWalk) \ Call(GotoMap, Ref(map), entryIdx) \ Wait(100) \ Return \ End \ }
#define EVT_EXIT_SINGLE_DOOR(exitIdx, map, entryIdx, colliderID, modelID, swingDir) \ { \ SetGroup(EVT_GROUP_EXIT_MAP) \ Call(DisablePlayerInput, true) \ Set(LVar0, exitIdx) \ Set(LVar1, colliderID) \ Set(LVar2, modelID) \ Set(LVar3, swingDir) \ Exec(ExitSingleDoor) \ Wait(17) \ Call(GotoMap, Ref(map), entryIdx) \ Wait(100) \ Return \ End \ }
#define EVT_EXIT_SINGLE_DOOR_SET_SOUNDS(exitIdx, map, entryIdx, colliderID, modelID, swingDir, sounds) \ { \ SetGroup(EVT_GROUP_EXIT_MAP) \ Call(DisablePlayerInput, true) \ Call(UseDoorSounds, sounds) \ Set(LVar0, exitIdx) \ Set(LVar1, colliderID) \ Set(LVar2, modelID) \ Set(LVar3, swingDir) \ Exec(ExitSingleDoor) \ Wait(17) \ Call(GotoMap, Ref(map), entryIdx) \ Wait(100) \ Return \ End \ }
#define EVT_EXIT_SPLIT_SINGLE_DOOR(exitIdx, map, entryIdx, colliderID, topModelID, bottomModelID, swingDir) \ { \ SetGroup(EVT_GROUP_EXIT_MAP) \ Call(DisablePlayerInput, true) \ Set(LVar0, exitIdx) \ Set(LVar1, colliderID) \ Set(LVar2, topModelID) \ Set(LVar4, bottomModelID) \ Set(LVar3, swingDir) \ Exec(ExitSplitSingleDoor) \ Wait(17) \ Call(GotoMap, Ref(map), entryIdx) \ Wait(100) \ Return \ End \ }
#define EVT_EXIT_DOUBLE_DOOR(exitIdx, map, entryIdx, colliderID, leftDoorModelID, rightDoorModelID) \ { \ SetGroup(EVT_GROUP_EXIT_MAP) \ Call(DisablePlayerInput, true) \ Set(LVar0, exitIdx) \ Set(LVar1, colliderID) \ Set(LVar2, leftDoorModelID) \ Set(LVar3, rightDoorModelID) \ Exec(ExitDoubleDoor) \ Wait(17) \ Call(GotoMap, Ref(map), entryIdx) \ Wait(100) \ Return \ End \ }
#define EVT_EXIT_DOUBLE_DOOR_SET_SOUNDS(exitIdx, map, entryIdx, colliderID, leftDoorModelID, rightDoorModelID, sounds) \ { \ SetGroup(EVT_GROUP_EXIT_MAP) \ Call(DisablePlayerInput, true) \ Call(UseDoorSounds, sounds) \ Set(LVar0, exitIdx) \ Set(LVar1, colliderID) \ Set(LVar2, leftDoorModelID) \ Set(LVar3, rightDoorModelID) \ Exec(ExitDoubleDoor) \ Wait(17) \ Call(GotoMap, Ref(map), entryIdx) \ Wait(100) \ Return \ End \ }
/// Enable camera using standard parameters for clip distances and FOV./// `r`, `g`, and `b` are the background color./// @param r/// @param g/// @param b#define EVT_SETUP_CAMERA_DEFAULT(r, g, b) \ Call(SetCamPerspective, CAM_DEFAULT, CAM_UPDATE_FROM_ZONE, 25, 16, 4096) \ Call(SetCamBGColor, CAM_DEFAULT, r, g, b) \ Call(SetCamEnabled, CAM_DEFAULT, true)
/// Enable camera using standard parameters for clip distances and FOV with LeadPlayer disabled./// `r`, `g`, and `b` are the background color./// @param r/// @param g/// @param b#define EVT_SETUP_CAMERA_NO_LEAD(r, g, b) \ Call(SetCamPerspective, CAM_DEFAULT, CAM_UPDATE_FROM_ZONE, 25, 16, 4096) \ Call(SetCamBGColor, CAM_DEFAULT, r, g, b) \ Call(SetCamLeadPlayer, CAM_DEFAULT, false) \ Call(SetCamEnabled, CAM_DEFAULT, true)
/// Enable camera for `AREA_MIM` using a closer far clip distance and appropriate background color#define EVT_SETUP_CAMERA_MIM() \ Call(SetCamPerspective, CAM_DEFAULT, CAM_UPDATE_FROM_ZONE, 25, 16, 650) \ Call(SetCamBGColor, CAM_DEFAULT, 0, 0, 0) \ Call(SetCamLeadPlayer, CAM_DEFAULT, false) \ Call(SetCamEnabled, CAM_DEFAULT, true)
// allow macros with variable number of arguments// see https://stackoverflow.com/questions/11761703/overloading-macro-on-number-of-arguments// solution provided by R1tschY and edited by Gabriel Staples#define __NARG__(args...) \ __NARG_I_(args,__RSEQ_N())#define __NARG_I_(args...) \ __ARG_N(args)#define __ARG_N( \ _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, \ _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, \ _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, N, ... \) N#define __RSEQ_N() \ 63,62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ 39,38,37,36,35,34,33,32,31,30, \ 29,28,27,26,25,24,23,22,21,20, \ 19,18,17,16,15,14,13,12,11,10, \ 9,8,7,6,5,4,3,2,1,0#define _VFUNC_(name, n) name##n#define _VFUNC(name, n) _VFUNC_(name, n)#define VFUNC(func, args...) _VFUNC(func, __NARG__(args)) (args)
#define PlayEffect(effect, args...) Call(PlayEffect_impl, effect, ##args)
#ifdef _LANGUAGE_C_PLUS_PLUS} // extern "C"#endif
#endif