2023-12-16 18:57:24 +00:00
if SM64COOPDX_VERSION == nil then return end
2022-05-22 04:05:41 +00:00
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 )