USING "invade_persuade_using.sch" USING "invade_persuade_drawing.sch" // ------------------------------ HELPERS ------------------------------ /// PURPOSE: /// Moves a float value representing a X coordinate using a speed scaled by the current stage speed FUNC FLOAT IAP_APPLY_SPEED_TO_VALUE(FLOAT fValue, FLOAT fSpeed) RETURN fValue +@ (fSpeed * sIAPData.fStageSpeedMod) ENDFUNC /// PURPOSE: /// Moves a VECTOR_2D towards another VECTOR_2D by fDistance FUNC VECTOR_2D IAP_MOVE_TOWARDS_VECTOR(VECTOR_2D vCurrent, VECTOR_2D vDesired, FLOAT fDistance) VECTOR_2D vReturn FLOAT fDistanceX = fDistance * cfBASE_SCREEN_WIDTH fDistanceX = 0 +@ fDistanceX FLOAT fDistanceY = fDistance * cfBASE_SCREEN_HEIGHT fDistanceY = 0 +@ fDistanceY vCurrent = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(vCurrent) vDesired = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(vDesired) FLOAT fNorm = SQRT(POW(vDesired.x - vCurrent.x, 2) + POW(vDesired.y - vCurrent.y, 2)) FLOAT fDirectionX = vDesired.x - vCurrent.x FLOAT fDirectionY = vDesired.y - vCurrent.y IF fNorm != 0 fDirectionX /= fNorm fDirectionY /= fNorm ENDIF vReturn.x = vCurrent.x + fDistanceX * fDirectionX vReturn.y = vCurrent.y + fDistanceY * fDirectionY RETURN ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vReturn) ENDFUNC /// PURPOSE: /// Returns the width of the pitfall sprite for the current stage FUNC FLOAT IAP_GET_CURRENT_PITFALL_SCALE() RETURN sIAPData.sObjectData[ENUM_TO_INT(IAP_GET_CURRENT_STAGE_PITFALL_INDEX())].vSpriteScale.x ENDFUNC /// PURPOSE: /// Returns the width of the ledge sprite for the current stage FUNC FLOAT IAP_GET_CURRENT_LEDGE_SCALE() RETURN sIAPData.sObjectData[ENUM_TO_INT(IAP_GET_CURRENT_STAGE_LEDGE_INDEX())].vSpriteScale.x ENDFUNC /// PURPOSE: /// Returns the width of the foreground sprite at iForegroundIndex FUNC FLOAT IAP_GET_FOREGROUND_X_SCALE(INT iForegroundIndex) IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[iForegroundIndex] = ciIAP_PARALLAX_PITFALL RETURN IAP_GET_CURRENT_PITFALL_SCALE() ENDIF IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[iForegroundIndex] = ciIAP_PARALLAX_RAISED_LEDGE RETURN IAP_GET_CURRENT_LEDGE_SCALE() ENDIF RETURN sIAPData.sCurrentStageData.vForegroundSpriteScale.x ENDFUNC /// PURPOSE: /// Returns the speed boost applied when passing a drum of oil of type FUNC FLOAT IAP_GET_SPEED_BOOST_FROM_OIL_TYPE(IAP_OBJECT eObjectType) SWITCH eObjectType CASE IAP_OBJECT_OIL_SMALL RETURN cfIAP_SMALL_OIL_SPEED_BOOST CASE IAP_OBJECT_OIL_MED_DARK CASE IAP_OBJECT_OIL_MED_LIGHT RETURN cfIAP_MEDIUM_OIL_SPEED_BOOST CASE IAP_OBJECT_OIL_LARGE RETURN cfIAP_LARGE_OIL_SPEED_BOOST ENDSWITCH RETURN 0.0 ENDFUNC /// PURPOSE: /// Returns the ground Y position at pos X /// RETURNS: /// FUNC FLOAT IAP_GET_GROUND_Y_AT_X_POS(FLOAT fX, BOOL bForSpawning = FALSE) FLOAT fCurrentX = sIAPData.sParallax.fForegroundPosX[0] - (IAP_GET_FOREGROUND_X_SCALE(0)/2) INT i FOR i = 0 TO sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1 fCurrentX += IAP_GET_FOREGROUND_X_SCALE(i) IF fX < fCurrentX IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] = ciIAP_PARALLAX_PITFALL AND (bForSpawning OR (sIAPData.sObjectInstances[sIAPData.sParallax.iLinkedObjectIndexes[i]].iFlags & ciIAP_OBJECT_FLAG_PITFALL_CRUMBLING) = 0) IF fX > fCurrentX - IAP_GET_CURRENT_PITFALL_SCALE() + IAP_GET_CURRENT_STAGE_PITFALL_GROUND_WIDTH_LEFT() AND fX < fCurrentX - IAP_GET_CURRENT_STAGE_PITFALL_GROUND_WIDTH_RIGHT() //Pitfall Hole RETURN cfIAP_PITFALL_DEPTH ENDIF ENDIF IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] = ciIAP_PARALLAX_RAISED_LEDGE RETURN (1.0 - cfIAP_FACADE_TOP_HEIGHT) - sIAPData.sObjectData[ENUM_TO_INT(IAP_GET_CURRENT_STAGE_LEDGE_INDEX())].vSpriteScale.y + cfIAP_LEDGE_OFFSET ENDIF RETURN sIAPData.sCurrentStageData.fBaseY ENDIF ENDFOR RETURN sIAPData.sCurrentStageData.fBaseY ENDFUNC FUNC BOOL SHOULD_ALLOW_IAP_IN_PROPERTY() IF IS_PLAYER_IN_CASINO_APARTMENT(GET_PLAYER_INDEX()) RETURN TRUE ENDIF #IF FEATURE_CASINO_HEIST IF IS_PLAYER_IN_ARCADE_PROPERTY(GET_PLAYER_INDEX()) RETURN TRUE ENDIF #ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Returns true if the game should quit /// Processes holding a button to quit /// RETURNS: /// FUNC BOOL IAP_SHOULD_QUIT_NOW() IF g_bForceQuitPenthouseArcadeMachines CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SHOULD_QUIT_NOW - g_bForceQuitPenthouseArcadeMachines") RETURN TRUE ENDIF IF IS_PLAYER_LEAVING_ANY_SIMPLE_INTERIOR_USING_THE_LIMO_SERVICE() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SHOULD_QUIT_NOW - IS_PLAYER_LEAVING_ANY_SIMPLE_INTERIOR_USING_THE_LIMO_SERVICE") RETURN TRUE ENDIF IF IS_PLAYER_DOING_HELI_DOCK_CUTSCENE(GET_PLAYER_INDEX()) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SHOULD_QUIT_NOW - IS_PLAYER_DOING_HELI_DOCK_CUTSCENE") RETURN TRUE ENDIF IF NOT SHOULD_ALLOW_IAP_IN_PROPERTY() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SHOULD_QUIT_NOW - Not allowed in this property") RETURN TRUE ENDIF IF SHOULD_KICK_PLAYER_FROM_ANY_ARCADE_GAME() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SHOULD_QUIT_NOW - SHOULD_KICK_PLAYER_FROM_ANY_ARCADE_GAME") RETURN TRUE ENDIF IF sIAPData.eCurrentState < IAP_CLIENT_STATE_DEGENETRON RETURN FALSE ENDIF CONTROL_ACTION CA_Quit = INPUT_FRONTEND_CANCEL IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) CA_Quit = INPUT_FRONTEND_DELETE ENDIF IF IS_CONTROL_PRESSED(FRONTEND_CONTROL, CA_Quit) OR (IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_Quit)) DRAW_GENERIC_METER(ciIAP_HOLD_TO_QUIT_TIME - ABSI(NATIVE_TO_INT(GET_NETWORK_TIME()) - sIAPData.iQuitTime), ciIAP_HOLD_TO_QUIT_TIME, "DEG_GAME_QUIT") ELSE DRAW_GENERIC_METER(0, ciIAP_HOLD_TO_QUIT_TIME, "DEG_GAME_QUIT") ENDIF IF IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_Quit) IF sIAPData.iQuitTime = -HIGHEST_INT sIAPData.iQuitTime = NATIVE_TO_INT(GET_NETWORK_TIME()) + ciIAP_HOLD_TO_QUIT_TIME ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.iQuitTime CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SHOULD_QUIT_NOW - Button Held") RETURN TRUE ENDIF //DRAW_GENERIC_METER(ciIAP_HOLD_TO_QUIT_TIME - (sIAPData.iQuitTime - NATIVE_TO_INT(GET_NETWORK_TIME())), ciIAP_HOLD_TO_QUIT_TIME, "IAP_EXIT", HUD_COLOUR_RED, -1, HUDORDER_TOP) ELIF sIAPData.iQuitTime != -HIGHEST_INT sIAPData.iQuitTime = -HIGHEST_INT ENDIF IF IS_PLAYER_IN_ARCADE_PROPERTY(PLAYER_ID()) IF SHOULD_KICK_PLAYER_FROM_ANY_ARCADE_GAME() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SHOULD_QUIT_NOW - SHOULD_KICK_PLAYER_FROM_ANY_ARCADE_GAME true") RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Resets the score tracking struct /// Use when the player starts a new game from the title screen PROC IAP_WIPE_SCORE_TRACKING_STRUCT() sIAPData.sScoreTracking.iScoreFromPickups = 0 sIAPData.sScoreTracking.iPickupsCollected = 0 sIAPData.sScoreTracking.iTotalPickupsCollected = 0 sIAPData.sScoreTracking.iScoreFromEnemies = 0 sIAPData.sScoreTracking.iEnemiesKilled = 0 sIAPData.sScoreTracking.iTotalEnemiesKilled = 0 sIAPData.sScoreTracking.iTotalAnimalsKilled = 0 sIAPData.sScoreTracking.iScoreFromOil = 0 sIAPData.sScoreTracking.iOilCollected = 0 sIAPData.sScoreTracking.iTotalOilCollected = 0 sIAPData.sScoreTracking.iScoreFromDistance = 0 sIAPData.sScoreTracking.iScoreFromLives = 0 sIAPData.sScoreTracking.iScoreFromArmour = 0 ENDPROC // ------------------------------ LEADERBOARD ------------------------------ /// PURPOSE: /// Returns the default initials for a leaderboard position FUNC INT IAP_GET_DEFAULT_INITIALS_FOR_POSITION(INT iPosition) SWITCH iPosition CASE 0 RETURN 54161 //RON CASE 1 RETURN 1172 //USA CASE 2 RETURN 45582 //OIL CASE 3 RETURN 70801 //RSR CASE 4 RETURN 5199 //PRB CASE 5 RETURN 12994 //CLD CASE 6 RETURN 4613 //FIB CASE 7 RETURN 73734 //GAS CASE 8 RETURN 8256 //ABC CASE 9 RETURN 13078 //WMD ENDSWITCH RETURN 0 ENDFUNC /// PURPOSE: /// Returns the default score for a leaderboard position FUNC INT IAP_GET_DEFAULT_SCORE_FOR_POSITION(INT iPosition) SWITCH iPosition CASE 0 RETURN 2273775 CASE 1 RETURN 2000000 CASE 2 RETURN 1900000 CASE 3 RETURN 1800000 CASE 4 RETURN 1700000 CASE 5 RETURN 1600000 CASE 6 RETURN 1500000 CASE 7 RETURN 1400000 CASE 8 RETURN 1200000 CASE 9 RETURN 1000000 ENDSWITCH RETURN 0 ENDFUNC /// PURPOSE: /// Initialise the leaderboard data PROC IAP_INITIALISE_LEADERBOARD(INT &iInitials[ciCASINO_ARCADE_LEADERBOARD_POSITIONS], INT &iScores[ciCASINO_ARCADE_LEADERBOARD_POSITIONS]) INT i FOR i = 0 TO ciCASINO_ARCADE_LEADERBOARD_POSITIONS - 1 IF iScores[i] <= 0 //First time - Initialise sIAPData.sLeaderboard[i].iScore = IAP_GET_DEFAULT_SCORE_FOR_POSITION(i) sIAPData.sLeaderboard[i].iInitials = IAP_GET_DEFAULT_INITIALS_FOR_POSITION(i) BROADCAST_CASINO_ARCADE_UPDATE_LEADERBOARD_EVENT(GET_OWNER_OF_SIMPLE_INTERIOR_PLAYER_IS_IN(PLAYER_ID()), CASINO_ARCADE_GAME_INVADE_PERSUADE, i, sIAPData.sLeaderboard[i].iInitials, sIAPData.sLeaderboard[i].iScore) ELSE sIAPData.sLeaderboard[i].iScore = iScores[i] sIAPData.sLeaderboard[i].iInitials = iInitials[i] ENDIF ENDFOR sIAPData.bLeaderboardRecieved = TRUE ENDPROC PROC IAP_QUICK_SORT_LEADERBOARD(IAP_LEADERBOARD_STRUCT &sArray[], INT iLeft, INT iRight) INT i, j INT p = sArray[((iLeft + iRight) / 2)].iScore IAP_LEADERBOARD_STRUCT q i = iLeft j = iRight WHILE (i <= j) WHILE ((sArray[i].iScore > p) AND (i < iRight)) i++ ENDWHILE WHILE ((p > sArray[j].iScore) AND (j > iLeft)) j-- ENDWHILE IF (i <= j) q.iInitials = sArray[i].iInitials q.bPlayer = sArray[i].bPlayer q.iScore = sArray[i].iScore sArray[i].iInitials = sArray[j].iInitials sArray[i].bPlayer = sArray[j].bPlayer sArray[i].iScore = sArray[j].iScore sArray[j].iInitials = q.iInitials sArray[j].bPlayer = q.bPlayer sArray[j].iScore = q.iScore i++ j-- ENDIF ENDWHILE IF (i < iRight) IAP_QUICK_SORT_LEADERBOARD(sArray, i, iRight) ENDIF IF (iLeft < j) IAP_QUICK_SORT_LEADERBOARD(sArray, iLeft, j) ENDIF ENDPROC /// PURPOSE: /// Sorts the leaderboard once players' final scores are set PROC IAP_SORT_LEADERBOARD() IAP_LEADERBOARD_STRUCT sTempArray[ciCASINO_ARCADE_LEADERBOARD_POSITIONS + 1] INT i FOR i = 0 TO ciCASINO_ARCADE_LEADERBOARD_POSITIONS - 1 sTempArray[i].iInitials = sIAPData.sLeaderboard[i].iInitials sTempArray[i].bPlayer = FALSE sTempArray[i].iScore = sIAPData.sLeaderboard[i].iScore ENDFOR IF !sIAPData.bCheated sTempArray[ciCASINO_ARCADE_LEADERBOARD_POSITIONS].bPlayer = TRUE sTempArray[ciCASINO_ARCADE_LEADERBOARD_POSITIONS].iScore = IAP_GET_CURRENT_SCORE() sTempArray[ciCASINO_ARCADE_LEADERBOARD_POSITIONS].iInitials = 0 ENDIF IAP_QUICK_SORT_LEADERBOARD(sTempArray, 0, ciCASINO_ARCADE_LEADERBOARD_POSITIONS) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SORT_LEADERBOARD - Sorting") FOR i = 0 TO ciCASINO_ARCADE_LEADERBOARD_POSITIONS - 1 sIAPData.sLeaderboard[i].iInitials = sTempArray[i].iInitials sIAPData.sLeaderboard[i].bPlayer = sTempArray[i].bPlayer sIAPData.sLeaderboard[i].iScore = sTempArray[i].iScore BROADCAST_CASINO_ARCADE_UPDATE_LEADERBOARD_EVENT(GET_OWNER_OF_SIMPLE_INTERIOR_PLAYER_IS_IN(PLAYER_ID()), CASINO_ARCADE_GAME_INVADE_PERSUADE, i, sIAPData.sLeaderboard[i].iInitials, sIAPData.sLeaderboard[i].iScore) ENDFOR ENDPROC PROC IAP_PROCESS_LEADERBOARD_ENTRY() IF IAP_GET_PLAYER_LEADERBOARD_POSITION() >= ciCASINO_ARCADE_LEADERBOARD_POSITIONS EXIT ENDIF INT iUnpackedInitials[ciARCADE_CABINET_LEADERBOARD_INITIALS] IF SC_PROFANITY_GET_CHECK_IS_VALID(sIAPData.iLbdInitialProfanityToken) IF SC_PROFANITY_GET_CHECK_IS_PENDING(sIAPData.iLbdInitialProfanityToken) EXIT ENDIF IF SC_PROFANITY_GET_STRING_PASSED(sIAPData.iLbdInitialProfanityToken) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PROCESS_LEADERBOARD_ENTRY - Profanity: Initials OK") sIAPData.sLeaderboard[IAP_GET_PLAYER_LEADERBOARD_POSITION()].iInitials = sIAPData.iInitials BROADCAST_CASINO_ARCADE_UPDATE_LEADERBOARD_EVENT(GET_OWNER_OF_SIMPLE_INTERIOR_PLAYER_IS_IN(PLAYER_ID()), CASINO_ARCADE_GAME_INVADE_PERSUADE, IAP_GET_PLAYER_LEADERBOARD_POSITION(), sIAPData.sLeaderboard[IAP_GET_PLAYER_LEADERBOARD_POSITION()].iInitials, sIAPData.sLeaderboard[IAP_GET_PLAYER_LEADERBOARD_POSITION()].iScore) sIAPData.iLbdInitialProfanityToken = 0 ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PROCESS_LEADERBOARD_ENTRY - Profanity: Initials BAD") IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Change_Letter") sIAPData.iCurrentInitial = 0 sIAPData.iInitials = 0 sIAPData.iLbdInitialProfanityToken = 0 ENDIF EXIT ENDIF IF sIAPData.iCurrentInitial >= ciARCADE_CABINET_LEADERBOARD_INITIALS - 1 EXIT ENDIF CONTROL_ACTION CA_InitialUp = INPUT_SCRIPT_RB CONTROL_ACTION CA_InitialDown = INPUT_SCRIPT_LB CONTROL_ACTION CA_InitialAccept = INPUT_FRONTEND_RDOWN CONTROL_ACTION CA_InitialBack = INPUT_FRONTEND_RRIGHT IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) CA_InitialAccept = INPUT_CURSOR_ACCEPT CA_InitialBack = INPUT_CURSOR_CANCEL CA_InitialUp = INPUT_FRONTEND_UP CA_InitialDown = INPUT_FRONTEND_DOWN ENDIF IF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_InitialAccept) sIAPData.iCurrentInitial ++ IF sIAPData.iCurrentInitial >= ciARCADE_CABINET_LEADERBOARD_INITIALS - 1 sIAPData.iCurrentInitial = ciARCADE_CABINET_LEADERBOARD_INITIALS - 1 ARCADE_UNPACK_LEADERBOARD_INITIALS(sIAPData.iInitials, iUnpackedInitials) TEXT_LABEL_3 tl3Initials = ARCADE_GET_CHAR_FROM_INT(iUnpackedInitials[0]) tl3Initials += ARCADE_GET_CHAR_FROM_INT(iUnpackedInitials[1]) tl3Initials += ARCADE_GET_CHAR_FROM_INT(iUnpackedInitials[2]) IF SC_PROFANITY_CHECK_STRING(tl3Initials, sIAPData.iLbdInitialProfanityToken) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PROCESS_LEADERBOARD_ENTRY - Profanity: Starting check") IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Entered_Score") ENDIF ENDIF EXIT ENDIF IF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_InitialBack) IF sIAPData.iCurrentInitial > 0 sIAPData.iCurrentInitial -- ENDIF EXIT ENDIF INT iDelta = 0 IF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_InitialUp) iDelta = 1 ELIF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_InitialDown) iDelta = -1 ENDIF IF iDelta = 0 EXIT ENDIF IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Change_Letter") ARCADE_UNPACK_LEADERBOARD_INITIALS(sIAPData.iInitials, iUnpackedInitials) iUnpackedInitials[sIAPData.iCurrentInitial] += iDelta IF iUnpackedInitials[sIAPData.iCurrentInitial] >= ciARCADE_CABINET_LEADERBOARD_INITIALS_MAX iUnpackedInitials[sIAPData.iCurrentInitial] = 0 ELIF iUnpackedInitials[sIAPData.iCurrentInitial] < 0 iUnpackedInitials[sIAPData.iCurrentInitial] = ciARCADE_CABINET_LEADERBOARD_INITIALS_MAX - 1 ENDIF sIAPData.iInitials = ARCADE_PACK_LEADERBOARD_INITIALS(iUnpackedInitials) ENDPROC // ------------------------------ HELP TEXT ------------------------------ /// PURPOSE: /// Returns whether or not the help text is on display FUNC BOOL IAP_IS_THIS_HELP_BEING_DISPLAYED(STRING stHelp) IF sIAPData.iDisplayedHelpText = GET_HASH_KEY(stHelp) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Prints a help text string and sets iDisplayedHelpText /// PARAMS: /// stHelp - PROC IAP_PRINT_HELP_FOREVER(STRING stHelp) sIAPData.iDisplayedHelpText = GET_HASH_KEY(stHelp) PRINT_HELP_FOREVER(stHelp) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] SCGW_PRINT_HELP_FOREVER - Printing ", stHelp, "(",sIAPData.iDisplayedHelpText,")") ENDPROC /// PURPOSE: /// Prints a help text string with a number and sets iDisplayedHelpText /// PARAMS: /// stHelp - PROC IAP_PRINT_HELP_FOREVER_WITH_NUMBER(STRING stHelp, INT iValue) sIAPData.iDisplayedHelpText = GET_HASH_KEY(stHelp) PRINT_HELP_WITH_NUMBER(stHelp, iValue) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PRINT_HELP_FOREVER_WITH_NUMBER - Printing ", stHelp, "(",sIAPData.iDisplayedHelpText,")") ENDPROC /// PURPOSE: /// Clears help text and resets stCurrentHelpText & iCurrentHelpTextExpiry to stop it being redrawn PROC IAP_CLEAR_HELP_TEXT() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_CLEAR_HELP_TEXT - Clearing") DEBUG_PRINTCALLSTACK() sIAPData.iDisplayedHelpText = -1 IF sIAPData.iCurrentHelpTextExpiry != -HIGHEST_INT sIAPData.iCurrentHelpTextExpiry = -HIGHEST_INT ENDIF IF NOT IS_STRING_NULL_OR_EMPTY(sIAPData.stCurrentHelpText) sIAPData.stCurrentHelpText = ARCADE_GET_NULL_STRING() ENDIF IF IS_HELP_MESSAGE_BEING_DISPLAYED() CLEAR_HELP() ENDIF ENDPROC /// PURPOSE: /// Draws start/quit helptext on the title screen PROC IAP_PROCESS_TITLE_SCREEN_HELP_TEXT() SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHOWING_HELP_TEXT) TEXT_LABEL_15 stHelp = "IAP_H_TITLE" IF IS_PLAYSTATION_PLATFORM() stHelp += "_PS4" ELIF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) stHelp += "_PC" ENDIF IF IAP_IS_THIS_HELP_BEING_DISPLAYED(stHelp) EXIT ENDIF IAP_CLEAR_HELP_TEXT() IAP_PRINT_HELP_FOREVER(stHelp) ENDPROC /// PURPOSE: /// Draws the leaderboard help text PROC IAP_PROCESS_LEADERBOARD_HELP_TEXT() SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHOWING_HELP_TEXT) TEXT_LABEL_15 stHelp IF IAP_GET_PLAYER_LEADERBOARD_POSITION() = ciIAP_LBD_DEFAULT_RANK OR sIAPData.iCurrentInitial > ciARCADE_CABINET_LEADERBOARD_INITIALS - 2 stHelp = "IAP_H_LBD0" IF IS_PLAYSTATION_PLATFORM() stHelp += "_PS4" ENDIF ELIF sIAPData.iCurrentInitial = ciARCADE_CABINET_LEADERBOARD_INITIALS - 2 stHelp = "IAP_H_LBD1" ELSE stHelp = "IAP_H_LBD2" ENDIF IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) stHelp += "_PC" ENDIF IF IAP_IS_THIS_HELP_BEING_DISPLAYED(stHelp) EXIT ENDIF IAP_CLEAR_HELP_TEXT() IAP_PRINT_HELP_FOREVER(stHelp) ENDPROC /// PURPOSE: /// Draws help text for spawned objects PROC IAP_PROCESS_OBJECT_HELP_TEXT() IF sIAPData.iCurrentHelpTextExpiry = -HIGHEST_INT EXIT ENDIF IF IS_STRING_NULL_OR_EMPTY(sIAPData.stCurrentHelpText) EXIT ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.iCurrentHelpTextExpiry CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PROCESS_OBJECT_HELP_TEXT - Text: ", sIAPData.stCurrentHelpText, " has expired") IAP_CLEAR_HELP_TEXT() EXIT ENDIF SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHOWING_HELP_TEXT) TEXT_LABEL_15 stHelp = sIAPData.stCurrentHelpText IF sIAPData.iCurrentHelpTextValue = -1 IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) stHelp += "_PC" ENDIF ELSE IF IAP_IS_THIS_HELP_BEING_DISPLAYED(stHelp) EXIT ENDIF IAP_PRINT_HELP_FOREVER_WITH_NUMBER(stHelp, sIAPData.iCurrentHelpTextValue) EXIT ENDIF IF IAP_IS_THIS_HELP_BEING_DISPLAYED(stHelp) EXIT ENDIF IAP_PRINT_HELP_FOREVER(stHelp) ENDPROC /// PURPOSE: /// Triggers help text from a spawned object PROC IAP_TRIGGER_OBJECT_HELP_TEXT(STRING stHelpText, INT iDuration) IAP_CLEAR_HELP_TEXT() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_TRIGGER_OBJECT_HELP_TEXT - Triggering: ", stHelpText, " Duration: ", iDuration) sIAPData.iCurrentHelpTextExpiry = NATIVE_TO_INT(GET_NETWORK_TIME()) + iDuration sIAPData.stCurrentHelpText = stHelpText sIAPData.iCurrentHelpTextValue = -1 ENDPROC /// PURPOSE: /// Triggers help text for completing a challenge PROC IAP_TRIGGER_CHALLENGE_HELP_TEXT(STRING stHelpText, INT iValue, INT iDuration) IAP_CLEAR_HELP_TEXT() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_TRIGGER_CHALLENGE_HELP_TEXT - Triggering: ", stHelpText, " iValue = ", iValue, " Duration: ", iDuration) sIAPData.iCurrentHelpTextExpiry = NATIVE_TO_INT(GET_NETWORK_TIME()) + iDuration sIAPData.stCurrentHelpText = stHelpText sIAPData.iCurrentHelpTextValue = iValue ENDPROC /// PURPOSE: /// Returns whether or not help text is being drawn by the minigame this frame FUNC BOOL IAP_SHOULD_ALLOW_HELP_TEXT_THIS_FRAME() RETURN IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHOWING_HELP_TEXT) ENDFUNC // ------------------------------ CHALLENGES ------------------------------ PROC IAP_TRIGGER_AWARD_TICKERS() IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_KILL_CHALLENGE_UNLOCKED_THIS_GAME) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_TRIGGER_AWARD_TICKERS - Kill Challenge Ticker") SET_REWARD_UNLOCKED(UNLOCKTYPEENUM_TATTOO, "CLO_VWM_U_23_1", "UNLOCK_NAME_SHIRT3","FeedhitTshirt04","MPTshirtAwards3" ,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,TRUE) ENDIF IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_OIL_CHALLENGE_UNLOCKED_THIS_GAME) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_TRIGGER_AWARD_TICKERS - Oil Challenge Ticker") SET_REWARD_UNLOCKED(UNLOCKTYPEENUM_TATTOO, "CLO_VWM_U_23_3", "UNLOCK_NAME_SHIRT3","FeedhitTshirt04","MPTshirtAwards3" ,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,TRUE) ENDIF IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_MOON_DISTANCE_UNLOCKED_THIS_GAME) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_TRIGGER_AWARD_TICKERS - Moon Challenge Ticker") SET_REWARD_UNLOCKED(UNLOCKTYPEENUM_TATTOO, "CLO_VWM_D_1_10", "UNLOCK_NAME_SHIRT3","FeedhitTshirt04","MPTshirtAwards3" ,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,TRUE) ENDIF IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_LIVES_CHALLENGE_UNLOCKED_THIS_GAME) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_TRIGGER_AWARD_TICKERS - Lives Challenge Ticker") SET_REWARD_UNLOCKED(UNLOCKTYPEENUM_TATTOO, "CLO_VWM_U_23_6", "UNLOCK_NAME_SHIRT3","FeedhitTshirt04","MPTshirtAwards3" ,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,TRUE) ENDIF IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_SCORE_CHALLENGE_UNLOCKED_THIS_GAME) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_TRIGGER_AWARD_TICKERS - Score Challenge Ticker") SET_REWARD_UNLOCKED(UNLOCKTYPEENUM_TATTOO, "CLO_VWM_D_1_9", "UNLOCK_NAME_SHIRT3","FeedhitTshirt04","MPTshirtAwards3" ,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,TRUE) ENDIF ENDPROC PROC IAP_CHECK_IF_GOLDEN_TANK_UNLOCKED() IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_GOLDEN_TANK_UNLOCKED) //Already unlocked EXIT ENDIF IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_GOLDEN_TANK_UNLOCKED_THIS_GAME) //Already unlocked but not applied this game EXIT ENDIF IF g_sMPtunables.bVC_IAP_KILL_CHALLENGE_REQUIRED_FOR_GOLD AND NOT IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_KILL_CHALLENGE_COMPLETE) EXIT ENDIF IF g_sMPtunables.bVC_IAP_OIL_CHALLENGE_REQUIRED_FOR_GOLD AND NOT IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_OIL_CHALLENGE_COMPLETE) EXIT ENDIF IF g_sMPtunables.bVC_IAP_MOON_DISTANCE_CHALLENGE_REQUIRED_FOR_GOLD AND NOT IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_MOON_DISTANCE_CHALLENGE_COMPLETE) EXIT ENDIF IF g_sMPtunables.bVC_IAP_LIVES_CHALLENGE_REQUIRED_FOR_GOLD AND NOT IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_LIVES_CHALLENGE_COMPLETE) EXIT ENDIF IF g_sMPtunables.bVC_IAP_SCORE_CHALLENGE_REQUIRED_FOR_GOLD AND NOT IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_SCORE_CHALLENGE_COMPLETE) EXIT ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_CHECK_IF_GOLDEN_TANK_UNLOCKED - Golden Tank Unlock Requirements Met") SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_GOLD_TANK, TRUE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_GOLDEN_TANK_UNLOCKED_THIS_GAME) ENDPROC PROC IAP_UPDATE_KILL_CHALLENGE(#IF IS_DEBUG_BUILD BOOL bForce = FALSE #ENDIF) IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_KILL_CHALLENGE_COMPLETE) EXIT ENDIF IF sIAPData.sScoreTracking.iTotalAnimalsKilled < g_sMPtunables.iVC_IAP_KILL_CHALLENGE_REQUIREMENT #IF IS_DEBUG_BUILD AND NOT bForce #ENDIF EXIT ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_UPDATE_KILL_CHALLENGE - Kill Challenge Complete") SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_0, TRUE) SET_PACKED_STAT_BOOL(PACKED_MP_UNNATURAL_SELECTION, TRUE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_KILL_CHALLENGE_COMPLETE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_KILL_CHALLENGE_UNLOCKED_THIS_GAME) IAP_CHECK_IF_GOLDEN_TANK_UNLOCKED() IAP_TRIGGER_CHALLENGE_HELP_TEXT("IAP_CH_0", g_sMPtunables.iVC_IAP_KILL_CHALLENGE_REQUIREMENT, ciIAP_DEFAULT_HELP_TEXT_TIME) ENDPROC PROC IAP_UPDATE_OIL_CHALLENGE(#IF IS_DEBUG_BUILD BOOL bForce = FALSE #ENDIF) IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_OIL_CHALLENGE_COMPLETE) EXIT ENDIF IF sIAPData.sScoreTracking.iTotalOilCollected < g_sMPtunables.iVC_IAP_OIL_CHALLENGE_REQUIREMENT #IF IS_DEBUG_BUILD AND NOT bForce #ENDIF EXIT ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_UPDATE_OIL_CHALLENGE - Oil Challenge Complete") SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_1, TRUE) SET_PACKED_STAT_BOOL(PACKED_MP_ENDLESS_OIL, TRUE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_OIL_CHALLENGE_COMPLETE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_OIL_CHALLENGE_UNLOCKED_THIS_GAME) IAP_CHECK_IF_GOLDEN_TANK_UNLOCKED() IAP_TRIGGER_CHALLENGE_HELP_TEXT("IAP_CH_1", g_sMPtunables.iVC_IAP_OIL_CHALLENGE_REQUIREMENT, ciIAP_DEFAULT_HELP_TEXT_TIME) ENDPROC PROC IAP_UPDATE_MAX_MOON_DISTANCE(#IF IS_DEBUG_BUILD BOOL bForce = FALSE #ENDIF) IF sIAPData.eCurrentStage != IAP_STAGE_MOON #IF IS_DEBUG_BUILD AND NOT bForce #ENDIF EXIT ENDIF //Distance INT iDistanceTravelled = FLOOR(sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) IF (iDistanceTravelled > sIAPData.iCachedMaxMoonDistance) sIAPData.iCachedMaxMoonDistance = iDistanceTravelled ENDIF //Challenge IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_MOON_DISTANCE_CHALLENGE_COMPLETE) EXIT ENDIF IF iDistanceTravelled < g_sMPtunables.iVC_IAP_MOON_DISTANCE_CHALLENGE_REQUIREMENT #IF IS_DEBUG_BUILD AND NOT bForce #ENDIF EXIT ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_UPDATE_MAX_MOON_DISTANCE - Moon Distance Challenge Complete") SET_PACKED_STAT_BOOL(PACKED_MP_FULL_MOON, TRUE) SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_2, TRUE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_MOON_DISTANCE_CHALLENGE_COMPLETE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_MOON_DISTANCE_UNLOCKED_THIS_GAME) IAP_CHECK_IF_GOLDEN_TANK_UNLOCKED() IAP_TRIGGER_CHALLENGE_HELP_TEXT("IAP_CH_2", g_sMPtunables.iVC_IAP_MOON_DISTANCE_CHALLENGE_REQUIREMENT, ciIAP_DEFAULT_HELP_TEXT_TIME) ENDPROC PROC IAP_UPDATE_LIVES_CHALLENGE(#IF IS_DEBUG_BUILD BOOL bForce = FALSE #ENDIF) IF sIAPData.bCheated #IF IS_DEBUG_BUILD AND NOT bForce #ENDIF EXIT ENDIF IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_LIVES_CHALLENGE_COMPLETE) EXIT ENDIF IF sIAPData.sPlayerTank.iLives < g_sMPtunables.iVC_IAP_LIVES_CHALLENGE_REQUIREMENT #IF IS_DEBUG_BUILD AND NOT bForce #ENDIF EXIT ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_UPDATE_LIVES_CHALLENGE - Lives Challenge Complete") SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_3, TRUE) SET_PACKED_STAT_BOOL(PACKED_MP_LIFE_SAVER, TRUE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_LIVES_CHALLENGE_COMPLETE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_LIVES_CHALLENGE_UNLOCKED_THIS_GAME) IAP_CHECK_IF_GOLDEN_TANK_UNLOCKED() IAP_TRIGGER_CHALLENGE_HELP_TEXT("IAP_CH_3", g_sMPtunables.iVC_IAP_LIVES_CHALLENGE_REQUIREMENT, ciIAP_DEFAULT_HELP_TEXT_TIME) ENDPROC PROC IAP_UPDATE_SCORE_CHALLENGE(#IF IS_DEBUG_BUILD BOOL bForce = FALSE #ENDIF) IF IS_BIT_SET(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_SCORE_CHALLENGE_COMPLETE) EXIT ENDIF IF sIAPData.iScoreToShow < g_sMPtunables.iVC_IAP_SCORE_CHALLENGE_REQUIREMENT #IF IS_DEBUG_BUILD AND NOT bForce #ENDIF EXIT ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_UPDATE_SCORE_CHALLENGE - Score Challenge Complete") SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_4, TRUE) SET_PACKED_STAT_BOOL(PACKED_MP_HE_WHO_CONTROLS_THE_OIL, TRUE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_SCORE_CHALLENGE_COMPLETE) SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_SCORE_CHALLENGE_UNLOCKED_THIS_GAME) IAP_CHECK_IF_GOLDEN_TANK_UNLOCKED() IAP_TRIGGER_CHALLENGE_HELP_TEXT("IAP_CH_4", g_sMPtunables.iVC_IAP_SCORE_CHALLENGE_REQUIREMENT, ciIAP_DEFAULT_HELP_TEXT_TIME) ENDPROC PROC IAP_INITIALISE_CHALLENGE_COMPLETION() IF GET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_GOLD_TANK) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_CHALLENGE_COMPLETION - Golden Tank Unlocked") SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_GOLDEN_TANK_UNLOCKED) ENDIF IF GET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_0) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_CHALLENGE_COMPLETION - Kill Challenge Complete") SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_KILL_CHALLENGE_COMPLETE) ENDIF IF GET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_1) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_CHALLENGE_COMPLETION - Oil Challenge Complete") SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_OIL_CHALLENGE_COMPLETE) ENDIF IF GET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_2) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_CHALLENGE_COMPLETION - Moon Distance Challenge Complete") SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_MOON_DISTANCE_CHALLENGE_COMPLETE) ENDIF IF GET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_3) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_CHALLENGE_COMPLETION - Lives Challenge Complete") SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_LIVES_CHALLENGE_COMPLETE) ENDIF IF GET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_4) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_CHALLENGE_COMPLETION - Score Challenge Complete") SET_BIT(sIAPData.iChallengeBitSet, ciIAP_CHALLENGEBS_SCORE_CHALLENGE_COMPLETE) ENDIF sIAPData.iCachedMaxMoonDistance = GET_MP_INT_CHARACTER_STAT(MP_STAT_IAP_MAX_MOON_DIST) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_CHALLENGE_COMPLETION - Moon Distance = ", sIAPData.iCachedMaxMoonDistance) ENDPROC // ------------------------------ CHEATING ------------------------------ FUNC CONTROL_ACTION IAP_GET_NEXT_CHEAT_INPUT() SWITCH sIAPData.iCheatInputProgress CASE ciIAP_CHEAT_PROGRESS_UP_1 CASE ciIAP_CHEAT_PROGRESS_UP_2 IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) RETURN INPUT_FRONTEND_UP ELSE RETURN INPUT_SCRIPT_PAD_UP ENDIF BREAK CASE ciIAP_CHEAT_PROGRESS_DOWN_1 CASE ciIAP_CHEAT_PROGRESS_DOWN_2 IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) RETURN INPUT_FRONTEND_DOWN ELSE RETURN INPUT_SCRIPT_PAD_DOWN ENDIF BREAK CASE ciIAP_CHEAT_PROGRESS_LEFT_1 CASE ciIAP_CHEAT_PROGRESS_LEFT_2 IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) RETURN INPUT_FRONTEND_LEFT ELSE RETURN INPUT_SCRIPT_PAD_LEFT ENDIF BREAK CASE ciIAP_CHEAT_PROGRESS_RIGHT_1 CASE ciIAP_CHEAT_PROGRESS_RIGHT_2 IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) RETURN INPUT_FRONTEND_RIGHT ELSE RETURN INPUT_SCRIPT_PAD_RIGHT ENDIF BREAK CASE ciIAP_CHEAT_PROGRESS_B IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) RETURN INPUT_CURSOR_CANCEL ELSE RETURN INPUT_SCRIPT_RRIGHT ENDIF BREAK CASE ciIAP_CHEAT_PROGRESS_A IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) RETURN INPUT_CURSOR_ACCEPT ELSE RETURN INPUT_SCRIPT_RDOWN ENDIF BREAK ENDSWITCH RETURN MAX_INPUTS ENDFUNC PROC IAP_PROCESS_CHEATING() IF sIAPData.iCheatInputTime != -HIGHEST_INT AND NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.iCheatInputTime CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PROCESS_CHEATING - Cheat time expired - iCheatInputProgress = ", sIAPData.iCheatInputProgress) sIAPData.iCheatInputTime = -HIGHEST_INT sIAPData.iCheatInputProgress = 0 ENDIF CONTROL_ACTION CA_NextCheat = IAP_GET_NEXT_CHEAT_INPUT() IF CA_NextCheat = MAX_INPUTS EXIT ENDIF IF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_NextCheat) sIAPData.iCheatInputTime = NATIVE_TO_INT(GET_NETWORK_TIME()) + ciIAP_CHEAT_TIMEOUT_DELAY sIAPData.iCheatInputProgress ++ CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PROCESS_CHEATING - iCheatInputProgress = ", sIAPData.iCheatInputProgress) ENDIF IF sIAPData.iCheatInputProgress >= ciIAP_CHEAT_PROGRESS_COMPLETE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PROCESS_CHEATING - CHEAT ACTIVE") sIAPData.bCheated = TRUE sIAPData.sPlayerTank.iLives = ciIAP_STARTING_LIVES_CHEATED IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Retry") sIAPData.iCheatInputTime = -HIGHEST_INT sIAPData.iCheatInputProgress = 0 ENDIF ENDPROC // ------------------------------ NUKE ------------------------------ /// PURPOSE: /// STARTS A NUCLEAR STRIKE PROC IAP_NUKE_SCREEN() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_NUKE_SCREEN - NUCLEAR STRIKE APPROACHING") IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Tank_Weapon_Nuke_Blast", "dlc_vw_am_ip_tank_sounds", INIT_VECTOR_2D(cfSCREEN_CENTER, cfSCREEN_CENTER)) REINIT_NET_TIMER(sIAPData.tdNukeTimer) ENDPROC /// PURPOSE: /// Returns true if the object type is not destroyed by nukes FUNC BOOL IAP_IS_OBJECT_TYPE_NUKE_PROOF(IAP_OBJECT_TYPE eObjectType) IF eObjectType = IAP_OBJECT_TYPE_INDESTRUCTABLE_HAZARD OR eObjectType = IAP_OBJECT_TYPE_PITFALL OR eObjectType = IAP_OBJECT_TYPE_LEDGE OR eObjectType = IAP_OBJECT_TYPE_PICKUP OR eObjectType = IAP_OBJECT_TYPE_OIL RETURN TRUE ENDIF RETURN FALSE ENDFUNC // ------------------------------ FLOATING TEXT ------------------------------ /// PURPOSE: /// Starts flashing floating text showing score at a location on screen PROC IAP_ADD_SCORE_TEXT(INT iScore, VECTOR_2D vPos) sIAPData.sScoreText[sIAPData.iNextScoreTextIndex].iStartTime = NATIVE_TO_INT(GET_NETWORK_TIME()) sIAPData.sScoreText[sIAPData.iNextScoreTextIndex].iScore = iScore sIAPData.sScoreText[sIAPData.iNextScoreTextIndex].vPos = vPos sIAPData.iNextScoreTextIndex++ IF sIAPData.iNextScoreTextIndex >= ciIAP_MAX_SCORE_TEXT sIAPData.iNextScoreTextIndex = 0 ENDIF ENDPROC /// PURPOSE: /// Starts flashing floating text above the player's tank PROC IAP_ADD_ABOVE_PLAYER_TEXT(STRING tl63Text) sIAPData.sPlayerTank.sAbovePlayerText.iStartTime = NATIVE_TO_INT(GET_NETWORK_TIME()) sIAPData.sPlayerTank.sAbovePlayerText.tl63Text = tl63Text ENDPROC PROC IAP_PROCESS_SCORE_TEXT() INT i FOR i = 0 TO ciIAP_MAX_SCORE_TEXT - 1 IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sScoreText[i].iStartTime + ciIAP_SCORE_TEXT_DURATION RELOOP ENDIF IF sIAPData.eCurrentState = IAP_CLIENT_STATE_RUNNING sIAPData.sScoreText[i].vPos.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sScoreText[i].vPos.x, CFIAP_BASE_FOREGROUND_SPEED) ENDIF ENDFOR ENDPROC // ------------------------------ SCORING ------------------------------ /// PURPOSE: /// Adds to the player's score and keeps track of what it was added for /// Triggers floating text if relevant to the scoring type PROC IAP_ADD_SCORE(INT iScoreToAdd, IAP_SCORE_TYPE eScoreType, VECTOR_2D vScorePos) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_ADD_SCORE - iScoreToAdd: ", iScoreToAdd, " type: ", IAP_DEBUG_GET_IAP_SCORE_TYPE_AS_STRING(eScoreType)) SWITCH eScoreType CASE IAP_SCORE_TYPE_ENEMY sIAPData.sScoreTracking.iScoreFromEnemies += iScoreToAdd sIAPData.sScoreTracking.iEnemiesKilled ++ sIAPData.sScoreTracking.iTotalEnemiesKilled ++ IAP_ADD_SCORE_TEXT(iScoreToAdd, vScorePos) IAP_UPDATE_KILL_CHALLENGE() BREAK CASE IAP_SCORE_TYPE_PICKUP sIAPData.sScoreTracking.iScoreFromPickups += iScoreToAdd BREAK CASE IAP_SCORE_TYPE_OIL sIAPData.sScoreTracking.iScoreFromOil += iScoreToAdd sIAPData.sScoreTracking.iOilCollected ++ sIAPData.sScoreTracking.iTotalOilCollected ++ IAP_ADD_SCORE_TEXT(iScoreToAdd, vScorePos) IAP_UPDATE_OIL_CHALLENGE() BREAK CASE IAP_SCORE_TYPE_DISTANCE sIAPData.sScoreTracking.iScoreFromDistance += iScoreToAdd BREAK CASE IAP_SCORE_TYPE_ARMOUR sIAPData.sScoreTracking.iScoreFromArmour += iScoreToAdd BREAK CASE IAP_SCORE_TYPE_LIVES sIAPData.sScoreTracking.iScoreFromLives += iScoreToAdd BREAK ENDSWITCH ENDPROC /// PURPOSE: /// Calculates the players score and updates iScoreToShow PROC IAP_PROCESS_PLAYER_SCORE() INT iActualScore = IAP_GET_CURRENT_SCORE() INT iDelta = iActualScore - sIAPData.iScoreToShow IF iDelta = 0 EXIT ENDIF INT iFrameTime = ROUND(GET_FRAME_TIME() * 1000) INT iScoreToAdd = iFrameTime * PICK_INT(sIAPData.eCurrentState = IAP_CLIENT_STATE_STAGE_OUTRO, ciIAP_SCORE_PER_MS_OUTRO, ciIAP_SCORE_PER_MS) IF sIAPData.eCurrentState = IAP_CLIENT_STATE_STAGE_OUTRO AND NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SCORE_TALLY_STARTED) //Boost through the massive end oil score iScoreToAdd *= ciIAP_SCORE_END_OIL_SPEED_MULTIPLIER ENDIF IF iScoreToAdd > iDelta iScoreToAdd = iDelta ENDIF sIAPData.iScoreToShow += iScoreToAdd IAP_UPDATE_SCORE_CHALLENGE() ENDPROC /// PURPOSE: /// Returns true when the player's final score has been tallied up /// RETURNS: /// FUNC BOOL IAP_PROCESSED_FINAL_STAGE_SCORE() IF sIAPData.iMiddleTextAnimFrame < IAP_GET_MIDDLE_TEXT_SEQUENCE_FRAMES(IAP_MIDDLE_TEXT_SEQ_STAGE_CLEARED) + ciIAP_STAGE_CLEAR_TALLY_DELAY_FRAMES + ciIAP_STAGE_CLEAR_SCALE_UP_FRAMES RETURN FALSE ENDIF CONTROL_ACTION CA_Skip = INPUT_SCRIPT_RDOWN IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) CA_Skip = INPUT_CURSOR_ACCEPT ENDIF BOOL bSkipPressed = IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_Skip) IF bSkipPressed sIAPData.iScoreToShow = IAP_GET_CURRENT_SCORE() ENDIF IF IAP_GET_CURRENT_SCORE() > sIAPData.iScoreToShow RETURN FALSE ENDIF IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SCORE_TALLY_STARTED) SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SCORE_TALLY_STARTED) ENDIF IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_ARMOUR_SCORE_ADDED) IF sIAPData.iEndArmourToShow = 0 SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_ARMOUR_SCORE_ADDED) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Score_Tick_Total") IAP_STOP_LOOPING_FRONTEND_SOUND(sIAPData.iTallyLoopSoundId) ELSE IF bSkipPressed IAP_ADD_SCORE(ciIAP_SCORE_PER_ARMOUR_REMAINING * sIAPData.iEndArmourToShow, IAP_SCORE_TYPE_LIVES, INIT_VECTOR_2D(-1, -1)) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Score_Tick_Large") sIAPData.iEndArmourToShow = 0 sIAPData.iScoreToShow = IAP_GET_CURRENT_SCORE() RETURN FALSE ENDIF sIAPData.iEndArmourToShow -- IAP_START_LOOPING_FRONTEND_SOUND("Frontend_Score_Tick_Loop_Small", sIAPData.iTallyLoopSoundId) IAP_ADD_SCORE(ciIAP_SCORE_PER_ARMOUR_REMAINING, IAP_SCORE_TYPE_ARMOUR, INIT_VECTOR_2D(-1, -1)) ENDIF RETURN FALSE ENDIF IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_LIVES_SCORE_ADDED) IF sIAPData.iEndLivesToShow <= 0 SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_LIVES_SCORE_ADDED) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Score_Tick_Total") RETURN FALSE ELSE IF bSkipPressed IAP_ADD_SCORE(ciIAP_SCORE_PER_LIFE_REMAINING * sIAPData.iEndLivesToShow, IAP_SCORE_TYPE_LIVES, INIT_VECTOR_2D(-1, -1)) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Score_Tick_Large") sIAPData.iEndLivesToShow = 0 sIAPData.iScoreToShow = IAP_GET_CURRENT_SCORE() RETURN FALSE ENDIF sIAPData.iEndLivesToShow -- IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Score_Tick_Large") IAP_ADD_SCORE(ciIAP_SCORE_PER_LIFE_REMAINING, IAP_SCORE_TYPE_LIVES, INIT_VECTOR_2D(-1, -1)) ENDIF RETURN FALSE ENDIF IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_DISTANCE_SCORE_ADDED) IF sIAPData.iEndDistanceToShow = 0 SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_DISTANCE_SCORE_ADDED) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Score_Tick_Total") IAP_STOP_LOOPING_FRONTEND_SOUND(sIAPData.iTallyLoopSoundId) ELSE IF bSkipPressed IAP_ADD_SCORE(ROUND(cfIAP_DISTANCE_CONVERSION * cfIAP_DISTANCE_SCORE_MOD) * sIAPData.iEndDistanceToShow, IAP_SCORE_TYPE_LIVES, INIT_VECTOR_2D(-1, -1)) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Score_Tick_Large") sIAPData.iEndDistanceToShow = 0 sIAPData.iScoreToShow = IAP_GET_CURRENT_SCORE() RETURN FALSE ENDIF sIAPData.iEndDistanceToShow -- IAP_START_LOOPING_FRONTEND_SOUND("Frontend_Score_Tick_Loop_Small", sIAPData.iTallyLoopSoundId) IAP_ADD_SCORE(ROUND(cfIAP_DISTANCE_CONVERSION * cfIAP_DISTANCE_SCORE_MOD), IAP_SCORE_TYPE_DISTANCE, INIT_VECTOR_2D(-1, -1)) ENDIF RETURN FALSE ENDIF RETURN TRUE ENDFUNC // ------------------------------ ANIMATION ------------------------------ /// PURPOSE: /// Updates the values used for animating sprite sequences PROC IAP_UPDATE_ANIM_FRAMES() sIAPData.iFrameTimeCounter15FPS += ROUND(GET_FRAME_TIME() * 1000) sIAPData.iUpdateFrames15FPS = FLOOR(sIAPData.iFrameTimeCounter15FPS / 66.0) sIAPData.iFrameTimeCounter15FPS = sIAPData.iFrameTimeCounter15FPS - ROUND(66.0 * sIAPData.iUpdateFrames15FPS) sIAPData.iFrameTimeCounter30FPS += ROUND(GET_FRAME_TIME() * 1000) sIAPData.iUpdateFrames30FPS = FLOOR(sIAPData.iFrameTimeCounter30FPS / 33.0) sIAPData.iFrameTimeCounter30FPS = sIAPData.iFrameTimeCounter30FPS - ROUND(33.0 * sIAPData.iUpdateFrames30FPS) ENDPROC // ------------------------------ ASSET LOADING ------------------------------ FUNC BOOL IAP_HAVE_ALL_ASSETS_LOADED() IF NOT ARCADE_GAMES_POSTFX_REQUESTING_ASSETS() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_ALL_ASSETS_LOADED - Loading PostFX") RETURN FALSE ENDIF //Texture Dictionaries REQUEST_STREAMED_TEXTURE_DICT(IAP_GET_PLAYER_TEXTURE_DICT()) IF NOT HAS_STREAMED_TEXTURE_DICT_LOADED(IAP_GET_PLAYER_TEXTURE_DICT()) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_ALL_ASSETS_LOADED - Loading ", IAP_GET_PLAYER_TEXTURE_DICT()) RETURN FALSE ENDIF REQUEST_STREAMED_TEXTURE_DICT("MPInvPersHud") IF NOT HAS_STREAMED_TEXTURE_DICT_LOADED("MPInvPersHud") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_ALL_ASSETS_LOADED - Loading MPInvPersHud") RETURN FALSE ENDIF REQUEST_STREAMED_TEXTURE_DICT("MPInvPersMessages") IF NOT HAS_STREAMED_TEXTURE_DICT_LOADED("MPInvPersMessages") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_ALL_ASSETS_LOADED - Loading MPInvPersMessages") RETURN FALSE ENDIF REQUEST_STREAMED_TEXTURE_DICT("MPInvPersMessages2") IF NOT HAS_STREAMED_TEXTURE_DICT_LOADED("MPInvPersMessages2") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_ALL_ASSETS_LOADED - Loading MPInvPersMessages2") RETURN FALSE ENDIF REQUEST_STREAMED_TEXTURE_DICT("MpInvPersCommon") IF NOT HAS_STREAMED_TEXTURE_DICT_LOADED("MpInvPersCommon") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_ALL_ASSETS_LOADED - Loading MpInvPersCommon") RETURN FALSE ENDIF //Additional Text REQUEST_ADDITIONAL_TEXT("IAP", MINIGAME_TEXT_SLOT) IF NOT HAS_THIS_ADDITIONAL_TEXT_LOADED("IAP", MINIGAME_TEXT_SLOT) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_ALL_ASSETS_LOADED - Loading Additional Text: IAP") RETURN FALSE ENDIF //Audio IF NOT REQUEST_SCRIPT_AUDIO_BANK("DLC_VINEWOOD/DLC_VW_AM_IP") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_ALL_ASSETS_LOADED - Loading Audio Bank DLC_VINEWOOD/DLC_VW_AM_IP") RETURN FALSE ENDIF RETURN TRUE ENDFUNC FUNC BOOL IAP_HAVE_CURRENT_STAGE_ASSETS_LOADED() REQUEST_STREAMED_TEXTURE_DICT(sIAPData.stLoadedStageTextureDictionary) IF NOT HAS_STREAMED_TEXTURE_DICT_LOADED(sIAPData.stLoadedStageTextureDictionary) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_HAVE_CURRENT_STAGE_ASSETS_LOADED - Loading ", sIAPData.stLoadedStageTextureDictionary) RETURN FALSE ENDIF RETURN TRUE ENDFUNC // ------------------------------ BINK MOVIES ------------------------------ /// PURPOSE: /// Sets the bink movie asset for the intro video and starts playback PROC IAP_START_DEGENETRON_INTRO_MOVIE() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_START_DEGENETRON_INTRO_MOVIE - Starting intro movie") sIAPData.binkDegenIntro = SET_BINK_MOVIE("_1992_DegenatronLogo_720_auto") PLAY_BINK_MOVIE(sIAPData.binkDegenIntro) SET_BINK_SHOULD_SKIP(sIAPData.binkDegenIntro, TRUE) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Degenatron_Screen") ENDPROC /// PURPOSE: /// Sets the bink movie asset for the title intro movie and starts playback PROC IAP_START_TITLE_INTRO_MOVIE_LOOP() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_START_TITLE_INTRO_MOVIE_LOOP - Starting title movie") sIAPData.binkIntroLoop = SET_BINK_MOVIE("I&P_intro_16x9") PLAY_BINK_MOVIE(sIAPData.binkIntroLoop) SET_BINK_SHOULD_SKIP(sIAPData.binkIntroLoop, TRUE) ENDPROC /// PURPOSE: /// Processes stopping and restarting the intro music to keep it in sync with the bink PROC IAP_PROCESS_TITLE_INTRO_AUDIO() IF IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STARTED) IF GET_BINK_MOVIE_TIME(sIAPData.binkIntroLoop) >= 95.0 IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_STOP_MUSIC)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] - IAP_PROCESS_TITLE_INTRO_AUDIO - Stopping Intro Music") SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STOPPED) CLEAR_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STARTED) ELSE CLEAR_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STOPPED) ENDIF ENDIF IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STARTED) AND IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STOPPED) IF GET_BINK_MOVIE_TIME(sIAPData.binkIntroLoop) >= 99.0 OR GET_BINK_MOVIE_TIME(sIAPData.binkIntroLoop) <= 1.0 IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_TITLE_SCREEN)) SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STARTED) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] - IAP_PROCESS_TITLE_INTRO_AUDIO - Restarting Intro Music") ENDIF ENDIF ENDPROC /// PURPOSE: /// Stops the title intro video and releases the bink PROC IAP_STOP_TITLE_INTRO_MOVIE_LOOP() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_STOP_TITLE_INTRO_MOVIE_LOOP - Stopping title movie") STOP_BINK_MOVIE(sIAPData.binkIntroLoop) RELEASE_BINK_MOVIE(sIAPData.binkIntroLoop) ENDPROC /// PURPOSE: /// Sets the bink movie asset for the leaderboard movie and starts playback PROC IAP_START_LEADERBOARD_MOVIE_LOOP() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_START_LEADERBOARD_MOVIE_LOOP - Starting leaderboard movie") sIAPData.binkLeaderboard = SET_BINK_MOVIE("I&P_Leaderboard_loop_16x9") PLAY_BINK_MOVIE(sIAPData.binkLeaderboard) ENDPROC /// PURPOSE: /// Stops the leaderboard video and releases the bink PROC IAP_STOP_LEADERBOARD_MOVIE_LOOP() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_STOP_LEADERBOARD_MOVIE_LOOP - stopping leaderboard movie") STOP_BINK_MOVIE(sIAPData.binkLeaderboard) RELEASE_BINK_MOVIE(sIAPData.binkLeaderboard) ENDPROC // ------------------------------ EXPLOSIONS ------------------------------ /// PURPOSE: /// Triggers an explosion of type at a location /// PARAMS: /// vCoords - /// eType - PROC IAP_ADD_EXPLOSION_AT_COORDS(VECTOR_2D vCoords, IAP_EXPLOSION eType = IAP_EXPLOSION_MEDIUM) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_ADD_EXPLOSION_AT_COORDS - Adding explosion: ", IAP_DEBUG_GET_IAP_EXPLOSION_AS_STRING(eType), " at (", vCoords.x, ", ", vCoords.y, ")") sIAPData.sExplosions[sIAPData.iNextExplosionIndex].iAnimFrame = 0 sIAPData.sExplosions[sIAPData.iNextExplosionIndex].vPosition = vCoords sIAPData.sExplosions[sIAPData.iNextExplosionIndex].eExplosionType = eType sIAPData.iNextExplosionIndex ++ IF sIAPData.iNextExplosionIndex >= ciIAP_MAX_EXPLOSIONS sIAPData.iNextExplosionIndex = 0 ENDIF ENDPROC /// PURPOSE: /// Processes the positions of all active explosions PROC IAP_PROCESS_EXPLOSIONS() INT i FOR i = 0 TO ciIAP_MAX_EXPLOSIONS - 1 IF sIAPData.sExplosions[i].iAnimFrame <= -1 RELOOP ENDIF sIAPData.sExplosions[i].vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sExplosions[i].vPosition.x, CFIAP_BASE_FOREGROUND_SPEED) ENDFOR ENDPROC // ------------------------------ PROJECTILE PROCESSING ------------------------------ /// PURPOSE: /// Processes the positions of all player projectiles PROC IAP_PROCESS_PLAYER_PROJECTILES() INT i, j VECTOR_2D v0, v1 RGBA_COLOUR_STRUCT rgba INIT_RGBA_STRUCT(rgba, 255, 255, 255, 255) FOR i = 0 TO ciIAP_MAX_PLAYER_PROJECTILES - 1 IF sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType = IAP_PROJECTILE_TYPE_PLASMA IF sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType].iMaxAnimFrames > 0 sIAPData.sPlayerTank.sProjectileInstances[i].iAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sPlayerTank.sProjectileInstances[i].iAnimFrame >= sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType].iMaxAnimFrames sIAPData.sPlayerTank.sProjectileInstances[i].iAnimFrame = 0 ENDIF ENDIF RELOOP ENDIF IF sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime = -HIGHEST_INT RELOOP ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime + sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType].iSpeed IF sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType = IAP_PROJECTILE_TYPE_HOMING_ROCKET sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime = -HIGHEST_INT IF NOT IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos, INIT_VECTOR_2D(cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE)) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION(IAP_GET_HIT_SOUND_FOR_PLAYER_PROJECTILE(sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType), "dlc_vw_am_ip_tank_sounds", sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos) IAP_ADD_EXPLOSION_AT_COORDS(sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos) ENDIF ENDIF RELOOP ENDIF FLOAT fAlpha = TO_FLOAT(NATIVE_TO_INT(GET_NETWORK_TIME()) - sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime) / sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType].iSpeed sIAPData.sPlayerTank.sProjectileInstances[i].vPreviousFramePos = sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos IF sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType = IAP_PROJECTILE_TYPE_HOMING_ROCKET FOR j = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 IF sIAPData.sObjectInstances[j].eObjectType = IAP_OBJECT_NONE RELOOP ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[j].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[j].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[j].eObjectType)].eObjectType = IAP_OBJECT_TYPE_LEDGE OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[j].eObjectType)].eObjectType = IAP_OBJECT_TYPE_OIL OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[j].eObjectType)].eObjectType = IAP_OBJECT_TYPE_INDESTRUCTABLE_HAZARD RELOOP ENDIF IF sIAPData.sObjectInstances[j].iHealth = 0 RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sObjectInstances[j].vPosition, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[j].eObjectType)].vSpriteScale) RELOOP ENDIF VECTOR_2D vPos = sIAPData.sObjectInstances[j].vPosition IF VECTOR_2D_DIST2(vPos, sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos) < POW(cfIAP_HOMING_ROCKET_RANGE, 2) sIAPData.sPlayerTank.sProjectileInstances[i].vDirection = vPos BREAKLOOP ENDIF ENDFOR v1 = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sPlayerTank.sProjectileInstances[i].vDirection) v0 = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos) sIAPData.sPlayerTank.sProjectileInstances[i].fDesiredRotation = ATAN2(v1.y - v0.y, v1.x - v0.x) sIAPData.sPlayerTank.sProjectileInstances[i].fDesiredRotation += SIN(TO_FLOAT(NATIVE_TO_INT(GET_NETWORK_TIME()) - sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime)) * 30 IF sIAPData.sPlayerTank.sProjectileInstances[i].fRotation > sIAPData.sPlayerTank.sProjectileInstances[i].fDesiredRotation sIAPData.sPlayerTank.sProjectileInstances[i].fRotation = CLAMP(sIAPData.sPlayerTank.sProjectileInstances[i].fRotation -@ cfIAP_HOMING_ROCKET_TURN_SPEED, sIAPData.sPlayerTank.sProjectileInstances[i].fDesiredRotation, sIAPData.sPlayerTank.sProjectileInstances[i].fRotation) ELIF sIAPData.sPlayerTank.sProjectileInstances[i].fDesiredRotation > sIAPData.sPlayerTank.sProjectileInstances[i].fRotation sIAPData.sPlayerTank.sProjectileInstances[i].fRotation = CLAMP(sIAPData.sPlayerTank.sProjectileInstances[i].fRotation +@ cfIAP_HOMING_ROCKET_TURN_SPEED, sIAPData.sPlayerTank.sProjectileInstances[i].fRotation, sIAPData.sPlayerTank.sProjectileInstances[i].fDesiredRotation) ENDIF v0 = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(ROTATE_VECTOR_2D_AROUND_VECTOR_2D(v0, ADD_VECTOR_2D(v0, INIT_VECTOR_2D(cfBASE_SCREEN_WIDTH,0)), sIAPData.sPlayerTank.sProjectileInstances[i].fRotation)) sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos = IAP_MOVE_TOWARDS_VECTOR(sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos, v0, cfIAP_HOMING_ROCKET_SPEED) ELSE sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos = LERP_VECTOR_2D(sIAPData.sPlayerTank.sProjectileInstances[i].vOrigin, sIAPData.sPlayerTank.sProjectileInstances[i].vDirection, fAlpha) ENDIF IF sIAPData.sPlayerTank.sProjectileInstances[i].vDirection.y >= sIAPData.sPlayerTank.sProjectileInstances[i].vOrigin.y FLOAT fGroundY = IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos.x) IF sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos.y > fGroundY sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime = -HIGHEST_INT IF NOT IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos, INIT_VECTOR_2D(cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE)) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION(IAP_GET_HIT_SOUND_FOR_PLAYER_PROJECTILE(sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType), "dlc_vw_am_ip_tank_sounds", sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos) IAP_ADD_EXPLOSION_AT_COORDS(sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos) ENDIF ENDIF ENDIF IF sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType].iMaxAnimFrames > 0 sIAPData.sPlayerTank.sProjectileInstances[i].iAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sPlayerTank.sProjectileInstances[i].iAnimFrame >= sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType].iMaxAnimFrames sIAPData.sPlayerTank.sProjectileInstances[i].iAnimFrame = 0 ENDIF ENDIF ENDFOR ENDPROC /// PURPOSE: /// Processes the positions of all enemy projectiles PROC IAP_PROCESS_ENEMY_PROJECTILES() INT i FOR i = 0 TO ciIAP_MAX_ENEMY_PROJECTILES - 1 IF sIAPData.sEnemyProjectileInstances[i].iShotTime = -HIGHEST_INT RELOOP ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sEnemyProjectileInstances[i].iShotTime + sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[i].eProjectileType].iSpeed RELOOP ENDIF IF IAP_IS_NUKE_ACTIVE() IAP_ADD_EXPLOSION_AT_COORDS(sIAPData.sEnemyProjectileInstances[i].vThisFramePos) IF sIAPData.sEnemyProjectileInstances[i].eProjectileType = IAP_PROJECTILE_TYPE_FALLING_BARREL IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Jet_Bomb_Barrel_Explode", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[i].vThisFramePos) ELSE IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Blaster_Fire_Hit", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[i].vThisFramePos) ENDIF sIAPData.sEnemyProjectileInstances[i].iShotTime = -HIGHEST_INT ENDIF IF sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[i].eProjectileType].iMaxAnimFrames > 0 sIAPData.sEnemyProjectileInstances[i].iAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sEnemyProjectileInstances[i].iAnimFrame >= sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[i].eProjectileType].iMaxAnimFrames sIAPData.sEnemyProjectileInstances[i].iAnimFrame = 0 ENDIF ENDIF FLOAT fAlpha = TO_FLOAT(NATIVE_TO_INT(GET_NETWORK_TIME()) - sIAPData.sEnemyProjectileInstances[i].iShotTime) / sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[i].eProjectileType].iSpeed sIAPData.sEnemyProjectileInstances[i].vPreviousFramePos = sIAPData.sEnemyProjectileInstances[i].vThisFramePos sIAPData.sEnemyProjectileInstances[i].vThisFramePos = LERP_VECTOR_2D(sIAPData.sEnemyProjectileInstances[i].vOrigin, sIAPData.sEnemyProjectileInstances[i].vDirection, fAlpha) IF sIAPData.sEnemyProjectileInstances[i].vDirection.y >= sIAPData.sEnemyProjectileInstances[i].vOrigin.y FLOAT fGroundY = IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sEnemyProjectileInstances[i].vThisFramePos.x) IF sIAPData.sEnemyProjectileInstances[i].vThisFramePos.y > fGroundY IAP_ADD_EXPLOSION_AT_COORDS(sIAPData.sEnemyProjectileInstances[i].vThisFramePos) IF sIAPData.sEnemyProjectileInstances[i].eProjectileType = IAP_PROJECTILE_TYPE_FALLING_BARREL IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Jet_Bomb_Barrel_Explode", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[i].vThisFramePos) ELSE IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Blaster_Fire_Hit", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[i].vThisFramePos) ENDIF sIAPData.sEnemyProjectileInstances[i].iShotTime = -HIGHEST_INT ENDIF ENDIF ENDFOR ENDPROC // ------------------------------ OBJECT PROCESSING ------------------------------ /// PURPOSE: /// Called when an object is no longer on the screen to clean up PROC IAP_CLEAN_UP_OBJECT(INT iObjectIndex) IF sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId > -1 RELEASE_SOUND_ID(sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId) sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId = -1 ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId > -1 STOP_SOUND(sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId) RELEASE_SOUND_ID(sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId) sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId = -1 ENDIF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_NONE ENDPROC FUNC BOOL IAP_IS_OBJECT_AN_ANIMAL(INT iObjectIndex) IF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_ENEMY_CAMEL OR sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_ENEMY_BEAR OR sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_ENEMY_PANDA OR sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_ENEMY_MOOSE RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Updates an object's health by iHealthChange PROC IAP_UPDATE_OBJECT_HEALTH(INT iObjectIndex, INT iHealthChange) IF iHealthChange = 0 EXIT ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iHealth <= 0 //Already dead EXIT ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_UPDATE_OBJECT_HEALTH - Updating Object ", iObjectIndex, "'s health from ", sIAPData.sObjectInstances[iObjectIndex].iHealth, " Change: ", iHealthChange) sIAPData.sObjectInstances[iObjectIndex].iHealth = CLAMP_INT(sIAPData.sObjectInstances[iObjectIndex].iHealth + iHealthChange, 0, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iMaxHealth) sIAPData.sObjectInstances[iObjectIndex].iLastDamagedTime = NATIVE_TO_INT(GET_NETWORK_TIME()) IF sIAPData.sObjectInstances[iObjectIndex].iHealth > 0 EXIT ENDIF //Object is dead IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iScoreValue > 0 IAP_ADD_SCORE(sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iScoreValue, IAP_SCORE_TYPE_ENEMY, sIAPData.sObjectInstances[iObjectIndex].vPosition) IF IAP_IS_OBJECT_AN_ANIMAL(iObjectIndex) sIAPData.sScoreTracking.iTotalAnimalsKilled ++ ENDIF ENDIF IF IAP_DOES_OBJECT_HAVE_DEATH_SOUND(iObjectIndex) AND sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId != -1 IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_OBJECT(IAP_GET_OBJECT_DEATH_SOUND(iObjectIndex), IAP_GET_SOUND_SET_FOR_OBJECT(iObjectIndex), iObjectIndex) ENDIF ENDPROC /// PURPOSE: /// Processes collecting oil drums by passing them PROC IAP_PROCESS_OIL_DRUM(INT iObjectIndex) IF sIAPData.sObjectInstances[iObjectIndex].iLastDamagedTime != -HIGHEST_INT //Raise the flag sIAPData.sObjectInstances[iObjectIndex].vDesiredPosition.y = sIAPData.sObjectInstances[iObjectIndex].vDesiredPosition.y +@ cfIAP_FLAG_MAX_Y_SPEED IF sIAPData.sObjectInstances[iObjectIndex].vDesiredPosition.y > cfIAP_FLAG_MAX_Y_OFFSET sIAPData.sObjectInstances[iObjectIndex].vDesiredPosition.y = cfIAP_FLAG_MAX_Y_OFFSET ENDIF EXIT ENDIF IF sIAPData.sObjectInstances[iObjectIndex].vPosition.x < sIAPData.sPlayerTank.vPosition.x sIAPData.sObjectInstances[iObjectIndex].iLastDamagedTime = NATIVE_TO_INT(GET_NETWORK_TIME()) sIAPData.sObjectInstances[iObjectIndex].vDesiredPosition.y = 0 IAP_ADD_SCORE(sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iScoreValue, IAP_SCORE_TYPE_OIL, sIAPData.sObjectInstances[iObjectIndex].vPosition) IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_OIL_DRUM_NO_SFX) = 0 IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_OBJECT("Tank_Raise_Flag", "dlc_vw_am_ip_tank_sounds", iObjectIndex) ENDIF IF sIAPData.eCurrentState = IAP_CLIENT_STATE_RUNNING AND sIAPData.iNextOilToSpawn < 1 IF sIAPData.fStageSpeedMod < cfIAP_MAX_STAGE_SPEED_MOD IAP_ADD_ABOVE_PLAYER_TEXT("IAP_SPD_UP") ENDIF IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Player_Oil_Collect") sIAPData.fStageSpeedMod += IAP_GET_SPEED_BOOST_FROM_OIL_TYPE(sIAPData.sObjectInstances[iObjectIndex].eObjectType) IF sIAPData.fStageSpeedMod > cfIAP_MAX_STAGE_SPEED_MOD sIAPData.fStageSpeedMod = cfIAP_MAX_STAGE_SPEED_MOD ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Returns the distance the next procedurally generated object will spawn FUNC FLOAT GET_IAP_NEXT_SPAWN_OFFSET() RETURN GET_RANDOM_FLOAT_IN_RANGE(sIAPData.sRandomGeneration.fMinDistBetweenSpawns, sIAPData.sRandomGeneration.fMaxDistBetweenSpawns) ENDFUNC /// PURPOSE: /// Returns the next procedurally generated object type to spawn FUNC IAP_OBJECT GET_IAP_OBJECT_TO_SPAWN() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] GET_IAP_OBJECT_TO_SPAWN - Finding object to spawn at ", sIAPData.sRandomGeneration.fNextSpawnDistance) IAP_OBJECT eValidTypes[COUNT_OF(IAP_OBJECT)] INT i, j, iValidCount, iInvalidGroupBS FOR i = 0 TO ciIAP_RANDOM_GENERATION_OBJECT_GROUP_MAX - 1 FOR j = 0 TO ciIAP_RANDOM_GENERATION_OBJECT_GROUP_MAX - 1 //CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] GET_IAP_OBJECT_TO_SPAWN - Checking Groups: ", i, ", ", j, "Min Dist = ", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[i][j]) IF sIAPData.sRandomGeneration.fNextSpawnDistance - sIAPData.sRandomGeneration.fLastSpawnedFromGroup[i] < sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[i][j] //CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] GET_IAP_OBJECT_TO_SPAWN - Spawn group INVALID - Dist = ", sIAPData.sRandomGeneration.fNextSpawnDistance - sIAPData.sRandomGeneration.fLastSpawnedFromGroup[i]) SET_BIT(iInvalidGroupBS, j) ENDIF //CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] GET_IAP_OBJECT_TO_SPAWN - Spawn group OK - Dist = ", sIAPData.sRandomGeneration.fNextSpawnDistance - sIAPData.sRandomGeneration.fLastSpawnedFromGroup[i]) ENDFOR ENDFOR FOR i = 0 TO COUNT_OF(IAP_OBJECT) - 1 IF NOT IS_BIT_SET(sIAPData.sObjectData[i].iValidStagesBS, ENUM_TO_INT(sIAPData.eCurrentStage)) RELOOP ENDIF IF NOT IS_BIT_SET(iInvalidGroupBS, sIAPData.sObjectData[i].iRandomGenerationObjectGroup) eValidTypes[iValidCount] = INT_TO_ENUM(IAP_OBJECT, i) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bRandomPickupsOnly IF sIAPData.sObjectData[ENUM_TO_INT(eValidTypes[iValidCount])].eObjectType = IAP_OBJECT_TYPE_PICKUP eValidTypes[iValidCount] = IAP_OBJECT_PICKUP_RANDOM ENDIF ENDIF #ENDIF iValidCount++ ENDIF ENDFOR IF iValidCount = 0 sIAPData.sRandomGeneration.fNextSpawnDistance += GET_IAP_NEXT_SPAWN_OFFSET() RETURN IAP_OBJECT_NONE ENDIF IAP_OBJECT eTypeToReturn = INT_TO_ENUM(IAP_OBJECT, eValidTypes[GET_RANDOM_INT_IN_RANGE(0, iValidCount)]) sIAPData.sRandomGeneration.fLastSpawnedFromGroup[sIAPData.sObjectData[ENUM_TO_INT(eTypeToReturn)].iRandomGenerationObjectGroup] = sIAPData.sRandomGeneration.fNextSpawnDistance #IF IS_DEBUG_BUILD sIAPData.sRandomGeneration.iNumSpawnedFromGroup[sIAPData.sObjectData[ENUM_TO_INT(eTypeToReturn)].iRandomGenerationObjectGroup] ++ #ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] GET_IAP_OBJECT_TO_SPAWN - Spawning Object: ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(eTypeToReturn)) RETURN eTypeToReturn ENDFUNC /// PURPOSE: /// Converts an object to another if if is not valid to spawn now PROC IAP_CONVERT_OBJECT_IF_NOT_VALID_NOW(IAP_OBJECT &eObjectType) IF eObjectType = IAP_OBJECT_PICKUP_TRIPLE AND sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_DEFAULT eObjectType = IAP_OBJECT_PICKUP_SCORE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_CONVERT_OBJECT_IF_NOT_VALID_NOW - Converting to score pickup") ENDIF ENDPROC /// PURPOSE: /// Sets up the object instance with the values for the object type spawning PROC IAP_INITIALISE_SPAWNED_OBJECT(INT iObjectIndex, IAP_OBJECT eObjectType, INT iFlags, FLOAT fSpawnDistance) sIAPData.sObjectInstances[iObjectIndex].eObjectType = eObjectType sIAPData.sObjectInstances[iObjectIndex].iFlags = iFlags sIAPData.sObjectInstances[iObjectIndex].iAnimFrame = 0 IF sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId > -1 STOP_SOUND(sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId) RELEASE_SOUND_ID(sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId) sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId = -1 ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId > -1 STOP_SOUND(sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId) RELEASE_SOUND_ID(sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId) sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId = -1 ENDIF sIAPData.sObjectInstances[iObjectIndex].iLastDamagedTime = -HIGHEST_INT sIAPData.sObjectInstances[iObjectIndex].iHealth = sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].iMaxHealth FLOAT fDistanceOffset = (fSpawnDistance * cfIAP_DISTANCE_CONVERSION) - sIAPData.fDistanceTravelled FLOAT fXOffset = fDistanceOffset * ((cfIAP_BASE_FOREGROUND_SPEED * sIAPData.fStageSpeedMod) / (sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].fBaseScrollSpeed * sIAPData.fStageSpeedMod)) sIAPData.sObjectInstances[iObjectIndex].vPosition = INIT_VECTOR_2D(1.0 - fXOffset, sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].fBaseYOffset) #IF IS_DEBUG_BUILD CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_SPAWNED_OBJECT - Distance between objects: ", sIAPData.fDistanceTravelled - fXOffset - sIAPData.sDebugStruct.fLastObjectSpawned) sIAPData.sDebugStruct.fLastObjectSpawned = sIAPData.fDistanceTravelled - fXOffset #ENDIF //Dont add Y offset to Pitfalls, Ledges, Jets or Drones IF sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType != IAP_OBJECT_TYPE_PITFALL AND sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType != IAP_OBJECT_TYPE_LEDGE AND sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType != IAP_OBJECT_TYPE_JET AND sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType != IAP_OBJECT_TYPE_DRONE sIAPData.sObjectInstances[iObjectIndex].vPosition.y += IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sObjectInstances[iObjectIndex].vPosition.x) ENDIF //Y offset for falling pickups IF sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP FLOAT fYOffset = fDistanceOffset * (cfIAP_PICKUP_FALL_SPEED) sIAPData.sObjectInstances[iObjectIndex].vPosition.y -= (cfIAP_PICKUP_SPAWN_Y - fYOffset) sIAPData.sObjectInstances[iObjectIndex].eState = IAP_OBJECT_STATE_FALLING ENDIF //Pitfall and ledge linked objects IF sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL sIAPData.sParallax.iActiveForegroundSpriteIndexes[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] = ciIAP_PARALLAX_PITFALL sIAPData.sParallax.iLinkedObjectIndexes[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] = iObjectIndex sIAPData.sObjectInstances[iObjectIndex].vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sParallax.fForegroundPosX[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] + ((IAP_GET_CURRENT_PITFALL_SCALE() - sIAPData.sCurrentStageData.vForegroundSpriteScale.x) / 2), -cfIAP_BASE_FOREGROUND_SPEED) ELIF sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType = IAP_OBJECT_TYPE_LEDGE sIAPData.sParallax.iActiveForegroundSpriteIndexes[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] = ciIAP_PARALLAX_RAISED_LEDGE sIAPData.sParallax.iLinkedObjectIndexes[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] = iObjectIndex sIAPData.sObjectInstances[iObjectIndex].vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sParallax.fForegroundPosX[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] + ((IAP_GET_CURRENT_PITFALL_SCALE() - sIAPData.sCurrentStageData.vForegroundSpriteScale.x) / 2), -cfIAP_BASE_FOREGROUND_SPEED) ENDIF //Oil drums IF sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType = IAP_OBJECT_TYPE_OIL IF (iFlags & ciIAP_OBJECT_FLAG_OIL_DRUM_RAISED) != 0 sIAPData.sObjectInstances[iObjectIndex].vPosition.y -= sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].vSpriteScale.y / 2 ENDIF ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_SPAWNED_OBJECT - fDistanceOffset: ", fDistanceOffset, " fXOffset: ", fXOffset, " start pos: ", sIAPData.sObjectInstances[sIAPData.iNextObjectIndex].vPosition.x, ", ", sIAPData.sObjectInstances[sIAPData.iNextObjectIndex].vPosition.y) //Offset time by the distance offset sIAPData.sObjectInstances[iObjectIndex].iSpawnTime = NATIVE_TO_INT(GET_NETWORK_TIME_ACCURATE()) ENDPROC /// PURPOSE: /// Spawns the next object /// Returns true is successful FUNC BOOL IAP_SPAWN_OBJECT(IAP_OBJECT eObjectType, FLOAT fSpawnDistance) IF sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL OR sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType = IAP_OBJECT_TYPE_LEDGE IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] = ciIAP_PARALLAX_PITFALL OR sIAPData.sParallax.iActiveForegroundSpriteIndexes[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] = ciIAP_PARALLAX_RAISED_LEDGE OR NOT IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(INIT_VECTOR_2D(sIAPData.sParallax.fForegroundPosX[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] + ((IAP_GET_CURRENT_PITFALL_SCALE() - sIAPData.sCurrentStageData.vForegroundSpriteScale.x) / 2), sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].fBaseYOffset), sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].vSpriteScale) //WAIT RETURN FALSE ELSE IF sIAPData.sRandomGeneration.fNextSpawnDistance > -1 AND eObjectType != IAP_OBJECT_CRASHED_TANK sIAPData.sRandomGeneration.fNextSpawnDistance += ((sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) - sIAPData.sRandomGeneration.fNextSpawnDistance) + ((sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].vSpriteScale.x / 2) / cfIAP_DISTANCE_CONVERSION) + ((1.0 - sIAPData.sParallax.fForegroundPosX[sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1] + ((IAP_GET_CURRENT_PITFALL_SCALE() - sIAPData.sCurrentStageData.vForegroundSpriteScale.x) / 2)) / -cfIAP_DISTANCE_CONVERSION) sIAPData.sRandomGeneration.fLastSpawnedFromGroup[sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].iRandomGenerationObjectGroup] = sIAPData.sRandomGeneration.fNextSpawnDistance ENDIF ENDIF ENDIF IF NOT IAP_IS_NUKE_ACTIVE() OR IAP_IS_OBJECT_TYPE_NUKE_PROOF(sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].eObjectType) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SPAWN_OBJECT - Spawning object type: ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(eObjectType), " at distance: ", fSpawnDistance) IAP_CONVERT_OBJECT_IF_NOT_VALID_NOW(eObjectType) #IF IS_DEBUG_BUILD IF sIAPData.sObjectInstances[sIAPData.iNextObjectIndex].eObjectType != IAP_OBJECT_NONE AND sIAPData.eCurrentStage != IAP_STAGE_MOON ASSERTLN("[IAP] [JS] IAP_SPAWN_OBJECT - OBJECT ", sIAPData.iNextObjectToSpawn, " IS SPAWNING AT AN ACTIVE OBJECT'S INDEX") ENDIF #ENDIF INT iFlags = 0 IF sIAPData.sCurrentStageData.sObjectSpawningData[sIAPData.iNextObjectToSpawn].eObject != IAP_OBJECT_START_RANDOM_GENERATION iFlags = sIAPData.sCurrentStageData.sObjectSpawningData[sIAPData.iNextObjectToSpawn].iFlags ENDIF IAP_INITIALISE_SPAWNED_OBJECT(sIAPData.iNextObjectIndex, eObjectType, iFlags, fSpawnDistance) sIAPData.iNextObjectIndex++ IF sIAPData.iNextObjectIndex >= ciIAP_MAX_ACTIVE_OBJECTS sIAPData.iNextObjectIndex = 0 ENDIF #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SPAWN_OBJECT - Skipping due to nuke ", sIAPData.iNextObjectToSpawn) #ENDIF ENDIF IF NOT IS_LONG_BIT_SET(sIAPData.iSpawnedObjectBitSet, ENUM_TO_INT(eObjectType)) SET_LONG_BIT(sIAPData.iSpawnedObjectBitSet, ENUM_TO_INT(eObjectType)) IF NOT IS_STRING_NULL_OR_EMPTY(sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].stHelpText) IAP_TRIGGER_OBJECT_HELP_TEXT(sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].stHelpText, sIAPData.sObjectData[ENUM_TO_INT(eObjectType)].iHelpTextTime) ENDIF ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// Processes generating and spawning objects for procedurally generated stages PROC IAP_PROCESS_RANDOM_STAGE_OBJECT_SPAWNING() IF sIAPData.sCurrentStageData.fStageDistance != ciIAP_STAGE_INFINITE_LENGTH AND (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) >= sIAPData.sCurrentStageData.fStageDistance - 12.5 //Leave room for the barrels sIAPData.iNextObjectToSpawn++ EXIT ENDIF FLOAT fAlpha = (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION)/cfIAP_RANDOM_DISTANCE_TO_END_SPAWN_DIST IF fAlpha > 1.0 fAlpha = 1.0 ENDIF sIAPData.sRandomGeneration.fMinDistBetweenSpawns = INTERP_FLOAT(cfIAP_RANDOM_MIN_DIST_BETWEEN_SPAWNS_START, cfIAP_RANDOM_MIN_DIST_BETWEEN_SPAWNS_END, fAlpha, INTERPTYPE_DECEL) sIAPData.sRandomGeneration.fMaxDistBetweenSpawns = INTERP_FLOAT(cfIAP_RANDOM_MAX_DIST_BETWEEN_SPAWNS_START, cfIAP_RANDOM_MAX_DIST_BETWEEN_SPAWNS_END, fAlpha, INTERPTYPE_DECEL) IF (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) > sIAPData.sRandomGeneration.fNextSpawnDistance IAP_OBJECT eObjectType = sIAPData.sRandomGeneration.eNextSpawnType IF eObjectType = IAP_OBJECT_NONE IF sIAPData.sRandomGeneration.fNextSpawnDistance < 0 SET_RANDOM_SEED(sIAPData.sCurrentStageData.iRandomSeed) ELSE SET_RANDOM_SEED(FLOOR(SIN(sIAPData.sRandomGeneration.fNextSpawnDistance)* sIAPData.sRandomGeneration.fNextSpawnDistance)) ENDIF sIAPData.sRandomGeneration.fNextSpawnDistance += GET_IAP_NEXT_SPAWN_OFFSET() sIAPData.sRandomGeneration.eNextSpawnType = GET_IAP_OBJECT_TO_SPAWN() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_PROCESS_RANDOM_STAGE_OBJECT_SPAWNING - Next spawn: object type: ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(sIAPData.sRandomGeneration.eNextSpawnType), " at distance: ", sIAPData.sRandomGeneration.fNextSpawnDistance) EXIT ENDIF IF (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) >= sIAPData.sRandomGeneration.fNextSpawnDistance IF IAP_SPAWN_OBJECT(sIAPData.sRandomGeneration.eNextSpawnType, sIAPData.sRandomGeneration.fNextSpawnDistance) sIAPData.sRandomGeneration.eNextSpawnType = IAP_OBJECT_NONE ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Processes spawning objects PROC IAP_PROCESS_STAGE_OBJECT_SPAWNING() IF sIAPData.eCurrentState != IAP_CLIENT_STATE_RUNNING EXIT ENDIF FLOAT fSpawnDistance IAP_OBJECT eObjectType IF sIAPData.eCurrentStage = IAP_STAGE_MOON AND NOT IS_LONG_BIT_SET(sIAPData.iSpawnedObjectBitSet, ENUM_TO_INT(IAP_OBJECT_CRASHED_TANK)) IF sIAPData.iCachedMaxMoonDistance < 1 SET_LONG_BIT(sIAPData.iSpawnedObjectBitSet, ENUM_TO_INT(IAP_OBJECT_CRASHED_TANK)) ELIF (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) >= sIAPData.iCachedMaxMoonDistance - 1 IAP_SPAWN_OBJECT(IAP_OBJECT_CRASHED_TANK, TO_FLOAT(sIAPData.iCachedMaxMoonDistance)) ENDIF ENDIF IF sIAPData.iNextObjectToSpawn >= ciIAP_MAX_SPAWNING_OBJECTS OR sIAPData.sCurrentStageData.sObjectSpawningData[sIAPData.iNextObjectToSpawn].eObject = IAP_OBJECT_NONE IF sIAPData.sCurrentStageData.fStageDistance = ciIAP_STAGE_INFINITE_LENGTH EXIT ENDIF IF sIAPData.iNextOilToSpawn >= ciIAP_MAX_END_OIL_OBJECTS EXIT ENDIF eObjectType = sIAPData.sCurrentStageData.sEndOilSpawningData[sIAPData.iNextOilToSpawn].eObject fSpawnDistance = sIAPData.sCurrentStageData.fStageDistance - sIAPData.sCurrentStageData.sEndOilSpawningData[sIAPData.iNextOilToSpawn].fSpawnDistance IF (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) >= sIAPData.sCurrentStageData.fStageDistance - 5.0 #IF IS_DEBUG_BUILD IF sIAPData.sObjectInstances[sIAPData.iNextOilIndex].eObjectType != IAP_OBJECT_NONE AND sIAPData.eCurrentStage != IAP_STAGE_MOON ASSERTLN("[IAP] [JS] IAP_PROCESS_STAGE_OBJECT_SPAWNING - OIL ", sIAPData.iNextOilToSpawn, " IS SPAWNING AT AN ACTIVE OBJECT'S INDEX") ENDIF #ENDIF IAP_INITIALISE_SPAWNED_OBJECT(sIAPData.iNextOilIndex, eObjectType, sIAPData.sCurrentStageData.sEndOilSpawningData[sIAPData.iNextOilToSpawn].iFlags, fSpawnDistance) sIAPData.iNextOilToSpawn++ sIAPData.iNextOilIndex++ IF sIAPData.iNextOilIndex >= ciIAP_MAX_ACTIVE_OBJECTS sIAPData.iNextOilIndex = 0 ENDIF ENDIF EXIT ENDIF IF sIAPData.eCurrentState != IAP_CLIENT_STATE_RUNNING EXIT ENDIF IF sIAPData.sCurrentStageData.sObjectSpawningData[sIAPData.iNextObjectToSpawn].eObject = IAP_OBJECT_START_RANDOM_GENERATION IAP_PROCESS_RANDOM_STAGE_OBJECT_SPAWNING() EXIT ENDIF eObjectType = sIAPData.sCurrentStageData.sObjectSpawningData[sIAPData.iNextObjectToSpawn].eObject fSpawnDistance = sIAPData.sCurrentStageData.sObjectSpawningData[sIAPData.iNextObjectToSpawn].fSpawnDistance IF (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) >= fSpawnDistance IF IAP_SPAWN_OBJECT(eObjectType, fSpawnDistance) sIAPData.iNextObjectToSpawn++ ENDIF ENDIF ENDPROC /// PURPOSE: /// Processing crumbling pits breaking when in range of the player PROC PROCESS_CRUMBLING_PITFALL(INT iObjectIndex) IF sIAPData.sObjectInstances[iObjectIndex].iHealth = 0 sIAPData.sObjectInstances[iObjectIndex].iAnimFrame += ROUND(sIAPData.iUpdateFrames15FPS / ciIAP_PITFALL_CRUMBLE_TRIGGER_DISTANCE_MOD) IF sIAPData.sObjectInstances[iObjectIndex].iAnimFrame >= ciIAP_PITFALL_CRUMBLE_ANIM_FRAMES //Fully crumbled sIAPData.sObjectInstances[iObjectIndex].iFlags = (sIAPData.sObjectInstances[iObjectIndex].iFlags & (ciIAP_OBJECT_FLAG_PITFALL_CRUMBLING ^ -1)) sIAPData.sObjectInstances[iObjectIndex].iHealth = 1 ENDIF ELIF sIAPData.sObjectInstances[iObjectIndex].vPosition.x < (sIAPData.sPlayerTank.vPosition.x + (IAP_GET_CURRENT_PITFALL_SCALE())) sIAPData.sObjectInstances[iObjectIndex].iHealth = 0 sIAPData.sObjectInstances[iObjectIndex].iAnimFrame = 0 IF sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId != -1 IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_OBJECT("Enemy_Hazard_Wall_Collapse", "dlc_vw_am_ip_enemy_sounds", iObjectIndex) ENDIF ENDIF ENDPROC /// PURPOSE: /// Processes all spawned objects positions PROC IAP_PROCESS_STAGE_OBJECT_POSITION(INT iObjectIndex) FLOAT fGroundY IF sIAPData.sObjectInstances[iObjectIndex].vPosition.x < cfIAP_FACADE_WIDTH - (sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale.x / 2) IAP_CLEAN_UP_OBJECT(iObjectIndex) EXIT ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId = -1 OR sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId = -1 IF NOT IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sObjectInstances[iObjectIndex].vPosition, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale) sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId = GET_SOUND_ID() sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId = GET_SOUND_ID() IF IAP_DOES_OBJECT_HAVE_SPAWN_SOUND(iObjectIndex) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_OBJECT(IAP_GET_OBJECT_SPAWN_SOUND(iObjectIndex), IAP_GET_SOUND_SET_FOR_OBJECT(iObjectIndex), iObjectIndex) ENDIF ENDIF ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL AND (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PITFALL_CRUMBLING) != 0 PROCESS_CRUMBLING_PITFALL(iObjectIndex) ELSE sIAPData.sObjectInstances[iObjectIndex].iAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sObjectInstances[iObjectIndex].iHealth > 0 SWITCH sIAPData.sObjectInstances[iObjectIndex].eState CASE IAP_OBJECT_STATE_DEFAULT CASE IAP_OBJECT_STATE_FALLING IF sIAPData.sObjectInstances[iObjectIndex].iAnimFrame >= sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iAnimationFrames sIAPData.sObjectInstances[iObjectIndex].iAnimFrame = 0 ENDIF BREAK CASE IAP_OBJECT_STATE_SHOOTING IF sIAPData.sObjectInstances[iObjectIndex].iAnimFrame >= sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iShootingAnimationFrames sIAPData.sObjectInstances[iObjectIndex].iAnimFrame = 0 sIAPData.sObjectInstances[iObjectIndex].eState = IAP_OBJECT_STATE_DEFAULT ENDIF BREAK ENDSWITCH ELSE IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP IF sIAPData.sObjectInstances[iObjectIndex].iAnimFrame > ciIAP_PICKUP_OPEN_FRAMES IAP_CLEAN_UP_OBJECT(iObjectIndex) EXIT ENDIF ELSE IF sIAPData.sObjectInstances[iObjectIndex].iAnimFrame > ciIAP_EXPLOSION_FRAMES IAP_CLEAN_UP_OBJECT(iObjectIndex) EXIT ENDIF ENDIF ENDIF ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_OIL IAP_PROCESS_OIL_DRUM(iObjectIndex) ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_DRONE VECTOR_2D vEndMidpoint FLOAT fDroneSpeed = sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].fBaseScrollSpeed IF NATIVE_TO_INT(GET_NETWORK_TIME()) - sIAPData.sObjectInstances[iObjectIndex].iSpawnTime > ciIAP_DRONE_LIFESPAN OR sIAPData.eCurrentState > IAP_CLIENT_STATE_RUNNING IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_DRONE_BOMB_PLAYER_ON_CLEANUP) != 0 AND sIAPData.eCurrentState = IAP_CLIENT_STATE_RUNNING //Fly straight into the player vEndMidpoint = sIAPData.sPlayerTank.vPosition ELSE vEndMidpoint.x = -1.0 vEndMidpoint.y = 0.0 ENDIF fDroneSpeed *= 1.25 ELSE vEndMidpoint = INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_DRONE_END_OFFSET_X, sIAPData.sPlayerTank.vPosition.y + cfIAP_DRONE_END_OFFSET_Y) IF vEndMidPoint.y > sIAPData.sCurrentStageData.fBaseY + cfIAP_DRONE_END_OFFSET_Y vEndMidPoint.y = sIAPData.sCurrentStageData.fBaseY + cfIAP_DRONE_END_OFFSET_Y ENDIF ENDIF VECTOR_2D vEnd vEnd = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(ADD_VECTOR_2D(vEndMidpoint, INIT_VECTOR_2D(cfIAP_DRONE_END_OFFSET_LENGTH, 0))) vEndMidpoint = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(vEndMidpoint) FLOAT fSinNumber fSinNumber = SIN(((sIAPData.fDistanceTravelled * cfIAP_DRONE_SIN_ANGLE_MOD)) + (iObjectIndex * 100)) FLOAT fAngle fAngle = cfIAP_DRONE_END_POSITION_ANGLE + (fSinNumber * cfIAP_DRONE_END_POSITION_ANGLE_MOD) VECTOR_2D vEndRight vEndRight = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vEndMidpoint, vEnd, 180 + fAngle)) sIAPData.sObjectInstances[iObjectIndex].vDesiredPosition = LERP_VECTOR_2D(ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vEndMidpoint), vEndRight, SIN((sIAPData.fDistanceTravelled * cfIAP_DRONE_SIN_POS_MOD) + (iObjectIndex * 100))) sIAPData.sObjectInstances[iObjectIndex].vPosition = IAP_MOVE_TOWARDS_VECTOR(sIAPData.sObjectInstances[iObjectIndex].vPosition, sIAPData.sObjectInstances[iObjectIndex].vDesiredPosition, fDroneSpeed) IF sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId > -1 IF sIAPData.sObjectInstances[iObjectIndex].iHealth > 0 IAP_PLAY_LOOPING_SOUND_FROM_OBJECT("Enemy_Drone_Loop", iObjectIndex) ENDIF ENDIF EXIT ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP AND sIAPData.sObjectInstances[iObjectIndex].eState = IAP_OBJECT_STATE_FALLING fGroundY = IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sObjectInstances[iObjectIndex].vPosition.x) IF sIAPData.sObjectInstances[iObjectIndex].vPosition.y < sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].fBaseYOffset + fGroundY sIAPData.sObjectInstances[iObjectIndex].vPosition.y = sIAPData.sObjectInstances[iObjectIndex].vPosition.y +@ cfIAP_PICKUP_FALL_SPEED IF sIAPData.sObjectInstances[iObjectIndex].vPosition.y >= sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].fBaseYOffset + fGroundY sIAPData.sObjectInstances[iObjectIndex].vPosition.y = sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].fBaseYOffset + fGroundY sIAPData.sObjectInstances[iObjectIndex].eState = IAP_OBJECT_STATE_DEFAULT IF sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId != -1 IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_OBJECT("Powerup_Crate_Land", IAP_GET_SOUND_SET_FOR_OBJECT(iObjectIndex),iObjectIndex) ENDIF ENDIF ENDIF ENDIF IF sIAPData.eCurrentState != IAP_CLIENT_STATE_RUNNING AND sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType != IAP_OBJECT_TYPE_JET EXIT ENDIF IF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_CRASHED_TANK fGroundY = IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sObjectInstances[iObjectIndex].vPosition.x - (sIAPData.sObjectData[IAP_OBJECT_CRASHED_TANK].vSpriteScale.x / 2)) FLOAT fGroundY2 =IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sObjectInstances[iObjectIndex].vPosition.x + (sIAPData.sObjectData[IAP_OBJECT_CRASHED_TANK].vSpriteScale.x / 2)) IF fGroundY > sIAPData.sCurrentStageData.fBaseY OR NOT IS_FLOAT_IN_RANGE(fGroundY, fGroundY2 - cfARCADE_MINIGAME_FLOAT_TOLERANCE, fGroundY2 + cfARCADE_MINIGAME_FLOAT_TOLERANCE) OR NOT IS_FLOAT_IN_RANGE(fGroundY + sIAPData.sObjectData[IAP_OBJECT_CRASHED_TANK].fBaseYOffset, sIAPData.sObjectInstances[iObjectIndex].vPosition.y - cfARCADE_MINIGAME_FLOAT_TOLERANCE, sIAPData.sObjectInstances[iObjectIndex].vPosition.y + cfARCADE_MINIGAME_FLOAT_TOLERANCE) //Move backwards until safe sIAPData.sObjectInstances[iObjectIndex].vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sObjectInstances[iObjectIndex].vPosition.x, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].fBaseScrollSpeed) EXIT ENDIF ENDIF sIAPData.sObjectInstances[iObjectIndex].vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sObjectInstances[iObjectIndex].vPosition.x, -sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].fBaseScrollSpeed) IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_JET IF sIAPData.sObjectInstances[iObjectIndex].iHealth > 0 IF sIAPData.sObjectInstances[iObjectIndex].iLoopingSoundId > -1 IAP_PLAY_LOOPING_SOUND_FROM_OBJECT("Enemy_Jet_Flyover", iObjectIndex) ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Returns the time in ms between shots for this enemy FUNC INT IAP_GET_ENEMY_PROJECTILE_INTERVAL(INT iObjectIndex) INT iInterval = sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iShotInterval //Jets shoot speed needs to scale with stage speed or they get easier IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_JET iInterval = ROUND(iInterval / sIAPData.fStageSpeedMod) ENDIF RETURN iInterval ENDFUNC /// PURPOSE: /// Returns the projectile type for the this enemy FUNC IAP_PROJECTILE_TYPE IAP_GET_ENEMY_PROJECTILE_TYPE(INT iObjectIndex) SWITCH sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType CASE IAP_OBJECT_TYPE_GROUND_ENEMY CASE IAP_OBJECT_TYPE_DRONE RETURN IAP_PROJECTILE_TYPE_ENEMY CASE IAP_OBJECT_TYPE_JET RETURN IAP_PROJECTILE_TYPE_FALLING_BARREL ENDSWITCH RETURN IAP_PROJECTILE_TYPE_NONE ENDFUNC /// PURPOSE: /// Returns the starting anim frame for this enemy's projectiles FUNC INT IAP_GET_ENEMY_PROJECTILE_START_ANIM_FRAME(INT iObjectIndex) SWITCH sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType CASE IAP_OBJECT_TYPE_GROUND_ENEMY CASE IAP_OBJECT_TYPE_DRONE RETURN -1 CASE IAP_OBJECT_TYPE_JET RETURN 0 ENDSWITCH RETURN HIGHEST_INT ENDFUNC /// PURPOSE: /// Returns the origin and end point for this enemy's projectiles PROC IAP_GET_SHOT_ORIGIN_AND_END_FOR_ENEMY_PROJECTILE(INT iObjectIndex, VECTOR_2D &vShotOrigin, VECTOR_2D &vShotEnd) vShotOrigin = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(sIAPData.sObjectInstances[iObjectIndex].vPosition.x + sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vShotOffset.x, sIAPData.sObjectInstances[iObjectIndex].vPosition.y + sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vShotOffset.y)) SWITCH sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType CASE IAP_OBJECT_TYPE_GROUND_ENEMY vShotEnd = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(1.0, 0.0))), -180) BREAK CASE IAP_OBJECT_TYPE_DRONE vShotEnd = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(1.0, 0.0))), 135) BREAK CASE IAP_OBJECT_TYPE_JET vShotEnd = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(1.0, 0.0))), 85) BREAK ENDSWITCH vShotOrigin = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vShotOrigin) vShotEnd = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vShotEnd) ENDPROC /// PURPOSE: /// Returns the rotation for this enemy's projectiles FUNC FLOAT IAP_GET_ENEMY_PROJECTILE_ROTATION(INT iObjectIndex) SWITCH sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType CASE IAP_OBJECT_TYPE_GROUND_ENEMY CASE IAP_OBJECT_TYPE_JET RETURN 0.0 CASE IAP_OBJECT_TYPE_DRONE RETURN -45.0 ENDSWITCH RETURN 0.0 ENDFUNC /// PURPOSE: /// Returns the damage dealt by this enemy's projectiles FUNC INT IAP_GET_ENEMY_PROJECTILE_DAMAGE(INT iObjectIndex) RETURN sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iShotDamage ENDFUNC /// PURPOSE: /// Processes firing obejct projectiles PROC IAP_PROCESS_STAGE_OBJECT_SHOOTING(INT iObjectIndex) IF sIAPData.eCurrentState != IAP_CLIENT_STATE_RUNNING EXIT ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iHealth <= 0 EXIT ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sObjectInstances[iObjectIndex].vPosition, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale) EXIT ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iShotInterval = 0 EXIT ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) < sIAPData.sObjectInstances[iObjectIndex].iLastShotTime + IAP_GET_ENEMY_PROJECTILE_INTERVAL(iObjectIndex) EXIT ENDIF VECTOR_2D vShotOrigin, vShotEnd IAP_GET_SHOT_ORIGIN_AND_END_FOR_ENEMY_PROJECTILE(iObjectIndex, vShotOrigin, vShotEnd) IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(vShotOrigin, INIT_VECTOR_2D(cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE)) //Dont fire if the start point is outwith the screen sIAPData.sObjectInstances[iObjectIndex].iLastShotTime = NATIVE_TO_INT(GET_NETWORK_TIME()) EXIT ENDIF sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].eProjectileType = IAP_GET_ENEMY_PROJECTILE_TYPE(iObjectIndex) sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].vOrigin = vShotOrigin sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].vDirection = vShotEnd sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].vThisFramePos = vShotOrigin sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].vPreviousFramePos = vShotOrigin sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].fRotation = IAP_GET_ENEMY_PROJECTILE_ROTATION(iObjectIndex) sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].iShotTime = NATIVE_TO_INT(GET_NETWORK_TIME()) sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].iDamage = IAP_GET_ENEMY_PROJECTILE_DAMAGE(iObjectIndex) sIAPData.sEnemyProjectileInstances[sIAPData.iCurrentEnemyProjectile].iAnimFrame = IAP_GET_ENEMY_PROJECTILE_START_ANIM_FRAME(iObjectIndex) sIAPData.iCurrentEnemyProjectile++ IF sIAPData.iCurrentEnemyProjectile >= ciIAP_MAX_ENEMY_PROJECTILES sIAPData.iCurrentEnemyProjectile = 0 ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iShootingAnimationFrames > 0 AND sIAPData.eCurrentState = IAP_CLIENT_STATE_RUNNING sIAPData.sObjectInstances[iObjectIndex].eState = IAP_OBJECT_STATE_SHOOTING sIAPData.sObjectInstances[iObjectIndex].iAnimFrame = 0 ENDIF sIAPData.sObjectInstances[iObjectIndex].iLastShotTime = NATIVE_TO_INT(GET_NETWORK_TIME()) IF IAP_DOES_OBJECT_HAVE_SHOOT_SOUND(iObjectIndex) AND sIAPData.sObjectInstances[iObjectIndex].iOneShotSoundId > -1 IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_OBJECT(IAP_GET_OBJECT_SHOOT_SOUND(iObjectIndex), IAP_GET_SOUND_SET_FOR_OBJECT(iObjectIndex), iObjectIndex) ENDIF ENDPROC /// PURPOSE: /// Processes the object's state while being nuked PROC IAP_PROCESS_STAGE_OBJECT_NUKED(INT iObjectIndex) IF IAP_IS_OBJECT_TYPE_NUKE_PROOF(sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType) EXIT ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iHealth <= 0 EXIT ENDIF IF NOT HAS_NET_TIMER_EXPIRED(sIAPData.tdNukeTimer, ciIAP_PICKUP_NUKE_START_DURATION) sIAPData.sObjectInstances[iObjectIndex].iLastDamagedTime = NATIVE_TO_INT(GET_NETWORK_TIME()) ELSE IAP_UPDATE_OBJECT_HEALTH(iObjectIndex, -sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iMaxHealth) ENDIF ENDPROC /// PURPOSE: /// Main object update loop PROC IAP_PROCESS_STAGE_OBJECTS() IAP_PROCESS_STAGE_OBJECT_SPAWNING() INT iObjectIndex FOR iObjectIndex = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 IF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_NONE RELOOP ENDIF IAP_PROCESS_STAGE_OBJECT_POSITION(iObjectIndex) IF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_NONE RELOOP ENDIF IF IAP_IS_NUKE_ACTIVE() IAP_PROCESS_STAGE_OBJECT_NUKED(iObjectIndex) ELSE IAP_PROCESS_STAGE_OBJECT_SHOOTING(iObjectIndex) ENDIF ENDFOR ENDPROC // ------------------------------ PLAYER PROCESSING ------------------------------ /// PURPOSE: /// Updates the player tank state PROC IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE eNewState) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SET_PLAYER_TANK_STATE - State changed from ", IAP_DEBUG_GET_IAP_PLAYER_TANK_STATE_AS_STRING(sIAPData.sPlayerTank.eTankState), " to ", IAP_DEBUG_GET_IAP_PLAYER_TANK_STATE_AS_STRING(eNewState)) sIAPData.sPlayerTank.eTankState = eNewState ENDPROC /// PURPOSE: /// Updates the player turret state PROC IAP_SET_PLAYER_TURRET_STATE(IAP_PLAYER_TURRET_STATE eNewState) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SET_PLAYER_TURRET_STATE - State changed from ", IAP_DEBUG_GET_IAP_PLAYER_TURRET_STATE_AS_STRING(sIAPData.sPlayerTank.eTurretState), " to ", IAP_DEBUG_GET_IAP_PLAYER_TURRET_STATE_AS_STRING(eNewState)) sIAPData.sPlayerTank.eTurretState = eNewState ENDPROC /// PURPOSE: /// Updates the player's weapon type PROC IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON eWeapon) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SET_PLAYER_WEAPON_TYPE - Weapon changed from ", IAP_DEBUG_GET_IAP_PLAYER_WEAPON_AS_STRING(sIAPData.sPlayerTank.eWeaponType), " to ", IAP_DEBUG_GET_IAP_PLAYER_WEAPON_AS_STRING(eWeapon)) sIAPData.sPlayerTank.eWeaponType = eWeapon IF eWeapon != IAP_PLAYER_WEAPON_DEFAULT AND IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_TRIPLE_SHOT_ACTIVE) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SET_PLAYER_WEAPON_TYPE - Triple Fire deactivated") SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_TRIPLE_SHOT_ACTIVE) ENDIF ENDPROC /// PURPOSE: /// Updates the player's global state PROC IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE eState) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SET_GLOBAL_PLAYER_STATE - State changed from ", IAP_DEBUG_GET_CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_STRING(g_sCasinoArcadeInvadeAndPersuadeVars.ePlayerState), " to ", IAP_DEBUG_GET_CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_STRING(eState)) g_sCasinoArcadeInvadeAndPersuadeVars.ePlayerState = eState ENDPROC /// PURPOSE: /// Updates the player's health PROC IAP_CHANGE_PLAYER_HEALTH(INT iHealthChange) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bNoDamage CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_CHANGE_PLAYER_HEALTH - bNoDamage on!") EXIT ENDIF #ENDIF IF sIAPData.sPlayerTank.eTankState = IAP_PLAYER_TANK_STATE_EXPLODING OR sIAPData.sPlayerTank.eTankState = IAP_PLAYER_TANK_STATE_RESPAWNING EXIT ENDIF IF iHealthChange < 0 IF (sIAPData.sPlayerTank.iLastDamagedTime + ciIAP_PLAYER_DAMAGE_RED_TIME > NATIVE_TO_INT(GET_NETWORK_TIME()) OR sIAPData.sPlayerTank.iRespawnTime + ciIAP_PLAYER_RESPAWN_INVULN_TIME > NATIVE_TO_INT(GET_NETWORK_TIME())) EXIT ENDIF IF IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHIELD_ACTIVE) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_CHANGE_PLAYER_HEALTH - Shield deactivated") CLEAR_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHIELD_ACTIVE) EXIT ENDIF ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_CHANGE_PLAYER_HEALTH - Current Health = ", sIAPData.sPlayerTank.iHealth, " iHealthChange = ", iHealthChange) INT iMinHealth = PICK_INT(sIAPData.sPlayerTank.iHealth > 1, 1, 0) INT iNewHealth = CLAMP_INT(sIAPData.sPlayerTank.iHealth + iHealthChange, iMinHealth, ciIAP_MAX_HEALTH) sIAPData.sPlayerTank.iDisplayHealth = sIAPData.sPlayerTank.iHealth sIAPData.sPlayerTank.iHealth = iNewHealth IF iHealthChange < 0 #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bLoseWeaponOnHit IF sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_DEFAULT IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_DEFAULT) ENDIF ENDIF #ENDIF sIAPData.sPlayerTank.vPosition.x -= cfIAP_PLAYER_TANK_KNOCK_BACK_X IF sIAPData.sPlayerTank.vPosition.x < cfIAP_PLAYER_TANK_MIN_POS_X sIAPData.sPlayerTank.vPosition.x = cfIAP_PLAYER_TANK_MIN_POS_X ENDIF sIAPData.sPlayerTank.iLastDamagedTime = NATIVE_TO_INT(GET_NETWORK_TIME()) ELIF iHealthChange > 0 sIAPData.sPlayerTank.iLastHealedTime = NATIVE_TO_INT(GET_NETWORK_TIME()) ENDIF IF iNewHealth = 0 sIAPData.sPlayerTank.iLives -- sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_EXPLODING) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Destroyed", sIAPData.sPlayerTank.iGeneralSoundId) IF sIAPData.sPlayerTank.iLives >= 0 #IF IS_DEBUG_BUILD OR sIAPData.sDebugStruct.bDontFailWhenOutOfLives = TRUE #ENDIF IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Player_Death") ENDIF sIAPData.sPlayerTank.iLastJumpTime = NATIVE_TO_INT(GET_NETWORK_TIME()) IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_DEFAULT) ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_CHANGE_PLAYER_HEALTH - New Health = ", sIAPData.sPlayerTank.iHealth) ENDPROC /// PURPOSE: /// Moves the player tank into the play area, returns true when the tank is in the start position FUNC BOOL IAP_IS_PLAYER_TANK_IN_START_POSITION() sIAPData.sPlayerTank.vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sPlayerTank.vPosition.x, -cfIAP_BASE_FOREGROUND_SPEED) IF sIAPData.sPlayerTank.vPosition.x < cfIAP_PLAYER_TANK_BASE_POS_X RETURN FALSE ENDIF sIAPData.sPlayerTank.vPosition.x = cfIAP_PLAYER_TANK_BASE_POS_X RETURN TRUE ENDFUNC /// PURPOSE: /// Moves the player tank out of the play area, returns true when the tank is in the end position FUNC BOOL IAP_IS_PLAYER_TANK_IN_END_POSITION() sIAPData.sPlayerTank.vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sPlayerTank.vPosition.x, -cfIAP_BASE_FOREGROUND_SPEED) IF sIAPData.sPlayerTank.vPosition.x < 1.0 RETURN FALSE ENDIF sIAPData.sPlayerTank.vPosition.x = 1.0 RETURN TRUE ENDFUNC /// PURPOSE: /// Every frame processing for the player tank's turret PROC IAP_PROCESS_PLAYER_TURRET_STATE() SWITCH sIAPData.sPlayerTank.eTurretState CASE IAP_PLAYER_TURRET_STATE_DEFAULT IF sIAPData.sPlayerTank.iTankShootAnimFrame != 0 sIAPData.sPlayerTank.iTankShootAnimFrame = 0 ENDIF BREAK CASE IAP_PLAYER_TURRET_STATE_SHOOTING sIAPData.sPlayerTank.iTankShootAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sPlayerTank.iTankShootAnimFrame >= ciIAP_TANK_SHOOT_ANIM_FRAMES sIAPData.sPlayerTank.iTankShootAnimFrame = 0 IAP_SET_PLAYER_TURRET_STATE(IAP_PLAYER_TURRET_STATE_DEFAULT) ENDIF BREAK ENDSWITCH ENDPROC /// PURPOSE: /// Resets the player tank state for a respawn PROC IAP_RESPAWN_PLAYER() IF sIAPData.sPlayerTank.iLives < 0 #IF IS_DEBUG_BUILD AND sIAPData.sDebugStruct.bDontFailWhenOutOfLives = FALSE #ENDIF EXIT ENDIF sIAPData.sPlayerTank.vPosition.x = cfIAP_PLAYER_TANK_BASE_POS_X sIAPData.sPlayerTank.vPosition.y = cfIAP_PLAYER_TANK_RESPAWN_POS_Y sIAPData.sPlayerTank.iRespawnTime = NATIVE_TO_INT(GET_NETWORK_TIME()) sIAPData.sPlayerTank.iHealth = ciIAP_MAX_HEALTH sIAPData.sPlayerTank.iDisplayHealth = 0 sIAPData.sPlayerTank.iPlayerTankBitset = 0 sIAPData.sPlayerTank.iTurretDirection = 0 sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_RESPAWNING) ENDPROC /// PURPOSE: /// Every frame processing for the player tank PROC IAP_PROCESS_PLAYER_TANK_STATE() INT iTime = NATIVE_TO_INT(GET_NETWORK_TIME()) FLOAT fAlpha FLOAT fGroundPosAtTarget, fGroundPosAtTarget2 VECTOR_2D vSmokePos = sIAPData.sPlayerTank.vPosition FLOAT fGroundY = IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sPlayerTank.vPosition.x + cfIAP_PLAYER_TANK_GROUND_TEST_OFFSET_X) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_PLAYER_TANK_GROUND_TEST_OFFSET_X, fGroundY), INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_PLAYER_TANK_GROUND_TEST_OFFSET_X, sIAPData.sPlayerTank.vPosition.y), sIAPData.sColours.rgbaPlasma) ENDIF #ENDIF IAP_PLAY_TANK_LOOP() SWITCH sIAPData.sPlayerTank.eTankState CASE IAP_PLAYER_TANK_STATE_DEFAULT sIAPData.sPlayerTank.stTankSprite = "tank_drive" sIAPData.sPlayerTank.iTankBaseAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sPlayerTank.iTankBaseAnimFrame >= ciIAP_TANK_BASE_ANIM_FRAMES sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 ENDIF IF sIAPData.sPlayerTank.vPosition.y < cfIAP_PLAYER_TANK_BASE_POS_Y + fGroundY AND (sIAPData.sPlayerTank.iRespawnTime = -HIGHEST_INT OR iTime - sIAPData.sPlayerTank.iRespawnTime > ROUND(ciIAP_PLAYER_TANK_RESPAWN_FALL_TIME_DOWN * 1.5)) IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_FALLING) sIAPData.sPlayerTank.iLastJumpTime = iTime ELIF sIAPData.sPlayerTank.vPosition.y - (cfIAP_PLAYER_TANK_BASE_POS_Y/2) > fGroundY //Hit a wall IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Collision", sIAPData.sPlayerTank.iGeneralSoundId) sIAPData.sPlayerTank.iLives -- sIAPData.sPlayerTank.iHealth = 0 IF sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_DEFAULT IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_DEFAULT) ENDIF sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_EXPLODING) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Destroyed", sIAPData.sPlayerTank.iGeneralSoundId) IF sIAPData.sPlayerTank.iLives >= 0 #IF IS_DEBUG_BUILD OR sIAPData.sDebugStruct.bDontFailWhenOutOfLives = TRUE #ENDIF IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Player_Death") ENDIF sIAPData.sPlayerTank.iLastJumpTime = iTime EXIT ENDIF BREAK CASE IAP_PLAYER_TANK_STATE_JUMPING sIAPData.sPlayerTank.stTankSprite = "tank_jump" sIAPData.sPlayerTank.iTankBaseAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sPlayerTank.iTankBaseAnimFrame >= ciIAP_TANK_JUMP_ANIM_FRAMES sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 ENDIF fAlpha = (TO_FLOAT(iTime - sIAPData.sPlayerTank.iLastJumpTime) / ciIAP_PLAYER_TANK_JUMP_TIME_UP) IF fAlpha >= 1.0 fAlpha = 1.0 IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_FALLING) sIAPData.sPlayerTank.iLastJumpTime = iTime ENDIF sIAPData.sPlayerTank.vPosition.y = INTERP_FLOAT(sIAPData.sPlayerTank.fJumpStartY, sIAPData.sPlayerTank.fJumpEndY, fAlpha, INTERPTYPE_DECEL) IF sIAPData.sPlayerTank.vPosition.y - (cfIAP_PLAYER_TANK_BASE_POS_Y/2) > fGroundY //Hit a wall IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Collision", sIAPData.sPlayerTank.iGeneralSoundId) sIAPData.sPlayerTank.iLives -- sIAPData.sPlayerTank.iHealth = 0 IF sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_DEFAULT IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_DEFAULT) ENDIF sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_EXPLODING) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Destroyed", sIAPData.sPlayerTank.iGeneralSoundId) IF sIAPData.sPlayerTank.iLives >= 0 #IF IS_DEBUG_BUILD OR sIAPData.sDebugStruct.bDontFailWhenOutOfLives = TRUE #ENDIF IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Player_Death") ENDIF sIAPData.sPlayerTank.iLastJumpTime = iTime EXIT ENDIF BREAK CASE IAP_PLAYER_TANK_STATE_FALLING sIAPData.sPlayerTank.stTankSprite = "tank_jump" sIAPData.sPlayerTank.iTankBaseAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sPlayerTank.iTankBaseAnimFrame >= ciIAP_TANK_JUMP_ANIM_FRAMES sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 ENDIF IF sIAPData.sPlayerTank.vPosition.y - (cfIAP_PLAYER_TANK_BASE_POS_Y/2) > fGroundY //Hit a wall IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Collision", sIAPData.sPlayerTank.iGeneralSoundId) sIAPData.sPlayerTank.iLives -- sIAPData.sPlayerTank.iHealth = 0 IF sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_DEFAULT IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_DEFAULT) ENDIF sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_EXPLODING) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Destroyed", sIAPData.sPlayerTank.iGeneralSoundId) IF sIAPData.sPlayerTank.iLives >= 0 #IF IS_DEBUG_BUILD OR sIAPData.sDebugStruct.bDontFailWhenOutOfLives = TRUE #ENDIF IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Player_Death") ENDIF sIAPData.sPlayerTank.iLastJumpTime = iTime EXIT ENDIF IF sIAPData.sPlayerTank.vPosition.y > sIAPData.sCurrentStageData.fBaseY //If we are falling down a pit then go with the stage sIAPData.sPlayerTank.vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sPlayerTank.vPosition.x, cfIAP_BASE_FOREGROUND_SPEED) ENDIF sIAPData.sPlayerTank.vPosition.y = sIAPData.sPlayerTank.vPosition.y +@ INTERP_FLOAT(0, cfIAP_PLAYER_TANK_FALL_SPEED, (TO_FLOAT(iTime - sIAPData.sPlayerTank.iLastJumpTime) / ciIAP_PLAYER_TANK_FALL_ACCEL), INTERPTYPE_ACCEL) IF sIAPData.sPlayerTank.vPosition.y > cfIAP_PLAYER_TANK_BASE_POS_Y + fGroundY sIAPData.sPlayerTank.vPosition.y = cfIAP_PLAYER_TANK_BASE_POS_Y + fGroundY IF sIAPData.sPlayerTank.vPosition.y > sIAPData.sCurrentStageData.fBaseY IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Collision", sIAPData.sPlayerTank.iGeneralSoundId) sIAPData.sPlayerTank.iLives -- sIAPData.sPlayerTank.iHealth = 0 IF sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_DEFAULT IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_DEFAULT) ENDIF sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_EXPLODING) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Destroyed", sIAPData.sPlayerTank.iGeneralSoundId) IF sIAPData.sPlayerTank.iLives >= 0 #IF IS_DEBUG_BUILD OR sIAPData.sDebugStruct.bDontFailWhenOutOfLives = TRUE #ENDIF IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Player_Death") ENDIF sIAPData.sPlayerTank.iLastJumpTime = iTime EXIT ELSE IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_DEFAULT) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Jump_Land", sIAPData.sPlayerTank.iGeneralSoundId) sIAPData.sPlayerTank.iLastJumpTime = iTime ENDIF ENDIF BREAK CASE IAP_PLAYER_TANK_STATE_EXPLODING sIAPData.sPlayerTank.iTankBaseAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.eCurrentState = IAP_CLIENT_STATE_RUNNING sIAPData.sPlayerTank.vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sPlayerTank.vPosition.x, cfIAP_BASE_FOREGROUND_SPEED) ENDIF IF sIAPData.sPlayerTank.vPosition.y < cfIAP_PLAYER_TANK_BASE_POS_Y + fGroundY sIAPData.sPlayerTank.vPosition.y = sIAPData.sPlayerTank.vPosition.y +@ INTERP_FLOAT(0, cfIAP_PLAYER_TANK_FALL_SPEED, (TO_FLOAT(iTime - sIAPData.sPlayerTank.iLastJumpTime) / ciIAP_PLAYER_TANK_FALL_ACCEL), INTERPTYPE_ACCEL) IF sIAPData.sPlayerTank.vPosition.y >= cfIAP_PLAYER_TANK_BASE_POS_Y + fGroundY sIAPData.sPlayerTank.vPosition.y = cfIAP_PLAYER_TANK_BASE_POS_Y + fGroundY ENDIF ENDIF IF sIAPData.sPlayerTank.iTankBaseAnimFrame > ciIAP_TANK_EXPLOSION_ANIM_FRAMES AND sIAPData.eCurrentState = IAP_CLIENT_STATE_RUNNING IAP_RESPAWN_PLAYER() ENDIF BREAK CASE IAP_PLAYER_TANK_STATE_RESPAWNING fAlpha = TO_FLOAT(iTime - sIAPData.sPlayerTank.iRespawnTime) / ciIAP_PLAYER_TANK_RESPAWN_FALL_TIME_DOWN fGroundPosAtTarget = IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sPlayerTank.vPosition.x + cfIAP_PLAYER_TANK_GROUND_TEST_OFFSET_X + ((-cfIAP_BASE_FOREGROUND_SPEED * sIAPData.fStageSpeedMod)/1000) * (ciIAP_PLAYER_TANK_RESPAWN_FALL_TIME_DOWN * (1 - fAlpha)), TRUE) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_PLAYER_TANK_GROUND_TEST_OFFSET_X + ((-cfIAP_BASE_FOREGROUND_SPEED * sIAPData.fStageSpeedMod)/1000) * (ciIAP_PLAYER_TANK_RESPAWN_FALL_TIME_DOWN * (1 - fAlpha)), fGroundPosAtTarget), INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_PLAYER_TANK_GROUND_TEST_OFFSET_X, sIAPData.sPlayerTank.vPosition.y), sIAPData.sColours.rgbaHeal) ENDIF #ENDIF IF sIAPData.sPlayerTank.vPosition.y < 0.0 IF fGroundPosAtTarget > sIAPData.sCurrentStageData.fBaseY sIAPData.sPlayerTank.iRespawnTime = iTime sIAPData.sPlayerTank.vPosition.y = cfIAP_PLAYER_TANK_RESPAWN_POS_Y //Gonna land in a pitfall - wait EXIT ELSE fGroundPosAtTarget2 = IAP_GET_GROUND_Y_AT_X_POS(sIAPData.sPlayerTank.vPosition.x + (cfIAP_PLAYER_TANK_SCALE_X) + ((-cfIAP_BASE_FOREGROUND_SPEED * sIAPData.fStageSpeedMod)/1000) * (ciIAP_PLAYER_TANK_RESPAWN_FALL_TIME_DOWN * (1 - fAlpha)), TRUE) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + (cfIAP_PLAYER_TANK_SCALE_X / 2) + ((-cfIAP_BASE_FOREGROUND_SPEED * sIAPData.fStageSpeedMod)/1000) * (ciIAP_PLAYER_TANK_RESPAWN_FALL_TIME_DOWN * (1 - fAlpha)), fGroundPosAtTarget2), INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_PLAYER_TANK_GROUND_TEST_OFFSET_X, sIAPData.sPlayerTank.vPosition.y), sIAPData.sColours.rgbaBlack) ENDIF #ENDIF IF NOT IS_FLOAT_IN_RANGE(fGroundPosAtTarget2 - fGroundPosAtTarget, -cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE) //Gonna land with no time to jump before falling/crashing sIAPData.sPlayerTank.iRespawnTime = iTime sIAPData.sPlayerTank.vPosition.y = cfIAP_PLAYER_TANK_RESPAWN_POS_Y EXIT ENDIF ENDIF ENDIF sIAPData.sPlayerTank.stTankSprite = "tank_jump" sIAPData.sPlayerTank.iTankBaseAnimFrame += sIAPData.iUpdateFrames15FPS IF sIAPData.sPlayerTank.iTankBaseAnimFrame >= ciIAP_TANK_JUMP_ANIM_FRAMES sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 ENDIF IF fAlpha >= 1.0 fAlpha = 1.0 sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Jump_Land", sIAPData.sPlayerTank.iGeneralSoundId) IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_DEFAULT) sIAPData.sPlayerTank.vPosition.y = cfIAP_PLAYER_TANK_BASE_POS_Y + fGroundY ELSE sIAPData.sPlayerTank.vPosition.y = INTERP_FLOAT(cfIAP_PLAYER_TANK_RESPAWN_POS_Y, cfIAP_PLAYER_TANK_BASE_POS_Y + fGroundPosAtTarget, fAlpha, INTERPTYPE_ACCEL) ENDIF BREAK ENDSWITCH IF sIAPData.sPlayerTank.iHealth = 1 IF iTime > sIAPData.sPlayerTank.iLastSmokeTime + ciIAP_TANK_EXPLOSION_SMOKE_INTERVAL vSmokePos.x += GET_RANDOM_FLOAT_IN_RANGE(-cfIAP_PLAYER_TANK_SCALE_X/2, cfIAP_PLAYER_TANK_SCALE_X/2) vSmokePos.y += GET_RANDOM_FLOAT_IN_RANGE(-cfIAP_PLAYER_TANK_SCALE_Y/2, cfIAP_PLAYER_TANK_SCALE_Y/2) IAP_ADD_EXPLOSION_AT_COORDS(vSmokePos, IAP_EXPLOSION_SMOKE) sIAPData.sPlayerTank.iLastSmokeTime = iTime ENDIF ENDIF ENDPROC /// PURPOSE: /// Rotates the player turret by iRotateDelta turns /// If IgnoreInterval is false this will only rotate if ciIAP_TURRET_ROTATION_INTERVAL ms have passed since last rotation PROC IAP_ROTATE_TURRET(INT iRotateDelta, BOOL IgnoreInterval = FALSE, FLOAT fAxisValue = 0.0) INT iInterval = ciIAP_TURRET_ROTATION_INTERVAL IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) AND (fAxisValue > cfSTICK_THRESHOLD * cfIAP_KEYBOARD_MOUSE_AXIS_THRESHOLD_MOD OR fAxisValue < -cfSTICK_THRESHOLD * cfIAP_KEYBOARD_MOUSE_AXIS_THRESHOLD_MOD) iInterval = ciIAP_TURRET_ROTATION_INTERVAL_PC ENDIF IF NOT IgnoreInterval IF NATIVE_TO_INT(GET_NETWORK_TIME()) < sIAPData.sPlayerTank.iTurretLastRotationTime + iInterval EXIT ENDIF ENDIF IF iRotateDelta = 0 EXIT ENDIF sIAPData.sPlayerTank.iLastFrameTurretDirection = sIAPData.sPlayerTank.iTurretDirection sIAPData.sPlayerTank.iTurretDirection += iRotateDelta IF sIAPData.sPlayerTank.iTurretDirection > ciIAP_MAX_TURRET_DIRECTIONS - 1 sIAPData.sPlayerTank.iTurretDirection = ciIAP_MAX_TURRET_DIRECTIONS - 1 ELIF sIAPData.sPlayerTank.iTurretDirection < -1 sIAPData.sPlayerTank.iTurretDirection = -1 ELSE IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Turret_Move", sIAPData.sPlayerTank.iTurretSoundId) ENDIF sIAPData.sPlayerTank.iTurretLastRotationTime = NATIVE_TO_INT(GET_NETWORK_TIME()) ENDPROC /// PURPOSE: /// Returns the time in ms between shots for the current weapon FUNC INT IAP_GET_CURRENT_WEAPON_PROJECTILE_INTERVAL() SWITCH sIAPData.sPlayerTank.eWeaponType CASE IAP_PLAYER_WEAPON_DEFAULT IF IAP_IS_TRIPLE_FIRE_ACTIVE() RETURN (ciIAP_BULLET_SHOOTING_INTERVAL / 3) ENDIF RETURN ROUND(ciIAP_BULLET_SHOOTING_INTERVAL * IAP_GET_STAGE_WEAPON_SPEED_MOD()) CASE IAP_PLAYER_WEAPON_FLAMETHROWER RETURN ROUND(ciIAP_FLAME_SHOOTING_INTERVAL * IAP_GET_STAGE_WEAPON_SPEED_MOD()) CASE IAP_PLAYER_WEAPON_ROCKET_LAUNCHER RETURN ROUND(ciIAP_HOMING_ROCKET_SHOOTING_INTERVAL * IAP_GET_STAGE_WEAPON_SPEED_MOD()) CASE IAP_PLAYER_WEAPON_PLASMA RETURN ciIAP_PLASMA_SHOOTING_INTERVAL ENDSWITCH RETURN HIGHEST_INT ENDFUNC /// PURPOSE: /// Returns the projectile type for the current weapon FUNC IAP_PROJECTILE_TYPE IAP_GET_CURRENT_WEAPON_PROJECTILE_TYPE() SWITCH sIAPData.sPlayerTank.eWeaponType CASE IAP_PLAYER_WEAPON_DEFAULT RETURN IAP_PROJECTILE_TYPE_BULLET CASE IAP_PLAYER_WEAPON_FLAMETHROWER RETURN IAP_PROJECTILE_TYPE_FLAME CASE IAP_PLAYER_WEAPON_ROCKET_LAUNCHER RETURN IAP_PROJECTILE_TYPE_HOMING_ROCKET CASE IAP_PLAYER_WEAPON_PLASMA RETURN IAP_PROJECTILE_TYPE_PLASMA ENDSWITCH RETURN IAP_PROJECTILE_TYPE_NONE ENDFUNC /// PURPOSE: /// Returns the starting anim frame for the current weapon's projectiles FUNC INT IAP_GET_CURRENT_WEAPON_START_ANIM_FRAME() SWITCH sIAPData.sPlayerTank.eWeaponType CASE IAP_PLAYER_WEAPON_DEFAULT RETURN -1 CASE IAP_PLAYER_WEAPON_FLAMETHROWER RETURN GET_RANDOM_INT_IN_RANGE(0, ciIAP_FLAME_PROJECTILE_ANIM_START_MAX_FRAME) CASE IAP_PLAYER_WEAPON_ROCKET_LAUNCHER RETURN 0 CASE IAP_PLAYER_WEAPON_PLASMA IF sIAPData.sPlayerTank.sProjectileInstances[0].iAnimFrame >= sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[0].eProjectileType].iMaxAnimFrames OR sIAPData.sPlayerTank.sProjectileInstances[0].iAnimFrame < 0 sIAPData.sPlayerTank.sProjectileInstances[0].iAnimFrame = 0 ENDIF RETURN sIAPData.sPlayerTank.sProjectileInstances[0].iAnimFrame ENDSWITCH RETURN HIGHEST_INT ENDFUNC /// PURPOSE: /// Updates vShotEnd if the beam intersects the ground PROC IAP_CHECK_PLASMA_GROUND_INTERSECTION(VECTOR_2D vShotOrigin, VECTOR_2D &vShotEnd) IF sIAPData.sPlayerTank.iTurretDirection > 0 //Can't hit the ground EXIT ENDIF IF vShotOrigin.y > IAP_GET_GROUND_Y_AT_X_POS(vShotOrigin.x) vShotEnd = vShotOrigin IAP_PLAY_PLASMA_HIT_AT_POSITION(vShotEnd, 1) EXIT ENDIF VECTOR_2D vStart, vEnd, vIntersect vStart.x = sIAPData.sParallax.fForegroundPosX[0] - (IAP_GET_FOREGROUND_X_SCALE(0)/2) vStart.y = sIAPData.sCurrentStageData.fBaseY vEnd = vStart INT i FOR i = 0 TO sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1 //Pitfall IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] = ciIAP_PARALLAX_PITFALL AND (sIAPData.sObjectInstances[sIAPData.sParallax.iLinkedObjectIndexes[i]].iFlags & ciIAP_OBJECT_FLAG_PITFALL_CRUMBLING) = 0 FLOAT fEndBefore = vEnd.x vEnd.x += IAP_GET_CURRENT_STAGE_PITFALL_GROUND_WIDTH_LEFT() //Left side ground IF ARCADE_CABINET_GET_LINE_INTERSECT(vShotOrigin, vShotEnd, vStart, vEnd, vIntersect) vShotEnd = vIntersect IAP_PLAY_PLASMA_HIT_AT_POSITION(vShotEnd, 1) EXIT ENDIF //Skip left wall as impossible to hit //Skip bottom as impossible to hit //Right Wall vStart.y = 1.0 vEnd.x += IAP_GET_CURRENT_PITFALL_SCALE() - IAP_GET_CURRENT_STAGE_PITFALL_GROUND_WIDTH_LEFT() - IAP_GET_CURRENT_STAGE_PITFALL_GROUND_WIDTH_RIGHT() vStart.x = vEnd.x vEnd.y = sIAPData.sCurrentStageData.fBaseY IF ARCADE_CABINET_GET_LINE_INTERSECT(vShotOrigin, vShotEnd, vStart, vEnd, vIntersect) vShotEnd = vIntersect IAP_PLAY_PLASMA_HIT_AT_POSITION(vShotEnd, 1) EXIT ENDIF vStart = vEnd vEnd.x = fEndBefore + IAP_GET_CURRENT_PITFALL_SCALE() vStart.x = vEnd.x - IAP_GET_CURRENT_STAGE_PITFALL_GROUND_WIDTH_RIGHT() //Right side ground handled next change RELOOP ENDIF IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] = ciIAP_PARALLAX_RAISED_LEDGE //Check current line IF ARCADE_CABINET_GET_LINE_INTERSECT(vShotOrigin, vShotEnd, vStart, vEnd, vIntersect) vShotEnd = vIntersect IAP_PLAY_PLASMA_HIT_AT_POSITION(vShotEnd, 1) EXIT ENDIF //Check left wall vStart = vEnd vEnd.y = (1.0 - cfIAP_FACADE_TOP_HEIGHT) - sIAPData.sObjectData[ENUM_TO_INT(IAP_GET_CURRENT_STAGE_LEDGE_INDEX())].vSpriteScale.y + cfIAP_LEDGE_OFFSET IF ARCADE_CABINET_GET_LINE_INTERSECT(vShotOrigin, vShotEnd, vStart, vEnd, vIntersect) vShotEnd = vIntersect IAP_PLAY_PLASMA_HIT_AT_POSITION(vShotEnd, 1) EXIT ENDIF vStart = vEnd vEnd.x += IAP_GET_FOREGROUND_X_SCALE(i) //Check top IF ARCADE_CABINET_GET_LINE_INTERSECT(vShotOrigin, vShotEnd, vStart, vEnd, vIntersect) vShotEnd = vIntersect IAP_PLAY_PLASMA_HIT_AT_POSITION(vShotEnd, 1) EXIT ENDIF //Skip right wall, it cant be hit vEnd.y = sIAPData.sCurrentStageData.fBaseY vStart = vEnd RELOOP ENDIF //Normal foreground vEnd.x += IAP_GET_FOREGROUND_X_SCALE(i) ENDFOR IF ARCADE_CABINET_GET_LINE_INTERSECT(vShotOrigin, vShotEnd, vStart, vEnd, vIntersect) vShotEnd = vIntersect IAP_PLAY_PLASMA_HIT_AT_POSITION(vShotEnd, 1) ENDIF ENDPROC /// PURPOSE: /// Returns the origin and end point for the current weapon's projectiles PROC IAP_GET_SHOT_ORIGIN_AND_END_FOR_CURRENT_WEAPON(VECTOR_2D &vShotOrigin, VECTOR_2D &vShotEnd) FLOAT fJumpOffset = PICK_FLOAT(IAP_IS_PLAYER_TANK_IN_AIR(), cfIAP_PLAYER_TANK_JUMP_SPRITE_OFFSET_Y, 0.0) SWITCH sIAPData.sPlayerTank.eWeaponType CASE IAP_PLAYER_WEAPON_DEFAULT CASE IAP_PLAYER_WEAPON_ROCKET_LAUNCHER vShotOrigin = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_TURRET_OFFSET_X, sIAPData.sPlayerTank.vPosition.y + cfIAP_TURRET_SPRITE_OFFSET_Y + fJumpOffset)) vShotOrigin = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(cfIAP_TURRET_SPRITE_OFFSET_X, 0))), sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT) vShotEnd = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(1.0, 0.0))), sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT) BREAK CASE IAP_PLAYER_WEAPON_FLAMETHROWER vShotOrigin = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_TURRET_OFFSET_X + GET_RANDOM_FLOAT_IN_RANGE(-cfIAP_FLAME_PROJECTILE_ORIGIN_MOD, cfIAP_FLAME_PROJECTILE_ORIGIN_MOD), sIAPData.sPlayerTank.vPosition.y + cfIAP_TURRET_SPRITE_OFFSET_Y + fJumpOffset + GET_RANDOM_FLOAT_IN_RANGE(-cfIAP_FLAME_PROJECTILE_ORIGIN_MOD, cfIAP_FLAME_PROJECTILE_ORIGIN_MOD))) vShotOrigin = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(cfIAP_TURRET_SPRITE_OFFSET_X, 0))), sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT + GET_RANDOM_INT_IN_RANGE(-ciIAP_FLAME_PROJECTILE_ANGLE_MOD, ciIAP_FLAME_PROJECTILE_ANGLE_MOD)) vShotEnd = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(cfIAP_FLAME_PROJECTILE_RANGE + GET_RANDOM_FLOAT_IN_RANGE(0.0, cfIAP_FLAME_PROJECTILE_ADDITIONAL_RANGE_MAX), 0.0))), sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT) BREAK CASE IAP_PLAYER_WEAPON_PLASMA vShotOrigin = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_TURRET_OFFSET_X, sIAPData.sPlayerTank.vPosition.y + cfIAP_TURRET_SPRITE_OFFSET_Y + fJumpOffset)) vShotOrigin = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(cfIAP_TURRET_SPRITE_OFFSET_X / cfIAP_PLASMA_ORIGIN_POSITION_MOD, 0))), sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT) vShotEnd = ROTATE_VECTOR_2D_AROUND_VECTOR_2D(vShotOrigin, ADD_VECTOR_2D(vShotOrigin, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(1.0, 0.0))), sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT) BREAK ENDSWITCH vShotOrigin = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vShotOrigin) vShotEnd = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vShotEnd) //Special Case - stop plasma when it intersects the ground IF sIAPData.sPlayerTank.eWeaponType = IAP_PLAYER_WEAPON_PLASMA IAP_CHECK_PLASMA_GROUND_INTERSECTION(vShotOrigin, vShotEnd) ENDIF ENDPROC /// PURPOSE: /// Returns the damage dealt by the current weapon's projectiles FUNC INT IAP_GET_CURRENT_WEAPON_PROJECTILE_DAMAGE() SWITCH sIAPData.sPlayerTank.eWeaponType CASE IAP_PLAYER_WEAPON_DEFAULT RETURN ciIAP_BULLET_WEAPON_DAMAGE CASE IAP_PLAYER_WEAPON_FLAMETHROWER RETURN ciIAP_FLAME_WEAPON_DAMAGE CASE IAP_PLAYER_WEAPON_ROCKET_LAUNCHER RETURN ciIAP_HOMING_ROCKET_WEAPON_DAMAGE CASE IAP_PLAYER_WEAPON_PLASMA RETURN ciIAP_PLASMA_WEAPON_DAMAGE ENDSWITCH RETURN 0 ENDFUNC /// PURPOSE: /// Fires a projectile from the player's turret PROC IAP_SHOOT(BOOL bTapped = FALSE) IF IAP_IS_PLAYER_WEAPON_SOUND_LOOPING() IAP_PLAY_TANK_WEAPON_LOOP() ENDIF IF NOT bTapped AND NATIVE_TO_INT(GET_NETWORK_TIME()) < sIAPData.sPlayerTank.iTurretLastShootTime + IAP_GET_CURRENT_WEAPON_PROJECTILE_INTERVAL() EXIT ENDIF IF sIAPData.sPlayerTank.eWeaponType = IAP_PLAYER_WEAPON_PLASMA //Plasma always uses shot 0 for easier chaining sIAPData.sPlayerTank.iCurrentProjectile = 0 ENDIF VECTOR_2D vShotOrigin, vShotEnd IAP_GET_SHOT_ORIGIN_AND_END_FOR_CURRENT_WEAPON(vShotOrigin, vShotEnd) sIAPData.sPlayerTank.sProjectileInstances[sIAPData.sPlayerTank.iCurrentProjectile].eProjectileType = IAP_GET_CURRENT_WEAPON_PROJECTILE_TYPE() sIAPData.sPlayerTank.sProjectileInstances[sIAPData.sPlayerTank.iCurrentProjectile].vOrigin = vShotOrigin sIAPData.sPlayerTank.sProjectileInstances[sIAPData.sPlayerTank.iCurrentProjectile].vDirection = vShotEnd sIAPData.sPlayerTank.sProjectileInstances[sIAPData.sPlayerTank.iCurrentProjectile].vThisFramePos = vShotOrigin sIAPData.sPlayerTank.sProjectileInstances[sIAPData.sPlayerTank.iCurrentProjectile].fRotation = sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT sIAPData.sPlayerTank.sProjectileInstances[sIAPData.sPlayerTank.iCurrentProjectile].iDamage = IAP_GET_CURRENT_WEAPON_PROJECTILE_DAMAGE() sIAPData.sPlayerTank.sProjectileInstances[sIAPData.sPlayerTank.iCurrentProjectile].iAnimFrame = IAP_GET_CURRENT_WEAPON_START_ANIM_FRAME() sIAPData.sPlayerTank.sProjectileInstances[sIAPData.sPlayerTank.iCurrentProjectile].iShotTime = NATIVE_TO_INT(GET_NETWORK_TIME()) sIAPData.sPlayerTank.iTurretLastShootTime = NATIVE_TO_INT(GET_NETWORK_TIME()) IF sIAPData.sPlayerTank.eWeaponType = IAP_PLAYER_WEAPON_FLAMETHROWER //Randomise the flamethrower interval for a better effect sIAPData.sPlayerTank.iTurretLastShootTime += GET_RANDOM_INT_IN_RANGE(-ciIAP_FLAME_SHOT_TIME_MOD , ciIAP_FLAME_SHOT_TIME_MOD) ENDIF IAP_SET_PLAYER_TURRET_STATE(IAP_PLAYER_TURRET_STATE_SHOOTING) IF NOT IAP_IS_PLAYER_WEAPON_SOUND_LOOPING() IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK(IAP_GET_SHOOT_SOUND_FOR_CURRENT_PLAYER_WEAPON(), sIAPData.sPlayerTank.iWeaponSoundId) ENDIF sIAPData.sPlayerTank.iCurrentProjectile++ IF sIAPData.sPlayerTank.iCurrentProjectile >= ciIAP_MAX_PLAYER_PROJECTILES sIAPData.sPlayerTank.iCurrentProjectile = 0 ENDIF ENDPROC /// PURPOSE: /// Triggers a player tank jump PROC IAP_JUMP() IF sIAPData.sPlayerTank.eTankState != IAP_PLAYER_TANK_STATE_DEFAULT EXIT ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) < sIAPData.sPlayerTank.iLastJumpTime + ciIAP_PLAYER_TANK_JUMP_INTERVAL EXIT ENDIF IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_JUMPING) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Jump", sIAPData.sPlayerTank.iGeneralSoundId) sIAPData.sPlayerTank.iLastJumpTime = NATIVE_TO_INT(GET_NETWORK_TIME()) sIAPData.sPlayerTank.fJumpStartY = sIAPData.sPlayerTank.vPosition.y sIAPData.sPlayerTank.fJumpEndY = sIAPData.sPlayerTank.vPosition.y + cfIAP_PLAYER_TANK_JUMP_HEIGHT ENDPROC /// PURPOSE: /// Processes speeding up and slowing down the player tank PROC IAP_CHANGE_SPEED(BOOL bSpeedUp) IF sIAPData.sPlayerTank.eTankState = IAP_PLAYER_TANK_STATE_FALLING AND sIAPData.sPlayerTank.vPosition.y > sIAPData.sCurrentStageData.fBaseY EXIT ENDIF sIAPData.sPlayerTank.iMovementModTime += ROUND(GET_FRAME_TIME() * 1000) FLOAT fAlpha = TO_FLOAT(sIAPData.sPlayerTank.iMovementModTime) / ciIAP_PLAYER_TANK_SPEED_MOD_TIME IF fAlpha > 1.0 fAlpha = 1.0 ENDIF IF IAP_IS_PLAYER_TANK_IN_AIR() #IF IS_DEBUG_BUILD AND sIAPData.sDebugStruct.bAccelInAir = FALSE #ENDIF fAlpha = 1.0 ENDIF #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bNoAccel fAlpha = 1.0 ENDIF #ENDIF FLOAT fSpeedChange = cfIAP_PLAYER_TANK_MAX_SPEED_MOD * INTERP_FLOAT(0, 1, fAlpha, INTERPTYPE_ACCEL) IF NOT bSpeedUp fSpeedChange *= -1.0 ENDIF sIAPData.sPlayerTank.vPosition.x = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sPlayerTank.vPosition.x, fSpeedChange) IF sIAPData.sPlayerTank.vPosition.x > cfIAP_PLAYER_TANK_MAX_POS_X sIAPData.sPlayerTank.vPosition.x = cfIAP_PLAYER_TANK_MAX_POS_X ELIF sIAPData.sPlayerTank.vPosition.x < cfIAP_PLAYER_TANK_MIN_POS_X sIAPData.sPlayerTank.vPosition.x = cfIAP_PLAYER_TANK_MIN_POS_X ENDIF FLOAT fSoundTankSpeed = (sIAPData.fStageSpeedMod / 10) IF bSpeedUp fSoundTankSpeed += CLAMP(fAlpha ,fSoundTankSpeed, 0.9) ELSE fSoundTankSpeed -= CLAMP(fAlpha ,fSoundTankSpeed, 0.9) ENDIF IF sIAPData.sPlayerTank.iEngineLoopSoundId > -1 AND NOT HAS_SOUND_FINISHED(sIAPData.sPlayerTank.iEngineLoopSoundId) SET_VARIABLE_ON_SOUND(sIAPData.sPlayerTank.iEngineLoopSoundId, "TankSpeed", fSoundTankSpeed) ENDIF ENDPROC // ------------------------------ INPUT ------------------------------ /// PURPOSE: /// Returns true if the player has pressed start this frame FUNC BOOL IAP_HAS_PLAYER_PRESSED_START() CONTROL_ACTION CA_Start = INPUT_FRONTEND_PAUSE IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) CA_Start = INPUT_FRONTEND_ACCEPT ENDIF IF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_Start) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Returns true if the player has pressed quit this frame FUNC BOOL IAP_HAS_PLAYER_PRESSED_QUIT() CONTROL_ACTION CA_Quit = INPUT_SCRIPT_RRIGHT IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) CA_Quit = INPUT_FRONTEND_DELETE ENDIF IF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_Quit) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Returns true if player input should be disabled this frame FUNC BOOL IS_IAP_INPUT_DISABLED_THIS_FRAME() IF sIAPData.sCurrentStageData.fStageDistance != ciIAP_STAGE_INFINITE_LENGTH AND (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) >= sIAPData.sCurrentStageData.fStageDistance RETURN TRUE ENDIF IF sIAPData.sPlayerTank.iHealth <= 0 RETURN TRUE ENDIF IF sIAPData.sPlayerTank.eTankState = IAP_PLAYER_TANK_STATE_EXPLODING RETURN TRUE ENDIF IF sIAPData.sPlayerTank.eTankState = IAP_PLAYER_TANK_STATE_RESPAWNING RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Processes player input before movement has been applied this frame PROC IAP_PROCESS_INPUT_PRE_MOVEMENT() IF IS_IAP_INPUT_DISABLED_THIS_FRAME() EXIT ENDIF CONTROL_ACTION CA_SlowDown = INPUT_SCRIPT_PAD_LEFT CONTROL_ACTION CA_SpeedUp = INPUT_SCRIPT_PAD_RIGHT CONTROL_ACTION CA_Jump = INPUT_SCRIPT_RLEFT CONTROL_ACTION CA_RotateLeft = INPUT_SCRIPT_LB CONTROL_ACTION CA_RotateRight = INPUT_SCRIPT_RB CONTROL_ACTION CA_TurretFront = INPUT_SCRIPT_LT CONTROL_ACTION CA_TurretFrontAlt = MAX_INPUTS FLOAT fAxisThresholdMod = cfIAP_CONTROLLER_AXIS_THRESHOLD_MOD IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) CA_SlowDown = INPUT_SCRIPT_PAD_LEFT CA_SpeedUp = INPUT_SCRIPT_PAD_RIGHT CA_TurretFront = INPUT_CURSOR_CANCEL CA_TurretFrontAlt = INPUT_FRONTEND_DOWN CA_RotateLeft = INPUT_FRONTEND_LEFT CA_RotateRight = INPUT_FRONTEND_RIGHT CA_Jump = INPUT_FRONTEND_X fAxisThresholdMod = cfIAP_KEYBOARD_MOUSE_AXIS_THRESHOLD_MOD ENDIF FLOAT fLeftStickX = GET_DISABLED_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_LEFT_AXIS_X) //Movement IF fLeftStickX < -cfSTICK_THRESHOLD * fAxisThresholdMod OR (CA_SlowDown != MAX_INPUTS AND IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_SlowDown)) IAP_CHANGE_SPEED(FALSE) ELIF fLeftStickX > cfSTICK_THRESHOLD * fAxisThresholdMod OR (CA_SpeedUp != MAX_INPUTS AND IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_SpeedUp)) IAP_CHANGE_SPEED(TRUE) ELIF sIAPData.sPlayerTank.iMovementModTime > 0 sIAPData.sPlayerTank.iMovementModTime = 0 FLOAT fSoundTankSpeed = (sIAPData.fStageSpeedMod / 10) IF sIAPData.sPlayerTank.iEngineLoopSoundId > -1 AND NOT HAS_SOUND_FINISHED(sIAPData.sPlayerTank.iEngineLoopSoundId) SET_VARIABLE_ON_SOUND(sIAPData.sPlayerTank.iEngineLoopSoundId, "TankSpeed", fSoundTankSpeed) ENDIF ENDIF //Jumping IF IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_Jump) IAP_JUMP() ENDIF //Turret Rotation FLOAT fRightStickX = GET_DISABLED_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_RIGHT_AXIS_X) IF (CA_RotateLeft != MAX_INPUTS AND IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_RotateLeft)) IAP_ROTATE_TURRET(1, TRUE) ELIF (CA_RotateRight != MAX_INPUTS AND IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_RotateRight)) IAP_ROTATE_TURRET(-1, TRUE) ELIF (CA_RotateLeft != MAX_INPUTS AND IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_RotateLeft)) OR fRightStickX < -cfSTICK_THRESHOLD * fAxisThresholdMod IAP_ROTATE_TURRET(1, FALSE, fRightStickX) ELIF (CA_RotateRight != MAX_INPUTS AND IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_RotateRight)) OR fRightStickX > cfSTICK_THRESHOLD * fAxisThresholdMod IAP_ROTATE_TURRET(-1, FALSE, fRightStickX) ENDIF IF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_TurretFront) OR (CA_TurretFrontAlt != MAX_INPUTS AND IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_TurretFrontAlt)) IF sIAPData.sPlayerTank.iTurretDirection != 0 IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Turret_Move", sIAPData.sPlayerTank.iTurretSoundId) ENDIF sIAPData.sPlayerTank.iTurretDirection = 0 sIAPData.sPlayerTank.iLastFrameTurretDirection = 0 //Skip extra beam processing - too powerful ENDIF ENDPROC /// PURPOSE: /// Processes player input after movement has been applied this frame PROC IAP_PROCESS_INPUT_POST_MOVEMENT() IF IS_IAP_INPUT_DISABLED_THIS_FRAME() IAP_STOP_TANK_WEAPON_LOOP() EXIT ENDIF CONTROL_ACTION CA_Shoot = INPUT_SCRIPT_RDOWN CONTROL_ACTION CA_Shoot_Alt = INPUT_SCRIPT_RT IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) CA_Shoot = INPUT_CURSOR_ACCEPT CA_Shoot_Alt = INPUT_VEH_ATTACK2 ENDIF //Shooting IF IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_Shoot) OR (CA_Shoot_Alt != MAX_INPUTS AND IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, CA_Shoot_Alt)) IAP_SHOOT(sIAPData.sPlayerTank.eWeaponType = IAP_PLAYER_WEAPON_DEFAULT) ELIF IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_Shoot) OR (CA_Shoot_Alt != MAX_INPUTS AND IS_DISABLED_CONTROL_PRESSED(FRONTEND_CONTROL, CA_Shoot_Alt)) IAP_SHOOT() ELIF sIAPData.sPlayerTank.iWeaponLoopSoundId > -1 IAP_STOP_TANK_WEAPON_LOOP() ENDIF ENDPROC // ------------------------------ PICKUPS ------------------------------ /// PURPOSE: /// Returns a valid pickup type for a random pickup's reward FUNC IAP_OBJECT IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP(INT iObjectIndex) IAP_OBJECT eValidPickups[ciIAP_PICKUP_MAX] INT iCount = 0 IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_FLAMETHROWER) = 0 AND sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_FLAMETHROWER eValidPickups[iCount] = IAP_OBJECT_PICKUP_FLAMETHROWER iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_FLAMETHROWER)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_ROCKETS) = 0 AND sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_ROCKET_LAUNCHER eValidPickups[iCount] = IAP_OBJECT_PICKUP_ROCKETS iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_ROCKETS)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_HEALTH) = 0 AND sIAPData.sPlayerTank.iHealth < ciIAP_MAX_HEALTH eValidPickups[iCount] = IAP_OBJECT_PICKUP_HEALTH iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_HEALTH)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_LIFE) = 0 eValidPickups[iCount] = IAP_OBJECT_PICKUP_LIFE iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_LIFE)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_SCORE) = 0 eValidPickups[iCount] = IAP_OBJECT_PICKUP_SCORE iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_SCORE)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_SHIELD) = 0 AND NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHIELD_ACTIVE) eValidPickups[iCount] = IAP_OBJECT_PICKUP_SHIELD iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_SHIELD)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_ENEMY) = 0 eValidPickups[iCount] = IAP_OBJECT_PICKUP_ENEMY iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_ENEMY)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_PLASMA) = 0 AND sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_PLASMA eValidPickups[iCount] = IAP_OBJECT_PICKUP_PLASMA iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_PLASMA)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_TRIPLE) = 0 AND sIAPData.sPlayerTank.eWeaponType = IAP_PLAYER_WEAPON_DEFAULT AND NOT IAP_IS_TRIPLE_FIRE_ACTIVE() eValidPickups[iCount] = IAP_OBJECT_PICKUP_TRIPLE iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_TRIPLE)) #ENDIF ENDIF IF (sIAPData.sObjectInstances[iObjectIndex].iFlags & ciIAP_OBJECT_FLAG_PICKUP_BLOCK_RANDOM_NUKE) = 0 AND NOT IAP_IS_NUKE_ACTIVE() eValidPickups[iCount] = IAP_OBJECT_PICKUP_NUKE iCount++ #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Blocking ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(IAP_OBJECT_PICKUP_NUKE)) #ENDIF ENDIF #IF IS_DEBUG_BUILD IF iCount = 0 ASSERTLN("[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - NO VALID PICKUP TYPES!") ENDIF #ENDIF IAP_OBJECT ePickup = eValidPickups[GET_RANDOM_INT_IN_RANGE(0, iCount)] CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP - Returning ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(ePickup)) RETURN ePickup ENDFUNC /// PURPOSE: /// Sets a pickup as collected and applies it's effect PROC IAP_COLLECT_PICKUP(INT iObjectIndex, BOOL bFromRandom = FALSE) SWITCH sIAPData.sObjectInstances[iObjectIndex].eObjectType CASE IAP_OBJECT_PICKUP_FLAMETHROWER IF sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_FLAMETHROWER IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_FLAME") IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_FLAMETHROWER) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Weapon_Change", sIAPData.sPlayerTank.iGeneralSoundId) ELSE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_WAO") IAP_ADD_SCORE(1000, IAP_SCORE_TYPE_PICKUP, INIT_VECTOR_2D(-1,-1)) ENDIF BREAK CASE IAP_OBJECT_PICKUP_ROCKETS IF sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_ROCKET_LAUNCHER IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_ROCKETS") IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_ROCKET_LAUNCHER) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Weapon_Change", sIAPData.sPlayerTank.iGeneralSoundId) ELSE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_WAO") IAP_ADD_SCORE(1000, IAP_SCORE_TYPE_PICKUP, INIT_VECTOR_2D(-1,-1)) ENDIF BREAK CASE IAP_OBJECT_PICKUP_PLASMA IF sIAPData.sPlayerTank.eWeaponType != IAP_PLAYER_WEAPON_PLASMA IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_PLASMA") IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_PLASMA) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Weapon_Change", sIAPData.sPlayerTank.iGeneralSoundId) ELSE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_WAO") IAP_ADD_SCORE(1000, IAP_SCORE_TYPE_PICKUP, INIT_VECTOR_2D(-1,-1)) ENDIF BREAK CASE IAP_OBJECT_PICKUP_HEALTH IF sIAPData.sPlayerTank.iHealth = ciIAP_MAX_HEALTH IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_HPO") sIAPData.sPlayerTank.iLives ++ ELSE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_HP") IAP_CHANGE_PLAYER_HEALTH(ciIAP_MAX_HEALTH / 5) ENDIF BREAK CASE IAP_OBJECT_PICKUP_LIFE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_1UP") sIAPData.sPlayerTank.iLives ++ BREAK CASE IAP_OBJECT_PICKUP_ENEMY IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_ARMOR") IAP_CHANGE_PLAYER_HEALTH(-ciIAP_MAX_HEALTH / 5) BREAK CASE IAP_OBJECT_PICKUP_SCORE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_SCORE") IAP_ADD_SCORE(ciIAP_PICKUP_SCORE_VALUE, IAP_SCORE_TYPE_PICKUP, INIT_VECTOR_2D(-1,-1)) BREAK CASE IAP_OBJECT_PICKUP_RANDOM IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION(IAP_GET_PICKUP_COLLECTION_SOUND(sIAPData.sObjectInstances[iObjectIndex].eObjectType), "dlc_vw_am_ip_powerup_sounds", sIAPData.sObjectInstances[iObjectIndex].vPosition) sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_GET_RANDOM_PICKUP_EFFECT_FOR_PICKUP(iObjectIndex) IAP_COLLECT_PICKUP(iObjectIndex, TRUE) EXIT CASE IAP_OBJECT_PICKUP_SHIELD IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_SHIELD") IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHIELD_ACTIVE) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_COLLECT_PICKUP - Shield activated") SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHIELD_ACTIVE) ELSE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_SAO") IAP_ADD_SCORE(1000, IAP_SCORE_TYPE_PICKUP, INIT_VECTOR_2D(-1,-1)) ENDIF BREAK CASE IAP_OBJECT_PICKUP_TRIPLE IF sIAPData.sPlayerTank.eWeaponType = IAP_PLAYER_WEAPON_DEFAULT AND NOT IAP_IS_TRIPLE_FIRE_ACTIVE() IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_TRIPLE") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_COLLECT_PICKUP - Triple Fire activated") SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_TRIPLE_SHOT_ACTIVE) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Weapon_Change", sIAPData.sPlayerTank.iGeneralSoundId) ELSE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_WAO") IAP_ADD_SCORE(1000, IAP_SCORE_TYPE_PICKUP, INIT_VECTOR_2D(-1,-1)) ENDIF BREAK CASE IAP_OBJECT_PICKUP_NUKE IAP_ADD_ABOVE_PLAYER_TEXT("IAP_PU_NUKE") IAP_NUKE_SCREEN() BREAK ENDSWITCH sIAPData.sScoreTracking.iPickupsCollected ++ sIAPData.sScoreTracking.iTotalPickupsCollected ++ IF sIAPData.sPlayerTank.iLives > ciIAP_STARTING_LIVES_CHEATED sIAPData.sPlayerTank.iLives = ciIAP_STARTING_LIVES_CHEATED ENDIF IF NOT bFromRandom IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION(IAP_GET_PICKUP_COLLECTION_SOUND(sIAPData.sObjectInstances[iObjectIndex].eObjectType), "dlc_vw_am_ip_powerup_sounds", sIAPData.sObjectInstances[iObjectIndex].vPosition) ENDIF ENDPROC // ------------------------------ COLLISION ------------------------------ /// PURPOSE: /// Returns the the scale of the projectile covering its current and last frame positions for collision FUNC VECTOR_2D IAP_GET_PROJECTILE_SCALE_THIS_FRAME(VECTOR_2D vThisFramePos, VECTOR_2D vLastFramePos, VECTOR_2D vSpriteScale) VECTOR_2D vScale FLOAT fXDist = ABSF(vThisFramePos.x - vLastFramePos.x) FLOAT fYDist = ABSF(vThisFramePos.y - vLastFramePos.y) vScale = INIT_VECTOR_2D(fXDist + vSpriteScale.x, fYDist + vSpriteScale.y) RETURN vScale ENDFUNC /// PURPOSE: /// Main collision processing loop PROC IAP_PROCESS_COLLISIONS() #IF IS_DEBUG_BUILD INT iDebugLoop RGBA_COLOUR_STRUCT rgba #ENDIF FLOAT fCos FLOAT fSin //Player Collision //Tank: VECTOR_2D vPlayerCorners[4] vPlayerCorners[0] = INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_TANK_COLLISION_BOTTOM_LEFT_X, sIAPData.sPlayerTank.vPosition.y + cfIAP_TANK_COLLISION_BOTTOM_LEFT_Y) vPlayerCorners[1] = INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_TANK_COLLISION_TOP_LEFT_X, sIAPData.sPlayerTank.vPosition.y + cfIAP_TANK_COLLISION_TOP_LEFT_Y) vPlayerCorners[2] = INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_TANK_COLLISION_TOP_RIGHT_X, sIAPData.sPlayerTank.vPosition.y + cfIAP_TANK_COLLISION_TOP_RIGHT_Y) vPlayerCorners[3] = INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_TANK_COLLISION_BOTTOM_RIGHT_X, sIAPData.sPlayerTank.vPosition.y + cfIAP_TANK_COLLISION_BOTTOM_RIGHT_Y) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug INIT_RGBA_STRUCT(rgba, 0, 255, 0, 255) FOR iDebugLoop = 0 TO 3 INT iNext = iDebugLoop + 1 IF iNext > 3 iNext = 0 ENDIF DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(vPlayerCorners[iDebugLoop], vPlayerCorners[iNext], rgba) ENDFOR ENDIF #ENDIF //Turret: FLOAT fJumpOffset = 0 IF sIAPData.sPlayerTank.eTankState = IAP_PLAYER_TANK_STATE_JUMPING OR sIAPData.sPlayerTank.eTankState = IAP_PLAYER_TANK_STATE_FALLING OR sIAPData.sPlayerTank.eTankState = IAP_PLAYER_TANK_STATE_RESPAWNING fJumpOffset = -((cfIAP_PLAYER_TANK_JUMP_SCALE_Y - cfIAP_PLAYER_TANK_SCALE_Y) / 2) ENDIF VECTOR_2D vPlayerTurretCorners[3] VECTOR_2D vTurretCenter = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(sIAPData.sPlayerTank.vPosition.x + cfIAP_TURRET_OFFSET_X, sIAPData.sPlayerTank.vPosition.y + cfIAP_TURRET_SPRITE_OFFSET_Y + fJumpOffset)) vPlayerTurretCorners[0] = ADD_VECTOR_2D(vTurretCenter, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(cfIAP_TURRET_COLLISION_BOTTOM_LEFT_X, cfIAP_TURRET_COLLISION_BOTTOM_LEFT_Y))) vPlayerTurretCorners[1] = ADD_VECTOR_2D(vTurretCenter, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(cfIAP_TURRET_COLLISION_TOP_LEFT_X, cfIAP_TURRET_COLLISION_TOP_LEFT_Y))) vPlayerTurretCorners[2] = ADD_VECTOR_2D(vTurretCenter, ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(INIT_VECTOR_2D(cfIAP_TURRET_COLLISION_CENTRE_RIGHT_X, cfIAP_TURRET_COLLISION_CENTRE_RIGHT_Y))) IF sIAPData.sPlayerTank.iTurretDirection != 0 fSin = SIN(sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT) fCos = COS(sIAPData.sPlayerTank.iTurretDirection * cfIAP_TURRET_DIRECTION_INCREMENT) vPlayerTurretCorners[0] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vTurretCenter, vPlayerTurretCorners[0], fSin, fCos) vPlayerTurretCorners[1] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vTurretCenter, vPlayerTurretCorners[1], fSin, fCos) vPlayerTurretCorners[2] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vTurretCenter, vPlayerTurretCorners[2], fSin, fCos) ENDIF vPlayerTurretCorners[0] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vPlayerTurretCorners[0]) vPlayerTurretCorners[1] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vPlayerTurretCorners[1]) vPlayerTurretCorners[2] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vPlayerTurretCorners[2]) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug INIT_RGBA_STRUCT(rgba, 0, 200, 55, 255) FOR iDebugLoop = 0 TO 2 INT iNext = iDebugLoop + 1 IF iNext > 2 iNext = 0 ENDIF DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(vPlayerTurretCorners[iDebugLoop], vPlayerTurretCorners[iNext], rgba) ENDFOR ENDIF #ENDIF //Player Projectiles: VECTOR_2D vPlayerProjectileCorners[ciIAP_MAX_PLAYER_PROJECTILES][4] VECTOR_2D vFlatCurrentPos, vFlatPreviousPos INT iProjectileIndex = 0 FOR iProjectileIndex = 0 TO ciIAP_MAX_PLAYER_PROJECTILES - 1 IF sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT RELOOP ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].iShotTime + sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].eProjectileType].iSpeed RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].vThisFramePos, INIT_VECTOR_2D(cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE)) RELOOP ENDIF IF sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].eProjectileType = IAP_PROJECTILE_TYPE_PLASMA RELOOP ENDIF VECTOR_2D vCurrentPosPixels = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].vThisFramePos) VECTOR_2D vPreviousPosPixels = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].vPreviousFramePos) VECTOR_2D vMidPoint = DIVIDE_VECTOR_2D(ADD_VECTOR_2D(vCurrentPosPixels, vPreviousPosPixels), 2) IF NOT IS_FLOAT_IN_RANGE(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].fRotation, -cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE) fSin = SIN(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].fRotation) fCos = COS(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].fRotation) vFlatCurrentPos = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vCurrentPosPixels, -fSin, fCos) vFlatPreviousPos = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vPreviousPosPixels, -fSin, fCos) ELSE vFlatCurrentPos = vCurrentPosPixels vFlatPreviousPos = vPreviousPosPixels ENDIF VECTOR_2D vSpriteScale = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(DIVIDE_VECTOR_2D(sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale, 2)) vPlayerProjectileCorners[iProjectileIndex][0].x = vFlatPreviousPos.x - vSpriteScale.x vPlayerProjectileCorners[iProjectileIndex][1].x = vPlayerProjectileCorners[iProjectileIndex][0].x vPlayerProjectileCorners[iProjectileIndex][2].x = vFlatCurrentPos.x + vSpriteScale.x vPlayerProjectileCorners[iProjectileIndex][3].x = vPlayerProjectileCorners[iProjectileIndex][2].x vPlayerProjectileCorners[iProjectileIndex][0].y = vFlatPreviousPos.y + vSpriteScale.y vPlayerProjectileCorners[iProjectileIndex][1].y = vFlatCurrentPos.y - vSpriteScale.y vPlayerProjectileCorners[iProjectileIndex][2].y = vPlayerProjectileCorners[iProjectileIndex][1].y vPlayerProjectileCorners[iProjectileIndex][3].y = vPlayerProjectileCorners[iProjectileIndex][0].y IF NOT IS_FLOAT_IN_RANGE(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].fRotation, -cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE) vPlayerProjectileCorners[iProjectileIndex][0] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vPlayerProjectileCorners[iProjectileIndex][0], fSin, fCos) vPlayerProjectileCorners[iProjectileIndex][1] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vPlayerProjectileCorners[iProjectileIndex][1], fSin, fCos) vPlayerProjectileCorners[iProjectileIndex][2] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vPlayerProjectileCorners[iProjectileIndex][2], fSin, fCos) vPlayerProjectileCorners[iProjectileIndex][3] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vPlayerProjectileCorners[iProjectileIndex][3], fSin, fCos) ENDIF vPlayerProjectileCorners[iProjectileIndex][0] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vPlayerProjectileCorners[iProjectileIndex][0]) vPlayerProjectileCorners[iProjectileIndex][1] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vPlayerProjectileCorners[iProjectileIndex][1]) vPlayerProjectileCorners[iProjectileIndex][2] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vPlayerProjectileCorners[iProjectileIndex][2]) vPlayerProjectileCorners[iProjectileIndex][3] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vPlayerProjectileCorners[iProjectileIndex][3]) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug INIT_RGBA_STRUCT(rgba, 0, 175, 175, 255) DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(vPlayerProjectileCorners[iProjectileIndex][0], vPlayerProjectileCorners[iProjectileIndex][2], rgba) DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(vPlayerProjectileCorners[iProjectileIndex][1], vPlayerProjectileCorners[iProjectileIndex][3], rgba) ENDIF #ENDIF ENDFOR //Enemy Projectiles: VECTOR_2D vEnemyProjectileCorners[ciIAP_MAX_ENEMY_PROJECTILES][4] FOR iProjectileIndex = 0 TO ciIAP_MAX_ENEMY_PROJECTILES - 1 IF sIAPData.sEnemyProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT RELOOP ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sEnemyProjectileInstances[iProjectileIndex].iShotTime + sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType].iSpeed RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos, INIT_VECTOR_2D(cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE)) RELOOP ENDIF VECTOR_2D vCurrentPosPixels = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) VECTOR_2D vPreviousPosPixels = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sEnemyProjectileInstances[iProjectileIndex].vPreviousFramePos) VECTOR_2D vMidPoint = DIVIDE_VECTOR_2D(ADD_VECTOR_2D(vCurrentPosPixels, vPreviousPosPixels), 2) IF NOT IS_FLOAT_IN_RANGE(sIAPData.sEnemyProjectileInstances[iProjectileIndex].fRotation, -cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE) fSin = SIN(sIAPData.sEnemyProjectileInstances[iProjectileIndex].fRotation) fCos = COS(sIAPData.sEnemyProjectileInstances[iProjectileIndex].fRotation) vFlatCurrentPos = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vCurrentPosPixels, -fSin, fCos) vFlatPreviousPos = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vPreviousPosPixels, -fSin, fCos) ELSE vFlatCurrentPos = vCurrentPosPixels vFlatPreviousPos = vPreviousPosPixels ENDIF VECTOR_2D vSpriteScale = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(DIVIDE_VECTOR_2D(sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale, 2)) vEnemyProjectileCorners[iProjectileIndex][0].x = vFlatCurrentPos.x - vSpriteScale.x vEnemyProjectileCorners[iProjectileIndex][1].x = vEnemyProjectileCorners[iProjectileIndex][0].x vEnemyProjectileCorners[iProjectileIndex][2].x = vFlatPreviousPos.x + vSpriteScale.x vEnemyProjectileCorners[iProjectileIndex][3].x = vEnemyProjectileCorners[iProjectileIndex][2].x vEnemyProjectileCorners[iProjectileIndex][0].y = vFlatPreviousPos.y + vSpriteScale.y vEnemyProjectileCorners[iProjectileIndex][1].y = vFlatCurrentPos.y - vSpriteScale.y vEnemyProjectileCorners[iProjectileIndex][2].y = vEnemyProjectileCorners[iProjectileIndex][1].y vEnemyProjectileCorners[iProjectileIndex][3].y = vEnemyProjectileCorners[iProjectileIndex][0].y IF NOT IS_FLOAT_IN_RANGE(sIAPData.sEnemyProjectileInstances[iProjectileIndex].fRotation, -cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE) vEnemyProjectileCorners[iProjectileIndex][0] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vEnemyProjectileCorners[iProjectileIndex][0], fSin, fCos) vEnemyProjectileCorners[iProjectileIndex][1] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vEnemyProjectileCorners[iProjectileIndex][1], fSin, fCos) vEnemyProjectileCorners[iProjectileIndex][2] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vEnemyProjectileCorners[iProjectileIndex][2], fSin, fCos) vEnemyProjectileCorners[iProjectileIndex][3] = ROTATE_VECTOR_2D_AROUND_VECTOR_2D_PRECOMPUTE(vMidPoint, vEnemyProjectileCorners[iProjectileIndex][3], fSin, fCos) ENDIF vEnemyProjectileCorners[iProjectileIndex][0] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vEnemyProjectileCorners[iProjectileIndex][0]) vEnemyProjectileCorners[iProjectileIndex][1] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vEnemyProjectileCorners[iProjectileIndex][1]) vEnemyProjectileCorners[iProjectileIndex][2] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vEnemyProjectileCorners[iProjectileIndex][2]) vEnemyProjectileCorners[iProjectileIndex][3] = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(vEnemyProjectileCorners[iProjectileIndex][3]) #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug INIT_RGBA_STRUCT(rgba, 175, 0, 175, 255) DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(vEnemyProjectileCorners[iProjectileIndex][0], vEnemyProjectileCorners[iProjectileIndex][2], rgba) DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(vEnemyProjectileCorners[iProjectileIndex][1], vEnemyProjectileCorners[iProjectileIndex][3], rgba) ENDIF #ENDIF ENDFOR //Object Collision VECTOR_2D vObjectCorners[4] VECTOR_2D vIntersectionPoint = INIT_VECTOR_2D(-1, -1) INT iObjectIndex, i, j FLOAT fDistanceX, fDistanceY FOR iObjectIndex = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 IF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_NONE RELOOP ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_OIL RELOOP ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL RELOOP ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_LEDGE RELOOP ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iHealth = 0 RELOOP ENDIF IF sIAPData.sObjectInstances[iObjectIndex].vPosition.x - (sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale.x / 2) > (1 - cfIAP_FACADE_WIDTH) RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sObjectInstances[iObjectIndex].vPosition, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale) RELOOP ENDIF VECTOR_2D vPos = sIAPData.sObjectInstances[iObjectIndex].vPosition FOR i = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 vObjectCorners[i] = ADD_VECTOR_2D(vPos, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vCollisionBounds[i]) ENDFOR #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug INIT_RGBA_STRUCT(rgba, 255, 0, 0, 255) FOR iDebugLoop = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 INT iNext = iDebugLoop + 1 IF iNext > 3 iNext = 0 ENDIF DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(vObjectCorners[iDebugLoop], vObjectCorners[iNext], rgba) ENDFOR ENDIF #ENDIF //Object Vs Player Tank Collision IF sIAPData.sPlayerTank.iHealth > 0 AND sIAPData.sPlayerTank.eTankState != IAP_PLAYER_TANK_STATE_EXPLODING fDistanceX = ABSF(vPos.x - sIAPData.sPlayerTank.vPosition.x) fDistanceY = ABSF(vPos.y - sIAPData.sPlayerTank.vPosition.y) IF fDistanceX <= FMAX(sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale.x,cfIAP_PLAYER_TANK_SCALE_X) AND fDistanceY <= FMAX(sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale.y, cfIAP_PLAYER_TANK_SCALE_Y) BOOL bHit = FALSE FOR i = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 INT iNext = i + 1 IF iNext >= ciIAP_MAX_OBJECT_COLLISION_POINTS iNext = 0 ENDIF FOR j = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 INT jNext = j + 1 IF jNext >= ciIAP_MAX_OBJECT_COLLISION_POINTS jNext = 0 ENDIF IF ARCADE_CABINET_GET_LINE_INTERSECT(vPlayerCorners[i], vPlayerCorners[iNext], vObjectCorners[j], vObjectCorners[jNext], vIntersectionPoint) IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP IAP_COLLECT_PICKUP(iObjectIndex) sIAPData.sObjectInstances[iObjectIndex].iHealth = 0 ELSE IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType != IAP_OBJECT_TYPE_INDESTRUCTABLE_HAZARD IAP_UPDATE_OBJECT_HEALTH(iObjectIndex, -sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].iMaxHealth) ENDIF IF (sIAPData.sPlayerTank.iLastDamagedTime + ciIAP_PLAYER_DAMAGE_RED_TIME < NATIVE_TO_INT(GET_NETWORK_TIME()) AND sIAPData.sPlayerTank.iRespawnTime + ciIAP_PLAYER_RESPAWN_INVULN_TIME < NATIVE_TO_INT(GET_NETWORK_TIME())) IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_TANK("Tank_Collision", sIAPData.sPlayerTank.iGeneralSoundId) ENDIF IAP_CHANGE_PLAYER_HEALTH(-ciIAP_DEFAULT_PLAYER_OBJECT_COLLISION_DAMAGE) ENDIF bHit = TRUE BREAKLOOP ENDIF ENDFOR IF bHit BREAKLOOP ENDIF ENDFOR IF bHit RELOOP ENDIF ENDIF ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_LEDGE RELOOP ENDIF //Object Vs Player Projectile Collision FOR iProjectileIndex = 0 TO ciIAP_MAX_PLAYER_PROJECTILES - 1 IF sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT RELOOP ENDIF IF sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].eProjectileType = IAP_PROJECTILE_TYPE_PLASMA RELOOP ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].iShotTime + sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].eProjectileType].iSpeed RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].vThisFramePos, INIT_VECTOR_2D(cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE)) RELOOP ENDIF fDistanceX = ABSF(vPos.x - sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].vThisFramePos.x) fDistanceY = ABSF(vPos.y - sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].vThisFramePos.y) IF fDistanceX <= sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale.x + sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale.x AND fDistanceY <= sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale.y + sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale.y BOOL bHit = FALSE FOR i = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 INT iNext = i + 1 IF iNext >= ciIAP_MAX_OBJECT_COLLISION_POINTS iNext = 0 ENDIF IF ARCADE_CABINET_GET_LINE_INTERSECT(vPlayerProjectileCorners[iProjectileIndex][0], vPlayerProjectileCorners[iProjectileIndex][2], vObjectCorners[i], vObjectCorners[iNext], vIntersectionPoint) OR ARCADE_CABINET_GET_LINE_INTERSECT(vPlayerProjectileCorners[iProjectileIndex][1], vPlayerProjectileCorners[iProjectileIndex][3], vObjectCorners[i], vObjectCorners[iNext], vIntersectionPoint) IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType != IAP_OBJECT_TYPE_INDESTRUCTABLE_HAZARD IAP_UPDATE_OBJECT_HEALTH(iObjectIndex, -sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].iDamage) ENDIF IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION(IAP_GET_HIT_SOUND_FOR_PLAYER_PROJECTILE(sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].eProjectileType), "dlc_vw_am_ip_tank_sounds", sIAPData.sPlayerTank.sProjectileInstances[i].vThisFramePos) IAP_ADD_EXPLOSION_AT_COORDS(vIntersectionPoint) sIAPData.sPlayerTank.sProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT bHit = TRUE BREAKLOOP ENDIF ENDFOR IF bHit RELOOP ENDIF ENDIF ENDFOR ENDFOR IF sIAPData.sPlayerTank.eWeaponType = IAP_PLAYER_WEAPON_PLASMA AND sIAPData.sPlayerTank.sProjectileInstances[0].iShotTime != -HIGHEST_INT AND sIAPData.sPlayerTank.sProjectileInstances[0].eProjectileType = IAP_PROJECTILE_TYPE_PLASMA AND NATIVE_TO_INT(GET_NETWORK_TIME()) <= sIAPData.sPlayerTank.sProjectileInstances[0].iShotTime + sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[0].eProjectileType].iSpeed INT iHitObjectsBS = 0 INT iClosestObjectIndex = -1 INT iTargetsHit = 0 FLOAT fClosestDist2 = MAX_FLOAT VECTOR_2D vIntersect = INIT_VECTOR_2D(-1, -1) FOR iObjectIndex = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 IF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_NONE RELOOP ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_LEDGE OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_OIL RELOOP ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iHealth = 0 RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sObjectInstances[iObjectIndex].vPosition, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale) RELOOP ENDIF VECTOR_2D vPos = sIAPData.sObjectInstances[iObjectIndex].vPosition FOR i = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 vObjectCorners[i] = ADD_VECTOR_2D(vPos, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vCollisionBounds[i]) ENDFOR FOR i = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 INT iNext = i + 1 IF iNext >= ciIAP_MAX_OBJECT_COLLISION_POINTS iNext = 0 ENDIF IF ARCADE_CABINET_GET_LINE_INTERSECT(sIAPData.sPlayerTank.sProjectileInstances[0].vOrigin, sIAPData.sPlayerTank.sProjectileInstances[0].vDirection, vObjectCorners[i], vObjectCorners[iNext], vIntersectionPoint) FLOAT fDist2 = VECTOR_2D_DIST2(sIAPData.sPlayerTank.sProjectileInstances[0].vOrigin, vIntersectionPoint) IF fDist2 < fClosestDist2 fClosestDist2 = fDist2 iClosestObjectIndex = iObjectIndex vIntersect = vIntersectionPoint ENDIF ENDIF ENDFOR ENDFOR IF iClosestObjectIndex != -1 iTargetsHit++ SET_BIT(iHitObjectsBS, iClosestObjectIndex) sIAPData.sPlayerTank.sProjectileInstances[0].vDirection = vIntersect IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iClosestObjectIndex].eObjectType)].eObjectType != IAP_OBJECT_TYPE_INDESTRUCTABLE_HAZARD IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sObjectInstances[iClosestObjectIndex].iLastDamagedTime + (ciIAP_PLASMA_DAMAGE_INTERVAL * IAP_GET_STAGE_WEAPON_SPEED_MOD()) IAP_UPDATE_OBJECT_HEALTH(iClosestObjectIndex, -sIAPData.sPlayerTank.sProjectileInstances[0].iDamage) ENDIF VECTOR_2D v0, v1 FOR i = 0 TO ciIAP_PLASMA_BOUNCE_MAX - 1 BOOL bTargetAquired = FALSE FOR iObjectIndex = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 IF IS_BIT_SET(iHitObjectsBS, iObjectIndex) RELOOP ENDIF IF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_NONE RELOOP ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_LEDGE OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_OIL OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_INDESTRUCTABLE_HAZARD RELOOP ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iHealth = 0 RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sObjectInstances[iObjectIndex].vPosition, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale) RELOOP ENDIF VECTOR_2D vPos = sIAPData.sObjectInstances[iObjectIndex].vPosition IF VECTOR_2D_DIST2(sIAPData.sPlayerTank.sProjectileInstances[i].vDirection, vPos) < POW(cfIAP_PLASMA_BOUNCE_MAX_DISTANCE, 2) SET_BIT(iHitObjectsBS, iObjectIndex) bTargetAquired = TRUE iTargetsHit++ v0 = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sPlayerTank.sProjectileInstances[i].vDirection) v1 = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(vPos) sIAPData.sPlayerTank.sProjectileInstances[i + 1].eProjectileType = IAP_PROJECTILE_TYPE_PLASMA sIAPData.sPlayerTank.sProjectileInstances[i + 1].vOrigin = sIAPData.sPlayerTank.sProjectileInstances[i].vDirection sIAPData.sPlayerTank.sProjectileInstances[i + 1].vDirection = vPos sIAPData.sPlayerTank.sProjectileInstances[i + 1].vThisFramePos = sIAPData.sPlayerTank.sProjectileInstances[i + 1].vOrigin sIAPData.sPlayerTank.sProjectileInstances[i + 1].fRotation = ATAN2(v1.y - v0.y, v1.x - v0.x) sIAPData.sPlayerTank.sProjectileInstances[i + 1].iShotTime = NATIVE_TO_INT(GET_NETWORK_TIME()) sIAPData.sPlayerTank.sProjectileInstances[i + 1].iDamage = ciIAP_PLASMA_WEAPON_DAMAGE sIAPData.sPlayerTank.sProjectileInstances[i + 1].iAnimFrame = IAP_GET_CURRENT_WEAPON_START_ANIM_FRAME() IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sObjectInstances[iObjectIndex].iLastDamagedTime + (ciIAP_PLASMA_DAMAGE_INTERVAL * IAP_GET_STAGE_WEAPON_SPEED_MOD()) IAP_UPDATE_OBJECT_HEALTH(iObjectIndex, -sIAPData.sPlayerTank.sProjectileInstances[0].iDamage) ENDIF #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug INIT_RGBA_STRUCT(rgba, 0, 175, 175, 255) DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(sIAPData.sPlayerTank.sProjectileInstances[i+1].vOrigin, sIAPData.sPlayerTank.sProjectileInstances[i+1].vDirection, rgba) ENDIF #ENDIF BREAKLOOP ENDIF ENDFOR IF NOT bTargetAquired BREAKLOOP ENDIF ENDFOR IAP_PLAY_PLASMA_HIT_AT_POSITION(sIAPData.sPlayerTank.sProjectileInstances[0].vDirection, iTargetsHit) ENDIF ENDIF IF sIAPData.sPlayerTank.iLastFrameTurretDirection != sIAPData.sPlayerTank.iTurretDirection //Fake sweeping plasma FLOAT fMidRotation = 0.0 IF sIAPData.sPlayerTank.iLastFrameTurretDirection > sIAPData.sPlayerTank.iTurretDirection fMidRotation = cfIAP_TURRET_DIRECTION_INCREMENT / 2 ELSE fMidRotation = -cfIAP_TURRET_DIRECTION_INCREMENT/ 2 ENDIF VECTOR_2D vMidEnd = ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_SCREENSPACE(ROTATE_VECTOR_2D_AROUND_VECTOR_2D(ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sPlayerTank.sProjectileInstances[0].vOrigin), ARCADE_CABINET_CONVERT_TO_VECTOR_2D_TO_PIXELSPACE(sIAPData.sPlayerTank.sProjectileInstances[0].vDirection), fMidRotation)) iClosestObjectIndex = -1 fClosestDist2 = MAX_FLOAT FOR iObjectIndex = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 IF IS_BIT_SET(iHitObjectsBS, iObjectIndex) RELOOP ENDIF IF sIAPData.sObjectInstances[iObjectIndex].eObjectType = IAP_OBJECT_NONE RELOOP ENDIF IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PICKUP OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_PITFALL OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_LEDGE OR sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].eObjectType = IAP_OBJECT_TYPE_OIL RELOOP ENDIF IF sIAPData.sObjectInstances[iObjectIndex].iHealth = 0 RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sObjectInstances[iObjectIndex].vPosition, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vSpriteScale) RELOOP ENDIF VECTOR_2D vPos = sIAPData.sObjectInstances[iObjectIndex].vPosition FOR i = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 vObjectCorners[i] = ADD_VECTOR_2D(vPos, sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iObjectIndex].eObjectType)].vCollisionBounds[i]) ENDFOR FOR i = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 INT iNext = i + 1 IF iNext >= ciIAP_MAX_OBJECT_COLLISION_POINTS iNext = 0 ENDIF IF ARCADE_CABINET_GET_LINE_INTERSECT(sIAPData.sPlayerTank.sProjectileInstances[0].vOrigin, vMidEnd, vObjectCorners[i], vObjectCorners[iNext], vIntersectionPoint) FLOAT fDist2 = VECTOR_2D_DIST2(sIAPData.sPlayerTank.sProjectileInstances[0].vOrigin, vIntersectionPoint) IF fDist2 < fClosestDist2 fClosestDist2 = fDist2 iClosestObjectIndex = iObjectIndex vIntersect = vIntersectionPoint ENDIF ENDIF ENDFOR ENDFOR IF iClosestObjectIndex != -1 vMidEnd = vIntersect IF sIAPData.sObjectData[ENUM_TO_INT(sIAPData.sObjectInstances[iClosestObjectIndex].eObjectType)].eObjectType != IAP_OBJECT_TYPE_INDESTRUCTABLE_HAZARD IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sObjectInstances[iClosestObjectIndex].iLastDamagedTime + (ciIAP_PLASMA_DAMAGE_INTERVAL * IAP_GET_STAGE_WEAPON_SPEED_MOD()) IAP_UPDATE_OBJECT_HEALTH(iClosestObjectIndex, -sIAPData.sPlayerTank.sProjectileInstances[0].iDamage) ENDIF ENDIF ENDIF #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug INIT_RGBA_STRUCT(rgba, 0, 0, 0, 255) DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(sIAPData.sPlayerTank.sProjectileInstances[0].vOrigin, vMidEnd, rgba) ENDIF #ENDIF ENDIF #IF IS_DEBUG_BUILD IF sIAPData.sDebugStruct.bDrawCollisionDebug INIT_RGBA_STRUCT(rgba, 0, 175, 175, 255) DRAW_DEBUG_LINE_2D_FROM_VECTOR_2D(sIAPData.sPlayerTank.sProjectileInstances[0].vOrigin, sIAPData.sPlayerTank.sProjectileInstances[0].vDirection, rgba) ENDIF #ENDIF ENDIF FOR iProjectileIndex = 0 TO ciIAP_MAX_ENEMY_PROJECTILES - 1 IF sIAPData.sEnemyProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT RELOOP ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sEnemyProjectileInstances[iProjectileIndex].iShotTime + sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType].iSpeed RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos, INIT_VECTOR_2D(cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE)) RELOOP ENDIF //Object Projectile Vs Player Tank fDistanceX = ABSF(sIAPData.sPlayerTank.vPosition.x - sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos.x) fDistanceY = ABSF(sIAPData.sPlayerTank.vPosition.y - sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos.y) IF fDistanceX <= cfIAP_PLAYER_TANK_SCALE_X + sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale.x AND fDistanceY <= cfIAP_PLAYER_TANK_SCALE_Y + sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale.y BOOL bHit = FALSE FOR i = 0 TO ciIAP_MAX_OBJECT_COLLISION_POINTS - 1 INT iNext = i + 1 IF iNext >= ciIAP_MAX_OBJECT_COLLISION_POINTS iNext = 0 ENDIF IF ARCADE_CABINET_GET_LINE_INTERSECT(vEnemyProjectileCorners[iProjectileIndex][0], vEnemyProjectileCorners[iProjectileIndex][2], vPlayerCorners[i], vPlayerCorners[iNext], vIntersectionPoint) OR ARCADE_CABINET_GET_LINE_INTERSECT(vEnemyProjectileCorners[iProjectileIndex][1], vEnemyProjectileCorners[iProjectileIndex][3], vPlayerCorners[i], vPlayerCorners[iNext], vIntersectionPoint) IAP_CHANGE_PLAYER_HEALTH(-sIAPData.sEnemyProjectileInstances[iProjectileIndex].iDamage) IAP_ADD_EXPLOSION_AT_COORDS(vIntersectionPoint) sIAPData.sEnemyProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT IF sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType = IAP_PROJECTILE_TYPE_FALLING_BARREL IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Jet_Bomb_Barrel_Explode", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) ELSE IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Blaster_Fire_Hit", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) ENDIF bHit = TRUE BREAKLOOP ENDIF ENDFOR IF bHit RELOOP ENDIF ENDIF //Object Projectile Vs Player Tank Turret fDistanceX = ABSF(sIAPData.sPlayerTank.vPosition.x + cfIAP_TURRET_OFFSET_X - sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos.x) fDistanceY = ABSF(sIAPData.sPlayerTank.vPosition.y + cfIAP_TURRET_SPRITE_OFFSET_Y - sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos.y) IF fDistanceX <= cfIAP_TURRET_SCALE_X + sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale.x AND fDistanceY <= cfIAP_TURRET_SCALE_Y + sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale.y BOOL bHit = FALSE FOR i = 0 TO 2 INT iNext = i + 1 IF iNext > 2 iNext = 0 ENDIF IF ARCADE_CABINET_GET_LINE_INTERSECT(vEnemyProjectileCorners[iProjectileIndex][0], vEnemyProjectileCorners[iProjectileIndex][2], vPlayerTurretCorners[i], vPlayerTurretCorners[iNext], vIntersectionPoint) OR ARCADE_CABINET_GET_LINE_INTERSECT(vEnemyProjectileCorners[iProjectileIndex][1], vEnemyProjectileCorners[iProjectileIndex][3], vPlayerTurretCorners[i], vPlayerTurretCorners[iNext], vIntersectionPoint) IAP_CHANGE_PLAYER_HEALTH(-sIAPData.sEnemyProjectileInstances[iProjectileIndex].iDamage) IAP_ADD_EXPLOSION_AT_COORDS(vIntersectionPoint) sIAPData.sEnemyProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT IF sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType = IAP_PROJECTILE_TYPE_FALLING_BARREL IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Jet_Bomb_Barrel_Explode", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) ELSE IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Blaster_Fire_Hit", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) ENDIF bHit = TRUE BREAKLOOP ENDIF ENDFOR IF bHit RELOOP ENDIF ENDIF //Object Projectile Collision VS Player Projectile INT iPlayerProjectileIndex = 0 FOR iPlayerProjectileIndex = 0 TO ciIAP_MAX_PLAYER_PROJECTILES - 1 IF sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].iShotTime = -HIGHEST_INT RELOOP ENDIF IF NATIVE_TO_INT(GET_NETWORK_TIME()) > sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].iShotTime + sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].eProjectileType].iSpeed RELOOP ENDIF IF sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].eProjectileType = IAP_PROJECTILE_TYPE_PLASMA IF ARCADE_CABINET_GET_LINE_INTERSECT(sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vOrigin, sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vDirection, vEnemyProjectileCorners[iProjectileIndex][0], vEnemyProjectileCorners[iProjectileIndex][2], vIntersectionPoint) OR ARCADE_CABINET_GET_LINE_INTERSECT(sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vOrigin, sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vDirection, vEnemyProjectileCorners[iProjectileIndex][1], vEnemyProjectileCorners[iProjectileIndex][3], vIntersectionPoint) sIAPData.sEnemyProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT IAP_ADD_EXPLOSION_AT_COORDS(vIntersectionPoint) IF sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType = IAP_PROJECTILE_TYPE_FALLING_BARREL IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Jet_Bomb_Barrel_Explode", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) ELSE IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Blaster_Fire_Hit", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) ENDIF BREAKLOOP ENDIF RELOOP ENDIF IF IAP_IS_RECT_COMPLETELY_OUTSIDE_OF_GAME_AREA(sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vThisFramePos, INIT_VECTOR_2D(cfARCADE_MINIGAME_FLOAT_TOLERANCE, cfARCADE_MINIGAME_FLOAT_TOLERANCE)) RELOOP ENDIF fDistanceX = ABSF(sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos.x - sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vThisFramePos.x) fDistanceY = ABSF(sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos.y - sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vThisFramePos.y) VECTOR_2D vPlayerProjectileScale = IAP_GET_PROJECTILE_SCALE_THIS_FRAME(sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vThisFramePos, sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vPreviousFramePos, sIAPData.sProjectileData[sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].eProjectileType].vSpriteScale) VECTOR_2D vEnemyProjectileScale = IAP_GET_PROJECTILE_SCALE_THIS_FRAME(sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos, sIAPData.sEnemyProjectileInstances[iProjectileIndex].vPreviousFramePos, sIAPData.sProjectileData[sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType].vSpriteScale) IF fDistanceX <= vPlayerProjectileScale.x AND fDistanceY <= vPlayerProjectileScale.y AND fDistanceX <= vEnemyProjectileScale.x AND fDistanceY <= vEnemyProjectileScale.y IF ARCADE_CABINET_GET_LINE_INTERSECT(vPlayerProjectileCorners[iPlayerProjectileIndex][0], vPlayerProjectileCorners[iPlayerProjectileIndex][2], vEnemyProjectileCorners[iProjectileIndex][0], vEnemyProjectileCorners[iProjectileIndex][2], vIntersectionPoint) OR ARCADE_CABINET_GET_LINE_INTERSECT(vPlayerProjectileCorners[iPlayerProjectileIndex][1], vPlayerProjectileCorners[iPlayerProjectileIndex][3], vEnemyProjectileCorners[iProjectileIndex][1], vEnemyProjectileCorners[iProjectileIndex][3], vIntersectionPoint) OR ARCADE_CABINET_GET_LINE_INTERSECT(vPlayerProjectileCorners[iPlayerProjectileIndex][0], vPlayerProjectileCorners[iPlayerProjectileIndex][2], vEnemyProjectileCorners[iProjectileIndex][1], vEnemyProjectileCorners[iProjectileIndex][3], vIntersectionPoint) OR ARCADE_CABINET_GET_LINE_INTERSECT(vPlayerProjectileCorners[iPlayerProjectileIndex][1], vPlayerProjectileCorners[iPlayerProjectileIndex][3], vEnemyProjectileCorners[iProjectileIndex][0], vEnemyProjectileCorners[iProjectileIndex][2], vIntersectionPoint) sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].iShotTime = -HIGHEST_INT sIAPData.sEnemyProjectileInstances[iProjectileIndex].iShotTime = -HIGHEST_INT IAP_ADD_EXPLOSION_AT_COORDS(vIntersectionPoint) IF sIAPData.sEnemyProjectileInstances[iProjectileIndex].eProjectileType = IAP_PROJECTILE_TYPE_FALLING_BARREL IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Jet_Bomb_Barrel_Explode", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) ELSE IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION("Enemy_Blaster_Fire_Hit", "dlc_vw_am_ip_enemy_sounds", sIAPData.sEnemyProjectileInstances[iProjectileIndex].vThisFramePos) ENDIF IAP_PLAY_FIRE_AND_FORGET_SOUND_FROM_POSITION(IAP_GET_HIT_SOUND_FOR_PLAYER_PROJECTILE(sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].eProjectileType), "dlc_vw_am_ip_tank_sounds", sIAPData.sPlayerTank.sProjectileInstances[iPlayerProjectileIndex].vThisFramePos) BREAKLOOP ENDIF ENDIF ENDFOR ENDFOR ENDPROC // ------------------------------ STAGE SCROLLING ------------------------------ /// PURPOSE: /// Updates the locations of the stage background sprites PROC IAP_PROCESS_SCROLLING_STAGE() INT i //Background Position IF sIAPData.eCurrentStage != IAP_STAGE_MOON sIAPData.sParallax.fBackgroundPosX = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sParallax.fBackgroundPosX, cfIAP_BASE_BACKGROUND_SPEED) IF sIAPData.sParallax.fBackgroundPosX < cfIAP_FACADE_WIDTH - (sIAPData.sCurrentStageData.vBackgroundSpriteScale.x/2) sIAPData.sParallax.fBackgroundPosX += sIAPData.sCurrentStageData.vBackgroundSpriteScale.x ENDIF ENDIF //Midground 1 Position sIAPData.sParallax.fMidground1PosX = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sParallax.fMidground1PosX, CFIAP_BASE_MIDGROUND1_SPEED) IF sIAPData.sParallax.fMidground1PosX < cfIAP_FACADE_WIDTH - (sIAPData.sCurrentStageData.vMidground1SpriteScale.x/2) sIAPData.sParallax.fMidground1PosX += sIAPData.sCurrentStageData.vMidground1SpriteScale.x ENDIF //Midground 2 Position sIAPData.sParallax.fMidground2PosX = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sParallax.fMidground2PosX, CFIAP_BASE_MIDGROUND2_SPEED) IF sIAPData.sParallax.fMidground2PosX < cfIAP_FACADE_WIDTH - (sIAPData.sCurrentStageData.vMidground2SpriteScale.x/2) sIAPData.sParallax.fMidground2PosX += sIAPData.sCurrentStageData.vMidground2SpriteScale.x ENDIF //Midground 3 Position sIAPData.sParallax.fMidground3PosX = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sParallax.fMidground3PosX, CFIAP_BASE_MIDGROUND3_SPEED) IF sIAPData.sParallax.fMidground3PosX < cfIAP_FACADE_WIDTH - (sIAPData.sCurrentStageData.vMidground3SpriteScale.x/2) sIAPData.sParallax.fMidground3PosX += sIAPData.sCurrentStageData.vMidground3SpriteScale.x ENDIF //Foreground Position sIAPData.sParallax.fForegroundPosX[0] = IAP_APPLY_SPEED_TO_VALUE(sIAPData.sParallax.fForegroundPosX[0], CFIAP_BASE_FOREGROUND_SPEED) //If the 1st sprite is off screen shuffle the positions down FLOAT fForeground0ScaleX = IAP_GET_FOREGROUND_X_SCALE(0) IF sIAPData.sParallax.fForegroundPosX[0] < cfIAP_FACADE_WIDTH - (fForeground0ScaleX/2) sIAPData.sParallax.fForegroundPosX[0] += (fForeground0ScaleX) FOR i = 0 TO sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1 IF i < sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1 //If this foreground sprite is a pitfall and the next is not //Subtract half the difference of the foreground scale and pitfall scale from this position IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] != ciIAP_PARALLAX_DEFAULT_SPRITE AND sIAPData.sParallax.iActiveForegroundSpriteIndexes[i + 1] = ciIAP_PARALLAX_DEFAULT_SPRITE sIAPData.sParallax.fForegroundPosX[i] -= ((IAP_GET_CURRENT_PITFALL_SCALE() - sIAPData.sCurrentStageData.vForegroundSpriteScale.x) / 2) //If this foreground sprite is not a pitfall and the next is //Add half the difference of the foreground scale and pitfall scale to this position ELIF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] = ciIAP_PARALLAX_DEFAULT_SPRITE AND sIAPData.sParallax.iActiveForegroundSpriteIndexes[i + 1] != ciIAP_PARALLAX_DEFAULT_SPRITE sIAPData.sParallax.fForegroundPosX[i] += ((IAP_GET_CURRENT_PITFALL_SCALE() - sIAPData.sCurrentStageData.vForegroundSpriteScale.x) / 2) ENDIF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] = sIAPData.sParallax.iActiveForegroundSpriteIndexes[i + 1] sIAPData.sParallax.iLinkedObjectIndexes[i] = sIAPData.sParallax.iLinkedObjectIndexes[i + 1] ELSE IF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] != ciIAP_PARALLAX_DEFAULT_SPRITE sIAPData.sParallax.fForegroundPosX[i] -= ((IAP_GET_CURRENT_PITFALL_SCALE() - sIAPData.sCurrentStageData.vForegroundSpriteScale.x) / 2) ENDIF sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] = ciIAP_PARALLAX_DEFAULT_SPRITE sIAPData.sParallax.iLinkedObjectIndexes[i] = -1 ENDIF ENDFOR ENDIF //Update foreground positions FOR i = 1 TO sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1 FLOAT fScaleX = IAP_GET_FOREGROUND_X_SCALE(i) FLOAT fPrevScaleX = IAP_GET_FOREGROUND_X_SCALE(i - 1) sIAPData.sParallax.fForegroundPosX[i] = sIAPData.sParallax.fForegroundPosX[i - 1] + (fPrevScaleX/2) + (fScaleX / 2) ENDFOR IF sIAPData.eCurrentState != IAP_CLIENT_STATE_RUNNING EXIT ENDIF sIAPData.fDistanceTravelled = IAP_APPLY_SPEED_TO_VALUE(sIAPData.fDistanceTravelled, -CFIAP_BASE_FOREGROUND_SPEED) IAP_UPDATE_MAX_MOON_DISTANCE() ENDPROC /// PURPOSE: /// Updates the locations of weather effects PROC IAP_PROCESS_WEATHER_EFFECTS() IF NOT IAP_DOES_CURRENT_STAGE_HAVE_WEATHER_EFFECTS() EXIT ENDIF sIAPData.vBaseWeatherPos.x = sIAPData.vBaseWeatherPos.x +@ (cfIAP_BLIZZARD_SPEED_X / 4) sIAPData.vBaseWeatherPos.y = sIAPData.vBaseWeatherPos.y +@ (cfIAP_BLIZZARD_SPEED_Y / 4) IF sIAPData.vBaseWeatherPos.x < cfIAP_FACADE_WIDTH - cfIAP_WEATHER_SPRITE_SCALE_X OR sIAPData.vBaseWeatherPos.y > 1 + cfIAP_WEATHER_SPRITE_SCALE_Y sIAPData.vBaseWeatherPos.x += (cfIAP_WEATHER_SPRITE_SCALE_X) sIAPData.vBaseWeatherPos.y -= (cfIAP_WEATHER_SPRITE_SCALE_Y) ENDIF ENDPROC // ------------------------------ INITIALISATION ------------------------------ /// PURPOSE: /// Initialises all variables for the parallax background at the start of each stage PROC IAP_INITIALISE_PARALLAX_DATA() INT i CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_INITIALISE_PARALLAX_DATA - Initialising parallax data") sIAPData.sParallax.fBackgroundPosX = cfIAP_FACADE_WIDTH + (sIAPData.sCurrentStageData.vBackgroundSpriteScale.x / 2) sIAPData.sParallax.fMidground3PosX = cfIAP_FACADE_WIDTH + (sIAPData.sCurrentStageData.vMidground3SpriteScale.x / 2) sIAPData.sParallax.fMidground2PosX = cfIAP_FACADE_WIDTH + (sIAPData.sCurrentStageData.vMidground2SpriteScale.x / 2) sIAPData.sParallax.fMidground1PosX = cfIAP_FACADE_WIDTH + (sIAPData.sCurrentStageData.vMidground1SpriteScale.x / 2) FLOAT fScaleX = sIAPData.sCurrentStageData.vForegroundSpriteScale.x FOR i = 0 TO sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1 sIAPData.sParallax.fForegroundPosX[i] = cfIAP_FACADE_WIDTH + (fScaleX * i) + (fScaleX / 2) sIAPData.sParallax.iActiveForegroundSpriteIndexes[i] = ciIAP_PARALLAX_DEFAULT_SPRITE ENDFOR IF IAP_DOES_CURRENT_STAGE_HAVE_WEATHER_EFFECTS() sIAPData.vBaseWeatherPos = INIT_VECTOR_2D(cfIAP_FACADE_WIDTH - (cfIAP_WEATHER_SPRITE_SCALE_X / 2), 1 + (cfIAP_WEATHER_SPRITE_SCALE_Y / 2)) ENDIF ENDPROC /// PURPOSE: /// Resets all stage specific variables at the start of each stage PROC IAP_RESET_STAGE_DATA() INT i CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_RESET_STAGE_DATA - Resetting data for new stage: ", IAP_DEBUG_GET_IAP_STAGE_AS_STRING(sIAPData.eCurrentStage)) g_sCasinoArcadeInvadeAndPersuadeVars.iCurrentStage = ENUM_TO_INT(sIAPData.eCurrentStage) //Populate Stage Data IAP_INITIALISE_STAGE_DATA(sIAPData.eCurrentStage) //Set old texture dictionary as no longer needed and prep the new one IF NOT IS_STRING_NULL_OR_EMPTY(sIAPData.stLoadedStageTextureDictionary) SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED(sIAPData.stLoadedStageTextureDictionary) ENDIF sIAPData.stLoadedStageTextureDictionary = sIAPData.sCurrentStageData.stStageTextureDictionary //Reset per stage score tracking variables sIAPData.sScoreTracking.iPickupsCollected = 0 sIAPData.sScoreTracking.iOilCollected = 0 sIAPData.sScoreTracking.iEnemiesKilled = 0 //Reset procedural generation variables sIAPData.sRandomGeneration.fNextSpawnDistance = -1 sIAPData.sRandomGeneration.eNextSpawnType = IAP_OBJECT_NONE FOR i = 0 TO ciIAP_RANDOM_GENERATION_OBJECT_GROUP_MAX - 1 sIAPData.sRandomGeneration.fLastSpawnedFromGroup[i] = 0 #IF IS_DEBUG_BUILD sIAPData.sRandomGeneration.iNumSpawnedFromGroup[i] = 0 #ENDIF ENDFOR //Reset object spawning variables sIAPData.iNextObjectIndex = 0 sIAPData.iNextObjectToSpawn = 0 sIAPData.iNextOilIndex = 0 sIAPData.iNextOilToSpawn = 0 //Reset all object instances FOR i = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 sIAPData.sObjectInstances[i].eObjectType = IAP_OBJECT_NONE sIAPData.sObjectInstances[i].eState = IAP_OBJECT_STATE_DEFAULT IF sIAPData.sObjectInstances[i].iOneShotSoundId > -1 STOP_SOUND(sIAPData.sObjectInstances[i].iOneShotSoundId) RELEASE_SOUND_ID(sIAPData.sObjectInstances[i].iOneShotSoundId) sIAPData.sObjectInstances[i].iOneShotSoundId = -1 ENDIF IF sIAPData.sObjectInstances[i].iLoopingSoundId > -1 STOP_SOUND(sIAPData.sObjectInstances[i].iLoopingSoundId) RELEASE_SOUND_ID(sIAPData.sObjectInstances[i].iLoopingSoundId) sIAPData.sObjectInstances[i].iLoopingSoundId = -1 ENDIF ENDFOR IAP_STOP_LOOPING_FRONTEND_SOUND(sIAPData.iTallyLoopSoundId) //Reset all explosions FOR i = 0 TO ciIAP_MAX_EXPLOSIONS - 1 sIAPData.sExplosions[i].iAnimFrame = -1 ENDFOR sIAPData.iNextExplosionIndex = 0 //Reset all projectiles FOR i = 0 TO ciIAP_MAX_ENEMY_PROJECTILES - 1 sIAPData.sEnemyProjectileInstances[i].iShotTime = -HIGHEST_INT ENDFOR FOR i = 0 TO ciIAP_MAX_PLAYER_PROJECTILES - 1 sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime = -HIGHEST_INT ENDFOR //Reset stage variables sIAPData.fDistanceTravelled = 0.0 sIAPData.fStageSpeedMod = sIAPData.sCurrentStageData.fBaseSpeed IAP_INITIALISE_PARALLAX_DATA() //Reset player tank variables sIAPData.sPlayerTank.iTurretDirection = 0 sIAPData.sPlayerTank.iLastFrameTurretDirection = 0 sIAPData.sPlayerTank.vPosition.y = cfIAP_PLAYER_TANK_BASE_POS_Y + sIAPData.sCurrentStageData.fBaseY sIAPData.sPlayerTank.vPosition.x = 0 #IF IS_DEBUG_BUILD sIAPData.sDebugStruct.fLastObjectSpawned = 0.0 IF NOT sIAPData.sDebugStruct.bDontReplenishLivesEachStage #ENDIF IF sIAPData.bCheated sIAPData.sPlayerTank.iLives = ciIAP_STARTING_LIVES_CHEATED ELSE sIAPData.sPlayerTank.iLives = ciIAP_STARTING_LIVES ENDIF #IF IS_DEBUG_BUILD ENDIF #ENDIF sIAPData.sPlayerTank.iHealth = ciIAP_MAX_HEALTH sIAPData.sPlayerTank.iDisplayHealth = 0 sIAPData.sPlayerTank.iLastDamagedTime = -HIGHEST_INT sIAPData.sPlayerTank.iLastHealedTime = -HIGHEST_INT sIAPData.sPlayerTank.iPlayerTankBitset = 0 sIAPData.sPlayerTank.stTankSprite = "tank_drive" IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_DEFAULT) sIAPData.sPlayerTank.sAbovePlayerText.iStartTime = -HIGHEST_INT sIAPData.sPlayerTank.iTankShootAnimFrame = 0 IAP_SET_PLAYER_TANK_STATE(IAP_PLAYER_TANK_STATE_DEFAULT) IAP_SET_PLAYER_TURRET_STATE(IAP_PLAYER_TURRET_STATE_DEFAULT) IAP_RESET_PLAYER_TANK_SOUNDS() //HUD sIAPData.iMiddleTextAnimFrame = 0 //Timers IF HAS_NET_TIMER_STARTED(sIAPData.tdStageTimer) RESET_NET_TIMER(sIAPData.tdStageTimer) ENDIF IF HAS_NET_TIMER_STARTED(sIAPData.tdStageOutroTimer) RESET_NET_TIMER(sIAPData.tdStageOutroTimer) ENDIF IF HAS_NET_TIMER_STARTED(sIAPData.tdRetryTimer) RESET_NET_TIMER(sIAPData.tdRetryTimer) ENDIF ENDPROC PROC IAP_RESET_GAME_DATA_FOR_TITLE_SCREEN() sIAPData.eCurrentStage = IAP_STAGE_IRAQ IAP_WIPE_SCORE_TRACKING_STRUCT() sIAPData.iCurrentInitial = 0 sIAPData.iInitials = 0 sIAPData.iLocalLbdPos = -1 IF IS_LONG_BIT_SET(sIAPData.iSpawnedObjectBitSet, ENUM_TO_INT(IAP_OBJECT_CRASHED_TANK)) CLEAR_LONG_BIT(sIAPData.iSpawnedObjectBitSet, ENUM_TO_INT(IAP_OBJECT_CRASHED_TANK)) ENDIF ENDPROC // ------------------------------ CLIENT STATE MACHINE ------------------------------ /// PURPOSE: /// Updates the client state PROC IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE eNewState) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_SET_CLIENT_STATE - State changed from ", IAP_DEBUG_GET_IAP_CLIENT_STATE_AS_STRING(sIAPData.eCurrentState), " to ", IAP_DEBUG_GET_IAP_CLIENT_STATE_AS_STRING(eNewState)) sIAPData.eCurrentState = eNewState ENDPROC FUNC INT GET_TELEMETRY_LOCATION() IF PLAYER_ID() != INVALID_PLAYER_INDEX() SWITCH GET_SIMPLE_INTERIOR_TYPE_LOCAL_PLAYER_IS_IN() CASE SIMPLE_INTERIOR_TYPE_ARCADE RETURN HASH("SIMPLE_INTERIOR_TYPE_ARCADE") BREAK CASE SIMPLE_INTERIOR_TYPE_CASINO_APARTMENT RETURN HASH("SIMPLE_INTERIOR_TYPE_CASINO_APARTMENT") BREAK DEFAULT CDEBUG1LN(DEBUG_MINIGAME, "[[INVADE_PERSUADE_MAIN] [SET_TELEMETRY_LOCATION] not in valid arcade location, setting sArcadePlayStats.location = 0") RETURN 0 BREAK ENDSWITCH ENDIF CDEBUG2LN(DEBUG_MINIGAME, "[INVADE_PERSUADE_MAIN] [SET_TELEMETRY_LOCATION] Invalid Player ID, setting sArcadePlayStats.location = 0") RETURN 0 ENDFUNC PROC IAP_INITIALISE_LEADERBOARD_STAGE() IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_STATS_SENT) sArcadePlayStats.numPlayers = 1 sArcadePlayStats.powerUps = sIAPData.sScoreTracking.iTotalPickupsCollected sArcadePlayStats.kills = sIAPData.sScoreTracking.iTotalEnemiesKilled sArcadePlayStats.score = IAP_GET_CURRENT_SCORE() SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_STATS_SENT) sArcadePlayStats.location = GET_TELEMETRY_LOCATION() ARCADE_SEND_PLAY_STATS() ENDIF STOP_AUDIO_SCENE("dlc_vw_am_ip_in_gameplay_scene") START_AUDIO_SCENE("dlc_vw_am_ip_in_menus_scene") IF IS_ACCOUNT_OVER_17_FOR_UGC() IAP_START_LEADERBOARD_MOVIE_LOOP() IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_LEADERBOARD_START)) IAP_SORT_LEADERBOARD() IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_STAGE_LEADERBOARD) ELSE IAP_CLEAR_HELP_TEXT() IAP_START_TITLE_INTRO_MOVIE_LOOP() IAP_RESET_GAME_DATA_FOR_TITLE_SCREEN() IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Retry") IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_TITLE_SCREEN) ENDIF ENDPROC /// PURPOSE: /// Final cleanup procedure: removes all assets and resets player state. PROC IAP_CLEANUP_AND_EXIT_CLIENT() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] - IAP_CLEANUP_AND_EXIT_CLIENT - Cleaning up and terminating the script") IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_STATS_SENT) sArcadePlayStats.numPlayers = 1 sArcadePlayStats.powerUps = sIAPData.sScoreTracking.iTotalPickupsCollected sArcadePlayStats.kills = sIAPData.sScoreTracking.iTotalEnemiesKilled sArcadePlayStats.score = IAP_GET_CURRENT_SCORE() sArcadePlayStats.location = GET_TELEMETRY_LOCATION() ARCADE_SEND_PLAY_STATS() ENDIF ARCADE_CABINET_COMMON_CLEANUP() //Set texture dictionaries as no longer needed SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED(IAP_GET_PLAYER_TEXTURE_DICT()) SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("MPInvPersHud") SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("MPInvPersMessages") SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("MPInvPersMessages2") SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("MpInvPersCommon") IF NOT IS_STRING_NULL_OR_EMPTY(sIAPData.stLoadedStageTextureDictionary) SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED(sIAPData.stLoadedStageTextureDictionary) ENDIF //Clear text CLEAR_ADDITIONAL_TEXT(MINIGAME_TEXT_SLOT, FALSE) //Clean up Audio //TODO: May need handled in the penthouse instead? IAP_RESET_PLAYER_TANK_SOUNDS() INT i FOR i = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 IF sIAPData.sObjectInstances[i].iOneShotSoundId > -1 STOP_SOUND(sIAPData.sObjectInstances[i].iOneShotSoundId) RELEASE_SOUND_ID(sIAPData.sObjectInstances[i].iOneShotSoundId) sIAPData.sObjectInstances[i].iOneShotSoundId = -1 ENDIF IF sIAPData.sObjectInstances[i].iLoopingSoundId > -1 STOP_SOUND(sIAPData.sObjectInstances[i].iLoopingSoundId) RELEASE_SOUND_ID(sIAPData.sObjectInstances[i].iLoopingSoundId) sIAPData.sObjectInstances[i].iLoopingSoundId = -1 ENDIF ENDFOR IAP_STOP_LOOPING_FRONTEND_SOUND(sIAPData.iTallyLoopSoundId) IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_STOP_MUSIC)) RELEASE_NAMED_SCRIPT_AUDIO_BANK("DLC_VINEWOOD/DLC_VW_AM_IP") IF IS_AUDIO_SCENE_ACTIVE("dlc_vw_am_ip_in_gameplay_scene") STOP_AUDIO_SCENE("dlc_vw_am_ip_in_gameplay_scene") ENDIF IF IS_AUDIO_SCENE_ACTIVE("dlc_vw_am_ip_in_menus_scene") STOP_AUDIO_SCENE("dlc_vw_am_ip_in_menus_scene") ENDIF IAP_CLEAN_UP_BINKS() IAP_CLEAR_HELP_TEXT() IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_FINISHED) //Reset global player state for anims IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_NOT_PLAYING) IAP_TRIGGER_AWARD_TICKERS() TERMINATE_THIS_MULTIPLAYER_THREAD_NO_ARGS() ENDPROC //~~~~~ Client State Machine State Updates ~~~~~ /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_INITIALISING PROC IAP_PROCESS_CLIENT_STATE_INITIALISING() ARCADE_CABINET_COMMON_INITIALIZATION() ARCADE_GAMES_POSTFX_INIT(CASINO_ARCADE_GAME_INVADE_PERSUADE) //Initialise static data IAP_INITIALISE_OBJECT_DATA() IAP_INITIALISE_PROJECTILE_TYPES() IAP_INITIALISE_RANDOM_DISTANCE_BETWEEN_GROUPS() IAP_INITIALISE_COLOURS() IAP_INITIALISE_CHALLENGE_COMPLETION() IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_INTRO) IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_REQUESTING_ASSETS) ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_REQUESTING_ASSETS PROC IAP_PROCESS_CLIENT_STATE_REQUESTING_ASSETS() IF NOT IAP_HAVE_ALL_ASSETS_LOADED() EXIT ENDIF //Start the intro movie IAP_START_DEGENETRON_INTRO_MOVIE() START_AUDIO_SCENE("dlc_vw_am_ip_in_menus_scene") IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_DEGENETRON) ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_DEGENETRON PROC IAP_PROCESS_CLIENT_STATE_DEGENETRON() //Wait for the intro movie to finish IF NOT IAP_DRAW_DEGENETRON_INTRO_MOVIE() EXIT ENDIF IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_RON_OIL) ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_RON_OIL PROC IAP_PROCESS_CLIENT_STATE_RON_OIL() IF NOT HAS_NET_TIMER_STARTED(sIAPData.tdRonOilTimer) REINIT_NET_TIMER(sIAPData.tdRonOilTimer) ENDIF IF NOT HAS_NET_TIMER_EXPIRED(sIAPData.tdRonOilTimer, ciIAP_RON_OIL_SPLASH_FADE_TIME) FLOAT fAlpha = TO_FLOAT(GET_NET_TIMER_DIFFERENCE_WITH_CURRENT_TIME(sIAPData.tdRonOilTimer)) / ciIAP_RON_OIL_SPLASH_FADE_TIME INT iAlpha = ROUND(INTERP_FLOAT(0, 255, fAlpha, INTERPTYPE_SMOOTHSTEP)) IAP_DRAW_RON_OIL_INTRO(iAlpha) ELSE IAP_DRAW_RON_OIL_INTRO() ENDIF IF NOT HAS_NET_TIMER_EXPIRED(sIAPData.tdRonOilTimer, ciIAP_RON_OIL_SPLASH_FADE_TIME + ciIAP_RON_OIL_SPLASH_HOLD_TIME) EXIT ENDIF IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_TITLE_SCREEN)) SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STARTED) IAP_START_TITLE_INTRO_MOVIE_LOOP() IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_TITLE_SCREEN) ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_TITLE_SCREEN PROC IAP_PROCESS_CLIENT_STATE_TITLE_SCREEN() IAP_DRAW_TITLE_SCREEN() IAP_PROCESS_TITLE_SCREEN_HELP_TEXT() IAP_PROCESS_TITLE_INTRO_AUDIO() IAP_PROCESS_CHEATING() IF NOT IAP_HAS_PLAYER_PRESSED_START() EXIT ENDIF CLEAR_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STARTED) CLEAR_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_INTRO_MUSIC_STOPPED) IAP_RESET_STAGE_DATA() IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_STOP_MUSIC)) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Start") IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_STAGE_LOADING) IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_LEVEL_BRIEF)) IAP_STOP_TITLE_INTRO_MOVIE_LOOP() ARCADE_INITIALISE_PLAY_STATS(FALSE) IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_STAGE_LOADING) ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_STAGE_LOADING PROC IAP_PROCESS_CLIENT_STATE_STAGE_LOADING() IF NOT HAS_NET_TIMER_STARTED(sIAPData.tdStageLoadingTimer) REINIT_NET_TIMER(sIAPData.tdStageLoadingTimer) ENDIF IAP_PROCESS_OBJECT_HELP_TEXT() IAP_DRAW_STAGE_LOADING_SCREEN() IF NOT IAP_HAVE_CURRENT_STAGE_ASSETS_LOADED() EXIT ENDIF IF NOT HAS_NET_TIMER_EXPIRED(sIAPData.tdStageLoadingTimer, ciIAP_STAGE_LOADING_TIME) #IF IS_DEBUG_BUILD AND NOT IS_DEBUG_KEY_JUST_PRESSED(KEY_J, KEYBOARD_MODIFIER_NONE, "Skip Loading Screen") #ENDIF EXIT ENDIF RESET_NET_TIMER(sIAPData.tdStageLoadingTimer) IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_LEVEL_PLAY)) IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_STAGE_INTRO) STOP_AUDIO_SCENE("dlc_vw_am_ip_in_menus_scene") START_AUDIO_SCENE("dlc_vw_am_ip_in_gameplay_scene") IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Get_Ready") ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_STAGE_INTRO PROC IAP_PROCESS_CLIENT_STATE_STAGE_INTRO() IAP_PROCESS_PLAYER_TANK_STATE() IAP_PROCESS_WEATHER_EFFECTS() IAP_PROCESS_OBJECT_HELP_TEXT() IAP_DRAW_STAGE_INTRO() IF NOT IAP_IS_PLAYER_TANK_IN_START_POSITION() EXIT ENDIF IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_PLAYING) IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_RUNNING) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Go") ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_RUNNING PROC IAP_PROCESS_CLIENT_STATE_RUNNING() IF NOT HAS_NET_TIMER_STARTED(sIAPData.tdStageTimer) REINIT_NET_TIMER(sIAPData.tdStageTimer) sIAPData.iMiddleTextAnimFrame = 0 ENDIF IAP_PROCESS_SCROLLING_STAGE() IAP_PROCESS_INPUT_PRE_MOVEMENT() IAP_PROCESS_STAGE_OBJECTS() IAP_PROCESS_PLAYER_TANK_STATE() IAP_PROCESS_PLAYER_TURRET_STATE() IAP_PROCESS_INPUT_POST_MOVEMENT() IAP_PROCESS_PLAYER_PROJECTILES() IAP_PROCESS_ENEMY_PROJECTILES() IAP_PROCESS_EXPLOSIONS() IAP_PROCESS_SCORE_TEXT() IAP_PROCESS_WEATHER_EFFECTS() IAP_PROCESS_COLLISIONS() IAP_PROCESS_PLAYER_SCORE() IAP_PROCESS_OBJECT_HELP_TEXT() IAP_DRAW_STAGE_RUNNING() IF sIAPData.sPlayerTank.iHealth = 0 AND sIAPData.sPlayerTank.iLives < 0 #IF IS_DEBUG_BUILD AND sIAPData.sDebugStruct.bDontFailWhenOutOfLives = FALSE #ENDIF IAP_STOP_TANK_WEAPON_LOOP() sIAPData.iMiddleTextAnimFrame = 0 SET_MP_INT_CHARACTER_STAT(MP_STAT_IAP_MAX_MOON_DIST, sIAPData.iCachedMaxMoonDistance) IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_GAMEOVER_STAGE) sIAPData.sPlayerTank.iTankBaseAnimFrame = 0 RESET_NET_TIMER(sIAPData.tdStageTimer) sIAPData.iEndLivesToShow = 0 SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_LIVES_SCORE_ADDED) sIAPData.iEndArmourToShow = 0 SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_ARMOUR_SCORE_ADDED) sIAPData.iEndDistanceToShow = FLOOR(sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_DEAD) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Game_Over") IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_STAGE_CLEAR)) EXIT ENDIF IF (sIAPData.sCurrentStageData.fStageDistance != ciIAP_STAGE_INFINITE_LENGTH AND (sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) >= sIAPData.sCurrentStageData.fStageDistance) #IF IS_DEBUG_BUILD OR IS_KEYBOARD_KEY_PRESSED(KEY_J) #ENDIF IAP_STOP_TANK_WEAPON_LOOP() IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_LEVEL_COMPLETE) sIAPData.iMiddleTextAnimFrame = 0 IAP_SET_PLAYER_TURRET_STATE(IAP_PLAYER_TURRET_STATE_DEFAULT) SET_MP_INT_CHARACTER_STAT(MP_STAT_IAP_MAX_MOON_DIST, sIAPData.iCachedMaxMoonDistance) IAP_UPDATE_LIVES_CHALLENGE() sIAPData.iEndLivesToShow = sIAPData.sPlayerTank.iLives sIAPData.iEndArmourToShow = sIAPData.sPlayerTank.iHealth sIAPData.iEndDistanceToShow = FLOOR(sIAPData.fDistanceTravelled / cfIAP_DISTANCE_CONVERSION) IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_STAGE_OUTRO) IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Stage_Clear") IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_STAGE_CLEAR)) RESET_NET_TIMER(sIAPData.tdStageTimer) ENDIF ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_GAMEOVER_STAGE PROC IAP_PROCESS_CLIENT_STATE_GAMEOVER_STAGE() IF NOT HAS_NET_TIMER_STARTED(sIAPData.tdRetryTimer) REINIT_NET_TIMER(sIAPData.tdRetryTimer) ENDIF IAP_PROCESS_STAGE_OBJECTS() IAP_PROCESS_PLAYER_TURRET_STATE() IAP_PROCESS_PLAYER_TANK_STATE() IAP_PROCESS_WEATHER_EFFECTS() IAP_PROCESS_EXPLOSIONS() IAP_PROCESS_SCORE_TEXT() IAP_PROCESS_PLAYER_SCORE() IAP_PROCESS_OBJECT_HELP_TEXT() IAP_DRAW_STAGE_GAMEOVER() IF NOT IAP_PROCESSED_FINAL_STAGE_SCORE() EXIT ENDIF IF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_END_MUSIC_TRIGGERED) AND HAS_NET_TIMER_EXPIRED(sIAPData.tdRetryTimer, ciIAP_DEATH_TIME - 2000) IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_LEVEL_END)) SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_END_MUSIC_TRIGGERED) ENDIF IF NOT HAS_NET_TIMER_EXPIRED(sIAPData.tdRetryTimer, ciIAP_DEATH_TIME) EXIT ENDIF IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_GAMEOVER_SCREEN) IAP_INITIALISE_LEADERBOARD_STAGE() ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_STAGE_OUTRO PROC IAP_PROCESS_CLIENT_STATE_STAGE_OUTRO() IAP_PROCESS_STAGE_OBJECTS() IAP_PROCESS_PLAYER_TURRET_STATE() IAP_PROCESS_PLAYER_TANK_STATE() IAP_PROCESS_PLAYER_PROJECTILES() IAP_PROCESS_EXPLOSIONS() IAP_PROCESS_SCORE_TEXT() IAP_PROCESS_WEATHER_EFFECTS() IAP_PROCESS_PLAYER_SCORE() IAP_PROCESS_OBJECT_HELP_TEXT() IAP_DRAW_STAGE_OUTRO() IF IAP_IS_PLAYER_TANK_IN_END_POSITION() IF NOT IAP_PROCESSED_FINAL_STAGE_SCORE() EXIT ENDIF IF NOT HAS_NET_TIMER_STARTED(sIAPData.tdStageOutroTimer) REINIT_NET_TIMER(sIAPData.tdStageOutroTimer) ELIF HAS_NET_TIMER_EXPIRED(sIAPData.tdStageOutroTimer, ciIAP_OUTRO_TEXT_TIME) sIAPData.eCurrentStage = INT_TO_ENUM(IAP_STAGE, ENUM_TO_INT(sIAPData.eCurrentStage) + 1) IF sIAPData.eCurrentStage = IAP_STAGE_MAX IAP_INITIALISE_LEADERBOARD_STAGE() ELSE IAP_RESET_STAGE_DATA() IAP_SET_GLOBAL_PLAYER_STATE(CASINO_ARCADE_INVADE_PERSUADE_PLAYER_STATE_STAGE_LOADING) IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_LEVEL_BRIEF)) IF IS_AUDIO_SCENE_ACTIVE("dlc_vw_am_ip_in_gameplay_scene") STOP_AUDIO_SCENE("dlc_vw_am_ip_in_gameplay_scene") ENDIF START_AUDIO_SCENE("dlc_vw_am_ip_in_menus_scene") IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_STAGE_LOADING) ENDIF RESET_NET_TIMER(sIAPData.tdStageOutroTimer) ELIF NOT IS_BIT_SET(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_END_MUSIC_TRIGGERED) AND HAS_NET_TIMER_EXPIRED(sIAPData.tdStageOutroTimer, ciIAP_OUTRO_TEXT_TIME - 2000) SET_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_END_MUSIC_TRIGGERED) IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_LEVEL_END)) ENDIF ENDIF ENDPROC /// PURPOSE: /// Processing for the client state: IAP_CLIENT_STATE_STAGE_LEADERBOARD PROC IAP_PROCESS_CLIENT_STATE_STAGE_LEADERBOARD() IAP_DRAW_LEADERBOARD() IAP_PROCESS_LEADERBOARD_ENTRY() IAP_PROCESS_LEADERBOARD_HELP_TEXT() IF NOT IAP_HAS_PLAYER_PRESSED_START() EXIT ENDIF IF IAP_GET_PLAYER_LEADERBOARD_POSITION() < ciCASINO_ARCADE_LEADERBOARD_POSITIONS sIAPData.sLeaderboard[IAP_GET_PLAYER_LEADERBOARD_POSITION()].bPlayer = FALSE sIAPData.sLeaderboard[IAP_GET_PLAYER_LEADERBOARD_POSITION()].iInitials = sIAPData.iInitials ENDIF IAP_CLEAR_HELP_TEXT() IAP_STOP_LEADERBOARD_MOVIE_LOOP() IAP_START_TITLE_INTRO_MOVIE_LOOP() IAP_RESET_GAME_DATA_FOR_TITLE_SCREEN() IAP_PLAY_FIRE_AND_FORGET_FRONTEND_SOUND("Frontend_Retry") IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_TITLE_SCREEN) ENDPROC //~~~~~ Client State Machine Main Update ~~~~~ /// PURPOSE: /// Processes the client state machine PROC IAP_PROCESS_CLIENT_STATE_MACHINE() SWITCH sIAPData.eCurrentState CASE IAP_CLIENT_STATE_INITIALISING IAP_PROCESS_CLIENT_STATE_INITIALISING() BREAK CASE IAP_CLIENT_STATE_REQUESTING_ASSETS IAP_PROCESS_CLIENT_STATE_REQUESTING_ASSETS() BREAK CASE IAP_CLIENT_STATE_DEGENETRON IAP_PROCESS_CLIENT_STATE_DEGENETRON() BREAK CASE IAP_CLIENT_STATE_RON_OIL IAP_PROCESS_CLIENT_STATE_RON_OIL() BREAK CASE IAP_CLIENT_STATE_TITLE_SCREEN IAP_PROCESS_CLIENT_STATE_TITLE_SCREEN() BREAK CASE IAP_CLIENT_STATE_STAGE_LOADING IAP_PROCESS_CLIENT_STATE_STAGE_LOADING() BREAK CASE IAP_CLIENT_STATE_STAGE_INTRO IAP_PROCESS_CLIENT_STATE_STAGE_INTRO() BREAK CASE IAP_CLIENT_STATE_RUNNING IAP_PROCESS_CLIENT_STATE_RUNNING() BREAK CASE IAP_CLIENT_STATE_GAMEOVER_STAGE IAP_PROCESS_CLIENT_STATE_GAMEOVER_STAGE() BREAK CASE IAP_CLIENT_STATE_STAGE_OUTRO IAP_PROCESS_CLIENT_STATE_STAGE_OUTRO() BREAK CASE IAP_CLIENT_STATE_STAGE_LEADERBOARD IAP_PROCESS_CLIENT_STATE_STAGE_LEADERBOARD() BREAK CASE IAP_CLIENT_STATE_CLEANUP IAP_CLEANUP_AND_EXIT_CLIENT() BREAK CASE IAP_CLIENT_STATE_FINISHED //Do nothing BREAK ENDSWITCH ENDPROC #IF IS_DEBUG_BUILD // ------------------------------ DEBUG ------------------------------ /// PURPOSE: /// Skips to another stage of the game PROC IAP_DEBUG_SKIP_TO_STAGE(IAP_STAGE eStage) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_SKIP_TO_STAGE - SKIPPING TO STAGE: ", IAP_DEBUG_GET_IAP_STAGE_AS_STRING(eStage)) IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_STOP_MUSIC)) sIAPData.eCurrentStage = eStage IAP_CLEAN_UP_BINKS() IAP_WIPE_SCORE_TRACKING_STRUCT() IAP_RESET_STAGE_DATA() IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_STAGE_LOADING) IF IS_AUDIO_SCENE_ACTIVE("dlc_vw_am_ip_in_gameplay_scene") STOP_AUDIO_SCENE("dlc_vw_am_ip_in_gameplay_scene") ENDIF IF NOT IS_AUDIO_SCENE_ACTIVE("dlc_vw_am_ip_in_menus_scene") START_AUDIO_SCENE("dlc_vw_am_ip_in_menus_scene") ENDIF IAP_TRIGGER_MUSIC_EVENT(IAP_GET_MUSIC_EVENT_STRING(IAP_MUSIC_EVENT_LEVEL_BRIEF)) ENDPROC /// PURPOSE: /// Sets the given widget group to be the parent for any widgets created by the minigame. PROC IAP_DEBUG_SET_PARENT_WIDGET_GROUP(WIDGET_GROUP_ID parentWidgetGroup) sIAPData.sDebugStruct.widgetScrollingMinigame = parentWidgetGroup ENDPROC /// PURPOSE: /// Creates all of the debug widgets. PROC IAP_DEBUG_CREATE_WIDGETS() IF NOT sIAPData.sDebugStruct.bDebugCreatedWidgets AND sIAPData.sDebugStruct.widgetScrollingMinigame != NULL SET_CURRENT_WIDGET_GROUP(sIAPData.sDebugStruct.widgetScrollingMinigame) START_WIDGET_GROUP("Scrolling Arcade Cabinet Minigame") ADD_WIDGET_BOOL("bDrawCollisionDebug", sIAPData.sDebugStruct.bDrawCollisionDebug) ADD_WIDGET_BOOL("bBlockDrawing", g_bBlockArcadeCabinetDrawing) ADD_WIDGET_BOOL("g_bMinimizeArcadeCabinetDrawing", g_bMinimizeArcadeCabinetDrawing) ADD_WIDGET_BOOL("bDisableSFX", sIAPData.sDebugStruct.bDisableSFX) ADD_WIDGET_BOOL("bDisableMusic", sIAPData.sDebugStruct.bDisableMusic) ADD_WIDGET_BOOL("bEnableAllChallenges", sIAPData.sDebugStruct.bEnableAllChallenges) ADD_WIDGET_BOOL("bDisableAllChallenges", sIAPData.sDebugStruct.bDisableAllChallenges) ADD_WIDGET_BOOL("bTriggerChallenge0", sIAPData.sDebugStruct.bTriggerChallenge0) ADD_WIDGET_BOOL("bTriggerChallenge1", sIAPData.sDebugStruct.bTriggerChallenge1) ADD_WIDGET_BOOL("bTriggerChallenge2", sIAPData.sDebugStruct.bTriggerChallenge2) ADD_WIDGET_BOOL("bTriggerChallenge3", sIAPData.sDebugStruct.bTriggerChallenge3) ADD_WIDGET_BOOL("bTriggerChallenge4", sIAPData.sDebugStruct.bTriggerChallenge4) ADD_WIDGET_FLOAT_SLIDER("Midground1PosOffset", cfIAP_MIDGROUND1_Y_OFFSET, -1, 1, 0.001) ADD_WIDGET_FLOAT_SLIDER("Midground2PosOffset", cfIAP_MIDGROUND2_Y_OFFSET, -1, 1, 0.001) ADD_WIDGET_FLOAT_SLIDER("Midground3PosOffset", cfIAP_MIDGROUND3_Y_OFFSET, -1, 1, 0.001) ADD_WIDGET_FLOAT_SLIDER("BackgroundPosOffset", cfIAP_BACKGROUND_Y_OFFSET, -1, 1, 0.001) ADD_WIDGET_INT_READ_ONLY("iRectsDrawnThisFrame", iRectsDrawnThisFrame) ADD_WIDGET_INT_READ_ONLY("iSpritesDrawnThisFrame", iSpritesDrawnThisFrame) ADD_WIDGET_INT_READ_ONLY("iDebugLinesDrawnThisFrame", iDebugLinesDrawnThisFrame) START_WIDGET_GROUP("Player Tank") ADD_WIDGET_FLOAT_SLIDER("Max Speed", cfIAP_PLAYER_TANK_MAX_SPEED_MOD, 0, 1, 0.001) ADD_WIDGET_INT_SLIDER("Accel Time", ciIAP_PLAYER_TANK_SPEED_MOD_TIME, 0, 10000, 250) ADD_WIDGET_INT_SLIDER("Jump Up Duration", ciIAP_PLAYER_TANK_JUMP_TIME_UP, 0, 2000, 50) ADD_WIDGET_INT_SLIDER("Jump Interval", ciIAP_PLAYER_TANK_JUMP_INTERVAL, 0, 5000, 50) ADD_WIDGET_FLOAT_SLIDER("Jump Height", cfIAP_PLAYER_TANK_JUMP_HEIGHT, -1, 0, 0.001) ADD_WIDGET_BOOL("bNoDamage", sIAPData.sDebugStruct.bNoDamage) ADD_WIDGET_BOOL("bDontFailWhenOutOfLives", sIAPData.sDebugStruct.bDontFailWhenOutOfLives) ADD_WIDGET_BOOL("bDontReplenishLivesEachStage", sIAPData.sDebugStruct.bDontReplenishLivesEachStage) ADD_WIDGET_BOOL("bLoseWeaponOnHit", sIAPData.sDebugStruct.bLoseWeaponOnHit) ADD_WIDGET_BOOL("bNoAccel", sIAPData.sDebugStruct.bNoAccel) ADD_WIDGET_BOOL("bAccelInAir", sIAPData.sDebugStruct.bAccelInAir) STOP_WIDGET_GROUP() START_WIDGET_GROUP("Score Tally") ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_TEXT_POS_Y", cfIAP_STAGE_CLEAR_TALLY_TEXT_POS_Y, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_TEXT_TITLE_COLUMN_WRAP_MIN", cfIAP_STAGE_CLEAR_TALLY_TEXT_TITLE_COLUMN_WRAP_MIN, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_TEXT_TITLE_COLUMN_WRAP_MAX", cfIAP_STAGE_CLEAR_TALLY_TEXT_TITLE_COLUMN_WRAP_MAX, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_TEXT_VALUE_COLUMN_WRAP_MIN", cfIAP_STAGE_CLEAR_TALLY_TEXT_VALUE_COLUMN_WRAP_MIN, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_TEXT_VALUE_COLUMN_WRAP_MAX", cfIAP_STAGE_CLEAR_TALLY_TEXT_VALUE_COLUMN_WRAP_MAX, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_TEXT_SPACING_Y", cfIAP_STAGE_CLEAR_TALLY_TEXT_SPACING_Y, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_RECT_OFFSET_X", cfIAP_STAGE_CLEAR_TALLY_RECT_OFFSET_X, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_RECT_OFFSET_Y", cfIAP_STAGE_CLEAR_TALLY_RECT_OFFSET_Y, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_RECT_WIDTH", cfIAP_STAGE_CLEAR_TALLY_RECT_WIDTH, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_RECT_HEIGHT", cfIAP_STAGE_CLEAR_TALLY_RECT_HEIGHT, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_STAGE_CLEAR_TALLY_TEXT_SCALE", cfIAP_STAGE_CLEAR_TALLY_TEXT_SCALE, 0.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_LIVES_TEXT_OFFSET_X", cfIAP_LIVES_TEXT_OFFSET_X, -1.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_LIVES_TEXT_OFFSET_Y", cfIAP_LIVES_TEXT_OFFSET_Y, -1.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_LIVES_TEXT_WRAP_MAX", cfIAP_LIVES_TEXT_WRAP_MAX, -1.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_SCORE_TEXT_OFFSET_Y", cfIAP_SCORE_TEXT_OFFSET_Y, -1.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_DISTANCE_TEXT_BEST_OFFSET_X", cfIAP_DISTANCE_TEXT_BEST_OFFSET_X, -1.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_DISTANCE_TEXT_OFFSET_X", cfIAP_DISTANCE_TEXT_OFFSET_X, -1.0, 1.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("cfIAP_DISTANCE_TEXT_OFFSET_Y", cfIAP_DISTANCE_TEXT_OFFSET_Y, -1.0, 1.0, 0.001) STOP_WIDGET_GROUP() START_WIDGET_GROUP("Stage Speed") ADD_WIDGET_FLOAT_SLIDER("Max Stage Speed", cfIAP_MAX_STAGE_SPEED_MOD, 1.0, 3.0, 0.05) ADD_WIDGET_FLOAT_SLIDER("Current Stage Speed", sIAPData.fStageSpeedMod, 1.0, 3.0, 0.05) ADD_WIDGET_FLOAT_SLIDER("Large Oil Speed Boost", cfIAP_LARGE_OIL_SPEED_BOOST, 0, 1.0, 0.005) ADD_WIDGET_FLOAT_SLIDER("Medium Oil Speed Boost", cfIAP_MEDIUM_OIL_SPEED_BOOST, 0, 1.0, 0.005) ADD_WIDGET_FLOAT_SLIDER("Small Oil Speed Boost", cfIAP_SMALL_OIL_SPEED_BOOST, 0, 1.0, 0.005) STOP_WIDGET_GROUP() START_WIDGET_GROUP("Procedural Level") ADD_WIDGET_FLOAT_SLIDER("Min Distance Between Spawns Start", cfIAP_RANDOM_MIN_DIST_BETWEEN_SPAWNS_START, 0, 20, 0.25) ADD_WIDGET_FLOAT_SLIDER("Max Distance Between Spawns Start", cfIAP_RANDOM_MAX_DIST_BETWEEN_SPAWNS_START, 0, 20, 0.25) ADD_WIDGET_FLOAT_SLIDER("Min Distance Between Spawns End", cfIAP_RANDOM_MIN_DIST_BETWEEN_SPAWNS_END, 0, 20, 0.25) ADD_WIDGET_FLOAT_SLIDER("Max Distance Between Spawns End", cfIAP_RANDOM_MAX_DIST_BETWEEN_SPAWNS_END, 0, 20, 0.25) ADD_WIDGET_FLOAT_SLIDER("Distance To End Spawn Distance", cfIAP_RANDOM_DISTANCE_TO_END_SPAWN_DIST, 0, 10000, 100) ADD_WIDGET_FLOAT_READ_ONLY("Current Min Dist Between Spawns", sIAPData.sRandomGeneration.fMinDistBetweenSpawns) ADD_WIDGET_FLOAT_READ_ONLY("Current Max Dist Between Spawns", sIAPData.sRandomGeneration.fMaxDistBetweenSpawns) ADD_WIDGET_BOOL("bRandomPickupsOnly", sIAPData.sDebugStruct.bRandomPickupsOnly) START_WIDGET_GROUP("Spawn Groups") START_WIDGET_GROUP("Group - Pitfalls") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Pitfall to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Ground Enemy") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ground Enemy to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Jet") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Jet to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Jet to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Drone") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Drone to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Drone to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Rare Pickup") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Rare Pickup to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Common Pickup") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Common Pickup to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Small Oil") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Small Oil to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Medium Oil") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Medium Oil to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Large Oil") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Large Oil to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() START_WIDGET_GROUP("Group - Ledges") ADD_WIDGET_FLOAT_READ_ONLY("Last Spawned", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES]) ADD_WIDGET_INT_READ_ONLY("Total Spawned", sIAPData.sRandomGeneration.iNumSpawnedFromGroup[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES]) START_WIDGET_GROUP("Group Min Spawn Distances") ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Pitfall", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PITFALLS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Ground Enemy", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_GROUND_ENEMIES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Jet", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_JETS], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Drone", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_DRONES], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Rare Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_RARE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Common Pickup", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_PICKUPS_COMMON], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Small Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_SMALL], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Medium Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_MEDIUM], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Large Oil", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_OIL_LARGE], 0, 100, 0.25) ADD_WIDGET_FLOAT_SLIDER("Ledge to Next Ledge", sIAPData.sRandomGeneration.fMinDistancesBetweenGroups[ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES][ciIAP_RANDOM_GENERATION_OBJECT_GROUP_LEDGES], 0, 100, 0.25) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() ARCADE_GAMES_POSTFX_WIDGET_CREATE() STOP_WIDGET_GROUP() CLEAR_CURRENT_WIDGET_GROUP(sIAPData.sDebugStruct.widgetScrollingMinigame) sIAPData.sDebugStruct.bDebugCreatedWidgets = TRUE ENDIF ENDPROC /// PURPOSE: /// Turns all challenge stats on or off PROC IAP_ENABLE_ALL_CHALLENGES(BOOL bEnable) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_ENABLE_ALL_CHALLENGES - bEnable ", bEnable) SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_GOLD_TANK, bEnable) SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_0, bEnable) SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_1, bEnable) SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_2, bEnable) SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_3, bEnable) SET_MP_BOOL_CHARACTER_STAT(MP_STAT_IAP_CHALLENGE_4, bEnable) ENDPROC /// PURPOSE: /// Dumps the current state of the game to the logs /// Automatically called when a bug is entered PROC IAP_DEBUG_DUMP_DATA_TO_LOGS() INT i ARCADE_CABINET_DUMP_DATA_TO_CONSOLE() CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_DUMP_DATA_TO_LOGS - Dumping data...") //General CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- GENERAL -----") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eCurrentState = ", IAP_DEBUG_GET_IAP_CLIENT_STATE_AS_STRING(sIAPData.eCurrentState)) //Objects CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- OBJECTS -----") FOR i = 0 TO ciIAP_MAX_ACTIVE_OBJECTS - 1 IF sIAPData.sObjectInstances[i].eObjectType = IAP_OBJECT_NONE RELOOP ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eObjectType[",i,"] = ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(sIAPData.sObjectInstances[i].eObjectType)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eState[",i,"] = ", IAP_DEBUG_GET_IAP_OBJECT_STATE_AS_STRING(sIAPData.sObjectInstances[i].eState)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] vPosition[",i,"] = (", sIAPData.sObjectInstances[i].vPosition.x, ", ", sIAPData.sObjectInstances[i].vPosition.y, ")") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iSpawnTime[",i,"] = ", sIAPData.sObjectInstances[i].iSpawnTime) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iHealth[",i,"] = ", sIAPData.sObjectInstances[i].iHealth) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iLastDamagedTime[",i,"] = ", sIAPData.sObjectInstances[i].iLastDamagedTime) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iLastShotTime[",i,"] = ", sIAPData.sObjectInstances[i].iLastShotTime) ENDFOR CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- ENEMY PROJECTILES -----") FOR i = 0 TO ciIAP_MAX_ENEMY_PROJECTILES - 1 IF sIAPData.sEnemyProjectileInstances[i].eProjectileType = IAP_PROJECTILE_TYPE_NONE OR sIAPData.sEnemyProjectileInstances[i].iShotTime = -HIGHEST_INT RELOOP ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eProjectileType[",i,"] = ", IAP_DEBUG_GET_IAP_PROJECTILE_TYPE_AS_STRING(sIAPData.sEnemyProjectileInstances[i].eProjectileType)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iShotTime[",i,"] = ", sIAPData.sEnemyProjectileInstances[i].iShotTime) ENDFOR //Spawning CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- SPAWNING -----") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iNextObjectToSpawn = ", sIAPData.iNextObjectToSpawn) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iNextObjectIndex = ", sIAPData.iNextObjectIndex) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iNextOilToSpawn = ", sIAPData.iNextOilToSpawn) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iNextOilIndex = ", sIAPData.iNextOilIndex) //Procedural Generation CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- PROCEDURAL GENERATION -----") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] fNextSpawnDistance = ", sIAPData.sRandomGeneration.fNextSpawnDistance) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eNextSpawnType = ", IAP_DEBUG_GET_IAP_OBJECT_AS_STRING(sIAPData.sRandomGeneration.eNextSpawnType)) FOR i = 0 TO ciIAP_RANDOM_GENERATION_OBJECT_GROUP_MAX - 1 CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] fLastSpawnedFromGroup[",i,"] = ", sIAPData.sRandomGeneration.fLastSpawnedFromGroup[i]) ENDFOR //Stage CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- STAGE -----") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eCurrentStage = ", IAP_DEBUG_GET_IAP_STAGE_AS_STRING(sIAPData.eCurrentStage)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] fDistanceTravelled = ", sIAPData.fDistanceTravelled) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] fStageSpeedMod = ", sIAPData.fStageSpeedMod) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] stLoadedStageTextureDictionary = ", sIAPData.stLoadedStageTextureDictionary) FOR i = 0 TO sIAPData.sCurrentStageData.iMaxActiveForegroundSprites - 1 CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iActiveForegroundSpriteIndexes[",i,"] = ", sIAPData.sParallax.iActiveForegroundSpriteIndexes[i]) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] fForegroundPosX[",i,"] = ", sIAPData.sParallax.fForegroundPosX[i]) ENDFOR //Player Tank CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- PLAYER TANK -----") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eTankState = ", IAP_DEBUG_GET_IAP_PLAYER_TANK_STATE_AS_STRING(sIAPData.sPlayerTank.eTankState)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eTurretState = ", IAP_DEBUG_GET_IAP_PLAYER_TURRET_STATE_AS_STRING(sIAPData.sPlayerTank.eTurretState)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eWeaponType = ", IAP_DEBUG_GET_IAP_PLAYER_WEAPON_AS_STRING(sIAPData.sPlayerTank.eWeaponType)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] vPosition = (", sIAPData.sPlayerTank.vPosition.x, ", ", sIAPData.sPlayerTank.vPosition.y, ")") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iTurretDirection = ", sIAPData.sPlayerTank.iTurretDirection) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iTurretLastShootTime = ", sIAPData.sPlayerTank.iTurretLastShootTime) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iLastJumpTime = ", sIAPData.sPlayerTank.iLastJumpTime) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iLastDamagedTime = ", sIAPData.sPlayerTank.iLastDamagedTime) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iLastHealedTime = ", sIAPData.sPlayerTank.iLastHealedTime) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iLastSmokeTime = ", sIAPData.sPlayerTank.iLastSmokeTime) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iRespawnTime = ", sIAPData.sPlayerTank.iRespawnTime) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iLives = ", sIAPData.sPlayerTank.iLives) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iHealth = ", sIAPData.sPlayerTank.iHealth) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iPlayerTankBitset = ", sIAPData.sPlayerTank.iPlayerTankBitset) FOR i = 0 TO ciIAP_MAX_PLAYER_PROJECTILES - 1 IF sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType = IAP_PROJECTILE_TYPE_NONE OR sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime = -HIGHEST_INT RELOOP ENDIF CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] eProjectileType[",i,"] = ", IAP_DEBUG_GET_IAP_PROJECTILE_TYPE_AS_STRING(sIAPData.sPlayerTank.sProjectileInstances[i].eProjectileType)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iShotTime[",i,"] = ", sIAPData.sPlayerTank.sProjectileInstances[i].iShotTime) ENDFOR //Scoring CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- SCORE TRACKING -----") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iScoreFromPickups = ", sIAPData.sScoreTracking.iScoreFromPickups) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iPickupsCollected = ", sIAPData.sScoreTracking.iPickupsCollected) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iTotalPickupsCollected = ", sIAPData.sScoreTracking.iTotalPickupsCollected) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iScoreFromEnemies = ", sIAPData.sScoreTracking.iScoreFromEnemies) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iEnemiesKilled = ", sIAPData.sScoreTracking.iEnemiesKilled) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iTotalEnemiesKilled = ", sIAPData.sScoreTracking.iTotalEnemiesKilled) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iScoreFromOil = ", sIAPData.sScoreTracking.iScoreFromOil) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iOilCollected = ", sIAPData.sScoreTracking.iOilCollected) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iTotalOilCollected = ", sIAPData.sScoreTracking.iTotalOilCollected) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iScoreFromDistance = ", sIAPData.sScoreTracking.iScoreFromDistance) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iScoreFromLives = ", sIAPData.sScoreTracking.iScoreFromLives) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] iScoreFromArmour = ", sIAPData.sScoreTracking.iScoreFromArmour) //Debug CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] ----- DEBUG VALUES -----") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] bDrawCollisionDebug = ", sIAPData.sDebugStruct.bDrawCollisionDebug) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] bNoDamage = ", sIAPData.sDebugStruct.bNoDamage) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] bDontFailWhenOutOfLives = ", sIAPData.sDebugStruct.bDontFailWhenOutOfLives) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] bDontReplenishLivesEachStage = ", sIAPData.sDebugStruct.bDontReplenishLivesEachStage) ENDPROC /// PURPOSE: /// Updates all debug functionality for the minigame. PROC IAP_DEBUG_PROCESSING() IAP_DEBUG_CREATE_WIDGETS() ARCADE_GAMES_POSTFX_WIDGET_UPDATE() //Enable debug lines for collision debug SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) //Clamp Stage Speed IF sIAPData.fStageSpeedMod > cfIAP_MAX_STAGE_SPEED_MOD sIAPData.fStageSpeedMod = cfIAP_MAX_STAGE_SPEED_MOD ENDIF //Weapon Swaps IF IS_DEBUG_KEY_JUST_PRESSED(KEY_1, KEYBOARD_MODIFIER_NONE, "Swap to default weapon") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG WEAPON SWAP - IAP_PLAYER_WEAPON_DEFAULT") IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_DEFAULT) ENDIF IF IS_DEBUG_KEY_JUST_PRESSED(KEY_2, KEYBOARD_MODIFIER_NONE, "Swap to flamethrower") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG WEAPON SWAP - IAP_PLAYER_WEAPON_FLAMETHROWER") IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_FLAMETHROWER) ENDIF IF IS_DEBUG_KEY_JUST_PRESSED(KEY_3, KEYBOARD_MODIFIER_NONE, "Swap to rocket launcher") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG WEAPON SWAP - IAP_PLAYER_WEAPON_ROCKET_LAUNCHER") IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_ROCKET_LAUNCHER) ENDIF IF IS_DEBUG_KEY_JUST_PRESSED(KEY_4, KEYBOARD_MODIFIER_NONE, "Swap to plasma cannon") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG WEAPON SWAP - IAP_PLAYER_WEAPON_PLASMA") IAP_SET_PLAYER_WEAPON_TYPE(IAP_PLAYER_WEAPON_PLASMA) ENDIF //Stage Skipping IF IS_DEBUG_KEY_JUST_PRESSED(KEY_1, KEYBOARD_MODIFIER_CTRL, "Select Stage 0") IAP_DEBUG_SKIP_TO_STAGE(IAP_STAGE_IRAQ) ENDIF IF IS_DEBUG_KEY_JUST_PRESSED(KEY_2, KEYBOARD_MODIFIER_CTRL, "Select Stage 1") IAP_DEBUG_SKIP_TO_STAGE(IAP_STAGE_RUSSIA) ENDIF IF IS_DEBUG_KEY_JUST_PRESSED(KEY_3, KEYBOARD_MODIFIER_CTRL, "Select Stage 2") IAP_DEBUG_SKIP_TO_STAGE(IAP_STAGE_CHINA) ENDIF IF IS_DEBUG_KEY_JUST_PRESSED(KEY_4, KEYBOARD_MODIFIER_CTRL, "Select Stage 3") IAP_DEBUG_SKIP_TO_STAGE(IAP_STAGE_CANADA) ENDIF IF IS_DEBUG_KEY_JUST_PRESSED(KEY_5, KEYBOARD_MODIFIER_CTRL, "Select Stage 4") IAP_DEBUG_SKIP_TO_STAGE(IAP_STAGE_MOON) ENDIF //SCORE IF IS_DEBUG_KEY_JUST_PRESSED(KEY_PLUS, KEYBOARD_MODIFIER_CTRL, "+ Score") IAP_ADD_SCORE(500000, IAP_SCORE_TYPE_OIL, INIT_VECTOR_2D(cfSCREEN_CENTER, cfSCREEN_CENTER)) CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG SCORE") sIAPData.iScoreToShow = IAP_GET_CURRENT_SCORE() ENDIF //CHALLENGES IF sIAPData.sDebugStruct.bEnableAllChallenges IAP_ENABLE_ALL_CHALLENGES(TRUE) sIAPData.sDebugStruct.bEnableAllChallenges = FALSE ENDIF IF sIAPData.sDebugStruct.bDisableAllChallenges IAP_ENABLE_ALL_CHALLENGES(FALSE) sIAPData.sDebugStruct.bDisableAllChallenges = FALSE ENDIF IF sIAPData.sDebugStruct.bTriggerChallenge0 CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - TRIGGER CHALLENGE 0") IAP_UPDATE_KILL_CHALLENGE(TRUE) sIAPData.sDebugStruct.bTriggerChallenge0 = FALSE ENDIF IF sIAPData.sDebugStruct.bTriggerChallenge1 CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - TRIGGER CHALLENGE 1") IAP_UPDATE_OIL_CHALLENGE(TRUE) sIAPData.sDebugStruct.bTriggerChallenge1 = FALSE ENDIF IF sIAPData.sDebugStruct.bTriggerChallenge2 CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - TRIGGER CHALLENGE 2") IAP_UPDATE_MAX_MOON_DISTANCE(TRUE) sIAPData.sDebugStruct.bTriggerChallenge2 = FALSE ENDIF IF sIAPData.sDebugStruct.bTriggerChallenge3 CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - TRIGGER CHALLENGE 3") IAP_UPDATE_LIVES_CHALLENGE(TRUE) sIAPData.sDebugStruct.bTriggerChallenge3 = FALSE ENDIF IF sIAPData.sDebugStruct.bTriggerChallenge4 CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - TRIGGER CHALLENGE 4") IAP_UPDATE_SCORE_CHALLENGE(TRUE) sIAPData.sDebugStruct.bTriggerChallenge4 = FALSE ENDIF //NUKE IF IS_DEBUG_KEY_JUST_PRESSED(KEY_N, KEYBOARD_MODIFIER_NONE, "NUKE") CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG NUKE") IAP_NUKE_SCREEN() ENDIF //Debug pause IF IS_DEBUG_KEY_JUST_PRESSED(KEY_P, KEYBOARD_MODIFIER_NONE, "Pause Game") sIAPData.sDebugStruct.bDebugPause = !sIAPData.sDebugStruct.bDebugPause IF sIAPData.sDebugStruct.bDebugPause CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG PAUSE - PAUSED") ELSE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG PAUSE - RESUMED") ENDIF ENDIF IF sIAPData.sDebugStruct.bDebugPause SET_TEXT_SCALE(1, 1) SET_TEXT_COLOUR(255, 255, 255, 255) SET_TEXT_CENTRE(TRUE) SET_TEXT_FONT(FONT_STANDARD) BEGIN_TEXT_COMMAND_DISPLAY_TEXT("STRING") ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME("ARCADE GAME PAUSED - PRESS 'P' ON DEBUG KEYBOARD TO RESUME") END_TEXT_COMMAND_DISPLAY_TEXT(cfSCREEN_CENTER, cfSCREEN_CENTER) ENDIF //If a bug is entered dump all data to the console. IF IS_KEYBOARD_KEY_PRESSED(KEY_SPACE) OR IS_KEYBOARD_KEY_PRESSED(KEY_RBRACKET) sIAPData.sDebugStruct.bDebugPause = TRUE CDEBUG1LN(DEBUG_MINIGAME, "[IAP] [JS] IAP_DEBUG_PROCESSING - DEBUG PAUSE - PAUSED") IAP_DEBUG_DUMP_DATA_TO_LOGS() ENDIF ENDPROC #ENDIF // ------------------------------ EVENT PROCESSING ------------------------------ /// PURPOSE: /// Processes all incoming events PROC IAP_PROCESS_EVENTS() //REMOVE IF ANY OTHER EVENTS ADDED IF sIAPData.bLeaderboardRecieved EXIT ENDIF INT iCount SCRIPT_EVENT_DATA_CASINO_ARCADE_SEND_LEADERBOARD_EVENT EventDataLeaderboardSend REPEAT GET_NUMBER_OF_EVENTS(SCRIPT_EVENT_QUEUE_NETWORK) iCount IF GET_EVENT_AT_INDEX(SCRIPT_EVENT_QUEUE_NETWORK, iCount) != EVENT_NETWORK_SCRIPT_EVENT RELOOP ENDIF IF GET_EVENT_DATA(SCRIPT_EVENT_QUEUE_NETWORK, iCount, EventDataLeaderboardSend, SIZE_OF(EventDataLeaderboardSend)) IF EventDataLeaderboardSend.Details.Type = SCRIPT_EVENT_CASINO_ARCADE_SEND_LEADERBOARD_EVENT IF EventDataLeaderboardSend.eGameType != CASINO_ARCADE_GAME_INVADE_PERSUADE RELOOP ENDIF IAP_INITIALISE_LEADERBOARD(EventDataLeaderboardSend.iInitials, EventDataLeaderboardSend.iScores) RELOOP ENDIF ENDIF ENDREPEAT ENDPROC // ------------------------------ MAIN UPDATE ------------------------------ /// PURPOSE: /// Run every frame before the client state machine is processed PROC IAP_PRE_UPDATE() IF sIAPData.eCurrentState >= IAP_CLIENT_STATE_CLEANUP // Cleaning up, don't do anything EXIT ENDIF IF NOT IS_SKYSWOOP_AT_GROUND() IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_CLEANUP) EXIT ENDIF IF IAP_SHOULD_QUIT_NOW() IF IS_PLAYER_IN_ARCADE_PROPERTY(PLAYER_ID()) sIAPData.sArcadeCabinetAnimEvent.bLoopAnim = FALSE sIAPData.sArcadeCabinetAnimEvent.bHoldLastFrame = FALSE PLAY_ARCADE_CABINET_ANIMATION(sIAPData.sArcadeCabinetAnimEvent, ARCADE_CABINET_ANIM_CLIP_EXIT) ENDIF IAP_SET_CLIENT_STATE(IAP_CLIENT_STATE_CLEANUP) EXIT ENDIF IAP_PROCESS_EVENTS() IF NOT sIAPData.bLeaderboardRecieved AND (sIAPData.iLastLeaderboardRequest = -HIGHEST_INT OR NATIVE_TO_INT(GET_NETWORK_TIME()) - sIAPData.iLastLeaderboardRequest > ciIAP_RESEND_LEADERBOARD_REQUEST_TIME) BROADCAST_CASINO_ARCADE_REQUEST_LEADERBOARD_EVENT(GET_OWNER_OF_SIMPLE_INTERIOR_PLAYER_IS_IN(PLAYER_ID()), CASINO_ARCADE_GAME_INVADE_PERSUADE) sIAPData.iLastLeaderboardRequest = NATIVE_TO_INT(GET_NETWORK_TIME()) ENDIF IAP_UPDATE_ANIM_FRAMES() //Reset help text bit CLEAR_BIT(sIAPData.sPlayerTank.iPlayerTankBitset, ciIAP_PLAYER_TANK_BS_SHOWING_HELP_TEXT) BOOL bIsPlaying = sIAPData.eCurrentState >= IAP_CLIENT_STATE_DEGENETRON ARCADE_CABINET_COMMON_EVERY_FRAME_PROCESSING(bIsPlaying) ENDPROC /// PURPOSE: /// Run every frame after the client state machine is processed PROC IAP_POST_UPDATE() IF NOT IAP_SHOULD_ALLOW_HELP_TEXT_THIS_FRAME() HIDE_HELP_TEXT_THIS_FRAME() ENDIF sIAPData.sPlayerTank.iLastFrameTurretDirection = sIAPData.sPlayerTank.iTurretDirection ENDPROC /// PURPOSE: /// Call every frame to run the minigame PROC PROCESS_INVADE_AND_PERSUADE() IAP_PRE_UPDATE() #IF IS_DEBUG_BUILD IF NOT sIAPData.sDebugStruct.bDebugPause #ENDIF IAP_PROCESS_CLIENT_STATE_MACHINE() #IF IS_DEBUG_BUILD ENDIF #ENDIF IAP_POST_UPDATE() #IF IS_DEBUG_BUILD IAP_DEBUG_PROCESSING() #ENDIF ENDPROC