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

168 lines
5.9 KiB
XML
Executable File

USING "minigames_helpers.sch"
USING "minigame_UIInputs.sch"
USING "tennis_debug.sch"
/// PURPOSE:
ENUM TENNIS_AI_STATE_ENUM
ASE_AI_IDLE = 0,
ASE_AI_MOVING_TO_BALL,
ASE_AI_CHOOSING_SHOT,
ASE_AI_CHARGING_TOPSPIN,
ASE_AI_CHARGING_LOB,
ASE_AI_MOVING_TO_IDLE,
ASE_AI_REACTING
ENDENUM
/// PURPOSE:
ENUM AI_DIFFICULTY
AD_EASY,
AD_NORMAL,
AD_HARD,
AD_TUTORIAL // Moved Tutorial to the back, it was messing with the ENUM_TO_INT() call for setting difficulty
ENDENUM
/// PURPOSE:
STRUCT TENNIS_AI_PLAYER
VECTOR vAIBallPredictionPoint
VECTOR vCurrentDestinationPoint
VECTOR vHomePos[MAX_HOME_POS]
TENNIS_AI_STATE_ENUM eTennisAIState
AI_DIFFICULTY eDifficulty
FLOAT fRightBucket = 0.0
FLOAT fBackBucket = 0.0
FLOAT fServeBucket = 0.0
FLOAT fReactionTime
INT iAIFlags
INT iActionTakenStamp
#IF IS_DEBUG_BUILD
TEXT_LABEL_7 texName
#ENDIF
ENDSTRUCT
ENUM TENNIS_AI_FLAGS
TAF_PREVENT_DBL_SWING = BIT0, // Used to prevent AI from swinging after missing the ball
TAF_AI_HAS_SWUNG = BIT1, // Used to prevent AI from swinging more than once after the ball is launched
TAF_JUST_TASKED = BIT2, // Used for AI indicates that the AI was just tasked to move to a coord
TAF_DONT_CHASE = BIT3, // Used when the AI knows the ball is out of bounds so we don't chase it.
TAF_TASKED_ANIM = BIT4,
TAF_CHECK_FOR_OOB = BIT5, // Used to tell the AI to start looking for OOB balls
TAF_CHECK_REACTS = BIT6,
TAF_PLYR_RUN_LR_HELD = BIT7,
TAF_TASKED_NEW_RALLY = BIT8, // Intended to gate setting the player to get ready for the next rally.
TAF_PREVENT_MP_TENNIS_MODE_UPDATE = BIT9,
TAF_TASKED_ANIM_2_IDLE = BIT10
ENDENUM
FUNC STRING GET_STRING_FROM_TENNIS_AI_FLAG(TENNIS_AI_FLAGS eFlag)
SWITCH eFlag
CASE TAF_PREVENT_DBL_SWING RETURN "TAF_PREVENT_DBL_SWING"
CASE TAF_AI_HAS_SWUNG RETURN "TAF_AI_HAS_SWUNG"
CASE TAF_JUST_TASKED RETURN "TAF_JUST_TASKED"
CASE TAF_DONT_CHASE RETURN "TAF_DONT_CHASE"
CASE TAF_TASKED_ANIM RETURN "TAF_TASKED_ANIM"
CASE TAF_CHECK_FOR_OOB RETURN "TAF_CHECK_FOR_OOB"
CASE TAF_CHECK_REACTS RETURN "TAF_CHECK_REACTS"
CASE TAF_PLYR_RUN_LR_HELD RETURN "TAF_PLYR_RUN_LR_HELD"
CASE TAF_TASKED_NEW_RALLY RETURN "TAF_TASKED_NEW_RALLY"
CASE TAF_PREVENT_MP_TENNIS_MODE_UPDATE RETURN "TAF_PREVENT_MP_TENNIS_MODE_UPDATE"
CASE TAF_TASKED_ANIM_2_IDLE RETURN "TAF_TASKED_ANIM_2_IDLE"
ENDSWITCH
RETURN "Unknown TENNIS_AI_FLAGS"
ENDFUNC
PROC SET_TENNIS_AI_ACTION_TAKEN_STAMP(TENNIS_AI_PLAYER &thisAI, INT iNewStamp)
thisAI.iActionTakenStamp = iNewStamp
ENDPROC
FUNC INT GET_TENNIS_AI_ACTION_TAKEN_STAMP(TENNIS_AI_PLAYER &thisAI)
RETURN thisAI.iActionTakenStamp
ENDFUNC
PROC CLEAR_TENNIS_AI_FLAGS_ALL(TENNIS_AI_PLAYER &thisAI)
CPRINTLN(DEBUG_TENNIS, "CLEAR_TENNIS_AI_FLAGS_ALL called on ", thisAI.texName)
thisAI.iAIFlags = 0
ENDPROC
PROC SET_TENNIS_AI_FLAG(TENNIS_AI_PLAYER &thisAI, TENNIS_AI_FLAGS eFlag)
CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_AI_FLAG :: ", thisAI.texName, ", ", GET_STRING_FROM_TENNIS_AI_FLAG(eFlag))
SET_BITMASK_AS_ENUM(thisAI.iAIFlags, eFlag)
ENDPROC
FUNC BOOL IS_TENNIS_AI_FLAG_SET(TENNIS_AI_PLAYER &thisAI, TENNIS_AI_FLAGS eFlag)
RETURN IS_BITMASK_AS_ENUM_SET(thisAI.iAIFlags, eFlag)
ENDFUNC
PROC CLEAR_TENNIS_AI_FLAG(TENNIS_AI_PLAYER &thisAI, TENNIS_AI_FLAGS eFlag)
CDEBUG2LN(DEBUG_TENNIS, "CLEAR_TENNIS_AI_FLAG :: ", thisAI.texName, ", ", GET_STRING_FROM_TENNIS_AI_FLAG(eFlag))
CLEAR_BITMASK_AS_ENUM(thisAI.iAIFlags, eFlag)
ENDPROC
PROC SET_AI_PREDICTION_POINT(TENNIS_AI_PLAYER &thisAI, VECTOR newPredictionPoint)
CDEBUG2LN(DEBUG_TENNIS, "SET_AI_PREDICTION_POINT: ", newPredictionPoint)
thisAI.vAIBallPredictionPoint = newPredictionPoint
ENDPROC
FUNC VECTOR GET_AI_PREDICTION_POINT(TENNIS_AI_PLAYER &thisAI)
RETURN thisAI.vAIBallPredictionPoint
ENDFUNC
FUNC BOOL SHOULD_RETASK_MOTION(TENNIS_AI_PLAYER &thisAI)
FLOAT fDist = VDIST(thisAI.vAIBallPredictionPoint, thisAI.vCurrentDestinationPoint)
IF fDist > 0.1
CDEBUG2LN(DEBUG_TENNIS, "SHOULD_RETASK_MOTION :: fDist=", fDist)
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNC
FUNC VECTOR GET_AI_DESTINATION_POINT(TENNIS_AI_PLAYER &thisAI)
RETURN thisAI.vCurrentDestinationPoint
ENDFUNC
PROC SET_AI_DESTINATION_POINT(TENNIS_AI_PLAYER &thisAI, VECTOR vPos)
thisAI.vCurrentDestinationPoint = vPos
ENDPROC
PROC SET_AI_DIFFICULTY(TENNIS_AI_PLAYER &thisAI, AI_DIFFICULTY thisDiff)
CPRINTLN(DEBUG_TENNIS, "SET_AI_DIFFICULTY: ", thisAI.texName, " newDifficulty is ",
PICK_STRING(thisDiff = AD_TUTORIAL, "AD_TUTORIAL",
PICK_STRING(thisDiff = AD_EASY, "AD_EASY",
PICK_STRING(thisDiff = AD_NORMAL, "AD_NORMAL",
PICK_STRING(thisDiff = AD_HARD, "AD_HARD", "Unknown Difficulty")))))
thisAI.eDifficulty = thisDiff
ENDPROC
FUNC AI_DIFFICULTY GET_AI_DIFFICULTY(TENNIS_AI_PLAYER &thisAI)
RETURN thisAI.eDifficulty
ENDFUNC
#IF IS_DEBUG_BUILD
FUNC STRING GET_AI_STATE_STRING(TENNIS_AI_STATE_ENUM newASE)
SWITCH newASE
CASE ASE_AI_IDLE RETURN "ASE_AI_IDLE"
CASE ASE_AI_MOVING_TO_BALL RETURN "ASE_AI_MOVING_TO_BALL"
CASE ASE_AI_CHOOSING_SHOT RETURN "ASE_AI_CHOOSING_SHOT"
CASE ASE_AI_CHARGING_TOPSPIN RETURN "ASE_AI_CHARGING_TOPSPIN"
CASE ASE_AI_CHARGING_LOB RETURN "ASE_AI_CHARGING_LOB"
CASE ASE_AI_MOVING_TO_IDLE RETURN "ASE_AI_MOVING_TO_IDLE"
CASE ASE_AI_REACTING RETURN "ASE_AI_REACTING"
ENDSWITCH
RETURN "Unknown ASE"
ENDFUNC
#ENDIF
PROC SET_TENNIS_AI_STATE(TENNIS_AI_PLAYER &thisAI, TENNIS_AI_STATE_ENUM newASE)
#IF IS_DEBUG_BUILD
#IF TENNIS_DEBUG_RECORDING
DEBUG_RECORD_STRING("SET_TENNIS_AI_STATE", GET_AI_STATE_STRING(newASE))
#ENDIF
CDEBUG2LN(DEBUG_TENNIS, "SET_TENNIS_AI_STATE :: ", thisAI.texName, ", oldState: ", GET_AI_STATE_STRING(thisAI.eTennisAIState), " newState: ", GET_AI_STATE_STRING(newASE))
#ENDIF
thisAI.eTennisAIState = newASE
ENDPROC
FUNC TENNIS_AI_STATE_ENUM GET_TENNIS_AI_STATE(TENNIS_AI_PLAYER &thisAI)
RETURN thisAI.eTennisAIState
ENDFUNC