sm64coopdx/mods/flood/misc.lua

210 lines
7.1 KiB
Lua

if unsupported then return end
E_MODEL_FLOOD = smlua_model_util_get_id("flood_geo")
E_MODEL_CTT = smlua_model_util_get_id("ctt_geo") -- easter egg in the distance
E_MODEL_LAUNCHPAD = smlua_model_util_get_id("launchpad_geo")
local COL_LAUNCHPAD = smlua_collision_util_get("launchpad_collision")
-- localize functions to improve performance
local get_environment_region,set_environment_region,set_override_far,cur_obj_scale,cur_obj_init_animation,bhv_pole_base_loop,nearest_mario_state_to_object,play_mario_jump_sound,set_mario_action,spawn_non_sync_object,mario_set_forward_vel,vec3f_set,load_object_collision_model,obj_mark_for_deletion,network_is_server,obj_check_hitbox_overlap,obj_has_behavior_id = get_environment_region,set_environment_region,set_override_far,cur_obj_scale,cur_obj_init_animation,bhv_pole_base_loop,nearest_mario_state_to_object,play_mario_jump_sound,set_mario_action,spawn_non_sync_object,mario_set_forward_vel,vec3f_set,load_object_collision_model,obj_mark_for_deletion,network_is_server,obj_check_hitbox_overlap,obj_has_behavior_id
--- @param o Object
local function bhv_water_init(o)
o.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
o.oAnimState = gLevels[gGlobalSyncTable.level].type
o.header.gfx.skipInViewCheck = true
o.oFaceAnglePitch = 0
o.oFaceAngleRoll = 0
end
--- @param o Object
local function bhv_water_loop(o)
o.oPosY = gGlobalSyncTable.waterLevel
if game == GAME_VANILLA and gGlobalSyncTable.level ~= LEVEL_SSL then
o.oFaceAngleYaw = o.oTimer * 5 * (gLevels[gNetworkPlayers[0].currLevelNum].speed or 1)
end
if game == GAME_VANILLA and gNetworkPlayers[0].currLevelNum ~= LEVEL_WDW and gNetworkPlayers[0].currLevelNum ~= LEVEL_HMC then
for i = 1, 3 do
if get_environment_region(i) < gGlobalSyncTable.waterLevel then
set_environment_region(i, -20000)
end
end
else
set_environment_region(1, -20000)
end
end
id_bhvWater = hook_behavior(nil, OBJ_LIST_SURFACE, true, bhv_water_init, bhv_water_loop)
--- @param o Object
local function bhv_custom_static_object_init(o)
o.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
o.header.gfx.skipInViewCheck = true
set_override_far(50000)
end
id_bhvCustomStaticObject = hook_behavior(nil, OBJ_LIST_LEVEL, true, bhv_custom_static_object_init, nil)
--- @param o Object
local function bhv_final_star_init(o)
o.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
o.hitboxRadius = 160
o.hitboxHeight = 100
cur_obj_scale(2)
end
--- @param o Object
local function bhv_final_star_loop(o)
o.oFaceAngleYaw = o.oFaceAngleYaw + 0x800
end
id_bhvFinalStar = hook_behavior(nil, OBJ_LIST_GENACTOR, true, bhv_final_star_init, bhv_final_star_loop)
--- @param o Object
local function bhv_flood_flag_init(o)
o.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
o.oInteractType = INTERACT_POLE
o.hitboxRadius = 80
o.hitboxHeight = 700
o.oIntangibleTimer = 0
o.oAnimations = gObjectAnimations.koopa_flag_seg6_anims_06001028
cur_obj_init_animation(0)
end
--- @param o Object
local function bhv_flood_flag_loop(o)
bhv_pole_base_loop()
end
id_bhvFloodFlag = hook_behavior(nil, OBJ_LIST_POLELIKE, true, bhv_flood_flag_init, bhv_flood_flag_loop)
local function bhv_launchpad_init(o)
o.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
o.oCollisionDistance = 500
o.collisionData = COL_LAUNCHPAD
obj_scale(o, 0.85)
end
local function bhv_launchpad_loop(o)
local m = nearest_mario_state_to_object(o)
if m.marioObj.platform == o then
play_mario_jump_sound(m)
if o.oBehParams2ndByte ~= 255 then
set_mario_action(m, ACT_TWIRLING, 0)
m.vel.y = o.oBehParams2ndByte
else
spawn_non_sync_object(
id_bhvWingCap,
E_MODEL_NONE,
m.pos.x + m.vel.x, m.pos.y + m.vel.y, m.pos.z + m.vel.z,
nil
)
set_mario_action(m, ACT_FLYING_TRIPLE_JUMP, 0)
mario_set_forward_vel(m, 100)
vec3f_set(m.angleVel, 0, 0, 0)
vec3f_set(m.faceAngle, 0, 0x4500, 0)
m.vel.y = 55
end
end
load_object_collision_model()
end
id_bhvLaunchpad = hook_behavior(nil, OBJ_LIST_SURFACE, true, bhv_launchpad_init, bhv_launchpad_loop)
--- @param o Object
local function obj_hide(o)
o.header.gfx.node.flags = o.header.gfx.node.flags | GRAPH_RENDER_INVISIBLE
end
--- @param o Object
local function obj_mark_for_deletion_on_sync(o)
if gNetworkPlayers[0].currAreaSyncValid then obj_mark_for_deletion(o) end
end
hook_behavior(id_bhvStar, OBJ_LIST_UNIMPORTANT, true, obj_hide, obj_mark_for_deletion_on_sync)
hook_behavior(id_bhvHoot, OBJ_LIST_UNIMPORTANT, true, obj_hide, obj_mark_for_deletion_on_sync)
hook_behavior(id_bhvWarpPipe, OBJ_LIST_UNIMPORTANT, true, obj_hide, obj_mark_for_deletion_on_sync)
hook_behavior(id_bhvFadingWarp, OBJ_LIST_UNIMPORTANT, true, obj_hide, obj_mark_for_deletion_on_sync)
hook_behavior(id_bhvBalconyBigBoo, OBJ_LIST_UNIMPORTANT, true, obj_hide, obj_mark_for_deletion_on_sync)
hook_behavior(id_bhvExclamationBox, OBJ_LIST_UNIMPORTANT, true, obj_hide, obj_mark_for_deletion_on_sync)
hook_behavior(id_bhvWaterLevelDiamond, OBJ_LIST_UNIMPORTANT, true, obj_hide, obj_mark_for_deletion_on_sync)
hook_behavior(id_bhvKoopaRaceEndpoint, OBJ_LIST_UNIMPORTANT, true, obj_hide, obj_mark_for_deletion_on_sync)
--- @param m MarioState
local function before_phys_step(m)
if m.playerIndex ~= 0 then return end
if m.pos.y + 40 < gGlobalSyncTable.waterLevel and gNetworkPlayers[m.playerIndex].currLevelNum == gGlobalSyncTable.level then
m.vel.y = m.vel.y + 2
m.peakHeight = m.pos.y
end
end
--- @param m MarioState
--- @param o Object
local function allow_interact(m, o)
if m.action == ACT_SPECTATOR or
(o.header.gfx.node.flags & GRAPH_RENDER_ACTIVE) == 0 or
o.oInteractType == INTERACT_WARP_DOOR or
o.oInteractType == INTERACT_WARP then
return false
end
return true
end
local function on_death()
local m = gMarioStates[0]
if m.floor.type == SURFACE_DEATH_PLANE or m.floor.type == SURFACE_VERTICAL_WIND then
m.health = 0xff
end
return false
end
local function on_pause_exit()
if network_is_server() then
network_send(true, { restart = true })
level_restart()
end
return false
end
--- @param m MarioState
local function allow_hazard_surface(m)
if m.health <= 0xff then return false end
return true
end
-- thanks Peachy
--- @param o Object
local function on_object_unload(o)
local m = gMarioStates[0]
if (o.header.gfx.node.flags & GRAPH_RENDER_INVISIBLE) == 0 and obj_has_behavior_id(o, id_bhv1Up) == 1 and obj_check_hitbox_overlap(o, m.marioObj) then
m.healCounter = 31
m.hurtCounter = 0
end
end
local function on_packet_receive(dataTable)
if dataTable.restart then level_restart() end
end
hook_event(HOOK_BEFORE_PHYS_STEP, before_phys_step)
hook_event(HOOK_ALLOW_INTERACT, allow_interact)
hook_event(HOOK_ON_DEATH, on_death)
hook_event(HOOK_ON_PAUSE_EXIT, on_pause_exit)
hook_event(HOOK_ALLOW_HAZARD_SURFACE, allow_hazard_surface)
hook_event(HOOK_ON_OBJECT_UNLOAD, on_object_unload)
hook_event(HOOK_ON_PACKET_RECEIVE, on_packet_receive)