1616 lines
80 KiB
Scheme
Executable File
1616 lines
80 KiB
Scheme
Executable File
USING "minigames_helpers.sch"
|
|
USING "golf.sch"
|
|
USING "golf_helpers.sch"
|
|
USING "golf_foursome.sch"
|
|
USING "golf_clubs_lib.sch"
|
|
USING "golf_anims_lib.sch"
|
|
USING "golf_physics_lib.sch"
|
|
USING "oddjob_aggro.sch"
|
|
|
|
FUNC FLOAT GET_DISTANCE_BETWEEN_ENTITIES_SQUARED(ENTITY_INDEX entityA, ENTITY_INDEX entityB, BOOL bCheck3D = TRUE)
|
|
VECTOR vEntityAPos
|
|
VECTOR vEntityBPos
|
|
|
|
IF NOT IS_ENTITY_DEAD(entityA)
|
|
vEntityAPos = GET_ENTITY_COORDS(entityA)
|
|
ELSE
|
|
vEntityAPos = GET_ENTITY_COORDS(entityA, FALSE)
|
|
ENDIF
|
|
IF NOT IS_ENTITY_DEAD(entityB)
|
|
vEntityBPos = GET_ENTITY_COORDS(entityB)
|
|
ELSE
|
|
vEntityBPos = GET_ENTITY_COORDS(entityB, FALSE)
|
|
ENDIF
|
|
|
|
IF bCheck3D
|
|
RETURN VDIST2(vEntityAPos, vEntityBPos)
|
|
ELSE
|
|
RETURN POW(vEntityAPos.x - vEntityBPos.x, 2.0) + POW(vEntityAPos.y - vEntityBPos.y, 2.0)
|
|
ENDIF
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Updates a specific AI golfer status to see if it is far away from a given ped (the player, generally) or not
|
|
/// PARAMS:
|
|
/// thisPlayerCore -
|
|
/// pedReference -
|
|
/// newBallPos - There is a good chance that the balls Z cord will be way off when the player gets close to a golfer who used to be far away.
|
|
/// Pass the golf balls position vector in to correct this. It will only change if the golfer changes its far away flag.
|
|
PROC UPDATE_AI_FAR_AWAY(GOLF_PLAYER_CORE &thisPlayerCore, PED_INDEX pedReference, GOLF_FOURSOME &thisFoursome, INT playerIndex, GOLF_COURSE &thisCourse)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
EXIT
|
|
ENDIF
|
|
IF IS_ENTITY_DEAD(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
OR IS_PED_INJURED(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
EXIT
|
|
ENDIF
|
|
IF NOT DOES_ENTITY_EXIST(pedReference)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF GET_SCRIPT_TASK_STATUS(GET_GOLF_PLAYER_PED(thisPlayerCore), SCRIPT_TASK_ENTER_VEHICLE) = PERFORMING_TASK
|
|
//walking to cart, he might walk out of the acceptable range. Don't teleport until he is in the cart
|
|
EXIT
|
|
ENDIF
|
|
|
|
VECTOR golfBallPos = GET_GOLF_PLAYER_BALL_POSITION(thisPlayerCore)
|
|
VECTOR playerPos = GET_ENTITY_COORDS(pedReference)
|
|
VECTOR golferPos = GET_ENTITY_COORDS(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
FLOAT fHeight
|
|
|
|
IF VDIST2(golferPos, playerPos) > (FAR_AWAY_THRESHOLD*FAR_AWAY_THRESHOLD) AND VDIST2(golfBallPos, playerPos) > (FAR_AWAY_THRESHOLD*FAR_AWAY_THRESHOLD)
|
|
|
|
//Golfers will sometimes fall to there deaths in the far away state
|
|
IF NOT IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_FAR_AWAY)
|
|
SET_PED_GRAVITY(thisPlayerCore.pedGolfPlayer, FALSE)
|
|
SET_PED_CAN_RAGDOLL(thisPlayerCore.pedGolfPlayer, FALSE)
|
|
ENDIF
|
|
|
|
SET_GOLF_PLAYER_CONTROL_FLAG(thisPlayerCore, GOLF_FAR_AWAY)
|
|
ELSE
|
|
|
|
IF IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_FAR_AWAY)
|
|
SET_PED_GRAVITY(thisPlayerCore.pedGolfPlayer, TRUE)
|
|
SET_PED_CAN_RAGDOLL(thisPlayerCore.pedGolfPlayer, TRUE)
|
|
ENDIF
|
|
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisPlayerCore, GOLF_FAR_AWAY)
|
|
ENDIF
|
|
|
|
|
|
//golf ball far away
|
|
IF VDIST2(golfBallPos, playerPos) > (FAR_AWAY_THRESHOLD*FAR_AWAY_THRESHOLD)
|
|
SET_GOLF_PLAYER_CONTROL_FLAG(thisPlayerCore, GOLF_BALL_FAR_AWAY)
|
|
|
|
IF golfBallPos.z > 100.0
|
|
IF DOES_ENTITY_EXIST(thisPlayerCore.objBall)
|
|
IF NOT IS_ENTITY_DEAD(thisPlayerCore.objBall)
|
|
SET_ENTITY_COORDS(thisPlayerCore.objBall, <<golfBallPos.x, golfBallPos.y, 50.0>>)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
|
|
IF IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_BALL_FAR_AWAY)
|
|
//move ball to correct spot
|
|
IF DOES_ENTITY_EXIST(thisPlayerCore.objBall)
|
|
IF NOT IS_ENTITY_DEAD(thisPlayerCore.objBall)
|
|
VECTOR tempPos = thisPlayerCore.vBallPosition + <<0,0, 50.0>>
|
|
IF GET_GROUND_Z_FOR_3D_COORD (tempPos, fHeight)
|
|
thisPlayerCore.vBallPosition.z = fHeight
|
|
SET_ENTITY_COORDS(thisPlayerCore.objBall, thisPlayerCore.vBallPosition)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF GET_GOLF_PLAYER_STATE(thisPlayerCore) = GPS_BALL_IN_FLIGHT //if ball was flying put it at rest
|
|
SET_GOLF_PLAYER_STATE(thisPlayerCore, GPS_BALL_AT_REST)
|
|
ENDIF
|
|
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisPlayerCore, GOLF_BALL_FAR_AWAY)
|
|
ENDIF
|
|
|
|
IF IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_AI_FAR_AWAY) AND ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome)
|
|
//ball is close to player but golfer isn't
|
|
FLOAT distanceToBall = VDIST(golferPos, golfBallPos)
|
|
VECTOR directionToBall = NORMALISE_VECTOR(golfBallPos - golferPos)
|
|
VECTOR teleportLoc = golferPos + directionToBall*distanceToBall*0.5
|
|
TELEPORT_GOLFER_TO_COORD(thisFoursome, playerIndex, teleportLoc, thisCourse, TRUE)
|
|
|
|
IF GET_SCRIPT_TASK_STATUS(GET_GOLF_PLAYER_PED(thisPlayerCore), SCRIPT_TASK_ANY) = PERFORMING_TASK
|
|
CLEAR_PED_TASKS(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
//ai far away
|
|
IF VDIST2(golferPos, playerPos) > (FAR_AWAY_THRESHOLD*FAR_AWAY_THRESHOLD)
|
|
SET_GOLF_PLAYER_CONTROL_FLAG(thisPlayerCore, GOLF_AI_FAR_AWAY)
|
|
|
|
//golf ball is far away, set up the golfer for the far away logic
|
|
IF IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_BALL_FAR_AWAY) AND playerIndex = GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)
|
|
IF GET_SCRIPT_TASK_STATUS(thisPlayerCore.pedGolfPlayer, SCRIPT_TASK_ANY) = PERFORMING_TASK
|
|
CLEAR_PED_TASKS(thisPlayerCore.pedGolfPlayer)
|
|
ENDIF
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
ENDIF
|
|
|
|
ELSE
|
|
|
|
//aproaching golfer who was in the far away state, teleport him to his ball if the ball is far away
|
|
IF IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_AI_FAR_AWAY)
|
|
|
|
|
|
IF IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_BALL_FAR_AWAY) AND ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome)
|
|
|
|
TELEPORT_GOLFER_TO_BALL(thisFoursome, playerIndex, thisCourse, TRUE)
|
|
IF GET_SCRIPT_TASK_STATUS(thisPlayerCore.pedGolfPlayer, SCRIPT_TASK_ANY) = PERFORMING_TASK
|
|
CLEAR_PED_TASKS(thisPlayerCore.pedGolfPlayer)
|
|
ENDIF
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_GET_IN_CART)
|
|
|
|
IF IS_TEE_SHOT(thisCourse, thisFoursome)
|
|
SET_GOLF_PLAYER_STATE(thisPlayerCore, GPS_PLACE_BALL)
|
|
ELSE
|
|
SET_GOLF_PLAYER_STATE(thisPlayerCore, GPS_APPROACH_BALL)
|
|
ENDIF
|
|
ELSE ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome)
|
|
IF GET_GROUND_Z_FOR_3D_COORD (golferPos, fHeight)
|
|
golferPos.z = fHeight
|
|
SET_ENTITY_COORDS(thisPlayerCore.pedGolfPlayer, golferPos)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisPlayerCore, GOLF_AI_FAR_AWAY)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Does AI navigation to its next shot
|
|
/// PARAMS:
|
|
/// thisPlayerCore -
|
|
/// golfCart -
|
|
/// bOverridePlayer -
|
|
/// bInitialHole -
|
|
PROC DO_NAVIGATION_TO_NEXT_SHOT(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome, INT playerIndex)//, BOOL bPlayerTimeout = TRUE)
|
|
IF GET_GOLF_PLAYER_CONTROL(thisFoursome.playerCore[playerIndex]) != COMPUTER
|
|
EXIT
|
|
ENDIF
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]))
|
|
EXIT
|
|
ENDIF
|
|
IF IS_ENTITY_DEAD(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]))
|
|
EXIT
|
|
ENDIF
|
|
IF GET_GOLF_PLAYER_CONTROL(thisFoursome.playerCore[playerIndex]) = HUMAN_NETWORK
|
|
EXIT
|
|
ENDIF
|
|
|
|
VECTOR newBallLoc = GET_GOLF_PLAYER_BALL_POSITION(thisFoursome.playerCore[playerIndex])
|
|
PED_INDEX pedGolfPlayer = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)
|
|
|
|
IF IS_TEE_SHOT(thisCourse, thisFoursome)
|
|
newBallLoc = GET_GOLF_HOLE_TEE_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), playerIndex)
|
|
ENDIF
|
|
|
|
IF IS_PED_IN_GROUP(pedGolfPlayer) OR VMAG2(newBallLoc) = 0
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_FAR_AWAY)
|
|
// Probably need to check ball position also!
|
|
IF bDebugSpew DEBUG_MESSAGE("We are trying to task the user to go to the ball, but we are far away, so lets teleport instead") ENDIF
|
|
IF NOT IS_SPHERE_VISIBLE(newBallLoc, 5.0)
|
|
SET_ENTITY_COORDS(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]), newBallLoc, FALSE)
|
|
ENDIF
|
|
|
|
VECTOR cartSpawnPos = << 0,0,0 >>
|
|
FLOAT cartHeading = 0
|
|
//move cart
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CART(thisFoursome))
|
|
IF NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_CART(thisFoursome))
|
|
IF FIND_SAFE_SPOT_FOR_CART(GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL_POSITION(thisFoursome,0), GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)), cartSpawnPos, cartHeading, <<0,0,0>>, <<0,0,0>>)
|
|
IF NOT IS_SPHERE_VISIBLE(cartSpawnPos, 5.0)
|
|
SET_ENTITY_COORDS(GET_GOLF_FOURSOME_CART(thisFoursome), cartSpawnPos)
|
|
SET_ENTITY_HEADING(GET_GOLF_FOURSOME_CART(thisFoursome), cartHeading)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELIF GET_SCRIPT_TASK_STATUS( pedGolfPlayer, SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK
|
|
AND GET_SCRIPT_TASK_STATUS( pedGolfPlayer, SCRIPT_TASK_PERFORM_SEQUENCE) != WAITING_TO_START_TASK
|
|
|
|
IF IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome,playerIndex, GOLF_PUTTING_GREEN_AI)
|
|
AND DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
newBallLoc = GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
ELIF GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, playerIndex) = GPS_DONE_WITH_HOLE // We are approaching a hit ball
|
|
OR GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, playerIndex) = GPS_BALL_IN_HOLE_CELEBRATION
|
|
OR GET_GOLF_PLAYER_LIE(thisFoursome.playerCore[playerIndex]) = LIE_GREEN
|
|
IF GET_GOLF_PLAYER_LIE(thisFoursome.playerCore[playerIndex]) = LIE_GREEN
|
|
OR GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, playerIndex) = GPS_DONE_WITH_HOLE //don't go to the spectate location if you are the current golfer, unless you are finished with the hole
|
|
OR GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, playerIndex) = GPS_BALL_IN_HOLE_CELEBRATION
|
|
OR GET_GOLF_PLAYER_LIE(thisFoursome.playerCore[playerIndex]) = LIE_CUP
|
|
AND FIND_NEXT_SHOOTER(thisFoursome, thisCourse) != playerIndex
|
|
// PRINTLN("We are on the green, done with hole, or the lie is a cup - walk to green spectate")
|
|
newBallLoc = GET_GOLF_HOLE_GREEN_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome),playerIndex)
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG(thisFoursome, playerIndex, GOLF_STOP_USING_CART)
|
|
ELSE
|
|
// PRINTLN("We are not on the green, and done with hole, and the lie is not a cup - walk to ball")
|
|
newBallLoc = GET_GOLF_PLAYER_BALL_POSITION(thisFoursome.playerCore[playerIndex])
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Task the player to go to the ball offset position then turn right 90 degrees
|
|
IF VDIST2(newBallLoc, GET_ENTITY_COORDS(pedGolfPlayer)) > 1.5
|
|
CLEAR_PED_TASKS(pedGolfPlayer)
|
|
OPEN_SEQUENCE_TASK(thisFoursome.playerCore[playerIndex].seq_swing_and_outro)
|
|
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, newBallLoc, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP, DEFAULT_NAVMESH_RADIUS, ENAV_DEFAULT | ENAV_GO_FAR_AS_POSSIBLE_IF_TARGET_NAVMESH_NOT_LOADED, GET_HEADING_BETWEEN_VECTORS_2D(newBallLoc, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))))
|
|
//TASK_TURN_PED_TO_FACE_COORD(NULL, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)))
|
|
CLOSE_SEQUENCE_TASK(thisFoursome.playerCore[playerIndex].seq_swing_and_outro)
|
|
TASK_PERFORM_SEQUENCE(pedGolfPlayer, thisFoursome.playerCore[playerIndex].seq_swing_and_outro)
|
|
CLEAR_SEQUENCE_TASK(thisFoursome.playerCore[playerIndex].seq_swing_and_outro)
|
|
ENDIF
|
|
|
|
IF GET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL(thisFoursome, playerIndex) != COMPUTER
|
|
SET_GOLF_FOURSOME_LOCAL_PLAYER_CONTROL_FLAG(thisFoursome, GOLF_PLAYER_TASKED)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GOLF_AI_WALK_TO_CART(GOLF_FOURSOME &thisFoursome, INT playerIndex, BOOL bForceTaskEnterCart = FALSE)
|
|
|
|
IF GET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL(thisFoursome, playerIndex) != COMPUTER
|
|
EXIT
|
|
ENDIF
|
|
|
|
PED_INDEX pedIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)
|
|
VEHICLE_INDEX vehIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex)
|
|
VEHICLE_SEAT seat
|
|
|
|
IF playerIndex = 0 OR playerIndex = 2
|
|
seat = VS_DRIVER
|
|
ELSE
|
|
seat = VS_FRONT_RIGHT
|
|
ENDIF
|
|
bForceTaskEnterCart = bForceTaskEnterCart
|
|
|
|
IF DOES_ENTITY_EXIST(vehIndex) AND DOES_ENTITY_EXIST(pedIndex)
|
|
IF NOT IS_ENTITY_DEAD(vehIndex) AND NOT IS_ENTITY_DEAD(pedIndex)
|
|
IF NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_STOP_USING_CART)
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_CART_ARRIVED)
|
|
AND NOT IS_PED_IN_GROUP(pedIndex)
|
|
IF NOT IS_PED_IN_VEHICLE(pedIndex, vehIndex) AND IS_VEHICLE_SEAT_FREE(vehIndex, seat)
|
|
AND NOT IS_PED_BEING_JACKED(pedIndex) AND NOT IS_PED_JACKING(pedIndex) AND IS_VEHICLE_ON_ALL_WHEELS(vehIndex)
|
|
|
|
// IF VDIST2(GET_ENTITY_COORDS(vehIndex), GET_ENTITY_COORDS(pedIndex)) > (10.0 *10.0)
|
|
// AND GET_SCRIPT_TASK_STATUS(pedIndex, SCRIPT_TASK_FOLLOW_NAV_MESH_TO_COORD) != PERFORMING_TASK AND NOT bForceTaskEnterCart
|
|
// TASK_FOLLOW_NAV_MESH_TO_COORD(pedIndex, GET_ENTITY_COORDS(vehIndex), PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP, 5.0, ENAV_DEFAULT | ENAV_NEVER_ENTER_WATER | ENAV_GO_FAR_AS_POSSIBLE_IF_TARGET_NAVMESH_NOT_LOADED)
|
|
// ELIF GET_SCRIPT_TASK_STATUS(pedIndex, SCRIPT_TASK_ENTER_VEHICLE) != PERFORMING_TASK
|
|
// AND GET_SCRIPT_TASK_STATUS(pedIndex, SCRIPT_TASK_FOLLOW_NAV_MESH_TO_COORD) != PERFORMING_TASK
|
|
|
|
IF GET_SCRIPT_TASK_STATUS(pedIndex, SCRIPT_TASK_ENTER_VEHICLE) != PERFORMING_TASK
|
|
TASK_ENTER_VEHICLE(pedIndex, vehIndex, DEFAULT_TIME_NEVER_WARP, seat, PEDMOVE_WALK )
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Manages AI foursome navigation to next shot
|
|
/// PARAMS:
|
|
/// thisFoursome -
|
|
/// bOverridePlayer -
|
|
PROC GOLF_MANAGE_NAVIGATE_AI(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome)
|
|
INT iCurrentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
DO_NAVIGATION_TO_NEXT_SHOT(thisCourse, thisFoursome, iCurrentPlayer)
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Manages startup AI (walking from clubhouse to golfcart)
|
|
/// PARAMS:
|
|
/// thisFoursome -
|
|
/// allPlayers -
|
|
PROC GOLF_MANAGE_NAVIGATE_STARTUP_AI(GOLF_FOURSOME &thisFoursome)
|
|
INT iCurrentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
IF iCurrentPlayer > 1
|
|
GOLF_AI_WALK_TO_CART(thisFoursome, iCurrentPlayer, TRUE)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Stub for managing Address AI. Will eventually be flushed out with homing on a different/better shot
|
|
/// PARAMS:
|
|
/// thisGame -
|
|
/// thisCourse -
|
|
/// swingMeter -
|
|
/// RETURNS:
|
|
///
|
|
FUNC GOLF_PLAYER_STATE GOLF_MANAGE_ADDRESS_AI()
|
|
|
|
RETURN GPS_SWING_METER
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Stub/shortcut for managing AI swings. Just a slight randomization on the decided shot.
|
|
/// bUseRandomAim only matters if bSafety is set to TRUE
|
|
PROC GOLF_MANAGE_SWING_AI(GOLF_FOURSOME &thisFoursome, GOLF_GAME &thisGame, SWING_METER &swingMeter, BOOL bSafety = FALSE, BOOL bUseRandomAim = FALSE)
|
|
|
|
INT iBackswingModifier = 1000
|
|
|
|
IF IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_SHOT_IS_GIMMIE)
|
|
iBackswingModifier = 450
|
|
ENDIF
|
|
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
PRINTLN("Backswingtime + 1000: ",swingMeter.iBackswingStartTime, " Game time: ", GET_GAME_TIMER())
|
|
PRINTLN("Swing state ", swingMeter.meterState)
|
|
#ENDIF
|
|
|
|
BOOL bPlayerTimeout = IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_PLAYER_TIME_OUT)
|
|
FLOAT fAccuracyDistribution = 0
|
|
FLOAT fPowerReduction = PICK_FLOAT(bPlayerTimeout, 2.0, 1.0)
|
|
|
|
IF swingMeter.iBackswingDelta > 0
|
|
swingMeter.iBackswingDelta += FLOOR(GET_FRAME_TIME()*1000)
|
|
ENDIF
|
|
|
|
IF swingMeter.iBackswingStartTime = 0 AND NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
OR GET_GOLF_FOURSOME_CURRENT_PLAYER_SWING_ANIM(thisFoursome) = SAS_IDLE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SWING_ANIM(thisFoursome, SAS_SWINGING_BACK)
|
|
swingMeter.iBackswingStartTime = GET_GAME_TIMER()
|
|
swingMeter.iBackswingDelta = swingMeter.iBackswingStartTime
|
|
RESTART_TIMER_NOW(thisFoursome.physicsTimeout)
|
|
GOLF_PLAY_BACKSWING_SOUND(thisFoursome)
|
|
swingMeter.meterState = SWING_METER_RISING
|
|
ELIF ((swingMeter.iBackswingStartTime + iBackswingModifier < swingMeter.iBackswingDelta OR swingMeter.iBackswingHoldTime != 0)
|
|
AND swingMeter.meterState != SWING_METER_FINISHED AND swingMeter.meterState != SWING_METER_SHANK)
|
|
OR IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SWING_ANIM(thisFoursome, SAS_SWINGING_FORWARD)
|
|
swingMeter.meterState = SWING_METER_FINISHED
|
|
IF bSafety
|
|
swingMeter.fCurrentAccurRel = GET_RANDOM_FLOAT_POLAR(0, PICK_FLOAT(bUseRandomAim, 5.0, 0.0))
|
|
swingMeter.fCurrentPowerRel = GET_GOLF_FOURSOME_CURRENT_PLAYER_METER_GOAL(thisFoursome)
|
|
ELSE
|
|
swingMeter.fCurrentAccurRel = GET_RANDOM_FLOAT_POLAR(0, fAccuracyDistribution)
|
|
swingMeter.fCurrentPowerRel = GET_RANDOM_FLOAT_POLAR(GET_GOLF_FOURSOME_CURRENT_PLAYER_METER_GOAL(thisFoursome), 20) / fPowerReduction
|
|
IF swingMeter.fCurrentPowerRel < 15
|
|
swingMeter.fCurrentPowerRel = 15
|
|
ENDIF
|
|
ENDIF
|
|
IF GET_GOLF_FOURSOME_CURRENT_PLAYER_SWING_STYLE(thisFoursome) = SWING_STYLE_GREEN_SHORT
|
|
OR GET_GOLF_FOURSOME_CURRENT_PLAYER_SWING_STYLE(thisFoursome) = SWING_STYLE_GREEN_TAP
|
|
OR GET_GOLF_FOURSOME_CURRENT_PLAYER_SWING_STYLE(thisFoursome) = SWING_STYLE_GREEN_LONG
|
|
OR GET_GOLF_FOURSOME_CURRENT_PLAYER_SWING_STYLE(thisFoursome) = SWING_STYLE_GREEN
|
|
//we arnt doing the magic on the swing meter any more
|
|
ELSE
|
|
GOLF_PLAY_SWING_SOUND(thisFoursome, thisGame, FALSE, 1.0)
|
|
ENDIF
|
|
IF IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_METER_GOAL(thisFoursome, swingMeter.fCurrentPowerRel)
|
|
INCREMENT_GOLF_FOURSOME_CURRENT_PLAYER_AIM(thisFoursome, swingMeter.fCurrentAccurRel)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Stub for managing golf shot flight AI. May not be needed.
|
|
/// PARAMS:
|
|
/// swingMeter -
|
|
PROC GOLF_MANAGE_FLIGHT_AI(SWING_METER &swingMeter)
|
|
UNUSED_PARAMETER(swingMeter)
|
|
ENDPROC
|
|
|
|
|
|
PROC GOLF_CREATE_AI_GOLFER(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome, INT playerIndex)
|
|
|
|
VECTOR spawnPos
|
|
MODEL_NAMES pedModel
|
|
PED_TYPE pedType = PEDTYPE_PLAYER_UNUSED
|
|
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL(thisFoursome, playerIndex, COMPUTER)
|
|
IF playerIndex = 0
|
|
spawnPos = GET_GOLF_HOLE_TEE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
ELSE
|
|
spawnPos = GET_GOLF_HOLE_TEE_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), playerIndex)
|
|
ENDIF
|
|
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex))
|
|
pedModel = GET_GOLF_PED_MODEL(pedType)
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex, CREATE_PED( pedType, pedModel, spawnPos))
|
|
SET_ENTITY_HEADING(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), GET_HEADING_BETWEEN_VECTORS(spawnPos, GET_GOLF_HOLE_TEE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))))
|
|
IF HAS_ANIM_SET_LOADED("move_m@golfer@")
|
|
SET_PED_WEAPON_MOVEMENT_CLIPSET(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), "move_m@golfer@")
|
|
ENDIF
|
|
SET_TREAT_AS_AMBIENT_PED_FOR_DRIVER_LOCKON(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), TRUE)
|
|
//SET_PED_CAN_RAGDOLL(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), FALSE)
|
|
//SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), TRUE)
|
|
/*
|
|
IF playerIndex = 0
|
|
SET_PED_AS_GROUP_LEADER(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), GET_GOLF_FOURSOME_GROUP(thisFoursome))
|
|
ELSE
|
|
SET_PED_AS_GROUP_MEMBER(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), GET_GOLF_FOURSOME_GROUP(thisFoursome))
|
|
ENDIF
|
|
//*/
|
|
PRINTLN("Create AI Foursome PED!")
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC GOLF_INIT_FOURSOME_DATA(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome, INT holeToStart, INT iNumPlayers)
|
|
SET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome, holeToStart)
|
|
SET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome, iNumPlayers)
|
|
|
|
SET_GOLF_FOURSOME_CART_DRIVER(thisFoursome, 0, 0)
|
|
SET_GOLF_FOURSOME_CART_DRIVER(thisFoursome, 2, 1)
|
|
|
|
SET_GOLF_FOURSOME_LOCAL_PLAYER(thisFoursome, 0)//ai foursomes don't use this variable for its intended purpose so I am hyjacking it for somthing else
|
|
|
|
//SET_GOLF_FOURSOME_GROUP(thisFoursome, CREATE_GROUP(DEFAULT_TASK_ALLOCATOR_SIT_IN_LEADER_CAR))
|
|
|
|
GOLF_INIT_CURRENT_HOLE(thisCourse, thisFoursome)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome,0)
|
|
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
ENDPROC
|
|
|
|
PROC GOLF_CREATE_AI_CARTS(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome, INT holeToStart, INT iNumPlayers)
|
|
|
|
VECTOR cartSpawnPos
|
|
FLOAT cartHeading
|
|
INT iPlayerIndex
|
|
VECTOR cartOffset = <<0,0,0>>
|
|
|
|
REPEAT (iNumPlayers+1)/2 iPlayerIndex
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CART(thisFoursome,iPlayerIndex))
|
|
|
|
IF iPlayerIndex = 1
|
|
cartOffset = 10.0*GET_ENTITY_FORWARD_VECTOR(GET_GOLF_FOURSOME_CART(thisFoursome, 0))
|
|
PRINTLN(cartOffset)
|
|
ENDIF
|
|
|
|
IF FIND_SAFE_SPOT_FOR_CART_FAST(GET_GOLF_HOLE_TEE_POSITION(thisCourse, holeToStart) + cartOffset, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)), cartSpawnPos, cartHeading)
|
|
SET_GOLF_FOURSOME_CART(thisFoursome, CREATE_VEHICLE(CADDY, cartSpawnPos, cartHeading), iPlayerIndex)
|
|
SET_VEHICLE_EXTRA(GET_GOLF_FOURSOME_CART(thisFoursome, iPlayerIndex), 5, TRUE)
|
|
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(GET_GOLF_FOURSOME_CART(thisFoursome, iPlayerIndex), TRUE)
|
|
PRINTLN("Create AI Foursome Cart!")
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
/* we are streaming too manu models, no bags for ambient ai
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
IF iPlayerIndex < 2
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, iPlayerIndex, 0)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iPlayerIndex))
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iPlayerIndex, CREATE_OBJECT_NO_OFFSET(PROP_GOLF_BAG_01, GET_ENTITY_COORDS( GET_GOLF_FOURSOME_CART(thisFoursome, 0))))
|
|
PRINTLN("Create AI Foursome Bag!")
|
|
ENDIF
|
|
ATTACH_ENTITY_TO_ENTITY( GET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iPlayerIndex), GET_GOLF_FOURSOME_CART(thisFoursome, 0), 0, <<0.2 - (0.4 * iPlayerIndex) ,-1.0,0.6>>, <<0,0,0>>)
|
|
ELSE
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, iPlayerIndex, 1)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iPlayerIndex))
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iPlayerIndex, CREATE_OBJECT_NO_OFFSET(PROP_GOLF_BAG_01, GET_ENTITY_COORDS( GET_GOLF_FOURSOME_CART(thisFoursome, 1))))
|
|
PRINTLN("Create AI Foursome Bag!")
|
|
ENDIF
|
|
ATTACH_ENTITY_TO_ENTITY( GET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iPlayerIndex), GET_GOLF_FOURSOME_CART(thisFoursome, 1), 0, <<0.2 - (0.4 * (iPlayerIndex%2)) ,-1.0,0.6>>, <<0,0,0>>)
|
|
ENDIF
|
|
ENDREPEAT
|
|
//*/
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Creates an AI foursome, puts it on the proper hole, and prepares it to start playing golf.
|
|
/// PARAMS:
|
|
/// thisCourse -
|
|
/// thisFoursome -
|
|
/// iNumPlayers -
|
|
/// holeToStart -
|
|
PROC GOLF_CREATE_AI_FOURSOME (GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome, INT iNumPlayers, INT holeToStart, BOOL bCreateCarts = FALSE)
|
|
|
|
INT iPlayerIndex
|
|
|
|
GOLF_INIT_FOURSOME_DATA(thisCourse, thisFoursome, holeToStart, iNumPlayers)
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
GOLF_CREATE_AI_GOLFER(thisCourse, thisFoursome, iPlayerIndex)
|
|
ENDREPEAT
|
|
|
|
IF bCreateCarts
|
|
GOLF_CREATE_AI_CARTS(thisCourse, thisFoursome, holeToStart, iNumPlayers)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// State machine for an AI player taking a golf shot (from address to the ball being at rest)
|
|
/// PARAMS:
|
|
/// thisGame -
|
|
/// thisCourse -
|
|
/// thisFoursome -
|
|
PROC GOLF_AI_PLAYER_TAKE_SHOT(GOLF_GAME &thisGame,GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome)
|
|
|
|
// Need a better recovery mechanism here!
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
EXIT
|
|
ENDIF
|
|
IF IS_ENTITY_DEAD(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
EXIT
|
|
ENDIF
|
|
|
|
//FLOAT cameraOffsetZ
|
|
SWITCH GET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome)
|
|
CASE GPS_PLACE_BALL
|
|
DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: GPS_PLACE_BALL")
|
|
|
|
VECTOR vBallTeePos
|
|
|
|
vBallTeePos = GET_GOLF_HOLE_TEE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
|
|
GOLF_FIND_GROUND_Z(vBallTeePos)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome, CREATE_GOLF_BALL(vBallTeePos, GET_HEADING_BETWEEN_VECTORS(GET_GOLF_HOLE_FAIRWAY_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)), GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome))))
|
|
ELIF NOT IS_PLAYER_ON_PUTTING_GREEN()
|
|
SET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome), vBallTeePos)
|
|
ENDIF
|
|
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome, GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome)))
|
|
|
|
IF GET_GOLF_HOLE_PAR(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)) = 1
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome, <<0,0,0>>, LIE_GREEN)
|
|
ELSE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome, <<0,0,0>>, LIE_TEE)
|
|
ENDIF
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SHOT_NORMAL(thisFoursome, <<0,0,-1>>)
|
|
|
|
IF NOT bDrivingRangeMode
|
|
PICK_IDEAL_CLUB_AND_SHOT(thisGame, thisCourse,thisFoursome)
|
|
ENDIF
|
|
PLACE_PLAYER_AT_BALL(thisCourse, thisFoursome, thisGame.golfBag, FALSE, FALSE, TRUE, TRUE)
|
|
SET_ENTITY_RECORDS_COLLISIONS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome), FALSE)
|
|
FREEZE_GOLF_BALL(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome), TRUE)
|
|
SET_METER_MAX_DISTANCE(thisGame, thisCourse, thisFoursome)
|
|
SET_METER_CURRENT_DISTANCE(thisFoursome.swingMeter, thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], thisGame)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SHOT_ESTIMATE(thisFoursome, GOLF_FIND_SHOT_ESTIMATE(thisFoursome, thisGame.golfBag))
|
|
START_TIMER_NOW(thisFoursome.physicsTimeout)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_ADDRESS_BALL)
|
|
BREAK
|
|
|
|
CASE GPS_APPROACH_BALL
|
|
// DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: GPS_APPROACH_BALL")
|
|
IF NOT bDrivingRangeMode
|
|
PICK_IDEAL_CLUB_AND_SHOT(thisGame, thisCourse,thisFoursome)
|
|
ENDIF
|
|
PLACE_PLAYER_AT_BALL(thisCourse, thisFoursome, thisGame.golfBag, FALSE, FALSE, FALSE, TRUE)
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome, CREATE_GOLF_BALL(GET_GOLF_HOLE_TEE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)) + <<0,0, 0.075>>, GET_HEADING_BETWEEN_VECTORS(GET_GOLF_HOLE_FAIRWAY_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)), GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome))))
|
|
ENDIF
|
|
// SET_ENTITY_HEADING( GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome), GET_HEADING_BETWEEN_VECTORS(GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)), GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome))+90)
|
|
SET_METER_MAX_DISTANCE(thisGame, thisCourse, thisFoursome)
|
|
SET_METER_CURRENT_DISTANCE(thisFoursome.swingMeter, thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], thisGame)
|
|
IF NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_PUTTING(thisFoursome)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SHOT_ESTIMATE(thisFoursome, GOLF_FIND_SHOT_ESTIMATE(thisFoursome, thisGame.golfBag))
|
|
ENDIF
|
|
START_TIMER_NOW(thisFoursome.physicsTimeout)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_ADDRESS_BALL)
|
|
BREAK
|
|
|
|
CASE GPS_ADDRESS_BALL
|
|
IF IS_PLAYER_READY_TO_ADDRESS(thisFoursome)
|
|
OR IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_FAR_AWAY)
|
|
|
|
//When the golfer is in the address_ball state when he gets too far away from the player he will freeze
|
|
IF IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_FAR_AWAY)
|
|
TELEPORT_GOLFER_TO_BALL(thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome), thisCourse, FALSE)
|
|
//DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: State transition to GOLF_MANAGE_ADDRESS_AI()")
|
|
RESTART_TIMER_NOW(thisFoursome.physicsTimeout)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GOLF_MANAGE_ADDRESS_AI()) // The input manager here will change state - be careful!
|
|
EXIT
|
|
ENDIF
|
|
|
|
//make sure they are near the ball
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)) AND NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
IF VDIST2(GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)), GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome)) > 9
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
//DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: State transition back to GPS_ADDRESS_BALL for being far")
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_APPROACH_BALL)
|
|
EXIT
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RESTART_TIMER_NOW(thisFoursome.physicsTimeout)
|
|
//DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: State transition to GOLF_MANAGE_ADDRESS_AI()")
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GOLF_MANAGE_ADDRESS_AI()) // The input manager here will change state - be careful!
|
|
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SWING_ANIM(thisFoursome, SAS_SWINGING_BACK)
|
|
GOLF_MANAGE_SWING_ANIMS(thisGame, thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], thisFoursome.swingMeter)
|
|
IF IS_BALL_ON_GREEN(thisCourse, thisFoursome)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SHOT_ESTIMATE(thisFoursome, GOLF_FIND_SHOT_ESTIMATE(thisFoursome, thisGame.golfBag))
|
|
ENDIF
|
|
|
|
ELIF GET_ENTITY_SPEED(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)) = 0
|
|
AND TIMER_DO_ONCE_WHEN_READY( thisFoursome.physicsTimeout, 15)
|
|
//PRINTLN("Ped is performing sequence but not moving")
|
|
START_TIMER_NOW(thisFoursome.physicsTimeout)
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
|
|
IF NOT ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_PLACE_BALL)
|
|
ELSE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_APPROACH_BALL)
|
|
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GPS_SWING_METER
|
|
IF GET_DISTANCE_BETWEEN_ENTITIES_SQUARED(PLAYER_PED_ID(), thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].pedGolfPlayer, FALSE) < CLOSE_PED_DIST2
|
|
CPRINTLN(DEBUG_GOLF, "GOLF_MANAGE_AI_FOURSOME_PUTTING: Close to ped.")
|
|
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].pedGolfPlayer)
|
|
CLEAR_PED_TASKS_IMMEDIATELY(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].pedGolfPlayer)
|
|
//DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME_PUTTING: Ped has ragdolled. EXITING SWING_METER")
|
|
PLACE_PLAYER_AT_BALL(thisCourse, thisFoursome, thisGame.golfBag, FALSE, FALSE, FALSE, TRUE)
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_NAVIGATE_TO_SHOT)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_APPROACH_BALL)
|
|
|
|
CANCEL_TIMER(thisFoursome.physicsTimeout)
|
|
EXIT
|
|
ENDIF
|
|
ENDIF
|
|
//
|
|
|
|
|
|
// DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: GPS_SWING_METER")
|
|
IF bDebugSpew PRINTLN("Player ",GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome), " hitting ball") ENDIF
|
|
|
|
GOLF_MANAGE_SWING_AI(thisFoursome, thisGame, thisFoursome.swingMeter)
|
|
IF NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
GOLF_MANAGE_SWING_ANIMS(thisGame, thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], thisFoursome.swingMeter)
|
|
ENDIF
|
|
IF NOT IS_GOLF_CONTROL_FLAG_SET(thisGame, GCF_AI_HIT_BALL_THIS_FRAME)
|
|
IF (thisFoursome.swingMeter.meterState = SWING_METER_FINISHED OR thisFoursome.swingMeter.meterState = SWING_METER_SHANK OR IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)) AND DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
IF (HAS_SWING_ANIM_REACHED_BALL(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)) OR TIMER_DO_ONCE_WHEN_READY( thisFoursome.physicsTimeout, 2.5) OR IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)) AND DOES_ENTITY_HAVE_PHYSICS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
IF IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
IF bDebugSpew DEBUG_MESSAGE("Player hitting ball with no anim - we are far away") ENDIF
|
|
thisFoursome.swingMeter.meterState = SWING_METER_FINISHED
|
|
ENDIF
|
|
IF GOLF_HIT_BALL(thisGame, thisCourse, thisFoursome)
|
|
thisFoursome.swingMeter.meterState = SWING_METER_INACTIVE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_BALL_IN_FLIGHT)
|
|
ELSE
|
|
// We didnt hit the ball (force <<0,0,0>>) so lets false start instead
|
|
thisFoursome.swingMeter.meterState = SWING_METER_INACTIVE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_ADDRESS_BALL)
|
|
ENDIF
|
|
SET_GOLF_CONTROL_FLAG( thisGame, GCF_AI_HIT_BALL_THIS_FRAME)
|
|
ENDIF
|
|
ELIF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
thisFoursome.swingMeter.meterState = SWING_METER_INACTIVE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_PLACE_BALL)
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GPS_BALL_IN_FLIGHT
|
|
// DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: GPS_BALL_IN_FLIGHT")
|
|
IF HAS_SWING_ANIM_REACHED_TIME(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), 1.0)
|
|
GOLF_MANAGE_AI_POST_SHOT_ANIMATIONS(thisGame, thisFoursome, TRUE)
|
|
ENDIF
|
|
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome, CREATE_GOLF_BALL(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome), GET_HEADING_BETWEEN_VECTORS(GET_GOLF_HOLE_FAIRWAY_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)), GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome))))
|
|
ENDIF
|
|
IF NOT IS_BALL_ON_GREEN(thisCourse, thisFoursome)
|
|
GOLF_MANAGE_BALL_IN_FLIGHT(thisGame, thisCourse, thisFoursome)
|
|
GOLF_MANAGE_FLIGHT_AI(thisFoursome.swingMeter)
|
|
IF IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET( thisFoursome, GOLF_BALL_AT_REST)
|
|
GOLF_CLEAR_SWING_METER(thisFoursome.swingMeter)
|
|
ENDIF
|
|
ELSE
|
|
GOLF_MANAGE_BALL_ON_GREEN(thisGame, thisCourse, thisFoursome)
|
|
IF IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET( thisFoursome, GOLF_BALL_AT_REST)
|
|
GOLF_CLEAR_SWING_METER(thisFoursome.swingMeter)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
BREAK
|
|
CASE GPS_BALL_AT_REST
|
|
// DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: GPS_BALL_AT_REST")
|
|
GOLF_MANAGE_AI_POST_SHOT_ANIMATIONS(thisGame, thisFoursome, TRUE)
|
|
IF IS_BALL_IN_WATER_HAZARD(thisFoursome) OR IS_BALL_LIE_UNKOWN(thisFoursome)
|
|
OR IS_GOLF_COORD_OUTSIDE_BOUNDARY_PLANES(GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome)))
|
|
GOLF_RESET_BALL_AT_REST_HAZARD(thisFoursome)
|
|
ELSE
|
|
GOLF_RESET_BALL_AT_REST(thisCourse, thisFoursome)
|
|
ENDIF
|
|
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_POST_SHOT_REACTION)
|
|
INCREMENT_GOLF_FOURSOME_CURRENT_PLAYER_SHOTS_ON_HOLE(thisFoursome)
|
|
|
|
//If the ai is 4 over par, just end the hole
|
|
IF GET_GOLF_FOURSOME_CURRENT_PLAYER_SHOTS_ON_HOLE(thisFoursome) > (GET_GOLF_HOLE_PAR(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisfoursome)) + 3)
|
|
//PRINTLN("4 over par - finish hole.")
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_POST_SHOT_REACTION)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG(thisFoursome, GOLF_STROKE_LIMIT)
|
|
ENDIF
|
|
|
|
BREAK
|
|
CASE GPS_BALL_IN_HOLE_CELEBRATION
|
|
GOLF_MANAGE_AI_POST_SHOT_ANIMATIONS(thisGame, thisFoursome, TRUE)
|
|
// DEBUG_MESSAGE("GOLF_AI_PLAYER_TAKE_SHOT: GPS_BALL_IN_HOLE_CELEBRATION")
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_POST_SHOT_REACTION)
|
|
|
|
INCREMENT_GOLF_FOURSOME_CURRENT_PLAYER_SHOTS_ON_HOLE(thisFoursome)
|
|
CLEANUP_GOLF_FOURSOME_CURRENT_GOLF_BALL(thisFoursome)
|
|
CLEAR_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG(thisFoursome, GOLF_STOP_USING_CART)
|
|
IF NOT ARE_ALL_PLAYERS_DONE_WITH_HOLE(thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)) AND NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
OPEN_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
TASK_GO_TO_COORD_ANY_MEANS( NULL, GET_GOLF_HOLE_GREEN_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)), PEDMOVE_WALK, NULL)
|
|
TASK_TURN_PED_TO_FACE_COORD( NULL, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)))
|
|
CLOSE_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
TASK_PERFORM_SEQUENCE(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
CLEAR_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
ENDIF
|
|
|
|
BREAK
|
|
CASE GPS_POST_SHOT_REACTION
|
|
IF NOT GOLF_MANAGE_AI_POST_SHOT_ANIMATIONS(thisGame, thisFoursome, FALSE)
|
|
|
|
// If players are around the green or tee, move them to a spectating spot rather than have them walk around a bunch
|
|
IF WAS_TEE_SHOT(thisCourse, thisFoursome) // We are finished with the tee shot
|
|
AND NOT ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome))
|
|
IF NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
IF bDebugSpew DEBUG_MESSAGE("Moving player to tee spectate") ENDIF
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
OPEN_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
TASK_FOLLOW_NAV_MESH_TO_COORD( NULL, GET_GOLF_HOLE_TEE_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)), PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
|
|
TASK_TURN_PED_TO_FACE_COORD( NULL, GET_GOLF_HOLE_TEE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)))
|
|
CLOSE_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
TASK_PERFORM_SEQUENCE(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
CLEAR_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
ELSE
|
|
SET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), GET_GOLF_HOLE_TEE_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)))
|
|
ENDIF
|
|
ELIF IS_GOLF_FOURSOME_CURRENT_PLAYER_PUTTING(thisFoursome) OR IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_STOP_USING_CART)
|
|
IF NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
IF NOT ARE_ALL_PLAYERS_DONE_WITH_HOLE(thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome))
|
|
IF bDebugSpew DEBUG_MESSAGE("Moving player to green spectate") ENDIF
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
OPEN_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
TASK_FOLLOW_NAV_MESH_TO_COORD( NULL, GET_GOLF_HOLE_GREEN_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)), PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
|
|
TASK_TURN_PED_TO_FACE_COORD( NULL, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)))
|
|
CLOSE_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
TASK_PERFORM_SEQUENCE(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
CLEAR_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
ENDIF
|
|
ELIF NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_PUTTING_GREEN_AI)
|
|
SET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), GET_GOLF_HOLE_GREEN_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)))
|
|
ENDIF
|
|
ELSE //golfer just hit from fairway
|
|
IF NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
IF NOT ARE_ALL_PLAYERS_DONE_WITH_HOLE(thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)) AND DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_CART(thisFoursome))
|
|
IF NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_CURRENT_PLAYER_CART(thisFoursome))
|
|
//TASK_FOLLOW_NAV_MESH_TO_COORD(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_CART(thisFoursome)), PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
OPEN_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
TASK_ENTER_VEHICLE(NULL, GET_GOLF_FOURSOME_CURRENT_PLAYER_CART(thisFoursome), DEFAULT_TIME_NEVER_WARP, GET_GOLF_FOURSOME_CURRENT_PLAYER_SEAT(thisFoursome), PEDMOVE_WALK)
|
|
CLOSE_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
TASK_PERFORM_SEQUENCE(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
CLEAR_SEQUENCE_TASK(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)].seq_swing_and_outro)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF GET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome) = LIE_CUP OR IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_STROKE_LIMIT)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_DONE_WITH_HOLE)
|
|
CLEAR_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG(thisFoursome, GOLF_STROKE_LIMIT)
|
|
ELSE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_DONE_WITH_SHOT)
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
TYPEDEF FUNC VECTOR GET_GOLF_SPECTATE_LOCATION_CALLBACK(GOLF_COURSE &golfCourse, INT holeIndex, INT spectateIndex)
|
|
TYPEDEF FUNC VECTOR GET_GOLF_LOOK_AT_CALLBACK(GOLF_COURSE &golfCourse, INT holeIndex)
|
|
|
|
PROC AI_GOLFERS_LEAVE_CART_AND_MOVE_TO_SPECTATE(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse, INT cartIndex, BOOL stopUsingCart, GET_GOLF_SPECTATE_LOCATION_CALLBACK moveToCB, GET_GOLF_LOOK_AT_CALLBACK faceToCB)
|
|
|
|
INT playerIndex
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
IF ((cartIndex = 0 AND (playerIndex = 0 OR playerIndex = 1))
|
|
OR (cartIndex = 1 AND (playerIndex = 2 OR playerIndex = 3)))
|
|
AND GET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL(thisFoursome, playerIndex) = COMPUTER
|
|
OPEN_SEQUENCE_TASK(thisFoursome.playerCore[playerIndex].seq_swing_and_outro)
|
|
TASK_LEAVE_ANY_VEHICLE(NULL)
|
|
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, CALL moveToCB(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), playerIndex), PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
|
|
TASK_TURN_PED_TO_FACE_COORD( NULL, CALL faceToCB(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)))
|
|
CLOSE_SEQUENCE_TASK(thisFoursome.playerCore[playerIndex].seq_swing_and_outro)
|
|
TASK_PERFORM_SEQUENCE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome,playerIndex), thisFoursome.playerCore[playerIndex].seq_swing_and_outro)
|
|
CLEAR_SEQUENCE_TASK(thisFoursome.playerCore[playerIndex].seq_swing_and_outro)
|
|
|
|
IF stopUsingCart AND GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, playerIndex) != GPS_DONE_WITH_HOLE
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG(thisFoursome, playerIndex, GOLF_STOP_USING_CART)
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
FUNC BOOL DOES_GOLF_AI_FOURSOME_USE_CART(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse)
|
|
|
|
INT magicDistanceFromBall = 150
|
|
INT magicDistanceFromGreen = 1600
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
//too close to green, don't use cart
|
|
IF VDIST2(GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)), GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))) < magicDistanceFromGreen
|
|
//the cart is not near the green, drive to it
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_CART(thisFoursome)) AND NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_CART(thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER_CART_INDEX(thisFoursome)))
|
|
IF VDIST2(GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_CART(thisFoursome)), GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))) > magicDistanceFromGreen
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
//the cart and golfer are near green have everyone get out and walk to their ball
|
|
AI_GOLFERS_LEAVE_CART_AND_MOVE_TO_SPECTATE(thisFoursome, thisCourse, GET_GOLF_FOURSOME_CURRENT_PLAYER_CART_INDEX(thisFoursome) ,TRUE,
|
|
&GET_GOLF_HOLE_GREEN_SPECTATE_POSITION, &GET_GOLF_HOLE_PIN_POSITION)
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
//too close to ball don't bother going to cart first
|
|
IF VDIST2(GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)), GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome)) < magicDistanceFromBall
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC AI_DRIVE_CART(GOLF_FOURSOME &thisFoursome, INT playerIndex, GOLF_COURSE &thisCourse, BOOL getOutOfCart, BOOL bPlayersFoursome = FALSE)
|
|
|
|
//im not using thisFoursome.playerCore[playerIndex].vShotEstimate right now so im going to borrow it to keep track of where the cart is driving
|
|
FLOAT cartHeading, stoppingDistance
|
|
PED_INDEX cartDriver = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_DRIVER(thisFoursome,playerIndex))
|
|
INT tempIndex
|
|
VECTOR ballPos = GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL_POSITION(thisFoursome, playerIndex)
|
|
VECTOR cartOffset = <<0,0,0>>
|
|
|
|
IF IS_ENTITY_DEAD(cartDriver)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_DEAD(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex))
|
|
#IF GOLF_IS_AI_ONLY
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
#ENDIF
|
|
EXIT
|
|
ENDIF
|
|
|
|
stoppingDistance = 144
|
|
BOOL bNearBall = VDIST2(GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CART(thisFoursome, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, playerIndex))), thisFoursome.playerCore[playerIndex].vShotEstimate) < stoppingDistance
|
|
|
|
IF NOT IS_PED_IN_VEHICLE(cartDriver, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex))
|
|
AND NOT bNearBall
|
|
IF GET_SCRIPT_TASK_STATUS(cartDriver, SCRIPT_TASK_ENTER_VEHICLE) != PERFORMING_TASK
|
|
TASK_ENTER_VEHICLE(cartDriver, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex), DEFAULT_TIME_NEVER_WARP, VS_DRIVER, PEDMOVE_WALK)
|
|
ENDIF
|
|
|
|
EXIT //you must be in cart to drive
|
|
ENDIF
|
|
|
|
DRIVINGMODE cartDrivingMode = DRIVINGMODE_STOPFORCARS
|
|
IF bPlayersFoursome
|
|
cartDrivingMode = DF_StopForCars | DF_SteerAroundPeds
|
|
ENDIF
|
|
|
|
IF DOES_ENTITY_EXIST(cartDriver) AND NOT IS_ENTITY_DEAD(cartDriver)
|
|
AND (GET_SCRIPT_TASK_STATUS(cartDriver, SCRIPT_TASK_VEHICLE_DRIVE_TO_COORD) != PERFORMING_TASK )
|
|
AND NOT IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisFoursome.playerCore[playerIndex], GOLF_CART_ARRIVED)
|
|
|
|
//add an offset to the second cart when driving to the tee, this way the two carts wont try and park in the same spot
|
|
IF GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, playerIndex) = 1 AND NOT ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome)
|
|
IF IS_TEE_SHOT(thisCourse, thisFoursome)
|
|
AND GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome) = 0
|
|
cartOffset = <<-3,-3,0>>
|
|
ELSE
|
|
cartOffset = <<3,3,0>>
|
|
ENDIF
|
|
ENDIF
|
|
|
|
//drive cart to the vehicle node near the ball
|
|
FIND_SAFE_SPOT_FOR_CART( ballPos + cartOffset, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)),thisFoursome.playerCore[playerIndex].vShotEstimate, cartHeading, <<0,0,0>>, <<0,0,0>>)
|
|
|
|
TASK_VEHICLE_DRIVE_TO_COORD(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_DRIVER(thisFoursome, playerIndex)), GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex),
|
|
thisFoursome.playerCore[playerIndex].vShotEstimate, 4.0, DRIVINGSTYLE_NORMAL, DUMMY_MODEL_FOR_SCRIPT, cartDrivingMode , 4, -1)
|
|
ENDIF
|
|
|
|
//you are getting close to the ball stop and let the current player out
|
|
IF bNearBall
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_DRIVER(thisFoursome, playerIndex)))
|
|
SET_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playerCore[playerIndex], GOLF_CART_ARRIVED)
|
|
|
|
//tee shot
|
|
IF NOT ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome)
|
|
//move to the tee make everyone leave the vehicle
|
|
TASK_EVERYONE_LEAVE_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex))
|
|
|
|
BOOL everyoneOutOfCart = TRUE
|
|
//tell golfers to move to tee spectate once they get out of cart
|
|
AI_GOLFERS_LEAVE_CART_AND_MOVE_TO_SPECTATE(thisFoursome, thisCourse, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, playerIndex), FALSE,
|
|
&GET_GOLF_HOLE_TEE_SPECTATE_POSITION, &GET_GOLF_HOLE_TEE_POSITION)
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) tempIndex
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, tempIndex))
|
|
AND NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, tempIndex))
|
|
IF IS_PED_IN_ANY_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, tempIndex))
|
|
everyoneOutOfCart = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF everyoneOutOfCart AND getOutOfCart
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
ENDIF
|
|
|
|
//green
|
|
ELIF VDIST2(GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL_POSITION(thisFoursome, playerIndex), GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))) < 1600
|
|
AND VDIST2(GET_ENTITY_COORDS(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex)), GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))) < 1600
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_STOP_USING_CART)
|
|
|
|
//the cart and ball are near green have everyone get out and walk to their ball
|
|
AI_GOLFERS_LEAVE_CART_AND_MOVE_TO_SPECTATE(thisFoursome, thisCourse, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, playerIndex), TRUE,
|
|
&GET_GOLF_HOLE_GREEN_SPECTATE_POSITION, &GET_GOLF_HOLE_PIN_POSITION)
|
|
|
|
IF getOutOfCart
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
ENDIF
|
|
ELIF IS_PED_IN_ANY_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)) // driving cart when player reached destination
|
|
|
|
TASK_VEHICLE_PARK(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_DRIVER(thisFoursome, playerIndex)),
|
|
GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex), GET_ENTITY_COORDS(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex)), 0, PARK_TYPE_PULL_OVER,360)
|
|
|
|
IF getOutOfCart
|
|
TASK_LEAVE_ANY_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex))
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, playerIndex, GPS_APPROACH_BALL)
|
|
ENDIF
|
|
ELSE //player reached destination while not in a cart, probably because he recently was in the far away state
|
|
|
|
IF getOutofCart
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, playerIndex, GPS_APPROACH_BALL)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC MOVE_GOLF_AI_FOURSOME_TO_HOLE(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse, INT iHole)
|
|
PRINTLN("Move Foursome to Hole ", iHole)
|
|
GOLF_CLEANUP_CURRENT_HOLE(thisCourse, thisFoursome)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome,0)
|
|
SET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome, iHole)
|
|
GOLF_INIT_CURRENT_HOLE(thisCourse, thisFoursome)
|
|
|
|
TELEPORT_FOURSOME_TO_TEE(thisFoursome, thisCourse)
|
|
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
ENDPROC
|
|
|
|
PROC MOVE_GOLF_FOURSOME_TO_NEXT_AVAILABLE_HOLE(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse, GOLF_FOURSOME &allAIFoursomes[])
|
|
|
|
INT holeIndex
|
|
|
|
REPEAT GET_GOLF_COURSE_NUM_HOLES(thisCourse) holeIndex
|
|
IF NOT IS_ANY_GOLF_FOURSOME_PLAYING_HOLE(allAIFoursomes, holeIndex) //no other foursome is playing at the hole we might move to
|
|
|
|
// Player is playing on this hole, move group to next available hole
|
|
MOVE_GOLF_AI_FOURSOME_TO_HOLE(thisFoursome, thisCourse, holeIndex)
|
|
|
|
EXIT// break out of loop
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
FUNC INT GET_HOLE_FOURSOME_SHOULD_BE_AT_WHEN_PLAYER_IS_AT_HOLE(INT iPlayersHole)
|
|
|
|
SWITCH iPlayersHole
|
|
CASE 0
|
|
RETURN 2
|
|
BREAK
|
|
CASE 1
|
|
RETURN 0
|
|
BREAK
|
|
CASE 2
|
|
RETURN 1
|
|
BREAK
|
|
CASE 3
|
|
RETURN 2
|
|
BREAK
|
|
CASE 4
|
|
RETURN 3
|
|
BREAK
|
|
CASE 5
|
|
RETURN 4
|
|
BREAK
|
|
CASE 6
|
|
RETURN 5
|
|
BREAK
|
|
CASE 7
|
|
RETURN 2
|
|
BREAK
|
|
CASE 8
|
|
RETURN 2
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN 2
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Manages an AI foursome - navigating to shots, taking shots, finishing hole, etc
|
|
/// PARAMS:
|
|
/// thisGame -
|
|
/// thisCourse -
|
|
/// thisFoursome -
|
|
PROC GOLF_MANAGE_AI_FOURSOME(GOLF_GAME &thisGame,GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome, GOLF_FOURSOME &allAIFoursomes[], INT iFoursomeIndex)
|
|
// PRINTSTRING("GOLF_MANAGE_AI_FOURSOME working on golfer ")PRINTINT(GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome))PRINTNL()
|
|
INT playerIndex
|
|
|
|
IF ARE_ALL_PLAYERS_REMOVED_FROM_GOLF_GAME(thisFoursome)
|
|
//The peds only get deleted if they are far from the player, check to see if peds removed from the golf game need to be deleted
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
GOLF_REMOVE_AI_PED(thisFoursome, playerIndex)
|
|
ENDREPEAT
|
|
EXIT
|
|
ENDIF
|
|
|
|
//local player is never used in ai foursomes, I am using it to round robin this expensive function
|
|
UPDATE_AI_FAR_AWAY(thisFoursome.playerCore[thisFoursome.iLocalPlayerIndex], PLAYER_PED_ID(), thisFoursome, thisFoursome.iLocalPlayerIndex , thisCourse)
|
|
thisFoursome.iLocalPlayerIndex++
|
|
IF thisFoursome.iLocalPlayerIndex >= GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome)
|
|
thisFoursome.iLocalPlayerIndex = 0
|
|
ENDIF
|
|
|
|
BOOL bWanted = GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
|
|
AGGRO_ARGS aggroArguments
|
|
EAGGRO aggroReason
|
|
aggroArguments.iShotIRange = 25
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
//Has a golfer been killed
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]))
|
|
IF IS_ENTITY_DEAD(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]))
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_PLAYER_REMOVED )
|
|
PRINTSTRING("Some one died, stop golfing.\n")
|
|
GOLF_REMOVE_AI_FOURSOME(thisFoursome)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF bWanted AND GET_PLAYER_DISTANCE_FROM_ENTITY(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex])) < 100
|
|
PRINTLN("player nearby is wanted, stop golfing")
|
|
GOLF_REMOVE_AI_FOURSOME(thisFoursome)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF DO_AGGRO_CHECK(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]), GET_GOLF_FOURSOME_CART(thisFoursome,0), aggroArguments, aggroReason, TRUE)
|
|
PRINTLN("DO_AGGRO_CHECK, stop golfing")
|
|
GOLF_REMOVE_AI_FOURSOME(thisFoursome)
|
|
EXIT
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
//The player stole your cart, don't try and use it anymore
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
IF GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) = GET_GOLF_FOURSOME_CART(thisFoursome,0)
|
|
PRINTLN("Disowning ai cart")
|
|
SET_ENTITY_AS_MISSION_ENTITY(GET_GOLF_FOURSOME_CART(thisFoursome,0), FALSE)
|
|
SET_VEHICLE_AS_NO_LONGER_NEEDED(thisFoursome.vehCart[0])
|
|
SET_GOLF_FOURSOME_CART(thisFoursome, NULL, 0)
|
|
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 0))
|
|
AND NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 0))
|
|
IF GET_SCRIPT_TASK_STATUS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 0), SCRIPT_TASK_ENTER_VEHICLE) != PERFORMING_TASK
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 0))
|
|
TASK_TURN_PED_TO_FACE_ENTITY(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 0), PLAYER_PED_ID(), -1)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 1))
|
|
AND NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 1))
|
|
IF GET_SCRIPT_TASK_STATUS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 1), SCRIPT_TASK_ENTER_VEHICLE) != PERFORMING_TASK
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 1))
|
|
TASK_TURN_PED_TO_FACE_ENTITY(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 1), PLAYER_PED_ID(), -1)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) = GET_GOLF_FOURSOME_CART(thisFoursome,1)
|
|
SET_ENTITY_AS_MISSION_ENTITY(GET_GOLF_FOURSOME_CART(thisFoursome,1), FALSE)
|
|
SET_VEHICLE_AS_NO_LONGER_NEEDED(thisFoursome.vehCart[1])
|
|
SET_GOLF_FOURSOME_CART(thisFoursome, NULL, 1)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
//moves group if the player starts the game and there is a group on that hole
|
|
IF g_sGolfGlobals.CurrrentPlayerHole = GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)
|
|
MOVE_GOLF_FOURSOME_TO_NEXT_AVAILABLE_HOLE(thisFoursome, thisCourse, allAIFoursomes)
|
|
ENDIF
|
|
|
|
//Make sure foursome is in an appropiate hole when the player is on the course
|
|
IF iFoursomeIndex = 0 AND IS_GLOBAL_GOLF_CONTROL_FLAG_SET(GGCF_PLAYER_ADDRESSING_BALL)
|
|
INT iMoveToHole = GET_HOLE_FOURSOME_SHOULD_BE_AT_WHEN_PLAYER_IS_AT_HOLE(g_sGolfGlobals.CurrrentPlayerHole)
|
|
|
|
IF GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome) != iMoveToHole
|
|
AND NOT IS_ANY_GOLF_FOURSOME_PLAYING_HOLE(allAIFoursomes, iMoveToHole)
|
|
MOVE_GOLF_AI_FOURSOME_TO_HOLE(thisFoursome, thisCourse, iMoveToHole)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_GOLF_CONTROL_FLAG_SET(thisGame, GCF_PLAYER_SKIP) OR IS_GLOBAL_GOLF_CONTROL_FLAG_SET(GGCF_PLAYER_SKIP)
|
|
// Player has pressed skip - move all players to their next shot
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]))
|
|
IF NOT IS_ENTITY_DEAD(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]))
|
|
SET_ENTITY_COORDS(GET_GOLF_PLAYER_PED(thisFoursome.playerCore[playerIndex]), GET_GOLF_PLAYER_BALL_POSITION(thisFoursome.playerCore[playerIndex]))
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
|
|
ENDIF
|
|
|
|
IF IS_GOLF_CONTROL_FLAG_SET(thisGame, GCF_PLAYER_DONE_WITH_HOLE) OR IS_GLOBAL_GOLF_CONTROL_FLAG_SET(GGCF_PLAYER_DONE_WITH_HOLE)
|
|
// Player has finished hole - move all players to their next tee
|
|
INT iMoveToHole = GET_HOLE_FOURSOME_SHOULD_BE_AT_WHEN_PLAYER_IS_AT_HOLE(g_sGolfGlobals.CurrrentPlayerHole)
|
|
MOVE_GOLF_AI_FOURSOME_TO_HOLE(thisFoursome, thisCourse, iMoveToHole)
|
|
ENDIF
|
|
|
|
INT iCurrentHole
|
|
VECTOR moveTo
|
|
SWITCH GET_GOLF_FOURSOME_STATE(thisFoursome)
|
|
|
|
CASE GGS_GET_IN_CART
|
|
|
|
IF NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY)
|
|
|
|
//task every golfer in the foursome to go to the cart
|
|
// REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome,thisFoursome.iLocalPlayerIndex)) AND NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome,thisFoursome.iLocalPlayerIndex))
|
|
AND DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex))
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, thisFoursome.iLocalPlayerIndex, GOLF_PLAYER_REMOVED)
|
|
AND GET_DISTANCE_BETWEEN_ENTITIES(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, thisFoursome.iLocalPlayerIndex), GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex)) < 25.0
|
|
|
|
IF GET_SCRIPT_TASK_STATUS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex), SCRIPT_TASK_ENTER_VEHICLE) != PERFORMING_TASK
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, thisFoursome.iLocalPlayerIndex, GOLF_STOP_USING_CART)
|
|
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex))
|
|
IF NOT IS_PED_IN_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex), GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome,thisFoursome.iLocalPlayerIndex))
|
|
IF thisFoursome.iLocalPlayerIndex = GET_GOLF_FOURSOME_CART_DRIVER(thisFoursome, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome,thisFoursome.iLocalPlayerIndex))
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex+1)) OR NOT IS_PED_GETTING_INTO_A_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex+1))
|
|
TASK_ENTER_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex), GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome,thisFoursome.iLocalPlayerIndex), DEFAULT_TIME_NEVER_WARP, VS_DRIVER, PEDMOVE_WALK)
|
|
ENDIF
|
|
ELSE
|
|
TASK_ENTER_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, thisFoursome.iLocalPlayerIndex), GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome,thisFoursome.iLocalPlayerIndex), DEFAULT_TIME_NEVER_WARP, VS_FRONT_RIGHT, PEDMOVE_WALK)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELSE
|
|
//the cart does not exist tell everyone to walk to ball
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
IF playerIndex != GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)
|
|
IF IS_INDEXED_BALL_IN_RANGE_OF_GREEN(thisCourse, thisFoursome, playerIndex)
|
|
moveTo = GET_GOLF_HOLE_GREEN_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), playerIndex)
|
|
ELIF NOT ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome)
|
|
moveTo = GET_GOLF_HOLE_TEE_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), playerIndex)
|
|
ELSE
|
|
moveTo = GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL_POSITION(thisFoursome, playerIndex)
|
|
ENDIF
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)) AND NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex))
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex))
|
|
TASK_FOLLOW_NAV_MESH_TO_COORD(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), moveTo, PEDMOVE_WALK,DEFAULT_TIME_NEVER_WARP)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
IF IS_TEE_SHOT(thisCourse, thisFoursome)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_PLACE_BALL)
|
|
ELSE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_APPROACH_BALL)
|
|
ENDIF
|
|
ENDIF
|
|
//ENDREPEAT
|
|
|
|
IF ARE_ALL_GOLFERS_IN_CART(thisFoursome)
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playerCore[playerIndex], GOLF_CART_ARRIVED)
|
|
ENDREPEAT
|
|
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_DRIVE_TO_SHOT)
|
|
START_TIMER_NOW(thisFoursome.physicsTimer)
|
|
ENDIF
|
|
|
|
ELSE
|
|
//the player is far away from this golfer
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
IF IS_TEE_SHOT(thisCourse, thisFoursome)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_PLACE_BALL)
|
|
ELSE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_APPROACH_BALL)
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGS_DRIVE_TO_SHOT
|
|
|
|
|
|
//wait a little bit before the cart starts driving, otherwise it looks to robotic
|
|
IF TIMER_DO_WHEN_READY(thisFoursome.physicsTimer, 2.0)
|
|
AI_DRIVE_CART(thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome), thisCourse, TRUE)
|
|
ENDIF
|
|
|
|
|
|
//the first cart is driving the current golfer and there are more then two golfers
|
|
IF GET_GOLF_FOURSOME_CURRENT_PLAYER_CART_INDEX(thisFoursome) = 0 AND GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) > 2
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, 2, GOLF_STOP_USING_CART)
|
|
//have the second cart drive to a ball
|
|
IF GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) = 3
|
|
AI_DRIVE_CART(thisFoursome, 2, thisCourse, FALSE) //the third ped is the only possible driver in this case
|
|
ELSE
|
|
AI_DRIVE_CART(thisFoursome, GET_GOLF_PLAYER_WHOSE_BALL_IS_FARTHER_FROM_PIN(thisFoursome, 2, 3), thisCourse, FALSE)
|
|
ENDIF
|
|
|
|
ELIF GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) > 2 //the second cart is driving the current gofler
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, 0, GOLF_STOP_USING_CART)
|
|
//have the first cart drive to a ball
|
|
AI_DRIVE_CART(thisFoursome, GET_GOLF_PLAYER_WHOSE_BALL_IS_FARTHER_FROM_PIN(thisFoursome, 0, 1), thisCourse, FALSE)
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
/*
|
|
CASE GGS_NAVIGATE_TO_SHOT
|
|
// DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: GMS_NAVIGATE_TO_SHOT")
|
|
|
|
GOLF_MANAGE_NAVIGATE_AI(thisCourse, thisFoursome)
|
|
IF ARE_ALL_PLAYERS_ON_THE_GREEN(thisFoursome)
|
|
// Delete the flag as everyone is on the green
|
|
CLEANUP_GOLF_HOLE_FLAG(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
ENDIF
|
|
IF GOLF_IS_ANY_PLAYER_APPROACHING_BALL(thisFoursome)
|
|
IF bDebugSpew DEBUG_MESSAGE("GMS_NAVIGATE_TO_SHOT - player approaches shot") ENDIF
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
ENDIF
|
|
BREAK
|
|
//*/
|
|
CASE GGS_TAKING_SHOT
|
|
// DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: GMS_TAKING_SHOT")
|
|
//If the 'wait for available hole' flag is not set
|
|
IF NOT IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_WAITING_FOR_HOLE)
|
|
//take shot
|
|
GOLF_AI_PLAYER_TAKE_SHOT(thisGame, thisCourse, thisFoursome)
|
|
ELSE
|
|
//Check availablity again
|
|
IF IS_NEXT_GOLF_HOLE_AVAILABLE(thisCourse, thisFoursome, allAIFoursomes, 0)
|
|
//Clear wait control flag
|
|
CLEAR_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG(thisFoursome, GOLF_WAITING_FOR_HOLE)
|
|
ENDIF
|
|
ENDIF
|
|
IF NOT IS_PED_INJURED(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
SET_PED_RESET_FLAG(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), PRF_ExpandPedCapsuleFromSkeleton, TRUE)
|
|
ENDIF
|
|
|
|
// Next state logic is getting more complicated
|
|
IF ARE_ALL_PLAYERS_DONE_WITH_HOLE(thisFoursome)
|
|
|
|
GOLF_CLEANUP_CURRENT_HOLE(thisCourse, thisFoursome)
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) thisFoursome.iCurrentPlayer
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_PLACE_BALL)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome, <<0,0,0>>, LIE_TEE)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SHOT_NORMAL(thisFoursome, <<0,0,-1>>)
|
|
ENDREPEAT
|
|
iCurrentHole = GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)
|
|
//Check to see if next hole is not empty
|
|
IF NOT IS_NEXT_GOLF_HOLE_AVAILABLE(thisCourse, thisFoursome, allAIFoursomes)
|
|
//Set control flag to wait
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG(thisFoursome, 0, GOLF_WAITING_FOR_HOLE)
|
|
ENDIF
|
|
|
|
GOLF_MOVE_TO_NEXT_HOLE(thisGame, thisCourse, thisFoursome, 8)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome, 0)
|
|
IF GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome) != iCurrentHole
|
|
GOLF_INIT_CURRENT_HOLE(thisCourse, thisFoursome)
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_SCORECARD_END_HOLE)
|
|
ENDIF
|
|
|
|
IF IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_FAR_AWAY) //golfer is far away, teleport him to his next shot
|
|
moveTo = GET_GOLF_HOLE_TEE_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome))
|
|
TELEPORT_GOLFER_TO_COORD(thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome), moveTo, thisCourse, FALSE)
|
|
TASK_TURN_PED_TO_FACE_COORD(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)))
|
|
ENDIF
|
|
ELIF IS_PLAYER_DONE_WITH_SHOT(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)])
|
|
|
|
CLEANUP_GOLF_CLUB(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)])
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome, FIND_NEXT_SHOOTER(thisFoursome, thisCourse))
|
|
|
|
IF NOT ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome)
|
|
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_PLACE_BALL)
|
|
ELSE
|
|
|
|
IF DOES_GOLF_AI_FOURSOME_USE_CART(thisFoursome, thisCourse)
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_GET_IN_CART)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_APPROACH_BALL)
|
|
ELSE
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_APPROACH_BALL) //no cart
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGS_SCORECARD_END_HOLE
|
|
// DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: GMS_SCORECARD_END_HOLE")
|
|
|
|
IF IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_AI_FAR_AWAY)
|
|
TELEPORT_FOURSOME_TO_TEE(thisFoursome, thisCourse)
|
|
ENDIF
|
|
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_GET_IN_CART)
|
|
BREAK
|
|
CASE GGS_SCORECARD_END_GAME
|
|
// DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: GMS_SCORECARD_END_GAME")
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
ENDPROC
|
|
|
|
PROC TASK_GOLF_FOURSOME_FLEE(GOLF_FOURSOME &thisFoursome, GOLF_GAME &thisGame)
|
|
|
|
INT iCurrentPlayer
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
PED_INDEX pedIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iCurrentPlayer)
|
|
|
|
IF PLAYER_PED_ID() != pedIndex AND NOT IS_PED_INJURED(pedIndex)
|
|
PRINTLN("Send golfer flee")
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_CLUB(thisFoursome, iCurrentPlayer))
|
|
DETACH_ENTITY(GET_GOLF_FOURSOME_INDEXED_PLAYER_CLUB(thisFoursome, iCurrentPlayer))
|
|
ENDIF
|
|
|
|
//friends don't run
|
|
IF NOT IS_GOLF_CONTROL_FLAG_SET(thisGame, GCF_IS_FRIEND_ACTIVITY)
|
|
TASK_SMART_FLEE_PED(pedIndex, PLAYER_PED_ID(), FAR_AWAY_THRESHOLD, -1)
|
|
SET_PED_KEEP_TASK(pedIndex, TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Manages an AI foursome - navigating to shots, taking shots, finishing hole, etc
|
|
/// PARAMS:
|
|
/// thisGame -
|
|
/// thisCourse -
|
|
/// thisFoursome -
|
|
PROC GOLF_MANAGE_AI_FOURSOME_PUTTING(GOLF_GAME &thisGame,GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome)
|
|
// PRINTSTRING("GOLF_MANAGE_AI_FOURSOME working on golfer ")PRINTINT(GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome))PRINTNL()
|
|
|
|
IF IS_ENTITY_DEAD(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)) OR IS_PED_INJURED(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
OR NOT DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)) OR IS_PED_FLEEING(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
CLEANUP_GOLF_FOURSOME_CURRENT_GOLF_BALL(thisFoursome)
|
|
ENDIF
|
|
|
|
EXIT
|
|
ELSE
|
|
AGGRO_ARGS aggroArguments
|
|
EAGGRO aggroReason
|
|
IF DO_AGGRO_CHECK(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), NULL, aggroArguments, aggroReason)
|
|
OR IS_PED_IN_MELEE_COMBAT(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
OR IS_PED_RESPONDING_TO_EVENT(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), EVENT_POTENTIAL_GET_RUN_OVER)
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
TASK_SMART_FLEE_PED(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), PLAYER_PED_ID(), FAR_AWAY_THRESHOLD, -1)
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), TRUE)
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_SCORECARD_END_GAME)
|
|
EXIT
|
|
ENDIF
|
|
ENDIF
|
|
|
|
UPDATE_AI_FAR_AWAY(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], PLAYER_PED_ID(), thisFoursome, GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome), thisCourse)
|
|
|
|
INT iCurrentHole
|
|
SWITCH GET_GOLF_FOURSOME_STATE(thisFoursome)
|
|
CASE GGS_NAVIGATE_TO_SHOT
|
|
//DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: GMS_NAVIGATE_TO_SHOT")
|
|
GOLF_ATTACH_CLUB_FOR_WALKING(thisFoursome, thisGame)
|
|
GOLF_MANAGE_NAVIGATE_AI(thisCourse, thisFoursome)
|
|
IF GOLF_IS_PLAYER_APPROACHING_BALL(thisFoursome.playerCore[0])
|
|
//DEBUG_MESSAGE("GMS_NAVIGATE_TO_SHOT - player approaches shot")
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_TAKING_SHOT)
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
CASE GGS_TAKING_SHOT
|
|
//DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: GMS_TAKING_SHOT")
|
|
GOLF_AI_PLAYER_TAKE_SHOT(thisGame, thisCourse, thisFoursome)
|
|
|
|
SET_PED_RESET_FLAG(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), PRF_ExpandPedCapsuleFromSkeleton, TRUE)
|
|
|
|
IF GET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome) <= GPS_ADDRESS_BALL
|
|
GOLF_ATTACH_CLUB_FOR_WALKING(thisFoursome, thisGame)
|
|
ENDIF
|
|
|
|
// Next state logic is getting more complicated
|
|
IF ARE_ALL_PLAYERS_DONE_WITH_HOLE(thisFoursome)
|
|
IF bDebugSpew DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: ARE_ALL_PLAYERS_DONE_WITH_HOLE") ENDIF
|
|
GOLF_ATTACH_CLUB_FOR_WALKING(thisFoursome, thisGame)
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) thisFoursome.iCurrentPlayer
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_PLACE_BALL)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome, <<0,0,0>>, LIE_TEE)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_SHOT_NORMAL(thisFoursome, <<0,0,-1>>)
|
|
ENDREPEAT
|
|
iCurrentHole = GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)
|
|
IF iCurrentHole = 0
|
|
SET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome, 1)
|
|
ELIF iCurrentHole = 1
|
|
SET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome, 0)
|
|
ELIF iCurrentHole = 4
|
|
SET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome, 3)
|
|
ELIF iCurrentHole = 3
|
|
SET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome, 4)
|
|
ENDIF
|
|
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome, 0)
|
|
IF GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome) != iCurrentHole
|
|
GOLF_INIT_CURRENT_HOLE(thisCourse, thisFoursome)
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_SCORECARD_END_HOLE)
|
|
ENDIF
|
|
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome))
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome, GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome)))
|
|
ENDIF
|
|
|
|
ELIF IS_PLAYER_DONE_WITH_SHOT(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)])
|
|
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome, GPS_APPROACH_BALL)
|
|
GOLF_MANAGE_NAVIGATE_AI(thisCourse, thisFoursome)
|
|
SET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome, 0)
|
|
GOLF_ATTACH_CLUB_FOR_WALKING(thisFoursome, thisGame)
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_NAVIGATE_TO_SHOT)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGS_SCORECARD_END_HOLE
|
|
//DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: GMS_SCORECARD_END_HOLE")
|
|
GOLF_MANAGE_NAVIGATE_AI(thisCourse, thisFoursome)
|
|
|
|
SET_GOLF_FOURSOME_STATE(thisFoursome, GGS_NAVIGATE_TO_SHOT)
|
|
BREAK
|
|
CASE GGS_SCORECARD_END_GAME
|
|
//DEBUG_MESSAGE("GOLF_MANAGE_AI_FOURSOME: GMS_SCORECARD_END_GAME")
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Stub for cleaning up an AI foursome.
|
|
/// PARAMS:
|
|
/// thisFoursome -
|
|
PROC GOLF_CLEANUP_AI_FOURSOME (GOLF_FOURSOME &thisFoursome)
|
|
UNUSED_PARAMETER(thisFoursome)
|
|
ENDPROC
|
|
|
|
//Manage the second group of golfers in single player golf
|
|
PROC GOLF_MANAGE_NAVIAGTE_AI_GROUP(GOLF_GAME thisGame, GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse)
|
|
|
|
#IF GOLF_IS_MP
|
|
EXIT
|
|
#ENDIF
|
|
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
IF IS_SYNCHRONIZED_SCENE_RUNNING(iGolfResetSceneID)
|
|
EXIT //dont update ai while intro scene is running
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
INT iCurrentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
|
|
IF iCurrentPlayer > 1
|
|
IF NOT (IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, 2, GOLF_STOP_USING_CART) OR IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, 3, GOLF_STOP_USING_CART))
|
|
IF ARE_ALL_GOLFERS_IN_CART(thisFoursome, 2) AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, 3, GOLF_STOP_USING_CART)
|
|
AI_DRIVE_CART(thisFoursome, 2, thisCourse, FALSE, TRUE)
|
|
ELIF NOT (GET_GOLF_FOURSOME_INDEXED_PLAYER_LIE(thisFoursome, iCurrentPlayer) = LIE_GREEN AND GET_GOLF_FOURSOME_INDEXED_PLAYER_SHOTS_ON_HOLE(thisFoursome, iCurrentPlayer) != 1)
|
|
AND GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, iCurrentPlayer) != GPS_DONE_WITH_HOLE
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, 2, GOLF_CART_ARRIVED)
|
|
AND GET_DISTANCE_BETWEEN_ENTITIES(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, iCurrentPlayer), GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iCurrentPlayer)) < 40.0
|
|
GOLF_AI_WALK_TO_CART(thisFoursome, iCurrentPlayer)
|
|
ELSE
|
|
DO_NAVIGATION_TO_NEXT_SHOT(thisCourse, thisFoursome, iCurrentPlayer)
|
|
ENDIF
|
|
ELSE
|
|
DO_NAVIGATION_TO_NEXT_SHOT(thisCourse, thisFoursome, iCurrentPlayer)
|
|
ENDIF
|
|
|
|
ELIF iCurrentPlayer = 1
|
|
IF (GET_GOLF_FOURSOME_INDEXED_PLAYER_LIE(thisFoursome, iCurrentPlayer) = LIE_GREEN AND GET_GOLF_FOURSOME_INDEXED_PLAYER_SHOTS_ON_HOLE(thisFoursome, iCurrentPlayer) != 1)
|
|
OR IS_ENTITY_DEAD(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, 1)) OR IS_ENTITY_IN_WATER(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, 1))
|
|
OR GET_DISTANCE_BETWEEN_ENTITIES(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, iCurrentPlayer), GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iCurrentPlayer)) > 40.0
|
|
DO_NAVIGATION_TO_NEXT_SHOT(thisCourse, thisFoursome, iCurrentPlayer)
|
|
ELSE
|
|
IF NOT IS_GOLF_CONTROL_FLAG_SET(thisGame, GCF_IS_FRIEND_ACTIVITY) //during friend activity, just let the friend follow you around
|
|
GOLF_AI_WALK_TO_CART(thisFoursome, iCurrentPlayer)
|
|
ELSE
|
|
IF GET_SCRIPT_TASK_STATUS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iCurrentPlayer), SCRIPT_TASK_PLAY_ANIM) = PERFORMING_TASK
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iCurrentPlayer))
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Called every frame to manage golf buddies
|
|
/// PARAMS:
|
|
/// thisFoursome
|
|
/// RETURNS:
|
|
/// TRUE if a ped is dead, injured or non-exsistant
|
|
FUNC BOOL UPDATE_GOLF_BUDDIES_AI(GOLF_FOURSOME &thisFoursome)
|
|
INT iCurrentPlayer
|
|
// AGGRO_ARGS aggroArguments
|
|
// EAGGRO aggroReason
|
|
|
|
//
|
|
// SET_BITMASK_AS_ENUM(aggroArguments.iBitFieldDontCheck, EAggro_JackingCar)
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
PED_INDEX pedIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iCurrentPlayer)
|
|
|
|
IF iCurrentPlayer != 0
|
|
//Make sure the player isn't attacking a ped
|
|
IF IS_PED_INJURED(pedIndex)
|
|
RETURN TRUE
|
|
ELSE
|
|
IF iCurrentPlayer = 1 //buddy can't run
|
|
SET_PED_MAX_MOVE_BLEND_RATIO(pedIndex, PEDMOVE_WALK)
|
|
ENDIF
|
|
SET_PED_CAN_PLAY_AMBIENT_ANIMS(pedIndex, FALSE)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|