Files
gtav-src/script/dev_ng/singleplayer/scripts/Minigames/Tennis/tennis_server.sch
T
2025-09-29 00:52:08 +02:00

339 lines
14 KiB
Scheme
Executable File

USING "commands_network.sch"
USING "tennis_mp.sch"
USING "tennis_debug.sch"
USING "fmmc_restart_header.sch"
STRUCT TENNIS_PARTICIPANT_INFO
INT iPlayers[TENNIS_PLAYERS]
INT iSCTV[TENNIS_MAX_SCTV]
INT iPlayerCount
INT iSCTVCount
ENDSTRUCT
// The server broadcast data
// Everyone can read this data, only the server can update it
STRUCT TENNIS_SERVER_BD
TENNIS_MP_STATE eMPState
//Server Data
TENNIS_PLAYER_ID eWhoIsServing
TENNIS_PLAYER_ID eHitLast
TENNIS_PLAYER_ID eScoredLast
SERVING_SIDE_ENUM eServingSide = SERVING_FROM_RIGHT
TENNIS_GAME_STATE_ENUM eGameState
TENNIS_GAME_STATE_ENUM ePrevGameState
TENNIS_SCORES playerScores[TENNIS_PLAYERS]
TENNIS_MATCH_RULESET eRuleset
FLOAT fDesyncTimer
BOOL bOnTieBreak
INT iNumSets = 1
INT iServeCount
INT iCurrentSet
INT iTMSFlags
INT iCurrentOption
INT iMatchHistoryID
INT iMatchType
INT iHashMac
SERVER_EOM_VARS sServerFMMC_EOM
PLAYER_CURRENT_STATUS_COUNTS sPlayerCounts
SCRIPT_TIMER timeLeaderboardTimeOut
SCRIPT_TIMER timeServeTimeOut
ENDSTRUCT
PROC SET_TENNIS_SERVER_FLAG(TENNIS_SERVER_BD &serverBD, TENNIS_MP_SERVER_FLAGS eFlag)
CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_SERVER_FLAG :: Setting ", GET_STRING_FROM_TENNIS_SERVER_FLAG(eFlag))
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
SET_BITMASK_AS_ENUM(serverBD.iTMSFlags, eFlag)
ENDIF
ENDPROC
FUNC BOOL IS_TENNIS_SERVER_FLAG_SET(TENNIS_SERVER_BD &serverBD, TENNIS_MP_SERVER_FLAGS eFlag)
RETURN IS_BITMASK_AS_ENUM_SET(serverBD.iTMSFlags, eFlag)
ENDFUNC
PROC CLEAR_TENNIS_SERVER_FLAG(TENNIS_SERVER_BD &serverBD, TENNIS_MP_SERVER_FLAGS eFlag)
CDEBUG2LN(DEBUG_TENNIS, "CLEAR_TENNIS_SERVER_FLAG :: Clearing ", GET_STRING_FROM_TENNIS_SERVER_FLAG(eFlag))
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
CLEAR_BITMASK_AS_ENUM(serverBD.iTMSFlags, eFlag)
ENDIF
ENDPROC
/// PURPOSE:
/// WARNING: This will unset all other server flags!
/// PARAMS:
/// serverBD -
/// eFlag -
PROC SET_TENNIS_SERVER_FLAG_EXCLUSIVE(TENNIS_SERVER_BD &serverBD, TENNIS_MP_SERVER_FLAGS eFlag)
CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_SERVER_FLAG_EXCLUSIVE :: Setting ", GET_STRING_FROM_TENNIS_SERVER_FLAG(eFlag))
serverBD.iTMSFlags = ENUM_TO_INT(eFlag)
ENDPROC
PROC SET_TENNIS_MP_TIE_BREAK(TENNIS_SERVER_BD &serverBD, BOOL bOnTieBreak)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
CDEBUG2LN(DEBUG_TENNIS, "START_TENNIS_MP_TIE_BREAK :: bOnTieBreak=", PICK_STRING(bOnTieBreak, "TRUE", "FALSE"))
serverBD.bOnTieBreak = bOnTieBreak
ENDIF
ENDPROC
FUNC BOOL IS_TENNIS_MP_ON_TIE_BREAK(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.bOnTieBreak
ENDFUNC
PROC SET_TENNIS_MP_RULESET(TENNIS_SERVER_BD &serverBD, TENNIS_MATCH_RULESET eNewRuleset)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
serverBD.eRuleset = eNewRuleset
ENDIF
ENDPROC
FUNC TENNIS_MATCH_RULESET GET_TENNIS_MP_RULESET(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.eRuleset
ENDFUNC
PROC SET_TENNIS_MP_NUM_SETS(TENNIS_SERVER_BD &serverBD, INT iNewSets)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
serverBD.iNumSets = iNewSets
ENDIF
ENDPROC
FUNC INT GET_TENNIS_MP_NUM_SETS(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.iNumSets
ENDFUNC
FLOAT fDesyncTimer
PROC INCREASE_TENNIS_DESYNC_TIMER()
fDesyncTimer += GET_FRAME_TIME()
ENDPROC
FUNC BOOL SHOULD_TENNIS_DESYNC_BE_HANDLED()
RETURN fDesyncTimer > DESYNC_THRESHOLD
ENDFUNC
PROC RESET_TENNIS_DESYNC_TIMER()
fDesyncTimer = 0.0
ENDPROC
PROC TENNIS_MP_RESET_POINTS_WON(TENNIS_SCORES &playerScores[], INT &iUtilFlags)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
playerScores[0].iPointsWon = 0
playerScores[1].iPointsWon = 0
SET_BITMASK_AS_ENUM(iUtilFlags, TD_UPDATE_SCORES)
ENDIF
ENDPROC
/// PURPOSE:
///
/// PARAMS:
/// playerScores - The score struct of the player who just scored
PROC TENNIS_MP_INCREASE_POINTS_WON(TENNIS_SCORES &serverScores, INT &iUtilFlags)
#IF IS_DEBUG_BUILD
IF NOT DO_NOT_TRACK_SCORE
#ENDIF
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
serverScores.iPointsWon++
SET_BITMASK_AS_ENUM(iUtilFlags, TD_UPDATE_SCORES)
CPRINTLN(DEBUG_TENNIS, "Increasing Points Won for the serverScores passed in")
ENDIF
#IF IS_DEBUG_BUILD
ENDIF
#ENDIF
ENDPROC
/// PURPOSE:
/// Currently void, does nothing.
PROC RECORD_TENNIS_MP_GAME_WIN()
ENDPROC
FUNC TENNIS_GAME_STATE_ENUM GET_TENNIS_SERVER_PREV_GAME_STATE(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.ePrevGameState
ENDFUNC
PROC SET_TENNIS_MP_WHO_IS_SERVING(TENNIS_SERVER_BD &thisBD, TENNIS_PLAYER_ID newServing)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
thisBD.eWhoIsServing = newServing
CPRINTLN(DEBUG_TENNIS, "Tennis Server changed to ", PICK_STRING(newServing = TENNIS_PLAYER_AWAY, "TENNIS_PLAYER_AWAY", "TENNIS_PLAYER_HOME"))
ENDIF
ENDPROC
FUNC TENNIS_PLAYER_ID GET_TENNIS_MP_WHO_IS_SERVING(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.eWhoIsServing
ENDFUNC
PROC SET_TENNIS_MP_HIT_LAST(TENNIS_SERVER_BD &thisBD, TENNIS_PLAYER_ID newHitLast)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
thisBD.eHitLast = newHitLast
CPRINTLN(DEBUG_TENNIS, "Set ped to hit last as ", PICK_STRING(newHitLast = TENNIS_PLAYER_AWAY, "TENNIS_PLAYER_AWAY", "TENNIS_PLAYER_HOME"))
ENDIF
ENDPROC
FUNC TENNIS_PLAYER_ID GET_TENNIS_MP_HIT_LAST(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.eHitLast
ENDFUNC
FUNC INT GET_TENNIS_MP_CURRENT_SET(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.iCurrentSet
ENDFUNC
PROC SET_TENNIS_SERVER_MP_STATE(TENNIS_SERVER_BD &serverBD, TENNIS_MP_STATE newMPState)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
CDEBUG3LN(DEBUG_TENNIS, "SET_TENNIS_SERVER_MP_STATE :: newMPState=", GET_STRING_FROM_TENNIS_MP_STATE(newMPState))
serverBD.eMPState = newMPState
ENDIF
ENDPROC
FUNC TENNIS_MP_STATE GET_TENNIS_SERVER_MP_STATE(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.eMPState
ENDFUNC
PROC SET_TENNIS_SERVER_GAME_STATE(TENNIS_SERVER_BD &serverBD, TENNIS_GAME_STATE_ENUM newTGSE, BOOL desynced=FALSE)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
IF serverBD.eGameState <> newTGSE OR desynced
serverBD.ePrevGameState = serverBD.eGameState
serverBD.eGameState = newTGSE
CPRINTLN(DEBUG_TENNIS, "Game Timer: ", GET_GAME_TIMER(), " Server switched to: ",
PICK_STRING(newTGSE = TGSE_PREPARE_SERVE, "TGSE_PREPARE_FOR_SERVE ",
PICK_STRING(newTGSE = TGSE_RALLY, "TGSE_RALLY ",
PICK_STRING(newTGSE = TGSE_POINT_WON, "TGSE_POINT_WON ",
PICK_STRING(newTGSE = TGSE_POINT_CHECKS, "TGSE_POINT_CHECKS ",
PICK_STRING(newTGSE = TGSE_INTERSTITIAL, "TGSE_INTERSTITIAL ",
PICK_STRING(newTGSE = TGSE_TEST_STATE, "TGSE_TEST_STATE ",
PICK_STRING(newTGSE = TGSE_PREPARE_REMATCH, "TGSE_PREPARE_REMATCH ",
PICK_STRING(newTGSE = TGSE_CHANGE_SERVERS, "TGSE_CHANGE_SERVERS ", "TENNIS_GAME_STATE_ENUM Enum: ")))))))), newTGSE)
CPRINTLN(DEBUG_TENNIS, PICK_STRING(desynced, "Game experienced a desync", "Game is running smoothly"))
ELSE
CPRINTLN(DEBUG_TENNIS, "Trying to set to state: ",
PICK_STRING(newTGSE = TGSE_PREPARE_SERVE, "TGSE_PREPARE_FOR_SERVE ",
PICK_STRING(newTGSE = TGSE_RALLY, "TGSE_RALLY ",
PICK_STRING(newTGSE = TGSE_POINT_WON, "TGSE_POINT_WON ",
PICK_STRING(newTGSE = TGSE_POINT_CHECKS, "TGSE_POINT_CHECKS ",
PICK_STRING(newTGSE = TGSE_INTERSTITIAL, "TGSE_INTERSTITIAL ",
PICK_STRING(newTGSE = TGSE_PREPARE_REMATCH, "TGSE_PREPARE_REMATCH ",
PICK_STRING(newTGSE = TGSE_TEST_STATE, "TGSE_TEST_STATE ",
PICK_STRING(newTGSE = TGSE_CHANGE_SERVERS, "TGSE_CHANGE_SERVERS ", "TENNIS_GAME_STATE_ENUM Enum: ")))))))), newTGSE)
CPRINTLN(DEBUG_TENNIS, PICK_STRING(desynced, "Game experienced a desync", "Game is running smoothly"))
//SCRIPT_ASSERT("Server State is being set to itself, contact Rob Pearsall")
ENDIF
IF desynced AND newTGSE <> TGSE_POINT_WON
CLEAR_TENNIS_SERVER_FLAG(serverBD, TMS_RECOVERING_FROM_DESYNC)
CPRINTLN(DEBUG_TENNIS, "Clearing desync server flag")
ENDIF
ENDIF
ENDPROC
FUNC TENNIS_GAME_STATE_ENUM GET_TENNIS_SERVER_GAME_STATE(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.eGameState
ENDFUNC
PROC SET_TENNIS_MP_SCORED_LAST_private(TENNIS_SERVER_BD &serverBD, TENNIS_PLAYER_ID whoScored)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
serverBD.eScoredLast = whoScored
CPRINTLN(DEBUG_TENNIS, "Last ped to score is ", PICK_STRING(whoScored = TENNIS_PLAYER_AWAY, "TENNIS_PLAYER_AWAY", "TENNIS_PLAYER_HOME"))
ENDIF
ENDPROC
FUNC TENNIS_PLAYER_ID GET_TENNIS_MP_SCORED_LAST(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.eScoredLast
ENDFUNC
PROC SET_TENNIS_MP_SERVING_SIDE(TENNIS_SERVER_BD &serverBD, SERVING_SIDE_ENUM newSide)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
serverBD.eServingSide = newSide
CPRINTLN(DEBUG_TENNIS, "Changing the serving side to ", PICK_STRING(newSide = SERVING_FROM_RIGHT, "SERVING_FROM_RIGHT", "SERVING_FROM_LEFT"))
ENDIF
ENDPROC
FUNC SERVING_SIDE_ENUM GET_TENNIS_MP_SERVING_SIDE(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.eServingSide
ENDFUNC
PROC SET_TENNIS_MP_SERVE_COUNT(TENNIS_SERVER_BD &serverBD, INT iCount)
IF NETWORK_IS_HOST_OF_THIS_SCRIPT()
serverBD.iServeCount = iCount
CPRINTLN(DEBUG_TENNIS, "Game Timer: ", GET_GAME_TIMER(), " Serve count set to: ", iCount)
ENDIF
ENDPROC
FUNC INT GET_TENNIS_MP_SERVE_COUNT(TENNIS_SERVER_BD &serverBD)
RETURN serverBD.iServeCount
ENDFUNC
PROC PRINT_ALL_TENNIS_SERVER_FLAGS(TENNIS_SERVER_BD &serverBD)
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_GAME ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_GAME), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_RALLY ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_RALLY), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_PREPARE_SERVE ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_PREPARE_SERVE), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_OUTRO ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_OUTRO), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_POINT_WON ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_POINT_WON), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_INTERSTITIAL ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_INTERSTITIAL), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_CHANGE_SERVERS ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_CHANGE_SERVERS), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_PREPARE_FOR_DESYNC ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_PREPARE_FOR_DESYNC), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_RECOVERING_FROM_DESYNC ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_RECOVERING_FROM_DESYNC), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_FINISH ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_FINISH), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_SIDE_CHANGE ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_SIDE_CHANGE), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_PREPARE_REMATCH ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_PREPARE_REMATCH), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_MOVE_TO_POINT_CHECKS ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_MOVE_TO_POINT_CHECKS), "IS", "IS NOT"), " set")
CPRINTLN(DEBUG_TENNIS, "TMS_IS_REMATCH_FLAG ", PICK_STRING(IS_TENNIS_SERVER_FLAG_SET(serverBD, TMS_IS_REMATCH_FLAG), "IS", "IS NOT"), " set")
ENDPROC
PROC PRINT_ALL_TENNIS_SERVER_DATA(TENNIS_SERVER_BD &serverBD)
CPRINTLN(DEBUG_TENNIS, "PRINT_ALL_TENNIS_SERVER_DATA :: Data below")
CPRINTLN(DEBUG_TENNIS, "eMPState=", GET_STRING_FROM_TENNIS_MP_STATE(serverBD.eMPState))
CPRINTLN(DEBUG_TENNIS, "eWhoIsServing=", GET_STRING_FROM_TENNIS_PLAYER_ID(serverBD.eWhoIsServing))
CPRINTLN(DEBUG_TENNIS, "eHitLast=", GET_STRING_FROM_TENNIS_PLAYER_ID(serverBD.eHitLast))
CPRINTLN(DEBUG_TENNIS, "eScoredLast=", GET_STRING_FROM_TENNIS_PLAYER_ID(serverBD.eScoredLast))
CPRINTLN(DEBUG_TENNIS, "eServingSide=", serverBD.eServingSide)
CPRINTLN(DEBUG_TENNIS, "eGameState=", GET_STRING_FROM_TENNIS_GAME_STATE(serverBD.eGameState))
CPRINTLN(DEBUG_TENNIS, "ePrevGameState=", GET_STRING_FROM_TENNIS_GAME_STATE(serverBD.ePrevGameState))
CPRINTLN(DEBUG_TENNIS, "fDesyncTimer=", serverBD.fDesyncTimer)
CPRINTLN(DEBUG_TENNIS, "bOnTieBreak=", serverBD.bOnTieBreak)
CPRINTLN(DEBUG_TENNIS, "iNumSets=", serverBD.iNumSets)
CPRINTLN(DEBUG_TENNIS, "iServeCount=", serverBD.iServeCount)
CPRINTLN(DEBUG_TENNIS, "iCurrentSet=", serverBD.iCurrentSet)
CPRINTLN(DEBUG_TENNIS, "iCurrentOption=", serverBD.iCurrentOption)
CPRINTLN(DEBUG_TENNIS, "iMatchHistoryID=", serverBD.iMatchHistoryID)
CPRINTLN(DEBUG_TENNIS, "iMatchType=", serverBD.iMatchType)
CPRINTLN(DEBUG_TENNIS, "iHashMac=", serverBD.iHashMac)
PRINT_ALL_TENNIS_SERVER_FLAGS(serverBD)
ENDPROC
FUNC BOOL VALIDATE_TENNIS_PLAYERS_INFO(TENNIS_PARTICIPANT_INFO &info)
IF info.iPlayers[0] = TENNIS_INVALID_PARTICIPANT_ID
CERRORLN(DEBUG_TENNIS, "VALIDATE_TENNIS_PLAYERS_INFO :: Exiting player0=", PICK_STRING(info.iPlayers[0] = TENNIS_INVALID_PARTICIPANT_ID, "INVALID", "VALID"))
DEBUG_PRINTCALLSTACK()
RETURN FALSE
ENDIF
IF info.iPlayers[1] = TENNIS_INVALID_PARTICIPANT_ID
CERRORLN(DEBUG_TENNIS, "VALIDATE_TENNIS_PLAYERS_INFO :: Exiting player1=", PICK_STRING(info.iPlayers[1] = TENNIS_INVALID_PARTICIPANT_ID, "INVALID", "VALID"))
DEBUG_PRINTCALLSTACK()
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Checks if a player is SCTV or joined as a spectator
/// PARAMS:
/// iPlayerID - The INT of the player you're curious about, -1 returns the local player
/// RETURNS:
/// TRUE if the player joined as spectator or SCTV, FALSE otherwise
FUNC BOOL TENNIS_IS_PLAYER_SPECTATING( INT iPlayerID = -1 )
PLAYER_INDEX playerToCheck
IF iPlayerID = -1
playerToCheck = PLAYER_ID()
ELSE
playerToCheck = INT_TO_PLAYERINDEX( iPlayerID )
ENDIF
IF IS_PLAYER_SCTV( playerToCheck )
RETURN TRUE
ENDIF
IF DID_PLAYER_JOIN_MISSION_AS_SPECTATOR( playerToCheck )
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC