04.05.2016, 03:02
(
Последний раз редактировалось Swedky; 18.11.2016 в 22:26.
Причина: Fixes y screens!
)
PHY.inc
This include gives you functions to move various kinds of stuff (objects, vehicles, textdraws, etc...) like a physical movement. So you could give your server more "realistic" appearance.The experimental filterscript was originally created by adri1, I make it functional by adding new things.
Original code: https://sampforum.blast.hk/showthread.php?tid=592930
First I'll show the functions and macros, later I'll show some example codes.
- Functions
pawn Код:
native PHY_Create(type_id, Float:fX, Float:fY, Float:fZ);
native PHY_Finish(slotid);
native PHY_Start(slotid, mode = PHY_MODE_LAUNCH, interval = 20);
native PHY_SetPos(slotid, Float:fX, Float:fY, Float:fZ);
native PHY_SetMode(slotid, mode);
native PHY_SetType(slotid, type);
native PHY_SetTypeID(slotid, type_id);
native PHY_SetSpeed(slotid, Float:speed);
native PHY_SetAcc(slotid, Float:acceleration);
native PHY_SetAngle(slotid, Float:angle);
native PHY_SetHeightAngle(slotid, Float:h_angle);
native PHY_SetBound(slotid, Float:bound);
native PHY_RestarMovement(slotid);
native PHY_GetMode(slotid);
native PHY_GetType(slotid);
native PHY_GetTypeID(slotid);
native PHY_GetTick(slotid);
native PHY_GetSpeed(slotid);
native PHY_GetAcc(slotid);
native PHY_GetAngle(slotid);
native PHY_GetHeightAngle(slotid);
native PHY_GetBound(slotid);
native PHY_Init();
native PHY_Stop();
native PHY_IsValid(slotid);
native PHY_GetPoolSize();
forward PHY_OnUpdate(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick, direction);
forward PHY_OnFinish(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick);
Main functions:
PHY_Create | Search an unused slot for start a new movement.
|
PHY_Finish | Finish a movement.
|
PHY_Start | Start a movement
| PHY_SetPos | Set a new position for a movement.
| PHY_Init | Init the include. This function must be processed before ANY other PHY's functions.
| PHY_Stop | Stop the timer that updates all existent movements.
| PHY_IsValid | Check if a slot it's being used.
| PHY_GetPoolSize | Get the last slot using.
|
The next functions just have two parameters (PHY_Set*(slotid, ...)) and never return values:
PHY_SetMode |
|
PHY_SetType |
|
PHY_SetTypeID |
|
PHY_SetSpeed |
|
PHY_SetAcc |
|
PHY_SetAngle |
|
PHY_SetHeightAngle |
|
PHY_SetBound |
|
PHY_RestarMovement |
|
The next functions only have one parameter (PHY_Get*(slotid)) and return the value setted by "PHY_Set*(slotid, *)":
PHY_GetMode |
|
PHY_GetType |
|
PHY_GetTypeID |
|
PHY_GetSpeed |
|
PHY_GetAcc |
|
PHY_GetAngle |
|
PHY_GetHeightAngle |
|
PHY_GetBound |
|
Callbacks:
PHY_OnUpdate | Is called when all movements are updated.
|
PHY_OnFinish | Is called when the movement is finished. Direction ever will be "PHY_DIRECTION_DOWN".
|
- Macros
- Limits:
- PHY_MAX_SLOTS - amount of slots. (default is "50").
- Accelerations:
- PHY_GRAVITY - Acceleration by gravity (9.81m/seg2)
- PHY_FRICTION - Default acceleration (5.0m/seg2)
- Movement modes:
- PHY_MODE_NONE - Nothing. The movement won't be updated.
- PHY_MODE_LAUNCH - Parabolic movement.
- PHY_MODE_ROLL - Orizontal movement.
- PHY_MODE_VERTICAL - Vertical movement or free fall.
- Types:
- PHY_TYPE_NONE - Nothing.
- PHY_TYPE_OBJECT - Move a object.
- PHY_TYPE_VEHICLE - Move a vehicle.
- PHY_TYPE_PLAYER - Move a player.
- PHY_TYPE_NPC - Move a NPC. This type has a bad sync.
- PHY_TYPE_ACTOR - Move an actor, you may get problems with many actors moving at same time (ackslimit issues!).
- PHY_TYPE_PICKUP - Move a pickup. This type has a bad sync (but can be fixed (see examples!))
- PHY_TYPE_TEXTDRAW - Move a textdraw.
- Directions:
- PHY_DIRECTION_UP - The movement is getting heigth (up)
- PHY_DIRECTION_DOWN - The movement is losing heigth (down)
- Limits:
Example codes:
1. Create a parabolic movement, simple. Using a object:
pawn Код:
CMD:launch(playerid)
{
new slotid = PHY_Create(0xFFFF, 0.0, 0.0, 2.33); // Search a free slot. If nothing is found, it will return "-1".
// Put "0xFFFF" as "type_id" because we don't know if we found a freeslot.
// Relax, later we will set the objectid with "PHY_SetTypeID".
// Check if a free slot wasn't found (and so avoid a possible crash)
if(slotid == -1) return SendClientMessage(playerid, 0xFF0000FF, "[<!>] There's not free slots. Try later.");
new objectid = CreateObject(1946, 0.0, 0.0, 2.33, 0.0, 0.0, 0.0); // Create a basket ball
// A free slot has been found
PHY_SetType(slotid, PHY_TYPE_OBJECT); // We'll move a object
PHY_SetTypeID(slotid, objectid); // We'll move what "objectid" returned.
PHY_SetSpeed(slotid, 15.0); // Set an initial speed of 10.0 m/seg2
PHY_SetAcc(slotid, -PHY_GRAVITY); // Set an acceleration (in this case, as it's negative it's an deceleration). As is "LaunchMode", is deceleration by gravity.
PHY_SetAngle(slotid, 90.0); // Set a direction angle of 90°
PHY_SetHeightAngle(slotid, 45.0); // Set an height angle of 45° (will cover the maximun distance possible).
PHY_SetBound(slotid, 2.33); // Set a bound. On this case Z limit.
// Still the movement wont be updated. We have to use "PHY_Start".
PHY_Start(slotid, PHY_MODE_LAUNCH); // Start the movement in "LaunchMode".
return 1;
}
pawn Код:
CMD:roll(playerid)
{
new slotid = PHY_Create(objectid, 0.0, 0.0, 2.33);
if(slotid == -1) return SendClientMessage(playerid, 0xFF0000FF, "[<!>] There's not free slots. Try later.");
new objectid = CreateObject(1946, 0.0, 0.0, 2.33, 0.0, 0.0, 0.0);
PHY_SetType(slotid, PHY_TYPE_OBJECT);
PHY_SetTypeID(slotid, objectid);
PHY_SetSpeed(slotid, 10.0); // Set an initial speed of 10.0 m/seg2
PHY_SetAcc(slotid, -PHY_FRICTION); // Set a deceleration of 5.0m/seg2. If the value is positive, the object "increases" his speed, else it decrease.
PHY_SetAngle(slotid, 90.0); // Set an angle direction
PHY_SetHeightAngle(slotid, 0.0); // We don't need this value
PHY_SetBound(slotid, 3000.0); // Set the maximun distance this can cover. We use "3000" for be sure that this will cover all his possible distance.
PHY_Start(slotid, PHY_MODE_ROLL); // And the ball is rolling :P
return 1;
}
pawn Код:
public PHY_OnUpdate(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick, direction)
{
if(PHY_GetType(slotid) == PHY_TYPE_OBJECT)
{
SetObjectPos(PHY_GetTypeID(slotid), fX, fY, fZ);
}
return 1;
}
public PHY_OnFinish(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
PHY_Finish(slotid);
return 1;
}
3. launch a missile on vertical direction and up, later when the object tries to fall we make him to explode!
pawn Код:
CMD:misil(playerid)
{
SetPlayerTime(playerid, 0, 0);
new slotid = PHY_Create(0xFFFF, 0.0, 0.0, 2.33);
if(slotid == -1) return SendClientMessage(playerid, 0xFF0000FF, "[<!>] There's not free slots. Try later.");
new objectid = CreateObject(345, 0.0, 0.0, 2.33, 90.0, 0.0, 0.0);
PHY_SetType(slotid, PHY_TYPE_OBJECT);
PHY_SetTypeID(slotid, objectid);
PHY_SetSpeed(slotid, 25.0);
PHY_SetAcc(slotid, -PHY_GRAVITY);
PHY_SetAngle(slotid, 0.0); // We don't need this value
PHY_SetHeightAngle(slotid, 0.0); // We don't need this value
PHY_SetBound(slotid, 2.33);
PHY_Start(slotid, PHY_MODE_VERTICAL);
return 1;
}
public PHY_OnUpdate(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick, direction)
{
if(PHY_GetType(slotid) == PHY_TYPE_OBJECT)
{
SetObjectPos(PHY_GetTypeID(slotid), fX, fY, fZ);
if(direction == PHY_DIRECTION_DOWN) The object is falling, this means that the object arrived at his maximum height possible
{
DestroyObject(PHY_GetTypeID(slotid)); // Destroy the object
PHY_Finish(slotid); // End movement
CreateExplosion(fX, fY, fZ, 6, 25.0);
}
}
return 1;
}
Thats are just some examples of what you can do with this include. You can make a lot of things, just imagine them!
Here is some examples more:
- PHY_TYPE_OBJECT:
pawn Код:
/* PHY.inc - @misil_launcher
* 1 object (misil).
* Handle a MP5, look at where you want the misil go, and press N key.
*/
#include <a_samp>
#include <PHY>
public OnFilterScriptInit()
{
PHY_Init();
return 1;
}
public OnPlayerSpawn(playerid)
{
GivePlayerWeapon(playerid, WEAPON_MP5, 1000);
return 1;
}
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if(newkeys & KEY_NO && GetPlayerWeapon(playerid) == WEAPON_MP5)
{
new Float:Pos[3], Float:VectZ, Float:angle, Float:h_ang;
GetPlayerCameraPos(playerid, Pos[0], Pos[1], Pos[2]);
GetPlayerCameraFrontVector(playerid, VectZ, VectZ, VectZ);
Pos[2] += 3.5;
h_ang = atan2((Pos[2] + VectZ) - Pos[2], 1.0) + 15.0;
GetPlayerPos(playerid, Pos[0], Pos[1], Pos[2]);
GetPlayerFacingAngle(playerid, angle);
new objectid = CreateObject(345, Pos[0], Pos[1], Pos[2], h_ang, 0.0, angle, 150.0);
new slotid = PHY_Create(objectid, Pos[0], Pos[1], Pos[2]);
PHY_SetType(slotid, PHY_TYPE_OBJECT);
PHY_SetSpeed(slotid, 30.0);
PHY_SetAngle(slotid, angle);
PHY_SetHeightAngle(slotid, h_ang);
PHY_SetBound(slotid, Pos[2] - 1.5);
PHY_SetAcc(slotid, -PHY_GRAVITY);
PHY_Start(slotid, PHY_MODE_LAUNCH);
return 1;
}
return 1;
}
/* PHY.inc */
public PHY_OnUpdate(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
if(PHY_GetType(slotid) == PHY_TYPE_OBJECT)
{
SetObjectPos(PHY_GetTypeID(slotid), fX, fY, fZ);
}
return 1;
}
public PHY_OnFinish(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
CreateExplosion(fX, fY, fZ, 6, 10.0);
DestroyObject(PHY_GetTypeID(slotid));
PHY_Finish(slotid);
return 1;
}
- PHY_TYPE_PICKUP:
pawn Код:
/* PHY.inc - @animed_pickup
* 1 pickup (invisible object).
* 1 object, who will do the animed pickup, because we can't use "DestroyPickup" & "CreatePickup" and that the player's
client load them so fast as to do the effect.
*/
#include <a_samp>
#include <PHY>
static animed_pickup[2];
public OnFilterScriptInit()
{
PHY_Init();
animed_pickup[0] = CreatePickup(19300, 1, 0.0, 0.0, 3.0); // create a invisible pickup
animed_pickup[1] = CreateObject(1559, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0); // create the pickup object, who will do the "anime pickup"
new slotid = PHY_Create(animed_pickup[1], 0.0, 0.0, 3.0);
PHY_SetSpeed(slotid, 5.0);
PHY_SetAcc(slotid, -PHY_GRAVITY);
PHY_SetBound(slotid, 3.0);
PHY_SetType(slotid, PHY_TYPE_PICKUP);
PHY_Start(slotid, PHY_MODE_VERTICAL);
return 1;
}
public OnPlayerPickUpPickup(playerid, pickupid)
{
SendClientMessage(playerid, -1, "* I'm an animed pickup!");
return 1;
}
/* PHY.inc */
public PHY_OnUpdate(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
if(PHY_GetType(slotid) == PHY_TYPE_PICKUP && PHY_GetTypeID(slotid) == animed_pickup[1])
{
SetObjectPos(PHY_GetTypeID(slotid), fX, fY, fZ);
}
return 1;
}
public PHY_OnFinish(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
PHY_RestartMovement(slotid); // Start again
return 1;
}
- PHY_TYPE_TEXTDRAW:
pawn Код:
/* PHY.inc - @countdown
* Un countdown in textdraw. Like in NFS.
*/
#include <a_samp>
#include <ZCMD>
#include <PHY>
static Text:CountTD[2];
static Count = 3;
static CountStr[][] = {"~r~GO!", "1", "2", "3"};
public OnFilterScriptInit()
{
PHY_Init(); // Iniciar
CountTD[0] = TextDrawCreate(643.000000, 145.000000, "_"); // Box
TextDrawLetterSize(CountTD[0], 4.640000, 3.900000);
TextDrawUseBox(CountTD[0], 1);
TextDrawBoxColor(CountTD[0], 150);
TextDrawTextSize(CountTD[0], -4.000000, 0.000000);
CountTD[1] = TextDrawCreate(306.000000, 139.000000, "_"); // Count
TextDrawBackgroundColor(CountTD[1], 255);
TextDrawFont(CountTD[1], 2);
TextDrawLetterSize(CountTD[1], 1.330000, 4.600000);
TextDrawColor(CountTD[1], 16777215);
TextDrawSetOutline(CountTD[1], 1);
TextDrawSetProportional(CountTD[1], 1);
return 1;
}
/* Comandos */
CMD:countdown()
{
new slotid = PHY_Create(_:CountTD[1], -5.0, 139.0, -0.0);
PHY_SetSpeed(slotid, 500.0);
PHY_SetAcc(slotid, -400.0);
PHY_SetAngle(slotid, 270.0);
PHY_SetBound(slotid, 645.0);
PHY_SetType(slotid, PHY_TYPE_TEXTDRAW);
PHY_Start(slotid, PHY_MODE_ROLL, 5);
TextDrawShowForPlayer(0, CountTD[0]);
TextDrawShowForPlayer(0, CountTD[1]);
return 1;
}
/* PHY.inc */
public PHY_OnUpdate(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
if(PHY_GetType(slotid) == PHY_TYPE_TEXTDRAW && PHY_GetTypeID(slotid) == _:CountTD[1])
{
TextDrawDestroy(CountTD[1]);
CountTD[1] = TextDrawCreate(fX, 139.000000, CountStr[Count]);
TextDrawBackgroundColor(CountTD[1], 255);
TextDrawFont(CountTD[1], 2);
TextDrawLetterSize(CountTD[1], 1.330000, 4.600000);
TextDrawColor(CountTD[1], 16777215);
TextDrawSetOutline(CountTD[1], 1);
TextDrawSetProportional(CountTD[1], 1);
TextDrawShowForPlayer(0, CountTD[1]);
}
return 1;
}
public PHY_OnFinish(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
new Float:acc = PHY_GetAcc(slotid); // store the initial acceleration
PHY_Finish(slotid);
if(acc > 0.0) // if it exceed the middle of screen
{
if(--Count != -1) return cmd_countdown(); // restart the movement
TextDrawHideForPlayer(0, CountTD[0]);
TextDrawHideForPlayer(0, CountTD[1]);
return 1;
}
slotid = PHY_Create(_:CountTD[1], fX, 139.0, -0.0);
PHY_SetSpeed(slotid, 50.0);
PHY_SetAcc(slotid, 500.0);
PHY_SetAngle(slotid, 270.0);
PHY_SetBound(slotid, 645.0);
PHY_SetType(slotid, PHY_TYPE_TEXTDRAW);
PHY_Start(slotid, PHY_MODE_ROLL, 5);
return 1;
}
- PHY_TYPE_VEHICLE:
pawn Код:
/* PHY.inc - @vehicle
* Compete in a race against a unoccupied vehicle, using PHY_MODE_ROLL.
*/
#include <a_samp>
#include <iZCMD>
#include <PHY>
enum RaceInfo_enum
{
TimerCount,
CountDown,
Rival,
WinnerID
}
static RaceInfo[RaceInfo_enum];
static vehicle;
static Text:RacePosTD[3];
public OnFilterScriptInit()
{
PHY_Init();
vehicle = CreateVehicle(411, 1205.5000, 2255.0000, 6.7500 + 1.5, 180.0000, -1, -1, -1);
RacePosTD[0] = TextDrawCreate(612.000000, 124.000000, "_");
TextDrawBackgroundColor(RacePosTD[0], 255);
TextDrawFont(RacePosTD[0], 1);
TextDrawLetterSize(RacePosTD[0], 0.500000, 9.000000);
TextDrawColor(RacePosTD[0], -1);
TextDrawSetOutline(RacePosTD[0], 0);
TextDrawSetProportional(RacePosTD[0], 1);
TextDrawSetShadow(RacePosTD[0], 1);
TextDrawUseBox(RacePosTD[0], 1);
TextDrawBoxColor(RacePosTD[0], 150);
TextDrawTextSize(RacePosTD[0], 427.000000, 31.000000);
RacePosTD[1] = TextDrawCreate(436.000000, 126.000000, "1)~n~2)~n~~n~~r~~h~META:");
TextDrawBackgroundColor(RacePosTD[1], 255);
TextDrawFont(RacePosTD[1], 1);
TextDrawLetterSize(RacePosTD[1], 0.490000, 2.000000);
TextDrawColor(RacePosTD[1], -1);
TextDrawSetOutline(RacePosTD[1], 0);
TextDrawSetProportional(RacePosTD[1], 1);
TextDrawSetShadow(RacePosTD[1], 1);
RacePosTD[2] = TextDrawCreate(596.000000, 126.000000, "_");
TextDrawAlignment(RacePosTD[2], 3);
TextDrawBackgroundColor(RacePosTD[2], 255);
TextDrawFont(RacePosTD[2], 2);
TextDrawLetterSize(RacePosTD[2], 0.350000, 2.000000);
TextDrawColor(RacePosTD[2], -1);
TextDrawSetOutline(RacePosTD[2], 0);
TextDrawSetProportional(RacePosTD[2], 1);
TextDrawSetShadow(RacePosTD[2], 1);
return 1;
}
/* Commands */
CMD:go(playerid)
{
new vehicleid = CreateVehicle(411, 1211.5000, 2255.0000, 6.7500 + 1.5, 180.0, 0, 0, -1);
PutPlayerInVehicle(playerid, vehicleid, 0);
AddVehicleComponent(vehicleid, 1010);
return 1;
}
CMD:start(playerid)
{
RaceInfo[TimerCount] = SetTimer("OnCountDown", 1000, true);
RaceInfo[CountDown] = 3;
RaceInfo[Rival] = playerid;
RaceInfo[WinnerID] = 0xFFFF;
GameTextForAll("~w~3", 1000, 3);
TogglePlayerControllable(playerid, false);
SetCameraBehindPlayer(playerid);
SetPlayerRaceCheckpoint(playerid, 1, 1211.0000, 1195.0000, 6.5400, 1211.0, 1190.0, 6.5400, 10.0);
TextDrawShowForPlayer(playerid, RacePosTD[0]);
TextDrawShowForPlayer(playerid, RacePosTD[1]);
TextDrawShowForPlayer(playerid, RacePosTD[2]);
return 1;
}
forward OnCountDown();
public OnCountDown()
{
switch(--RaceInfo[CountDown])
{
case 2: GameTextForAll("~w~2", 1250, 3);
case 1: GameTextForAll("~w~1", 1250, 3);
case 0:
{
KillTimer(RaceInfo[TimerCount]);
GameTextForAll("~r~Go!", 1500, 3);
for(new i = 0; i <= GetPlayerPoolSize(); i++) TogglePlayerControllable(i, true);
new slotid = PHY_Create(vehicle, 1205.5000, 2255.0000, 6.5400);
PHY_SetSpeed(slotid, 0.0);
PHY_SetAcc(slotid, 2.5 + (random(15) / 10.0));
PHY_SetBound(slotid, 1075.0); // the maximun distance it can cover
PHY_SetAngle(slotid, 180.0);
PHY_SetType(slotid, PHY_TYPE_VEHICLE);
PHY_Start(slotid, PHY_MODE_ROLL, 5);
return 1;
}
}
return 1;
}
public OnPlayerEnterRaceCheckpoint(playerid)
{
if(RaceInfo[WinnerID] == 0xFFFF)
{
SendClientMessage(playerid, 0x00FF00FF, "* You won!");
GivePlayerMoney(playerid, 30000);
RaceInfo[WinnerID] = playerid;
DisablePlayerRaceCheckpoint(playerid);
}
return 1;
}
/* PHY.inc */
public PHY_OnUpdate(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
if(PHY_GetType(slotid) == PHY_TYPE_VEHICLE)
{
static vehicleid;
vehicleid = PHY_GetTypeID(slotid);
SetVehiclePos(vehicleid, fX, fY, fZ);
SetVehicleZAngle(vehicleid, 180.0);
if(PHY_GetAcc(slotid) > 0.0)
{
static Float:Pos[3], Float:dist[2], str[50];
GetPlayerPos(RaceInfo[Rival], Pos[0], Pos[1], Pos[2]);
dist[0] = VectorSize(fX - 1211.0000, fY - 1195.0000, 0.0);
dist[1] = VectorSize(Pos[0] - 1211.0000, Pos[1] - 1195.0000, Pos[2] - 6.5400);
GetPlayerName(RaceInfo[Rival], str, 21);
format(str, sizeof(str), "%s~n~%s~n~~n~%0.2f", (dist[0] < dist[1]) ? ("PHY") : (str), (dist[1] < dist[0]) ? ("PHY") : (str), dist[1]);
TextDrawSetString(RacePosTD[2], str);
}
}
return 1;
}
public PHY_OnFinish(slotid, Float:fX, Float:fY, Float:fZ, Float:speed, tick)
{
new Float:acc = PHY_GetAcc(slotid);
PHY_Finish(slotid);
if(acc > 0.0) // Stop the vehicle
{
slotid = PHY_Create(vehicle, fX, fY, fZ);
PHY_SetSpeed(slotid, speed);
PHY_SetAcc(slotid, -30.0);
PHY_SetBound(slotid, 3000.0);
PHY_SetAngle(slotid, 180.0);
PHY_SetType(slotid, PHY_TYPE_VEHICLE);
PHY_Start(slotid, PHY_MODE_ROLL, 20);
}
if(RaceInfo[WinnerID] == 0xFFFF)
{
SendClientMessageToAll(0x00FFFFFF, "* You lost!");
DisablePlayerRaceCheckpoint(RaceInfo[WinnerID]);
RaceInfo[WinnerID] = -1;
TextDrawSetString(RacePosTD[2], "_");
TextDrawHideForPlayer(RaceInfo[Rival], RacePosTD[0]);
TextDrawHideForPlayer(RaceInfo[Rival], RacePosTD[1]);
TextDrawHideForPlayer(RaceInfo[Rival], RacePosTD[2]);
}
return 1;
}
Download: http://pastebin.com/Q3TfxXfw
Pictures: