2244 lines
82 KiB
Scheme
Executable File
2244 lines
82 KiB
Scheme
Executable File
USING "minigames_helpers.sch"
|
|
USING "golf.sch"
|
|
USING "golf_mp.sch"
|
|
USING "golf_mp_client.sch"
|
|
USING "golf_clubs.sch"
|
|
USING "golf_course_lib.sch"
|
|
USING "golf_swing_meter.sch"
|
|
USING "golf_fx_lib.sch"
|
|
USING "golf_anims_lib.sch"
|
|
USING "shared_hud_displays.sch"
|
|
USING "clothes_shop_private.sch"
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Requesting all assets needed for golf
|
|
/// PARAMS:
|
|
/// streamedAssets - asset streaming array for golf
|
|
PROC GOLF_STREAM_ASSETS(STREAMED_MODEL &streamedAssets[])
|
|
|
|
#IF NOT GOLF_IS_MP
|
|
ADD_STREAMED_MODEL(streamedAssets, A_M_Y_GOLFER_01)
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
ADD_STREAMED_MODEL(streamedAssets, A_M_M_GOLFER_01)
|
|
#ENDIF
|
|
#ENDIF
|
|
|
|
ADD_STREAMED_MODEL(streamedAssets, PROP_GOLF_PUTTER_01)
|
|
ADD_STREAMED_MODEL(streamedAssets, PROP_GOLF_BALL)
|
|
ADD_STREAMED_MODEL(streamedAssets, Prop_Golf_Pitcher_01)
|
|
|
|
#IF NOT PUTTING_GREEN
|
|
ADD_STREAMED_MODEL(streamedAssets, PROP_GOLF_WOOD_01)
|
|
ADD_STREAMED_MODEL(streamedAssets, PROP_GOLF_IRON_01)
|
|
ADD_STREAMED_MODEL(streamedAssets, CADDY)
|
|
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
ADD_STREAMED_MODEL(streamedAssets, PROP_GOLF_BAG_01B)
|
|
ADD_STREAMED_MODEL(streamedAssets, PROP_GOLFFLAG)
|
|
ADD_STREAMED_MODEL(streamedAssets, PROP_GOLF_TEE )
|
|
ADD_STREAMED_MODEL(streamedAssets, PROP_GOLF_MARKER_01)
|
|
#ENDIF
|
|
#ENDIF
|
|
|
|
REQUEST_ALL_MODELS(streamedAssets)
|
|
ENDPROC
|
|
|
|
PROC GOLF_STREAM_UI(GOLF_HELPERS &thisHelpers)
|
|
|
|
LOAD_MENU_ASSETS()
|
|
REQUEST_ANIM_DICT(GET_GOLF_BASIC_ANIMATION_DICTIONARY_NAME())
|
|
REQUEST_ANIM_DICT(GET_GOLF_EXTRA_ANIMATION_DICTIONARY_NAME())
|
|
REQUEST_ANIM_DICT(GET_GOLF_IDLE_ANIMATION_DICTIONARY(TRUE))
|
|
REQUEST_ANIM_DICT(GET_GOLF_IDLE_ANIMATION_DICTIONARY(FALSE))
|
|
REQUEST_ANIM_DICT(GET_HOLE_PREVIEW_ANIM_DICT())
|
|
REQUEST_ANIM_DICT(GET_GOLF_REACTION_ANIM_DICT(NULL, FALSE))
|
|
|
|
IS_END_OF_GOLF_CUTSCENE_LOADED()
|
|
|
|
#IF NOT GOLF_IS_MP
|
|
REQUEST_ANIM_DICT(GET_GOLF_REACTION_ANIM_DICT(PLAYER_PED_ID(), TRUE))
|
|
REQUEST_ANIM_DICT(GET_GOLF_REACTION_ANIM_DICT(PLAYER_PED_ID(), FALSE))
|
|
REQUEST_ANIM_SET("move_m@golfer@")
|
|
#ENDIF
|
|
|
|
#IF GOLF_IS_MP
|
|
REQUEST_ANIM_DICT("reaction@shove")
|
|
#ENDIF
|
|
|
|
thisHelpers.golfUI = REQUEST_SCALEFORM_MOVIE("golf")
|
|
thisHelpers.floatingUI = REQUEST_SCALEFORM_MOVIE("golf_floating_ui")
|
|
thisHelpers.leaderboardUI = REQUEST_SC_LEADERBOARD_UI()
|
|
REQUEST_GOLF_SPLASH_SCALEFORM()
|
|
|
|
REQUEST_SCRIPT_AUDIO_BANK("GOLF_I")
|
|
REQUEST_SCRIPT_AUDIO_BANK("GOLF_2")
|
|
REQUEST_SCRIPT_AUDIO_BANK("GOLF_3")
|
|
REQUEST_PTFX_ASSET()
|
|
REQUEST_STREAMED_TEXTURE_DICT(GET_GOLF_TEXTURE_DICTIONARY_NAME())
|
|
#IF GOLF_IS_MP
|
|
//REQUEST_SCALEFORM_MOVIE("MPHUD")
|
|
#ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if all assets are streamed for golf
|
|
/// PARAMS:
|
|
/// streamedAssets - streaming array
|
|
/// RETURNS:
|
|
/// TRUE if all of the golf assets are streamed
|
|
FUNC BOOL GOLF_ASSETS_ARE_STREAMED(GOLF_HELPERS &thisHelpers,STREAMED_MODEL &streamedAssets[])
|
|
|
|
IF NOT ARE_MODELS_STREAMED(streamedAssets)
|
|
CDEBUG1LN(DEBUG_GOLF,"Models not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT HAS_ANIM_DICT_LOADED(GET_GOLF_BASIC_ANIMATION_DICTIONARY_NAME())
|
|
CDEBUG1LN(DEBUG_GOLF,"Basic golf dictionanry not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT HAS_ANIM_DICT_LOADED(GET_GOLF_EXTRA_ANIMATION_DICTIONARY_NAME())
|
|
CDEBUG1LN(DEBUG_GOLF,"Extra golf dictionanry not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
#IF NOT GOLF_IS_MP
|
|
IF NOT HAS_ANIM_SET_LOADED("move_m@golfer@")
|
|
CDEBUG1LN(DEBUG_GOLF,"walking golf dictionanry not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
#IF GOLF_IS_MP
|
|
IF NOT LOAD_MENU_ASSETS()
|
|
CDEBUG1LN(DEBUG_GOLF,"golf menu not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
IF NOT HAS_SCALEFORM_MOVIE_LOADED(thisHelpers.golfUI)
|
|
CDEBUG1LN(DEBUG_GOLF,"golf UI not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT HAS_SCALEFORM_MOVIE_LOADED(thisHelpers.floatingUI)
|
|
CDEBUG1LN(DEBUG_GOLF,"floating UI not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT IS_GOLF_SPLASH_LOADED()
|
|
CDEBUG1LN(DEBUG_GOLF,"splash UI not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT REQUEST_SCRIPT_AUDIO_BANK("GOLF_I")
|
|
CDEBUG1LN(DEBUG_GOLF,"audio 1 not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT REQUEST_SCRIPT_AUDIO_BANK("GOLF_2")
|
|
CDEBUG1LN(DEBUG_GOLF,"audio 2 not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT REQUEST_SCRIPT_AUDIO_BANK("GOLF_3")
|
|
CDEBUG1LN(DEBUG_GOLF,"audio 3 not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT HAS_PTFX_ASSET_LOADED()
|
|
CDEBUG1LN(DEBUG_GOLF,"PTFX not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT HAS_STREAMED_TEXTURE_DICT_LOADED(GET_GOLF_TEXTURE_DICTIONARY_NAME())
|
|
CDEBUG1LN(DEBUG_GOLF,"texture Dictionary not loaded in")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
CDEBUG1LN(DEBUG_GOLF,"Everything loaded")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL DOES_PLAYER_OWN_GOLF_HOUSE()
|
|
RETURN GET_CURRENT_PROPERTY_OWNER(PROPERTY_GOLF_CLUB) = GET_CURRENT_PLAYER_PED_ENUM()
|
|
// RETURN GET_CURRENT_PROPERTY_OWNER(PROPERTY_GOLF_CLUB) != NO_CHARACTER
|
|
ENDFUNC
|
|
|
|
FUNC BOOL DOES_GOLF_NAV_MESH_BLOCKING_OBJECT_EXIST(GOLF_HELPERS &thisHelpers)
|
|
IF thisHelpers.iBlockNavMeshIndex < 0
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN DOES_NAVMESH_BLOCKING_OBJECT_EXIST(thisHelpers.iBlockNavMeshIndex)
|
|
ENDFUNC
|
|
|
|
FUNC INT GET_GOLF_PLAYER_CASH()
|
|
|
|
#IF GOLF_IS_MP
|
|
RETURN GET_PLAYER_CASH(PLAYER_ID())
|
|
#ENDIF
|
|
|
|
RETURN GET_TOTAL_CASH(GET_CURRENT_PLAYER_PED_ENUM())
|
|
|
|
ENDFUNC
|
|
|
|
PROC GOLF_SPEND_CASH(INT iCost)
|
|
|
|
#IF GOLF_IS_MP
|
|
// GIVE_LOCAL_PLAYER_CnC_CASH(-iCost)
|
|
// INCREMENT_BY_MP_FLOAT_CHARACTER_STAT(MP_STAT_MONEY_SPENT_IN_STRIP_CLUBS, TO_FLOAT(iCost))
|
|
EXIT
|
|
#ENDIF
|
|
|
|
DEBIT_BANK_ACCOUNT(GET_CURRENT_PLAYER_PED_ENUM(), BAAC_LOS_SANTOS_GOLF_CLUB, iCost)
|
|
ENDPROC
|
|
|
|
|
|
FUNC MODEL_NAMES GET_GOLF_PED_MODEL(PED_TYPE &pedType, FLOAT fPercentagetMale = 1.01)
|
|
IF GET_RANDOM_FLOAT_IN_RANGE() < fPercentagetMale
|
|
pedType = PEDTYPE_CIVMALE
|
|
RETURN A_M_Y_GOLFER_01
|
|
ENDIF
|
|
pedType = PEDTYPE_CIVFEMALE
|
|
RETURN A_F_Y_GOLFER_01
|
|
ENDFUNC
|
|
|
|
PROC SET_PLAYER_GOLF_OUTFIT(GOLF_HELPERS &thisHelpers)
|
|
|
|
PED_INDEX playerPed = PLAYER_PED_ID()
|
|
|
|
GET_PED_VARIATIONS(playerPed, thisHelpers.sPedVariations)
|
|
|
|
IF NOT DOES_PLAYER_OWN_GOLF_HOUSE()
|
|
SetPedCompItemCurrent fpSetPedCompItemCurrent = &SET_PED_COMP_ITEM_CURRENT_SP
|
|
REMOVE_ALL_MASKS(playerPed, fpSetPedCompItemCurrent)
|
|
REMOVE_PED_HELMET(PLAYER_PED_ID(), TRUE)
|
|
SET_GOLF_OUTFIT(playerPed)
|
|
CLEAR_PED_WETNESS(playerPed)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC RESET_GOLF_PLAYER_OUTFIT(GOLF_HELPERS &thisHelpers)
|
|
SET_PED_VARIATIONS(PLAYER_PED_ID(), thisHelpers.sPedVariations)
|
|
CLEAR_PED_WETNESS(PLAYER_PED_ID())
|
|
|
|
#IF GOLF_IS_MP
|
|
FINALIZE_HEAD_BLEND(PLAYER_PED_ID())
|
|
#ENDIF
|
|
ENDPROC
|
|
|
|
PROC ADD_GOLF_FOURSOME_TO_GROUP(GOLF_FOURSOME &thisFoursome)
|
|
#IF GOLF_IS_AI_ONLY
|
|
EXIT
|
|
#ENDIF
|
|
#IF GOLF_IS_MP
|
|
EXIT
|
|
#ENDIF
|
|
|
|
IF NOT DOES_GROUP_EXIST(GET_PED_GROUP_INDEX(PLAYER_PED_ID()))
|
|
EXIT //no player group exist?
|
|
ENDIF
|
|
|
|
INT iPlayerIndex
|
|
INT iPlayerCartIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, GET_GOLF_FOURSOME_LOCAL_PLAYER(thisFoursome))
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
PED_INDEX pedGolfer = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iPlayerIndex)
|
|
|
|
IF NOT IS_PED_INJURED(pedGolfer)
|
|
IF NOT IS_PED_IN_GROUP(pedGolfer)
|
|
//if this golfer is sharing a cart with me
|
|
AND iPlayerCartIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, iPlayerIndex)
|
|
SET_PED_AS_GROUP_MEMBER(pedGolfer, GET_PED_GROUP_INDEX(PLAYER_PED_ID()))
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC REMOVE_GOLF_FOURSOME_FROM_GROUP(GOLF_FOURSOME &thisFoursome)
|
|
#IF GOLF_IS_AI_ONLY
|
|
EXIT
|
|
#ENDIF
|
|
#IF GOLF_IS_MP
|
|
EXIT
|
|
#ENDIF
|
|
|
|
IF NOT DOES_GROUP_EXIST(GET_PED_GROUP_INDEX(PLAYER_PED_ID()))
|
|
EXIT //no player group exist?
|
|
ENDIF
|
|
|
|
INT iPlayerIndex
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
PED_INDEX pedGolfer = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iPlayerIndex)
|
|
|
|
IF NOT IS_PED_INJURED(pedGolfer)
|
|
IF IS_PED_IN_GROUP(pedGolfer)
|
|
IF pedGolfer != PLAYER_PED_ID()
|
|
REMOVE_PED_FROM_GROUP(pedGolfer)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
|
|
PROC SET_GOLF_FOURSOME_RELATIONSHIP_HASH(GOLF_FOURSOME &thisFoursome, GOLF_HELPERS &thisHelpers)
|
|
|
|
ADD_RELATIONSHIP_GROUP("golferRelGroup", thisHelpers.golfersRelationshipHash)
|
|
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, thisHelpers.golfersRelationshipHash, RELGROUPHASH_CIVFEMALE)
|
|
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, thisHelpers.golfersRelationshipHash, RELGROUPHASH_CIVMALE)
|
|
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, thisHelpers.golfersRelationshipHash, RELGROUPHASH_PLAYER)
|
|
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RELGROUPHASH_PLAYER, thisHelpers.golfersRelationshipHash)
|
|
|
|
INT iPlayerIndex
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
IF iPlayerIndex != 0 //player ped should not be added to group
|
|
SET_PED_RELATIONSHIP_GROUP_HASH(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iPlayerIndex), thisHelpers.golfersRelationshipHash)
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if the player is in BALL_RADIUS of the next shot (tee or ball). For free form navigation, tells the game to make the player address the ball
|
|
/// PARAMS:
|
|
/// thisPlayerCore -
|
|
/// RETURNS:
|
|
/// TRUE if the player is within BALL_RADIUS of the next shot position, false otherwise
|
|
FUNC BOOL GOLF_IS_PLAYER_APPROACHING_BALL(GOLF_PLAYER_CORE &thisPlayerCore)
|
|
IF NOT DOES_ENTITY_EXIST(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
FLOAT fDistSqToBall = VDIST2(GET_ENTITY_COORDS(GET_GOLF_PLAYER_PED(thisPlayerCore)), GET_GOLF_PLAYER_BALL_POSITION(thisPlayerCore))
|
|
IF (fDistSqToBall < (BALL_RADIUS*BALL_RADIUS) OR IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_WAS_IN_CART))
|
|
AND (NOT IS_PED_RAGDOLL(GET_GOLF_PLAYER_PED(thisPlayerCore)) AND NOT IS_ENTITY_IN_AIR(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
AND NOT IS_PED_GETTING_UP(GET_GOLF_PLAYER_PED(thisPlayerCore)))
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_PED_IN_ANY_VEHICLE(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
IF fDistSqToBall < (BALL_IN_VEHICLE_RADIUS*BALL_IN_VEHICLE_RADIUS)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if any player in a foursome is in BALL_RADIUS of the next shot (tee or ball). For free form navigation, tells the game to make the player address the ball
|
|
/// PARAMS:
|
|
/// thisFoursome -
|
|
/// RETURNS:
|
|
/// TRUE if any player is within BALL_RADIUS of the next shot position, false otherwise
|
|
FUNC BOOL GOLF_IS_ANY_PLAYER_APPROACHING_BALL(GOLF_FOURSOME &thisFoursome)
|
|
INT currentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) currentPlayer
|
|
IF GOLF_IS_PLAYER_APPROACHING_BALL(thisFoursome.playerCore[currentPlayer])
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if all players in a foursome have completed their tee shots on the current hole
|
|
/// PARAMS:
|
|
/// thisFoursome - Foursome to check
|
|
/// iExcludeIndex - optional exclusion index - don't check this player
|
|
/// RETURNS:
|
|
/// TRUE if all players aside from iExcludeIndex have completed their tee shot
|
|
FUNC BOOL ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(GOLF_FOURSOME &thisFoursome, INT iExcludeIndex = -1)
|
|
INT iCurrentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
IF iExcludeIndex < 0 OR iExcludeIndex != iCurrentPlayer
|
|
IF GET_GOLF_PLAYER_SHOTS_ON_HOLE(thisFoursome.playerCore[iCurrentPlayer]) < 1 AND GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisfoursome, iCurrentPlayer) != GPS_DONE_WITH_HOLE
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if all players in a foursome have completed their tee shots in their last shot
|
|
/// PARAMS:
|
|
/// thisFoursome - Foursome to check
|
|
/// iExcludeIndex - optional exclusion index - don't check this player
|
|
/// RETURNS:
|
|
/// TRUE if all players aside from iExcludeIndex have completed their tee shot in the previous shot
|
|
FUNC BOOL ARE_ALL_PLAYERS_RECENTLY_DONE_WITH_TEE_SHOT(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse, INT iExcludeIndex = -1)
|
|
|
|
IF NOT ARE_ALL_PLAYERS_DONE_WITH_TEE_SHOT(thisFoursome, iExcludeIndex)
|
|
//CDEBUG1LN(DEBUG_GOLF,"NOT ALL PLAYERS DONE WITH TEE SHOT")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT WAS_TEE_SHOT(thisCourse, thisFoursome)
|
|
//CDEBUG1LN(DEBUG_GOLF,"PREVIOUS LIE IS NOT TEE")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_TEE_SHOT(thisCourse, thisFoursome)
|
|
//CDEBUG1LN(DEBUG_GOLF,"LIE IS STILL TEE")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Checks ot see if a player is done with his current shot
|
|
/// PARAMS:
|
|
/// thisPlayerCore -
|
|
/// RETURNS:
|
|
/// TRUE if player has completed his current shot (and its time to move to the next shooter)
|
|
FUNC BOOL IS_PLAYER_DONE_WITH_SHOT(GOLF_PLAYER_CORE &thisPlayerCore)
|
|
|
|
IF GET_GOLF_PLAYER_STATE(thisPlayerCore) = GPS_DONE_WITH_SHOT OR GET_GOLF_PLAYER_STATE(thisPlayerCore) = GPS_DONE_WITH_HOLE
|
|
OR IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_PLAYER_REMOVED)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if all players are done with their shots. Not sure if this is currently used
|
|
/// PARAMS:
|
|
/// thisFoursome -
|
|
/// bHumanOnly -
|
|
/// RETURNS:
|
|
///
|
|
FUNC BOOL ARE_ALL_PLAYERS_DONE_WITH_SHOT(GOLF_FOURSOME &thisFoursome, BOOL bHumanOnly = FALSE)
|
|
INT iCurrentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
IF GET_GOLF_PLAYER_STATE(thisFoursome.playerCore[iCurrentPlayer]) != GPS_DONE_WITH_SHOT AND (GET_GOLF_PLAYER_CONTROL(thisFoursome.playerCore[iCurrentPlayer]) != COMPUTER OR NOT bHumanOnly)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if any players in a foursome are still on their tee shot
|
|
/// PARAMS:
|
|
/// thisCourse -
|
|
/// thisFoursome -
|
|
/// RETURNS:
|
|
///
|
|
FUNC BOOL IS_ANY_PLAYER_ON_THE_TEE(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome)
|
|
INT iCurrentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
IF IS_TEE_SHOT(thisCourse, thisFoursome, iCurrentPlayer)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL IS_ANY_PLAYER_ON_THE_GREEN(GOLF_FOURSOME &thisFoursome)
|
|
INT iCurrentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
IF GET_GOLF_PLAYER_LIE(thisFoursome.playerCore[iCurrentPlayer]) = LIE_GREEN
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL ARE_ALL_PLAYERS_ON_THE_GREEN(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse)
|
|
INT iCurrentPlayer
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
IF GET_GOLF_PLAYER_LIE(thisFoursome.playerCore[iCurrentPlayer]) != LIE_GREEN
|
|
AND GET_GOLF_PLAYER_LIE(thisFoursome.playerCore[iCurrentPlayer]) != LIE_CUP
|
|
AND GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, iCurrentPlayer) != GPS_DONE_WITH_HOLE
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, iCurrentPlayer, GOLF_STROKE_LIMIT)
|
|
AND NOT IS_SHOT_LIMIT_EXCEEDED(thisFoursome, thisCourse, iCurrentPlayer)
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, iCurrentPlayer, GOLF_PLAYER_REMOVED)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
//PURPOSE:
|
|
// Checks if any foursome is playing on a hole
|
|
//PARAMS:
|
|
// thisFoursome[]
|
|
// golfHole
|
|
|
|
FUNC BOOL IS_ANY_GOLF_FOURSOME_PLAYING_HOLE(GOLF_FOURSOME &thisFoursome[], INT golfhole)
|
|
|
|
int playerIndex
|
|
REPEAT COUNT_OF(thisFoursome) playerIndex
|
|
IF GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome[playerIndex]) = golfhole
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Returns the index of the golfer closest to the pin
|
|
/// PARAMS:
|
|
/// playerCore0 -
|
|
/// playerCore1 -
|
|
/// RETURNS:
|
|
///
|
|
FUNC INT GET_GOLF_PLAYER_WHOSE_BALL_IS_FARTHER_FROM_PIN(GOLF_FOURSOME &thisFoursome, INT playerIndex0, INT playerIndex1)
|
|
|
|
IF GET_GOLF_PLAYER_DISTANCE_TO_HOLE(thisFoursome.playerCore[playerIndex0]) > GET_GOLF_PLAYER_DISTANCE_TO_HOLE(thisFoursome.playerCore[playerIndex1])
|
|
RETURN playerIndex0
|
|
ENDIF
|
|
|
|
RETURN playerIndex1
|
|
ENDFUNC
|
|
|
|
PROC RESET_FOURSOME_NEXT_GOLFER_WEIGTHS(GOLF_FOURSOME &thisFoursome)
|
|
|
|
INT playerIndex
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
thisFoursome.playerCore[playerIndex].iNextGolferWeight = 0
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC GOLF_SWAP_POSITIONS(INT &i, INT &j)
|
|
INT temp = i
|
|
i=j
|
|
j=temp
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Uses a bubble sort to figure who goes next based on scores of previous holes. Finally tiebreaks on player index.
|
|
/// PARAMS:
|
|
/// thisFoursome -
|
|
/// allPlayers -
|
|
/// iLastHole -
|
|
PROC SET_FOURSOME_NEXT_GOLFER_WEIGHT_BASED_ON_WHO_WON_HOLE(GOLF_FOURSOME &thisFoursome, GOLF_PLAYER &allPlayers[], INT iLastHole)
|
|
|
|
INT placeIndex
|
|
|
|
#IF NOT GOLF_IS_MP
|
|
INT placeAtHole[4]
|
|
#ENDIF
|
|
#IF GOLF_IS_MP
|
|
INT placeAtHole[MP_GOLF_MAX_PLAYERS]
|
|
#ENDIF
|
|
|
|
INT i
|
|
INT repeats = 0 // failsafe to ensure we don't loop forever.
|
|
INT maxRepeats = 100
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) placeIndex
|
|
placeAtHole[placeIndex] = placeIndex
|
|
ENDREPEAT
|
|
|
|
BOOL bSwapped = TRUE
|
|
WHILE bSwapped AND repeats < maxRepeats
|
|
bSwapped = FALSE
|
|
repeats++
|
|
|
|
i = 1
|
|
WHILE i < GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome)
|
|
// If thisHoleScore[i] is less than thisHoleScore[i-1] then we swap
|
|
IF GET_GOLF_FOURSOME_INDEXED_PLAYER_SHOTS_ON_HOLE(thisFoursome, placeAtHole[i]) < GET_GOLF_FOURSOME_INDEXED_PLAYER_SHOTS_ON_HOLE(thisFoursome, placeAtHole[i-1])
|
|
GOLF_SWAP_POSITIONS(placeAtHole[i], placeAtHole[i-1])
|
|
bSwapped = TRUE
|
|
// otherwise if thisHoleScore[i] equals thisHoleScore[i-1] we move onto the tiebreak
|
|
ELIF GET_GOLF_FOURSOME_INDEXED_PLAYER_SHOTS_ON_HOLE(thisFoursome, placeAtHole[i]) = GET_GOLF_FOURSOME_INDEXED_PLAYER_SHOTS_ON_HOLE(thisFoursome, placeAtHole[i-1])
|
|
// If the last hole was no the first hole we can tie break on the previous score
|
|
IF iLastHole > 0
|
|
// tiebreaking on the previous score, if prevHoleScore[i] < prevHoleScore[i-1] we swap
|
|
IF GET_GOLF_PLAYER_HOLE_SCORE(allPlayers[placeAtHole[i]], iLastHole-1) < GET_GOLF_PLAYER_HOLE_SCORE(allPlayers[placeAtHole[i-1]], iLastHole-1)
|
|
GOLF_SWAP_POSITIONS(placeAtHole[i], placeAtHole[i-1])
|
|
bSwapped = TRUE
|
|
// If the previous score is a tie then we tiebreak again on player index
|
|
ELIF GET_GOLF_PLAYER_HOLE_SCORE(allPlayers[placeAtHole[i]], iLastHole-1) = GET_GOLF_PLAYER_HOLE_SCORE(allPlayers[placeAtHole[i-1]], iLastHole-1)
|
|
IF placeAtHole[i] < placeAtHole[i-1]
|
|
GOLF_SWAP_POSITIONS(placeAtHole[i], placeAtHole[i-1])
|
|
bSwapped = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
// if the last hole is 0 then we tiebreak on player index alone
|
|
ELSE
|
|
IF placeAtHole[i] < placeAtHole[i-1]
|
|
GOLF_SWAP_POSITIONS(placeAtHole[i], placeAtHole[i-1])
|
|
bSwapped = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
i++
|
|
ENDWHILE
|
|
ENDWHILE
|
|
|
|
//placeAtHole now has the player index in order of who won the hole, adjust weights with the winner getting the biggest weight
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) placeIndex
|
|
thisFoursome.playerCore[placeAtHole[placeIndex]].iNextGolferWeight = (GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome)-1)-placeIndex
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Finds the next shooter in a foursome, the player who's ball is the farthest from the pin
|
|
/// PARAMS:
|
|
/// thisFoursome - Foursome to check
|
|
/// RETURNS:
|
|
/// Index of the player who's ball is farthest from the pin
|
|
FUNC INT FIND_NEXT_SHOOTER(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse)
|
|
FLOAT fFarthestShot = 0.0
|
|
INT iFarthestPlayer = -1
|
|
INT iCurrentPlayer
|
|
FLOAT fCurrentAdjustedDistance
|
|
|
|
IF GET_GOLF_FOURSOME_CURRENT_PLAYER_DISTANCE_TO_HOLE(thisFoursome) < (DIST_FOR_GIMMIE*DIST_FOR_GIMMIE) AND GET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome) = LIE_GREEN
|
|
AND GET_GOLF_FOURSOME_CURRENT_PLAYER_STATE(thisFoursome) != GPS_DONE_WITH_HOLE AND ARE_ALL_PLAYERS_ON_THE_GREEN(thisFoursome, thisCourse)
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
CDEBUG1LN(DEBUG_GOLF,"Golfer goes again for gimmie shot")
|
|
#ENDIF
|
|
RETURN GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)
|
|
ENDIF
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
IF GET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL(thisFoursome, iCurrentPlayer) != CONTROL_NONE
|
|
IF GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, iCurrentPlayer) != GPS_DONE_WITH_HOLE
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, iCurrentPlayer, GOLF_PLAYER_REMOVED)
|
|
|
|
VECTOR vStartPos, vEndPos
|
|
vStartPos = GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL_POSITION(thisFoursome, iCurrentPlayer)
|
|
vEndPos = GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
|
|
vStartPos.z = 0
|
|
vEndPos.z = 0 //only 2d distance
|
|
|
|
fCurrentAdjustedDistance = VDIST(vStartPos, vEndPos)
|
|
fCurrentAdjustedDistance *= PICK_FLOAT(GET_GOLF_PLAYER_LIE(thisFoursome.playerCore[iCurrentPlayer]) = LIE_GREEN, 1, 99999)
|
|
fCurrentAdjustedDistance *= PICK_FLOAT(GET_GOLF_PLAYER_LIE(thisFoursome.playerCore[iCurrentPlayer]) = LIE_TEE, 100, 1)
|
|
fCurrentAdjustedDistance *= (thisFoursome.playerCore[iCurrentPlayer].iNextGolferWeight+1)
|
|
//fCurrentAdjustedDistance *= PICK_FLOAT(GET_GOLF_FOURSOME_INDEXED_PLAYER_SHOTS_ON_HOLE(thisFoursome, iCurrentPlayer) != 0, 1, 100)
|
|
IF fCurrentAdjustedDistance > fFarthestShot
|
|
iFarthestPlayer = iCurrentPlayer
|
|
fFarthestShot = fCurrentAdjustedDistance
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF iFarthestPlayer = -1
|
|
iFarthestPlayer = 0
|
|
ENDIF
|
|
IF bDebugSpew CDEBUG1LN(DEBUG_GOLF,"Next player is ", iFarthestPlayer) ENDIF
|
|
RETURN iFarthestPlayer
|
|
ENDFUNC
|
|
|
|
PROC MANAGE_CURRENT_ESTIMATE_BLIP(GOLF_HELPERS &thisHelpers, VECTOR vBlipLocation, INT iColour, BLIP_SPRITE blipSprtie = RADAR_TRACE_INVALID)
|
|
|
|
IF IS_VECTOR_ZERO(vBlipLocation)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF NOT DOES_BLIP_EXIST(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers))
|
|
SET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers, CREATE_BLIP_FOR_COORD(vBlipLocation))
|
|
ENDIF
|
|
|
|
IF DOES_BLIP_EXIST(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers))
|
|
SET_BLIP_COLOUR( GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers), iColour)
|
|
IF NOT ARE_VECTORS_EQUAL(GET_BLIP_COORDS(GET_GOLF_HELPER_ESTIMATE_BLIP( thisHelpers)), vBlipLocation)
|
|
SET_BLIP_COORDS( GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers), vBlipLocation)
|
|
ENDIF
|
|
SET_BLIP_PRIORITY(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers), BLIPPRIORITY_HIGHEST)
|
|
SHOW_HEIGHT_ON_BLIP(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers), FALSE)
|
|
|
|
IF blipSprtie != RADAR_TRACE_INVALID
|
|
IF GET_BLIP_SPRITE(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers)) != blipSprtie
|
|
CDEBUG1LN(DEBUG_GOLF,"Setting estimate blip sprite to ", blipSprtie)
|
|
CDEBUG1LN(DEBUG_GOLF,"Current sprite ", GET_BLIP_SPRITE(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers)))
|
|
SET_BLIP_SPRITE(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers), blipSprtie)
|
|
SET_BLIP_NAME_FROM_TEXT_FILE(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers), "SHOT_EST")
|
|
ENDIF
|
|
ELSE
|
|
SET_BLIP_SCALE(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers), GOLF_BALL_BLIP_SCALE)
|
|
ENDIF
|
|
|
|
// CDEBUG1LN(DEBUG_GOLF,"Blip sprite ", GET_BLIP_SPRITE(GET_GOLF_HELPER_ESTIMATE_BLIP(thisHelpers)))
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
FUNC BOOL HAS_ANY_GOLFER_TAKEN_A_SHOT_THIS_HOLE(GOLF_FOURSOME &thisFoursome)
|
|
|
|
INT iPlayerIndex
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
IF GET_GOLF_FOURSOME_INDEXED_PLAYER_SHOTS_ON_HOLE(thisFoursome, iPlayerIndex) > 0
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL FIND_SAFE_SPOT_FOR_CART(VECTOR vOrigin, VECTOR vDestination, VECTOR &vNearby, FLOAT &fNearbyHeading, VECTOR vShotDir, VECTOR vFrontCheckOrigin, BOOL inFrontCheck = FALSE)
|
|
|
|
BOOL bFoundSpot
|
|
INT iSpotIndex = 1
|
|
INT iReturnLanes
|
|
VECTOR locationToNewSpot = <<0,0,0>>
|
|
WHILE NOT bFoundSpot
|
|
AND iSpotIndex < 10
|
|
IF NOT GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING( vOrigin, iSpotIndex, vNearby, fNearbyHeading, iReturnLanes)
|
|
RETURN FALSE
|
|
ELSE
|
|
IF VDIST2(vOrigin, vNearby) > 100
|
|
AND NOT IS_ANY_VEHICLE_NEAR_POINT(vNearby, 5.0)
|
|
#IF NOT GOLF_IS_MP
|
|
AND NOT IS_GOLF_COORD_OUTSIDE_BOUNDARY_PLANES(vNearby)
|
|
#ENDIF
|
|
locationToNewSpot= NORMALISE_VECTOR(<<vNearby.x, vNearby.y, 0>> - <<vFrontCheckOrigin.x, vFrontCheckOrigin.y, 0>>)
|
|
//CDEBUG1LN(DEBUG_GOLF,vNearby, " ", vDestination)
|
|
//CDEBUG1LN(DEBUG_GOLF,vShotDir, " ",locationToNewSpot , " ", DOT_PRODUCT_XY(vShotDir, locationToNewSpot))
|
|
IF NOT inFrontCheck OR DOT_PRODUCT_XY(vShotDir, locationToNewSpot) < 0.75
|
|
bFoundSpot = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
iSpotIndex++
|
|
ENDWHILE
|
|
// Lets make sure the heading is actually pointing toward the hole, otherwise turn 180
|
|
IF ABSF(GET_HEADING_FROM_VECTOR_2D (vDestination.x - vOrigin.x, vDestination.y - vOrigin.y) - fNearbyHeading) > 90
|
|
fNearbyHeading += 180
|
|
ENDIF
|
|
|
|
GOLF_FIND_GROUND_Z(vNearby, 5.0, 0.5)
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL FIND_SAFE_SPOT_FOR_CART_FAST(VECTOR vOrigin, VECTOR vDestination, VECTOR &vNearby, FLOAT &fNearbyHeading)
|
|
|
|
IF NOT GET_CLOSEST_VEHICLE_NODE_WITH_HEADING( vOrigin, vNearby, fNearbyHeading)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Lets make sure the heading is actually pointing toward the hole, otherwise turn 180
|
|
IF ABSF(GET_HEADING_FROM_VECTOR_2D (vDestination.x - vOrigin.x, vDestination.y - vOrigin.y) - fNearbyHeading) > 90
|
|
fNearbyHeading += 180
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL IS_CART_FAR_FROM_BALL(GOLF_FOURSOME &thisFoursome, VEHICLE_INDEX vehIndex)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(vehIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_DEAD(vehIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN VDIST2(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome), GET_ENTITY_COORDS(vehIndex)) > (40.0 * 40.0)
|
|
ENDFUNC
|
|
|
|
FUNC BOOL IS_CART_BLOCKING_PLAYERS_SHOT(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse, VEHICLE_INDEX thisVehicle)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(thisVehicle)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
VECTOR vHolePosition = GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
VECTOR ballPos = GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome)
|
|
VECTOR vShotDir = NORMALISE_VECTOR(<<vHolePosition.x, vHolePosition.y,0>> - <<ballPos.x, ballPos.y,0>>)
|
|
VECTOR vVehCoords = GET_ENTITY_COORDS(thisVehicle, FALSE)
|
|
|
|
IF DOT_PRODUCT_XY(vShotDir, NORMALISE_VECTOR(vVehCoords - ballPos)) < 0.75 AND VDIST2(ballPos, vVehCoords) > 5.0*5.0
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC MOVE_GOLF_PLAYER_CART_TO_SAFE_LOCATION(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse, VECTOR vDestination, VEHICLE_INDEX thisVehicle, INT cartIndex)
|
|
IF NOT DOES_ENTITY_EXIST(thisVehicle)
|
|
EXIT
|
|
ENDIF
|
|
IF IS_ENTITY_DEAD(thisVehicle)
|
|
EXIT
|
|
ENDIF
|
|
cartIndex = cartIndex
|
|
VECTOR newCartPosition
|
|
FLOAT newCartHeading
|
|
VECTOR vHolePosition = GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
VECTOR ballPos = GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome)
|
|
VECTOR shotDirection = NORMALISE_VECTOR(<<vHolePosition.x, vHolePosition.y,0>> - <<ballPos.x, ballPos.y,0>>)
|
|
//find safe spot for cart behind the ball
|
|
IF FIND_SAFE_SPOT_FOR_CART(ballPos, vDestination, newCartPosition, newCartHeading, shotDirection, ballPos, TRUE)
|
|
SET_ENTITY_HEADING(thisVehicle, newCartHeading)
|
|
|
|
IF NOT GOLF_FIND_GROUND_Z(newCartPosition)
|
|
EXIT //can't find good spot just get out
|
|
ENDIF
|
|
SET_ENTITY_COORDS(thisVehicle, newCartPosition)
|
|
|
|
//we put it somewhere that blocked its door.
|
|
IF NOT IS_ENTRY_POINT_FOR_SEAT_CLEAR(PLAYER_PED_ID(), thisVehicle, VS_DRIVER)
|
|
CDEBUG1LN(DEBUG_GOLF,"Can't get in cart, move it a little bit")
|
|
VECTOR vMoveDirection = GET_ENTITY_FORWARD_VECTOR(thisVehicle)
|
|
vMoveDirection.z = 0
|
|
vMoveDirection = NORMALISE_VECTOR(vMoveDirection)
|
|
vMoveDirection = ROTATE_VECTOR_ABOUT_Z_ORTHO(vMoveDirection, ROTSTEP_NEG_90)
|
|
newCartPosition += vMoveDirection *0.5
|
|
|
|
IF NOT GOLF_FIND_GROUND_Z(newCartPosition)
|
|
EXIT //can't find good spot just get out
|
|
ENDIF
|
|
|
|
SET_ENTITY_COORDS(thisVehicle, newCartPosition)
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Creates a golf ball and sets up its physics properties
|
|
/// PARAMS:
|
|
/// vPosition - Location to create the ball
|
|
/// fHeading - Heading to create the ball with
|
|
/// RETURNS:
|
|
/// OBJECT_INDEX for the new ball
|
|
FUNC OBJECT_INDEX CREATE_GOLF_BALL(VECTOR vPosition, FLOAT fHeading)
|
|
IF ARE_VECTORS_ALMOST_EQUAL(vPosition, <<0,0,0>>)
|
|
SCRIPT_ASSERT("Trying to create a golf ball at 0,0,0.")
|
|
RETURN NULL
|
|
ENDIF
|
|
OBJECT_INDEX newBall
|
|
|
|
#IF NOT GOLF_IS_MP
|
|
newBall = CREATE_OBJECT(PROP_GOLF_BALL, vPosition)
|
|
#ENDIF
|
|
#IF GOLF_IS_MP
|
|
NETWORK_INDEX newNetBall
|
|
CREATE_NET_OBJ(newNetBall, PROP_GOLF_BALL, vPosition, TRUE)
|
|
newBall = GET_OBJECT_INDEX_FROM_ENTITY_INDEX( NETWORK_GET_ENTITY_FROM_NETWORK_ID(newNetBall ))
|
|
SET_NETWORK_ID_CAN_MIGRATE(newNetBall,FALSE)
|
|
// SET_NETWORK_ID_CAN_BE_REASSIGNED(newNetBall,FALSE)
|
|
SET_NETWORK_ID_EXISTS_ON_ALL_MACHINES(newNetBall, TRUE)
|
|
NETWORK_USE_HIGH_PRECISION_BLENDING(newNetBall, TRUE)
|
|
NETWORK_SET_OBJECT_CAN_BLEND_WHEN_FIXED(NET_TO_OBJ(newNetBall), TRUE)
|
|
#ENDIF
|
|
SET_OBJECT_IS_SPECIAL_GOLFBALL(newBall)
|
|
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(newBall, FALSE)
|
|
SET_ENTITY_HEADING( newBall, fHeading)
|
|
IF bDebugSpew DEBUG_MESSAGE("CREATE BALL") ENDIF
|
|
RETURN newBall
|
|
ENDFUNC
|
|
|
|
FUNC OBJECT_INDEX CREATE_GOLF_BALL_MARKER(GOLF_FOURSOME &thisFoursome, INT playerIndex)
|
|
|
|
OBJECT_INDEX newMarker
|
|
VECTOR markerPos = GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL_POSITION(thisFoursome, playerIndex)
|
|
|
|
GET_GROUND_Z_FOR_3D_COORD(markerPos, markerPos.z)
|
|
newMarker = CREATE_OBJECT(PROP_GOLF_MARKER_01, markerPos, FALSE)
|
|
IF DOES_ENTITY_EXIST(newMarker)
|
|
SET_ENTITY_COLLISION(newMarker, FALSE)
|
|
ENDIF
|
|
|
|
RETURN newMarker
|
|
ENDFUNC
|
|
|
|
PROC CREATE_TEE(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse)
|
|
|
|
VECTOR vTeePos = GET_GOLF_HOLE_TEE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)) - <<0.0, 0.0, 0.017>>
|
|
// CDEBUG1LN(DEBUG_GOLF, "Set Tee Pos to ", vTeePos)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(thisFoursome.objTee)
|
|
thisFoursome.objTee = CREATE_OBJECT(PROP_GOLF_TEE, vTeePos, FALSE)
|
|
SET_ENTITY_COLLISION(thisFoursome.objTee, FALSE)
|
|
FREEZE_ENTITY_POSITION(thisFoursome.objTee, TRUE)
|
|
ELSE
|
|
SET_ENTITY_COLLISION(thisFoursome.objTee, FALSE)
|
|
FREEZE_ENTITY_POSITION(thisFoursome.objTee, FALSE)
|
|
SET_ENTITY_COORDS(thisFoursome.objTee, vTeePos + <<0.0, 0.0, 0.035>>)
|
|
FREEZE_ENTITY_POSITION(thisFoursome.objTee, TRUE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC DELETE_TEE(GOLF_FOURSOME &thisFoursome)
|
|
|
|
IF DOES_ENTITY_EXIST(thisFoursome.objTee)
|
|
DELETE_OBJECT(thisFoursome.objTee)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
FUNC BOOL IS_PLAYER_READY_TO_ADDRESS(GOLF_FOURSOME &thisFoursome)
|
|
IF IS_PLAYER_ON_PUTTING_GREEN()
|
|
OR IS_GOLF_FOURSOME_CURRENT_PLAYER_PUTTING(thisFoursome)
|
|
IF GET_SCRIPT_TASK_STATUS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), SCRIPT_TASK_PERFORM_SEQUENCE) = PERFORMING_TASK
|
|
IF GET_SEQUENCE_PROGRESS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome)) = 2
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF GET_SCRIPT_TASK_STATUS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK
|
|
AND GET_SCRIPT_TASK_STATUS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), SCRIPT_TASK_PERFORM_SEQUENCE) != WAITING_TO_START_TASK
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
/// PURPOSE:
|
|
/// Places a given player at his next shot and aiming in a direction. Creates a new club if necessary
|
|
/// PARAMS:
|
|
/// thisPlayerCore -
|
|
/// golfBag -
|
|
/// fHeading -
|
|
/// bSnapToBall -
|
|
PROC PLACE_PLAYER_AT_BALL_WITH_HEADING(GOLF_PLAYER_CORE &thisPlayerCore, GOLF_BAG &golfBag, FLOAT fHeading, BOOL bClearTask, BOOL bUseNetWarp, BOOL bSnapToBall = TRUE, BOOL bRecreateClub = FALSE, BOOL startIdleNow = FALSE)
|
|
IF GET_GOLF_PLAYER_CONTROL(thisPlayerCore) = COMPUTER
|
|
TASK_STAND_STILL(GET_GOLF_PLAYER_PED(thisPlayerCore), -1)
|
|
ELSE
|
|
//only AI gets tasked to walk to ball
|
|
bSnapToBall = TRUE
|
|
ENDIF
|
|
eCLUB_TYPE clubType = GET_GOLF_CLUB_TYPE(golfBag, GET_GOLF_PLAYER_CURRENT_CLUB(thisPlayerCore))
|
|
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisPlayerCore, GOLF_PLAYER_REPOSITIONED)
|
|
|
|
SET_GOLF_PLAYER_AIM(thisPlayerCore, fHeading)
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
CDEBUG1LN(DEBUG_GOLF,"PLACE_PLAYER_AT_BALL_WITH_HEADING: The clubType = ", clubType, ". placement offset = ", GET_STRING_FROM_VECTOR(GET_GOLF_CLUB_PLACEMENT_OFFSET(clubType)))
|
|
DEBUG_PRINTCALLSTACK()
|
|
#ENDIF
|
|
|
|
VECTOR newPlayerPos = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(GET_GOLF_PLAYER_BALL_POSITION(thisPlayerCore), GET_GOLF_PLAYER_AIM(thisPlayerCore), GET_GOLF_CLUB_PLACEMENT_OFFSET(clubType))
|
|
VECTOR vCurrentPlayerHeight = GET_ENTITY_COORDS(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
FLOAT fHeight
|
|
|
|
IF bClearTask
|
|
CLEAR_PED_TASKS_IMMEDIATELY(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
ENDIF
|
|
|
|
IF bSnapToBall OR IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_FAR_AWAY)
|
|
|
|
IF GET_GOLF_PLAYER_CONTROL(thisPlayerCore) != COMPUTER
|
|
GOLF_FIND_GROUND_Z(vCurrentPlayerHeight, 100.0, 0.0)
|
|
ENDIF
|
|
|
|
IF GET_GROUND_Z_FOR_3D_COORD(newPlayerPos+<<0,0,1>>, fHeight)
|
|
IF ABSF(fHeight- vCurrentPlayerHeight.z) < 0.35 //don't allow a dramtic change in height
|
|
OR fHeight < newPlayerPos.z OR startIdleNow
|
|
newPlayerPos.z = fHeight
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bUseNetWarp AND IS_GOLF_FOURSOME_MP()
|
|
NET_WARP_TO_COORD(newPlayerPos, GET_GOLF_PLAYER_AIM(thisPlayerCore), FALSE, FALSE)
|
|
ELSE
|
|
BOOL bControlEntity = TRUE
|
|
#IF GOLF_IS_MP
|
|
bControlEntity = NETWORK_HAS_CONTROL_OF_ENTITY(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
#ENDIF
|
|
|
|
IF bControlEntity
|
|
SET_ENTITY_HEADING(GET_GOLF_PLAYER_PED(thisPlayerCore), GET_GOLF_PLAYER_AIM(thisPlayerCore))
|
|
SET_ENTITY_COORDS(GET_GOLF_PLAYER_PED(thisPlayerCore), newPlayerPos, FALSE, TRUE, TRUE)
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
SET_PED_CAN_ARM_IK(GET_GOLF_PLAYER_PED(thisPlayerCore), FALSE)
|
|
CDEBUG1LN(DEBUG_GOLF,"Setting player pos to ", newPlayerPos, " Setting heading to ", GET_GOLF_PLAYER_AIM(thisPlayerCore))
|
|
#ENDIF
|
|
ELSE
|
|
CDEBUG1LN(DEBUG_GOLF, "Golf place player mp. Player ped ", NATIVE_TO_INT(PLAYER_PED_ID()), " golfer ped ", NATIVE_TO_INT(GET_GOLF_PLAYER_PED(thisPlayerCore)))
|
|
CASSERTLN(DEBUG_GOLF, "PLACE_PLAYER_AT_BALL_WITH_HEADING - Called when you don't own the current player ped.")
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ELSE
|
|
CLEAR_PED_TASKS(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
// CDEBUG1LN(DEBUG_GOLF, "PLACE_PLAYER_AT_BALL_WITH_HEADING: Should be approaching ball right now")
|
|
|
|
OPEN_SEQUENCE_TASK(thisPlayerCore.seq_swing_and_outro)
|
|
//TASK_STAND_STILL(NULL, 3000)
|
|
IF IS_PLAYER_ON_PUTTING_GREEN() OR IS_GOLF_PLAYER_PUTTING(thisPlayerCore)
|
|
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, newPlayerPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP, DEFAULT_NAVMESH_RADIUS, ENAV_STOP_EXACTLY, fHeading)
|
|
TASK_PLAY_ANIM(NULL, "mini@golfai", "putt_approach_no_ball", REALLY_SLOW_BLEND_IN, SLOW_BLEND_OUT, -1)
|
|
TASK_PLAY_ANIM(NULL, "mini@golfai", "putt_approach_no_ball", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_HOLD_LAST_FRAME, 0.999)
|
|
ELSE
|
|
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, newPlayerPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP, DEFAULT_NAVMESH_RADIUS, ENAV_STOP_EXACTLY, fHeading)
|
|
ENDIF
|
|
CLOSE_SEQUENCE_TASK(thisPlayerCore.seq_swing_and_outro)
|
|
|
|
TASK_PERFORM_SEQUENCE(GET_GOLF_PLAYER_PED(thisPlayerCore), thisPlayerCore.seq_swing_and_outro)
|
|
CLEAR_SEQUENCE_TASK(thisPlayerCore.seq_swing_and_outro)
|
|
ENDIF
|
|
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
thisPlayerCore.vAddressBallPos = newPlayerPos
|
|
#ENDIF
|
|
|
|
IF startIdleNow
|
|
CDEBUG1LN(DEBUG_GOLF,"startIdleNow")
|
|
// IF IS_GOLF_FOURSOME_MP()
|
|
// CLEAR_PED_TASKS_IMMEDIATELY(GET_GOLF_PLAYER_PED(thisPlayerCore))
|
|
// ENDIF
|
|
|
|
GOLF_FORCE_IDLE_ANIMATION(thisPlayerCore, golfBag)
|
|
ENDIF
|
|
|
|
IF bRecreateClub AND NOT IS_GOLF_PLAYER_CONTROL_FLAG_SET(thisPlayerCore, GOLF_FAR_AWAY)
|
|
GOLF_ATTACH_CLUB_TO_PLAYER(thisPlayerCore, golfBag)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Places a given player at his next shot and aiming toward the pin
|
|
/// PARAMS:
|
|
/// thisCourse -
|
|
/// thisFoursome -
|
|
/// golfBag -
|
|
/// bSnapToBall -
|
|
PROC PLACE_PLAYER_AT_BALL(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome, GOLF_BAG &golfBag, BOOL bUseNetWarp, BOOL bSnapToBall = TRUE, BOOL bIsTeeShot = FALSE, BOOL bRecreateClub = FALSE, BOOL startIdleNow = FALSE)
|
|
VECTOR aimSpot
|
|
IF bIsTeeShot
|
|
aimSpot = GET_GOLF_HOLE_FAIRWAY_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
ELSE
|
|
aimSpot= GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
ENDIF
|
|
FLOAT aim = GET_HEADING_BETWEEN_VECTORS(aimSpot, GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome))+90
|
|
|
|
PLACE_PLAYER_AT_BALL_WITH_HEADING(thisFoursome.playerCore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], golfBag, aim, FALSE, bUseNetWarp, bSnapToBall, bRecreateClub, startIdleNow)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Resets a golf ball (ie destroys and recreates) a golf ball once it is in the hole. Does all of the scoring elements also
|
|
/// PARAMS:
|
|
/// thisCourse -
|
|
/// thisPlayer -
|
|
/// thisFoursome -
|
|
PROC GOLF_RESET_BALL_IN_HOLE(GOLF_GAME &thisGame, GOLF_PLAYER &thisPlayer, GOLF_FOURSOME &thisFoursome, GOLF_HELPERS &thisHelpers)
|
|
UNUSED_PARAMETER(thisGame)
|
|
|
|
INCREMENT_GOLF_PLAYER_CURRENT_SCORE(thisPlayer, GET_GOLF_PLAYER_HOLE_SCORE(thisPlayer, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)))
|
|
|
|
CLEANUP_GOLF_HELPER_HOLE_BLIP(thisHelpers)
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Checks global wind and sets it up for golf
|
|
/// PARAMS:
|
|
/// thisGame -
|
|
PROC GRAB_WIND_FOR_HOLE(GOLF_GAME &thisGame, GOLF_FOURSOME &thisFoursome, INT iWeather)// #IF NOT GOLF_IS_AI_ONLY , GOLF_HELPERS &thisHelpers #ENDIF)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
#IF NOT GOLF_IS_AI_ONLY
|
|
IF bUseDebugWind
|
|
EXIT
|
|
ENDIF
|
|
#ENDIF
|
|
#ENDIF
|
|
|
|
#IF GOLF_IS_AI_ONLY
|
|
thisGame.fWindStrength = 0
|
|
EXIT
|
|
#ENDIF
|
|
|
|
// FLOAT fWeatherEffect = 1.0
|
|
FLOAT fRainMax = 10.0
|
|
FLOAT fRainMin = 5.0
|
|
FLOAT fClearMax = 6.0
|
|
FLOAT fClearMin = 1.0
|
|
|
|
FLOAT fNewValue
|
|
|
|
//EXTRASUNNY, CLEAR, CLOUDS, SMOG, CLOUDY, OVERCAST, RAIN, THUNDER, CLEARING, NEUTRAL, SNOW, MULTIPLAYER
|
|
IF IS_PREV_WEATHER_TYPE("RAIN")
|
|
OR IS_PREV_WEATHER_TYPE("THUNDER")
|
|
OR IS_PREV_WEATHER_TYPE("OVERCAST")
|
|
// fWeatherEffect = 1.2
|
|
iWeather = ciGOLF_OPTION_RAINING
|
|
CDEBUG1LN(DEBUG_GOLF, "Using rain wind modifier")
|
|
ENDIF
|
|
|
|
IF thisGame.fWindStrength = 0 //init wind strength
|
|
IF iWeather = ciGOLF_OPTION_RAINING
|
|
thisGame.fWindStrength = GET_RANDOM_FLOAT_IN_RANGE(fRainMin, fRainMax-2.0)
|
|
ELSE
|
|
thisGame.fWindStrength = GET_RANDOM_FLOAT_IN_RANGE(fClearMin, fClearMax-2.0)
|
|
ENDIF
|
|
|
|
CDEBUG1LN(DEBUG_GOLF, "Init wind strength to ", thisGame.fWindStrength)
|
|
ELSE
|
|
fNewValue = GET_RANDOM_FLOAT_IN_RANGE(-1.0, 1.0)
|
|
fNewValue = PICK_FLOAT(ABSF(fNewValue) < 0.1, 1.0, fNewValue) //10% chance of big increase
|
|
|
|
fNewValue /= GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome)
|
|
|
|
thisGame.fWindStrength += fNewValue
|
|
CDEBUG1LN(DEBUG_GOLF, "Inc wind strength by ", fNewValue)
|
|
ENDIF
|
|
|
|
IF iWeather = ciGOLF_OPTION_RAINING
|
|
IF thisGame.fWindStrength < fRainMin
|
|
thisGame.fWindStrength = fRainMin
|
|
ELIF thisGame.fWindStrength > fRainMax
|
|
thisGame.fWindStrength = fRainMax
|
|
ENDIF
|
|
ELSE
|
|
IF thisGame.fWindStrength < fClearMin
|
|
thisGame.fWindStrength = fClearMin
|
|
ELIF thisGame.fWindStrength > fClearMax
|
|
thisGame.fWindStrength = fClearMax
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF thisGame.vWindDirection.z = 0 //wind not intialized
|
|
thisGame.vWindDirection = GET_WIND_DIRECTION()
|
|
thisGame.vWindDirection = NORMALISE_VECTOR(thisGame.vWindDirection)
|
|
thisGame.vWindDirection.z = 1
|
|
ELSE
|
|
thisGame.vWindDirection.z = 0
|
|
thisGame.vWindDirection.x += GET_RANDOM_FLOAT_IN_RANGE(-0.3, 0.3)
|
|
thisGame.vWindDirection.y += GET_RANDOM_FLOAT_IN_RANGE(-0.3, 0.3)
|
|
thisGame.vWindDirection = NORMALISE_VECTOR(thisGame.vWindDirection)
|
|
thisGame.vWindDirection.z = 1
|
|
ENDIF
|
|
|
|
CDEBUG1LN(DEBUG_GOLF, "Wind Speed ", thisGame.fWindStrength)
|
|
CDEBUG1LN(DEBUG_GOLF, "Wind Direction ", thisGame.vWindDirection)
|
|
ENDPROC
|
|
|
|
|
|
FUNC BOOL IS_NEXT_GOLF_HOLE_AVAILABLE(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome, GOLF_FOURSOME &allAIFoursomes[], INT holeOffset = 1)
|
|
|
|
INT foursomeIndex
|
|
INT nextHole = GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)+holeOffset
|
|
|
|
IF nextHole >= GET_GOLF_COURSE_NUM_HOLES(thisCourse)
|
|
nextHole = 0
|
|
ENDIF
|
|
|
|
REPEAT COUNT_OF(allAIFoursomes) foursomeIndex
|
|
IF GET_GOLF_FOURSOME_CURRENT_HOLE(allAIFoursomes[foursomeIndex]) = nextHole
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(allAIFoursomes[foursomeIndex], 0, GOLF_WAITING_FOR_HOLE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL ARE_ALL_PLAYERS_REMOVED_FROM_GOLF_GAME(GOLF_FOURSOME &thisFoursome)
|
|
INT playerIndex
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
IF NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_PLAYER_REMOVED)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC GOLF_REMOVE_AI_PED(GOLF_FOURSOME &thisFoursome, INT playerIndex)
|
|
|
|
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))
|
|
IF NOT HAS_ENTITY_CLEAR_LOS_TO_ENTITY(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), PLAYER_PED_ID())
|
|
DELETE_PED(thisFoursome.playerCore[ playerIndex].pedGolfPlayer)
|
|
EXIT
|
|
ELIF NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_PLAYER_REMOVED)
|
|
TASK_SMART_FLEE_PED(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), PLAYER_PED_ID(), FAR_AWAY_THRESHOLD, -1)
|
|
ENDIF
|
|
|
|
IF IS_PED_IN_MELEE_COMBAT(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex))
|
|
CLEAR_PED_TASKS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex))
|
|
TASK_SMART_FLEE_PED(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), PLAYER_PED_ID(), FAR_AWAY_THRESHOLD, -1)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG(thisFoursome, playerIndex, GOLF_PLAYER_REMOVED)
|
|
ENDPROC
|
|
|
|
PROC GOLF_REMOVE_AI_FOURSOME(GOLF_FOURSOME &thisFoursome)
|
|
|
|
INT playerCount
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerCount
|
|
CLEANUP_GOLF_FOURSOME_INDEXED_GOLF_BALL(thisFoursome, playerCount)
|
|
CLEANUP_GOLF_CLUB(thisFoursome.playerCore[playerCount])
|
|
CLEANUP_GOLF_GOLFBAG(thisFoursome.playerCore[playerCount])
|
|
IF DOES_ENTITY_EXIST(thisFoursome.playerCore[playerCount].pedGolfPlayer) AND NOT IS_ENTITY_DEAD(thisFoursome.playerCore[playerCount].pedGolfPlayer)
|
|
CLEAR_PED_TASKS(thisFoursome.playerCore[playerCount].pedGolfPlayer)
|
|
ENDIF
|
|
|
|
GOLF_REMOVE_AI_PED(thisFoursome, playerCount)
|
|
ENDREPEAT
|
|
|
|
SET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome, -2)
|
|
|
|
ENDPROC
|
|
FUNC BOOL ARE_ALL_GOLFERS_IN_CART(GOLF_FOURSOME &thisFoursome, INT startIndex = 0)
|
|
|
|
INT playerIndex
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
|
|
IF playerIndex >= startIndex
|
|
IF NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)) AND NOT IS_ENTITY_DEAD( GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex))
|
|
IF NOT IS_PED_IN_VEHICLE(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex))
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_PLAYER_REMOVED)
|
|
AND NOT IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_STOP_USING_CART)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC TELEPORT_GOLFER_TO_COORD(GOLF_FOURSOME &thisFoursome, INT playerIndex, VECTOR coord, GOLF_COURSE &thisCourse, BOOL snapToGround, BOOL teleportCart = TRUE)
|
|
|
|
//do not teleport the golfer in mid air
|
|
FLOAT fHeight
|
|
IF snapToGround
|
|
IF GET_GROUND_Z_FOR_3D_COORD (coord + <<0,0,50.0>>, fHeight)
|
|
coord.z = fHeight
|
|
ENDIF
|
|
ENDIF
|
|
|
|
SET_ENTITY_COORDS(GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex), coord, FALSE)
|
|
|
|
INT cartIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, playerIndex)
|
|
|
|
//move cart
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CART(thisFoursome, cartIndex)) AND teleportCart
|
|
VECTOR cartSpawnPos = << 0,0,0 >>
|
|
VECTOR cartOffset = <<0,0,0>>
|
|
FLOAT cartHeading = 0
|
|
BOOL foundSafeSpot
|
|
|
|
IF cartIndex > 0
|
|
cartOffset = <<5,5,0>>
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_CART(thisFoursome, cartIndex))
|
|
IF IS_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG_SET(thisFoursome, playerIndex, GOLF_FAR_AWAY)
|
|
foundSafeSpot = FIND_SAFE_SPOT_FOR_CART_FAST(coord+ cartOffset, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)), cartSpawnPos, cartHeading)
|
|
ELSE
|
|
foundSafeSpot =FIND_SAFE_SPOT_FOR_CART(coord+ cartOffset, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)), cartSpawnPos, cartHeading, <<0,0,0>>, <<0,0,0>>)
|
|
ENDIF
|
|
|
|
IF foundSafeSpot AND NOT IS_SPHERE_VISIBLE(cartSpawnPos, 5.0)
|
|
SET_ENTITY_COORDS(GET_GOLF_FOURSOME_CART(thisFoursome, cartIndex), cartSpawnPos)
|
|
SET_ENTITY_HEADING(GET_GOLF_FOURSOME_CART(thisFoursome, cartIndex), cartHeading)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
//Teleports a golfer and his cart to his ball
|
|
PROC TELEPORT_GOLFER_TO_BALL(GOLF_FOURSOME &thisFoursome, INT playerIndex, GOLF_COURSE &thisCourse, BOOL snapToGround, BOOL teleportCart = TRUE)
|
|
TELEPORT_GOLFER_TO_COORD(thisFoursome, playerIndex, GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL_POSITION(thisFoursome, playerIndex), thisCourse, snapToGround, teleportCart)
|
|
|
|
ENDPROC
|
|
|
|
PROC TELEPORT_FOURSOME_TO_TEE(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse, BOOL teleportCart = TRUE)
|
|
|
|
INT playerIndex
|
|
INT holeIndex = GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)
|
|
|
|
//move players
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
SET_GOLF_PLAYER_STATE(thisFoursome.playerCore[playerIndex], GPS_PLACE_BALL)
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_LIE(thisFoursome, playerIndex, <<0,0,0>>, LIE_TEE)
|
|
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_HOLE_TEE_SPECTATE_POSITION(thisCourse, holeIndex, playerIndex))
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF teleportCart
|
|
VECTOR cartSpawnPos = << 0,0,0 >>
|
|
VECTOR cartOffset = <<5,5,0>>
|
|
FLOAT cartHeading = 0
|
|
INT cartIndex
|
|
|
|
//move cart
|
|
IF FIND_SAFE_SPOT_FOR_CART(GET_GOLF_HOLE_TEE_POSITION(thisCourse, holeIndex), GET_GOLF_HOLE_PIN_POSITION(thisCourse, holeIndex), cartSpawnPos, cartHeading, <<0,0,0>>, <<0,0,0>>)
|
|
|
|
REPEAT 2 cartIndex
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CART(thisFoursome, cartIndex))
|
|
IF NOT IS_ENTITY_DEAD(GET_GOLF_FOURSOME_CART(thisFoursome, cartIndex))
|
|
AND NOT IS_SPHERE_VISIBLE(cartSpawnPos+ TO_FLOAT(cartIndex)*cartOffset, 5.0)
|
|
SET_ENTITY_COORDS(GET_GOLF_FOURSOME_CART(thisFoursome, cartIndex), cartSpawnPos + TO_FLOAT(cartIndex)*cartOffset)
|
|
SET_ENTITY_HEADING(GET_GOLF_FOURSOME_CART(thisFoursome, cartIndex), cartHeading)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
FUNC STRING GET_GOLF_RANDOM_POSITIVE_ANIM_NAME()
|
|
|
|
INT randomNumber = GET_RANDOM_INT_IN_RANGE(0, 100)
|
|
|
|
IF randomNumber < 50
|
|
RETURN "average"
|
|
ENDIF
|
|
|
|
IF randomNumber < 75
|
|
RETURN "average_b"
|
|
ENDIF
|
|
|
|
IF randomNumber < 90
|
|
RETURN "celeb_a"
|
|
ENDIF
|
|
|
|
RETURN "celeb_c"
|
|
|
|
ENDFUNC
|
|
|
|
//Moves all other golfers off the course to the cart path so the player has a clear shot
|
|
PROC MOVE_GOLFERS_OFF_COURSE(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse)
|
|
|
|
IF GET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome) = LIE_TEE OR GET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome) = LIE_GREEN
|
|
EXIT
|
|
ENDIF
|
|
|
|
#IF GOLF_IS_MP
|
|
EXIT
|
|
#ENDIF
|
|
|
|
INT currentPlayer = GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)
|
|
INT playerIndex
|
|
FLOAT returnHeading, fHeight
|
|
VECTOR pinPos = GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
VECTOR originPos, returnPos
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
VEHICLE_INDEX playersCart = GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex)
|
|
PED_INDEX playersPed = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)
|
|
|
|
|
|
IF playerIndex != currentPlayer AND GET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL(thisFoursome, playerIndex) = COMPUTER
|
|
AND DOES_ENTITY_EXIST(playersPed) AND NOT IS_ENTITY_DEAD(playersPed)
|
|
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(playersPed, TRUE)
|
|
originPos = GET_ENTITY_COORDS(playersPed)
|
|
|
|
CLEAR_PED_TASKS(playersPed)
|
|
|
|
IF FIND_SAFE_SPOT_FOR_CART(originPos, pinPos, returnPos, returnHeading, <<0,0,0>>, <<0,0,0>>)
|
|
IF GET_GROUND_Z_FOR_3D_COORD(returnPos+<<0,0,2>>, fHeight)
|
|
returnPos.z = fHeight
|
|
ENDIF
|
|
|
|
SET_ENTITY_COORDS(playersPed, returnPos)
|
|
SET_ENTITY_HEADING(playersPed, GET_HEADING_BETWEEN_VECTORS(returnPos,pinPos))
|
|
ENDIF
|
|
ELSE
|
|
IF DOES_ENTITY_EXIST(playersCart) AND NOT IS_ENTITY_DEAD(playersCart)
|
|
SET_PED_INTO_VEHICLE(playersPed, playersCart, GET_GOLF_FOURSOME_INDEXED_PLAYER_SEAT(playerIndex))
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC CLEAR_NEARBY_GOLF_BALLS(GOLF_FOURSOME &thisFoursome)
|
|
INT idx
|
|
INT idxExclude = GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) idx
|
|
IF idx != idxExclude
|
|
IF DOES_ENTITY_EXIST(thisFoursome.playerCore[idx].objBall)
|
|
IF VDIST2(GET_ENTITY_COORDS(thisFoursome.playerCore[idx].objBall), thisFoursome.playerCore[idxExclude].vBallPosition) <= 1.0
|
|
CDEBUG1LN(DEBUG_GOLF,"CLEAR_NEARBY_GOLF_BALLS: Deleting the golf ball of player: ", idx)
|
|
DELETE_OBJECT(thisFoursome.playerCore[idx].objBall)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC CLEAR_AREA_AROUND_BALL(GOLF_COURSE &thisCourse, GOLF_FOURSOME &thisFoursome)
|
|
|
|
IF IS_GOLF_FOURSOME_MP()
|
|
EXIT //not needed in mp
|
|
ENDIF
|
|
|
|
CLEAR_AREA_OF_PEDS(GET_GOLF_COURSE_CENTER(thisCourse), 400)
|
|
CLEAR_AREA_OF_PEDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome), 5.0)
|
|
CLEAR_AREA_OF_OBJECTS(GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome), 5.0)
|
|
CLEAR_AREA_OF_VEHICLES(GET_GOLF_COURSE_CENTER(thisCourse), 400)
|
|
|
|
ENDPROC
|
|
|
|
//The spectating players rotation from the player
|
|
FUNC FLOAT GET_GOLFERS_PLACEMENT_ROTATION_FROM_INDEX(INT iPlayerIndex)
|
|
|
|
IF iPlayerIndex = 0
|
|
RETURN 15.0
|
|
ELIF iPlayerIndex = 1
|
|
RETURN -15.0
|
|
ELIF iPlayerIndex = 2
|
|
RETURN 30.0
|
|
ELIF iPlayerIndex = 3
|
|
RETURN -30.0
|
|
ENDIF
|
|
|
|
RETURN 0.0
|
|
ENDFUNC
|
|
|
|
FUNC BOOL TELEPORT_SPECTATOR_TO_POSITION_IN_GOLF(GOLF_FOURSOME &thisFoursome, GOLF_HELPERS &thisHelpers, GOLF_COURSE &thisCourse, INT iSpectatorIndex)
|
|
|
|
PED_INDEX pedPlayer = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iSpectatorIndex)
|
|
FLOAT fTeleportHeading, fHeight, fDegree
|
|
INT iCurrentHole = GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome)
|
|
VECTOR vTeleportPosition, vCurrentShootersPos
|
|
BOOL bSafe = TRUE
|
|
GOLF_LIE_TYPE teleportPosLie
|
|
|
|
vCurrentShootersPos = GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome)
|
|
|
|
CDEBUG1LN(DEBUG_GOLF,"Teleporting player")
|
|
VECTOR vHolePosition = GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
VECTOR vShotDir = NORMALISE_VECTOR(<<vHolePosition.x, vHolePosition.y,0>> - <<vCurrentShootersPos.x, vCurrentShootersPos.y,0>>)
|
|
|
|
IF IS_TEE_SHOT(thisCourse, thisFoursome)
|
|
CDEBUG1LN(DEBUG_GOLF,"Teleporting to tee spectate")
|
|
vTeleportPosition = GET_GOLF_HOLE_TEE_SPECTATE_POSITION(thisCourse,iCurrentHole, iSpectatorIndex)
|
|
ELIF GET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome) = LIE_GREEN
|
|
OR SHOULD_USE_GREEN_SPECATE_FOR_COORD(vCurrentShootersPos, iCurrentHole)
|
|
CDEBUG1LN(DEBUG_GOLF,"Teleporting to green spectate")
|
|
vTeleportPosition = GET_GOLF_HOLE_GREEN_SPECTATE_POSITION(thisCourse,iCurrentHole, iSpectatorIndex)
|
|
|
|
IF VDIST2(vTeleportPosition, vCurrentShootersPos) < 3.5*3.5 //teleport spot is really close to player
|
|
OR (DOT_PRODUCT_XY(vShotDir, NORMALISE_VECTOR(vTeleportPosition - vCurrentShootersPos)) > 0.5 //the player is within 6 meters and in the line of sight of the shooter
|
|
AND VDIST2(vTeleportPosition, vCurrentShootersPos) < 6.0*6.0)
|
|
|
|
CDEBUG1LN(DEBUG_GOLF,"Use extra green spectate for player ", iSpectatorIndex)
|
|
vTeleportPosition = GET_GOLF_HOLE_GREEN_SPECTATE_POSITION(thisCourse, iCurrentHole, 6)
|
|
ENDIF
|
|
ELIF GET_GOLF_FOURSOME_CURRENT_PLAYER_LIE(thisFoursome) = LIE_BUNKER
|
|
|
|
IF IS_GOLF_COORD_NEAR_BUNKER(vCurrentShootersPos, iCurrentHole, vTeleportPosition, iSpectatorIndex)
|
|
CDEBUG1LN(DEBUG_GOLF,"Current player is in bunker, use pre defined specate spot ", vTeleportPosition)
|
|
ELSE
|
|
CDEBUG1LN(DEBUG_GOLF,"Current player is in bunker, but didn't find safe specate spot on hole ", iCurrentHole)
|
|
ENDIF
|
|
ELIF IS_GOLF_COORD_NEAR_LAKE(vCurrentShootersPos, iCurrentHole, vTeleportPosition, iSpectatorIndex)
|
|
CDEBUG1LN(DEBUG_GOLF,"Current player is near lake, use pre defined specate spot ", vTeleportPosition)
|
|
ELSE
|
|
CDEBUG1LN(DEBUG_GOLF,"Teleporting not tee or green shot")
|
|
FLOAT fMoveDist = PICK_FLOAT(IS_GOLF_FOURSOME_MP(), 5.5, 4.5)
|
|
|
|
vTeleportPosition = vCurrentShootersPos - fMoveDist*vShotDir
|
|
fDegree = GET_GOLFERS_PLACEMENT_ROTATION_FROM_INDEX(iSpectatorIndex)
|
|
vTeleportPosition = ROTATE_VECTOR_ABOUT_Z(vTeleportPosition - vCurrentShootersPos, fDegree)
|
|
vTeleportPosition += vCurrentShootersPos
|
|
|
|
IF NOT GET_GROUND_Z_FOR_3D_COORD(vTeleportPosition + <<0, 0, 2.0>>, fHeight)
|
|
bSafe = FALSE
|
|
ELSE
|
|
vTeleportPosition.z = fHeight
|
|
ENDIF
|
|
|
|
IF IS_GOLF_COORD_OUTSIDE_BOUNDARY_PLANES(vTeleportPosition)
|
|
bSafe = FALSE
|
|
ENDIF
|
|
|
|
IF (DOT_PRODUCT_XY(vShotDir, NORMALISE_VECTOR(vTeleportPosition - vCurrentShootersPos)) > 0.5
|
|
AND VDIST2(vCurrentShootersPos, vTeleportPosition) < 25.0*25.0) //if you are more then 25 yards away, its ok to be in players los
|
|
OR VDIST2(vTeleportPosition, vCurrentShootersPos) < 3.5*3.5 //teleport spot is really close to player
|
|
CDEBUG1LN(DEBUG_GOLF, "Teleport spot obstructing golfer.")
|
|
CDEBUG1LN(DEBUG_GOLF, "Dist ", VDIST2(vTeleportPosition, vCurrentShootersPos), " DOT ", DOT_PRODUCT_XY(vShotDir, NORMALISE_VECTOR(vTeleportPosition - vCurrentShootersPos)))
|
|
bSafe = FALSE
|
|
ENDIF
|
|
|
|
IF bSafe //the spot is safe so far, lets see what lie it's on
|
|
GET_GOLF_LIE_FROM_WORLD_POSITION(vTeleportPosition + <<0,0,0.1>>, teleportPosLie, LIE_UNKNOWN, PLAYER_PED_ID())
|
|
IF NOT IS_GOLF_LIE_SAFE_FOR_TELEPORT(teleportPosLie)
|
|
CDEBUG1LN(DEBUG_GOLF,"Going to teleport player to bad lie ", teleportPosLie)
|
|
bSafe = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bSafe
|
|
fTeleportHeading = GET_HEADING_BETWEEN_VECTORS(vTeleportPosition, vCurrentShootersPos)
|
|
|
|
CDEBUG1LN(DEBUG_GOLF,"Teleporting to ",vTeleportPosition, " with heading ", fTeleportHeading)
|
|
|
|
CLEAR_PED_TASKS_IMMEDIATELY(pedPlayer)
|
|
SET_ENTITY_COORDS(pedPlayer, vTeleportPosition, FALSE, TRUE)
|
|
SET_ENTITY_HEADING(pedPlayer, fTeleportHeading)
|
|
thisHelpers.bAllowPlayerViewCam = TRUE
|
|
RETURN TRUE
|
|
ELSE
|
|
CDEBUG1LN(DEBUG_GOLF,"Don't teleport to unsafe location")
|
|
#IF GOLF_IS_MP
|
|
//to close to player, move far away
|
|
IF VDIST(GET_ENTITY_COORDS(pedPlayer), vCurrentShootersPos) < 3.0
|
|
vTeleportPosition = <<-1378.6844, 55.8883, 52.6896>>
|
|
SET_ENTITY_COORDS(pedPlayer, vTeleportPosition, FALSE, TRUE)
|
|
FREEZE_ENTITY_POSITION(pedPlayer, TRUE)
|
|
thisHelpers.bAllowPlayerViewCam = FALSE
|
|
ELIF VDIST(GET_ENTITY_COORDS(pedPlayer), vCurrentShootersPos) < 50.0
|
|
//current position is close enough to count as good pos
|
|
fTeleportHeading = GET_HEADING_BETWEEN_VECTORS(vTeleportPosition, vCurrentShootersPos)
|
|
SET_ENTITY_HEADING(pedPlayer, fTeleportHeading)
|
|
thisHelpers.bAllowPlayerViewCam = TRUE
|
|
ELSE
|
|
thisHelpers.bAllowPlayerViewCam = FALSE
|
|
ENDIF
|
|
#ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
//Moves any golfers in the way of the players shot
|
|
PROC MOVE_ENTITIES_AROUND_CURRENT_PLAYER(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse)
|
|
#IF GOLF_IS_MP //dont use this function in mp golf
|
|
EXIT
|
|
#ENDIF
|
|
|
|
INT playerIndex
|
|
VECTOR currentPlayerPos = GET_ENTITY_COORDS(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome), FALSE)
|
|
// VEHICLE_INDEX vehIndex
|
|
//PED_INDEX randomPed
|
|
// INT vehSearchFlag = ( VEHICLE_SEARCH_FLAG_RETURN_LAW_ENFORCER_VEHICLES | VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES | VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_GROUP_MEMBERS | VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_A_PLAYER | VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_A_DEAD_OR_DYING_PED | VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_WITH_PEDS_ENTERING_OR_EXITING | VEHICLE_SEARCH_FLAG_ALLOW_VEHICLE_OCCUPANTS_TO_BE_PERFORMING_A_SCRIPTED_TASK )
|
|
//
|
|
// INT iSafe = 0
|
|
// //remove random vehicles
|
|
// WHILE IS_ANY_VEHICLE_NEAR_POINT(currentPlayerPos, 5.0) AND iSafe < 10
|
|
// CDEBUG1LN(DEBUG_GOLF,"Vehicle not owned by script near player shot")
|
|
// vehIndex = GET_CLOSEST_VEHICLE(currentPlayerPos, 5.0, DUMMY_MODEL_FOR_SCRIPT, vehSearchFlag)
|
|
// DELETE_VEHICLE(vehIndex)
|
|
// iSafe++
|
|
// ENDWHILE
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
|
|
IF playerIndex != GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)
|
|
|
|
PED_INDEX indexedPlayerPed = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)
|
|
|
|
IF DOES_ENTITY_EXIST(indexedPlayerPed) AND NOT IS_ENTITY_DEAD(indexedPlayerPed)
|
|
REMOVE_GOLF_CLUB_WEAPON(indexedPlayerPed, TRUE)
|
|
|
|
//within 3 metters just teleport them away
|
|
IF VDIST2(GET_ENTITY_COORDS(indexedPlayerPed), currentPlayerPos) < 9.0
|
|
CDEBUG1LN(DEBUG_GOLF,"Ped Moved")
|
|
VECTOR newCoord = currentPlayerPos - 5.0*GET_ENTITY_FORWARD_VECTOR(GET_GOLF_FOURSOME_CURRENT_PLAYER_PED(thisFoursome))
|
|
|
|
//the ped is going to be moved out of bounds, rotate coord 90 deg
|
|
IF IS_GOLF_COORD_OUTSIDE_BOUNDARY_PLANES(newCoord)
|
|
newCoord = ROTATE_VECTOR_ABOUT_Z_ORTHO(newCoord - currentPlayerPos, ROTSTEP_90)
|
|
newCoord+=currentPlayerPos
|
|
ENDIF
|
|
|
|
VECTOR vHolePosition = GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))
|
|
VECTOR ballPos = GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL_POSITION(thisFoursome)
|
|
VECTOR vShotDir = NORMALISE_VECTOR(<<vHolePosition.x, vHolePosition.y,0>> - <<ballPos.x, ballPos.y,0>>)
|
|
VECTOR vToNewPos = NORMALISE_VECTOR(<<newCoord.x, newCoord.y,0>> - <<ballPos.x, ballPos.y,0>>)
|
|
|
|
//ped is now in front of golfer, rotate
|
|
IF DOT_PRODUCT_XY(vShotDir, vToNewPos) > 0.75
|
|
newCoord = ROTATE_VECTOR_ABOUT_Z_ORTHO(newCoord - currentPlayerPos, ROTSTEP_180)
|
|
newCoord += currentPlayerPos
|
|
ENDIF
|
|
|
|
CLEAR_PED_TASKS(indexedPlayerPed)
|
|
GET_GROUND_Z_FOR_3D_COORD(newCoord+<<0,0,50>>, newCoord.z)
|
|
SET_ENTITY_COORDS(indexedPlayerPed, newCoord)
|
|
SET_ENTITY_HEADING(indexedPlayerPed, GET_HEADING_BETWEEN_VECTORS(newCoord, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))))
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC TELEPORT_GOLFERS_TO_SPECTATE(GOLF_FOURSOME &thisFoursome, GOLF_HELPERS &thisHelpers, GOLF_COURSE &thisCourse,INT iExcludeIndex)
|
|
|
|
#IF GOLF_IS_MP
|
|
EXIT
|
|
#ENDIF
|
|
|
|
INT playerIndex
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
|
|
IF iExcludeIndex != playerIndex
|
|
//only teleport the local player if the current player is putting
|
|
AND (IS_GOLF_FOURSOME_CURRENT_PLAYER_PUTTING(thisFoursome) OR playerIndex != GET_GOLF_FOURSOME_LOCAL_PLAYER(thisFoursome))
|
|
|
|
PED_INDEX pedIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)
|
|
VEHICLE_INDEX vehIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex)
|
|
|
|
IF DOES_ENTITY_EXIST(pedIndex) AND NOT IS_ENTITY_DEAD(pedIndex)
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(pedIndex, TRUE)
|
|
CLEAR_PED_TASKS(pedIndex)
|
|
TELEPORT_SPECTATOR_TO_POSITION_IN_GOLF(thisFoursome, thisHelpers, thisCourse, playerIndex)
|
|
ELIF DOES_ENTITY_EXIST(vehIndex) AND NOT IS_ENTITY_DEAD(vehIndex)
|
|
SET_PED_INTO_VEHICLE(pedIndex, vehIndex, GET_GOLF_FOURSOME_INDEXED_PLAYER_SEAT(playerIndex))
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC TELEPORT_GOLF_FOURSOME_TO_TEE_SPECTATE(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse,INT iExcludeIndex)
|
|
|
|
#IF GOLF_IS_MP
|
|
EXIT
|
|
#ENDIF
|
|
|
|
INT playerIndex
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
|
|
IF iExcludeIndex != playerIndex
|
|
PED_INDEX pedIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, playerIndex)
|
|
//VEHICLE_INDEX vehIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, playerIndex)
|
|
VECTOR spectatePos = GET_GOLF_HOLE_TEE_SPECTATE_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome), playerIndex)
|
|
IF DOES_ENTITY_EXIST(pedIndex) AND NOT IS_ENTITY_DEAD(pedIndex) AND GET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL(thisFoursome, playerIndex) != HUMAN_NETWORK
|
|
CLEAR_PED_TASKS(pedIndex)
|
|
SET_ENTITY_COORDS(pedIndex, spectatePos)
|
|
SET_ENTITY_HEADING(pedIndex, GET_HEADING_BETWEEN_VECTORS(spectatePos, GET_GOLF_HOLE_PIN_POSITION(thisCourse, GET_GOLF_FOURSOME_CURRENT_HOLE(thisFoursome))))
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
//Clears flags when the ball is at rest after a hit
|
|
PROC CLEAR_CONTROL_FLAGS_BALL_AT_REST(GOLF_FOURSOME &thisFoursome, GOLF_GAME &thisGame, GOLF_HELPERS &thisHelpers)
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playercore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_BALL_IS_OOB)
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playercore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_BALL_IN_FOCUS)
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playercore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_HIT_FLAG)
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playercore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_FORCE_UPDATE)
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playercore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_CART_ARRIVED)
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playercore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_SHOT_IS_GIMMIE)
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playercore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_USE_HARD_AI)
|
|
CLEAR_GOLF_PLAYER_CONTROL_FLAG(thisFoursome.playercore[GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome)], GOLF_PLAYER_TIME_OUT)
|
|
CLEAR_GOLF_UI_FLAG(thisHelpers, GUC_USE_FILL_QUALITY)
|
|
CLEAR_GOLF_UI_FLAG(thisHelpers, GUC_STYLE_HELP_DISPLAYED)
|
|
CLEAR_GOLF_CONTROL_FLAG(thisGame, GCF_BALL_JUST_LAND)
|
|
CLEAR_GOLF_CONTROL_FLAG(thisGame, GCF_WAS_PERFECT_HIT)
|
|
CLEAR_GOLF_CONTROL_FLAG(thisGame, GCF_BALL_POP_SOUND)
|
|
CLEAR_GOLF_CONTROL_FLAG(thisGame, GCF_BALL_IN_CUP_SOUND)
|
|
CLEAR_GOLF_DIALOGUE_FLAG(thisHelpers, GDF_PARTNER_SAID_AIM_WARNING)
|
|
CLEAR_GOLF_STREAMING_FLAG(thisHelpers, GSF_SET_HELPER_BLIP_ADDRESS_NAME)
|
|
CLEAR_GOLF_STREAMING_FLAG(thisHelpers, GSF_SET_HELPER_BLIP_IN_FLIGHT_NAME)
|
|
CLEAR_GOLF_STREAMING_FLAG(thisHelpers, GSF_SKIP_AI_PRESSED)
|
|
thisHelpers.vLastGoodAddressCamPos = <<0,0,0>>
|
|
|
|
STOP_AUDIO_SCENE("GOLF_FLY_CAM")
|
|
ENDPROC
|
|
|
|
PROC SET_GOLF_MARKER_FLUSH_WITH_GROUND(OBJECT_INDEX objMarker)
|
|
FLOAT fHeight
|
|
VECTOR vMarkerPos, vGroundNormal, vMarkerRot
|
|
|
|
FLOAT h, h2
|
|
|
|
IF DOES_ENTITY_EXIST(objMarker)
|
|
vMarkerPos = GET_ENTITY_COORDS(objMarker)
|
|
|
|
IF GET_GROUND_Z_AND_NORMAL_FOR_3D_COORD(vMarkerPos + <<0,0,1>>, fHeight, vGroundNormal)
|
|
vMarkerPos.z = fHeight + 0.005
|
|
SET_ENTITY_COORDS(objMarker, vMarkerPos)
|
|
|
|
h = SQRT(vGroundNormal.x*vGroundNormal.x + vGroundNormal.z*vGroundNormal.z)
|
|
h2 = SQRT(vGroundNormal.y*vGroundNormal.y + vGroundNormal.z*vGroundNormal.z)
|
|
|
|
vMarkerRot.x = 90 - ASIN(vGroundNormal.z/h)
|
|
vMarkerRot.y = 90 - ASIN(vGroundNormal.z/h2)
|
|
|
|
SET_ENTITY_ROTATION(objMarker, vMarkerRot)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC GOLF_REPLACE_BALL_WITH_MARKER(GOLF_FOURSOME &thisFoursome)
|
|
|
|
INT playerIndex
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) playerIndex
|
|
IF playerIndex != GET_GOLF_FOURSOME_CURRENT_PLAYER(thisFoursome) AND GET_GOLF_FOURSOME_INDEXED_PLAYER_MARKER(thisFoursome, playerIndex) = NULL
|
|
AND GET_GOLF_FOURSOME_INDEXED_PLAYER_STATE(thisFoursome, playerIndex) != GPS_DONE_WITH_HOLE
|
|
OBJECT_INDEX newMarker = CREATE_GOLF_BALL_MARKER(thisFoursome, playerIndex)
|
|
|
|
CLEANUP_GOLF_BALL(thisFoursome.playerCore[playerIndex])
|
|
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_MARKER(thisFoursome, newMarker, playerIndex)
|
|
SET_GOLF_MARKER_FLUSH_WITH_GROUND(newMarker)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GOLF_MANAGE_CART_OWNER(GOLF_FOURSOME &thisFoursome)
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
//player got into the wrong vehicle
|
|
IF GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) != GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, 0)
|
|
CDEBUG1LN(DEBUG_GOLF,"Switch carts")
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, 0, ABSI(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, 0) - 1))
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, 2, ABSI(GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, 0) - 1))
|
|
|
|
SET_GOLF_FOURSOME_CART_DRIVER(thisFoursome, 0, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, 0))
|
|
SET_GOLF_FOURSOME_CART_DRIVER(thisFoursome, 2, GET_GOLF_FOURSOME_INDEXED_PLAYER_CART_INDEX(thisFoursome, 2))
|
|
|
|
//if ped was entering cart when you stole it, have him stop trying to get in
|
|
PED_INDEX pedIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, 2)
|
|
VEHICLE_INDEX vehIndex = GET_GOLF_FOURSOME_INDEXED_PLAYER_CART(thisFoursome, 2)
|
|
IF DOES_ENTITY_EXIST(vehIndex) AND DOES_ENTITY_EXIST(pedIndex)
|
|
IF NOT IS_ENTITY_DEAD(vehIndex) AND NOT IS_ENTITY_DEAD(pedIndex)
|
|
IF GET_SCRIPT_TASK_STATUS(pedIndex, SCRIPT_TASK_ENTER_VEHICLE) = PERFORMING_TASK
|
|
CDEBUG1LN(DEBUG_GOLF,"Ped stops moveing to cart")
|
|
CLEAR_PED_TASKS_IMMEDIATELY(pedIndex)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
FUNC BOOL IS_GOLF_CURRENT_PLAYER_HARD_AI(GOLF_FOURSOME &thisFoursome)
|
|
RETURN (GET_GOLF_FOURSOME_CURRENT_PLAYER_AI_DIFFICULTY(thisFoursome) = GOLF_AI_HARD OR IS_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL_FLAG_SET(thisFoursome, GOLF_USE_HARD_AI))
|
|
AND GET_GOLF_FOURSOME_CURRENT_PLAYER_CONTROL(thisFoursome) = COMPUTER //important, do not remove
|
|
ENDFUNC
|
|
|
|
PROC GOLF_MANAGE_END_OF_HOLE_TIMER(GOLF_FOURSOME &thisFoursome, INT iTime)
|
|
UNUSED_PARAMETER(thisFoursome)
|
|
|
|
IF iTime < 0
|
|
iTime = 0
|
|
ENDIF
|
|
|
|
IF GET_GOLF_FOURSOME_STATE(thisFoursome) = GGS_SCORECARD_END_GAME
|
|
DRAW_GENERIC_TIMER(iTime*1000, "GOLF_END_TIMER")
|
|
ELSE
|
|
DRAW_GENERIC_TIMER(iTime*1000, "GOLF_NEXT_HOLE")
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
FUNC FLOAT GET_GOLF_SCALER_FROM_COORD(VECTOR vPos)
|
|
FLOAT fPedRange = GET_DISTANCE_BETWEEN_COORDS(GET_CAM_COORD(GET_RENDERING_CAM()), vPos)
|
|
FLOAT DefaultFov = 50.0
|
|
FLOAT DefaultRange = 4.5
|
|
FLOAT fScalerX = (GET_CAM_FOV(GET_RENDERING_CAM()) * fPedRange) / (DefaultFov*DefaultRange)
|
|
IF fScalerX > 1
|
|
RETURN fScalerX
|
|
ELSE
|
|
RETURN 1.0
|
|
ENDIF
|
|
ENDFUNC
|
|
|
|
PROC DRAW_GOLF_ARROW(VECTOR vDrawPos, FLOAT fAimHeading, VECTOR vHolePos, VECTOR vBallPos, BOOL bUseStaticSize)
|
|
|
|
fAimHeading = fAimHeading%360
|
|
// //Sprite Placement details
|
|
// SPRITE_PLACEMENT drawSprite
|
|
// //Set up the sprite
|
|
// drawSprite.x = 0
|
|
// drawSprite.y = 0
|
|
// drawSprite.w = 0.03
|
|
// drawSprite.h = 0.075
|
|
// drawSprite.r = 255
|
|
// drawSprite.g = 255
|
|
// drawSprite.b = 255
|
|
// drawSprite.a = 200
|
|
//
|
|
// FLOAT fScreenX, fScreenY, Scaler
|
|
// //FLOAT XShiftStat = -0.015
|
|
|
|
IF VDIST2(vDrawPos, vHolePos) < (0.15*0.15)
|
|
vDrawPos.z = vHolePos.z + 0.08
|
|
ENDIF
|
|
FLOAT fMaxDist = 20.0 * 20.0
|
|
FLOAT fDistance = VDIST2(<<vBallPos.x, vBallPos.y, 0>> , <<vDrawPos.x, vDrawPos.y, 0>>)
|
|
FLOAT fSize = 0.3
|
|
|
|
IF NOT bUseStaticSize
|
|
IF fDistance < (0.5 *0.5)
|
|
fSize = 0.25
|
|
ELSE
|
|
fSize = 0.25 + (fDistance/fMaxDist)*0.2
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// CDEBUG1LN(DEBUG_GOLF,"Size, ", fSize)
|
|
// CDEBUG1LN(DEBUG_GOLF,"fAimHeading ", fAimHeading)
|
|
DRAW_MARKER(MARKER_ARROW_FLAT, vDrawPos + <<0, 0, 0.152>>, <<0,0,0>>, <<90.0 - fAimHeading, 90.0, 0>>, <<fSize, fSize, fSize>>, 255, 255, 255, 200, FALSE, FALSE, EULER_YXZ, FALSE, GET_GOLF_TEXTURE_DICTIONARY_NAME(), "PuttingMarker")
|
|
//
|
|
// IF HAS_STREAMED_TEXTURE_DICT_LOADED(GET_GOLF_TEXTURE_DICTIONARY_NAME())
|
|
// IF GET_SCREEN_COORD_FROM_WORLD_COORD(vDrawPos, fScreenX, fScreenY)
|
|
// fScreenX = drawSprite.x
|
|
// fScreenY = drawSprite.y
|
|
// Scaler = GET_GOLF_SCALER_FROM_COORD(vDrawPos)
|
|
//
|
|
// IF Scaler > 1
|
|
// //Adjust the xpos
|
|
// //XShiftStat /= Scaler
|
|
// //Set the scale of the icon
|
|
// drawSprite.w = drawSprite.w / Scaler
|
|
// drawSprite.h = drawSprite.h / Scaler
|
|
// ENDIF
|
|
// //set up the sprite
|
|
// //fScreenX += XShiftStat
|
|
// //Make it so the icon is drawn in the center.
|
|
// drawSprite.x = fScreenX// + (aSprite.w/2)
|
|
// drawSprite.y = fScreenY - (drawSprite.h/2)
|
|
// SET_DRAW_ORIGIN(vDrawPos)
|
|
//
|
|
// SET_SCRIPT_GFX_DRAW_ORDER(GFX_ORDER_BEFORE_HUD)
|
|
// DRAW_2D_SPRITE(GET_GOLF_TEXTURE_DICTIONARY_NAME(), "PuttingMarker", drawSprite, TRUE, HIGHLIGHT_OPTION_NORMAL)
|
|
// SET_SCRIPT_GFX_DRAW_ORDER(GFX_ORDER_AFTER_HUD)
|
|
// CLEAR_DRAW_ORIGIN()
|
|
// ENDIF
|
|
// ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC DRAW_GOLF_TERRAIN_GRID(VECTOR vBallPos, INT iHole)
|
|
|
|
VECTOR vGridPos, vGridDir, vGridSize
|
|
FLOAT fGridRes
|
|
FLOAT fColourMuti = 20.0
|
|
FLOAT fChangeInHeight = 0.08
|
|
|
|
SWITCH iHole
|
|
|
|
CASE 0
|
|
vGridPos = <<-1120.569, 222.185, 64.814>>
|
|
vGridDir = <<-0.712, 0.700, 0.0>>
|
|
vGridSize = <<14.920, 24.480, -0.63>>
|
|
fGridRes = 42.000
|
|
BREAK
|
|
|
|
CASE 1
|
|
vGridPos = <<-1326.193, 162.310, 56.974>>
|
|
vGridDir = <<-0.771, 0.636, 0.003>>
|
|
vGridSize = <<19.480, 24.340, -0.63>>
|
|
fGridRes = 42.000
|
|
BREAK
|
|
|
|
CASE 2
|
|
vGridPos = <<-1238.702, 106.882, 56.462>>
|
|
vGridDir = <<0.177, 0.982, 0.060>>
|
|
vGridSize = << 15.720, 27.980, 0.100>>
|
|
fGridRes = 42.000
|
|
BREAK
|
|
|
|
CASE 3
|
|
vGridPos = <<-1099.278, 10.541, 50.810>>
|
|
vGridDir = <<-0.993, 0.110, -0.046>>
|
|
vGridSize = <<33.050, 36.350, -0.63>>
|
|
fGridRes = 65.000
|
|
BREAK
|
|
|
|
CASE 4
|
|
vGridPos = <<-965.273, -82.437, 41.041>>
|
|
vGridDir = <<0.549, -0.835, -0.031>>
|
|
vGridSize = <<20.470, 42.540, -0.63>>
|
|
fGridRes = 42.000
|
|
BREAK
|
|
|
|
CASE 5
|
|
vGridPos = <<-1102.084, -116.732, 40.891>>
|
|
vGridDir = <<-0.485, -0.875, -0.006>>
|
|
vGridSize = <<18.560, 20.000, -0.63>>
|
|
fGridRes = 42.000
|
|
BREAK
|
|
|
|
CASE 6
|
|
vGridPos = <<-1284.205, 4.114, 49.654>>
|
|
vGridDir = <<-0.997, -0.018, 0.076>>
|
|
vGridSize = <<19.010, 20.000, 0.700>>
|
|
fGridRes = 42.000
|
|
BREAK
|
|
|
|
CASE 7
|
|
vGridPos = <<-1041.863, -84.943, 43.140>>
|
|
vGridDir = <<0.799, 0.600, 0.033>>
|
|
vGridSize = <<18.690, 24.090, 0.68>>
|
|
fGridRes = 42.000
|
|
BREAK
|
|
|
|
CASE 8
|
|
vGridPos = <<-1289.969, 83.574, 54.183>>
|
|
vGridDir = <<-1.000, 0.004, 0.005>>
|
|
vGridSize = <<19.010, 20.000, -0.63>>
|
|
fGridRes = 42.000
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
vGridPos.z = vBallPos.z +0.5
|
|
|
|
TERRAINGRID_ACTIVATE(TRUE)
|
|
TERRAINGRID_SET_PARAMS(vGridPos, vGridDir, vGridSize.x, vGridSize.y, vGridSize.z, fGridRes, fColourMuti, vBallPos.z, fChangeInHeight)
|
|
TERRAINGRID_SET_COLOURS(255, 0, 0, 64, 255, 255, 255, 5, 255, 255, 0, 64)
|
|
|
|
// FLOAT fGridRes, fGridWidth, fGridHeight
|
|
// VECTOR vCenterPos, vForward
|
|
//
|
|
// GET_TERRAIN_GRID_DATA(iHole, vCenterPos, vForward, fGridRes, fGridWidth, fGridHeight)
|
|
// TERRAINGRID_SET_PARAMS(vCenterPos, vForward, fGridWidth, fGridHeight, 2.0, fGridRes, fColourMuti, vBallPos.z, 0.25 )
|
|
|
|
ENDPROC
|
|
|
|
PROC DRAW_GOLF_ESTIMATE_RING(VECTOR vEstimatePos, VECTOR vHolePos)
|
|
|
|
IF VDIST2(vEstimatePos, vHolePos) < (0.15*0.15)
|
|
vEstimatePos.z = vHolePos.z + 0.12
|
|
ENDIF
|
|
|
|
//DRAW_MARKER(MARKER_CYLINDER, vEstimatePos, <<0,0,0>>, <<0,0,0>>, <<0.31, 0.31, 0.05>>, 255, 255, 0, 200)
|
|
|
|
DRAW_MARKER(MARKER_RING, vEstimatePos + <<0,0,0.01>>, <<0,0,0>>, <<-90,0,0>>, <<0.25, 0.25, 0.05>>, 255, 255, 0, 255)
|
|
ENDPROC
|
|
|
|
//PROC DRAW_GOLF_ESTIMATE_RING(VECTOR vEstimatePos, VECTOR vHolePos)
|
|
//
|
|
// IF VDIST2(vEstimatePos, vHolePos) < (0.15*0.15)
|
|
// vEstimatePos.z = vHolePos.z + 0.12
|
|
// ENDIF
|
|
//
|
|
// FLOAT fHieght
|
|
// VECTOR vNormal = <<0, 0, -1>>
|
|
// VECTOR vDirX = <<1, 0, 0>>
|
|
// VECTOR vDirY = <<0, 1, 0>>
|
|
// VECTOR vDirZ = <<0, 0, 1>>
|
|
//
|
|
// GET_GROUND_Z_AND_NORMAL_FOR_3D_COORD(vEstimatePos + <<0, 0, 1>>, fHieght, vNormal)
|
|
// VECTOR vRot
|
|
//
|
|
// //vRot = <<ACOS(vNormal.y), ACOS(vNormal.x), ACOS(vNormal.z)>>
|
|
//
|
|
// vRot.x = ACOS(vNormal.y/SQRT(vNormal.y*vNormal.y + vNormal.z*vNormal.z))
|
|
// vRot.z = ACOS(vNormal.x/SQRT(vNormal.y*vNormal.y + vNormal.x*vNormal.x))
|
|
//
|
|
// // + +, - Cos y
|
|
// //- +, 180 + Sin x
|
|
// //+ -, 180 + Sin x
|
|
// //- -, - Sin y
|
|
// IF bDebugSpew
|
|
// CDEBUG1LN(DEBUG_GOLF,"Normal ", vNormal, " vRot( ", vRot)
|
|
//
|
|
// CDEBUG1LN(DEBUG_GOLF,"Cos x ", ACOS(vNormal.x/SQRT(vNormal.y*vNormal.y + vNormal.x*vNormal.x)))
|
|
// CDEBUG1LN(DEBUG_GOLF,"Cos y ", ACOS(vNormal.y/SQRT(vNormal.y*vNormal.y + vNormal.x*vNormal.x)))
|
|
// CDEBUG1LN(DEBUG_GOLF,"Sin x ", ASIN(vNormal.x/SQRT(vNormal.y*vNormal.y + vNormal.x*vNormal.x)))
|
|
// CDEBUG1LN(DEBUG_GOLF,"Sin y ", ASIN(vNormal.y/SQRT(vNormal.y*vNormal.y + vNormal.x*vNormal.x)))
|
|
// ENDIF
|
|
//
|
|
// vEstimatePos += <<0,0,0.01>>
|
|
//
|
|
//
|
|
//
|
|
// //89.59, 81.66, 8.5
|
|
// DRAW_DEBUG_LINE(vEstimatePos, vEstimatePos +vDirX, 255, 0 ,0 )
|
|
// DRAW_DEBUG_LINE(vEstimatePos, vEstimatePos +vDirY, 0, 255 ,0 )
|
|
// DRAW_DEBUG_LINE(vEstimatePos, vEstimatePos +vDirZ, 0, 0 ,255 )
|
|
// DRAW_DEBUG_LINE(vEstimatePos, vEstimatePos+vNormal, 255, 255 ,255 )
|
|
//
|
|
//
|
|
// //DRAW_MARKER(MARKER_CYLINDER, vEstimatePos, <<0,0,0>>, <<0,0,0>>, <<0.31, 0.31, 0.05>>, 255, 255, 0, 200)
|
|
//
|
|
// DRAW_MARKER(MARKER_RING, vEstimatePos, <<0, 0, 0>>, <<vRingScale.x,vRingScale.y,vRingScale.z>>, <<0.25, 0.25, 0.05>>, 255, 255, 0, 255)
|
|
//ENDPROC
|
|
|
|
PROC GOLF_MANAGE_BALL_COLLISION(GOLF_FOURSOME &thisFoursome)
|
|
|
|
#IF GOLF_IS_MP
|
|
EXIT //no need to do it in mp golf, this is handled elsewhere
|
|
#ENDIF
|
|
|
|
INT iPlayerIndex, iPlayerIndex2
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
OBJECT_INDEX playerBall = GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL(thisFoursome, iPlayerIndex)
|
|
IF DOES_ENTITY_EXIST(playerBall)
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex2
|
|
OBJECT_INDEX playerBall2 = GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL(thisFoursome, iPlayerIndex2)
|
|
|
|
IF iPlayerIndex2 != iPlayerIndex AND DOES_ENTITY_EXIST(playerBall2)
|
|
IF IS_ENTITY_TOUCHING_ENTITY(playerBall, playerBall2)
|
|
CDEBUG1LN(DEBUG_GOLF,"Ball collision unfreeze balls")
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG(thisFoursome, iPlayerIndex, GOLF_BALL_NEEDS_SNAP)
|
|
SET_GOLF_FOURSOME_INDEXED_PLAYER_CONTROL_FLAG(thisFoursome, iPlayerIndex2, GOLF_BALL_NEEDS_SNAP)
|
|
FREEZE_GOLF_BALL(playerBall, FALSE)
|
|
FREEZE_GOLF_BALL(playerBall2, FALSE)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GOLF_KNOCK_OVER_PED(PED_INDEX golferPed, OBJECT_INDEX playerBall)
|
|
IF IS_PED_INJURED(golferPed)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF IS_PED_RAGDOLL(golferPed)
|
|
EXIT
|
|
ENDIf
|
|
|
|
VECTOR vForce
|
|
FLOAT fMaxForce = 10.0
|
|
|
|
IF DOES_ENTITY_EXIST(playerBall)
|
|
vForce = GET_ENTITY_VELOCITY(playerBall) //* 0.1
|
|
ELSE
|
|
vForce = <<0,0,1>>
|
|
ENDIF
|
|
|
|
IF VMAG2(vForce) > (fMaxForce * fMaxForce)
|
|
vForce = NORMALISE_VECTOR(vForce)*fMaxForce
|
|
ENDIF
|
|
|
|
PRINTLN("Knock ped over")
|
|
FREEZE_ENTITY_POSITION(golferPed, FALSE)
|
|
|
|
|
|
#IF NOT GOLF_IS_MP
|
|
SET_PED_TO_RAGDOLL(golferPed, 3000, 5000, TASK_NM_BALANCE, FALSE )
|
|
APPLY_FORCE_TO_ENTITY(golferPed, APPLY_TYPE_IMPULSE, vForce, <<0,0,0>>, 0, FALSE, FALSE, TRUE)
|
|
#ENDIF
|
|
|
|
#IF GOLF_IS_MP
|
|
TASK_PLAY_ANIM(golferPed, "reaction@shove", "shoved_front")
|
|
#ENDIF
|
|
ENDPROC
|
|
|
|
PROC GOLF_MANAGE_BALL_PLAYER_COLLISION(GOLF_FOURSOME &thisFoursome)
|
|
|
|
#IF GOLF_IS_MP
|
|
EXIT //no need to do it in mp golf, this is handled elsewhere
|
|
#ENDIF
|
|
|
|
INT iPlayerIndex
|
|
OBJECT_INDEX playerBall = GET_GOLF_FOURSOME_CURRENT_PLAYER_BALL(thisFoursome)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(playerBall)
|
|
EXIT
|
|
ENDIF
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
PED_INDEX golferPed = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iPlayerIndex)
|
|
|
|
IF NOT IS_PED_INJURED(golferPed)
|
|
IF IS_ENTITY_TOUCHING_ENTITY(playerBall, golferPed)
|
|
CDEBUG1LN(DEBUG_GOLF,"Ball is touching a golfer")
|
|
GOLF_KNOCK_OVER_PED(golferPed, playerBall)
|
|
GOLF_DETACH_CLUB(thisFoursome, iPlayerIndex)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GOLF_FREEZE_ALL_BALL_POSITIONS(GOLF_FOURSOME &thisFoursome)
|
|
|
|
#IF GOLF_IS_MP
|
|
EXIT //no need to do it in mp golf, this is handled elsewhere
|
|
#ENDIF
|
|
|
|
INT iPlayerIndex
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iPlayerIndex
|
|
OBJECT_INDEX playerBall = GET_GOLF_FOURSOME_INDEXED_PLAYER_BALL(thisFoursome, iPlayerIndex)
|
|
IF DOES_ENTITY_EXIST(playerBall)
|
|
FREEZE_GOLF_BALL(playerBall, TRUE)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
FUNC TEXT_LABEL_23 GET_GOLF_SPLASH_TEXT_FROM_ENUM(GOLF_SPLASH_TEXT_ENUM eSplashText, TEXT_LABEL_23 &sRetStrapLine)
|
|
|
|
TEXT_LABEL_23 txtReturnSplashName
|
|
sRetStrapLine = ""
|
|
|
|
SWITCH eSplashText
|
|
CASE GOLF_SPLASH_NONE
|
|
txtReturnSplashName = ""
|
|
BREAK
|
|
CASE GOLF_SPLASH_HOLE_IN_ONE
|
|
txtReturnSplashName = "SCORE_HOLEINONE"
|
|
BREAK
|
|
CASE GOLF_SPLASH_EAGLE2
|
|
txtReturnSplashName = "SCORE_EAGLE2"
|
|
BREAK
|
|
CASE GOLF_SPLASH_EAGLE
|
|
txtReturnSplashName = "SCORE_EAGLE"
|
|
BREAK
|
|
CASE GOLF_SPLASH_BIRDIE
|
|
txtReturnSplashName = "SCORE_BIRDIE"
|
|
BREAK
|
|
CASE GOLF_SPLASH_PAR
|
|
txtReturnSplashName = "SCORE_PAR"
|
|
BREAK
|
|
CASE GOLF_SPLASH_BOGEY
|
|
txtReturnSplashName = "SCORE_BOGEY"
|
|
BREAK
|
|
CASE GOLF_SPLASH_BOGEY2
|
|
txtReturnSplashName = "SCORE_BOGEY2"
|
|
BREAK
|
|
CASE GOLF_SPLASH_BOGEY3
|
|
txtReturnSplashName = "SCORE_BOGEY3"
|
|
BREAK
|
|
CASE GOLF_SPLASH_BOGEY4
|
|
txtReturnSplashName = "SCORE_BOGEY4"
|
|
BREAK
|
|
CASE GOLF_SPLASH_BOGEY5
|
|
txtReturnSplashName = "SCORE_BOGEY5"
|
|
BREAK
|
|
CASE GOLF_SPLASH_FIR
|
|
txtReturnSplashName = "FIR"
|
|
sRetStrapLine = "GOLF_F_REGULATION"
|
|
BREAK
|
|
CASE GOLF_SPLASH_GIR
|
|
txtReturnSplashName = "GIR"
|
|
sRetStrapLine = "GOLF_G_REGULATION"
|
|
BREAK
|
|
CASE GOLF_SPLASH_LONGEST_DIVE
|
|
txtReturnSplashName = "GOLF_NEW_RECORD"
|
|
sRetStrapLine = "DRIVE_LONG"
|
|
IF GOLF_SHOULD_USE_FOREIGN_DISTANCE()
|
|
sRetStrapLine = "DRIVE_LONG_M"
|
|
ENDIF
|
|
BREAK
|
|
CASE GOLF_SPLASH_LONGEST_HOLE
|
|
txtReturnSplashName = "GOLF_NEW_RECORD"
|
|
txtReturnSplashName = "DRIVE_HOLE"
|
|
IF GOLF_SHOULD_USE_FOREIGN_DISTANCE()
|
|
sRetStrapLine = "DRIVE_HOLE_M"
|
|
ENDIF
|
|
BREAK
|
|
CASE GOLF_SPLASH_CLOSEST_TO_PIN
|
|
txtReturnSplashName = "GOLF_NEW_RECORD"
|
|
sRetStrapLine = GET_DRIVE_PIN_TEXT_LABEL(0)
|
|
BREAK
|
|
CASE GOLF_SPLASH_OOB
|
|
txtReturnSplashName = "LIE_UNKNOWN"
|
|
BREAK
|
|
CASE GOLF_SPLASH_WATER
|
|
txtReturnSplashName = "LIE_WATER"
|
|
BREAK
|
|
CASE GOLF_SPLASH_SCORE_LIMIT
|
|
txtReturnSplashName = "SCORE_LIMIT"
|
|
BREAK
|
|
CASE GOLF_SPLASH_UNPLAYABLE
|
|
txtReturnSplashName = "LIE_UNPLAYABLE"
|
|
BREAK
|
|
CASE GOLF_SPLASH_OBSTRUCTED
|
|
txtReturnSplashName = "LIE_UNPLAYABLE"
|
|
sRetStrapLine = "LIE_OBSTRUCT"
|
|
BREAK
|
|
DEFAULT
|
|
CDEBUG1LN(DEBUG_GOLF,"Invalid Splash text enum ", eSplashText)
|
|
SCRIPT_ASSERT("Invalid Splash text enum")
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN txtReturnSplashName
|
|
ENDFUNC
|
|
|
|
|
|
PROC RESET_FRIEND_FOR_CLEANUP(PED_INDEX pedFriend)
|
|
IF NOT IS_PED_INJURED(pedFriend)
|
|
RESET_PED_WEAPON_MOVEMENT_CLIPSET(pedFriend)
|
|
SET_PED_CAN_PLAY_AMBIENT_ANIMS(pedFriend, TRUE)
|
|
SET_PED_CONFIG_FLAG(pedFriend, PCF_IgnoreLegIkRestrictions, FALSE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC RESET_FRIEND_FOR_GOLF_OUTRO(GOLF_FOURSOME &thisFoursome, PED_VARIATION_STRUCT &sResetVariation, INT iFriendIndex, VECTOR vEndPos, FLOAT fEndHeading)
|
|
|
|
PED_INDEX pedFriend = GET_GOLF_FOURSOME_INDEXED_PLAYER_PED(thisFoursome, iFriendIndex)
|
|
|
|
IF NOT IS_PED_INJURED(pedFriend)
|
|
REMOVE_PED_FROM_GROUP(pedFriend)
|
|
SET_ENTITY_COORDS(pedFriend, vEndPos)
|
|
SET_ENTITY_HEADING(pedFriend, fEndHeading)
|
|
REMOVE_GOLF_CLUB_WEAPON(pedFriend, TRUE)
|
|
SET_PED_VARIATIONS(pedFriend, sResetVariation)
|
|
CLEAR_PED_TASKS(pedFriend)
|
|
RESET_FRIEND_FOR_CLEANUP(pedFriend)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC CREATE_GOLF_PLAYER_GOLF_CARTS(GOLF_FOURSOME &thisFoursome, GOLF_COURSE &thisCourse)
|
|
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CART(thisFoursome, 0))
|
|
VEHICLE_INDEX veh = GET_GOLF_FOURSOME_CART(thisFoursome, 0)
|
|
DELETE_VEHICLE(veh)
|
|
ENDIF
|
|
|
|
SET_GOLF_FOURSOME_CART(thisFoursome, CREATE_VEHICLE(CADDY, GET_GOLF_COURSE_CART_POSITION(thisCourse, 0)), 0)
|
|
SET_VEHICLE_EXTRA(GET_GOLF_FOURSOME_CART(thisFoursome, 0), 5, TRUE)
|
|
SET_VEHICLE_HAS_STRONG_AXLES(GET_GOLF_FOURSOME_CART(thisFoursome, 0), TRUE)
|
|
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(GET_GOLF_FOURSOME_CART(thisFoursome, 0), TRUE)
|
|
DEBUG_MESSAGE("CREATE CART")
|
|
|
|
IF GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) > 2
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_CART(thisFoursome, 1))
|
|
VEHICLE_INDEX veh = GET_GOLF_FOURSOME_CART(thisFoursome, 1)
|
|
DELETE_VEHICLE(veh)
|
|
ENDIF
|
|
|
|
SET_GOLF_FOURSOME_CART(thisFoursome, CREATE_VEHICLE(CADDY, GET_GOLF_COURSE_CART_POSITION(thisCourse, 1)), 1)
|
|
SET_VEHICLE_EXTRA(GET_GOLF_FOURSOME_CART(thisFoursome, 1), 5, TRUE)
|
|
SET_VEHICLE_HAS_STRONG_AXLES(GET_GOLF_FOURSOME_CART(thisFoursome, 1), TRUE)
|
|
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(GET_GOLF_FOURSOME_CART(thisFoursome, 1), TRUE)
|
|
DEBUG_MESSAGE("CREATE CART 2")
|
|
ENDIF
|
|
|
|
INT iCurrentPlayer
|
|
|
|
REPEAT GET_GOLF_FOURSOME_NUM_PLAYERS(thisFoursome) iCurrentPlayer
|
|
IF DOES_ENTITY_EXIST(GET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iCurrentPlayer))
|
|
OBJECT_INDEX obj = GET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iCurrentPlayer)
|
|
DELETE_OBJECT(obj)
|
|
ENDIF
|
|
|
|
SET_GOLF_PLAYER_GOLFBAG(thisFoursome.playerCore[iCurrentPlayer], CREATE_OBJECT_NO_OFFSET(PROP_GOLF_BAG_01B, GET_GOLF_COURSE_START_POSITION(thisCourse, iCurrentPlayer)))
|
|
|
|
ATTACH_ENTITY_TO_ENTITY( GET_GOLF_FOURSOME_INDEXED_PLAYER_GOLFBAG(thisFoursome, iCurrentPlayer), GET_GOLF_FOURSOME_CART(thisFoursome, PICK_INT(iCurrentPlayer < 2, 0, 1)), 0, <<-0.225 - (-0.444 * ((iCurrentPlayer+1)%2)),-1.111, 0.570>>, <<0,0,-87.000 + (180.0 * ((iCurrentPlayer+1)%2)) >>)
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC GOLF_TOGGLE_LOADING_SPINNER(BOOL bOn)
|
|
IF bOn
|
|
BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("MP_SPINLOADING")
|
|
END_TEXT_COMMAND_BUSYSPINNER_ON(5)
|
|
ELSE
|
|
IF BUSYSPINNER_IS_ON()
|
|
BUSYSPINNER_OFF()
|
|
PRELOAD_BUSYSPINNER()
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|