Merge branch 'dev' into deadzone

This commit is contained in:
abcpea 2026-02-13 21:26:34 +11:00
commit 4362ae61fe
24 changed files with 182 additions and 88 deletions

View file

@ -3276,7 +3276,7 @@ PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT = 10
PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE = -5
--- @type integer
PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY = 0x0000FFFF
PVP_ATTACK_KNOCKBACK_ACTION_ARG = 0x10000
--- @type integer
INT_STATUS_ATTACK_MASK = 0x000000FF

View file

@ -97,11 +97,6 @@ gServerSettings = {}
--- Struct containing the settings for Nametags
gNametagsSettings = {}
--- @type Camera
--- Struct contaning camera fields
--- - This camera is the same as `gMarioStates[i].area.camera` or `gCurrentArea.camera`
gCamera = {}
-----------
-- hooks --
-----------

View file

@ -597,5 +597,11 @@ enum BehaviorId get_id_from_behavior_name(const char* name) {
return i;
}
}
for (int i = 0; i < gHookedBehaviorsCount; i++) {
struct LuaHookedBehavior *hooked = &gHookedBehaviors[i];
if (hooked->bhvName && !strcmp(name, hooked->bhvName)) {
return hooked->overrideId;
}
}
return id_bhv_max_count;
}

View file

@ -2449,6 +2449,48 @@ static void ParseBehaviorScriptSymbol(GfxData *aGfxData, DataNode<BehaviorScript
PrintDataError(" ERROR: Unknown behavior symbol: %s", _Symbol.begin());
}
static bool DynOS_Bhv_CheckCommands(const BehaviorScript *aBhv, const Array<BehaviorScript> &aCommands) {
u8 bhvCommand = (*aBhv >> 24) & 0xFF;
for (const auto &commandToCheck : aCommands) {
if (bhvCommand == ((commandToCheck >> 24) & 0xFF)) {
return true;
}
}
return false;
}
static bool DynOS_Bhv_Validate(GfxData *aGfxData, const DataNode<BehaviorScript> *aNode) {
// 1st command must be BEGIN
if (!DynOS_Bhv_CheckCommands(aNode->mData + 0, { BEGIN(0) })) {
PrintDataError(" ERROR: Validation failed for behavior %s: First command of the script must be BEGIN.", aNode->mName.begin());
return false;
}
// 2nd command must be ID
if (!DynOS_Bhv_CheckCommands(aNode->mData + 1, { ID(0) })) {
PrintDataError(" ERROR: Validation failed for behavior %s: Second command of the script must be ID.", aNode->mName.begin());
return false;
}
// Last command must be a terminating command
if (!DynOS_Bhv_CheckCommands(aNode->mData + aNode->mSize - 1, {
CALL(0),
RETURN(),
GOTO(0),
END_LOOP(),
BREAK(),
DEACTIVATE(),
CALL_EXT(0),
GOTO_EXT(0),
})) {
PrintDataError(" ERROR: Validation failed for behavior %s: Last command of the script must be one of:\n CALL, RETURN, GOTO, END_LOOP, BREAK, DEACTIVATE", aNode->mName.begin());
return false;
}
return true;
}
DataNode<BehaviorScript> *DynOS_Bhv_Parse(GfxData *aGfxData, DataNode<BehaviorScript> *aNode, bool aDisplayPercent) {
if (aNode->mData) return aNode;
@ -2460,9 +2502,13 @@ DataNode<BehaviorScript> *DynOS_Bhv_Parse(GfxData *aGfxData, DataNode<BehaviorSc
ParseBehaviorScriptSymbol(aGfxData, aNode, _Head, _TokenIndex, _SwitchNodes);
if (aDisplayPercent && aGfxData->mErrorCount == 0) { PrintNoNewLine("%3d%%\b\b\b\b", (s32) (_TokenIndex * 100) / aNode->mTokens.Count()); }
}
if (aDisplayPercent && aGfxData->mErrorCount == 0) { Print("100%%"); }
aNode->mSize = (u32)(_Head - aNode->mData);
aNode->mLoadIndex = aGfxData->mLoadIndex++;
// Validate behavior script
DynOS_Bhv_Validate(aGfxData, aNode);
if (aDisplayPercent && aGfxData->mErrorCount == 0) { Print("100%%"); }
return aNode;
}
@ -2592,6 +2638,12 @@ static DataNode<BehaviorScript> *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat
}
}
// Validate it
if (!DynOS_Bhv_Validate(aGfxData, _Node)) {
Delete(_Node);
return NULL;
}
// Add it
if (aGfxData != NULL) {
aGfxData->mBehaviorScripts.Add(_Node);

View file

@ -1459,7 +1459,7 @@
- ATTACK_FROM_BELOW
- PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT
- PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE
- PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY
- PVP_ATTACK_KNOCKBACK_ACTION_ARG
- INT_STATUS_ATTACK_MASK
- INT_STATUS_HOOT_GRABBED_BY_MARIO
- INT_STATUS_MARIO_UNK1

View file

@ -557,7 +557,7 @@ enum BehaviorId get_id_from_vanilla_behavior(const BehaviorScript* behavior);
const BehaviorScript* get_behavior_from_id(enum BehaviorId id);
/* |description|Gets a behavior name from a behavior ID (bhvMyGreatMODCustom004)|descriptionEnd| */
const char* get_behavior_name_from_id(enum BehaviorId id);
/* |description|gets a behavior ID from a behavior name|descriptionEnd| */
/* |description|Gets a behavior ID from a behavior name|descriptionEnd| */
enum BehaviorId get_id_from_behavior_name(const char* name);
#endif

Binary file not shown.

Binary file not shown.

View file

@ -52,6 +52,9 @@ function check_mario_attacking(obj, mario)
if mario.action == ACT_WALL_KICK_AIR then
return 2
end
if (mario.action & ACT_FLAG_CUSTOM_ACTION ~= 0) and (mario.action & ACT_FLAG_ATTACKING ~= 0) then
return 2
end
end
end
@ -121,4 +124,4 @@ function object_drop_to_floor(obj)
local floorHeight = find_floor_height(x, y + 200, z)
obj.oPosY = floorHeight
obj.oMoveFlags = (obj.oMoveFlags | OBJ_MOVE_ON_GROUND)
end
end

View file

@ -987,6 +987,11 @@ static s32 bhv_cmd_call_native_ext(void) {
}
const char *funcStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(1));
if (!funcStr) {
LOG_LUA("Could not retrieve function name from behavior command.");
gCurBhvCommand += 2;
return BHV_PROC_CONTINUE;
}
gSmLuaConvertSuccess = true;
LuaFunction funcRef = smlua_get_function_mod_variable(modIndex, funcStr);

