USING "minigames_helpers.sch" USING "minigame_UIInputs.sch" USING "script_oddjob_funcs.sch" USING "net_celebration_screen.sch" USING "tennis_ai.sch" USING "tennis_court.sch" USING "tennis_player.sch" USING "tennis_ball.sch" USING "tennis_ui.sch" USING "tennis_cameras.sch" USING "tennis_debug.sch" USING "MP_Scaleform_Functions.sch" CONST_INT MAX_SETS 5 CONST_FLOAT fBaseRewardMoney 25.0 CONST_FLOAT DEFAULT_FORCE_SCALE 0.1 CONST_FLOAT DEFAULT_DAMPENING 4.0 CONST_FLOAT DEFAULT_MASS 1.0 CONST_FLOAT fBallOffsetX 0.110 CONST_FLOAT fBallOffsetY 0.000 CONST_FLOAT fBallOffsetZ 0.040 CONST_FLOAT fDragApproximation 0.82 CONST_FLOAT RacketOffX 0.1 CONST_FLOAT RacketOffY 0.04 CONST_FLOAT RacketOffZ -0.01 CONST_FLOAT RacketRotX -80.96 CONST_FLOAT RacketRotY 3.59 CONST_FLOAT RacketRotZ -21.54 CONST_FLOAT POWER_STAT_MULT 0.1 CONST_FLOAT SPEED_MOD 0.1 CONST_FLOAT ANIM_PLAYING_TIME 3.550 CONST_FLOAT CAM_OFFSET_HEADING 80.0 CONST_FLOAT CAM_LOOK_AT_MULT 6.535 CONST_FLOAT CAM_OFFSET_X 4.113 CONST_FLOAT CAM_OFFSET_Y -6.157 CONST_FLOAT CAM_OFFSET_Z 6.3 CONST_INT SHAKE_DURATION 1 CONST_INT SHAKE_FREQ 65 CONST_FLOAT RALLY_CONVO_RATE 0.25 CONST_FLOAT CUT_DELAY 0.4 CONST_FLOAT CUT_DELAY_ONLINE 0.5 CONST_FLOAT QUIT_PT_RADIUS 2.925 CONST_FLOAT QUIT_PT_RESET 1.25 CONST_FLOAT SKIP_INTER_DELAY 0.25 CONST_FLOAT DISABLED_INPUT_DEAD_ZONE 0.2 CONST_FLOAT HURRY_SPEECH_DELAY 15.0 // Rob, if you have a better place for this please move it STRUCTTIMER m_timerSkip /// ******************************************************* ENUMS *************************************************************************** ENUM TENNIS_GAME_STATE_ENUM TGSE_PRE_INIT = 0, TGSE_PRE_INIT_WAIT, TGSE_FRIEND_INIT_WAIT, TGSE_CAMERA_PAN_WAIT, TGSE_INIT, TGSE_INTRO, //5 TGSE_OPTION_MENU, TGSE_OPTION_FINISHED, TGSE_PREPARE_SERVE, TGSE_SERVE, TGSE_SERVE_RESULT, //10 TGSE_WAIT_FOR_PREDICTION, TGSE_RALLY, TGSE_RALLY_PREDICT, TGSE_POINT_WON, TGSE_POINT_CHECKS, //Used in MP to wait until scores are synced //15 TGSE_INTERSTITIAL, TGSE_SIDE_CHANGE, TGSE_CHANGE_SERVERS, TGSE_SCORE, TGSE_TENNIS_PLAYERS_WALKING_WAIT, //20 TGSE_QUIT_CONFIRM, TGSE_OUTRO, TGSE_OUTRO_FROM_OPTIONS, TGSE_QUIT_FROM_OPTION_MENU, TGSE_FINISH, //25 TGSE_CLEANUP, TGSE_PREPARE_REMATCH, TGSE_TEST_STATE ENDENUM FUNC STRING GET_STRING_FROM_TENNIS_GAME_STATE(TENNIS_GAME_STATE_ENUM eState) SWITCH eState CASE TGSE_PRE_INIT RETURN "TGSE_PRE_INIT" CASE TGSE_PRE_INIT_WAIT RETURN "TGSE_PRE_INIT_WAIT" CASE TGSE_FRIEND_INIT_WAIT RETURN "TGSE_FRIEND_INIT_WAIT" CASE TGSE_CAMERA_PAN_WAIT RETURN "TGSE_CAMERA_PAN_WAIT" CASE TGSE_INIT RETURN "TGSE_INIT" CASE TGSE_INTRO RETURN "TGSE_INTRO" CASE TGSE_OPTION_MENU RETURN "TGSE_OPTION_MENU" CASE TGSE_OPTION_FINISHED RETURN "TGSE_OPTION_FINISHED" CASE TGSE_PREPARE_SERVE RETURN "TGSE_PREPARE_SERVE" CASE TGSE_SERVE RETURN "TGSE_SERVE" CASE TGSE_SERVE_RESULT RETURN "TGSE_SERVE_RESULT" CASE TGSE_WAIT_FOR_PREDICTION RETURN "TGSE_WAIT_FOR_PREDICTION" CASE TGSE_RALLY RETURN "TGSE_RALLY" CASE TGSE_RALLY_PREDICT RETURN "TGSE_RALLY_PREDICT" CASE TGSE_POINT_WON RETURN "TGSE_POINT_WON" CASE TGSE_POINT_CHECKS RETURN "TGSE_POINT_CHECKS" CASE TGSE_INTERSTITIAL RETURN "TGSE_INTERSTITIAL" CASE TGSE_SIDE_CHANGE RETURN "TGSE_SIDE_CHANGE" CASE TGSE_CHANGE_SERVERS RETURN "TGSE_CHANGE_SERVERS" CASE TGSE_SCORE RETURN "TGSE_SCORE" CASE TGSE_TENNIS_PLAYERS_WALKING_WAIT RETURN "TGSE_TENNIS_PLAYERS_WALKING_WAIT" CASE TGSE_QUIT_CONFIRM RETURN "TGSE_QUIT_CONFIRM" CASE TGSE_OUTRO RETURN "TGSE_OUTRO" CASE TGSE_OUTRO_FROM_OPTIONS RETURN "TGSE_OUTRO_FROM_OPTIONS" CASE TGSE_QUIT_FROM_OPTION_MENU RETURN "TGSE_QUIT_FROM_OPTION_MENU" CASE TGSE_FINISH RETURN "TGSE_FINISH" CASE TGSE_CLEANUP RETURN "TGSE_CLEANUP" CASE TGSE_PREPARE_REMATCH RETURN "TGSE_PREPARE_REMATCH" CASE TGSE_TEST_STATE RETURN "TGSE_TEST_STATE" ENDSWITCH RETURN "Unknown TENNIS_GAME_STATE_ENUM" ENDFUNC ENUM TENNIS_MP_STAT_TRACKING_ENUM TMST_TENNIS_TOTAL_POINTS = 0, TMST_TENNIS_TOTAL_ACES, TMST_TENNIS_TOTAL_ACED, TMST_TENNIS_HIGHEST_DEUCE, TMST_TENNIS_GAMES_WON, TMST_TENNIS_GAMES_LOST, TMST_TENNIS_SETS_WON, TMST_TENNIS_SETS_LOST, TMST_TENNIS_MATCHES_WON, TMST_TENNIS_MATCHES_LOST, TMST_TENNIS_TOTAL_OOB_HITS, TMST_TENNIS_TOTAL_FAULTS, TMST_STAT_TOTAL ENDENUM #IF IS_DEBUG_BUILD FUNC STRING GET_STRING_FROM_TENNIS_MP_STAT_TRACKING_ENUM( TENNIS_MP_STAT_TRACKING_ENUM eStat ) SWITCH eStat CASE TMST_TENNIS_TOTAL_POINTS RETURN "TMST_TENNIS_TOTAL_POINTS" CASE TMST_TENNIS_TOTAL_ACES RETURN "TMST_TENNIS_TOTAL_ACES" CASE TMST_TENNIS_TOTAL_ACED RETURN "TMST_TENNIS_TOTAL_ACED" CASE TMST_TENNIS_HIGHEST_DEUCE RETURN "TMST_TENNIS_HIGHEST_DEUCE" CASE TMST_TENNIS_GAMES_WON RETURN "TMST_TENNIS_GAMES_WON" CASE TMST_TENNIS_GAMES_LOST RETURN "TMST_TENNIS_GAMES_LOST" CASE TMST_TENNIS_SETS_WON RETURN "TMST_TENNIS_SETS_WON" CASE TMST_TENNIS_SETS_LOST RETURN "TMST_TENNIS_SETS_LOST" CASE TMST_TENNIS_MATCHES_WON RETURN "TMST_TENNIS_MATCHES_WON" CASE TMST_TENNIS_MATCHES_LOST RETURN "TMST_TENNIS_MATCHES_LOST" CASE TMST_TENNIS_TOTAL_OOB_HITS RETURN "TMST_TENNIS_TOTAL_OOB_HITS" CASE TMST_TENNIS_TOTAL_FAULTS RETURN "TMST_TENNIS_TOTAL_FAULTS" CASE TMST_STAT_TOTAL RETURN "TMST_STAT_TOTAL" ENDSWITCH RETURN "unknown TENNIS_MP_STAT_TRACKING_ENUM" ENDFUNC #ENDIF INT TENNIS_STAT_TRACKING_ARRAY[TMST_STAT_TOTAL] ENUM LAUNCH_DETAIL_ENUM LD_INVALID = -1, LD_SERVE_S_PLUS = 0, LD_SERVE_S, LD_SERVE_A, LD_SERVE_B, LD_SERVE_C, LD_SERVE_D, LD_SERVE_FAULT, LD_SERVE_OOB, LD_MID, LD_OVERHEAD, MAX_DETAILS ENDENUM FUNC STRING GET_STRING_FROM_TENNIS_SERVE_GRADE(LAUNCH_DETAIL_ENUM eServe) SWITCH eServe CASE LD_INVALID RETURN "LD_INVALID" CASE LD_SERVE_S_PLUS RETURN "LD_SERVE_S_PLUS" CASE LD_SERVE_S RETURN "LD_SERVE_S" CASE LD_SERVE_A RETURN "LD_SERVE_A" CASE LD_SERVE_B RETURN "LD_SERVE_B" CASE LD_SERVE_C RETURN "LD_SERVE_C" CASE LD_SERVE_D RETURN "LD_SERVE_D" CASE LD_SERVE_FAULT RETURN "LD_SERVE_FAULT" CASE LD_SERVE_OOB RETURN "LD_SERVE_OOB" CASE LD_MID RETURN "LD_MID" CASE LD_OVERHEAD RETURN "LD_OVERHEAD" CASE MAX_DETAILS RETURN "MAX_DETAILS" ENDSWITCH RETURN "Unknonwn LAUNCH_DETAIL_ENUM enum" ENDFUNC ENUM SERVING_SIDE_ENUM SERVING_FROM_LEFT = 0, SERVING_FROM_RIGHT = 1 ENDENUM ENUM OPTION_BIT_ENUMS TENNIS_OPTION_NEAR_CAMERA_DEFAULT = BIT0, TENNIS_OPTION_HOLD_RELEASE_SERVE = BIT1, TENNIS_OPTION_1_SET = BIT2, TENNIS_OPTION_3_SET = BIT3, TENNIS_OPTION_5_SET = BIT4 ENDENUM ENUM OPTIONS_STATES OPT_NUM_SETS, OPT_DIFFICULTY, OPT_FINISHED, OPT_SERVE, OPT_CAMERA ENDENUM ENUM TENNIS_ACTIVITY TA_PLAYER_VS_AI, TA_AI_VS_AI, TA_FRIEND_ACTIVITY, TA_FAMILY_ACTIVITY, TA_MULTIPLAYER ENDENUM //Bitmasks needed to transmit info from PROCESS_GAME_STATE to other update functions involving UI //When the bitmask is not needed in PROCESS_GAME_STATE then it can be moved to a different bitmask to make for more room in this enum ENUM TENNIS_UTILS TD_FIRST_SERVE = BIT0, //Used to blend into the first serve of the match from the options screen TD_UPDATE_SCORES = BIT1, // TD_SHOW_TIE_BREAK = BIT2, //set when we want to show the Tie Breaks message TD_MATCH_POINT_DSTAR = BIT3, //MGTN_matp, tho this is an indirect flag that makes the serve flag flip appropriately TD_SERVE_DSTAR = BIT4, //MGTN_serv1 TD_FAULT_DSTAR = BIT5, //MGTN_bad TD_POINT_W_DSTAR = BIT6, //MGTN_winp TD_ACE = BIT7, //Used when showing an Aced serve TD_GAME_WON_DSTAR = BIT8, //MGTN_win TD_GAME_LOST_DSTAR = BIT9, //MGTN_LOS TD_POINT_L_DSTAR = BIT10, //MGTN_losp TD_PAUSE_THE_CUT = BIT11, //Used for waiting a beat after a fault, double fault, or OOB TD_OOB = BIT12, TD_FAULT = BIT13, TD_PAUSE_DIALOGUE = BIT14, TD_GAME_POINT = BIT15, TD_DEUCE = BIT16, TD_ADVANTAGE = BIT17, TD_POINT_WON = BIT18, TD_POINT_LOST = BIT19, TD_GAME_WON = BIT20, TD_GAME_LOST = BIT21, TD_ANIM_PLAYING = BIT22, TD_GAME_DONE_STISH = BIT23, //Set when the game is won, check in conjunction with Happy and Sad bits TD_OPP_HAPPY = BIT24, TD_OPP_SAD = BIT25, TD_PLR_HAPPY = BIT26, TD_PLR_SAD = BIT27, TD_DELAY_THE_CUT_DELAY = BIT28, TD_X_MARKER = BIT29, TD_QUIT_BIT = BIT30 ENDENUM /// PURPOSE: Keeping tabs on the single player gameflow from state to state. Held in thisProps. ENUM TENNIS_FLOW_FLAGS TFF_WALKING_TO_POSITION = BIT0, TFF_STOP_INTERSTITIAL_CAM_POINTING = BIT1, TFF_BALL_RESET_IN_HAND = BIT2, TFF_BASELINE_TRACKING_INIT = BIT3, TFF_GAME_HAS_SHOWN_SIDE_CHANGE_MSG = BIT4, TFF_CALL_SIDE_CHANGE_ONCE = BIT5, TFF_HANDLE_UI_AFTER_SIDE_CHANGE = BIT6, TFF_HANDLE_NEW_SERVE_MSG = BIT7, TFF_SHOWN_SERVE_MESSAGE = BIT8, TFF_CONTINUE_AFTER_VOTE_PASSING = BIT9, TFF_SCLB_RANK_PRED_DONE = BIT10 ENDENUM FUNC STRING GET_STRING_FROM_TENNIS_FLOW_FLAGS(TENNIS_FLOW_FLAGS eFlag) SWITCH eFlag CASE TFF_WALKING_TO_POSITION RETURN "TFF_WALKING_TO_POSITION" CASE TFF_STOP_INTERSTITIAL_CAM_POINTING RETURN "TFF_STOP_INTERSTITIAL_CAM_POINTING" CASE TFF_BALL_RESET_IN_HAND RETURN "TFF_BALL_RESET_IN_HAND" CASE TFF_BASELINE_TRACKING_INIT RETURN "TFF_BASELINE_TRACKING_INIT" CASE TFF_GAME_HAS_SHOWN_SIDE_CHANGE_MSG RETURN "TFF_GAME_HAS_SHOWN_SIDE_CHANGE_MSG" CASE TFF_CALL_SIDE_CHANGE_ONCE RETURN "TFF_CALL_SIDE_CHANGE_ONCE" CASE TFF_HANDLE_UI_AFTER_SIDE_CHANGE RETURN "TFF_HANDLE_UI_AFTER_SIDE_CHANGE" CASE TFF_HANDLE_NEW_SERVE_MSG RETURN "TFF_HANDLE_NEW_SERVE_MSG" CASE TFF_SHOWN_SERVE_MESSAGE RETURN "TFF_SHOWN_SERVE_MESSAGE" CASE TFF_CONTINUE_AFTER_VOTE_PASSING RETURN "TFF_CONTINUE_AFTER_VOTE_PASSING" CASE TFF_SCLB_RANK_PRED_DONE RETURN "TFF_SCLB_RANK_PRED_DONE" ENDSWITCH RETURN "Unknown TENNIS_FLOW_FLAGS enum" ENDFUNC ENUM TENNIS_CONVO_FLAGS TCVF_MIKE_TREVOR_SERVE_PLAYED = BIT0, TCVF_LONG_RALLY = BIT1, TCVF_MIKE_AMANDA_SERVE_PLAYED = BIT2, TCVF_TREVOR_AMANDA_SERVE_PLAYED = BIT3, TCVF_AMANDA_SERVE_TO_MICHAEL = BIT4, TCVF_AMANDA_SERVE_TO_TREVOR = BIT5, TCVF_AMANDA_CHAT_BAD_SELF = BIT6, TCVF_MIKE_CHAT = BIT7, TCVF_INTRO_OPP_HECKLE = BIT8, TCVF_INTRO_PLYR_RETORT = BIT9, TCVF_PLAY_AS_AMBIENT_SPEECH = BIT10, TCVF_AMANDA_GETS_LAST_WORD = BIT11 ENDENUM FUNC STRING GET_STRING_FROM_TENNIS_CONVO_FLAG(TENNIS_CONVO_FLAGS eFlag) SWITCH eFlag CASE TCVF_MIKE_TREVOR_SERVE_PLAYED RETURN "TCVF_MIKE_TREVOR_SERVE_PLAYED" CASE TCVF_LONG_RALLY RETURN "TCVF_LONG_RALLY" CASE TCVF_MIKE_AMANDA_SERVE_PLAYED RETURN "TCVF_MIKE_AMANDA_SERVE_PLAYED" CASE TCVF_TREVOR_AMANDA_SERVE_PLAYED RETURN "TCVF_TREVOR_AMANDA_SERVE_PLAYED" CASE TCVF_AMANDA_SERVE_TO_MICHAEL RETURN "TCVF_AMANDA_SERVE_TO_MICHAEL" CASE TCVF_AMANDA_SERVE_TO_TREVOR RETURN "TCVF_AMANDA_SERVE_TO_TREVOR" CASE TCVF_AMANDA_CHAT_BAD_SELF RETURN "TCVF_AMANDA_CHAT_BAD_SELF" CASE TCVF_MIKE_CHAT RETURN "TCVF_MIKE_CHAT" CASE TCVF_PLAY_AS_AMBIENT_SPEECH RETURN "TCVF_PLAY_AS_AMBIENT_SPEECH" CASE TCVF_INTRO_OPP_HECKLE RETURN "TCVF_INTRO_OPP_HECKLE" CASE TCVF_INTRO_PLYR_RETORT RETURN "TCVF_INTRO_PLYR_RETORT" CASE TCVF_AMANDA_GETS_LAST_WORD RETURN "TCVF_AMANDA_GETS_LAST_WORD" ENDSWITCH RETURN "unknown TENNIS_CONVO_FLAGS enum" ENDFUNC ENUM TENNIS_MATCH_RULESET TMR_SETS = 0, TMR_ONE_GAME, TMR_THREE_GAMES, TMR_FIVE_GAMES, TMR_MAX_RULES ENDENUM FUNC STRING GET_STRING_FROM_TENNIS_RULESET(TENNIS_MATCH_RULESET eRules) RETURN PICK_STRING(eRules = TMR_SETS, "TMR_SETS", PICK_STRING(eRules = TMR_ONE_GAME, "TMR_ONE_GAME", PICK_STRING(eRules = TMR_THREE_GAMES, "TMR_THREE_GAMES", PICK_STRING(eRules = TMR_FIVE_GAMES, "TMR_FIVE_GAMES", PICK_STRING(eRules = TMR_MAX_RULES, "TMR_MAX_RULES", "Unknown Ruleset"))))) ENDFUNC ENUM TENNIS_SP_FLAGS TSP_PICK_OUT_ABUSIVE_PED = BIT0, TSP_MONITOR_ABUSE_SEQUENCE = BIT1, TSP_GUARANTEE_FIRST_ABUSE = BIT2, TSP_PRINT_FIRST_TUT_HELP = BIT3, TSP_PRINT_SECOND_TUT_HELP = BIT4, TSP_TUT_SERVE_SET = BIT5 ENDENUM FUNC STRING GET_STRING_FROM_TENNIS_SP_FLAG(TENNIS_SP_FLAGS eFlag) SWITCH eFlag CASE TSP_PICK_OUT_ABUSIVE_PED RETURN "TSP_PICK_OUT_ABUSIVE_PED" CASE TSP_MONITOR_ABUSE_SEQUENCE RETURN "TSP_MONITOR_ABUSE_SEQUENCE" CASE TSP_GUARANTEE_FIRST_ABUSE RETURN "TSP_GUARANTEE_FIRST_ABUSE" CASE TSP_PRINT_FIRST_TUT_HELP RETURN "TSP_PRINT_FIRST_TUT_HELP" CASE TSP_PRINT_SECOND_TUT_HELP RETURN "TSP_PRINT_SECOND_TUT_HELP" CASE TSP_TUT_SERVE_SET RETURN "TSP_TUT_SERVE_SET" ENDSWITCH RETURN "Unknown TennisSP Flag" ENDFUNC ENUM TENNIS_SERVE_VALIDATION TENNIS_SERVE_INVALID, TENNIS_SERVE_SUCCESS, TENNIS_SERVE_FAILSAFE ENDENUM FUNC STRING GET_STRING_FROM_TENNIS_SERVE_VALIDATION(TENNIS_SERVE_VALIDATION eValidation) SWITCH eValidation CASE TENNIS_SERVE_INVALID RETURN "TENNIS_SERVE_INVALID" CASE TENNIS_SERVE_SUCCESS RETURN "TENNIS_SERVE_SUCCESS" CASE TENNIS_SERVE_FAILSAFE RETURN "TENNIS_SERVE_FAILSAFE" ENDSWITCH RETURN "unknown TENNIS_SERVE_VALIDATION" ENDFUNC /// ******************************************************* STRUCTS *************************************************************************** STRUCT TENNIS_SWING_PHASES FLOAT fInit = -1.0 FLOAT fActive = -1.0 FLOAT fEnd = -1.0 INT iFrameTot = -1 TEXT_LABEL_31 sAnimName ENDSTRUCT STRUCT TENNIS_SCORES INT iPointsWon INT iGamesWon[MAX_SETS] INT iSetsWon ENDSTRUCT STRUCT TENNIS_GAME_PROPERTIES //Single AND Multi TENNIS_PLAYER tennisPlayers[TENNIS_PLAYERS] TENNIS_COURT tennisCourt TENNIS_BALL tennisBall INT iFrameCounter LAUNCH_DETAILS grades[MAX_DETAILS] VECTOR vSwingStateOffsets[TSS_MAX_SWINGS] TENNIS_SWING_PHASES phasesArray[TSS_MAX_SWINGS] TENNIS_SWING_STATES swingBuckets[MAX_SWING_BUCKETS][MAX_SWINGS_PER_BUCKET] FLOAT swingBucketSteps[MAX_SWING_BUCKETS+1] VECTOR vFuturePoints[MAX_FUTURE_POINTS] enumActivityLocation thisLocation TENNIS_ACTIVITY eTennisActivity VECTOR vForward,vRight,vUp // Rereference frame BOOL bCheckPredictionFlag MODEL_NAMES mTheOpponentModel MODEL_NAMES mThePlayerAIModel TEXT_LABEL_7 texIdleEvent INT iTimerA TENNIS_FLOW_FLAGS eFlowFlags INT iBallResetStamp structTimer tServe INT iDelayNextUITimeStamp // used to delay the tiebreak message TENNIS_PLAYER_ID eCachedScoredLast // Changed locally because we want to start the walk sooner but can't rely on server data #IF IS_TENNIS_MULTIPLAYER TENNIS_SCORES cachedMPScores[TENNIS_PLAYERS] // cached these for earlier calculations for walking to position, can't rely on server data in time INT iCachedCurrentSet // Cached because the set from the server can change before we've done our game/set won message calculations TENNIS_BALL lerpBall #ENDIF #IF IS_DEBUG_BUILD TENNIS_WIDGET_DATA tennisWidgets #ENDIF ENDSTRUCT STRUCT TENNIS_GAME_STATUS 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_GAME_STATE_ENUM ePausedFromState TENNIS_SCORES playerScores[TENNIS_PLAYERS] TENNIS_MATCH_RULESET eRuleset BOOL bRematch = FALSE BOOL bTieBreakOn INT iAIWait INT iNumSets = 1 INT iServeCount INT iCurrentSet FLOAT fPointTimer ENDSTRUCT STRUCT TENNIS_GAME_SP_DATA //Single AI_DIFFICULTY eDifficulty = AD_EASY VECTOR vQuitPoint OBJECT_INDEX oCollBox[4] PED_VARIATION_STRUCT sVariations VEHICLE_SAVE_ARGS playerVehicle FLOAT fAbuseTimer SCENARIO_BLOCKING_INDEX blockingArea[4] VECTOR vBlockingArea[6] VECTOR vNonCreationArea[2] OBJECT_INDEX oLighting TENNIS_SP_FLAGS eSPFlags PED_INDEX pedAbuser PED_VARIATION_STRUCT sOppVariations OBJECT_INDEX oBottle ENDSTRUCT STRUCT TENNIS_GAME_UI_DATA TENNIS_CAMERAS tennisCameras TENNIS_UI tennisUI UI_STATE_ENUM eUIState UI_STATE_ENUM ePrevUIState enumCharacterList playerChars[TENNIS_PLAYERS] TENNIS_PLAYER_ID eInterstitialPlayer STRING playerNames[TENNIS_PLAYERS] VECTOR vInterstitialOffset // menu selections INT iRulesSelection = 3 INT iDiffSelection = 1 INT iCurrentOption = 0 // conversation struct structPedsForConversation myDialogueStruct // bitflags INT iUtilFlags INT iPrevUtilFlags TENNIS_CONVO_FLAGS eConvoFlags INT iBS // Used for Conor's offline SCLB screen // in-game counters INT iDeuceCount = 1 INT iRallyCounter INT iNumWalksSinceCut // cached sync scene ID INT iSceneID // Tracking the anims played for peds, got complicated because we have to track each happy and sad anim for both players INT iLastPlayerHappyAnim INT iLastAIHappyAnim INT iUsedPlayerHappyAnims[NUM_PLAYER_ANIMS] INT iUsedAIHappyAnims[NUM_AI_ANIMS] INT iLastPlayerSadAnim INT iLastAISadAnim INT iUsedPlayerSadAnims[NUM_PLAYER_ANIMS] INT iUsedAISadAnims[NUM_AI_ANIMS] // frame/time stamps INT iQuitWaitStamp INT iLongRallyConvoStamp // used for interstitials and cutscenes STRING sSubtitleGroupID TEXT_LABEL_63 sInterstitialDict TEXT_LABEL_31 sInterstitialPlrAnim TEXT_LABEL_31 sInterstitialCamAnim TEXT_LABEL_63 sInterstitialFaceDict TEXT_LABEL_31 sInterstitialFaceAnim // Timers FLOAT fMessageTimer FLOAT fInterstitialTime structTimer interstitialTimer structTimer trackingTimer // Currently deprecated // (x, y) of the swing meter FLOAT fSwingMeterX FLOAT fSwingMeterY // Camera offsets FLOAT fFarCamBaseOffset FLOAT fFarCamOtherSideBaseOffset #IF IS_TENNIS_MULTIPLAYER PEDHEADSHOT_ID myPedHeadshots[TENNIS_PLAYERS] BOOL bHeadshotStarted[TENNIS_PLAYERS] BOOL bHeadshotRegistered[TENNIS_PLAYERS] CELEBRATION_SCREEN_DATA sCelebData GENERIC_MINIGAME_STAGE eGenericMGStage #ENDIF ENDSTRUCT STRUCT TENNISMP_LOADING_SPINNER SCALEFORM_INDEX spinnerMovie SCALEFORM_LOADING_ICON loadingStruct ENDSTRUCT /// ******************************************************* FUNCTIONS *************************************************************************** #IF IS_TENNIS_MULTIPLAYER PROC SET_TENNIS_MP_PROPS_CACHED_SET(TENNIS_GAME_PROPERTIES &thisProps, INT iCachedValue) CDEBUG3LN(DEBUG_TENNIS, "SET_TENNIS_MP_PROPS_CACHED_SET :: iCachedValue=", iCachedValue) thisProps.iCachedCurrentSet = iCachedValue ENDPROC FUNC INT GET_TENNIS_MP_PROPS_CACHED_SET(TENNIS_GAME_PROPERTIES &thisProps) RETURN thisProps.iCachedCurrentSet ENDFUNC #ENDIF PROC SET_TENNIS_PROPS_DELAY_NEXT_UI_TIME_STAMP(TENNIS_GAME_PROPERTIES &thisProps, INT iNewStamp) CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_PROPS_DELAY_NEXT_UI_TIME_STAMP :: iNewStamp=", iNewStamp) thisProps.iDelayNextUITimeStamp = iNewStamp ENDPROC FUNC INT GET_TENNIS_PROPS_DELAY_NEXT_UI_TIME_STAMP(TENNIS_GAME_PROPERTIES &thisProps) RETURN thisProps.iDelayNextUITimeStamp ENDFUNC PROC SET_TENNIS_STATUS_NUMBER_OF_SETS(TENNIS_GAME_STATUS &thisStatus, INT iNewSets) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_STATUS_NUMBER_OF_SETS :: ", thisStatus.iNumSets) thisStatus.iNumSets = iNewSets ENDPROC FUNC INT GET_TENNIS_STATUS_NUM_SETS(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.iNumSets ENDFUNC PROC SET_TENNIS_LONG_RALLY_CONVO_STAMP(TENNIS_GAME_UI_DATA &thisUIData, INT iNewStamp) thisUIData.iLongRallyConvoStamp = iNewStamp ENDPROC FUNC INT GET_TENNIS_LONG_RALLY_CONVO_STAMP(TENNIS_GAME_UI_DATA &thisUIData) RETURN thisUIData.iLongRallyConvoStamp ENDFUNC PROC SET_TENNIS_PROPS_BALL_RESET_STAMP(TENNIS_GAME_PROPERTIES &thisProps, INT iNewStamp) thisProps.iBallResetStamp = iNewStamp ENDPROC FUNC INT GET_TENNIS_PROPS_BALL_RESET_STAMP(TENNIS_GAME_PROPERTIES &thisProps) RETURN thisProps.iBallResetStamp ENDFUNC PROC SET_TENNIS_FLOW_FLAG(TENNIS_GAME_PROPERTIES &thisProps, TENNIS_FLOW_FLAGS eFlag) CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_FLOW_FLAG :: Setting ", GET_STRING_FROM_TENNIS_FLOW_FLAGS(eFlag)) thisProps.eFlowFlags = thisProps.eFlowFlags | eFlag ENDPROC PROC CLEAR_TENNIS_FLOW_FLAG(TENNIS_GAME_PROPERTIES &thisProps, TENNIS_FLOW_FLAGS eFlag) CDEBUG2LN(DEBUG_TENNIS, "CLEAR_TENNIS_FLOW_FLAG :: Clearing ", GET_STRING_FROM_TENNIS_FLOW_FLAGS(eFlag)) thisProps.eFlowFlags -= thisProps.eFlowFlags & eFlag ENDPROC FUNC BOOL IS_TENNIS_FLOW_FLAG_SET(TENNIS_GAME_PROPERTIES &thisProps, TENNIS_FLOW_FLAGS eFlag) RETURN (ENUM_TO_INT(thisProps.eFlowFlags) & ENUM_TO_INT(eFlag)) <> 0 ENDFUNC PROC SET_TENNIS_CONVO_FLAG(TENNIS_GAME_UI_DATA &thisUIData, TENNIS_CONVO_FLAGS eFlag) CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_CONVO_FLAG :: Setting ", GET_STRING_FROM_TENNIS_CONVO_FLAG(eFlag)) thisUIData.eConvoFlags = thisUIData.eConvoFlags | eFlag ENDPROC PROC CLEAR_TENNIS_CONVO_FLAG(TENNIS_GAME_UI_DATA &thisUIData, TENNIS_CONVO_FLAGS eFlag) CDEBUG2LN(DEBUG_TENNIS, "CLEAR_TENNIS_CONVO_FLAG :: Clearing ", GET_STRING_FROM_TENNIS_CONVO_FLAG(eFlag)) thisUIData.eConvoFlags -= thisUIData.eConvoFlags & eFlag ENDPROC FUNC BOOL IS_TENNIS_CONVO_FLAG_SET(TENNIS_GAME_UI_DATA &thisUIData, TENNIS_CONVO_FLAGS eFlag) RETURN (ENUM_TO_INT(thisUIData.eConvoFlags) & ENUM_TO_INT(eFlag)) <> 0 ENDFUNC PROC SET_TENNIS_QUIT_WAIT_STAMP(TENNIS_GAME_UI_DATA &thisUIData, INT iNewStamp) thisUIData.iQuitWaitStamp = iNewStamp ENDPROC FUNC INT GET_TENNIS_QUIT_WAIT_STAMP(TENNIS_GAME_UI_DATA &thisUIData) RETURN thisUIData.iQuitWaitStamp ENDFUNC PROC SET_TENNIS_SP_FLAG(TENNIS_GAME_SP_DATA &thisSPData, TENNIS_SP_FLAGS eFlag) CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_SP_FLAG :: Setting ", GET_STRING_FROM_TENNIS_SP_FLAG(eFlag)) thisSPData.eSPFlags = thisSPData.eSPFlags | eFlag ENDPROC PROC CLEAR_TENNIS_SP_FLAG(TENNIS_GAME_SP_DATA &thisSPData, TENNIS_SP_FLAGS eFlag) CDEBUG2LN(DEBUG_TENNIS, "CLEAR_TENNIS_SP_FLAG :: Clearing ", GET_STRING_FROM_TENNIS_SP_FLAG(eFlag)) thisSPData.eSPFlags -= thisSPData.eSPFlags & eFlag ENDPROC FUNC BOOL IS_TENNIS_SP_FLAG_SET(TENNIS_GAME_SP_DATA &thisSPData, TENNIS_SP_FLAGS eFlag) RETURN (ENUM_TO_INT(thisSPData.eSPFlags) & ENUM_TO_INT(eFlag)) <> 0 ENDFUNC PROC SET_TENNIS_RALLY_COUNTER(TENNIS_GAME_UI_DATA &thisUIData, INT iNewCount) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_RALLY_COUNTER(", iNewCount, ")") thisUIData.iRallyCounter = iNewCount ENDPROC FUNC INT GET_TENNIS_RALLY_COUNTER(TENNIS_GAME_UI_DATA &thisUIData) RETURN thisUIData.iRallyCounter ENDFUNC PROC SET_TENNIS_TIMER_A(TENNIS_GAME_PROPERTIES &thisProps, INT i) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_TIMER_A :: thisProps.iTimerA(", i, ")") thisProps.iTimerA = i ENDPROC /// PURPOSE: /// Returns in ms /// PARAMS: /// thisProps - /// RETURNS: /// FUNC INT GET_TENNIS_TIMER_A(TENNIS_GAME_PROPERTIES &thisProps) RETURN thisProps.iTimerA ENDFUNC /// PURPOSE: /// Updates in ms /// PARAMS: /// thisProps - PROC UPDATE_TENNIS_TIMER_A(TENNIS_GAME_PROPERTIES &thisProps) thisProps.iTimerA += ROUND(GET_FRAME_TIME() * 1000) ENDPROC PROC SET_TENNIS_STATUS_REMATCH(TENNIS_GAME_STATUS &thisStatus, BOOL bIsRematch) thisStatus.bRematch = bIsRematch ENDPROC FUNC BOOL GET_TENNIS_STATUS_REMATCH(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.bRematch ENDFUNC PROC SET_TENNIS_STATUS_POINT_TIMER(TENNIS_GAME_STATUS &thisStatus, FLOAT fVal = 0.0) thisStatus.fPointTimer = fVal ENDPROC FUNC FLOAT GET_TENNIS_STATUS_POINT_TIMER(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.fPointTimer ENDFUNC /// PURPOSE: /// increments thisStatus.fPointTimer by GET_FRAME_TIME /// PARAMS: /// thisStatus - PROC UPDATE_TENNIS_STATUS_POINT_TIMER(TENNIS_GAME_STATUS &thisStatus) thisStatus.fPointTimer += GET_FRAME_TIME() ENDPROC PROC INCREASE_TENNIS_ABUSE_TIMER(TENNIS_GAME_SP_DATA &thisSPData) thisSPData.fAbuseTimer += GET_FRAME_TIME() ENDPROC FUNC FLOAT GET_TENNIS_ABUSE_TIMER(TENNIS_GAME_SP_DATA &thisSPData) RETURN thisSPData.fAbuseTimer ENDFUNC PROC RESET_TENNIS_ABUSE_TIMER(TENNIS_GAME_SP_DATA &thisSPData) CDEBUG2LN(DEBUG_TENNIS, "RESET_TENNIS_ABUSE_TIMER timerWas=", thisSPData.fAbuseTimer) thisSPData.fAbuseTimer = 0 ENDPROC PROC SET_TENNIS_SET_TIE_BREAK(TENNIS_GAME_STATUS &thisStatus, BOOL bOnTieBreak) CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_SET_TIE_BREAK :: bOnTieBreak=", PICK_STRING(bOnTieBreak, "TRUE", "FALSE")) thisStatus.bTieBreakOn = bOnTieBreak ENDPROC FUNC BOOL IS_TENNIS_SET_ON_TIE_BREAK(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.bTieBreakOn ENDFUNC PROC SET_TENNIS_MATCH_RULESET(TENNIS_GAME_STATUS &thisStatus, TENNIS_MATCH_RULESET eNewRuleset) thisStatus.eRuleset = eNewRuleset ENDPROC FUNC TENNIS_MATCH_RULESET GET_TENNIS_MATCH_RULESET(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.eRuleset ENDFUNC FUNC INT GET_TENNIS_STATUS_CURRENT_SET(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.iCurrentSet ENDFUNC PROC SET_TENNIS_INTERSTITIAL_PLAYER(TENNIS_GAME_UI_DATA &thisUIData, TENNIS_PLAYER_ID eNewPlayer) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_INTERSTITIAL_PLAYER :: setting to ", GET_STRING_FROM_TENNIS_PLAYER_ID(eNewPlayer)) thisUIData.eInterstitialPlayer = eNewPlayer ENDPROC FUNC TENNIS_PLAYER_ID GET_TENNIS_INTERSTITIAL_PLAYER(TENNIS_GAME_UI_DATA &thisUIData) RETURN thisUIData.eInterstitialPlayer ENDFUNC PROC INCREASE_TENNIS_FRAME_COUNTER(INT &iFrameCounter) iFrameCounter++ ENDPROC FUNC INT GET_TENNIS_FRAME_COUNTER(TENNIS_GAME_PROPERTIES &thisProps) RETURN thisProps.iFrameCounter ENDFUNC PROC SET_TENNIS_STATUS_WHO_IS_SERVING(TENNIS_GAME_STATUS &thisStatus, TENNIS_PLAYER_ID eNewServer) thisStatus.eWhoIsServing = eNewServer ENDPROC FUNC TENNIS_PLAYER_ID GET_TENNIS_STATUS_WHO_IS_SERVING(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.eWhoIsServing ENDFUNC /// PURPOSE: /// Pass in the playerScores you want to increase the score of. /// PARAMS: /// scores - /// iUtilFlags - PROC INCREASE_TENNIS_POINTS_WON(TENNIS_SCORES &scores, INT &iUtilFlags) #IF IS_DEBUG_BUILD IF NOT DO_NOT_TRACK_SCORE #ENDIF scores.iPointsWon++ SET_BITMASK_AS_ENUM(iUtilFlags, TD_UPDATE_SCORES) #IF IS_DEBUG_BUILD ENDIF #ENDIF ENDPROC /// PURPOSE: /// Pass in the struct for both players as an array, this will reset the points won /// PARAMS: /// scores - /// eSelfID - /// iUtilFlags - PROC RESET_TENNIS_POINTS_WON(TENNIS_SCORES &scores[], INT &iUtilFlags) scores[0].iPointsWon = 0 scores[1].iPointsWon = 0 SET_BITMASK_AS_ENUM(iUtilFlags, TD_UPDATE_SCORES) ENDPROC /// PURPOSE: /// mutator for the player who hit the ball last /// PARAMS: /// thisStatus - /// playerID - PROC SET_TENNIS_STATUS_HIT_LAST(TENNIS_GAME_STATUS &thisStatus, TENNIS_PLAYER_ID playerID) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_STATUS_HIT_LAST: Setting Stroke Flags, ", GET_STRING_FROM_TENNIS_PLAYER_ID(playerID), " just hit the ball.") thisStatus.eHitLast = playerID ENDPROC /// PURPOSE: /// accessor for the player who hit the ball last /// PARAMS: /// thisStatus - /// RETURNS: /// FUNC TENNIS_PLAYER_ID GET_TENNIS_STATUS_HIT_LAST(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.eHitLast ENDFUNC /// PURPOSE: /// mutator for the delay given to ambient AI games /// prevents ambient games from being exactly in sync when they start /// PARAMS: /// thisStatus - /// iNewWait - PROC SET_TENNIS_STATUS_AI_WAIT(TENNIS_GAME_STATUS &thisStatus, INT iNewWait) thisStatus.iAIWait = iNewWait CPRINTLN(DEBUG_TENNIS, "AI Wait time set to: ", iNewWait) ENDPROC /// PURPOSE: /// accessor for the delay given to ambient AI games /// prevents ambient games from being exactly in sync when they start /// PARAMS: /// thisStatus - /// RETURNS: /// FUNC INT GET_TENNIS_STATUS_AI_WAIT(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.iAIWait ENDFUNC /// PURPOSE: /// mutator for the player's name /// PARAMS: /// thisUIData - /// eSelfID - The ID in the player array, either eSelfID or eOtherID /// newName - PROC SET_TENNIS_PLAYER_NAME(TENNIS_GAME_UI_DATA &thisUIData, TENNIS_PLAYER_ID eSelfID, STRING newName) thisUIData.playerNames[eSelfID] = newName ENDPROC /// PURPOSE: /// accessor for player's name /// PARAMS: /// thisUIData - /// ePlayerID - /// RETURNS: /// FUNC STRING GET_TENNIS_PLAYER_NAME(TENNIS_GAME_UI_DATA &thisUIData, TENNIS_PLAYER_ID ePlayerID) RETURN thisUIData.playerNames[ePlayerID] ENDFUNC /// PURPOSE: /// Call GET_TENNIS_PED_VARIATIONS before using this function /// PARAMS: /// ped - the ped index of the tennis player you're outfitting /// thisChar - the character enum for the ped above PROC SET_TENNIS_OUTFIT(PED_INDEX ped, enumCharacterList thisChar) //Change player ped into tennis outfit here. IF thisChar = CHAR_MICHAEL SET_PED_COMP_ITEM_CURRENT_SP(ped, COMP_TYPE_OUTFIT, OUTFIT_P0_TENNIS, FALSE) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_OUTFIT Michael") ELIF thisChar = CHAR_TREVOR SET_PED_COMP_ITEM_CURRENT_SP(ped, COMP_TYPE_OUTFIT, OUTFIT_P2_TENNIS, FALSE) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_OUTFIT Trevor") ELIF thisChar = CHAR_LAMAR CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_OUTFIT Lamar") SET_PED_COMPONENT_VARIATION(ped, PED_COMP_TORSO, 1, 0) SET_PED_COMPONENT_VARIATION(ped, PED_COMP_LEG, 1, 0) ELIF thisChar = CHAR_AMANDA CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_OUTFIT Amanda") SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,0), 0, 0) SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,1), 0, 0) SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,2), 0, 0) SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,3), 0, 0) SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,4), 0, 0) SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,5), 0, 0) SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,7), 0, 0) SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,8), 0, 0) SET_PED_COMPONENT_VARIATION(ped, INT_TO_ENUM(PED_COMPONENT,10), 0, 0) ELIF thisChar = CHAR_JIMMY CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_OUTFIT Jimmy") SET_PED_COMPONENT_VARIATION(ped, PED_COMP_BERD, 1, 0) SET_PED_COMPONENT_VARIATION(ped, PED_COMP_TORSO, 5, 1) SET_PED_COMPONENT_VARIATION(ped, PED_COMP_LEG, 3, 1) SET_PED_COMPONENT_VARIATION(ped, PED_COMP_DECL, 1, 0) ELSE CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_OUTFIT :: Ped is not Michael, Trevor, Franklin, Amanda, or Lamar. Not changing outfit.") ENDIF ENDPROC PROC SET_TENNIS_SCORED_LAST(TENNIS_GAME_STATUS &thisStatus, TENNIS_PLAYER_ID whoScored) thisStatus.eScoredLast = whoScored CPRINTLN(DEBUG_TENNIS, "Setting Scored Last to ", PICK_STRING(thisStatus.eScoredLast = TENNIS_PLAYER_AWAY, "TENNIS_PLAYER_AWAY", "TENNIS_PLAYER_HOME")) ENDPROC FUNC TENNIS_PLAYER_ID GET_TENNIS_STATUS_SCORED_LAST(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.eScoredLast ENDFUNC PROC SET_TENNIS_SERVING_SIDE(TENNIS_GAME_STATUS &thisStatus, SERVING_SIDE_ENUM newSide) CDEBUG1LN(DEBUG_TENNIS, "SET_TENNIS_SERVING_SIDE: Setting to ", ENUM_TO_INT(newSide)) thisStatus.eServingSide = newSide ENDPROC FUNC SERVING_SIDE_ENUM GET_TENNIS_SERVING_SIDE(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.eServingSide ENDFUNC FUNC FLOAT GET_TENNIS_REACT_ANIM_TIME(STRING sReactAnim) CPRINTLN(DEBUG_TENNIS, "GET_TENNIS_REACT_ANIM_TIME :: ", sReactAnim) IF ARE_STRINGS_EQUAL(sReactAnim, "react_lose_01") RETURN (125 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_lose_02") RETURN (155 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_lose_03") RETURN (135 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_lose_04") RETURN (195 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_lose_05") RETURN (135 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_win_01") RETURN (114 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_win_02") RETURN (144 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_win_03") RETURN (155 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_win_04") RETURN (139 * 0.033) ENDIF IF ARE_STRINGS_EQUAL(sReactAnim, "react_win_05") RETURN (150 * 0.033) ENDIF CPRINTLN(DEBUG_TENNIS, "GET_TENNIS_REACT_ANIM_TIME :: Returning ANIM_PLAYING_TIME") RETURN ANIM_PLAYING_TIME ENDFUNC PROC RESET_TENNIS_TIMER_AND_INTERSTITIAL_TIME(TENNIS_GAME_UI_DATA &thisUIData, FLOAT newTime) CPRINTLN(DEBUG_TENNIS, "RESET_TENNIS_TIMER_AND_INTERSTITIAL_TIME newTime=", newTime) RESTART_TIMER_NOW(thisUIData.interstitialTimer) thisUIData.fInterstitialTime = newTime ENDPROC PROC SET_TENNIS_ANIM_REACTION_FLAGS(INT &iUtilFlags, TENNIS_UTILS thisBitmask) CLEAR_BITMASK_AS_ENUM(iUtilFlags, TD_PLR_HAPPY) CLEAR_BITMASK_AS_ENUM(iUtilFlags, TD_PLR_SAD) CLEAR_BITMASK_AS_ENUM(iUtilFlags, TD_OPP_HAPPY) CLEAR_BITMASK_AS_ENUM(iUtilFlags, TD_OPP_SAD) SET_BITMASK_AS_ENUM(iUtilFlags, thisBitmask) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_ANIM_REACTION_FLAGS: Turning on thisBitmask: ", PICK_STRING(thisBitmask = TD_PLR_HAPPY, "TD_PLR_HAPPY", PICK_STRING(thisBitmask = TD_PLR_SAD, "TD_PLR_SAD", PICK_STRING(thisBitmask = TD_OPP_HAPPY, "TD_OPP_HAPPY", PICK_STRING(thisBitmask = TD_OPP_SAD, "TD_OPP_SAD", "bitmask is invalid"))))) ENDPROC PROC SET_TENNIS_PLAYER_NAME_OFF_ENUM(TENNIS_GAME_UI_DATA &thisUIData, TENNIS_PLAYER_ID eSelfID) SWITCH thisUIData.playerChars[eSelfID] CASE CHAR_MICHAEL SET_TENNIS_PLAYER_NAME(thisUIData, eSelfID, "MICHAEL") BREAK CASE CHAR_FRANKLIN SET_TENNIS_PLAYER_NAME(thisUIData, eSelfID, "FRANKLIN") BREAK CASE CHAR_TREVOR SET_TENNIS_PLAYER_NAME(thisUIData, eSelfID, "TREVOR") BREAK CASE CHAR_LAMAR SET_TENNIS_PLAYER_NAME(thisUIData, eSelfID, "LAMAR") BREAK CASE CHAR_AMANDA SET_TENNIS_PLAYER_NAME(thisUIData, eSelfID, "AMANDA") BREAK CASE CHAR_JIMMY SET_TENNIS_PLAYER_NAME(thisUIData, eSelfID, "JIMMY") BREAK DEFAULT SET_TENNIS_PLAYER_NAME(thisUIData, eSelfID, "TENNIS_OPP") BREAK ENDSWITCH ENDPROC FUNC TENNIS_GAME_STATE_ENUM GET_TENNIS_GAME_STATE(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.eGameState ENDFUNC /// PURPOSE: /// Sets the current game state and stores the previous state /// Do not use this accessor when moving to TGSE_QUIT_CONFIRM, use SET_TENNIS_GAME_STATE_QUIT /// PARAMS: /// thisStatus - /// newTGSE - PROC SET_TENNIS_GAME_STATE(TENNIS_GAME_STATUS &thisStatus, TENNIS_GAME_STATE_ENUM newTGSE) IF newTGSE = TGSE_QUIT_CONFIRM OR GET_TENNIS_GAME_STATE(thisStatus) = TGSE_QUIT_CONFIRM SCRIPT_ASSERT("Do not use SET_TENNIS_GAME_STATE to enter or exit the quit state, use SET_TENNIS_GAME_STATE_QUIT or RETURN_FROM_TENNIS_QUIT_STATE instead") ELIF GET_TENNIS_GAME_STATE(thisStatus) <> newTGSE thisStatus.ePrevGameState = GET_TENNIS_GAME_STATE(thisStatus) thisStatus.eGameState = newTGSE CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_GAME_STATE Previous State=", GET_STRING_FROM_TENNIS_GAME_STATE(thisStatus.ePrevGameState), ", new state=", GET_STRING_FROM_TENNIS_GAME_STATE(newTGSE)) ELSE CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_GAME_STATE Trying to set state to same state=", GET_STRING_FROM_TENNIS_GAME_STATE(newTGSE)) ENDIF ENDPROC /// PURPOSE: /// Used when entering the quit state, does not alter the previous game state variable as that is used for important tracking calculations /// PARAMS: /// thisStatus - PROC SET_TENNIS_GAME_STATE_QUIT(TENNIS_GAME_STATUS &thisStatus) thisStatus.ePausedFromState = GET_TENNIS_GAME_STATE(thisStatus) IF thisStatus.ePausedFromState < TGSE_OPTION_FINISHED thisStatus.eGameState = TGSE_QUIT_FROM_OPTION_MENU ELSE thisStatus.eGameState = TGSE_QUIT_CONFIRM ENDIF CPRINTLN(DEBUG_TENNIS, "entering quit state") ENDPROC /// PURPOSE: /// Used when returning from TGSE_QUIT_CONFIRM /// PARAMS: /// thisStatus - PROC RETURN_FROM_TENNIS_QUIT_STATE(TENNIS_GAME_STATUS &thisStatus) thisStatus.eGameState = thisStatus.ePausedFromState CPRINTLN(DEBUG_TENNIS, "Returning from quit state") ENDPROC FUNC UI_STATE_ENUM GET_TENNIS_UI_STATE(TENNIS_GAME_UI_DATA &thisUIData) RETURN thisUIData.eUIState ENDFUNC FUNC STRING GET_STRING_FROM_TENNIS_UI_STATE(UI_STATE_ENUM eUI) RETURN PICK_STRING(eUI = TENNIS_UI_SET_INIT, "TENNIS_UI_SET_INIT", PICK_STRING(eUI = TENNIS_UI_SET_SELECT, "TENNIS_UI_SET_SELECT", PICK_STRING(eUI = TENNIS_UI_SET_CONVO, "TENNIS_UI_SET_CONVO", PICK_STRING(eUI = TENNIS_UI_DIFF_INIT, "TENNIS_UI_DIFF_INIT", PICK_STRING(eUI = TENNIS_UI_DIFF_SELECT, "TENNIS_UI_DIFF_SELECT", PICK_STRING(eUI = TENNIS_UI_REMATCH, "TENNIS_UI_REMATCH", PICK_STRING(eUI = TENNIS_UI_AIM, "TENNIS_UI_AIM", PICK_STRING(eUI = TENNIS_UI_SPIN1, "TENNIS_UI_SPIN1", PICK_STRING(eUI = TENNIS_UI_SPIN2, "TENNIS_UI_SPIN2", PICK_STRING(eUI = TENNIS_UI_STROKES, "TENNIS_UI_STROKES", PICK_STRING(eUI = TENNIS_UI_HELP_SERVE, "TENNIS_UI_HELP_SERVE", PICK_STRING(eUI = TENNIS_UI_PLAYING, "TENNIS_UI_PLAYING", PICK_STRING(eUI = TENNIS_UI_STRONG_SWING, "TENNIS_UI_STRONG_SWING", PICK_STRING(eUI = TENNIS_UI_VETERAN, "TENNIS_UI_VETERAN", PICK_STRING(eUI = TENNIS_UI_SCOREBOARD, "TENNIS_UI_SCOREBOARD", PICK_STRING(eUI = TENNIS_UI_FAR_AWAY, "TENNIS_UI_FAR_AWAY", PICK_STRING(eUI = TENNIS_UI_STR_INFO, "TENNIS_UI_STR_INFO", PICK_STRING(eUI = TENNIS_UI_QUIT, "TENNIS_UI_QUIT", "UNKNOWN ENUM")))))))))))))))))) ENDFUNC PROC SET_TENNIS_UI_STATE(TENNIS_GAME_UI_DATA &thisUIData, UI_STATE_ENUM newUI, BOOL bRecordPrevious=TRUE) IF GET_TENNIS_UI_STATE(thisUIData) <> newUI IF bRecordPrevious thisUIData.ePrevUIState = GET_TENNIS_UI_STATE(thisUIData) ENDIF thisUIData.eUIState = newUI CPRINTLN(DEBUG_TENNIS, "UI State changed to ", GET_STRING_FROM_TENNIS_UI_STATE(newUI)) ENDIF ENDPROC PROC SET_TENNIS_SERVE_COUNT(TENNIS_GAME_STATUS &thisStatus, INT newCount) thisStatus.iServeCount = newCount ENDPROC FUNC INT GET_TENNIS_SERVE_COUNT(TENNIS_GAME_STATUS &thisStatus) RETURN thisStatus.iServeCount ENDFUNC /// PURPOSE: /// used primarily for finding the serv ice positions for MP tennis, could be used/adapted for single player too /// PARAMS: /// thisCourt - /// serveSide - /// vRight - /// amIServing - /// eCourtSide - /// RETURNS: /// FUNC VECTOR GET_TENNIS_SERVICE_POSITION(TENNIS_COURT &thisCourt, SERVING_SIDE_ENUM serveSide, VECTOR vCourtRight, VECTOR vCourtForward, BOOL amIServing, TENNIS_PLAYER_ID eCourtSide) VECTOR vDest, vBase FLOAT fMult, fUpMult TENNIS_PLAYER_ID me = eCourtSide IF amIServing AND serveSide = SERVING_FROM_RIGHT AND me = TENNIS_PLAYER_AWAY fMult = 0.75 fUpMult = -SERVICE_Y_BASELINE vBase = thisCourt.vCourtCorners[0] CPRINTLN(DEBUG_TENNIS, "TENNIS_PLAYER_AWAY is serving, from Right, on Away side") ELIF amIServing AND serveSide = SERVING_FROM_LEFT AND me = TENNIS_PLAYER_AWAY fMult = 0.25 fUpMult = -SERVICE_Y_BASELINE vBase = thisCourt.vCourtCorners[0] CPRINTLN(DEBUG_TENNIS, "TENNIS_PLAYER_AWAY is serving, from Left, on Away side") ELIF amIServing AND serveSide = SERVING_FROM_RIGHT AND me = TENNIS_PLAYER_HOME fMult = 0.25 fUpMult = SERVICE_Y_BASELINE vBase = thisCourt.vCourtCorners[3] CPRINTLN(DEBUG_TENNIS, "TENNIS_PLAYER_HOME is serving, from Right, on Home side") ELIF amIServing AND serveSide = SERVING_FROM_LEFT AND me = TENNIS_PLAYER_HOME fMult = 0.75 fUpMult = SERVICE_Y_BASELINE vBase = thisCourt.vCourtCorners[3] CPRINTLN(DEBUG_TENNIS, "TENNIS_PLAYER_HOME is serving, from Left, on Home side") ELIF !amIServing AND serveSide = SERVING_FROM_RIGHT AND me = TENNIS_PLAYER_AWAY fMult = 0.75 fUpMult = 0 vBase = thisCourt.vCourtCorners[0] CPRINTLN(DEBUG_TENNIS, "TENNIS_PLAYER_AWAY not serving, from Right, on Away side") ELIF !amIServing AND serveSide = SERVING_FROM_LEFT AND me = TENNIS_PLAYER_AWAY fMult = 0.25 fUpMult = 0 vBase = thisCourt.vCourtCorners[0] CPRINTLN(DEBUG_TENNIS, "TENNIS_PLAYER_AWAY not serving, from Left, on Away side") ELIF !amIServing AND serveSide = SERVING_FROM_RIGHT AND me = TENNIS_PLAYER_HOME fMult = 0.25 fUpMult = 0 vBase = thisCourt.vCourtCorners[3] CPRINTLN(DEBUG_TENNIS, "TENNIS_PLAYER_HOME not serving, from Right, on Home side") ELIF !amIServing AND serveSide = SERVING_FROM_LEFT AND me = TENNIS_PLAYER_HOME fMult = 0.75 fUpMult = 0 vBase = thisCourt.vCourtCorners[3] CPRINTLN(DEBUG_TENNIS, "TENNIS_PLAYER_HOME not serving, from Left, on Home side") ELSE SCRIPT_ASSERT("We missed a case in GET_TENNIS_SERVICE_POSITION, contact Rob Pearsall") ENDIF vDest = vBase + (vCourtRight * fMult) + (vCourtForward * fUpMult) // #IF NOT IS_TENNIS_MULTIPLAYER // SET_GRAVITY_LEVEL(GRAV_ZERO) // #ENDIF RETURN vDest ENDFUNC /// PURPOSE: /// records the win in the current set and checks to see if the set was won and increases sets won as well /// iCurrentSet is NOT incremented here tho you might think it should be, that's done in TGSE_CHANGE_SERVERS /// PARAMS: /// thisStatus - /// eSelfID - ID of the winner of the game. /// eOtherID - Loser of the game /// iUtilFlags - /// bOnTieBreak - when TRUE it will mark the set as won, a game won on a tie break will decide a set PROC RECORD_TENNIS_GAME_WIN(TENNIS_SCORES &playerScores[], INT iCurrentSet, TENNIS_PLAYER_ID eWinnerID, TENNIS_PLAYER_ID eLoserID, INT &iUtilFlags, BOOL bOnTieBreak) IF playerScores[eWinnerID].iGamesWon[iCurrentSet] = -1 //this case shouldn't hit but this is here in case it does. playerScores[eWinnerID].iGamesWon[iCurrentSet] = 1 CPRINTLN(DEBUG_TENNIS, "RECORD_TENNIS_GAME_WIN: something wrong occurred, games won in the current set is -1, this should have been primed elsewhere.") ELSE playerScores[eWinnerID].iGamesWon[iCurrentSet]++ ENDIF // Set won? IF (playerScores[eWinnerID].iGamesWon[iCurrentSet] > 5 AND (playerScores[eWinnerID].iGamesWon[iCurrentSet]) - playerScores[eLoserID].iGamesWon[iCurrentSet] >= 2 AND playerScores[eWinnerID].iPointsWon >= 3 AND NOT bOnTieBreak) OR (bOnTieBreak) //end of huge IF statement playerScores[eWinnerID].iSetsWon++ CPRINTLN(DEBUG_TENNIS, "Set won by ", PICK_STRING((TENNIS_PLAYER_AWAY) = eWinnerID, "TENNIS_PLAYER_AWAY", "TENNIS_PLAYER_HOME")) ENDIF SET_BITMASK_AS_ENUM(iUtilFlags, TD_UPDATE_SCORES) CPRINTLN(DEBUG_TENNIS, "Recording Tennis Game Win for ", PICK_STRING((TENNIS_PLAYER_AWAY) = eWinnerID, "TENNIS_PLAYER_AWAY", "TENNIS_PLAYER_HOME"), " in iCurrentSet: ", iCurrentSet) ENDPROC /// PURPOSE: /// /// PARAMS: /// playerScores - /// iCurrentSet - Pass by reference, not a GET_ method /// iUtilFlags - PROC INCREASE_CURRENT_TENNIS_SET(TENNIS_SCORES &playerScores[], INT &iCurrentSet, INT &iUtilFlags, INT iMaxSets) IF iCurrentSet + 1 < iMaxSets iCurrentSet++ playerScores[0].iPointsWon = 0 playerScores[1].iPointsWon = 0 playerScores[0].iGamesWon[iCurrentSet] = 0 playerScores[1].iGamesWon[iCurrentSet] = 0 CPRINTLN(DEBUG_TENNIS, "actually resetting points in set ", iCurrentSet) ENDIF SET_BITMASK_AS_ENUM(iUtilFlags, TD_UPDATE_SCORES) CPRINTLN(DEBUG_TENNIS, "INCREASE_CURRENT_TENNIS_SET called, points and games reset.") ENDPROC PROC SET_TENNIS_CHARACTER_SEEN_TUTORIAL() SET_TENNIS_SAVED_GLOBAL_FLAG(g_savedGlobals.sTennisData, TGF_STR_INFO_SHOWN) ENDPROC PROC CLEAR_TENNIS_CHARACTER_SEEN_TUTORIAL() CLEAR_TENNIS_SAVED_GLOBAL_FLAG(g_savedGlobals.sTennisData, TGF_STR_INFO_SHOWN) ENDPROC FUNC BOOL HAS_TENNIS_CHARACTER_SEEN_TUTORIAL() RETURN IS_TENNIS_SAVED_GLOBAL_FLAG_SET(g_savedGlobals.sTennisData, TGF_STR_INFO_SHOWN) ENDFUNC /// PURPOSE: /// gates whether or not we use a specific ped for the game. /// PARAMS: /// eActivity - the current tennis activity enum /// RETURNS: /// true if the tutorial isn't seen and the activity is not a friend activity FUNC BOOL VALIDATE_PICK_DEFAULT_TENNIS_OPPONENT(TENNIS_ACTIVITY eActivity) IF eActivity = TA_FRIEND_ACTIVITY RETURN FALSE ENDIF IF HAS_TENNIS_CHARACTER_SEEN_TUTORIAL() RETURN FALSE ENDIF IF IS_TENNIS_GLOBAL_FLAG_SET(TGF_AMANDA_IS_OPP) RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// Wrapper for the timer so we have output. /// PARAMS: /// sTimer - PROC TENNIS_PAUSE_TIMER(structTimer &sTimer) PAUSE_TIMER(sTimer) DEBUG_PRINTCALLSTACK() ENDPROC