/* SA:MP Multiplayer Modification Copyright 2004-2007 SA:MP Team Version: $Id: e_objects.inc,v 1.5 03/03/2007 00:20:32 Y_Less Exp $ Use exactly like any other include files in terms of functions. Few special notes: 1) If you want to use this you MUST call InitObjectPool(); Preferably in OnGameModeInit() but elsewhere will do. 2) There are a number of define lines for customisation, these are not required and if you don't know what they do ignore this part #define MAX_DYN_OBJECTS Sets the maximum number of objects the script can hold (default 1024) #define VIEW_DISTANCE Max distance from a player for an object to show (default 80.0) #define LOOP_GRANULARITY Number of itterations per second of the main objects processing loop less itterations = less processing but less accurate renderings however even a granularity of 1 should be fine for a decent view distance #define E_OBJECT_ALL_WARNINGS Turns off the function stock declarations so you can see which functions aren't used #define NO_OBJECTS_MOVE Disables object movement processing, if your objects don't move (instant jumping is different) turning this on greatly reduces processing #define NO_PLAYER_ONLY Defining this disables individual objects so all players see all objects this again increases speed but decreases flexibility #define MAX_WORLDS n This sets the number of virtual worlds objects are visible in (note, they may not be visible in this number depending on individual settings). Setting this to 0 disables virtual world options. (default 256) #define OBJECT_ARRAY_VISIBLE By default the object data array is hidden to the parent script (i.e. your script) for safety reasons, if you wish to make it visible to your script define this and the variable will be declared as new instead of static. #define GLOBAL_OBJECT_ARRAY Use this to set the name of the objects array, default is gss_odEObjects (Global Static Stock _ Object Data E_Objects) (not likely to cause conflicts) */ #if !defined MAX_WORLDS #define MAX_WORLDS 256 #endif #if !defined E_OBJECTS_ALL_WARNINGS #define STOCK stock #else #define STOCK #endif #if !defined OBJECT_ARRAY_VISIBLE #define OBJECT_ARRAY_SCOPE static #else #define OBJECT_ARRAY_SCOPE new #endif #if !defined GLOBAL_OBJECT_ARRAY #define GLOBAL_OBJECT_ARRAY gss_odEObjects #endif #if !defined MAX_DYN_OBJECTS #define MAX_DYN_OBJECTS 1024 #endif #if !defined VIEW_DISTANCE #define VIEW_DISTANCE 80.0 #endif #if !defined LOOP_GRANULARITY #define LOOP_GRANULARITY 5 #endif stock bool:operator==(xor:oper1, xor:oper2) return (oper1 || oper2) && !(oper1 && oper2); forward ObjectsLoop(); #define CEIL_DIV(%1,%2) (((%1) + (%2) - 1) / (%2)) // Round int divisions up #define PLAYERS_ARRAY_COUNT CEIL_DIV(MAX_PLAYERS, cellbits) #if MAX_WORLDS > 32 #define VW_ARRAY_COUNT CEIL_DIV(MAX_WORLDS, cellbits) #else #define VW_ARRAY_COUNT 2 #endif #define OBJECTS_ARRAY_COUNT CEIL_DIV(MAX_DYN_OBJECTS, cellbits) enum (<<=1) { OBJECT_ROTATED = 0x01000000, OBJECT_JUMPED, OBJECT_MOVING2, OBJECT_MOVING1, SHOW_ALL_WORLDS, SHOW_ALL_PLAYERS } #define OBJECT_MOVING (OBJECT_MOVING2 | OBJECT_MOVING1) #define NO_FLAGS 0x00FFFFFF enum OBJECT_DATA { Float:OD_POSITION[6], // Current location in the world #if !defined NO_OBJECTS_MOVE Float:OD_TARGET[4], // Place it's moving to #endif #if !defined NO_PLAYER_ONLY OD_PLAYERS[PLAYERS_ARRAY_COUNT], // Bit array of players #endif #if MAX_WORLDS > 0 OD_WORLDS[VW_ARRAY_COUNT], // Bit array of worlds #endif OD_MODEL // Model of the object, -1 = inactive, highest byte= flags } #define NO_OBJECT -1 #define DISTANCE(%1,%2,%3) DistanceToOrigin((X - (%1)), (Y - (%2)), (Z - (%3))) #define SET_ACTIVE(%1,%2) %1[(%2) / cellbits] |= 0x01 << ((%2) % cellbits) #define IS_BIT(%1,%2) ((((%2) / cellbits) < sizeof (%1)) && (%1[(%2) / cellbits] & 0x01 << ((%2) % cellbits))) STOCK OBJECT_ARRAY_SCOPE GLOBAL_OBJECT_ARRAY[MAX_DYN_OBJECTS][OBJECT_DATA]; forward rot(); STOCK GetDynamicObjectPos(objectid, &Float:X, &Float:Y, &Float:Z) { if (IsValidDynamicObject(objectid)) { X = GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][0]; Y = GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][1]; Z = GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][2]; return 1; } return 0; } STOCK GetDynamicObjectRot(objectid, &Float:RX, &Float:RY, &Float:RZ) { if (IsValidDynamicObject(objectid)) { RX = GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][3]; RY = GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][4]; RZ = GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][5]; return 1; } return 0; } STOCK MoveDynamicObject(objectid, Float:X, Float:Y, Float:Z, Float:S) { #if !defined NO_OBJECTS_MOVE if (IsValidDynamicObject(objectid)) { // Uses overloaded == operator, using xor: tags to do logical XOR // Very counter intuative but you can't define a ^^ operator // So although this looks like == it's true if ONLY ONE is true if (xor:(GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] & OBJECT_MOVING1) == xor:(GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] & OBJECT_MOVING2)) { // One of the moving flags is set // There's two so models can be re-moved GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] ^= OBJECT_MOVING; // Swap which flag is on } else { // Else and error checking - neither or both (can't be) were on GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] |= OBJECT_MOVING1; } GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][0] = X; GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][1] = Y; GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][2] = Z; GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][3] = S; return 1; } #else #pragma unused objectid, X, Y, Z, S #endif return 0; } STOCK StopDynamicObject(objectid) { #if !defined NO_OBJECTS_MOVE if (IsValidDynamicObject(objectid)) { // Get rid of both moving flags GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] &= ~(OBJECT_MOVING); } #else #pragma unused objectid #endif return 0; } STOCK IsValidDynamicObject(objectid) { if (objectid >= 0 && objectid < MAX_DYN_OBJECTS && GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] != NO_OBJECT) return 1; return 0; } // No STOCK as this function must be called for the script to be used InitObjectPool() { ObjectsLoop(); // Initial call to setup variables for (new i = 0; i < MAX_DYN_OBJECTS; i++) { GLOBAL_OBJECT_ARRAY[i][OD_MODEL] = NO_OBJECT; } SetTimer("ObjectsLoop", 1000 / LOOP_GRANULARITY, 1); } STOCK CreateDynamicObject(model, Float:X, Float:Y, Float:Z, Float:RX, Float:RY, Float:RZ) { new object = InternalAddObject(model, X, Y, Z, RX, RY, RZ); if (object != NO_OBJECT) { GLOBAL_OBJECT_ARRAY[object][OD_MODEL] |= SHOW_ALL_PLAYERS | SHOW_ALL_WORLDS; // 0b11000000... } return object; } STOCK CreatePlayerDynamicObject(playerid, model, Float:X, Float:Y, Float:Z, Float:RX, Float:RY, Float:RZ) { new object; #if !defined NO_PLAYER_ONLY object = InternalAddObject(model, X, Y, Z, RX, RY, RZ); if (object != NO_OBJECT) { GLOBAL_OBJECT_ARRAY[object][OD_PLAYERS] = AddPlayer(GLOBAL_OBJECT_ARRAY[object][OD_PLAYERS], playerid, 1); GLOBAL_OBJECT_ARRAY[object][OD_MODEL] |= SHOW_ALL_WORLDS; // 0b01000000... } #else #pragma unused playerid object = CreateDynamicObject(model, X, Y, Z, RX, RY, RZ); #endif return object; } STOCK CreateVWDynamicObject(virtualworld, model, Float:X, Float:Y, Float:Z, Float:RX, Float:RY, Float:RZ) { new object; #if MAX_WORLDS > 0 object = InternalAddObject(model, X, Y, Z, RX, RY, RZ); if (object != NO_OBJECT) { GLOBAL_OBJECT_ARRAY[object][OD_WORLDS] = AddVW(GLOBAL_OBJECT_ARRAY[object][OD_WORLDS], virtualworld, 1); GLOBAL_OBJECT_ARRAY[object][OD_MODEL] |= SHOW_ALL_PLAYERS; // 0b10000000... } #else #pragma unused virtualworld object = CreateDynamicObject(model, X, Y, Z, RX, RY, RZ); #endif return object; } STOCK CreatePlayerVWDynamicObject(playerid, virtualworld, model, Float:X, Float:Y, Float:Z, Float:RX, Float:RY, Float:RZ) { new object; #if !defined NO_PLAYER_ONLY #if MAX_WORLDS > 0 object = InternalAddObject(model, X, Y, Z, RX, RY, RZ); if (object != NO_OBJECT) { GLOBAL_OBJECT_ARRAY[object][OD_WORLDS] = AddVW(GLOBAL_OBJECT_ARRAY[object][OD_WORLDS], virtualworld, 1); GLOBAL_OBJECT_ARRAY[object][OD_PLAYERS] = AddPlayer(GLOBAL_OBJECT_ARRAY[object][OD_PLAYERS], playerid, 1); } #else #pragma unused virtualworld object = CreatePlayerDynamicObject(playerid, model, X, Y, Z, RX, RY, RZ); #endif #else #pragma unused playerid object = CreateVWDynamicObject(virtualworld, model, X, Y, Z, RX, RY, RZ); #endif return object; } static STOCK InternalAddObject(model, Float:X, Float:Y, Float:Z, Float:RX, Float:RY, Float:RZ) { // Check model here, all calls to the system go through here model &= NO_FLAGS; // Just make sure if (!IsValidModel(model)) return NO_OBJECT; for (new i = 0; i < MAX_DYN_OBJECTS; i++) { if (GLOBAL_OBJECT_ARRAY[i][OD_MODEL] == NO_OBJECT) { GLOBAL_OBJECT_ARRAY[i][OD_MODEL] = model; GLOBAL_OBJECT_ARRAY[i][OD_POSITION][0] = X; GLOBAL_OBJECT_ARRAY[i][OD_POSITION][1] = Y; GLOBAL_OBJECT_ARRAY[i][OD_POSITION][2] = Z; GLOBAL_OBJECT_ARRAY[i][OD_POSITION][3] = RX; GLOBAL_OBJECT_ARRAY[i][OD_POSITION][4] = RY; GLOBAL_OBJECT_ARRAY[i][OD_POSITION][5] = RZ; return i; } } return NO_OBJECT; } STOCK AddPlayerToObject(objectid, playerid) { #if !defined NO_PLAYER_ONLY if (objectid < MAX_DYN_OBJECTS && GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] != NO_OBJECT) { GLOBAL_OBJECT_ARRAY[objectid][OD_PLAYERS] = AddPlayer(GLOBAL_OBJECT_ARRAY[objectid][OD_PLAYERS], playerid); return 1; } #else #pragma unused objectid, playerid #endif return 0; } STOCK AddVWToObject(objectid, virtualworld) { #if MAX_WORLDS > 0 if (IsValidDynamicObject(objectid)) { GLOBAL_OBJECT_ARRAY[objectid][OD_WORLDS] = AddVW(GLOBAL_OBJECT_ARRAY[objectid][OD_WORLDS], virtualworld); return 1; } #else #pragma unused objectid, virtualworld #endif return 0; } STOCK AddAllVWToObject(objectid) { #if MAX_WORLDS > 0 if (IsValidDynamicObject(objectid)) { GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] |= SHOW_ALL_WORLDS; return 1; } #else #pragma unused objectid #endif return 0; } STOCK AddAllPlayersToObject(objectid) { #if !defined NO_PLAYER_ONLY if (IsValidDynamicObject(objectid)) { GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] |= SHOW_ALL_PLAYERS; return 1; } #else #pragma unused objectid #endif return 0; } STOCK RemovePlayerFromObject(objectid, playerid) { #if !defined NO_PLAYER_ONLY if (IsValidDynamicObject(objectid)) { GLOBAL_OBJECT_ARRAY[objectid][OD_PLAYERS] = RemovePlayer(GLOBAL_OBJECT_ARRAY[objectid][OD_PLAYERS], playerid); return 1; } #else #pragma unused objectid, playerid #endif return 0; } STOCK RemoveVWFromObject(objectid, virtualworld) { #if MAX_WORLDS > 0 if (IsValidDynamicObject(objectid)) { GLOBAL_OBJECT_ARRAY[objectid][OD_WORLDS] = RemoveVW(GLOBAL_OBJECT_ARRAY[objectid][OD_WORLDS], virtualworld); return 1; } #else #pragma unused objectid, virtualworld #endif return 0; } #if !defined NO_PLAYER_ONLY static STOCK RemovePlayer(players[], playerid) { new temp[PLAYERS_ARRAY_COUNT]; for (new i = 0; i < PLAYERS_ARRAY_COUNT; i++) { temp[i] = players[i]; } temp[playerid / cellbits] &= ~(0x01 << (playerid % cellbits)); return temp; } static STOCK AddPlayer(players[], playerid, set = 0) { new temp[PLAYERS_ARRAY_COUNT]; for (new i = 0; i < PLAYERS_ARRAY_COUNT; i++) { temp[i] = players[i]; } if (set) { temp[playerid / cellbits] = 0; } SET_ACTIVE(temp, playerid); return temp; } #endif #if MAX_WORLDS > 0 static STOCK RemoveVW(worlds[], vwid) { new temp[VW_ARRAY_COUNT]; for (new i = 0; i < VW_ARRAY_COUNT; i++) { temp[i] = worlds[i]; } temp[vwid / cellbits] &= ~(0x01 << (vwid % cellbits)); return temp; } static STOCK AddVW(worlds[], vwid, set = 0) { new temp[VW_ARRAY_COUNT]; for (new i = 0; i < VW_ARRAY_COUNT; i++) { temp[i] = worlds[i]; } if (set) { temp[vwid / cellbits] = 0; } SET_ACTIVE(temp, vwid); return temp; } #endif STOCK DestroyDynamicObject(objectid) { if (IsValidDynamicObject(objectid)) { GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] = NO_OBJECT; return 1; } return 0; } STOCK SetDynamicObjectPos(objectid, Float:X, Float:Y, Float:Z) { if (IsValidDynamicObject(objectid)) { GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][0] = X; GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][1] = Y; GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][2] = Z; GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] |= OBJECT_JUMPED; // Mark the object as having jumped to be recreated if it exists return 1; } return 0; } STOCK SetDynamicObjectRot(objectid, Float:RX, Float:RY, Float:RZ) { if (IsValidDynamicObject(objectid)) { GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][3] = RX; GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][4] = RY; GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][5] = RZ; GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] |= OBJECT_ROTATED; // Mark the object as having jumped to be recreated if it exists return 1; } return 0; } STOCK GetObject(objectid) { return GLOBAL_OBJECT_ARRAY[objectid]; } static STOCK PlayerObject(object[OBJECT_DATA], playerid) { // This function determines wether or not the player can see the object // Based on settings for the object and compile options for the script // If neither Worlds or Individuals are defined the result MUST be 1 #if MAX_WORLDS > 0 new vwid = GetPlayerVirtualWorld(playerid); if ((object[OD_MODEL] & SHOW_ALL_WORLDS) || IS_BIT(object[OD_WORLDS], vwid)) { #endif #if !defined NO_PLAYER_ONLY if ((object[OD_MODEL] & SHOW_ALL_PLAYERS) || IS_BIT(object[OD_PLAYERS], playerid)) { #endif #if MAX_WORLDS > 0 || !defined NO_PLAYER_ONLY return 1; #endif #if !defined NO_PLAYER_ONLY } #endif #if MAX_WORLDS > 0 } #endif #if MAX_WORLDS > 0 || !defined NO_PLAYER_ONLY return 0; #else #pragma unused object, playerid return 1; #endif } STOCK Float:DistanceToOrigin(Float:X, Float:Y, Float:Z) { return floatsqroot((X * X) + (Y * Y) + (Z * Z)); } #if !defined NO_OBJECTS_MOVE static STOCK Float:DistanceRemaining(objectid) { return DistanceToOrigin(GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][0] - GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][0], GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][1] - GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][1], GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][2] - GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][2]); } static STOCK InternalMoveObject(objectid, Float:elapsedtime) { new Float:distance = elapsedtime * GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][3]; new Float:remaining = DistanceRemaining(objectid); if (distance >= remaining) { GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][0] = GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][0]; GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][1] = GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][1]; GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][2] = GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][2]; new oldmove = GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] & OBJECT_MOVING; //OnDynamicObjectMoved(objectid); CallRemoteFunction("OnDynamicObjectMoved", "i", objectid); if (oldmove == GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] & OBJECT_MOVING) { // The object hasn't been repositioned in OnDynamicObjectMoved GLOBAL_OBJECT_ARRAY[objectid][OD_MODEL] &= ~(OBJECT_MOVING); } return 1; } else { remaining /= distance; // Calculate ratio GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][0] += (GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][0] - GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][0]) / remaining; GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][1] += (GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][1] - GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][1]) / remaining; GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][2] += (GLOBAL_OBJECT_ARRAY[objectid][OD_TARGET][2] - GLOBAL_OBJECT_ARRAY[objectid][OD_POSITION][2]) / remaining; } return 0; } /*OnDynamicObjectMoved(objectid) { #pragma unused objectid return 1; }*/ #endif public ObjectsLoop() { static sObjects[MAX_PLAYERS][MAX_OBJECTS]; static sLastModel[MAX_DYN_OBJECTS]; static firsttime = 0; #if !defined NO_OBJECTS_MOVE static sLastTickCount = 0; new TickCount = GetTickCount(); #endif if (firsttime) { #if !defined NO_OBJECTS_MOVE // Update moving object's locations new Float:fElapsedTime = float(TickCount - sLastTickCount) / 1000.0; for (new i = 0; i < MAX_DYN_OBJECTS; i++) { if (IsValidDynamicObject(i)) { if (GLOBAL_OBJECT_ARRAY[i][OD_MODEL] & (OBJECT_MOVING)) { // The object is moving according to either flag InternalMoveObject(i, fElapsedTime); } } } #endif new Float:X, Float:Y, Float:Z; for (new i = 0; i < MAX_PLAYERS; i++) { if (!IsPlayerConnected(i)) continue; GetPlayerPos(i, X, Y, Z); new activecount = 0; // Number of objects for this player new playeractive[OBJECTS_ARRAY_COUNT]; for (new j = 0; j < MAX_OBJECTS; j++) { // Check existing objects new obj = sObjects[i][j] & NO_FLAGS; // Strip flags if (obj != (NO_OBJECT & NO_FLAGS) && IsValidPlayerObject(i, j)) { if (IsValidDynamicObject(obj)) { new objdat[OBJECT_DATA]; objdat = GetObject(obj); if (sLastModel[obj] != objdat[OD_MODEL] & NO_FLAGS) goto mark_as_ignored; if (PlayerObject(objdat, i) && DISTANCE(objdat[OD_POSITION][0], objdat[OD_POSITION][1], objdat[OD_POSITION][2]) <= VIEW_DISTANCE) { // It's still active and OK activecount++; if (objdat[OD_MODEL] & OBJECT_JUMPED) { SetPlayerObjectPos(i, j, objdat[OD_POSITION][0], objdat[OD_POSITION][1], objdat[OD_POSITION][2]); } if (objdat[OD_MODEL] & OBJECT_ROTATED) { SetPlayerObjectRot(i, j, objdat[OD_POSITION][3], objdat[OD_POSITION][4], objdat[OD_POSITION][5]); } #if !defined NO_OBJECTS_MOVE if ((objdat[OD_MODEL] & OBJECT_MOVING) != (sObjects[i][j] & OBJECT_MOVING)) { // Object has changed motion SetPlayerObjectPos(i, j, objdat[OD_POSITION][0], objdat[OD_POSITION][1], objdat[OD_POSITION][2]); sObjects[i][j] &= ~(OBJECT_MOVING); if (objdat[OD_MODEL] & OBJECT_MOVING) { // Change of target // Mark as having got the new target sObjects[i][j] |= objdat[OD_MODEL] & OBJECT_MOVING; MovePlayerObject(i, j, objdat[OD_TARGET][0], objdat[OD_TARGET][1], objdat[OD_TARGET][2], objdat[OD_TARGET][3]); } else { // Stopped StopPlayerObject(i, j); } } #endif goto mark_as_done; } } mark_as_ignored: // Skipped if it's a good object DestroyPlayerObject(i, j); sObjects[i][j] = NO_OBJECT; mark_as_done: SET_ACTIVE(playeractive, obj); // Possibly not technically active but we know it can't be // so no point checking it againbelow } else { sObjects[i][j] = NO_OBJECT; } } for (new k = 0; k < MAX_DYN_OBJECTS && activecount < MAX_OBJECTS; k++) { // If activecount is filled subsequent itterations will // be ignored if (!IS_BIT(playeractive, k) && IsValidDynamicObject(k)) { new objdat[OBJECT_DATA]; objdat = GetObject(k); if (PlayerObject(objdat, i)) { // Go through the objects by priority: high-low //printf("found one: %d", k); if (DISTANCE(objdat[OD_POSITION][0], objdat[OD_POSITION][1], objdat[OD_POSITION][2]) <= VIEW_DISTANCE) { // Valid model new num = CreatePlayerObject(i, objdat[OD_MODEL] & NO_FLAGS, objdat[OD_POSITION][0], objdat[OD_POSITION][1], objdat[OD_POSITION][2], objdat[OD_POSITION][3], objdat[OD_POSITION][4], objdat[OD_POSITION][5]); if (IsValidPlayerObject(i, num)) { //printf("created: %d", num); sObjects[i][num] = k; // Store the obj activecount++; //sActive[i][k] = 1; SET_ACTIVE(playeractive, k); #if !defined NO_OBJECTS_MOVE if (objdat[OD_MODEL] & OBJECT_MOVING) { sObjects[i][num] |= objdat[OD_MODEL] & OBJECT_MOVING; MovePlayerObject(i, num, objdat[OD_TARGET][0], objdat[OD_TARGET][1], objdat[OD_TARGET][2], objdat[OD_TARGET][3]); } #endif } } } } } printf("player %d objects = %d", i, activecount); } for (new i = 0; i < MAX_DYN_OBJECTS; i++) { if (GLOBAL_OBJECT_ARRAY[i][OD_MODEL] != NO_OBJECT) { // Mark all objects as having been moved for all players GLOBAL_OBJECT_ARRAY[i][OD_MODEL] &= ~(OBJECT_JUMPED | OBJECT_ROTATED); } // Update the local settings so we know it's changed // Not in the loop as it could have been destroyed sLastModel[i] = GLOBAL_OBJECT_ARRAY[i][OD_MODEL] & NO_FLAGS; } } else { // Initial static setup for (new i = 0; i < MAX_PLAYERS; i++) { for (new j = 0; j < MAX_OBJECTS; j++) { sObjects[i][j] = NO_OBJECT; } } firsttime = 1; } #if !defined NO_OBJECTS_MOVE sLastTickCount = TickCount; #endif } STOCK IsValidModel(modelid) { static modeldat[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -515899393, -134217729, -1, -1, 33554431, -1, -1, -1, -14337, -1, -33, 127, 0, 0, 0, 0, 0, -8388608, -1, -1, -1, -16385, -1, -1, -1, -1, -1, -1, -1, -33, -1, -771751937, -1, -9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33554431, -25, -1, -1, -1, -1, -1, -1, -1073676289, -2147483648, 34079999, 2113536, -4825600, -5, -1, -3145729, -1, -16777217, -63, -1, -1, -1, -1, -201326593, -1, -1, -1, -1, -1, -257, -1, 1073741823, -133122, -1, -1, -65, -1, -1, -1, -1, -1, -1, -2146435073, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1073741823, -64, -1, -1, -1, -1, -2635777, 134086663, 0, -64, -1, -1, -1, -1, -1, -1, -1, -536870927, -131069, -1, -1, -1, -1, -1, -1, -1, -1, -16384, -1, -33554433, -1, -1, -1, -1, -1, -1610612737, 524285, -128, -1, 2080309247, -1, -1, -1114113, -1, -1, -1, 66977343, -524288, -1, -1, -1, -1, -2031617, -1, 114687, -256, -1, -4097, -1, -4097, -1, -1, 1010827263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -32768, -1, -1, -1, -1, -1, 2147483647, -33554434, -1, -1, -49153, -1148191169, 2147483647, -100781080, -262145, -57, 134217727, -8388608, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1048577, -1, -449, -1017, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1835009, -2049, -1, -1, -1, -1, -1, -1, -8193, -1, -536870913, -1, -1, -1, -1, -1, -87041, -1, -1, -1, -1, -1, -1, -209860, -1023, -8388609, -2096897, -1, -1048577, -1, -1, -1, -1, -1, -1, -897, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1610612737, -3073, -28673, -1, -1, -1, -1537, -1, -1, -13, -1, -1, -1, -1, -1985, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1056964609, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -236716037, -1, -1, -1, -1, -1, -1, -1, -536870913, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2097153, -2109441, -1, 201326591, -4194304, -1, -1, -241, -1, -1, -1, -1, -1, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -32768, -1, -1, -1, -2, -671096835, -1, -8388609, -66323585, -13, -1793, -32257, -247809, -1, -1, -513, 16252911, 0, 0, 0, -131072, 33554383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8356095, 0, 0, 0, 0, 0, 0, -256, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -268435449, -1, -1, -2049, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 92274627, -65536, -2097153, -268435457, 591191935, 1, 0, -16777216, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 127 }; if ((modelid >= 0) && (modelid < (sizeof (modeldat) * 32)) && IS_BIT(modeldat, modelid)) { return 1; } return 0; }