USING "minigames_helpers.sch" USING "minigame_UIInputs.sch" USING "tennis_debug.sch" ENUM TENNIS_BALL_SPIN TBS_NO_SPIN = 0, TBS_TOPSPIN, TBS_SLICE ENDENUM ENUM TENNIS_NET_BOUNCE_ENUM TNB_NO_BOUNCE = 0, TNB_GROUND_BOUNCE, // bounce against the ground TNB_NORMAL_BOUNCE, // bounce against net, nothing special TNB_RICOCHET // crazy bounce off net, ricochets ENDENUM ENUM TENNIS_BALL_FLAGS_ENUM TBF_UPDATE_PTFX = BIT0, TBF_PAUSE_UPDATE = BIT1, TBF_HIT_PLAYER = BIT2, TBF_SOUND_ON_FOR_TUT = BIT3, TBF_BOUNCED_IN_TIME_SLICE = BIT4, // used for more than just time slicing, speed increase causes collisions to miss occassionally TBF_INCREASE_SIM_SPEED = BIT5, TBF_SERVE_WAS_POWERFUL = BIT6, TBF_NO_BOUNCE_TIMEOUT_OCCURED = BIT7, TBF_RICOCHETED = BIT8 ENDENUM FUNC STRING GET_STRING_FROM_TENNIS_BALL_FLAG(TENNIS_BALL_FLAGS_ENUM eFlag) SWITCH eFlag CASE TBF_UPDATE_PTFX RETURN "TBF_UPDATE_PTFX" CASE TBF_PAUSE_UPDATE RETURN "TBF_PAUSE_UPDATE" CASE TBF_HIT_PLAYER RETURN "TBF_HIT_PLAYER" CASE TBF_SOUND_ON_FOR_TUT RETURN "TBF_SOUND_ON_FOR_TUT" CASE TBF_BOUNCED_IN_TIME_SLICE RETURN "TBF_BOUNCED_IN_TIME_SLICE" CASE TBF_INCREASE_SIM_SPEED RETURN "TBF_INCREASE_SIM_SPEED" CASE TBF_SERVE_WAS_POWERFUL RETURN "TBF_SERVE_WAS_POWERFUL" CASE TBF_NO_BOUNCE_TIMEOUT_OCCURED RETURN "TBF_NO_BOUNCE_TIMEOUT_OCCURED" CASE TBF_RICOCHETED RETURN "TBF_RICOCHETED" ENDSWITCH RETURN "Unknown Ball Flag" ENDFUNC STRUCT TENNIS_BALL OBJECT_INDEX oBall INT iBounceCount // To track first bounce in / out / second bounce missed swing INT iBallBounceFrameStamp = 0 INT iBallIntoPlayerFrameStamp FLOAT fFlightTimer, fSpinTimer, fNoBounceTimeOut VECTOR vBallPosHidden, vBallVel, vCollPos, vBallLaunchPos, vBallServeSafety TENNIS_BALL_SPIN eBallSpin PTFX_ID ptfxBallTrail INT iBallFlags // Time Slice Variables FLOAT fTargetTime, fSimTime VECTOR vNaught, vNext FLOAT fPredTimeRemainder ENDSTRUCT FUNC STRING GET_STRING_FROM_TENNIS_BALL_SPIN(TENNIS_BALL_SPIN eSpin) SWITCH eSpin CASE TBS_NO_SPIN RETURN "TBS_NO_SPIN" CASE TBS_TOPSPIN RETURN "TBS_TOPSPIN" CASE TBS_SLICE RETURN "TBS_SLICE" ENDSWITCH RETURN "Unknown TENNIS_BALL_SPIN enum" ENDFUNC /// PURPOSE: /// Accessor. Used to set a failsafe position to launch the ball from when receiving a serve event. PROC SET_TENNIS_BALL_SERVE_SAFETY_POS(TENNIS_BALL & thisBall, VECTOR vSafetyPos) CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_BALL_SERVE_SAFETY_POS setting to ", vSafetyPos) thisBall.vBallServeSafety = vSafetyPos ENDPROC /// PURPOSE: /// Accessor. Gets the ball position stored from the serve event. Used only when a failsafe is encountered. FUNC VECTOR GET_TENNIS_BALL_SERVE_SAFETY_POS(TENNIS_BALL & thisBall) RETURN thisBall.vBallServeSafety ENDFUNC PROC SET_TENNIS_BALL_INTO_PLAYER_FRAME_STAMP(TENNIS_BALL &thisBall, INT iNewStamp) CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_BALL_INTO_PLAYER_FRAME_STAMP :: iNewStamp=", iNewStamp) thisBall.iBallIntoPlayerFrameStamp = iNewStamp ENDPROC FUNC INT GET_TENNIS_BALL_INTO_PLAYER_FRAME_STAMP(TENNIS_BALL &thisBall) RETURN thisBall.iBallIntoPlayerFrameStamp ENDFUNC PROC SET_TENNIS_BALL_BOUNCE_FRAME_STAMP(TENNIS_BALL &thisBall, INT iNewStamp) CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_BALL_BOUNCE_FRAME_STAMP :: iNewStamp=", iNewStamp) thisBall.iBallBounceFrameStamp = iNewStamp ENDPROC PROC INCREASE_TENNIS_BALL_BOUNCE_TIMEOUT(TENNIS_BALL &thisBall) thisBall.fNoBounceTimeOut += GET_FRAME_TIME() ENDPROC FUNC FLOAT GET_TENNIS_BALL_BOUNCE_TIMEOUT(TENNIS_BALL &thisBall) RETURN thisBall.fNoBounceTimeOut ENDFUNC PROC RESET_TENNIS_BALL_BOUNCE_TIMEOUT(TENNIS_BALL &thisBall) thisBall.fNoBounceTimeOut = 0 ENDPROC FUNC VECTOR GET_TENNIS_BALL_POS(TENNIS_BALL &thisBall) RETURN thisBall.vBallPosHidden ENDFUNC PROC SET_TENNIS_BALL_POS(TENNIS_BALL &thisBall, VECTOR vPos) thisBall.vBallPosHidden = vPos #IF TENNIS_DEBUG_RECORDING #IF IS_DEBUG_BUILD DEBUG_RECORD_ENTITY_VECTOR( GET_PLAYER_PED(GET_PLAYER_INDEX()), "SET_TENNIS_BALL_POS", vPos, TRUE) #ENDIF #ENDIF ENDPROC PROC SET_TENNIS_BALL_FLAG(TENNIS_BALL &thisBall, TENNIS_BALL_FLAGS_ENUM eFlag) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_BALL_FLAG :: ", GET_STRING_FROM_TENNIS_BALL_FLAG(eFlag)) SET_BITMASK_AS_ENUM(thisBall.iBallFlags, eFlag) ENDPROC FUNC BOOL IS_TENNIS_BALL_FLAG_SET(TENNIS_BALL &thisBall, TENNIS_BALL_FLAGS_ENUM eFlag) RETURN IS_BITMASK_AS_ENUM_SET(thisBall.iBallFlags, eFlag) ENDFUNC PROC CLEAR_TENNIS_BALL_FLAG(TENNIS_BALL &thisBall, TENNIS_BALL_FLAGS_ENUM eFlag) CPRINTLN(DEBUG_TENNIS, "CLEAR_TENNIS_BALL_FLAG :: ", GET_STRING_FROM_TENNIS_BALL_FLAG(eFlag)) CLEAR_BITMASK_AS_ENUM(thisBall.iBallFlags, eFlag) ENDPROC PROC CLEAR_ALL_TENNIS_BALL_FLAGS(TENNIS_BALL &thisBall) CDEBUG3LN(DEBUG_TENNIS, "CLEAR_ALL_TENNIS_BALL_FLAGS called") thisBall.iBallFlags = 0 ENDPROC FUNC BOOL DOES_TENNIS_BALL_TRAIL_EXIST(TENNIS_BALL &thisBall) RETURN DOES_PARTICLE_FX_LOOPED_EXIST(thisBall.ptfxBallTrail) ENDFUNC PROC START_TENNIS_BALL_TRAIL(TENNIS_BALL &thisBall) CPRINTLN(DEBUG_TENNIS, "START_TENNIS_BALL_TRAIL called") SET_TENNIS_BALL_FLAG(thisBall, TBF_UPDATE_PTFX) ENDPROC PROC STOP_TENNIS_BALL_TRAIL(TENNIS_BALL &thisBall) // CPRINTLN(DEBUG_TENNIS, "STOP_TENNIS_BALL_TRAIL called") IF DOES_TENNIS_BALL_TRAIL_EXIST(thisBall) STOP_PARTICLE_FX_LOOPED(thisBall.ptfxBallTrail, TRUE) CPRINTLN(DEBUG_TENNIS, "STOP_PARTICLE_FX_LOOPED(thisBall.ptfxBallTrail) called on thisBall.PTFX=", NATIVE_TO_INT(thisBall.ptfxBallTrail)) CLEAR_TENNIS_BALL_FLAG(thisBall, TBF_UPDATE_PTFX) ENDIF ENDPROC PROC UPDATE_TENNIS_BALL_TRAIL(TENNIS_BALL &thisBall, VECTOR vLoopedOffsets) IF IS_TENNIS_BALL_FLAG_SET(thisBall, TBF_UPDATE_PTFX) IF NOT DOES_TENNIS_BALL_TRAIL_EXIST(thisBall) thisBall.ptfxBallTrail = START_PARTICLE_FX_LOOPED_AT_COORD("scr_tennis_ball_trail", vLoopedOffsets, (<<0,0,0>>), DEFAULT, DEFAULT, DEFAULT, DEFAULT, TRUE) INT r, g, b, a GET_HUD_COLOUR(HUD_COLOUR_YELLOW, r, g, b, a) SET_PARTICLE_FX_LOOPED_COLOUR(thisBall.ptfxBallTrail, TO_FLOAT(r)/255.0, TO_FLOAT(g)/255.0, TO_FLOAT(b)/255.0) a=a CPRINTLN(DEBUG_TENNIS, "START_PARTICLE_FX_LOOPED_AT_COORD(scr_tennis_ball_trail) called at vPos:", vLoopedOffsets, ", thisBall.PTFX=", NATIVE_TO_INT(thisBall.ptfxBallTrail), ", r=", r, ", g=", g, ", b=", b) ENDIF SET_PARTICLE_FX_LOOPED_OFFSETS(thisBall.ptfxBallTrail, vLoopedOffsets, (<<0,0,0>>)) ENDIF ENDPROC PROC RESET_TENNIS_BALL_TIMERS(TENNIS_BALL &thisBall) thisBall.fFlightTimer = 0 thisBall.fSpinTimer = 0 RESET_TENNIS_BALL_BOUNCE_TIMEOUT(thisBall) ENDPROC FUNC FLOAT GET_TENNIS_BALL_FLIGHT_TIMER(TENNIS_BALL &thisBall) RETURN thisBall.fFlightTimer ENDFUNC FUNC FLOAT GET_TENNIS_BALL_SPIN_TIMER(TENNIS_BALL &thisBall) RETURN thisBall.fSpinTimer ENDFUNC PROC RESET_TENNIS_BALL_SPIN(TENNIS_BALL &thisBall) thisball.eBallSpin = TBS_NO_SPIN ENDPROC PROC RESET_TENNIS_BALL_BOUNCE_COUNT(TENNIS_BALL &thisBall) thisBall.iBounceCount = 0 ENDPROC PROC INCREASE_TENNIS_BALL_BOUNCE_COUNT(TENNIS_BALL &thisBall) thisBall.iBounceCount++ CPRINTLN(DEBUG_TENNIS, "INCREASE_TENNIS_BALL_BOUNCE_COUNT to ", thisBall.iBounceCount) ENDPROC FUNC INT GET_TENNIS_BALL_BOUNCE_COUNT(TENNIS_BALL &thisBall) RETURN thisBall.iBounceCount ENDFUNC PROC SET_TENNIS_BALL_SPIN(TENNIS_BALL &thisBall, TENNIS_BALL_SPIN newSpin) thisBall.eBallSpin = newSpin CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_BALL_SPIN :: Applying ", GET_STRING_FROM_TENNIS_BALL_SPIN(newSpin)) ENDPROC FUNC TENNIS_BALL_SPIN GET_TENNIS_BALL_SPIN(TENNIS_BALL &thisBall) RETURN thisBall.eBallSpin ENDFUNC PROC SET_TENNIS_BALL_VISIBILITY(OBJECT_INDEX oBall, BOOL bVisible) IF DOES_ENTITY_EXIST(oBall) IF (IS_ENTITY_VISIBLE(oBall) AND NOT bVisible) OR (NOT IS_ENTITY_VISIBLE(oBall) AND bVisible) SET_ENTITY_VISIBLE(oBall, bVisible) SET_ENTITY_FLAG_RENDER_SMALL_SHADOW(oBall, bVisible) CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_BALL_VISIBILITY with: ", bVisible) ENDIF ELSE CPRINTLN(DEBUG_TENNIS, "SET_TENNIS_BALL_VISIBILITY Ball doesn't exist") ENDIF ENDPROC