mirror of
				https://github.com/coop-deluxe/sm64coopdx.git
				synced 2025-10-30 08:01:01 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			359 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			359 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
ARENA_FLAG_INVALID_GLOBAL = 0xFF
 | 
						|
---
 | 
						|
 | 
						|
gArenaFlagInfo = {}
 | 
						|
sFlagScoreTimer = 0
 | 
						|
 | 
						|
define_custom_obj_fields({
 | 
						|
    oArenaFlagTeam = 'u32',
 | 
						|
    oArenaFlagHeldByGlobal = 'u32',
 | 
						|
    oArenaFlagAtBase = 'u32',
 | 
						|
})
 | 
						|
 | 
						|
function bhv_arena_flag_init(obj)
 | 
						|
    local team = (obj.oBehParams >> 24) & 0xFF
 | 
						|
 | 
						|
    obj.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
 | 
						|
    obj.oOpacity = 255
 | 
						|
    obj.oArenaFlagTeam = team
 | 
						|
    obj.oArenaFlagHeldByGlobal = ARENA_FLAG_INVALID_GLOBAL
 | 
						|
    obj.oArenaFlagAtBase = 1
 | 
						|
 | 
						|
    gArenaFlagInfo[team] = {
 | 
						|
        pos = { x = obj.oPosX, y = obj.oPosY, z = obj.oPosZ },
 | 
						|
        team = team,
 | 
						|
        obj = obj,
 | 
						|
    }
 | 
						|
 | 
						|
    if team == 0 then
 | 
						|
        obj_set_model_extended(obj, E_MODEL_FLAG_WHITE)
 | 
						|
    elseif team == 1 then
 | 
						|
        obj_set_model_extended(obj, E_MODEL_FLAG_RED)
 | 
						|
    elseif team == 2 then
 | 
						|
        obj_set_model_extended(obj, E_MODEL_FLAG_BLUE)
 | 
						|
    else
 | 
						|
        obj_mark_for_deletion(obj)
 | 
						|
    end
 | 
						|
 | 
						|
    network_init_object(obj, false, {
 | 
						|
        'oArenaFlagHeldByGlobal',
 | 
						|
        'oArenaFlagAtBase',
 | 
						|
        'oPosX',
 | 
						|
        'oPosY',
 | 
						|
        'oPosZ',
 | 
						|
    })
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_update_pos_rot(obj)
 | 
						|
    -- spin
 | 
						|
    obj.oFaceAngleYaw   = obj.oFaceAngleYaw - 600
 | 
						|
    obj.oFaceAngleRoll  = 0
 | 
						|
    obj.oFaceAnglePitch = 0
 | 
						|
 | 
						|
    local data = gArenaFlagInfo[obj.oArenaFlagTeam]
 | 
						|
    if obj.oArenaFlagAtBase == 1 then
 | 
						|
        -- set at base
 | 
						|
        obj.oPosX = data.pos.x
 | 
						|
        obj.oPosY = data.pos.y
 | 
						|
        obj.oPosZ = data.pos.z
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if obj.oArenaFlagHeldByGlobal == ARENA_FLAG_INVALID_GLOBAL then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local np = network_player_from_global_index(obj.oArenaFlagHeldByGlobal)
 | 
						|
    if np == nil then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    -- set at player
 | 
						|
    local m = gMarioStates[np.localIndex]
 | 
						|
    local awayMag = -50
 | 
						|
    local yOffset = 50
 | 
						|
    if np.localIndex ~= 0 then
 | 
						|
        yOffset = 150
 | 
						|
        awayMag = -30
 | 
						|
    end
 | 
						|
    obj.oPosX = m.pos.x + sins(m.faceAngle.y) * awayMag
 | 
						|
    obj.oPosY = m.pos.y + yOffset
 | 
						|
    obj.oPosZ = m.pos.z + coss(m.faceAngle.y) * awayMag
 | 
						|
    obj.oFaceAngleYaw = m.faceAngle.y + 0x4000
 | 
						|
    obj.oFaceAngleRoll = -0x400
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_update_score(obj)
 | 
						|
    if gGlobalSyncTable.gameMode ~= GAME_MODE_FT and gGlobalSyncTable.gameMode ~= GAME_MODE_TFT then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if not network_is_server() then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if obj.oArenaFlagTeam ~= 0 then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if obj.oArenaFlagHeldByGlobal == ARENA_FLAG_INVALID_GLOBAL then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if gGlobalSyncTable.gameState ~= GAME_STATE_ACTIVE then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local np = network_player_from_global_index(obj.oArenaFlagHeldByGlobal)
 | 
						|
    if np == nil then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    sFlagScoreTimer = sFlagScoreTimer + 1
 | 
						|
    if (sFlagScoreTimer % 30) == 0 then
 | 
						|
        local s = gPlayerSyncTable[np.localIndex]
 | 
						|
        s.score = s.score + 1
 | 
						|
        if gGlobalSyncTable.gameMode == GAME_MODE_TFT then
 | 
						|
            local teamScore = calculate_team_score(s.team)
 | 
						|
            if teamScore >= gGameModes[gGlobalSyncTable.gameMode].scoreCap then
 | 
						|
                round_end()
 | 
						|
            end
 | 
						|
        elseif s.score >= gGameModes[gGlobalSyncTable.gameMode].scoreCap then
 | 
						|
            round_end()
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_update_rotation(obj)
 | 
						|
    if obj.oArenaFlagHeldByGlobal ~= ARENA_FLAG_INVALID_GLOBAL then
 | 
						|
        return
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_return(obj, showMessage)
 | 
						|
    if obj.oArenaFlagAtBase == 1 then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    local otherTeam = get_other_team(obj.oArenaFlagTeam)
 | 
						|
    local data = gArenaFlagInfo[obj.oArenaFlagTeam]
 | 
						|
 | 
						|
    obj.oArenaFlagHeldByGlobal = ARENA_FLAG_INVALID_GLOBAL
 | 
						|
    obj.oArenaFlagAtBase = 1
 | 
						|
    obj.oPosX = data.pos.x
 | 
						|
    obj.oPosY = data.pos.y
 | 
						|
    obj.oPosZ = data.pos.z
 | 
						|
    network_send_object(obj, true)
 | 
						|
    if showMessage then
 | 
						|
        local msg = string.format('%sThe %s%s%s flag was returned!', team_color_str(otherTeam), team_color_str(obj.oArenaFlagTeam), team_name_str(obj.oArenaFlagTeam), team_color_str(otherTeam))
 | 
						|
        send_arena_flag(obj.oArenaFlagTeam, ARENA_FLAG_INVALID_GLOBAL, msg)
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_collect(obj, m)
 | 
						|
    local data = gArenaFlagInfo[obj.oArenaFlagTeam]
 | 
						|
    local s  = gPlayerSyncTable[m.playerIndex]
 | 
						|
    local np = gNetworkPlayers[m.playerIndex]
 | 
						|
    local e  = gMarioStateExtras[m.playerIndex]
 | 
						|
    if e.levelTimer < 30 then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    if obj.oArenaFlagTeam > 0 and s.team == obj.oArenaFlagTeam then
 | 
						|
        if obj.oArenaFlagAtBase == 1 then
 | 
						|
            local otherTeam = get_other_team(obj.oArenaFlagTeam)
 | 
						|
            local otherData = gArenaFlagInfo[otherTeam]
 | 
						|
            local otherFlag = otherData.obj
 | 
						|
            if otherFlag.oArenaFlagHeldByGlobal == np.globalIndex then
 | 
						|
                -- capture flag
 | 
						|
                otherFlag.oArenaFlagHeldByGlobal = ARENA_FLAG_INVALID_GLOBAL
 | 
						|
                otherFlag.oArenaFlagAtBase = 1
 | 
						|
                otherFlag.oPosX = otherData.pos.x
 | 
						|
                otherFlag.oPosY = otherData.pos.y
 | 
						|
                otherFlag.oPosZ = otherData.pos.z
 | 
						|
                network_send_object(otherFlag, true)
 | 
						|
                local msg = string.format('%s%s captured the %s%s%s flag!', team_color_str(s.team), strip_colors(np.name), team_color_str(otherTeam), team_name_str(otherTeam), team_color_str(s.team))
 | 
						|
                send_arena_flag(otherFlag.oArenaFlagTeam, np.globalIndex, msg)
 | 
						|
                if gGlobalSyncTable.gameState == GAME_STATE_ACTIVE then
 | 
						|
                    if s.team == 1 then
 | 
						|
                        gGlobalSyncTable.capTeam1 = gGlobalSyncTable.capTeam1 + 1
 | 
						|
                        if gGlobalSyncTable.capTeam1 >= gGameModes[gGlobalSyncTable.gameMode].scoreCap then
 | 
						|
                            round_end()
 | 
						|
                        end
 | 
						|
                    elseif s.team == 2 then
 | 
						|
                        gGlobalSyncTable.capTeam2 = gGlobalSyncTable.capTeam2 + 1
 | 
						|
                        if gGlobalSyncTable.capTeam2 >= gGameModes[gGlobalSyncTable.gameMode].scoreCap then
 | 
						|
                            round_end()
 | 
						|
                        end
 | 
						|
                    end
 | 
						|
                end
 | 
						|
                return true
 | 
						|
            end
 | 
						|
            return false
 | 
						|
        end
 | 
						|
 | 
						|
        -- return flag
 | 
						|
        obj.oArenaFlagHeldByGlobal = ARENA_FLAG_INVALID_GLOBAL
 | 
						|
        obj.oArenaFlagAtBase = 1
 | 
						|
        obj.oPosX = data.pos.x
 | 
						|
        obj.oPosY = data.pos.y
 | 
						|
        obj.oPosZ = data.pos.z
 | 
						|
        network_send_object(obj, true)
 | 
						|
        local msg = string.format('%s%s returned the %s flag!', team_color_str(s.team), strip_colors(np.name), team_name_str(s.team))
 | 
						|
        send_arena_flag(obj.oArenaFlagTeam, np.globalIndex, msg)
 | 
						|
        return true
 | 
						|
    end
 | 
						|
 | 
						|
    -- pick up flag
 | 
						|
    obj.oArenaFlagHeldByGlobal = np.globalIndex
 | 
						|
    obj.oArenaFlagAtBase = 0
 | 
						|
    obj.oTimer = 0
 | 
						|
    obj.oPosX = m.pos.x
 | 
						|
    obj.oPosY = m.pos.y
 | 
						|
    obj.oPosZ = m.pos.z
 | 
						|
    network_send_object(obj, true)
 | 
						|
    local msg = string.format('%s%s picked up the %s%s%s flag!', team_color_str(s.team), strip_colors(np.name), team_color_str(obj.oArenaFlagTeam), team_name_str(obj.oArenaFlagTeam), team_color_str(s.team))
 | 
						|
    send_arena_flag(obj.oArenaFlagTeam, np.globalIndex, msg)
 | 
						|
    return true
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_check_collect(obj)
 | 
						|
    if not network_is_server() then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if obj.oArenaFlagHeldByGlobal ~= ARENA_FLAG_INVALID_GLOBAL then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    for i = 0, MAX_PLAYERS - 1 do
 | 
						|
        local m  = gMarioStates[i]
 | 
						|
        local player = m.marioObj
 | 
						|
        local yDist = math.abs(obj.oPosY - player.oPosY)
 | 
						|
        local xzDist = math.sqrt((obj.oPosX - player.oPosX) ^ 2 + (obj.oPosZ - player.oPosZ) ^ 2)
 | 
						|
        if active_player(m) and mario_health_float(m) > 0 and xzDist < 160 and yDist < 250 then
 | 
						|
            if bhv_arena_flag_collect(obj, m) then
 | 
						|
                return
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_update_scale(obj)
 | 
						|
    local np = gNetworkPlayers[0]
 | 
						|
    if obj.oArenaFlagHeldByGlobal == np.globalIndex then
 | 
						|
        cur_obj_scale(0.4)
 | 
						|
    else
 | 
						|
        cur_obj_scale(1.0)
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_check_drop(obj)
 | 
						|
    if not network_is_server() then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if obj.oArenaFlagHeldByGlobal == ARENA_FLAG_INVALID_GLOBAL then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local np = network_player_from_global_index(obj.oArenaFlagHeldByGlobal)
 | 
						|
    if np == nil then
 | 
						|
        bhv_arena_flag_return(obj, true)
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local m = gMarioStates[np.localIndex]
 | 
						|
    local s = gPlayerSyncTable[np.localIndex]
 | 
						|
    if not active_player(m) then
 | 
						|
        bhv_arena_flag_return(obj, true)
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if mario_health_float(m) <= 0 then
 | 
						|
        obj.oArenaFlagHeldByGlobal = ARENA_FLAG_INVALID_GLOBAL
 | 
						|
        obj.oArenaFlagAtBase = 0
 | 
						|
        obj.oTimer = 0
 | 
						|
        network_send_object(obj, true)
 | 
						|
        local msg = string.format('%s%s dropped the %s%s%s flag!', team_color_str(s.team), strip_colors(np.name), team_color_str(obj.oArenaFlagTeam), team_name_str(obj.oArenaFlagTeam), team_color_str(s.team))
 | 
						|
        send_arena_flag(obj.oArenaFlagTeam, ARENA_FLAG_INVALID_GLOBAL, msg)
 | 
						|
        return
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_check_death(npVictim)
 | 
						|
    if not network_is_server() then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    if npVictim == nil then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    for teamNum = 0, 2 do
 | 
						|
        local data = gArenaFlagInfo[teamNum]
 | 
						|
        if data ~= nil and data.obj ~= nil and npVictim.globalIndex == data.obj.oArenaFlagHeldByGlobal then
 | 
						|
            bhv_arena_flag_return(data.obj, true)
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_check_return(obj)
 | 
						|
    if not network_is_server() then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    if obj.oArenaFlagHeldByGlobal ~= ARENA_FLAG_INVALID_GLOBAL then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    if obj.oArenaFlagAtBase == 1 then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    if obj.oTimer > 30 * 30 then
 | 
						|
        obj.oTimer = 0
 | 
						|
        bhv_arena_flag_return(obj, true)
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_reset()
 | 
						|
    for teamNum = 0, 2 do
 | 
						|
        local data = gArenaFlagInfo[teamNum]
 | 
						|
        if data ~= nil and data.obj ~= nil then
 | 
						|
            bhv_arena_flag_return(data.obj, false)
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_hide(obj)
 | 
						|
    if gGlobalSyncTable.gameMode == GAME_MODE_CTF and (obj.oArenaFlagTeam == 1 or obj.oArenaFlagTeam == 2) then
 | 
						|
        cur_obj_unhide()
 | 
						|
        return false
 | 
						|
    elseif (gGlobalSyncTable.gameMode == GAME_MODE_FT or gGlobalSyncTable.gameMode == GAME_MODE_TFT) and obj.oArenaFlagTeam == 0 then
 | 
						|
        cur_obj_unhide()
 | 
						|
        return false
 | 
						|
    else
 | 
						|
        cur_obj_hide()
 | 
						|
        return true
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function is_holding_flag(m)
 | 
						|
    local np = gNetworkPlayers[m.playerIndex]
 | 
						|
    for teamNum = 0, 2 do
 | 
						|
        local data = gArenaFlagInfo[teamNum]
 | 
						|
        if data ~= nil and data.obj ~= nil and np.globalIndex == data.obj.oArenaFlagHeldByGlobal then
 | 
						|
            return true
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return false
 | 
						|
end
 | 
						|
 | 
						|
function bhv_arena_flag_loop(obj)
 | 
						|
    if bhv_arena_flag_hide(obj) then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    bhv_arena_flag_update_pos_rot(obj)
 | 
						|
    bhv_arena_flag_update_score(obj)
 | 
						|
    bhv_arena_flag_check_collect(obj)
 | 
						|
    bhv_arena_update_scale(obj)
 | 
						|
    bhv_arena_flag_check_drop(obj)
 | 
						|
    bhv_arena_flag_check_return(obj)
 | 
						|
end
 | 
						|
 | 
						|
id_bhvArenaFlag = hook_behavior(nil, OBJ_LIST_LEVEL, true, bhv_arena_flag_init, bhv_arena_flag_loop)
 |