Advertisement
Guest User

Untitled

a guest
Jun 28th, 2014
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 32.16 KB | None | 0 0
  1. /*  <SA-MP Objects Physics - Handle collisions and more.>
  2.     Copyright (C) <2013>  <Peppe>
  3.  
  4.     This program is free software: you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation, either version 3 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program.  If not, see <http://www.gnu.org/licenses/>. */
  16.  
  17. #include <modelsizes>
  18. #pragma compress 1
  19. #include <YSI\y_iterate>
  20.  
  21. #if !defined PHY_TIMER_INTERVAL
  22.     #define PHY_TIMER_INTERVAL (20)
  23. #endif
  24. #if !defined PHY_MAX_WALLS    
  25.     #define PHY_MAX_WALLS (512)
  26. #endif
  27. #if !defined PHY_MAX_CYLINDERS
  28.     #define PHY_MAX_CYLINDERS (512)
  29. #endif     
  30.  
  31. #define PHY_MODE_3D (0)
  32. #define PHY_MODE_2D (1)
  33.  
  34. #if defined FLOAT_INFINITY
  35.     #undef FLOAT_INFINITY
  36. #endif
  37.  
  38. #if defined FLOAT_NEG_INFINITY
  39.     #undef FLOAT_NEG_INFINITY
  40. #endif
  41.  
  42. #if defined FLOAT_NAN
  43.     #undef FLOAT_NAN
  44. #endif
  45.  
  46. #define FLOAT_INFINITY   (Float:0x7F800000)
  47. #define FLOAT_NEG_INFINITY (Float:0xFF800000)
  48. #define FLOAT_NAN     (Float:0xFFFFFFFF)
  49.  
  50.  
  51. /* Callbacks */
  52. forward PHY_OnObjectUpdate(objectid);
  53. forward PHY_OnObjectCollideWithObject(object1, object2);
  54. forward PHY_OnObjectCollideWithWall(objectid, wallid);
  55. forward PHY_OnObjectCollideWithCylinder(objectid, cylinderid);
  56. forward PHY_OnObjectCollideWithPlayer(objectid, playerid);
  57.  
  58.  
  59. enum (<<= 1)
  60. {
  61.     PHY_OBJECT_USED = 0b01,
  62.     PHY_OBJECT_MODE,
  63.     PHY_OBJECT_ROLL,
  64.     PHY_OBJECT_GHOST_OBJECTS,
  65.     PHY_OBJECT_GHOST_WALLS,
  66.     PHY_OBJECT_GHOST_CYLINDERS,
  67.     PHY_OBJECT_PLAYER_COLLISIONS
  68. }
  69.  
  70. enum E_PHY_OBJECT
  71. {
  72.     PHY_Properties,
  73.     PHY_World,
  74.     Float:PHY_Size,
  75.     Float:PHY_Mass,
  76.     Float:PHY_VX,
  77.     Float:PHY_VY,
  78.     Float:PHY_VZ,
  79.     Float:PHY_AX,
  80.     Float:PHY_AY,
  81.     Float:PHY_AZ,
  82.     Float:PHY_Friction,
  83.     Float:PHY_AirResistance,
  84.     Float:PHY_Gravity,
  85.     Float:PHY_LowZBound,
  86.     Float:PHY_HighZBound,
  87.     Float:PHY_BoundConst,
  88.     Float:PHY_PlayerConst,
  89.     Float:PHY_PlayerDist,
  90.     Float:PHY_PlayerLowZ,
  91.     Float:PHY_PlayerHighZ
  92. }
  93.  
  94. new
  95.     PHY_Object[MAX_OBJECTS][E_PHY_OBJECT],
  96.     Iterator:ITER_Object<MAX_OBJECTS>;
  97.  
  98.  
  99. enum E_PHY_WALL
  100. {
  101.     PHY_Created,
  102.     PHY_World,
  103.     Float:PHY_X1,
  104.     Float:PHY_Y1,
  105.     Float:PHY_X2,
  106.     Float:PHY_Y2,
  107.     Float:PHY_Z1,
  108.     Float:PHY_Z2,
  109.     Float:PHY_BounceConst,
  110.     Float:PHY_ANG
  111. }
  112.  
  113. new
  114.     PHY_Wall[PHY_MAX_WALLS][E_PHY_WALL],
  115.     Iterator:ITER_Wall<PHY_MAX_WALLS>;
  116.  
  117.  
  118. enum E_PHY_CYLINDER
  119. {
  120.     PHY_Created,
  121.     PHY_World,
  122.     Float:PHY_X,
  123.     Float:PHY_Y,
  124.     Float:PHY_Z1,
  125.     Float:PHY_Z2,
  126.     Float:PHY_Size,
  127.     Float:PHY_BounceConst
  128. }
  129.  
  130. new
  131.     PHY_Cylinder[PHY_MAX_CYLINDERS][E_PHY_CYLINDER],
  132.     Iterator:ITER_Cylinder<PHY_MAX_CYLINDERS>;
  133.  
  134.  
  135. enum E_PHY_PLAYER
  136. {
  137.     PHY_World
  138. }
  139.  
  140. new
  141.     PHY_Player[MAX_PLAYERS][E_PHY_PLAYER];
  142.  
  143.  
  144. /* Macros are self-explanatory */
  145. #define PHY_IsObjectUsingPhysics(%1) (PHY_Object[%1][PHY_Properties] & PHY_OBJECT_USED)
  146. #define PHY_IsObjectUsing3D(%1) (PHY_Object[%1][PHY_Properties] & PHY_OBJECT_MODE)
  147. #define PHY_IsObjectGhostWithObjects(%1) (PHY_Object[%1][PHY_Properties] & PHY_OBJECT_GHOST_OBJECTS)
  148. #define PHY_IsObjectGhostWithWalls(%1) (PHY_Object[%1][PHY_Properties] & PHY_OBJECT_GHOST_WALLS)
  149. #define PHY_IsObjectGhostWithCylinders(%1) (PHY_Object[%1][PHY_Properties] & PHY_OBJECT_GHOST_CYLINDERS)
  150. #define PHY_IsObjectCollidingWithPlayers(%1) (PHY_Object[%1][PHY_Properties] & PHY_OBJECT_PLAYER_COLLISIONS)
  151. #define PHY_IsObjectMoving(%1) (PHY_Object[%1][PHY_VX] != 0 || PHY_Object[%1][PHY_VY] != 0 || PHY_Object[%1][PHY_VZ] != 0)
  152. #define PHY_IsObjectRolling(%1) (PHY_Object[%1][PHY_Properties] & PHY_OBJECT_ROLL)
  153. #define PHY_GetObjectFriction(%1) (PHY_Object[%1][PHY_Friction])
  154. #define PHY_GetObjectAirResistance(%1) (PHY_Object[%1][PHY_AirResistance])
  155. #define PHY_GetObjectGravity(%1) (PHY_Object[%1][PHY_Gravity])
  156. #define PHY_GetObjectMode(%1) (PHY_Object[%1][PHY_Properties] & PHY_OBJECT_MODE)
  157. #define PHY_MoveObject PHY_SetObjectVelocity
  158.  
  159.  
  160. static
  161.     cb_Connect;
  162.  
  163. public OnGameModeInit()
  164. {
  165.     SetTimer("PHY_CoreTimer", PHY_TIMER_INTERVAL, true);
  166.  
  167.     cb_Connect = funcidx("PHY_OnPlayerConnect") != -1;
  168.     if(funcidx("PHY_OnGameModeInit") != -1)
  169.         return CallLocalFunction("PHY_OnGameModeInit", "");
  170.     return 1;
  171. }
  172.  
  173. public OnPlayerConnect(playerid)
  174. {
  175.     PHY_Player[playerid][PHY_World] = 0;
  176.  
  177.     if(cb_Connect)
  178.         return CallLocalFunction("PHY_OnPlayerConnect", "i", playerid);
  179.     return 1;
  180. }
  181.  
  182. forward PHY_CoreTimer();
  183. public PHY_CoreTimer()
  184. {
  185.     new
  186.         Float:x,
  187.         Float:y,
  188.         Float:z,
  189.         Float:x1,
  190.         Float:y1,
  191.         Float:z1,
  192.         Float:xclosest,
  193.         Float:yclosest,
  194.         Float:x2,
  195.         Float:y2,
  196.         Float:z2,
  197.         Float:speed,
  198.         Float:dx,
  199.         Float:dy,
  200.         Float:dz,
  201.         Float:dist,
  202.         Float:maxdist,
  203.         Float:angle,
  204.         Float:moveangle,
  205.         Float:dvx,
  206.         Float:dvy,
  207.         Float:mag,
  208.         Float:tmpvx1,
  209.         Float:tmpvx2,
  210.         Float:newvy1,
  211.         Float:newvy2,
  212.         Float:newvx1,
  213.         Float:newvx2;
  214.     foreach(ITER_Object, a)
  215.     {
  216.         if(PHY_Object[a][PHY_Properties] & PHY_OBJECT_USED)
  217.         {
  218.             GetObjectPos(a, x, y, z);
  219.             x1 = x + PHY_Object[a][PHY_VX] * (PHY_TIMER_INTERVAL/1000.0);
  220.             y1 = y + PHY_Object[a][PHY_VY] * (PHY_TIMER_INTERVAL/1000.0);
  221.             if(PHY_GetObjectMode(a) == PHY_MODE_3D)
  222.             {
  223.                 z1 = z + PHY_Object[a][PHY_VZ] * (PHY_TIMER_INTERVAL/1000.0);
  224.  
  225.                 if(z1 > PHY_Object[a][PHY_HighZBound])
  226.                 {
  227.                     if(PHY_Object[a][PHY_VZ] > 0)
  228.                         PHY_Object[a][PHY_VZ] = -PHY_Object[a][PHY_VZ] * PHY_Object[a][PHY_BoundConst];
  229.                     z1 = PHY_Object[a][PHY_HighZBound];
  230.                 }
  231.                 else if(z1 < PHY_Object[a][PHY_LowZBound])
  232.                 {
  233.                     if(PHY_Object[a][PHY_VZ] < 0)
  234.                         PHY_Object[a][PHY_VZ] = -PHY_Object[a][PHY_VZ] * PHY_Object[a][PHY_BoundConst];
  235.                     z1 = PHY_Object[a][PHY_LowZBound];
  236.                 }
  237.                 if(PHY_GetObjectGravity(a) != 0)
  238.                 {
  239.                     if(PHY_Object[a][PHY_VZ] > 0)
  240.                     {
  241.                         PHY_Object[a][PHY_VZ] -= PHY_Object[a][PHY_Gravity] * (PHY_TIMER_INTERVAL/1000.0);
  242.                         if(PHY_Object[a][PHY_VZ] < 0)
  243.                             PHY_Object[a][PHY_VZ] = 0;
  244.                     }
  245.                     else
  246.                         PHY_Object[a][PHY_VZ] -= PHY_Object[a][PHY_Gravity] * (PHY_TIMER_INTERVAL/1000.0);
  247.                 }
  248.             }
  249.             else
  250.                 z1 = z;
  251.             if(PHY_IsObjectMoving(a))
  252.             {
  253.                 if(!PHY_IsObjectGhostWithObjects(a))
  254.                 {
  255.                     foreach(ITER_Object, b)
  256.                     {
  257.                         if(a != b && PHY_Object[b][PHY_Properties] & PHY_OBJECT_USED && !PHY_IsObjectGhostWithObjects(b) && (!PHY_Object[a][PHY_World] || !PHY_Object[b][PHY_World] || PHY_Object[a][PHY_World] == PHY_Object[b][PHY_World]))
  258.                         {
  259.                             GetObjectPos(b, x2, y2, z2);
  260.                             dx = x1 - x2;
  261.                             dy = y1 - y2;
  262.                             dz = (PHY_GetObjectMode(a) == PHY_MODE_3D && PHY_GetObjectMode(b) == PHY_MODE_3D) ? (z1 - z2) : (0.0);
  263.                             dist = (dx * dx) + (dy * dy) + (dz * dz);
  264.                             maxdist = PHY_Object[a][PHY_Size] + PHY_Object[b][PHY_Size];
  265.                             if(dist < (maxdist * maxdist))
  266.                             {
  267.                                 dvx = PHY_Object[a][PHY_VX] - PHY_Object[b][PHY_VX];
  268.                                 dvy = PHY_Object[a][PHY_VY] - PHY_Object[b][PHY_VX];
  269.                                 mag = dvx * dx + dvy * dy;
  270.  
  271.                                 if(mag < 0.0)
  272.                                 {
  273.                                     angle = -atan2(dy, dx);
  274.                                     tmpvx1 = PHY_Object[a][PHY_VX] * floatcos(angle, degrees) - PHY_Object[a][PHY_VY] * floatsin(angle, degrees);
  275.                                     newvy1 = PHY_Object[a][PHY_VX] * floatsin(angle, degrees) + PHY_Object[a][PHY_VY] * floatcos(angle, degrees);
  276.                                     tmpvx2 = PHY_Object[b][PHY_VX] * floatcos(angle, degrees) - PHY_Object[b][PHY_VY] * floatsin(angle, degrees);
  277.                                     newvy2 = PHY_Object[b][PHY_VX] * floatsin(angle, degrees) + PHY_Object[b][PHY_VY] * floatcos(angle, degrees);
  278.  
  279.                                     if(PHY_Object[a][PHY_Mass] == FLOAT_INFINITY)
  280.                                         newvx2 = -tmpvx2;
  281.                                     else if(PHY_Object[b][PHY_Mass] == FLOAT_INFINITY)
  282.                                         newvx1 = -tmpvx1;
  283.                                     else
  284.                                     {
  285.                                         newvx1 = ((PHY_Object[a][PHY_Mass] - PHY_Object[b][PHY_Mass]) * tmpvx1 + 2 * PHY_Object[b][PHY_Mass] * tmpvx2) / (PHY_Object[a][PHY_Mass] + PHY_Object[b][PHY_Mass]);
  286.                                         newvx2 = ((PHY_Object[b][PHY_Mass] - PHY_Object[a][PHY_Mass]) * tmpvx2 + 2 * PHY_Object[a][PHY_Mass] * tmpvx1) / (PHY_Object[a][PHY_Mass] + PHY_Object[b][PHY_Mass]);
  287.                                     }
  288.  
  289.                                     angle = -angle;
  290.                                     PHY_Object[a][PHY_VX] = newvx1 * floatcos(angle, degrees) - newvy1 * floatsin(angle, degrees);
  291.                                     PHY_Object[a][PHY_VY] = newvx1 * floatsin(angle, degrees) + newvy1 * floatcos(angle, degrees);
  292.                                     PHY_Object[b][PHY_VX] = newvx2 * floatcos(angle, degrees) - newvy2 * floatsin(angle, degrees);
  293.                                     PHY_Object[b][PHY_VY] = newvx2 * floatsin(angle, degrees) + newvy2 * floatcos(angle, degrees);
  294.  
  295.                                     CallLocalFunction("PHY_OnObjectCollideWithObject", "dd", a, b);
  296.                                 }
  297.                             }
  298.                         }
  299.                     }
  300.                 }
  301.                 if(!PHY_IsObjectGhostWithWalls(a))
  302.                 {
  303.                     foreach(ITER_Wall, w)
  304.                     {
  305.                         if(PHY_Wall[w][PHY_Created])
  306.                         {
  307.                             if((!PHY_Object[a][PHY_World] || !PHY_Wall[w][PHY_World] || PHY_Object[a][PHY_World] == PHY_Wall[w][PHY_World]))
  308.                             {
  309.                                 //dist = (y1 - PHY_Wall[w][PHY_M] * x1 - PHY_Wall[w][PHY_Q])/floatsqroot(1 + PHY_Wall[w][PHY_M] * PHY_Wall[w][PHY_M]);
  310.                                 //dist = (PHY_Wall[w][PHY_A] * x1 + PHY_Wall[w][PHY_B] * y1 + PHY_Wall[w][PHY_C])/floatsqroot(PHY_Wall[w][PHY_A] * PHY_Wall[w][PHY_A] + PHY_Wall[w][PHY_B] * PHY_Wall[w][PHY_B]);
  311.                                 angle = PHY_Wall[w][PHY_ANG];
  312.                                 if(PHY_Wall[w][PHY_Z1] - PHY_Object[a][PHY_Size] < z1 < PHY_Wall[w][PHY_Z2] + PHY_Object[a][PHY_Size] &&
  313.                                 (check_segment_intersection(PHY_Wall[w][PHY_X1], PHY_Wall[w][PHY_Y1], PHY_Wall[w][PHY_X2], PHY_Wall[w][PHY_Y2], x1, y1, PHY_Object[a][PHY_Size], xclosest, yclosest) || /* && floatabs(dist) < PHY_Object[a][PHY_Size]*/
  314.                                 check_segment_intersection(PHY_Wall[w][PHY_X1], PHY_Wall[w][PHY_Y1], PHY_Wall[w][PHY_X2], PHY_Wall[w][PHY_Y2], (x + x1)/2, (y + y1)/2, PHY_Object[a][PHY_Size], xclosest, yclosest)))
  315.                                 {
  316.                                     //mag = y1 + PHY_Object[a][PHY_Size] * floatcos(-moveangle, degrees) - (x1 + PHY_Object[a][PHY_Size] * floatsin(-moveangle, degrees)) * PHY_Wall[w][PHY_M] - PHY_Wall[w][PHY_Q];
  317.                                     //mag = PHY_Wall[w][PHY_A] * (x1 + PHY_Object[a][PHY_Size] * floatsin(-moveangle, degrees)) + PHY_Wall[w][PHY_B] * (y1 + PHY_Object[a][PHY_Size] * floatcos(-moveangle, degrees)) + PHY_Wall[w][PHY_C];
  318.                                     //if((dist >= 0) ? (mag <= 0) : (mag >= 0))
  319.                                     newvx1 = PHY_Wall[w][PHY_BounceConst] * (PHY_Object[a][PHY_VX] * floatcos(angle, degrees) - PHY_Object[a][PHY_VY] * floatsin(angle, degrees));
  320.                                     newvy1 = -PHY_Wall[w][PHY_BounceConst] * (PHY_Object[a][PHY_VX] * floatsin(angle, degrees) + PHY_Object[a][PHY_VY] * floatcos(angle, degrees));
  321.                                     angle = -angle;
  322.                                     PHY_Object[a][PHY_VX] = newvx1 * floatcos(angle, degrees) - newvy1 * floatsin(angle, degrees);
  323.                                     PHY_Object[a][PHY_VY] = newvx1 * floatsin(angle, degrees) + newvy1 * floatcos(angle, degrees);
  324.  
  325.                                     angle = angle + (newvy1 > 0 ? 90.0 : -90.0);
  326.                                     x1 = xclosest + (PHY_Object[a][PHY_Size] + 0.001) * floatcos(angle, degrees);
  327.                                     y1 = yclosest + (PHY_Object[a][PHY_Size] + 0.001) * floatsin(angle, degrees);
  328.  
  329.                                     CallLocalFunction("PHY_OnObjectCollideWithWall", "dd", a, w);
  330.                                 }
  331.                             }
  332.                         }
  333.                         else
  334.                             Iter_SafeRemove(ITER_Wall, w, w);
  335.                     }
  336.                 }
  337.                 if(!PHY_IsObjectGhostWithCylinders(a))
  338.                 {
  339.                     foreach(ITER_Cylinder, c)
  340.                     {
  341.                         if(PHY_Cylinder[c][PHY_Created])
  342.                         {
  343.                             if((!PHY_Object[a][PHY_World] || !PHY_Cylinder[c][PHY_World] || PHY_Object[a][PHY_World] == PHY_Cylinder[c][PHY_World]))
  344.                             {
  345.                                 if(PHY_Cylinder[c][PHY_Z1] - PHY_Object[a][PHY_Size] < z1 < PHY_Cylinder[c][PHY_Z2] + PHY_Object[a][PHY_Size])
  346.                                 {
  347.                                     x2 = PHY_Cylinder[c][PHY_X];
  348.                                     y2 = PHY_Cylinder[c][PHY_Y];
  349.                                     dx = x1 - x2;
  350.                                     dy = y1 - y2;
  351.                                     dist = (dx * dx) + (dy * dy);
  352.                                     maxdist = PHY_Object[a][PHY_Size] + PHY_Cylinder[c][PHY_Size];
  353.                                     if(dist < (maxdist * maxdist))
  354.                                     {
  355.                                         mag = PHY_Object[a][PHY_VX] * dx + PHY_Object[a][PHY_VY] * dy;
  356.  
  357.                                         if(mag < 0.0)
  358.                                         {
  359.                                             angle = -atan2(dy, dx);
  360.                                             newvx1 = -PHY_Cylinder[c][PHY_BounceConst] * (PHY_Object[a][PHY_VX] * floatcos(angle, degrees) - PHY_Object[a][PHY_VY] * floatsin(angle, degrees));
  361.                                             newvy1 = PHY_Cylinder[c][PHY_BounceConst] * (PHY_Object[a][PHY_VX] * floatsin(angle, degrees) + PHY_Object[a][PHY_VY] * floatcos(angle, degrees));
  362.  
  363.                                             angle = -angle;
  364.                                             PHY_Object[a][PHY_VX] = newvx1 * floatcos(angle, degrees) - newvy1 * floatsin(angle, degrees);
  365.                                             PHY_Object[a][PHY_VY] = newvx1 * floatsin(angle, degrees) + newvy1 * floatcos(angle, degrees);
  366.  
  367.                                             CallLocalFunction("PHY_OnObjectCollideWithCylinder", "dd", a, c);
  368.                                         }
  369.                                     }
  370.                                 }
  371.                             }
  372.                         }
  373.                         else
  374.                             Iter_SafeRemove(ITER_Cylinder, c, c);
  375.                     }
  376.                 }
  377.                 if(PHY_IsObjectCollidingWithPlayers(a))
  378.                 {
  379.                     foreach(Player, i)
  380.                     {
  381.                         if((!PHY_Object[a][PHY_World] || !PHY_Player[i][PHY_World] || PHY_Object[a][PHY_World] == PHY_Player[i][PHY_World]))
  382.                         {
  383.                             GetPlayerPos(i, x2, y2, z2);
  384.  
  385.                             if(z2 - PHY_Object[a][PHY_PlayerLowZ] - PHY_Object[a][PHY_Size] < z1 < z2 + PHY_Object[a][PHY_PlayerHighZ] + PHY_Object[a][PHY_Size])
  386.                             {
  387.                                 dx = x1 - x2;
  388.                                 dy = y1 - y2;
  389.                                 dist = (dx * dx) + (dy * dy);
  390.                                 maxdist = PHY_Object[a][PHY_Size] + PHY_Object[a][PHY_PlayerDist];
  391.                                 if(dist < (maxdist * maxdist))
  392.                                 {
  393.                                     mag = PHY_Object[a][PHY_VX] * dx + PHY_Object[a][PHY_VY] * dy;
  394.  
  395.                                     if(mag < 0.0)
  396.                                     {
  397.                                         angle = -atan2(dy, dx);
  398.                                         newvx1 = -PHY_Object[a][PHY_PlayerConst] * (PHY_Object[a][PHY_VX] * floatcos(angle, degrees) - PHY_Object[a][PHY_VY] * floatsin(angle, degrees));
  399.                                         newvy1 = PHY_Object[a][PHY_PlayerConst] * (PHY_Object[a][PHY_VX] * floatsin(angle, degrees) + PHY_Object[a][PHY_VY] * floatcos(angle, degrees));
  400.  
  401.                                         angle = -angle;
  402.                                         PHY_Object[a][PHY_VX] = newvx1 * floatcos(angle, degrees) - newvy1 * floatsin(angle, degrees);
  403.                                         PHY_Object[a][PHY_VY] = newvx1 * floatsin(angle, degrees) + newvy1 * floatcos(angle, degrees);
  404.  
  405.                                         CallLocalFunction("PHY_OnObjectCollideWithPlayer", "dd", a, i);
  406.                                     }
  407.                                 }
  408.                             }
  409.                         }
  410.                     }
  411.                 }
  412.                 moveangle = atan2(PHY_Object[a][PHY_VY], PHY_Object[a][PHY_VX]) - 90.0;
  413.                 speed = floatsqroot(PHY_Object[a][PHY_VX] * PHY_Object[a][PHY_VX] + PHY_Object[a][PHY_VY] * PHY_Object[a][PHY_VY]);
  414.                 if(PHY_GetObjectFriction(a) != 0 && z1 == PHY_Object[a][PHY_LowZBound])
  415.                 {
  416.                     speed -= PHY_Object[a][PHY_Friction] * (PHY_TIMER_INTERVAL/1000.0);
  417.                     if(speed < 0.001)
  418.                         speed = 0;
  419.                     PHY_Object[a][PHY_VX] = speed * floatsin(-moveangle, degrees);
  420.                     PHY_Object[a][PHY_VY] = speed * floatcos(-moveangle, degrees);
  421.                 }
  422.                 if(PHY_GetObjectAirResistance(a) != 0)
  423.                 {
  424.                     PHY_Object[a][PHY_VX] -= PHY_Object[a][PHY_VX] * PHY_Object[a][PHY_AirResistance] * (PHY_TIMER_INTERVAL/1000.0);
  425.                     PHY_Object[a][PHY_VY] -= PHY_Object[a][PHY_VY] * PHY_Object[a][PHY_AirResistance] * (PHY_TIMER_INTERVAL/1000.0);
  426.                     PHY_Object[a][PHY_VZ] -= PHY_Object[a][PHY_VZ] * PHY_Object[a][PHY_AirResistance] * (PHY_TIMER_INTERVAL/1000.0);
  427.                 }
  428.                 if(PHY_IsObjectRolling(a) && speed > 0.0)
  429.                     PHY_ApplyRotation(a, speed, moveangle);
  430.             }
  431.  
  432.             PHY_Object[a][PHY_VX] += PHY_Object[a][PHY_AX];
  433.             PHY_Object[a][PHY_VY] += PHY_Object[a][PHY_AY];
  434.             PHY_Object[a][PHY_VZ] += PHY_Object[a][PHY_AZ];
  435.  
  436.             SetObjectPos(a, x1, y1, z1);
  437.             CallLocalFunction("PHY_OnObjectUpdate", "d", a);
  438.         }
  439.         else
  440.             Iter_SafeRemove(ITER_Object, a, a);
  441.     }
  442.     return 1;
  443. }
  444.  
  445.  
  446. /* Starts using physics for objectid.
  447. modelid - object's modelid, used to get its size with modelsizes include.
  448. mass - object's mass, it is like its weight and is used in collisions.
  449. size - object's sphere radius, taken from modelsizes.inc by default.
  450. mode - PHY_MODE_3D or PHY_MODE_2D. */
  451. stock PHY_InitObject(objectid, modelid = 0, Float:mass = 1.0, Float:size = FLOAT_NAN, mode = PHY_MODE_3D)
  452. {
  453.     if(IsValidObject(objectid))
  454.     {
  455.         PHY_Object[objectid][PHY_Properties] = PHY_OBJECT_USED | (mode ? PHY_OBJECT_MODE : 0);
  456.         PHY_Object[objectid][PHY_Mass] = mass;
  457.         PHY_Object[objectid][PHY_World] = 0;
  458.         PHY_Object[objectid][PHY_VX] = 0;
  459.         PHY_Object[objectid][PHY_VY] = 0;
  460.         PHY_Object[objectid][PHY_VZ] = 0;
  461.         PHY_Object[objectid][PHY_Gravity] = 0;
  462.         new
  463.             Float:unused;
  464.         GetObjectPos(objectid, unused, unused, PHY_Object[objectid][PHY_LowZBound]);
  465.         PHY_Object[objectid][PHY_HighZBound] = FLOAT_INFINITY;
  466.         PHY_Object[objectid][PHY_BoundConst] = 0;
  467.  
  468.         if(size != size)
  469.         {
  470.             if(modelid)
  471.                 PHY_Object[objectid][PHY_Size] = GetColSphereRadius(modelid);
  472.         }
  473.         else
  474.             PHY_Object[objectid][PHY_Size] = size;
  475.  
  476.         Iter_Add(ITER_Object, objectid);
  477.         return 1;
  478.     }
  479.     return 0;
  480. }
  481.  
  482. /* Stops using physics for objectid (doesn't destroy it). */
  483. stock PHY_DeleteObject(objectid)
  484. {
  485.     PHY_Object[objectid][PHY_Properties] = 0;
  486.     // Iter_Remove(ITER_Object, objectid);
  487.     return 1;
  488. }
  489.  
  490. /* Moves the object with vx, vy, vz velocities. */
  491. stock PHY_SetObjectVelocity(objectid, Float:vx, Float:vy, Float:vz = 0.0)
  492. {
  493.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  494.     {
  495.         PHY_Object[objectid][PHY_VX] = vx;
  496.         PHY_Object[objectid][PHY_VY] = vy;
  497.         PHY_Object[objectid][PHY_VZ] = vz;
  498.         return 1;
  499.     }
  500.     return 0;
  501. }
  502.  
  503. /* Self-explanatory */
  504. stock PHY_GetObjectVelocity(objectid, &Float:vx, &Float:vy, &Float:vz)
  505. {
  506.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  507.     {
  508.         vx = PHY_Object[objectid][PHY_VX];
  509.         vy = PHY_Object[objectid][PHY_VY];
  510.         vz = PHY_Object[objectid][PHY_VZ];
  511.         return 1;
  512.     }
  513.     return 0;
  514. }
  515.  
  516. /* Sets the object's acceleration. */
  517. stock PHY_SetObjectAcceleration(objectid, Float:ax, Float:ay, Float:az = 0.0)
  518. {
  519.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  520.     {
  521.         PHY_Object[objectid][PHY_AX] = ax;
  522.         PHY_Object[objectid][PHY_AY] = ay;
  523.         PHY_Object[objectid][PHY_AZ] = az;
  524.         return 1;
  525.     }
  526.     return 0;
  527. }
  528.  
  529. /* Self-explanatory */
  530. stock PHY_GetObjectAcceleration(objectid, &Float:ax, &Float:ay, &Float:az)
  531. {
  532.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  533.     {
  534.         ax = PHY_Object[objectid][PHY_AX];
  535.         ay = PHY_Object[objectid][PHY_AY];
  536.         az = PHY_Object[objectid][PHY_AZ];
  537.         return 1;
  538.     }
  539.     return 0;
  540. }
  541.  
  542. /* Self-explanatory */
  543. stock PHY_GetObjectSpeed(objectid, &Float:speed, _3D = 0)
  544. {
  545.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  546.     {
  547.         speed = floatsqroot(PHY_Object[objectid][PHY_VX] * PHY_Object[objectid][PHY_VX] + PHY_Object[objectid][PHY_VY] * PHY_Object[objectid][PHY_VY] + _3D ? (PHY_Object[objectid][PHY_VZ] * PHY_Object[objectid][PHY_VZ]) : 0.0);
  548.         return 1;
  549.     }
  550.     return 0;
  551. }
  552.  
  553. /* Self-explanatory */
  554. stock PHY_GetObjectMoveAngle(objectid, &Float:moveangle)
  555. {
  556.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  557.     {
  558.         moveangle = atan2(PHY_Object[objectid][PHY_VY], PHY_Object[objectid][PHY_VX]) - 90.0;
  559.         return 1;
  560.     }
  561.     return 0;
  562. }
  563.  
  564. /* Starts rolling the object when it moves of toggle = 1 or stops if toggle = 0. */
  565. stock PHY_RollObject(objectid, toggle = 1)
  566. {
  567.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  568.     {
  569.         if(toggle)
  570.             PHY_Object[objectid][PHY_Properties] |= PHY_OBJECT_ROLL;
  571.         else
  572.             PHY_Object[objectid][PHY_Properties] &= ~PHY_OBJECT_ROLL;
  573.         return 1;
  574.     }
  575.     return 0;
  576. }
  577.  
  578. /* Applies friction to the object when it moves on the floor. */
  579. stock PHY_SetObjectFriction(objectid, Float:friction)
  580. {
  581.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  582.     {
  583.         if(friction >= 0.0)
  584.             PHY_Object[objectid][PHY_Friction] = friction;
  585.         return 1;
  586.     }
  587.     return 0;
  588. }
  589.  
  590. /* Applies air resistance to the object when it moves. */
  591. stock PHY_SetObjectAirResistance(objectid, Float:resistance)
  592. {
  593.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  594.     {
  595.         if(0.0 <= resistance <= 1.0)
  596.             PHY_Object[objectid][PHY_AirResistance] = resistance;
  597.         return 1;
  598.     }
  599.     return 0;
  600. }
  601.  
  602. /* Limits the object's Z position.
  603. low - The lowest Z that the object can have (you can use FLOAT_NEG_INFINITY). If it is set to NaN it doesn't change.
  604. high - The highest Z that the object can have (you can use FLOAT_INFINITY). If it is set to NaN it doesn't change.
  605. (When you use PHY_InitObject lowest Z is set to the current object's Z and highest Z to FLOAT_INFINITY.
  606. constant - It should be from 0.0 to 1.0. If it is 1.0 the object doesn't lose velocity,
  607. if it is 0.0 the object stops when it bounces. It could be a middle ground.*/
  608. stock PHY_SetObjectZBound(objectid, Float:low = FLOAT_NAN, Float:high = FLOAT_NAN, Float:constant = 0.0)
  609. {
  610.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  611.     {
  612.         if(low == low)
  613.             PHY_Object[objectid][PHY_LowZBound] = low;
  614.         if(high == high)
  615.             PHY_Object[objectid][PHY_HighZBound] = high;
  616.         PHY_Object[objectid][PHY_BoundConst] = constant;
  617.         return 1;
  618.     }
  619.     return 0;
  620. }
  621.  
  622. /* Sets the gravity's acceleration that the object is subjected to. */
  623. stock PHY_SetObjectGravity(objectid, Float:gravity)
  624. {
  625.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  626.     {
  627.         PHY_Object[objectid][PHY_Gravity] = gravity;
  628.         return 1;
  629.     }
  630.     return 0;
  631. }
  632.  
  633. /* Object and walls collide only if the are in the same world or one of them is in the world 0 (default). */
  634. stock PHY_SetObjectWorld(objectid, world)
  635. {
  636.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  637.     {
  638.         PHY_Object[objectid][PHY_World] = world;
  639.         return 1;
  640.     }
  641.     return 0;
  642. }
  643.  
  644. /* Toggles object's collisions with players.
  645. - constant - It should be from 0.0 to 1.0. If it is 1.0 the object doesn't lose velocity,
  646. if it is 0.0 the object stops when it bounces. It could be a middle ground.
  647. - distoffset - The distance at which the object collides with the player.
  648. - zoffsetlow/zoffsethigh - The max Z distance (downward/upward) at which the object collides with the player. */
  649. stock PHY_ToggleObjectPlayerColls(objectid, toggle = 1, Float:constant = 1.0, Float:distoffset = 0.8, Float:zoffsetlow = 1.0, Float:zoffsethigh = 1.0)
  650. {
  651.     if(PHY_Object[objectid][PHY_Properties] & PHY_OBJECT_USED)
  652.     {
  653.         if(toggle)
  654.         {
  655.             PHY_Object[objectid][PHY_Properties] |= PHY_OBJECT_PLAYER_COLLISIONS;
  656.             PHY_Object[objectid][PHY_PlayerConst] = constant;
  657.             PHY_Object[objectid][PHY_PlayerDist] = distoffset;
  658.             PHY_Object[objectid][PHY_PlayerLowZ] = zoffsetlow;
  659.             PHY_Object[objectid][PHY_PlayerHighZ] = zoffsethigh;
  660.         }
  661.         else
  662.             PHY_Object[objectid][PHY_Properties] &= ~PHY_OBJECT_PLAYER_COLLISIONS;
  663.         return 1;
  664.     }
  665.     return 0;
  666. }
  667.  
  668. /* Used internally to rotate the objects */
  669. stock PHY_ApplyRotation(objectid, Float:speed, Float:moveangle)
  670. {
  671.     new
  672.         Float:rx, Float:ry, Float:rz;
  673.     GetObjectRot(objectid, rx, ry, rz);
  674.     rx -= speed * (PHY_TIMER_INTERVAL/1000.0) * (180.0/3.14159) / PHY_Object[objectid][PHY_Size];
  675.     if(rx < 0.0)
  676.         rx += 360.0;
  677.     rz = moveangle;
  678.     //PHY_Roll(rx, ry, rz, PHY_Object[a][PHY_VX], PHY_Object[a][PHY_VY], ((speed * PHY_TIMER_INTERVAL)/1000) * (180/3.14159) / PHY_Object[a][PHY_Size]);
  679.     SetObjectRot(objectid, rx, ry, rz);
  680.     return 1;
  681. }
  682.  
  683. /* Creates a collision wall (straight line) from A(x1, y1) to B(x2, y2).
  684. constant should be from 0.0 to 1.0. If it is 1.0 the object doesn't lose velocity,
  685. if it is 0.0 the object stops when it collides.
  686. low is the lowest wall's Z, high is the highest. If they're set to default the wall is like infinitely high.*/
  687. stock PHY_CreateWall(Float:x1, Float:y1, Float:x2, Float:y2, Float:constant = 1.0, Float:low = FLOAT_NEG_INFINITY, Float:high = FLOAT_INFINITY)
  688. {
  689.     new
  690.         i = Iter_Free(ITER_Wall);
  691.     if(i != -1)
  692.     {
  693.         if(!PHY_Wall[i][PHY_Created])
  694.         {
  695.             PHY_Wall[i][PHY_Created] = 1;
  696.             PHY_Wall[i][PHY_World] = 0;
  697.             PHY_Wall[i][PHY_X1] = x1;
  698.             PHY_Wall[i][PHY_Y1] = y1;
  699.             PHY_Wall[i][PHY_X2] = x2;
  700.             PHY_Wall[i][PHY_Y2] = y2;
  701.             PHY_Wall[i][PHY_Z1] = low;
  702.             PHY_Wall[i][PHY_Z2] = high;
  703.             PHY_Wall[i][PHY_BounceConst] = constant;
  704.             PHY_Wall[i][PHY_ANG] = atan2(y1 - y2, x1 - x2);
  705.             /*PHY_Wall[i][PHY_A] = -(y2 - y1);
  706.             PHY_Wall[i][PHY_B] = (x2 - x1);
  707.             PHY_Wall[i][PHY_C] = (y2 - y1) * x1 - (x2 - x1) * y1;*/
  708.             //PHY_Wall[i][PHY_Q] = -((y2 - y1) * x1)/(x2 - x1) + y1;
  709.  
  710.             Iter_Add(ITER_Wall, i);
  711.             return i;
  712.         }
  713.     }
  714.     return -1;
  715. }
  716.  
  717. /* Creates four walls that form an area. Works like IsPlayerInArea. */
  718. stock PHY_CreateArea(Float:minX, Float:minY, Float:maxX, Float:maxY, Float:constant = 1.0, Float:low = FLOAT_NEG_INFINITY, Float:high = FLOAT_INFINITY)
  719. {
  720.     PHY_CreateWall(minX, minY, minX, maxY, constant, low, high);
  721.     PHY_CreateWall(minX, maxY, maxX, maxY, constant, low, high);
  722.     PHY_CreateWall(maxX, maxY, maxX, minY, constant, low, high);
  723.     PHY_CreateWall(maxX, minY, minX, minY, constant, low, high);
  724. }
  725.  
  726. /* Self-explanatory */
  727. stock PHY_DestroyWall(wallid)
  728. {
  729.     PHY_Wall[wallid][PHY_Created] = 0;
  730.     // Iter_Remove(ITER_Wall, wallid);
  731.     return 1;
  732. }
  733.  
  734. /* See PHY_SetObjectWorld(objectid, world). */
  735. stock PHY_SetWallWorld(wallid, world)
  736. {
  737.     if(PHY_Wall[wallid][PHY_Created])
  738.     {
  739.         PHY_Wall[wallid][PHY_World] = world;
  740.         return 1;
  741.     }
  742.     return 0;
  743. }
  744.  
  745. /* Creates a collision cylinder at position x, y.
  746. constant should be from 0.0 to 1.0. If it is 1.0 the object doesn't lose velocity,
  747. if it is 0.0 the object stops when it collides.
  748. low is the lowest cylinder's Z, high is the highest. If they're set to default the cylinder is like infinitely high.*/
  749. stock PHY_CreateCylinder(Float:x, Float:y, Float:size, Float:constant = 1.0, Float:low = FLOAT_NEG_INFINITY, Float:high = FLOAT_INFINITY)
  750. {
  751.     new
  752.         i = Iter_Free(ITER_Cylinder);
  753.     if(i != -1)
  754.     {
  755.         if(!PHY_Cylinder[i][PHY_Created])
  756.         {
  757.             PHY_Cylinder[i][PHY_Created] = 1;
  758.             PHY_Cylinder[i][PHY_World] = 0;
  759.             PHY_Cylinder[i][PHY_X] = x;
  760.             PHY_Cylinder[i][PHY_Y] = y;
  761.             PHY_Cylinder[i][PHY_Size] = size;
  762.             PHY_Cylinder[i][PHY_Z1] = low;
  763.             PHY_Cylinder[i][PHY_Z2] = high;
  764.             PHY_Cylinder[i][PHY_BounceConst] = constant;
  765.  
  766.             Iter_Add(ITER_Cylinder, i);
  767.             return i;
  768.         }
  769.     }
  770.     return -1;
  771. }
  772.  
  773. /* Self-explanatory */
  774. stock PHY_DestroyCylinder(cylinderid)
  775. {
  776.     PHY_Cylinder[cylinderid][PHY_Created] = 0;
  777.     // Iter_Remove(ITER_Cylinder, cylinderid);
  778.     return 1;
  779. }
  780.  
  781. /* See PHY_SetObjectWorld(objectid, world). */
  782. stock PHY_SetCylinderWorld(cylinderid, world)
  783. {
  784.     if(PHY_Cylinder[cylinderid][PHY_Created])
  785.     {
  786.         PHY_Cylinder[cylinderid][PHY_World] = world;
  787.         return 1;
  788.     }
  789.     return 0;
  790. }
  791.  
  792. /* See PHY_SetObjectWorld(objectid, world). */
  793. stock PHY_SetPlayerWorld(playerid, world)
  794. {
  795.     PHY_Player[playerid][PHY_World] = world;
  796.     return 1;
  797. }
  798.  
  799. /* Privates */
  800.  
  801. stock Float:vectordotp(Float:v1x, Float:v1y, Float:v2x, Float:v2y)
  802.     return (v1x * v2x + v1y * v2y);
  803.  
  804. stock check_segment_intersection(Float:x1, Float:y1, Float:x2, Float:y2, Float:xc, Float:yc, Float:r, &Float:x, &Float:y)
  805. {
  806.     new Float:v1[2];
  807.     new Float:v2[2];
  808.     v1[0] = x2 - x1;
  809.     v1[1] = y2 - y1;
  810.     v2[0] = xc - x1;
  811.     v2[1] = yc - y1;
  812.     new Float:v1_len = floatsqroot(v1[0] * v1[0] + v1[1] * v1[1]);
  813.     v1[0] /= v1_len;
  814.     v1[1] /= v1_len;
  815.     new Float:proj = vectordotp(v2[0], v2[1], v1[0], v1[1]);
  816.     x = proj * v1[0] + x1;
  817.     y = proj * v1[1] + y1;
  818.     return ((0 - r < proj < v1_len + r) && ((x - xc) * (x - xc) + (y - yc) * (y - yc) < (r * r)));
  819. }
  820.  
  821. /* Function to make a better ball rolling, not used because it doesn't work well. */
  822. stock PHY_Roll(&Float:x, &Float:y, &Float:z, Float:dx, Float:dy, Float:speed)
  823. {
  824.     new Float:q_roll[4];
  825.     new Float:vx, Float:vy, Float:vz;
  826.     vectorcrossp(dx, dy, 0.0, 0.0, 0.0, 1.0, vx, vy, vz);
  827.     QuatFromAxisAngle(vx, vy, vz, -speed, q_roll[0], q_roll[1], q_roll[2], q_roll[3]);
  828.  
  829.     new Float:q_rot[4];
  830.     EulerToQuaternion(x, y, z, q_rot[0], q_rot[1], q_rot[2], q_rot[3]);
  831.  
  832.     new Float:q_res[4];
  833.     QuatMultiply(q_roll[0], q_roll[1], q_roll[2], q_roll[3], q_rot[0], q_rot[1], q_rot[2], q_rot[3], q_res[0], q_res[1], q_res[2], q_res[3]);
  834.  
  835.     QuaternionToEuler(q_res[0], q_res[1], q_res[2], q_res[3], x, y, z);
  836. }
  837.  
  838. stock QuatMultiply(Float:w1, Float:x1, Float:y1, Float:z1, Float:w2, Float:x2, Float:y2, Float:z2, &Float:q_w, &Float:q_x, &Float:q_y, &Float:q_z)
  839. {
  840.     q_w = w1*w2 - x1*x2 - y1*y2 - z1*z2;
  841.     q_x = w1*x2 + x1*w2 + y1*z2 - z1*y2;
  842.     q_y = w1*y2 - x1*z2 + y1*w2 + z1*x2;
  843.     q_z = w1*z2 + x1*y2 - y1*x2 + z1*w2;
  844.  
  845.     QuatNormalize(q_w, q_x, q_y, q_z);
  846. }
  847.  
  848. stock QuatFromAxisAngle(Float:x, Float:y, Float:z, Float:angle, &Float:q_w, &Float:q_x, &Float:q_y, &Float:q_z)
  849. {
  850.     new
  851.         Float:omega,
  852.         Float:s;
  853.  
  854.     s = floatsqroot(x*x + y*y + z*z);
  855.  
  856.     if (s > 0.01)
  857.     {
  858.  
  859.         x /= s;
  860.         y /= s;
  861.         z /= s;
  862.  
  863.         omega = 0.5 * angle;
  864.         s = floatsin(omega, degrees);
  865.  
  866.         q_x = s*x;
  867.         q_y = s*y;
  868.         q_z = s*z;
  869.         q_w = floatcos(omega, degrees);
  870.     }
  871.     else
  872.     {
  873.         q_x = 0.0;
  874.         q_y = 0.0;
  875.         q_z = 0.0;
  876.         q_w = 1.0;
  877.     }
  878.    
  879.     QuatNormalize(q_w, q_x, q_y, q_z);
  880. }
  881.  
  882. stock QuatNormalize(&Float:q_w, &Float:q_x, &Float:q_y, &Float:q_z)
  883. {
  884.     new Float:magnitude = floatsqroot(q_w*q_w + q_x*q_x + q_y*q_y + q_z*q_z);
  885.     if (magnitude == 0.0)
  886.     {
  887.         q_w = 1.0;
  888.         q_x = 0.0;
  889.         q_y = 0.0;
  890.         q_z = 0.0;
  891.     }
  892.     else
  893.     {
  894.         q_w /= magnitude;
  895.         q_x /= magnitude;
  896.         q_y /= magnitude;
  897.         q_z /= magnitude;
  898.     }
  899. }
  900.  
  901. stock EulerToQuaternion(Float:z, Float:x, Float:y, &Float:q_w, &Float:q_x, &Float:q_y, &Float:q_z)
  902. {
  903.     new Float:c1 = floatcos(x, degrees);
  904.     new Float:s1 = floatsin(x, degrees);
  905.     new Float:c2 = floatcos(y, degrees);
  906.     new Float:s2 = floatsin(y, degrees);
  907.     new Float:c3 = floatcos(z, degrees);
  908.     new Float:s3 = floatsin(z, degrees);
  909.     q_w = floatsqroot(1.0 + c1 * c2 + c1*c3 - s1 * s2 * s3 + c2*c3) / 2.0;
  910.     new Float:w4 = (4.0 * q_w);
  911.     q_x = (c2 * s3 + c1 * s3 + s1 * s2 * c3) / w4 ;
  912.     q_y = (s1 * c2 + s1 * c3 + c1 * s2 * s3) / w4 ;
  913.     q_z = (-s1 * s3 + c1 * s2 * c3 +s2) / w4 ;
  914.    
  915.     QuatNormalize(q_w, q_x, q_y, q_z);
  916. }
  917.  
  918. stock QuaternionToEuler(Float:q_w, Float:q_x, Float:q_y, Float:q_z, &Float:z, &Float:x, &Float:y)
  919. {
  920.     new Float:test = q_x*q_y + q_z*q_w;
  921.     if (test > 0.499) { // singularity at north pole
  922.         x = 2 * atan2(q_x,q_w);
  923.         y = 90.0;
  924.         z = 0;
  925.         return;
  926.     }
  927.     if (test < -0.499) { // singularity at south pole
  928.         x = -2 * atan2(q_x,q_w);
  929.         y = -90.0;
  930.         z = 0;
  931.         return;
  932.     }
  933.     new Float:sqx = q_x*q_x;
  934.     new Float:sqy = q_y*q_y;
  935.     new Float:sqz = q_z*q_z;
  936.     x = atan2(2*q_y*q_w-2*q_x*q_z , 1 - 2*sqy - 2*sqz);
  937.     y = asin(2*test);
  938.     z = atan2(2*q_x*q_w-2*q_y*q_z , 1 - 2*sqx - 2*sqz);
  939. }
  940.  
  941. stock vectorcrossp(Float:v1x, Float:v1y, Float:v1z, Float:v2x, Float:v2y, Float:v2z, &Float:c1, &Float:c2, &Float:c3)
  942. {
  943.     c1 = (v1y * v2z) - (v1z * v2y),
  944.     c2 = (v1z * v2x) - (v1x * v2z),
  945.     c3 = (v1x * v2y) - (v1y * v2x);
  946. }
  947.  
  948.  
  949. #if defined _ALS_OnGameModeInit
  950.     #undef OnGameModeInit
  951. #else
  952.     #define _ALS_OnGameModeInit
  953. #endif
  954. #define OnGameModeInit PHY_OnGameModeInit
  955.  
  956. forward OnGameModeInit();
  957.  
  958.  
  959. #if defined _ALS_OnPlayerConnect
  960.     #undef OnPlayerConnect
  961. #else
  962.     #define _ALS_OnPlayerConnect
  963. #endif
  964. #define OnPlayerConnect PHY_OnPlayerConnect
  965.  
  966. forward OnPlayerConnect(playerid);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement