stock Pool_RespawnBalls(poolid) { if (g_poolTableData[poolid] [E_AIMER] != -1) { TogglePlayerControllable(g_poolTableData[poolid] [E_AIMER], 1); //ClearAnimations(g_poolTableData[poolid] [E_AIMER]); //ApplyAnimation(g_poolTableData[poolid] [E_AIMER], "CARRY", "crry_prtial", 1.0, 0, 0, 0, 0, 0); SetCameraBehindPlayer(g_poolTableData[poolid] [E_AIMER]); DestroyDynamicObject(g_poolTableData[poolid] [E_AIMER_OBJECT]); g_poolTableData[poolid] [E_AIMER_OBJECT] = -1; //TextDrawHideForPlayer(g_poolTableData[poolid] [E_AIMER], gPoolTD); //HidePlayerProgressBar(g_poolTableData[poolid] [E_AIMER], g_PoolPowerBar[g_poolTableData[poolid] [E_AIMER]]); g_poolTableData[poolid] [E_AIMER] = -1; } new Float: offset_x, Float: offset_y; for (new i = 0; i < sizeof(g_poolBallOffsetData); i ++) { // get offset according to angle of table Pool_RotateXY(g_poolBallOffsetData[i] [E_OFFSET_X], g_poolBallOffsetData[i] [E_OFFSET_Y], g_poolTableData[poolid] [E_ANGLE], offset_x, offset_y); // reset balls if (PHY_IsHandleValid(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i])) { PHY_DeleteObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i]); DestroyDynamicObject(PHY_GetHandleObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i])); g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i] = ITER_NONE; } // create pool balls on table new objectid = CreateDynamicObject( g_poolBallOffsetData[i] [E_MODEL_ID], g_poolTableData[poolid] [E_X] + offset_x, g_poolTableData[poolid] [E_Y] + offset_y, g_poolTableData[poolid] [E_Z] - 0.045, 0.0, 0.0, 0.0, .worldid = g_poolTableData[poolid] [E_WORLD], .priority = 999 ); // initialize physics on each ball Pool_InitBalls(poolid, objectid, i); } stop g_poolTableData[poolid] [E_TIMER]; // g_poolTableData[poolid] [E_TIMER] = SetTimerEx("OnPoolUpdate", POOL_TIMER_SPEED, true, "d", poolid); g_poolTableData[poolid] [E_TIMER] = repeat OnPoolUpdate[POOL_TIMER_SPEED](poolid); g_poolTableData[poolid] [E_BALLS_SCORED] = 0; } stock Pool_AreBallsStopped(poolid) { new balls_not_moving = 0; for (new i = 0; i < 16; i ++) { new ball_handle = g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i]; if (! PHY_IsHandleValid(ball_handle) || g_poolBallData[poolid] [E_POCKETED] [i] || ! PHY_IsObjectMoving(ball_handle)) { balls_not_moving ++; } } return balls_not_moving >= 16; } stock Pool_EndGame(poolid) { // hide scoreboard in 5 seconds Pool_UpdateScoreboard(poolid, 5000); // unset pool variables foreach (new i : poolplayers< poolid >) { DestroyDynamicObject(p_PoolHoleGuide[i]); p_PoolHoleGuide[i] = -1; p_isPlayingPool{ i } = false; p_PoolScore[i] = -1; p_PoolID[i] = -1; RestoreCamera(i); } Iter_Clear(poolplayers< poolid >); g_poolTableData[poolid] [E_STARTED] = false; g_poolTableData[poolid] [E_AIMER] = -1; g_poolTableData[poolid] [E_SHOTS_LEFT] = 0; g_poolTableData[poolid] [E_FOULS] = 0; g_poolTableData[poolid] [E_EXTRA_SHOT] = false; g_poolTableData[poolid] [E_READY] = false; g_poolTableData[poolid] [E_WAGER] = 0; g_poolTableData[poolid] [E_CUE_POCKETED] = false; stop g_poolTableData[poolid] [E_TIMER]; DestroyDynamicObject(g_poolTableData[poolid] [E_AIMER_OBJECT]); g_poolTableData[poolid] [E_AIMER_OBJECT] = -1; for (new i = 0; i < 16; i ++) { if (PHY_IsHandleValid(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i])) { PHY_DeleteObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i]); DestroyDynamicObject(PHY_GetHandleObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i])); g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i] = ITER_NONE; } } UpdateDynamic3DTextLabelText(g_poolTableData[poolid] [E_LABEL], COLOR_GREY, DEFAULT_POOL_STRING); return 1; } timer OnPoolUpdate[1000](poolid) { if (! g_poolTableData[poolid] [E_STARTED]) { return 1; } if (! Iter_Count(poolplayers< poolid >)) { Pool_EndGame(poolid); return 1; } new Float: Xa, Float: Ya, Float: Za; new Float: X, Float: Y, Float: Z; new keys, ud, lr; if (g_poolTableData[poolid] [E_CUE_POCKETED]) { new playerid = g_poolTableData[poolid] [E_NEXT_SHOOTER]; new cueball_handle = g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [0]; if (PHY_IsHandleValid(cueball_handle)) { new cueball_object = PHY_GetHandleObject(cueball_handle); GetPlayerKeys(playerid, keys, ud, lr); GetDynamicObjectPos(cueball_object, X, Y, Z); if (ud == KEY_UP) Y += 0.01; else if (ud == KEY_DOWN) Y -= 0.01; if (lr == KEY_LEFT) X -= 0.01; else if (lr == KEY_RIGHT) X += 0.01; // set position only if it is within boundaries if (IsPointInDynamicArea(g_poolTableData[poolid] [E_CUEBALL_AREA], X, Y, 0.0)) { SetDynamicObjectPos(cueball_object, X, Y, Z); } // click to set if (keys & KEY_FIRE) { // check if we are placing the pool ball near another pool ball for (new i = 1; i < MAX_POOL_BALLS; i ++) if (PHY_IsHandleValid(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i])) { GetDynamicObjectPos(PHY_GetHandleObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i]), Xa, Ya, Za); if (GetDistanceFromPointToPoint(X, Y, Xa, Ya) < 0.085) { return GameTextForPlayer(playerid, "~n~~n~~n~~r~~h~Ball too close to other!", 500, 3); } } // check if ball is close to hole new Float: hole_x, Float: hole_y; for (new i = 0; i < sizeof(g_poolPotOffsetData); i ++) { // rotate offsets according to table Pool_RotateXY(g_poolPotOffsetData[i] [0], g_poolPotOffsetData[i] [1], g_poolTableData[poolid] [E_ANGLE], hole_x, hole_y); // check if it is at the pocket if (Pool_IsObjectAtPos(PHY_GetHandleObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [0]), g_poolTableData[poolid] [E_X] + hole_x , g_poolTableData[poolid] [E_Y] + hole_y, g_poolTableData[poolid] [E_Z], POCKET_RADIUS)) { return GameTextForPlayer(playerid, "~n~~n~~n~~r~~h~Ball too close to hole!", 500, 3); } } // reset state SetCameraBehindPlayer(playerid); TogglePlayerControllable(playerid, true); g_poolTableData[poolid] [E_CUE_POCKETED] = false; ApplyAnimation(playerid, "CARRY", "crry_prtial", 4.0, 0, 1, 1, 0, 0, 1); Pool_SendTableMessage(poolid, -1, "{2DD9A9} * * %s(%d) has placed the cueball!", PlayerName(playerid), playerid); } } } else if (g_poolTableData[poolid] [E_AIMER] != -1) { new playerid = g_poolTableData[poolid] [E_AIMER]; GetPlayerKeys(playerid, keys, ud, lr); if (! (keys & KEY_FIRE)) { if (lr) { new Float: x, Float: y, Float: newrot, Float: dist; GetPlayerPos(playerid, X, Y ,Z); GetDynamicObjectPos(PHY_GetHandleObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [0]), Xa, Ya, Za); newrot = p_PoolAngle[playerid] [0] + (lr > 0 ? 0.9 : -0.9); dist = GetDistanceBetweenPoints(X, Y, 0.0, Xa, Ya, 0.0); // keep the head out of the point of view if (dist < 1.20) { dist = 1.20; } if (AngleInRangeOfAngle(p_PoolAngle[playerid] [1], newrot, 30.0)) { p_PoolAngle[playerid] [0] = newrot; Pool_UpdatePlayerCamera(playerid, poolid); Pool_GetXYInFrontOfPos(Xa, Ya, newrot + 180, x, y, 0.085); SetDynamicObjectPos(g_poolTableData[poolid] [E_AIMER_OBJECT], x, y, Za); SetDynamicObjectRot(g_poolTableData[poolid] [E_AIMER_OBJECT], 7.0, 0, p_PoolAngle[playerid] [0] + 180); Pool_GetXYInFrontOfPos(Xa, Ya, newrot + 180 - 5.0, x, y, dist); // offset 5 degrees SetPlayerPos(playerid, x, y, Z); SetPlayerFacingAngle(playerid, newrot); } } } else { if (g_poolTableData[poolid] [E_DIRECTION]) { g_poolTableData[poolid] [E_POWER] -= 2.0; } else { g_poolTableData[poolid] [E_POWER] += 2.0; } if (g_poolTableData[poolid] [E_POWER] <= 0) { g_poolTableData[poolid] [E_DIRECTION] = 0; g_poolTableData[poolid] [E_POWER] = 2.0; } else if (g_poolTableData[poolid] [E_POWER] > 100.0) { g_poolTableData[poolid] [E_DIRECTION] = 1; g_poolTableData[poolid] [E_POWER] = 99.0; } SetPlayerProgressBarMaxValue(playerid, g_PoolPowerBar[playerid], 67.0); SetPlayerProgressBarValue(playerid, g_PoolPowerBar[playerid], ((67.0 * g_poolTableData[poolid] [E_POWER]) / 100.0)); ShowPlayerProgressBar(playerid, g_PoolPowerBar[playerid]); TextDrawShowForPlayer(playerid, g_PoolTextdraw); } } new current_player = g_poolTableData[poolid] [E_NEXT_SHOOTER]; if ((! g_poolTableData[poolid] [E_SHOTS_LEFT] || g_poolTableData[poolid] [E_FOULS] || g_poolTableData[poolid] [E_EXTRA_SHOT]) && Pool_AreBallsStopped(poolid)) { Pool_QueueNextPlayer(poolid, current_player); // SetTimerEx("RestoreCamera", 800, 0, "d", current_player); defer RestoreCamera[800](current_player); } return 1; } timer deleteBall[100](poolid, ballid) { if (g_poolBallData[poolid] [E_POCKETED] [ballid] && PHY_IsHandleValid(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [ballid])) { PHY_DeleteObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [ballid]); DestroyDynamicObject(PHY_GetHandleObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [ballid])); g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [ballid] = ITER_NONE; } return 1; } public PHY_OnObjectCollideWithObject(object1, object2) { foreach (new poolid : pooltables) if (g_poolTableData[poolid] [E_STARTED]) { for (new i = 0; i < 16; i ++) { new table_ball_handle = g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i]; if (PHY_IsHandleValid(table_ball_handle) && PHY_GetHandleObject(object1) == PHY_GetHandleObject(table_ball_handle)) { PlayPoolSound(poolid, 31800 + random(3)); return 1; } } } return 1; } public PHY_OnObjectCollideWithWall(objectid, wallid) { foreach (new poolid : pooltables) if (g_poolTableData[poolid] [E_STARTED]) { for (new i = 0; i < 16; i ++) { new table_ball_handle = g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i]; if (PHY_IsHandleValid(table_ball_handle) && PHY_GetHandleObject(objectid) == PHY_GetHandleObject(table_ball_handle)) { PlayPoolSound(poolid, 31808); return 1; } } } return 1; } public PHY_OnObjectUpdate(objectid) { //new objectid = PHY_GetHandleObject(objectid); if (! IsValidDynamicObject(objectid)) { return 1; } new poolball_index = GetPoolBallIndexFromModel(Streamer_GetIntData(STREAMER_TYPE_OBJECT, objectid, E_STREAMER_MODEL_ID)); if (poolball_index == -1) { return 1; } foreach (new poolid : pooltables) if (g_poolTableData[poolid] [E_STARTED]) { new poolball_handle = g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [poolball_index]; if (! PHY_IsHandleValid(poolball_handle)) return 1; if (objectid == PHY_GetHandleObject(poolball_handle) && ! g_poolBallData[poolid] [E_POCKETED] [poolball_index] && PHY_IsObjectMoving(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [poolball_index])) { new holeid = Pool_IsBallInHole(poolid, objectid); if (holeid != -1) { new first_player = Iter_First(poolplayers< poolid >); new second_player = Iter_Last(poolplayers< poolid >); new current_player = g_poolTableData[poolid] [E_NEXT_SHOOTER]; new opposite_player = current_player != first_player ? first_player : second_player; // printf ("first_player %d, second_player %d, current_player = %d", first_player, second_player, current_player); // check if first ball was pocketed to figure winner if (g_poolBallOffsetData[poolball_index] [E_BALL_TYPE] == E_STRIPED || g_poolBallOffsetData[poolball_index] [E_BALL_TYPE] == E_SOLID) { if (++ g_poolTableData[poolid] [E_BALLS_SCORED] == 1) { // assign first player a type after first one is hit g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [current_player] = g_poolBallOffsetData[poolball_index] [E_BALL_TYPE]; // assign second player if (current_player == first_player) { g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [second_player] = g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [first_player] == E_STRIPED ? E_SOLID : E_STRIPED; } else if (current_player == second_player) { g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [first_player] = g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [second_player] == E_STRIPED ? E_SOLID : E_STRIPED; } // alert players in table foreach (new playerid : poolplayers< poolid >) { ClearPlayerChat(playerid); sendMessage(playerid, -1, ""COL_GREY"-- "COL_WHITE" %s(%d) is now playing as %s", PlayerName(first_player), first_player, g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [first_player] == E_STRIPED ? ("Striped") : ("Solid")); sendMessage(playerid, -1, ""COL_GREY"-- "COL_WHITE" %s(%d) is playing as %s", PlayerName(second_player), second_player, g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [second_player] == E_STRIPED ? ("Striped") : ("Solid")); } } } new Float: hole_x, Float: hole_y; // check what was pocketed if (g_poolBallOffsetData[poolball_index] [E_BALL_TYPE] == E_CUE) { GameTextForPlayer(current_player, "~n~~n~~n~~r~wrong ball", 3000, 3); Pool_SendTableMessage(poolid, -1, "{2DD9A9} * * %s(%d) has pocketed the cue ball, %s(%d) will set it!", PlayerName(current_player), current_player, PlayerName(opposite_player), opposite_player); // penalty for that g_poolTableData[poolid] [E_FOULS] ++; g_poolTableData[poolid] [E_SHOTS_LEFT] = 0; g_poolTableData[poolid] [E_EXTRA_SHOT] = false; g_poolTableData[poolid] [E_CUE_POCKETED] = true; } else if (g_poolBallOffsetData[poolball_index] [E_BALL_TYPE] == E_8BALL) { g_poolTableData[poolid] [E_BALLS_SCORED] ++; // restore player camera RestoreCamera(current_player); // check if valid shot if (p_PoolScore[current_player] < 7) { p_PoolScore[opposite_player] ++; Pool_SendTableMessage(poolid, -1, "{2DD9A9} * * %s(%d) has accidentally pocketed the 8-Ball ... %s(%d) wins!", PlayerName(current_player), current_player, PlayerName(opposite_player), opposite_player); Pool_OnPlayerWin(poolid, opposite_player); } else if (g_poolTableData[poolid] [E_PLAYER_8BALL_TARGET] [current_player] != holeid) { p_PoolScore[opposite_player] ++; Pool_SendTableMessage(poolid, -1, "{2DD9A9} * * %s(%d) has put the 8-Ball in the wrong pocket ... %s(%d) wins!", PlayerName(current_player), current_player, PlayerName(opposite_player), opposite_player); Pool_OnPlayerWin(poolid, opposite_player); } else { p_PoolScore[current_player] ++; Pool_OnPlayerWin(poolid, current_player); } return Pool_EndGame(poolid); } else { // check if player pocketed their own ball type or btfo if (g_poolTableData[poolid] [E_BALLS_SCORED] > 1 && g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [current_player] != g_poolBallOffsetData[poolball_index] [E_BALL_TYPE]) { p_PoolScore[opposite_player] += 1; GameTextForPlayer(current_player, "~n~~n~~n~~r~wrong ball", 3000, 3); Pool_SendTableMessage(poolid, -1, "{2DD9A9} * * %s(%d) has wrongly pocketed %s %s, instead of %s!", PlayerName(current_player), current_player, g_poolBallOffsetData[poolball_index] [E_BALL_TYPE] == E_STRIPED ? ("Striped") : ("Solid"), g_poolBallOffsetData[poolball_index] [E_BALL_NAME], g_poolTableData[poolid] [E_PLAYER_BALL_TYPE] [current_player] == E_STRIPED ? ("Striped") : ("Solid")); // penalty for that g_poolTableData[poolid] [E_FOULS] ++; g_poolTableData[poolid] [E_SHOTS_LEFT] = 0; g_poolTableData[poolid] [E_EXTRA_SHOT] = false; } else { p_PoolScore[current_player] ++; GameTextForPlayer(current_player, "~n~~n~~n~~g~+1 score", 3000, 3); Pool_SendTableMessage(poolid, -1, "{2DD9A9} * * %s(%d) has pocketed a %s %s!", PlayerName(current_player), current_player, g_poolBallOffsetData[poolball_index] [E_BALL_TYPE] == E_STRIPED ? ("Striped") : ("Solid"), g_poolBallOffsetData[poolball_index] [E_BALL_NAME]); // extra shot for scoring one's own g_poolTableData[poolid] [E_SHOTS_LEFT] = g_poolTableData[poolid] [E_FOULS] > 0 ? 0 : 1; g_poolTableData[poolid] [E_EXTRA_SHOT] = true; } // mark final target hole if ((p_PoolScore[first_player] == 7 && p_PoolHoleGuide[first_player] == -1) || (p_PoolScore[second_player] == 7 && p_PoolHoleGuide[second_player] == -1)) { foreach (new player_being_marked : poolplayers< poolid >) if (p_PoolScore[player_being_marked] == 7 && p_PoolHoleGuide[player_being_marked] == -1) { new opposite_holeid = g_poolHoleOpposite[holeid]; Pool_RotateXY(g_poolPotOffsetData[opposite_holeid] [0], g_poolPotOffsetData[opposite_holeid] [1], g_poolTableData[poolid] [E_ANGLE], hole_x, hole_y); p_PoolHoleGuide[player_being_marked] = CreateDynamicObject(18643, g_poolTableData[poolid] [E_X] + hole_x, g_poolTableData[poolid] [E_Y] + hole_y, g_poolTableData[poolid] [E_Z] - 0.5, 0.0, -90.0, 0.0, .playerid = player_being_marked); g_poolTableData[poolid] [E_PLAYER_8BALL_TARGET] [player_being_marked] = opposite_holeid; SendPoolMessage(player_being_marked, "You are now required to put the 8-Ball in the designated pocket."); Streamer_Update(player_being_marked); } } } // rotate hole offsets according to table Pool_RotateXY(g_poolPotOffsetData[holeid] [0], g_poolPotOffsetData[holeid] [1], g_poolTableData[poolid] [E_ANGLE], hole_x, hole_y); // move object into the pocket new move_speed = MoveDynamicObject(PHY_GetHandleObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [poolball_index]), g_poolTableData[poolid] [E_X] + hole_x, g_poolTableData[poolid] [E_Y] + hole_y, g_poolTableData[poolid] [E_Z] - 0.5, 1.0); // mark ball as pocketed g_poolBallData[poolid] [E_POCKETED] [poolball_index] = true; // delete it anyway // SetTimerEx("deleteBall", move_speed + 100, false, "dd", poolid, poolball_index); defer deleteBall[move_speed + 100](poolid, poolball_index); // update scoreboard Pool_UpdateScoreboard(poolid); PlayerPlaySound(current_player, 31803, 0.0, 0.0, 0.0); } return 1; } } return 1; } stock Pool_RespawnCueBall(poolid) { if (g_poolBallData[poolid] [E_POCKETED] [0]) { new Float: x, Float: y; Pool_RotateXY(0.5, 0.0, g_poolTableData[poolid] [E_ANGLE], x, y); // make sure object dont exist if (PHY_IsHandleValid(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [0])) { PHY_DeleteObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [0]); DestroyDynamicObject(PHY_GetHandleObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [0])); } // recreate cueball new cueball_object = CreateDynamicObject(3003, g_poolTableData[poolid] [E_X] + x, g_poolTableData[poolid] [E_Y] + y, g_poolTableData[poolid] [E_Z] - 0.045, 0.0, 0.0, 0.0, .worldid = g_poolTableData[poolid] [E_WORLD], .priority = 999); Pool_InitBalls(poolid, cueball_object, 0); // set next player camera new next_shooter = g_poolTableData[poolid] [E_NEXT_SHOOTER]; SetPlayerCameraPos(next_shooter, g_poolTableData[poolid] [E_X], g_poolTableData[poolid] [E_Y], g_poolTableData[poolid] [E_Z] + 2.0); SetPlayerCameraLookAt(next_shooter, g_poolTableData[poolid] [E_X], g_poolTableData[poolid] [E_Y], g_poolTableData[poolid] [E_Z]); ApplyAnimation(next_shooter, "POOL", "POOL_Idle_Stance", 3.0, 0, 1, 1, 0, 0, 1); TogglePlayerControllable(next_shooter, false); } } stock Pool_ResetBallPositions(poolid, begining_ball = 0, last_ball = MAX_POOL_BALLS) { static Float: last_x, Float: last_y, Float: last_z; static Float: last_rx, Float: last_ry, Float: last_rz; for (new i = begining_ball; i < last_ball; i ++) if (! g_poolBallData[poolid] [E_POCKETED] [i]) { new ball_handle = g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i]; if (! PHY_IsHandleValid(ball_handle)) continue; new ball_object = PHY_GetHandleObject(ball_handle); if (! IsValidDynamicObject(ball_object)) continue; new modelid = Streamer_GetIntData(STREAMER_TYPE_OBJECT, ball_object, E_STREAMER_MODEL_ID); //FIX // get current position GetDynamicObjectPos(ball_object, last_x, last_y, last_z); GetDynamicObjectRot(ball_object, last_rx, last_ry, last_rz); // destroy object if (PHY_IsHandleValid(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i])) { PHY_DeleteObject(g_poolBallData[poolid] [E_BALL_PHY_HANDLE] [i]); DestroyDynamicObject(ball_object); } // create pool balls on table new object = CreateDynamicObject(modelid, last_x, last_y, last_z, last_rx, last_ry, last_rz, .worldid = g_poolTableData[poolid] [E_WORLD], .priority = 999); // initialize physics on each ball Pool_InitBalls(poolid, object, i); } // show objects foreach (new playerid : poolplayers< poolid >) { Streamer_Update(playerid, STREAMER_TYPE_OBJECT); } }