//-------------------------------------------------
|
|
//
|
|
// 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 <a_samp>
|
|
|
|
// 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<MAX_PLAYERS; x++)
|
|
{
|
|
if(noclipdata[x][cameramode] == CAMERA_MODE_FLY) CancelFlyMode(x);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
|
|
public OnPlayerConnect(playerid)
|
|
{
|
|
// Reset the data belonging to this player slot
|
|
noclipdata[playerid][cameramode] = CAMERA_MODE_NONE;
|
|
noclipdata[playerid][lrold] = 0;
|
|
noclipdata[playerid][udold] = 0;
|
|
noclipdata[playerid][mode] = 0;
|
|
noclipdata[playerid][lastmove] = 0;
|
|
noclipdata[playerid][accelmul] = 0.0;
|
|
return 1;
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
|
|
public OnPlayerCommandText(playerid, cmdtext[])
|
|
{
|
|
if(!strcmp(cmdtext, "/flymode", true))
|
|
{
|
|
// Place the player in and out of edit mode
|
|
if(GetPVarType(playerid, "FlyMode")) CancelFlyMode(playerid);
|
|
else FlyMode(playerid);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
|
|
public OnPlayerUpdate(playerid)
|
|
{
|
|
if(noclipdata[playerid][cameramode] == CAMERA_MODE_FLY)
|
|
{
|
|
new keys,ud,lr;
|
|
GetPlayerKeys(playerid,keys,ud,lr);
|
|
|
|
if(noclipdata[playerid][mode] && (GetTickCount() - noclipdata[playerid][lastmove] > 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;
|
|
}
|
|
|
|
//--------------------------------------------------
|