View file

@ -162,7 +162,7 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
closest_point_to_triangle(surf, src, cPos);
// Exclude triangles where y isn't inside of it
if (cPos[1] < surf->lowerY || cPos[1] > surf->upperY) { continue; }
if (fabs(cPos[1] - y) > 1) { continue; }
// Figure out normal
f32 dX = src[0] - cPos[0];

View file

@ -643,7 +643,9 @@ static u32 unused_determine_knockback_action(struct MarioState *m) {
return bonkAction;
}
u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
u32 determine_knockback_action(struct MarioState *m, RET bool *isPlayerAttack) {
*isPlayerAttack = false;
if (!m) { return 0; }
if (m->interactObj == NULL) {
return sForwardKnockbackActions[0][0];
@ -739,6 +741,7 @@ u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
m->knockbackTimer = hasBeenPunched ? PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE : PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT;
#undef IF_REVAMPED_PVP
m->faceAngle[1] = m->interactObj->oFaceAngleYaw + (sign == 1.0f ? 0 : 0x8000);
*isPlayerAttack = true;
}
return bonkAction;
@ -870,7 +873,10 @@ u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) {
}
update_mario_sound_and_camera(m);
return drop_and_set_mario_action(m, determine_knockback_action(m, o->oDamageOrCoinValue), damage);
bool isPlayerAttack = false;
u32 knockbackAction = determine_knockback_action(m, &isPlayerAttack);
return drop_and_set_mario_action(m, knockbackAction, damage | (isPlayerAttack ? PVP_ATTACK_KNOCKBACK_ACTION_ARG : 0));
}
return FALSE;
@ -1724,8 +1730,9 @@ u32 interact_snufit_bullet(struct MarioState *m, UNUSED u32 interactType, struct
play_character_sound(m, CHAR_SOUND_ATTACKED);
update_mario_sound_and_camera(m);
return drop_and_set_mario_action(m, determine_knockback_action(m, o->oDamageOrCoinValue),
o->oDamageOrCoinValue);
bool isPlayerAttack = false;
u32 knockbackAction = determine_knockback_action(m, &isPlayerAttack);
return drop_and_set_mario_action(m, knockbackAction, o->oDamageOrCoinValue | (isPlayerAttack ? PVP_ATTACK_KNOCKBACK_ACTION_ARG : 0));
}
}

