mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-29 23:43:01 +00:00
319 lines
9.6 KiB
Lua
319 lines
9.6 KiB
Lua
|
gItemHeld = {}
|
||
|
|
||
|
-- setup held items
|
||
|
for i = 0, (MAX_PLAYERS - 1) do
|
||
|
gItemHeld[i] = nil
|
||
|
end
|
||
|
|
||
|
ATTACH_NONE = 0
|
||
|
ATTACH_HAND = 1
|
||
|
ATTACH_HEAD = 2
|
||
|
|
||
|
------------
|
||
|
|
||
|
|
||
|
------------
|
||
|
|
||
|
define_custom_obj_fields({
|
||
|
oArenaItemHeldType = 'u32',
|
||
|
oArenaItemHeldOwner = 'u32',
|
||
|
})
|
||
|
|
||
|
function bhv_arena_item_held_init(obj)
|
||
|
obj.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
|
||
|
obj.oOpacity = 255
|
||
|
obj.oArenaItemHeldType = ITEM_FIRE_FLOWER
|
||
|
obj.hookRender = 1
|
||
|
obj_scale(obj, 1)
|
||
|
cur_obj_hide()
|
||
|
end
|
||
|
|
||
|
function bhv_arena_item_held_loop(obj)
|
||
|
local m = gMarioStates[obj.oArenaItemHeldOwner]
|
||
|
local s = gPlayerSyncTable[obj.oArenaItemHeldOwner]
|
||
|
local data = gItemHeldData[s.item]
|
||
|
|
||
|
-- check if this should be inactive
|
||
|
if s.item == ITEM_NONE or data == nil or not active_player(m) then
|
||
|
cur_obj_hide()
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- if the player is off screen, hide the obj
|
||
|
if m.marioBodyState.updateTorsoTime ~= gMarioStates[0].marioBodyState.updateTorsoTime then
|
||
|
cur_obj_hide()
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- update pallet
|
||
|
local np = gNetworkPlayers[obj.oArenaItemHeldOwner]
|
||
|
if np ~= nil then
|
||
|
obj.globalPlayerIndex = np.globalIndex
|
||
|
end
|
||
|
|
||
|
-- check if this should be activated
|
||
|
if obj_is_hidden(obj) ~= 0 or obj.oArenaItemHeldType ~= s.item then
|
||
|
cur_obj_unhide()
|
||
|
obj_set_model_extended(obj, data.heldModel)
|
||
|
obj_scale(obj, data.scale)
|
||
|
obj.oAnimState = 0
|
||
|
if data.billboard then
|
||
|
obj.header.gfx.node.flags = obj.header.gfx.node.flags | GRAPH_RENDER_BILLBOARD
|
||
|
else
|
||
|
obj.header.gfx.node.flags = obj.header.gfx.node.flags & ~GRAPH_RENDER_BILLBOARD
|
||
|
end
|
||
|
if data.animations ~= nil then
|
||
|
obj.oAnimations = data.animations
|
||
|
cur_obj_init_animation(data.animationIndex)
|
||
|
else
|
||
|
obj.oAnimations = nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- update things
|
||
|
obj.oArenaItemHeldType = s.item
|
||
|
if data.updateAnimState then
|
||
|
obj.oAnimState = obj.oAnimState + 1
|
||
|
end
|
||
|
end
|
||
|
|
||
|
id_bhvArenaItemHeld = hook_behavior(nil, OBJ_LIST_DEFAULT, true, bhv_arena_item_held_init, bhv_arena_item_held_loop)
|
||
|
|
||
|
------------
|
||
|
|
||
|
function on_level_init()
|
||
|
-- initialize all held items
|
||
|
for i = 0, (MAX_PLAYERS - 1) do
|
||
|
gItemHeld[i] = spawn_non_sync_object(id_bhvArenaItemHeld, E_MODEL_NONE, 0, 0, 0,
|
||
|
function(obj)
|
||
|
obj.oArenaItemHeldType = ITEM_NONE
|
||
|
obj.oArenaItemHeldOwner = i
|
||
|
end)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function dot_along_angle(obj, m, angle)
|
||
|
local v1 = {
|
||
|
x = obj.oPosX - m.pos.x,
|
||
|
y = obj.oPosY - m.pos.y,
|
||
|
z = obj.oPosZ - m.pos.z,
|
||
|
}
|
||
|
vec3f_normalize(v1)
|
||
|
local v2 = {
|
||
|
x = sins(m.faceAngle.y + angle),
|
||
|
y = 0,
|
||
|
z = coss(m.faceAngle.y + angle),
|
||
|
}
|
||
|
return vec3f_dot(v1, v2)
|
||
|
end
|
||
|
|
||
|
function bhv_arena_item_held_hammer_render(obj)
|
||
|
local m = gMarioStates[obj.oArenaItemHeldOwner]
|
||
|
local e = gMarioStateExtras[obj.oArenaItemHeldOwner]
|
||
|
local animFrame = m.marioObj.header.gfx.animInfo.animFrame
|
||
|
|
||
|
if m.action == ACT_DIVE then
|
||
|
obj.oFaceAnglePitch = e.rotAngle
|
||
|
obj.oFaceAngleRoll = 0
|
||
|
elseif m.action == ACT_DIVE_SLIDE then
|
||
|
obj.oFaceAnglePitch = 0x4000
|
||
|
obj.oFaceAngleRoll = 0
|
||
|
elseif m.action == ACT_STOMACH_SLIDE_STOP then
|
||
|
local loopEnd = m.marioObj.header.gfx.animInfo.curAnim.loopEnd
|
||
|
local scalar = 1
|
||
|
if loopEnd == 38 then
|
||
|
scalar = (1 - (animFrame / loopEnd) ^ 2)
|
||
|
end
|
||
|
obj.oFaceAnglePitch = 0x4000 * scalar
|
||
|
obj.oFaceAngleRoll = 0
|
||
|
elseif m.action == ACT_PUNCHING or m.action == ACT_MOVE_PUNCHING then
|
||
|
local scalar = dot_along_angle(obj, m, 0) * 1.5
|
||
|
if scalar > 0.723 then scalar = 0.723 end
|
||
|
obj.oFaceAnglePitch = 0x5000 * scalar + 0x500
|
||
|
obj.oFaceAngleRoll = 0x1000 * dot_along_angle(obj, m, -0x4000)
|
||
|
elseif m.action == ACT_GROUND_POUND then
|
||
|
local loopEnd = m.marioObj.header.gfx.animInfo.curAnim.loopEnd
|
||
|
if m.actionState == 0 then
|
||
|
obj.oFaceAnglePitch = 0x16000 * animFrame / loopEnd
|
||
|
else
|
||
|
obj.oFaceAnglePitch = 0x4000
|
||
|
end
|
||
|
obj.oFaceAngleRoll = 0
|
||
|
elseif m.action == ACT_GROUND_POUND_LAND then
|
||
|
local loopEnd = m.marioObj.header.gfx.animInfo.curAnim.loopEnd
|
||
|
local scalar = 1
|
||
|
if loopEnd == 6 then
|
||
|
scalar = (1 - (animFrame / loopEnd) ^ 2)
|
||
|
end
|
||
|
obj.oFaceAnglePitch = 0x4000 * scalar
|
||
|
obj.oFaceAngleRoll = 0
|
||
|
elseif m.action == ACT_JUMP_KICK then
|
||
|
local loopEnd = m.marioObj.header.gfx.animInfo.curAnim.loopEnd
|
||
|
local scalar = (animFrame / loopEnd) * 9
|
||
|
if scalar > 4 then scalar = 4 end
|
||
|
obj.oFaceAnglePitch = -0x8000 * scalar
|
||
|
obj.oFaceAngleRoll = 0
|
||
|
elseif m.action == ACT_BACKFLIP then
|
||
|
local loopEnd = m.marioObj.header.gfx.animInfo.curAnim.loopEnd
|
||
|
local scalar = (animFrame / loopEnd) * 4
|
||
|
if scalar > 4 then scalar = 4 end
|
||
|
obj.oFaceAnglePitch = -0x8000 * scalar
|
||
|
obj.oFaceAngleRoll = 0x1000 * dot_along_angle(obj, m, -0x4000)
|
||
|
elseif m.action == ACT_TRIPLE_JUMP then
|
||
|
local loopEnd = m.marioObj.header.gfx.animInfo.curAnim.loopEnd
|
||
|
local scalar = (animFrame / loopEnd) * 4
|
||
|
if scalar > 4 then scalar = 4 end
|
||
|
obj.oFaceAnglePitch = 0x8000 * scalar
|
||
|
obj.oFaceAngleRoll = 0x1000 * dot_along_angle(obj, m, -0x4000)
|
||
|
elseif m.action == ACT_SIDE_FLIP then
|
||
|
local loopEnd = m.marioObj.header.gfx.animInfo.curAnim.loopEnd
|
||
|
local scalar = (animFrame / loopEnd) * 2
|
||
|
if scalar > 4 then scalar = 4 end
|
||
|
obj.oFaceAnglePitch = 0x8000 * scalar
|
||
|
obj.oFaceAngleRoll = 0x1000 * dot_along_angle(obj, m, -0x4000)
|
||
|
else
|
||
|
obj.oFaceAnglePitch = 0x2500 * dot_along_angle(obj, m, 0) + 0x500
|
||
|
obj.oFaceAngleRoll = 0x1000 * dot_along_angle(obj, m, -0x4000)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function on_object_render(obj)
|
||
|
if get_id_from_behavior(obj.behavior) ~= id_bhvArenaItemHeld then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local m = gMarioStates[obj.oArenaItemHeldOwner]
|
||
|
local data = gItemHeldData[obj.oArenaItemHeldType]
|
||
|
|
||
|
if data == nil or not active_player(m) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
obj.oFaceAngleYaw = m.faceAngle.y + data.yawOffset
|
||
|
obj.oFaceAnglePitch = data.pitchOffset
|
||
|
obj.oFaceAngleRoll = 0
|
||
|
|
||
|
if data.attachment == ATTACH_HAND then
|
||
|
obj.oPosX = get_hand_foot_pos_x(m, 0)
|
||
|
obj.oPosY = get_hand_foot_pos_y(m, 0) + data.yOffset
|
||
|
obj.oPosZ = get_hand_foot_pos_z(m, 0)
|
||
|
elseif data.attachment == ATTACH_HEAD then
|
||
|
obj.oPosX = m.marioBodyState.headPos.x
|
||
|
obj.oPosY = m.marioBodyState.headPos.y + data.yOffset
|
||
|
obj.oPosZ = m.marioBodyState.headPos.z
|
||
|
end
|
||
|
|
||
|
if data.renderAdjust ~= nil then
|
||
|
data.renderAdjust(obj)
|
||
|
end
|
||
|
|
||
|
-- if the player is off screen, move the obj to the player origin
|
||
|
if m.marioBodyState.updateTorsoTime ~= gMarioStates[0].marioBodyState.updateTorsoTime then
|
||
|
obj.oPosX = m.pos.x
|
||
|
obj.oPosY = m.pos.y
|
||
|
obj.oPosZ = m.pos.z
|
||
|
end
|
||
|
|
||
|
if data.forwardOffset > 0 then
|
||
|
obj.oPosX = obj.oPosX + sins(m.faceAngle.y) * data.forwardOffset
|
||
|
obj.oPosZ = obj.oPosZ + coss(m.faceAngle.y) * data.forwardOffset
|
||
|
end
|
||
|
|
||
|
obj.header.gfx.pos.x = obj.oPosX
|
||
|
obj.header.gfx.pos.y = obj.oPosY
|
||
|
obj.header.gfx.pos.z = obj.oPosZ
|
||
|
end
|
||
|
|
||
|
hook_event(HOOK_ON_OBJECT_RENDER, on_object_render)
|
||
|
hook_event(HOOK_ON_LEVEL_INIT, on_level_init)
|
||
|
|
||
|
----
|
||
|
|
||
|
gItemHeldData = {
|
||
|
[ITEM_NONE] = {
|
||
|
heldModel = E_MODEL_NONE,
|
||
|
updateAnimState = false,
|
||
|
billboard = false,
|
||
|
scale = 1,
|
||
|
attachment = ATTACH_NONE,
|
||
|
yawOffset = 0,
|
||
|
pitchOffset = 0,
|
||
|
yOffset = 0,
|
||
|
forwardOffset = 0,
|
||
|
renderAdjust = nil,
|
||
|
},
|
||
|
[ITEM_METAL_CAP] = {
|
||
|
heldModel = E_MODEL_NONE,
|
||
|
updateAnimState = false,
|
||
|
billboard = false,
|
||
|
scale = 1,
|
||
|
attachment = ATTACH_NONE,
|
||
|
yawOffset = 0,
|
||
|
pitchOffset = 0,
|
||
|
yOffset = 0,
|
||
|
forwardOffset = 0,
|
||
|
renderAdjust = nil,
|
||
|
},
|
||
|
[ITEM_HAMMER] = {
|
||
|
heldModel = E_MODEL_HAMMER,
|
||
|
updateAnimState = false,
|
||
|
billboard = false,
|
||
|
scale = 1,
|
||
|
attachment = ATTACH_HAND,
|
||
|
yawOffset = 0,
|
||
|
pitchOffset = 0x1000,
|
||
|
yOffset = 0,
|
||
|
forwardOffset = 10,
|
||
|
renderAdjust = bhv_arena_item_held_hammer_render,
|
||
|
},
|
||
|
[ITEM_FIRE_FLOWER] = {
|
||
|
heldModel = E_MODEL_RED_FLAME,
|
||
|
updateAnimState = true,
|
||
|
billboard = true,
|
||
|
scale = 2,
|
||
|
attachment = ATTACH_HAND,
|
||
|
yawOffset = 0,
|
||
|
pitchOffset = 0,
|
||
|
forwardOffset = 25,
|
||
|
yOffset = 10,
|
||
|
renderAdjust = nil,
|
||
|
},
|
||
|
[ITEM_CANNON_BOX] = {
|
||
|
heldModel = E_MODEL_CANNON_BOX,
|
||
|
updateAnimState = false,
|
||
|
billboard = false,
|
||
|
scale = 0.65,
|
||
|
attachment = ATTACH_HEAD,
|
||
|
yawOffset = -0x4000,
|
||
|
pitchOffset = 0,
|
||
|
yOffset = 50,
|
||
|
forwardOffset = 0,
|
||
|
renderAdjust = nil,
|
||
|
},
|
||
|
[ITEM_BOBOMB] = {
|
||
|
heldModel = E_MODEL_BLACK_BOBOMB,
|
||
|
updateAnimState = false,
|
||
|
billboard = false,
|
||
|
scale = 0.5,
|
||
|
attachment = ATTACH_HAND,
|
||
|
yawOffset = 0,
|
||
|
pitchOffset = 0,
|
||
|
yOffset = -25,
|
||
|
forwardOffset = 25,
|
||
|
animations = gObjectAnimations.bobomb_seg8_anims_0802396C,
|
||
|
animationIndex = 1,
|
||
|
renderAdjust = nil,
|
||
|
},
|
||
|
[ITEM_COIN] = {
|
||
|
heldModel = E_MODEL_NONE,
|
||
|
updateAnimState = false,
|
||
|
billboard = false,
|
||
|
scale = 1,
|
||
|
attachment = ATTACH_NONE,
|
||
|
yawOffset = 0,
|
||
|
pitchOffset = 0,
|
||
|
yOffset = 0,
|
||
|
forwardOffset = 0,
|
||
|
renderAdjust = nil,
|
||
|
},
|
||
|
}
|