mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-05-07 17:31:41 +00:00
Merge branch 'dev' into deadzone
This commit is contained in:
commit
4362ae61fe
24 changed files with 182 additions and 88 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 --
|
||||
-----------
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
BIN
mods/sm74/actors/mad_toad_geo.bin
Normal file
BIN
mods/sm74/actors/mad_toad_geo.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue