//------------------------------------------------- // // This is an example of using the AttachCameraToObject function // to create a no-clip flying camera. // // h02 2012 // // SA-MP 0.3e and above // //------------------------------------------------- #include // Players Move Speed #define MOVE_SPEED 100.0 #define ACCEL_RATE 0.03 // Players Mode #define CAMERA_MODE_NONE 0 #define CAMERA_MODE_FLY 1 // Key state definitions #define MOVE_FORWARD 1 #define MOVE_BACK 2 #define MOVE_LEFT 3 #define MOVE_RIGHT 4 #define MOVE_FORWARD_LEFT 5 #define MOVE_FORWARD_RIGHT 6 #define MOVE_BACK_LEFT 7 #define MOVE_BACK_RIGHT 8 // Enumeration for storing data about the player enum noclipenum { cameramode, flyobject, mode, lrold, udold, lastmove, Float:accelmul } new noclipdata[MAX_PLAYERS][noclipenum]; //-------------------------------------------------- public OnFilterScriptExit() { // If any players are still in edit mode, boot them out before the filterscript unloads for(new x; x 100)) { // If the last move was > 100ms ago, process moving the object the players camera is attached to MoveCamera(playerid); } // Is the players current key state different than their last keystate? if(noclipdata[playerid][udold] != ud || noclipdata[playerid][lrold] != lr) { if((noclipdata[playerid][udold] != 0 || noclipdata[playerid][lrold] != 0) && ud == 0 && lr == 0) { // All keys have been released, stop the object the camera is attached to and reset the acceleration multiplier StopPlayerObject(playerid, noclipdata[playerid][flyobject]); noclipdata[playerid][mode] = 0; noclipdata[playerid][accelmul] = 0.0; } else { // Indicates a new key has been pressed // Get the direction the player wants to move as indicated by the keys noclipdata[playerid][mode] = GetMoveDirectionFromKeys(ud, lr); // Process moving the object the players camera is attached to MoveCamera(playerid); } } noclipdata[playerid][udold] = ud; noclipdata[playerid][lrold] = lr; // Store current keys pressed for comparison next update return 0; } return 1; } //-------------------------------------------------- stock GetMoveDirectionFromKeys(ud, lr) { new direction = 0; if(lr < 0) { if(ud < 0) direction = MOVE_FORWARD_LEFT; // Up & Left key pressed else if(ud > 0) direction = MOVE_BACK_LEFT; // Back & Left key pressed else direction = MOVE_LEFT; // Left key pressed } else if(lr > 0) // Right pressed { if(ud < 0) direction = MOVE_FORWARD_RIGHT; // Up & Right key pressed else if(ud > 0) direction = MOVE_BACK_RIGHT; // Back & Right key pressed else direction = MOVE_RIGHT; // Right key pressed } else if(ud < 0) direction = MOVE_FORWARD; // Up key pressed else if(ud > 0) direction = MOVE_BACK; // Down key pressed return direction; } //-------------------------------------------------- stock MoveCamera(playerid) { new Float:FV[3], Float:CP[3]; GetPlayerCameraPos(playerid, CP[0], CP[1], CP[2]); // Cameras position in space GetPlayerCameraFrontVector(playerid, FV[0], FV[1], FV[2]); // Where the camera is looking at // Increases the acceleration multiplier the longer the key is held if(noclipdata[playerid][accelmul] <= 1) noclipdata[playerid][accelmul] += ACCEL_RATE; // Determine the speed to move the camera based on the acceleration multiplier new Float:speed = MOVE_SPEED * noclipdata[playerid][accelmul]; // Calculate the cameras next position based on their current position and the direction their camera is facing new Float:X, Float:Y, Float:Z; GetNextCameraPosition(noclipdata[playerid][mode], CP, FV, X, Y, Z); MovePlayerObject(playerid, noclipdata[playerid][flyobject], X, Y, Z, speed); // Store the last time the camera was moved as now noclipdata[playerid][lastmove] = GetTickCount(); return 1; } //-------------------------------------------------- stock GetNextCameraPosition(move_mode, Float:CP[3], Float:FV[3], &Float:X, &Float:Y, &Float:Z) { // Calculate the cameras next position based on their current position and the direction their camera is facing #define OFFSET_X (FV[0]*6000.0) #define OFFSET_Y (FV[1]*6000.0) #define OFFSET_Z (FV[2]*6000.0) switch(move_mode) { case MOVE_FORWARD: { X = CP[0]+OFFSET_X; Y = CP[1]+OFFSET_Y; Z = CP[2]+OFFSET_Z; } case MOVE_BACK: { X = CP[0]-OFFSET_X; Y = CP[1]-OFFSET_Y; Z = CP[2]-OFFSET_Z; } case MOVE_LEFT: { X = CP[0]-OFFSET_Y; Y = CP[1]+OFFSET_X; Z = CP[2]; } case MOVE_RIGHT: { X = CP[0]+OFFSET_Y; Y = CP[1]-OFFSET_X; Z = CP[2]; } case MOVE_BACK_LEFT: { X = CP[0]+(-OFFSET_X - OFFSET_Y); Y = CP[1]+(-OFFSET_Y + OFFSET_X); Z = CP[2]-OFFSET_Z; } case MOVE_BACK_RIGHT: { X = CP[0]+(-OFFSET_X + OFFSET_Y); Y = CP[1]+(-OFFSET_Y - OFFSET_X); Z = CP[2]-OFFSET_Z; } case MOVE_FORWARD_LEFT: { X = CP[0]+(OFFSET_X - OFFSET_Y); Y = CP[1]+(OFFSET_Y + OFFSET_X); Z = CP[2]+OFFSET_Z; } case MOVE_FORWARD_RIGHT: { X = CP[0]+(OFFSET_X + OFFSET_Y); Y = CP[1]+(OFFSET_Y - OFFSET_X); Z = CP[2]+OFFSET_Z; } } } //-------------------------------------------------- stock CancelFlyMode(playerid) { DeletePVar(playerid, "FlyMode"); CancelEdit(playerid); TogglePlayerSpectating(playerid, false); DestroyPlayerObject(playerid, noclipdata[playerid][flyobject]); noclipdata[playerid][cameramode] = CAMERA_MODE_NONE; return 1; } //-------------------------------------------------- stock FlyMode(playerid) { // Create an invisible object for the players camera to be attached to new Float:X, Float:Y, Float:Z; GetPlayerPos(playerid, X, Y, Z); noclipdata[playerid][flyobject] = CreatePlayerObject(playerid, 19300, X, Y, Z, 0.0, 0.0, 0.0); // Place the player in spectating mode so objects will be streamed based on camera location TogglePlayerSpectating(playerid, true); // Attach the players camera to the created object AttachCameraToPlayerObject(playerid, noclipdata[playerid][flyobject]); SetPVarInt(playerid, "FlyMode", 1); noclipdata[playerid][cameramode] = CAMERA_MODE_FLY; return 1; } //--------------------------------------------------