Guest User

Supply Drops

a guest
Aug 1st, 2016
571
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #define     FILTERSCRIPT
  2. #include    <a_samp>
  3. #include    <foreach>       // by Kar - http://forum.sa-mp.com/showthread.php?t=570868
  4. #include    <izcmd>         // by Yashas - http://forum.sa-mp.com/showthread.php?t=576114
  5. #include    <mapandreas>    // by RyDeR - http://forum.sa-mp.com/showthread.php?t=273263
  6.  
  7. #define     MAX_DROPS       (50)
  8. #define     DIST            (300.0)
  9.  
  10. // Config
  11. #define     PLANE_TIME      (7)     // how many seconds does a plane need before flying (Default: 7)
  12. #define     REQ_COOLDOWN    (3)     // how many minutes does someone need to wait for requesting a supply drop again (Default: 3)
  13. #define     DROP_LIFE       (5)     // life time of a supply drop, in minutes (Default: 5)
  14. #define     AMMO_PRICE      (750)   // price of ammo request (Default: 750)
  15. #define     HEALTH_PRICE    (500)   // price of health kit request (Default: 500)
  16. #define     ARMOR_PRICE     (450)   // price of body armor request (Default: 450)
  17. #define     AMMO_AMOUNT     (150)   // how much ammo will be given with a weapon/ammo drop (Default: 150)
  18.  
  19. enum    _:E_DROPTYPE
  20. {
  21.     DROP_TYPE_WEAPON,
  22.     DROP_TYPE_AMMO,
  23.     DROP_TYPE_HEALTH,
  24.     DROP_TYPE_ARMOR
  25. }
  26.  
  27. enum    _:E_DROPDIALOG
  28. {
  29.     DIALOG_DROP_MENU,
  30.     DIALOG_DROP_WEAPONS,
  31.     DIALOG_DROP_CONFIRM
  32. }
  33.  
  34. enum    E_WEPDATA
  35. {
  36.     weaponID,
  37.     weaponPrice
  38. }
  39.  
  40. enum    E_DROP
  41. {
  42.     // objects
  43.     planeObj,
  44.     boxObj,
  45.     paraObj,
  46.     // pickup (created after drop is done)
  47.     dropPickup,
  48.     // label
  49.     Text3D: dropLabel,
  50.     // drop data
  51.     dropType,
  52.     dropData,
  53.     // timer
  54.     dropTimer,
  55.     // other
  56.     requestedBy
  57. }
  58.  
  59. new
  60.     SupplyData[MAX_DROPS][E_DROP],
  61.     Iterator: SupplyDrops<MAX_DROPS>;
  62.  
  63. new
  64.     AvailableWeapons[][E_WEPDATA] = {
  65.         // weapon id, price
  66.         // you can get weapon ids from here: https://wiki.sa-mp.com/wiki/Weapons
  67.         {WEAPON_SHOTGUN, 300},
  68.         {WEAPON_SAWEDOFF, 130},
  69.         {WEAPON_AK47, 500},
  70.         {WEAPON_MINIGUN, 1000000}
  71.     };
  72.  
  73. formatInt(intVariable, iThousandSeparator = ',', iCurrencyChar = '$')
  74. {
  75.     /*
  76.         By Kar
  77.         https://gist.github.com/Kar2k/bfb0eafb2caf71a1237b349684e091b9/8849dad7baa863afb1048f40badd103567c005a5#file-formatint-function
  78.     */
  79.     static
  80.         s_szReturn[ 32 ],
  81.         s_szThousandSeparator[ 2 ] = { ' ', EOS },
  82.         s_szCurrencyChar[ 2 ] = { ' ', EOS },
  83.         s_iVariableLen,
  84.         s_iChar,
  85.         s_iSepPos,
  86.         bool:s_isNegative
  87.     ;
  88.  
  89.     format( s_szReturn, sizeof( s_szReturn ), "%d", intVariable );
  90.  
  91.     if(s_szReturn[0] == '-')
  92.         s_isNegative = true;
  93.     else
  94.         s_isNegative = false;
  95.  
  96.     s_iVariableLen = strlen( s_szReturn );
  97.  
  98.     if ( s_iVariableLen >= 4 && iThousandSeparator)
  99.     {
  100.         s_szThousandSeparator[ 0 ] = iThousandSeparator;
  101.  
  102.         s_iChar = s_iVariableLen;
  103.         s_iSepPos = 0;
  104.  
  105.         while ( --s_iChar > _:s_isNegative )
  106.         {
  107.             if ( ++s_iSepPos == 3 )
  108.             {
  109.                 strins( s_szReturn, s_szThousandSeparator, s_iChar );
  110.  
  111.                 s_iSepPos = 0;
  112.             }
  113.         }
  114.     }
  115.     if(iCurrencyChar) {
  116.         s_szCurrencyChar[ 0 ] = iCurrencyChar;
  117.         strins( s_szReturn, s_szCurrencyChar, _:s_isNegative );
  118.     }
  119.     return s_szReturn;
  120. }
  121.  
  122. ConvertToMinutes(time)
  123. {
  124.     // http://forum.sa-mp.com/showpost.php?p=3223897&postcount=11
  125.     new string[15];//-2000000000:00 could happen, so make the string 15 chars to avoid any errors
  126.     format(string, sizeof(string), "%02d:%02d", time / 60, time % 60);
  127.     return string;
  128. }
  129.  
  130. GetWeaponModel(weaponid)
  131. {
  132.     switch(weaponid)
  133.     {
  134.         case 1: return 331;
  135.         case 2..8: return weaponid+331;
  136.         case 9: return 341;
  137.         case 10..15: return weaponid+311;
  138.         case 16..18: return weaponid+326;
  139.         case 22..29: return weaponid+324;
  140.         case 30,31: return weaponid+325;
  141.         case 32: return 372;
  142.         case 33..45: return weaponid+324;
  143.         case 46: return 371;
  144.     }
  145.  
  146.     return 18631;
  147. }
  148.  
  149. ReturnDropPickupModel(id)
  150. {
  151.     new model = 18631;
  152.    
  153.     switch(SupplyData[id][dropType])
  154.     {
  155.         case DROP_TYPE_WEAPON: model = GetWeaponModel(SupplyData[id][dropData]);
  156.         case DROP_TYPE_AMMO: model = 19832;
  157.         case DROP_TYPE_HEALTH: model = 11738;
  158.         case DROP_TYPE_ARMOR: model = 1242;
  159.     }
  160.    
  161.     return model;
  162. }
  163.  
  164. ShowDropMenu(playerid)
  165. {
  166.     new string[128];
  167.     format(string, sizeof(string), "Request Weapons\t\nRequest Ammo\t{2ECC71}%s\nRequest Health Kit\t{2ECC71}%s\nRequest Body Armor\t{2ECC71}%s", formatInt(AMMO_PRICE), formatInt(HEALTH_PRICE), formatInt(ARMOR_PRICE));
  168.     ShowPlayerDialog(playerid, DIALOG_DROP_MENU, DIALOG_STYLE_TABLIST, "Supply Drop", string, "Request", "Close");
  169.     return 1;
  170. }
  171.  
  172. ShowWeaponsMenu(playerid)
  173. {
  174.     new string[512], wname[24];
  175.     format(string, sizeof(string), "Weapon\tPrice\n");
  176.    
  177.     for(new i; i < sizeof(AvailableWeapons); i++)
  178.     {
  179.         GetWeaponName(AvailableWeapons[i][weaponID], wname, sizeof(wname));
  180.         format(string, sizeof(string), "%s%s\t{2ECC71}%s\n", string, wname, formatInt(AvailableWeapons[i][weaponPrice]));
  181.     }
  182.    
  183.     ShowPlayerDialog(playerid, DIALOG_DROP_WEAPONS, DIALOG_STYLE_TABLIST_HEADERS, "Supply Drop » {FFFFFF}Weapons", string, "Request", "Back");
  184.     return 1;
  185. }
  186.  
  187. ShowConfirmDialog(playerid)
  188. {
  189.     if(GetPVarInt(playerid, "supply_Price") > GetPlayerMoney(playerid)) return 1;
  190.     new string[128];
  191.    
  192.     switch(GetPVarInt(playerid, "supply_ReqType"))
  193.     {
  194.         case DROP_TYPE_WEAPON:
  195.         {
  196.             new wname[24];
  197.             GetWeaponName(AvailableWeapons[ GetPVarInt(playerid, "supply_WepIndex") ][weaponID], wname, sizeof(wname));
  198.             format(string, sizeof(string), "{FFFFFF}You're about to order a supply drop for {F1C40F}%s.\n\n{FFFFFF}Price: {2ECC71}%s", wname, formatInt(GetPVarInt(playerid, "supply_Price")));
  199.         }
  200.        
  201.         case DROP_TYPE_AMMO:
  202.         {
  203.             format(string, sizeof(string), "{FFFFFF}You're about to order a supply drop for {F1C40F}Ammo.\n\n{FFFFFF}Price: {2ECC71}%s", formatInt(GetPVarInt(playerid, "supply_Price")));
  204.         }
  205.  
  206.         case DROP_TYPE_HEALTH:
  207.         {
  208.             format(string, sizeof(string), "{FFFFFF}You're about to order a supply drop for {F1C40F}Health Kit.\n\n{FFFFFF}Price: {2ECC71}%s", formatInt(GetPVarInt(playerid, "supply_Price")));
  209.         }
  210.  
  211.         case DROP_TYPE_ARMOR:
  212.         {
  213.             format(string, sizeof(string), "{FFFFFF}You're about to order a supply drop for {F1C40F}Body Armor.\n\n{FFFFFF}Price: {2ECC71}%s", formatInt(GetPVarInt(playerid, "supply_Price")));
  214.         }
  215.     }
  216.    
  217.     ShowPlayerDialog(playerid, DIALOG_DROP_CONFIRM, DIALOG_STYLE_MSGBOX, "Supply Drop » {FFFFFF}Confirmation", string, "Confirm", "Cancel");
  218.     return 1;
  219. }
  220.  
  221. public OnFilterScriptInit()
  222. {
  223.     for(new i; i < MAX_DROPS; i++)
  224.     {
  225.         SupplyData[i][planeObj] = SupplyData[i][boxObj] = SupplyData[i][paraObj] = SupplyData[i][dropPickup] = SupplyData[i][dropTimer] = SupplyData[i][requestedBy] = -1;
  226.         SupplyData[i][dropLabel] = Text3D: -1;
  227.     }
  228.    
  229.     return 1;
  230. }
  231.  
  232. public OnFilterScriptExit()
  233. {
  234.     foreach(new i : SupplyDrops)
  235.     {
  236.         if(IsValidObject(SupplyData[i][planeObj])) DestroyObject(SupplyData[i][planeObj]);
  237.         if(IsValidObject(SupplyData[i][boxObj])) DestroyObject(SupplyData[i][boxObj]);
  238.         if(IsValidObject(SupplyData[i][paraObj])) DestroyObject(SupplyData[i][paraObj]);
  239.        
  240.         if(SupplyData[i][dropPickup] != -1) DestroyPickup(SupplyData[i][dropPickup]);
  241.         if(SupplyData[i][dropTimer] != -1) KillTimer(SupplyData[i][dropTimer]);
  242.         if(SupplyData[i][dropLabel] != Text3D: -1) Delete3DTextLabel(SupplyData[i][dropLabel]);
  243.     }
  244.    
  245.     return 1;
  246. }
  247.  
  248. public OnPlayerDisconnect(playerid, reason)
  249. {
  250.     foreach(new i : SupplyDrops) if(SupplyData[i][requestedBy] == playerid) SupplyData[i][requestedBy] = -1;
  251.     return 1;
  252. }
  253.  
  254. public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
  255. {
  256.     switch(dialogid)
  257.     {
  258.         case DIALOG_DROP_MENU:
  259.         {
  260.             if(!response) return 1;
  261.             SetPVarInt(playerid, "supply_ReqType", listitem);
  262.            
  263.             if(listitem == 0) {
  264.                 ShowWeaponsMenu(playerid);
  265.             }else{
  266.                 new price;
  267.                 switch(listitem)
  268.                 {
  269.                     case DROP_TYPE_AMMO: price = AMMO_PRICE;
  270.                     case DROP_TYPE_HEALTH: price = HEALTH_PRICE;
  271.                     case DROP_TYPE_ARMOR: price = ARMOR_PRICE;
  272.                 }
  273.                
  274.                 if(price > GetPlayerMoney(playerid))
  275.                 {
  276.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't afford this request.");
  277.                     return ShowDropMenu(playerid);
  278.                 }
  279.                
  280.                 SetPVarInt(playerid, "supply_Price", price);
  281.                 ShowConfirmDialog(playerid);
  282.             }
  283.            
  284.             return 1;
  285.         }
  286.        
  287.         case DIALOG_DROP_WEAPONS:
  288.         {
  289.             if(!response) return ShowDropMenu(playerid);
  290.             new price = AvailableWeapons[listitem][weaponPrice];
  291.             if(price > GetPlayerMoney(playerid))
  292.             {
  293.                 SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't afford this weapon.");
  294.                 return ShowWeaponsMenu(playerid);
  295.             }
  296.            
  297.             SetPVarInt(playerid, "supply_WepIndex", listitem);
  298.             SetPVarInt(playerid, "supply_Price", price);
  299.             ShowConfirmDialog(playerid);
  300.             return 1;
  301.         }
  302.        
  303.         case DIALOG_DROP_CONFIRM:
  304.         {
  305.             if(!response) return ShowDropMenu(playerid);
  306.             new price = GetPVarInt(playerid, "supply_Price");
  307.             if(price > GetPlayerMoney(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't afford this drop.");
  308.             new cooldown = GetPVarInt(playerid, "supply_Cooldown");
  309.             if(cooldown > gettime())
  310.             {
  311.                 new string[72];
  312.                 format(string, sizeof(string), "ERROR: {FFFFFF}Please wait %s more to request a supply drop again.", ConvertToMinutes(cooldown - gettime()));
  313.                 return SendClientMessage(playerid, 0xE74C3CFF, string);
  314.             }
  315.            
  316.             new id = Iter_Free(SupplyDrops);
  317.             if(id == -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't request a supply drop right now.");
  318.             GivePlayerMoney(playerid, -price);
  319.            
  320.             new Float: x, Float: y, Float: z;
  321.             GetPlayerPos(playerid, x, y, z);
  322.             GetPointZPos(x, y, z);
  323.  
  324.             SupplyData[id][requestedBy] = playerid;
  325.             SupplyData[id][dropType] = GetPVarInt(playerid, "supply_ReqType");
  326.             SupplyData[id][dropData] = AvailableWeapons[ GetPVarInt(playerid, "supply_WepIndex") ][weaponID];
  327.             SupplyData[id][dropTimer] = SetTimerEx("FlyPlane", PLANE_TIME * 1000, false, "ifffi", id, x, y, z, random(360));
  328.             Iter_Add(SupplyDrops, id);
  329.            
  330.             SendClientMessage(playerid, 0x3498DBFF, "PILOT: {FFFFFF}Request received.");
  331.             SetPVarInt(playerid, "supply_Cooldown", gettime() + REQ_COOLDOWN * 60);
  332.             return 1;
  333.         }
  334.     }
  335.    
  336.     return 0;
  337. }
  338.  
  339. public OnObjectMoved(objectid)
  340. {
  341.     switch(GetObjectModel(objectid))
  342.     {
  343.         case 1681:
  344.         {
  345.             // it's a plane, validate it & remove
  346.             foreach(new i : SupplyDrops)
  347.             {
  348.                 if(SupplyData[i][planeObj] == objectid)
  349.                 {
  350.                     DestroyObject(SupplyData[i][planeObj]);
  351.                     SupplyData[i][planeObj] = -1;
  352.                     break;
  353.                 }
  354.             }
  355.         }
  356.        
  357.         case 2975:
  358.         {
  359.             // it's a supply drop, validate it, create pickup then remove
  360.             foreach(new i : SupplyDrops)
  361.             {
  362.                 if(SupplyData[i][boxObj] == objectid)
  363.                 {
  364.                     new Float: x, Float: y, Float: z, string[48];
  365.                     switch(SupplyData[i][dropType])
  366.                     {
  367.                         case DROP_TYPE_WEAPON:
  368.                         {
  369.                             new weap_name[24];
  370.                             GetWeaponName(SupplyData[i][dropData], weap_name, sizeof(weap_name));
  371.                             format(string, sizeof(string), "Supply Drop\n\n{FFFFFF}%s", weap_name);
  372.                         }
  373.                        
  374.                         case DROP_TYPE_AMMO: format(string, sizeof(string), "Supply Drop\n\n{FFFFFF}Ammo");
  375.                         case DROP_TYPE_HEALTH: format(string, sizeof(string), "Supply Drop\n\n{FFFFFF}Health");
  376.                         case DROP_TYPE_ARMOR: format(string, sizeof(string), "Supply Drop\n\n{FFFFFF}Body Armor");
  377.                     }
  378.                    
  379.                     GetObjectPos(objectid, x, y, z);
  380.                     SupplyData[i][dropPickup] = CreatePickup(ReturnDropPickupModel(i), 1, x, y, z + 0.85);
  381.                     SupplyData[i][dropLabel] = Create3DTextLabel(string, 0xF1C40FFF, x, y, z + 1.65, 10.0, 0, 1);
  382.                    
  383.                     DestroyObject(SupplyData[i][paraObj]);
  384.                     DestroyObject(SupplyData[i][boxObj]);
  385.                     SupplyData[i][boxObj] = SupplyData[i][paraObj] = -1;
  386.                     SupplyData[i][dropTimer] = SetTimerEx("RemoveDrop", DROP_LIFE * 60000, false, "i", i);
  387.                    
  388.                     if(IsPlayerConnected(SupplyData[i][requestedBy])) SendClientMessage(SupplyData[i][requestedBy], 0x3498DBFF, "SUPPLY DROP: {FFFFFF}Drop complete.");
  389.                     break;
  390.                 }
  391.             }
  392.         }
  393.     }
  394.    
  395.     return 1;
  396. }
  397.  
  398. public OnPlayerPickUpPickup(playerid, pickupid)
  399. {
  400.     foreach(new i : SupplyDrops)
  401.     {
  402.         if(pickupid == SupplyData[i][dropPickup])
  403.         {
  404.             switch(SupplyData[i][dropType])
  405.             {
  406.                 case DROP_TYPE_WEAPON: GivePlayerWeapon(playerid, SupplyData[i][dropData], AMMO_AMOUNT);
  407.                
  408.                 case DROP_TYPE_AMMO:
  409.                 {
  410.                     new weapon, ammo;
  411.                     for(new x = 2; x <= 7; x++)
  412.                     {
  413.                         GetPlayerWeaponData(playerid, x, weapon, ammo);
  414.                         SetPlayerAmmo(playerid, weapon, ammo + AMMO_AMOUNT);
  415.                     }
  416.                 }
  417.                
  418.                 case DROP_TYPE_HEALTH: SetPlayerHealth(playerid, 100.0);
  419.                 case DROP_TYPE_ARMOR: SetPlayerArmour(playerid, 100.0);
  420.             }
  421.            
  422.             DestroyPickup(SupplyData[i][dropPickup]);
  423.             Delete3DTextLabel(SupplyData[i][dropLabel]);
  424.             KillTimer(SupplyData[i][dropTimer]);
  425.            
  426.             SupplyData[i][dropPickup] = SupplyData[i][requestedBy] = SupplyData[i][dropTimer] = -1;
  427.             SupplyData[i][dropLabel] = Text3D: -1;
  428.            
  429.             new next;
  430.             Iter_SafeRemove(SupplyDrops, i, next);
  431.             break;
  432.         }
  433.     }
  434.    
  435.     return 1;
  436. }
  437.  
  438. forward FlyPlane(id, Float: x, Float: y, Float: z, angle);
  439. public FlyPlane(id, Float: x, Float: y, Float: z, angle)
  440. {
  441.     SupplyData[id][planeObj] = CreateObject(1681, x + (DIST * -floatsin(-angle, degrees)), y + (DIST * -floatcos(-angle, degrees)), z + 75.0, 0.0, 0.0, angle);
  442.     new time = MoveObject(SupplyData[id][planeObj], x + (DIST * floatsin(-angle, degrees)), y + (DIST * floatcos(-angle, degrees)), z + 75.0, 60.0);
  443.    
  444.     SupplyData[id][dropTimer] = SetTimerEx("MakeDrop", floatround(time / 2.5), false, "ifff", id, x, y, z);
  445.    
  446.     if(IsPlayerConnected(SupplyData[id][requestedBy])) SendClientMessage(SupplyData[id][requestedBy], 0x3498DBFF, "PILOT: {FFFFFF}I'm getting close.");
  447.     return 1;
  448. }
  449.  
  450. forward MakeDrop(id, Float: x, Float: y, Float: z);
  451. public MakeDrop(id, Float: x, Float: y, Float: z)
  452. {
  453.     new Float: plx, Float: ply, Float: plz;
  454.     GetObjectPos(SupplyData[id][planeObj], plx, ply, plz);
  455.    
  456.     SupplyData[id][boxObj] = CreateObject(2975, plx, ply, plz - 15.0, 0.0, 0.0, 0.0);
  457.     SupplyData[id][paraObj] = CreateObject(18849, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
  458.     SetObjectMaterial(SupplyData[id][paraObj], 2, 19478, "signsurf", "sign", 0xFFFFFFFF);
  459.     AttachObjectToObject(SupplyData[id][paraObj], SupplyData[id][boxObj], 0.0, -0.05, 7.5, 0.0, 0.0, 0.0);
  460.     MoveObject(SupplyData[id][boxObj], x, y, z, 8.0);
  461.  
  462.     if(IsPlayerConnected(SupplyData[id][requestedBy])) SendClientMessage(SupplyData[id][requestedBy], 0x3498DBFF, "PILOT: {FFFFFF}Supplies dropped.");
  463.     return 1;
  464. }
  465.  
  466. forward RemoveDrop(id);
  467. public RemoveDrop(id)
  468. {
  469.     DestroyPickup(SupplyData[id][dropPickup]);
  470.     Delete3DTextLabel(SupplyData[id][dropLabel]);
  471.  
  472.     SupplyData[id][dropPickup] = SupplyData[id][requestedBy] = SupplyData[id][dropTimer] = -1;
  473.     SupplyData[id][dropLabel] = Text3D: -1;
  474.  
  475.     Iter_Remove(SupplyDrops, id);
  476.     return 1;
  477. }
  478.  
  479. CMD:drop(playerid, params[])
  480. {
  481.     if(IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't use this command in a vehicle.");
  482.     new cooldown = GetPVarInt(playerid, "supply_Cooldown");
  483.     if(cooldown > gettime())
  484.     {
  485.         new string[72];
  486.         format(string, sizeof(string), "ERROR: {FFFFFF}Please wait %s more to request a supply drop again.", ConvertToMinutes(cooldown - gettime()));
  487.         return SendClientMessage(playerid, 0xE74C3CFF, string);
  488.     }
  489.    
  490.     ShowDropMenu(playerid);
  491.     return 1;
  492. }
RAW Paste Data