View file

@ -101,7 +101,7 @@ enum InteractionFlag {
#define PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT 10
#define PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE -5
#define PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY 0x0000FFFF
#define PVP_ATTACK_KNOCKBACK_ACTION_ARG 0x10000
#define INT_STATUS_ATTACK_MASK 0x000000FF

View file

@ -1043,6 +1043,29 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio
case ACT_JUMP_KICK:
m->vel[1] = 20.0f;
break;
// Set forward vel to a predefined value for non-player knockbacks
case ACT_BACKWARD_AIR_KB:
case ACT_HARD_BACKWARD_AIR_KB:
if (!(actionArg & PVP_ATTACK_KNOCKBACK_ACTION_ARG)) {
mario_set_forward_vel(m, -16.0f);
}
break;
case ACT_FORWARD_AIR_KB:
case ACT_HARD_FORWARD_AIR_KB:
if (!(actionArg & PVP_ATTACK_KNOCKBACK_ACTION_ARG)) {
mario_set_forward_vel(m, 16.0f);
}
break;
case ACT_THROWN_BACKWARD:
case ACT_THROWN_FORWARD:
case ACT_SOFT_BONK:
if (!(actionArg & PVP_ATTACK_KNOCKBACK_ACTION_ARG)) {
mario_set_forward_vel(m, m->forwardVel); // needed to update velocities
}
break;
}
m->peakHeight = m->pos[1];
@ -2221,6 +2244,7 @@ void init_single_mario(struct MarioState* m) {
m->heldObj = NULL;
m->heldByObj = NULL;
m->interactObj = NULL;
m->riddenObj = NULL;
m->usedObj = NULL;
m->bubbleObj = NULL;

View file

@ -57,7 +57,7 @@ depending on whether Mario's forward velocity is high enough to be considered a
|descriptionEnd| */
void play_knockback_sound(struct MarioState *m) {
if (!m) { return; }
if (m->actionArg == 0 && (m->forwardVel <= -28.0f || m->forwardVel >= 28.0f)) {
if ((m->actionArg & ~PVP_ATTACK_KNOCKBACK_ACTION_ARG) == 0 && (m->forwardVel <= -28.0f || m->forwardVel >= 28.0f)) {
play_character_sound_if_no_flag(m, CHAR_SOUND_DOH, MARIO_MARIO_SOUND_PLAYED);
} else {
play_character_sound_if_no_flag(m, CHAR_SOUND_UH, MARIO_MARIO_SOUND_PLAYED);
@ -1236,13 +1236,8 @@ u32 common_air_knockback_step(struct MarioState *m, u32 landAction, u32 hardFall
if (!m) { return 0; }
u32 stepResult;
if (m->knockbackTimer == 0) {
if (m->interactObj == NULL || !(m->interactObj->oInteractType & INTERACT_PLAYER)) {
mario_set_forward_vel(m, speed);
}
} else if (m->knockbackTimer < 0) {
// do nothing
} else {
// Refresh knockbackTimer
if (m->knockbackTimer > 0) {
m->knockbackTimer = PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT;
}
@ -1356,7 +1351,7 @@ s32 act_hard_forward_air_kb(struct MarioState *m) {
s32 act_thrown_backward(struct MarioState *m) {
if (!m) { return 0; }
u32 landAction;
if (m->actionArg != 0) {
if ((m->actionArg & ~PVP_ATTACK_KNOCKBACK_ACTION_ARG) != 0) {
landAction = ACT_HARD_BACKWARD_GROUND_KB;
} else {
landAction = ACT_BACKWARD_GROUND_KB;
@ -1375,7 +1370,7 @@ s32 act_thrown_forward(struct MarioState *m) {
s16 pitch;
u32 landAction;
if (m->actionArg != 0) {
if ((m->actionArg & ~PVP_ATTACK_KNOCKBACK_ACTION_ARG) != 0) {
landAction = ACT_HARD_FORWARD_GROUND_KB;
} else {
landAction = ACT_FORWARD_GROUND_KB;

View file

@ -1775,12 +1775,13 @@ Handles knockback on the ground (getting hit while on the ground) with shared lo
s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2, s32 arg3, s32 arg4) {
if (!m) { return 0; }
s32 animFrame;
s32 damage = arg4 & ~PVP_ATTACK_KNOCKBACK_ACTION_ARG;
if (arg3) {
play_mario_heavy_landing_sound_once(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND);
}
if (arg4 > 0) {
if (damage > 0) {
play_character_sound_if_no_flag(m, CHAR_SOUND_ATTACKED, MARIO_MARIO_SOUND_PLAYED);
} else {
#ifdef VERSION_JP
@ -1790,18 +1791,18 @@ s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2
#endif
}
if (m->knockbackTimer == 0) {
if (m->interactObj == NULL || !(m->interactObj->oInteractType & INTERACT_PLAYER)) {
if (m->forwardVel > 32.0f) {
m->forwardVel = 32.0f;
}
if (m->forwardVel < -32.0f) {
m->forwardVel = -32.0f;
}
// Cap speed if it's not a PVP attack
if (!(arg4 & PVP_ATTACK_KNOCKBACK_ACTION_ARG)) {
if (m->forwardVel > 32.0f) {
m->forwardVel = 32.0f;
}
} else if (m->knockbackTimer < 0) {
// do nothing
} else {
if (m->forwardVel < -32.0f) {
m->forwardVel = -32.0f;
}
}
// Refresh knockbackTimer
if (m->knockbackTimer > 0) {
m->knockbackTimer = PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT;
}
@ -1824,7 +1825,7 @@ s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2
if (m->health < 0x100) {
set_mario_action(m, ACT_STANDING_DEATH, 0);
} else {
if (arg4 > 0) {
if (damage > 0) {
m->invincTimer = 30;
}
set_mario_action(m, ACT_IDLE, 0);

View file

@ -769,13 +769,13 @@ static struct PlayerColor geo_mario_get_player_color(const struct PlayerPalette
for (s32 part = 0; part != PLAYER_PART_MAX; ++part) {
color.parts[part] = (Lights1) gdSPDefLights1(
// Shadow
palette->parts[part][0] * bodyState->shadeR / 255.0f,
palette->parts[part][1] * bodyState->shadeG / 255.0f,
palette->parts[part][2] * bodyState->shadeB / 255.0f,
min(palette->parts[part][0] * bodyState->shadeR / 255.0f, 255),
min(palette->parts[part][1] * bodyState->shadeG / 255.0f, 255),
min(palette->parts[part][2] * bodyState->shadeB / 255.0f, 255),
// Light
palette->parts[part][0] * bodyState->lightR / 255.0f,
palette->parts[part][1] * bodyState->lightG / 255.0f,
palette->parts[part][2] * bodyState->lightB / 255.0f,
min(palette->parts[part][0] * bodyState->lightR / 255.0f, 255),
min(palette->parts[part][1] * bodyState->lightG / 255.0f, 255),
min(palette->parts[part][2] * bodyState->lightB / 255.0f, 255),
0x28 + bodyState->lightingDirX * 127.0f, 0x28 + bodyState->lightingDirY * 127.0f, 0x28 + bodyState->lightingDirZ * 127.0f
);
}

View file

@ -331,6 +331,9 @@ struct Object *allocate_object(struct ObjectNode *objList) {
vec3s_zero(obj->header.gfx.angle);
obj->header.gfx.throwMatrix = NULL;
obj->header.gfx.inited = false;
obj->header.gfx.disableAutomaticShadowPos = false;
obj->header.gfx.shadowInvisible = false;
obj->header.gfx.skipInViewCheck = false;
obj->coopFlags = 0;
obj->hookRender = 0;

View file

@ -1653,7 +1653,7 @@ char gSmluaConstants[] = ""
"ATTACK_FROM_BELOW=6\n"
"PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT=10\n"
"PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE=-5\n"
"PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY=0x0000FFFF\n"
"PVP_ATTACK_KNOCKBACK_ACTION_ARG=0x10000\n"
"INT_STATUS_ATTACK_MASK=0x000000FF\n"
"INT_STATUS_HOOT_GRABBED_BY_MARIO=(1 << 0)\n"
"INT_STATUS_MARIO_UNK1=(1 << 1)\n"

View file

@ -398,30 +398,13 @@ u32 smlua_get_action_interaction_type(struct MarioState* m) {
// hooked behaviors //
//////////////////////
struct LuaHookedBehavior {
u32 behaviorId;
u32 overrideId;
u32 originalId;
BehaviorScript *behavior;
const BehaviorScript* originalBehavior;
const char* bhvName;
int initReference;
int loopReference;
bool replace;
bool luaBehavior;
struct Mod* mod;
struct ModFile* modFile;
};
#define MAX_HOOKED_BEHAVIORS 1024
static struct LuaHookedBehavior sHookedBehaviors[MAX_HOOKED_BEHAVIORS] = { 0 };
static int sHookedBehaviorsCount = 0;
struct LuaHookedBehavior gHookedBehaviors[MAX_HOOKED_BEHAVIORS] = { 0 };
int gHookedBehaviorsCount = 0;
enum BehaviorId smlua_get_original_behavior_id(const BehaviorScript* behavior) {
enum BehaviorId id = get_id_from_behavior(behavior);
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &sHookedBehaviors[i];
for (int i = 0; i < gHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &gHookedBehaviors[i];
if (hooked->behavior == behavior) {
id = hooked->overrideId;
}
@ -443,8 +426,8 @@ const BehaviorScript* smlua_get_hooked_behavior_from_id(enum BehaviorId id, bool
lua_State *L = gLuaState;
if (L == NULL) { return NULL; }
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &sHookedBehaviors[i];
for (int i = 0; i < gHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &gHookedBehaviors[i];
if (hooked->behaviorId != id && hooked->overrideId != id) { continue; }
if (returnOriginal && !hooked->replace) { return hooked->originalBehavior; }
return hooked->behavior;
@ -457,8 +440,8 @@ bool smlua_is_behavior_hooked(const BehaviorScript *behavior) {
if (L == NULL) { return false; }
enum BehaviorId id = get_id_from_behavior(behavior);
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior *hooked = &sHookedBehaviors[i];
for (int i = 0; i < gHookedBehaviorsCount; i++) {
struct LuaHookedBehavior *hooked = &gHookedBehaviors[i];
if (hooked->behaviorId != id && hooked->overrideId != id) { continue; }
return hooked->luaBehavior;
}
@ -467,8 +450,8 @@ bool smlua_is_behavior_hooked(const BehaviorScript *behavior) {
}
const char* smlua_get_name_from_hooked_behavior_id(enum BehaviorId id) {
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior *hooked = &sHookedBehaviors[i];
for (int i = 0; i < gHookedBehaviorsCount; i++) {
struct LuaHookedBehavior *hooked = &gHookedBehaviors[i];
if (hooked->behaviorId != id && hooked->overrideId != id) { continue; }
return hooked->bhvName;
}
@ -476,7 +459,7 @@ const char* smlua_get_name_from_hooked_behavior_id(enum BehaviorId id) {
}
int smlua_hook_custom_bhv(BehaviorScript *bhvScript, const char *bhvName) {
if (sHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
if (gHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
LOG_ERROR("Hooked behaviors exceeded maximum references!");
return 0;
}
@ -490,8 +473,8 @@ int smlua_hook_custom_bhv(BehaviorScript *bhvScript, const char *bhvName) {
u8 newBehavior = originalBehaviorId >= id_bhv_max_count;
struct LuaHookedBehavior *hooked = &sHookedBehaviors[sHookedBehaviorsCount];
u16 customBehaviorId = (sHookedBehaviorsCount & 0xFFFF) | LUA_BEHAVIOR_FLAG;
struct LuaHookedBehavior *hooked = &gHookedBehaviors[gHookedBehaviorsCount];
u16 customBehaviorId = (gHookedBehaviorsCount & 0xFFFF) | LUA_BEHAVIOR_FLAG;
hooked->behavior = bhvScript;
hooked->behavior[1] = (BehaviorScript)BC_B0H(0x39, customBehaviorId); // This is ID(customBehaviorId)
hooked->behaviorId = customBehaviorId;
@ -506,7 +489,7 @@ int smlua_hook_custom_bhv(BehaviorScript *bhvScript, const char *bhvName) {
hooked->mod = gLuaActiveMod;
hooked->modFile = gLuaActiveModFile;
sHookedBehaviorsCount++;
gHookedBehaviorsCount++;
// We want to push the behavior into the global LUA state. So mods can access it.
// It's also used for some things that would normally access a LUA behavior instead.
@ -531,7 +514,7 @@ int smlua_hook_behavior(lua_State* L) {
int paramCount = lua_gettop(L);
if (sHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
if (gHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
LOG_LUA_LINE("Hooked behaviors exceeded maximum references!");
return 0;
}
@ -634,8 +617,8 @@ int smlua_hook_behavior(lua_State* L) {
bhvName = sGenericBhvName;
}
struct LuaHookedBehavior* hooked = &sHookedBehaviors[sHookedBehaviorsCount];
u16 customBehaviorId = (sHookedBehaviorsCount & 0xFFFF) | LUA_BEHAVIOR_FLAG;
struct LuaHookedBehavior* hooked = &gHookedBehaviors[gHookedBehaviorsCount];
u16 customBehaviorId = (gHookedBehaviorsCount & 0xFFFF) | LUA_BEHAVIOR_FLAG;
hooked->behavior = calloc(4, sizeof(BehaviorScript));
hooked->behavior[0] = (BehaviorScript)BC_BB(0x00, objectList); // This is BEGIN(objectList)
hooked->behavior[1] = (BehaviorScript)BC_B0H(0x39, customBehaviorId); // This is ID(customBehaviorId)
@ -653,7 +636,7 @@ int smlua_hook_behavior(lua_State* L) {
hooked->mod = gLuaActiveMod;
hooked->modFile = gLuaActiveModFile;
sHookedBehaviorsCount++;
gHookedBehaviorsCount++;
// We want to push the behavior into the global LUA state. So mods can access it.
// It's also used for some things that would normally access a LUA behavior instead.
@ -670,8 +653,8 @@ int smlua_hook_behavior(lua_State* L) {
bool smlua_call_behavior_hook(const BehaviorScript** behavior, struct Object* object, bool before) {
lua_State* L = gLuaState;
if (L == NULL) { return false; }
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &sHookedBehaviors[i];
for (int i = 0; i < gHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &gHookedBehaviors[i];
// find behavior
if (object->behavior != hooked->behavior) {
@ -1518,8 +1501,8 @@ void smlua_hook_replace_function_references(lua_State* L, int oldReference, int
smlua_hook_replace_function_reference(L, &hooked->reference, oldReference, newReference);
}
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &sHookedBehaviors[i];
for (int i = 0; i < gHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &gHookedBehaviors[i];
smlua_hook_replace_function_reference(L, &hooked->initReference, oldReference, newReference);
smlua_hook_replace_function_reference(L, &hooked->loopReference, oldReference, newReference);
}
@ -1574,8 +1557,8 @@ void smlua_clear_hooks(void) {
}
gHookedModMenuElementsCount = 0;
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &sHookedBehaviors[i];
for (int i = 0; i < gHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &gHookedBehaviors[i];
// If this is NULL. We can't do anything with it.
if (hooked->behavior != NULL) {
@ -1601,7 +1584,7 @@ void smlua_clear_hooks(void) {
hooked->mod = NULL;
hooked->modFile = NULL;
}
sHookedBehaviorsCount = 0;
gHookedBehaviorsCount = 0;
memset(gLuaMarioActionIndex, 0, sizeof(gLuaMarioActionIndex));
}

View file

@ -127,6 +127,26 @@ extern u32 gLuaMarioActionIndex[];
extern struct LuaHookedModMenuElement gHookedModMenuElements[];
extern int gHookedModMenuElementsCount;
#define MAX_HOOKED_BEHAVIORS 1024
struct LuaHookedBehavior {
u32 behaviorId;
u32 overrideId;
u32 originalId;
BehaviorScript *behavior;
const BehaviorScript* originalBehavior;
const char* bhvName;
int initReference;
int loopReference;
bool replace;
bool luaBehavior;
struct Mod* mod;
struct ModFile* modFile;
};
extern int gHookedBehaviorsCount;
extern struct LuaHookedBehavior gHookedBehaviors[MAX_HOOKED_BEHAVIORS];
#define OUTPUT
#define SMLUA_EVENT_HOOK(hookEventType, hookReturn, ...) bool smlua_call_event_hooks_##hookEventType(__VA_ARGS__);
#include "smlua_hook_events.inl"